@nrk/core-toggle
Advanced tools
Comparing version
import {name, version} from './package.json' | ||
import {addEvent, ariaExpand, ariaTarget, queryAll} from '../utils' | ||
import {IS_ANDROID, addEvent, dispatchEvent, queryAll} from '../utils' | ||
const UUID = `data-${name}-${version}`.replace(/\W+/g, '-') // Strip invalid attribute characters | ||
const ARIA = IS_ANDROID ? 'data' : 'aria' // Andriod has a bug and reads only label instead of content | ||
const OPEN = 'aria-expanded' | ||
const POPS = 'aria-haspopup' | ||
const isBool = (val) => typeof val === 'boolean' | ||
export default function toggle (selector, open) { | ||
export default function toggle (buttons, open) { | ||
const options = typeof open === 'object' ? open : {open} | ||
return queryAll(selector).forEach((button) => { | ||
const open = isBool(options.open) ? options.open : button.getAttribute(OPEN) === 'true' | ||
const pops = isBool(options.popup) ? options.popup : button.getAttribute(POPS) === 'true' | ||
return queryAll(buttons).forEach((button) => { | ||
const open = typeof options.open === 'boolean' ? options.open : button.getAttribute(OPEN) === 'true' | ||
const pops = typeof options.popup === 'boolean' ? options.popup : button.getAttribute(POPS) === 'true' | ||
const next = button.nextElementSibling | ||
button.setAttribute(UUID, '') | ||
button.setAttribute(POPS, pops) | ||
button.setAttribute('aria-controls', next.id = next.id || getUUID()) | ||
next.setAttribute(`${ARIA}-labelledby`, button.id = button.id || getUUID()) | ||
ariaTarget(button, 'controls') | ||
ariaExpand(button, open) | ||
toggleExpand(button, open) | ||
return button | ||
@@ -30,6 +31,26 @@ }) | ||
const pops = el.getAttribute(POPS) === 'true' | ||
const next = el.nextElementSibling | ||
if (el.contains(target)) toggle(el, !open) // Click on toggle | ||
else if (pops) toggle(el, ariaTarget(el).contains(target)) // Click in target or outside | ||
if (el.contains(target)) toggleExpand(el, !open) // Click on toggle | ||
else if (pops) toggleExpand(el, next.contains(target)) // Click in target or outside | ||
}) | ||
}) | ||
function toggleExpand (button, open) { | ||
const isOpen = button.getAttribute(OPEN) === 'true' | ||
const willOpen = typeof open === 'boolean' ? open : (open === 'toggle' ? !isOpen : isOpen) | ||
const relatedTarget = button.nextElementSibling | ||
if (isOpen === willOpen) setExpand(button, isOpen) | ||
else if (dispatchEvent(button, 'toggle', {relatedTarget, isOpen, willOpen})) setExpand(button, willOpen) | ||
return willOpen | ||
} | ||
function getUUID () { | ||
return Date.now().toString(36) + Math.random().toString(36).slice(2, 5) | ||
} | ||
function setExpand (button, open) { | ||
button.setAttribute(OPEN, open) | ||
button.nextElementSibling[open ? 'removeAttribute' : 'setAttribute']('hidden', '') | ||
} |
@@ -5,7 +5,11 @@ import React from 'react' | ||
const DEFAULTS = {open: null, popup: null} | ||
const DEFAULTS = {open: null, popup: null, onToggle: null} // Remove onToggle prop as this is also a native event | ||
export default class Toggle extends React.Component { | ||
componentDidMount () { coreToggle(this.el.firstElementChild) } // Mount client side only to avoid rerender | ||
componentDidMount () { | ||
coreToggle(this.el.firstElementChild) // Mount client side only to avoid rerender | ||
this.el.addEventListener('toggle', this.props.onToggle) | ||
} | ||
componentDidUpdate () { coreToggle(this.el.firstElementChild) } // Must mount also on update in case content changes | ||
componentWillUnmount () { this.el.removeEventListener('toggle', this.props.onToggle) } | ||
render () { | ||
@@ -12,0 +16,0 @@ return React.createElement('div', exclude(this.props, DEFAULTS, {ref: (el) => (this.el = el)}), |
@@ -1,2 +0,2 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.coreToggle=e()}(this,function(){"use strict";var t="undefined"!=typeof window,e=t&&/(android)/i.test(navigator.userAgent);t&&/iPad|iPhone|iPod/.test(String(navigator.platform));function n(t,e){var n=r(t),i="true"===t.getAttribute("aria-expanded"),o="boolean"==typeof e?e:"toggle"===e?!i:i,u=i===o||function(t,e,n){void 0===n&&(n={});var r;"function"==typeof window.CustomEvent?r=new window.CustomEvent(e,{bubbles:!0,cancelable:!0,detail:n}):(r=document.createEvent("CustomEvent")).initCustomEvent(e,!0,!0,n);return t.dispatchEvent(r)}(t,"toggle",{relatedTarget:n,isOpen:i})?o:i;return n[u?"removeAttribute":"setAttribute"]("hidden",""),t.setAttribute("aria-expanded",u),u}function r(t,n){var r=t.getAttribute("aria-controls")||t.getAttribute("aria-owns"),o=document.getElementById(r)||t.nextElementSibling,u=e?"data":"aria";if(!o)throw new Error("missing nextElementSibling on "+t.outerHTML);return n&&(t.setAttribute("aria-"+n,o.id=o.id||i()),o.setAttribute(u+"-labelledby",t.id=t.id||i())),o}function i(t,e){return Date.now().toString(36)+Math.random().toString(36).slice(2,5)}function o(t,e){if(void 0===e&&(e=document),t){if(t.nodeType)return[t];if("string"==typeof t)return[].slice.call(e.querySelectorAll(t));if(t.length)return[].slice.call(t)}return[]}var u,a,d,c,f="data-@nrk/core-toggle-1.0.1".replace(/\W+/g,"-"),l="aria-expanded",s="aria-haspopup",p=function(t){return"boolean"==typeof t};function g(t,e){var i="object"==typeof e?e:{open:e};return o(t).forEach(function(t){var e=p(i.open)?i.open:"true"===t.getAttribute(l),o=p(i.popup)?i.popup:"true"===t.getAttribute(s);return t.setAttribute(f,""),t.setAttribute(s,o),r(t,"controls"),n(t,e),t})}return a=function(t){var e=t.target;o("["+f+"]").forEach(function(t){var n="true"===t.getAttribute(l),i="true"===t.getAttribute(s);t.contains(e)?g(t,!n):i&&g(t,r(t).contains(e))})},d="blur"===(u="click")||"focus"===u,c=f+"-"+u,"undefined"==typeof window||window[c]||document.addEventListener(window[c]=u,a,d),g}); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.coreToggle=e()}(this,function(){"use strict";var t="undefined"!=typeof window,e=t&&/(android)/i.test(navigator.userAgent);t&&/iPad|iPhone|iPod/.test(String(navigator.platform));function n(t,e){if(void 0===e&&(e=document),t){if(t.nodeType)return[t];if("string"==typeof t)return[].slice.call(e.querySelectorAll(t));if(t.length)return[].slice.call(t)}return[]}var i,o,r,u,a="data-@nrk/core-toggle-1.0.2".replace(/\W+/g,"-"),d=e?"data":"aria",l="aria-expanded",c="aria-haspopup";function f(t,e){var n,i,o,r,u="true"===t.getAttribute(l),a="boolean"==typeof e?e:"toggle"===e?!u:u,d=t.nextElementSibling;return u===a?s(t,u):(n=t,i="toggle",void 0===(o={relatedTarget:d,isOpen:u,willOpen:a})&&(o={}),"function"==typeof window.CustomEvent?r=new window.CustomEvent(i,{bubbles:!0,cancelable:!0,detail:o}):(r=document.createEvent("CustomEvent")).initCustomEvent(i,!0,!0,o),n.dispatchEvent(r)&&s(t,a)),a}function p(){return Date.now().toString(36)+Math.random().toString(36).slice(2,5)}function s(t,e){t.setAttribute(l,e),t.nextElementSibling[e?"removeAttribute":"setAttribute"]("hidden","")}return o=function(t){var e=t.target;n("["+a+"]").forEach(function(t){var n="true"===t.getAttribute(l),i="true"===t.getAttribute(c),o=t.nextElementSibling;t.contains(e)?f(t,!n):i&&f(t,o.contains(e))})},r="blur"===(i="click")||"focus"===i,u=a+"-"+i,"undefined"==typeof window||window[u]||document.addEventListener(window[u]=i,o,r),function(t,e){var i="object"==typeof e?e:{open:e};return n(t).forEach(function(t){var e="boolean"==typeof i.open?i.open:"true"===t.getAttribute(l),n="boolean"==typeof i.popup?i.popup:"true"===t.getAttribute(c),o=t.nextElementSibling;return t.setAttribute(a,""),t.setAttribute(c,n),t.setAttribute("aria-controls",o.id=o.id||p()),o.setAttribute(d+"-labelledby",t.id=t.id||p()),f(t,e),t})}}); | ||
//# sourceMappingURL=core-toggle.min.js.map |
@@ -1,2 +0,2 @@ | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("react")):"function"==typeof define&&define.amd?define(["react"],e):t.CoreToggle=e(t.React)}(this,function(t){"use strict";t=t&&t.hasOwnProperty("default")?t.default:t;var e="undefined"!=typeof window,n=e&&/(android)/i.test(navigator.userAgent);e&&/iPad|iPhone|iPod/.test(String(navigator.platform));function r(t,e){var n=o(t),r="true"===t.getAttribute("aria-expanded"),i="boolean"==typeof e?e:"toggle"===e?!r:r,u=r===i||function(t,e,n){void 0===n&&(n={});var r;"function"==typeof window.CustomEvent?r=new window.CustomEvent(e,{bubbles:!0,cancelable:!0,detail:n}):(r=document.createEvent("CustomEvent")).initCustomEvent(e,!0,!0,n);return t.dispatchEvent(r)}(t,"toggle",{relatedTarget:n,isOpen:r})?i:r;return n[u?"removeAttribute":"setAttribute"]("hidden",""),t.setAttribute("aria-expanded",u),u}function o(t,e){var r=t.getAttribute("aria-controls")||t.getAttribute("aria-owns"),o=document.getElementById(r)||t.nextElementSibling,u=n?"data":"aria";if(!o)throw new Error("missing nextElementSibling on "+t.outerHTML);return e&&(t.setAttribute("aria-"+e,o.id=o.id||i()),o.setAttribute(u+"-labelledby",t.id=t.id||i())),o}function i(t,e){return Date.now().toString(36)+Math.random().toString(36).slice(2,5)}function u(t,e){if(void 0===e&&(e=document),t){if(t.nodeType)return[t];if("string"==typeof t)return[].slice.call(e.querySelectorAll(t));if(t.length)return[].slice.call(t)}return[]}var a,p,d,c,l="data-@nrk/core-toggle-1.0.1".replace(/\W+/g,"-"),f="aria-expanded",s="aria-haspopup",g=function(t){return"boolean"==typeof t};function b(t,e){var n="object"==typeof e?e:{open:e};return u(t).forEach(function(t){var e=g(n.open)?n.open:"true"===t.getAttribute(f),i=g(n.popup)?n.popup:"true"===t.getAttribute(s);return t.setAttribute(l,""),t.setAttribute(s,i),o(t,"controls"),r(t,e),t})}p=function(t){var e=t.target;u("["+l+"]").forEach(function(t){var n="true"===t.getAttribute(f),r="true"===t.getAttribute(s);t.contains(e)?b(t,!n):r&&b(t,o(t).contains(e))})},d="blur"===(a="click")||"focus"===a,c=l+"-"+a,"undefined"==typeof window||window[c]||document.addEventListener(window[c]=a,p,d);var m={open:null,popup:null};return function(e){function n(){e.apply(this,arguments)}return e&&(n.__proto__=e),n.prototype=Object.create(e&&e.prototype),n.prototype.constructor=n,n.prototype.componentDidMount=function(){b(this.el.firstElementChild)},n.prototype.componentDidUpdate=function(){b(this.el.firstElementChild)},n.prototype.render=function(){var e=this;return t.createElement("div",function(t,e,n){return void 0===n&&(n={}),Object.keys(t).reduce(function(n,r){return e.hasOwnProperty(r)||(n[r]=t[r]),n},n)}(this.props,m,{ref:function(t){return e.el=t}}),t.Children.map(this.props.children,function(n,r){return r?t.cloneElement(n,{hidden:!e.props.open}):t.cloneElement(n,{"aria-expanded":String(Boolean(e.props.open)),"aria-haspopup":String(Boolean(e.props.popup))})}))},n}(t.Component)}); | ||
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e(require("react")):"function"==typeof define&&define.amd?define(["react"],e):t.CoreToggle=e(t.React)}(this,function(t){"use strict";t=t&&t.hasOwnProperty("default")?t.default:t;var e="undefined"!=typeof window,n=e&&/(android)/i.test(navigator.userAgent);e&&/iPad|iPhone|iPod/.test(String(navigator.platform));function o(t,e){if(void 0===e&&(e=document),t){if(t.nodeType)return[t];if("string"==typeof t)return[].slice.call(e.querySelectorAll(t));if(t.length)return[].slice.call(t)}return[]}var r,i,u,p,l="data-@nrk/core-toggle-1.0.2".replace(/\W+/g,"-"),a=n?"data":"aria",c="aria-expanded",d="aria-haspopup";function s(t,e){var n="object"==typeof e?e:{open:e};return o(t).forEach(function(t){var e="boolean"==typeof n.open?n.open:"true"===t.getAttribute(c),o="boolean"==typeof n.popup?n.popup:"true"===t.getAttribute(d),r=t.nextElementSibling;return t.setAttribute(l,""),t.setAttribute(d,o),t.setAttribute("aria-controls",r.id=r.id||g()),r.setAttribute(a+"-labelledby",t.id=t.id||g()),f(t,e),t})}function f(t,e){var n,o,r,i,u="true"===t.getAttribute(c),p="boolean"==typeof e?e:"toggle"===e?!u:u,l=t.nextElementSibling;return u===p?b(t,u):(n=t,o="toggle",void 0===(r={relatedTarget:l,isOpen:u,willOpen:p})&&(r={}),"function"==typeof window.CustomEvent?i=new window.CustomEvent(o,{bubbles:!0,cancelable:!0,detail:r}):(i=document.createEvent("CustomEvent")).initCustomEvent(o,!0,!0,r),n.dispatchEvent(i)&&b(t,p)),p}function g(){return Date.now().toString(36)+Math.random().toString(36).slice(2,5)}function b(t,e){t.setAttribute(c,e),t.nextElementSibling[e?"removeAttribute":"setAttribute"]("hidden","")}i=function(t){var e=t.target;o("["+l+"]").forEach(function(t){var n="true"===t.getAttribute(c),o="true"===t.getAttribute(d),r=t.nextElementSibling;t.contains(e)?f(t,!n):o&&f(t,r.contains(e))})},u="blur"===(r="click")||"focus"===r,p=l+"-"+r,"undefined"==typeof window||window[p]||document.addEventListener(window[p]=r,i,u);var m={open:null,popup:null,onToggle:null};return function(e){function n(){e.apply(this,arguments)}return e&&(n.__proto__=e),n.prototype=Object.create(e&&e.prototype),n.prototype.constructor=n,n.prototype.componentDidMount=function(){s(this.el.firstElementChild),this.el.addEventListener("toggle",this.props.onToggle)},n.prototype.componentDidUpdate=function(){s(this.el.firstElementChild)},n.prototype.componentWillUnmount=function(){this.el.removeEventListener("toggle",this.props.onToggle)},n.prototype.render=function(){var e=this;return t.createElement("div",function(t,e,n){return void 0===n&&(n={}),Object.keys(t).reduce(function(n,o){return e.hasOwnProperty(o)||(n[o]=t[o]),n},n)}(this.props,m,{ref:function(t){return e.el=t}}),t.Children.map(this.props.children,function(n,o){return o?t.cloneElement(n,{hidden:!e.props.open}):t.cloneElement(n,{"aria-expanded":String(Boolean(e.props.open)),"aria-haspopup":String(Boolean(e.props.popup))})}))},n}(t.Component)}); | ||
//# sourceMappingURL=index.js.map |
@@ -5,3 +5,3 @@ { | ||
"author": "NRK <opensource@nrk.no> (https://www.nrk.no/)", | ||
"version": "1.0.2", | ||
"version": "1.1.0", | ||
"license": "MIT", | ||
@@ -8,0 +8,0 @@ "main": "core-toggle.min.js", |
Sorry, the diff of this file is not supported yet
Sorry, the diff of this file is not supported yet
95
28.38%32930
-0.4%