1% Make sure the encoding of the characters `á` and `ö` is 2% correctly understood. . (utf8) 4 5:- module(autocomplete, [autocomplete//1]).
11:- use_module(library(http/html_head)). 12:- use_module(library(http/html_write)). 13 14:- ensure_loaded(weblog(resources/resources)). 15:- use_module(library(http/js_write)). 16:- use_module(library(http/http_wrapper)). 17:- use_module(library(http/http_dispatch)). 18:- use_module(library(http/json_convert)). 19:- use_module(library(http/http_parameters)). 20:- use_module(library(http/http_json)). 21 22:- html_meta autocomplete(1, ?, ?).
Generator is an arity n term that corresponds to an arity n+1 predicate.
autocomplete//1 will repeatedly query Generator for information and build up the autocomplete field. The final argument may be
choice(-Atom)
A choice for the autocomplete fieldid(-ID)
The input field id will be set to this. default tagschoice(+Term, -Choice)
where Term is an atom representation of
the current contents of the field, and Choice is an atom
representation of one of the choices*/
45autocomplete(Generator) --> 46 { 47 ( call(Generator, id(ID)) ; ID = 'tags' ) 48 }, 49 html([ 50 \html_requires(jquery_ui), 51 \html_post(head, [\autocomplete_script(Generator)]), 52 input([id=ID], [])]). 53 54autocomplete_script(Generator) --> 55 { 56 call(Generator, ajax), 57 ( call(Generator, id(ID)) ; ID = 'tags' ), 58 ajax_path_name(Generator, PathName) 59 }, 60 html([ 61 \js_script( {| javascript(ID, PathName) || 62$(function() { 63 $( "#"+ID ).autocomplete({ 64 source: PathName 65 }); 66 }); 67|} ) 68 ]). 69 70autocomplete_script(Generator) --> 71 { 72 call(Generator, accents),!, 73 bagof(Choice, call(Generator, choice(Choice)), Choices), 74 ( call(Generator, id(ID)) ; ID = 'tags' ) 75 }, 76 html([ 77 \js_script( {| javascript(Choices, ID) || 78 $(function() { 79 var names = Choices; 80 81 var accentMap = { 82 "á": "a", 83 "ö": "o" 84 }; 85 var normalize = function( term ) { 86 var ret = ""; 87 for ( var i = 0; i < term.length; i++ ) { 88 ret += accentMap[ term.charAt(i) ] || term.charAt(i); 89 } 90 return ret; 91 }; 92 93 $( "#"+ID ).autocomplete({ 94 source: function( request, response ) { 95 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( request.term ), "i" ); 96 response( $.grep( names, function( value ) { 97 value = value.label || value.value || value; 98 return matcher.test( value ) || matcher.test( normalize( value ) ); 99 }) ); 100 } 101 }); 102 }); 103|} ) 104 ]). 105 106autocomplete_script(Generator) --> 107 { 108 bagof(Choice, call(Generator, choice(Choice)), Choices), 109 ( call(Generator, id(ID)) ; ID = 'tags' ) 110 }, 111 html([ 112 \js_script( {| javascript(Choices, ID) || 113$(function() { 114 var availableTags = Choices; 115 $( "#"+ID ).autocomplete({ 116 source: availableTags 117 }); 118 }); 119|} ) 120 ]). 121 122ajax_path_name(Generator, AjaxPath) :- 123 ( call(Generator, id(ID)) ; ID = 'tags' ), 124 http_current_request(Request), 125 member(path(Path), Request), 126 atomic_list_concat([Path, '/ajax/', ID], AjaxPath), 127 ensure_ajax_handler_exists(Generator, AjaxPath). 128 129ensure_ajax_handler_exists(_, AjaxPath) :- 130 http_dispatch:handler(AjaxPath, _, _, _),!. 131ensure_ajax_handler_exists(Generator, AjaxPath) :- 132 http_handler(AjaxPath, ajax_wrapper(Generator), []). 133 134:- meta_predicate ajax_wrapper( , ). 135 136ajax_wrapper(Generator, Request) :- 137 http_parameters(Request, [ 138 term(Term, [])]), 139 findall(Choice, call(Generator, choice(Term, Choice)), Choices), 140 prolog_to_json(Choices, JSONOut), 141 reply_json(JSONOut)
Autocomplete
jQuery based autocomplete widget
*/