8

我想使用带有 ajax 的自动完成功能。所以我的目标是:

  • 当用户在文本字段中键入内容时,会出现服务器提供的一些建议(我必须在数据库中找到建议)

  • 当用户按下“enter”,点击自动完成框以外的其他地方,或者当他/她选择一个建议时,文本字段中的字符串被发送到服务器。

我首先尝试使用 lift 提供的自动完成小部件,但我遇到了三个问题:

  • 它是一种扩展选择,也就是说您最初只能提交建议值。
  • 它不适合与 ajax 一起使用。
  • WiringUI.

所以,我的问题是:如何结合jquery 自动完成并与服务器交互。我想我应该使用一些回调,但我不掌握它们。

提前致谢。

更新这是我尝试的第一个实现,但回调不起作用:

private def update_source(current: String, limit: Int) = {   
  val results = if (current.length == 0) Nil else /* generate list of results */
  new JsCmd{def toJsCmd = if(results.nonEmpty) results.mkString("[\"", "\", \"", "\"]") else "[]" }
}   

def render = {
  val id = "my-autocomplete"
  val cb = SHtml.ajaxCall(JsRaw("request"), update_source(_, 4))
  val script = Script(new JsCmd{
    def toJsCmd = "$(function() {"+
      "$(\"#"+id+"\").autocomplete({ "+
      "autocomplete: on, "+
      "source: function(request, response) {"+
        "response("+cb._2.toJsCmd + ");"  +
      "}"+
      "})});"
  })

  <head><script charset="utf-8"> {script} </script></head> ++
  <span id={id}> {SHtml.ajaxText(init, s=>{ /*set cell to value s*/; Noop}) }   </span>
}

所以我的想法是:

  • 通过一个SHtml.ajaxText字段获取选定的结果,该字段将被包装到一个自动完成字段中
  • 使用 javascript 函数更新自动完成建议
4

2 回答 2

8

这是你需要做的。

1) 确保您使用的是 Lift 2.5-SNAPSHOT(这在早期版本中是可行的,但更难)

2)在你用来呈现页面的片段中,使用 SHtml.ajaxCall (特别是,你可能想要这个版本:https ://github.com/lift/framework/blob/master/web/webkit/src/main/ scala/net/liftweb/http/SHtml.scala#L170)这将允许您注册一个服务器端函数,该函数接受您的搜索词并返回包含完成的 JSON 响应。您还将使用 JsContext 注册在 JSON 响应上发生的一些操作。

3) 上面的 ajaxCall 会返回一个 JsExp 对象,当它被调用时会产生 ajax 请求。使用您的代码段将其嵌入页面上的 javascript 函数中。

4)将它们与一些客户端JS连接起来。

更新- 一些可以帮助您的代码。使用 Lift 2.5 肯定可以更简洁地完成,但由于 2.4 中的一些不一致,我最终推出了自己的类似 ajaxCall 的函数。S.fmapFunc 在服务器端注册函数,函数体从客户端进行 Lift ajax 调用,然后在 JSON 响应上调用 res 函数(来自 jQuery 自动完成)。

我的 jQuery 插件“激活”文本输入


(function($) {
    $.fn.initAssignment = function() {
     return this.autocomplete({
         autoFocus: true,
         source: function(req, res) {
              search(req.term, res);
         },
         select: function(event, ui) {
             assign(ui.item.value, function(data){
                eval(data);
             });
             event.preventDefault();
             $(this).val("");
         },
         focus: function(event, ui) {
             event.preventDefault();
         }
     });
    }
})(jQuery);

我的 Scala 代码导致 javascript 搜索功能:


def autoCompleteJs = JsRaw("""
        function search(term, res) {
        """ +
             (S.fmapFunc(S.contextFuncBuilder(SFuncHolder({ terms: String =>
                val _candidates = 
                  if(terms != null && terms.trim() != "")
                    assigneeCandidates(terms)
                  else
                    Nil
                JsonResponse(JArray(_candidates map { c => c.toJson }))
             })))
             ({ name => 
               "liftAjax.lift_ajaxHandler('" + name 
             })) + 
             "=' + encodeURIComponent(term), " +
             "function(data){ res(data); }" +
             ", null, 'json');" +
        """
        }
        """)

更新 2 - 要将上面的功能添加到您的页面,请使用类似于下面的 CssSelector 转换。>* 表示附加到匹配的脚本元素中已经存在的任何内容。我在该页面上定义了其他功能,这为它们添加了搜索功能。


"script >*" #> autoCompleteJs

您可以查看源代码以验证它是否存在于页面上,并且可以像任何其他 JS 函数一样被调用。

于 2012-04-06T16:00:11.760 回答
2

在 Dave Whittaker 的帮助下,这是我提出的解决方案。

我不得不改变一些行为来获得:

  • ajaxText 元素中所需的文本(是否来自自动完成)
  • 在同一页面上有多个自动完成表单的可能性
  • 在自动完成建议中选择某些内容时,在模糊之前在 ajaxText 上提交答案。

斯卡拉部分

private def getSugggestions(current: String, limit: Int):List[String] = {
  /* returns list of suggestions */
}

private def autoCompleteJs = AnonFunc("term, res",JsRaw(
  (S.fmapFunc(S.contextFuncBuilder(SFuncHolder({ terms: String =>
    val _candidates =
      if(terms != null && terms.trim() != "")
        getSugggestions(terms, 5)
      else
        Nil
    JsonResponse(JArray(_candidates map { c => JString(c)/*.toJson*/ }))
  })))
  ({ name =>
    "liftAjax.lift_ajaxHandler('" + name
  })) +
  "=' + encodeURIComponent(term), " +
  "function(data){ res(data); }" +
  ", null, 'json');"))


def xml = {
  val id = "myId" //possibility to have multiple autocomplete fields on same page
  Script(OnLoad(JsRaw("jQuery('#"+id+"').createAutocompleteField("+autoCompleteJs.toJsCmd+")")))     ++
  SHtml.ajaxText(cell.get, s=>{ cell.set(s); SearchMenu.recomputeResults; Noop}, "id" -> id)
}

插入页眉的脚本:

(function($) {
    $.fn.createAutocompleteField = function(search) {
        return this.autocomplete({
            autoFocus: true,
            source: function(req, res) {
                search(req.term, res);
            },
            select: function(event, ui) {
                $(this).val(ui.item.value);
                $(this).blur();
            },
            focus: function(event, ui) {
                event.preventDefault();
            }
        });
    }
})(jQuery);

注意:我接受了戴夫的回答,我只是为了我的目的提供一个完整的答案

于 2012-04-17T08:12:01.957 回答