ctrly
Version:
Lightweight and dependency-free content toggling with a focus on accessibility.
7 lines (6 loc) • 8.56 kB
JavaScript
/*!
* ctrly v0.7.0
* Copyright (c) 2018-2019 Jan Sorgalla
* License: MIT
*/
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):(t=t||self).ctrly=e()}(this,(function(){"use strict";function t(){try{var t=document.activeElement;return t&&t.nodeName?t:document.body}catch(t){return document.body}}function e(t){for(var e=[];t&&t.parentNode&&1===t.parentNode.nodeType;)t=t.parentNode,e.push(t);return e}function n(t){var n;(arguments.length>1&&void 0!==arguments[1]?arguments[1]:{}).restoreScrollPosition&&(n=function(t){var n=e(t).map((function(t){return[t,t.scrollTop,t.scrollLeft]}));return function(){n.forEach((function(t){t[0].scrollTop=t[1],t[0].scrollLeft=t[2]}))}}(t));try{t.focus()}catch(t){}n&&n()}function r(t,e){if(!t)return!1;var n=t.matches||t.webkitMatchesSelector||t.msMatchesSelector;return"function"==typeof n&&n.call(t,e)}function o(t,e){if(!t)return null;if("function"==typeof t.closest)return t.closest(e);do{if(r(t,e))return t;t=t.parentNode}while(t&&1===t.nodeType);return null}function i(t,e){var n=arguments.length>1?e:document;return n&&"function"==typeof n.querySelectorAll?[].slice.call(n.querySelectorAll(t)):[]}var a,u=["a[href]","area[href]","input","select","textarea","button","iframe","object","audio[controls]","video[controls]","[contenteditable]","[tabindex]"].join(","),c=/^(input|select|textarea|button|object)$/;function l(t){var e=t.nodeName.toLowerCase();if("area"===e)return function(t){var e=t.parentNode,n=e.name;if(!t.href||!n||"map"!==e.nodeName.toLowerCase())return!1;var r=i('img[usemap="#'.concat(n,'"]'));return r.length>0&&f(r[0])}(t);if(t.disabled)return!1;if(c.test(e)){var n=o(t,"fieldset");if(n&&n.disabled)return!1}return f(t)}function s(t){var e=p(t);return l(t)&&e>=0}function d(t,e){var n=p(t,!0),r=p(e,!0);return n===r?2&t.compareDocumentPosition(e)?1:-1:n-r}function f(t){var n=getComputedStyle(t);return"hidden"!==n.visibility&&"collapse"!==n.visibility&&"none"!==n.display&&e(t).every((function(t){return"none"!==getComputedStyle(t).display}))}function p(t){var e=arguments.length>1&&void 0!==arguments[1]&&arguments[1],n=parseInt(t.getAttribute("tabindex"),10);return isNaN(n)?0:e&&n<0?0:n}function v(){if(a)return a;a={capture:!1,once:!1,passive:!1};var t={get capture(){return a.capture=!0,!1},get once(){return a.once=!0,!1},get passive(){return a.passive=!0,!1}};return window.addEventListener("test",t,t),window.removeEventListener("test",t,t),a}function b(){var t=arguments.length>0&&void 0!==arguments[0]?arguments[0]:{},e=v(),n=e.once,r=e.passive,o=e.capture;return n||r||o?(n||delete t.once,r||delete t.passive,o||delete t.capture,t):Boolean(t.capture)}function h(t,e,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{capture:!1};if(!t||"function"!=typeof t.addEventListener)return function(){};var o=n,i=function(){!function(t,e,n){var r=arguments.length>3&&void 0!==arguments[3]?arguments[3]:{capture:!1};t&&"function"==typeof t.removeEventListener&&t.removeEventListener(e,n,b(r))}(t,e,o,r)};return r.once&&!v().once&&(o=function(e){i(),n.call(t,e)}),t.addEventListener(e,o,b(r)),i}function m(t,e,n,r){var i=arguments.length>4&&void 0!==arguments[4]?arguments[4]:{capture:!1},a=!0===i.once;delete i.once;var u=h(t,e,(function(t){var e=o(t.target,n);e&&(a&&u(),r.call(e,t,e))}),i);return u}function y(t){return i(u,arguments.length>0?t:document).filter(s).sort(d)}var A={selector:"[data-ctrly]",context:null,focusTarget:!0,closeOnBlur:!0,closeOnEsc:!0,closeOnOutsideClick:!0,closeOnScroll:!1,trapFocus:!1,allowMultiple:!1,on:null,autoInit:!0};function g(t){return"which"in t?t.which:t.keyCode}function E(t){return i('[aria-controls="'.concat(t.id,'"]'))}function w(t){return document.getElementById(t.getAttribute("aria-controls")||t.getAttribute("data-ctrly"))}function x(t){t.removeAttribute("aria-pressed"),t.removeAttribute("aria-controls"),t.removeAttribute("aria-expanded")}var L=0;return function(){var e,a,c,l,d=function(t){var e={};return[A,t].forEach((function(t){for(var n in t)Object.prototype.hasOwnProperty.call(t,n)&&(e[n]=t[n])})),e}(arguments.length>0&&void 0!==arguments[0]?arguments[0]:{}),f=d.selector,p=d.on||{},v={};function O(t,e){return("function"!=typeof p[e]||!1!==p[e](t))&&!1!==function(t,e){var n,r=arguments.length>2&&void 0!==arguments[2]?arguments[2]:{};if(!t||"function"!=typeof t.dispatchEvent)return!0;r.bubbles=r.bubbles||!1,r.cancelable=r.cancelable||!1,r.composed=r.composed||!1,r.detail=r.detail||null;try{n=new CustomEvent(e,r)}catch(t){(n=document.createEvent("CustomEvent")).initCustomEvent(e,r.bubbles,r.cancelable,r.detail)}return t.dispatchEvent(n)}(t,"ctrly:".concat(e),{bubbles:!0,cancelable:!0})}function C(e){var r=!(arguments.length>1&&void 0!==arguments[1])||arguments[1];if(!e)return!1;if(!e.hasAttribute("data-ctrly-opened"))return!1;if(!O(e,"close"))return!1;var o=t(),i=v[e.id]||{},a=i.lastActiveElement,u=i.destroy;return delete v[e.id],u&&u(),E(e).forEach((function(t){"button"!==t.tagName.toLowerCase()&&t.setAttribute("aria-pressed","false"),t.setAttribute("aria-expanded","false")})),e.removeAttribute("data-ctrly-opened"),e.setAttribute("aria-hidden","true"),e.removeAttribute("tabindex"),e.blur(),r&&a&&e.contains(o)&&n(a,{restoreScrollPosition:!0}),O(e,"closed"),e}function N(t){var e;i(f,(e=t,d.context?o(e,d.context):document)).forEach((function(e){var n=w(e);n&&n.id!==t.id&&C(n,!1)}))}function S(e,r){var i=[];if(d.closeOnBlur&&!d.trapFocus&&i.push(h(document,"focusin",(function(t){r.contains(t.target)||setTimeout((function(){C(r,!1)}),0)}),{capture:!0,passive:!0})),d.closeOnEsc&&i.push(h(document,"keydown",(function(t){27===g(t)&&C(r)&&t.preventDefault()}))),d.closeOnOutsideClick&&i.push(h(document,"click",(function(t){1!==g(t)||r.contains(t.target)||o(t.target,f)||C(r)}),{passive:!0})),d.closeOnScroll){var a=!1,u=function(){a=!0},c=function(){a=!1};i.push(h(r,"mouseenter",u,{passive:!0})),i.push(h(r,"mouseleave",c,{passive:!0})),i.push(h(r,"touchstart",u,{passive:!0})),i.push(h(r,"touchend",c,{passive:!0})),i.push(h(window,"scroll",(function(){a||C(r)}),{passive:!0}))}return d.trapFocus&&i.push(h(document,"keydown",(function(e){if(9===g(e)){var o=y(r);if(!o[0])return e.preventDefault(),void n(r);var i=t(),a=o[0],u=o[o.length-1];if(e.shiftKey&&i===a)return e.preventDefault(),void n(u);e.shiftKey||i!==u||(n(a),e.preventDefault())}}))),function(){for(;i.length;)i.shift().call()}}function k(e){var n=w(e);return n?!n.hasAttribute("data-ctrly-opened")&&(!!O(n,"open")&&(v[n.id]={lastActiveElement:t(),destroy:S(0,n)},E(n).forEach((function(t){"button"!==t.tagName.toLowerCase()&&t.setAttribute("aria-pressed","true"),t.setAttribute("aria-expanded","true")})),n.setAttribute("data-ctrly-opened",""),n.setAttribute("aria-hidden","false"),n.setAttribute("tabindex","-1"),O(n,"opened"),n)):(x(e),!1)}function D(t,e){var r=w(e);r?"true"!==e.getAttribute("aria-expanded")?(d.allowMultiple||N(r),k(e),r&&(t.preventDefault(),d.focusTarget&&n(y(r)[0]||r),r.scrollTop=0,r.scrollLeft=0)):C(r)&&t.preventDefault():C(function(t){for(var e=t;e;){if(e.id&&v[e.id])return e;e=e.parentElement}}(e))&&t.preventDefault()}function T(){e||(e=m(document,"click",f,(function(t,e){1===g(t)&&D(t,e)})),a=m(document,"keydown",f,(function(t,e){13!==g(t)&&32!==g(t)||D(t,e)}))),i(f).forEach((function(t){var e=w(t);if(e){var n;"button"!==t.tagName.toLowerCase()&&(t.hasAttribute("role")||t.setAttribute("role","button"),r(n=t,u)&&s(n)||t.setAttribute("tabindex","0")),t.setAttribute("aria-controls",e.id);var o=E(e).map((function(t){return t.id||t.setAttribute("id","ctrly-control-"+ ++L),t.id})),i=(e.getAttribute("aria-labelledby")||"").split(" ").concat(o).filter((function(t,e,n){return""!==t&&n.indexOf(t)===e}));e.setAttribute("aria-labelledby",i.join(" ")),"true"===t.getAttribute("aria-expanded")||t.hasAttribute("data-ctrly-open")?k(t):("button"!==t.tagName.toLowerCase()&&t.setAttribute("aria-pressed","false"),t.setAttribute("aria-expanded","false"),e.setAttribute("aria-hidden","true"),e.removeAttribute("tabindex"))}else x(t)}))}function j(t){for(var n in t&&e&&(e(),e=null,a(),a=null),i(f).forEach((function(e){t&&x(e);var n=w(e);n&&(C(n,!1),t&&n.removeAttribute("aria-hidden"))})),v)Object.prototype.hasOwnProperty.call(v,n)&&(v[n].destroy(),delete v[n])}return d.autoInit&&(c=T,"complete"!==(l=document.readyState)&&"interactive"!==l?document.addEventListener("DOMContentLoaded",(function(){c()}),b({capture:!0,once:!0,passive:!0})):setTimeout(c,0)),{closeAll:function(){j(!1)},destroy:function(){j(!0)},init:T}}}));