datalist-polyfill
Advanced tools
Comparing version 1.17.0 to 1.18.0
{ | ||
"name": "datalist-polyfill", | ||
"description": "A minimal and dependency-free vanilla JavaScript datalist polyfill. Supports all standard's functionality as well as mimics other browsers behavior.", | ||
"version": "1.17.0", | ||
"version": "1.18.0", | ||
"homepage": "https://github.com/mfranzke/datalist-polyfill", | ||
@@ -6,0 +6,0 @@ "authors": [{ |
@@ -9,2 +9,11 @@ # Changelog | ||
## [1.18.0] - 2018-07-10 | ||
### Changed | ||
- Defined the system-font for the demo-page | ||
- Renamed some variables to some more meaningful names | ||
- Cleanup on some unnecessary variables & comments | ||
### Removed | ||
- Removed an old separation in between eventTarget-Tagnames of select and option, that was integrated due to the mouse-event, which has been replaced again a while ago | ||
## [1.17.0] - 2018-07-07 | ||
@@ -11,0 +20,0 @@ ### Added |
@@ -106,8 +106,8 @@ /* | ||
if (input.value !== '') { | ||
var dataList = datalistNeedsAnUpdate; | ||
// Prepare the options and toggle the visiblity afterwards | ||
toggleVisibility( | ||
prepOptions(dataList, input), | ||
dataList.getElementsByClassName(classNamePolyfillingSelect)[0] | ||
prepOptions(datalistNeedsAnUpdate, input).length, | ||
datalistNeedsAnUpdate.getElementsByClassName( | ||
classNamePolyfillingSelect | ||
)[0] | ||
); | ||
@@ -121,46 +121,44 @@ } | ||
var inputInputList = function(event) { | ||
var eventTarget = event.target, | ||
eventTargetTagName = eventTarget.tagName.toLowerCase(), | ||
dataList = eventTarget.list; | ||
var input = event.target, | ||
datalist = input.list; | ||
// Check for whether the events target was an input datalist and still check for an existing instance | ||
// Check for whether the events target was an input and still check for an existing instance of the datalist | ||
if ( | ||
eventTargetTagName && | ||
eventTargetTagName === 'input' && | ||
dataList !== null | ||
input.tagName && | ||
input.tagName.toLowerCase() === 'input' && | ||
datalist !== null | ||
) { | ||
var dataListSelect = | ||
dataList.getElementsByClassName(classNamePolyfillingSelect)[0] || | ||
setUpPolyfillingSelect(eventTarget, dataList); | ||
// Creating the select if there's no instance so far (e.g. because of that it hasn't been handled or it has been dynamically inserted) | ||
var datalistSelect = | ||
datalist.getElementsByClassName(classNamePolyfillingSelect)[0] || | ||
setUpPolyfillingSelect(input, datalist); | ||
// Still check for an existing instance | ||
if (dataListSelect !== undefined) { | ||
if (datalistSelect !== undefined) { | ||
var visible = false, | ||
inputValue = eventTarget.value, | ||
keyOpen = event.keyCode === keyUP || event.keyCode === keyDOWN; | ||
// On an ESC or ENTER key press within the input, let's break here and afterwards hide the datalist select, and if the input contains a value | ||
// On an ESC or ENTER key press within the input, let's break here and afterwards hide the datalist select, but if the input contains a value or one of the opening keys have been pressed ... | ||
if ( | ||
event.keyCode !== keyESC && | ||
event.keyCode !== keyENTER && | ||
(inputValue !== '' || keyOpen) | ||
(input.value !== '' || keyOpen) | ||
) { | ||
// Prepare the options | ||
if (prepOptions(dataList, eventTarget)) { | ||
// ... prepare the options | ||
if (prepOptions(datalist, input).length > 0) { | ||
visible = true; | ||
} | ||
var dataListSelectOptionsLength = dataListSelect.options.length, | ||
firstEntry = 0, | ||
lastEntry = dataListSelectOptionsLength - 1; | ||
var firstEntry = 0, | ||
lastEntry = datalistSelect.options.length - 1; | ||
// ... preselect best fitting index | ||
if (touched) { | ||
// Preselect best fitting index | ||
dataListSelect.selectedIndex = firstEntry; | ||
datalistSelect.selectedIndex = firstEntry; | ||
} else if (keyOpen) { | ||
dataListSelect.selectedIndex = | ||
datalistSelect.selectedIndex = | ||
event.keyCode === keyUP ? lastEntry : firstEntry; | ||
// On arrow up or down keys, focus the select | ||
dataListSelect.focus(); | ||
// ... and on arrow up or down keys, focus the select | ||
datalistSelect.focus(); | ||
} | ||
@@ -170,3 +168,3 @@ } | ||
// Toggle the visibility of the datalist select according to previous checks | ||
toggleVisibility(visible, dataListSelect); | ||
toggleVisibility(visible, datalistSelect); | ||
} | ||
@@ -177,3 +175,3 @@ } | ||
// Function for preparing and sorting the options/suggestions | ||
var prepOptions = function(dataList, input) { | ||
var prepOptions = function(datalist, input) { | ||
if (typeof obs !== 'undefined') { | ||
@@ -183,6 +181,6 @@ obs.disconnect(); | ||
var dataListSelect = | ||
dataList.getElementsByClassName(classNamePolyfillingSelect)[0] || | ||
setUpPolyfillingSelect(input, dataList), | ||
dataListOptions = dataList.querySelectorAll('option:not(:disabled)'), | ||
var // Creating the select if there's no instance so far (e.g. because of that it hasn't been handled or it has been dynamically inserted) | ||
datalistSelect = | ||
datalist.getElementsByClassName(classNamePolyfillingSelect)[0] || | ||
setUpPolyfillingSelect(input, datalist), | ||
inputValue = input.value, | ||
@@ -197,7 +195,6 @@ newSelectValues = document.createDocumentFragment(), | ||
// ... create an array out of the options list | ||
var nodeArray = Array.prototype.slice.call(dataListOptions); | ||
// ... sort all entries and | ||
nodeArray | ||
// Create an array out of the options list | ||
Array.prototype.slice | ||
.call(datalist.querySelectorAll('option:not(:disabled)')) | ||
// ... sort all entries and | ||
.sort(function(a, b) { | ||
@@ -224,3 +221,3 @@ return a.value.localeCompare(b.value); | ||
// The innertext should be value / text in case they are different | ||
// The innertext should be 'value seperator text' in case they are different | ||
if ( | ||
@@ -246,18 +243,17 @@ text && | ||
// Input the options fragment into the datalists select | ||
dataListSelect.appendChild(newSelectValues); | ||
datalistSelect.appendChild(newSelectValues); | ||
var dataListSelectOptionsLength = dataListSelect.options.length; | ||
var datalistSelectOptionsLength = datalistSelect.options.length; | ||
dataListSelect.size = | ||
dataListSelectOptionsLength > 10 ? 10 : dataListSelectOptionsLength; | ||
dataListSelect.multiple = !touched && dataListSelectOptionsLength < 2; | ||
datalistSelect.size = | ||
datalistSelectOptionsLength > 10 ? 10 : datalistSelectOptionsLength; | ||
datalistSelect.multiple = !touched && datalistSelectOptionsLength < 2; | ||
// Input the unused options as siblings next to the select - and differentiate in between the regular, and the IE9 fix syntax upfront | ||
var dataListAppend = | ||
dataList.getElementsByClassName('ie9_fix')[0] || dataList; | ||
(datalist.getElementsByClassName('ie9_fix')[0] || datalist).appendChild( | ||
disabledValues | ||
); | ||
dataListAppend.appendChild(disabledValues); | ||
if (typeof obs !== 'undefined') { | ||
obs.observe(dataList, { | ||
obs.observe(datalist, { | ||
childList: true | ||
@@ -267,3 +263,3 @@ }); | ||
return dataListSelectOptionsLength; | ||
return datalistSelect.options; | ||
}; | ||
@@ -273,56 +269,53 @@ | ||
var changesInputList = function(event) { | ||
var eventTarget = event.target, | ||
eventTargetTagName = eventTarget.tagName.toLowerCase(), | ||
dataList = eventTarget.list; | ||
var input = event.target, | ||
datalist = input.list; | ||
// Check for whether the events target was an input datalist and still check for an existing instance | ||
// Check for whether the events target was an input and still check for an existing instance of the datalist | ||
if ( | ||
eventTargetTagName && | ||
eventTargetTagName === 'input' && | ||
dataList !== null | ||
input.tagName && | ||
input.tagName.toLowerCase() === 'input' && | ||
datalist !== null | ||
) { | ||
var eventType = event.type, | ||
// Creating the select if there's no instance so far (e.g. because of that it hasn't been handled or it has been dynamically inserted) | ||
dataListSelect = | ||
dataList.getElementsByClassName(classNamePolyfillingSelect)[0] || | ||
setUpPolyfillingSelect(eventTarget, dataList), | ||
datalistSelect = | ||
datalist.getElementsByClassName(classNamePolyfillingSelect)[0] || | ||
setUpPolyfillingSelect(input, datalist), | ||
// Either have the select set to the state to get displayed in case of that it would have been focused or because it's the target on the inputs blur - and check for general existance of any option as suggestions | ||
visible = | ||
dataListSelect && | ||
dataListSelect.querySelector('option:not(:disabled)') && | ||
((eventType === 'focusin' && eventTarget.value !== '') || | ||
(event.relatedTarget && event.relatedTarget === dataListSelect)); | ||
datalistSelect && | ||
datalistSelect.querySelector('option:not(:disabled)') && | ||
((eventType === 'focusin' && input.value !== '') || | ||
(event.relatedTarget && event.relatedTarget === datalistSelect)); | ||
// Test for whether this input has already been enhanced by the polyfill | ||
if ( | ||
(' ' + eventTarget.className + ' ').indexOf( | ||
' ' + classNameInput + ' ' | ||
) < 0 | ||
(' ' + input.className + ' ').indexOf(' ' + classNameInput + ' ') < 0 | ||
) { | ||
// We'd like to prevent autocomplete on the input datalist field | ||
eventTarget.setAttribute('autocomplete', 'off'); | ||
input.setAttribute('autocomplete', 'off'); | ||
// WAI ARIA attributes | ||
eventTarget.setAttribute('role', 'textbox'); | ||
eventTarget.setAttribute('aria-haspopup', 'true'); | ||
eventTarget.setAttribute('aria-autocomplete', 'list'); | ||
eventTarget.setAttribute('aria-owns', eventTarget.getAttribute('list')); | ||
input.setAttribute('role', 'textbox'); | ||
input.setAttribute('aria-haspopup', 'true'); | ||
input.setAttribute('aria-autocomplete', 'list'); | ||
input.setAttribute('aria-owns', input.getAttribute('list')); | ||
// Bind the keyup event on the related datalists input | ||
if (eventType === 'focusin') { | ||
eventTarget.addEventListener('keyup', inputInputList); | ||
input.addEventListener('keyup', inputInputList); | ||
eventTarget.addEventListener('focusout', changesInputList, true); | ||
input.addEventListener('focusout', changesInputList, true); | ||
} else if (eventType === 'blur') { | ||
eventTarget.removeEventListener('keyup', inputInputList); | ||
input.removeEventListener('keyup', inputInputList); | ||
eventTarget.removeEventListener('focusout', changesInputList, true); | ||
input.removeEventListener('focusout', changesInputList, true); | ||
} | ||
// Add class for identifying that this input is even already being polyfilled | ||
eventTarget.className += ' ' + classNameInput; | ||
input.className += ' ' + classNameInput; | ||
} | ||
// Toggle the visibility of the datalist select according to previous checks | ||
toggleVisibility(visible, dataListSelect); | ||
toggleVisibility(visible, datalistSelect); | ||
} | ||
@@ -332,36 +325,29 @@ }; | ||
// Define function for setting up the polyfilling select | ||
var setUpPolyfillingSelect = function(input, dataList) { | ||
var setUpPolyfillingSelect = function(input, datalist) { | ||
// Check for whether it's of one of the supported input types defined at the beginning | ||
if (supportedTypes.indexOf(input.type) > -1) { | ||
// Still check for an existing instance | ||
if (dataList !== null) { | ||
var message = dataList.title, | ||
rects = input.getClientRects(), | ||
if (datalist !== null) { | ||
var rects = input.getClientRects(), | ||
// Measurements | ||
inputStyles = window.getComputedStyle(input), | ||
inputStyleMarginRight = parseFloat( | ||
inputStyles.getPropertyValue('margin-right') | ||
), | ||
inputStyleMarginLeft = parseFloat( | ||
inputStyles.getPropertyValue('margin-left') | ||
), | ||
dataListSelect = document.createElement('select'); | ||
datalistSelect = document.createElement('select'); | ||
// Setting a class for easier selecting that select afterwards | ||
dataListSelect.setAttribute('class', classNamePolyfillingSelect); | ||
// Setting a class for easier identifying that select afterwards | ||
datalistSelect.setAttribute('class', classNamePolyfillingSelect); | ||
// Set general styling related definitions | ||
dataListSelect.style.position = 'absolute'; | ||
datalistSelect.style.position = 'absolute'; | ||
// Initially hiding the datalist select | ||
toggleVisibility(false, dataListSelect); | ||
toggleVisibility(false, datalistSelect); | ||
// The select itself shouldn't be a possible target for tabbing | ||
dataListSelect.setAttribute('tabindex', '-1'); | ||
datalistSelect.setAttribute('tabindex', '-1'); | ||
// WAI ARIA attributes | ||
dataListSelect.setAttribute('aria-live', 'polite'); | ||
dataListSelect.setAttribute('role', 'listbox'); | ||
datalistSelect.setAttribute('aria-live', 'polite'); | ||
datalistSelect.setAttribute('role', 'listbox'); | ||
if (!touched) { | ||
dataListSelect.setAttribute('aria-multiselectable', 'false'); | ||
datalistSelect.setAttribute('aria-multiselectable', 'false'); | ||
} | ||
@@ -371,16 +357,22 @@ | ||
if (inputStyles.getPropertyValue('display') === 'block') { | ||
dataListSelect.style.marginTop = | ||
datalistSelect.style.marginTop = | ||
'-' + inputStyles.getPropertyValue('margin-bottom'); | ||
} else { | ||
if (inputStyles.getPropertyValue('direction') === 'rtl') { | ||
dataListSelect.style.marginRight = | ||
'-' + (rects[0].width + inputStyleMarginLeft) + 'px'; | ||
datalistSelect.style.marginRight = | ||
'-' + | ||
(rects[0].width + | ||
parseFloat(inputStyles.getPropertyValue('margin-left'))) + | ||
'px'; | ||
} else { | ||
dataListSelect.style.marginLeft = | ||
'-' + (rects[0].width + inputStyleMarginRight) + 'px'; | ||
datalistSelect.style.marginLeft = | ||
'-' + | ||
(rects[0].width + | ||
parseFloat(inputStyles.getPropertyValue('margin-right'))) + | ||
'px'; | ||
} | ||
dataListSelect.style.marginTop = | ||
datalistSelect.style.marginTop = | ||
parseInt( | ||
rects[0].height + (input.offsetTop - dataList.offsetTop), | ||
rects[0].height + (input.offsetTop - datalist.offsetTop), | ||
10 | ||
@@ -390,7 +382,7 @@ ) + 'px'; | ||
// Set the polyfilling selects border-radius equally as the one by the polyfilled input | ||
dataListSelect.style.borderRadius = inputStyles.getPropertyValue( | ||
// Set the polyfilling selects border-radius equally to the one by the polyfilled input | ||
datalistSelect.style.borderRadius = inputStyles.getPropertyValue( | ||
'border-radius' | ||
); | ||
dataListSelect.style.minWidth = rects[0].width + 'px'; | ||
datalistSelect.style.minWidth = rects[0].width + 'px'; | ||
@@ -401,3 +393,3 @@ if (touched) { | ||
// ... and it's first entry should contain the localized message to select an entry | ||
messageElement.innerText = message; | ||
messageElement.innerText = datalist.title; | ||
// ... and disable this option, as it shouldn't get selected by the user | ||
@@ -408,20 +400,19 @@ messageElement.disabled = true; | ||
// ... and finally insert it into the select | ||
dataListSelect.appendChild(messageElement); | ||
datalistSelect.appendChild(messageElement); | ||
} | ||
// Add select to datalist element ... | ||
dataList.appendChild(dataListSelect); | ||
datalist.appendChild(datalistSelect); | ||
// ... and our upfollowing function to the change event | ||
// ... and our upfollowing functions to the related event | ||
if (touched) { | ||
dataListSelect.addEventListener('change', changeDataListSelect); | ||
datalistSelect.addEventListener('change', changeDataListSelect); | ||
} else { | ||
dataListSelect.addEventListener('click', changeDataListSelect); | ||
datalistSelect.addEventListener('click', changeDataListSelect); | ||
} | ||
dataListSelect.addEventListener('blur', changeDataListSelect); | ||
dataListSelect.addEventListener('keydown', changeDataListSelect); | ||
dataListSelect.addEventListener('keypress', datalistSelectKeyPress); | ||
datalistSelect.addEventListener('blur', changeDataListSelect); | ||
datalistSelect.addEventListener('keydown', changeDataListSelect); | ||
datalistSelect.addEventListener('keypress', datalistSelectKeyPress); | ||
return dataListSelect; | ||
return datalistSelect; | ||
} | ||
@@ -433,18 +424,12 @@ } | ||
var datalistSelectKeyPress = function(event) { | ||
var eventTarget = event.target, | ||
eventTargetTagName = eventTarget.tagName.toLowerCase(); | ||
var datalistSelect = event.target; | ||
// Check for whether the events target was a select or an option | ||
// Check for whether the events target was a select | ||
if ( | ||
eventTargetTagName && | ||
(eventTargetTagName === 'select' || eventTargetTagName === 'option') | ||
datalistSelect.tagName && | ||
datalistSelect.tagName.toLowerCase() === 'select' | ||
) { | ||
var select = | ||
eventTargetTagName === 'select' | ||
? eventTarget | ||
: eventTarget.parentNode, | ||
datalist = select.parentNode, | ||
var datalist = datalistSelect.parentNode, | ||
inputList = document.querySelector('input[list="' + datalist.id + '"]'); | ||
// Change or mouseup event or ENTER key | ||
if ( | ||
@@ -473,18 +458,12 @@ inputList !== null && | ||
var changeDataListSelect = function(event) { | ||
var eventTarget = event.target, | ||
eventTargetTagName = eventTarget.tagName.toLowerCase(); | ||
var datalistSelect = event.target; | ||
// Check for whether the events target was a select or an option | ||
// Check for whether the events target was a select | ||
if ( | ||
eventTargetTagName && | ||
(eventTargetTagName === 'select' || eventTargetTagName === 'option') | ||
datalistSelect.tagName && | ||
datalistSelect.tagName.toLowerCase() === 'select' | ||
) { | ||
var select = | ||
eventTargetTagName === 'select' | ||
? eventTarget | ||
: eventTarget.parentNode, | ||
datalist = select.parentNode, | ||
var datalist = datalistSelect.parentNode, | ||
inputList = document.querySelector('input[list="' + datalist.id + '"]'), | ||
selectValue = select.value, | ||
message = datalist.title, | ||
datalistSelectValue = datalistSelect.value, | ||
eventType = event.type, | ||
@@ -496,3 +475,3 @@ // ENTER and ESC | ||
// On change, click or ENTER or TAB key, input the selects value into the input on a change within the list | ||
// On change, click or after pressing ENTER or TAB key, input the selects value into the input on a change within the list | ||
if ( | ||
@@ -504,5 +483,5 @@ inputList !== null && | ||
(event.keyCode === keyENTER || event.key === 'Tab'))) && | ||
typeof selectValue !== 'undefined' && | ||
selectValue.length > 0 && | ||
selectValue !== message | ||
typeof datalistSelectValue !== 'undefined' && | ||
datalistSelectValue.length > 0 && | ||
datalistSelectValue !== datalist.title | ||
) { | ||
@@ -516,4 +495,6 @@ var lastSeperator, evt; | ||
(lastSeperator = inputList.value.lastIndexOf(',')) > -1 | ||
? inputList.value.slice(0, lastSeperator) + ',' + selectValue | ||
: (inputList.value = selectValue); | ||
? inputList.value.slice(0, lastSeperator) + | ||
',' + | ||
datalistSelectValue | ||
: (inputList.value = datalistSelectValue); | ||
@@ -541,3 +522,3 @@ // Create and dispatch the input event; divided for IE9 usage | ||
// Toggle the visibility of the datalist select according to previous checks | ||
toggleVisibility(visible, select); | ||
toggleVisibility(visible, datalistSelect); | ||
} | ||
@@ -547,9 +528,9 @@ }; | ||
// Toggle the visibility of the datalist select | ||
var toggleVisibility = function(visible, dataListSelect) { | ||
var toggleVisibility = function(visible, datalistSelect) { | ||
if (visible) { | ||
dataListSelect.removeAttribute('hidden'); | ||
datalistSelect.removeAttribute('hidden'); | ||
} else { | ||
dataListSelect.setAttributeNode(document.createAttribute('hidden')); | ||
datalistSelect.setAttributeNode(document.createAttribute('hidden')); | ||
} | ||
dataListSelect.setAttribute('aria-hidden', (!visible).toString()); | ||
datalistSelect.setAttribute('aria-hidden', (!visible).toString()); | ||
}; | ||
@@ -556,0 +537,0 @@ |
@@ -6,2 +6,2 @@ /* | ||
*/ | ||
!function(){"use strict";if("list"in document.createElement("input")&&Boolean(document.createElement("datalist")&&window.HTMLDataListElement))return!1;!function(e){e&&e.prototype&&void 0===e.prototype.list&&Object.defineProperty(e.prototype,"list",{get:function(){return"object"==typeof this&&this instanceof e?document.getElementById(this.getAttribute("list")):null}})}(window.HTMLInputElement),function(e){e&&e.prototype&&void 0===e.prototype.options&&Object.defineProperty(e.prototype,"options",{get:function(){return"object"==typeof this&&this instanceof e?this.getElementsByTagName("option"):null}})}(window.HTMLElement);var e=!1,t=13,i=27,n=38,o=40,a=" / ",l=["text","email","number","search","tel","url"],r="polyfilled",s="polyfilling";window.addEventListener("touchstart",function t(){e=!0,window.removeEventListener("touchstart",t)});var u=window.MutationObserver||window.WebKitMutationObserver,d;void 0!==u&&(d=new u(function(e){var t=!1;if(e.forEach(function(e){for(var i=0;i<e.addedNodes.length;++i)"datalist"===e.target.tagName.toLowerCase()&&(t=e.target)}),t){var i=document.querySelector('[list="'+t.id+'"]');if(""!==i.value){var n=t;g(c(n,i),n.getElementsByClassName("polyfilling")[0])}}}));var p=function(t){var i=t.target,n=i.tagName.toLowerCase(),o=i.list;if(n&&"input"===n&&null!==o){var a=o.getElementsByClassName("polyfilling")[0]||f(i,o);if(void 0!==a){var l=!1,r=i.value,s=38===t.keyCode||40===t.keyCode;if(27!==t.keyCode&&13!==t.keyCode&&(""!==r||s)){c(o,i)&&(l=!0);var u=a.options.length,d=0,p=u-1;e?a.selectedIndex=0:s&&(a.selectedIndex=38===t.keyCode?p:0,a.focus())}g(l,a)}}},c=function(t,i){void 0!==d&&d.disconnect();var n=t.getElementsByClassName("polyfilling")[0]||f(i,t),o=t.querySelectorAll("option:not(:disabled)"),a=i.value,l=document.createDocumentFragment(),r=document.createDocumentFragment();"email"===i.type&&i.multiple&&(a=a.substring(a.lastIndexOf(",")+1)),Array.prototype.slice.call(o).sort(function(e,t){return e.value.localeCompare(t.value)}).forEach(function(e){var t=e.value;if(""!==t&&-1!==t.toLowerCase().indexOf(a.toLowerCase())&&!1===e.disabled){var i=e.getAttribute("label"),n=e.text,o=n.substr(0,t.length+" / ".length),s=t+" / ";n&&!i&&n!==t&&o!==s?e.innerText=t+" / "+n:e.text||(e.innerText=i||t),l.appendChild(e)}else r.appendChild(e)}),n.appendChild(l);var s=n.options.length;return n.size=s>10?10:s,n.multiple=!e&&s<2,(t.getElementsByClassName("ie9_fix")[0]||t).appendChild(r),void 0!==d&&d.observe(t,{childList:!0}),s},y=function(e){var t=e.target,i=t.tagName.toLowerCase(),n=t.list;if(i&&"input"===i&&null!==n){var o=e.type,a=n.getElementsByClassName("polyfilling")[0]||f(t,n),l=a&&a.querySelector("option:not(:disabled)")&&("focusin"===o&&""!==t.value||e.relatedTarget&&e.relatedTarget===a);(" "+t.className+" ").indexOf(" polyfilled ")<0&&(t.setAttribute("autocomplete","off"),t.setAttribute("role","textbox"),t.setAttribute("aria-haspopup","true"),t.setAttribute("aria-autocomplete","list"),t.setAttribute("aria-owns",t.getAttribute("list")),"focusin"===o?(t.addEventListener("keyup",p),t.addEventListener("focusout",y,!0)):"blur"===o&&(t.removeEventListener("keyup",p),t.removeEventListener("focusout",y,!0)),t.className+=" polyfilled"),g(l,a)}},f=function(t,i){if(l.indexOf(t.type)>-1&&null!==i){var n=i.title,o=t.getClientRects(),a=window.getComputedStyle(t),r=parseFloat(a.getPropertyValue("margin-right")),s=parseFloat(a.getPropertyValue("margin-left")),u=document.createElement("select");if(u.setAttribute("class","polyfilling"),u.style.position="absolute",g(!1,u),u.setAttribute("tabindex","-1"),u.setAttribute("aria-live","polite"),u.setAttribute("role","listbox"),e||u.setAttribute("aria-multiselectable","false"),"block"===a.getPropertyValue("display")?u.style.marginTop="-"+a.getPropertyValue("margin-bottom"):("rtl"===a.getPropertyValue("direction")?u.style.marginRight="-"+(o[0].width+s)+"px":u.style.marginLeft="-"+(o[0].width+r)+"px",u.style.marginTop=parseInt(o[0].height+(t.offsetTop-i.offsetTop),10)+"px"),u.style.borderRadius=a.getPropertyValue("border-radius"),u.style.minWidth=o[0].width+"px",e){var d=document.createElement("option");d.innerText=n,d.disabled=!0,d.setAttribute("class","message"),u.appendChild(d)}return i.appendChild(u),e?u.addEventListener("change",m):u.addEventListener("click",m),u.addEventListener("blur",m),u.addEventListener("keydown",m),u.addEventListener("keypress",v),u}},v=function(e){var t=e.target,i=t.tagName.toLowerCase();if(i&&("select"===i||"option"===i)){var n="select"===i?t:t.parentNode,o=n.parentNode,a=document.querySelector('input[list="'+o.id+'"]');null===a||!e.key||"Backspace"!==e.key&&1!==e.key.length||(a.focus(),"Backspace"===e.key?a.value=a.value.substr(0,a.value.length-1):a.value+=e.key,c(o,a))}},m=function(e){var t=e.target,i=t.tagName.toLowerCase();if(i&&("select"===i||"option"===i)){var n="select"===i?t:t.parentNode,o=n.parentNode,a=document.querySelector('input[list="'+o.id+'"]'),l=n.value,r=o.title,s=e.type,u="keydown"===s&&13!==e.keyCode&&27!==e.keyCode;if(null!==a&&("change"===s||"click"===s||"keydown"===s&&(13===e.keyCode||"Tab"===e.key))&&void 0!==l&&l.length>0&&l!==r){var d,p;a.value="email"===a.type&&a.multiple&&(d=a.value.lastIndexOf(","))>-1?a.value.slice(0,d)+","+l:a.value=l,"function"==typeof Event?p=new Event("input",{bubbles:!0}):(p=document.createEvent("Event"),p.initEvent("input",!0,!1)),a.dispatchEvent(p),"Tab"!==e.key&&a.focus(),u=!1}g(u,n)}},g=function(e,t){e?t.removeAttribute("hidden"):t.setAttributeNode(document.createAttribute("hidden")),t.setAttribute("aria-hidden",(!e).toString())};document.addEventListener("focusin",y,!0)}(); | ||
!function(){"use strict";if("list"in document.createElement("input")&&Boolean(document.createElement("datalist")&&window.HTMLDataListElement))return!1;!function(e){e&&e.prototype&&void 0===e.prototype.list&&Object.defineProperty(e.prototype,"list",{get:function(){return"object"==typeof this&&this instanceof e?document.getElementById(this.getAttribute("list")):null}})}(window.HTMLInputElement),function(e){e&&e.prototype&&void 0===e.prototype.options&&Object.defineProperty(e.prototype,"options",{get:function(){return"object"==typeof this&&this instanceof e?this.getElementsByTagName("option"):null}})}(window.HTMLElement);var e=!1,t=13,i=27,n=38,a=40,o=" / ",l=["text","email","number","search","tel","url"],r="polyfilled",s="polyfilling";window.addEventListener("touchstart",function t(){e=!0,window.removeEventListener("touchstart",t)});var u=window.MutationObserver||window.WebKitMutationObserver,d;void 0!==u&&(d=new u(function(e){var t=!1;if(e.forEach(function(e){for(var i=0;i<e.addedNodes.length;++i)"datalist"===e.target.tagName.toLowerCase()&&(t=e.target)}),t){var i=document.querySelector('[list="'+t.id+'"]');""!==i.value&&g(c(t,i).length,t.getElementsByClassName("polyfilling")[0])}}));var p=function(t){var i=t.target,n=i.list;if(i.tagName&&"input"===i.tagName.toLowerCase()&&null!==n){var a=n.getElementsByClassName("polyfilling")[0]||m(i,n);if(void 0!==a){var o=!1,l=38===t.keyCode||40===t.keyCode;if(27!==t.keyCode&&13!==t.keyCode&&(""!==i.value||l)){c(n,i).length>0&&(o=!0);var r=0,s=a.options.length-1;e?a.selectedIndex=0:l&&(a.selectedIndex=38===t.keyCode?s:0,a.focus())}g(o,a)}}},c=function(t,i){void 0!==d&&d.disconnect();var n=t.getElementsByClassName("polyfilling")[0]||m(i,t),a=i.value,o=document.createDocumentFragment(),l=document.createDocumentFragment();"email"===i.type&&i.multiple&&(a=a.substring(a.lastIndexOf(",")+1)),Array.prototype.slice.call(t.querySelectorAll("option:not(:disabled)")).sort(function(e,t){return e.value.localeCompare(t.value)}).forEach(function(e){var t=e.value;if(""!==t&&-1!==t.toLowerCase().indexOf(a.toLowerCase())&&!1===e.disabled){var i=e.getAttribute("label"),n=e.text,r=n.substr(0,t.length+" / ".length),s=t+" / ";n&&!i&&n!==t&&r!==s?e.innerText=t+" / "+n:e.text||(e.innerText=i||t),o.appendChild(e)}else l.appendChild(e)}),n.appendChild(o);var r=n.options.length;return n.size=r>10?10:r,n.multiple=!e&&r<2,(t.getElementsByClassName("ie9_fix")[0]||t).appendChild(l),void 0!==d&&d.observe(t,{childList:!0}),n.options},y=function(e){var t=e.target,i=t.list;if(t.tagName&&"input"===t.tagName.toLowerCase()&&null!==i){var n=e.type,a=i.getElementsByClassName("polyfilling")[0]||m(t,i),o=a&&a.querySelector("option:not(:disabled)")&&("focusin"===n&&""!==t.value||e.relatedTarget&&e.relatedTarget===a);(" "+t.className+" ").indexOf(" polyfilled ")<0&&(t.setAttribute("autocomplete","off"),t.setAttribute("role","textbox"),t.setAttribute("aria-haspopup","true"),t.setAttribute("aria-autocomplete","list"),t.setAttribute("aria-owns",t.getAttribute("list")),"focusin"===n?(t.addEventListener("keyup",p),t.addEventListener("focusout",y,!0)):"blur"===n&&(t.removeEventListener("keyup",p),t.removeEventListener("focusout",y,!0)),t.className+=" polyfilled"),g(o,a)}},m=function(t,i){if(l.indexOf(t.type)>-1&&null!==i){var n=t.getClientRects(),a=window.getComputedStyle(t),o=document.createElement("select");if(o.setAttribute("class","polyfilling"),o.style.position="absolute",g(!1,o),o.setAttribute("tabindex","-1"),o.setAttribute("aria-live","polite"),o.setAttribute("role","listbox"),e||o.setAttribute("aria-multiselectable","false"),"block"===a.getPropertyValue("display")?o.style.marginTop="-"+a.getPropertyValue("margin-bottom"):("rtl"===a.getPropertyValue("direction")?o.style.marginRight="-"+(n[0].width+parseFloat(a.getPropertyValue("margin-left")))+"px":o.style.marginLeft="-"+(n[0].width+parseFloat(a.getPropertyValue("margin-right")))+"px",o.style.marginTop=parseInt(n[0].height+(t.offsetTop-i.offsetTop),10)+"px"),o.style.borderRadius=a.getPropertyValue("border-radius"),o.style.minWidth=n[0].width+"px",e){var r=document.createElement("option");r.innerText=i.title,r.disabled=!0,r.setAttribute("class","message"),o.appendChild(r)}return i.appendChild(o),e?o.addEventListener("change",v):o.addEventListener("click",v),o.addEventListener("blur",v),o.addEventListener("keydown",v),o.addEventListener("keypress",f),o}},f=function(e){var t=e.target;if(t.tagName&&"select"===t.tagName.toLowerCase()){var i=t.parentNode,n=document.querySelector('input[list="'+i.id+'"]');null===n||!e.key||"Backspace"!==e.key&&1!==e.key.length||(n.focus(),"Backspace"===e.key?n.value=n.value.substr(0,n.value.length-1):n.value+=e.key,c(i,n))}},v=function(e){var t=e.target;if(t.tagName&&"select"===t.tagName.toLowerCase()){var i=t.parentNode,n=document.querySelector('input[list="'+i.id+'"]'),a=t.value,o=e.type,l="keydown"===o&&13!==e.keyCode&&27!==e.keyCode;if(null!==n&&("change"===o||"click"===o||"keydown"===o&&(13===e.keyCode||"Tab"===e.key))&&void 0!==a&&a.length>0&&a!==i.title){var r,s;n.value="email"===n.type&&n.multiple&&(r=n.value.lastIndexOf(","))>-1?n.value.slice(0,r)+","+a:n.value=a,"function"==typeof Event?s=new Event("input",{bubbles:!0}):(s=document.createEvent("Event"),s.initEvent("input",!0,!1)),n.dispatchEvent(s),"Tab"!==e.key&&n.focus(),l=!1}g(l,t)}},g=function(e,t){e?t.removeAttribute("hidden"):t.setAttributeNode(document.createAttribute("hidden")),t.setAttribute("aria-hidden",(!e).toString())};document.addEventListener("focusin",y,!0)}(); |
{ | ||
"name": "datalist-polyfill", | ||
"version": "1.17.0", | ||
"version": "1.18.0", | ||
"description": "A minimal and dependency-free vanilla JavaScript datalist polyfill. Supports all standard's functionality as well as mimics other browsers behavior.", | ||
@@ -5,0 +5,0 @@ "main": "datalist-polyfill.js", |
@@ -24,3 +24,3 @@ [npm]: https://npmjs.com/package/datalist-polyfill "datalist polyfill – on NPM" | ||
## Features | ||
* Lightweight: 6.07 kB of minified JavaScript, around 2.59 kB gzipped | ||
* Lightweight: 5.98 kB of minified JavaScript, around 2.54 kB gzipped | ||
* Fully flexible to change the datalist entries / `<option>`s | ||
@@ -27,0 +27,0 @@ * Supporting: |
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
55300
481