datalist-polyfill
Advanced tools
Comparing version 1.16.2 to 1.17.0
{ | ||
"name": "datalist-polyfill", | ||
"description": "An extremely lightweight and library-dependency-free vanilla JavaScript datalist polyfill.", | ||
"version": "1.16.2", | ||
"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", | ||
"homepage": "https://github.com/mfranzke/datalist-polyfill", | ||
@@ -6,0 +6,0 @@ "authors": [{ |
@@ -9,2 +9,7 @@ # Changelog | ||
## [1.17.0] - 2018-07-07 | ||
### Added | ||
- Include behavior on pressing Tab or other printable keys (#GH-#27) | ||
- Added Greenkeeper badge. I'm using this service to keep being updated on the dev dependencies. | ||
## [1.16.2] - 2018-07-04 | ||
@@ -55,3 +60,3 @@ ### Fixed | ||
### Added | ||
- Hiding the polyfilling select on pressing ENTER, which is equal to the behaviour on typing ESC. | ||
- Hiding the polyfilling select on pressing ENTER, which is equal to the behavior on typing ESC. | ||
- Added more badges to the readme. I'm loving badges. | ||
@@ -203,3 +208,3 @@ | ||
### Fixed | ||
- fixed another simple bug that lead to an incorrect index being selected - let's skip this, as it's not even the standard behaviour | ||
- fixed another simple bug that lead to an incorrect index being selected - let's skip this, as it's not even the standard behavior | ||
@@ -206,0 +211,0 @@ ## [1.1.0] - 2017-05-09 |
/* | ||
* Datalist polyfill - https://github.com/mfranzke/datalist-polyfill | ||
* @license Copyright(c) 2017 by Maximilian Franzke | ||
* Supported by Christian, Johannes, @mitchhentges, @mertenhanisch, @ailintom, @Kravimir, @mischah, @hryamzik, @ottoville, @IceCreamYou, @wlekin, @eddr and @beebee1987 - many thanks for that ! | ||
* Supported by Christian, Johannes, @mitchhentges, @mertenhanisch, @ailintom, @Kravimir, @mischah, @hryamzik, @ottoville, @IceCreamYou, @wlekin, @eddr, @beebee1987 and @mricherzhagen - many thanks for that ! | ||
*/ | ||
/* | ||
* A minimal and dependency-free vanilla JavaScript datalist polyfill. | ||
* Supports all standard's functionality as well as mimics other browsers behavior. | ||
* Tests for native support of an inputs elements datalist functionality. | ||
@@ -287,4 +288,5 @@ * Elsewhere the functionality gets emulated by a select element. | ||
if ( | ||
(' ' + eventTarget.className + ' ').indexOf(' ' + classNameInput + ' ') < | ||
0 | ||
(' ' + eventTarget.className + ' ').indexOf( | ||
' ' + classNameInput + ' ' | ||
) < 0 | ||
) { | ||
@@ -347,2 +349,5 @@ // We'd like to prevent autocomplete on the input datalist field | ||
// The select itself shouldn't be a possible target for tabbing | ||
dataListSelect.setAttribute('tabindex', '-1'); | ||
// WAI ARIA attributes | ||
@@ -405,3 +410,4 @@ dataListSelect.setAttribute('aria-live', 'polite'); | ||
dataListSelect.addEventListener('blur', changeDataListSelect); | ||
dataListSelect.addEventListener('keyup', changeDataListSelect); | ||
dataListSelect.addEventListener('keydown', changeDataListSelect); | ||
dataListSelect.addEventListener('keypress', datalistSelectKeyPress); | ||
@@ -413,3 +419,42 @@ return dataListSelect; | ||
// Function regarding changes to the datalist polyfilling created select | ||
// Functions regarding changes to the datalist polyfilling created select | ||
var datalistSelectKeyPress = function(event) { | ||
var eventTarget = event.target, | ||
eventTargetTagName = eventTarget.tagName.toLowerCase(); | ||
// Check for whether the events target was a select or an option | ||
if ( | ||
eventTargetTagName && | ||
(eventTargetTagName === 'select' || eventTargetTagName === 'option') | ||
) { | ||
var select = | ||
eventTargetTagName === 'select' | ||
? eventTarget | ||
: eventTarget.parentNode, | ||
datalist = select.parentNode, | ||
inputList = document.querySelector('input[list="' + datalist.id + '"]'); | ||
// Change or mouseup event or ENTER key | ||
if ( | ||
inputList !== null && | ||
// Determine a relevant key - either printable characters (that would have a length of 1) or controlling like Backspace | ||
event.key && | ||
(event.key === 'Backspace' || event.key.length === 1) | ||
) { | ||
inputList.focus(); | ||
if (event.key === 'Backspace') { | ||
inputList.value = inputList.value.substr( | ||
0, | ||
inputList.value.length - 1 | ||
); | ||
} else { | ||
inputList.value += event.key; | ||
} | ||
prepOptions(datalist, inputList); | ||
} | ||
} | ||
}; | ||
var changeDataListSelect = function(event) { | ||
@@ -429,2 +474,4 @@ var eventTarget = event.target, | ||
datalist = select.parentNode, | ||
inputList = document.querySelector('input[list="' + datalist.id + '"]'), | ||
selectValue = select.value, | ||
message = datalist.title, | ||
@@ -434,49 +481,44 @@ eventType = event.type, | ||
visible = | ||
eventType === 'keyup' && | ||
eventType === 'keydown' && | ||
(event.keyCode !== keyENTER && event.keyCode !== keyESC); | ||
// Change or mouseup event or ENTER key | ||
// On change, click or ENTER or TAB key, input the selects value into the input on a change within the list | ||
if ( | ||
eventType === 'change' || | ||
eventType === 'click' || | ||
(eventType === 'keyup' && event.keyCode === keyENTER) | ||
inputList !== null && | ||
(eventType === 'change' || | ||
eventType === 'click' || | ||
(eventType === 'keydown' && | ||
(event.keyCode === keyENTER || event.key === 'Tab'))) && | ||
typeof selectValue !== 'undefined' && | ||
selectValue.length > 0 && | ||
selectValue !== message | ||
) { | ||
var list = datalist.id, | ||
inputList = document.querySelector('input[list="' + list + '"]'), | ||
selectValue = select.value; | ||
var lastSeperator, evt; | ||
// Input the selects value into the input on a change within the list | ||
if ( | ||
inputList !== null && | ||
typeof selectValue !== 'undefined' && | ||
selectValue.length > 0 && | ||
selectValue !== message | ||
) { | ||
var lastSeperator, evt; | ||
// In case of type=email and multiple attribute, we need to set up the resulting inputs value differently | ||
inputList.value = | ||
inputList.type === 'email' && | ||
inputList.multiple && | ||
(lastSeperator = inputList.value.lastIndexOf(',')) > -1 | ||
? inputList.value.slice(0, lastSeperator) + ',' + selectValue | ||
: (inputList.value = selectValue); | ||
// In case of type=email and multiple attribute, we need to set up the resulting inputs value differently | ||
inputList.value = | ||
inputList.type === 'email' && | ||
inputList.multiple && | ||
(lastSeperator = inputList.value.lastIndexOf(',')) > -1 | ||
? inputList.value.slice(0, lastSeperator) + ',' + selectValue | ||
: (inputList.value = selectValue); | ||
// Create and dispatch the input event; divided for IE9 usage | ||
if (typeof Event === 'function') { | ||
evt = new Event('input', { | ||
bubbles: true | ||
}); | ||
} else { | ||
evt = document.createEvent('Event'); | ||
evt.initEvent('input', true, false); | ||
} | ||
inputList.dispatchEvent(evt); | ||
// Create and dispatch the input event; divided for IE9 usage | ||
if (typeof Event === 'function') { | ||
evt = new Event('input', { | ||
bubbles: true | ||
}); | ||
} else { | ||
evt = document.createEvent('Event'); | ||
evt.initEvent('input', true, false); | ||
} | ||
inputList.dispatchEvent(evt); | ||
// Finally focusing the input, as other browser do this as well | ||
// Finally focusing the input, as other browser do this as well | ||
if (event.key !== 'Tab') { | ||
inputList.focus(); | ||
} | ||
// Set the visibility to false afterwards, as we're done here | ||
visible = false; | ||
} | ||
// Set the visibility to false afterwards, as we're done here | ||
visible = false; | ||
} | ||
@@ -483,0 +525,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,l=" / ",r=["text","email","number","search","tel","url"],a="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;y(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 l=o.getElementsByClassName("polyfilling")[0]||m(i,o);if(void 0!==l){var r=!1,a=i.value,s=38===t.keyCode||40===t.keyCode;if(27!==t.keyCode&&13!==t.keyCode&&(""!==a||s)){c(o,i)&&(r=!0);var u=l.options.length,d=0,p=u-1;e?l.selectedIndex=0:s&&(l.selectedIndex=38===t.keyCode?p:0,l.focus())}y(r,l)}}},c=function(t,i){void 0!==d&&d.disconnect();var n=t.getElementsByClassName("polyfilling")[0]||m(i,t),o=t.querySelectorAll("option:not(:disabled)"),l=i.value,r=document.createDocumentFragment(),a=document.createDocumentFragment();"email"===i.type&&i.multiple&&(l=l.substring(l.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(l.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),r.appendChild(e)}else a.appendChild(e)}),n.appendChild(r);var s=n.options.length;return n.size=s>10?10:s,n.multiple=!e&&s<2,(t.getElementsByClassName("ie9_fix")[0]||t).appendChild(a),void 0!==d&&d.observe(t,{childList:!0}),s},f=function(e){var t=e.target,i=t.tagName.toLowerCase(),n=t.list;if(i&&"input"===i&&null!==n){var o=e.type,l=n.getElementsByClassName("polyfilling")[0]||m(t,n),r=l&&l.querySelector("option:not(:disabled)")&&("focusin"===o&&""!==t.value||e.relatedTarget&&e.relatedTarget===l);(" "+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",f,!0)):"blur"===o&&(t.removeEventListener("keyup",p),t.removeEventListener("focusout",f,!0)),t.className+=" polyfilled"),y(r,l)}},m=function(t,i){if(r.indexOf(t.type)>-1&&null!==i){var n=i.title,o=t.getClientRects(),l=window.getComputedStyle(t),a=parseFloat(l.getPropertyValue("margin-right")),s=parseFloat(l.getPropertyValue("margin-left")),u=document.createElement("select");if(u.setAttribute("class","polyfilling"),u.style.position="absolute",y(!1,u),u.setAttribute("aria-live","polite"),u.setAttribute("role","listbox"),e||u.setAttribute("aria-multiselectable","false"),"block"===l.getPropertyValue("display")?u.style.marginTop="-"+l.getPropertyValue("margin-bottom"):("rtl"===l.getPropertyValue("direction")?u.style.marginRight="-"+(o[0].width+s)+"px":u.style.marginLeft="-"+(o[0].width+a)+"px",u.style.marginTop=parseInt(o[0].height+(t.offsetTop-i.offsetTop),10)+"px"),u.style.borderRadius=l.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",v):u.addEventListener("click",v),u.addEventListener("blur",v),u.addEventListener("keyup",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,l=o.title,r=e.type,a="keyup"===r&&13!==e.keyCode&&27!==e.keyCode;if("change"===r||"click"===r||"keyup"===r&&13===e.keyCode){var s=o.id,u=document.querySelector('input[list="'+s+'"]'),d=n.value;if(null!==u&&void 0!==d&&d.length>0&&d!==l){var p,c;u.value="email"===u.type&&u.multiple&&(p=u.value.lastIndexOf(","))>-1?u.value.slice(0,p)+","+d:u.value=d,"function"==typeof Event?c=new Event("input",{bubbles:!0}):(c=document.createEvent("Event"),c.initEvent("input",!0,!1)),u.dispatchEvent(c),u.focus(),a=!1}}y(a,n)}},y=function(e,t){e?t.removeAttribute("hidden"):t.setAttributeNode(document.createAttribute("hidden")),t.setAttribute("aria-hidden",(!e).toString())};document.addEventListener("focusin",f,!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,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)}(); |
{ | ||
"name": "datalist-polyfill", | ||
"version": "1.16.2", | ||
"description": "A lightweight and dependency-free vanilla JavaScript datalist polyfill.", | ||
"version": "1.17.0", | ||
"description": "A minimal and dependency-free vanilla JavaScript datalist polyfill. Supports all standard's functionality as well as mimics other browsers behavior.", | ||
"main": "datalist-polyfill.js", | ||
@@ -6,0 +6,0 @@ "scripts": { |
@@ -6,2 +6,3 @@ [npm]: https://npmjs.com/package/datalist-polyfill "datalist polyfill – on NPM" | ||
[![MIT license](https://img.shields.io/npm/l/datalist-polyfill.svg "license badge")](https://opensource.org/licenses/mit-license.php) | ||
[![datalist-polyfill on Npmjs](https://img.shields.io/npm/v/datalist-polyfill.svg "npm version")][npm] | ||
@@ -14,11 +15,13 @@ [![Total downloads ~ Npmjs](https://img.shields.io/npm/dt/datalist-polyfill.svg "Count of total downloads – NPM")][npm] | ||
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/d1f98a2d1fd44c41b7ad5c7670d8cdcd)](https://app.codacy.com/app/mfranzke/datalist-polyfill?utm_source=github.com&utm_medium=referral&utm_content=mfranzke/datalist-polyfill&utm_campaign=badger) | ||
[![Greenkeeper badge](https://badges.greenkeeper.io/mfranzke/datalist-polyfill.svg)](https://greenkeeper.io/) | ||
This is a minimal and dependency-free vanilla JavaScript polyfill for the awesome datalist-functionality, that will bring joy and happiness into our lives :-) | ||
* 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) | ||
* Released under the [![MIT license](https://img.shields.io/npm/l/datalist-polyfill.svg "license badge")](https://opensource.org/licenses/mit-license.php) | ||
* Released under the MIT license | ||
* Made in Germany. And supported by so many great people from all over this planet - see "Credits" accordingly. | ||
## Features | ||
* Lightweight: 5.64 kB of minified JavaScript, around 2.49 kB gzipped | ||
* Lightweight: 6.07 kB of minified JavaScript, around 2.59 kB gzipped | ||
* Fully flexible to change the datalist entries / `<option>`s | ||
@@ -25,0 +28,0 @@ * Supporting: |
55348
496
124