Hello,
While playing around with the AutoComplete widget i wanted to change
some of the values passed to the jQuery autocomplete plugin and
couldn't figure out if this was possible or not. It didn't seem so
when i looked into the AutoComplete.scala file so i added a few lines
of code to the AutoComplete file and wanted to share it here :)

/* -------------------------------------- MyAutoComplete.scala starts
-------------------------------------- */
object MyAutoComplete {

  def apply(start: String,
            options: (String, Int) => Seq[String],
            onSubmit: String => Unit,
            jqOptions:  List[Pair[String,String]],
            attrs: (String, String)*) = new MyAutoComplete().render
(start, options, onSubmit, jqOptions ,attrs:_*)


  /**
   * register the resources with lift (typically in boot)
   */
  def init() {
    import net.liftweb.http.ResourceServer

    ResourceServer.allow({
        case "autocomplete" :: _ => true
     })
  }

}

class MyAutoComplete {


  /**
   * Render a text field with Ajax autocomplete support
   *
   * @param start - the initial input string
   * @param option - the function to be called when user is typing
text. The text and th options limit is provided to this functions
   * @param attrs - the attributes that can be added to the input text
field
   * @param jsonOptions - a list of pairs that will be send along to
the jQuery().AutoComplete call (for customization purposes)
   */
  def render(start: String,
             options: (String, Int) => Seq[String],
             onSubmit: String => Unit,
             jsonOptions: List[Pair[String,String]],
             attrs: (String, String)*): Elem = {

    val f = (ignore: String) => {
      val q = S.param("q").openOr("")
      val limit = S.param("limit").flatMap(asInt).openOr(10)
      PlainTextResponse(options(q, limit).map(s => s+"|"+s).mkString
("\n"))
    }


    fmapFunc(SFuncHolder(f)){ func =>
      val what: String = encodeURL(S.contextPath + "/" +
LiftRules.ajaxPath+"?"+func+"=foo")

      val id = Helpers.nextFuncName
      fmapFunc(SFuncHolder(onSubmit)){hidden =>

      /* merge the options that the user wants */
      val jqOptions =  ("minChars","0") ::
                       ("matchContains","true") ::
                       Nil ::: jsonOptions
      /* jsonify to options */
      var counter = 0
      var isLast = false
      var json = "{"
      jqOptions.foreach{ pair: Pair[String,String] =>
          counter += 1
          isLast = (counter == jqOptions.size)
          json += pair._1 + ": " + pair._2
          if (!isLast) json += "," }
      json += "}"

      val autocompleteOptions = JsRaw(json)

      val onLoad = JsRaw("""
      jQuery(document).ready(function(){
        var data = """+what.encJs+""";
        jQuery("#"""+id+"""").autocomplete(data,
"""+autocompleteOptions.toJsCmd+""").result(function(event, dt,
formatted) {
          jQuery("#"""+hidden+"""").val(formatted);
        });
      });""")

      <span>
        <head>
          <link rel="stylesheet" href={"/" +
LiftRules.resourceServerPath +"/autocomplete/jquery.autocomplete.css"}
type="text/css" />
          <script type="text/javascript" src={"/" +
LiftRules.resourceServerPath +"/autocomplete/jquery.autocomplete.js"} /
>
          <script type="text/javascript">{Unparsed(onLoad.toJsCmd)}</
script>
        </head>
        {
          attrs.foldLeft(<input type="text" id={id} value={start} />)
(_ % _)
        }
        <input type="hidden" name={hidden} id={hidden} value={start} /
>
      </span>
    }
   }
  }
}
/* -------------------------------------- MyAutoComplete.scala ends
-------------------------------------- */

I use it in a snippet like this:

val myoptions: List[Pair[String,String]] = ("width","300") :: Nil
bind("ajax",in,"auto" -> MyAutoComplete("", buildQuery _, _ => (),
myoptions))

Is there any way you would allow me to merge this with the existing
widget in case anyone else would like this feature?

Recap: The reason i added this is to take advantage of the
customizability the autocomplete plugin offers you.

the following is the values that you can customize if you have full
control over the JS object that is passed to the autocomplete method.
In my case i only needed to change the width but i could image that
someone would want to change some of the others too :)

$.Autocompleter.defaults = {
        inputClass: "ac_input",
        resultsClass: "ac_results",
        loadingClass: "ac_loading",
        minChars: 1,
        delay: 400,
        matchCase: false,
        matchSubset: true,
        matchContains: false,
        cacheLength: 10,
        max: 100,
        mustMatch: false,
        extraParams: {},
        selectFirst: true,
        formatItem: function(row) { return row[0]; },
        formatMatch: null,
        autoFill: false,
        width: 0,
        multiple: false,
        multipleSeparator: ", ",
        highlight: function(value, term) {
                return value.replace(new RegExp("(?![^&;]+;)(?!<[^<>]*)(" +
term.replace(/([\^\$\(\)\[\]\{\}\*\.\+\?\|\\])/gi, "\\$1") + ")(?![^<>]
*>)(?![^&;]+;)", "gi"), "<strong>$1</strong>");
        },
    scroll: true,
    scrollHeight: 180
};

Thanks,
Mads Hartmann Jensen

-- 
You received this message because you are subscribed to the Google Groups 
"Lift" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/liftweb?hl=en.


Reply via email to