{"version":3,"file":"analytics-util-listener.cjs","sources":["../src/index.js"],"sourcesContent":["import { isBrowser, isString, isFunction, ensureArray, noOp } from '@analytics/type-utils'\n\nconst EVENT = 'Event'\nconst EL = EVENT + 'Listener'\n\nfunction createListener(add) {\n  return (els, evts, callback, options) => {\n    const handler = callback || noOp\n    const opts = options || false\n    /* SSR support */\n    if (!isBrowser) return handler\n    const events = toArray(evts)\n    const elements = toArray(els, true)\n    /* Throw if no element found */\n    if (!elements.length) throw new Error('noElements')\n    /* Throw if no events found */\n    if (!events.length) throw new Error('no' + EVENT)\n    let fns = []\n    function smartAttach(isAdd) {\n      if (isAdd) fns = []\n      const method = (isAdd) ? 'add' + EL : 'remove' + EL\n      // Apply to all elements\n      for (let i = 0; i < elements.length; i++) {\n        const el = elements[i]\n        fns[i] = (isAdd ? ((opts && opts.once) ? once(handler) : handler) : fns[i] || handler)\n        // Apply to all events\n        for (let n = 0; n < events.length; n++) {\n          if (!el[method]) {\n            el[method](events[n], fns[i], opts)\n            continue;\n          }\n          el['on' + events[n]] = (isAdd) ? fns[i] : null /* Fallback for older browsers IE <=8 */\n        }\n      }\n      // return opposite function with inverse event handler\n      return smartAttach.bind(null, !isAdd)\n    }\n    /* // debug\n    console.log('events', events)\n    console.log('elements', elements)\n    /** */\n    return smartAttach(add)\n  }\n}\n\nfunction strToArray(str) {\n  return str.split(str.indexOf(',') > -1 ? ',' : ' ').map(e => e.trim())\n}\n\nfunction toArray(val, isSelector) {\n  if (isString(val)) {\n    return isSelector ? toArray(document.querySelectorAll(val)) : strToArray(val)\n  }\n  // Convert NodeList to Array\n  if (NodeList.prototype.isPrototypeOf(val)) {\n    const nodes = []\n    for (var i = val.length >>> 0; i--;) {\n      nodes[i] = val[i] // iterate backwards ensuring that length is an UInt32\n    }\n    return nodes\n  }\n  // Arrayify\n  const array = ensureArray(val)\n  return (!isSelector) ? array : array.map((v) => isString(v) ? toArray(v, true) : v).flat()\n}\n\n/**\n * Run function once\n * @param {Function} fn - Function to run just once\n * @param {*} [context] - Extend function context\n * @returns {Function} Function that only runs 1 time\n */\nexport function once(fn, context) {\n  var result\n  return function() {\n    if (fn) {\n      result = fn.apply(context || this, arguments)\n      fn = null\n    }\n    return result\n  }\n}\n\n/**\n * Element selector or valid DOM node\n * @typedef {(string|Node|NodeList|EventTarget|null)} Selector\n */\n\n/**\n * Event or events to addEventListener to \n * @typedef {(string|string[])} EventType\n */\n\n/**\n * Cleanup event listener\n * @callback RemoveListener\n * @returns {AttachListener}\n */\n\n/**\n * Reattach event listener\n * @callback AttachListener\n * @returns {RemoveListener}\n */\n\n/**\n * Add an event listener\n * @callback AddListener\n * @param {Selector}  elements  - Element(s) to attach event(s) to.\n * @param {EventType} eventType - Event(s) to listen to \n * @param {Function}  [handler] - Function to fire\n * @param {Object}    [options] - Event listener options\n * @param {Boolean}   [options.once] - Trigger handler just once\n * @returns {RemoveListener}\n */\n\n/** @type {AddListener} */\nexport const addListener = createListener(EVENT)\n\n/**\n * Remove an event listener\n * @callback RemoveListener\n * @param {Selector}  elements  - Element(s) to remove event(s) from.\n * @param {EventType} eventType - Event(s) to remove\n * @param {Function}  [handler] - Function to remove\n * @param {Object}    [options] - Event listener options\n * @param {Boolean}   [options.once] - Trigger handler just once\n * @returns {AttachListener}\n */\n\n/** @type {RemoveListener} */\nexport const removeListener = createListener()\n\n\nfunction wrap(existing, newFunction, context = null) {\n  if (!isFunction(existing)) return newFunction\n  return function () {\n    existing.apply(context, arguments)\n    newFunction.apply(context, arguments)\n  }\n}\n\n// https://gist.github.com/DavidWells/18ff6633ce356237ef91c764812ee08a\nexport function addWindowEvent(event, fn) {\n  if (!isBrowser || !isFunction(window[event])) {\n    return window[event] = fn\n  }\n  return wrap(window[event], fn, window)\n}\n\nexport const onError = addWindowEvent.bind(null, 'onerror')\nexport const onLoad = addWindowEvent.bind(null, 'onload')"],"names":["EVENT","EL","createListener","add","els","evts","callback","options","handler","noOp","opts","isBrowser","events","toArray","elements","length","Error","fns","smartAttach","isAdd","method","i","el","once","n","bind","val","isSelector","isString","document","querySelectorAll","str","split","indexOf","map","e","trim","NodeList","prototype","isPrototypeOf","nodes","array","ensureArray","v","flat","fn","context","result","apply","this","arguments","addListener","removeListener","addWindowEvent","event","isFunction","window","existing","newFunction","onError","onLoad"],"mappings":"uCAEMA,EAAQ,QACRC,EAAKD,EAAQ,WAEnB,SAASE,EAAeC,GACtB,OAAO,SAACC,EAAKC,EAAMC,EAAUC,GAC3B,IAAMC,EAAUF,GAAYG,EAAAA,KACtBC,EAAOH,IAAW,EAExB,IAAKI,EAAAA,UAAW,OAAOH,EACvB,IAAMI,EAASC,EAAQR,GACjBS,EAAWD,EAAQT,GAAK,GAE9B,IAAKU,EAASC,OAAQ,UAAUC,MAAM,cAEtC,IAAKJ,EAAOG,OAAQ,MAAM,IAAIC,MAAM,KAAOhB,GAC3C,IAAIiB,EAAM,GAwBV,OAvBA,SAASC,EAAYC,GACfA,IAAOF,EAAM,IAGjB,IAFA,IAAMG,EAAUD,EAAS,MAAQlB,EAAK,SAAWA,EAExCoB,EAAI,EAAGA,EAAIP,EAASC,OAAQM,IAAK,CACxC,IAAMC,EAAKR,EAASO,GACpBJ,EAAII,GAAMF,EAAUT,GAAQA,EAAKa,KAAQA,EAAKf,GAAWA,EAAWS,EAAII,IAAMb,EAE9E,IAAK,IAAIgB,EAAI,EAAGA,EAAIZ,EAAOG,OAAQS,IAC5BF,EAAGF,GAIRE,EAAG,KAAOV,EAAOY,IAAOL,EAASF,EAAII,GAAK,KAHxCC,EAAGF,GAAQR,EAAOY,GAAIP,EAAII,GAAIX,EAKpC,CAEA,OAAOQ,EAAYO,KAAK,MAAON,EACjC,CAKOD,CAAYf,EACrB,CACF,CAMA,SAASU,EAAQa,EAAKC,GACpB,GAAIC,EAAQA,SAACF,GACX,OAAOC,EAAad,EAAQgB,SAASC,iBAAiBJ,KANtCK,EAMyDL,GALhEM,MAAMD,EAAIE,QAAQ,MAAQ,EAAI,IAAM,KAAKC,IAAI,SAAAC,GAAK,OAAAA,EAAEC,MAAM,GADvE,IAAoBL,EASlB,GAAIM,SAASC,UAAUC,cAAcb,GAAM,CAEzC,IADA,IAAMc,EAAQ,GACLnB,EAAIK,EAAIX,SAAW,EAAGM,KAC7BmB,EAAMnB,GAAKK,EAAIL,GAEjB,OAAOmB,CACT,CAEA,IAAMC,EAAQC,EAAWA,YAAChB,GAC1B,OAASC,EAAsBc,EAAMP,IAAI,SAACS,GAAC,OAAKf,EAAAA,SAASe,GAAK9B,EAAQ8B,GAAG,GAAQA,CAAC,GAAEC,OAA7DH,CACzB,CAQO,SAASlB,EAAKsB,EAAIC,GACvB,IAAIC,EACJ,OAAkB,WAKhB,OAJIF,IACFE,EAASF,EAAGG,MAAMF,GAAWG,KAAMC,WACnCL,EAAK,MAEAE,CACT,CACF,CAoCa,IAAAI,EAAcjD,EAAeF,GAc7BoD,EAAiBlD,aAYdmD,EAAeC,EAAOT,GACpC,OAAKlC,EAAAA,WAAc4C,EAAUA,WAACC,OAAOF,KAVzBG,EAaAD,OAAOF,GAbGI,EAaKb,OAbQC,KAAAA,EAaJU,UAbIV,EAAU,MACxCS,EAAUA,WAACE,GACG,WACjBA,EAAST,MAAMF,EAASI,WACxBQ,EAAYV,MAAMF,EAASI,UAC7B,EAJkCQ,GAUzBF,OAAOF,GAAST,EAX3B,IAAcY,EAAUC,EAAaZ,CAcrC,CAEa,IAAAa,EAAUN,EAAe5B,KAAK,KAAM,WACpCmC,EAASP,EAAe5B,KAAK,KAAM"}