summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAlex DiLiberto <alex@alexdiliberto.com>2015-02-24 21:04:32 -0500
committerAlex DiLiberto <alex@alexdiliberto.com>2015-02-24 21:04:32 -0500
commitce9aad862dd2f199160411a428632bc980b73632 (patch)
tree77c0da0ee4b6507236bd52a726719e1b5b81fdf5
parent75834f2e6b9130a9bc1d1b732b71eafaca9ae72b (diff)
downloadawesomplete-ce9aad862dd2f199160411a428632bc980b73632.zip
awesomplete-ce9aad862dd2f199160411a428632bc980b73632.tar.gz
awesomplete-ce9aad862dd2f199160411a428632bc980b73632.tar.bz2
[BUGFIX] Keydown events while `ul` is hidden should not trigger component actions
This fixes a bug where previously, if the `ul` was hidden, the component would still act upon keydown events for Enter/Esc/Up/Down To replicate the previous bug: In the demo, you can select `Java` then keyup and down. You know see that the context is not within the input tag iself, however it's within the component which is still selecting items from the previously searched list.
-rw-r--r--awesomplete.js126
-rw-r--r--awesomplete.min.js9
2 files changed, 66 insertions, 69 deletions
diff --git a/awesomplete.js b/awesomplete.js
index 9b388ef..653b524 100644
--- a/awesomplete.js
+++ b/awesomplete.js
@@ -4,19 +4,19 @@
* @author Lea Verou http://leaverou.github.io/awesomplete
* MIT license
*/
-
+
(function () {
var _ = self.Awesomplete = function (input, o) {
var me = this;
-
+
// Setup
-
+
this.input = input;
input.setAttribute("aria-autocomplete", "list");
-
+
o = o || {};
-
+
configure.call(this, {
minChars: 2,
maxItems: 10,
@@ -27,66 +27,70 @@ var _ = self.Awesomplete = function (input, o) {
return $.create("li", {
innerHTML: text.replace(RegExp($.regExpEscape(input.trim()), "gi"), "<mark>$&</mark>"),
"aria-selected": "false"
- });
+ });
},
replace: function (text) {
this.input.value = text;
}
}, o);
-
+
this.index = -1;
-
+
// Create necessary elements
-
+
this.container = $.create("div", {
className: "awesomplete",
around: input
});
-
+
this.ul = $.create("ul", {
hidden: "",
inside: this.container
});
-
+
// Bind events
-
+
$.bind(this.input, {
"input": this.evaluate.bind(this),
"blur": this.close.bind(this),
"keydown": function(evt) {
var c = evt.keyCode;
-
- if (c === 13 && me.selected) { // Enter
- evt.preventDefault();
- me.select();
- }
- else if (c === 27) { // Esc
- me.close();
- }
- else if (c === 38 || c === 40) { // Down/Up arrow
- evt.preventDefault();
- me[c === 38? "previous" : "next"]();
+
+ // If the dropdown `ul` is in view, then act on keydown for the following keys:
+ // Enter / Esc / Up / Down
+ if(me.ul && me.ul.getAttribute("hidden") == null) {
+ if (c === 13 && me.selected) { // Enter
+ evt.preventDefault();
+ me.select();
+ }
+ else if (c === 27) { // Esc
+ me.close();
+ }
+ else if (c === 38 || c === 40) { // Down/Up arrow
+ evt.preventDefault();
+ me[c === 38? "previous" : "next"]();
+ }
}
}
});
-
+
$.bind(this.input.form, {"submit": me.close.bind(me)});
-
+
$.bind(this.ul, {"mousedown": function(evt) {
var li = evt.target;
-
+
if (li !== this) {
-
+
while (li && !/li/i.test(li.nodeName)) {
li = li.parentNode;
}
-
+
if (li) {
- me.select(li);
+ me.select(li);
}
}
}});
-
+
if (input.hasAttribute("list")) {
this.list = "#" + input.getAttribute("list");
input.removeAttribute("list");
@@ -94,7 +98,7 @@ var _ = self.Awesomplete = function (input, o) {
else {
this.list = input.getAttribute("data-list") || o.list || [];
}
-
+
_.all.push(this);
};
@@ -108,80 +112,80 @@ _.prototype = {
}
else { // Element or CSS selector
list = $(list);
-
+
if (list && list.children) {
this._list = slice.apply(list.children).map(function (el) {
return el.innerHTML.trim();
});
}
}
-
+
if (document.activeElement === this.input) {
this.evaluate();
}
},
-
+
get selected() {
return this.index > -1;
},
-
+
close: function () {
this.ul.setAttribute("hidden", "");
this.index = -1;
-
+
$.fire(this.input, "awesomplete-close");
},
-
+
open: function () {
this.ul.removeAttribute("hidden");
-
+
if (this.autoFirst && this.index === -1) {
this.goto(0);
}
-
+
$.fire(this.input, "awesomplete-open");
},
-
+
next: function () {
var count = this.ul.children.length;
this.goto(this.index < count - 1? this.index + 1 : -1);
},
-
+
previous: function () {
var count = this.ul.children.length;
-
+
this.goto(this.selected? this.index - 1 : count - 1);
},
-
+
// Should not be used, highlights specific item without any checks!
goto: function (i) {
var lis = this.ul.children;
-
+
if (this.selected) {
lis[this.index].setAttribute("aria-selected", "false");
}
-
+
this.index = i;
-
+
if (i > -1 && lis.length > 0) {
lis[i].setAttribute("aria-selected", "true");
}
},
-
+
select: function (selected) {
selected = selected || this.ul.children[this.index];
if (selected) {
var prevented;
-
+
$.fire(this.input, "awesomplete-select", {
text: selected.textContent,
preventDefault: function () {
prevented = true;
}
});
-
+
if (!prevented) {
this.replace(selected.textContent);
this.close();
@@ -189,11 +193,11 @@ _.prototype = {
}
}
},
-
+
evaluate: function() {
var me = this;
var value = this.input.value;
-
+
if (value.length >= this.minChars && this._list.length > 0) {
this.index = -1;
// Populate list with options that match
@@ -206,10 +210,10 @@ _.prototype = {
.sort(this.sort)
.every(function(text, i) {
me.ul.appendChild(me.item(text, value));
-
+
return i < me.maxItems - 1;
});
-
+
this.open();
}
else {
@@ -234,7 +238,7 @@ _.SORT_BYLENGTH = function (a, b) {
if (a.length !== b.length) {
return a.length - b.length;
}
-
+
return a < b? -1 : 1;
};
@@ -244,7 +248,7 @@ function configure(properties, o) {
for (var i in properties) {
var initial = properties[i],
attrValue = this.input.getAttribute("data-" + i.toLowerCase());
-
+
if (typeof initial === "number") {
this[i] = +attrValue;
}
@@ -257,7 +261,7 @@ function configure(properties, o) {
else {
this[i] = attrValue;
}
-
+
this[i] = this[i] || o[i] || initial;
}
}
@@ -276,10 +280,10 @@ function $$(expr, con) {
$.create = function(tag, o) {
var element = document.createElement(tag);
-
+
for (var i in o) {
var val = o[i];
-
+
if (i === "inside") {
$(val).appendChild(element);
}
@@ -295,7 +299,7 @@ $.create = function(tag, o) {
element.setAttribute(i, val);
}
}
-
+
return element;
};
@@ -303,7 +307,7 @@ $.bind = function(element, o) {
if (element) {
for (var event in o) {
var callback = o[event];
-
+
event.split(/\s+/).forEach(function (event) {
element.addEventListener(event, callback);
});
@@ -313,7 +317,7 @@ $.bind = function(element, o) {
$.fire = function(target, type, properties) {
var evt = document.createEvent("HTMLEvents");
-
+
evt.initEvent(type, true, true );
for (var j in properties) {
diff --git a/awesomplete.min.js b/awesomplete.min.js
index c7f82b3..3b7c534 100644
--- a/awesomplete.min.js
+++ b/awesomplete.min.js
@@ -1,9 +1,2 @@
// Awesomplete - Lea Verou - MIT license
-(function(){function m(a,b){for(var c in a){var f=a[c],e=this.input.getAttribute("data-"+c.toLowerCase());this[c]="number"===typeof f?+e:!1===f?null!==e:f instanceof Function?null:e;this[c]=this[c]||b[c]||f}}function d(a,b){return"string"===typeof a?(b||document).querySelector(a):a||null}function h(a,b){return k.call((b||document).querySelectorAll(a))}function l(){h("input.awesomplete").forEach(function(a){new Awesomplete(a)})}var g=self.Awesomplete=function(a,b){var c=this;this.input=a;a.setAttribute("aria-autocomplete",
-"list");b=b||{};m.call(this,{minChars:2,maxItems:10,autoFirst:!1,filter:g.FILTER_CONTAINS,sort:g.SORT_BYLENGTH,item:function(a,b){return d.create("li",{innerHTML:a.replace(RegExp(d.regExpEscape(b.trim()),"gi"),"<mark>$&</mark>"),"aria-selected":"false"})},replace:function(a){this.input.value=a}},b);this.index=-1;this.container=d.create("div",{className:"awesomplete",around:a});this.ul=d.create("ul",{hidden:"",inside:this.container});d.bind(this.input,{input:this.evaluate.bind(this),blur:this.close.bind(this),
-keydown:function(a){var b=a.keyCode;if(13===b&&c.selected)a.preventDefault(),c.select();else if(27===b)c.close();else if(38===b||40===b)a.preventDefault(),c[38===b?"previous":"next"]()}});d.bind(this.input.form,{submit:c.close.bind(c)});d.bind(this.ul,{mousedown:function(a){a=a.target;if(a!==this){for(;a&&!/li/i.test(a.nodeName);)a=a.parentNode;a&&c.select(a)}}});a.hasAttribute("list")?(this.list="#"+a.getAttribute("list"),a.removeAttribute("list")):this.list=a.getAttribute("data-list")||b.list||
-[];g.all.push(this)};g.prototype={set list(a){Array.isArray(a)?this._list=a:"string"===typeof a&&-1<a.indexOf(",")?this._list=a.split(/\s*,\s*/):(a=d(a))&&a.children&&(this._list=k.apply(a.children).map(function(a){return a.innerHTML.trim()}));document.activeElement===this.input&&this.evaluate()},get selected(){return-1<this.index},close:function(){this.ul.setAttribute("hidden","");this.index=-1;d.fire(this.input,"awesomplete-close")},open:function(){this.ul.removeAttribute("hidden");this.autoFirst&&
--1===this.index&&this.goto(0);d.fire(this.input,"awesomplete-open")},next:function(){this.goto(this.index<this.ul.children.length-1?this.index+1:-1)},previous:function(){var a=this.ul.children.length;this.goto(this.selected?this.index-1:a-1)},goto:function(a){var b=this.ul.children;this.selected&&b[this.index].setAttribute("aria-selected","false");this.index=a;-1<a&&0<b.length&&b[a].setAttribute("aria-selected","true")},select:function(a){if(a=a||this.ul.children[this.index]){var b;d.fire(this.input,
-"awesomplete-select",{text:a.textContent,preventDefault:function(){b=!0}});b||(this.replace(a.textContent),this.close(),d.fire(this.input,"awesomplete-selectcomplete"))}},evaluate:function(){var a=this,b=this.input.value;b.length>=this.minChars&&0<this._list.length?(this.index=-1,this.ul.innerHTML="",this._list.filter(function(c){return a.filter(c,b)}).sort(this.sort).every(function(c,d){a.ul.appendChild(a.item(c,b));return d<a.maxItems-1}),this.open()):this.close()}};g.all=[];g.FILTER_CONTAINS=function(a,
-b){return RegExp(d.regExpEscape(b.trim()),"i").test(a)};g.FILTER_STARTSWITH=function(a,b){return RegExp("^"+d.regExpEscape(b.trim()),"i").test(a)};g.SORT_BYLENGTH=function(a,b){return a.length!==b.length?a.length-b.length:a<b?-1:1};var k=Array.prototype.slice;d.create=function(a,b){var c=document.createElement(a),f;for(f in b){var e=b[f];"inside"===f?d(e).appendChild(c):"around"===f?(e=d(e),e.parentNode.insertBefore(c,e),c.appendChild(e)):f in c?c[f]=e:c.setAttribute(f,e)}return c};d.bind=function(a,
-b){if(a)for(var c in b){var d=b[c];c.split(/\s+/).forEach(function(b){a.addEventListener(b,d)})}};d.fire=function(a,b,c){var d=document.createEvent("HTMLEvents");d.initEvent(b,!0,!0);for(var e in c)d[e]=c[e];a.dispatchEvent(d)};d.regExpEscape=function(a){return a.replace(/[-\\^$*+?.()|[\]{}]/g,"\\$&")};"loading"!==document.readyState?l():document.addEventListener("DOMContentLoaded",l);g.$=d;g.$$=h})(); \ No newline at end of file
+!function(){function t(t,e){for(var i in t){var n=t[i],s=this.input.getAttribute("data-"+i.toLowerCase());this[i]="number"==typeof n?+s:n===!1?null!==s:n instanceof Function?null:s,this[i]=this[i]||e[i]||n}}function e(t,e){return"string"==typeof t?(e||document).querySelector(t):t||null}function i(t,e){return r.call((e||document).querySelectorAll(t))}function n(){i("input.awesomplete").forEach(function(t){new Awesomplete(t)})}var s=self.Awesomplete=function(i,n){var r=this;this.input=i,i.setAttribute("aria-autocomplete","list"),n=n||{},t.call(this,{minChars:2,maxItems:10,autoFirst:!1,filter:s.FILTER_CONTAINS,sort:s.SORT_BYLENGTH,item:function(t,i){return e.create("li",{innerHTML:t.replace(RegExp(e.regExpEscape(i.trim()),"gi"),"<mark>$&</mark>"),"aria-selected":"false"})},replace:function(t){this.input.value=t}},n),this.index=-1,this.container=e.create("div",{className:"awesomplete",around:i}),this.ul=e.create("ul",{hidden:"",inside:this.container}),e.bind(this.input,{input:this.evaluate.bind(this),blur:this.close.bind(this),keydown:function(t){var e=t.keyCode;r.ul&&null==r.ul.getAttribute("hidden")&&(13===e&&r.selected?(t.preventDefault(),r.select()):27===e?r.close():(38===e||40===e)&&(t.preventDefault(),r[38===e?"previous":"next"]()))}}),e.bind(this.input.form,{submit:r.close.bind(r)}),e.bind(this.ul,{mousedown:function(t){var e=t.target;if(e!==this){for(;e&&!/li/i.test(e.nodeName);)e=e.parentNode;e&&r.select(e)}}}),i.hasAttribute("list")?(this.list="#"+i.getAttribute("list"),i.removeAttribute("list")):this.list=i.getAttribute("data-list")||n.list||[],s.all.push(this)};s.prototype={set list(t){Array.isArray(t)?this._list=t:"string"==typeof t&&t.indexOf(",")>-1?this._list=t.split(/\s*,\s*/):(t=e(t),t&&t.children&&(this._list=r.apply(t.children).map(function(t){return t.innerHTML.trim()}))),document.activeElement===this.input&&this.evaluate()},get selected(){return this.index>-1},close:function(){this.ul.setAttribute("hidden",""),this.index=-1,e.fire(this.input,"awesomplete-close")},open:function(){this.ul.removeAttribute("hidden"),this.autoFirst&&-1===this.index&&this["goto"](0),e.fire(this.input,"awesomplete-open")},next:function(){var t=this.ul.children.length;this["goto"](this.index<t-1?this.index+1:-1)},previous:function(){var t=this.ul.children.length;this["goto"](this.selected?this.index-1:t-1)},"goto":function(t){var e=this.ul.children;this.selected&&e[this.index].setAttribute("aria-selected","false"),this.index=t,t>-1&&e.length>0&&e[t].setAttribute("aria-selected","true")},select:function(t){if(t=t||this.ul.children[this.index]){var i;e.fire(this.input,"awesomplete-select",{text:t.textContent,preventDefault:function(){i=!0}}),i||(this.replace(t.textContent),this.close(),e.fire(this.input,"awesomplete-selectcomplete"))}},evaluate:function(){var t=this,e=this.input.value;e.length>=this.minChars&&this._list.length>0?(this.index=-1,this.ul.innerHTML="",this._list.filter(function(i){return t.filter(i,e)}).sort(this.sort).every(function(i,n){return t.ul.appendChild(t.item(i,e)),n<t.maxItems-1}),this.open()):this.close()}},s.all=[],s.FILTER_CONTAINS=function(t,i){return RegExp(e.regExpEscape(i.trim()),"i").test(t)},s.FILTER_STARTSWITH=function(t,i){return RegExp("^"+e.regExpEscape(i.trim()),"i").test(t)},s.SORT_BYLENGTH=function(t,e){return t.length!==e.length?t.length-e.length:e>t?-1:1};var r=Array.prototype.slice;e.create=function(t,i){var n=document.createElement(t);for(var s in i){var r=i[s];if("inside"===s)e(r).appendChild(n);else if("around"===s){var l=e(r);l.parentNode.insertBefore(n,l),n.appendChild(l)}else s in n?n[s]=r:n.setAttribute(s,r)}return n},e.bind=function(t,e){if(t)for(var i in e){var n=e[i];i.split(/\s+/).forEach(function(e){t.addEventListener(e,n)})}},e.fire=function(t,e,i){var n=document.createEvent("HTMLEvents");n.initEvent(e,!0,!0);for(var s in i)n[s]=i[s];t.dispatchEvent(n)},e.regExpEscape=function(t){return t.replace(/[-\\^$*+?.()|[\]{}]/g,"\\$&")},"loading"!==document.readyState?n():document.addEventListener("DOMContentLoaded",n),s.$=e,s.$$=i}();