@nrk/core-input
Advanced tools
Comparing version 1.1.3 to 1.2.0
'use strict'; | ||
var name = "@nrk/core-input"; | ||
var version = "1.1.2"; | ||
var version = "1.1.3"; | ||
@@ -155,3 +155,3 @@ var IS_BROWSER = typeof window !== 'undefined'; | ||
} | ||
}); | ||
}, true); // Use capture to enable checking defaultPrevented (from ESC key) in parents | ||
@@ -161,2 +161,3 @@ function onKey (input, event) { | ||
var focusable = [input].concat(queryAll((ITEM + ":not([hidden])"), list)); | ||
var isClosing = event.keyCode === KEYS.ESC && input.getAttribute('aria-expanded') === 'true'; | ||
var index = focusable.indexOf(document.activeElement); | ||
@@ -174,4 +175,4 @@ var item = false; | ||
// Prevent leaving maximized safari and event.preventDefault even if undefined item (empty list) | ||
if (event.keyCode === KEYS.ESC || item !== false) { event.preventDefault(); } | ||
setupExpand(input, event.keyCode !== KEYS.ESC); | ||
if (item !== false || isClosing) { event.preventDefault(); } | ||
if (item) { item.focus(); } | ||
@@ -191,4 +192,7 @@ } | ||
queryAll(ITEM, input.nextElementSibling).reduce(function (acc, item) { | ||
var list = item.parentElement.nodeName === 'LI' && item.parentElement; | ||
var show = item.textContent.toLowerCase().indexOf(input.value.toLowerCase()) !== -1; | ||
item[show ? 'removeAttribute' : 'setAttribute']('hidden', ''); | ||
var attr = show ? 'removeAttribute' : 'setAttribute'; | ||
if (list) { list[attr]('hidden', ''); } // JAWS requires hiding of <li> too (if they exist) | ||
item[attr]('hidden', ''); | ||
return show ? acc.concat(item) : acc | ||
@@ -225,10 +229,12 @@ }, []).forEach(setupItem); | ||
}; | ||
ajax.timer = setTimeout(function () { // Debounce next request 500 milliseconds | ||
ajax.timer = setTimeout(function () { | ||
if (!input.value) { return } // Abort if input is empty | ||
req.open('GET', url.replace('{{value}}', window.encodeURIComponent(input.value)), true); | ||
req.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); // https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Requested-With | ||
req.send(); | ||
}, AJAX_DEBOUNCE); | ||
if (dispatchEvent(input, 'input.ajax.beforeSend', req)) { | ||
req.open('GET', url.replace('{{value}}', window.encodeURIComponent(input.value)), true); | ||
req.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); // https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Requested-With | ||
req.send(); | ||
} | ||
}, AJAX_DEBOUNCE); // Debounce request | ||
} | ||
module.exports = input; |
@@ -61,3 +61,3 @@ import { name, version } from './package.json' | ||
} | ||
}) | ||
}, true) // Use capture to enable checking defaultPrevented (from ESC key) in parents | ||
@@ -67,2 +67,3 @@ function onKey (input, event) { | ||
const focusable = [input].concat(queryAll(`${ITEM}:not([hidden])`, list)) | ||
const isClosing = event.keyCode === KEYS.ESC && input.getAttribute('aria-expanded') === 'true' | ||
const index = focusable.indexOf(document.activeElement) | ||
@@ -80,4 +81,4 @@ let item = false | ||
// Prevent leaving maximized safari and event.preventDefault even if undefined item (empty list) | ||
if (event.keyCode === KEYS.ESC || item !== false) event.preventDefault() | ||
setupExpand(input, event.keyCode !== KEYS.ESC) | ||
if (item !== false || isClosing) event.preventDefault() | ||
if (item) item.focus() | ||
@@ -97,4 +98,7 @@ } | ||
queryAll(ITEM, input.nextElementSibling).reduce((acc, item) => { | ||
const list = item.parentElement.nodeName === 'LI' && item.parentElement | ||
const show = item.textContent.toLowerCase().indexOf(input.value.toLowerCase()) !== -1 | ||
item[show ? 'removeAttribute' : 'setAttribute']('hidden', '') | ||
const attr = show ? 'removeAttribute' : 'setAttribute' | ||
if (list) list[attr]('hidden', '') // JAWS requires hiding of <li> too (if they exist) | ||
item[attr]('hidden', '') | ||
return show ? acc.concat(item) : acc | ||
@@ -129,8 +133,10 @@ }, []).forEach(setupItem) | ||
} | ||
ajax.timer = setTimeout(() => { // Debounce next request 500 milliseconds | ||
ajax.timer = setTimeout(() => { | ||
if (!input.value) return // Abort if input is empty | ||
req.open('GET', url.replace('{{value}}', window.encodeURIComponent(input.value)), true) | ||
req.setRequestHeader('X-Requested-With', 'XMLHttpRequest') // https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Requested-With | ||
req.send() | ||
}, AJAX_DEBOUNCE) | ||
if (dispatchEvent(input, 'input.ajax.beforeSend', req)) { | ||
req.open('GET', url.replace('{{value}}', window.encodeURIComponent(input.value)), true) | ||
req.setRequestHeader('X-Requested-With', 'XMLHttpRequest') // https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Requested-With | ||
req.send() | ||
} | ||
}, AJAX_DEBOUNCE) // Debounce request | ||
} |
@@ -49,4 +49,7 @@ import React from 'react' | ||
onAjax: PropTypes.func, | ||
ajax: PropTypes.string, | ||
open: PropTypes.bool | ||
open: PropTypes.bool, | ||
ajax: PropTypes.oneOfType([ | ||
PropTypes.string, | ||
PropTypes.object | ||
]) | ||
} |
@@ -1,65 +0,3 @@ | ||
/*! @nrk/core-input v1.1.2 - Copyright (c) 2017-2018 NRK */ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("react"),require("prop-types")):"function"==typeof define&&define.amd?define(["react","prop-types"],t):e.CoreInput=t(e.React,e.PropTypes)}(this,function(a,e){"use strict";a=a&&a.hasOwnProperty("default")?a.default:a,e=e&&e.hasOwnProperty("default")?e.default:e;var t="undefined"!=typeof window,i=(t&&/(android)/i.test(navigator.userAgent),t&&/iPad|iPhone|iPod/.test(String(navigator.platform))),r=function(e){void 0===e&&(e=!1);try{window.addEventListener("test",null,{get passive(){e=!0}})}catch(e){}return e}(); | ||
/** | ||
* addEvent | ||
* @param {String} uuid An unique ID of the event to bind - ensurnes single instance | ||
* @param {String} type The type of event to bind | ||
* @param {Function} handler The function to call on event | ||
* @param {Boolean|Object} options useCapture or options object for addEventListener. Defaults to false | ||
*/ | ||
function n(e,t,n,o){(void 0===o&&(o=!1),"undefined"==typeof window||window[e=e+"-"+t])||(// Ensure single instance | ||
r||"object"!=typeof o||(o=Boolean(o.capture)),("resize"===t||"load"===t?window:document).addEventListener(window[e]=t,n,o))} | ||
/** | ||
* escapeHTML | ||
* @param {String} str A string with potential html tokens | ||
* @return {String} Escaped HTML string according to OWASP recommendation | ||
*/var o={"&":"&","<":"<",">":">",'"':""","/":"/","'":"'"};function u(e){return String(e||"").replace(/[&<>"'/]/g,function(e){return o[e]})} | ||
/** | ||
* exclude | ||
* @param {Object} target The target object | ||
* @param {Object} exclude The source to exclude keys from | ||
* @return {Object} The target object without keys found in source | ||
*/ | ||
/** | ||
* dispatchEvent - with infinite loop prevention | ||
* @param {Element} elem The target object | ||
* @param {String} name The source object(s) | ||
* @param {Object} detail Detail object (bubbles and cancelable is set to true) | ||
* @return {Boolean} Whether the event was canceled | ||
*/ | ||
var l="prevent_recursive_dispatch_maximum_callstack";function s(e,t,n){void 0===n&&(n={});var o,r=""+l+t;if(e[r])return!0;// Add name to dispatching ignore | ||
e[r]=!0,"function"==typeof window.CustomEvent?o=new window.CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n}):(o=document.createEvent("CustomEvent")).initCustomEvent(t,!0,!0,n); | ||
// IE reports incorrect event.defaultPrevented | ||
// but correct return value on element.dispatchEvent | ||
var i=e.dispatchEvent(o);// Remove name from dispatching ignore | ||
return e[r]=null,i;// Follow W3C standard for return value | ||
} | ||
/** | ||
* requestAnimFrame (super simple polyfill) | ||
*/ | ||
/** | ||
* queryAll | ||
* @param {String|NodeList|Array|Element} elements A CSS selector string, nodeList, element array, or single element | ||
* @return {Element[]} Array of elements | ||
*/ | ||
function c(e,t){if(void 0===t&&(t=document),e){if(e.nodeType)return[e];if("string"==typeof e)return[].slice.call(t.querySelectorAll(e));if(e.length)return[].slice.call(e)}return[]}var p="data-@nrk/core-input-1.1.2".replace(/\W+/g,"-"),d=13,f=27,h=33,v=34,m=35,y=36,b=38,g=40,x='[tabindex="-1"]',E=500;// Strip invalid attribute characters | ||
function w(e,t){var o="object"==typeof t?t:{content:t},r="string"==typeof o.content;return c(e).map(function(e){var t=e.nextElementSibling,n=void 0===o.ajax?e.getAttribute(p):o.ajax;return e.setAttribute(p,n||""),e.setAttribute(i?"data-role":"role","combobox"),// iOS does not inform user area is editable if combobox | ||
e.setAttribute("aria-autocomplete","list"),e.setAttribute("autocomplete","off"),r&&(t.innerHTML=o.content),c("a,button",t).forEach(j),S(e,o.open),e})} | ||
// Expose helper functions | ||
// Use focus with capturing instead of focusin for old Firefox | ||
function A(a){a.ctrlKey||a.altKey||a.metaKey||a.defaultPrevented||c("["+p+"]").forEach(function(e){var t,n,o=e.nextElementSibling,r=e===a.target||o.contains(a.target),i="click"===a.type&&r&&c(x,o).filter(function(e){return e.contains(a.target)})[0];i?(t=e,n={relatedTarget:o,currentTarget:i,value:i.value||i.textContent.trim()},s(t,"input.select",n)&&(t.value=n.value,t.focus(),S(t,!1))):S(e,r)})}function C(e,t){var n=e.nextElementSibling,o=[e].concat(c(x+":not([hidden])",n)),r=o.indexOf(document.activeElement),i=!1;t.keyCode===g?i=o[r+1]||o[0]:t.keyCode===b?i=o[r-1]||o.pop():n.contains(t.target)&&(// Aditional shortcuts if focus is inside list | ||
t.keyCode===m||t.keyCode===v?i=o.pop():t.keyCode===y||t.keyCode===h?i=o[1]:t.keyCode!==d&&e.focus()), | ||
// Prevent leaving maximized safari and event.preventDefault even if undefined item (empty list) | ||
t.keyCode!==f&&!1===i||t.preventDefault(),S(e,t.keyCode!==f),i&&i.focus()}function S(e,t){var n;void 0===t&&(t="true"===e.getAttribute("aria-expanded")),n=function(){// Fixes VoiceOver Safari focus jumping to parentElement | ||
e.nextElementSibling[t?"removeAttribute":"setAttribute"]("hidden",""),e.setAttribute("aria-expanded",t)},(window.requestAnimationFrame||window.setTimeout)(n)}function j(e,t,n){e.setAttribute("aria-label",e.textContent.trim()+", "+(t+1)+" av "+n.length),e.setAttribute("tabindex","-1"),e.setAttribute("type","button")}function k(e){var t=e.getAttribute(p),n=k.req=k.req||new window.XMLHttpRequest;if(!t)return!1;clearTimeout(k.timer),// Clear previous search | ||
n.abort(),// Abort previous request | ||
n.onload=function(){try{n.responseJSON=JSON.parse(n.responseText)}catch(e){n.responseJSON=!1}s(e,"input.ajax",n)},k.timer=setTimeout(function(){// Debounce next request 500 milliseconds | ||
e.value&&(// Abort if input is empty | ||
n.open("GET",t.replace("{{value}}",window.encodeURIComponent(e.value)),!0),n.setRequestHeader("X-Requested-With","XMLHttpRequest"),// https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Requested-With | ||
n.send())},E)}w.escapeHTML=u,w.highlight=function(e,t){var n=t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&");// From lodash | ||
return u(e).replace(new RegExp(n||".^","gi"),"<mark>$&</mark>")},n(p,"click",A),n(p,"focus",A,!0),n(p,"input",function(e){var o,t,n=e.target;n.hasAttribute(p)&&(t={relatedTarget:(o=n).nextElementSibling},s(o,"input.filter",t)&&!k(o)&&c(x,o.nextElementSibling).reduce(function(e,t){var n=-1!==t.textContent.toLowerCase().indexOf(o.value.toLowerCase());return t[n?"removeAttribute":"setAttribute"]("hidden",""),n?e.concat(t):e},[]).forEach(j))}),n(p,"keydown",function(e){if(!(e.ctrlKey||e.altKey||e.metaKey)){if(e.target.hasAttribute(p))return C(e.target,e);// Quick check | ||
for(var t=e.target,n=void 0;t;t=t.parentElement)// Check if inside list | ||
if((n=t.previousElementSibling)&&n.hasAttribute(p))return C(n,e)}});var L=function(t){function i(e){t.call(this,e),this.onFilter=this.onFilter.bind(this),this.onSelect=this.onSelect.bind(this),this.onAjax=this.onAjax.bind(this)}t&&(i.__proto__=t),(i.prototype=Object.create(t&&t.prototype)).constructor=i;var e={defaultProps:{configurable:!0}};return e.defaultProps.get=function(){return{open:null,ajax:null,onAjax:null,onFilter:null,onSelect:null}},i.prototype.componentDidMount=function(){// Mount client side only to avoid rerender | ||
this.el.addEventListener("input.filter",this.onFilter),this.el.addEventListener("input.select",this.onSelect),this.el.addEventListener("input.ajax",this.onAjax),w(this.el.firstElementChild,this.props)},i.prototype.componentDidUpdate=function(){w(this.el.firstElementChild)},// Must mount also on update in case content changes | ||
i.prototype.componentWillUnmount=function(){this.el.removeEventListener("input.filter",this.onFilter),this.el.removeEventListener("input.select",this.onSelect),this.el.removeEventListener("input.ajax",this.onAjax)},i.prototype.onFilter=function(e){this.props.onFilter&&this.props.onFilter(e)},i.prototype.onSelect=function(e){this.props.onSelect&&this.props.onSelect(e)},i.prototype.onAjax=function(e){this.props.onAjax&&this.props.onAjax(e)},i.prototype.render=function(){var n,o,e,r=this;return a.createElement("div",(n=this.props,o=i.defaultProps,void 0===(e={ref:function(e){return r.el=e}})&&(e={}),Object.keys(n).reduce(function(e,t){return o.hasOwnProperty(t)||(e[t]=n[t]),e},e)),a.Children.map(this.props.children,function(e,t){return 0===t?a.cloneElement(e,{"aria-expanded":String(Boolean(r.props.open))}):1===t?a.cloneElement(e,{hidden:!r.props.open}):e}))},Object.defineProperties(i,e),i}(a.Component);return L.Highlight=function(e){var t=e.text,n=e.query;return void 0===n&&(n=""),a.createElement("span",{dangerouslySetInnerHTML:{__html:w.highlight(t,n)}})},L.propTypes={onFilter:e.func,onSelect:e.func,onAjax:e.func,ajax:e.string,open:e.bool},L}); | ||
/*! @nrk/core-input v1.1.3 - Copyright (c) 2017-2018 NRK */ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t(require("react"),require("prop-types")):"function"==typeof define&&define.amd?define(["react","prop-types"],t):e.CoreInput=t(e.React,e.PropTypes)}(this,function(a,e){"use strict";a=a&&a.hasOwnProperty("default")?a.default:a,e=e&&e.hasOwnProperty("default")?e.default:e;var t="undefined"!=typeof window,i=(t&&/(android)/i.test(navigator.userAgent),t&&/iPad|iPhone|iPod/.test(String(navigator.platform))),r=function(e){void 0===e&&(e=!1);try{window.addEventListener("test",null,{get passive(){e=!0}})}catch(e){}return e}();function n(e,t,n,o){(void 0===o&&(o=!1),"undefined"==typeof window||window[e=e+"-"+t])||(r||"object"!=typeof o||(o=Boolean(o.capture)),("resize"===t||"load"===t?window:document).addEventListener(window[e]=t,n,o))}var o={"&":"&","<":"<",">":">",'"':""","/":"/","'":"'"};function u(e){return String(e||"").replace(/[&<>"'/]/g,function(e){return o[e]})}var l="prevent_recursive_dispatch_maximum_callstack";function c(e,t,n){void 0===n&&(n={});var o,r=""+l+t;if(e[r])return!0;e[r]=!0,"function"==typeof window.CustomEvent?o=new window.CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n}):(o=document.createEvent("CustomEvent")).initCustomEvent(t,!0,!0,n);var i=e.dispatchEvent(o);return e[r]=null,i}function s(e,t){if(void 0===t&&(t=document),e){if(e.nodeType)return[e];if("string"==typeof e)return[].slice.call(t.querySelectorAll(e));if(e.length)return[].slice.call(e)}return[]}var p="data-@nrk/core-input-1.1.3".replace(/\W+/g,"-"),d=13,f=27,h=33,v=34,m=35,y=36,b=38,g=40,x='[tabindex="-1"]',E=500;function w(e,t){var o="object"==typeof t?t:{content:t},r="string"==typeof o.content;return s(e).map(function(e){var t=e.nextElementSibling,n=void 0===o.ajax?e.getAttribute(p):o.ajax;return e.setAttribute(p,n||""),e.setAttribute(i?"data-role":"role","combobox"),e.setAttribute("aria-autocomplete","list"),e.setAttribute("autocomplete","off"),r&&(t.innerHTML=o.content),s("a,button",t).forEach(C),j(e,o.open),e})}function A(a){a.ctrlKey||a.altKey||a.metaKey||a.defaultPrevented||s("["+p+"]").forEach(function(e){var t,n,o=e.nextElementSibling,r=e===a.target||o.contains(a.target),i="click"===a.type&&r&&s(x,o).filter(function(e){return e.contains(a.target)})[0];i?(t=e,n={relatedTarget:o,currentTarget:i,value:i.value||i.textContent.trim()},c(t,"input.select",n)&&(t.value=n.value,t.focus(),j(t,!1))):j(e,r)})}function S(e,t){var n=e.nextElementSibling,o=[e].concat(s(x+":not([hidden])",n)),r=t.keyCode===f&&"true"===e.getAttribute("aria-expanded"),i=o.indexOf(document.activeElement),a=!1;t.keyCode===g?a=o[i+1]||o[0]:t.keyCode===b?a=o[i-1]||o.pop():n.contains(t.target)&&(t.keyCode===m||t.keyCode===v?a=o.pop():t.keyCode===y||t.keyCode===h?a=o[1]:t.keyCode!==d&&e.focus()),j(e,t.keyCode!==f),(!1!==a||r)&&t.preventDefault(),a&&a.focus()}function j(e,t){var n;void 0===t&&(t="true"===e.getAttribute("aria-expanded")),n=function(){e.nextElementSibling[t?"removeAttribute":"setAttribute"]("hidden",""),e.setAttribute("aria-expanded",t)},(window.requestAnimationFrame||window.setTimeout)(n)}function C(e,t,n){e.setAttribute("aria-label",e.textContent.trim()+", "+(t+1)+" av "+n.length),e.setAttribute("tabindex","-1"),e.setAttribute("type","button")}function k(e){var t=e.getAttribute(p),n=k.req=k.req||new window.XMLHttpRequest;if(!t)return!1;clearTimeout(k.timer),n.abort(),n.onload=function(){try{n.responseJSON=JSON.parse(n.responseText)}catch(e){n.responseJSON=!1}c(e,"input.ajax",n)},k.timer=setTimeout(function(){e.value&&c(e,"input.ajax.beforeSend",n)&&(n.open("GET",t.replace("{{value}}",window.encodeURIComponent(e.value)),!0),n.setRequestHeader("X-Requested-With","XMLHttpRequest"),n.send())},E)}w.escapeHTML=u,w.highlight=function(e,t){var n=t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&");return u(e).replace(new RegExp(n||".^","gi"),"<mark>$&</mark>")},n(p,"click",A),n(p,"focus",A,!0),n(p,"input",function(e){var i,t,n=e.target;n.hasAttribute(p)&&(t={relatedTarget:(i=n).nextElementSibling},c(i,"input.filter",t)&&!k(i)&&s(x,i.nextElementSibling).reduce(function(e,t){var n="LI"===t.parentElement.nodeName&&t.parentElement,o=-1!==t.textContent.toLowerCase().indexOf(i.value.toLowerCase()),r=o?"removeAttribute":"setAttribute";return n&&n[r]("hidden",""),t[r]("hidden",""),o?e.concat(t):e},[]).forEach(C))}),n(p,"keydown",function(e){if(!(e.ctrlKey||e.altKey||e.metaKey)){if(e.target.hasAttribute(p))return S(e.target,e);for(var t=e.target,n=void 0;t;t=t.parentElement)if((n=t.previousElementSibling)&&n.hasAttribute(p))return S(n,e)}},!0);var L=function(t){function i(e){t.call(this,e),this.onFilter=this.onFilter.bind(this),this.onSelect=this.onSelect.bind(this),this.onAjax=this.onAjax.bind(this)}t&&(i.__proto__=t),(i.prototype=Object.create(t&&t.prototype)).constructor=i;var e={defaultProps:{configurable:!0}};return e.defaultProps.get=function(){return{open:null,ajax:null,onAjax:null,onFilter:null,onSelect:null}},i.prototype.componentDidMount=function(){this.el.addEventListener("input.filter",this.onFilter),this.el.addEventListener("input.select",this.onSelect),this.el.addEventListener("input.ajax",this.onAjax),w(this.el.firstElementChild,this.props)},i.prototype.componentDidUpdate=function(){w(this.el.firstElementChild)},i.prototype.componentWillUnmount=function(){this.el.removeEventListener("input.filter",this.onFilter),this.el.removeEventListener("input.select",this.onSelect),this.el.removeEventListener("input.ajax",this.onAjax)},i.prototype.onFilter=function(e){this.props.onFilter&&this.props.onFilter(e)},i.prototype.onSelect=function(e){this.props.onSelect&&this.props.onSelect(e)},i.prototype.onAjax=function(e){this.props.onAjax&&this.props.onAjax(e)},i.prototype.render=function(){var n,o,e,r=this;return a.createElement("div",(n=this.props,o=i.defaultProps,void 0===(e={ref:function(e){return r.el=e}})&&(e={}),Object.keys(n).reduce(function(e,t){return o.hasOwnProperty(t)||(e[t]=n[t]),e},e)),a.Children.map(this.props.children,function(e,t){return 0===t?a.cloneElement(e,{"aria-expanded":String(Boolean(r.props.open))}):1===t?a.cloneElement(e,{hidden:!r.props.open}):e}))},Object.defineProperties(i,e),i}(a.Component);return L.Highlight=function(e){var t=e.text,n=e.query;return void 0===n&&(n=""),a.createElement("span",{dangerouslySetInnerHTML:{__html:w.highlight(t,n)}})},L.propTypes={onFilter:e.func,onSelect:e.func,onAjax:e.func,open:e.bool,ajax:e.oneOfType([e.string,e.object])},L}); | ||
//# sourceMappingURL=core-input.jsx.js.map |
@@ -1,56 +0,3 @@ | ||
/*! @nrk/core-input v1.1.2 - Copyright (c) 2017-2018 NRK */ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.coreInput=t()}(this,function(){"use strict";var e="undefined"!=typeof window,o=(e&&/(android)/i.test(navigator.userAgent),e&&/iPad|iPhone|iPod/.test(String(navigator.platform))),i=function(e){void 0===e&&(e=!1);try{window.addEventListener("test",null,{get passive(){e=!0}})}catch(e){}return e}(); | ||
/** | ||
* addEvent | ||
* @param {String} uuid An unique ID of the event to bind - ensurnes single instance | ||
* @param {String} type The type of event to bind | ||
* @param {Function} handler The function to call on event | ||
* @param {Boolean|Object} options useCapture or options object for addEventListener. Defaults to false | ||
*/ | ||
function t(e,t,n,r){(void 0===r&&(r=!1),"undefined"==typeof window||window[e=e+"-"+t])||(// Ensure single instance | ||
i||"object"!=typeof r||(r=Boolean(r.capture)),("resize"===t||"load"===t?window:document).addEventListener(window[e]=t,n,r))} | ||
/** | ||
* escapeHTML | ||
* @param {String} str A string with potential html tokens | ||
* @return {String} Escaped HTML string according to OWASP recommendation | ||
*/var n={"&":"&","<":"<",">":">",'"':""","/":"/","'":"'"};function r(e){return String(e||"").replace(/[&<>"'/]/g,function(e){return n[e]})} | ||
/** | ||
* dispatchEvent - with infinite loop prevention | ||
* @param {Element} elem The target object | ||
* @param {String} name The source object(s) | ||
* @param {Object} detail Detail object (bubbles and cancelable is set to true) | ||
* @return {Boolean} Whether the event was canceled | ||
*/var a="prevent_recursive_dispatch_maximum_callstack";function u(e,t,n){void 0===n&&(n={});var r,i=""+a+t;if(e[i])return!0;// Add name to dispatching ignore | ||
e[i]=!0,"function"==typeof window.CustomEvent?r=new window.CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n}):(r=document.createEvent("CustomEvent")).initCustomEvent(t,!0,!0,n); | ||
// IE reports incorrect event.defaultPrevented | ||
// but correct return value on element.dispatchEvent | ||
var o=e.dispatchEvent(r);// Remove name from dispatching ignore | ||
return e[i]=null,o;// Follow W3C standard for return value | ||
} | ||
/** | ||
* requestAnimFrame (super simple polyfill) | ||
*/ | ||
/** | ||
* queryAll | ||
* @param {String|NodeList|Array|Element} elements A CSS selector string, nodeList, element array, or single element | ||
* @return {Element[]} Array of elements | ||
*/ | ||
function c(e,t){if(void 0===t&&(t=document),e){if(e.nodeType)return[e];if("string"==typeof e)return[].slice.call(t.querySelectorAll(e));if(e.length)return[].slice.call(e)}return[]}var d="data-@nrk/core-input-1.1.2".replace(/\W+/g,"-"),l=13,s=27,f=33,p=34,v=35,m=36,b=38,g=40,y='[tabindex="-1"]',w=500;// Strip invalid attribute characters | ||
function x(e,t){var r="object"==typeof t?t:{content:t},i="string"==typeof r.content;return c(e).map(function(e){var t=e.nextElementSibling,n=void 0===r.ajax?e.getAttribute(d):r.ajax;return e.setAttribute(d,n||""),e.setAttribute(o?"data-role":"role","combobox"),// iOS does not inform user area is editable if combobox | ||
e.setAttribute("aria-autocomplete","list"),e.setAttribute("autocomplete","off"),i&&(t.innerHTML=r.content),c("a,button",t).forEach(C),A(e,r.open),e})} | ||
// Expose helper functions | ||
// Use focus with capturing instead of focusin for old Firefox | ||
function E(a){a.ctrlKey||a.altKey||a.metaKey||a.defaultPrevented||c("["+d+"]").forEach(function(e){var t,n,r=e.nextElementSibling,i=e===a.target||r.contains(a.target),o="click"===a.type&&i&&c(y,r).filter(function(e){return e.contains(a.target)})[0];o?(t=e,n={relatedTarget:r,currentTarget:o,value:o.value||o.textContent.trim()},u(t,"input.select",n)&&(t.value=n.value,t.focus(),A(t,!1))):A(e,i)})}function h(e,t){var n=e.nextElementSibling,r=[e].concat(c(y+":not([hidden])",n)),i=r.indexOf(document.activeElement),o=!1;t.keyCode===g?o=r[i+1]||r[0]:t.keyCode===b?o=r[i-1]||r.pop():n.contains(t.target)&&(// Aditional shortcuts if focus is inside list | ||
t.keyCode===v||t.keyCode===p?o=r.pop():t.keyCode===m||t.keyCode===f?o=r[1]:t.keyCode!==l&&e.focus()), | ||
// Prevent leaving maximized safari and event.preventDefault even if undefined item (empty list) | ||
t.keyCode!==s&&!1===o||t.preventDefault(),A(e,t.keyCode!==s),o&&o.focus()}function A(e,t){var n;void 0===t&&(t="true"===e.getAttribute("aria-expanded")),n=function(){// Fixes VoiceOver Safari focus jumping to parentElement | ||
e.nextElementSibling[t?"removeAttribute":"setAttribute"]("hidden",""),e.setAttribute("aria-expanded",t)},(window.requestAnimationFrame||window.setTimeout)(n)}function C(e,t,n){e.setAttribute("aria-label",e.textContent.trim()+", "+(t+1)+" av "+n.length),e.setAttribute("tabindex","-1"),e.setAttribute("type","button")}function k(e){var t=e.getAttribute(d),n=k.req=k.req||new window.XMLHttpRequest;if(!t)return!1;clearTimeout(k.timer),// Clear previous search | ||
n.abort(),// Abort previous request | ||
n.onload=function(){try{n.responseJSON=JSON.parse(n.responseText)}catch(e){n.responseJSON=!1}u(e,"input.ajax",n)},k.timer=setTimeout(function(){// Debounce next request 500 milliseconds | ||
e.value&&(// Abort if input is empty | ||
n.open("GET",t.replace("{{value}}",window.encodeURIComponent(e.value)),!0),n.setRequestHeader("X-Requested-With","XMLHttpRequest"),// https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Requested-With | ||
n.send())},w)}return x.escapeHTML=r,x.highlight=function(e,t){var n=t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&");// From lodash | ||
return r(e).replace(new RegExp(n||".^","gi"),"<mark>$&</mark>")},t(d,"click",E),t(d,"focus",E,!0),t(d,"input",function(e){var r,t,n=e.target;n.hasAttribute(d)&&(t={relatedTarget:(r=n).nextElementSibling},u(r,"input.filter",t)&&!k(r)&&c(y,r.nextElementSibling).reduce(function(e,t){var n=-1!==t.textContent.toLowerCase().indexOf(r.value.toLowerCase());return t[n?"removeAttribute":"setAttribute"]("hidden",""),n?e.concat(t):e},[]).forEach(C))}),t(d,"keydown",function(e){if(!(e.ctrlKey||e.altKey||e.metaKey)){if(e.target.hasAttribute(d))return h(e.target,e);// Quick check | ||
for(var t=e.target,n=void 0;t;t=t.parentElement)// Check if inside list | ||
if((n=t.previousElementSibling)&&n.hasAttribute(d))return h(n,e)}}),x}); | ||
/*! @nrk/core-input v1.1.3 - Copyright (c) 2017-2018 NRK */ | ||
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.coreInput=t()}(this,function(){"use strict";var e="undefined"!=typeof window,o=(e&&/(android)/i.test(navigator.userAgent),e&&/iPad|iPhone|iPod/.test(String(navigator.platform))),i=function(e){void 0===e&&(e=!1);try{window.addEventListener("test",null,{get passive(){e=!0}})}catch(e){}return e}();function t(e,t,n,r){(void 0===r&&(r=!1),"undefined"==typeof window||window[e=e+"-"+t])||(i||"object"!=typeof r||(r=Boolean(r.capture)),("resize"===t||"load"===t?window:document).addEventListener(window[e]=t,n,r))}var n={"&":"&","<":"<",">":">",'"':""","/":"/","'":"'"};function r(e){return String(e||"").replace(/[&<>"'/]/g,function(e){return n[e]})}var a="prevent_recursive_dispatch_maximum_callstack";function u(e,t,n){void 0===n&&(n={});var r,i=""+a+t;if(e[i])return!0;e[i]=!0,"function"==typeof window.CustomEvent?r=new window.CustomEvent(t,{bubbles:!0,cancelable:!0,detail:n}):(r=document.createEvent("CustomEvent")).initCustomEvent(t,!0,!0,n);var o=e.dispatchEvent(r);return e[i]=null,o}function c(e,t){if(void 0===t&&(t=document),e){if(e.nodeType)return[e];if("string"==typeof e)return[].slice.call(t.querySelectorAll(e));if(e.length)return[].slice.call(e)}return[]}var d="data-@nrk/core-input-1.1.3".replace(/\W+/g,"-"),l=13,f=27,s=33,p=34,v=35,m=36,b=38,g=40,y='[tabindex="-1"]',w=500;function x(e,t){var r="object"==typeof t?t:{content:t},i="string"==typeof r.content;return c(e).map(function(e){var t=e.nextElementSibling,n=void 0===r.ajax?e.getAttribute(d):r.ajax;return e.setAttribute(d,n||""),e.setAttribute(o?"data-role":"role","combobox"),e.setAttribute("aria-autocomplete","list"),e.setAttribute("autocomplete","off"),i&&(t.innerHTML=r.content),c("a,button",t).forEach(C),A(e,r.open),e})}function E(a){a.ctrlKey||a.altKey||a.metaKey||a.defaultPrevented||c("["+d+"]").forEach(function(e){var t,n,r=e.nextElementSibling,i=e===a.target||r.contains(a.target),o="click"===a.type&&i&&c(y,r).filter(function(e){return e.contains(a.target)})[0];o?(t=e,n={relatedTarget:r,currentTarget:o,value:o.value||o.textContent.trim()},u(t,"input.select",n)&&(t.value=n.value,t.focus(),A(t,!1))):A(e,i)})}function h(e,t){var n=e.nextElementSibling,r=[e].concat(c(y+":not([hidden])",n)),i=t.keyCode===f&&"true"===e.getAttribute("aria-expanded"),o=r.indexOf(document.activeElement),a=!1;t.keyCode===g?a=r[o+1]||r[0]:t.keyCode===b?a=r[o-1]||r.pop():n.contains(t.target)&&(t.keyCode===v||t.keyCode===p?a=r.pop():t.keyCode===m||t.keyCode===s?a=r[1]:t.keyCode!==l&&e.focus()),A(e,t.keyCode!==f),(!1!==a||i)&&t.preventDefault(),a&&a.focus()}function A(e,t){var n;void 0===t&&(t="true"===e.getAttribute("aria-expanded")),n=function(){e.nextElementSibling[t?"removeAttribute":"setAttribute"]("hidden",""),e.setAttribute("aria-expanded",t)},(window.requestAnimationFrame||window.setTimeout)(n)}function C(e,t,n){e.setAttribute("aria-label",e.textContent.trim()+", "+(t+1)+" av "+n.length),e.setAttribute("tabindex","-1"),e.setAttribute("type","button")}function k(e){var t=e.getAttribute(d),n=k.req=k.req||new window.XMLHttpRequest;if(!t)return!1;clearTimeout(k.timer),n.abort(),n.onload=function(){try{n.responseJSON=JSON.parse(n.responseText)}catch(e){n.responseJSON=!1}u(e,"input.ajax",n)},k.timer=setTimeout(function(){e.value&&u(e,"input.ajax.beforeSend",n)&&(n.open("GET",t.replace("{{value}}",window.encodeURIComponent(e.value)),!0),n.setRequestHeader("X-Requested-With","XMLHttpRequest"),n.send())},w)}return x.escapeHTML=r,x.highlight=function(e,t){var n=t.replace(/[-/\\^$*+?.()|[\]{}]/g,"\\$&");return r(e).replace(new RegExp(n||".^","gi"),"<mark>$&</mark>")},t(d,"click",E),t(d,"focus",E,!0),t(d,"input",function(e){var o,t,n=e.target;n.hasAttribute(d)&&(t={relatedTarget:(o=n).nextElementSibling},u(o,"input.filter",t)&&!k(o)&&c(y,o.nextElementSibling).reduce(function(e,t){var n="LI"===t.parentElement.nodeName&&t.parentElement,r=-1!==t.textContent.toLowerCase().indexOf(o.value.toLowerCase()),i=r?"removeAttribute":"setAttribute";return n&&n[i]("hidden",""),t[i]("hidden",""),r?e.concat(t):e},[]).forEach(C))}),t(d,"keydown",function(e){if(!(e.ctrlKey||e.altKey||e.metaKey)){if(e.target.hasAttribute(d))return h(e.target,e);for(var t=e.target,n=void 0;t;t=t.parentElement)if((n=t.previousElementSibling)&&n.hasAttribute(d))return h(n,e)}},!0),x}); | ||
//# sourceMappingURL=core-input.min.js.map |
31
jsx.js
@@ -9,3 +9,3 @@ 'use strict'; | ||
var name = "@nrk/core-input"; | ||
var version = "1.1.2"; | ||
var version = "1.1.3"; | ||
@@ -176,3 +176,3 @@ var IS_BROWSER = typeof window !== 'undefined'; | ||
} | ||
}); | ||
}, true); // Use capture to enable checking defaultPrevented (from ESC key) in parents | ||
@@ -182,2 +182,3 @@ function onKey (input, event) { | ||
var focusable = [input].concat(queryAll((ITEM + ":not([hidden])"), list)); | ||
var isClosing = event.keyCode === KEYS.ESC && input.getAttribute('aria-expanded') === 'true'; | ||
var index = focusable.indexOf(document.activeElement); | ||
@@ -195,4 +196,4 @@ var item = false; | ||
// Prevent leaving maximized safari and event.preventDefault even if undefined item (empty list) | ||
if (event.keyCode === KEYS.ESC || item !== false) { event.preventDefault(); } | ||
setupExpand(input, event.keyCode !== KEYS.ESC); | ||
if (item !== false || isClosing) { event.preventDefault(); } | ||
if (item) { item.focus(); } | ||
@@ -212,4 +213,7 @@ } | ||
queryAll(ITEM, input.nextElementSibling).reduce(function (acc, item) { | ||
var list = item.parentElement.nodeName === 'LI' && item.parentElement; | ||
var show = item.textContent.toLowerCase().indexOf(input.value.toLowerCase()) !== -1; | ||
item[show ? 'removeAttribute' : 'setAttribute']('hidden', ''); | ||
var attr = show ? 'removeAttribute' : 'setAttribute'; | ||
if (list) { list[attr]('hidden', ''); } // JAWS requires hiding of <li> too (if they exist) | ||
item[attr]('hidden', ''); | ||
return show ? acc.concat(item) : acc | ||
@@ -246,8 +250,10 @@ }, []).forEach(setupItem); | ||
}; | ||
ajax.timer = setTimeout(function () { // Debounce next request 500 milliseconds | ||
ajax.timer = setTimeout(function () { | ||
if (!input.value) { return } // Abort if input is empty | ||
req.open('GET', url.replace('{{value}}', window.encodeURIComponent(input.value)), true); | ||
req.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); // https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Requested-With | ||
req.send(); | ||
}, AJAX_DEBOUNCE); | ||
if (dispatchEvent(input, 'input.ajax.beforeSend', req)) { | ||
req.open('GET', url.replace('{{value}}', window.encodeURIComponent(input.value)), true); | ||
req.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); // https://en.wikipedia.org/wiki/List_of_HTTP_header_fields#Requested-With | ||
req.send(); | ||
} | ||
}, AJAX_DEBOUNCE); // Debounce request | ||
} | ||
@@ -315,6 +321,9 @@ | ||
onAjax: PropTypes.func, | ||
ajax: PropTypes.string, | ||
open: PropTypes.bool | ||
open: PropTypes.bool, | ||
ajax: PropTypes.oneOfType([ | ||
PropTypes.string, | ||
PropTypes.object | ||
]) | ||
}; | ||
module.exports = Input; |
@@ -5,3 +5,3 @@ { | ||
"author": "NRK <opensource@nrk.no> (https://www.nrk.no/)", | ||
"version": "1.1.3", | ||
"version": "1.2.0", | ||
"license": "MIT", | ||
@@ -8,0 +8,0 @@ "main": "core-input.cjs.js", |
@@ -67,3 +67,3 @@ # Core Input | ||
*Important: Always use `coreInput.escapeHTML(String)` to safely render data from API or user.* | ||
<small><b>Important:</b> Always use `coreInput.escapeHTML(String)` to safely render data from API or user.</small> | ||
@@ -116,3 +116,3 @@ ```html | ||
### input.filter | ||
`'input.filter'` is fired before a default filtering (both for VanillaJS and React/Preact components). The `input.filter` event is cancelable, meaning you can use `event.preventDefault()` to cancel default filtering and respond to users typing yourself. The event also bubbles, and can therefore be detected both from button element itself, or any parent element (read event delegation): | ||
`'input.filter'` is fired before a default filtering (both for VanillaJS and React/Preact components). The `input.filter` event is cancelable, meaning you can use `event.preventDefault()` to cancel default filtering and respond to users typing yourself. The event also bubbles, and can therefore be detected both from the input element itself, or any parent element (read event delegation): | ||
@@ -127,3 +127,3 @@ ```js | ||
### input.select | ||
`'input.select'` event is fired when the user clicks/selects a item (both for VanillaJS and React/Preact components). The `input.select` event is cancelable, meaning you can use `event.preventDefault()` to cancel replacing the input value and handle select-action yourself. The event also bubbles, and can therefore be detected both from button element itself, or any parent element (read event delegation): | ||
`'input.select'` event is fired when the user clicks/selects a item (both for VanillaJS and React/Preact components). The `input.select` event is cancelable, meaning you can use `event.preventDefault()` to cancel replacing the input value and handle select-action yourself. The event also bubbles, and can therefore be detected both from the button element itself, or any parent element (read event delegation): | ||
@@ -139,4 +139,25 @@ ```js | ||
### input.ajax.beforeSend | ||
The `'input.ajax.beforeSend'` event is fired before sending debounced ajax requests. If you wish to alter the [XMLHttpRequest](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest), use `event.preventDefault()` and then execute [XHR methods](https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest#Methods) on the `event.detail`. If not prevented, requests are sent using the `GET` method and the header `'X-Requested-With': 'XMLHttpRequest'`. The event bubbles, and can therefore be detected both from the input element itself, or any parent element (read event delegation): | ||
```js | ||
document.addEventListener('input.ajax.beforeSend', (event) => { | ||
event.target // The core-input element triggering input.ajax.beforeSend event | ||
event.detail // The XMLHttpRequest object | ||
}) | ||
``` | ||
```js | ||
// Example | ||
document.addEventListener('input.ajax.beforeSend', (event) => { | ||
event.preventDefault() // Stop default behaviour | ||
event.detail.open('POST', 'https://example.com') | ||
event.detail.setRequestHeader('Content-Type', 'application/json') | ||
event.detail.setRequestHeader('my-custom-header', 'my-custom-value') | ||
event.detail.send(JSON.stringify({query: event.target.value})) | ||
}) | ||
``` | ||
### input.ajax | ||
`'input.ajax'` event is fired when the input field receives data from ajax. The event also bubbles, and can therefore be detected both from button element itself, or any parent element (read event delegation): | ||
`'input.ajax'` event is fired when the input field receives data from ajax. The event also bubbles, and can therefore be detected both from the input element itself, or any parent element (read event delegation): | ||
@@ -172,2 +193,12 @@ ```js | ||
## Ajax | ||
When using `@nrk/core-input` with the `ajax: https://search.com?q={{value}}` functionality, make sure to implement both a `Searching...` status (while fetching data from the server), and a `No hits` status (if server responds with no results). These status indicators are highly recommended, but not provided by default as the context of use will affect the optimal textual formulation. [See example implementation →](#demo-ajax) | ||
### Customise the request | ||
If you need to alter default headers, request method or post data, use the [`input.ajax.beforeSend` event →](#input-ajax-beforesend) | ||
--- | ||
## Demo: Ajax | ||
@@ -247,2 +278,4 @@ | ||
--- | ||
## Demo: Lazy | ||
@@ -307,2 +340,4 @@ Hybrid solution; lazy load items, but let `core-input` still handle filtering: | ||
--- | ||
## Demo: Dynamic | ||
@@ -309,0 +344,0 @@ Synchronous operation; dynamically populating items based input value: |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
104848
413
865