diff --git a/demo/demo.css b/demo/demo.css
index 03c0cd6..5efc209 100644
--- a/demo/demo.css
+++ b/demo/demo.css
@@ -4,11 +4,32 @@ html,body,div,span,applet,object,iframe,h1,h2,h3,h4,h5,h6,p,blockquote,pre,a,abb
/* @end */
+body {
+ background: #fff;
+ font: 12px/1.5 'Helvetica Neue', Arial, 'Liberation Sans', FreeSans, sans-serif;
+}
+
+p, dl, hr, h1, h2, h3, h4, h5, h6, ol,
+ul, pre, table, address, fieldset {
+ margin-bottom: 20px;
+}
+
+h1 { font-size: 25px; }
+h2 { font-size: 23px; }
+h3 { font-size: 21px; }
+h4 { font-size: 19px; }
+h5 { font-size: 17px; }
+h6 { font-size: 13px; }
+
input {
border: 1px solid #999;
+ width: 200px;
+ padding: 3px 3px;
+ font-size: 12px;
}
#container {
width: 960px;
margin: 0px auto;
+ text-align: center;
}
\ No newline at end of file
diff --git a/demo/demo.html b/demo/demo.html
deleted file mode 100644
index f79bbc8..0000000
--- a/demo/demo.html
+++ /dev/null
@@ -1,60 +0,0 @@
-
-
-
-
-
-
- examples
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/demo/demo.js b/demo/demo.js
new file mode 100644
index 0000000..de57dea
--- /dev/null
+++ b/demo/demo.js
@@ -0,0 +1,102 @@
+var data = [
+ {"title": "Ädams, Egbert", "info": "Bedfordshire", "href": "/demo/user/1"},
+ {"title": "Altman, Alisha", "info": "Buckinghamshire", "href": "/demo/user/2"},
+ {"title": "Archibald, Janna", "info": "Cambridgeshire", "href": "/demo/user/3"},
+ {"title": "Auman, Cody", "info": "Cheshire", "href": "/demo/user/4"},
+ {"title": "Bagley, Sheree", "info": "Cornwall", "href": "/demo/user/5"},
+ {"title": "Ballou, Wilmot", "info": "Cumbria", "href": "/demo/user/6"},
+ {"title": "Bard, Cassian", "info": "Derbyshire", "href": "/demo/user/1"},
+ {"title": "Bash, Latanya", "info": "Devon", "href": "/demo/user/2"},
+ {"title": "Beail, May", "info": "Dorset", "href": "/demo/user/3"},
+ {"title": "Black, Lux", "info": "Durham", "href": "/demo/user/4"},
+ {"title": "Bloise, India", "info": "East Sussex", "href": "/demo/user/5"},
+ {"title": "Blyant, Nora", "info": "Essex", "href": "/demo/user/6"},
+ {"title": "Bollinger, Carter", "info": "Gloucestershire", "href": "/demo/user/1"},
+ {"title": "Burns, Jaycob", "info": "Hampshire", "href": "/demo/user/2"},
+ {"title": "Carden, Preston", "info": "Hertfordshire", "href": "/demo/user/3"},
+ {"title": "Carter, Merrilyn", "info": "Kent", "href": "/demo/user/4"},
+ {"title": "Christner, Addie", "info": "Lancashire", "href": "/demo/user/5"},
+ {"title": "Churchill, Mirabelle", "info": "Leicestershire", "href": "/demo/user/6"},
+ {"title": "Conkle, Erin", "info": "Lincolnshire", "href": "/demo/user/1"},
+ {"title": "Countryman, Abner", "info": "Norfolk", "href": "/demo/user/2"},
+ {"title": "Courtney, Edgar", "info": "Northamptonshire", "href": "/demo/user/3"},
+ {"title": "Cowher, Antony", "info": "Northumberland", "href": "/demo/user/4"},
+ {"title": "Craig, Charlie", "info": "North Yorkshire", "href": "/demo/user/5"},
+ {"title": "Cram, Zacharias", "info": "Nottinghamshire", "href": "/demo/user/6"},
+ {"title": "Cressman, Ted", "info": "Oxfordshire", "href": "/demo/user/1"},
+ {"title": "Crissman, Annie", "info": "Shropshire", "href": "/demo/user/2"},
+ {"title": "Davis, Palmer", "info": "Somerset", "href": "/demo/user/3"},
+ {"title": "Downing, Casimir", "info": "Staffordshire", "href": "/demo/user/4"},
+ {"title": "Earl, Missie", "info": "Suffolk", "href": "/demo/user/5"},
+ {"title": "Eckert, Janele", "info": "Surrey", "href": "/demo/user/6"},
+ {"title": "Eisenman, Briar", "info": "Warwickshire", "href": "/demo/user/1"},
+ {"title": "Fitzgerald, Love", "info": "West Sussex", "href": "/demo/user/2"},
+ {"title": "Fleming, Sidney", "info": "Wiltshire", "href": "/demo/user/3"},
+ {"title": "Fuchs, Bridger", "info": "Worcestershire", "href": "/demo/user/4"},
+ {"title": "Fulton, Rosalynne", "info": "Durham", "href": "/demo/user/5"},
+ {"title": "Fye, Webster", "info": "East Sussex", "href": "/demo/user/6"},
+ {"title": "Geyer, Rylan", "info": "Essex", "href": "/demo/user/1"},
+ {"title": "Greene, Charis", "info": "Gloucestershire", "href": "/demo/user/2"},
+ {"title": "Greif, Jem", "info": "Hampshire", "href": "/demo/user/3"},
+ {"title": "Guest, Sarahjeanne", "info": "Hertfordshire", "href": "/demo/user/4"},
+ {"title": "Harper, Phyllida", "info": "Kent", "href": "/demo/user/5"},
+ {"title": "Hildyard, Erskine", "info": "Lancashire", "href": "/demo/user/6"},
+ {"title": "Hoenshell, Eulalia", "info": "Leicestershire", "href": "/demo/user/1"},
+ {"title": "Isaman, Lalo", "info": "Lincolnshire", "href": "/demo/user/2"},
+ {"title": "James, Diamond", "info": "Norfolk", "href": "/demo/user/3"},
+ {"title": "Jenkins, Merrill", "info": "Northamptonshire", "href": "/demo/user/4"},
+ {"title": "Jube, Bennett", "info": "Northumberland", "href": "/demo/user/5"},
+ {"title": "Kava, Marianne", "info": "North Yorkshire", "href": "/demo/user/6"},
+ {"title": "Kern, Linda", "info": "Nottinghamshire", "href": "/demo/user/1"},
+ {"title": "Klockman, Jenifer", "info": "Oxfordshire", "href": "/demo/user/2"},
+ {"title": "Lacon, Quincy", "info": "Shropshire", "href": "/demo/user/3"},
+ {"title": "Laurenzi, Leland", "info": "Somerset", "href": "/demo/user/4"},
+ {"title": "Leichter, Jeane", "info": "Staffordshire", "href": "/demo/user/5"},
+ {"title": "Leslie, Kerrie", "info": "Suffolk", "href": "/demo/user/6"},
+ {"title": "Lester, Noah", "info": "Surrey", "href": "/demo/user/1"},
+ {"title": "Llora, Roxana", "info": "Warwickshire", "href": "/demo/user/2"},
+ {"title": "Lombardi, Polly", "info": "West Sussex", "href": "/demo/user/3"},
+ {"title": "Lowstetter, Louisa", "info": "Wiltshire", "href": "/demo/user/4"},
+ {"title": "Mays, Emery", "info": "Worcestershire", "href": "/demo/user/5"},
+ {"title": "Mccullough, Bernadine", "info": "Durham", "href": "/demo/user/6"},
+ {"title": "Mckinnon, Kristie", "info": "East Sussex", "href": "/demo/user/1"},
+ {"title": "Meyers, Hector", "info": "Essex", "href": "/demo/user/2"},
+ {"title": "Monahan, Penelope", "info": "Gloucestershire", "href": "/demo/user/3"},
+ {"title": "Mull, Kaelea", "info": "Hampshire", "href": "/demo/user/4"},
+ {"title": "Newbiggin, Osmond", "info": "Hertfordshire", "href": "/demo/user/5"},
+ {"title": "Nickolson, Alfreda", "info": "Kent", "href": "/demo/user/6"},
+ {"title": "Pawle, Jacki", "info": "Lancashire", "href": "/demo/user/1"},
+ {"title": "Paynter, Nerissa", "info": "Leicestershire", "href": "/demo/user/2"},
+ {"title": "Pinney, Wilkie", "info": "Lincolnshire", "href": "/demo/user/3"},
+ {"title": "Pratt, Ricky", "info": "Norfolk", "href": "/demo/user/4"},
+ {"title": "Putnam, Stephanie", "info": "Northamptonshire", "href": "/demo/user/5"},
+ {"title": "Ream, Terrence", "info": "Northumberland", "href": "/demo/user/6"},
+ {"title": "Rumbaugh, Noelle", "info": "North Yorkshire", "href": "/demo/user/1"},
+ {"title": "Ryals, Titania", "info": "Nottinghamshire", "href": "/demo/user/2"},
+ {"title": "Saylor, Lenora", "info": "Oxfordshire", "href": "/demo/user/3"},
+ {"title": "Schofield, Denice", "info": "Shropshire", "href": "/demo/user/4"},
+ {"title": "Schuck, John", "info": "Somerset", "href": "/demo/user/5"},
+ {"title": "Scott, Clover", "info": "Staffordshire", "href": "/demo/user/6"},
+ {"title": "Smith, Estella", "info": "Suffolk", "href": "/demo/user/1"},
+ {"title": "Smothers, Matthew", "info": "Surrey", "href": "/demo/user/2"},
+ {"title": "Stainforth, Maurene", "info": "Warwickshire", "href": "/demo/user/3"},
+ {"title": "Stephenson, Phillipa", "info": "West Sussex", "href": "/demo/user/4"},
+ {"title": "Stewart, Hyram", "info": "Wiltshire", "href": "/demo/user/5"},
+ {"title": "Stough, Gussie", "info": "Worcestershire", "href": "/demo/user/6"},
+ {"title": "Strickland, Temple", "info": "Durham", "href": "/demo/user/1"},
+ {"title": "Sullivan, Gertie", "info": "East Sussex", "href": "/demo/user/2"},
+ {"title": "Swink, Stefanie", "info": "Essex", "href": "/demo/user/3"},
+ {"title": "Tavoularis, Terance", "info": "Gloucestershire", "href": "/demo/user/4"},
+ {"title": "Taylor, Kizzy", "info": "Hampshire", "href": "/demo/user/5"},
+ {"title": "Thigpen, Alwyn", "info": "Hertfordshire", "href": "/demo/user/6"},
+ {"title": "Treeby, Jim", "info": "Kent", "href": "/demo/user/1"},
+ {"title": "Trevithick, Jayme", "info": "Lancashire", "href": "/demo/user/2"},
+ {"title": "Waldron, Ashley", "info": "Leicestershire", "href": "/demo/user/3"},
+ {"title": "Wheeler, Bysshe", "info": "Lincolnshire", "href": "/demo/user/4"},
+ {"title": "Whishaw, Dodie", "info": "Norfolk", "href": "/demo/user/5"},
+ {"title": "Whitehead, Jericho", "info": "Northamptonshire", "href": "/demo/user/6"},
+ {"title": "Wilks, Debby", "info": "Northumberland", "href": "/demo/user/1"},
+ {"title": "Wire, Tallulah", "info": "North Yorkshire", "href": "/demo/user/2"},
+ {"title": "Woodworth, Alexandria", "info": "Nottinghamshire", "href": "/demo/user/3"},
+ {"title": "Zaun, Jillie", "info": "", "href": ""}
+];
\ No newline at end of file
diff --git a/demo/demo.json b/demo/demo.json
deleted file mode 100644
index 44576b5..0000000
--- a/demo/demo.json
+++ /dev/null
@@ -1,11 +0,0 @@
-[
- {title: "head", href: "/head", match: "head zzz"},
- {title: "headache", href: "/headache", match: "headache zzz"},
- {title: "health", href: "/health", match: "health zzz"},
- {title: "healthcare", href: "/healthcare", match: "healthcare zzz"},
- {title: "healthier", href: "/healthier", match: "healthier zzz"},
- {title: "heck", href: "/heck", match: "heck zzz"},
- {title: "hectic", href: "/hectic", match: "hectic zzz"},
- {title: "held", href: "/held", match: "held zzz"},
- {title: "hell", href: "/hell", match: "hell zzz"},
-];
\ No newline at end of file
diff --git a/demo/index.html b/demo/index.html
new file mode 100644
index 0000000..2836de1
--- /dev/null
+++ b/demo/index.html
@@ -0,0 +1,71 @@
+
+
+
+
+
+
+ Suggest Results Demo
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
Suggest Results Demo
+
+ Results from local array:
+
+
+
+ Results from ajax call:
+
+
+
+ Customized results from ajax call:
+
+
+
+
+
+
diff --git a/demo/server-side.php b/demo/server-side.php
new file mode 100644
index 0000000..ea0fde1
--- /dev/null
+++ b/demo/server-side.php
@@ -0,0 +1,135 @@
+($i+1),
+ "title"=>htmlspecialchars($aUsers[$i]),
+ "info"=>htmlspecialchars($aInfo[$i]),
+ "href"=>$aImg[$i],
+ );
+ }
+
+ if ($limit && $count==$limit)
+ break;
+ }
+ }
+
+ header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // Date in the past
+ header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); // always modified
+ header ("Cache-Control: no-cache, must-revalidate"); // HTTP/1.1
+ header ("Pragma: no-cache"); // HTTP/1.0
+
+ header("Content-Type: application/json");
+
+ echo "{\"results\": [\n\t";
+ $arr = array();
+ for ($i=0;$i
\ No newline at end of file
diff --git a/suggest_results/jquery.suggest_results.css b/suggest_results/jquery.suggest_results.css
index 5e57070..e6dc6ed 100644
--- a/suggest_results/jquery.suggest_results.css
+++ b/suggest_results/jquery.suggest_results.css
@@ -1,33 +1,48 @@
#suggest_results {
- background: #fbfbfb;
- border: 1px solid #ccc;
- border-top: none;
+ border-bottom: 1px solid #efefef;
display: none;
position: absolute;
z-index: 1000;
+}
+
+#suggest_results ol {
+ background: #fbfbfb;
+ border: 1px solid #bbb;
+ border-top: none;
margin: 0px;
padding: 0px;
+ list-style: none;
}
- #suggest_results li {
- margin: 0px;
- border-bottom: 1px solid #ddd;
- }
- #suggest_results li.first {
-
- }
- #suggest_results li.last {
- border-bottom: none;
- }
- #suggest_results li.result {
- display: block;
- }
- #suggest_results li.result a {
- display: block;
- padding: 3px 5px;
- }
- #suggest_results li.result a:hover,
- #suggest_results li.result.selected a {
- background: #698DE5;
- color: #fff;
- }
\ No newline at end of file
+
+#suggest_results li {
+ margin: 0px;
+ border-bottom: 1px solid #ddd;
+}
+
+#suggest_results li.result {
+ display: block;
+}
+
+#suggest_results li.first {
+
+}
+
+#suggest_results li.last {
+ border-bottom: none;
+}
+
+#suggest_results li.result a {
+ display: block;
+ padding: 3px 5px;
+ text-decoration: none;
+}
+#suggest_results li.result a span {
+ display: block;
+}
+
+#suggest_results li.result a:hover,
+#suggest_results li.result.selected a {
+ background: #698DE5;
+ color: #fff;
+}
\ No newline at end of file
diff --git a/suggest_results/jquery.suggest_results.js b/suggest_results/jquery.suggest_results.js
index 561f188..5d0414e 100644
--- a/suggest_results/jquery.suggest_results.js
+++ b/suggest_results/jquery.suggest_results.js
@@ -5,10 +5,17 @@
self.init($options);
+ var BACKSPACE = 8;
+ var RETURN = 13;
+ var ESC = 27;
+ var ARRUP = 38;
+ var ARRDN = 40;
+ var SPECIALS_END = 45;
+
return this.each(function(){
var $e = $(this);
$e.focus(function(){
- self.attach($e, options);
+ self.attach($e, $options);
if ($e.val().length > 0) {
self.search_timeout = self.setTimeout(function(){
self.search($e, $options);
@@ -17,59 +24,75 @@
}).blur(function(){
self.hide();
}).keydown(function(e){
- var RETURN = 13;
- var ESC = 27;
- var ARRUP = 38;
- var ARRDN = 40;
switch(e.keyCode) {
case ARRUP: self.select_prev($e, $options); return false;
case ARRDN: self.select_next($e, $options); return false;
case ESC: self.clear($e, $options); break;
case RETURN: self.activate_selected($options); return false;
- default:
- self.clearTimeout();
- self.search($e, $options);
+ default: self.clearTimeout(); self.search($e, $options);
}
+ }).keyup(function(e){
+ if (e.keyCode > SPECIALS_END || e.keyCode == BACKSPACE) {
+ self.clearTimeout();
+ self.search($e, $options);
+ };
});
});
};
$.fn.suggest_results.box = null;
+ $.fn.suggest_results.list = null;
$.fn.suggest_results.attached_to = null;
$.fn.suggest_results.current_results = [];
$.fn.suggest_results.selected_result = null;
$.fn.suggest_results.timeout = null;
+ $.fn.suggest_results.query_cache = [];
$.fn.suggest_results.init = function(options){
var self = $.fn.suggest_results;
- self.box = $("#" + options.template.container_id);
+ self.box = $("#" + options.tpl_container_id);
if (self.box.length == 0) {
- $("body").append(self.mustache(options.template.container, {id: options.template.container_id}));
- self.box = $("#" + options.template.container_id);
+ $("body").append(self.mustache(options.tpl_container, {id: options.tpl_container_id}));
+ self.box = $("#" + options.tpl_container_id);
+ self.list = $("ol", self.box);
};
};
$.fn.suggest_results.search = function(elm, options){
var self = $.fn.suggest_results;
- var terms = (options.exact_match) ? $.trim(elm.val()) : elm.val().split(/\s/);
+ var terms = (options.exactMatch) ? $.trim(elm.val()) : elm.val().split(/\s/);
if (typeof(options.url) === "string" && options.url !== "") {
- //TODO support fetching results from server-side
+ self.query_for_data(elm, options);
} else {
- var results = self.filter_data(terms, options.data, options);
- };
- self.current_results = results;
- if (results.length > 0) {
- self.render(results, options);
- self.show();
- } else {
- self.hide();
+ self.current_results = self.filter_data(terms, options.data, options);
+ self.prerender(self.current_results, options);
};
};
$.fn.suggest_results.clear = function(elm, options){
var self = $.fn.suggest_results;
elm.val("");
- self.hide();
+ self.hide(0);
+ self.selected_result = null;
+ };
+
+ $.fn.suggest_results.no_results = function(options){
+ var self = $.fn.suggest_results;
+ if (options.empty) {
+ //TODO display "No Results" label.
+ } else {
+ self.hide(0);
+ };
+ };
+
+ $.fn.suggest_results.prerender = function(results, options){
+ var self = $.fn.suggest_results;
+ if (results.length > 0) {
+ self.render(results, options);
+ self.show();
+ } else {
+ self.no_results(options);
+ };
};
$.fn.suggest_results.render = function(results, options){
@@ -77,14 +100,16 @@
var results_length = results.length;
var html = "";
for (var i=0; i < results_length; i++) {
- var meta = {id: "suggested_result_" + i, "class": ""};
+ var meta = $.extend({}, results[i], {id: "suggested_result_" + i, "class": ""});
if (i == 0) { $.extend(meta, {"class": "first"}); };
if (i == results_length - 1) { $.extend(meta, {"class": "last"}); };
- html += self.mustache(options.template.result, $.extend({}, meta, results[i]));
+ html += self.mustache(options.tpl_result_begin, meta);
+ html += self.mustache(options.tpl_result_body, meta);
+ html += self.mustache(options.tpl_result_end, meta);
};
- self.box.html("");
- self.box.append(html);
- $(".result", self.box).click(function(){
+ self.list.html("");
+ self.list.append(html);
+ $(".result", self.list).click(function(){
self.redirect_to($("a", $(this)).attr("href"));
});
};
@@ -93,6 +118,7 @@
var self = $.fn.suggest_results;
var elm_uid = self.elm_uid(elm);
if (elm_uid !== self.attached_to) {
+ self.box.hide().attr("class", options.name);
var offset = elm.offset();
// left offset
@@ -112,7 +138,6 @@
width -= parseInt(self.box.css("border-left-width"), 10) + parseInt(self.box.css("border-right-width"), 10);
self.box.css("width", width + "px");
};
-
self.attached_to = elm_uid;
};
};
@@ -121,12 +146,14 @@
$.fn.suggest_results.box.show();
};
- $.fn.suggest_results.hide = function(){
+ $.fn.suggest_results.hide = function(delay){
var self = $.fn.suggest_results;
+ if (typeof(delay) !== "number") { delay = 250; };
+ self.selected_result = null;
self.setTimeout(function(){
self.selected_result = null;
self.box.hide();
- }, 500);
+ }, delay);
};
$.fn.suggest_results.select_next = function(elm, options){
@@ -140,6 +167,10 @@
$(".selected", self.box).removeClass("selected");
self.selected_result++;
$("#suggested_result_" + self.selected_result, self.box).addClass("selected");
+ } else {
+ $(".selected", self.box).removeClass("selected");
+ self.selected_result = null;
+ elm.putCursorAtEnd();
};
};
return false;
@@ -199,12 +230,44 @@
return results;
};
+ $.fn.suggest_results.query_for_data = function(elm, options){
+ var self = $.fn.suggest_results;
+ var term = elm.val();
+ var uid = options.url + "?" + term + ":" + options.limit;
+ if (term !== "") {
+ if (self.query_cache.hasOwnProperty(uid)) {
+ self.current_results = self.query_cache[uid];
+ self.prerender(self.current_results, options);
+ } else {
+ var data = { limit: options.limit };
+ data[options.url_query_var] = term;
+ $.ajax({
+ type: options.url_method,
+ url: options.url,
+ data: data,
+ dataType: "json",
+ success: function(response){
+ self.current_results = response.results;
+ self.query_cache[uid] = self.current_results;
+ self.prerender(self.current_results, options);
+ }
+ });
+ };
+ } else {
+ self.no_results(options);
+ };
+ return [];
+ };
+
$.fn.suggest_results.elm_uid = function(elm){
- var uid = "";
- if ( elm.attr("id") !== "" ) { uid += "#" + elm.attr("id"); };
- if ( elm.attr("class") !== "" ) { uid += "." + elm.attr("class"); };
- if ( elm.attr("name") !== "" ) { uid += "[" + elm.attr("name") + "]"; };
- return uid;
+ if (elm.attr("id") !== "") {
+ return "#" + elm.attr("id");
+ } else if (elm.attr("class") !== "") {
+ return "." + elm.attr("class");
+ } else if (elm.attr("name") !== "") {
+ return "!" + elm.attr("name");
+ };
+ return "";
};
$.fn.suggest_results.mustache = function(string, data){
@@ -263,16 +326,34 @@
};
$.fn.suggest_results.defaults = {
- delay: 150,
+ url: null,
+ url_query_var: "search",
+ url_method: "get",
+ empty: false,
+ empty_label: "No Results",
+ name: "",
+ delay: 100,
limit: 6,
data: null,
- exact_match: true,
- template: {
- container_id: "suggest_results",
- container: ' ',
- result: '{{title}} ',
- category: '{{category}} ' //TODO add support for categories
- }
+ exactMatch: true,
+ tpl_container_id: "suggest_results",
+ tpl_container: '',
+ tpl_result_begin: '',
+ tpl_result_body: '{{title}} ',
+ tpl_result_end: ' ',
+ tpl_label: '' //TODO add support for labels/categories
};
-})(jQuery);
\ No newline at end of file
+})(jQuery);
+
+
+/*
+ Crossbrowser hasOwnProperty solution, based on answers from:
+ http://stackoverflow.com/questions/135448/how-do-i-check-to-see-if-an-object-has-an-attribute-in-javascript
+*/
+if ( !Object.prototype.hasOwnProperty ) {
+ Object.prototype.hasOwnProperty = function(prop) {
+ var proto = obj.__proto__ || obj.constructor.prototype;
+ return (prop in this) && (!(prop in proto) || proto[prop] !== this[prop]);
+ };
+}
\ No newline at end of file