Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

datalist-polyfill

Package Overview
Dependencies
Maintainers
1
Versions
64
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

datalist-polyfill - npm Package Compare versions

Comparing version 1.21.2 to 1.22.0

.codacy.yaml

2

bower.json
{
"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.21.2",
"version": "1.22.0",
"homepage": "https://github.com/mfranzke/datalist-polyfill",

@@ -6,0 +6,0 @@ "authors": [

@@ -10,2 +10,8 @@ # Changelog

## [1.22.0] - 2018-08-27
### Added
- Substring matching for the suggestions on both the `value` and the `text` values / #GH-36
## [1.21.2] - 2018-08-11

@@ -15,7 +21,7 @@

- Finally integrated the test regarding clicking the selects option elements, as this was actually previously prevented by the other bug fixed in the previous release
- Finally integrated the test regarding clicking the `select`s `option` elements, as this was actually previously prevented by the other bug fixed in the previous release
### Fixed
- Corrected the code style of the readme file again, as this got incorrectly reformatted previously
- Corrected the code style of the README file again, as this got incorrectly reformatted previously

@@ -26,3 +32,3 @@ ## [1.21.1] - 2018-08-09

- Suggestions aren‘t working onclick any more (#GH-35)
- Suggestions aren‘t working onClick any more (#GH-35)

@@ -29,0 +35,0 @@ ## [1.21.0] - 2018-08-08

@@ -16,50 +16,23 @@ /*

// Performance: Set a local variable
var dcmnt = window.document;
// Performance: Set local variables
var dcmnt = window.document,
ua = window.navigator.userAgent,
// Feature detection
datalistSupported =
'list' in dcmnt.createElement('input') &&
Boolean(dcmnt.createElement('datalist') && window.HTMLDataListElement),
// IE & EDGE browser detection via UserAgent
// TODO: obviously ugly. But sadly necessary until Microsoft enhances the UX within EDGE (compare to https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/9573654/)
// adapted out of https://gist.github.com/gaboratorium/25f08b76eb82b1e7b91b01a0448f8b1d :
isGteIE11orEDGE = Boolean(
ua.indexOf('Trident/') !== -1 || ua.indexOf('Edge/') !== -1
);
// Feature detection - let's break here, if it's even already supported
if (
'list' in dcmnt.createElement('input') &&
Boolean(dcmnt.createElement('datalist') && window.HTMLDataListElement)
) {
// Let's break here, if it's even already supported ... and not IE11+ or EDGE
if (datalistSupported && !isGteIE11orEDGE) {
return false;
}
// Emulate the two properties regarding the datalist and input elements
// list property / https://developer.mozilla.org/en/docs/Web/API/HTMLInputElement
(function(constructor) {
if (
constructor &&
constructor.prototype &&
constructor.prototype.list === undefined
) {
Object.defineProperty(constructor.prototype, 'list', {
get: function() {
// The list IDL attribute must return the current suggestions source element, if any, or null otherwise.
return typeof this === 'object' && this instanceof constructor
? dcmnt.querySelector('datalist#' + this.getAttribute('list'))
: null;
}
});
}
})(window.HTMLInputElement);
// Options property / https://developer.mozilla.org/en/docs/Web/API/HTMLDataListElement
(function(constructor) {
if (
constructor &&
constructor.prototype &&
constructor.prototype.options === undefined
) {
Object.defineProperty(constructor.prototype, 'options', {
get: function() {
return typeof this === 'object' && this instanceof constructor
? this.getElementsByTagName('option')
: null;
}
});
}
})(window.HTMLElement);
// .matches polyfill
// TODO: probably needs enhancement on the to supported browsers
// TODO: probably needs enhancement on the expected to be supported browsers
if (!Element.prototype.matches) {

@@ -82,3 +55,5 @@ Element.prototype.matches = Element.prototype.msMatchesSelector;

classNameInput = 'polyfilled',
classNamePolyfillingSelect = 'polyfilling';
classNamePolyfillingSelect = 'polyfilling',
// Defining a most likely unique polyfill string
uniquePolyfillString = '###[P0LYFlLLed]###';

@@ -134,17 +109,31 @@ // Differentiate for touch interactions, adapted by https://medium.com/@david.gilbertson/the-only-way-to-detect-touch-with-javascript-7791a3346685

datalist = input.list,
// 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);
keyOpen = event.keyCode === keyUP || event.keyCode === keyDOWN;
// Check for whether the events target was an input and still check for an existing instance of the datalist and polyfilling select
if (
input.tagName.toLowerCase() !== 'input' ||
datalist === null ||
datalistSelect === undefined
) {
if (input.tagName.toLowerCase() !== 'input' || datalist === null) {
return;
}
// Handling IE11+ & EDGE
if (isGteIE11orEDGE) {
// On keypress check for value
if (
input.value !== '' &&
!keyOpen &&
event.keyCode !== keyENTER &&
event.keyCode !== keyESC
) {
updateIEOptions(input, datalist);
// TODO: Check whether this update is necessary depending on the options values
input.focus();
}
return;
}
var visible = false,
keyOpen = event.keyCode === keyUP || event.keyCode === keyDOWN;
// 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);

@@ -155,3 +144,4 @@ // 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 ...

event.keyCode !== keyENTER &&
(input.value !== '' || keyOpen)
(input.value !== '' || keyOpen) &&
datalistSelect !== undefined
) {

@@ -182,2 +172,148 @@ // ... prepare the options

// On keypress check all options for that as a substring, save the original value as a data-attribute and preset that inputs value (for sorting) for all option values (probably as well enhanced by a token)
var updateIEOptions = function(input, datalist) {
// Loop through the options
Array.prototype.slice.call(datalist.options, 0).forEach(function(option) {
var originalValue = option.dataset.originalvalue || option.value;
// In case of that the original value hasn't been saved as data so far, do that now
if (!option.dataset.originalvalue) {
option.dataset.originalvalue = originalValue;
}
// As we'd manipulate the value in the next step, we'd like to put in that value as either a label or text if none of those exist
if (!option.label && !option.text) {
option.label = originalValue;
}
/*
Check for whether the current option is a valid suggestion and replace its value by
- the current input string, as IE11+ and EDGE don't do substring, but only prefix matching
- followed by a unique string that should prevent any interferance
- and the original string, that is still necessary e.g. for sorting within the suggestions list
As the value is being inserted on users selection, we'll replace that one within the upfollowing inputInputListIE function
*/
option.value = isValidSuggestion(option, input.value)
? input.value + uniquePolyfillString + originalValue.toLowerCase()
: originalValue;
});
};
// Check for the input and probably replace by correct options elements value
var inputInputListIE = function(event) {
var input = event.target,
datalist = input.list;
if (
!input.matches('input[list]') ||
!input.matches('.' + classNameInput) ||
!datalist
) {
return;
}
// Query for related option
var option = datalist.querySelector('option[value="' + input.value + '"]');
if (option && option.dataset.originalvalue) {
input.value = option.dataset.originalvalue;
}
};
// Check for whether this is a valid suggestion
var isValidSuggestion = function(option, inputValue) {
var optVal = option.value.toLowerCase(),
inptVal = inputValue.toLowerCase(),
label = option.getAttribute('label'),
text = option.text.toLowerCase();
/*
"Each option element that is a descendant of the datalist element, that is not disabled, and whose value is a string that isn't the empty string, represents a suggestion. Each suggestion has a value and a label."
"If appropriate, the user agent should use the suggestion's label and value to identify the suggestion to the user."
*/
return Boolean(
option.disabled === false &&
((optVal !== '' && optVal.indexOf(inptVal) !== -1) ||
(label && label.toLowerCase().indexOf(inptVal) !== -1) ||
(text !== '' && text.indexOf(inptVal) !== -1))
);
};
// Focusin and -out events
var changesInputList = function(event) {
// Check for correct element on this event delegation
if (!event.target.matches('input[list]')) {
return;
}
var input = event.target,
datalist = input.list;
// Check for whether the events target was an input and still check for an existing instance of the datalist
if (input.tagName.toLowerCase() !== 'input' || datalist === null) {
return;
}
// Test for whether this input has already been enhanced by the polyfill
if (!input.matches('.' + classNameInput)) {
// We'd like to prevent autocomplete on the input datalist field
input.setAttribute('autocomplete', 'off');
// WAI ARIA attributes
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 (event.type === 'focusin') {
input.addEventListener('keyup', inputInputList);
input.addEventListener('focusout', changesInputList, true);
if (isGteIE11orEDGE) {
input.addEventListener('input', inputInputListIE);
}
} else if (event.type === 'blur') {
input.removeEventListener('keyup', inputInputList);
input.removeEventListener('focusout', changesInputList, true);
if (isGteIE11orEDGE) {
input.removeEventListener('input', inputInputListIE);
}
}
// Add class for identifying that this input is even already being polyfilled
input.className += ' ' + classNameInput;
}
// Break here for IE11+ & EDGE
if (isGteIE11orEDGE) {
return;
}
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),
// 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)') &&
((event.type === 'focusin' && input.value !== '') ||
(event.relatedTarget && event.relatedTarget === datalistSelect));
// Toggle the visibility of the datalist select according to previous checks
toggleVisibility(visible, datalistSelect);
};
// Binding the focus event - matching the input[list]s happens in the function afterwards
dcmnt.addEventListener('focusin', changesInputList, true);
// Break here for IE11+ & EDGE
if (isGteIE11orEDGE) {
return;
}
// Function for preparing and sorting the options/suggestions

