autocomplete.js
Advanced tools
Comparing version 0.0.1 to 0.0.2
@@ -126,3 +126,4 @@ /*! | ||
this.$el = $(html.dataset.replace('%CLASS%', this.name)); | ||
this.$el = o.$menu && o.name && o.$menu.find('.aa-dataset-' + o.name).length > 0 ? | ||
$(o.$menu.find('.aa-dataset-' + o.name)[0]) : $(html.dataset.replace('%CLASS%', this.name)); | ||
} | ||
@@ -328,4 +329,2 @@ | ||
this.datasets = _.map(o.datasets, initializeDataset); | ||
// bound functions | ||
@@ -341,6 +340,18 @@ onSuggestionClick = _.bind(this._onSuggestionClick, this); | ||
if (o.templates && o.templates.header) { | ||
this.$menu.prepend((_.templatify(o.templates.header))()); | ||
} | ||
this.datasets = _.map(o.datasets, function(oDataset) { return initializeDataset(that.$menu, oDataset); }); | ||
_.each(this.datasets, function(dataset) { | ||
that.$menu.append(dataset.getRoot()); | ||
var root = dataset.getRoot(); | ||
if (root && root.parent().length === 0) { | ||
that.$menu.append(root); | ||
} | ||
dataset.onSync('rendered', that._onRendered, that); | ||
}); | ||
if (o.templates && o.templates.footer) { | ||
this.$menu.append((_.templatify(o.templates.footer))()); | ||
} | ||
} | ||
@@ -555,4 +566,4 @@ | ||
function initializeDataset(oDataset) { | ||
return new Dropdown.Dataset(oDataset); | ||
function initializeDataset($menu, oDataset) { | ||
return new Dropdown.Dataset(_.mixin({ '$menu': $menu }, oDataset)); | ||
} | ||
@@ -1086,5 +1097,7 @@ | ||
eventBus: eventBus, | ||
withHint: _.isUndefined(o.hint) ? true : !!o.hint, | ||
hint: _.isUndefined(o.hint) ? true : !!o.hint, | ||
minLength: o.minLength, | ||
autoselect: o.autoselect, | ||
templates: o.templates, | ||
debug: o.debug, | ||
datasets: datasets | ||
@@ -1181,2 +1194,4 @@ }); | ||
module.exports = $.fn.autocomplete; | ||
},{"../common/utils.js":11,"./event_bus.js":5,"./typeahead.js":10}],10:[function(require,module,exports){ | ||
@@ -1212,5 +1227,6 @@ 'use strict'; | ||
this.isActivated = false; | ||
this.debug = !!o.debug; | ||
this.autoselect = !!o.autoselect; | ||
this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; | ||
this.$node = buildDom(o.input, o.withHint); | ||
this.$node = buildDom(o); | ||
@@ -1248,3 +1264,3 @@ $menu = this.$node.find('.aa-dropdown-menu'); | ||
this.dropdown = new Typeahead.Dropdown({menu: $menu, datasets: o.datasets}) | ||
this.dropdown = new Typeahead.Dropdown({menu: $menu, datasets: o.datasets, templates: o.templates}) | ||
.onSync('suggestionClicked', this._onSuggestionClicked, this) | ||
@@ -1323,5 +1339,7 @@ .onSync('cursorMoved', this._onCursorMoved, this) | ||
_onBlurred: function onBlurred() { | ||
this.isActivated = false; | ||
this.dropdown.empty(); | ||
this.dropdown.close(); | ||
if (!this.debug) { | ||
this.isActivated = false; | ||
this.dropdown.empty(); | ||
this.dropdown.close(); | ||
} | ||
}, | ||
@@ -1538,3 +1556,3 @@ | ||
function buildDom(input, withHint) { | ||
function buildDom(options) { | ||
var $input; | ||
@@ -1545,5 +1563,8 @@ var $wrapper; | ||
$input = $(input); | ||
$input = $(options.input); | ||
$wrapper = $(html.wrapper).css(css.wrapper); | ||
$dropdown = $(html.dropdown).css(css.dropdown); | ||
if (options.templates && options.templates.dropdownMenu) { | ||
$dropdown.html((_.templatify(options.templates.dropdownMenu))()); | ||
} | ||
$hint = $input.clone().css(css.hint).css(getBackgroundStyles($input)); | ||
@@ -1571,3 +1592,3 @@ | ||
.attr({autocomplete: 'off', spellcheck: false}) | ||
.css(withHint ? css.input : css.inputWithNoHint); | ||
.css(options.hint ? css.input : css.inputWithNoHint); | ||
@@ -1586,3 +1607,3 @@ // ie7 does not like it when dir is set to auto | ||
.parent() | ||
.prepend(withHint ? $hint : null) | ||
.prepend(options.hint ? $hint : null) | ||
.append($dropdown); | ||
@@ -1643,4 +1664,2 @@ } | ||
isBlankString: function(str) { return !str || /^\s*$/.test(str); }, | ||
// http://stackoverflow.com/a/6969486 | ||
@@ -1651,4 +1670,2 @@ escapeRegExChars: function(str) { | ||
isString: function(obj) { return typeof obj === 'string'; }, | ||
isNumber: function(obj) { return typeof obj === 'number'; }, | ||
@@ -1696,16 +1713,2 @@ | ||
some: function(obj, test) { | ||
var result = false; | ||
if (!obj) { return result; } | ||
$.each(obj, function(key, val) { | ||
if (result = test.call(null, val, key, obj)) { | ||
return false; | ||
} | ||
}); | ||
return !!result; | ||
}, | ||
mixin: $.extend, | ||
@@ -1719,5 +1722,10 @@ | ||
templatify: function templatify(obj) { | ||
return $.isFunction(obj) ? obj : template; | ||
function template() { return String(obj); } | ||
if ($.isFunction(obj)) { | ||
return obj; | ||
} | ||
var $template = $(obj); | ||
if ($template.prop('tagName') === 'SCRIPT') { | ||
return function template() { return $template.text() }; | ||
} | ||
return function template() { return String(obj); }; | ||
}, | ||
@@ -1727,63 +1735,2 @@ | ||
debounce: function(func, wait, immediate) { | ||
var timeout; | ||
var result; | ||
return function() { | ||
var context = this; | ||
var args = arguments; | ||
var later; | ||
var callNow; | ||
later = function() { | ||
timeout = null; | ||
if (!immediate) { result = func.apply(context, args); } | ||
}; | ||
callNow = immediate && !timeout; | ||
clearTimeout(timeout); | ||
timeout = setTimeout(later, wait); | ||
if (callNow) { result = func.apply(context, args); } | ||
return result; | ||
}; | ||
}, | ||
throttle: function(func, wait) { | ||
var context; | ||
var args; | ||
var timeout; | ||
var result; | ||
var previous; | ||
var later; | ||
previous = 0; | ||
later = function() { | ||
previous = new Date(); | ||
timeout = null; | ||
result = func.apply(context, args); | ||
}; | ||
return function() { | ||
var now = new Date(); | ||
var remaining = wait - (now - previous); | ||
context = this; | ||
args = arguments; | ||
if (remaining <= 0) { | ||
clearTimeout(timeout); | ||
timeout = null; | ||
previous = now; | ||
result = func.apply(context, args); | ||
} else if (!timeout) { | ||
timeout = setTimeout(later, remaining); | ||
} | ||
return result; | ||
}; | ||
}, | ||
noop: function() {} | ||
@@ -1790,0 +1737,0 @@ }; |
@@ -13,5 +13,5 @@ /*! | ||
},{"../common/utils.js":11}],3:[function(require,module,exports){ | ||
"use strict";function Dataset(t){t=t||{},t.templates=t.templates||{},t.source||$.error("missing source"),t.name&&!isValidName(t.name)&&$.error("invalid dataset name: "+t.name),this.query=null,this.highlight=!!t.highlight,this.name=t.name||_.getUniqueId(),this.source=t.source,this.displayFn=getDisplayFn(t.display||t.displayKey),this.templates=getTemplates(t.templates,this.displayFn),this.$el=$(html.dataset.replace("%CLASS%",this.name))}function getDisplayFn(t){function e(e){return e[t]}return t=t||"value",_.isFunction(t)?t:e}function getTemplates(t,e){function a(t){return"<p>"+e(t)+"</p>"}return{empty:t.empty&&_.templatify(t.empty),header:t.header&&_.templatify(t.header),footer:t.footer&&_.templatify(t.footer),suggestion:t.suggestion||a}}function isValidName(t){return/^[_a-zA-Z0-9-]+$/.test(t)}var datasetKey="aaDataset",valueKey="aaValue",datumKey="aaDatum",_=require("../common/utils.js"),html=require("./html.js"),css=require("./css.js"),EventEmitter=require("./event_emitter.js");Dataset.extractDatasetName=function(t){return $(t).data(datasetKey)},Dataset.extractValue=function(t){return $(t).data(valueKey)},Dataset.extractDatum=function(t){return $(t).data(datumKey)},_.mixin(Dataset.prototype,EventEmitter,{_render:function(t,e){function a(){var e=[].slice.call(arguments,0);return e=[{query:t,isEmpty:!0}].concat(e),l.templates.empty.apply(this,e)}function s(){function t(t){var e;return e=$(html.suggestion).append(l.templates.suggestion.apply(this,[t].concat(n))).data(datasetKey,l.name).data(valueKey,l.displayFn(t)).data(datumKey,t),e.children().each(function(){$(this).css(css.suggestionChild)}),e}var a,s,n=[].slice.call(arguments,0);return a=$(html.suggestions).css(css.suggestions),s=_.map(e,t),a.append.apply(a,s),a}function n(){var e=[].slice.call(arguments,0);return e=[{query:t,isEmpty:!r}].concat(e),l.templates.header.apply(this,e)}function i(){var e=[].slice.call(arguments,0);return e=[{query:t,isEmpty:!r}].concat(e),l.templates.footer.apply(this,e)}if(this.$el){var r,l=this,u=[].slice.call(arguments,2);this.$el.empty(),r=e&&e.length,!r&&this.templates.empty?this.$el.html(a.apply(this,u)).prepend(l.templates.header?n.apply(this,u):null).append(l.templates.footer?i.apply(this,u):null):r&&this.$el.html(s.apply(this,u)).prepend(l.templates.header?n.apply(this,u):null).append(l.templates.footer?i.apply(this,u):null),this.trigger("rendered")}},getRoot:function(){return this.$el},update:function(t){function e(e){if(!a.canceled&&t===a.query){var s=[].slice.call(arguments,1);s=[t,e].concat(s),a._render.apply(a,s)}}var a=this;this.query=t,this.canceled=!1,this.source(t,e)},cancel:function(){this.canceled=!0},clear:function(){this.cancel(),this.$el.empty(),this.trigger("rendered")},isEmpty:function(){return this.$el.is(":empty")},destroy:function(){this.$el=null}}),module.exports=Dataset; | ||
"use strict";function Dataset(t){t=t||{},t.templates=t.templates||{},t.source||$.error("missing source"),t.name&&!isValidName(t.name)&&$.error("invalid dataset name: "+t.name),this.query=null,this.highlight=!!t.highlight,this.name=t.name||_.getUniqueId(),this.source=t.source,this.displayFn=getDisplayFn(t.display||t.displayKey),this.templates=getTemplates(t.templates,this.displayFn),this.$el=t.$menu&&t.name&&t.$menu.find(".aa-dataset-"+t.name).length>0?$(t.$menu.find(".aa-dataset-"+t.name)[0]):$(html.dataset.replace("%CLASS%",this.name))}function getDisplayFn(t){function e(e){return e[t]}return t=t||"value",_.isFunction(t)?t:e}function getTemplates(t,e){function a(t){return"<p>"+e(t)+"</p>"}return{empty:t.empty&&_.templatify(t.empty),header:t.header&&_.templatify(t.header),footer:t.footer&&_.templatify(t.footer),suggestion:t.suggestion||a}}function isValidName(t){return/^[_a-zA-Z0-9-]+$/.test(t)}var datasetKey="aaDataset",valueKey="aaValue",datumKey="aaDatum",_=require("../common/utils.js"),html=require("./html.js"),css=require("./css.js"),EventEmitter=require("./event_emitter.js");Dataset.extractDatasetName=function(t){return $(t).data(datasetKey)},Dataset.extractValue=function(t){return $(t).data(valueKey)},Dataset.extractDatum=function(t){return $(t).data(datumKey)},_.mixin(Dataset.prototype,EventEmitter,{_render:function(t,e){function a(){var e=[].slice.call(arguments,0);return e=[{query:t,isEmpty:!0}].concat(e),l.templates.empty.apply(this,e)}function s(){function t(t){var e;return e=$(html.suggestion).append(l.templates.suggestion.apply(this,[t].concat(n))).data(datasetKey,l.name).data(valueKey,l.displayFn(t)).data(datumKey,t),e.children().each(function(){$(this).css(css.suggestionChild)}),e}var a,s,n=[].slice.call(arguments,0);return a=$(html.suggestions).css(css.suggestions),s=_.map(e,t),a.append.apply(a,s),a}function n(){var e=[].slice.call(arguments,0);return e=[{query:t,isEmpty:!r}].concat(e),l.templates.header.apply(this,e)}function i(){var e=[].slice.call(arguments,0);return e=[{query:t,isEmpty:!r}].concat(e),l.templates.footer.apply(this,e)}if(this.$el){var r,l=this,u=[].slice.call(arguments,2);this.$el.empty(),r=e&&e.length,!r&&this.templates.empty?this.$el.html(a.apply(this,u)).prepend(l.templates.header?n.apply(this,u):null).append(l.templates.footer?i.apply(this,u):null):r&&this.$el.html(s.apply(this,u)).prepend(l.templates.header?n.apply(this,u):null).append(l.templates.footer?i.apply(this,u):null),this.trigger("rendered")}},getRoot:function(){return this.$el},update:function(t){function e(e){if(!a.canceled&&t===a.query){var s=[].slice.call(arguments,1);s=[t,e].concat(s),a._render.apply(a,s)}}var a=this;this.query=t,this.canceled=!1,this.source(t,e)},cancel:function(){this.canceled=!0},clear:function(){this.cancel(),this.$el.empty(),this.trigger("rendered")},isEmpty:function(){return this.$el.is(":empty")},destroy:function(){this.$el=null}}),module.exports=Dataset; | ||
},{"../common/utils.js":11,"./css.js":2,"./event_emitter.js":6,"./html.js":7}],4:[function(require,module,exports){ | ||
"use strict";function Dropdown(t){var e,s,i,n=this;t=t||{},t.menu||$.error("menu is required"),this.isOpen=!1,this.isEmpty=!0,this.datasets=_.map(t.datasets,initializeDataset),e=_.bind(this._onSuggestionClick,this),s=_.bind(this._onSuggestionMouseEnter,this),i=_.bind(this._onSuggestionMouseLeave,this),this.$menu=$(t.menu).on("click.aa",".aa-suggestion",e).on("mouseenter.aa",".aa-suggestion",s).on("mouseleave.aa",".aa-suggestion",i),_.each(this.datasets,function(t){n.$menu.append(t.getRoot()),t.onSync("rendered",n._onRendered,n)})}function initializeDataset(t){return new Dropdown.Dataset(t)}var _=require("../common/utils.js"),EventEmitter=require("./event_emitter.js"),Dataset=require("./dataset.js"),css=require("./css.js");_.mixin(Dropdown.prototype,EventEmitter,{_onSuggestionClick:function(t){this.trigger("suggestionClicked",$(t.currentTarget))},_onSuggestionMouseEnter:function(t){this._removeCursor(),this._setCursor($(t.currentTarget),!0)},_onSuggestionMouseLeave:function(){this._removeCursor()},_onRendered:function(){function t(t){return t.isEmpty()}this.isEmpty=_.every(this.datasets,t),this.isEmpty?this._hide():this.isOpen&&this._show(),this.trigger("datasetRendered")},_hide:function(){this.$menu.hide()},_show:function(){this.$menu.css("display","block")},_getSuggestions:function(){return this.$menu.find(".aa-suggestion")},_getCursor:function(){return this.$menu.find(".aa-cursor").first()},_setCursor:function(t,e){t.first().addClass("aa-cursor"),e||this.trigger("cursorMoved")},_removeCursor:function(){this._getCursor().removeClass("aa-cursor")},_moveCursor:function(t){var e,s,i,n;if(this.isOpen){if(s=this._getCursor(),e=this._getSuggestions(),this._removeCursor(),i=e.index(s)+t,i=(i+1)%(e.length+1)-1,-1===i)return void this.trigger("cursorRemoved");-1>i&&(i=e.length-1),this._setCursor(n=e.eq(i)),this._ensureVisible(n)}},_ensureVisible:function(t){var e,s,i,n;e=t.position().top,s=e+t.outerHeight(!0),i=this.$menu.scrollTop(),n=this.$menu.height()+parseInt(this.$menu.css("paddingTop"),10)+parseInt(this.$menu.css("paddingBottom"),10),0>e?this.$menu.scrollTop(i+e):s>n&&this.$menu.scrollTop(i+(s-n))},close:function(){this.isOpen&&(this.isOpen=!1,this._removeCursor(),this._hide(),this.trigger("closed"))},open:function(){this.isOpen||(this.isOpen=!0,this.isEmpty||this._show(),this.trigger("opened"))},setLanguageDirection:function(t){this.$menu.css("ltr"===t?css.ltr:css.rtl)},moveCursorUp:function(){this._moveCursor(-1)},moveCursorDown:function(){this._moveCursor(1)},getDatumForSuggestion:function(t){var e=null;return t.length&&(e={raw:Dataset.extractDatum(t),value:Dataset.extractValue(t),datasetName:Dataset.extractDatasetName(t)}),e},getDatumForCursor:function(){return this.getDatumForSuggestion(this._getCursor().first())},getDatumForTopSuggestion:function(){return this.getDatumForSuggestion(this._getSuggestions().first())},update:function(t){function e(e){e.update(t)}_.each(this.datasets,e)},empty:function(){function t(t){t.clear()}_.each(this.datasets,t),this.isEmpty=!0},isVisible:function(){return this.isOpen&&!this.isEmpty},destroy:function(){function t(t){t.destroy()}this.$menu.off(".aa"),this.$menu=null,_.each(this.datasets,t)}}),Dropdown.Dataset=Dataset,module.exports=Dropdown; | ||
"use strict";function Dropdown(t){var e,s,i,n=this;t=t||{},t.menu||$.error("menu is required"),this.isOpen=!1,this.isEmpty=!0,e=_.bind(this._onSuggestionClick,this),s=_.bind(this._onSuggestionMouseEnter,this),i=_.bind(this._onSuggestionMouseLeave,this),this.$menu=$(t.menu).on("click.aa",".aa-suggestion",e).on("mouseenter.aa",".aa-suggestion",s).on("mouseleave.aa",".aa-suggestion",i),t.templates&&t.templates.header&&this.$menu.prepend(_.templatify(t.templates.header)()),this.datasets=_.map(t.datasets,function(t){return initializeDataset(n.$menu,t)}),_.each(this.datasets,function(t){var e=t.getRoot();e&&0===e.parent().length&&n.$menu.append(e),t.onSync("rendered",n._onRendered,n)}),t.templates&&t.templates.footer&&this.$menu.append(_.templatify(t.templates.footer)())}function initializeDataset(t,e){return new Dropdown.Dataset(_.mixin({$menu:t},e))}var _=require("../common/utils.js"),EventEmitter=require("./event_emitter.js"),Dataset=require("./dataset.js"),css=require("./css.js");_.mixin(Dropdown.prototype,EventEmitter,{_onSuggestionClick:function(t){this.trigger("suggestionClicked",$(t.currentTarget))},_onSuggestionMouseEnter:function(t){this._removeCursor(),this._setCursor($(t.currentTarget),!0)},_onSuggestionMouseLeave:function(){this._removeCursor()},_onRendered:function(){function t(t){return t.isEmpty()}this.isEmpty=_.every(this.datasets,t),this.isEmpty?this._hide():this.isOpen&&this._show(),this.trigger("datasetRendered")},_hide:function(){this.$menu.hide()},_show:function(){this.$menu.css("display","block")},_getSuggestions:function(){return this.$menu.find(".aa-suggestion")},_getCursor:function(){return this.$menu.find(".aa-cursor").first()},_setCursor:function(t,e){t.first().addClass("aa-cursor"),e||this.trigger("cursorMoved")},_removeCursor:function(){this._getCursor().removeClass("aa-cursor")},_moveCursor:function(t){var e,s,i,n;if(this.isOpen){if(s=this._getCursor(),e=this._getSuggestions(),this._removeCursor(),i=e.index(s)+t,i=(i+1)%(e.length+1)-1,-1===i)return void this.trigger("cursorRemoved");-1>i&&(i=e.length-1),this._setCursor(n=e.eq(i)),this._ensureVisible(n)}},_ensureVisible:function(t){var e,s,i,n;e=t.position().top,s=e+t.outerHeight(!0),i=this.$menu.scrollTop(),n=this.$menu.height()+parseInt(this.$menu.css("paddingTop"),10)+parseInt(this.$menu.css("paddingBottom"),10),0>e?this.$menu.scrollTop(i+e):s>n&&this.$menu.scrollTop(i+(s-n))},close:function(){this.isOpen&&(this.isOpen=!1,this._removeCursor(),this._hide(),this.trigger("closed"))},open:function(){this.isOpen||(this.isOpen=!0,this.isEmpty||this._show(),this.trigger("opened"))},setLanguageDirection:function(t){this.$menu.css("ltr"===t?css.ltr:css.rtl)},moveCursorUp:function(){this._moveCursor(-1)},moveCursorDown:function(){this._moveCursor(1)},getDatumForSuggestion:function(t){var e=null;return t.length&&(e={raw:Dataset.extractDatum(t),value:Dataset.extractValue(t),datasetName:Dataset.extractDatasetName(t)}),e},getDatumForCursor:function(){return this.getDatumForSuggestion(this._getCursor().first())},getDatumForTopSuggestion:function(){return this.getDatumForSuggestion(this._getSuggestions().first())},update:function(t){function e(e){e.update(t)}_.each(this.datasets,e)},empty:function(){function t(t){t.clear()}_.each(this.datasets,t),this.isEmpty=!0},isVisible:function(){return this.isOpen&&!this.isEmpty},destroy:function(){function t(t){t.destroy()}this.$menu.off(".aa"),this.$menu=null,_.each(this.datasets,t)}}),Dropdown.Dataset=Dataset,module.exports=Dropdown; | ||
},{"../common/utils.js":11,"./css.js":2,"./dataset.js":3,"./event_emitter.js":6}],5:[function(require,module,exports){ | ||
@@ -26,7 +26,7 @@ "use strict";function EventBus(e){e&&e.el||$.error("EventBus initialized without el"),this.$el=$(e.el)}var namespace="typeahead:",_=require("../common/utils.js");_.mixin(EventBus.prototype,{trigger:function(e){var t=[].slice.call(arguments,1);this.$el.trigger(namespace+e,t)}}),module.exports=EventBus; | ||
},{"../common/utils.js":11,"./event_emitter.js":6}],9:[function(require,module,exports){ | ||
"use strict";var _=require("../common/utils.js"),Typeahead=require("./typeahead.js"),EventBus=require("./event_bus.js"),old,typeaheadKey,methods;old=$.fn.typeahead,typeaheadKey="aaAutocomplete",methods={initialize:function(e,t){function a(){var a,n=$(this),i=new EventBus({el:n});a=new Typeahead({input:n,eventBus:i,withHint:_.isUndefined(e.hint)?!0:!!e.hint,minLength:e.minLength,autoselect:e.autoselect,datasets:t}),n.data(typeaheadKey,a)}return t=_.isArray(t)?t:[].slice.call(arguments,1),e=e||{},this.each(a)},open:function(){function e(){var e,t=$(this);(e=t.data(typeaheadKey))&&e.open()}return this.each(e)},close:function(){function e(){var e,t=$(this);(e=t.data(typeaheadKey))&&e.close()}return this.each(e)},val:function(e){function t(){var t,a=$(this);(t=a.data(typeaheadKey))&&t.setVal(e)}function a(e){var t,a;return(t=e.data(typeaheadKey))&&(a=t.getVal()),a}return arguments.length?this.each(t):a(this.first())},destroy:function(){function e(){var e,t=$(this);(e=t.data(typeaheadKey))&&(e.destroy(),t.removeData(typeaheadKey))}return this.each(e)}},$.fn.autocomplete=function(e){var t;return methods[e]&&"initialize"!==e?(t=this.filter(function(){return!!$(this).data(typeaheadKey)}),methods[e].apply(t,[].slice.call(arguments,1))):methods.initialize.apply(this,arguments)},$.fn.autocomplete.noConflict=function(){return $.fn.autocomplete=old,this}; | ||
"use strict";var _=require("../common/utils.js"),Typeahead=require("./typeahead.js"),EventBus=require("./event_bus.js"),old,typeaheadKey,methods;old=$.fn.typeahead,typeaheadKey="aaAutocomplete",methods={initialize:function(e,t){function a(){var a,n=$(this),i=new EventBus({el:n});a=new Typeahead({input:n,eventBus:i,hint:_.isUndefined(e.hint)?!0:!!e.hint,minLength:e.minLength,autoselect:e.autoselect,templates:e.templates,debug:e.debug,datasets:t}),n.data(typeaheadKey,a)}return t=_.isArray(t)?t:[].slice.call(arguments,1),e=e||{},this.each(a)},open:function(){function e(){var e,t=$(this);(e=t.data(typeaheadKey))&&e.open()}return this.each(e)},close:function(){function e(){var e,t=$(this);(e=t.data(typeaheadKey))&&e.close()}return this.each(e)},val:function(e){function t(){var t,a=$(this);(t=a.data(typeaheadKey))&&t.setVal(e)}function a(e){var t,a;return(t=e.data(typeaheadKey))&&(a=t.getVal()),a}return arguments.length?this.each(t):a(this.first())},destroy:function(){function e(){var e,t=$(this);(e=t.data(typeaheadKey))&&(e.destroy(),t.removeData(typeaheadKey))}return this.each(e)}},$.fn.autocomplete=function(e){var t;return methods[e]&&"initialize"!==e?(t=this.filter(function(){return!!$(this).data(typeaheadKey)}),methods[e].apply(t,[].slice.call(arguments,1))):methods.initialize.apply(this,arguments)},$.fn.autocomplete.noConflict=function(){return $.fn.autocomplete=old,this},module.exports=$.fn.autocomplete; | ||
},{"../common/utils.js":11,"./event_bus.js":5,"./typeahead.js":10}],10:[function(require,module,exports){ | ||
"use strict";function Typeahead(t){var e,n,i;t=t||{},t.input||$.error("missing input"),this.isActivated=!1,this.autoselect=!!t.autoselect,this.minLength=_.isNumber(t.minLength)?t.minLength:1,this.$node=buildDom(t.input,t.withHint),e=this.$node.find(".aa-dropdown-menu"),n=this.$node.find(".aa-input"),i=this.$node.find(".aa-hint"),n.on("blur.aa",function(t){var i,o,s;i=document.activeElement,o=e.is(i),s=e.has(i).length>0,_.isMsie()&&(o||s)&&(t.preventDefault(),t.stopImmediatePropagation(),_.defer(function(){n.focus()}))}),e.on("mousedown.aa",function(t){t.preventDefault()}),this.eventBus=t.eventBus||new EventBus({el:n}),this.dropdown=new Typeahead.Dropdown({menu:e,datasets:t.datasets}).onSync("suggestionClicked",this._onSuggestionClicked,this).onSync("cursorMoved",this._onCursorMoved,this).onSync("cursorRemoved",this._onCursorRemoved,this).onSync("opened",this._onOpened,this).onSync("closed",this._onClosed,this).onAsync("datasetRendered",this._onDatasetRendered,this),this.input=new Typeahead.Input({input:n,hint:i}).onSync("focused",this._onFocused,this).onSync("blurred",this._onBlurred,this).onSync("enterKeyed",this._onEnterKeyed,this).onSync("tabKeyed",this._onTabKeyed,this).onSync("escKeyed",this._onEscKeyed,this).onSync("upKeyed",this._onUpKeyed,this).onSync("downKeyed",this._onDownKeyed,this).onSync("leftKeyed",this._onLeftKeyed,this).onSync("rightKeyed",this._onRightKeyed,this).onSync("queryChanged",this._onQueryChanged,this).onSync("whitespaceChanged",this._onWhitespaceChanged,this),this._setLanguageDirection()}function buildDom(t,e){var n,i,o,s;n=$(t),i=$(html.wrapper).css(css.wrapper),o=$(html.dropdown).css(css.dropdown),s=n.clone().css(css.hint).css(getBackgroundStyles(n)),s.val("").removeData().addClass("aa-hint").removeAttr("id name placeholder required").prop("readonly",!0).attr({autocomplete:"off",spellcheck:"false",tabindex:-1}),n.data(attrsKey,{dir:n.attr("dir"),autocomplete:n.attr("autocomplete"),spellcheck:n.attr("spellcheck"),style:n.attr("style")}),n.addClass("aa-input").attr({autocomplete:"off",spellcheck:!1}).css(e?css.input:css.inputWithNoHint);try{n.attr("dir")||n.attr("dir","auto")}catch(r){}return n.wrap(i).parent().prepend(e?s:null).append(o)}function getBackgroundStyles(t){return{backgroundAttachment:t.css("background-attachment"),backgroundClip:t.css("background-clip"),backgroundColor:t.css("background-color"),backgroundImage:t.css("background-image"),backgroundOrigin:t.css("background-origin"),backgroundPosition:t.css("background-position"),backgroundRepeat:t.css("background-repeat"),backgroundSize:t.css("background-size")}}function destroyDomStructure(t){var e=t.find(".aa-input");_.each(e.data(attrsKey),function(t,n){_.isUndefined(t)?e.removeAttr(n):e.attr(n,t)}),e.detach().removeData(attrsKey).removeClass("aa-input").insertAfter(t),t.remove()}var attrsKey="aaAttrs",_=require("../common/utils.js"),EventBus=require("./event_bus.js"),Input=require("./input.js"),Dropdown=require("./dropdown.js"),html=require("./html.js"),css=require("./css.js");_.mixin(Typeahead.prototype,{_onSuggestionClicked:function(t,e){var n;(n=this.dropdown.getDatumForSuggestion(e))&&this._select(n)},_onCursorMoved:function(){var t=this.dropdown.getDatumForCursor();this.input.setInputValue(t.value,!0),this.eventBus.trigger("cursorchanged",t.raw,t.datasetName)},_onCursorRemoved:function(){this.input.resetInputValue(),this._updateHint()},_onDatasetRendered:function(){this._updateHint()},_onOpened:function(){this._updateHint(),this.eventBus.trigger("opened")},_onClosed:function(){this.input.clearHint(),this.eventBus.trigger("closed")},_onFocused:function(){this.isActivated=!0,this.dropdown.open()},_onBlurred:function(){this.isActivated=!1,this.dropdown.empty(),this.dropdown.close()},_onEnterKeyed:function(t,e){var n,i;n=this.dropdown.getDatumForCursor(),i=this.dropdown.getDatumForTopSuggestion(),n?(this._select(n),e.preventDefault()):this.autoselect&&i&&(this._select(i),e.preventDefault())},_onTabKeyed:function(t,e){var n;(n=this.dropdown.getDatumForCursor())?(this._select(n),e.preventDefault()):this._autocomplete(!0)},_onEscKeyed:function(){this.dropdown.close(),this.input.resetInputValue()},_onUpKeyed:function(){var t=this.input.getQuery();this.dropdown.isEmpty&&t.length>=this.minLength?this.dropdown.update(t):this.dropdown.moveCursorUp(),this.dropdown.open()},_onDownKeyed:function(){var t=this.input.getQuery();this.dropdown.isEmpty&&t.length>=this.minLength?this.dropdown.update(t):this.dropdown.moveCursorDown(),this.dropdown.open()},_onLeftKeyed:function(){"rtl"===this.dir&&this._autocomplete()},_onRightKeyed:function(){"ltr"===this.dir&&this._autocomplete()},_onQueryChanged:function(t,e){this.input.clearHintIfInvalid(),e.length>=this.minLength?this.dropdown.update(e):this.dropdown.empty(),this.dropdown.open(),this._setLanguageDirection()},_onWhitespaceChanged:function(){this._updateHint(),this.dropdown.open()},_setLanguageDirection:function(){var t=this.input.getLanguageDirection();this.dir!==t&&(this.dir=t,this.$node.css("direction",t),this.dropdown.setLanguageDirection(t))},_updateHint:function(){var t,e,n,i,o,s;t=this.dropdown.getDatumForTopSuggestion(),t&&this.dropdown.isVisible()&&!this.input.hasOverflow()?(e=this.input.getInputValue(),n=Input.normalizeQuery(e),i=_.escapeRegExChars(n),o=new RegExp("^(?:"+i+")(.+$)","i"),s=o.exec(t.value),s?this.input.setHint(e+s[1]):this.input.clearHint()):this.input.clearHint()},_autocomplete:function(t){var e,n,i,o;e=this.input.getHint(),n=this.input.getQuery(),i=t||this.input.isCursorAtEnd(),e&&n!==e&&i&&(o=this.dropdown.getDatumForTopSuggestion(),o&&this.input.setInputValue(o.value),this.eventBus.trigger("autocompleted",o.raw,o.datasetName))},_select:function(t){this.input.setQuery(t.value),this.input.setInputValue(t.value,!0),this._setLanguageDirection(),this.eventBus.trigger("selected",t.raw,t.datasetName),this.dropdown.close(),_.defer(_.bind(this.dropdown.empty,this.dropdown))},open:function(){if(!this.isActivated){var t=this.input.getInputValue();t.length>=this.minLength?this.dropdown.update(t):this.dropdown.empty()}this.dropdown.open()},close:function(){this.dropdown.close()},setVal:function(t){t=_.toStr(t),this.isActivated?this.input.setInputValue(t):(this.input.setQuery(t),this.input.setInputValue(t,!0)),this._setLanguageDirection()},getVal:function(){return this.input.getQuery()},destroy:function(){this.input.destroy(),this.dropdown.destroy(),destroyDomStructure(this.$node),this.$node=null}}),Typeahead.Dropdown=Dropdown,Typeahead.Input=Input,module.exports=Typeahead; | ||
"use strict";function Typeahead(t){var e,n,i;t=t||{},t.input||$.error("missing input"),this.isActivated=!1,this.debug=!!t.debug,this.autoselect=!!t.autoselect,this.minLength=_.isNumber(t.minLength)?t.minLength:1,this.$node=buildDom(t),e=this.$node.find(".aa-dropdown-menu"),n=this.$node.find(".aa-input"),i=this.$node.find(".aa-hint"),n.on("blur.aa",function(t){var i,o,s;i=document.activeElement,o=e.is(i),s=e.has(i).length>0,_.isMsie()&&(o||s)&&(t.preventDefault(),t.stopImmediatePropagation(),_.defer(function(){n.focus()}))}),e.on("mousedown.aa",function(t){t.preventDefault()}),this.eventBus=t.eventBus||new EventBus({el:n}),this.dropdown=new Typeahead.Dropdown({menu:e,datasets:t.datasets,templates:t.templates}).onSync("suggestionClicked",this._onSuggestionClicked,this).onSync("cursorMoved",this._onCursorMoved,this).onSync("cursorRemoved",this._onCursorRemoved,this).onSync("opened",this._onOpened,this).onSync("closed",this._onClosed,this).onAsync("datasetRendered",this._onDatasetRendered,this),this.input=new Typeahead.Input({input:n,hint:i}).onSync("focused",this._onFocused,this).onSync("blurred",this._onBlurred,this).onSync("enterKeyed",this._onEnterKeyed,this).onSync("tabKeyed",this._onTabKeyed,this).onSync("escKeyed",this._onEscKeyed,this).onSync("upKeyed",this._onUpKeyed,this).onSync("downKeyed",this._onDownKeyed,this).onSync("leftKeyed",this._onLeftKeyed,this).onSync("rightKeyed",this._onRightKeyed,this).onSync("queryChanged",this._onQueryChanged,this).onSync("whitespaceChanged",this._onWhitespaceChanged,this),this._setLanguageDirection()}function buildDom(t){var e,n,i,o;e=$(t.input),n=$(html.wrapper).css(css.wrapper),i=$(html.dropdown).css(css.dropdown),t.templates&&t.templates.dropdownMenu&&i.html(_.templatify(t.templates.dropdownMenu)()),o=e.clone().css(css.hint).css(getBackgroundStyles(e)),o.val("").removeData().addClass("aa-hint").removeAttr("id name placeholder required").prop("readonly",!0).attr({autocomplete:"off",spellcheck:"false",tabindex:-1}),e.data(attrsKey,{dir:e.attr("dir"),autocomplete:e.attr("autocomplete"),spellcheck:e.attr("spellcheck"),style:e.attr("style")}),e.addClass("aa-input").attr({autocomplete:"off",spellcheck:!1}).css(t.hint?css.input:css.inputWithNoHint);try{e.attr("dir")||e.attr("dir","auto")}catch(s){}return e.wrap(n).parent().prepend(t.hint?o:null).append(i)}function getBackgroundStyles(t){return{backgroundAttachment:t.css("background-attachment"),backgroundClip:t.css("background-clip"),backgroundColor:t.css("background-color"),backgroundImage:t.css("background-image"),backgroundOrigin:t.css("background-origin"),backgroundPosition:t.css("background-position"),backgroundRepeat:t.css("background-repeat"),backgroundSize:t.css("background-size")}}function destroyDomStructure(t){var e=t.find(".aa-input");_.each(e.data(attrsKey),function(t,n){_.isUndefined(t)?e.removeAttr(n):e.attr(n,t)}),e.detach().removeData(attrsKey).removeClass("aa-input").insertAfter(t),t.remove()}var attrsKey="aaAttrs",_=require("../common/utils.js"),EventBus=require("./event_bus.js"),Input=require("./input.js"),Dropdown=require("./dropdown.js"),html=require("./html.js"),css=require("./css.js");_.mixin(Typeahead.prototype,{_onSuggestionClicked:function(t,e){var n;(n=this.dropdown.getDatumForSuggestion(e))&&this._select(n)},_onCursorMoved:function(){var t=this.dropdown.getDatumForCursor();this.input.setInputValue(t.value,!0),this.eventBus.trigger("cursorchanged",t.raw,t.datasetName)},_onCursorRemoved:function(){this.input.resetInputValue(),this._updateHint()},_onDatasetRendered:function(){this._updateHint()},_onOpened:function(){this._updateHint(),this.eventBus.trigger("opened")},_onClosed:function(){this.input.clearHint(),this.eventBus.trigger("closed")},_onFocused:function(){this.isActivated=!0,this.dropdown.open()},_onBlurred:function(){this.debug||(this.isActivated=!1,this.dropdown.empty(),this.dropdown.close())},_onEnterKeyed:function(t,e){var n,i;n=this.dropdown.getDatumForCursor(),i=this.dropdown.getDatumForTopSuggestion(),n?(this._select(n),e.preventDefault()):this.autoselect&&i&&(this._select(i),e.preventDefault())},_onTabKeyed:function(t,e){var n;(n=this.dropdown.getDatumForCursor())?(this._select(n),e.preventDefault()):this._autocomplete(!0)},_onEscKeyed:function(){this.dropdown.close(),this.input.resetInputValue()},_onUpKeyed:function(){var t=this.input.getQuery();this.dropdown.isEmpty&&t.length>=this.minLength?this.dropdown.update(t):this.dropdown.moveCursorUp(),this.dropdown.open()},_onDownKeyed:function(){var t=this.input.getQuery();this.dropdown.isEmpty&&t.length>=this.minLength?this.dropdown.update(t):this.dropdown.moveCursorDown(),this.dropdown.open()},_onLeftKeyed:function(){"rtl"===this.dir&&this._autocomplete()},_onRightKeyed:function(){"ltr"===this.dir&&this._autocomplete()},_onQueryChanged:function(t,e){this.input.clearHintIfInvalid(),e.length>=this.minLength?this.dropdown.update(e):this.dropdown.empty(),this.dropdown.open(),this._setLanguageDirection()},_onWhitespaceChanged:function(){this._updateHint(),this.dropdown.open()},_setLanguageDirection:function(){var t=this.input.getLanguageDirection();this.dir!==t&&(this.dir=t,this.$node.css("direction",t),this.dropdown.setLanguageDirection(t))},_updateHint:function(){var t,e,n,i,o,s;t=this.dropdown.getDatumForTopSuggestion(),t&&this.dropdown.isVisible()&&!this.input.hasOverflow()?(e=this.input.getInputValue(),n=Input.normalizeQuery(e),i=_.escapeRegExChars(n),o=new RegExp("^(?:"+i+")(.+$)","i"),s=o.exec(t.value),s?this.input.setHint(e+s[1]):this.input.clearHint()):this.input.clearHint()},_autocomplete:function(t){var e,n,i,o;e=this.input.getHint(),n=this.input.getQuery(),i=t||this.input.isCursorAtEnd(),e&&n!==e&&i&&(o=this.dropdown.getDatumForTopSuggestion(),o&&this.input.setInputValue(o.value),this.eventBus.trigger("autocompleted",o.raw,o.datasetName))},_select:function(t){this.input.setQuery(t.value),this.input.setInputValue(t.value,!0),this._setLanguageDirection(),this.eventBus.trigger("selected",t.raw,t.datasetName),this.dropdown.close(),_.defer(_.bind(this.dropdown.empty,this.dropdown))},open:function(){if(!this.isActivated){var t=this.input.getInputValue();t.length>=this.minLength?this.dropdown.update(t):this.dropdown.empty()}this.dropdown.open()},close:function(){this.dropdown.close()},setVal:function(t){t=_.toStr(t),this.isActivated?this.input.setInputValue(t):(this.input.setQuery(t),this.input.setInputValue(t,!0)),this._setLanguageDirection()},getVal:function(){return this.input.getQuery()},destroy:function(){this.input.destroy(),this.dropdown.destroy(),destroyDomStructure(this.$node),this.$node=null}}),Typeahead.Dropdown=Dropdown,Typeahead.Input=Input,module.exports=Typeahead; | ||
},{"../common/utils.js":11,"./css.js":2,"./dropdown.js":4,"./event_bus.js":5,"./html.js":7,"./input.js":8}],11:[function(require,module,exports){ | ||
"use strict";module.exports={isMsie:function(){return/(msie|trident)/i.test(navigator.userAgent)?navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2]:!1},isBlankString:function(n){return!n||/^\s*$/.test(n)},escapeRegExChars:function(n){return n.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isString:function(n){return"string"==typeof n},isNumber:function(n){return"number"==typeof n},isArray:$.isArray,isFunction:$.isFunction,isObject:$.isPlainObject,isUndefined:function(n){return"undefined"==typeof n},toStr:function(n){return this.isUndefined(n)||null===n?"":n+""},bind:$.proxy,each:function(n,t){function e(n,e){return t(e,n)}$.each(n,e)},map:$.map,filter:$.grep,every:function(n,t){var e=!0;return n?($.each(n,function(r,i){return e=t.call(null,i,r,n),e?void 0:!1}),!!e):e},some:function(n,t){var e=!1;return n?($.each(n,function(r,i){return(e=t.call(null,i,r,n))?!1:void 0}),!!e):e},mixin:$.extend,getUniqueId:function(){var n=0;return function(){return n++}}(),templatify:function(n){function t(){return String(n)}return $.isFunction(n)?n:t},defer:function(n){setTimeout(n,0)},debounce:function(n,t,e){var r,i;return function(){var u,o,c=this,a=arguments;return u=function(){r=null,e||(i=n.apply(c,a))},o=e&&!r,clearTimeout(r),r=setTimeout(u,t),o&&(i=n.apply(c,a)),i}},throttle:function(n,t){var e,r,i,u,o,c;return o=0,c=function(){o=new Date,i=null,u=n.apply(e,r)},function(){var a=new Date,s=t-(a-o);return e=this,r=arguments,0>=s?(clearTimeout(i),i=null,o=a,u=n.apply(e,r)):i||(i=setTimeout(c,s)),u}},noop:function(){}}; | ||
"use strict";module.exports={isMsie:function(){return/(msie|trident)/i.test(navigator.userAgent)?navigator.userAgent.match(/(msie |rv:)(\d+(.\d+)?)/i)[2]:!1},escapeRegExChars:function(n){return n.replace(/[\-\[\]\/\{\}\(\)\*\+\?\.\\\^\$\|]/g,"\\$&")},isNumber:function(n){return"number"==typeof n},isArray:$.isArray,isFunction:$.isFunction,isObject:$.isPlainObject,isUndefined:function(n){return"undefined"==typeof n},toStr:function(n){return this.isUndefined(n)||null===n?"":n+""},bind:$.proxy,each:function(n,t){function e(n,e){return t(e,n)}$.each(n,e)},map:$.map,filter:$.grep,every:function(n,t){var e=!0;return n?($.each(n,function(r,i){return e=t.call(null,i,r,n),e?void 0:!1}),!!e):e},mixin:$.extend,getUniqueId:function(){var n=0;return function(){return n++}}(),templatify:function(n){if($.isFunction(n))return n;var t=$(n);return"SCRIPT"===t.prop("tagName")?function(){return t.text()}:function(){return String(n)}},defer:function(n){setTimeout(n,0)},noop:function(){}}; | ||
},{}]},{},[1]); |
@@ -15,7 +15,12 @@ 'use strict'; | ||
type: 'lcov', | ||
dir: 'test/coverage/' | ||
dir: 'coverage/' | ||
}, | ||
browserify: { | ||
debug: true, | ||
transform: ['browserify-istanbul'] | ||
}, | ||
preprocessors: { | ||
'src/**/*.js': 'coverage', | ||
'src/**/*.js': ['browserify', 'coverage'], | ||
'test/**/*_spec.js': 'browserify' | ||
@@ -27,2 +32,3 @@ }, | ||
'node_modules/jasmine-jquery/lib/jasmine-jquery.js', | ||
'src/**/*.js', | ||
'test/**/*_spec.js' | ||
@@ -29,0 +35,0 @@ ] |
@@ -5,4 +5,4 @@ { | ||
"keywords": [ | ||
"typeahead", | ||
"autocomplete" | ||
"autocomplete", | ||
"typeahead" | ||
], | ||
@@ -20,2 +20,3 @@ "homepage": "https://github.com/algolia/autocomplete.js", | ||
"devDependencies": { | ||
"browserify-istanbul": "^0.2.1", | ||
"chai": "^3.0.0", | ||
@@ -43,3 +44,3 @@ "colors": "^1.1.2", | ||
"karma-chrome-launcher": "^0.2.0", | ||
"karma-coverage": "^0.4.2", | ||
"karma-coverage": "0.2.6", | ||
"karma-coveralls": "^1.1.2", | ||
@@ -59,4 +60,4 @@ "karma-firefox-launcher": "^0.1.6", | ||
}, | ||
"version": "0.0.1", | ||
"version": "0.0.2", | ||
"main": "index.js" | ||
} |
209
README.md
@@ -8,3 +8,3 @@ Autocomplete.js | ||
[![NPM version](https://badge.fury.io/js/autocomplete.js.svg)](http://badge.fury.io/js/autocomplete.js) | ||
[![Coverage Status](https://coveralls.io/repos/algolia/autocomplete.js/badge.png?branch=master)](https://coveralls.io/r/algolia/autocomplete.js?branch=master) | ||
[![Coverage Status](https://coveralls.io/repos/algolia/autocomplete.js/badge.svg?branch=master)](https://coveralls.io/r/algolia/autocomplete.js?branch=master) | ||
@@ -24,3 +24,3 @@ | ||
* [Look and Feel](#look-and-feel) | ||
* [Specification](#specification) | ||
* [Development](#development) | ||
* [Testing](#testing) | ||
@@ -120,2 +120,66 @@ * [Credits](#credits) | ||
* `templates` – An optional hash overriding the default templates. | ||
* `dropdownMenu` – the dropdown menu template. The template should include all *dataset* placeholders. | ||
* `header` – the header to prepend to the dropdown menu | ||
* `footer` – the footer to append to the dropdown menu | ||
```html | ||
<script type="text/template" id="my-custom-menu-template"> | ||
<div class="my-custom-menu"> | ||
<div class="row"> | ||
<div class="col-sm-6"> | ||
<div class="aa-dataset-contacts1"></div> | ||
</div> | ||
<div class="col-sm-6"> | ||
<div class="aa-dataset-contacts2"></div> | ||
<div class="aa-dataset-contacts3"></div> | ||
</div> | ||
</div> | ||
</div> | ||
</script> | ||
<script> | ||
$('#search-input').autocomplete( | ||
{ | ||
templates: { | ||
dropdownMenu: '#my-custom-menu-template', | ||
footer: '<div class="branding">Powered by <img src="https://www.algolia.com/assets/algolia128x40.png" /></div>' | ||
} | ||
}, | ||
[ | ||
{ | ||
source: index.ttAdapter({ hitsPerPage: 5 }), | ||
name: 'contacts1', | ||
templates: { | ||
header: '<h4>List 1</h4>', | ||
suggestion: function(suggestion) { | ||
// FIXME | ||
} | ||
} | ||
}, | ||
{ | ||
source: index.ttAdapter({ hitsPerPage: 2 }), | ||
name: 'contacts2', | ||
templates: { | ||
header: '<h4>List 2</h4>', | ||
suggestion: function(suggestion) { | ||
// FIXME | ||
} | ||
} | ||
}, | ||
{ | ||
source: index.ttAdapter({ hitsPerPage: 2 }), | ||
name: 'contacts3', | ||
templates: { | ||
header: '<h4>List 3</h4>', | ||
suggestion: function(suggestion, answer) { | ||
// FIXME | ||
} | ||
} | ||
} | ||
] | ||
); | ||
</script> | ||
``` | ||
* `minLength` – The minimum character length needed before suggestions start | ||
@@ -226,140 +290,19 @@ getting rendered. Defaults to `1`. | ||
Specification | ||
------------- | ||
Development | ||
----------- | ||
In an effort to take advantage of the pre-existing knowledge of autocomplete.js | ||
users, the behavior of the typeahead.js UI is modeled after google.com's search | ||
box. Below is pseudocode that details how the UI reacts to pertinent events. | ||
The project is built using [Grunt](http://gruntjs.com/). To start developing, you can use the following commands: | ||
**Input Control Gains Focus** | ||
```sh | ||
$ npm install | ||
$ grunt dev | ||
$ open http://localhost:8888/test/playground.html | ||
``` | ||
activate typeahead | ||
``` | ||
**Input Control Loses Focus** | ||
[eslint](http://eslint.org/) is used to lint the code based on [Algolia's configuration](https://github.com/algolia/eslint-config-algolia). | ||
```sh | ||
$ grunt lint | ||
``` | ||
deactivate typeahead | ||
close dropdown menu | ||
remove hint | ||
clear suggestions from dropdown menu | ||
``` | ||
**Value of the Input Control Changes** | ||
``` | ||
IF query satisfies minLength requirement THEN | ||
request suggestions for new query | ||
IF suggestions are available THEN | ||
render suggestions in dropdown menu | ||
open dropdown menu | ||
update hint | ||
ELSE | ||
close dropdown menu | ||
clear suggestions from dropdown menu | ||
remove hint | ||
ENDIF | ||
ELSE | ||
close dropdown menu | ||
clear suggestions from dropdown menu | ||
remove hint | ||
ENDIF | ||
``` | ||
**Up Arrow is Keyed** | ||
``` | ||
IF dropdown menu is open THEN | ||
move dropdown menu cursor up 1 suggestion | ||
ELSE | ||
request suggestions for current query | ||
IF suggestions are available THEN | ||
render suggestions in dropdown menu | ||
open dropdown menu | ||
update hint | ||
ENDIF | ||
ENDIF | ||
``` | ||
**Down Arrow is Keyed** | ||
``` | ||
IF dropdown menu is open THEN | ||
move dropdown menu cursor down 1 suggestion | ||
ELSE | ||
request suggestions for current query | ||
IF suggestions are available THEN | ||
render suggestions in dropdown menu | ||
open dropdown menu | ||
update hint | ||
ENDIF | ||
ENDIF | ||
``` | ||
**Left Arrow is Keyed** | ||
``` | ||
IF detected query language direction is right-to-left THEN | ||
IF hint is being shown THEN | ||
IF text cursor is at end of query THEN | ||
autocomplete query to hint | ||
ENDIF | ||
ENDIF | ||
ENDIF | ||
``` | ||
**Right Arrow is Keyed** | ||
``` | ||
IF detected query language direction is left-to-right THEN | ||
IF hint is being shown THEN | ||
IF text cursor is at the end of the query THEN | ||
autocomplete query to hint | ||
ENDIF | ||
ENDIF | ||
ENDIF | ||
``` | ||
**Tab is Keyed** | ||
``` | ||
IF dropdown menu cursor is on suggestion THEN | ||
close dropdown menu | ||
update query to display key of suggestion | ||
remove hint | ||
ELSIF hint is being shown THEN | ||
autocomplete query to hint | ||
ENDIF | ||
``` | ||
**Enter is Keyed** | ||
``` | ||
IF dropdown menu cursor is on suggestion THEN | ||
close dropdown menu | ||
update query to display key of suggestion | ||
remove hint | ||
prevent default browser action e.g. form submit | ||
ENDIF | ||
``` | ||
**Esc is Keyed** | ||
``` | ||
close dropdown menu | ||
remove hint | ||
``` | ||
**Suggestion is Clicked** | ||
``` | ||
update query to display key of suggestion | ||
close dropdown menu | ||
remove hint | ||
``` | ||
Testing | ||
@@ -366,0 +309,0 @@ ------ |
@@ -40,3 +40,4 @@ 'use strict'; | ||
this.$el = $(html.dataset.replace('%CLASS%', this.name)); | ||
this.$el = o.$menu && o.name && o.$menu.find('.aa-dataset-' + o.name).length > 0 ? | ||
$(o.$menu.find('.aa-dataset-' + o.name)[0]) : $(html.dataset.replace('%CLASS%', this.name)); | ||
} | ||
@@ -43,0 +44,0 @@ |
@@ -28,4 +28,2 @@ 'use strict'; | ||
this.datasets = _.map(o.datasets, initializeDataset); | ||
// bound functions | ||
@@ -41,6 +39,18 @@ onSuggestionClick = _.bind(this._onSuggestionClick, this); | ||
if (o.templates && o.templates.header) { | ||
this.$menu.prepend((_.templatify(o.templates.header))()); | ||
} | ||
this.datasets = _.map(o.datasets, function(oDataset) { return initializeDataset(that.$menu, oDataset); }); | ||
_.each(this.datasets, function(dataset) { | ||
that.$menu.append(dataset.getRoot()); | ||
var root = dataset.getRoot(); | ||
if (root && root.parent().length === 0) { | ||
that.$menu.append(root); | ||
} | ||
dataset.onSync('rendered', that._onRendered, that); | ||
}); | ||
if (o.templates && o.templates.footer) { | ||
this.$menu.append((_.templatify(o.templates.footer))()); | ||
} | ||
} | ||
@@ -255,6 +265,6 @@ | ||
function initializeDataset(oDataset) { | ||
return new Dropdown.Dataset(oDataset); | ||
function initializeDataset($menu, oDataset) { | ||
return new Dropdown.Dataset(_.mixin({ '$menu': $menu }, oDataset)); | ||
} | ||
module.exports = Dropdown; |
@@ -37,5 +37,7 @@ 'use strict'; | ||
eventBus: eventBus, | ||
withHint: _.isUndefined(o.hint) ? true : !!o.hint, | ||
hint: _.isUndefined(o.hint) ? true : !!o.hint, | ||
minLength: o.minLength, | ||
autoselect: o.autoselect, | ||
templates: o.templates, | ||
debug: o.debug, | ||
datasets: datasets | ||
@@ -131,1 +133,3 @@ }); | ||
}; | ||
module.exports = $.fn.autocomplete; |
@@ -30,5 +30,6 @@ 'use strict'; | ||
this.isActivated = false; | ||
this.debug = !!o.debug; | ||
this.autoselect = !!o.autoselect; | ||
this.minLength = _.isNumber(o.minLength) ? o.minLength : 1; | ||
this.$node = buildDom(o.input, o.withHint); | ||
this.$node = buildDom(o); | ||
@@ -66,3 +67,3 @@ $menu = this.$node.find('.aa-dropdown-menu'); | ||
this.dropdown = new Typeahead.Dropdown({menu: $menu, datasets: o.datasets}) | ||
this.dropdown = new Typeahead.Dropdown({menu: $menu, datasets: o.datasets, templates: o.templates}) | ||
.onSync('suggestionClicked', this._onSuggestionClicked, this) | ||
@@ -141,5 +142,7 @@ .onSync('cursorMoved', this._onCursorMoved, this) | ||
_onBlurred: function onBlurred() { | ||
this.isActivated = false; | ||
this.dropdown.empty(); | ||
this.dropdown.close(); | ||
if (!this.debug) { | ||
this.isActivated = false; | ||
this.dropdown.empty(); | ||
this.dropdown.close(); | ||
} | ||
}, | ||
@@ -356,3 +359,3 @@ | ||
function buildDom(input, withHint) { | ||
function buildDom(options) { | ||
var $input; | ||
@@ -363,5 +366,8 @@ var $wrapper; | ||
$input = $(input); | ||
$input = $(options.input); | ||
$wrapper = $(html.wrapper).css(css.wrapper); | ||
$dropdown = $(html.dropdown).css(css.dropdown); | ||
if (options.templates && options.templates.dropdownMenu) { | ||
$dropdown.html((_.templatify(options.templates.dropdownMenu))()); | ||
} | ||
$hint = $input.clone().css(css.hint).css(getBackgroundStyles($input)); | ||
@@ -389,3 +395,3 @@ | ||
.attr({autocomplete: 'off', spellcheck: false}) | ||
.css(withHint ? css.input : css.inputWithNoHint); | ||
.css(options.hint ? css.input : css.inputWithNoHint); | ||
@@ -404,3 +410,3 @@ // ie7 does not like it when dir is set to auto | ||
.parent() | ||
.prepend(withHint ? $hint : null) | ||
.prepend(options.hint ? $hint : null) | ||
.append($dropdown); | ||
@@ -407,0 +413,0 @@ } |
@@ -12,4 +12,2 @@ 'use strict'; | ||
isBlankString: function(str) { return !str || /^\s*$/.test(str); }, | ||
// http://stackoverflow.com/a/6969486 | ||
@@ -20,4 +18,2 @@ escapeRegExChars: function(str) { | ||
isString: function(obj) { return typeof obj === 'string'; }, | ||
isNumber: function(obj) { return typeof obj === 'number'; }, | ||
@@ -65,16 +61,2 @@ | ||
some: function(obj, test) { | ||
var result = false; | ||
if (!obj) { return result; } | ||
$.each(obj, function(key, val) { | ||
if (result = test.call(null, val, key, obj)) { | ||
return false; | ||
} | ||
}); | ||
return !!result; | ||
}, | ||
mixin: $.extend, | ||
@@ -88,5 +70,10 @@ | ||
templatify: function templatify(obj) { | ||
return $.isFunction(obj) ? obj : template; | ||
function template() { return String(obj); } | ||
if ($.isFunction(obj)) { | ||
return obj; | ||
} | ||
var $template = $(obj); | ||
if ($template.prop('tagName') === 'SCRIPT') { | ||
return function template() { return $template.text() }; | ||
} | ||
return function template() { return String(obj); }; | ||
}, | ||
@@ -96,64 +83,3 @@ | ||
debounce: function(func, wait, immediate) { | ||
var timeout; | ||
var result; | ||
return function() { | ||
var context = this; | ||
var args = arguments; | ||
var later; | ||
var callNow; | ||
later = function() { | ||
timeout = null; | ||
if (!immediate) { result = func.apply(context, args); } | ||
}; | ||
callNow = immediate && !timeout; | ||
clearTimeout(timeout); | ||
timeout = setTimeout(later, wait); | ||
if (callNow) { result = func.apply(context, args); } | ||
return result; | ||
}; | ||
}, | ||
throttle: function(func, wait) { | ||
var context; | ||
var args; | ||
var timeout; | ||
var result; | ||
var previous; | ||
var later; | ||
previous = 0; | ||
later = function() { | ||
previous = new Date(); | ||
timeout = null; | ||
result = func.apply(context, args); | ||
}; | ||
return function() { | ||
var now = new Date(); | ||
var remaining = wait - (now - previous); | ||
context = this; | ||
args = arguments; | ||
if (remaining <= 0) { | ||
clearTimeout(timeout); | ||
timeout = null; | ||
previous = now; | ||
result = func.apply(context, args); | ||
} else if (!timeout) { | ||
timeout = setTimeout(later, remaining); | ||
} | ||
return result; | ||
}; | ||
}, | ||
noop: function() {} | ||
}; |
@@ -24,2 +24,17 @@ var fixtures = {}; | ||
menu: '<span class="aa-dropdown-menu"></span>', | ||
customMenu: [ | ||
'<script type="text/template" id="my-custom-menu-template">', | ||
'<div class="my-custom-menu">', | ||
'<div class="row">', | ||
'<div class="col-sm-6">', | ||
'<div class="aa-dataset-contacts1"></div>', | ||
'</div>', | ||
'<div class="col-sm-6">', | ||
'<div class="aa-dataset-contacts2"></div>', | ||
'<div class="aa-dataset-contacts3"></div>', | ||
'</div>', | ||
'</div>', | ||
'</div>', | ||
'</script>' | ||
].join(''), | ||
dataset: [ | ||
@@ -26,0 +41,0 @@ '<div class="aa-dataset-test">', |
@@ -40,2 +40,5 @@ 'use strict'; | ||
// have some datasets methods call through | ||
instance.getRoot && instance.getRoot.and.callFake(function() { return $('<span class="aa-dataset-fake" />'); }); | ||
instance.constructor = Constructor; | ||
@@ -42,0 +45,0 @@ |
@@ -47,2 +47,24 @@ 'use strict'; | ||
describe('when instantiated with a custom header or footer', function() { | ||
beforeEach(function() { | ||
this.view.destroy(); | ||
this.view = new Dropdown({ | ||
menu: this.$menu, | ||
datasets: [{}], | ||
templates: { | ||
header: '<h2 class="header">Header</h2>', | ||
footer: '<h2 class="footer">Footer</h2>' | ||
} | ||
}); | ||
}); | ||
it('should include the header', function() { | ||
expect(this.$menu.find('h2.header').length).toEqual(1); | ||
}); | ||
it('should include the footer', function() { | ||
expect(this.$menu.find('h2.footer').length).toEqual(1); | ||
}); | ||
}); | ||
describe('when mouseenter is triggered on a suggestion', function() { | ||
@@ -49,0 +71,0 @@ it('should remove pre-existing cursor', function() { |
@@ -6,3 +6,5 @@ 'use strict'; | ||
global.$ = require('jquery'); | ||
var Typeahead = require('../../src/autocomplete/typeahead.js'); | ||
var $autocomplete = require('../../src/autocomplete/plugin.js'); | ||
var fixtures = require('../fixtures.js'); | ||
@@ -30,3 +32,3 @@ var mocks = require('../helpers/mocks.js'); | ||
input: this.$input, | ||
withHint: true, | ||
hint: true, | ||
datasets: {} | ||
@@ -197,2 +199,31 @@ }); | ||
describe('when debug flag is set', function() { | ||
beforeEach(function() { | ||
this.view = new Typeahead({ | ||
input: this.$input, | ||
debug: true, | ||
hint: true, | ||
datasets: {} | ||
}); | ||
this.input = this.view.input; | ||
}); | ||
describe('when input triggers blurred', function() { | ||
it('should not empty the dropdown', function() { | ||
this.input.trigger('blurred'); | ||
expect(this.dropdown.empty).not.toHaveBeenCalled(); | ||
}); | ||
it('should not close the dropdown', function() { | ||
this.input.trigger('blurred'); | ||
expect(this.dropdown.close).not.toHaveBeenCalled(); | ||
}); | ||
}); | ||
}); | ||
describe('when input triggers enterKeyed', function() { | ||
@@ -592,2 +623,54 @@ beforeEach(function() { | ||
}); | ||
describe('when instantiated with a custom menu template', function() { | ||
beforeEach(function() { | ||
appendSetFixtures(fixtures.html.customMenu); | ||
this.view.destroy(); | ||
this.view = new Typeahead({ | ||
input: this.$input, | ||
templates: { | ||
dropdownMenu: '#my-custom-menu-template' | ||
}, | ||
datasets: {} | ||
}); | ||
}); | ||
it('should include the template in the menu', function() { | ||
var $fixture = $('#jasmine-fixtures'); | ||
expect($fixture.find('.aa-dropdown-menu .my-custom-menu').length).toEqual(1); | ||
}); | ||
}); | ||
describe('when instantiated from jquery', function() { | ||
beforeEach(function() { | ||
this.view.destroy(); | ||
this.view = $autocomplete.call($('input'), {}, { | ||
name: 'test', | ||
source: function(q, cb) { | ||
cb([ { name: 'test' } ]); | ||
}, | ||
templates: { | ||
suggestion: function(sugg) { | ||
return sugg.name; | ||
} | ||
} | ||
}).data('aaAutocomplete'); | ||
}); | ||
it('should initialize', function() { | ||
var $fixture = $('#jasmine-fixtures'); | ||
expect($fixture.find('.aa-dropdown-menu').length).toEqual(1); | ||
}); | ||
it('should open the dropdown', function() { | ||
var $fixture = $('#jasmine-fixtures'); | ||
this.view.input.getInputValue.and.returnValue('test'); | ||
$autocomplete.call($('input'), 'val', 'test'); | ||
$autocomplete.call($('input'), 'open'); | ||
$autocomplete.call($('input'), 'close'); | ||
}); | ||
}); | ||
}); |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
203222
36
4726
34
328