diff --git a/auto-complete.css b/auto-complete.css index 4261b1d..634abaa 100644 --- a/auto-complete.css +++ b/auto-complete.css @@ -4,6 +4,6 @@ /* core styles should not be changed */ position: absolute; display: none; z-index: 9999; max-height: 254px; overflow: hidden; overflow-y: auto; box-sizing: border-box; } -.autocomplete-suggestion { position: relative; padding: 0 .6em; line-height: 23px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 1.02em; color: #333; } +.autocomplete-suggestion, .noresults-suggestion { position: relative; padding: 0 .6em; line-height: 23px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 1.02em; color: #333; } .autocomplete-suggestion b { font-weight: normal; color: #1f8dd6; } .autocomplete-suggestion.selected { background: #f0f0f0; } diff --git a/auto-complete.js b/auto-complete.js index 2f5a88c..b3d84aa 100644 --- a/auto-complete.js +++ b/auto-complete.js @@ -43,7 +43,12 @@ var autoComplete = (function(){ var re = new RegExp("(" + search.split(' ').join('|') + ")", "gi"); return '
' + item.replace(re, "$1") + '
'; }, - onSelect: function(e, term, item){} + onSelect: function(e, term, item){}, + renderNoResults: function() { return '
No results returned
'; }, + preventSource: function(val){ return false;}, + sourcePrevented: function(val) {}, + widthScale: 1, + valueFilter: function(val, lastVal) { return val; } }; for (var k in options) { if (options.hasOwnProperty(k)) o[k] = options[k]; } @@ -65,7 +70,7 @@ var autoComplete = (function(){ var rect = that.getBoundingClientRect(); that.sc.style.left = Math.round(rect.left + (window.pageXOffset || document.documentElement.scrollLeft) + o.offsetLeft) + 'px'; that.sc.style.top = Math.round(rect.bottom + (window.pageYOffset || document.documentElement.scrollTop) + o.offsetTop) + 'px'; - that.sc.style.width = Math.round(rect.right - rect.left) + 'px'; // outerWidth + that.sc.style.width = (o.widthScale * Math.round(rect.right - rect.left)) + 'px'; // outerWidth if (!resize) { that.sc.style.display = 'block'; if (!that.sc.maxHeight) { that.sc.maxHeight = parseInt((window.getComputedStyle ? getComputedStyle(that.sc, null) : that.sc.currentStyle).maxHeight); } @@ -84,7 +89,7 @@ var autoComplete = (function(){ addEvent(window, 'resize', that.updateSC); document.body.appendChild(that.sc); - live('autocomplete-suggestion', 'mouseleave', function(e){ + live('autocomplete-suggestion', 'mouseout', function(e){ var sel = that.sc.querySelector('.autocomplete-suggestion.selected'); if (sel) setTimeout(function(){ sel.className = sel.className.replace('selected', ''); }, 20); }, that.sc); @@ -97,7 +102,7 @@ var autoComplete = (function(){ live('autocomplete-suggestion', 'mousedown', function(e){ if (hasClass(this, 'autocomplete-suggestion')) { // else outside click - var v = this.getAttribute('data-val'); + var v = o.valueFilter(this.getAttribute('data-val'), that.value); that.value = v; o.onSelect(e, v, this); that.sc.style.display = 'none'; @@ -123,8 +128,7 @@ var autoComplete = (function(){ that.sc.innerHTML = s; that.updateSC(0); } - else - that.sc.style.display = 'none'; + else that.sc.innerHTML = o.renderNoResults(); } that.keydownHandler = function(e){ @@ -135,15 +139,15 @@ var autoComplete = (function(){ if (!sel) { next = (key == 40) ? that.sc.querySelector('.autocomplete-suggestion') : that.sc.childNodes[that.sc.childNodes.length - 1]; // first : last next.className += ' selected'; - that.value = next.getAttribute('data-val'); + that.value = o.valueFilter(next.getAttribute('data-val'), that.value); } else { next = (key == 40) ? sel.nextSibling : sel.previousSibling; if (next) { sel.className = sel.className.replace('selected', ''); next.className += ' selected'; - that.value = next.getAttribute('data-val'); + that.value = o.valueFilter(next.getAttribute('data-val'), that.value); } - else { sel.className = sel.className.replace('selected', ''); that.value = that.last_val; next = 0; } + else { sel.className = sel.className.replace('selected', ''); that.value = o.valueFilter(that.last_val, that.val); next = 0; } } that.updateSC(0, next); return false; @@ -168,13 +172,19 @@ var autoComplete = (function(){ clearTimeout(that.timer); if (o.cache) { if (val in that.cache) { suggest(that.cache[val]); return; } - // no requests if previous suggestions were empty - for (var i=1; iSettings delay150The delay in milliseconds between when a keystroke occurs and when a search is performed. A zero-delay is more responsive, but can produce a lot of load. offsetLeft0Optional left offset of the suggestions container. offsetTop1Optional top offset of the suggestions container. - cachetrueDetermines if performed searches should be cached. + cache1Determines if performed searches should be cached. Falsy values turn caching off, 1 turns on (legacy) non-strict cache-checking, any other numeric values turn on strict cache-checking. menuClass'' Custom class/es that get/s added to the dropdown menu container. @@ -127,6 +127,19 @@

Settings

} + + renderNoResultfunction + +

A function that gives you control over what is displayed when there are no results to suggest. Default:

+
renderNoResults: function(){
+    return '<div class="noresults-suggestion">No results returned</div>';
+}
+ + + + widthScale1 +

Optional coefficient applied to base suggestion width.

+   Callbacks @@ -136,6 +149,21 @@

Settings

term is the selected value. and item is the item rendered by the renderItem function. + preventSource(val) + A callback function that fires before the source function would normally be called to evaluate conditions, and should return a truthy value. + val is the currently entered value. + + sourcePrevented(val) + A callback function that fires when the preventSource function returns true and the source function is prevented. + val is the value previously passed to preventSource. + + + valueFilter(val, lastVal) + A callback function that fires prior to onSelect, allowing exact specification of how the new value should be handled, to provide to onSelect. + val is the new value from the last selection. + lastVal is the value currently stored. + valueFilter should return the appropriate value to be stored. +   Public Methods @@ -276,6 +304,12 @@

Advanced suggestions handling and custom layout

for (i=0;i