datalist-polyfill
Advanced tools
Comparing version 1.2.1 to 1.3.0
{ | ||
"name": "datalist-polyfill", | ||
"description": "An extremely lightweight and library-dependency-free vanilla JavaScript datalist polyfill.", | ||
"version": "1.2.1", | ||
"version": "1.3.0", | ||
"homepage": "https://github.com/mfranzke/datalist-polyfill", | ||
@@ -6,0 +6,0 @@ "authors": [{ |
@@ -86,3 +86,12 @@ /* | ||
disabledValues = document.createDocumentFragment(), | ||
visible = false; | ||
visible = false, | ||
multipleEmails = ( $eventTarget.type === 'email' && $eventTarget.multiple ); | ||
// in case of type=email and multiple attribute, we would need to split the inputs value into pieces | ||
if ( multipleEmails ) { | ||
var multipleEntries = inputValue.split( ',' ), | ||
relevantIndex = multipleEntries.length - 1; | ||
inputValue = multipleEntries[ relevantIndex ].trim(); | ||
} | ||
@@ -248,3 +257,12 @@ // if the input contains a value, than ... | ||
if ( $inputList !== null && eventTargetValue.length > 0 && eventTargetValue !== message ) { | ||
$inputList.value = eventTargetValue; | ||
var inputListValue = $inputList.value, | ||
lastSeperator, | ||
multipleEmails = ( $inputList.type === 'email' && $inputList.multiple ); | ||
// in case of type=email and multiple attribute, we need to set up the resulting inputs value differently | ||
if ( multipleEmails && ( lastSeperator = inputListValue.lastIndexOf(',') ) > -1 ) { | ||
$inputList.value = inputListValue.slice( 0, lastSeperator ) + ',' + eventTargetValue; | ||
} else { | ||
$inputList.value = eventTargetValue; | ||
} | ||
} | ||
@@ -251,0 +269,0 @@ } |
@@ -6,2 +6,2 @@ /* | ||
*/ | ||
!function(){"use strict";if(!("list"in document.createElement("input"))||(!document.createElement("datalist")||!window.HTMLDataListElement)){!function(e){e&&e.prototype&&void 0===e.prototype.list&&Object.defineProperty(e.prototype,"list",{get:function(){if("object"==typeof this&&this instanceof e){var t=this.getAttribute("list");return document.getElementById(t)}return null}})}(window.HTMLInputElement),function(e){e&&e.prototype&&void 0===e.prototype.options&&Object.defineProperty(e.prototype,"options",{get:function(){if("object"==typeof this&&this instanceof e)return this.getElementsByTagName("option")}})}(window.HTMLElement);var e=function(e){var t=e.target,i=t.tagName;if(i&&"input"===i.toLowerCase()&&t.getAttribute("list")){var n=t.getAttribute("list"),r=document.getElementById(n);if(null!==r){var a=r.getElementsByTagName("select")[0];if(void 0!==a){if(27===e.keyCode)return a.classList.remove("visible"),void a.setAttribute("aria-hidden",!0);var o=r.querySelectorAll("option[value]"),l=t.value,s=document.createDocumentFragment(),u=document.createDocumentFragment(),d=!1;""!==l&&(Array.prototype.slice.call(o).sort(function(e,t){return e.value.localeCompare(t.value)}).forEach(function(e){var t=e.value;""!==t&&-1!==t.toLowerCase().indexOf(l.toLowerCase())&&!1===e.disabled?(e.innerText=t,s.appendChild(e),d=!0):u.appendChild(e)}),a.appendChild(s),a.selectedIndex=0,r.appendChild(u)),a.classList.toggle("visible",d),a.setAttribute("aria-hidden",!d),38!==e.keyCode&&40!==e.keyCode||a.focus()}}}},t=function(n){var r=n.target,a=r.tagName;if(a&&"input"===a.toLowerCase()&&r.getAttribute("list")){var o=n.type,l=r.getAttribute("list"),s=document.getElementById(l);if(null!==s){var u=s.getElementsByTagName("select")[0],d="focus"===o&&""!==n.target.value||n.relatedTarget&&n.relatedTarget===u,c=s.title;if(void 0===u){var p=r.getClientRects(),m=document.createElement("option");u=document.createElement("select"),u.setAttribute("aria-hidden",!0),u.setAttribute("aria-live","polite"),u.setAttribute("role","listbox"),u.style.marginLeft="-"+p[0].width+"px",u.style.marginTop=p[0].height+"px",u.style.minWidth=p[0].width+"px",m.innerText=c,m.disabled=!0,u.appendChild(m),s.appendChild(u),u.addEventListener("change",i),u.addEventListener("blur",i),u.addEventListener("keyup",i),r.setAttribute("autocomplete","off"),r.setAttribute("role","textbox"),r.setAttribute("aria-haspopup","true"),r.setAttribute("aria-autocomplete","list"),r.setAttribute("aria-owns",l)}switch(u.classList.toggle("visible",d),u.setAttribute("aria-hidden",!d),o){case"focus":r.addEventListener("keyup",e),r.addEventListener("blur",t,!0);break;case"blur":r.removeEventListener("keyup",e),r.removeEventListener("blur",t,!0);break}}}},i=function(e){var t=e.target,i=t.tagName,n=t.parentNode.title;if(i&&"select"===i.toLowerCase()){var r=e.type,a="keyup"===r&&13!==e.keyCode&&27!==e.keyCode;if("change"===r||"keyup"===r&&13===e.keyCode){var o=t.parentNode.id,l=document.querySelector('input[list="'+o+'"]'),s=t.value;null!==l&&s.length>0&&s!==n&&(l.value=s)}t.classList.toggle("visible",a),t.setAttribute("aria-hidden",!a)}};document.addEventListener("focus",t,!0)}}(); | ||
!function(){"use strict";if(!("list"in document.createElement("input"))||(!document.createElement("datalist")||!window.HTMLDataListElement)){!function(e){e&&e.prototype&&void 0===e.prototype.list&&Object.defineProperty(e.prototype,"list",{get:function(){if("object"==typeof this&&this instanceof e){var t=this.getAttribute("list");return document.getElementById(t)}return null}})}(window.HTMLInputElement),function(e){e&&e.prototype&&void 0===e.prototype.options&&Object.defineProperty(e.prototype,"options",{get:function(){if("object"==typeof this&&this instanceof e)return this.getElementsByTagName("option")}})}(window.HTMLElement);var e=function(e){var t=e.target,i=t.tagName;if(i&&"input"===i.toLowerCase()&&t.getAttribute("list")){var a=t.getAttribute("list"),n=document.getElementById(a);if(null!==n){var r=n.getElementsByTagName("select")[0];if(void 0!==r){if(27===e.keyCode)return r.classList.remove("visible"),void r.setAttribute("aria-hidden",!0);var o=n.querySelectorAll("option[value]"),l=t.value,s=document.createDocumentFragment(),u=document.createDocumentFragment(),d=!1;if("email"===t.type&&t.multiple){var p=l.split(","),c=p.length-1;l=p[c].trim()}""!==l&&(Array.prototype.slice.call(o).sort(function(e,t){return e.value.localeCompare(t.value)}).forEach(function(e){var t=e.value;""!==t&&-1!==t.toLowerCase().indexOf(l.toLowerCase())&&!1===e.disabled?(e.innerText=t,s.appendChild(e),d=!0):u.appendChild(e)}),r.appendChild(s),r.selectedIndex=0,n.appendChild(u)),r.classList.toggle("visible",d),r.setAttribute("aria-hidden",!d),38!==e.keyCode&&40!==e.keyCode||r.focus()}}}},t=function(a){var n=a.target,r=n.tagName;if(r&&"input"===r.toLowerCase()&&n.getAttribute("list")){var o=a.type,l=n.getAttribute("list"),s=document.getElementById(l);if(null!==s){var u=s.getElementsByTagName("select")[0],d="focus"===o&&""!==a.target.value||a.relatedTarget&&a.relatedTarget===u,p=s.title;if(void 0===u){var c=n.getClientRects(),m=document.createElement("option");u=document.createElement("select"),u.setAttribute("aria-hidden",!0),u.setAttribute("aria-live","polite"),u.setAttribute("role","listbox"),u.style.marginLeft="-"+c[0].width+"px",u.style.marginTop=c[0].height+"px",u.style.minWidth=c[0].width+"px",m.innerText=p,m.disabled=!0,u.appendChild(m),s.appendChild(u),u.addEventListener("change",i),u.addEventListener("blur",i),u.addEventListener("keyup",i),n.setAttribute("autocomplete","off"),n.setAttribute("role","textbox"),n.setAttribute("aria-haspopup","true"),n.setAttribute("aria-autocomplete","list"),n.setAttribute("aria-owns",l)}switch(u.classList.toggle("visible",d),u.setAttribute("aria-hidden",!d),o){case"focus":n.addEventListener("keyup",e),n.addEventListener("blur",t,!0);break;case"blur":n.removeEventListener("keyup",e),n.removeEventListener("blur",t,!0);break}}}},i=function(e){var t=e.target,i=t.tagName,a=t.parentNode.title;if(i&&"select"===i.toLowerCase()){var n=e.type,r="keyup"===n&&13!==e.keyCode&&27!==e.keyCode;if("change"===n||"keyup"===n&&13===e.keyCode){var o=t.parentNode.id,l=document.querySelector('input[list="'+o+'"]'),s=t.value;if(null!==l&&s.length>0&&s!==a){var u=l.value,d;"email"===l.type&&l.multiple&&(d=u.lastIndexOf(","))>-1?l.value=u.slice(0,d)+","+s:l.value=s}}t.classList.toggle("visible",r),t.setAttribute("aria-hidden",!r)}};document.addEventListener("focus",t,!0)}}(); |
{ | ||
"name": "datalist-polyfill", | ||
"version": "1.2.1", | ||
"version": "1.3.0", | ||
"description": "An extremely lightweight and library-dependency-free vanilla JavaScript datalist polyfill.", | ||
@@ -5,0 +5,0 @@ "main": "datalist-polyfill.js", |
@@ -8,5 +8,8 @@ # datalist-polyfill | ||
## Features | ||
* Lightweight: 3.26 kB of JavaScript - less than 1.58 kB gzipped | ||
* Lightweight: 3.43 kB of JavaScript - less than 1.68 kB gzipped | ||
* Fully flexible to change the datalist entries / `<option>`s | ||
* Enables core keyboard controls like e.g. the up and down arrow keys, ESC and ENTER | ||
* Supporting: | ||
* `input[type=email]` elements multiple attribute | ||
* properties `.options` for `datalist` elements and `.list` for `input` elements | ||
* Enables core keyboard controls like e.g. the up and down arrow keys, `ESC` and `ENTER` | ||
* Implements the [WAI-ARIA design pattern](https://www.w3.org/TR/wai-aria-practices/) | ||
@@ -34,22 +37,22 @@ | ||
We're even also enabling the [.options (for `datalist` elements)](https://developer.mozilla.org/en/docs/Web/API/HTMLDataListElement) and [.list (for `input` elements)](https://developer.mozilla.org/en/docs/Web/API/HTMLInputElement) properties according to the specs. | ||
We're even also enabling the [`.options` (for `datalist` elements)](https://developer.mozilla.org/en/docs/Web/API/HTMLDataListElement) and [`.list` (for `input` elements)](https://developer.mozilla.org/en/docs/Web/API/HTMLInputElement) properties according to the specs. | ||
And you'd like to set a title-Attribute on the datalist HTML tag, as this would get used as label for the first, disabled entry within the polyfilling select. | ||
And you'd like to set a `title`-Attribute on the `<datalist>` HTML tag, as this would get used as label for the first, disabled entry within the polyfilling select. | ||
### dynamic HTML (or DHTML, if you like to be a little bit nostalgic) | ||
In case that you'd like to dynamically add or modify / create your HTML code, you're even also good to go with this polyfill, as it's based on event delegation that makes your UI work with a glance - no function to call after DOM manipulation or something similar. | ||
In case that you'd like to dynamically add or modify / create your HTML code, you're even also good to go with this polyfill, as it's based on event delegation that makes your UI work easily - no (refresh) function to call after DOM manipulation or something similar. | ||
### Changes to the available `option`s | ||
If you'd like to make a change to the integrated list of `<option>` elements, feel free to either remove or add them right away - the list would get generated on the fly after the user typed in something into the input field, so I've even also got you covered on this. | ||
### Changes to the available `option` elements | ||
If you'd like to make a change to the integrated list of `<option>` elements, feel free to either remove or add them right away - the list would get generated on the fly after the user typed in something into the `<input>` field, so I've even also got you covered on this. | ||
You could even also disable `<option>` elements by the disabled attribute if necessary. | ||
You could even also disable `<option>` elements by adding the `disabled` attribute to the `<option>` HTML tag if necessary. | ||
## Demo | ||
See the polyfill in action either by downloading / forking this repo and have a look at the demo.html, or on JSFiddle: <https://jsfiddle.net/mfranzke/s6awjfze/> | ||
See the polyfill in action either by downloading / forking this repo and have a look at `demo.html`, or at the hosted demo on JSFiddle: <https://jsfiddle.net/mfranzke/s6awjfze/> | ||
## things to keep in mind | ||
* The demo HTML code is meant to be simple - I do know that things like a surrounding `<form>` and `<fieldset>` are missing. But lets focus on the relevant tags that this polyfill is all about for the demo. | ||
* After I thought it through and even also did some experiments, I've finally chosen the `<select>` element to polyfill the functionality of the datalist functionality, as it brought most of the functionality, whereas I accepted that it doesn't behave and doesn't look totally equally. | ||
* As I wanted to use most native elements in the most low level / simple way instead of visually emulating a list and than afterwards regain all of the functionality via a lot of JavaScript logic, I've ended up with this element, that even also knows how to play with nested `<option>` elements pretty well. | ||
* I even also tried its multiple attribute, as this is most likely even already what you're up to regarding appearance and functionality, but it does result in - surprise - the possibility for multiple selections, which isn't `<datalist>`s kind of thing ... | ||
* The demo HTML code is meant to be simple - I do know that things like a surrounding `<form>` are missing. But lets focus on the relevant tags that this polyfill is all about for the demo. | ||
* After I thought it through and even also did some experiments, I've finally chosen the `<select>` element to polyfill the functionality of the `<datalist>` functionality, as it brought most of the functionality, whereas I accepted that it doesn't behave and doesn't look totally equally. | ||
* As I wanted to mainly focus on native elements in the most low level / simple way instead of visually emulating a list and than afterwards regain all of the functionality via a lot of JavaScript logic, I've ended up with this element, that even also knows how to play nicely with nested `<option>` elements. | ||
* I even also tried its `multiple` attribute, as this is most likely even already what you're up to regarding appearance, but it does result in - surprise - the possibility for multiple selections, which isn't always `<datalist>` elements kind of thing ... | ||
* If you'd like to support oldies, but goldies like Internet Exlorer 9 and below, you'll even also need to include some `classlist` polyfill | ||
@@ -62,2 +65,5 @@ | ||
### Version 1.3.0 - 2017/05/30 | ||
Added support for multiple email addresses, separated by comma. And again, updated documentation slightly. And demo accordingly. | ||
### Version 1.2.1 - 2017/05/29 | ||
@@ -67,6 +73,6 @@ Simple code style modifications. Because style matters. | ||
### Version 1.2.0 - 2017/05/29 | ||
Added .options (for `datalist`s) and .list (for `input`s) properties according to the specs. | ||
Added .options (for `datalist` elements) and .list (for `input` elements) properties according to the specs. | ||
### Version 1.1.2 - 2017/05/14 | ||
Further simplified the code, so that we could even skip the .matches() polyfill. Yeah. And documentation updates. | ||
Further simplified the code, so that we could even skip the `.matches()` polyfill. Yeah. And documentation updates. | ||
@@ -83,3 +89,3 @@ ### Version 1.1.1 - 2017/05/10 | ||
### Version 1.0.2 - 2017/05/08 | ||
added a package.json file | ||
added a `package.json` file | ||
@@ -109,2 +115,4 @@ ### Version 1.0.1 - 2017/05/08 | ||
But on the other hand this leads to an additional visible field and doesn't emulate the (hopefully, fingers crossed) upcoming x-browser implementation and leaves unnecessary syntax for all of the clients that wouldn't even need it (anymore). | ||
But on the other hand this leads to an additional visible field, but doesn't emulate the (hopefully, fingers crossed) upcoming x-browser implementation and leaves unnecessary syntax for all of the clients that wouldn't even need it (anymore). | ||
If you're trying out and using my work, feel free to contact me and give me any feedback. I'm curious about how it's gonna be used. |
Sorry, the diff of this file is not supported yet
24781
259
112