@@ -223,14 +359,10 @@ var prepOptions = function(datalist, input) {

.forEach(function(opt) {
var optionValue = opt.value;
var optionValue = opt.value,
label = opt.getAttribute('label'),
text = opt.text;
// ... put this option into the fragment that is meant to get inserted into the select
// "Each option element that is a descendant of the datalist element, that is not disabled, and whose value is a string that isn't the empty string, represents a suggestion. Each suggestion has a value and a label." (W3C)
if (
optionValue !== '' &&
optionValue.toLowerCase().indexOf(inputValue.toLowerCase()) !== -1 &&
opt.disabled === false
) {
var label = opt.getAttribute('label'),
text = opt.text,
textOptionPart = text.substr(
// Put this option into the fragment that is meant to get inserted into the select. Additionally according to the specs ...
// TODO: This might get slightly changed/optimized in a future release
if (isValidSuggestion(opt, inputValue)) {
var textOptionPart = text.substr(
0,

@@ -284,59 +416,2 @@ optionValue.length + textValueSeperator.length

// Focusin and -out events
var changesInputList = function(event) {
// Check for correct element on this event delegation
if (!event.target.matches('input[list]')) {
return;
}
var input = event.target,
datalist = input.list;
// Check for whether the events target was an input and still check for an existing instance of the datalist
if (input.tagName.toLowerCase() !== 'input' || datalist === null) {
return;
}
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(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' && input.value !== '') ||
(event.relatedTarget && event.relatedTarget === datalistSelect));
// Test for whether this input has already been enhanced by the polyfill
if (!input.matches('.' + classNameInput)) {
// We'd like to prevent autocomplete on the input datalist field
input.setAttribute('autocomplete', 'off');
// WAI ARIA attributes
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') {
input.addEventListener('keyup', inputInputList);
input.addEventListener('focusout', changesInputList, true);
} else if (eventType === 'blur') {
input.removeEventListener('keyup', inputInputList);
input.removeEventListener('focusout', changesInputList, true);
}
// Add class for identifying that this input is even already being polyfilled
input.className += ' ' + classNameInput;
}
// Toggle the visibility of the datalist select according to previous checks
toggleVisibility(visible, datalistSelect);
};
// Define function for setting up the polyfilling select

@@ -542,4 +617,45 @@ var setUpPolyfillingSelect = function(input, datalist) {

// Binding the focus event - matching the input[list]s happens in the function afterwards
dcmnt.addEventListener('focusin', changesInputList, true);
// Emulate the two properties regarding the datalist and input elements
// list property / https://developer.mozilla.org/en/docs/Web/API/HTMLInputElement
(function(constructor) {
if (
constructor &&
constructor.prototype &&
constructor.prototype.list === undefined
) {
Object.defineProperty(constructor.prototype, 'list', {
get: function() {
/*
According to the specs ...
"The list IDL attribute must return the current suggestions source element, if any, or null otherwise."
"If there is no list attribute, or if there is no element with that ID, or if the first element with that ID is not a datalist element, then there is no suggestions source element."
*/
var element = dcmnt.getElementById(this.getAttribute('list'));
return typeof this === 'object' &&
this instanceof constructor &&
element &&
element.matches('datalist')
? element
: null;
}
});
}
})(window.HTMLInputElement);
// Options property / https://developer.mozilla.org/en/docs/Web/API/HTMLDataListElement
(function(constructor) {
if (
constructor &&
constructor.prototype &&
constructor.prototype.options === undefined
) {
Object.defineProperty(constructor.prototype, 'options', {
get: function() {
return typeof this === 'object' && this instanceof constructor
? this.getElementsByTagName('option')
: null;
}
});
}
})(window.HTMLElement);
})();

@@ -6,2 +6,2 @@ /*

*/
!function(){"use strict";var e=window.document;if("list"in e.createElement("input")&&Boolean(e.createElement("datalist")&&window.HTMLDataListElement))return!1;!function(t){t&&t.prototype&&void 0===t.prototype.list&&Object.defineProperty(t.prototype,"list",{get:function(){return"object"==typeof this&&this instanceof t?e.querySelector("datalist#"+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),Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector);var t=!1,i=13,n=27,l=38,r=40,a=" / ",o=["text","email","number","search","tel","url"],s="polyfilled",u="polyfilling";window.addEventListener("touchstart",function e(){t=!0,window.removeEventListener("touchstart",e)});var d=window.MutationObserver||window.WebKitMutationObserver,p;void 0!==d&&(p=new d(function(t){var i=!1;if(t.forEach(function(e){for(var t=0;t<e.addedNodes.length;++t)"datalist"===e.target.tagName.toLowerCase()&&(i=e.target)}),i){var n=e.querySelector('input[list="'+i.id+'"]');""!==n.value&&h(y(i,n).length,i.getElementsByClassName("polyfilling")[0])}}));var c=function(e){var i=e.target,n=i.list,l=n.getElementsByClassName("polyfilling")[0]||f(i,n);if("input"===i.tagName.toLowerCase()&&null!==n&&void 0!==l){var r=!1,a=38===e.keyCode||40===e.keyCode;if(27!==e.keyCode&&13!==e.keyCode&&(""!==i.value||a)){y(n,i).length>0&&(r=!0);var o=0,s=l.options.length-1;t?l.selectedIndex=0:a&&"number"!==i.getAttribute("type")&&(l.selectedIndex=38===e.keyCode?s:0,l.focus())}h(r,l)}},y=function(i,n){void 0!==p&&p.disconnect();var l=i.getElementsByClassName("polyfilling")[0]||f(n,i),r=n.value,a=e.createDocumentFragment(),o=e.createDocumentFragment();"email"===n.getAttribute("type")&&null!==n.getAttribute("multiple")&&(r=r.substring(r.lastIndexOf(",")+1)),Array.prototype.slice.call(i.querySelectorAll("option:not(:disabled)")).sort(function(e,t){var i=e.value,l=t.value;return"url"===n.getAttribute("type")&&(i=i.replace(/(^\w+:|^)\/\//,""),l=l.replace(/(^\w+:|^)\/\//,"")),i.localeCompare(l)}).forEach(function(e){var t=e.value;if(""!==t&&-1!==t.toLowerCase().indexOf(r.toLowerCase())&&!1===e.disabled){var i=e.getAttribute("label"),n=e.text,l=n.substr(0,t.length+" / ".length),s=t+" / ";n&&!i&&n!==t&&l!==s?e.innerText=t+" / "+n:e.text||(e.innerText=i||t),a.appendChild(e)}else o.appendChild(e)}),l.appendChild(a);var s=l.options.length;return l.size=s>10?10:s,l.multiple=!t&&s<2,(i.getElementsByClassName("ie9_fix")[0]||i).appendChild(o),void 0!==p&&p.observe(i,{childList:!0}),l.options},v=function(e){if(e.target.matches("input[list]")){var t=e.target,i=t.list;if("input"===t.tagName.toLowerCase()&&null!==i){var n=e.type,l=i.getElementsByClassName("polyfilling")[0]||f(t,i),r=l&&l.querySelector("option:not(:disabled)")&&("focusin"===n&&""!==t.value||e.relatedTarget&&e.relatedTarget===l);t.matches(".polyfilled")||(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",c),t.addEventListener("focusout",v,!0)):"blur"===n&&(t.removeEventListener("keyup",c),t.removeEventListener("focusout",v,!0)),t.className+=" polyfilled"),h(r,l)}}},f=function(i,n){if(-1!==o.indexOf(i.getAttribute("type"))&&null!==n){var l=i.getClientRects(),r=window.getComputedStyle(i),a=e.createElement("select");if(a.setAttribute("class","polyfilling"),a.style.position="absolute",h(!1,a),a.setAttribute("tabindex","-1"),a.setAttribute("aria-live","polite"),a.setAttribute("role","listbox"),t||a.setAttribute("aria-multiselectable","false"),"block"===r.getPropertyValue("display"))a.style.marginTop="-"+r.getPropertyValue("margin-bottom");else{var s="rtl"===r.getPropertyValue("direction")?"right":"left";a.style.setProperty("margin-"+s,"-"+(l[0].width+parseFloat(r.getPropertyValue("margin-"+s)))+"px"),a.style.marginTop=parseInt(l[0].height+(i.offsetTop-n.offsetTop),10)+"px"}if(a.style.borderRadius=r.getPropertyValue("border-radius"),a.style.minWidth=l[0].width+"px",t){var u=e.createElement("option");u.innerText=n.title,u.disabled=!0,u.setAttribute("class","message"),a.appendChild(u)}return n.appendChild(a),t?a.addEventListener("change",m):a.addEventListener("click",m),a.addEventListener("blur",m),a.addEventListener("keydown",m),a.addEventListener("keypress",g),a}},g=function(t){var i=t.target,n=i.parentNode,l=e.querySelector('input[list="'+n.id+'"]');"select"===i.tagName.toLowerCase()&&null!==l&&(!t.key||"Backspace"!==t.key&&1!==t.key.length||(l.focus(),"Backspace"===t.key?(l.value=l.value.substr(0,l.value.length-1),b(l)):l.value+=t.key,y(n,l)))},m=function(t){var i=t.currentTarget,n=i.parentNode,l=e.querySelector('input[list="'+n.id+'"]');if("select"===i.tagName.toLowerCase()&&null!==l){var r=t.type,a="keydown"===r&&13!==t.keyCode&&27!==t.keyCode;if(("change"===r||"click"===r||"keydown"===r&&(13===t.keyCode||"Tab"===t.key))&&i.value.length>0&&i.value!==n.title){var o;l.value="email"===l.getAttribute("type")&&null!==l.getAttribute("multiple")&&(o=l.value.lastIndexOf(","))>-1?l.value.slice(0,o)+","+i.value:l.value=i.value,b(l),"Tab"!==t.key&&l.focus(),a=!1}else"keydown"===r&&27===t.keyCode&&l.focus();h(a,i)}},b=function(t){var i;"function"==typeof Event?i=new Event("input",{bubbles:!0}):(i=e.createEvent("Event"),i.initEvent("input",!0,!1)),t.dispatchEvent(i)},h=function(t,i){t?i.removeAttribute("hidden"):i.setAttributeNode(e.createAttribute("hidden")),i.setAttribute("aria-hidden",(!t).toString())};e.addEventListener("focusin",v,!0)}();
!function(){"use strict";var e=window.document,t=window.navigator.userAgent,i="list"in e.createElement("input")&&Boolean(e.createElement("datalist")&&window.HTMLDataListElement),a=Boolean(-1!==t.indexOf("Trident/")||-1!==t.indexOf("Edge/"));if(i&&!a)return!1;Element.prototype.matches||(Element.prototype.matches=Element.prototype.msMatchesSelector);var n=!1,l=13,r=27,o=38,s=40,u=" / ",d=["text","email","number","search","tel","url"],p="polyfilled",c="polyfilling",v="###[P0LYFlLLed]###";window.addEventListener("touchstart",function e(){n=!0,window.removeEventListener("touchstart",e)});var y=window.MutationObserver||window.WebKitMutationObserver,f;void 0!==y&&(f=new y(function(t){var i=!1;if(t.forEach(function(e){for(var t=0;t<e.addedNodes.length;++t)"datalist"===e.target.tagName.toLowerCase()&&(i=e.target)}),i){var a=e.querySelector('input[list="'+i.id+'"]');""!==a.value&&x(E(i,a).length,i.getElementsByClassName("polyfilling")[0])}}));var g=function(e){var t=e.target,i=t.list,l=38===e.keyCode||40===e.keyCode;if("input"===t.tagName.toLowerCase()&&null!==i){if(a)return void(""===t.value||l||13===e.keyCode||27===e.keyCode||(m(t,i),t.focus()));var r=!1,o=i.getElementsByClassName("polyfilling")[0]||C(t,i);if(27!==e.keyCode&&13!==e.keyCode&&(""!==t.value||l)&&void 0!==o){E(i,t).length>0&&(r=!0);var s=0,u=o.options.length-1;n?o.selectedIndex=0:l&&"number"!==t.getAttribute("type")&&(o.selectedIndex=38===e.keyCode?u:0,o.focus())}x(r,o)}},m=function(e,t){Array.prototype.slice.call(t.options,0).forEach(function(t){var i=t.dataset.originalvalue||t.value;t.dataset.originalvalue||(t.dataset.originalvalue=i),t.label||t.text||(t.label=i),t.value=h(t,e.value)?e.value+"###[P0LYFlLLed]###"+i.toLowerCase():i})},b=function(e){var t=e.target,i=t.list;if(t.matches("input[list]")&&t.matches(".polyfilled")&&i){var a=i.querySelector('option[value="'+t.value+'"]');a&&a.dataset.originalvalue&&(t.value=a.dataset.originalvalue)}},h=function(e,t){var i=e.value.toLowerCase(),a=t.toLowerCase(),n=e.getAttribute("label"),l=e.text.toLowerCase();return Boolean(!1===e.disabled&&(""!==i&&-1!==i.indexOf(a)||n&&-1!==n.toLowerCase().indexOf(a)||""!==l&&-1!==l.indexOf(a)))},w=function(e){if(e.target.matches("input[list]")){var t=e.target,i=t.list;if("input"===t.tagName.toLowerCase()&&null!==i&&(t.matches(".polyfilled")||(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"===e.type?(t.addEventListener("keyup",g),t.addEventListener("focusout",w,!0),a&&t.addEventListener("input",b)):"blur"===e.type&&(t.removeEventListener("keyup",g),t.removeEventListener("focusout",w,!0),a&&t.removeEventListener("input",b)),t.className+=" polyfilled"),!a)){var n=i.getElementsByClassName("polyfilling")[0]||C(t,i),l=n&&n.querySelector("option:not(:disabled)")&&("focusin"===e.type&&""!==t.value||e.relatedTarget&&e.relatedTarget===n);x(l,n)}}};if(e.addEventListener("focusin",w,!0),!a){var E=function(t,i){void 0!==f&&f.disconnect();var a=t.getElementsByClassName("polyfilling")[0]||C(i,t),l=i.value,r=e.createDocumentFragment(),o=e.createDocumentFragment();"email"===i.getAttribute("type")&&null!==i.getAttribute("multiple")&&(l=l.substring(l.lastIndexOf(",")+1)),Array.prototype.slice.call(t.querySelectorAll("option:not(:disabled)")).sort(function(e,t){var a=e.value,n=t.value;return"url"===i.getAttribute("type")&&(a=a.replace(/(^\w+:|^)\/\//,""),n=n.replace(/(^\w+:|^)\/\//,"")),a.localeCompare(n)}).forEach(function(e){var t=e.value,i=e.getAttribute("label"),a=e.text;if(h(e,l)){var n=a.substr(0,t.length+" / ".length),s=t+" / ";a&&!i&&a!==t&&n!==s?e.innerText=t+" / "+a:e.text||(e.innerText=i||t),r.appendChild(e)}else o.appendChild(e)}),a.appendChild(r);var s=a.options.length;return a.size=s>10?10:s,a.multiple=!n&&s<2,(t.getElementsByClassName("ie9_fix")[0]||t).appendChild(o),void 0!==f&&f.observe(t,{childList:!0}),a.options},C=function(t,i){if(-1!==d.indexOf(t.getAttribute("type"))&&null!==i){var a=t.getClientRects(),l=window.getComputedStyle(t),r=e.createElement("select");if(r.setAttribute("class","polyfilling"),r.style.position="absolute",x(!1,r),r.setAttribute("tabindex","-1"),r.setAttribute("aria-live","polite"),r.setAttribute("role","listbox"),n||r.setAttribute("aria-multiselectable","false"),"block"===l.getPropertyValue("display"))r.style.marginTop="-"+l.getPropertyValue("margin-bottom");else{var o="rtl"===l.getPropertyValue("direction")?"right":"left";r.style.setProperty("margin-"+o,"-"+(a[0].width+parseFloat(l.getPropertyValue("margin-"+o)))+"px"),r.style.marginTop=parseInt(a[0].height+(t.offsetTop-i.offsetTop),10)+"px"}if(r.style.borderRadius=l.getPropertyValue("border-radius"),r.style.minWidth=a[0].width+"px",n){var s=e.createElement("option");s.innerText=i.title,s.disabled=!0,s.setAttribute("class","message"),r.appendChild(s)}return i.appendChild(r),n?r.addEventListener("change",k):r.addEventListener("click",k),r.addEventListener("blur",k),r.addEventListener("keydown",k),r.addEventListener("keypress",L),r}},L=function(t){var i=t.target,a=i.parentNode,n=e.querySelector('input[list="'+a.id+'"]');"select"===i.tagName.toLowerCase()&&null!==n&&(!t.key||"Backspace"!==t.key&&1!==t.key.length||(n.focus(),"Backspace"===t.key?(n.value=n.value.substr(0,n.value.length-1),A(n)):n.value+=t.key,E(a,n)))},k=function(t){var i=t.currentTarget,a=i.parentNode,n=e.querySelector('input[list="'+a.id+'"]');if("select"===i.tagName.toLowerCase()&&null!==n){var l=t.type,r="keydown"===l&&13!==t.keyCode&&27!==t.keyCode;if(("change"===l||"click"===l||"keydown"===l&&(13===t.keyCode||"Tab"===t.key))&&i.value.length>0&&i.value!==a.title){var o;n.value="email"===n.getAttribute("type")&&null!==n.getAttribute("multiple")&&(o=n.value.lastIndexOf(","))>-1?n.value.slice(0,o)+","+i.value:n.value=i.value,A(n),"Tab"!==t.key&&n.focus(),r=!1}else"keydown"===l&&27===t.keyCode&&n.focus();x(r,i)}},A=function(t){var i;"function"==typeof Event?i=new Event("input",{bubbles:!0}):(i=e.createEvent("Event"),i.initEvent("input",!0,!1)),t.dispatchEvent(i)},x=function(t,i){t?i.removeAttribute("hidden"):i.setAttributeNode(e.createAttribute("hidden")),i.setAttribute("aria-hidden",(!t).toString())};!function(t){t&&t.prototype&&void 0===t.prototype.list&&Object.defineProperty(t.prototype,"list",{get:function(){var i=e.getElementById(this.getAttribute("list"));return"object"==typeof this&&this instanceof t&&i&&i.matches("datalist")?i: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)}}();
{
"name": "datalist-polyfill",
"version": "1.21.2",
"version": "1.22.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",

@@ -18,3 +18,3 @@ [npm]: https://npmjs.com/package/datalist-polyfill 'datalist polyfill – on NPM'

- Supports all standard's functionality as well as mimics other browsers behavior.
- Mainly built for Safari (but supporting IE9 as well), as nearly all of the other browsers [support it quite nicely](https://caniuse.com/#feat=datalist)
- Mitigating the [different levels of support](https://caniuse.com/#feat=datalist) both by Safari and IE9+ as well as EDGE
- Released under the MIT license

@@ -25,3 +25,3 @@ - Made in Germany. And supported by so many great people from all over this planet - see "Credits" accordingly.

- Lightweight: 6.23 kB of minified JavaScript, around 2.66 kB gzipped
- Lightweight: 5.6 kB of minified JavaScript, around 2.2 kB gzipped
- Fully flexible to change the datalist entries / `<option>`s

@@ -39,2 +39,3 @@ - Supporting:

- on `input[type=url]` omitting the scheme part and performing intelligent matching on the domain name
- substring matching on both the `value` and the `text` values
- Emits "input" event when item in the `datalist` is selected

@@ -138,2 +139,3 @@ - Enables core keyboard controls such as the

- Windows 7 SP1, Internet Explorer 9.0.8112.16421
- Windows 8.1, Internet Explorer 11.0.9600.19101

@@ -148,2 +150,38 @@ ### Big Thanks

## Prospects & functionality overview
The following problems are mainly reported and [listed on caniuse](https://caniuse.com/#feat=datalist) as well as due to issues flagged on Github.
<table>
<tr>
<th>Problem</th>
<th>iOS</th>
<th>Safari</th>
<th>IE9</th>
<th>IE11+</th>
<th>EDGE</th>
<th>Firefox</th>
<th>Chrome</th>
<th>Chrome WebView</th>
</tr>
<tr>
<th align="left">Basic functionality</th>
<td colspan="3" align="center">✔ <i>Polyfill</i></td>
<td colspan="4" align="center">✔</td>
<td align="center"><a href="https://github.com/mfranzke/datalist-polyfill/issues/33">#GH-33</a></td>
</tr>
<tr>
<th align="left"><a href="https://bugs.chromium.org/p/chromium/issues/detail?id=773041">long lists of items are unscrollable resulting in unselectable options</a></th>
<td colspan="6">&nbsp;</td>
<td>fixed with v.70</td>
<td>&nbsp;</td>
</tr>
<tr>
<th align="left"><a href="https://developer.microsoft.com/en-us/microsoft-edge/platform/issues/9573654/">No substring matching for the suggestions</a></th>
<td colspan="3">✔</td>
<td colspan="2" align="center">✔ by <a href="https://github.com/mfranzke/datalist-polyfill/issues/36">#GH-36</a></td>
<td colspan="3">✔</td>
</tr>
</table>
## Outro

@@ -150,0 +188,0 @@

@@ -40,3 +40,3 @@ exports.config = {

exclude: [
// 'path/to/excluded/files'
// 'path/to/excluded/files'
],

@@ -75,3 +75,3 @@ //

version: '11.0'
}/*,
} /*,
// TODO: Fix the test cases regarding older versions of safari/selenium

@@ -78,0 +78,0 @@ {

@@ -6,2 +6,5 @@ var field = { fieldId: 'animal', initialValue: 'Ca', expectedAmount: 2, wrongValue: 'Cc' };

/* global browser $ $$ */
/* eslint-env mocha */
var expect = require('chai').expect;

@@ -8,0 +11,0 @@

@@ -6,2 +6,5 @@ var field = { fieldId: 'animal2', initialValue: 'Ca', expectedAmount: 2, wrongValue: 'Cc' };

/* global browser $ $$ */
/* eslint-env mocha */
var expect = require('chai').expect;

@@ -8,0 +11,0 @@

@@ -30,2 +30,5 @@ var field = { fieldId: 'email', initialValue: '@r', expectedAmount: 4, wrongValue: 'doe1' };

/* global browser $ $$ */
/* eslint-env mocha */
var expect = require('chai').expect;

@@ -32,0 +35,0 @@

@@ -6,2 +6,5 @@ var field = { fieldId: 'number', initialValue: '19', expectedAmount: 28, wrongValue: '99' };

/* global browser $ $$ */
/* eslint-env mocha */
var expect = require('chai').expect;

@@ -8,0 +11,0 @@

@@ -6,2 +6,5 @@ var field = { fieldId: 'options', initialValue: ' 1', expectedAmount: 4, wrongValue: 'options' };

/* global browser $ $$ */
/* eslint-env mocha */
var expect = require('chai').expect;

@@ -8,0 +11,0 @@

@@ -6,2 +6,5 @@ var field = { fieldId: 'search', initialValue: 'ma', expectedAmount: 2, wrongValue: 'google' };

/* global browser $ $$ */
/* eslint-env mocha */
var expect = require('chai').expect;

@@ -8,0 +11,0 @@

@@ -6,2 +6,5 @@ var field = { fieldId: 'tel', initialValue: '-3', expectedAmount: 6, wrongValue: '911' };

/* global browser $ $$ */
/* eslint-env mocha */
var expect = require('chai').expect;

@@ -8,0 +11,0 @@

@@ -6,2 +6,5 @@ var field = { fieldId: 'url', initialValue: '.u', expectedAmount: 3, wrongValue: 'ftp:' };

/* global browser $ $$ */
/* eslint-env mocha */
var expect = require('chai').expect;

@@ -8,0 +11,0 @@

@@ -0,1 +1,4 @@

/* global browser $ $$ */
/* eslint-env mocha */
var expect = require('chai').expect;

@@ -2,0 +5,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc