Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

creating ajax editable

  • Loading branch information...
commit e584344abf6c31c087635071705df149256c05ca 1 parent f9f0b38
timur.br@gmail.com authored
View
232 src/main/scala/code/snippet/AEditable.scala
@@ -6,7 +6,7 @@ import Helpers._
import http._
import js._
import js.JE._
-import js.jquery.JqJE
+import js.jquery.{JqJsCmds, JqJE}
import js.jquery.JqJsCmds.{FadeOut, FadeIn}
import js.JsCmds._
import xml._
@@ -34,37 +34,54 @@ object BootstrapMsgs {
}
val wrapHtml = encJs(<div class={noticeNodeClass}></div>.toString())
val closeButton = encJs(<button type="button" class="close" data-dismiss="alert">&times;</button>.toString())
- JsRaw("jQuery('#%s').wrap(%s).parent().prepend(%s)".format(id, wrapHtml, closeButton))
-
- }
+// """
+// | function(){
+// | if (jQuery('#%s').attr(""))
+// | jQuery('#%s').wrap(%s).parent().prepend(%s)
+// | }()
+// """.stripMargin
+ //JsRaw(("jQuery('#%s').wrap(%s).parent().prepend(%s)").format(id, wrapHtml, closeButton))})
+ JsRaw(("jQuery('#%s').addClass('%s').prepend(%s)").format(id, noticeNodeClass, closeButton))})
+ def render(in:NodeSeq) = {
+ LiftRules.noticesEffects.request.set(Vendor(BootstrapMsgs.wrapMsgsJsCmd _))
+ NodeSeq.Empty
+// val msgs = S.eval(<lift:msgs></lift:msgs>).openOr(NodeSeq.Empty)
+// if (S.getAllNotices.length > 0) {
+// <div class="alert alert-block">
+// <button type="button" class="close" data-dismiss="alert">&times;</button>
+// {msgs}
+// </div>
+// } else msgs
+ }
+}
-// AnonFunc(
-// JqJE.JqId(id) ~> JqJE.JqHtml(
-// JsCrVar("h", encJs(<div class="alert alert-block">{{0}}</div>.text)) &
-// JsVar("h") ~> JsFunc("format", JqJE.JqId(id) ~> JqJE.JqHtml())
-// )
-// )
+object FadeOutNotices {
+ def render(ns:NodeSeq): NodeSeq = {
+ LiftRules.noticesAutoFadeOut.request.set( (notices: NoticeType.Value) => {
+ notices match {
+ case NoticeType.Notice => Full((2 seconds, 2 seconds))
+ case _ => Empty
+ }
+ }
)
+ NodeSeq.Empty
+ }
+}
-
- def render(in:NodeSeq) = {
- val msgs = S.eval(<lift:msgs></lift:msgs>).openOr(NodeSeq.Empty)
- if (S.getAllNotices.length > 0) {
- <div class="alert alert-block">
- <button type="button" class="close" data-dismiss="alert">&times;</button>
- {msgs}
- </div>
- } else msgs
+object NoticeTest {
+ def render(ns:NodeSeq):NodeSeq = {
+ SHtml.a(() => {S.notice("Ajax notice"); S.warning("Ajax notice")}, Text("Ajax notice"))
}
}
object AEditable {
- val editLinkCSSClass = "liftedit_link_class_"
+ val editLinkCSSClass = "lift_edit_link_class_"
val hideLinksFnName = "lift_hide_edit_links_"
val showLinksFnName = "lift_show_edit_links_"
+ val newRecordMarkerId = "lift_new_record_marker_id_"
val ajaxEditLinkNodes = Text("Edit")
val ajaxEditLinkAttributes:List[net.liftweb.http.SHtml.ElemAttr] = List(("class" -> "btn"))
@@ -73,6 +90,8 @@ object AEditable {
val ajaxCancelLinkNodes = Text("Cancel")
val ajaxCancelLinkAttributes = List(("class" -> "btn"))
+ val addButtonAttributes:List[net.liftweb.http.SHtml.ElemAttr] = List(("class" -> "btn"))
+
val editModeClass = "info"
case class Field(viewFunc: CssSel, editFunc: CssSel)
@@ -83,41 +102,71 @@ object AEditable {
Nil
object dataVar extends SessionVar(population)
+ object editForm extends RequestVar[Box[MemoizeTransform]](Empty)
def table(ns:NodeSeq) =
- // <head_merge>
- // <script type="text/javascript">
- // function lift_hide_edit_links() {{jQuery("liftedit_link_class_").hide()}}
- // function lift_show_edit_links() {{jQuery(".liftedit_link_class_").show()}}
- // </script>
- // </head_merge> ++
- <head_merge>
- {Script(
- Function(hideLinksFnName, Nil, JqJE.Jq("."+editLinkCSSClass) ~> JsFunc("fadeOut", 100)) &
- Function(showLinksFnName, Nil, JqJE.Jq("."+editLinkCSSClass) ~> JsFunc("fadeIn", 100))
- )}
- </head_merge> ++
+ <head_merge>
+ <script type="text/javascript">
+ function {hideLinksFnName}() {{jQuery(".{editLinkCSSClass}").fadeOut(100)}}
+ function {showLinksFnName}() {{jQuery(".{editLinkCSSClass}").fadeIn(100)}}
+ </script>
+ </head_merge> ++
+// <head_merge>
+// {Script(
+// Function(hideLinksFnName, Nil, JqJE.Jq("."+editLinkCSSClass) ~> JsFunc("fadeOut", 100)) &
+// Function(showLinksFnName, Nil, JqJE.Jq("."+editLinkCSSClass) ~> JsFunc("fadeIn", 100))
+// )}
+// </head_merge> ++
SHtml.ajaxForm(ns)
def editableList = {
- LiftRules.noticesEffects.request.set(Vendor(BootstrapMsgs.wrapMsgsJsCmd _))
- "*" #> dataVar.get.map(h =>
- editable(
- "@edit", "@ok", "@cancel",
- () => {
- S.notice(Text("Value is updated"))
- S.notice(Text("Value is updated 2"))
- S.warning(Text("Value is updated"))
- S.error(Text("Value is updated"))
- },
- Field("@name *" #> h.name, "@name *" #> SHtml.text(h.name, h.name = _)),
- Field("@age *" #> h.age, "@age *" #> SHtml.number(h.age, h.age = _, 0, 1000)),
- Field("@was-expelled *" #> (if (h.wasExpelled) "Yes" else "No"),
- "@was-expelled *" #> SHtml.checkbox(h.wasExpelled, h.wasExpelled = _)),
- Field("@in-paradise *" #> (if (h.inParadise) "Yes" else "No"),
- "@in-paradise *" #> (if (h.inParadise) "Yes" else "No"))
- ) _
+ "*" #> dataVar.get.map(h => {
+ editableRow(h)
+ })
+ }
+
+ def editableRow(h:Human) =
+ editable(
+ "@edit", "@ok", "@cancel",
+ () => S.notice(Text("Value was updated")),
+ fieldsFor(h): _*
)
+
+ def fieldsFor(h:Human) =
+ List(Field("@name *" #> h.name, "@name *" #> SHtml.text(h.name, h.name = _)),
+ Field("@age *" #> h.age, "@age *" #> SHtml.number(h.age, h.age = _, 0, 1000)),
+ Field("@was-expelled *" #> (if (h.wasExpelled) "Yes" else "No"),
+ "@was-expelled *" #> SHtml.checkbox(h.wasExpelled, h.wasExpelled = _)),
+ Field("@in-paradise *" #> (if (h.inParadise) "Yes" else "No"),
+ "@in-paradise *" #> (if (h.inParadise) "Yes" else "No")))
+
+ val createNew =
+ makeAddForm {
+ val h = new Human("Homunculus", 0)
+ addRecordForm(
+ "@add", "@ok", "@cancel",
+ () => {dataVar.set(dataVar.get ++ List(h));S.notice(Text("Value was added"))},
+ editableRow(h)()
+ fieldsFor(h): _*
+ )
+ }
+
+ def addButton(ns:NodeSeq) = {
+ val a = SHtml.a(() => {
+ editForm.map(form => {
+ hideControls &
+ JsRaw("jQuery('#%s').before(%s)".format(newRecordMarkerId, encJs(form.applyAgain().toString()))):JsCmd
+ }).openOr(Noop)
+ }, ns)
+ addEditClassName(addButtonAttributes.foldLeft(a)(_ % _))
+ }
+
+ def makeAddForm(createNewFrom: => (NodeSeq => NodeSeq)):NodeSeq => NodeSeq = {
+ (ns) => {
+ editForm.set(Full(SHtml.memoize{createNewFrom})) // we do not evaluate createNewFrom here (it's so lazy and cool)
+ editForm.get.foreach(_.apply(ns)) // createNewFrom is evaluated here and in each editForm.get.applyAgain() call
+ <tr id={newRecordMarkerId}></tr>
+ }
}
def smoothReplace(nodeId:String, ns:NodeSeq) =
@@ -128,52 +177,73 @@ object AEditable {
JqJE.JqId(nodeId) ~> JsFunc("fadeIn", 100)))
- def editable(editLinkSelector:String, okButtonSelecor: String, cancelButtonSelecor: String,
- onSubmit:() => JsCmd, fields:Field*)(ns:NodeSeq): NodeSeq = {
-
+ def addRecordForm(addLinkSelector:String, okButtonSelector: String,
+ cancelButtonSelector: String, onSubmit:() => JsCmd, afterAddNodes:NodeSeq, fields:Field*) = {
val nodeId = nextFuncName
+ def removeRowFn =
+ JqJE.JqId(nodeId) ~> JqJE.JqRemove() & showControls
+ makeForm(nodeId, addLinkSelector, okButtonSelector,
+ cancelButtonSelector, onSubmit, Full(removeRowFn _), fields: _*) _
+ }
- var makeForm: CssSel = null // dumb forward declaration
- var rowTransform: CssSel = null // dumb forward declaration
-
- def renderRow() =
- Call(showLinksFnName) &
- smoothReplace(nodeId, rowTransform(ns))
-
- val addEditClassName = "a [class+]" #> editLinkCSSClass
-
- rowTransform = viewRow(fields) &
+ def makeRowView(nodeId:String, editLinkSelector:String, okButtonSelector: String, cancelButtonSelector: String,
+ onSubmit: () => JsCmd, fields:Field*)(ns:NodeSeq):NodeSeq = {
+ val fn = viewRowFn(fields) &
editLinkSelector #>
{
addEditClassName(
SHtml.a(
- () => Call(hideLinksFnName) & smoothReplace(nodeId, makeForm(ns)),
+ () => hideControls &
+ smoothReplace(nodeId, makeForm(nodeId, editLinkSelector, okButtonSelector, cancelButtonSelector,
+ onSubmit, Empty, fields: _*)(ns)),
ajaxEditLinkNodes,
ajaxEditLinkAttributes: _*)
)
} &
"tr [id]" #> nodeId &
- okButtonSelecor #> NodeSeq.Empty &
- cancelButtonSelecor #> NodeSeq.Empty
-
- makeForm = {
- editRow(fields) &
- okButtonSelecor #>
- ajaxSubmitInputAttributes.foldLeft(
- SHtml.ajaxSubmit(ajaxSubmitInputText, () => {
- renderRow & onSubmit()
- }))(_ % _) &
- cancelButtonSelecor #> ajaxCancelLinkAttributes.foldLeft(SHtml.a(renderRow _, ajaxCancelLinkNodes))(_ % _) &
- "tr [id]" #> nodeId &
- "tr [style]" #> "display:none" &
- editLinkSelector #> NodeSeq.Empty
- }
- rowTransform(ns)
+ okButtonSelector #> NodeSeq.Empty &
+ cancelButtonSelector #> NodeSeq.Empty
+ fn(ns)
}
- def viewRow(fields: Seq[Field]) =
+ def makeForm(nodeId:String, editLinkSelector:String, okButtonSelector: String, cancelButtonSelector: String,
+ onSubmit: () => JsCmd, onCancel:Box[() => JsCmd], fields:Field*)(ns:NodeSeq): NodeSeq = {
+ val renderViewRow = () =>
+ showControls &
+ smoothReplace(nodeId, makeRowView(nodeId, editLinkSelector, okButtonSelector, cancelButtonSelector,
+ onSubmit, fields: _*)(ns))
+
+ val fn = editRowFn(fields) &
+ okButtonSelector #>
+ ajaxSubmitInputAttributes.foldLeft(
+ SHtml.ajaxSubmit(ajaxSubmitInputText, () => {
+ renderViewRow() & onSubmit()
+ }))(_ % _) &
+ cancelButtonSelector #> ajaxCancelLinkAttributes.foldLeft(SHtml.a(onCancel.openOr(renderViewRow), ajaxCancelLinkNodes))(_ % _) &
+ "tr [id]" #> nodeId &
+ editLinkSelector #> NodeSeq.Empty
+ fn(ns)
+ }
+
+ def editable(editLinkSelector:String, okButtonSelector: String, cancelButtonSelector: String,
+ onSubmit: () => JsCmd, fields:Field*):NodeSeq => NodeSeq =
+ makeRowView(nextFuncName, editLinkSelector, okButtonSelector, cancelButtonSelector,
+ onSubmit, fields: _*)
+
+ val addEditClassName = "a [class+]" #> editLinkCSSClass
+
+ val showControls:JsCmd =
+ Call(showLinksFnName)
+
+ val hideControls:JsCmd =
+ Call(hideLinksFnName)
+
+ def viewRowFn(fields: Seq[Field]) =
fields.map(_.viewFunc) reduceLeft {(fs, f) => fs & f}
- def editRow(fields: Seq[Field])=
+ def editRowFn(fields: Seq[Field])=
+ fields.map(_.editFunc) reduceLeft {(fs, f) => fs & f}
+
+ def addRowFn(fields: Seq[Field])=
fields.map(_.editFunc) reduceLeft {(fs, f) => fs & f}
}
View
21 src/main/webapp/ajax_editable.html
@@ -14,6 +14,12 @@
<div class="container-fluid">
<div data-lift="BootstrapMsgs"></div>
+ <div data-lift="FadeOutNotices"></div>
+ <div class="row">
+ <div class="span12" style="min-height:60px">
+ <lift:msgs></lift:msgs>
+ </div>
+ </div>
<div class="row">
<div class="span12">
<table class="table" data-lift="AEditable.table">
@@ -40,8 +46,23 @@
<td height="40px" width="10%" name="was-expelled"></td>
<td height="40px" width="10%" name="in-paradise"></td>
</tr>
+ <tr data-lift="AEditable.createNew">
+ <td height="45px" width="20%">
+ <div name="add"></div>
+ <div>
+ <span name="ok"></span>
+ <span name="cancel"></span>
+ </div>
+ </td>
+ <td height="40px" width="30%" name="name"></td>
+ <td height="40px" width="30%" name="age"></td>
+ <td height="40px" width="10%" name="was-expelled"></td>
+ <td height="40px" width="10%" name="in-paradise"></td>
+ </tr>
</tbody>
</table>
+ <div data-lift="AEditable.addButton">Add</div>
+ <div data-lift="NoticeTest"></div>
</div>
</div>
</div>
Please sign in to comment.
Something went wrong with that request. Please try again.