@tarekraafat/autocomplete.js
Advanced tools
Comparing version 4.0.0 to 5.0.0
@@ -39,3 +39,3 @@ (function (global, factory) { | ||
var createResultsList = function createResultsList(renderResults) { | ||
var resultsList = document.createElement("ul"); | ||
var resultsList = document.createElement(renderResults.element); | ||
if (renderResults.container) { | ||
@@ -51,5 +51,5 @@ select.resultsList = renderResults.container(resultsList) || select.resultsList; | ||
}; | ||
var addResultsToList = function addResultsToList(resultsList, dataSrc, dataKey, callback) { | ||
var addResultsToList = function addResultsToList(resultsList, dataSrc, resultItem) { | ||
dataSrc.forEach(function (event, record) { | ||
var result = document.createElement("li"); | ||
var result = document.createElement(resultItem.element); | ||
var resultValue = dataSrc[record].value[event.key] || dataSrc[record].value; | ||
@@ -59,3 +59,3 @@ result.setAttribute(dataAttribute, resultValue); | ||
result.setAttribute("tabindex", "1"); | ||
result.innerHTML = callback ? callback(event, result) : event.match || event; | ||
result.innerHTML = resultItem.content ? resultItem.content(event, result) : event.match || event; | ||
resultsList.appendChild(result); | ||
@@ -133,10 +133,22 @@ }); | ||
}, | ||
key: config.data.key | ||
key: config.data.key, | ||
cache: typeof config.data.cache === "undefined" ? true : config.data.cache | ||
}; | ||
this.searchEngine = config.searchEngine === "loose" ? "loose" : "strict"; | ||
this.threshold = config.threshold || 0; | ||
this.debounce = config.debounce || 0; | ||
this.resultsList = autoCompleteView.createResultsList({ | ||
container: config.resultsList && config.resultsList.container ? config.resultsList.container : false, | ||
destination: config.resultsList && config.resultsList.destination ? config.resultsList.destination : autoCompleteView.getInput(this.selector), | ||
position: config.resultsList && config.resultsList.position ? config.resultsList.position : "afterend" | ||
container: | ||
config.resultsList && config.resultsList.container | ||
? config.resultsList.container | ||
: false, | ||
destination: | ||
config.resultsList && config.resultsList.destination | ||
? config.resultsList.destination | ||
: autoCompleteView.getInput(this.selector), | ||
position: | ||
config.resultsList && config.resultsList.position | ||
? config.resultsList.position | ||
: "afterend", | ||
element: config.resultsList && config.resultsList.element ? config.resultsList.element : "ul" | ||
}); | ||
@@ -146,5 +158,9 @@ this.sort = config.sort || false; | ||
this.maxResults = config.maxResults || 5; | ||
this.resultItem = config.resultItem; | ||
this.resultItem = { | ||
content: config.resultItem && config.resultItem.content ? config.resultItem.content : false, | ||
element: config.resultItem && config.resultItem.element ? config.resultItem.element : "li" | ||
}; | ||
this.highlight = config.highlight || false; | ||
this.onSelection = config.onSelection; | ||
this.dataSrc; | ||
this.init(); | ||
@@ -185,60 +201,62 @@ } | ||
var _this = this; | ||
var resList = []; | ||
var inputValue = autoCompleteView.getInput(this.selector).value.toLowerCase(); | ||
data.filter(function (record, index) { | ||
var search = function search(key) { | ||
var match = _this.search(inputValue, record[key] || record); | ||
if (match && key) { | ||
resList.push({ | ||
key: key, | ||
index: index, | ||
match: match, | ||
value: record | ||
}); | ||
} else if (match && !key) { | ||
resList.push({ | ||
index: index, | ||
match: match, | ||
value: record | ||
}); | ||
} | ||
}; | ||
if (_this.data.key) { | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
for (var _iterator = _this.data.key[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var key = _step.value; | ||
search(key); | ||
return new Promise(function (resolve) { | ||
var resList = []; | ||
var inputValue = autoCompleteView.getInput(_this.selector).value.toLowerCase(); | ||
data.filter(function (record, index) { | ||
var search = function search(key) { | ||
var match = _this.search(inputValue, record[key] || record); | ||
if (match && key) { | ||
resList.push({ | ||
key: key, | ||
index: index, | ||
match: match, | ||
value: record | ||
}); | ||
} else if (match && !key) { | ||
resList.push({ | ||
index: index, | ||
match: match, | ||
value: record | ||
}); | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
}; | ||
if (_this.data.key) { | ||
var _iteratorNormalCompletion = true; | ||
var _didIteratorError = false; | ||
var _iteratorError = undefined; | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator.return != null) { | ||
_iterator.return(); | ||
for (var _iterator = _this.data.key[Symbol.iterator](), _step; !(_iteratorNormalCompletion = (_step = _iterator.next()).done); _iteratorNormalCompletion = true) { | ||
var key = _step.value; | ||
search(key); | ||
} | ||
} catch (err) { | ||
_didIteratorError = true; | ||
_iteratorError = err; | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
try { | ||
if (!_iteratorNormalCompletion && _iterator["return"] != null) { | ||
_iterator["return"](); | ||
} | ||
} finally { | ||
if (_didIteratorError) { | ||
throw _iteratorError; | ||
} | ||
} | ||
} | ||
} else { | ||
search(); | ||
} | ||
} else { | ||
search(); | ||
} | ||
}); | ||
var list = _this.sort ? resList.sort(_this.sort).slice(0, _this.maxResults) : resList.slice(0, _this.maxResults); | ||
autoCompleteView.addResultsToList(_this.resultsList, list, _this.resultItem); | ||
autoCompleteView.navigation(_this.selector, _this.resultsList); | ||
return resolve({ | ||
matches: resList.length, | ||
list: list | ||
}); | ||
}); | ||
var list = this.sort ? resList.sort(this.sort).slice(0, this.maxResults) : resList.slice(0, this.maxResults); | ||
autoCompleteView.addResultsToList(this.resultsList, list, this.data.key, this.resultItem); | ||
autoCompleteView.navigation(this.selector, this.resultsList); | ||
return { | ||
matches: resList.length, | ||
list: list | ||
}; | ||
} | ||
}, { | ||
key: "ignite", | ||
value: function ignite(data) { | ||
value: function ignite() { | ||
var _this2 = this; | ||
@@ -252,22 +270,50 @@ var selector = this.selector; | ||
} | ||
input.onkeyup = function (event) { | ||
var debounce = function debounce(func, delay) { | ||
var inDebounce; | ||
return function () { | ||
var context = this; | ||
var args = arguments; | ||
clearTimeout(inDebounce); | ||
inDebounce = setTimeout(function () { | ||
return func.apply(context, args); | ||
}, delay); | ||
}; | ||
}; | ||
var exec = function exec(event) { | ||
var resultsList = _this2.resultsList; | ||
var clearResults = autoCompleteView.clearResults(resultsList); | ||
if (input.value.length > _this2.threshold && input.value.replace(/ /g, "").length) { | ||
var list = _this2.listMatchedResults(data); | ||
input.dispatchEvent(new CustomEvent("type", { | ||
bubbles: true, | ||
detail: { | ||
event: event, | ||
query: input.value, | ||
matches: list.matches, | ||
results: list.list | ||
}, | ||
cancelable: true | ||
})); | ||
if (onSelection) { | ||
autoCompleteView.getSelection(selector, resultsList, onSelection, list); | ||
_this2.listMatchedResults(_this2.dataSrc).then(function (list) { | ||
input.dispatchEvent(new CustomEvent("type", { | ||
bubbles: true, | ||
detail: { | ||
event: event, | ||
query: input.value, | ||
matches: list.matches, | ||
results: list.list | ||
}, | ||
cancelable: true | ||
})); | ||
if (onSelection) { | ||
autoCompleteView.getSelection(selector, resultsList, onSelection, list); | ||
} | ||
}); | ||
} | ||
}; | ||
input.addEventListener("keyup", debounce(function (event) { | ||
if (!_this2.data.cache) { | ||
var data = _this2.data.src(); | ||
if (data instanceof Promise) { | ||
data.then(function (response) { | ||
_this2.dataSrc = response; | ||
exec(event); | ||
}); | ||
} else { | ||
_this2.dataSrc = data; | ||
exec(event); | ||
} | ||
} else { | ||
exec(event); | ||
} | ||
}; | ||
}, this.debounce)); | ||
} | ||
@@ -280,7 +326,9 @@ }, { | ||
if (dataSrc instanceof Promise) { | ||
dataSrc.then(function (data) { | ||
return _this3.ignite(data); | ||
dataSrc.then(function (response) { | ||
_this3.dataSrc = response; | ||
_this3.ignite(); | ||
}); | ||
} else { | ||
this.ignite(dataSrc); | ||
this.dataSrc = dataSrc; | ||
this.ignite(); | ||
} | ||
@@ -287,0 +335,0 @@ } |
@@ -1,1 +0,1 @@ | ||
var a,b;a=this,b=function(){"use strict";function n(t,e){for(var s=0;s<e.length;s++){var i=e[s];i.enumerable=i.enumerable||!1,i.configurable=!0,"value"in i&&(i.writable=!0),Object.defineProperty(t,i.key,i)}}var a="data-result",l={resultsList:"autoComplete_results_list",result:"autoComplete_result",highlight:"autoComplete_highlighted"},u=function(t){return"string"==typeof t?document.querySelector(t):t()},c=function(t){return t.innerHTML=""},h=u,r=function(t){var e=document.createElement("ul");return t.container&&(l.resultsList=t.container(e)||l.resultsList),e.setAttribute("id",l.resultsList),t.destination.insertAdjacentElement(t.position,e),e},f=function(t){return"<span class=".concat(l.highlight,">").concat(t,"</span>")},o=function(n,r,t,o){r.forEach(function(t,e){var s=document.createElement("li"),i=r[e].value[t.key]||r[e].value;s.setAttribute(a,i),s.setAttribute("class",l.result),s.setAttribute("tabindex","1"),s.innerHTML=o?o(t,s):t.match||t,n.appendChild(s)})},d=function(t,s){var i=u(t),n=s.firstChild;document.onkeydown=function(t){var e=document.activeElement;switch(t.keyCode){case 38:e!==n&&e!==i?e.previousSibling.focus():e===n&&i.focus();break;case 40:e===i&&0<s.childNodes.length?n.focus():e!==s.lastChild&&e.nextSibling.focus()}}},v=c,m=function(s,i,n,r){var o=i.querySelectorAll(".".concat(l.result));Object.keys(o).forEach(function(e){["mousedown","keydown"].forEach(function(t){o[e].addEventListener(t,function(e){"mousedown"!==t&&13!==e.keyCode&&39!==e.keyCode||(n({event:e,query:u(s).value,matches:r.matches,results:r.list.map(function(t){return t.value}),selection:r.list.find(function(t){return(t.value[t.key]||t.value)===e.target.closest(".".concat(l.result)).getAttribute(a)})}),c(i))})})})};return function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.selector=t.selector||"#autoComplete",this.data={src:function(){return"function"==typeof t.data.src?t.data.src():t.data.src},key:t.data.key},this.searchEngine="loose"===t.searchEngine?"loose":"strict",this.threshold=t.threshold||0,this.resultsList=r({container:!(!t.resultsList||!t.resultsList.container)&&t.resultsList.container,destination:t.resultsList&&t.resultsList.destination?t.resultsList.destination:h(this.selector),position:t.resultsList&&t.resultsList.position?t.resultsList.position:"afterend"}),this.sort=t.sort||!1,this.placeHolder=t.placeHolder,this.maxResults=t.maxResults||5,this.resultItem=t.resultItem,this.highlight=t.highlight||!1,this.onSelection=t.onSelection,this.init()}var t,s,i;return t=e,(s=[{key:"search",value:function(t,e){var s=this.highlight,i=e.toLowerCase();if("loose"===this.searchEngine){t=t.replace(/ /g,"");for(var n=[],r=0,o=0;o<i.length;o++){var a=e[o];r<t.length&&i[o]===t[r]&&(a=s?f(a):a,r++),n.push(a)}return r===t.length&&n.join("")}if(i.includes(t))return t=new RegExp("".concat(t),"i").exec(e),s?e.replace(t,f(t)):e}},{key:"listMatchedResults",value:function(t){var l=this,u=[],c=h(this.selector).value.toLowerCase();t.filter(function(s,i){var t=function(t){var e=l.search(c,s[t]||s);e&&t?u.push({key:t,index:i,match:e,value:s}):e&&!t&&u.push({index:i,match:e,value:s})};if(l.data.key){var e=!0,n=!1,r=void 0;try{for(var o,a=l.data.key[Symbol.iterator]();!(e=(o=a.next()).done);e=!0){t(o.value)}}catch(t){n=!0,r=t}finally{try{e||null==a.return||a.return()}finally{if(n)throw r}}}else t()});var e=this.sort?u.sort(this.sort).slice(0,this.maxResults):u.slice(0,this.maxResults);return o(this.resultsList,e,this.data.key,this.resultItem),d(this.selector,this.resultsList),{matches:u.length,list:e}}},{key:"ignite",value:function(i){var n=this,r=this.selector,o=h(r),t=this.placeHolder,a=this.onSelection;t&&o.setAttribute("placeholder",t),o.onkeyup=function(t){var e=n.resultsList;v(e);if(o.value.length>n.threshold&&o.value.replace(/ /g,"").length){var s=n.listMatchedResults(i);o.dispatchEvent(new CustomEvent("type",{bubbles:!0,detail:{event:t,query:o.value,matches:s.matches,results:s.list},cancelable:!0})),a&&m(r,e,a,s)}}}},{key:"init",value:function(){var e=this,t=this.data.src();t instanceof Promise?t.then(function(t){return e.ignite(t)}):this.ignite(t)}}])&&n(t.prototype,s),i&&n(t,i),e}()},"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.autoComplete=b(); | ||
var a,b;a=this,b=function(){"use strict";function i(t,e){for(var n=0;n<e.length;n++){var s=e[n];s.enumerable=s.enumerable||!1,s.configurable=!0,"value"in s&&(s.writable=!0),Object.defineProperty(t,s.key,s)}}var o="data-result",l={resultsList:"autoComplete_results_list",result:"autoComplete_result",highlight:"autoComplete_highlighted"},u=function(t){return"string"==typeof t?document.querySelector(t):t()},c=function(t){return t.innerHTML=""},h=u,r=function(t){var e=document.createElement(t.element);return t.container&&(l.resultsList=t.container(e)||l.resultsList),e.setAttribute("id",l.resultsList),t.destination.insertAdjacentElement(t.position,e),e},d=function(t){return"<span class=".concat(l.highlight,">").concat(t,"</span>")},a=function(i,r,a){r.forEach(function(t,e){var n=document.createElement(a.element),s=r[e].value[t.key]||r[e].value;n.setAttribute(o,s),n.setAttribute("class",l.result),n.setAttribute("tabindex","1"),n.innerHTML=a.content?a.content(t,n):t.match||t,i.appendChild(n)})},f=function(t,n){var s=u(t),i=n.firstChild;document.onkeydown=function(t){var e=document.activeElement;switch(t.keyCode){case 38:e!==i&&e!==s?e.previousSibling.focus():e===i&&s.focus();break;case 40:e===s&&0<n.childNodes.length?i.focus():e!==n.lastChild&&e.nextSibling.focus()}}},m=c,v=function(n,s,i,r){var a=s.querySelectorAll(".".concat(l.result));Object.keys(a).forEach(function(e){["mousedown","keydown"].forEach(function(t){a[e].addEventListener(t,function(e){"mousedown"!==t&&13!==e.keyCode&&39!==e.keyCode||(i({event:e,query:u(n).value,matches:r.matches,results:r.list.map(function(t){return t.value}),selection:r.list.find(function(t){return(t.value[t.key]||t.value)===e.target.closest(".".concat(l.result)).getAttribute(o)})}),c(s))})})})};return function(){function e(t){!function(t,e){if(!(t instanceof e))throw new TypeError("Cannot call a class as a function")}(this,e),this.selector=t.selector||"#autoComplete",this.data={src:function(){return"function"==typeof t.data.src?t.data.src():t.data.src},key:t.data.key,cache:void 0===t.data.cache||t.data.cache},this.searchEngine="loose"===t.searchEngine?"loose":"strict",this.threshold=t.threshold||0,this.debounce=t.debounce||0,this.resultsList=r({container:!(!t.resultsList||!t.resultsList.container)&&t.resultsList.container,destination:t.resultsList&&t.resultsList.destination?t.resultsList.destination:h(this.selector),position:t.resultsList&&t.resultsList.position?t.resultsList.position:"afterend",element:t.resultsList&&t.resultsList.element?t.resultsList.element:"ul"}),this.sort=t.sort||!1,this.placeHolder=t.placeHolder,this.maxResults=t.maxResults||5,this.resultItem={content:!(!t.resultItem||!t.resultItem.content)&&t.resultItem.content,element:t.resultItem&&t.resultItem.element?t.resultItem.element:"li"},this.highlight=t.highlight||!1,this.onSelection=t.onSelection,this.dataSrc,this.init()}var t,n,s;return t=e,(n=[{key:"search",value:function(t,e){var n=this.highlight,s=e.toLowerCase();if("loose"===this.searchEngine){t=t.replace(/ /g,"");for(var i=[],r=0,a=0;a<s.length;a++){var o=e[a];r<t.length&&s[a]===t[r]&&(o=n?d(o):o,r++),i.push(o)}return r===t.length&&i.join("")}if(s.includes(t))return t=new RegExp("".concat(t),"i").exec(e),n?e.replace(t,d(t)):e}},{key:"listMatchedResults",value:function(n){var c=this;return new Promise(function(t){var l=[],u=h(c.selector).value.toLowerCase();n.filter(function(n,s){var t=function(t){var e=c.search(u,n[t]||n);e&&t?l.push({key:t,index:s,match:e,value:n}):e&&!t&&l.push({index:s,match:e,value:n})};if(c.data.key){var e=!0,i=!1,r=void 0;try{for(var a,o=c.data.key[Symbol.iterator]();!(e=(a=o.next()).done);e=!0){t(a.value)}}catch(t){i=!0,r=t}finally{try{e||null==o.return||o.return()}finally{if(i)throw r}}}else t()});var e=c.sort?l.sort(c.sort).slice(0,c.maxResults):l.slice(0,c.maxResults);return a(c.resultsList,e,c.resultItem),f(c.selector,c.resultsList),t({matches:l.length,list:e})})}},{key:"ignite",value:function(){var s=this,i=this.selector,r=h(i),t=this.placeHolder,a=this.onSelection;t&&r.setAttribute("placeholder",t);var n,o,l,u=function(e){var n=s.resultsList;m(n);r.value.length>s.threshold&&r.value.replace(/ /g,"").length&&s.listMatchedResults(s.dataSrc).then(function(t){r.dispatchEvent(new CustomEvent("type",{bubbles:!0,detail:{event:e,query:r.value,matches:t.matches,results:t.list},cancelable:!0})),a&&v(i,n,a,t)})};r.addEventListener("keyup",(n=function(e){if(s.data.cache)u(e);else{var t=s.data.src();t instanceof Promise?t.then(function(t){s.dataSrc=t,u(e)}):(s.dataSrc=t,u(e))}},o=this.debounce,function(){var t=this,e=arguments;clearTimeout(l),l=setTimeout(function(){return n.apply(t,e)},o)}))}},{key:"init",value:function(){var e=this,t=this.data.src();t instanceof Promise?t.then(function(t){e.dataSrc=t,e.ignite()}):(this.dataSrc=t,this.ignite())}}])&&i(t.prototype,n),s&&i(t,s),e}()},"object"==typeof exports&&"undefined"!=typeof module?module.exports=b():"function"==typeof define&&define.amd?define(b):a.autoComplete=b(); |
// autoComplete.js on type event emitter | ||
document.querySelector("#autoComplete").addEventListener("type", event => { | ||
console.log(event); | ||
}) | ||
console.log(event); | ||
}); | ||
// The autoComplete.js Engine instance creator | ||
@@ -17,3 +17,3 @@ const autoCompletejs = new autoComplete({ | ||
}, | ||
key: ["food", "cities", "animals"] | ||
key: ["food", "cities", "animals"], | ||
}, | ||
@@ -28,2 +28,3 @@ sort: (a, b) => { | ||
threshold: 0, | ||
debounce: 0, | ||
searchEngine: "strict", | ||
@@ -38,6 +39,10 @@ highlight: true, | ||
destination: document.querySelector("#autoComplete"), | ||
position: "afterend" | ||
position: "afterend", | ||
element: "ul", | ||
}, | ||
resultItem: (data, source) => { | ||
return `${data.match}`; | ||
resultItem: { | ||
content: (data, source) => { | ||
return `${data.match}`; | ||
}, | ||
element: "li", | ||
}, | ||
@@ -54,3 +59,3 @@ onSelection: feedback => { | ||
console.log(feedback); | ||
} | ||
}, | ||
}); | ||
@@ -57,0 +62,0 @@ |
@@ -5,3 +5,3 @@ <a href="https://tarekraafat.github.io/autoComplete.js/demo/"> | ||
> Simple autocomplete pure vanilla Javascript library. <a href="https://tarekraafat.github.io/autoComplete.js/demo/" target="\_blank">Live Demo</a> **v4.0** | ||
> Simple autocomplete pure vanilla Javascript library. <a href="https://tarekraafat.github.io/autoComplete.js/demo/" target="\_blank">Live Demo</a> **v5.0** | ||
@@ -8,0 +8,0 @@ autoComplete.js is a simple pure vanilla Javascript library that's progressively designed for speed,<br>high versatility and seamless integration with wide range of projects & systems. |
@@ -5,2 +5,3 @@ // autoComplete.js on type event emitter | ||
}); | ||
// The autoComplete.js Engine instance creator | ||
@@ -12,9 +13,16 @@ const autoCompletejs = new autoComplete({ | ||
document.querySelector("#autoComplete").setAttribute("placeholder", "Loading..."); | ||
// API key token | ||
const token = "5c2d4273b2930ee4b53f4e84a7c4440d"; | ||
// User search query | ||
const query = document.querySelector("#autoComplete").value; | ||
// Fetch External Data Source | ||
const source = await fetch("./db/generic.json"); | ||
const source = await fetch(`https://www.food2fork.com/api/search?key=${token}&q=${query}`); | ||
const data = await source.json(); | ||
// Returns Fetched data | ||
return data; | ||
// Post loading placeholder text | ||
document.querySelector("#autoComplete").setAttribute("placeholder", "Food & Drinks"); | ||
// Return Fetched data | ||
return data.recipes; | ||
}, | ||
key: ["food", "cities", "animals"] | ||
key: ["title"], | ||
cache: false, | ||
}, | ||
@@ -26,8 +34,8 @@ sort: (a, b) => { | ||
}, | ||
placeHolder: "Food & Drinks", | ||
selector: "#autoComplete", | ||
threshold: 0, | ||
threshold: 3, | ||
debounce: 300, | ||
searchEngine: "strict", | ||
highlight: true, | ||
maxResults: 10, | ||
maxResults: Infinity, | ||
resultsList: { | ||
@@ -39,18 +47,25 @@ container: source => { | ||
destination: document.querySelector("#autoComplete"), | ||
position: "afterend" | ||
position: "afterend", | ||
element: "ul", | ||
}, | ||
resultItem: (data, source) => { | ||
return `${data.match}`; | ||
resultItem: { | ||
content: (data, source) => { | ||
return `${data.match}`; | ||
}, | ||
element: "li", | ||
}, | ||
onSelection: feedback => { | ||
const selection = feedback.selection.value.food; | ||
const title = feedback.selection.value.title; | ||
const image = feedback.selection.value.image_url; | ||
// Render selected choice to selection div | ||
document.querySelector(".selection").innerHTML = selection; | ||
document.querySelector( | ||
".selection", | ||
).innerHTML = `<span style="display: block; font-size: 25px; width: 90vw; max-width: 400px; margin-bottom: 20px;">${title}</span><img src="${image}" style="height: 30vh; border-radius: 8px; box-shadow: 0 0 80px rgba(255, 122, 122,0.2), 0 4px 10px -3px rgba(255, 122, 122,0.4), inset 0 -10px 30px -5px rgba(255, 122, 122,0.1);"></img>`; | ||
// Clear Input | ||
document.querySelector("#autoComplete").value = ""; | ||
// Change placeholder with the selected value | ||
document.querySelector("#autoComplete").setAttribute("placeholder", selection); | ||
document.querySelector("#autoComplete").setAttribute("placeholder", title); | ||
// Concole log autoComplete data feedback | ||
console.log(feedback); | ||
} | ||
}, | ||
}); | ||
@@ -57,0 +72,0 @@ |
@@ -9,3 +9,3 @@ # Introduction | ||
![\[Zero Dependencies\]()](https://img.shields.io/badge/Dependencies-0-blue.svg) | ||
![\[Size\]()](https://img.shields.io/badge/Size-4%20KB-green.svg) | ||
![\[Size\]()](https://img.shields.io/badge/Size-5%20KB-green.svg) | ||
[![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://github.com/TarekRaafat/autoComplete.js) | ||
@@ -18,3 +18,3 @@ | ||
> Simple autocomplete pure vanilla Javascript library. <a href="https://tarekraafat.github.io/autoComplete.js/demo/" target="\_blank">:rocket: Live Demo</a> **v4.0** | ||
> Simple autocomplete pure vanilla Javascript library. <a href="https://tarekraafat.github.io/autoComplete.js/demo/" target="\_blank">:rocket: Live Demo</a> **v5.0** | ||
@@ -72,3 +72,3 @@ autoComplete.js is a simple pure vanilla Javascript library that's progressively designed for speed, high versatility and seamless integration with wide range of projects & systems, made for users and developers in mind. | ||
```html | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@4.0.0/dist/css/autoComplete.min.css"> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@5.0.0/dist/css/autoComplete.min.css"> | ||
``` | ||
@@ -79,3 +79,3 @@ | ||
```html | ||
<script src="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@4.0.0/dist/js/autoComplete.min.js"></script> | ||
<script src="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@5.0.0/dist/js/autoComplete.min.js"></script> | ||
``` | ||
@@ -122,3 +122,3 @@ | ||
OR | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@4.0.0/dist/css/autoComplete.min.css"> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@5.0.0/dist/css/autoComplete.min.css"> | ||
``` | ||
@@ -138,3 +138,3 @@ | ||
OR | ||
<script src="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@4.0.0/dist/js/autoComplete.min.js"></script> | ||
<script src="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@5.0.0/dist/js/autoComplete.min.js"></script> | ||
<script src="./js/index.js"></script> | ||
@@ -149,6 +149,23 @@ ``` | ||
new autoComplete({ | ||
data: { src: data, key: "food" }, // Data src [Array, Function, Async] | (REQUIRED) | ||
data: { // Data src [Array, Function, Async] | (REQUIRED) | ||
src: async () => { | ||
// Fetch External Data Source | ||
const source = await fetch(`https://www.food2fork.com/api/search?key=${token}&q=${query}`); | ||
// Format data into JSON | ||
const data = await source.json(); | ||
// Return Fetched data | ||
return data.recipes; | ||
}, | ||
key: ["title"], | ||
cache: false | ||
}, | ||
sort: (a, b) => { // Sort rendered results ascendingly | (Optional) | ||
if (a.match < b.match) return -1; | ||
if (a.match > b.match) return 1; | ||
return 0; | ||
}, | ||
placeHolder: "Food & Drinks...", // Place Holder text | (Optional) | ||
selector: "#autoComplete", // Input field selector | (Optional) | ||
threshold: 0, // Min. Chars length to start Engine | (Optional) | ||
threshold: 3, // Min. Chars length to start Engine | (Optional) | ||
debounce: 300, // Post duration for engine to start | (Optional) | ||
searchEngine: "strict", // Search Engine type/mode | (Optional) | ||
@@ -161,6 +178,10 @@ resultsList: { // Rendered results list object | (Optional) | ||
destination: document.querySelector("#autoComplete"), | ||
position: "afterend" | ||
position: "afterend", | ||
element: "ul" | ||
}, | ||
resultItem: (data, source) => { // Rendered result item | (Optional) | ||
return `${data.match}`; | ||
resultItem: { // Rendered result item | (Optional) | ||
content: (data, source) => { | ||
return `${data.match}`; | ||
}, | ||
element: "li" | ||
}, | ||
@@ -170,3 +191,3 @@ highlight: true, // Highlight matching results | (Optional) | ||
onSelection: feedback => { // Action script onSelection event | (Optional) | ||
console.log(feedback); | ||
console.log(feedback.selection.value.image_url); | ||
} | ||
@@ -176,15 +197,17 @@ }); | ||
### API Configurations: | ||
### API Configuration: | ||
<br> | ||
| Features | Description | Values | Default | | ||
| Keys | Description | Values | Default | | ||
| -------------- | ---------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------------------- | | ||
| `data` | Data Source & Data Key | **1- src**: <br> - `Array` of `Strings` / `Objects`<br>**OR**<br> - `Function` => `Array` of `Strings` / `Objects` <br> **2- key**: <br> **Required** if `src` is `Object`, it will point to `key` in the object for the search | Data `src` **REQUIRED** any **NOT** both | | ||
| `data` | Data Source, Data Key & Data Caching | **1- src**: <br> - `Array` of `Strings` / `Objects`<br>**OR**<br> - `Function` => `Array` of `Strings` / `Objects` <br> **2- key**: <br>- `Array` of `Strings`<br>**Required** if `src` is `Object`, for search to point to desired `keys` <br> **3- Cache**: <br> - `True` for static data `src` <br> - `False` for dynamic data `src` "API" | Data `src` **REQUIRED** | | ||
| `sort` | Sort rendered results | `Function` | Blank / Empty **(Random Results)** | | ||
| `placeHolder` | Place Holder text | `String` | Blank / Empty | | ||
| `selector` | Input field selector | **-** `String` `id`/`class` <br>**OR**<br> **-** `Function` ( ) => `document.querySelector("")` | `"#autoComplete"` | | ||
| `threshold` | Minimum characters length before engine starts rendering results | `Number` | `0` | | ||
| `debounce` | Minimum duration after typing idle state for engine to kick in | `Number` <br> Milliseconds value <br> debounce: `300` | `0` | | ||
| `searchEngine` | Search Engine Type/Mode | **-** `"strict"` lowerCase string<br>**OR**<br>**-** `"loose"` lowerCase string | `"strict"` | | ||
| `resultsList` | Rendered results list destination & position | **-** `Object` with 3 methods<br> 1- Container: <br> `Function` (source) => `id`<br> 2- destination: `document.querySelector("#div")`<br> 3- position:<br> `"beforebegin"`, `"afterbegin"`, `"beforeend"`, `"afterend"` lowerCase string <br>**OR**<br>**-** `Function` ( ) => `{destination: "...", position: "..."}` | `{container: (source) => { }, destination: document.querySelector("#autoComplete"), position: "afterend"}` | | ||
| `resultItem` | Rendered result Item | **-** `Function` (data, source) => `String` <br> **-** `data.match` has to be used for **Highlighted** result | `data.match` | | ||
| `resultsList` | Rendered results list destination, position & element | **-** `Object` with 4 methods<br> 1- container: <br> `Function` (source) => `id`<br> 2- destination: `document.querySelector("#div")`<br> 3- position:<br> `"beforebegin"`, `"afterbegin"`, `"beforeend"`, `"afterend"` lowerCase string <br>**OR**<br>**-** `Function` ( ) => `{destination: "...", position: "..."}` <br> 4- element: <br> `"ul", "span", "div" or Custom`| `{container: (source) => { }, destination: document.querySelector("#autoComplete"), position: "afterend", element: "ul"}` | | ||
| `resultItem` | Rendered result Item content & element | **-** `Object` with 2 methods<br> 1- content: <br>**-** `Function` (data, source) => `String` <br> **-** `data.match` has to be used for **Highlighted** result <br> 2- element: <br> `"li", "span", "div" or Custom` | `{content: (data, source) => data.match, element: "li"}` | | ||
| `highlight` | Highlight matching results | `Boolean` | `false` | | ||
@@ -194,3 +217,3 @@ | `maxResults` | Maximum number of displayed results | `Number` | `5` | | ||
3. That's it, you're ready to go! | ||
1. That's it, you're ready to go! | ||
@@ -237,3 +260,3 @@ * * * | ||
## 5. What's New in v4.0? | ||
## 5. What's New in v5.0? | ||
@@ -256,11 +279,11 @@ Check out <a href="#/releases?id=versioning">Releases</a> Information :sparkles: | ||
- [x] Choose different results render destination & position | ||
- [ ] Sort rendered results | ||
- [ ] Alphabet | ||
- [ ] Weight | ||
- [x] Sort rendered results | ||
- [x] Results list Keyboard `ARROW` or `TAB` Navigation | ||
- [x] Enhance error Handling (Ongoing) | ||
- [ ] Number of returned results value | ||
- [ ] Results Lazy Load/Pagination for External data source | ||
- [ ] Multiple searchable `keys` for data `src` | ||
- [x] Number of matching results | ||
- [x] Fetching dynamically External API data source | ||
- [x] Multiple searchable `keys` for data `src` | ||
- [ ] Reload data `src` on data change | ||
- [x] Event emitter on input field events | ||
- [x] Handling large data sets | ||
@@ -284,3 +307,4 @@ ### Usability: | ||
- [x] Capability for multiple instances | ||
- [ ] Render `results` in default case | ||
- [x] Render `results` in default case | ||
- [x] Render `resultsList` & `resultItem` in different/custom elements | ||
@@ -287,0 +311,0 @@ * * * |
@@ -29,4 +29,13 @@ ## Versioning | ||
- v4.0.0 :sparkles: | ||
- v5.0.0 :sparkles: | ||
- Large datasets handeling (Thanks @Johann-S) | ||
- API Data fetching & Dynamic Data reloading (Thanks @Brostafa) | ||
- Debouncing API Calls | ||
- Custom `resultsList` & `resultItem` Elements (Thanks @Johann-S) | ||
- Bug fixes | ||
- Code Clean Up | ||
- v4.0.0 | ||
- Multiple searchable `keys` for data `src` (Thanks @Johann-S) | ||
@@ -33,0 +42,0 @@ - Rendered `results` in original case (Thanks @nickbp12) |
{ | ||
"name": "@tarekraafat/autocomplete.js", | ||
"version": "4.0.0", | ||
"version": "5.0.0", | ||
"description": "Simple autocomplete pure vanilla Javascript library.", | ||
@@ -51,4 +51,4 @@ "main": "dist/js/autoComplete.js", | ||
"devDependencies": { | ||
"@babel/core": "^7.3.4", | ||
"@babel/preset-env": "^7.3.4", | ||
"@babel/core": "^7.4.4", | ||
"@babel/preset-env": "^7.4.4", | ||
"acorn": "^6.1.1", | ||
@@ -59,6 +59,6 @@ "local-web-server": "^2.6.1", | ||
"rollup-plugin-cleanup": "^3.1.0", | ||
"rollup-plugin-eslint": "^5.0.0", | ||
"rollup-plugin-eslint": "^5.1.0", | ||
"rollup-plugin-gzip": "^2.2.0", | ||
"rollup-plugin-uglify": "^6.0.0" | ||
} | ||
} | ||
} |
@@ -9,3 +9,3 @@ # autoComplete.js :sparkles: | ||
![\[Zero Dependencies\]()](https://img.shields.io/badge/Dependencies-0-blue.svg) | ||
![\[Size\]()](https://img.shields.io/badge/Size-4%20KB-green.svg) | ||
![\[Size\]()](https://img.shields.io/badge/Size-5%20KB-green.svg) | ||
[![Open Source Love](https://badges.frapsoft.com/os/v1/open-source.svg?v=103)](https://github.com/TarekRaafat/autoComplete.js) | ||
@@ -23,3 +23,3 @@ | ||
> Simple autocomplete pure vanilla Javascript library. <a href="https://tarekraafat.github.io/autoComplete.js/demo/" target="\_blank">:rocket: Live Demo</a> **v4.0** | ||
> Simple autocomplete pure vanilla Javascript library. <a href="https://tarekraafat.github.io/autoComplete.js/demo/" target="\_blank">:rocket: Live Demo</a> **v5.0** | ||
@@ -57,3 +57,3 @@ autoComplete.js is a simple pure vanilla Javascript library that's progressively designed for speed, high versatility and seamless integration with wide range of projects & systems, made for users and developers in mind. | ||
```html | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@4.0.0/dist/css/autoComplete.min.css"> | ||
<link rel="stylesheet" href="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@5.0.0/dist/css/autoComplete.min.css"> | ||
``` | ||
@@ -64,3 +64,3 @@ | ||
```html | ||
<script src="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@4.0.0/dist/js/autoComplete.min.js"></script> | ||
<script src="https://cdn.jsdelivr.net/gh/TarekRaafat/autoComplete.js@5.0.0/dist/js/autoComplete.min.js"></script> | ||
``` | ||
@@ -67,0 +67,0 @@ |
@@ -9,4 +9,8 @@ import { autoCompleteView } from "../views/autoCompleteView"; | ||
this.data = { | ||
// Data src selection | ||
src: () => (typeof config.data.src === "function" ? config.data.src() : config.data.src), | ||
key: config.data.key | ||
// Data src key selection | ||
key: config.data.key, | ||
// Cache Data src or NOT | ||
cache: typeof config.data.cache === "undefined" ? true : config.data.cache, | ||
}; | ||
@@ -17,10 +21,33 @@ // Search engine type | ||
this.threshold = config.threshold || 0; | ||
// Minimum duration for API calls debouncing | ||
this.debounce = config.debounce || 0; | ||
// Rendered results destination | ||
this.resultsList = autoCompleteView.createResultsList({ | ||
container: config.resultsList && config.resultsList.container ? config.resultsList.container : false, | ||
// Results List function | ||
container: | ||
// If resultsList and container are set | ||
config.resultsList && config.resultsList.container | ||
// Then set resultsList container | ||
? config.resultsList.container | ||
// Else set default false | ||
: false, | ||
// Results List selector | ||
destination: | ||
// If resultsList and destination are set | ||
config.resultsList && config.resultsList.destination | ||
// Then set resultList destination | ||
? config.resultsList.destination | ||
// Else set Default | ||
: autoCompleteView.getInput(this.selector), | ||
position: config.resultsList && config.resultsList.position ? config.resultsList.position : "afterend" | ||
// Results List position | ||
position: | ||
// If resultsList and position are set | ||
config.resultsList && config.resultsList.position | ||
// Then resultsList position | ||
? config.resultsList.position | ||
// Else set default "afterend" | ||
: "afterend", | ||
// Results List element tag | ||
element: config.resultsList && config.resultsList.element | ||
? config.resultsList.element : "ul" | ||
}); | ||
@@ -34,3 +61,10 @@ // Sorting results list | ||
// Rendered results item | ||
this.resultItem = config.resultItem; | ||
this.resultItem = { | ||
// Result Item function | ||
content: config.resultItem && config.resultItem.content | ||
? config.resultItem.content : false, | ||
// Result Item element tag | ||
element: config.resultItem && config.resultItem.element | ||
? config.resultItem.element : "li" | ||
}; | ||
// Highlighting matching results | ||
@@ -40,2 +74,4 @@ this.highlight = config.highlight || false; | ||
this.onSelection = config.onSelection; | ||
// Data source | ||
this.dataSrc; | ||
// Starts the app Enigne | ||
@@ -58,2 +94,3 @@ this.init(); | ||
const recordLowerCase = record.toLowerCase(); | ||
// Loose mode | ||
@@ -67,2 +104,3 @@ if (this.searchEngine === "loose") { | ||
let searchPosition = 0; | ||
// Iterate over record characters | ||
@@ -72,2 +110,3 @@ for (let number = 0; number < recordLowerCase.length; number++) { | ||
let recordChar = record[number]; | ||
// Matching case | ||
@@ -83,2 +122,3 @@ if (searchPosition < query.length && recordLowerCase[number] === query[searchPosition]) { | ||
} | ||
// Non-Matching case | ||
@@ -108,49 +148,61 @@ if (searchPosition !== query.length) { | ||
* | ||
* @return array | ||
* @return {*} | ||
*/ | ||
listMatchedResults(data) { | ||
// Final highlighted results list of array | ||
const resList = []; | ||
// Holds the input search value | ||
const inputValue = autoCompleteView.getInput(this.selector).value.toLowerCase(); | ||
// Checks input has matches in data source | ||
data.filter((record, index) => { | ||
// Search/Matching function | ||
const search = key => { | ||
// Holds match value | ||
const match = this.search(inputValue, record[key] || record); | ||
// Push match to results list with key if set | ||
if (match && key) { | ||
resList.push({ key, index, match, value: record }); | ||
// Push match to results list without key if not set | ||
} else if (match && !key) { | ||
resList.push({ index, match, value: record }); | ||
return new Promise(resolve => { | ||
// Final highlighted results list of array | ||
const resList = []; | ||
// Holds the input search value | ||
const inputValue = autoCompleteView.getInput(this.selector).value.toLowerCase(); | ||
// Checks input has matches in data source | ||
data.filter((record, index) => { | ||
// Search/Matching function | ||
const search = key => { | ||
// Holds match value | ||
const match = this.search(inputValue, record[key] || record); | ||
// Push match to results list with key if set | ||
if (match && key) { | ||
resList.push({ key, index, match, value: record }); | ||
// Push match to results list without key if not set | ||
} else if (match && !key) { | ||
resList.push({ index, match, value: record }); | ||
} | ||
}; | ||
// Checks if data key is set | ||
if (this.data.key) { | ||
// Iterates over all set data keys | ||
for (const key of this.data.key) { | ||
search(key); | ||
} | ||
// If no data key not set | ||
} else { | ||
search(); | ||
} | ||
}; | ||
// Checks if data key is set | ||
if(this.data.key) { | ||
// Iterates over all set data keys | ||
for (const key of this.data.key) { | ||
search(key); | ||
} | ||
// If no data key not set | ||
} else { | ||
search(); | ||
} | ||
}); | ||
// Sorting / Slicing final results list | ||
const list = this.sort | ||
? resList.sort(this.sort).slice(0, this.maxResults) | ||
: resList.slice(0, this.maxResults); | ||
// Rendering matching results to the UI list | ||
autoCompleteView.addResultsToList(this.resultsList, list, this.resultItem); | ||
// Keyboard Arrow Navigation | ||
autoCompleteView.navigation(this.selector, this.resultsList); | ||
// Returns rendered list | ||
return resolve({ | ||
matches: resList.length, | ||
list, | ||
}); | ||
}); | ||
// Sorting / Slicing final results list | ||
const list = this.sort ? resList.sort(this.sort) | ||
.slice(0, this.maxResults) : resList.slice(0, this.maxResults); | ||
// Rendering matching results to the UI list | ||
autoCompleteView.addResultsToList(this.resultsList, list, this.data.key, this.resultItem); | ||
// Keyboard Arrow Navigation | ||
autoCompleteView.navigation(this.selector, this.resultsList); | ||
// Returns rendered list | ||
return { | ||
matches: resList.length, | ||
list | ||
}; | ||
} | ||
ignite(data) { | ||
/** | ||
* App Engine Ignition. | ||
* | ||
* @return void | ||
*/ | ||
ignite() { | ||
// Selector value holder | ||
@@ -164,2 +216,3 @@ const selector = this.selector; | ||
const onSelection = this.onSelection; | ||
// Placeholder setter | ||
@@ -169,4 +222,18 @@ if (placeHolder) { | ||
} | ||
// Input field handler fires an event onKeyup action | ||
input.onkeyup = (event) => { | ||
// Debouncer | ||
const debounce = (func, delay) => { | ||
let inDebounce; | ||
return function() { | ||
const context = this; | ||
const args = arguments; | ||
clearTimeout(inDebounce); | ||
inDebounce = setTimeout(() => | ||
func.apply(context, args) | ||
, delay); | ||
}; | ||
}; | ||
// Excute autoComplete processes | ||
const exec = (event) => { | ||
// Get results list value | ||
@@ -176,22 +243,25 @@ const resultsList = this.resultsList; | ||
const clearResults = autoCompleteView.clearResults(resultsList); | ||
// Check if input is not empty or just have space before triggering the app | ||
if (input.value.length > this.threshold && input.value.replace(/ /g, "").length) { | ||
// List matching results | ||
const list = this.listMatchedResults(data); | ||
// Event emitter on input field | ||
input.dispatchEvent(new CustomEvent("type", { | ||
bubbles: true, | ||
detail: { | ||
event, | ||
query: input.value, | ||
matches: list.matches, | ||
results: list.list | ||
}, | ||
cancelable: true | ||
})); | ||
// Gets user's selection | ||
// If action configured | ||
if (onSelection) { | ||
autoCompleteView.getSelection(selector, resultsList, onSelection, list); | ||
} | ||
this.listMatchedResults(this.dataSrc).then(list => { | ||
// Event emitter on input field | ||
input.dispatchEvent( | ||
new CustomEvent("type", { | ||
bubbles: true, | ||
detail: { | ||
event, | ||
query: input.value, | ||
matches: list.matches, | ||
results: list.list, | ||
}, | ||
cancelable: true, | ||
})); | ||
// Gets user's selection | ||
// If action configured | ||
if (onSelection) { | ||
autoCompleteView.getSelection(selector, resultsList, onSelection, list); | ||
} | ||
}); | ||
} else { | ||
@@ -202,2 +272,27 @@ // clears all results list | ||
}; | ||
// Input field handler fires an event onKeyup action | ||
input.addEventListener("keyup", debounce((event) => { | ||
// If data src NOT to be cached | ||
// then we should invoke its function again | ||
if (!this.data.cache) { | ||
const data = this.data.src(); | ||
// Check if data src is a Promise | ||
// and resolve it before setting data src | ||
if (data instanceof Promise) { | ||
data.then(response => { | ||
this.dataSrc = response; | ||
exec(event); | ||
}); | ||
// Else if not Promise | ||
} else { | ||
this.dataSrc = data; | ||
exec(event); | ||
} | ||
// Else if data src is local | ||
// not external src | ||
} else { | ||
exec(event); | ||
} | ||
}, this.debounce)); | ||
} | ||
@@ -216,9 +311,12 @@ | ||
// Return Data | ||
dataSrc.then(data => this.ignite(data)); | ||
dataSrc.then(response => { | ||
this.dataSrc = response; | ||
this.ignite(); | ||
}); | ||
// Data source is Array/Function | ||
} else { | ||
// Return Data | ||
this.ignite(dataSrc); | ||
this.dataSrc = dataSrc; | ||
this.ignite(); | ||
} | ||
} | ||
} | ||
} |
@@ -25,3 +25,3 @@ const dataAttribute = "data-result"; | ||
const createResultsList = renderResults => { | ||
const resultsList = document.createElement("ul"); | ||
const resultsList = document.createElement(renderResults.element); | ||
if (renderResults.container) { | ||
@@ -49,10 +49,9 @@ select.resultsList = renderResults.container(resultsList) || select.resultsList; | ||
* @param dataSrc | ||
* @param dataKey | ||
* @param callback | ||
* @param resultItem | ||
* | ||
* @return void | ||
*/ | ||
const addResultsToList = (resultsList, dataSrc, dataKey, callback) => { | ||
const addResultsToList = (resultsList, dataSrc, resultItem) => { | ||
dataSrc.forEach((event, record) => { | ||
const result = document.createElement("li"); | ||
const result = document.createElement(resultItem.element); | ||
const resultValue = dataSrc[record].value[event.key] || dataSrc[record].value; | ||
@@ -62,3 +61,3 @@ result.setAttribute(dataAttribute, resultValue); | ||
result.setAttribute("tabindex", "1"); | ||
result.innerHTML = callback ? callback(event, result) : event.match || event; | ||
result.innerHTML = resultItem.content ? resultItem.content(event, result) : event.match || event; | ||
resultsList.appendChild(result); | ||
@@ -72,3 +71,2 @@ }); | ||
* @param selector | ||
* | ||
* @param resultsList | ||
@@ -75,0 +73,0 @@ */ |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
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
1259520
11721