<?xml version='1.0' encoding='UTF-8'?>
<?xml-stylesheet href="/static/style.xsl" type="text/xsl"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
  <id>https://vulnerability.circl.lu/sightings/feed</id>
  <title>Most recent sightings.</title>
  <updated>2026-09-05T20:22:09.611632+00:00</updated>
  <author>
    <name>Vulnerability-Lookup</name>
    <email>info@circl.lu</email>
  </author>
  <link href="https://vulnerability.circl.lu" rel="alternate"/>
  <generator uri="https://lkiesow.github.io/python-feedgen" version="1.0.0">python-feedgen</generator>
  <subtitle>Contains only the most 10 recent sightings.</subtitle>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/f916a65a-6d0f-4bc2-9e53-7fe42a1f0ce5/export</id>
    <title>f916a65a-6d0f-4bc2-9e53-7fe42a1f0ce5</title>
    <updated>2026-09-05T20:22:09.622567+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://vulnerability.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "f916a65a-6d0f-4bc2-9e53-7fe42a1f0ce5", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "GHSA-gxr4-xjj5-5px2", "type": "seen", "source": "https://gist.github.com/Garneauma/78045432fb49de029a628e2c83df5c33", "content": "/*!\n * Web Experience Toolkit (WET) / Bo\u00eete \u00e0 outils de l'exp\u00e9rience Web (BOEW)\n * wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * v4.0.97 - 2026-09-02\n *\n */\n\n/*! Modernizr (Custom Build) | MIT &amp;amp; BSD */\n/*! @license DOMPurify 3.4.2 | (c) Cure53 and other contributors | Released under the Apache license 2.0 and Mozilla Public License 2.0 | github.com/cure53/DOMPurify/blob/3.4.2/LICENSE */\n\n(function (global, factory) {\n    typeof exports === 'object' &amp;amp;&amp;amp; typeof module !== 'undefined' ? module.exports = factory() :\n    typeof define === 'function' &amp;amp;&amp;amp; define.amd ? define(factory) :\n    (global = typeof globalThis !== 'undefined' ? globalThis : global || self, global.DOMPurify = factory());\n})(this, (function () { 'use strict';\n\n    const {\n      entries,\n      setPrototypeOf,\n      isFrozen,\n      getPrototypeOf,\n      getOwnPropertyDescriptor\n    } = Object;\n    let {\n      freeze,\n      seal,\n      create\n    } = Object; // eslint-disable-line import/no-mutable-exports\n    let {\n      apply,\n      construct\n    } = typeof Reflect !== 'undefined' &amp;amp;&amp;amp; Reflect;\n    if (!freeze) {\n      freeze = function freeze(x) {\n        return x;\n      };\n    }\n    if (!seal) {\n      seal = function seal(x) {\n        return x;\n      };\n    }\n    if (!apply) {\n      apply = function apply(func, thisArg) {\n        for (var _len = arguments.length, args = new Array(_len &amp;gt; 2 ? _len - 2 : 0), _key = 2; _key &amp;lt; _len; _key++) {\n          args[_key - 2] = arguments[_key];\n        }\n        return func.apply(thisArg, args);\n      };\n    }\n    if (!construct) {\n      construct = function construct(Func) {\n        for (var _len2 = arguments.length, args = new Array(_len2 &amp;gt; 1 ? _len2 - 1 : 0), _key2 = 1; _key2 &amp;lt; _len2; _key2++) {\n          args[_key2 - 1] = arguments[_key2];\n        }\n        return new Func(...args);\n      };\n    }\n    const arrayForEach = unapply(Array.prototype.forEach);\n    const arrayLastIndexOf = unapply(Array.prototype.lastIndexOf);\n    const arrayPop = unapply(Array.prototype.pop);\n    const arrayPush = unapply(Array.prototype.push);\n    const arraySplice = unapply(Array.prototype.splice);\n    const arrayIsArray = Array.isArray;\n    const stringToLowerCase = unapply(String.prototype.toLowerCase);\n    const stringToString = unapply(String.prototype.toString);\n    const stringMatch = unapply(String.prototype.match);\n    const stringReplace = unapply(String.prototype.replace);\n    const stringIndexOf = unapply(String.prototype.indexOf);\n    const stringTrim = unapply(String.prototype.trim);\n    const numberToString = unapply(Number.prototype.toString);\n    const booleanToString = unapply(Boolean.prototype.toString);\n    const bigintToString = typeof BigInt === 'undefined' ? null : unapply(BigInt.prototype.toString);\n    const symbolToString = typeof Symbol === 'undefined' ? null : unapply(Symbol.prototype.toString);\n    const objectHasOwnProperty = unapply(Object.prototype.hasOwnProperty);\n    const objectToString = unapply(Object.prototype.toString);\n    const regExpTest = unapply(RegExp.prototype.test);\n    const typeErrorCreate = unconstruct(TypeError);\n    /**\n     * Creates a new function that calls the given function with a specified thisArg and arguments.\n     *\n     * @param func - The function to be wrapped and called.\n     * @returns A new function that calls the given function with a specified thisArg and arguments.\n     */\n    function unapply(func) {\n      return function (thisArg) {\n        if (thisArg instanceof RegExp) {\n          thisArg.lastIndex = 0;\n        }\n        for (var _len3 = arguments.length, args = new Array(_len3 &amp;gt; 1 ? _len3 - 1 : 0), _key3 = 1; _key3 &amp;lt; _len3; _key3++) {\n          args[_key3 - 1] = arguments[_key3];\n        }\n        return apply(func, thisArg, args);\n      };\n    }\n    /**\n     * Creates a new function that constructs an instance of the given constructor function with the provided arguments.\n     *\n     * @param func - The constructor function to be wrapped and called.\n     * @returns A new function that constructs an instance of the given constructor function with the provided arguments.\n     */\n    function unconstruct(Func) {\n      return function () {\n        for (var _len4 = arguments.length, args = new Array(_len4), _key4 = 0; _key4 &amp;lt; _len4; _key4++) {\n          args[_key4] = arguments[_key4];\n        }\n        return construct(Func, args);\n      };\n    }\n    /**\n     * Add properties to a lookup table\n     *\n     * @param set - The set to which elements will be added.\n     * @param array - The array containing elements to be added to the set.\n     * @param transformCaseFunc - An optional function to transform the case of each element before adding to the set.\n     * @returns The modified set with added elements.\n     */\n    function addToSet(set, array) {\n      let transformCaseFunc = arguments.length &amp;gt; 2 &amp;amp;&amp;amp; arguments[2] !== undefined ? arguments[2] : stringToLowerCase;\n      if (setPrototypeOf) {\n        // Make 'in' and truthy checks like Boolean(set.constructor)\n        // independent of any properties defined on Object.prototype.\n        // Prevent prototype setters from intercepting set as a this value.\n        setPrototypeOf(set, null);\n      }\n      if (!arrayIsArray(array)) {\n        return set;\n      }\n      let l = array.length;\n      while (l--) {\n        let element = array[l];\n        if (typeof element === 'string') {\n          const lcElement = transformCaseFunc(element);\n          if (lcElement !== element) {\n            // Config presets (e.g. tags.js, attrs.js) are immutable.\n            if (!isFrozen(array)) {\n              array[l] = lcElement;\n            }\n            element = lcElement;\n          }\n        }\n        set[element] = true;\n      }\n      return set;\n    }\n    /**\n     * Clean up an array to harden against CSPP\n     *\n     * @param array - The array to be cleaned.\n     * @returns The cleaned version of the array\n     */\n    function cleanArray(array) {\n      for (let index = 0; index &amp;lt; array.length; index++) {\n        const isPropertyExist = objectHasOwnProperty(array, index);\n        if (!isPropertyExist) {\n          array[index] = null;\n        }\n      }\n      return array;\n    }\n    /**\n     * Shallow clone an object\n     *\n     * @param object - The object to be cloned.\n     * @returns A new object that copies the original.\n     */\n    function clone(object) {\n      const newObject = create(null);\n      for (const [property, value] of entries(object)) {\n        const isPropertyExist = objectHasOwnProperty(object, property);\n        if (isPropertyExist) {\n          if (arrayIsArray(value)) {\n            newObject[property] = cleanArray(value);\n          } else if (value &amp;amp;&amp;amp; typeof value === 'object' &amp;amp;&amp;amp; value.constructor === Object) {\n            newObject[property] = clone(value);\n          } else {\n            newObject[property] = value;\n          }\n        }\n      }\n      return newObject;\n    }\n    /**\n     * Convert non-node values into strings without depending on direct property access.\n     *\n     * @param value - The value to stringify.\n     * @returns A string representation of the provided value.\n     */\n    function stringifyValue(value) {\n      switch (typeof value) {\n        case 'string':\n          {\n            return value;\n          }\n        case 'number':\n          {\n            return numberToString(value);\n          }\n        case 'boolean':\n          {\n            return booleanToString(value);\n          }\n        case 'bigint':\n          {\n            return bigintToString ? bigintToString(value) : '0';\n          }\n        case 'symbol':\n          {\n            return symbolToString ? symbolToString(value) : 'Symbol()';\n          }\n        case 'undefined':\n          {\n            return objectToString(value);\n          }\n        case 'function':\n        case 'object':\n          {\n            if (value === null) {\n              return objectToString(value);\n            }\n            const valueAsRecord = value;\n            const valueToString = lookupGetter(valueAsRecord, 'toString');\n            if (typeof valueToString === 'function') {\n              const stringified = valueToString(valueAsRecord);\n              return typeof stringified === 'string' ? stringified : objectToString(stringified);\n            }\n            return objectToString(value);\n          }\n        default:\n          {\n            return objectToString(value);\n          }\n      }\n    }\n    /**\n     * This method automatically checks if the prop is function or getter and behaves accordingly.\n     *\n     * @param object - The object to look up the getter function in its prototype chain.\n     * @param prop - The property name for which to find the getter function.\n     * @returns The getter function found in the prototype chain or a fallback function.\n     */\n    function lookupGetter(object, prop) {\n      while (object !== null) {\n        const desc = getOwnPropertyDescriptor(object, prop);\n        if (desc) {\n          if (desc.get) {\n            return unapply(desc.get);\n          }\n          if (typeof desc.value === 'function') {\n            return unapply(desc.value);\n          }\n        }\n        object = getPrototypeOf(object);\n      }\n      function fallbackValue() {\n        return null;\n      }\n      return fallbackValue;\n    }\n    function isRegex(value) {\n      try {\n        regExpTest(value, '');\n        return true;\n      } catch (_unused) {\n        return false;\n      }\n    }\n\n    const html$1 = freeze(['a', 'abbr', 'acronym', 'address', 'area', 'article', 'aside', 'audio', 'b', 'bdi', 'bdo', 'big', 'blink', 'blockquote', 'body', 'br', 'button', 'canvas', 'caption', 'center', 'cite', 'code', 'col', 'colgroup', 'content', 'data', 'datalist', 'dd', 'decorator', 'del', 'details', 'dfn', 'dialog', 'dir', 'div', 'dl', 'dt', 'element', 'em', 'fieldset', 'figcaption', 'figure', 'font', 'footer', 'form', 'h1', 'h2', 'h3', 'h4', 'h5', 'h6', 'head', 'header', 'hgroup', 'hr', 'html', 'i', 'img', 'input', 'ins', 'kbd', 'label', 'legend', 'li', 'main', 'map', 'mark', 'marquee', 'menu', 'menuitem', 'meter', 'nav', 'nobr', 'ol', 'optgroup', 'option', 'output', 'p', 'picture', 'pre', 'progress', 'q', 'rp', 'rt', 'ruby', 's', 'samp', 'search', 'section', 'select', 'shadow', 'slot', 'small', 'source', 'spacer', 'span', 'strike', 'strong', 'style', 'sub', 'summary', 'sup', 'table', 'tbody', 'td', 'template', 'textarea', 'tfoot', 'th', 'thead', 'time', 'tr', 'track', 'tt', 'u', 'ul', 'var', 'video', 'wbr']);\n    const svg$1 = freeze(['svg', 'a', 'altglyph', 'altglyphdef', 'altglyphitem', 'animatecolor', 'animatemotion', 'animatetransform', 'circle', 'clippath', 'defs', 'desc', 'ellipse', 'enterkeyhint', 'exportparts', 'filter', 'font', 'g', 'glyph', 'glyphref', 'hkern', 'image', 'inputmode', 'line', 'lineargradient', 'marker', 'mask', 'metadata', 'mpath', 'part', 'path', 'pattern', 'polygon', 'polyline', 'radialgradient', 'rect', 'stop', 'style', 'switch', 'symbol', 'text', 'textpath', 'title', 'tref', 'tspan', 'view', 'vkern']);\n    const svgFilters = freeze(['feBlend', 'feColorMatrix', 'feComponentTransfer', 'feComposite', 'feConvolveMatrix', 'feDiffuseLighting', 'feDisplacementMap', 'feDistantLight', 'feDropShadow', 'feFlood', 'feFuncA', 'feFuncB', 'feFuncG', 'feFuncR', 'feGaussianBlur', 'feImage', 'feMerge', 'feMergeNode', 'feMorphology', 'feOffset', 'fePointLight', 'feSpecularLighting', 'feSpotLight', 'feTile', 'feTurbulence']);\n    // List of SVG elements that are disallowed by default.\n    // We still need to know them so that we can do namespace\n    // checks properly in case one wants to add them to\n    // allow-list.\n    const svgDisallowed = freeze(['animate', 'color-profile', 'cursor', 'discard', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'foreignobject', 'hatch', 'hatchpath', 'mesh', 'meshgradient', 'meshpatch', 'meshrow', 'missing-glyph', 'script', 'set', 'solidcolor', 'unknown', 'use']);\n    const mathMl$1 = freeze(['math', 'menclose', 'merror', 'mfenced', 'mfrac', 'mglyph', 'mi', 'mlabeledtr', 'mmultiscripts', 'mn', 'mo', 'mover', 'mpadded', 'mphantom', 'mroot', 'mrow', 'ms', 'mspace', 'msqrt', 'mstyle', 'msub', 'msup', 'msubsup', 'mtable', 'mtd', 'mtext', 'mtr', 'munder', 'munderover', 'mprescripts']);\n    // Similarly to SVG, we want to know all MathML elements,\n    // even those that we disallow by default.\n    const mathMlDisallowed = freeze(['maction', 'maligngroup', 'malignmark', 'mlongdiv', 'mscarries', 'mscarry', 'msgroup', 'mstack', 'msline', 'msrow', 'semantics', 'annotation', 'annotation-xml', 'mprescripts', 'none']);\n    const text = freeze(['#text']);\n\n    const html = freeze(['accept', 'action', 'align', 'alt', 'autocapitalize', 'autocomplete', 'autopictureinpicture', 'autoplay', 'background', 'bgcolor', 'border', 'capture', 'cellpadding', 'cellspacing', 'checked', 'cite', 'class', 'clear', 'color', 'cols', 'colspan', 'controls', 'controlslist', 'coords', 'crossorigin', 'datetime', 'decoding', 'default', 'dir', 'disabled', 'disablepictureinpicture', 'disableremoteplayback', 'download', 'draggable', 'enctype', 'enterkeyhint', 'exportparts', 'face', 'for', 'headers', 'height', 'hidden', 'high', 'href', 'hreflang', 'id', 'inert', 'inputmode', 'integrity', 'ismap', 'kind', 'label', 'lang', 'list', 'loading', 'loop', 'low', 'max', 'maxlength', 'media', 'method', 'min', 'minlength', 'multiple', 'muted', 'name', 'nonce', 'noshade', 'novalidate', 'nowrap', 'open', 'optimum', 'part', 'pattern', 'placeholder', 'playsinline', 'popover', 'popovertarget', 'popovertargetaction', 'poster', 'preload', 'pubdate', 'radiogroup', 'readonly', 'rel', 'required', 'rev', 'reversed', 'role', 'rows', 'rowspan', 'spellcheck', 'scope', 'selected', 'shape', 'size', 'sizes', 'slot', 'span', 'srclang', 'start', 'src', 'srcset', 'step', 'style', 'summary', 'tabindex', 'title', 'translate', 'type', 'usemap', 'valign', 'value', 'width', 'wrap', 'xmlns']);\n    const svg = freeze(['accent-height', 'accumulate', 'additive', 'alignment-baseline', 'amplitude', 'ascent', 'attributename', 'attributetype', 'azimuth', 'basefrequency', 'baseline-shift', 'begin', 'bias', 'by', 'class', 'clip', 'clippathunits', 'clip-path', 'clip-rule', 'color', 'color-interpolation', 'color-interpolation-filters', 'color-profile', 'color-rendering', 'cx', 'cy', 'd', 'dx', 'dy', 'diffuseconstant', 'direction', 'display', 'divisor', 'dur', 'edgemode', 'elevation', 'end', 'exponent', 'fill', 'fill-opacity', 'fill-rule', 'filter', 'filterunits', 'flood-color', 'flood-opacity', 'font-family', 'font-size', 'font-size-adjust', 'font-stretch', 'font-style', 'font-variant', 'font-weight', 'fx', 'fy', 'g1', 'g2', 'glyph-name', 'glyphref', 'gradientunits', 'gradienttransform', 'height', 'href', 'id', 'image-rendering', 'in', 'in2', 'intercept', 'k', 'k1', 'k2', 'k3', 'k4', 'kerning', 'keypoints', 'keysplines', 'keytimes', 'lang', 'lengthadjust', 'letter-spacing', 'kernelmatrix', 'kernelunitlength', 'lighting-color', 'local', 'marker-end', 'marker-mid', 'marker-start', 'markerheight', 'markerunits', 'markerwidth', 'maskcontentunits', 'maskunits', 'max', 'mask', 'mask-type', 'media', 'method', 'mode', 'min', 'name', 'numoctaves', 'offset', 'operator', 'opacity', 'order', 'orient', 'orientation', 'origin', 'overflow', 'paint-order', 'path', 'pathlength', 'patterncontentunits', 'patterntransform', 'patternunits', 'points', 'preservealpha', 'preserveaspectratio', 'primitiveunits', 'r', 'rx', 'ry', 'radius', 'refx', 'refy', 'repeatcount', 'repeatdur', 'restart', 'result', 'rotate', 'scale', 'seed', 'shape-rendering', 'slope', 'specularconstant', 'specularexponent', 'spreadmethod', 'startoffset', 'stddeviation', 'stitchtiles', 'stop-color', 'stop-opacity', 'stroke-dasharray', 'stroke-dashoffset', 'stroke-linecap', 'stroke-linejoin', 'stroke-miterlimit', 'stroke-opacity', 'stroke', 'stroke-width', 'style', 'surfacescale', 'systemlanguage', 'tabindex', 'tablevalues', 'targetx', 'targety', 'transform', 'transform-origin', 'text-anchor', 'text-decoration', 'text-rendering', 'textlength', 'type', 'u1', 'u2', 'unicode', 'values', 'viewbox', 'visibility', 'version', 'vert-adv-y', 'vert-origin-x', 'vert-origin-y', 'width', 'word-spacing', 'wrap', 'writing-mode', 'xchannelselector', 'ychannelselector', 'x', 'x1', 'x2', 'xmlns', 'y', 'y1', 'y2', 'z', 'zoomandpan']);\n    const mathMl = freeze(['accent', 'accentunder', 'align', 'bevelled', 'close', 'columnalign', 'columnlines', 'columnspacing', 'columnspan', 'denomalign', 'depth', 'dir', 'display', 'displaystyle', 'encoding', 'fence', 'frame', 'height', 'href', 'id', 'largeop', 'length', 'linethickness', 'lquote', 'lspace', 'mathbackground', 'mathcolor', 'mathsize', 'mathvariant', 'maxsize', 'minsize', 'movablelimits', 'notation', 'numalign', 'open', 'rowalign', 'rowlines', 'rowspacing', 'rowspan', 'rspace', 'rquote', 'scriptlevel', 'scriptminsize', 'scriptsizemultiplier', 'selection', 'separator', 'separators', 'stretchy', 'subscriptshift', 'supscriptshift', 'symmetric', 'voffset', 'width', 'xmlns']);\n    const xml = freeze(['xlink:href', 'xml:id', 'xlink:title', 'xml:space', 'xmlns:xlink']);\n\n    // eslint-disable-next-line unicorn/better-regex\n    const MUSTACHE_EXPR = seal(/\\{\\{[\\w\\W]*|[\\w\\W]*\\}\\}/gm); // Specify template detection regex for SAFE_FOR_TEMPLATES mode\n    const ERB_EXPR = seal(/&amp;lt;%[\\w\\W]*|[\\w\\W]*%&amp;gt;/gm);\n    const TMPLIT_EXPR = seal(/\\$\\{[\\w\\W]*/gm); // eslint-disable-line unicorn/better-regex\n    const DATA_ATTR = seal(/^data-[\\-\\w.\\u00B7-\\uFFFF]+$/); // eslint-disable-line no-useless-escape\n    const ARIA_ATTR = seal(/^aria-[\\-\\w]+$/); // eslint-disable-line no-useless-escape\n    const IS_ALLOWED_URI = seal(/^(?:(?:(?:f|ht)tps?|mailto|tel|callto|sms|cid|xmpp|matrix):|[^a-z]|[a-z+.\\-]+(?:[^a-z+.\\-:]|$))/i // eslint-disable-line no-useless-escape\n    );\n    const IS_SCRIPT_OR_DATA = seal(/^(?:\\w+script|data):/i);\n    const ATTR_WHITESPACE = seal(/[\\u0000-\\u0020\\u00A0\\u1680\\u180E\\u2000-\\u2029\\u205F\\u3000]/g // eslint-disable-line no-control-regex\n    );\n    const DOCTYPE_NAME = seal(/^html$/i);\n    const CUSTOM_ELEMENT = seal(/^[a-z][.\\w]*(-[.\\w]+)+$/i);\n\n    var EXPRESSIONS = /*#__PURE__*/Object.freeze({\n        __proto__: null,\n        ARIA_ATTR: ARIA_ATTR,\n        ATTR_WHITESPACE: ATTR_WHITESPACE,\n        CUSTOM_ELEMENT: CUSTOM_ELEMENT,\n        DATA_ATTR: DATA_ATTR,\n        DOCTYPE_NAME: DOCTYPE_NAME,\n        ERB_EXPR: ERB_EXPR,\n        IS_ALLOWED_URI: IS_ALLOWED_URI,\n        IS_SCRIPT_OR_DATA: IS_SCRIPT_OR_DATA,\n        MUSTACHE_EXPR: MUSTACHE_EXPR,\n        TMPLIT_EXPR: TMPLIT_EXPR\n    });\n\n    /* eslint-disable @typescript-eslint/indent */\n    // https://developer.mozilla.org/en-US/docs/Web/API/Node/nodeType\n    const NODE_TYPE = {\n      element: 1,\n      text: 3,\n      // Deprecated\n      progressingInstruction: 7,\n      comment: 8,\n      document: 9};\n    const getGlobal = function getGlobal() {\n      return typeof window === 'undefined' ? null : window;\n    };\n    /**\n     * Creates a no-op policy for internal use only.\n     * Don't export this function outside this module!\n     * @param trustedTypes The policy factory.\n     * @param purifyHostElement The Script element used to load DOMPurify (to determine policy name suffix).\n     * @return The policy created (or null, if Trusted Types\n     * are not supported or creating the policy failed).\n     */\n    const _createTrustedTypesPolicy = function _createTrustedTypesPolicy(trustedTypes, purifyHostElement) {\n      if (typeof trustedTypes !== 'object' || typeof trustedTypes.createPolicy !== 'function') {\n        return null;\n      }\n      // Allow the callers to control the unique policy name\n      // by adding a data-tt-policy-suffix to the script element with the DOMPurify.\n      // Policy creation with duplicate names throws in Trusted Types.\n      let suffix = null;\n      const ATTR_NAME = 'data-tt-policy-suffix';\n      if (purifyHostElement &amp;amp;&amp;amp; purifyHostElement.hasAttribute(ATTR_NAME)) {\n        suffix = purifyHostElement.getAttribute(ATTR_NAME);\n      }\n      const policyName = 'dompurify' + (suffix ? '#' + suffix : '');\n      try {\n        return trustedTypes.createPolicy(policyName, {\n          createHTML(html) {\n            return html;\n          },\n          createScriptURL(scriptUrl) {\n            return scriptUrl;\n          }\n        });\n      } catch (_) {\n        // Policy creation failed (most likely another DOMPurify script has\n        // already run). Skip creating the policy, as this will only cause errors\n        // if TT are enforced.\n        console.warn('TrustedTypes policy ' + policyName + ' could not be created.');\n        return null;\n      }\n    };\n    const _createHooksMap = function _createHooksMap() {\n      return {\n        afterSanitizeAttributes: [],\n        afterSanitizeElements: [],\n        afterSanitizeShadowDOM: [],\n        beforeSanitizeAttributes: [],\n        beforeSanitizeElements: [],\n        beforeSanitizeShadowDOM: [],\n        uponSanitizeAttribute: [],\n        uponSanitizeElement: [],\n        uponSanitizeShadowNode: []\n      };\n    };\n    function createDOMPurify() {\n      let window = arguments.length &amp;gt; 0 &amp;amp;&amp;amp; arguments[0] !== undefined ? arguments[0] : getGlobal();\n      const DOMPurify = root =&amp;gt; createDOMPurify(root);\n      DOMPurify.version = '3.4.2';\n      DOMPurify.removed = [];\n      if (!window || !window.document || window.document.nodeType !== NODE_TYPE.document || !window.Element) {\n        // Not running in a browser, provide a factory function\n        // so that you can pass your own Window\n        DOMPurify.isSupported = false;\n        return DOMPurify;\n      }\n      let {\n        document\n      } = window;\n      const originalDocument = document;\n      const currentScript = originalDocument.currentScript;\n      const {\n        DocumentFragment,\n        HTMLTemplateElement,\n        Node,\n        Element,\n        NodeFilter,\n        NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap,\n        HTMLFormElement,\n        DOMParser,\n        trustedTypes\n      } = window;\n      const ElementPrototype = Element.prototype;\n      const cloneNode = lookupGetter(ElementPrototype, 'cloneNode');\n      const remove = lookupGetter(ElementPrototype, 'remove');\n      const getNextSibling = lookupGetter(ElementPrototype, 'nextSibling');\n      const getChildNodes = lookupGetter(ElementPrototype, 'childNodes');\n      const getParentNode = lookupGetter(ElementPrototype, 'parentNode');\n      // As per issue #47, the web-components registry is inherited by a\n      // new document created via createHTMLDocument. As per the spec\n      // (http://w3c.github.io/webcomponents/spec/custom/#creating-and-passing-registries)\n      // a new empty registry is used when creating a template contents owner\n      // document, so we use that as our parent document to ensure nothing\n      // is inherited.\n      if (typeof HTMLTemplateElement === 'function') {\n        const template = document.createElement('template');\n        if (template.content &amp;amp;&amp;amp; template.content.ownerDocument) {\n          document = template.content.ownerDocument;\n        }\n      }\n      let trustedTypesPolicy;\n      let emptyHTML = '';\n      const {\n        implementation,\n        createNodeIterator,\n        createDocumentFragment,\n        getElementsByTagName\n      } = document;\n      const {\n        importNode\n      } = originalDocument;\n      let hooks = _createHooksMap();\n      /**\n       * Expose whether this browser supports running the full DOMPurify.\n       */\n      DOMPurify.isSupported = typeof entries === 'function' &amp;amp;&amp;amp; typeof getParentNode === 'function' &amp;amp;&amp;amp; implementation &amp;amp;&amp;amp; implementation.createHTMLDocument !== undefined;\n      const {\n        MUSTACHE_EXPR,\n        ERB_EXPR,\n        TMPLIT_EXPR,\n        DATA_ATTR,\n        ARIA_ATTR,\n        IS_SCRIPT_OR_DATA,\n        ATTR_WHITESPACE,\n        CUSTOM_ELEMENT\n      } = EXPRESSIONS;\n      let {\n        IS_ALLOWED_URI: IS_ALLOWED_URI$1\n      } = EXPRESSIONS;\n      /**\n       * We consider the elements and attributes below to be safe. Ideally\n       * don't add any new ones but feel free to remove unwanted ones.\n       */\n      /* allowed element names */\n      let ALLOWED_TAGS = null;\n      const DEFAULT_ALLOWED_TAGS = addToSet({}, [...html$1, ...svg$1, ...svgFilters, ...mathMl$1, ...text]);\n      /* Allowed attribute names */\n      let ALLOWED_ATTR = null;\n      const DEFAULT_ALLOWED_ATTR = addToSet({}, [...html, ...svg, ...mathMl, ...xml]);\n      /*\n       * Configure how DOMPurify should handle custom elements and their attributes as well as customized built-in elements.\n       * @property {RegExp|Function|null} tagNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any custom elements)\n       * @property {RegExp|Function|null} attributeNameCheck one of [null, regexPattern, predicate]. Default: `null` (disallow any attributes not on the allow list)\n       * @property {boolean} allowCustomizedBuiltInElements allow custom elements derived from built-ins if they pass CUSTOM_ELEMENT_HANDLING.tagNameCheck. Default: `false`.\n       */\n      let CUSTOM_ELEMENT_HANDLING = Object.seal(create(null, {\n        tagNameCheck: {\n          writable: true,\n          configurable: false,\n          enumerable: true,\n          value: null\n        },\n        attributeNameCheck: {\n          writable: true,\n          configurable: false,\n          enumerable: true,\n          value: null\n        },\n        allowCustomizedBuiltInElements: {\n          writable: true,\n          configurable: false,\n          enumerable: true,\n          value: false\n        }\n      }));\n      /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n      let FORBID_TAGS = null;\n      /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n      let FORBID_ATTR = null;\n      /* Config object to store ADD_TAGS/ADD_ATTR functions (when used as functions) */\n      const EXTRA_ELEMENT_HANDLING = Object.seal(create(null, {\n        tagCheck: {\n          writable: true,\n          configurable: false,\n          enumerable: true,\n          value: null\n        },\n        attributeCheck: {\n          writable: true,\n          configurable: false,\n          enumerable: true,\n          value: null\n        }\n      }));\n      /* Decide if ARIA attributes are okay */\n      let ALLOW_ARIA_ATTR = true;\n      /* Decide if custom data attributes are okay */\n      let ALLOW_DATA_ATTR = true;\n      /* Decide if unknown protocols are okay */\n      let ALLOW_UNKNOWN_PROTOCOLS = false;\n      /* Decide if self-closing tags in attributes are allowed.\n       * Usually removed due to a mXSS issue in jQuery 3.0 */\n      let ALLOW_SELF_CLOSE_IN_ATTR = true;\n      /* Output should be safe for common template engines.\n       * This means, DOMPurify removes data attributes, mustaches and ERB\n       */\n      let SAFE_FOR_TEMPLATES = false;\n      /* Output should be safe even for XML used within HTML and alike.\n       * This means, DOMPurify removes comments when containing risky content.\n       */\n      let SAFE_FOR_XML = true;\n      /* Decide if document with ... should be returned */\n      let WHOLE_DOCUMENT = false;\n      /* Track whether config is already set on this instance of DOMPurify. */\n      let SET_CONFIG = false;\n      /* Decide if all elements (e.g. style, script) must be children of\n       * document.body. By default, browsers might move them to document.head */\n      let FORCE_BODY = false;\n      /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html\n       * string (or a TrustedHTML object if Trusted Types are supported).\n       * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n       */\n      let RETURN_DOM = false;\n      /* Decide if a DOM `DocumentFragment` should be returned, instead of a html\n       * string  (or a TrustedHTML object if Trusted Types are supported) */\n      let RETURN_DOM_FRAGMENT = false;\n      /* Try to return a Trusted Type object instead of a string, return a string in\n       * case Trusted Types are not supported  */\n      let RETURN_TRUSTED_TYPE = false;\n      /* Output should be free from DOM clobbering attacks?\n       * This sanitizes markups named with colliding, clobberable built-in DOM APIs.\n       */\n      let SANITIZE_DOM = true;\n      /* Achieve full DOM Clobbering protection by isolating the namespace of named\n       * properties and JS variables, mitigating attacks that abuse the HTML/DOM spec rules.\n       *\n       * HTML/DOM spec rules that enable DOM Clobbering:\n       *   - Named Access on Window (\u00a77.3.3)\n       *   - DOM Tree Accessors (\u00a73.1.5)\n       *   - Form Element Parent-Child Relations (\u00a74.10.3)\n       *   - Iframe srcdoc / Nested WindowProxies (\u00a74.8.5)\n       *   - HTMLCollection (\u00a74.2.10.2)\n       *\n       * Namespace isolation is implemented by prefixing `id` and `name` attributes\n       * with a constant string, i.e., `user-content-`\n       */\n      let SANITIZE_NAMED_PROPS = false;\n      const SANITIZE_NAMED_PROPS_PREFIX = 'user-content-';\n      /* Keep element content when removing element? */\n      let KEEP_CONTENT = true;\n      /* If a `Node` is passed to sanitize(), then performs sanitization in-place instead\n       * of importing it into a new Document and returning a sanitized copy */\n      let IN_PLACE = false;\n      /* Allow usage of profiles like html, svg and mathMl */\n      let USE_PROFILES = {};\n      /* Tags to ignore content of when KEEP_CONTENT is true */\n      let FORBID_CONTENTS = null;\n      const DEFAULT_FORBID_CONTENTS = addToSet({}, ['annotation-xml', 'audio', 'colgroup', 'desc', 'foreignobject', 'head', 'iframe', 'math', 'mi', 'mn', 'mo', 'ms', 'mtext', 'noembed', 'noframes', 'noscript', 'plaintext', 'script', 'style', 'svg', 'template', 'thead', 'title', 'video', 'xmp']);\n      /* Tags that are safe for data: URIs */\n      let DATA_URI_TAGS = null;\n      const DEFAULT_DATA_URI_TAGS = addToSet({}, ['audio', 'video', 'img', 'source', 'image', 'track']);\n      /* Attributes safe for values like \"javascript:\" */\n      let URI_SAFE_ATTRIBUTES = null;\n      const DEFAULT_URI_SAFE_ATTRIBUTES = addToSet({}, ['alt', 'class', 'for', 'id', 'label', 'name', 'pattern', 'placeholder', 'role', 'summary', 'title', 'value', 'style', 'xmlns']);\n      const MATHML_NAMESPACE = 'http://www.w3.org/1998/Math/MathML';\n      const SVG_NAMESPACE = 'http://www.w3.org/2000/svg';\n      const HTML_NAMESPACE = 'http://www.w3.org/1999/xhtml';\n      /* Document namespace */\n      let NAMESPACE = HTML_NAMESPACE;\n      let IS_EMPTY_INPUT = false;\n      /* Allowed XHTML+XML namespaces */\n      let ALLOWED_NAMESPACES = null;\n      const DEFAULT_ALLOWED_NAMESPACES = addToSet({}, [MATHML_NAMESPACE, SVG_NAMESPACE, HTML_NAMESPACE], stringToString);\n      let MATHML_TEXT_INTEGRATION_POINTS = addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']);\n      let HTML_INTEGRATION_POINTS = addToSet({}, ['annotation-xml']);\n      // Certain elements are allowed in both SVG and HTML\n      // namespace. We need to specify them explicitly\n      // so that they don't get erroneously deleted from\n      // HTML namespace.\n      const COMMON_SVG_AND_HTML_ELEMENTS = addToSet({}, ['title', 'style', 'font', 'a', 'script']);\n      /* Parsing of strict XHTML documents */\n      let PARSER_MEDIA_TYPE = null;\n      const SUPPORTED_PARSER_MEDIA_TYPES = ['application/xhtml+xml', 'text/html'];\n      const DEFAULT_PARSER_MEDIA_TYPE = 'text/html';\n      let transformCaseFunc = null;\n      /* Keep a reference to config to pass to hooks */\n      let CONFIG = null;\n      /* Ideally, do not touch anything below this line */\n      /* ______________________________________________ */\n      const formElement = document.createElement('form');\n      const isRegexOrFunction = function isRegexOrFunction(testValue) {\n        return testValue instanceof RegExp || testValue instanceof Function;\n      };\n      /**\n       * _parseConfig\n       *\n       * @param cfg optional config literal\n       */\n      // eslint-disable-next-line complexity\n      const _parseConfig = function _parseConfig() {\n        let cfg = arguments.length &amp;gt; 0 &amp;amp;&amp;amp; arguments[0] !== undefined ? arguments[0] : {};\n        if (CONFIG &amp;amp;&amp;amp; CONFIG === cfg) {\n          return;\n        }\n        /* Shield configuration object from tampering */\n        if (!cfg || typeof cfg !== 'object') {\n          cfg = {};\n        }\n        /* Shield configuration object from prototype pollution */\n        cfg = clone(cfg);\n        PARSER_MEDIA_TYPE =\n        // eslint-disable-next-line unicorn/prefer-includes\n        SUPPORTED_PARSER_MEDIA_TYPES.indexOf(cfg.PARSER_MEDIA_TYPE) === -1 ? DEFAULT_PARSER_MEDIA_TYPE : cfg.PARSER_MEDIA_TYPE;\n        // HTML tags and attributes are not case-sensitive, converting to lowercase. Keeping XHTML as is.\n        transformCaseFunc = PARSER_MEDIA_TYPE === 'application/xhtml+xml' ? stringToString : stringToLowerCase;\n        /* Set configuration parameters */\n        ALLOWED_TAGS = objectHasOwnProperty(cfg, 'ALLOWED_TAGS') &amp;amp;&amp;amp; arrayIsArray(cfg.ALLOWED_TAGS) ? addToSet({}, cfg.ALLOWED_TAGS, transformCaseFunc) : DEFAULT_ALLOWED_TAGS;\n        ALLOWED_ATTR = objectHasOwnProperty(cfg, 'ALLOWED_ATTR') &amp;amp;&amp;amp; arrayIsArray(cfg.ALLOWED_ATTR) ? addToSet({}, cfg.ALLOWED_ATTR, transformCaseFunc) : DEFAULT_ALLOWED_ATTR;\n        ALLOWED_NAMESPACES = objectHasOwnProperty(cfg, 'ALLOWED_NAMESPACES') &amp;amp;&amp;amp; arrayIsArray(cfg.ALLOWED_NAMESPACES) ? addToSet({}, cfg.ALLOWED_NAMESPACES, stringToString) : DEFAULT_ALLOWED_NAMESPACES;\n        URI_SAFE_ATTRIBUTES = objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') &amp;amp;&amp;amp; arrayIsArray(cfg.ADD_URI_SAFE_ATTR) ? addToSet(clone(DEFAULT_URI_SAFE_ATTRIBUTES), cfg.ADD_URI_SAFE_ATTR, transformCaseFunc) : DEFAULT_URI_SAFE_ATTRIBUTES;\n        DATA_URI_TAGS = objectHasOwnProperty(cfg, 'ADD_DATA_URI_TAGS') &amp;amp;&amp;amp; arrayIsArray(cfg.ADD_DATA_URI_TAGS) ? addToSet(clone(DEFAULT_DATA_URI_TAGS), cfg.ADD_DATA_URI_TAGS, transformCaseFunc) : DEFAULT_DATA_URI_TAGS;\n        FORBID_CONTENTS = objectHasOwnProperty(cfg, 'FORBID_CONTENTS') &amp;amp;&amp;amp; arrayIsArray(cfg.FORBID_CONTENTS) ? addToSet({}, cfg.FORBID_CONTENTS, transformCaseFunc) : DEFAULT_FORBID_CONTENTS;\n        FORBID_TAGS = objectHasOwnProperty(cfg, 'FORBID_TAGS') &amp;amp;&amp;amp; arrayIsArray(cfg.FORBID_TAGS) ? addToSet({}, cfg.FORBID_TAGS, transformCaseFunc) : clone({});\n        FORBID_ATTR = objectHasOwnProperty(cfg, 'FORBID_ATTR') &amp;amp;&amp;amp; arrayIsArray(cfg.FORBID_ATTR) ? addToSet({}, cfg.FORBID_ATTR, transformCaseFunc) : clone({});\n        USE_PROFILES = objectHasOwnProperty(cfg, 'USE_PROFILES') ? cfg.USE_PROFILES &amp;amp;&amp;amp; typeof cfg.USE_PROFILES === 'object' ? clone(cfg.USE_PROFILES) : cfg.USE_PROFILES : false;\n        ALLOW_ARIA_ATTR = cfg.ALLOW_ARIA_ATTR !== false; // Default true\n        ALLOW_DATA_ATTR = cfg.ALLOW_DATA_ATTR !== false; // Default true\n        ALLOW_UNKNOWN_PROTOCOLS = cfg.ALLOW_UNKNOWN_PROTOCOLS || false; // Default false\n        ALLOW_SELF_CLOSE_IN_ATTR = cfg.ALLOW_SELF_CLOSE_IN_ATTR !== false; // Default true\n        SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\n        SAFE_FOR_XML = cfg.SAFE_FOR_XML !== false; // Default true\n        WHOLE_DOCUMENT = cfg.WHOLE_DOCUMENT || false; // Default false\n        RETURN_DOM = cfg.RETURN_DOM || false; // Default false\n        RETURN_DOM_FRAGMENT = cfg.RETURN_DOM_FRAGMENT || false; // Default false\n        RETURN_TRUSTED_TYPE = cfg.RETURN_TRUSTED_TYPE || false; // Default false\n        FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n        SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n        SANITIZE_NAMED_PROPS = cfg.SANITIZE_NAMED_PROPS || false; // Default false\n        KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n        IN_PLACE = cfg.IN_PLACE || false; // Default false\n        IS_ALLOWED_URI$1 = isRegex(cfg.ALLOWED_URI_REGEXP) ? cfg.ALLOWED_URI_REGEXP : IS_ALLOWED_URI; // Default regexp\n        NAMESPACE = typeof cfg.NAMESPACE === 'string' ? cfg.NAMESPACE : HTML_NAMESPACE; // Default HTML namespace\n        MATHML_TEXT_INTEGRATION_POINTS = objectHasOwnProperty(cfg, 'MATHML_TEXT_INTEGRATION_POINTS') &amp;amp;&amp;amp; cfg.MATHML_TEXT_INTEGRATION_POINTS &amp;amp;&amp;amp; typeof cfg.MATHML_TEXT_INTEGRATION_POINTS === 'object' ? clone(cfg.MATHML_TEXT_INTEGRATION_POINTS) : addToSet({}, ['mi', 'mo', 'mn', 'ms', 'mtext']); // Default built-in map\n        HTML_INTEGRATION_POINTS = objectHasOwnProperty(cfg, 'HTML_INTEGRATION_POINTS') &amp;amp;&amp;amp; cfg.HTML_INTEGRATION_POINTS &amp;amp;&amp;amp; typeof cfg.HTML_INTEGRATION_POINTS === 'object' ? clone(cfg.HTML_INTEGRATION_POINTS) : addToSet({}, ['annotation-xml']); // Default built-in map\n        const customElementHandling = objectHasOwnProperty(cfg, 'CUSTOM_ELEMENT_HANDLING') &amp;amp;&amp;amp; cfg.CUSTOM_ELEMENT_HANDLING &amp;amp;&amp;amp; typeof cfg.CUSTOM_ELEMENT_HANDLING === 'object' ? clone(cfg.CUSTOM_ELEMENT_HANDLING) : create(null);\n        CUSTOM_ELEMENT_HANDLING = create(null);\n        if (objectHasOwnProperty(customElementHandling, 'tagNameCheck') &amp;amp;&amp;amp; isRegexOrFunction(customElementHandling.tagNameCheck)) {\n          CUSTOM_ELEMENT_HANDLING.tagNameCheck = customElementHandling.tagNameCheck; // Default undefined\n        }\n        if (objectHasOwnProperty(customElementHandling, 'attributeNameCheck') &amp;amp;&amp;amp; isRegexOrFunction(customElementHandling.attributeNameCheck)) {\n          CUSTOM_ELEMENT_HANDLING.attributeNameCheck = customElementHandling.attributeNameCheck; // Default undefined\n        }\n        if (objectHasOwnProperty(customElementHandling, 'allowCustomizedBuiltInElements') &amp;amp;&amp;amp; typeof customElementHandling.allowCustomizedBuiltInElements === 'boolean') {\n          CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements = customElementHandling.allowCustomizedBuiltInElements; // Default undefined\n        }\n        if (SAFE_FOR_TEMPLATES) {\n          ALLOW_DATA_ATTR = false;\n        }\n        if (RETURN_DOM_FRAGMENT) {\n          RETURN_DOM = true;\n        }\n        /* Parse profile info */\n        if (USE_PROFILES) {\n          ALLOWED_TAGS = addToSet({}, text);\n          ALLOWED_ATTR = create(null);\n          if (USE_PROFILES.html === true) {\n            addToSet(ALLOWED_TAGS, html$1);\n            addToSet(ALLOWED_ATTR, html);\n          }\n          if (USE_PROFILES.svg === true) {\n            addToSet(ALLOWED_TAGS, svg$1);\n            addToSet(ALLOWED_ATTR, svg);\n            addToSet(ALLOWED_ATTR, xml);\n          }\n          if (USE_PROFILES.svgFilters === true) {\n            addToSet(ALLOWED_TAGS, svgFilters);\n            addToSet(ALLOWED_ATTR, svg);\n            addToSet(ALLOWED_ATTR, xml);\n          }\n          if (USE_PROFILES.mathMl === true) {\n            addToSet(ALLOWED_TAGS, mathMl$1);\n            addToSet(ALLOWED_ATTR, mathMl);\n            addToSet(ALLOWED_ATTR, xml);\n          }\n        }\n        /* Always reset function-based ADD_TAGS / ADD_ATTR checks to prevent\n         * leaking across calls when switching from function to array config */\n        EXTRA_ELEMENT_HANDLING.tagCheck = null;\n        EXTRA_ELEMENT_HANDLING.attributeCheck = null;\n        /* Merge configuration parameters */\n        if (objectHasOwnProperty(cfg, 'ADD_TAGS')) {\n          if (typeof cfg.ADD_TAGS === 'function') {\n            EXTRA_ELEMENT_HANDLING.tagCheck = cfg.ADD_TAGS;\n          } else if (arrayIsArray(cfg.ADD_TAGS)) {\n            if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n              ALLOWED_TAGS = clone(ALLOWED_TAGS);\n            }\n            addToSet(ALLOWED_TAGS, cfg.ADD_TAGS, transformCaseFunc);\n          }\n        }\n        if (objectHasOwnProperty(cfg, 'ADD_ATTR')) {\n          if (typeof cfg.ADD_ATTR === 'function') {\n            EXTRA_ELEMENT_HANDLING.attributeCheck = cfg.ADD_ATTR;\n          } else if (arrayIsArray(cfg.ADD_ATTR)) {\n            if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n              ALLOWED_ATTR = clone(ALLOWED_ATTR);\n            }\n            addToSet(ALLOWED_ATTR, cfg.ADD_ATTR, transformCaseFunc);\n          }\n        }\n        if (objectHasOwnProperty(cfg, 'ADD_URI_SAFE_ATTR') &amp;amp;&amp;amp; arrayIsArray(cfg.ADD_URI_SAFE_ATTR)) {\n          addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR, transformCaseFunc);\n        }\n        if (objectHasOwnProperty(cfg, 'FORBID_CONTENTS') &amp;amp;&amp;amp; arrayIsArray(cfg.FORBID_CONTENTS)) {\n          if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n            FORBID_CONTENTS = clone(FORBID_CONTENTS);\n          }\n          addToSet(FORBID_CONTENTS, cfg.FORBID_CONTENTS, transformCaseFunc);\n        }\n        if (objectHasOwnProperty(cfg, 'ADD_FORBID_CONTENTS') &amp;amp;&amp;amp; arrayIsArray(cfg.ADD_FORBID_CONTENTS)) {\n          if (FORBID_CONTENTS === DEFAULT_FORBID_CONTENTS) {\n            FORBID_CONTENTS = clone(FORBID_CONTENTS);\n          }\n          addToSet(FORBID_CONTENTS, cfg.ADD_FORBID_CONTENTS, transformCaseFunc);\n        }\n        /* Add #text in case KEEP_CONTENT is set to true */\n        if (KEEP_CONTENT) {\n          ALLOWED_TAGS['#text'] = true;\n        }\n        /* Add html, head and body to ALLOWED_TAGS in case WHOLE_DOCUMENT is true */\n        if (WHOLE_DOCUMENT) {\n          addToSet(ALLOWED_TAGS, ['html', 'head', 'body']);\n        }\n        /* Add tbody to ALLOWED_TAGS in case tables are permitted, see #286, #365 */\n        if (ALLOWED_TAGS.table) {\n          addToSet(ALLOWED_TAGS, ['tbody']);\n          delete FORBID_TAGS.tbody;\n        }\n        if (cfg.TRUSTED_TYPES_POLICY) {\n          if (typeof cfg.TRUSTED_TYPES_POLICY.createHTML !== 'function') {\n            throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createHTML\" hook.');\n          }\n          if (typeof cfg.TRUSTED_TYPES_POLICY.createScriptURL !== 'function') {\n            throw typeErrorCreate('TRUSTED_TYPES_POLICY configuration option must provide a \"createScriptURL\" hook.');\n          }\n          // Overwrite existing TrustedTypes policy.\n          trustedTypesPolicy = cfg.TRUSTED_TYPES_POLICY;\n          // Sign local variables required by `sanitize`.\n          emptyHTML = trustedTypesPolicy.createHTML('');\n        } else {\n          // Uninitialized policy, attempt to initialize the internal dompurify policy.\n          if (trustedTypesPolicy === undefined) {\n            trustedTypesPolicy = _createTrustedTypesPolicy(trustedTypes, currentScript);\n          }\n          // If creating the internal policy succeeded sign internal variables.\n          if (trustedTypesPolicy !== null &amp;amp;&amp;amp; typeof emptyHTML === 'string') {\n            emptyHTML = trustedTypesPolicy.createHTML('');\n          }\n        }\n        // Prevent further manipulation of configuration.\n        // Not available in IE8, Safari 5, etc.\n        if (freeze) {\n          freeze(cfg);\n        }\n        CONFIG = cfg;\n      };\n      /* Keep track of all possible SVG and MathML tags\n       * so that we can perform the namespace checks\n       * correctly. */\n      const ALL_SVG_TAGS = addToSet({}, [...svg$1, ...svgFilters, ...svgDisallowed]);\n      const ALL_MATHML_TAGS = addToSet({}, [...mathMl$1, ...mathMlDisallowed]);\n      /**\n       * @param element a DOM element whose namespace is being checked\n       * @returns Return false if the element has a\n       *  namespace that a spec-compliant parser would never\n       *  return. Return true otherwise.\n       */\n      const _checkValidNamespace = function _checkValidNamespace(element) {\n        let parent = getParentNode(element);\n        // In JSDOM, if we're inside shadow DOM, then parentNode\n        // can be null. We just simulate parent in this case.\n        if (!parent || !parent.tagName) {\n          parent = {\n            namespaceURI: NAMESPACE,\n            tagName: 'template'\n          };\n        }\n        const tagName = stringToLowerCase(element.tagName);\n        const parentTagName = stringToLowerCase(parent.tagName);\n        if (!ALLOWED_NAMESPACES[element.namespaceURI]) {\n          return false;\n        }\n        if (element.namespaceURI === SVG_NAMESPACE) {\n          // The only way to switch from HTML namespace to SVG\n          // is via . If it happens via any other tag, then\n          // it should be killed.\n          if (parent.namespaceURI === HTML_NAMESPACE) {\n            return tagName === 'svg';\n          }\n          // The only way to switch from MathML to SVG is via`\n          // svg if parent is either  or MathML\n          // text integration points.\n          if (parent.namespaceURI === MATHML_NAMESPACE) {\n            return tagName === 'svg' &amp;amp;&amp;amp; (parentTagName === 'annotation-xml' || MATHML_TEXT_INTEGRATION_POINTS[parentTagName]);\n          }\n          // We only allow elements that are defined in SVG\n          // spec. All others are disallowed in SVG namespace.\n          return Boolean(ALL_SVG_TAGS[tagName]);\n        }\n        if (element.namespaceURI === MATHML_NAMESPACE) {\n          // The only way to switch from HTML namespace to MathML\n          // is via . If it happens via any other tag, then\n          // it should be killed.\n          if (parent.namespaceURI === HTML_NAMESPACE) {\n            return tagName === 'math';\n          }\n          // The only way to switch from SVG to MathML is via\n          //  and HTML integration points\n          if (parent.namespaceURI === SVG_NAMESPACE) {\n            return tagName === 'math' &amp;amp;&amp;amp; HTML_INTEGRATION_POINTS[parentTagName];\n          }\n          // We only allow elements that are defined in MathML\n          // spec. All others are disallowed in MathML namespace.\n          return Boolean(ALL_MATHML_TAGS[tagName]);\n        }\n        if (element.namespaceURI === HTML_NAMESPACE) {\n          // The only way to switch from SVG to HTML is via\n          // HTML integration points, and from MathML to HTML\n          // is via MathML text integration points\n          if (parent.namespaceURI === SVG_NAMESPACE &amp;amp;&amp;amp; !HTML_INTEGRATION_POINTS[parentTagName]) {\n            return false;\n          }\n          if (parent.namespaceURI === MATHML_NAMESPACE &amp;amp;&amp;amp; !MATHML_TEXT_INTEGRATION_POINTS[parentTagName]) {\n            return false;\n          }\n          // We disallow tags that are specific for MathML\n          // or SVG and should never appear in HTML namespace\n          return !ALL_MATHML_TAGS[tagName] &amp;amp;&amp;amp; (COMMON_SVG_AND_HTML_ELEMENTS[tagName] || !ALL_SVG_TAGS[tagName]);\n        }\n        // For XHTML and XML documents that support custom namespaces\n        if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' &amp;amp;&amp;amp; ALLOWED_NAMESPACES[element.namespaceURI]) {\n          return true;\n        }\n        // The code should never reach this place (this means\n        // that the element somehow got namespace that is not\n        // HTML, SVG, MathML or allowed via ALLOWED_NAMESPACES).\n        // Return false just in case.\n        return false;\n      };\n      /**\n       * _forceRemove\n       *\n       * @param node a DOM node\n       */\n      const _forceRemove = function _forceRemove(node) {\n        arrayPush(DOMPurify.removed, {\n          element: node\n        });\n        try {\n          // eslint-disable-next-line unicorn/prefer-dom-node-remove\n          getParentNode(node).removeChild(node);\n        } catch (_) {\n          remove(node);\n        }\n      };\n      /**\n       * _removeAttribute\n       *\n       * @param name an Attribute name\n       * @param element a DOM node\n       */\n      const _removeAttribute = function _removeAttribute(name, element) {\n        try {\n          arrayPush(DOMPurify.removed, {\n            attribute: element.getAttributeNode(name),\n            from: element\n          });\n        } catch (_) {\n          arrayPush(DOMPurify.removed, {\n            attribute: null,\n            from: element\n          });\n        }\n        element.removeAttribute(name);\n        // We void attribute values for unremovable \"is\" attributes\n        if (name === 'is') {\n          if (RETURN_DOM || RETURN_DOM_FRAGMENT) {\n            try {\n              _forceRemove(element);\n            } catch (_) {}\n          } else {\n            try {\n              element.setAttribute(name, '');\n            } catch (_) {}\n          }\n        }\n      };\n      /**\n       * _initDocument\n       *\n       * @param dirty - a string of dirty markup\n       * @return a DOM, filled with the dirty markup\n       */\n      const _initDocument = function _initDocument(dirty) {\n        /* Create a HTML document */\n        let doc = null;\n        let leadingWhitespace = null;\n        if (FORCE_BODY) {\n          dirty = '' + dirty;\n        } else {\n          /* If FORCE_BODY isn't used, leading whitespace needs to be preserved manually */\n          const matches = stringMatch(dirty, /^[\\r\\n\\t ]+/);\n          leadingWhitespace = matches &amp;amp;&amp;amp; matches[0];\n        }\n        if (PARSER_MEDIA_TYPE === 'application/xhtml+xml' &amp;amp;&amp;amp; NAMESPACE === HTML_NAMESPACE) {\n          // Root of XHTML doc must contain xmlns declaration (see https://www.w3.org/TR/xhtml1/normative.html#strict)\n          dirty = '' + dirty + '';\n        }\n        const dirtyPayload = trustedTypesPolicy ? trustedTypesPolicy.createHTML(dirty) : dirty;\n        /*\n         * Use the DOMParser API by default, fallback later if needs be\n         * DOMParser not work for svg when has multiple root element.\n         */\n        if (NAMESPACE === HTML_NAMESPACE) {\n          try {\n            doc = new DOMParser().parseFromString(dirtyPayload, PARSER_MEDIA_TYPE);\n          } catch (_) {}\n        }\n        /* Use createHTMLDocument in case DOMParser is not available */\n        if (!doc || !doc.documentElement) {\n          doc = implementation.createDocument(NAMESPACE, 'template', null);\n          try {\n            doc.documentElement.innerHTML = IS_EMPTY_INPUT ? emptyHTML : dirtyPayload;\n          } catch (_) {\n            // Syntax error if dirtyPayload is invalid xml\n          }\n        }\n        const body = doc.body || doc.documentElement;\n        if (dirty &amp;amp;&amp;amp; leadingWhitespace) {\n          body.insertBefore(document.createTextNode(leadingWhitespace), body.childNodes[0] || null);\n        }\n        /* Work on whole document or just its body */\n        if (NAMESPACE === HTML_NAMESPACE) {\n          return getElementsByTagName.call(doc, WHOLE_DOCUMENT ? 'html' : 'body')[0];\n        }\n        return WHOLE_DOCUMENT ? doc.documentElement : body;\n      };\n      /**\n       * Creates a NodeIterator object that you can use to traverse filtered lists of nodes or elements in a document.\n       *\n       * @param root The root element or node to start traversing on.\n       * @return The created NodeIterator\n       */\n      const _createNodeIterator = function _createNodeIterator(root) {\n        return createNodeIterator.call(root.ownerDocument || root, root,\n        // eslint-disable-next-line no-bitwise\n        NodeFilter.SHOW_ELEMENT | NodeFilter.SHOW_COMMENT | NodeFilter.SHOW_TEXT | NodeFilter.SHOW_PROCESSING_INSTRUCTION | NodeFilter.SHOW_CDATA_SECTION, null);\n      };\n      /**\n       * _isClobbered\n       *\n       * @param element element to check for clobbering attacks\n       * @return true if clobbered, false if safe\n       */\n      const _isClobbered = function _isClobbered(element) {\n        return element instanceof HTMLFormElement &amp;amp;&amp;amp; (typeof element.nodeName !== 'string' || typeof element.textContent !== 'string' || typeof element.removeChild !== 'function' || !(element.attributes instanceof NamedNodeMap) || typeof element.removeAttribute !== 'function' || typeof element.setAttribute !== 'function' || typeof element.namespaceURI !== 'string' || typeof element.insertBefore !== 'function' || typeof element.hasChildNodes !== 'function');\n      };\n      /**\n       * Checks whether the given object is a DOM node.\n       *\n       * @param value object to check whether it's a DOM node\n       * @return true is object is a DOM node\n       */\n      const _isNode = function _isNode(value) {\n        return typeof Node === 'function' &amp;amp;&amp;amp; value instanceof Node;\n      };\n      function _executeHooks(hooks, currentNode, data) {\n        arrayForEach(hooks, hook =&amp;gt; {\n          hook.call(DOMPurify, currentNode, data, CONFIG);\n        });\n      }\n      /**\n       * _sanitizeElements\n       *\n       * @protect nodeName\n       * @protect textContent\n       * @protect removeChild\n       * @param currentNode to check for permission to exist\n       * @return true if node was killed, false if left alive\n       */\n      const _sanitizeElements = function _sanitizeElements(currentNode) {\n        let content = null;\n        /* Execute a hook if present */\n        _executeHooks(hooks.beforeSanitizeElements, currentNode, null);\n        /* Check if element is clobbered or can clobber */\n        if (_isClobbered(currentNode)) {\n          _forceRemove(currentNode);\n          return true;\n        }\n        /* Now let's check the element's type and name */\n        const tagName = transformCaseFunc(currentNode.nodeName);\n        /* Execute a hook if present */\n        _executeHooks(hooks.uponSanitizeElement, currentNode, {\n          tagName,\n          allowedTags: ALLOWED_TAGS\n        });\n        /* Detect mXSS attempts abusing namespace confusion */\n        if (SAFE_FOR_XML &amp;amp;&amp;amp; currentNode.hasChildNodes() &amp;amp;&amp;amp; !_isNode(currentNode.firstElementChild) &amp;amp;&amp;amp; regExpTest(/&amp;lt;[/\\w!]/g, currentNode.innerHTML) &amp;amp;&amp;amp; regExpTest(/&amp;lt;[/\\w!]/g, currentNode.textContent)) {\n          _forceRemove(currentNode);\n          return true;\n        }\n        /* Remove risky CSS construction leading to mXSS */\n        if (SAFE_FOR_XML &amp;amp;&amp;amp; currentNode.namespaceURI === HTML_NAMESPACE &amp;amp;&amp;amp; tagName === 'style' &amp;amp;&amp;amp; _isNode(currentNode.firstElementChild)) {\n          _forceRemove(currentNode);\n          return true;\n        }\n        /* Remove any occurrence of processing instructions */\n        if (currentNode.nodeType === NODE_TYPE.progressingInstruction) {\n          _forceRemove(currentNode);\n          return true;\n        }\n        /* Remove any kind of possibly harmful comments */\n        if (SAFE_FOR_XML &amp;amp;&amp;amp; currentNode.nodeType === NODE_TYPE.comment &amp;amp;&amp;amp; regExpTest(/&amp;lt;[/\\w]/g, currentNode.data)) {\n          _forceRemove(currentNode);\n          return true;\n        }\n        /* Remove element if anything forbids its presence */\n        if (FORBID_TAGS[tagName] || !(EXTRA_ELEMENT_HANDLING.tagCheck instanceof Function &amp;amp;&amp;amp; EXTRA_ELEMENT_HANDLING.tagCheck(tagName)) &amp;amp;&amp;amp; !ALLOWED_TAGS[tagName]) {\n          /* Check if we have a custom element to handle */\n          if (!FORBID_TAGS[tagName] &amp;amp;&amp;amp; _isBasicCustomElement(tagName)) {\n            if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp &amp;amp;&amp;amp; regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, tagName)) {\n              return false;\n            }\n            if (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function &amp;amp;&amp;amp; CUSTOM_ELEMENT_HANDLING.tagNameCheck(tagName)) {\n              return false;\n            }\n          }\n          /* Keep content except for bad-listed elements */\n          if (KEEP_CONTENT &amp;amp;&amp;amp; !FORBID_CONTENTS[tagName]) {\n            const parentNode = getParentNode(currentNode) || currentNode.parentNode;\n            const childNodes = getChildNodes(currentNode) || currentNode.childNodes;\n            if (childNodes &amp;amp;&amp;amp; parentNode) {\n              const childCount = childNodes.length;\n              for (let i = childCount - 1; i &amp;gt;= 0; --i) {\n                const childClone = cloneNode(childNodes[i], true);\n                parentNode.insertBefore(childClone, getNextSibling(currentNode));\n              }\n            }\n          }\n          _forceRemove(currentNode);\n          return true;\n        }\n        /* Check whether element has a valid namespace */\n        if (currentNode instanceof Element &amp;amp;&amp;amp; !_checkValidNamespace(currentNode)) {\n          _forceRemove(currentNode);\n          return true;\n        }\n        /* Make sure that older browsers don't get fallback-tag mXSS */\n        if ((tagName === 'noscript' || tagName === 'noembed' || tagName === 'noframes') &amp;amp;&amp;amp; regExpTest(/&amp;lt;\\/no(script|embed|frames)/i, currentNode.innerHTML)) {\n          _forceRemove(currentNode);\n          return true;\n        }\n        /* Sanitize element content to be template-safe */\n        if (SAFE_FOR_TEMPLATES &amp;amp;&amp;amp; currentNode.nodeType === NODE_TYPE.text) {\n          /* Get the element's text content */\n          content = currentNode.textContent;\n          arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr =&amp;gt; {\n            content = stringReplace(content, expr, ' ');\n          });\n          if (currentNode.textContent !== content) {\n            arrayPush(DOMPurify.removed, {\n              element: currentNode.cloneNode()\n            });\n            currentNode.textContent = content;\n          }\n        }\n        /* Execute a hook if present */\n        _executeHooks(hooks.afterSanitizeElements, currentNode, null);\n        return false;\n      };\n      /**\n       * _isValidAttribute\n       *\n       * @param lcTag Lowercase tag name of containing element.\n       * @param lcName Lowercase attribute name.\n       * @param value Attribute value.\n       * @return Returns true if `value` is valid, otherwise false.\n       */\n      // eslint-disable-next-line complexity\n      const _isValidAttribute = function _isValidAttribute(lcTag, lcName, value) {\n        /* FORBID_ATTR must always win, even if ADD_ATTR predicate would allow it */\n        if (FORBID_ATTR[lcName]) {\n          return false;\n        }\n        /* Make sure attribute cannot clobber */\n        if (SANITIZE_DOM &amp;amp;&amp;amp; (lcName === 'id' || lcName === 'name') &amp;amp;&amp;amp; (value in document || value in formElement)) {\n          return false;\n        }\n        const nameIsPermitted = ALLOWED_ATTR[lcName] || EXTRA_ELEMENT_HANDLING.attributeCheck instanceof Function &amp;amp;&amp;amp; EXTRA_ELEMENT_HANDLING.attributeCheck(lcName, lcTag);\n        /* Allow valid data-* attributes: At least one character after \"-\"\n            (https://html.spec.whatwg.org/multipage/dom.html#embedding-custom-non-visible-data-with-the-data-*-attributes)\n            XML-compatible (https://html.spec.whatwg.org/multipage/infrastructure.html#xml-compatible and http://www.w3.org/TR/xml/#d0e804)\n            We don't need to check the value; it's always URI safe. */\n        if (ALLOW_DATA_ATTR &amp;amp;&amp;amp; !FORBID_ATTR[lcName] &amp;amp;&amp;amp; regExpTest(DATA_ATTR, lcName)) ; else if (ALLOW_ARIA_ATTR &amp;amp;&amp;amp; regExpTest(ARIA_ATTR, lcName)) ; else if (!nameIsPermitted || FORBID_ATTR[lcName]) {\n          if (\n          // First condition does a very basic check if a) it's basically a valid custom element tagname AND\n          // b) if the tagName passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n          // and c) if the attribute name passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.attributeNameCheck\n          _isBasicCustomElement(lcTag) &amp;amp;&amp;amp; (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp &amp;amp;&amp;amp; regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, lcTag) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function &amp;amp;&amp;amp; CUSTOM_ELEMENT_HANDLING.tagNameCheck(lcTag)) &amp;amp;&amp;amp; (CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof RegExp &amp;amp;&amp;amp; regExpTest(CUSTOM_ELEMENT_HANDLING.attributeNameCheck, lcName) || CUSTOM_ELEMENT_HANDLING.attributeNameCheck instanceof Function &amp;amp;&amp;amp; CUSTOM_ELEMENT_HANDLING.attributeNameCheck(lcName, lcTag)) ||\n          // Alternative, second condition checks if it's an `is`-attribute, AND\n          // the value passes whatever the user has configured for CUSTOM_ELEMENT_HANDLING.tagNameCheck\n          lcName === 'is' &amp;amp;&amp;amp; CUSTOM_ELEMENT_HANDLING.allowCustomizedBuiltInElements &amp;amp;&amp;amp; (CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof RegExp &amp;amp;&amp;amp; regExpTest(CUSTOM_ELEMENT_HANDLING.tagNameCheck, value) || CUSTOM_ELEMENT_HANDLING.tagNameCheck instanceof Function &amp;amp;&amp;amp; CUSTOM_ELEMENT_HANDLING.tagNameCheck(value))) ; else {\n            return false;\n          }\n          /* Check value is safe. First, is attr inert? If so, is safe */\n        } else if (URI_SAFE_ATTRIBUTES[lcName]) ; else if (regExpTest(IS_ALLOWED_URI$1, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if ((lcName === 'src' || lcName === 'xlink:href' || lcName === 'href') &amp;amp;&amp;amp; lcTag !== 'script' &amp;amp;&amp;amp; stringIndexOf(value, 'data:') === 0 &amp;amp;&amp;amp; DATA_URI_TAGS[lcTag]) ; else if (ALLOW_UNKNOWN_PROTOCOLS &amp;amp;&amp;amp; !regExpTest(IS_SCRIPT_OR_DATA, stringReplace(value, ATTR_WHITESPACE, ''))) ; else if (value) {\n          return false;\n        } else ;\n        return true;\n      };\n      /* Names the HTML spec reserves from valid-custom-element-name; these must\n       * never be treated as basic custom elements even when a permissive\n       * CUSTOM_ELEMENT_HANDLING.tagNameCheck is configured. */\n      const RESERVED_CUSTOM_ELEMENT_NAMES = addToSet({}, ['annotation-xml', 'color-profile', 'font-face', 'font-face-format', 'font-face-name', 'font-face-src', 'font-face-uri', 'missing-glyph']);\n      /**\n       * _isBasicCustomElement\n       * checks if at least one dash is included in tagName, and it's not the first char\n       * for more sophisticated checking see https://github.com/sindresorhus/validate-element-name\n       *\n       * @param tagName name of the tag of the node to sanitize\n       * @returns Returns true if the tag name meets the basic criteria for a custom element, otherwise false.\n       */\n      const _isBasicCustomElement = function _isBasicCustomElement(tagName) {\n        return !RESERVED_CUSTOM_ELEMENT_NAMES[stringToLowerCase(tagName)] &amp;amp;&amp;amp; regExpTest(CUSTOM_ELEMENT, tagName);\n      };\n      /**\n       * _sanitizeAttributes\n       *\n       * @protect attributes\n       * @protect nodeName\n       * @protect removeAttribute\n       * @protect setAttribute\n       *\n       * @param currentNode to sanitize\n       */\n      const _sanitizeAttributes = function _sanitizeAttributes(currentNode) {\n        /* Execute a hook if present */\n        _executeHooks(hooks.beforeSanitizeAttributes, currentNode, null);\n        const {\n          attributes\n        } = currentNode;\n        /* Check if we have attributes; if not we might have a text node */\n        if (!attributes || _isClobbered(currentNode)) {\n          return;\n        }\n        const hookEvent = {\n          attrName: '',\n          attrValue: '',\n          keepAttr: true,\n          allowedAttributes: ALLOWED_ATTR,\n          forceKeepAttr: undefined\n        };\n        let l = attributes.length;\n        /* Go backwards over all attributes; safely remove bad ones */\n        while (l--) {\n          const attr = attributes[l];\n          const {\n            name,\n            namespaceURI,\n            value: attrValue\n          } = attr;\n          const lcName = transformCaseFunc(name);\n          const initValue = attrValue;\n          let value = name === 'value' ? initValue : stringTrim(initValue);\n          /* Execute a hook if present */\n          hookEvent.attrName = lcName;\n          hookEvent.attrValue = value;\n          hookEvent.keepAttr = true;\n          hookEvent.forceKeepAttr = undefined; // Allows developers to see this is a property they can set\n          _executeHooks(hooks.uponSanitizeAttribute, currentNode, hookEvent);\n          value = hookEvent.attrValue;\n          /* Full DOM Clobbering protection via namespace isolation,\n           * Prefix id and name attributes with `user-content-`\n           */\n          if (SANITIZE_NAMED_PROPS &amp;amp;&amp;amp; (lcName === 'id' || lcName === 'name') &amp;amp;&amp;amp; stringIndexOf(value, SANITIZE_NAMED_PROPS_PREFIX) !== 0) {\n            // Remove the attribute with this value\n            _removeAttribute(name, currentNode);\n            // Prefix the value and later re-create the attribute with the sanitized value\n            value = SANITIZE_NAMED_PROPS_PREFIX + value;\n          }\n          // Else: already prefixed, leave the attribute alone \u2014 the prefix is\n          // itself the clobbering protection, and re-applying it is incorrect.\n          /* Work around a security issue with comments inside attributes */\n          if (SAFE_FOR_XML &amp;amp;&amp;amp; regExpTest(/((--!?|])&amp;gt;)|&amp;lt;\\/(style|script|title|xmp|textarea|noscript|iframe|noembed|noframes)/i, value)) {\n            _removeAttribute(name, currentNode);\n            continue;\n          }\n          /* Make sure we cannot easily use animated hrefs, even if animations are allowed */\n          if (lcName === 'attributename' &amp;amp;&amp;amp; stringMatch(value, 'href')) {\n            _removeAttribute(name, currentNode);\n            continue;\n          }\n          /* Did the hooks approve of the attribute? */\n          if (hookEvent.forceKeepAttr) {\n            continue;\n          }\n          /* Did the hooks approve of the attribute? */\n          if (!hookEvent.keepAttr) {\n            _removeAttribute(name, currentNode);\n            continue;\n          }\n          /* Work around a security issue in jQuery 3.0 */\n          if (!ALLOW_SELF_CLOSE_IN_ATTR &amp;amp;&amp;amp; regExpTest(/\\/&amp;gt;/i, value)) {\n            _removeAttribute(name, currentNode);\n            continue;\n          }\n          /* Sanitize attribute content to be template-safe */\n          if (SAFE_FOR_TEMPLATES) {\n            arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr =&amp;gt; {\n              value = stringReplace(value, expr, ' ');\n            });\n          }\n          /* Is `value` valid for this attribute? */\n          const lcTag = transformCaseFunc(currentNode.nodeName);\n          if (!_isValidAttribute(lcTag, lcName, value)) {\n            _removeAttribute(name, currentNode);\n            continue;\n          }\n          /* Handle attributes that require Trusted Types */\n          if (trustedTypesPolicy &amp;amp;&amp;amp; typeof trustedTypes === 'object' &amp;amp;&amp;amp; typeof trustedTypes.getAttributeType === 'function') {\n            if (namespaceURI) ; else {\n              switch (trustedTypes.getAttributeType(lcTag, lcName)) {\n                case 'TrustedHTML':\n                  {\n                    value = trustedTypesPolicy.createHTML(value);\n                    break;\n                  }\n                case 'TrustedScriptURL':\n                  {\n                    value = trustedTypesPolicy.createScriptURL(value);\n                    break;\n                  }\n              }\n            }\n          }\n          /* Handle invalid data-* attribute set by try-catching it */\n          if (value !== initValue) {\n            try {\n              if (namespaceURI) {\n                currentNode.setAttributeNS(namespaceURI, name, value);\n              } else {\n                /* Fallback to setAttribute() for browser-unrecognized namespaces e.g. \"x-schema\". */\n                currentNode.setAttribute(name, value);\n              }\n              if (_isClobbered(currentNode)) {\n                _forceRemove(currentNode);\n              } else {\n                arrayPop(DOMPurify.removed);\n              }\n            } catch (_) {\n              _removeAttribute(name, currentNode);\n            }\n          }\n        }\n        /* Execute a hook if present */\n        _executeHooks(hooks.afterSanitizeAttributes, currentNode, null);\n      };\n      /**\n       * _sanitizeShadowDOM\n       *\n       * @param fragment to iterate over recursively\n       */\n      const _sanitizeShadowDOM2 = function _sanitizeShadowDOM(fragment) {\n        let shadowNode = null;\n        const shadowIterator = _createNodeIterator(fragment);\n        /* Execute a hook if present */\n        _executeHooks(hooks.beforeSanitizeShadowDOM, fragment, null);\n        while (shadowNode = shadowIterator.nextNode()) {\n          /* Execute a hook if present */\n          _executeHooks(hooks.uponSanitizeShadowNode, shadowNode, null);\n          /* Sanitize tags and elements */\n          _sanitizeElements(shadowNode);\n          /* Check attributes next */\n          _sanitizeAttributes(shadowNode);\n          /* Deep shadow DOM detected */\n          if (shadowNode.content instanceof DocumentFragment) {\n            _sanitizeShadowDOM2(shadowNode.content);\n          }\n        }\n        /* Execute a hook if present */\n        _executeHooks(hooks.afterSanitizeShadowDOM, fragment, null);\n      };\n      // eslint-disable-next-line complexity\n      DOMPurify.sanitize = function (dirty) {\n        let cfg = arguments.length &amp;gt; 1 &amp;amp;&amp;amp; arguments[1] !== undefined ? arguments[1] : {};\n        let body = null;\n        let importedNode = null;\n        let currentNode = null;\n        let returnNode = null;\n        /* Make sure we have a string to sanitize.\n          DO NOT return early, as this will return the wrong type if\n          the user has requested a DOM object rather than a string */\n        IS_EMPTY_INPUT = !dirty;\n        if (IS_EMPTY_INPUT) {\n          dirty = '';\n        }\n        /* Stringify, in case dirty is an object */\n        if (typeof dirty !== 'string' &amp;amp;&amp;amp; !_isNode(dirty)) {\n          dirty = stringifyValue(dirty);\n          if (typeof dirty !== 'string') {\n            throw typeErrorCreate('dirty is not a string, aborting');\n          }\n        }\n        /* Return dirty HTML if DOMPurify cannot run */\n        if (!DOMPurify.isSupported) {\n          return dirty;\n        }\n        /* Assign config vars */\n        if (!SET_CONFIG) {\n          _parseConfig(cfg);\n        }\n        /* Clean up removed elements */\n        DOMPurify.removed = [];\n        /* Check if dirty is correctly typed for IN_PLACE */\n        if (typeof dirty === 'string') {\n          IN_PLACE = false;\n        }\n        if (IN_PLACE) {\n          /* Do some early pre-sanitization to avoid unsafe root nodes */\n          const nn = dirty.nodeName;\n          if (typeof nn === 'string') {\n            const tagName = transformCaseFunc(nn);\n            if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n              throw typeErrorCreate('root node is forbidden and cannot be sanitized in-place');\n            }\n          }\n        } else if (dirty instanceof Node) {\n          /* If dirty is a DOM element, append to an empty document to avoid\n             elements being stripped by the parser */\n          body = _initDocument('');\n          importedNode = body.ownerDocument.importNode(dirty, true);\n          if (importedNode.nodeType === NODE_TYPE.element &amp;amp;&amp;amp; importedNode.nodeName === 'BODY') {\n            /* Node is already a body, use as is */\n            body = importedNode;\n          } else if (importedNode.nodeName === 'HTML') {\n            body = importedNode;\n          } else {\n            // eslint-disable-next-line unicorn/prefer-dom-node-append\n            body.appendChild(importedNode);\n          }\n        } else {\n          /* Exit directly if we have nothing to do */\n          if (!RETURN_DOM &amp;amp;&amp;amp; !SAFE_FOR_TEMPLATES &amp;amp;&amp;amp; !WHOLE_DOCUMENT &amp;amp;&amp;amp;\n          // eslint-disable-next-line unicorn/prefer-includes\n          dirty.indexOf('&amp;lt;') === -1) {\n            return trustedTypesPolicy &amp;amp;&amp;amp; RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(dirty) : dirty;\n          }\n          /* Initialize the document to work on */\n          body = _initDocument(dirty);\n          /* Check we have a DOM node from the data */\n          if (!body) {\n            return RETURN_DOM ? null : RETURN_TRUSTED_TYPE ? emptyHTML : '';\n          }\n        }\n        /* Remove first element node (ours) if FORCE_BODY is set */\n        if (body &amp;amp;&amp;amp; FORCE_BODY) {\n          _forceRemove(body.firstChild);\n        }\n        /* Get node iterator */\n        const nodeIterator = _createNodeIterator(IN_PLACE ? dirty : body);\n        /* Now start iterating over the created document */\n        while (currentNode = nodeIterator.nextNode()) {\n          /* Sanitize tags and elements */\n          _sanitizeElements(currentNode);\n          /* Check attributes next */\n          _sanitizeAttributes(currentNode);\n          /* Shadow DOM detected, sanitize it */\n          if (currentNode.content instanceof DocumentFragment) {\n            _sanitizeShadowDOM2(currentNode.content);\n          }\n        }\n        /* If we sanitized `dirty` in-place, return it. */\n        if (IN_PLACE) {\n          return dirty;\n        }\n        /* Return sanitized string or DOM */\n        if (RETURN_DOM) {\n          if (SAFE_FOR_TEMPLATES) {\n            body.normalize();\n            let html = body.innerHTML;\n            arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr =&amp;gt; {\n              html = stringReplace(html, expr, ' ');\n            });\n            body.innerHTML = html;\n          }\n          if (RETURN_DOM_FRAGMENT) {\n            returnNode = createDocumentFragment.call(body.ownerDocument);\n            while (body.firstChild) {\n              // eslint-disable-next-line unicorn/prefer-dom-node-append\n              returnNode.appendChild(body.firstChild);\n            }\n          } else {\n            returnNode = body;\n          }\n          if (ALLOWED_ATTR.shadowroot || ALLOWED_ATTR.shadowrootmode) {\n            /*\n              AdoptNode() is not used because internal state is not reset\n              (e.g. the past names map of a HTMLFormElement), this is safe\n              in theory but we would rather not risk another attack vector.\n              The state that is cloned by importNode() is explicitly defined\n              by the specs.\n            */\n            returnNode = importNode.call(originalDocument, returnNode, true);\n          }\n          return returnNode;\n        }\n        let serializedHTML = WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n        /* Serialize doctype if allowed */\n        if (WHOLE_DOCUMENT &amp;amp;&amp;amp; ALLOWED_TAGS['!doctype'] &amp;amp;&amp;amp; body.ownerDocument &amp;amp;&amp;amp; body.ownerDocument.doctype &amp;amp;&amp;amp; body.ownerDocument.doctype.name &amp;amp;&amp;amp; regExpTest(DOCTYPE_NAME, body.ownerDocument.doctype.name)) {\n          serializedHTML = '\\n' + serializedHTML;\n        }\n        /* Sanitize final string template-safe */\n        if (SAFE_FOR_TEMPLATES) {\n          arrayForEach([MUSTACHE_EXPR, ERB_EXPR, TMPLIT_EXPR], expr =&amp;gt; {\n            serializedHTML = stringReplace(serializedHTML, expr, ' ');\n          });\n        }\n        return trustedTypesPolicy &amp;amp;&amp;amp; RETURN_TRUSTED_TYPE ? trustedTypesPolicy.createHTML(serializedHTML) : serializedHTML;\n      };\n      DOMPurify.setConfig = function () {\n        let cfg = arguments.length &amp;gt; 0 &amp;amp;&amp;amp; arguments[0] !== undefined ? arguments[0] : {};\n        _parseConfig(cfg);\n        SET_CONFIG = true;\n      };\n      DOMPurify.clearConfig = function () {\n        CONFIG = null;\n        SET_CONFIG = false;\n      };\n      DOMPurify.isValidAttribute = function (tag, attr, value) {\n        /* Initialize shared config vars if necessary. */\n        if (!CONFIG) {\n          _parseConfig({});\n        }\n        const lcTag = transformCaseFunc(tag);\n        const lcName = transformCaseFunc(attr);\n        return _isValidAttribute(lcTag, lcName, value);\n      };\n      DOMPurify.addHook = function (entryPoint, hookFunction) {\n        if (typeof hookFunction !== 'function') {\n          return;\n        }\n        arrayPush(hooks[entryPoint], hookFunction);\n      };\n      DOMPurify.removeHook = function (entryPoint, hookFunction) {\n        if (hookFunction !== undefined) {\n          const index = arrayLastIndexOf(hooks[entryPoint], hookFunction);\n          return index === -1 ? undefined : arraySplice(hooks[entryPoint], index, 1)[0];\n        }\n        return arrayPop(hooks[entryPoint]);\n      };\n      DOMPurify.removeHooks = function (entryPoint) {\n        hooks[entryPoint] = [];\n      };\n      DOMPurify.removeAllHooks = function () {\n        hooks = _createHooksMap();\n      };\n      return DOMPurify;\n    }\n    var purify = createDOMPurify();\n\n    return purify;\n\n}));\n//# sourceMappingURL=purify.js.map\n\n/**\n * jQuery fixes\n *\n * Note: The following analysis and/or changes was required also to be applied in our code base:\n *\t- Ensure there is no JSONP ajax call\n *\t- Ensure to not use self closing tag when a closing tag is usually needed.\n *\t\tex: `\n` need to change for `\n`\n *\t\tThis is applicable to all tags except the one in this list: area|br|col|embed|hr|img|input|link|meta|param\n *\t- Review how ``, ``, `` and `` are inserted with `$()`.\n *\t\tTheir insertion need to be completed differently like the by using the javascript DOM interface.\n *\t- All content that related to jQuery DOM manipulation are sanitized with DOMPurify\n *\t- You can't use jQuery for parsing XML document, you can use DOMParser() as an alternative\n *\t- Ensure AJAX and fetch are sanitized before they response are used\n */\n/*\n\n// Test case for the jQuery fixes bellow\n\nTest: jQuery()\n\n\t- Run in your browser console\n\t&amp;gt; $( \"\nabcdef\" ).appendTo( \"#wb-cont\" );\n\tresult: No iframe inserted around the heading level 1\n\nTest:\njQuery.html()\njQuery.append()\njQuery.prepend()\njQuery.before()\njQuery.after()\n\n\t- Use the data-ajax demo page: /demos/data-ajax/data-ajax-en.html\n\t- Insert the following in the ajaxed in file: \nabcdef\n\t- Check if the dirty HTML are cleaned for the example: \"append\", \"prepend\", \"before\", \"after\"\n\t- The data-ajax-replace will also test the jQuery.html() function.\n\nTest: jQuery.replaceWith()\n\n\t- Run in your browser console\n\t&amp;gt; $(\"#wb-cont\").replaceWith( \"\nabcdef\" );\n\tresult: No iframe inserted around the heading level 1\n\nTest: jQuery.parseHTML()\n\n\t- Run in your browser console, pass unsafe HTML and it should return sanitized HTML\n\t&amp;gt; jQuery.parseHTML( \"\nabcdef\" );\n\tresult: return an array with 1 element, [ p ]\n\nTest: jQuery.htmlPrefilter()\n\n\t- Run in your browser console\n\t&amp;gt; jQuery.htmlPrefilter( \"\" );\n\tresult: return \n\nTest: jQuery.extend\n\n\t- Run in your browser console\n\t&amp;gt; var dataFromAPI = JSON.parse( '{ \"new\": \"property\", \"__proto__\": { \"polluted\": \"true\" } }' );\n\t&amp;gt; var myObject = jQuery.extend( '{ \"new\": \"property\" }', dataFromAPI );\n\t&amp;gt; console.log( myObject.polluted );\n\tresult: &amp;gt; undefined\n\n*/\n\n( function( jQuery, DOMPurify, window ) {\n\"use strict\";\n\n/**\n * Copied from: https://git.drupalcode.org/project/drupal/-/commit/d2f26902ef5d6de58caaf2a7c766eb2115b1c17e\n *\n * This is almost verbatim copied from jQuery 3.4.0.\n *\n * Now compatible with jQuery 4.\n *\n */\njQuery.extend = jQuery.fn.extend = function() {\n\tvar options, name, src, copy, copyIsArray, clone,\n\t\ttarget = arguments[ 0 ] || {},\n\t\ti = 1,\n\t\tlength = arguments.length,\n\t\tdeep = false;\n\n\t// Handle a deep copy situation\n\tif ( typeof target === \"boolean\" ) {\n\t\tdeep = target;\n\n\t\t// Skip the boolean and the target\n\t\ttarget = arguments[ i ] || {};\n\t\ti++;\n\t}\n\n\t// Handle case when target is a string or something (possible in deep copy)\n\tif ( typeof target !== \"object\" &amp;amp;&amp;amp; typeof target !== \"function\" ) {\n\t\ttarget = {};\n\t}\n\n\t// Extend jQuery itself if only one argument is passed\n\tif ( i === length ) {\n\t\ttarget = this;\n\t\ti--;\n\t}\n\n\tfor ( ; i &amp;lt; length; i++ ) {\n\n\t\t// Only deal with non-null/undefined values\n\t\toptions = arguments[ i ];\n\t\tif ( options !== undefined || options !== null ) {\n\n\t\t\t// Extend the base object\n\t\t\tfor ( name in options ) {\n\t\t\t\tcopy = options[ name ];\n\n\t\t\t\t// Prevent Object.prototype pollution\n\t\t\t\t// Prevent never-ending loop\n\t\t\t\tif ( name === \"__proto__\" || target === copy ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Recurse if we're merging plain objects or arrays\n\t\t\t\tif ( deep &amp;amp;&amp;amp; copy &amp;amp;&amp;amp; ( jQuery.isPlainObject( copy ) ||\n\t\t\t\t\t( copyIsArray = Array.isArray( copy ) ) ) ) {\n\t\t\t\t\tsrc = target[ name ];\n\n\t\t\t\t\t// Ensure proper type for the source value\n\t\t\t\t\tif ( copyIsArray &amp;amp;&amp;amp; !Array.isArray( src ) ) {\n\t\t\t\t\t\tclone = [];\n\t\t\t\t\t} else if ( !copyIsArray &amp;amp;&amp;amp; !jQuery.isPlainObject( src ) ) {\n\t\t\t\t\t\tclone = {};\n\t\t\t\t\t} else {\n\t\t\t\t\t\tclone = src;\n\t\t\t\t\t}\n\t\t\t\t\tcopyIsArray = false;\n\n\t\t\t\t\t// Never move original objects, clone them\n\t\t\t\t\ttarget[ name ] = jQuery.extend( deep, clone, copy );\n\n\t\t\t\t\t// Don't bring in undefined values\n\t\t\t\t} else if ( copy !== undefined ) {\n\t\t\t\t\ttarget[ name ] = copy;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\t// Return the modified object\n\treturn target;\n};\n\n/**\n * Security advisories: https://github.com/jquery/jquery/security/advisories/GHSA-gxr4-xjj5-5px2\n */\njQuery.htmlPrefilter = function( html ) {\n\treturn html;\n};\n\n/**\n * Security advisories: https://github.com/jquery/jquery/security/advisories/GHSA-jpcq-cgw6-v4j6\n *\n * This implementation leverage DOMPurify for filtering every string prior DOM manipulation by jQuery\n *\n */\n\n// START: add hooks to DOMPurify to allow external links when they meet certain conditions as defined here: https://owasp.org/www-community/attacks/Reverse_Tabnabbing\nDOMPurify.addHook( \"beforeSanitizeAttributes\", function( node ) {\n\n\t// Add \"data-wb-external-link\" to all  with a target=\"_blank\" and rel=\"noreferrer\"\n\tif (\n\t\tnode.tagName === \"A\" &amp;amp;&amp;amp;\n\t\tnode.getAttribute( \"target\" ) &amp;amp;&amp;amp;\n\t\tnode.getAttribute( \"target\" ) === \"_blank\" &amp;amp;&amp;amp;\n\t\tnode.getAttribute( \"rel\" ) &amp;amp;&amp;amp;\n\t\tnode.relList.contains( \"noreferrer\" )\n\t) {\n\t\tnode.setAttribute( \"data-wb-external-link\", \"true\" );\n\t}\n} );\n\nDOMPurify.addHook( \"afterSanitizeAttributes\", function( node ) {\n\n\t// Put back the target=\"_blank\" to all  with attribute \"data-wb-external-link\"\n\tif ( node.tagName === \"A\" &amp;amp;&amp;amp; node.getAttribute( \"data-wb-external-link\" ) ) {\n\t\tnode.setAttribute( \"target\", \"_blank\" );\n\t\tnode.removeAttribute( \"data-wb-external-link\" );\n\t}\n} );\n\n// END\n\nvar localParseHTML = jQuery.parseHTML,\n\tappend = jQuery.fn.append,\n\tprepend = jQuery.fn.prepend,\n\tbefore = jQuery.fn.before,\n\tafter = jQuery.fn.after,\n\treplaceWith = jQuery.fn.replaceWith,\n\tjqInit = jQuery.fn.init,\n\tdataTableAllowedTag = [\n\t\t\"\",\n\t\t\"\",\n\t\t\"\",\n\t\t\"\"\n\t],\n\tallowedTags = [\n\t\t\"gc-combobox\"\n\t],\n\n\t// Declare the allowed attributes for custom tags\n\tallowedTagAttributes = {\n\t\t\"gc-combobox\": [ \"all-options-tag\", \"enable-select-all\", \"options\" ]\n\t},\n\n\tsanitize = function( html ) {\n\n\t\t// Add an exception for DataTable plugin\n\t\tif ( window.DataTable &amp;amp;&amp;amp; dataTableAllowedTag.indexOf( html ) !== -1 ) {\n\t\t\treturn html;\n\t\t}\n\n\t\treturn DOMPurify.sanitize( html, {\n\t\t\tADD_TAGS: allowedTags,\n\n\t\t\t// Add the allowed attributes for the declared custom tags to prevent them from being stripped during sanitization\n\t\t\tADD_ATTR: function( attributeName, tagName ) {\n\t\t\t\treturn ( allowedTagAttributes[ tagName ] || [] ).includes( attributeName );\n\t\t\t}\n\t\t} );\n\t};\n\njQuery.parseHTML = function( data, context, keepScripts ) {\n\treturn localParseHTML( sanitize( data ), context, keepScripts );\n};\n\njQuery.domManip = null;\n\njQuery.append = jQuery.fn.append = function() {\n\tvar args = arguments,\n\t\tvalue = args[ 0 ];\n\tif ( typeof value === \"string\" ) {\n\t\tvalue = sanitize( value );\n\t\targs[ 0 ] = value;\n\t}\n\treturn append.apply( this, args );\n};\n\njQuery.prepend = jQuery.fn.prepend = function() {\n\tvar args = arguments,\n\t\tvalue = args[ 0 ];\n\tif ( typeof value === \"string\" ) {\n\t\tvalue = sanitize( value );\n\t\targs[ 0 ] = value;\n\t}\n\treturn prepend.apply( this, args );\n};\n\njQuery.before = jQuery.fn.before = function() {\n\tvar args = arguments,\n\t\tvalue = args[ 0 ];\n\tif ( typeof value === \"string\" ) {\n\t\tvalue = sanitize( value );\n\t\targs[ 0 ] = value;\n\t}\n\treturn before.apply( this, args );\n};\n\njQuery.after = jQuery.fn.after = function() {\n\tvar args = arguments,\n\t\tvalue = args[ 0 ];\n\tif ( typeof value === \"string\" ) {\n\t\tvalue = sanitize( value );\n\t\targs[ 0 ] = value;\n\t}\n\treturn after.apply( this, args );\n};\n\njQuery.replaceWith = jQuery.fn.replaceWith = function() {\n\tvar args = arguments,\n\t\tvalue = args[ 0 ];\n\tif ( typeof value === \"string\" ) {\n\t\tvalue = sanitize( value );\n\t\targs[ 0 ] = value;\n\t}\n\treturn replaceWith.apply( this, args );\n};\n\njQuery.fn.init = function( selector, context, root ) {\n\tif ( typeof selector === \"string\" ) {\n\t\tselector = sanitize( selector );\n\t}\n\treturn new jqInit( selector, context, root );\n};\n\njQuery.html = function( value ) {\n\treturn jQuery.html( sanitize( value ) );\n};\n\n} )( jQuery, DOMPurify, window );\n\n/* Modernizr (Custom Build) | MIT &amp;amp; BSD\n\n * The minified JS code below is based on Modernizr 3.2.0.\n * Logic for MathML has been manually removed from the minified\n * code following the removal of MathJax from WET-BOEW. The build URL\n * was untouched.\n *\n * Build: https://modernizr.com/download/#-elem_details-elem_progress_meter-mathml-cors-load-mq-css3-input-inputtypes-svg-cssclasses-csstransitions-fontface-backgroundsize-borderimage-teststyles-testprops-testallprops-hasevents-prefixes-domprefixes\n */\n;window.Modernizr=function(e,t,n){function L(e){f.cssText=e}function A(e,t){return L(p.join(e+\";\")+(t||\"\"))}function O(e,t){return typeof e===t}function M(e,t){return!!~(\"\"+e).indexOf(t)}function _(e,t){for(var r in e){var i=e[r];if(!M(i,\"-\")&amp;amp;&amp;amp;f[i]!==n)return t==\"pfx\"?i:!0}return!1}function D(e,t,r){for(var i in e){var s=t[e[i]];if(s!==n)return r===!1?e[i]:O(s,\"function\")?s.bind(r||t):s}return!1}function P(e,t,n){var r=e.charAt(0).toUpperCase()+e.slice(1),i=(e+\" \"+v.join(r+\" \")+r).split(\" \");return O(t,\"string\")||O(t,\"undefined\")?_(i,t):(i=(e+\" \"+m.join(r+\" \")+r).split(\" \"),D(i,t,n))}function H(){i.input=function(n){for(var r=0,i=n.length;r',e,\"\"].join(\"\"),c.id=u,(h?c:p).innerHTML+=s,p.appendChild(c),h||(p.style.background=\"\",p.style.overflow=\"hidden\",l=o.style.overflow,o.style.overflow=\"hidden\",o.appendChild(p)),a=n(c,e),h?c.parentNode.removeChild(c):(p.parentNode.removeChild(p),o.style.overflow=l),!!a},N=function(t){var n=e.matchMedia||e.msMatchMedia;if(n)return n(t)&amp;amp;&amp;amp;n(t).matches||!1;var r;return T(\"@media \"+t+\" { #\"+u+\" { position: absolute; } }\",function(t){r=(e.getComputedStyle?getComputedStyle(t,null):t.currentStyle)[\"position\"]==\"absolute\"}),r},C={}.hasOwnProperty,k;!O(C,\"undefined\")&amp;amp;&amp;amp;!O(C.call,\"undefined\")?k=function(e,t){return C.call(e,t)}:k=function(e,t){return t in e&amp;amp;&amp;amp;O(e.constructor.prototype[t],\"undefined\")},Function.prototype.bind||(Function.prototype.bind=function(t){var n=this;if(typeof n!=\"function\")throw new TypeError;var r=S.call(arguments,1),i=function(){if(this instanceof i){var e=function(){};e.prototype=n.prototype;var s=new e,o=n.apply(s,r.concat(S.call(arguments)));return Object(o)===o?o:s}return n.apply(t,r.concat(S.call(arguments)))};return i}),y.backgroundsize=function(){return P(\"backgroundSize\")},y.borderimage=function(){return P(\"borderImage\")},y.csstransitions=function(){return P(\"transition\")},y.fontface=function(){var e;return T('@font-face {font-family:\"font\";src:url(\"https://\")}',function(n,r){var i=t.getElementById(\"smodernizr\"),s=i.sheet||i.styleSheet,o=s?s.cssRules&amp;amp;&amp;amp;s.cssRules[0]?s.cssRules[0].cssText:s.cssText||\"\":\"\";e=/src/i.test(o)&amp;amp;&amp;amp;o.indexOf(r.split(\" \")[0])===0}),e},y.svg=function(){return!!t.createElementNS&amp;amp;&amp;amp;!!t.createElementNS(g.svg,\"svg\").createSVGRect};for(var B in y)k(y,B)&amp;amp;&amp;amp;(x=B.toLowerCase(),i[x]=y[B](),E.push((i[x]?\"\":\"no-\")+x));return i.input||H(),i.addTest=function(e,t){if(typeof e==\"object\")for(var r in e)k(e,r)&amp;amp;&amp;amp;i.addTest(r,e[r]);else{e=e.toLowerCase();if(i[e]!==n)return i;t=typeof t==\"function\"?t():t,typeof s!=\"undefined\"&amp;amp;&amp;amp;s&amp;amp;&amp;amp;(o.className+=\" \"+(t?\"\":\"no-\")+e),i[e]=t}return i},L(\"\"),a=l=null,i._version=r,i._prefixes=p,i._domPrefixes=m,i._cssomPrefixes=v,i.mq=N,i.testProp=function(e){return _([e])},i.testAllProps=P,i.testStyles=T,o.className=o.className.replace(/(^|\\s)no-js(\\s|$)/,\"$1$2\")+(s?\" js \"+E.join(\" \"):\"\"),i}(this,this.document),function(e,t,n){function r(e){return\"[object Function]\"==d.call(e)}function i(e){return\"string\"==typeof e}function s(){}function o(e){return!e||\"loaded\"==e||\"complete\"==e||\"uninitialized\"==e}function u(){var e=v.shift();m=1,e?e.t?h(function(){(\"c\"==e.t?k.injectCss:k.injectJs)(e.s,0,e.a,e.x,e.e,1)},0):(e(),u()):m=0}function a(e,n,r,i,s,a,f){function l(t){if(!d&amp;amp;&amp;amp;o(c.readyState)&amp;amp;&amp;amp;(w.r=d=1,!m&amp;amp;&amp;amp;u(),c.onload=c.onreadystatechange=null,t)){\"img\"!=e&amp;amp;&amp;amp;h(function(){b.removeChild(c)},50);for(var r in T[n])T[n].hasOwnProperty(r)&amp;amp;&amp;amp;T[n][r].onload()}}var f=f||k.errorTimeout,c=t.createElement(e),d=0,g=0,w={t:r,s:n,e:s,a:a,x:f};1===T[n]&amp;amp;&amp;amp;(g=1,T[n]=[]),\"object\"==e?c.data=n:(c.src=n,c.type=e),c.width=c.height=\"0\",c.onerror=c.onload=c.onreadystatechange=function(){l.call(this,g)},v.splice(i,0,w),\"img\"!=e&amp;amp;&amp;amp;(g||2===T[n]?(b.insertBefore(c,y?null:p),h(l,f)):T[n].push(c))}function f(e,t,n,r,s){return m=0,t=t||\"j\",i(e)?a(\"c\"==t?E:w,e,t,this.i++,n,r,s):(v.splice(this.i++,0,e),1==v.length&amp;amp;&amp;amp;u()),this}function l(){var e=k;return e.loader={load:f,i:0},e}var c=t.documentElement,h=e.setTimeout,p=t.getElementsByTagName(\"script\")[0],d={}.toString,v=[],m=0,g=\"MozAppearance\"in c.style,y=g&amp;amp;&amp;amp;!!t.createRange().compareNode,b=y?c:p.parentNode,c=e.opera&amp;amp;&amp;amp;\"[object Opera]\"==d.call(e.opera),c=!!t.attachEvent&amp;amp;&amp;amp;!c,w=g?\"object\":c?\"script\":\"img\",E=c?\"script\":w,S=Array.isArray||function(e){return\"[object Array]\"==d.call(e)},x=[],T={},N={timeout:function(e,t){return t.length&amp;amp;&amp;amp;(e.timeout=t[0]),e}},C,k;k=function(e){function t(e){var e=e.split(\"!\"),t=x.length,n=e.pop(),r=e.length,n={url:n,origUrl:n,prefixes:e},i,s,o;for(s=0;sab\",t.style.display=\"block\",r.appendChild(t),i=t.offsetHeight,t.open=!0,i=i!=t.offsetHeight,r.removeChild(t),n&amp;amp;&amp;amp;r.parentNode.removeChild(r),i):!1}),Modernizr.addTest(\"progressbar\",function(){return document.createElement(\"progress\").max!==undefined}),Modernizr.addTest(\"meter\",function(){return document.createElement(\"meter\").max!==undefined}),Modernizr.addTest(\"cors\",!!(window.XMLHttpRequest&amp;amp;&amp;amp;\"withCredentials\"in new XMLHttpRequest));\n\n/**\n * String.prototype.includes() polyfill\n * @author Ricokola\n * @license MIT\n */\nif ( !String.prototype.includes ) {\n\tString.prototype.includes = function( string ) {\n\n\t\treturn this.indexOf( string ) !== -1;\n\n\t};\n}\n\n/**\n * String.prototype.replaceAll() polyfill\n * https://gomakethings.com/how-to-replace-a-section-of-a-string-with-another-one-with-vanilla-js/\n * @author Chris Ferdinandi\n * @license MIT\n */\nif ( !String.prototype.replaceAll ) {\n\tString.prototype.replaceAll = function( str, newStr ) {\n\n\t\t// If a regex pattern\n\t\tif ( Object.prototype.toString.call( str ).toLowerCase() === \"[object regexp]\" ) {\n\t\t\treturn this.replace( str, newStr );\n\t\t}\n\n\t\t// If a string\n\t\treturn this.replace( new RegExp( str, \"g\" ), newStr );\n\n\t};\n}\n\n/**\n * @title WET-BOEW Vapour loader\n * @overview Helper methods for WET\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author WET Community\n */\n/*\n * Vapour Object that will store tombstone data for plugins to leverage\n */\n( function( $, window, document, undef ) {\n\"use strict\";\n\n/**\n * @method getUrlParts\n * @param {String} url of URL to examine\n * @return {Object} of the parts of passed URL\n */\nvar getUrlParts = function( url ) {\n\t\tvar a = document.createElement( \"a\" );\n\t\ta.href = url;\n\t\treturn {\n\t\t\thref: a.href,\n\t\t\tabsolute: a.href,\n\t\t\thost: a.host,\n\t\t\thostname: a.hostname,\n\t\t\tport: a.port,\n\t\t\tpathname: a.pathname.replace( /^([^/])/, \"/$1\" ), // Prefix pathname with a slash in browsers that don't natively do it (i.e. all versions of IE and possibly early versions of Edge). See pull request #8110.\n\t\t\tprotocol: a.protocol,\n\t\t\thash: a.hash,\n\t\t\tsearch: a.search,\n\n\t\t\t// A collection of the parameters of the query string part of the URL.\n\t\t\tparams: ( function() {\n\t\t\t\tvar queryString = a.search.replace( /(^\\?)/, \"\" );\n\t\t\t\tif ( !queryString ) {\n\t\t\t\t\treturn {};\n\t\t\t\t}\n\t\t\t\treturn queryString.split( \"&amp;amp;\" ).map( function( n ) {\n\t\t\t\t\treturn ( n = n.split( \"=\" ), this[ n[ 0 ] ] = decodeURIComponent( n[ 1 ] ), this );\n\t\t\t\t}.bind( {} ) )[ 0 ];\n\t\t\t}() )\n\t\t};\n\t},\n\n\t/**\n\t * @variable seed\n\t * @return a unique number for auto-generating ids\n\t */\n\tseed = 0,\n\n\t/**\n\t * @variable $src\n\t * @return {jQuery Element} of wb script element\n\t */\n\t$src = $( \"script[src*='wet-boew.js'],script[src*='wet-boew.min.js'],script[data-wb-core]\" )\n\t\t.last(),\n\n\t/**\n\t * @variable i18n\n\t * @return {string} of WET document language\n\t */\n\tlang = ( function( ele ) {\n\t\tlet lang = document.documentElement.lang;\n\t\tconst shortLangLength = 2;\n\n\t\t// Perform extra checks if the page uses a long language code\n\t\tif ( lang.length &amp;gt; shortLangLength ) {\n\t\t\tlet longLangs = [ \"pt-BR\", \"zh-Hans\" ]; // Built-in long language codes\n\n\t\t\t// Check if any custom long language codes have been specified\n\t\t\t// Specify by adding data-wb-core and data-lang-long=\"en-CA en-US etc\" attributes to WET's script element (e.g. wet-boew.js or wet-boew.min.js)\n\t\t\tif ( ele[ 0 ].hasAttribute( \"data-wb-core\" ) &amp;amp;&amp;amp;  ele[ 0 ].hasAttribute( \"data-lang-long\" ) ) {\n\t\t\t\tconst longLangsCustom = ele.attr( \"data-lang-long\" ).split( \" \" );\n\n\t\t\t\t// Add extra language codes to the beginning of the longLangs array to match them more quickly\n\t\t\t\tlongLangs = longLangsCustom.concat( longLangs );\n\t\t\t}\n\n\t\t\t// Shorten the language code if it doesn't exist in the longLangs array\n\t\t\tif ( longLangs.indexOf( lang ) === -1 ) {\n\t\t\t\tlang = lang.substring( 0, shortLangLength );\n\t\t\t}\n\t\t}\n\n\t\treturn lang;\n\t}( $src ) ),\n\n\tpaths = ( function( ele ) {\n\t\tvar paths = {};\n\n\t\tpaths.home = ele.prop( \"src\" )\n\t\t\t.split( \"?\" )[ 0 ].split( \"/\" )\n\t\t\t.slice( 0, -1 )\n\t\t\t.join( \"/\" );\n\t\tpaths.asset = paths.home + \"/../assets\";\n\t\tpaths.template = paths.home + \"/assets/templates\";\n\t\tpaths.dep = paths.home + \"/deps\";\n\t\tpaths.js = paths.home;\n\t\tpaths.css = paths.home.substring( 0, paths.home.length - 2 ) + \"css\";\n\t\tpaths.mode = ele.prop( \"src\" ).indexOf( \".min\" ) &amp;lt; 0 ? \"\" : \".min\";\n\n\t\tif ( ele[ 0 ].hasAttribute( \"data-wb-core\" ) ) {\n\t\t\t$.extend( paths, {\n\t\t\t\thome: ele.attr( \"data-home\" ),\n\t\t\t\tasset: ele.attr( \"data-asset\" ),\n\t\t\t\ttemplate: ele.attr( \"data-template\" ),\n\t\t\t\tdep: ele.attr( \"data-dep\" ),\n\t\t\t\tjs: ele.attr( \"data-js\" ),\n\t\t\t\tcss: ele.attr( \"data-css\" ),\n\t\t\t\tmode: ele.attr( \"data-mode\" )\n\t\t\t} );\n\t\t}\n\n\t\treturn paths;\n\t}( $src ) ),\n\n\t/**\n\t * @variable oldie\n\t * @return {integer} of IE version\n\t */\n\toldie = ( function() {\n\t\tvar undef,\n\t\t\tv = 3,\n\t\t\tdiv = document.createElement( \"div\" ),\n\t\t\tall = div.getElementsByTagName( \"i\" );\n\n\t\twhile ( (\n\t\t\tdiv.innerHTML = \"\",\n\t\t\tall[ 0 ]\n\t\t) ) { /* empty */ }\n\n\t\treturn v &amp;gt; 4 ? v : undef;\n\t}() ),\n\n\t/**\n\t * @variable currentpage\n\t * @return {Object} of parts of the current page URL\n\t */\n\tcurrentpage = getUrlParts( window.location.href ),\n\n\t/**\n\t * @variable disabled\n\t * @return {boolean} of state of disabled flag\n\t */\n\tdisabled = ( function() {\n\t\tvar disabledSaved = \"false\",\n\t\t\tdisabled;\n\n\t\ttry {\n\t\t\tdisabledSaved = localStorage.getItem( \"wbdisable\" ) || disabledSaved;\n\t\t} catch ( e ) {\n\n\t\t\t/* swallow error */\n\t\t}\n\n\t\tdisabled = currentpage.params.wbdisable || disabledSaved;\n\t\treturn ( typeof disabled === \"string\" ) ? ( disabled.toLowerCase() === \"true\" ) : Boolean( disabled );\n\t}() ),\n\n\t/*-----------------------------\n\t * Core Library Object\n\t *-----------------------------\n\t */\n\twb = {\n\t\t\"/\": paths.home,\n\t\t\"/assets\": paths.asset,\n\t\t\"/templates\": paths.template,\n\t\t\"/deps\": paths.dep,\n\t\tlang: lang,\n\t\tmode: paths.mode,\n\t\tdoc: $( document ),\n\t\twin: $( window ),\n\t\thtml: $( \"html\" ),\n\t\tpageUrlParts: currentpage,\n\t\tgetUrlParts: getUrlParts,\n\t\tisDisabled: disabled,\n\t\tisStarted: false,\n\t\tisReady: false,\n\t\tignoreHashChange: false,\n\t\tinitQueue: 0,\n\n\t\t// Checks if the element \n is supported natively.\n\t\t// V\u00e9rifier si l'\u00e9l\u00e9ment \n est support\u00e9 nativement.\n\t\tsupportsDetails: function() {\n\t\t\treturn \"open\" in document.createElement( \"details\" );\n\t\t},\n\n\t\tgetPath: function( property ) {\n\t\t\treturn Object.prototype.hasOwnProperty.call( this, property ) ? this[ property ] : undef;\n\t\t},\n\n\t\tgetMode: function() {\n\t\t\treturn this.mode;\n\t\t},\n\n\t\tgetId: function() {\n\t\t\tvar idPrefix = \"wb-auto-\",\n\t\t\t\tids,\n\t\t\t\tnumberCandidate,\n\t\t\t\tnumbers = [];\n\n\t\t\t// Check for conflicting hardcoded IDs the first time an ID is requested\n\t\t\tif ( !seed ) {\n\t\t\t\tids = document.querySelectorAll( \"[id^='\" + idPrefix + \"']\" );\n\n\t\t\t\t// Loop through elements whose IDs begin with the prefix\n\t\t\t\tids.forEach( function( currentElm ) {\n\t\t\t\t\tnumberCandidate = currentElm.id.substring( idPrefix.length );\n\n\t\t\t\t\t// Verify whether the ID ends with a conflicting number and add it to an array\n\t\t\t\t\tif ( numberCandidate.search( /^\\d+$/ ) !== -1 ) {\n\t\t\t\t\t\tnumbers.push( numberCandidate );\n\t\t\t\t\t}\n\n\t\t\t\t\tconsole.error( \"wb.getId: ID '\" + currentElm.id + \"' isn't supposed to be hardcoded in the page. Please remove it or change its prefix to something different than '\" + idPrefix + \"'.\" );\n\t\t\t\t} );\n\n\t\t\t\t// Set the seed to the array's highest number (will be incremented later)\n\t\t\t\tseed = numbers.length ? Math.max.apply( null, numbers ) : seed;\n\t\t\t}\n\n\t\t\treturn idPrefix + ( seed += 1 );\n\t\t},\n\n\t\tinit: function( event, componentName, selector, noAutoId ) {\n\t\t\tvar\teventTarget = event.target,\n\t\t\t\tisEvent = !!eventTarget,\n\t\t\t\tnode = isEvent ? eventTarget : event,\n\t\t\t\tinitedClass = componentName + \"-inited\",\n\t\t\t\tisDocumentNode = node === document;\n\n\t\t\t// Filter out any events triggered by descendants and only initializes\n\t\t\t// the element once (if is an event and document node is not the target)\n\t\t\tif ( !isEvent || isDocumentNode || ( event.currentTarget === node &amp;amp;&amp;amp;\n\t\t\t\tnode.classList &amp;amp;&amp;amp;\n\t\t\t\t!node.classList.contains( initedClass ) ) ) {\n\n\t\t\t\tthis.initQueue += 1;\n\t\t\t\tthis.remove( selector );\n\t\t\t\tif ( !isDocumentNode ) {\n\t\t\t\t\tnode.classList.add( initedClass );\n\n\t\t\t\t\tif ( !noAutoId &amp;amp;&amp;amp; !node.id ) {\n\t\t\t\t\t\tnode.id = wb.getId();\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\treturn node;\n\t\t\t}\n\n\t\t\treturn undef;\n\t\t},\n\n\t\tready: function( $elm, componentName, context ) {\n\n\t\t\tif ( $elm ) {\n\n\t\t\t\t// Trigger any nested elements (excluding nested within nested)\n\t\t\t\t$elm\n\t\t\t\t\t.find( wb.allSelectors )\n\t\t\t\t\t.addClass( \"wb-init\" )\n\t\t\t\t\t.filter( \":not(#\" + $elm.attr( \"id\" ) + \" .wb-init .wb-init)\" )\n\t\t\t\t\t.trigger( \"timerpoke.wb\" );\n\n\t\t\t\t// Identify that the component is ready\n\t\t\t\t$elm.trigger( \"wb-ready.\" + componentName, context );\n\n\t\t\t\tthis.initQueue -= 1;\n\t\t\t} else {\n\t\t\t\tthis.doc.trigger( \"wb-ready.\" + componentName, context );\n\t\t\t}\n\n\t\t\t// Identify that global initialization is complete\n\t\t\tif ( !this.isReady &amp;amp;&amp;amp; this.isStarted &amp;amp;&amp;amp; this.initQueue &amp;lt; 1 ) {\n\n\t\t\t\t// Create DOM event\n\t\t\t\tconst DOMevent = new Event( \"wet-boew-ready\" );\n\n\t\t\t\tthis.isReady = true;\n\t\t\t\tthis.doc.trigger( \"wb-ready.wb\" );\n\t\t\t\tthis.doc[ 0 ].dispatchEvent( DOMevent ); // Trigger native DOM event\n\t\t\t}\n\t\t},\n\n\t\t// Lets load some variables into wb for IE detection\n\t\tother: !oldie,\n\t\tdesktop: ( window.orientation === undefined ),\n\t\tie: !!oldie,\n\t\tie6: ( oldie === 6 ),\n\t\tie7: ( oldie === 7 ),\n\t\tie8: ( oldie === 8 ),\n\t\tie9: ( oldie === 9 ),\n\t\tielt7: ( oldie &amp;lt; 7 ),\n\t\tielt8: ( oldie &amp;lt; 8 ),\n\t\tielt9: ( oldie &amp;lt; 9 ),\n\t\tielt10: ( oldie &amp;lt; 10 ),\n\t\tie11: ( navigator.userAgent.includes( \"Trident/7.\" ) ),\n\n\t\tselectors: [],\n\n\t\tresizeEvents: \"xxsmallview.wb xsmallview.wb smallview.wb mediumview.wb largeview.wb xlargeview.wb\",\n\n\t\t// For Charts and Geomap\n\t\tdrawColours: [\n\t\t\t\"#8d201c\",\n\t\t\t\"#EE8310\",\n\t\t\t\"#2a7da6\",\n\t\t\t\"#5a306b\",\n\t\t\t\"#285228\",\n\t\t\t\"#154055\",\n\t\t\t\"#555555\",\n\t\t\t\"#f6d200\",\n\t\t\t\"#d73d38\",\n\t\t\t\"#418541\",\n\t\t\t\"#87aec9\",\n\t\t\t\"#23447e\",\n\t\t\t\"#999999\"\n\t\t],\n\n\t\t// Get and generate a unique session id\n\t\tsessionGUID: function() {\n\t\t\tvar sessionId = sessionStorage.getItem( \"wb-session-GUID\" );\n\t\t\tif ( !sessionId ) {\n\t\t\t\tsessionId = wb.guid();\n\t\t\t\tsessionStorage.setItem( \"wb-session-GUID\", sessionId );\n\t\t\t}\n\t\t\treturn sessionId;\n\t\t},\n\n\t\t// Add a selector to be targeted by timerpoke\n\t\tadd: function( selector ) {\n\t\t\tvar exists = false,\n\t\t\t\tlen = wb.selectors.length,\n\t\t\t\ti;\n\n\t\t\t// Lets ensure we are not running if things are disabled\n\t\t\tif ( wb.isDisabled &amp;amp;&amp;amp; selector !== \"#wb-tphp\" ) {\n\t\t\t\treturn 0;\n\t\t\t}\n\n\t\t\t// Check to see if the selector is already targeted\n\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\tif ( wb.selectors[ i ] === selector ) {\n\t\t\t\t\texists = true;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add the selector if it isn't already targeted\n\t\t\tif ( !exists ) {\n\t\t\t\twb.selectors.push( selector );\n\t\t\t}\n\t\t},\n\n\t\t// Remove a selector targeted by timerpoke\n\t\tremove: function( selector ) {\n\t\t\tvar len = this.selectors.length,\n\t\t\t\ti;\n\n\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\tif ( this.selectors[ i ] === selector ) {\n\t\t\t\t\tthis.selectors.splice( i, 1 );\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t},\n\n\t\t// Handles triggering of timerpoke events\n\t\ttimerpoke: function( initial ) {\n\t\t\tvar selectorsLocal = wb.selectors.slice( 0 ),\n\t\t\t\tlen = selectorsLocal.length,\n\t\t\t\tselector, $elms, $foundElms, i;\n\n\t\t\tif ( initial ) {\n\t\t\t\t$foundElms = $();\n\t\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t\tselector = selectorsLocal[ i ];\n\t\t\t\t\t$elms = $( selector );\n\t\t\t\t\tif ( $elms.length !== 0 ) {\n\t\t\t\t\t\t$foundElms = $foundElms.add( $elms );\n\n\t\t\t\t\t// If the selector returns no elements, remove the selector\n\t\t\t\t\t} else {\n\t\t\t\t\t\twb.remove( selector );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Keep only the non-nested plugin/polyfill elements\n\t\t\t\t$elms = $foundElms.filter( \":not(.wb-init .wb-init)\" ).addClass( \"wb-init\" );\n\t\t\t} else {\n\t\t\t\t$elms = $( selectorsLocal.join( \", \" ) );\n\t\t\t}\n\t\t\t$elms.trigger( \"timerpoke.wb\" );\n\t\t},\n\n\t\tstart: function() {\n\n\t\t\t// Save a copy of all the possible selectors\n\t\t\twb.allSelectors = wb.selectors.join( \", \" );\n\n\t\t\t// Initiate timerpoke events right way\n\t\t\twb.timerpoke( true );\n\t\t\tthis.isStarted = true;\n\t\t\tthis.ready();\n\n\t\t\t// Initiate timerpoke events again every half second\n\t\t\tsetInterval( wb.timerpoke, 500 );\n\t\t},\n\n\t\ti18nDict: {},\n\t\ti18n: function( key, state, mixin ) {\n\t\t\tvar dictionary = wb.i18nDict,\n\n\t\t\t\t// eg. 000 or 001 ie. 0 or 1\n\t\t\t\ttruthiness = ( typeof key === \"string\" &amp;amp;&amp;amp; key !== \"\" ) |\n\n\t\t\t\t\t// eg. 000 or 010 ie. 0 or 2\n\t\t\t\t\t( typeof state === \"string\" &amp;amp;&amp;amp; state !== \"\" ) &amp;lt;&amp;lt; 1 |\n\n\t\t\t\t\t// eg. 000 or 100 ie. 0 or 4\n\t\t\t\t\t( typeof mixin === \"string\" &amp;amp;&amp;amp; mixin !== \"\" ) &amp;lt;&amp;lt; 2;\n\n\t\t\tswitch ( truthiness ) {\n\t\t\t\tcase 1:\n\n\t\t\t\t\t// only key was provided\n\t\t\t\t\treturn dictionary[ key ];\n\n\t\t\t\tcase 3:\n\n\t\t\t\t\t// key and state were provided\n\t\t\t\t\treturn dictionary[ key ][ state ];\n\n\t\t\t\tcase 7:\n\n\t\t\t\t\t// key, state, and mixin were provided\n\t\t\t\t\treturn dictionary[ key ][ state ].replace( \"[MIXIN]\", mixin );\n\t\t\t\tdefault:\n\t\t\t\t\treturn \"\";\n\t\t\t}\n\t\t},\n\n\t\thashString: function( str ) {\n\n\t\t\t// Sources:\n\t\t\t//\thttps://werxltd.com/wp/2010/05/13/javascript-implementation-of-javas-string-hashcode-method/\n\t\t\t//\thttps://jsperf.com/hashing-strings\n\t\t\tvar hash = 0,\n\t\t\t\tchr, i;\n\n\t\t\tif ( str.length === 0 ) {\n\t\t\t\treturn hash;\n\t\t\t}\n\n\t\t\tfor ( i = 0; i &amp;lt; str.length; i++ ) {\n\t\t\t\tchr = str.charCodeAt( i );\n\t\t\t\thash = ( ( hash &amp;lt;&amp;lt; 5 ) - hash ) + chr;\n\n\t\t\t\t// Convert to 32bit integer\n\t\t\t\thash = hash &amp;amp; hash;\n\t\t\t}\n\n\t\t\treturn hash;\n\t\t},\n\n\t\tstripWhitespace: function( str ) {\n\t\t\treturn str.replace( /\\s+/g, \"\" );\n\t\t},\n\n\t\t// Core function to deal with the dependency racing issue\n\t\twhenLibReady: function( testCallback, readyCallback ) {\n\t\t\tif ( testCallback() ) {\n\t\t\t\treadyCallback();\n\t\t\t} else {\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\twb.whenLibReady( testCallback, readyCallback );\n\t\t\t\t}, 50 );\n\t\t\t}\n\n\t\t}\n\t};\n\nwindow.wb = wb;\n\n/*-----------------------------\n * Yepnope Prefixes\n *-----------------------------*/\n/*\n * Establish the base path to be more flexible in terms of WCMS where JS can\n * reside in theme folders and not in the root of sites\n * @TODO: For modularity the prefixes where written independently as we are\n * flushing out some use cases on better grouping and optimization of polyfills.\n * Once this more hashed out, we could optimize the prefixes down to one or two\n * prefixes \"site\" and \"disabled\" to thin out the codeblock a bit more\n * increase performance due to redundant chaining of the prefixes.\n */\n\n/**\n * @prefix: site! - adds the root js directory of yepnope resources\n */\nyepnope.addPrefix( \"site\", function( resourceObj ) {\n\tresourceObj.url = paths.js + \"/\" + resourceObj.url;\n\treturn resourceObj;\n} );\n\n/**\n * @prefix: plyfll! - builds the path for the polyfill resource\n */\nyepnope.addPrefix( \"plyfll\", function( resourceObj ) {\n\tvar path,\n\t\turl = resourceObj.url;\n\n\tif ( disabled &amp;amp;&amp;amp; url.indexOf( \"svg\" ) === -1 ) {\n\t\tresourceObj.bypass = true;\n\t} else if ( !paths.mode ) {\n\t\turl = url.replace( \".min\", \"\" );\n\t}\n\n\tif ( url.indexOf( \".css\" ) !== -1 ) {\n\t\tresourceObj.forceCSS = true;\n\t\tpath = paths.css;\n\t} else {\n\t\tpath = paths.js;\n\t}\n\tresourceObj.url = path + \"/polyfills/\" + url;\n\n\treturn resourceObj;\n} );\n\n/**\n * @prefix: i18n! - adds the correct document language for our i18n library\n */\nyepnope.addPrefix( \"i18n\", function( resourceObj ) {\n\tresourceObj.url = paths.js + \"/\" + resourceObj.url + lang + paths.mode + \".js\";\n\treturn resourceObj;\n} );\n\n/*-----------------------------\n * Deps loading, call \"complete\" callback when the deps is ready if a testReady is defined\n *-----------------------------*/\nwb.modernizrLoad = Modernizr.load;\nModernizr.load = function( options ) {\n\tvar i, i_len, i_cache,\n\t\ttestReady, complete;\n\tif ( !Array.isArray( options ) ) {\n\t\toptions = [ options ];\n\t}\n\ti_len = options.length;\n\tfor ( i = 0; i !== i_len; i += 1 ) {\n\t\ti_cache = options[ i ];\n\t\ttestReady = i_cache.testReady;\n\t\tcomplete = i_cache.complete;\n\t\tif ( testReady &amp;amp;&amp;amp; complete ) {\n\t\t\ti_cache.complete = wb.whenLibReady( testReady, complete );\n\t\t}\n\t}\n\twb.modernizrLoad( options );\n};\n\n/*-----------------------------\n * Modernizr Polyfill Loading\n *-----------------------------*/\nModernizr.load( [\n\t{\n\t\ttest: Modernizr.details,\n\t\tnope: [\n\t\t\t\"plyfll!details.min.js\",\n\t\t\t\"plyfll!details.min.css\"\n\t\t]\n\t}, {\n\t\ttest: Modernizr.input.list,\n\t\tnope: [\n\t\t\t\"plyfll!datalist.min.js\",\n\t\t\t\"plyfll!datalist.min.css\"\n\t\t]\n\t}, {\n\t\ttest: Modernizr.inputtypes.date,\n\t\tnope: [\n\t\t\t\"plyfll!datepicker.min.js\",\n\t\t\t\"plyfll!datepicker.min.css\"\n\t\t]\n\t}, {\n\t\ttest: Modernizr.inputtypes.range,\n\t\tnope: [\n\t\t\t\"plyfll!slider.min.js\",\n\t\t\t\"plyfll!slider_wrapper.min.js\",\n\t\t\t\"plyfll!slider.min.css\"\n\t\t],\n\t\tcallback: function( url ) {\n\t\t\tif ( url === \"slider.min.js\" ) {\n\t\t\t\twindow.fdSlider.onDomReady();\n\t\t\t}\n\t\t}\n\t}, {\n\t\ttest: Modernizr.progressbar,\n\t\tnope: [\n\t\t\t\"plyfll!progress.min.js\",\n\t\t\t\"plyfll!progress.min.css\"\n\t\t]\n\t}, {\n\t\ttest: Modernizr.meter,\n\t\tnope: [\n\t\t\t\"plyfll!meter.min.js\",\n\t\t\t\"plyfll!meter.min.css\"\n\t\t]\n\t}, {\n\t\ttest: Modernizr.touch,\n\t\tyep: \"plyfll!mobile.min.js\"\n\t}, {\n\t\ttest: Modernizr.svg,\n\t\tnope: \"plyfll!svg.min.js\"\n\t}, {\n\t\tload: \"i18n!i18n/\",\n\t\ttestReady: function() {\n\t\t\treturn wb.i18nDict.tphp;\n\t\t},\n\t\tcomplete: function() {\n\t\t\twb.start();\n\t\t}\n\t}\n] );\n\n} )( jQuery, window, document );\n\n/**\n * @title WET-BOEW JQuery Helper Methods\n * @overview Helper methods for WET\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author WET Community\n * Credits: https://web.archive.org/web/20130826230640/http://kaibun.net/blog/2013/04/19/a-fully-fledged-coffeescript-boilerplate-for-jquery-plugins/\n */\n( function( $, wb ) {\n\nwb.getData = function( element, dataName ) {\n\tvar elm = !element.jquery ? element : element[ 0 ],\n\t\tdataAttr = elm.getAttribute( \"data-\" + dataName ),\n\t\tdataObj;\n\n\tif ( dataAttr ) {\n\t\ttry {\n\t\t\tdataObj = JSON.parse( dataAttr );\n\t\t\t$.data( elm, dataName, dataObj );\n\t\t} catch ( error ) {\n\t\t\tconsole.info( elm );\n\t\t\t$.error( \"Bad JSON array in data-\" + dataName + \" attribute\" );\n\t\t}\n\t}\n\n\treturn dataObj;\n};\n\n/*\n * Initiate an in-browser download from a blob\n * @param blob: a reference to a blob object\n * @param filename: a suggested file name to save as under\n * @param title: (Optional) a title added to the link. Its use case is for web analytics tracking.\n*/\nwb.download = function( blob, filename, title ) {\n\n\tvar objectURL = URL.createObjectURL( blob ),\n\t\tanchor = document.createElement( \"a\" );\n\n\tfilename = filename || \"unnamed\"; // Ensure a filename is defined\n\n\tanchor.textContent = title || \"\";\n\tanchor.download = filename;\n\n\tanchor.hidden = true;\n\tdocument.body.appendChild( anchor ); // Added to the body for the web analytic tracking use case.\n\n\tif ( window.navigator.msSaveOrOpenBlob ) {\n\n\t\t// This is for IE11 support\n\t\tanchor.addEventListener( \"click\", function( ) {\n\t\t\twindow.navigator.msSaveOrOpenBlob( blob, filename );\n\t\t} );\n\t\tanchor.setAttribute( \"target\", \"_blank\" );\n\t} else {\n\t\tanchor.href = objectURL;\n\t}\n\n\tanchor.click();\n\n\t// Clean the DOM, remove the accessory anchor at the next tick\n\tsetTimeout( function() {\n\t\tdocument.body.removeChild( anchor );\n\t}, 1 );\n\n\t// Revoke the object, A setTimeout is used because Blob API don't have a download complete event.\n\tsetTimeout( function() {\n\t\tif ( typeof objectURL === \"string\" ) {\n\t\t\tURL.revokeObjectURL( objectURL );\n\t\t} else {\n\t\t\tobjectURL.remove();\n\t\t}\n\t}, 40000 ); // The revoking time is arbitrary\n\n};\n\n/* ---------------------------------\n@extension: shuffleDOM\n@returns: [list] shuffles a list of items randomly\n-------------------------------- */\nwb.shuffleDOM = function( $elm ) {\n\tvar allElems = $elm.get(),\n\t\tshuffled = $.map( allElems, function() {\n\t\t\tvar random = Math.floor( Math.random() * allElems.length ),\n\t\t\t\trandEl = $( allElems[ random ] ).clone( true )[ 0 ];\n\t\t\tallElems.splice( random, 1 );\n\t\t\treturn randEl;\n\t\t} ),\n\t\telm_len = $elm.length,\n\t\ti;\n\n\tfor ( i = 0; i &amp;lt; elm_len; i++ ) {\n\t\t$( $elm[ i ] ).replaceWith( $( shuffled[ i ] ) );\n\t}\n\n\treturn $( shuffled );\n};\n\n/* ---------------------------------\n@extension: pickElements\n@returns: [collection] of random elements\n-------------------------------- */\nwb.pickElements = function( $elm, numOfElm ) {\n\tvar nbElm = $elm.size(),\n\t\telmCopies,\n\t\ti, swap;\n\n\tnumOfElm = numOfElm || 1;\n\n\t// Special cases\n\tif ( numOfElm &amp;gt; nbElm ) {\n\t\treturn $elm.pushStack( $elm );\n\t} else if ( numOfElm === 1 ) {\n\t\treturn $elm.filter( \":eq(\" + Math.floor( Math.random() * nbElm ) + \")\" );\n\t}\n\n\t// Create a randomized copy of the set of elements,\n\t// using Fisher-Yates sorting\n\telmCopies = $elm.get();\n\n\tfor ( i = 0; i &amp;lt; nbElm - 1; i++ ) {\n\t\tswap = Math.floor( Math.random() * ( nbElm - i ) ) + i;\n\t\telmCopies[ swap ] = elmCopies.splice( i, 1, elmCopies[ swap ] )[ 0 ];\n\t}\n\telmCopies = elmCopies.slice( 0, numOfElm );\n\n\t// Finally, filter jQuery stack\n\treturn $elm.filter( function( idx ) {\n\t\treturn $.inArray( $elm.get( idx ), elmCopies ) &amp;gt; -1;\n\t} );\n};\n\n/* ---------------------------------\nAdds a link to the Skip links navigation\n@param text: Text to display in the anchor or button\n@param attr: JSO with { attribute: value, ... } to add attributes to the anchor or button. Minimum is { href: \"#your-anchor\" } for the anchor tag\n@param isBtn: (Optional) Bool if true element is a button, otherwise it is an anchor by default\n@param isLast: (Optional) Bool if true element will be inserted last in the list\n-------------------------------- */\nwb.addSkipLink = function( text, attr, isBtn, isLast ) {\n\tvar list = document.getElementById( \"wb-tphp\" ),\n\t\tli = document.createElement( \"li\" ),\n\t\telm = document.createElement( ( isBtn ? \"button\" : \"a\" ) ),\n\t\tkey;\n\n\t// Add skip link's proprietary classes to new element\n\tli.className = \"wb-slc\";\n\telm.className = \"wb-sl\";\n\n\t// Add given attributes to element\n\tfor ( key in attr ) {\n\t\telm.setAttribute( key, attr[ key ] );\n\t}\n\n\t// Append text and new element to the skip link list (after main content)\n\telm.appendChild( document.createTextNode( text ) );\n\tli.appendChild( elm );\n\n\tif ( isLast ) {\n\t\tlist.appendChild( li );\n\t} else {\n\t\tlist.insertBefore( li, list.childNodes[ 2 ] );\n\t}\n\n\treturn true;\n};\n\n} )( jQuery, wb );\n\n( function( wb, window ) {\n\n\"use strict\";\n\n// Escapes the characters in a string for use in a jQuery selector\n// Based on https://totaldev.com/content/escaping-characters-get-valid-jquery-id\nwb.jqEscape = function( selector ) {\n\t// eslint-disable-next-line no-useless-escape\n\treturn selector.replace( /([;&amp;amp;,\\.\\+\\*\\~':\"\\\\\\!\\^\\/#$%@\\[\\]\\(\\)=&amp;gt;\\|])/g, \"\\\\$1\" );\n};\n\n// RegEx used by formattedNumCompare\nwb.formattedNumCompareRegEx = /(&amp;lt;[^&amp;gt;]*&amp;gt;|[^\\d.])/g;\n\n// Compares two formatted numbers (e.g., 1.2.12 or 1,000,345)\nwb.formattedNumCompare = function( a, b ) {\n\tvar regEx = wb.formattedNumCompareRegEx,\n\t\taMultiple = a.indexOf( \"-\" ) === -1 ? 1 : -1,\n\t\taNumbers = ( ( a === \"-\" || a === \"\" ) ? \"0\" : a.replace( regEx, \"\" ) ).split( \".\" ),\n\t\tbMultiple = b.indexOf( \"-\" ) === -1 ? 1 : -1,\n\t\tbNumbers = ( ( b === \"-\" || b === \"\" ) ? \"0\" : b.replace( regEx, \"\" ) ).split( \".\" ),\n\t\tlen = aNumbers.length,\n\t\ti, result;\n\n\tfor ( i = 0; i !== len; i += 1 ) {\n\t\tresult = parseInt( aNumbers[ i ], 10 ) * aMultiple - parseInt( bNumbers[ i ], 10 ) * bMultiple;\n\t\tif ( result !== 0 ) {\n\t\t\tbreak;\n\t\t}\n\t}\n\treturn result;\n};\n\n// Compare two strings with special characters (e.g., Cyrillic or Chinese characters)\nwb.i18nTextCompare = function( a, b ) {\n\treturn wb.normalizeDiacritics( a ).localeCompare( wb.normalizeDiacritics( b ) );\n};\n\n// Based upon https://gist.github.com/instanceofme/1731620\n// Licensed under WTFPL v2 http://sam.zoy.org/wtfpl/COPYING\nwb.normalizeDiacritics = function( str ) {\n\tvar diacritics = {\n\t\t\t\"\\u24B6\": \"A\",\n\t\t\t\"\\uFF21\": \"A\",\n\t\t\t\"\\u00C0\": \"A\",\n\t\t\t\"\\u00C1\": \"A\",\n\t\t\t\"\\u00C2\": \"A\",\n\t\t\t\"\\u1EA6\": \"A\",\n\t\t\t\"\\u1EA4\": \"A\",\n\t\t\t\"\\u1EAA\": \"A\",\n\t\t\t\"\\u1EA8\": \"A\",\n\t\t\t\"\\u00C3\": \"A\",\n\t\t\t\"\\u0100\": \"A\",\n\t\t\t\"\\u0102\": \"A\",\n\t\t\t\"\\u1EB0\": \"A\",\n\t\t\t\"\\u1EAE\": \"A\",\n\t\t\t\"\\u1EB4\": \"A\",\n\t\t\t\"\\u1EB2\": \"A\",\n\t\t\t\"\\u0226\": \"A\",\n\t\t\t\"\\u01E0\": \"A\",\n\t\t\t\"\\u00C4\": \"A\",\n\t\t\t\"\\u01DE\": \"A\",\n\t\t\t\"\\u1EA2\": \"A\",\n\t\t\t\"\\u00C5\": \"A\",\n\t\t\t\"\\u01FA\": \"A\",\n\t\t\t\"\\u01CD\": \"A\",\n\t\t\t\"\\u0200\": \"A\",\n\t\t\t\"\\u0202\": \"A\",\n\t\t\t\"\\u1EA0\": \"A\",\n\t\t\t\"\\u1EAC\": \"A\",\n\t\t\t\"\\u1EB6\": \"A\",\n\t\t\t\"\\u1E00\": \"A\",\n\t\t\t\"\\u0104\": \"A\",\n\t\t\t\"\\u023A\": \"A\",\n\t\t\t\"\\u2C6F\": \"A\",\n\t\t\t\"\\uA732\": \"AA\",\n\t\t\t\"\\u00C6\": \"AE\",\n\t\t\t\"\\u01FC\": \"AE\",\n\t\t\t\"\\u01E2\": \"AE\",\n\t\t\t\"\\uA734\": \"AO\",\n\t\t\t\"\\uA736\": \"AU\",\n\t\t\t\"\\uA738\": \"AV\",\n\t\t\t\"\\uA73A\": \"AV\",\n\t\t\t\"\\uA73C\": \"AY\",\n\t\t\t\"\\u24B7\": \"B\",\n\t\t\t\"\\uFF22\": \"B\",\n\t\t\t\"\\u1E02\": \"B\",\n\t\t\t\"\\u1E04\": \"B\",\n\t\t\t\"\\u1E06\": \"B\",\n\t\t\t\"\\u0243\": \"B\",\n\t\t\t\"\\u0182\": \"B\",\n\t\t\t\"\\u0181\": \"B\",\n\t\t\t\"\\u24B8\": \"C\",\n\t\t\t\"\\uFF23\": \"C\",\n\t\t\t\"\\u0106\": \"C\",\n\t\t\t\"\\u0108\": \"C\",\n\t\t\t\"\\u010A\": \"C\",\n\t\t\t\"\\u010C\": \"C\",\n\t\t\t\"\\u00C7\": \"C\",\n\t\t\t\"\\u1E08\": \"C\",\n\t\t\t\"\\u0187\": \"C\",\n\t\t\t\"\\u023B\": \"C\",\n\t\t\t\"\\uA73E\": \"C\",\n\t\t\t\"\\u24B9\": \"D\",\n\t\t\t\"\\uFF24\": \"D\",\n\t\t\t\"\\u1E0A\": \"D\",\n\t\t\t\"\\u010E\": \"D\",\n\t\t\t\"\\u1E0C\": \"D\",\n\t\t\t\"\\u1E10\": \"D\",\n\t\t\t\"\\u1E12\": \"D\",\n\t\t\t\"\\u1E0E\": \"D\",\n\t\t\t\"\\u0110\": \"D\",\n\t\t\t\"\\u018B\": \"D\",\n\t\t\t\"\\u018A\": \"D\",\n\t\t\t\"\\u0189\": \"D\",\n\t\t\t\"\\uA779\": \"D\",\n\t\t\t\"\\u01F1\": \"DZ\",\n\t\t\t\"\\u01C4\": \"DZ\",\n\t\t\t\"\\u01F2\": \"Dz\",\n\t\t\t\"\\u01C5\": \"Dz\",\n\t\t\t\"\\u24BA\": \"E\",\n\t\t\t\"\\uFF25\": \"E\",\n\t\t\t\"\\u00C8\": \"E\",\n\t\t\t\"\\u00C9\": \"E\",\n\t\t\t\"\\u00CA\": \"E\",\n\t\t\t\"\\u1EC0\": \"E\",\n\t\t\t\"\\u1EBE\": \"E\",\n\t\t\t\"\\u1EC4\": \"E\",\n\t\t\t\"\\u1EC2\": \"E\",\n\t\t\t\"\\u1EBC\": \"E\",\n\t\t\t\"\\u0112\": \"E\",\n\t\t\t\"\\u1E14\": \"E\",\n\t\t\t\"\\u1E16\": \"E\",\n\t\t\t\"\\u0114\": \"E\",\n\t\t\t\"\\u0116\": \"E\",\n\t\t\t\"\\u00CB\": \"E\",\n\t\t\t\"\\u1EBA\": \"E\",\n\t\t\t\"\\u011A\": \"E\",\n\t\t\t\"\\u0204\": \"E\",\n\t\t\t\"\\u0206\": \"E\",\n\t\t\t\"\\u1EB8\": \"E\",\n\t\t\t\"\\u1EC6\": \"E\",\n\t\t\t\"\\u0228\": \"E\",\n\t\t\t\"\\u1E1C\": \"E\",\n\t\t\t\"\\u0118\": \"E\",\n\t\t\t\"\\u1E18\": \"E\",\n\t\t\t\"\\u1E1A\": \"E\",\n\t\t\t\"\\u0190\": \"E\",\n\t\t\t\"\\u018E\": \"E\",\n\t\t\t\"\\u24BB\": \"F\",\n\t\t\t\"\\uFF26\": \"F\",\n\t\t\t\"\\u1E1E\": \"F\",\n\t\t\t\"\\u0191\": \"F\",\n\t\t\t\"\\uA77B\": \"F\",\n\t\t\t\"\\u24BC\": \"G\",\n\t\t\t\"\\uFF27\": \"G\",\n\t\t\t\"\\u01F4\": \"G\",\n\t\t\t\"\\u011C\": \"G\",\n\t\t\t\"\\u1E20\": \"G\",\n\t\t\t\"\\u011E\": \"G\",\n\t\t\t\"\\u0120\": \"G\",\n\t\t\t\"\\u01E6\": \"G\",\n\t\t\t\"\\u0122\": \"G\",\n\t\t\t\"\\u01E4\": \"G\",\n\t\t\t\"\\u0193\": \"G\",\n\t\t\t\"\\uA7A0\": \"G\",\n\t\t\t\"\\uA77D\": \"G\",\n\t\t\t\"\\uA77E\": \"G\",\n\t\t\t\"\\u24BD\": \"H\",\n\t\t\t\"\\uFF28\": \"H\",\n\t\t\t\"\\u0124\": \"H\",\n\t\t\t\"\\u1E22\": \"H\",\n\t\t\t\"\\u1E26\": \"H\",\n\t\t\t\"\\u021E\": \"H\",\n\t\t\t\"\\u1E24\": \"H\",\n\t\t\t\"\\u1E28\": \"H\",\n\t\t\t\"\\u1E2A\": \"H\",\n\t\t\t\"\\u0126\": \"H\",\n\t\t\t\"\\u2C67\": \"H\",\n\t\t\t\"\\u2C75\": \"H\",\n\t\t\t\"\\uA78D\": \"H\",\n\t\t\t\"\\u24BE\": \"I\",\n\t\t\t\"\\uFF29\": \"I\",\n\t\t\t\"\\u00CC\": \"I\",\n\t\t\t\"\\u00CD\": \"I\",\n\t\t\t\"\\u00CE\": \"I\",\n\t\t\t\"\\u0128\": \"I\",\n\t\t\t\"\\u012A\": \"I\",\n\t\t\t\"\\u012C\": \"I\",\n\t\t\t\"\\u0130\": \"I\",\n\t\t\t\"\\u00CF\": \"I\",\n\t\t\t\"\\u1E2E\": \"I\",\n\t\t\t\"\\u1EC8\": \"I\",\n\t\t\t\"\\u01CF\": \"I\",\n\t\t\t\"\\u0208\": \"I\",\n\t\t\t\"\\u020A\": \"I\",\n\t\t\t\"\\u1ECA\": \"I\",\n\t\t\t\"\\u012E\": \"I\",\n\t\t\t\"\\u1E2C\": \"I\",\n\t\t\t\"\\u0197\": \"I\",\n\t\t\t\"\\u24BF\": \"J\",\n\t\t\t\"\\uFF2A\": \"J\",\n\t\t\t\"\\u0134\": \"J\",\n\t\t\t\"\\u0248\": \"J\",\n\t\t\t\"\\u24C0\": \"K\",\n\t\t\t\"\\uFF2B\": \"K\",\n\t\t\t\"\\u1E30\": \"K\",\n\t\t\t\"\\u01E8\": \"K\",\n\t\t\t\"\\u1E32\": \"K\",\n\t\t\t\"\\u0136\": \"K\",\n\t\t\t\"\\u1E34\": \"K\",\n\t\t\t\"\\u0198\": \"K\",\n\t\t\t\"\\u2C69\": \"K\",\n\t\t\t\"\\uA740\": \"K\",\n\t\t\t\"\\uA742\": \"K\",\n\t\t\t\"\\uA744\": \"K\",\n\t\t\t\"\\uA7A2\": \"K\",\n\t\t\t\"\\u24C1\": \"L\",\n\t\t\t\"\\uFF2C\": \"L\",\n\t\t\t\"\\u013F\": \"L\",\n\t\t\t\"\\u0139\": \"L\",\n\t\t\t\"\\u013D\": \"L\",\n\t\t\t\"\\u1E36\": \"L\",\n\t\t\t\"\\u1E38\": \"L\",\n\t\t\t\"\\u013B\": \"L\",\n\t\t\t\"\\u1E3C\": \"L\",\n\t\t\t\"\\u1E3A\": \"L\",\n\t\t\t\"\\u0141\": \"L\",\n\t\t\t\"\\u023D\": \"L\",\n\t\t\t\"\\u2C62\": \"L\",\n\t\t\t\"\\u2C60\": \"L\",\n\t\t\t\"\\uA748\": \"L\",\n\t\t\t\"\\uA746\": \"L\",\n\t\t\t\"\\uA780\": \"L\",\n\t\t\t\"\\u01C7\": \"LJ\",\n\t\t\t\"\\u01C8\": \"Lj\",\n\t\t\t\"\\u24C2\": \"M\",\n\t\t\t\"\\uFF2D\": \"M\",\n\t\t\t\"\\u1E3E\": \"M\",\n\t\t\t\"\\u1E40\": \"M\",\n\t\t\t\"\\u1E42\": \"M\",\n\t\t\t\"\\u2C6E\": \"M\",\n\t\t\t\"\\u019C\": \"M\",\n\t\t\t\"\\u24C3\": \"N\",\n\t\t\t\"\\uFF2E\": \"N\",\n\t\t\t\"\\u01F8\": \"N\",\n\t\t\t\"\\u0143\": \"N\",\n\t\t\t\"\\u00D1\": \"N\",\n\t\t\t\"\\u1E44\": \"N\",\n\t\t\t\"\\u0147\": \"N\",\n\t\t\t\"\\u1E46\": \"N\",\n\t\t\t\"\\u0145\": \"N\",\n\t\t\t\"\\u1E4A\": \"N\",\n\t\t\t\"\\u1E48\": \"N\",\n\t\t\t\"\\u0220\": \"N\",\n\t\t\t\"\\u019D\": \"N\",\n\t\t\t\"\\uA790\": \"N\",\n\t\t\t\"\\uA7A4\": \"N\",\n\t\t\t\"\\u01CA\": \"NJ\",\n\t\t\t\"\\u01CB\": \"Nj\",\n\t\t\t\"\\u24C4\": \"O\",\n\t\t\t\"\\uFF2F\": \"O\",\n\t\t\t\"\\u00D2\": \"O\",\n\t\t\t\"\\u00D3\": \"O\",\n\t\t\t\"\\u00D4\": \"O\",\n\t\t\t\"\\u1ED2\": \"O\",\n\t\t\t\"\\u1ED0\": \"O\",\n\t\t\t\"\\u1ED6\": \"O\",\n\t\t\t\"\\u1ED4\": \"O\",\n\t\t\t\"\\u00D5\": \"O\",\n\t\t\t\"\\u1E4C\": \"O\",\n\t\t\t\"\\u022C\": \"O\",\n\t\t\t\"\\u1E4E\": \"O\",\n\t\t\t\"\\u014C\": \"O\",\n\t\t\t\"\\u1E50\": \"O\",\n\t\t\t\"\\u1E52\": \"O\",\n\t\t\t\"\\u014E\": \"O\",\n\t\t\t\"\\u022E\": \"O\",\n\t\t\t\"\\u0230\": \"O\",\n\t\t\t\"\\u00D6\": \"O\",\n\t\t\t\"\\u022A\": \"O\",\n\t\t\t\"\\u1ECE\": \"O\",\n\t\t\t\"\\u0150\": \"O\",\n\t\t\t\"\\u01D1\": \"O\",\n\t\t\t\"\\u020C\": \"O\",\n\t\t\t\"\\u020E\": \"O\",\n\t\t\t\"\\u01A0\": \"O\",\n\t\t\t\"\\u1EDC\": \"O\",\n\t\t\t\"\\u1EDA\": \"O\",\n\t\t\t\"\\u1EE0\": \"O\",\n\t\t\t\"\\u1EDE\": \"O\",\n\t\t\t\"\\u1EE2\": \"O\",\n\t\t\t\"\\u1ECC\": \"O\",\n\t\t\t\"\\u1ED8\": \"O\",\n\t\t\t\"\\u01EA\": \"O\",\n\t\t\t\"\\u01EC\": \"O\",\n\t\t\t\"\\u00D8\": \"O\",\n\t\t\t\"\\u01FE\": \"O\",\n\t\t\t\"\\u0186\": \"O\",\n\t\t\t\"\\u019F\": \"O\",\n\t\t\t\"\\uA74A\": \"O\",\n\t\t\t\"\\uA74C\": \"O\",\n\t\t\t\"\\u0152\": \"OE\",\n\t\t\t\"\\u01A2\": \"OI\",\n\t\t\t\"\\uA74E\": \"OO\",\n\t\t\t\"\\u0222\": \"OU\",\n\t\t\t\"\\u24C5\": \"P\",\n\t\t\t\"\\uFF30\": \"P\",\n\t\t\t\"\\u1E54\": \"P\",\n\t\t\t\"\\u1E56\": \"P\",\n\t\t\t\"\\u01A4\": \"P\",\n\t\t\t\"\\u2C63\": \"P\",\n\t\t\t\"\\uA750\": \"P\",\n\t\t\t\"\\uA752\": \"P\",\n\t\t\t\"\\uA754\": \"P\",\n\t\t\t\"\\u24C6\": \"Q\",\n\t\t\t\"\\uFF31\": \"Q\",\n\t\t\t\"\\uA756\": \"Q\",\n\t\t\t\"\\uA758\": \"Q\",\n\t\t\t\"\\u024A\": \"Q\",\n\t\t\t\"\\u24C7\": \"R\",\n\t\t\t\"\\uFF32\": \"R\",\n\t\t\t\"\\u0154\": \"R\",\n\t\t\t\"\\u1E58\": \"R\",\n\t\t\t\"\\u0158\": \"R\",\n\t\t\t\"\\u0210\": \"R\",\n\t\t\t\"\\u0212\": \"R\",\n\t\t\t\"\\u1E5A\": \"R\",\n\t\t\t\"\\u1E5C\": \"R\",\n\t\t\t\"\\u0156\": \"R\",\n\t\t\t\"\\u1E5E\": \"R\",\n\t\t\t\"\\u024C\": \"R\",\n\t\t\t\"\\u2C64\": \"R\",\n\t\t\t\"\\uA75A\": \"R\",\n\t\t\t\"\\uA7A6\": \"R\",\n\t\t\t\"\\uA782\": \"R\",\n\t\t\t\"\\u24C8\": \"S\",\n\t\t\t\"\\uFF33\": \"S\",\n\t\t\t\"\\u015A\": \"S\",\n\t\t\t\"\\u1E64\": \"S\",\n\t\t\t\"\\u015C\": \"S\",\n\t\t\t\"\\u1E60\": \"S\",\n\t\t\t\"\\u0160\": \"S\",\n\t\t\t\"\\u1E66\": \"S\",\n\t\t\t\"\\u1E62\": \"S\",\n\t\t\t\"\\u1E68\": \"S\",\n\t\t\t\"\\u0218\": \"S\",\n\t\t\t\"\\u015E\": \"S\",\n\t\t\t\"\\u2C7E\": \"S\",\n\t\t\t\"\\uA7A8\": \"S\",\n\t\t\t\"\\uA784\": \"S\",\n\t\t\t\"\\u1E9E\": \"SS\",\n\t\t\t\"\\u24C9\": \"T\",\n\t\t\t\"\\uFF34\": \"T\",\n\t\t\t\"\\u1E6A\": \"T\",\n\t\t\t\"\\u0164\": \"T\",\n\t\t\t\"\\u1E6C\": \"T\",\n\t\t\t\"\\u021A\": \"T\",\n\t\t\t\"\\u0162\": \"T\",\n\t\t\t\"\\u1E70\": \"T\",\n\t\t\t\"\\u1E6E\": \"T\",\n\t\t\t\"\\u0166\": \"T\",\n\t\t\t\"\\u01AC\": \"T\",\n\t\t\t\"\\u01AE\": \"T\",\n\t\t\t\"\\u023E\": \"T\",\n\t\t\t\"\\uA786\": \"T\",\n\t\t\t\"\\uA728\": \"TZ\",\n\t\t\t\"\\u24CA\": \"U\",\n\t\t\t\"\\uFF35\": \"U\",\n\t\t\t\"\\u00D9\": \"U\",\n\t\t\t\"\\u00DA\": \"U\",\n\t\t\t\"\\u00DB\": \"U\",\n\t\t\t\"\\u0168\": \"U\",\n\t\t\t\"\\u1E78\": \"U\",\n\t\t\t\"\\u016A\": \"U\",\n\t\t\t\"\\u1E7A\": \"U\",\n\t\t\t\"\\u016C\": \"U\",\n\t\t\t\"\\u00DC\": \"U\",\n\t\t\t\"\\u01DB\": \"U\",\n\t\t\t\"\\u01D7\": \"U\",\n\t\t\t\"\\u01D5\": \"U\",\n\t\t\t\"\\u01D9\": \"U\",\n\t\t\t\"\\u1EE6\": \"U\",\n\t\t\t\"\\u016E\": \"U\",\n\t\t\t\"\\u0170\": \"U\",\n\t\t\t\"\\u01D3\": \"U\",\n\t\t\t\"\\u0214\": \"U\",\n\t\t\t\"\\u0216\": \"U\",\n\t\t\t\"\\u01AF\": \"U\",\n\t\t\t\"\\u1EEA\": \"U\",\n\t\t\t\"\\u1EE8\": \"U\",\n\t\t\t\"\\u1EEE\": \"U\",\n\t\t\t\"\\u1EEC\": \"U\",\n\t\t\t\"\\u1EF0\": \"U\",\n\t\t\t\"\\u1EE4\": \"U\",\n\t\t\t\"\\u1E72\": \"U\",\n\t\t\t\"\\u0172\": \"U\",\n\t\t\t\"\\u1E76\": \"U\",\n\t\t\t\"\\u1E74\": \"U\",\n\t\t\t\"\\u0244\": \"U\",\n\t\t\t\"\\u24CB\": \"V\",\n\t\t\t\"\\uFF36\": \"V\",\n\t\t\t\"\\u1E7C\": \"V\",\n\t\t\t\"\\u1E7E\": \"V\",\n\t\t\t\"\\u01B2\": \"V\",\n\t\t\t\"\\uA75E\": \"V\",\n\t\t\t\"\\u0245\": \"V\",\n\t\t\t\"\\uA760\": \"VY\",\n\t\t\t\"\\u24CC\": \"W\",\n\t\t\t\"\\uFF37\": \"W\",\n\t\t\t\"\\u1E80\": \"W\",\n\t\t\t\"\\u1E82\": \"W\",\n\t\t\t\"\\u0174\": \"W\",\n\t\t\t\"\\u1E86\": \"W\",\n\t\t\t\"\\u1E84\": \"W\",\n\t\t\t\"\\u1E88\": \"W\",\n\t\t\t\"\\u2C72\": \"W\",\n\t\t\t\"\\u24CD\": \"X\",\n\t\t\t\"\\uFF38\": \"X\",\n\t\t\t\"\\u1E8A\": \"X\",\n\t\t\t\"\\u1E8C\": \"X\",\n\t\t\t\"\\u24CE\": \"Y\",\n\t\t\t\"\\uFF39\": \"Y\",\n\t\t\t\"\\u1EF2\": \"Y\",\n\t\t\t\"\\u00DD\": \"Y\",\n\t\t\t\"\\u0176\": \"Y\",\n\t\t\t\"\\u1EF8\": \"Y\",\n\t\t\t\"\\u0232\": \"Y\",\n\t\t\t\"\\u1E8E\": \"Y\",\n\t\t\t\"\\u0178\": \"Y\",\n\t\t\t\"\\u1EF6\": \"Y\",\n\t\t\t\"\\u1EF4\": \"Y\",\n\t\t\t\"\\u01B3\": \"Y\",\n\t\t\t\"\\u024E\": \"Y\",\n\t\t\t\"\\u1EFE\": \"Y\",\n\t\t\t\"\\u24CF\": \"Z\",\n\t\t\t\"\\uFF3A\": \"Z\",\n\t\t\t\"\\u0179\": \"Z\",\n\t\t\t\"\\u1E90\": \"Z\",\n\t\t\t\"\\u017B\": \"Z\",\n\t\t\t\"\\u017D\": \"Z\",\n\t\t\t\"\\u1E92\": \"Z\",\n\t\t\t\"\\u1E94\": \"Z\",\n\t\t\t\"\\u01B5\": \"Z\",\n\t\t\t\"\\u0224\": \"Z\",\n\t\t\t\"\\u2C7F\": \"Z\",\n\t\t\t\"\\u2C6B\": \"Z\",\n\t\t\t\"\\uA762\": \"Z\",\n\t\t\t\"\\u24D0\": \"a\",\n\t\t\t\"\\uFF41\": \"a\",\n\t\t\t\"\\u1E9A\": \"a\",\n\t\t\t\"\\u00E0\": \"a\",\n\t\t\t\"\\u00E1\": \"a\",\n\t\t\t\"\\u00E2\": \"a\",\n\t\t\t\"\\u1EA7\": \"a\",\n\t\t\t\"\\u1EA5\": \"a\",\n\t\t\t\"\\u1EAB\": \"a\",\n\t\t\t\"\\u1EA9\": \"a\",\n\t\t\t\"\\u00E3\": \"a\",\n\t\t\t\"\\u0101\": \"a\",\n\t\t\t\"\\u0103\": \"a\",\n\t\t\t\"\\u1EB1\": \"a\",\n\t\t\t\"\\u1EAF\": \"a\",\n\t\t\t\"\\u1EB5\": \"a\",\n\t\t\t\"\\u1EB3\": \"a\",\n\t\t\t\"\\u0227\": \"a\",\n\t\t\t\"\\u01E1\": \"a\",\n\t\t\t\"\\u00E4\": \"a\",\n\t\t\t\"\\u01DF\": \"a\",\n\t\t\t\"\\u1EA3\": \"a\",\n\t\t\t\"\\u00E5\": \"a\",\n\t\t\t\"\\u01FB\": \"a\",\n\t\t\t\"\\u01CE\": \"a\",\n\t\t\t\"\\u0201\": \"a\",\n\t\t\t\"\\u0203\": \"a\",\n\t\t\t\"\\u1EA1\": \"a\",\n\t\t\t\"\\u1EAD\": \"a\",\n\t\t\t\"\\u1EB7\": \"a\",\n\t\t\t\"\\u1E01\": \"a\",\n\t\t\t\"\\u0105\": \"a\",\n\t\t\t\"\\u2C65\": \"a\",\n\t\t\t\"\\u0250\": \"a\",\n\t\t\t\"\\uA733\": \"aa\",\n\t\t\t\"\\u00E6\": \"ae\",\n\t\t\t\"\\u01FD\": \"ae\",\n\t\t\t\"\\u01E3\": \"ae\",\n\t\t\t\"\\uA735\": \"ao\",\n\t\t\t\"\\uA737\": \"au\",\n\t\t\t\"\\uA739\": \"av\",\n\t\t\t\"\\uA73B\": \"av\",\n\t\t\t\"\\uA73D\": \"ay\",\n\t\t\t\"\\u24D1\": \"b\",\n\t\t\t\"\\uFF42\": \"b\",\n\t\t\t\"\\u1E03\": \"b\",\n\t\t\t\"\\u1E05\": \"b\",\n\t\t\t\"\\u1E07\": \"b\",\n\t\t\t\"\\u0180\": \"b\",\n\t\t\t\"\\u0183\": \"b\",\n\t\t\t\"\\u0253\": \"b\",\n\t\t\t\"\\u24D2\": \"c\",\n\t\t\t\"\\uFF43\": \"c\",\n\t\t\t\"\\u0107\": \"c\",\n\t\t\t\"\\u0109\": \"c\",\n\t\t\t\"\\u010B\": \"c\",\n\t\t\t\"\\u010D\": \"c\",\n\t\t\t\"\\u00E7\": \"c\",\n\t\t\t\"\\u1E09\": \"c\",\n\t\t\t\"\\u0188\": \"c\",\n\t\t\t\"\\u023C\": \"c\",\n\t\t\t\"\\uA73F\": \"c\",\n\t\t\t\"\\u2184\": \"c\",\n\t\t\t\"\\u24D3\": \"d\",\n\t\t\t\"\\uFF44\": \"d\",\n\t\t\t\"\\u1E0B\": \"d\",\n\t\t\t\"\\u010F\": \"d\",\n\t\t\t\"\\u1E0D\": \"d\",\n\t\t\t\"\\u1E11\": \"d\",\n\t\t\t\"\\u1E13\": \"d\",\n\t\t\t\"\\u1E0F\": \"d\",\n\t\t\t\"\\u0111\": \"d\",\n\t\t\t\"\\u018C\": \"d\",\n\t\t\t\"\\u0256\": \"d\",\n\t\t\t\"\\u0257\": \"d\",\n\t\t\t\"\\uA77A\": \"d\",\n\t\t\t\"\\u01F3\": \"dz\",\n\t\t\t\"\\u01C6\": \"dz\",\n\t\t\t\"\\u24D4\": \"e\",\n\t\t\t\"\\uFF45\": \"e\",\n\t\t\t\"\\u00E8\": \"e\",\n\t\t\t\"\\u00E9\": \"e\",\n\t\t\t\"\\u00EA\": \"e\",\n\t\t\t\"\\u1EC1\": \"e\",\n\t\t\t\"\\u1EBF\": \"e\",\n\t\t\t\"\\u1EC5\": \"e\",\n\t\t\t\"\\u1EC3\": \"e\",\n\t\t\t\"\\u1EBD\": \"e\",\n\t\t\t\"\\u0113\": \"e\",\n\t\t\t\"\\u1E15\": \"e\",\n\t\t\t\"\\u1E17\": \"e\",\n\t\t\t\"\\u0115\": \"e\",\n\t\t\t\"\\u0117\": \"e\",\n\t\t\t\"\\u00EB\": \"e\",\n\t\t\t\"\\u1EBB\": \"e\",\n\t\t\t\"\\u011B\": \"e\",\n\t\t\t\"\\u0205\": \"e\",\n\t\t\t\"\\u0207\": \"e\",\n\t\t\t\"\\u1EB9\": \"e\",\n\t\t\t\"\\u1EC7\": \"e\",\n\t\t\t\"\\u0229\": \"e\",\n\t\t\t\"\\u1E1D\": \"e\",\n\t\t\t\"\\u0119\": \"e\",\n\t\t\t\"\\u1E19\": \"e\",\n\t\t\t\"\\u1E1B\": \"e\",\n\t\t\t\"\\u0247\": \"e\",\n\t\t\t\"\\u025B\": \"e\",\n\t\t\t\"\\u01DD\": \"e\",\n\t\t\t\"\\u24D5\": \"f\",\n\t\t\t\"\\uFF46\": \"f\",\n\t\t\t\"\\u1E1F\": \"f\",\n\t\t\t\"\\u0192\": \"f\",\n\t\t\t\"\\uA77C\": \"f\",\n\t\t\t\"\\u24D6\": \"g\",\n\t\t\t\"\\uFF47\": \"g\",\n\t\t\t\"\\u01F5\": \"g\",\n\t\t\t\"\\u011D\": \"g\",\n\t\t\t\"\\u1E21\": \"g\",\n\t\t\t\"\\u011F\": \"g\",\n\t\t\t\"\\u0121\": \"g\",\n\t\t\t\"\\u01E7\": \"g\",\n\t\t\t\"\\u0123\": \"g\",\n\t\t\t\"\\u01E5\": \"g\",\n\t\t\t\"\\u0260\": \"g\",\n\t\t\t\"\\uA7A1\": \"g\",\n\t\t\t\"\\u1D79\": \"g\",\n\t\t\t\"\\uA77F\": \"g\",\n\t\t\t\"\\u24D7\": \"h\",\n\t\t\t\"\\uFF48\": \"h\",\n\t\t\t\"\\u0125\": \"h\",\n\t\t\t\"\\u1E23\": \"h\",\n\t\t\t\"\\u1E27\": \"h\",\n\t\t\t\"\\u021F\": \"h\",\n\t\t\t\"\\u1E25\": \"h\",\n\t\t\t\"\\u1E29\": \"h\",\n\t\t\t\"\\u1E2B\": \"h\",\n\t\t\t\"\\u1E96\": \"h\",\n\t\t\t\"\\u0127\": \"h\",\n\t\t\t\"\\u2C68\": \"h\",\n\t\t\t\"\\u2C76\": \"h\",\n\t\t\t\"\\u0265\": \"h\",\n\t\t\t\"\\u0195\": \"hv\",\n\t\t\t\"\\u24D8\": \"i\",\n\t\t\t\"\\uFF49\": \"i\",\n\t\t\t\"\\u00EC\": \"i\",\n\t\t\t\"\\u00ED\": \"i\",\n\t\t\t\"\\u00EE\": \"i\",\n\t\t\t\"\\u0129\": \"i\",\n\t\t\t\"\\u012B\": \"i\",\n\t\t\t\"\\u012D\": \"i\",\n\t\t\t\"\\u00EF\": \"i\",\n\t\t\t\"\\u1E2F\": \"i\",\n\t\t\t\"\\u1EC9\": \"i\",\n\t\t\t\"\\u01D0\": \"i\",\n\t\t\t\"\\u0209\": \"i\",\n\t\t\t\"\\u020B\": \"i\",\n\t\t\t\"\\u1ECB\": \"i\",\n\t\t\t\"\\u012F\": \"i\",\n\t\t\t\"\\u1E2D\": \"i\",\n\t\t\t\"\\u0268\": \"i\",\n\t\t\t\"\\u0131\": \"i\",\n\t\t\t\"\\u24D9\": \"j\",\n\t\t\t\"\\uFF4A\": \"j\",\n\t\t\t\"\\u0135\": \"j\",\n\t\t\t\"\\u01F0\": \"j\",\n\t\t\t\"\\u0249\": \"j\",\n\t\t\t\"\\u24DA\": \"k\",\n\t\t\t\"\\uFF4B\": \"k\",\n\t\t\t\"\\u1E31\": \"k\",\n\t\t\t\"\\u01E9\": \"k\",\n\t\t\t\"\\u1E33\": \"k\",\n\t\t\t\"\\u0137\": \"k\",\n\t\t\t\"\\u1E35\": \"k\",\n\t\t\t\"\\u0199\": \"k\",\n\t\t\t\"\\u2C6A\": \"k\",\n\t\t\t\"\\uA741\": \"k\",\n\t\t\t\"\\uA743\": \"k\",\n\t\t\t\"\\uA745\": \"k\",\n\t\t\t\"\\uA7A3\": \"k\",\n\t\t\t\"\\u24DB\": \"l\",\n\t\t\t\"\\uFF4C\": \"l\",\n\t\t\t\"\\u0140\": \"l\",\n\t\t\t\"\\u013A\": \"l\",\n\t\t\t\"\\u013E\": \"l\",\n\t\t\t\"\\u1E37\": \"l\",\n\t\t\t\"\\u1E39\": \"l\",\n\t\t\t\"\\u013C\": \"l\",\n\t\t\t\"\\u1E3D\": \"l\",\n\t\t\t\"\\u1E3B\": \"l\",\n\t\t\t\"\\u0142\": \"l\",\n\t\t\t\"\\u019A\": \"l\",\n\t\t\t\"\\u026B\": \"l\",\n\t\t\t\"\\u2C61\": \"l\",\n\t\t\t\"\\uA749\": \"l\",\n\t\t\t\"\\uA781\": \"l\",\n\t\t\t\"\\uA747\": \"l\",\n\t\t\t\"\\u01C9\": \"lj\",\n\t\t\t\"\\u24DC\": \"m\",\n\t\t\t\"\\uFF4D\": \"m\",\n\t\t\t\"\\u1E3F\": \"m\",\n\t\t\t\"\\u1E41\": \"m\",\n\t\t\t\"\\u1E43\": \"m\",\n\t\t\t\"\\u0271\": \"m\",\n\t\t\t\"\\u026F\": \"m\",\n\t\t\t\"\\u24DD\": \"n\",\n\t\t\t\"\\uFF4E\": \"n\",\n\t\t\t\"\\u01F9\": \"n\",\n\t\t\t\"\\u0144\": \"n\",\n\t\t\t\"\\u00F1\": \"n\",\n\t\t\t\"\\u1E45\": \"n\",\n\t\t\t\"\\u0148\": \"n\",\n\t\t\t\"\\u1E47\": \"n\",\n\t\t\t\"\\u0146\": \"n\",\n\t\t\t\"\\u1E4B\": \"n\",\n\t\t\t\"\\u1E49\": \"n\",\n\t\t\t\"\\u019E\": \"n\",\n\t\t\t\"\\u0272\": \"n\",\n\t\t\t\"\\u0149\": \"n\",\n\t\t\t\"\\uA791\": \"n\",\n\t\t\t\"\\uA7A5\": \"n\",\n\t\t\t\"\\u01CC\": \"nj\",\n\t\t\t\"\\u24DE\": \"o\",\n\t\t\t\"\\uFF4F\": \"o\",\n\t\t\t\"\\u00F2\": \"o\",\n\t\t\t\"\\u00F3\": \"o\",\n\t\t\t\"\\u00F4\": \"o\",\n\t\t\t\"\\u1ED3\": \"o\",\n\t\t\t\"\\u1ED1\": \"o\",\n\t\t\t\"\\u1ED7\": \"o\",\n\t\t\t\"\\u1ED5\": \"o\",\n\t\t\t\"\\u00F5\": \"o\",\n\t\t\t\"\\u1E4D\": \"o\",\n\t\t\t\"\\u022D\": \"o\",\n\t\t\t\"\\u1E4F\": \"o\",\n\t\t\t\"\\u014D\": \"o\",\n\t\t\t\"\\u1E51\": \"o\",\n\t\t\t\"\\u1E53\": \"o\",\n\t\t\t\"\\u014F\": \"o\",\n\t\t\t\"\\u022F\": \"o\",\n\t\t\t\"\\u0231\": \"o\",\n\t\t\t\"\\u00F6\": \"o\",\n\t\t\t\"\\u022B\": \"o\",\n\t\t\t\"\\u1ECF\": \"o\",\n\t\t\t\"\\u0151\": \"o\",\n\t\t\t\"\\u01D2\": \"o\",\n\t\t\t\"\\u020D\": \"o\",\n\t\t\t\"\\u020F\": \"o\",\n\t\t\t\"\\u01A1\": \"o\",\n\t\t\t\"\\u1EDD\": \"o\",\n\t\t\t\"\\u1EDB\": \"o\",\n\t\t\t\"\\u1EE1\": \"o\",\n\t\t\t\"\\u1EDF\": \"o\",\n\t\t\t\"\\u1EE3\": \"o\",\n\t\t\t\"\\u1ECD\": \"o\",\n\t\t\t\"\\u1ED9\": \"o\",\n\t\t\t\"\\u01EB\": \"o\",\n\t\t\t\"\\u01ED\": \"o\",\n\t\t\t\"\\u00F8\": \"o\",\n\t\t\t\"\\u01FF\": \"o\",\n\t\t\t\"\\u0254\": \"o\",\n\t\t\t\"\\uA74B\": \"o\",\n\t\t\t\"\\uA74D\": \"o\",\n\t\t\t\"\\u0275\": \"o\",\n\t\t\t\"\\u0153\": \"oe\",\n\t\t\t\"\\u0276\": \"oe\",\n\t\t\t\"\\u01A3\": \"oi\",\n\t\t\t\"\\u0223\": \"ou\",\n\t\t\t\"\\uA74F\": \"oo\",\n\t\t\t\"\\u24DF\": \"p\",\n\t\t\t\"\\uFF50\": \"p\",\n\t\t\t\"\\u1E55\": \"p\",\n\t\t\t\"\\u1E57\": \"p\",\n\t\t\t\"\\u01A5\": \"p\",\n\t\t\t\"\\u1D7D\": \"p\",\n\t\t\t\"\\uA751\": \"p\",\n\t\t\t\"\\uA753\": \"p\",\n\t\t\t\"\\uA755\": \"p\",\n\t\t\t\"\\u24E0\": \"q\",\n\t\t\t\"\\uFF51\": \"q\",\n\t\t\t\"\\u024B\": \"q\",\n\t\t\t\"\\uA757\": \"q\",\n\t\t\t\"\\uA759\": \"q\",\n\t\t\t\"\\u24E1\": \"r\",\n\t\t\t\"\\uFF52\": \"r\",\n\t\t\t\"\\u0155\": \"r\",\n\t\t\t\"\\u1E59\": \"r\",\n\t\t\t\"\\u0159\": \"r\",\n\t\t\t\"\\u0211\": \"r\",\n\t\t\t\"\\u0213\": \"r\",\n\t\t\t\"\\u1E5B\": \"r\",\n\t\t\t\"\\u1E5D\": \"r\",\n\t\t\t\"\\u0157\": \"r\",\n\t\t\t\"\\u1E5F\": \"r\",\n\t\t\t\"\\u024D\": \"r\",\n\t\t\t\"\\u027D\": \"r\",\n\t\t\t\"\\uA75B\": \"r\",\n\t\t\t\"\\uA7A7\": \"r\",\n\t\t\t\"\\uA783\": \"r\",\n\t\t\t\"\\u24E2\": \"s\",\n\t\t\t\"\\uFF53\": \"s\",\n\t\t\t\"\\u015B\": \"s\",\n\t\t\t\"\\u1E65\": \"s\",\n\t\t\t\"\\u015D\": \"s\",\n\t\t\t\"\\u1E61\": \"s\",\n\t\t\t\"\\u0161\": \"s\",\n\t\t\t\"\\u1E67\": \"s\",\n\t\t\t\"\\u1E63\": \"s\",\n\t\t\t\"\\u1E69\": \"s\",\n\t\t\t\"\\u0219\": \"s\",\n\t\t\t\"\\u015F\": \"s\",\n\t\t\t\"\\u023F\": \"s\",\n\t\t\t\"\\uA7A9\": \"s\",\n\t\t\t\"\\uA785\": \"s\",\n\t\t\t\"\\u017F\": \"s\",\n\t\t\t\"\\u1E9B\": \"s\",\n\t\t\t\"\\u00DF\": \"ss\",\n\t\t\t\"\\u24E3\": \"t\",\n\t\t\t\"\\uFF54\": \"t\",\n\t\t\t\"\\u1E6B\": \"t\",\n\t\t\t\"\\u1E97\": \"t\",\n\t\t\t\"\\u0165\": \"t\",\n\t\t\t\"\\u1E6D\": \"t\",\n\t\t\t\"\\u021B\": \"t\",\n\t\t\t\"\\u0163\": \"t\",\n\t\t\t\"\\u1E71\": \"t\",\n\t\t\t\"\\u1E6F\": \"t\",\n\t\t\t\"\\u0167\": \"t\",\n\t\t\t\"\\u01AD\": \"t\",\n\t\t\t\"\\u0288\": \"t\",\n\t\t\t\"\\u2C66\": \"t\",\n\t\t\t\"\\uA787\": \"t\",\n\t\t\t\"\\uA729\": \"tz\",\n\t\t\t\"\\u24E4\": \"u\",\n\t\t\t\"\\uFF55\": \"u\",\n\t\t\t\"\\u00F9\": \"u\",\n\t\t\t\"\\u00FA\": \"u\",\n\t\t\t\"\\u00FB\": \"u\",\n\t\t\t\"\\u0169\": \"u\",\n\t\t\t\"\\u1E79\": \"u\",\n\t\t\t\"\\u016B\": \"u\",\n\t\t\t\"\\u1E7B\": \"u\",\n\t\t\t\"\\u016D\": \"u\",\n\t\t\t\"\\u00FC\": \"u\",\n\t\t\t\"\\u01DC\": \"u\",\n\t\t\t\"\\u01D8\": \"u\",\n\t\t\t\"\\u01D6\": \"u\",\n\t\t\t\"\\u01DA\": \"u\",\n\t\t\t\"\\u1EE7\": \"u\",\n\t\t\t\"\\u016F\": \"u\",\n\t\t\t\"\\u0171\": \"u\",\n\t\t\t\"\\u01D4\": \"u\",\n\t\t\t\"\\u0215\": \"u\",\n\t\t\t\"\\u0217\": \"u\",\n\t\t\t\"\\u01B0\": \"u\",\n\t\t\t\"\\u1EEB\": \"u\",\n\t\t\t\"\\u1EE9\": \"u\",\n\t\t\t\"\\u1EEF\": \"u\",\n\t\t\t\"\\u1EED\": \"u\",\n\t\t\t\"\\u1EF1\": \"u\",\n\t\t\t\"\\u1EE5\": \"u\",\n\t\t\t\"\\u1E73\": \"u\",\n\t\t\t\"\\u0173\": \"u\",\n\t\t\t\"\\u1E77\": \"u\",\n\t\t\t\"\\u1E75\": \"u\",\n\t\t\t\"\\u0289\": \"u\",\n\t\t\t\"\\u24E5\": \"v\",\n\t\t\t\"\\uFF56\": \"v\",\n\t\t\t\"\\u1E7D\": \"v\",\n\t\t\t\"\\u1E7F\": \"v\",\n\t\t\t\"\\u028B\": \"v\",\n\t\t\t\"\\uA75F\": \"v\",\n\t\t\t\"\\u028C\": \"v\",\n\t\t\t\"\\uA761\": \"vy\",\n\t\t\t\"\\u24E6\": \"w\",\n\t\t\t\"\\uFF57\": \"w\",\n\t\t\t\"\\u1E81\": \"w\",\n\t\t\t\"\\u1E83\": \"w\",\n\t\t\t\"\\u0175\": \"w\",\n\t\t\t\"\\u1E87\": \"w\",\n\t\t\t\"\\u1E85\": \"w\",\n\t\t\t\"\\u1E98\": \"w\",\n\t\t\t\"\\u1E89\": \"w\",\n\t\t\t\"\\u2C73\": \"w\",\n\t\t\t\"\\u24E7\": \"x\",\n\t\t\t\"\\uFF58\": \"x\",\n\t\t\t\"\\u1E8B\": \"x\",\n\t\t\t\"\\u1E8D\": \"x\",\n\t\t\t\"\\u24E8\": \"y\",\n\t\t\t\"\\uFF59\": \"y\",\n\t\t\t\"\\u1EF3\": \"y\",\n\t\t\t\"\\u00FD\": \"y\",\n\t\t\t\"\\u0177\": \"y\",\n\t\t\t\"\\u1EF9\": \"y\",\n\t\t\t\"\\u0233\": \"y\",\n\t\t\t\"\\u1E8F\": \"y\",\n\t\t\t\"\\u00FF\": \"y\",\n\t\t\t\"\\u1EF7\": \"y\",\n\t\t\t\"\\u1E99\": \"y\",\n\t\t\t\"\\u1EF5\": \"y\",\n\t\t\t\"\\u01B4\": \"y\",\n\t\t\t\"\\u024F\": \"y\",\n\t\t\t\"\\u1EFF\": \"y\",\n\t\t\t\"\\u24E9\": \"z\",\n\t\t\t\"\\uFF5A\": \"z\",\n\t\t\t\"\\u017A\": \"z\",\n\t\t\t\"\\u1E91\": \"z\",\n\t\t\t\"\\u017C\": \"z\",\n\t\t\t\"\\u017E\": \"z\",\n\t\t\t\"\\u1E93\": \"z\",\n\t\t\t\"\\u1E95\": \"z\",\n\t\t\t\"\\u01B6\": \"z\",\n\t\t\t\"\\u0225\": \"z\",\n\t\t\t\"\\u0240\": \"z\",\n\t\t\t\"\\u2C6C\": \"z\",\n\t\t\t\"\\uA763\": \"z\",\n\t\t\t\"\\uFF10\": \"0\",\n\t\t\t\"\\u2080\": \"0\",\n\t\t\t\"\\u24EA\": \"0\",\n\t\t\t\"\\u2070\": \"0\",\n\t\t\t\"\\u00B9\": \"1\",\n\t\t\t\"\\u2474\": \"1\",\n\t\t\t\"\\u2081\": \"1\",\n\t\t\t\"\\u2776\": \"1\",\n\t\t\t\"\\u24F5\": \"1\",\n\t\t\t\"\\u2488\": \"1\",\n\t\t\t\"\\u2460\": \"1\",\n\t\t\t\"\\uFF11\": \"1\",\n\t\t\t\"\\u00B2\": \"2\",\n\t\t\t\"\\u2777\": \"2\",\n\t\t\t\"\\u2475\": \"2\",\n\t\t\t\"\\uFF12\": \"2\",\n\t\t\t\"\\u2082\": \"2\",\n\t\t\t\"\\u24F6\": \"2\",\n\t\t\t\"\\u2461\": \"2\",\n\t\t\t\"\\u2489\": \"2\",\n\t\t\t\"\\u00B3\": \"3\",\n\t\t\t\"\\uFF13\": \"3\",\n\t\t\t\"\\u248A\": \"3\",\n\t\t\t\"\\u2476\": \"3\",\n\t\t\t\"\\u2083\": \"3\",\n\t\t\t\"\\u2778\": \"3\",\n\t\t\t\"\\u24F7\": \"3\",\n\t\t\t\"\\u2462\": \"3\",\n\t\t\t\"\\u24F8\": \"4\",\n\t\t\t\"\\u2463\": \"4\",\n\t\t\t\"\\u248B\": \"4\",\n\t\t\t\"\\uFF14\": \"4\",\n\t\t\t\"\\u2074\": \"4\",\n\t\t\t\"\\u2084\": \"4\",\n\t\t\t\"\\u2779\": \"4\",\n\t\t\t\"\\u2477\": \"4\",\n\t\t\t\"\\u248C\": \"5\",\n\t\t\t\"\\u2085\": \"5\",\n\t\t\t\"\\u24F9\": \"5\",\n\t\t\t\"\\u2478\": \"5\",\n\t\t\t\"\\u277A\": \"5\",\n\t\t\t\"\\u2464\": \"5\",\n\t\t\t\"\\uFF15\": \"5\",\n\t\t\t\"\\u2075\": \"5\",\n\t\t\t\"\\u2479\": \"6\",\n\t\t\t\"\\u2076\": \"6\",\n\t\t\t\"\\uFF16\": \"6\",\n\t\t\t\"\\u277B\": \"6\",\n\t\t\t\"\\u2086\": \"6\",\n\t\t\t\"\\u2465\": \"6\",\n\t\t\t\"\\u24FA\": \"6\",\n\t\t\t\"\\u248D\": \"6\",\n\t\t\t\"\\uFF17\": \"7\",\n\t\t\t\"\\u2077\": \"7\",\n\t\t\t\"\\u277C\": \"7\",\n\t\t\t\"\\u24FB\": \"7\",\n\t\t\t\"\\u248E\": \"7\",\n\t\t\t\"\\u2087\": \"7\",\n\t\t\t\"\\u247A\": \"7\",\n\t\t\t\"\\u2466\": \"7\",\n\t\t\t\"\\u2467\": \"8\",\n\t\t\t\"\\u248F\": \"8\",\n\t\t\t\"\\u24FC\": \"8\",\n\t\t\t\"\\u247B\": \"8\",\n\t\t\t\"\\u2078\": \"8\",\n\t\t\t\"\\uFF18\": \"8\",\n\t\t\t\"\\u277D\": \"8\",\n\t\t\t\"\\u2088\": \"8\",\n\t\t\t\"\\u24FD\": \"9\",\n\t\t\t\"\\uFF19\": \"9\",\n\t\t\t\"\\u2490\": \"9\",\n\t\t\t\"\\u277E\": \"9\",\n\t\t\t\"\\u247C\": \"9\",\n\t\t\t\"\\u2089\": \"9\",\n\t\t\t\"\\u2468\": \"9\",\n\t\t\t\"\\u2079\": \"9\"\n\t\t},\n\t\tchars = str.split( \"\" ),\n\t\tlen = chars.length,\n\t\tnormalized = false,\n\t\ti, character;\n\tfor ( i = 0; i !== len; i += 1 ) {\n\t\tcharacter = chars[ i ];\n\t\tif ( Object.prototype.hasOwnProperty.call( diacritics, character ) ) {\n\t\t\tchars[ i ] = diacritics[ character ];\n\t\t\tnormalized = true;\n\t\t}\n\t}\n\treturn ( normalized ? chars.join( \"\" ) : str );\n};\n\n/**\n * @namespace wb.string\n */\nwb.string = {\n\n\t/*\n\t * Left-pads a number with zeros.\n\t * @memberof wb.string\n\t * @param {number} number The original number to pad.\n\t * @param {number} length The width of the resulting padded number, not the number of zeros to add to the front of the string.\n\t * @return {string} The padded string\n\t */\n\tpad: function( number, length ) {\n\t\tvar str = number + \"\",\n\t\t\tdiff = length - str.length,\n\t\t\ti;\n\t\tfor ( i = 0; i !== diff; i += 1 ) {\n\t\t\tstr = \"0\" + str;\n\t\t}\n\t\treturn str;\n\t},\n\n\t/*\n\t * Convert a base64 string into an ArrayBuffer (Note: this function are not fully UTF-8 supported and may create interoperability issue)\n\t * ref. https://www.isummation.com/blog/convert-arraybuffer-to-base64-string-and-vice-versa/\n\t * @memberof wb.string\n\t * @param {string} Base64 browser encoded\n\t * @return {ArrayBuffer} string converted into ArrayBuffer\n\t */\n\tbase64ToArrayBuffer: function( base64 ) {\n\t\tvar binary_string = window.atob( base64 ),\n\t\t\tlen = binary_string.length,\n\t\t\tbytes = new Uint8Array( len ),\n\t\t\ti;\n\t\tfor ( i = 0; i &amp;lt; len; i++ ) {\n\t\t\tbytes[ i ] = binary_string.charCodeAt( i );\n\t\t}\n\t\treturn bytes.buffer;\n\t},\n\n\t/*\n\t * Convert an ArrayBuffer into base64 string (Note: this function are not fully UTF-8 supported and may create interoperability issue)\n\t * ref. https://www.isummation.com/blog/convert-arraybuffer-to-base64-string-and-vice-versa/\n\t * @memberof wb.string\n\t * @param {ArrayBuffer}\n\t * @return {string} ArrayBuffer converted into base64 string\n\t */\n\tarrayBufferToBase64: function( buffer ) {\n\t\tvar binary = \"\",\n\t\t\tbytes = new Uint8Array( buffer ),\n\t\t\tlen = bytes.byteLength,\n\t\t\ti;\n\t\tfor ( i = 0; i &amp;lt; len; i++ ) {\n\t\t\tbinary += String.fromCharCode( bytes[ i ] );\n\t\t}\n\t\treturn window.btoa( binary );\n\t},\n\n\t/*\n\t * Convert an hexadecimal string into an ArrayBuffer\n\t * ref. https://stackoverflow.com/questions/38987784/how-to-convert-a-hexadecimal-string-to-uint8array-and-back-in-javascript/50868276#50868276\n\t * @memberof wb.string\n\t * @param {string} Encoded string in hexadecimal\n\t * @return {Uint8Array} Binary array buffer\n\t */\n\tfromHexString: function( hexString ) {\n\t\treturn hexString === null ? null : Uint8Array.from( hexString.match( /.{1,2}/g ).map( function( byte ) {\n\t\t\treturn parseInt( byte, 16 );\n\t\t} ) );\n\t},\n\n\t/*\n\t * Convert an ArrayBuffer into an hexadecimal string\n\t * ref. https://stackoverflow.com/questions/38987784/how-to-convert-a-hexadecimal-string-to-uint8array-and-back-in-javascript/50868276#50868276\n\t * @memberof wb.string\n\t * @param {Uint8Array} Binary array buffer\n\t * @return {string} Encoded string in hexadecimal\n\t */\n\ttoHexString: function( bytes ) {\n\t\treturn bytes.reduce( function( str, byte ) {\n\t\t\treturn str + byte.toString( 16 ).padStart( 2, \"0\" );\n\t\t}, \"\" );\n\t}\n\n};\n\n/*\n * A suite of date related functions for easier parsing of dates\n * @namespace wb.date\n */\nwb.date = {\n\n\t/*\n\t * Converts the date to a date-object. The input can be:\n\t * \n\n\t * \na Date object: returned without modification.\n\t * \nan array: Interpreted as [year,month,day]. NOTE: month is 0-11.\n\t * \na number: Interpreted as number of milliseconds since 1 Jan 1970 (a timestamp).\n\t * \na string: Any format supported by the javascript engine, like 'YYYY/MM/DD', 'MM/DD/YYYY', 'Jan 31 2009' etc.\n\t * \nan object: Interpreted as an object with year, month and date attributes. **NOTE** month is 0-11.\n\t * \n\t * @memberof wb.date\n\t * @param {Date | number[] | number | string | object} dateValue\n\t * @return {Date | NaN}\n\t */\n\tconvert: function( dateValue ) {\n\t\tvar dateConstructor = dateValue.constructor;\n\n\t\tswitch ( dateConstructor ) {\n\t\t\tcase Date:\n\t\t\t\treturn dateConstructor;\n\t\t\tcase Array:\n\t\t\t\treturn new Date( dateValue[ 0 ], dateValue[ 1 ], dateValue[ 2 ] );\n\t\t\tcase Number:\n\t\t\tcase String:\n\t\t\t\treturn new Date( dateValue );\n\t\t\tdefault:\n\t\t\t\treturn typeof dateValue === \"object\" ? new Date( dateValue.year, dateValue.month, dateValue.date ) : NaN;\n\t\t}\n\t},\n\n\t/*\n\t * Compares two dates (input can be any type supported by the convert function).\n\t * @memberof wb.date\n\t * @param {Date | number[] | number | string | object} dateValue1\n\t * @param {Date | number[] | number | string | object} dateValue2\n\t * @return {number | NaN}\n\t * @example returns\n\t * -1 if dateValue1 &amp;lt; dateValue2\n\t * 0 if dateValue1 = dateValue2\n\t * 1 if dateValue1 &amp;gt; dateValue2\n\t * NaN if dateValue1 or dateValue2 is an illegal date\n\t */\n\tcompare: function( dateValue1, dateValue2 ) {\n\t\tvar convert = wb.date.convert;\n\n\t\tif ( isFinite( dateValue1 = convert( dateValue1 ).valueOf() ) &amp;amp;&amp;amp; isFinite( dateValue2 = convert( dateValue2 ).valueOf() ) ) {\n\t\t\treturn ( dateValue1 &amp;gt; dateValue2 ) - ( dateValue1 &amp;lt; dateValue2 );\n\t\t}\n\t\treturn NaN;\n\t},\n\n\t/*\n\t * Cross-browser safe way of translating a date to ISO format\n\t * @memberof wb.date\n\t * @param {Date | number[] | number | string | object} dateValue\n\t * @param {boolean} withTime Optional. Whether to include the time in the result, or just the date. False if blank.\n\t * @return {string}\n\t * @example\n\t * toDateISO( new Date() )\n\t * returns \"2012-04-27\"\n\t * toDateISO( new Date(), true )\n\t * returns \"2012-04-27 13:46\"\n\t */\n\ttoDateISO: function( dateValue, withTime ) {\n\t\tvar date = wb.date.convert( dateValue ),\n\t\t\tpad = wb.string.pad;\n\n\t\treturn date.getFullYear() + \"-\" + pad( date.getMonth() + 1, 2, \"0\" ) + \"-\" + pad( date.getDate(), 2, \"0\" ) +\n\t\t\t( withTime ? \" \" + pad( date.getHours(), 2, \"0\" ) + \":\" + pad( date.getMinutes(), 2, \"0\" ) : \"\" );\n\t},\n\n\t/*\n\t * Cross-browser safe way of creating a date object from a date string in ISO format\n\t * @memberof wb.date\n\t * @param {string} dateISO Date string in ISO format\n\t * @return {Date}\n\t */\n\tfromDateISO: function( dateISO ) {\n\t\tvar date = null;\n\n\t\tif ( dateISO &amp;amp;&amp;amp; /\\d{4}-\\d{2}-\\d{2}/.test( dateISO ) ) {\n\t\t\tdate = new Date( dateISO.substr( 0, 4 ), dateISO.substr( 5, 2 ) - 1, dateISO.substr( 8, 2 ), 0, 0, 0, 0 );\n\t\t}\n\t\treturn date;\n\t}\n};\n\n/*\n * Returns a RFC4122 compliant Global Unique ID (GUID).\n * Originally from https://stackoverflow.com/a/2117523/455535\n */\nwb.guid = function() {\n\treturn \"xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx\".replace( /[xy]/g, function( replacementChar ) {\n\t\tvar rand = Math.random() * 16 | 0,\n\t\t\tnewChar = replacementChar === \"x\" ? rand : ( rand &amp;amp; 0x3 | 0x8 );\n\t\treturn newChar.toString( 16 );\n\t} );\n};\n\nwb.escapeAttribute = function( str ) {\n\treturn str.replace( /'/g, \"&amp;#39;\" ).replace( /\"/g, \"&amp;#34;\" );\n};\n\n/*\n * Returns an escaped HTML string\n */\nwb.escapeHTML = function( str ) {\n\treturn wb.escapeAttribute( str\n\t\t.replace( /&amp;amp;/g, \"&amp;#38;\" )\n\t\t.replace( //g, \"&amp;#62;\" ) );\n};\n\n/*\n * Returns a UTF-8 output from Base64\n * Reference: https://developer.mozilla.org/fr/docs/Glossary/Base64 (To be reviewed later because escape function is deprecated)\n */\nwb.decodeUTF8Base64 = function( str ) {\n\treturn decodeURIComponent( escape( atob( str ) ) );\n};\n\n/*\n* Find most common Personal Identifiable Information (PII) in a string and return either the cleaned string either true/false\n* @param {string} str (required) - the content that needs to be verified\n*\n* @param {boolean} scope - if true will scrub the content\n* @param {object} (optional) the 2nd param (scope) can also be an object having the following properties (optional):\n* \t{string} any key name of the default patterns e.g. email, digits, etc. with the value 1. The function will only scrub the content that match the regex of the default patterns passed in this object\n* \t{regex} customCase - this param is a regex. It will search and replace the values corresponding that pattern\n*\n* @param {object} opts (optional) - the 3rd param of the function that can contain the following properties (optional):\n* \t{boolean} isCustomExclusive - if true, it will scrub only the custom regex if the regex is the only property of the \"scope\" object\n* \t{boolean} useFullBlock - if true, it will replace the scrubbed characters with the \"\u2588\" symbol;\n* \t{string} replaceWith - this string will replace the scrubbed content\n*\n\n* @return {string | true | false}\n* @example\n* wb.findPotentialPII( \"email:test@test.com, phone:123 123 1234\", true )\n* returns \"email:, phone:\",\n*\n* wb.findPotentialPII( \"email:test@test.com, phone:123 123 1234\", false )\n* returns true\n*\n* wb.findPotentialPII( \"email:test@test.com, phone:123 123 1234\", { email:1 }{ replaceWith: [REDACTED/CAVIARD\u00c9] } )\n* returns \"email:[REDACTED/CAVIARD\u00c9], phone:123 123 1234\"\n*\n* wb.findPotentialPII( \"email:test@test.com, phone:123 123 1234, num\u00e9ro de cas 12345678\", { \"customCase\":/\\b(?:case[\\s-]?number[\\s\\-\\\\.]?(?:\\d{5,10}))|(?:num\u00e9ro[\\s-]?de[\\s-]?cas[\\s\\-\\\\.]?(?:\\d{5,10}))/ig }, { useFullBlock:1})\n* returns \"phone:\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588, email:\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588, postalCode:\u2588\u2588\u2588\u2588\u2588\u2588, \u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\u2588\"\n*/\nwb.findPotentialPII = function( str, scope, opts ) {\n\tif ( str &amp;amp;&amp;amp; typeof str  !== \"string\" ) {\n\t\treturn false;\n\t}\n\tconst STREET_TYPES =\n\t\t\t\"(?:street|avenue|road|drive|boulevard|lane|place|terrace|parkway|\" +\n\t\t\t\"circle|highway|pike|row|crescent|close|green|grove|\" +\n\t\t\t\"gate|heights|manor|ridge|rise|square|\" +\n\t\t\t\"hill|hills|acres|valley|rue|chemin|route|terrasse|rang|promenade|\" +\n\t\t\t\"all[\u00e9e]e?|st|ave|av|av\\\\.|rd|dr|blvd|boul|boul\\\\.|ln|ct|pl|\" +\n\t\t\t\"ter|terr|pkwy|cir|ci|hwy|wy|trl|cres|cr|cl|pt|gr|gv|ga|ht|hts|ld|lk|pa|\" +\n\t\t\t\"pk|rg|ri|rw|sq|tc|vi|vw|wk|co|ba|bv|hl|tr|cv|gd|mt|gw|sm|\" +\n\t\t\t\"rp|al|ch|ch\\\\.|chem|chem\\\\.|rte|all\\\\.|allee|prom|prom\\\\.)\",\n\t\tNAME_PART =\n\t\t\t\"(?:\\\\d{1,2}(?:st|nd|rd|th)|[A-Za-z\u00c0-\u00ff][A-Za-z\u00c0-\u00ff''\\\\-]*)\",\n\t\tDIRECTIONS =\n\t\t\t\"(?:n|s|e|w|ne|nw|se|sw|o|no|so|north|south|east|west)\",\n\t\tFR_ARTICLES =\n\t\t\t\"(?:de\\\\s+la\\\\s+|du\\\\s+|des\\\\s+|de\\\\s+|le\\\\s+|la\\\\s+|les\\\\s+|d'|l')?\",\n\t\tHOUSE_NUMBER = \"(\\\\d{1,6}[A-Za-z\u00c0-\u00ff]?)\";\n\n\tvar oRegEx = {\n\n\t\t\t/*\n\t\t\t* Digits:\n\t\t\t* 9 digits or more\n\t\t\t*/\n\t\t\tdigits: /\\d(?:[\\s\\-\\\\.\\\\/]?\\d){8,}(?!\\d)/ig,\n\n\t\t\t/*\n\t\t\t* Phone:\n\t\t\t* Any international phone number format\n\t\t\t*/\n\t\t\tphone: /\\+?(\\d{1,3})?[-._\\s]?(\\(?\\d{3}\\)?)[-._\\s]?(\\d{3})[-._\\s]?(\\d{4})/ig,\n\n\t\t\t/*\n\t\t\t* Passport:\n\t\t\t* 2 letters followed by either a \" \", a \"/\", a \".\", or a \"-\" any amount of times, followed by 6 digits\n\t\t\t*/\n\t\t\tpassport: /\\b[A-Za-z]{2}[\\s\\\\.-]*?\\d{6}\\b/ig,\n\n\t\t\t/*\n\t\t\t* Email:\n\t\t\t* valid email format\n\t\t\t*/\n\t\t\temail: /\\b(?:[a-zA-Z0-9_\\-\\\\.]+)(?:@|%40|%2540)(?:[a-zA-Z0-9_\\-\\\\.]+)\\.(?:[a-zA-Z]{2,5})\\b/ig,\n\n\t\t\t/*\n\t\t\t* Loose email:\n\t\t\t* email address that has one or more whitespaces before the \"@\" sign and either a \".\" or \",\" after the domain name\n\t\t\t*/\n\t\t\tlooseEmail: /([a-zA-Z0-9_\\-.]+)\\s*@([\\sa-zA-Z0-9_\\-.]+)[.,]([a-zA-Z]{1,5})/g,\n\n\t\t\t/*\n\t\t\t* Loose email 2:\n\t\t\t* matches probable email format that the user tried to hide\n\t\t\t* any amount of letters, numbers, \".\", \"_\", \"%\", \"+\", or \"-\", followed by 0 or 1 whitespace,\n\t\t\t* followed by \"@\", followed by 0 or 1 whitespace, followed by \"gmail\", \"outlook\", \"hotmail\", or \"yahoo\".\n\t\t\t*/\n\t\t\tlooseEmail2: /([a-zA-Z0-9._%+-]+)\\s?@\\s?(gmail|outlook|icloud|hotmail|yahoo)(\\s?\\.?\\s?(com|ca))?/ig,\n\n\t\t\t/*\n\t\t\t* Loose email 3: to catch obfuscated emails: supports +, spaces in domain, optional TLD, longer TLDs\n\t\t\t*/\n\t\t\tlooseEmail3: /([a-zA-Z0-9_+\\-\\\\.]+)\\s*@\\s*([a-zA-Z0-9_\\-\\\\.]+)(?:\\s*[\\\\.,]\\s*([a-zA-Z]{0,10}))?/ig,\n\n\t\t\t/*\n\t\t\t* Postal code:\n\t\t\t* valid Canadian postal code\n\t\t\t*/\n\t\t\tpostalCode: /\\b[A-Za-z]\\d[A-Za-z][ -]?\\d[A-Za-z]\\d\\b/ig,\n\n\t\t\t/*\n\t\t\t* Address pattern 1: NUMBER + (DIRECTION) + WORD(S) + STREET_TYPES + (DIRECTION)\n\t\t\t*/\n\t\t\taddress_pattern_1: new RegExp(\n\t\t\t\t\"\\\\b\" + HOUSE_NUMBER + \"\\\\s+\" +\n\t\t\t\t`(?:${ DIRECTIONS }\\\\s+)?` +\n\t\t\t\t`(?:${ NAME_PART }(?:\\\\s+${ NAME_PART }){0,3})\\\\s+` +\n\t\t\t\tSTREET_TYPES +\n\t\t\t\t`(?:\\\\s+${ DIRECTIONS })?\\\\b`,\n\t\t\t\t\"ig\" ),\n\n\t\t\t/*\n\t\t\t* Address pattern 2: NUMBER + STREET_TYPES + (FR_ARTICLES) + WORD(S)\n\t\t\t*/\n\t\t\taddress_pattern_2: new RegExp(\n\t\t\t\t\"\\\\b\" + HOUSE_NUMBER + \",?\\\\s+\" +\n\t\t\t\tSTREET_TYPES +\n\t\t\t\t\"\\\\s+\" +\n\t\t\t\tFR_ARTICLES +\n\t\t\t\t`(?:${ NAME_PART }(?:\\\\s+${ NAME_PART }){0,3})\\\\b`,\n\t\t\t\t\"ig\" ),\n\n\t\t\t/*\n\t\t\t* Address pattern 3: NUMBER + STREET_TYPES\n\t\t\t*/\n\t\t\taddress_pattern_3: RegExp(\n\t\t\t\t\"\\\\b\" + HOUSE_NUMBER + \"\\\\s+\" +\n\t\t\t\tSTREET_TYPES +\n\t\t\t\t\"\\\\b\",\n\t\t\t\t\"ig\" ),\n\n\t\t\t/*\n\t\t\t* Address pattern 4: STREET_TYPES + NUMBER\n\t\t\t*/\n\t\t\taddress_pattern_4: new RegExp(\n\t\t\t\t`\\\\b${ STREET_TYPES }\\\\s+${ HOUSE_NUMBER }\\\\b`,\n\t\t\t\t\"ig\" ),\n\n\t\t\t/*\n\t\t\t* Address pattern 5: PO BOX + NUMBER\n\t\t\t* e.g., \u201cPO Box 123\u201d, \u201cP.O. Box 456\u201d, \u201cPost Office Box 789\u201d, \u201cC.P. 123\u201d, \u201cB.P. 456\u201d, \u201cCase postale 789\u201d, \u201cBo\u00eete postale 123\u201d, \u201cCasier postal 456\u201d\n\t\t\t*/\n\t\t\taddress_pattern_5: /\\b(?:(?:p\\.?\\s*o\\.?\\s*box)|(?:post\\s+office\\s+box)|(?:c\\.?\\s*p\\.?)|(?:b\\.?\\s*p\\.?)|(?:case\\s+postale)|(?:bo[i\u00ee]te\\s+postale)|(?:casier\\s+postal))(?:\\.+)?[ \\t]*(?:#|no\\.?|n[\u00ba\u00b0]|n\u00b0|num(?:[\u00e9e]ro)?\\.?)?[ \\t]*(?[A-Za-z0-9][A-Za-z0-9\\\\-]*)\\b/giu,\n\n\t\t\t/*\n\t\t\t* Username:\n\t\t\t* \"username\" or \"user\",\n\t\t\t* followed by a colon or an equals sign,\n\t\t\t* followed by any character that is not a \" \" or a \"&amp;amp;\"\n\t\t\t*/\n\t\t\tusername: /(?:(username|user)[%20]?([:=]|(%EF%BC%9A))[^\\s&amp;amp;]*)/ig,\n\n\t\t\t/*\n\t\t\t* Password:\n\t\t\t* \"password\" or \"pass\",\n\t\t\t* followed by a \":\" or a \"=\",\n\t\t\t* followed by any character that is not a \" \" or a \"&amp;amp;\"\n\t\t\t*/\n\t\t\tpassword: /(?:(password|pass)[%20]?([:=]|(%EF%BC%9A))[^\\s&amp;amp;]*)/ig\n\t\t},\n\t\tisFound = false,\n\t\ttxtMarker = opts &amp;amp;&amp;amp; opts.replaceWith ? opts.replaceWith : \"\",\n\t\ttoClean = typeof scope === \"object\" ? true : scope,\n\t\tarMatchedStr,\n\t\tsettings = opts || {},\n\t\tdefaultSettings = {\n\t\t\tisCustomExclusive: false,\n\t\t\tuseFullBlock: false,\n\t\t\treplaceWith: \"\"\n\t\t},\n\t\tisFullBlock = settings.useFullBlock || false,\n\t\tvalidatedScope = typeof scope === \"object\" ? {} : oRegEx;\n\tsettings = $.extend( {}, defaultSettings, settings );\n\n\tif ( Object.keys( validatedScope ).length === 0 ) {\n\t\tif ( settings.isCustomExclusive ) {\n\t\t\tfor ( var key in scope ) {\n\t\t\t\tif ( scope[ key ] instanceof RegExp ) {\n\t\t\t\t\tvalidatedScope[ key ] = scope[ key ];\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif ( Object.keys( scope ).length === 1 &amp;amp;&amp;amp; Object.values( scope )[ 0 ] instanceof RegExp ) {\n\t\t\t\tvalidatedScope = oRegEx;\n\t\t\t\tvalidatedScope[ Object.keys( scope )[ 0 ] ] = Object.values( scope )[ 0 ];\n\t\t\t} else {\n\t\t\t\tfor ( var keyScope in scope ) {\n\t\t\t\t\tif ( Object.prototype.hasOwnProperty.call( oRegEx, keyScope ) ) {\n\t\t\t\t\t\tvalidatedScope [ keyScope ] = oRegEx [ keyScope ];\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( scope[ keyScope ]  instanceof RegExp ) {\n\t\t\t\t\t\t\tvalidatedScope [ keyScope ] = scope [ keyScope ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\tfor ( var valKey in validatedScope ) {\n\t\tarMatchedStr = str.match( validatedScope[ valKey ] );\n\t\tif ( arMatchedStr ) {\n\t\t\tisFound = true;\n\t\t\tif ( toClean ) {\n\t\t\t\ttxtMarker = isFullBlock ? \"\u2588\".repeat( arMatchedStr[ 0 ].length ) : txtMarker;\n\t\t\t\tstr = str.replaceAll( validatedScope[ valKey ], txtMarker );\n\t\t\t}\n\t\t}\n\t}\n\n\treturn toClean &amp;amp;&amp;amp; isFound ? str : isFound;\n};\n\n} )( wb, window );\n\n( function( $, undef ) {\n\"use strict\";\n\nvar methods,\n\tsettings = {\n\t\t\"default\": \"wet-boew\"\n\t};\n\nmethods = {\n\n\tinit: function( options ) {\n\t\treturn $.extend( settings, options || {} );\n\t},\n\n\tshow: function( onlyAria ) {\n\t\t$( this ).each( function() {\n\t\t\tvar $elm = $( this );\n\t\t\t$elm.attr( \"aria-hidden\", \"false\" );\n\t\t\tif ( onlyAria === undef ) {\n\t\t\t\t$elm.removeClass( \"wb-inv\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\thide: function( onlyAria ) {\n\t\t$( this )\n\t\t\t.each( function() {\n\t\t\t\tvar $elm = $( this );\n\t\t\t\t$elm.attr( \"aria-hidden\", \"true\" );\n\t\t\t\tif ( onlyAria === undef ) {\n\t\t\t\t\treturn $elm.addClass( \"wb-inv\" );\n\t\t\t\t}\n\t\t\t} );\n\t},\n\n\ttoggle: function( to, from ) {\n\t\t$( this )\n\t\t\t.addClass( to )\n\t\t\t.removeClass( from );\n\t}\n};\n\n$.fn.wb = function( method ) {\n\n\tif ( methods[ method ] ) {\n\t\tmethods[ method ].apply( this, Array.prototype.slice.call( arguments, 1 ) );\n\t} else if ( typeof method === \"object\" || !method ) {\n\t\tmethods.init.apply( this, arguments );\n\t} else {\n\t\t$.error( \"Method \" + method + \" does not exist on jquery.wb\" );\n\t}\n};\n\n} )( jQuery );\n\n/*!\n * jQuery UI Focusable/Tabbable\n * https://jqueryui.com\n *\n * Copyright OpenJS Foundation and other contributors\n * Released under the MIT license.\n * https://jquery.org/license\n */\n\n/*\n:focusable, :discoverable and :tabbable jQuery helper expressions\n\nDerived from jQuery UI, with the following changes:\n* Adheres to WET's ESLint settings (no-eq-null: changed loose null checks into strict undefined checks)\n* Adds an isVisible parameter to the focusable method (preset to true to behave like jQuery UI by default, can optionally be set to false)\n* Adds an extra discoverable method (leverages the focusable method with isVisible set to false)\n\nBased on:\n* https://github.com/jquery/jquery-ui/blob/e803d4f67be9d7ae9a5a125c188dd003e3e3043a/ui/focusable.js#L31-L73\n* https://github.com/jquery/jquery-ui/blob/e803d4f67be9d7ae9a5a125c188dd003e3e3043a/ui/tabbable.js#L30-L36\n* https://github.com/jquery/jquery-ui/blob/24756a978a977d7abbef5e5bce403837a01d964f/ui/jquery.ui.core.js#L121-L142 (old logic's extend structure)\n*/\n( function( $ ) {\n\n\"use strict\";\n\nfunction focusable( element, hasTabindex, isVisible = true ) {\n\tvar map, mapName, img, focusableIfVisible, fieldset,\n\t\tnodeName = element.nodeName.toLowerCase();\n\n\tif ( \"area\" === nodeName ) {\n\t\tmap = element.parentNode;\n\t\tmapName = map.name;\n\t\tif ( !element.href || !mapName || map.nodeName.toLowerCase() !== \"map\" ) {\n\t\t\treturn false;\n\t\t}\n\t\timg = $( \"img[usemap='#\" + mapName + \"']\" );\n\n\t\tif ( isVisible ) {\n\t\t\treturn img.length &amp;gt; 0 &amp;amp;&amp;amp; img.is( \":visible\" );\n\t\t}\n\n\t\treturn img.length &amp;gt; 0;\n\t}\n\n\tif ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {\n\t\tfocusableIfVisible = !element.disabled;\n\n\t\tif ( focusableIfVisible ) {\n\n\t\t\t// Form controls within a disabled fieldset are disabled.\n\t\t\t// However, controls within the fieldset's legend do not get disabled.\n\t\t\t// Since controls generally aren't placed inside legends, we skip\n\t\t\t// this portion of the check.\n\t\t\tfieldset = $( element ).closest( \"fieldset\" )[ 0 ];\n\t\t\tif ( fieldset ) {\n\t\t\t\tfocusableIfVisible = !fieldset.disabled;\n\t\t\t}\n\t\t}\n\t} else if ( \"a\" === nodeName ) {\n\t\tfocusableIfVisible = element.href || hasTabindex;\n\t} else {\n\t\tfocusableIfVisible = hasTabindex;\n\t}\n\n\tif ( isVisible ) {\n\t\treturn focusableIfVisible &amp;amp;&amp;amp; $( element ).is( \":visible\" ) &amp;amp;&amp;amp;\n\t\t\t$( element ).css( \"visibility\" ) === \"visible\";\n\t}\n\n\treturn focusableIfVisible &amp;amp;&amp;amp; $( element );\n}\n\n$.extend( $.expr.pseudos, {\n\tfocusable: function( element ) {\n\t\treturn focusable( element, $.attr( element, \"tabindex\" ) !== undefined );\n\t},\n\tdiscoverable: function( element ) {\n\t\treturn focusable( element, $.attr( element, \"tabindex\" ) !== undefined, false );\n\t},\n\ttabbable: function( element ) {\n\t\tvar tabIndex = $.attr( element, \"tabindex\" ),\n\t\t\thasTabindex = tabIndex !== undefined;\n\t\treturn ( !hasTabindex || tabIndex &amp;gt;= 0 ) &amp;amp;&amp;amp; focusable( element, hasTabindex );\n\t}\n} );\n\n} )( jQuery );\n\n/**\n * @title WET-BOEW Add to calendar\n * @overview Create an add to calendar button for an event\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @ricokola\n */\n( function( $, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-addcal\",\n\tselector = \".provisional.\" + componentName,\n\tinitEvent = \"wb-init.\" + componentName,\n\t$document = wb.doc,\n\n\t/**\n\t* @method init\n\t* @param {jQuery Event} event Event that triggered the function call\n\t*/\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm = $( elm );\n\n\t\tif ( elm ) {\n\n\t\t\twb.ready( $( elm ), componentName );\n\n\t\t\tvar properties = elm.querySelectorAll( \"[property]\" ),\n\t\t\t\tevent_details = new Object(),\n\t\t\t\tplace_details = [],\n\t\t\t\ti,\n\t\t\t\ti_len,\n\t\t\t\tprop_cache,\n\t\t\t\tgoogleLink,\n\t\t\t\ticsFile,\n\t\t\t\ti18nDict = {\n\t\t\t\t\ten: {\n\t\t\t\t\t\t\"addcal-addto\": \"Add to\",\n\t\t\t\t\t\t\"addcal-calendar\": \"calendar\",\n\t\t\t\t\t\t\"addcal-other\": \"Other (Outlook, Apple, etc.)\"\n\t\t\t\t\t},\n\t\t\t\t\tfr: {\n\t\t\t\t\t\t\"addcal-addto\": \"Ajouter au\",\n\t\t\t\t\t\t\"addcal-calendar\": \"calendrier\",\n\t\t\t\t\t\t\"addcal-other\": \"Autre (Outlook, Apple, etc.)\"\n\t\t\t\t\t}\n\t\t\t\t};\n\n\t\t\t// Initiate dictionary\n\t\t\ti18nDict = i18nDict[ $( \"html\" ).attr( \"lang\" ) || \"en\" ];\n\t\t\ti18nDict = {\n\t\t\t\taddto: i18nDict[ \"addcal-addto\" ],\n\t\t\t\tcalendar: i18nDict[ \"addcal-calendar\" ],\n\t\t\t\tical: i18nDict[ \"addcal-other\" ]\n\t\t\t};\n\n\t\t\t// Set date stamp with the date modified\n\t\t\tevent_details.dtStamp = dtToISOString( $( \"time[property='dateModified']\" ) );\n\n\t\t\ti_len = properties.length;\n\t\t\tfor ( i = 0; i &amp;lt; i_len; i++ ) {\n\t\t\t\tprop_cache = properties[ i ];\n\t\t\t\tswitch ( prop_cache.getAttribute( \"property\" ) ) {\n\t\t\t\t\tcase \"name\":\n\n\t\t\t\t\t\t// If the property=name is inside an element with typeof=Place defined\n\t\t\t\t\t\tif ( $( prop_cache ).parentsUntil( ( \".\" + componentName ), \"[typeof=Place]\" ).length ) {\n\t\t\t\t\t\t\tevent_details.placeName = prop_cache.textContent;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tevent_details.name = prop_cache.textContent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"description\":\n\t\t\t\t\t\tevent_details.description = prop_cache.textContent.replace( /(\\r\\n|\\n|\\r)/gm, \" \" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"startDate\":\n\t\t\t\t\t\tevent_details.sDate = dtToISOString( $( \"time[property='startDate']\", $elm ) );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"endDate\":\n\t\t\t\t\t\tevent_details.eDate = dtToISOString( $( \"time[property='endDate']\", $elm ) );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"location\":\n\n\t\t\t\t\t\t// If the location doesn't have typeof defined OR has typeof=VirtualLocation without URL inside.\n\t\t\t\t\t\tif ( !prop_cache.getAttribute( \"typeof\" ) || ( prop_cache.getAttribute( \"typeof\" ) === \"VirtualLocation\" &amp;amp;&amp;amp; !$( prop_cache ).find( \"[property=url]\" ).length ) ) {\n\t\t\t\t\t\t\tevent_details.placeName = prop_cache.textContent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"streetAddress\":\n\t\t\t\t\t\tevent_details.placeAddress = prop_cache.textContent;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"addressLocality\":\n\t\t\t\t\t\tevent_details.placeLocality = prop_cache.textContent;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"addressRegion\":\n\t\t\t\t\t\tevent_details.placeRegion = prop_cache.textContent;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"postalCode\":\n\t\t\t\t\t\tevent_details.placePostalCode = prop_cache.textContent;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"url\":\n\n\t\t\t\t\t\t// If the property=url is inside a property=location\n\t\t\t\t\t\tif ( $( prop_cache ).parentsUntil( ( \".\" + componentName ), \"[property=location]\" ).length ) {\n\t\t\t\t\t\t\tevent_details.placeName = prop_cache.textContent;\n\t\t\t\t\t\t}\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tplace_details.push( ( event_details.placeName || \"\" ), ( event_details.placeAddress || \"\" ), ( event_details.placeLocality || \"\" ), ( event_details.placeRegion || \"\" ), ( event_details.placePostalCode || \"\" ) );\n\n\t\t\t// Error handling\n\t\t\tif ( !event_details.name ) {\n\t\t\t\tthrow componentName + \": Event title is missing.\";\n\t\t\t} else if ( !event_details.sDate ) {\n\t\t\t\tthrow componentName + \": Start date is missing.\";\n\t\t\t} else if ( !event_details.eDate ) {\n\t\t\t\tthrow componentName + \": End date is missing.\";\n\t\t\t}\n\n\t\t\t// Set Unique Identifier (UID) and Date Stamp (DSTAMP)\n\t\t\tevent_details.uid = window.location.href.replace( /\\.|-|\\/|:|[G-Zg-z]/g, \"\" ).toUpperCase().substr( -10 ) + \"-\" + event_details.sDate + \"-\" + event_details.dtStamp;\n\n\t\t\t// Set google calendar link\n\t\t\tgoogleLink = encodeURI( \"https://www.google.com/calendar/render?action=TEMPLATE\" +  \"&amp;amp;text=\" + event_details.name +  \"&amp;amp;details=\" +\n\t\t\tevent_details.description +  \"&amp;amp;dates=\" + event_details.sDate + \"/\" + event_details.eDate + \"&amp;amp;location=\" + place_details.join( \" \" ) );\n\n\t\t\t// Set ICS file for Outlook, Apple and other calendars\n\t\t\ticsFile = \"BEGIN:VCALENDAR\\nVERSION:2.0\\nPRODID:-//WET-BOEW//Add to Calendar v4.0//\\nBEGIN:VEVENT\\nDTSTAMP:\" + event_details.dtStamp + \"\\nSUMMARY:\" + event_details.name +  \"\\nDESCRIPTION:\" + event_details.description + \"\\nUID:\" + event_details.uid + \"\\nDTSTART:\" + event_details.sDate + \"\\nDTEND:\" + event_details.eDate + \"\\nLOCATION:\" + place_details.join( \" \" ) + \"\\nEND:VEVENT\\nEND:VCALENDAR\";\n\n\t\t\telm.dataset.icsFile = icsFile;\n\n\t\t\t// Create and add details summary to the wb-addcal event and initiate the unordered list\n\t\t\t$elm.append( \"\n\" + i18nDict.addto + \" \" + i18nDict.calendar +\n\t\t\t\"\n\nGoogle\" + i18nDict.calendar + \"\n\" + i18nDict.ical +\n\t\t\t\"Calendar\" );\n\t\t}\n\n\t\twb.ready( $( elm ), componentName );\n\n\t};\n\n// Convert date to ISO string and formatting for ICS file\nvar dtToISOString = function( date ) {\n\tif ( date.is( \"[datetime]\" ) ) {\n\t\tdate = date.attr( \"datetime\" );\n\t} else {\n\t\tdate = date.text();\n\t}\n\n\treturn new Date( date ).toISOString().replace( /\\..*[0-9]/g, \"\" ).replace( /-|:|\\./g, \"\" );\n};\n\n$document.on( \"click\", \".download-ics\", function( event ) {\n\tvar icsFile = $( event.currentTarget ).parentsUntil( \".\" + componentName ).parent()[ 0 ];\n\ticsFile =  $( icsFile ).attr( \"data-ics-file\" );\n\twb.download( new Blob( [ icsFile ], { type: \"text/calendar;charset=utf-8\" } ), \"evenement-gc-event.ics\" );\n} );\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, wb );\n\n/**\n * @title WET-BOEW Ajax Fetch [ ajax-fetch ]\n * @overview A basic AjaxLoader wrapper for WET-BOEW\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author WET Community\n */\n( function( $, wb, DOMPurify ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar $document = wb.doc;\n\n// Event binding\n$document.on( \"ajax-fetch.wb\", function( event ) {\n\n\t// TODO: Remove event.element in future versions\n\tvar caller = event.element || event.target,\n\t\tfetchOpts = event.fetch,\n\t\turlParts = fetchOpts.url.split( \" \" ),\n\t\turl = urlParts[ 0 ],\n\t\turlSubParts = url.split( \"#\" ),\n\t\turlHash = urlSubParts[ 1 ],\n\t\tselector = urlParts[ 1 ] || ( urlHash ? \"#\" + urlHash : false ),\n\t\tfetchData = {},\n\t\tcallerId, fetchNoCacheURL, urlSub,\n\t\tfetchNoCache = fetchOpts.nocache,\n\t\tfetchNoCacheKey = fetchOpts.nocachekey || wb.cacheBustKey || \"wbCacheBust\";\n\n\t// Separate the URL from the filtering criteria\n\tif ( selector ) {\n\t\tfetchOpts.url = urlParts[ 0 ];\n\n\t\tif ( urlParts[ 1 ] ) {\n\t\t\tselector = urlParts.slice( 1 ).join( \" \" );\n\t\t}\n\t}\n\n\tif ( fetchNoCache ) {\n\t\tif ( fetchNoCache === \"nocache\" ) {\n\t\t\tfetchNoCacheURL = wb.guid();\n\t\t} else {\n\t\t\tfetchNoCacheURL = wb.sessionGUID();\n\t\t}\n\t\tfetchNoCacheURL = fetchNoCacheKey + \"=\" + fetchNoCacheURL;\n\n\t\turlSub = urlSubParts[ 0 ];\n\t\tif ( urlSub.indexOf( \"?\" ) !== -1 ) {\n\t\t\turl = urlSub + \"&amp;amp;\" + fetchNoCacheURL + ( urlHash ? \"#\" + urlHash : \"\" );\n\t\t} else {\n\t\t\turl = urlSub + \"?\" + fetchNoCacheURL + ( urlHash ? \"#\" + urlHash : \"\" );\n\t\t}\n\n\t\tfetchOpts.url = url;\n\t}\n\n\t// Filter out any events triggered by descendants\n\tif ( caller === event.target || event.currentTarget === event.target ) {\n\n\t\tif ( !caller.id ) {\n\t\t\tcaller.id = wb.getId();\n\t\t}\n\t\tcallerId = caller.id;\n\n\t\t// Ensure we don't allow jsonp load\n\t\tif ( fetchOpts.dataType &amp;amp;&amp;amp; fetchOpts.dataType === \"jsonp\" ) {\n\t\t\tfetchOpts.dataType = \"json\";\n\t\t}\n\t\tif ( fetchOpts.jsonp ) {\n\t\t\tfetchOpts.jsonp = false;\n\t\t}\n\n\t\t$.ajax( fetchOpts )\n\t\t\t.done( function( response, status, xhr ) {\n\t\t\t\tvar responseType = typeof response;\n\n\t\t\t\tif ( selector ) {\n\t\t\t\t\tresponse = $( \"\n\" + response + \"\" ).find( selector );\n\t\t\t\t}\n\n\t\t\t\tfetchData.pointer = $( \"\n\" )\n\t\t\t\t\t.append( responseType === \"string\" ? response : \"\" );\n\n\t\t\t\tif ( !xhr.responseJSON ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresponse = $( response );\n\t\t\t\t\t} catch ( e ) {\n\t\t\t\t\t\tresponse = DOMPurify.sanitize( xhr.responseText );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresponse = xhr.responseText;\n\t\t\t\t}\n\n\t\t\t\tfetchData.response = response;\n\t\t\t\tfetchData.hasSelector = !!selector;\n\t\t\t\tfetchData.status = status;\n\t\t\t\tfetchData.xhr = xhr;\n\n\t\t\t\t$( \"#\" + callerId ).trigger( {\n\t\t\t\t\ttype: \"ajax-fetched.wb\",\n\t\t\t\t\tfetch: fetchData\n\t\t\t\t}, this );\n\t\t\t} )\n\t\t\t.fail( function( xhr, status, error ) {\n\t\t\t\t$( \"#\" + callerId ).trigger( {\n\t\t\t\t\ttype: \"ajax-failed.wb\",\n\t\t\t\t\tfetch: {\n\t\t\t\t\t\txhr: xhr,\n\t\t\t\t\t\tstatus: status,\n\t\t\t\t\t\terror: error\n\t\t\t\t\t}\n\t\t\t\t}, this );\n\t\t\t}, this );\n\t}\n} );\n\n} )( jQuery, wb, DOMPurify );\n\n/**\n * @title WET-BOEW Set background image\n * @overview Apply a background image or detects the change in screen width and replace the background image accordingly\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @namjohn920, @duboisp\n */\n( function( $, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar $document = wb.doc,\n\t$window = wb.win,\n\tcomponentName = \"wb-bgimg\",\n\tselector = \"[data-bgimg-srcset], [data-bgimg]\",\n\tbgViews = {},\n\tids = [],\n\n\tinit = function( event ) {\n\n\t\tvar elm, elmId,\n\t\t\tbgImg, bgimgSrcset, bgRawViews,\n\t\t\ti, i_len, i_views,\n\t\t\timgSrc, imgSize;\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\telm = wb.init( event, componentName, selector );\n\n\t\tif ( elm ) {\n\n\t\t\t// Ensure the feature have an ID.\n\t\t\tif ( !elm.id ) {\n\t\t\t\telm.id = wb.getId();\n\t\t\t}\n\t\t\telmId = elm.id;\n\n\t\t\t// Apply default background image\n\t\t\tbgImg = elm.dataset.bgimg;\n\t\t\tif ( bgImg ) {\n\t\t\t\telm.style.backgroundImage = \"url(\" + bgImg + \")\";\n\t\t\t}\n\n\t\t\t// Apply background image set if defined\n\t\t\tbgimgSrcset = elm.dataset.bgimgSrcset;\n\t\t\tif ( bgimgSrcset ) {\n\t\t\t\tids.push( elm.id );\n\t\t\t\tbgRawViews = elm.dataset.bgimgSrcset.split( \",\" );\n\t\t\t\ti_len = bgRawViews.length;\n\t\t\t\tbgViews[ elmId ] = [];\n\n\t\t\t\tfor ( i = 0; i &amp;lt; i_len; i++ ) {\n\t\t\t\t\ti_views = bgRawViews[ i ].trim().split( \" \" );\n\n\t\t\t\t\timgSrc = i_views[ 0 ];\n\t\t\t\t\timgSize =  i_views[ i_views.length - 1 ];\n\n\t\t\t\t\timgSize = parseInt( imgSize.substring( 0, imgSize.length - 1 ) );\n\t\t\t\t\tbgViews[ elmId ].push( [ imgSrc, imgSize ] );\n\t\t\t\t}\n\n\t\t\t\tbgViews[ elmId ].sort(\n\t\t\t\t\tfunction( a, b ) {\n\t\t\t\t\t\treturn a[ 1 ] &amp;gt; b[ 1 ] ? 1 : -1;\n\t\t\t\t\t}\n\t\t\t\t);\n\n\t\t\t\tselectImage();\n\n\t\t\t\t// Add the resize listener\n\t\t\t\t$window.on( \"resize\", selectImage );\n\t\t\t}\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $( elm ), componentName );\n\t\t}\n\t},\n\n\tselectImage = function() {\n\t\tvar screenWidth = window.innerWidth,\n\t\t\toptimizedLink = {},\n\t\t\ti, i_len = ids.length, j,\n\t\t\toptimizedSize, currentId, currentId_len,\n\t\t\tcurrentInput,\n\t\t\tlink, elm;\n\n\t\tfor ( i = 0; i &amp;lt; i_len; i++ ) {\n\t\t\toptimizedSize = Infinity;\n\t\t\tcurrentId = bgViews[ ids[ i ] ];\n\t\t\tcurrentId_len = currentId.length;\n\n\t\t\tfor ( j = 0; j &amp;lt; currentId_len; j++ ) {\n\t\t\t\tcurrentInput = currentId[ j ];\n\t\t\t\tif ( currentInput[ 1 ] &amp;gt;= screenWidth ) {\n\t\t\t\t\tif ( optimizedSize &amp;gt; currentInput[ 1 ] ) {\n\t\t\t\t\t\toptimizedSize = currentInput[ 1 ];\n\t\t\t\t\t\toptimizedLink[ ids[ i ] ] = currentInput[ 0 ];\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( optimizedSize === Infinity ) {\n\t\t\t\toptimizedLink[ ids[ i ] ] = currentId[ currentId_len - 1 ][ 0 ];\n\t\t\t}\n\t\t}\n\n\t\tfor ( link in optimizedLink ) {\n\t\t\telm = document.getElementById( link );\n\n\t\t\tif ( optimizedLink[ link ] === \"https://wet-boew.github.io/vocab/wb/utilities#no-image\" ) {\n\t\t\t\telm.style.backgroundImage = \"none\";\n\t\t\t} else {\n\t\t\t\telm.style.backgroundImage = \"url(\" + optimizedLink[ link ] + \")\";\n\t\t\t}\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb wb-init.\" + componentName, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, wb );\n\n/**\n * @title WET-BOEW Events Calendar\n * @overview Dynamically generates a calendar interface for navigating a list of events.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author WET Community\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-calevt\",\n\tselector = \".\" + componentName,\n\tcomponentEventName = componentName + \"-cal\",\n\tselectorEvent = \".\" + componentEventName,\n\tinitEvent = \"wb-init\" + selector,\n\tevDetails = \"ev-details\",\n\tsetFocusEvent = \"focus\",\n\tdataAttr = componentName,\n\t$document = wb.doc,\n\thiddenClass = \"hidden\",\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered this handler\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\n\t\t\t// Load ajax content\n\t\t\t$.when.apply( $, $.map( $elm.find( \"[data-calevt]\" ), getAjax ) )\n\t\t\t\t.always( function() {\n\t\t\t\t\tprocessEvents( $elm );\n\n\t\t\t\t\t// Identify that initialization has completed\n\t\t\t\t\twb.ready( $elm, componentName );\n\t\t\t\t} );\n\t\t}\n\t},\n\n\tgetAjax = function( ajaxContainer ) {\n\t\tvar $ajaxContainer = $( ajaxContainer ),\n\t\t\turls = $ajaxContainer.data( \"calevt\" ).split( /\\s+/ ),\n\t\t\tdfd = $.Deferred(),\n\t\t\tlen = urls.length,\n\t\t\tpromises = [],\n\t\t\ti, appendData;\n\n\t\tappendData = function( data ) {\n\t\t\t$ajaxContainer.append( String( data ).trim() );\n\t\t};\n\n\t\tfor ( i = 0; i &amp;lt; len; i += 1 ) {\n\t\t\tpromises.push( $.get( urls[ i ], appendData, \"html\" ) );\n\t\t}\n\n\t\t$.when.apply( $, promises ).always( function() {\n\t\t\tdfd.resolve();\n\t\t} );\n\n\t\treturn dfd.promise();\n\t},\n\n\tprocessEvents = function( $elm ) {\n\t\tvar settings = $.extend( {}, window[ componentName ], $elm.data( dataAttr ) ),\n\t\t\tyear, month, events, containerId, $container,\n\t\t\tminDate, maxDate, minDateTime, maxDateTime,\n\t\t\tcurrDate = new Date(),\n\t\t\tcurrDateTime = currDate.getTime();\n\n\t\tevents = getEvents( $elm );\n\t\tcontainerId = $elm.data( \"calevtSrc\" );\n\t\t$container = $( \"#\" + containerId ).addClass( componentEventName );\n\n\t\tyear = settings.year;\n\t\tmonth = settings.month;\n\n\t\tif ( $elm.data( \"calevtMinDate\" ) ) {\n\t\t\tminDate = getLocaleDate( $elm.data( \"calevtMinDate\" ) );\n\t\t}\n\t\tif ( $elm.data( \"calevtMaxDate\" ) ) {\n\t\t\tmaxDate = getLocaleDate( $elm.data( \"calevtMaxDate\" ) );\n\t\t}\n\n\t\tif ( !minDate || ( events.minDate &amp;lt; minDate ) ) {\n\t\t\tminDate = events.minDate;\n\t\t}\n\t\tif ( !maxDate || ( events.maxDate &amp;gt; maxDate ) ) {\n\t\t\tmaxDate = events.maxDate;\n\t\t}\n\n\t\tminDateTime = minDate.getTime();\n\t\tmaxDateTime = maxDate.getTime();\n\n\t\tif ( !year &amp;amp;&amp;amp; minDateTime &amp;lt; currDateTime &amp;amp;&amp;amp; currDateTime &amp;lt; maxDateTime ) {\n\t\t\tyear = currDate.getFullYear();\n\t\t} else if ( !year &amp;amp;&amp;amp; currDateTime &amp;lt; minDateTime ) {\n\t\t\tyear = minDate.getFullYear();\n\t\t} else if ( !year &amp;amp;&amp;amp; maxDateTime &amp;lt; currDateTime ) {\n\t\t\tyear = maxDate.getFullYear();\n\t\t}\n\n\t\tif ( !month &amp;amp;&amp;amp; minDateTime &amp;lt; currDateTime &amp;amp;&amp;amp; currDate.getTime() &amp;lt; maxDateTime ) {\n\t\t\tmonth = currDate.getMonth();\n\t\t} else if ( !month &amp;amp;&amp;amp; currDateTime &amp;lt; minDateTime ) {\n\t\t\tmonth = minDate.getMonth();\n\t\t} else if ( !month &amp;amp;&amp;amp; maxDateTime &amp;lt; currDateTime ) {\n\t\t\tmonth = maxDate.getMonth();\n\t\t}\n\n\t\twb.calendar.create( $container, {\n\t\t\tyear: year,\n\t\t\tmonth: month,\n\t\t\tminDate: minDate,\n\t\t\tmaxDate: maxDate,\n\t\t\tdaysCallback: addEvents,\n\t\t\tevents: events.list,\n\t\t\t$events: $elm\n\t\t} );\n\t},\n\n\tdaysBetween = function( dateLow, dateHigh ) {\n\n\t\t// Simplified conversion to date object\n\t\tvar date1 = wb.date.convert( dateLow ),\n\t\t\tdate2 = wb.date.convert( dateHigh ),\n\t\t\tdstAdjust = 0,\n\t\t\toneMinute = 1000 * 60,\n\t\t\toneDay = oneMinute * 60 * 24,\n\t\t\tdiff;\n\n\t\t// Equalize times in case date objects have them\n\t\tdate1.setHours( 0 );\n\t\tdate1.setMinutes( 0 );\n\t\tdate1.setSeconds( 0 );\n\t\tdate2.setHours( 0 );\n\t\tdate2.setMinutes( 0 );\n\t\tdate2.setSeconds( 0 );\n\n\t\t// Take care of spans across Daylight Saving Time changes\n\t\tif ( date2 &amp;gt; date1 ) {\n\t\t\tdstAdjust = ( date2.getTimezoneOffset() - date1.getTimezoneOffset() ) * oneMinute;\n\t\t} else {\n\t\t\tdstAdjust = ( date1.getTimezoneOffset() - date2.getTimezoneOffset() ) * oneMinute;\n\t\t}\n\t\tdiff = Math.abs( date2.getTime() - date1.getTime() ) - dstAdjust;\n\t\treturn Math.ceil( diff / oneDay );\n\t},\n\n\t///TODO: Review this code\n\tgetEvents = function( obj ) {\n\t\tvar directLinking = !( $( obj ).hasClass( \"evt-anchor\" ) ),\n\t\t\tevents = {\n\t\t\t\tminDate: null,\n\t\t\t\tmaxDate: null,\n\t\t\t\tiCount: 0,\n\t\t\t\tlist: [\n\t\t\t\t\t{\n\t\t\t\t\t\ta: 1\n\t\t\t\t\t}\n\t\t\t\t]\n\t\t\t},\n\t\t\tobjEventsList = obj.find( \"ul, ol\" ).first(),\n\t\t\tobjEventsListItems = objEventsList.find( \"&amp;gt; li:not(.wb-fltr-out)\" ),\n\t\t\tiLen = objEventsListItems.length,\n\t\t\tdateTimeRegExp = /datetime\\s+\\{date:\\s*(\\d+-\\d+-\\d+)\\}/,\n\t\t\ti, $event, event, $objTitle, title, link, href, target,\n\t\t\tlinkId, date, tCollection, tCollectionTemp,\tstrDate1,\n\t\t\tstrDate2, z, zLen, className, dateClass;\n\n\t\tfor ( i = 0; i !== iLen; i += 1 ) {\n\t\t\t$event = objEventsListItems.eq( i );\n\t\t\tevent = $event[ 0 ];\n\t\t\t$objTitle = $event.find( \"*:header:first\" );\n\t\t\tclassName = $objTitle.attr( \"class\" );\n\t\t\ttitle = $objTitle.text();\n\t\t\tlink = $event.find( \"a\" )[ 0 ];\n\t\t\thref = link.getAttribute( \"href\" );\n\t\t\ttarget = link.getAttribute( \"target\" );\n\t\t\tzLen = 1;\n\n\t\t\t/*\n\t\t\t * Modification direct-linking or page-linking\n\t\t\t *\t- added the ability  to have class set the behaviour of the links\n\t\t\t *\t- default is to use the link of the item as the event link in the calendar\n\t\t\t *\t- 'evt-anchor' class dynamically generates page anchors on the links it maps to the event\n\t\t\t */\n\t\t\tif ( !directLinking ) {\n\t\t\t\tlinkId = event.id || wb.getId();\n\t\t\t\tevent.id = linkId;\n\t\t\t\thref = \"#\" + linkId;\n\t\t\t}\n\n\t\t\tdate = new Date();\n\t\t\tdate.setHours( 0, 0, 0, 0 );\n\t\t\ttCollection = event.getElementsByTagName( \"time\" );\n\n\t\t\t/*\n\t\t\t * Date spanning capability\n\t\t\t *   - since there may be some dates that are capable of spanning over months we need to identify them\n\t\t\t *     the process is see how many time nodes are in the event. 2 nodes will trigger a span\n\t\t\t */\n\t\t\tif ( tCollection.length !== 0 ) {\n\t\t\t\ttCollectionTemp = tCollection[ 0 ];\n\t\t\t\tstrDate1 = tCollectionTemp.nodeName.toLowerCase() === \"time\" ?\n\t\t\t\t\ttCollectionTemp.getAttribute( \"datetime\" ).substr( 0, 10 ).split( \"-\" ) :\n\t\t\t\t\ttCollectionTemp.className.match( dateTimeRegExp )[ 1 ].substr( 0, 10 ).split( \"-\" );\n\n\t\t\t\t// Convert to zero-based month\n\t\t\t\tstrDate1[ 1 ] = strDate1[ 1 ] - 1;\n\n\t\t\t\tdate.setFullYear( strDate1[ 0 ], strDate1[ 1 ], strDate1[ 2 ] );\n\n\t\t\t\tif ( tCollection.length !== 1 ) {\n\n\t\t\t\t\t// This is a spanning event\n\t\t\t\t\ttCollectionTemp = tCollection[ 1 ];\n\t\t\t\t\tstrDate2 = tCollectionTemp.nodeName.toLowerCase() === \"time\" ?\n\t\t\t\t\t\ttCollectionTemp.getAttribute( \"datetime\" ).substr( 0, 10 ).split( \"-\" ) :\n\t\t\t\t\t\ttCollectionTemp.className.match( dateTimeRegExp )[ 1 ].substr( 0, 10 ).split( \"-\" );\n\n\t\t\t\t\t// Convert to zero-based month\n\t\t\t\t\tstrDate2[ 1 ] = strDate2[ 1 ] - 1;\n\n\t\t\t\t\tzLen += daysBetween( strDate1, strDate2 );\n\t\t\t\t}\n\n\t\t\t\t// Now loop in events to load up all the days that it would be on tomorrow.setDate(tomorrow.getDate() + 1);\n\t\t\t\tfor ( z = 0; z !== zLen; z += 1 ) {\n\t\t\t\t\tif ( z !== 0 ) {\n\t\t\t\t\t\tdate = new Date( date.setDate( date.getDate() + 1 ) );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( events.minDate === null || date &amp;lt; events.minDate ) {\n\t\t\t\t\t\tevents.minDate = date;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( events.maxDate === null || date &amp;gt; events.maxDate ) {\n\t\t\t\t\t\tevents.maxDate = date;\n\t\t\t\t\t}\n\n\t\t\t\t\tevents.list[ events.iCount ] = {\n\t\t\t\t\t\ttitle: title,\n\t\t\t\t\t\tdate: new Date( date.getTime() ),\n\t\t\t\t\t\thref: href,\n\t\t\t\t\t\ttarget: target\n\t\t\t\t\t};\n\n\t\t\t\t\t// Add a viewfilter\n\t\t\t\t\tdateClass = \"filter-\" + ( date.getFullYear() ) + \"-\" +\n\t\t\t\t\t\twb.string.pad( date.getMonth() + 1, 2 );\n\t\t\t\t\tif ( !className ) {\n\t\t\t\t\t\tclassName = dateClass;\n\t\t\t\t\t} else if ( className.indexOf( dateClass ) === -1 ) {\n\t\t\t\t\t\tclassName += \" \" + dateClass;\n\t\t\t\t\t}\n\t\t\t\t\tevents.iCount += 1;\n\t\t\t\t}\n\t\t\t\t$objTitle.attr( \"class\", className );\n\t\t\t}\n\n\t\t// End of loop through objects/events\n\t\t}\n\n\t\t//Sort events\n\t\tevents.list.sort( function( firstEvent, secondEvent ) {\n\t\t\treturn firstEvent.date - secondEvent.date;\n\t\t} );\n\n\t\treturn events;\n\t},\n\n\taddEvents = function( year, month, $days ) {\n\t\tvar eventsList = this.events,\n\t\t\ti, eLen, date, dayIndex, $day, $dayEvents, event, eventMonth;\n\n\t\t/*\n\t\t * Determines for each event, if it occurs in the display month\n\t\t */\n\t\tfor ( i = 0, eLen = eventsList.length; i !== eLen; i += 1 ) {\n\t\t\tevent = eventsList[ i ];\n\t\t\tdate = event.date;\n\n\t\t\tif ( date.getFullYear() === year ) {\n\t\t\t\teventMonth = date.getMonth();\n\t\t\t\tif ( eventMonth &amp;gt; month ) {\n\n\t\t\t\t\t//End the loop if the next event is in a future month because events are sorted chronologically\n\t\t\t\t\tbreak;\n\t\t\t\t} else if ( date.getMonth() === month ) {\n\t\t\t\t\tdayIndex = date.getDate() - 1;\n\t\t\t\t\t$day = $( $days[ dayIndex ] );\n\n\t\t\t\t\t//Get the appropriate day events if a day link exists\n\t\t\t\t\tif ( $day.parent().get( 0 ).nodeName !== \"A\" ) {\n\t\t\t\t\t\t$dayEvents = $day.next();\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$dayEvents = $day.parent().next();\n\t\t\t\t\t}\n\n\t\t\t\t\t//Create the event list container if it doesn't exist\n\t\t\t\t\tif ( $dayEvents.length !== 1 ) {\n\t\t\t\t\t\t$dayEvents = $( \"\n\" ).insertAfter( $day );\n\n\t\t\t\t\t\t//Determine the focus based on the day before\n\t\t\t\t\t\tif ( dayIndex &amp;amp;&amp;amp; $days[ dayIndex - 1 ].parentNode.nodeName === \"A\" ) {\n\t\t\t\t\t\t\t$day.wrap( \"\" );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$day.wrap( \"\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$day.parent().attr( \"href\", \"javascript:;\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t//Add the event to the list\n\t\t\t\t\t$dayEvents.append( \"\n\" + event.title + \"\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\tfilterEvents = function( year, month ) {\n\t\tthis.find( \"li.cal-disp-onshow\" )\n\t\t\t.addClass( hiddenClass )\n\t\t\t.has( \":header[class*=filter-\" + year + \"-\" +\n\t\t\t\twb.string.pad( parseInt( month, 10 ) + 1, 2 ) + \"]\" )\n\t\t\t.removeClass( hiddenClass );\n\t},\n\n\tshowEvents = function() {\n\t\t$( this )\n\t\t\t.next()\n\t\t\t.addClass( evDetails );\n\t},\n\n\thideEvents = function() {\n\t\tvar $link = $( this ),\n\t\t\t$cell = $link.closest( \"td\" );\n\n\t\tsetTimeout( function() {\n\t\t\tif ( $cell.find( \"a:focus\" ).length === 0 ) {\n\t\t\t\t$cell.find( \"ul\" )\n\t\t\t\t\t.removeClass( evDetails )\n\t\t\t\t\t.find( \"a\" )\n\t\t\t\t\t.attr( \"tabindex\", \"-1\" );\n\t\t\t}\n\t\t}, 5 );\n\t},\n\n\tgetLocaleDate = function( dateString ) {\n\t\tvar date = new Date(),\n\t\t\tdateComponents = dateString.split( \"-\" );\n\n\t\tdateComponents[ 1 ] = dateComponents[ 1 ] - 1;\t// Convert to zero-based month\n\t\tdate.setFullYear( dateComponents[ 0 ], dateComponents[ 1 ], dateComponents[ 2 ] );\n\n\t\treturn date;\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent + \" wb-redraw\" + selector, selector, function( event ) {\n\n\tvar eventType = event.type,\n\t\tcalendarId = event.currentTarget.dataset.calevtSrc;\n\n\tswitch ( eventType ) {\n\t\tcase \"timerpoke\":\n\t\tcase \"wb-init\":\n\t\t\tinit( event );\n\t\t\tbreak;\n\n\t\tcase \"wb-redraw\":\n\t\t\tvar $elm = $( \"#\" + event.target.id );\n\t\t\t$( \"#\" + calendarId + \" .wb-clndr\" ).remove();\n\t\t\tprocessEvents( $elm );\n\t\t\t$elm.trigger( \"wb-updated\" + selector );\n\t\t\tbreak;\n\t}\n} );\n\n$document.on( \"wb-navigate.wb-clndr\", selectorEvent, function( event ) {\n\tvar lib = event.target.lib,\n\t\t$calEvent;\n\n\tif ( lib ) {\n\t\t$calEvent = lib.$events;\n\n\t\tif ( $calEvent ) {\n\t\t\tfilterEvents.call( $calEvent, event.year, event.month );\n\n\t\t\t//TODO: Added for backwards compatibility. Remove in previous versions\n\t\t\t$calEvent.trigger( \"wb-updated\" + selector );\n\t\t}\n\t}\n} );\n\n$document.on( \"focusin focusout keydown\", selectorEvent + \" .cal-evt\", function( event ) {\n\tvar eventType = event.type,\n\t\t$link;\n\n\tswitch ( eventType ) {\n\t\tcase \"focusin\":\n\t\t\tshowEvents.call( event.target );\n\t\t\tbreak;\n\t\tcase \"focusout\":\n\t\t\thideEvents.call( event.target );\n\t\t\tbreak;\n\t\tcase \"keydown\":\n\t\t\t$link = $( event.target );\n\t\t\tif ( ( event.which === 13 || event.which === 32 ) &amp;amp;&amp;amp; $link.hasClass( \"cal-evt\" ) ) {\n\t\t\t\t$( event.target ).next().find( \"a:first\" ).trigger( setFocusEvent );\n\t\t\t}\n\t\t\tbreak;\n\t}\n} );\n\n$document.on( \"keydown\", selectorEvent + \" td &amp;gt; ul li\", function( event ) {\n\tvar $item = $( event.currentTarget ),\n\t\t$toFocus, $itemParent;\n\n\tswitch ( event.which ) {\n\t\tcase 38:\n\t\t\t$toFocus = $item.prev().find( \"a\" );\n\t\t\tif ( $toFocus.length === 0 ) {\n\t\t\t\t$toFocus = $item.siblings( \":last\" ).find( \"a\" );\n\t\t\t}\n\t\t\t$toFocus.trigger( setFocusEvent );\n\t\t\tbreak;\n\t\tcase 40:\n\t\t\t$toFocus = $item.next().find( \"a\" );\n\t\t\tif ( $toFocus.length === 0 ) {\n\t\t\t\t$toFocus = $item.siblings( \":first\" ).find( \"a\" );\n\t\t\t}\n\t\t\t$toFocus.trigger( setFocusEvent );\n\t\t\tbreak;\n\t\tcase 27:\n\t\t\t$itemParent = $item.closest( \"td\" ).children( \"a\" );\n\t\t\t$itemParent.trigger( setFocusEvent );\n\t\t\tbreak;\n\t}\n} );\n\n$document.on( \"focusout\", selectorEvent + \" td &amp;gt; ul\", function( event ) {\n\thideEvents.call( event.target );\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n( function( $, DOMPurify, window, document, wb, undef ) {\n\nvar i18nText,\n\t$document = wb.doc,\n\tselector = \".wb-clndr\",\n\tnavigateEvent = \"wb-navigate\" + selector,\n\tinited = false,\n\tcurrDate = new Date(),\n\tcurrYear = currDate.getFullYear(),\n\tcurrMonth = currDate.getMonth(),\n\tdefaults = {\n\t\tyear: currYear,\n\t\tmonth: currMonth,\n\t\tminDate: new Date( currYear, 0, 1 ),\n\t\tmaxDate: new Date( currYear, 11, 31 )\n\t},\n\t$calBase,\n\n\tinit = function() {\n\t\tvar i18n = wb.i18n,\n\t\t\ttextWeekDayNames, textMonthNames;\n\n\t\ti18nText = {\n\t\t\tmonthNames: i18n( \"mnths\" ),\n\t\t\tprevMonth: i18n( \"prvMnth\" ),\n\t\t\tnextMonth: i18n( \"nxtMnth\" ),\n\t\t\tgoToYear: i18n( \"cal-goToYr\" ),\n\t\t\tgoToMonth: i18n( \"cal-goToMnth\" ),\n\t\t\tdayNames: i18n( \"days\" ),\n\t\t\tcurrDay: i18n( \"currDay\" ),\n\t\t\tformat: i18n( \"cal-format\" ),\n\t\t\tcalendar: i18n( \"cal\" )\n\t\t};\n\n\t\ttextWeekDayNames = i18nText.dayNames;\n\t\ttextMonthNames = i18nText.monthNames;\n\n\t\t$calBase = $( \"\n\" +\n\t\t\t\"\n\" +\n\t\t\t\t\"\" + // Added for screen-readers\n\t\t\t\t\"\" +\n\t\t\t\t\t\"\" +\n\t\t\t\t\t\"\" + i18nText.prevMonth + \"\" +\n\t\t\t\t\"\" +\n\t\t\t\t\"\" +\n\t\t\t\t\t\"\" +\n\t\t\t\t\t\"\" + i18nText.nextMonth + \"\" +\n\t\t\t\t\"\" +\n\t\t\t\t\"\n\" +\n\t\t\t\t\t\"\" + i18nText.goToYear + \"\\n\" +\n\t\t\t\t\t\"\" + i18nText.goToMonth + \"\" +\n\t\t\t\t\t\t( function() {\n\t\t\t\t\t\t\tvar months = \"\",\n\t\t\t\t\t\t\t\tm;\n\n\t\t\t\t\t\t\tfor ( m = 0; m &amp;lt; 12; m += 1 ) {\n\t\t\t\t\t\t\t\tmonths += \"\" + textMonthNames[ m ] + \"\";\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn months;\n\t\t\t\t\t\t} )() +\n\t\t\t\t\t\"\" +\n\t\t\t\t\"\" +\n\t\t\t\"\" +\n\t\t\t\"\n\" +\n\t\t\t\t\"\" +\n\t\t\t\t\t\"\" +\n\t\t\t\t\t\t( function() {\n\t\t\t\t\t\t\tvar days = \"\",\n\t\t\t\t\t\t\t\td;\n\n\t\t\t\t\t\t\tfor ( d = 0; d &amp;lt; 7; d += 1 ) {\n\t\t\t\t\t\t\t\tdays += \"\" + textWeekDayNames[ d ].substr( 0, 1 ) + \"\";\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\treturn days;\n\t\t\t\t\t\t} )() +\n\t\t\t\t\t\"\" +\n\t\t\t\t\"\" +\n\t\t\t\t\"\" +\n\t\t\t\"\" +\n\t\t\"\" );\n\n\t\tinited = true;\n\t},\n\n\tcreateCalendar = function( $container, settings ) {\n\t\tvar calendar = {\n\t\t\t\treInit: initCalendar\n\t\t\t}, $calendarObj, calendarObj;\n\n\t\tif ( !inited ) {\n\t\t\tinit();\n\t\t}\n\n\t\t$calendarObj = $calBase.clone();\n\t\tcalendarObj = $calendarObj.get( 0 );\n\n\t\tcalendar.$o = $calendarObj;\n\t\tcalendar.o = calendarObj;\n\t\tcalendarObj.lib = calendar;\n\n\t\t$calendarObj.appendTo( $container );\n\n\t\tcalendar.reInit( settings );\n\n\t\treturn calendar;\n\t},\n\n\tinitCalendar = function( settings ) {\n\t\tvar years = \"\",\n\t\t\t$calendarObj = this.$o,\n\t\t\t$yearField, lastYear, y, defaultsPartial;\n\n\t\tsettings = settings || {};\n\n\t\tif ( settings.year !== undef &amp;amp;&amp;amp; settings.month !== undef ) {\n\t\t\tdefaultsPartial = {\n\t\t\t\tminDate: new Date( settings.year, 0, 1 ),\n\t\t\t\tmaxDate: new Date( settings.year, 11, 31 )\n\t\t\t};\n\t\t\t$.extend( this, defaultsPartial, settings );\n\t\t} else {\n\t\t\t$.extend( this, defaults );\n\t\t}\n\n\t\t//Generates the list of years\n\t\tlastYear = this.maxDate.getFullYear();\n\t\t$yearField = $calendarObj.find( \".cal-year\" ).empty();\n\t\tfor ( y = this.minDate.getFullYear(); y &amp;lt;= lastYear; y += 1 ) {\n\t\t\tyears += \"\" + y + \"\";\n\t\t}\n\t\t$yearField.append( years );\n\n\t\t$calendarObj\n\t\t\t.trigger( {\n\t\t\t\ttype: navigateEvent,\n\t\t\t\tyear: this.year,\n\t\t\t\tmonth: this.month,\n\t\t\t\tinitEvent: true\n\t\t\t} );\n\t},\n\n\tcreateDays = function( calendar, year, month ) {\n\t\tvar $container = $( calendar ).find( \".cal-days\" ),\n\t\t\tdaysContainer = $container.get( 0 ),\n\t\t\tdayCount = 1,\n\t\t\ttextCurrentDay = i18nText.currDay,\n\t\t\tlib = calendar.lib,\n\t\t\tminDate = lib.minDate,\n\t\t\tmaxDate = lib.maxDate,\n\t\t\tcallback = lib.daysCallback,\n\t\t\trow, cell,\n\t\t\tdate, firstDay, lastDay, currYear, currMonth, currDay, week, day, className, isCurrentDate, isoDate, printDate, breakAtEnd, days, inRange;\n\n\t\tdate = new Date( year, month, 1 );\n\n\t\tfirstDay = date.getDay();\n\t\tdate.setMonth( month + 1, 0 );\n\t\tlastDay = date.getDate();\n\n\t\t// Get the current date\n\t\tdate = new Date();\n\t\tcurrYear = date.getFullYear();\n\t\tcurrMonth = date.getMonth();\n\t\tcurrDay = date.getDate();\n\n\t\t// Clean all existing rows\n\t\t$container.empty();\n\n\t\tfor ( week = 1; week &amp;lt; 7; week += 1 ) {\n\t\t\trow = daysContainer.insertRow();\n\n\t\t\tfor ( day = 0; day &amp;lt; 7; day += 1 ) {\n\n\t\t\t\tif ( ( week === 1 &amp;amp;&amp;amp; day &amp;lt; firstDay ) || ( dayCount &amp;gt; lastDay ) ) {\n\n\t\t\t\t\t// Creates empty cells | Cree les cellules vides\n\t\t\t\t\tcell = row.insertCell();\n\t\t\t\t\tcell.classList.add( \"cal-empty\" );\n\t\t\t\t\tcell.textContent = \" \";\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Creates date cells | Cree les cellules de date\n\t\t\t\t\tisCurrentDate = ( dayCount === currDay &amp;amp;&amp;amp; month === currMonth &amp;amp;&amp;amp; year === currYear );\n\t\t\t\t\tclassName = \"cal-index-\" + dayCount + ( isCurrentDate ? \" cal-curr-day \" : \"\" );\n\n\t\t\t\t\tdate.setFullYear( year, month, dayCount );\n\t\t\t\t\tisoDate = date.toLocalISOString().substr( 0, 10 );\n\t\t\t\t\tprintDate = displayDate( date ) + ( isCurrentDate ? \"\" + textCurrentDay + \"\" : \"\" );\n\n\t\t\t\t\tcell = row.insertCell();\n\t\t\t\t\tcell.setAttribute( \"class\", className );\n\t\t\t\t\tcell.innerHTML = DOMPurify.sanitize( \"\" + printDate + \"\" );\n\n\t\t\t\t\tif ( dayCount &amp;gt;= lastDay ) {\n\t\t\t\t\t\tbreakAtEnd = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdayCount += 1;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( breakAtEnd ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( callback ) {\n\t\t\tdays = $container.find( \"time\" );\n\t\t\tinRange = {};\n\n\t\t\tif ( year === minDate.getFullYear() &amp;amp;&amp;amp; month === minDate.getMonth() ) {\n\t\t\t\tinRange.min = minDate.getDate() - 1;\n\t\t\t}\n\n\t\t\tif ( year === maxDate.getFullYear() &amp;amp;&amp;amp; month === maxDate.getMonth() ) {\n\t\t\t\tinRange.max = maxDate.getDate() - 1;\n\t\t\t}\n\n\t\t\tcallback.call( calendar.lib, year, month, days, inRange );\n\t\t}\n\t},\n\n\tdisplayDate = function( date ) {\n\t\tvar textWeekDayNames = i18nText.dayNames,\n\t\t\ttextMonthNames = i18nText.monthNames;\n\n\t\treturn i18nText.format.replace( /\\{ddd\\}|\\{d\\}|\\{M\\}|\\{Y\\}/g, function( match ) {\n\t\t\tswitch ( match ) {\n\t\t\t\tcase \"{ddd}\":\n\t\t\t\t\treturn textWeekDayNames[ parseInt( date.getDay(), 10 ) ];\n\t\t\t\tcase \"{d}\":\n\t\t\t\t\treturn parseInt( date.getDate(), 10 );\n\t\t\t\tcase \"{M}\":\n\t\t\t\t\treturn textMonthNames[ parseInt( date.getMonth(), 10 ) ];\n\t\t\t\tcase \"{Y}\":\n\t\t\t\t\treturn date.getFullYear();\n\t\t\t}\n\t\t} );\n\t};\n\nwb.calendar = {\n\tcreate: createCalendar\n};\n\n$document.on( navigateEvent, selector, function( event ) {\n\tvar calendarObj = event.currentTarget,\n\t\t$calendar = $( calendarObj ),\n\t\tyear = event.year,\n\t\tmonth = event.month,\n\t\tlib = calendarObj.lib,\n\t\tmaxYear = lib.maxDate.getFullYear(),\n\t\tmaxMonth = lib.maxDate.getMonth(),\n\t\tminYear = lib.minDate.getFullYear(),\n\t\tminMonth = lib.minDate.getMonth(),\n\t\t$prevArrow = $calendar.find( \".cal-month-prev\" ),\n\t\t$nextArrow = $calendar.find( \".cal-month-next\" ),\n\t\t$monthField = $calendar.find( \".cal-month\" ),\n\t\tdisabled = \"disabled\";\n\n\tif ( year !== undef ) {\n\t\tlib.year = year;\n\t}\n\n\tif ( month !== undef ) {\n\t\tlib.month = month;\n\t}\n\n\t//Update UI\n\t$calendar.find( \".cal-year\" ).val( year );\n\n\t$monthField.val( month );\n\n\t$monthField.children( \":\" + disabled ).removeAttr( disabled );\n\n\tif ( year &amp;lt; minYear || ( year === minYear &amp;amp;&amp;amp; month &amp;lt;= minMonth ) ) {\n\t\t$prevArrow.attr( disabled, disabled );\n\t} else {\n\t\t$prevArrow.removeAttr( disabled );\n\t}\n\n\tif ( year &amp;gt; maxYear || ( year === maxYear &amp;amp;&amp;amp; month &amp;gt;= maxMonth ) ) {\n\t\t$nextArrow.attr( disabled, disabled );\n\t} else {\n\t\t$nextArrow.removeAttr( disabled );\n\t}\n\n\tif ( year === minYear ) {\n\t\t$monthField.children( \":lt(\" + minMonth + \")\" ).attr( disabled, disabled );\n\t}\n\n\tif ( year === maxYear ) {\n\t\t$monthField.children( \":gt(\" + maxMonth + \")\" ).attr( disabled, disabled );\n\t}\n\n\tcreateDays( event.currentTarget, event.year, event.month );\n\n\t// Added declaration of current month in aria-live=\"polite\" for screen-readers\n\tif ( !event.initEvent ) {\n\t\t$calendar.find( \".current-month\" ).text( i18nText.monthNames[ month ] + \" \" + year );\n\t}\n} );\n\n$document.on( \"change\", selector, function( event ) {\n\tvar target = event.target,\n\t\tcalendar = event.currentTarget,\n\t\tyear, month;\n\n\tswitch ( target.className ) {\n\t\tcase \"cal-year\":\n\t\t\tyear = parseInt( target.value, 10 );\n\t\t\tmonth = calendar.lib.month;\n\t\t\tbreak;\n\t\tcase \"cal-month\":\n\t\t\tyear = calendar.lib.year;\n\t\t\tmonth = parseInt( target.value, 10 );\n\t\t\tbreak;\n\t}\n\n\t$( calendar ).trigger( {\n\t\ttype: navigateEvent,\n\t\tyear: year,\n\t\tmonth: month\n\t} );\n} );\n\n$document.on( \"click\", \".cal-month-prev, .cal-month-next\", function( event ) {\n\tvar $calendar = $( event.currentTarget ).closest( selector ),\n\t\tcalendar = $calendar.get( 0 ),\n\t\tclassName = event.currentTarget.className,\n\t\tmodifier = className.indexOf( \"cal-month-prev\" ) !== -1 ? -1 : 1,\n\t\tdate = new Date( calendar.lib.year, calendar.lib.month + modifier, 1 );\n\n\t$calendar.trigger( {\n\t\ttype: navigateEvent,\n\t\tyear: date.getFullYear(),\n\t\tmonth: date.getMonth()\n\t} );\n\tif ( wb.ie11 ) {\n\t\t$calendar.trigger( \"focusin\" );\n\t}\n} );\n\n$document.on( \"keydown\", selector, function( event ) {\n\tvar calendar = event.currentTarget,\n\t\t$days = $( event.currentTarget ).find( \".cal-days\" ),\n\t\ttarget = event.target,\n\t\twhich = event.which,\n\t\tlib = calendar.lib,\n\t\tdate = new Date( lib.year, lib.month, 1 ),\n\t\tminDate = lib.minDate,\n\t\tmaxDate = lib.maxDate,\n\t\tcurrentDate = new Date( date ),\n\t\tnavigate = true,\n\t\tclassMatch, isDayLink, lastDay, modifier, day;\n\n\tif ( !event.altKey &amp;amp;&amp;amp; !event.metaKey &amp;amp;&amp;amp; which &amp;gt; 32 &amp;amp;&amp;amp; which &amp;lt; 41 ) {\n\n\t\tclassMatch = target.parentNode.className.match( /cal-index-(\\d{1,2})/ );\n\t\tisDayLink = classMatch !== null;\n\n\t\t//Key binding for the entire calendar\n\t\tswitch ( which ) {\n\n\t\t\t//page up\n\t\t\tcase 33:\n\t\t\t\tdate.setDate( minDate.getDate() );\n\n\t\t\t\t//page down\n\t\t\t\t/* falls through */\n\t\t\tcase 34:\n\t\t\t\tmodifier = ( which === 33 ? -1 : 1 );\n\n\t\t\t\tif ( event.ctrlKey || event.shiftKey || event.altKey ) {\n\t\t\t\t\tdate.setYear( date.getFullYear() + modifier );\n\t\t\t\t} else {\n\t\t\t\t\tdate.setMonth( date.getMonth() + modifier );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\t//Key binding for navigating calendar days\n\t\tif ( isDayLink ) {\n\t\t\tday = parseInt( classMatch[ 1 ], 10 );\n\t\t\tdate.setMonth( date.getMonth() + 1, 0 );\n\t\t\tlastDay = date.getDate();\n\t\t\tdate.setDate( day &amp;gt; lastDay ? lastDay : day );\n\n\t\t\tswitch ( which ) {\n\n\t\t\t\t// end / home\n\t\t\t\tcase 35:\n\t\t\t\t\tdate.setDate( lastDay );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 36:\n\t\t\t\t\tdate.setDate( 1 );\n\t\t\t\t\tbreak;\n\n\t\t\t\t// left / up / right / down arrows\n\t\t\t\tcase 37:\n\t\t\t\t\tdate.setDate( day - 1 );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 38:\n\t\t\t\t\tdate.setDate( day - 7 );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 39:\n\t\t\t\t\tdate.setDate( day + 1 );\n\t\t\t\t\tbreak;\n\t\t\t\tcase 40:\n\t\t\t\t\tdate.setDate( day + 7 );\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( date &amp;lt; minDate || date &amp;gt; maxDate ) {\n\t\t\tif ( which === 35 ) {\n\t\t\t\tdate.setDate( maxDate.getDate() );\n\t\t\t} else if ( which === 36 ) {\n\t\t\t\tdate = minDate;\n\t\t\t} else {\n\t\t\t\tnavigate = false;\n\t\t\t}\n\t\t}\n\n\t\tif ( navigate &amp;amp;&amp;amp; ( date.getMonth() !== currentDate.getMonth() || date.getFullYear() !== currentDate.getFullYear() ) ) {\n\t\t\t$( calendar ).trigger( {\n\t\t\t\ttype: navigateEvent,\n\t\t\t\tyear: date.getFullYear(),\n\t\t\t\tmonth: date.getMonth()\n\t\t\t} );\n\t\t}\n\n\t\tif ( isDayLink ) {\n\t\t\t$days.find( \".cal-index-\" + date.getDate() + \" a:first\" ).focus();\n\t\t}\n\n\t\tevent.preventDefault();\n\t\treturn false;\n\t}\n\n} );\n\n( function() {\n\n\tfunction pad( number ) {\n\t\tif ( number &amp;lt; 10 ) {\n\t\t\treturn \"0\" + number;\n\t\t}\n\t\treturn number;\n\t}\n\n\tDate.prototype.toLocalISOString = function() {\n\t\tvar tz = this.getTimezoneOffset();\n\t\tif ( tz === 0 ) {\n\t\t\treturn this.toISOString();\n\t\t}\n\t\treturn this.getFullYear() +\n\t\t\t\"-\" + pad( this.getMonth() + 1 ) +\n\t\t\t\"-\" + pad( this.getDate() ) +\n\t\t\t\"T\" + pad( this.getHours() ) +\n\t\t\t\":\" + pad( this.getMinutes() ) +\n\t\t\t\":\" + pad( this.getSeconds() ) +\n\t\t\t\".\" + ( this.getMilliseconds() / 1000 ).toFixed( 3 ).slice( 2, 5 ) +\n\t\t\t( tz &amp;lt; 0 ? \"+\" : \"-\" ) +\n\t\t\tpad( Math.floor( Math.abs( tz / 60 ) ) ) +\n\t\t\t\":\" + pad( tz % 60 );\n\t};\n\n\tif ( !Date.prototype.toISOString ) {\n\t\tDate.prototype.toISOString = function() {\n\t\t\treturn this.getUTCFullYear() +\n\t\t\t\t\"-\" + pad( this.getUTCMonth() + 1 ) +\n\t\t\t\t\"-\" + pad( this.getUTCDate() ) +\n\t\t\t\t\"T\" + pad( this.getUTCHours() ) +\n\t\t\t\t\":\" + pad( this.getUTCMinutes() ) +\n\t\t\t\t\":\" + pad( this.getUTCSeconds() ) +\n\t\t\t\t\".\" + ( this.getUTCMilliseconds() / 1000 ).toFixed( 3 ).slice( 2, 5 ) +\n\t\t\t\t\"Z\";\n\t\t};\n\t}\n}() );\n\n} )( jQuery, DOMPurify, window, document, wb );\n\n/**\n * Web Experience Toolkit (WET) / Bo\u00eete \u00e0 outils de l'exp\u00e9rience Web (BOEW)\n * @title Charts and Graph\n * @overview Draw charts from an html simple and complex data table\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @duboisp\n *\n */\n( function( $, window, document, wb ) {\n\"use strict\";\n\n/**\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-charts\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\ttableParsingEvent = \"passiveparse.wb-tableparser\",\n\ttableParsingCompleteEvent = \"parsecomplete.wb-tableparser\",\n\t$document = wb.doc,\n\ti18n, i18nText,\n\n\t/**\n\t * Main Entry function to create the charts\n\t * @method createCharts\n\t * @param {jQuery DOM element} $elm table element use to create the chart\n\t */\n\tcreateCharts = function( $elm ) {\n\t\tvar allSeries = [],\n\t\t\tchartslabels = [],\n\t\t\tdataSeries = [],\n\t\t\tnbBarChart = 0,\n\t\t\t$caption = $( \"caption\", $elm ),\n\t\t\tcaptionHtml = $caption.html() || \"\",\n\t\t\tcaptionText = $caption.text() || \"\",\n\t\t\tvaluePoint = 0,\n\t\t\tdataCellUnitRegExp = /[^+\\-., 0-9]+[^\\-+0-9]*/,\n\t\t\tlowestFlotDelta, $imgContainer, $placeHolder,\n\t\t\t$wetChartContainer, htmlPlaceHolder, figurehtml,\n\t\t\tcellValue, datacolgroupfound, dataGroup, header,\n\t\t\ti, iLength, j, jLength, parsedData, rIndex, currVectorOptions,\n\t\t\tcurrentRowGroup, reverseTblParsing, dataGroupVector,\n\t\t\tcurrentDataGroupVector, dataCell, previousDataCell, currDataVector,\n\t\t\tpieQuaterFlotSeries, optionFlot, optionsCharts, globalOptions,\n\t\t\tdefaultsOptions = {\n\n\t\t\t\t// Flot Global Options\n\t\t\t\tflot: {\n\t\t\t\t\tprefix: \"wb-charts-\",\n\t\t\t\t\tdefaults: {\n\t\t\t\t\t\tcolors: wb.drawColours,\n\t\t\t\t\t\tcanvas: true,\n\t\t\t\t\t\txaxis: {\n\t\t\t\t\t\t\tticks: { }\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tline: { },\n\t\t\t\t\tarea: {\n\t\t\t\t\t\tlines: {\n\t\t\t\t\t\t\tshow: true,\n\t\t\t\t\t\t\tfill: true\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tbar: {\n\t\t\t\t\t\tbars: {\n\t\t\t\t\t\t\tshow: true,\n\t\t\t\t\t\t\tbarWidth: 1,\n\t\t\t\t\t\t\talign: \"center\"\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tpie: {\n\t\t\t\t\t\tseries: {\n\t\t\t\t\t\t\tpie: {\n\t\t\t\t\t\t\t\tshow: true\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfn: {\n\t\t\t\t\t\t\t\"/series/pie/label/formatter\": function( label, series ) {\n\t\t\t\t\t\t\t\tvar textlabel;\n\t\t\t\t\t\t\t\tif ( !optionsCharts.decimal ) {\n\t\t\t\t\t\t\t\t\ttextlabel = Math.round( series.percent );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\ttextlabel = Math.round( series.percent * Math.pow( 10, optionsCharts.decimal ) );\n\t\t\t\t\t\t\t\t\ttextlabel = textlabel / Math.pow( 10, optionsCharts.decimal );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif ( optionsCharts.nolegend ) {\n\n\t\t\t\t\t\t\t\t\t// Add the series label\n\t\t\t\t\t\t\t\t\ttextlabel = label + \"\" + textlabel;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\treturn textlabel + \"%\";\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tdonut: {\n\t\t\t\t\t\tbase: \"pie\",\n\t\t\t\t\t\tseries: {\n\t\t\t\t\t\t\tpie: {\n\t\t\t\t\t\t\t\tradius: 1,\n\t\t\t\t\t\t\t\tlabel: {\n\t\t\t\t\t\t\t\t\tshow: true,\n\t\t\t\t\t\t\t\t\tradius: 1,\n\t\t\t\t\t\t\t\t\tthreshold: 0.08\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\ttilt: 0.5,\n\t\t\t\t\t\t\t\tinnerRadius: 0.45,\n\t\t\t\t\t\t\t\tstartAngle: 1\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tgrid: {\n\t\t\t\t\t\t\thoverable: true\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tslicelegend: {\n\t\t\t\t\t\tbase: \"pie\",\n\t\t\t\t\t\tseries: {\n\t\t\t\t\t\t\tpie: {\n\t\t\t\t\t\t\t\tradius: 1,\n\t\t\t\t\t\t\t\tlabel: {\n\t\t\t\t\t\t\t\t\tradius: 1,\n\t\t\t\t\t\t\t\t\tshow: true,\n\t\t\t\t\t\t\t\t\tthreshold: 0.05\n\t\t\t\t\t\t\t\t},\n\t\t\t\t\t\t\t\tcombine: {\n\t\t\t\t\t\t\t\t\tthreshold: 0.05,\n\t\t\t\t\t\t\t\t\tcolor: \"#555\",\n\t\t\t\t\t\t\t\t\tlabel: i18nText.slicelegend\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t},\n\t\t\t\t\t\tfn: {\n\t\t\t\t\t\t\t\"/series/pie/label/formatter\": function( label ) {\n\t\t\t\t\t\t\t\treturn label;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\t// Flot Series Options\n\t\t\t\tseries: {\n\t\t\t\t\tprefix: \"wb-charts-\",\n\t\t\t\t\tdefaults: { },\n\t\t\t\t\tline: { },\n\t\t\t\t\tarea: {\n\t\t\t\t\t\tlines: {\n\t\t\t\t\t\t\tshow: true,\n\t\t\t\t\t\t\tfill: true\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tbar: {\n\t\t\t\t\t\tbars: {\n\t\t\t\t\t\t\tshow: true,\n\t\t\t\t\t\t\tbarWidth: 1,\n\t\t\t\t\t\t\talign: \"center\"\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tstacked: {\n\t\t\t\t\t\tbase: \"bar\"\n\t\t\t\t\t}\n\t\t\t\t},\n\n\t\t\t\t// Wet-boew Charts Options\n\t\t\t\tcharts: {\n\t\t\t\t\tprefix: \"wb-charts-\",\n\t\t\t\t\tdefaults: {\n\n\t\t\t\t\t\t// [string] Class name added at the figure element container\n\t\t\t\t\t\tgraphclass: \"wb-graph\",\n\n\t\t\t\t\t\t// [boolean] Wrap or not the table in a details/summary elements\n\t\t\t\t\t\tnoencapsulation: false,\n\n\t\t\t\t\t\t// [number] false means the deepest vector will be used for labelling\n\t\t\t\t\t\tlabelposition: false,\n\n\t\t\t\t\t\t// [number] false means the deepest vector will be used for calculate the reference\n\t\t\t\t\t\treferencevalue: false,\n\n\t\t\t\t\t\t// [boolean] false means to move the legend from inside the charts to next to it\n\t\t\t\t\t\tlegendinline: false,\n\n\t\t\t\t\t\t// [boolean] true means that the legend will be destroyed and the label for pie chart will include the legend\n\t\t\t\t\t\tnolegend: false,\n\n\t\t\t\t\t\t// [number] Literal number of displayed decimal for a pie charts\n\t\t\t\t\t\tdecimal: 0,\n\n\t\t\t\t\t\t// [number] Provide a default width for the charts that will be rendered\n\t\t\t\t\t\twidth: $elm.width(),\n\n\t\t\t\t\t\t// [number] Provide a default height for the charts that will be rendered\n\t\t\t\t\t\theight: $elm.height(),\n\n\t\t\t\t\t\t// [boolean] Flag for defining if the data table should be read in reverse compared to HTML spec\n\t\t\t\t\t\treversettblparsing: false,\n\t\t\t\t\t\tfn: {\n\t\t\t\t\t\t\t\"/getcellvalue\": function( elem ) {\n\n\t\t\t\t\t\t\t\t// Get the number from the data cell, #3267\n\t\t\t\t\t\t\t\tvar cellValue = String( elem.dataset.wbChartsValue || $( elem ).text() ).trim();\n\t\t\t\t\t\t\t\treturn [\n\t\t\t\t\t\t\t\t\tparseFloat( cellValue.replace( /(\\d{1,3}(?:(?: |,)\\d{3})*)(?:(?:.|,)(\\d{1,2}))?$/, function( a, b, c ) {\n\t\t\t\t\t\t\t\t\t\treturn b.replace( / |,/g, \"\" ) + \".\" + c || \"0\";\n\t\t\t\t\t\t\t\t\t} ), 10 ),\n\t\t\t\t\t\t\t\t\tcellValue.match( dataCellUnitRegExp )\n\t\t\t\t\t\t\t\t];\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t},\n\t\t\t\t\tdonut: {\n\t\t\t\t\t\tdecimal: 1\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t};\n\n\t\t/**\n\t\t * A little function to overwrite and add preset into the default options\n\t\t *\n\t\t * @method overwriteDefaultsOptions\n\t\t * @param {string} scopekey - Key that represent the subject of the setting, [flot, charts, series,...]\n\t\t * @param {json object} target - DefaultOptions that will be overwritten\n\t\t * @param {json object} object - User defined object for overwriting options\n\t\t * @return {json object} - Return the new object\n\t\t */\n\t\tfunction overwriteDefaultsOptions( scopekey, target, object ) {\n\t\t\tvar cachedObj, key;\n\n\t\t\tcachedObj = object[ scopekey ];\n\t\t\tif ( !cachedObj ) {\n\t\t\t\treturn target;\n\t\t\t}\n\t\t\tfor ( key in cachedObj ) {\n\t\t\t\tif ( !Object.prototype.hasOwnProperty.call( cachedObj, key ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\ttarget[ scopekey ][ key ] = cachedObj[ key ];\n\t\t\t}\n\t\t\treturn target;\n\t\t}\n\n\t\t// User defined options\n\t\tif ( !window.chartsGraphOpts ) {\n\t\t\tglobalOptions = window[ componentName ];\n\n\t\t\t// Global setting\n\t\t\tif ( globalOptions ) {\n\t\t\t\toverwriteDefaultsOptions( \"flot\", defaultsOptions, globalOptions );\n\t\t\t\toverwriteDefaultsOptions( \"series\", defaultsOptions, globalOptions );\n\t\t\t\toverwriteDefaultsOptions( \"charts\", defaultsOptions, globalOptions );\n\t\t\t}\n\n\t\t\t// Save the setting here in a case of a second graphic on the same page\n\t\t\twindow.chartsGraphOpts = defaultsOptions;\n\t\t}\n\t\tdefaultsOptions = window.chartsGraphOpts;\n\n\t\t/**\n\t\t * A little function to ease the web editor life\n\t\t *\n\t\t * Apply preset defined by a set of space-separated tokens from a baseline json object and at the same time extend the result by using the HTML5 data attribute\n\t\t *\n\t\t * @method applyPreset\n\t\t * @param {json object} baseline - Base line json object that includes predefined and user defined preset\n\t\t * @param {jQuery} $elem - Element on which the class attribute will be taken for a set of space-separated tokens\n\t\t * @param {string} attribute - Name of the HTML5 data attribute for extending the object at the end\n\t\t * @return {json object} - Return a new object build from the ```baseline``` or ```baseline.default``` object with the preset applied.\n\t\t */\n\t\tfunction applyPreset( baseline, $elem, attribute ) {\n\n\t\t\tvar config = $.extend( true, {}, baseline.defaults || baseline ),\n\t\t\t\tfn = $.extend( true, {}, baseline.defaults &amp;amp;&amp;amp; baseline.defaults.fn || { } ),\n\t\t\t\ttokens = $elem.attr( \"class\" ) || \"\",\n\t\t\t\ttblTokens, i, iLength, token, tokenLength,\n\n\t\t\t\t// Prefix used in front of the token\n\t\t\t\tprefix, prefixLength,\n\t\t\t\tpreset, key, tblFn, localKey, currObj;\n\n\t\t\tif ( tokens.length ) {\n\n\t\t\t\tprefix = ( baseline.prefix || \"\" );\n\t\t\t\tprefixLength = prefix.length;\n\n\t\t\t\t// split the set of space-separated tokens\n\t\t\t\ttblTokens = tokens.split( \" \" );\n\n\t\t\t\tfor ( i = 0, iLength = tblTokens.length; i !== iLength; i += 1 ) {\n\n\t\t\t\t\t// Get the current token\n\t\t\t\t\ttoken = tblTokens[ i ];\n\t\t\t\t\ttokenLength = token.length;\n\n\t\t\t\t\t// Remove the token is used\n\t\t\t\t\tif ( tokenLength &amp;lt;= prefixLength || token.slice( 0, prefixLength ) !== prefix ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\ttoken = token.slice( prefixLength, tokenLength );\n\n\t\t\t\t\tpreset = baseline[ token ];\n\n\t\t\t\t\t// Apply the preset\n\t\t\t\t\tif ( preset ) {\n\t\t\t\t\t\tif ( preset.base ) {\n\n\t\t\t\t\t\t\t// Like setting inherited from a parent config\n\t\t\t\t\t\t\tconfig = $.extend( true, config, baseline[ preset.base ] );\n\t\t\t\t\t\t\tfn = $.extend( true, fn, baseline[ preset.base ].fn || { } );\n\t\t\t\t\t\t}\n\t\t\t\t\t\tconfig = $.extend( true, config, preset );\n\t\t\t\t\t\tfn = $.extend( true, fn, preset.fn || { } );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Extend the config from the element @data attribute\n\t\t\tconfig = $.extend( true, config, wb.getData( $elem, attribute ) );\n\n\t\t\t// Merge and override the function.\n\t\t\tfor ( key in fn ) {\n\t\t\t\tif ( !Object.prototype.hasOwnProperty.call( fn, key ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\ttblFn = key.split( \"/\" );\n\t\t\t\tcurrObj = config;\n\t\t\t\tfor ( i = 0, iLength = tblFn.length - 1; i !== iLength; i += 1 ) {\n\t\t\t\t\tlocalKey = tblFn.shift();\n\t\t\t\t\tif ( localKey === \"\" ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tif ( !currObj[ localKey ] ) {\n\t\t\t\t\t\tcurrObj[ localKey ] = { };\n\t\t\t\t\t}\n\t\t\t\t\tcurrObj = currObj[ localKey ];\n\t\t\t\t}\n\t\t\t\tlocalKey = tblFn.shift();\n\t\t\t\tcurrObj[ localKey ] = fn[ key ];\n\t\t\t}\n\t\t\treturn config;\n\t\t}\n\n\t\t// Apply any preset\n\t\toptionFlot = applyPreset( defaultsOptions.flot, $elm, \"flot\" );\n\n\t\t// Apply any preset\n\t\toptionsCharts = applyPreset( defaultsOptions.charts, $elm, componentName );\n\n\t\t// Fix default width and height in case the table is hidden or too small.\n\t\toptionsCharts.width = ( optionsCharts.width &amp;amp;&amp;amp; optionsCharts.width &amp;gt; 250 ? optionsCharts.width : 250 );\n\t\toptionsCharts.height = ( optionsCharts.height &amp;amp;&amp;amp; optionsCharts.height &amp;gt; 250 ? optionsCharts.height : 250 );\n\n\t\t/**\n\t\t * @method getColumnGroupHeaderCalculateSteps\n\t\t * @param {object} colGroupHead - Column Group Header Object from the table parser\n\t\t * @param {number} referenceValuePosition - Vector position use as reference for defining the steps, zero based position\n\t\t */\n\t\tfunction getColumnGroupHeaderCalculateSteps( colGroupHead, referenceValuePosition ) {\n\n\t\t\t// Get the appropriate ticks\n\t\t\tvar headerCell, i, iLen,\n\t\t\t\tcalcStep = 1,\n\t\t\t\tcolRefValue, colCurent;\n\n\t\t\tif ( !colGroupHead ) {\n\n\t\t\t\t// There is an error. Possibly the series are missing a header.\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tcolRefValue = colGroupHead.col[ referenceValuePosition ];\n\t\t\tcolCurent = colGroupHead.col[ 0 ];\n\n\t\t\tfor ( i = 0, iLen = colRefValue.cell.length; i !== iLen; i += 1 ) {\n\n\t\t\t\theaderCell = colRefValue.cell[ i ];\n\n\t\t\t\tif ( i === 0 || ( i &amp;gt; 0 &amp;amp;&amp;amp; colCurent.cell[ i - 1 ].uid !== headerCell.uid ) ) {\n\n\t\t\t\t\tif ( headerCell.rowgroup &amp;amp;&amp;amp; headerCell.rowgroup.type === 3 ) {\n\n\t\t\t\t\t\t// We only process the first column data group\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( headerCell.type === 1 || headerCell.type === 7 ) {\n\t\t\t\t\t\tif ( headerCell.child.length !== 0 ) {\n\t\t\t\t\t\t\tcalcStep = calcStep * groupHeaderCalculateStepsRecursive( headerCell, 1 );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn calcStep;\n\t\t}\n\n\t\t/**\n\t\t * @method getRowGroupHeaderCalculateSteps\n\t\t * @param {object} rowGroupHead - Row Group Header Object from the table parser\n\t\t * @param {number} referenceValuePosition - Vector position use as reference for defining the steps, zero based position\n\t\t * @param {number} dataColgroupStart - Column position where the column data group start\n\t\t */\n\t\tfunction getRowGroupHeaderCalculateSteps( rowGroupHead, referenceValuePosition, dataColgroupStart ) {\n\n\t\t\t// Find the range of the first data colgroup\n\t\t\tvar headerCell, i, iLen,\n\t\t\t\tcalcStep = 1,\n\t\t\t\trowRefValueCells = rowGroupHead[ referenceValuePosition ].elem.cells;\n\n\t\t\tfor ( i = 0, iLen = rowRefValueCells.length; i !== iLen; i += 1 ) {\n\n\t\t\t\theaderCell = $( rowRefValueCells[ i ] ).data().tblparser;\n\n\t\t\t\tif ( headerCell.colgroup &amp;amp;&amp;amp; headerCell.colgroup.type === 3 ) {\n\n\t\t\t\t\t// We only process the first column data group\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( headerCell.colpos &amp;gt;= dataColgroupStart &amp;amp;&amp;amp; ( headerCell.type === 1 || headerCell.type === 7 ) ) {\n\t\t\t\t\tif ( headerCell.child.length !== 0 ) {\n\t\t\t\t\t\tcalcStep = calcStep * headerCell.child.length * groupHeaderCalculateStepsRecursive( headerCell, 1 );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn calcStep;\n\t\t}\n\n\t\t/**\n\t\t * @method groupHeaderCalculateStepsRecursive\n\t\t * @param {object} headerCell - Header cell object from the table parser\n\t\t * @param {number} refValue - Reference Value (D\u00e9nominateur) of headerCell\n\t\t */\n\t\tfunction groupHeaderCalculateStepsRecursive( headerCell, refValue ) {\n\t\t\tvar childLength = headerCell.child.length,\n\t\t\t\tcalcStep = 1,\n\t\t\t\tkIndex, subRefValue, headerCellChild;\n\n\t\t\tif ( childLength === 0 ) {\n\t\t\t\treturn calcStep;\n\t\t\t}\n\n\t\t\tsubRefValue = childLength * refValue;\n\n\t\t\tcalcStep = calcStep * subRefValue;\n\n\t\t\tfor ( kIndex = 0; kIndex !== childLength; kIndex += 1 ) {\n\t\t\t\theaderCellChild = headerCell.child[ kIndex ];\n\t\t\t\tif ( headerCellChild.child.length !== 0 ) {\n\t\t\t\t\tcalcStep = calcStep * groupHeaderCalculateStepsRecursive( headerCellChild, subRefValue );\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn calcStep;\n\t\t}\n\n\t\t/**\n\t\t * Set the inner step value (divisor) of an header cell and for his child\n\t\t *\n\t\t * @method setInnerStepValues\n\t\t * @param {object} vectorHead - Group Header Object from the table parser\n\t\t * @param {number} headerLevel - Hierarchical Level of heading\n\t\t * @param {number} stepsValue - Step Value for the reference value vector\n\t\t * @param {number} referenceValue - Reference Value Vector ID\n\t\t * @param {number} dataColgroupStart - Column position where the column data group start\n\t\t *\n\t\t */\n\t\tfunction setInnerStepValues( vectorHead, headerLevel, stepsValue, referenceValue, dataColgroupStart ) {\n\t\t\tvar i, iLength,\n\t\t\t\theaderCell,\n\t\t\t\tcumulativeValue = 0;\n\n\t\t\tfor ( i = 0, iLength = vectorHead.cell.length; i !== iLength; i += 1 ) {\n\t\t\t\theaderCell = vectorHead.cell[ i ];\n\t\t\t\tif ( i !== 0 &amp;amp;&amp;amp; headerCell.uid === vectorHead.cell[ i - 1 ].uid || ( dataColgroupStart &amp;amp;&amp;amp; headerCell.colpos &amp;lt; dataColgroupStart ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\t// Only process the first data group\n\t\t\t\tif ( !reverseTblParsing ) {\n\t\t\t\t\tif ( headerCell.colgroup &amp;amp;&amp;amp; headerCell.colgroup.type === 3 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tif ( headerCell.rowgroup &amp;amp;&amp;amp; headerCell.rowgroup.type === 3 ) {\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( headerCell.child &amp;gt; 0 &amp;amp;&amp;amp; headerLevel &amp;lt; referenceValue ) {\n\t\t\t\t\theaderCell.flotDelta = stepsValue * headerCell.child.length;\n\t\t\t\t} else {\n\t\t\t\t\theaderCell.flotDelta = stepsValue;\n\t\t\t\t}\n\t\t\t\tif ( headerCell.type === 1 || headerCell.type === 7  ) {\n\n\t\t\t\t\tif ( !lowestFlotDelta || headerCell.flotDelta &amp;lt; lowestFlotDelta ) {\n\t\t\t\t\t\tlowestFlotDelta = headerCell.flotDelta;\n\t\t\t\t\t}\n\t\t\t\t\theaderCell.flotValue = cumulativeValue;\n\n\t\t\t\t\tcumulativeValue = cumulativeValue + stepsValue;\n\n\t\t\t\t\tif ( headerCell.child.length &amp;gt; 0 ) {\n\t\t\t\t\t\tsetInnerStepValuesChildRecursive( headerCell, headerLevel, stepsValue, referenceValue );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Recursize - Set the inner step value (divisor) of an sub header cell\n\t\t *\n\t\t * @method setInnerStepValuesChildRecursive\n\t\t * @param {object} headerCell - Header cell object from the table parser\n\t\t * @param {number} headerLevel - Hierarchical Level of heading\n\t\t * @param {number} stepsValue - Specific Step Value applied for current headerCell\n\t\t * @param {number} referenceValue - Reference Value Vector ID\n\t\t */\n\t\tfunction setInnerStepValuesChildRecursive( headerCell, headerLevel, stepsValue, referenceValue ) {\n\t\t\tvar cumulativeValue = 0,\n\n\t\t\t\t// Step Values for childs header in headerCell\n\t\t\t\tflotDelta,\n\t\t\t\ti, iLength,\tcurrentHeaderCellChild;\n\n\t\t\theaderLevel += 1;\n\t\t\tcumulativeValue = headerCell.flotValue;\n\t\t\tflotDelta = stepsValue / headerCell.child.length;\n\n\t\t\t// Use to calculate the largest width for a bar in a bar chart\n\t\t\tif ( !lowestFlotDelta || flotDelta &amp;lt; lowestFlotDelta ) {\n\t\t\t\tlowestFlotDelta = flotDelta;\n\t\t\t}\n\n\t\t\tfor ( i = 0, iLength = headerCell.child.length; i !== iLength; i += 1 ) {\n\t\t\t\tcurrentHeaderCellChild = headerCell.child[ i ];\n\t\t\t\tif ( headerLevel &amp;lt; referenceValue ) {\n\t\t\t\t\tcurrentHeaderCellChild.flotDelta = flotDelta * currentHeaderCellChild.child.length;\n\t\t\t\t} else {\n\t\t\t\t\tcurrentHeaderCellChild.flotDelta = flotDelta;\n\t\t\t\t}\n\t\t\t\tcurrentHeaderCellChild.flotValue = cumulativeValue;\n\t\t\t\tif ( currentHeaderCellChild.child.length &amp;gt; 0 ) {\n\t\t\t\t\tsetInnerStepValuesChildRecursive( currentHeaderCellChild, headerLevel, flotDelta, referenceValue );\n\t\t\t\t}\n\t\t\t\tcumulativeValue = cumulativeValue + flotDelta;\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Set the header cell step value (flotDelta) for vector that regroup more than one reference\n\t\t *\n\t\t * @method setUpperStepValues\n\t\t * @param {object} vectorHead - Group Header Object from the table parser\n\t\t * @param {number} referenceValue - Reference Value Vector ID\n\t\t */\n\t\tfunction setUpperStepValues( vectorHead, referenceValue ) {\n\t\t\tvar i, k, m, kLen, mLen,\n\t\t\t\tcumulativeValue,\n\t\t\t\tcurrentCell,\n\t\t\t\tcurrentCellChild,\n\t\t\t\tcurrentVectorHead;\n\n\t\t\t// Calculate upper-step for cells that are\n\t\t\t// less precise than the reference value vector\n\t\t\tfor ( i = referenceValue - 1; i !== -1; i -= 1 ) {\n\t\t\t\tcurrentVectorHead = vectorHead[ i ];\n\n\t\t\t\tfor ( k = 0, kLen = currentVectorHead.cell.length; k !== kLen; k += 1 ) {\n\t\t\t\t\tcurrentCell = currentVectorHead.cell[ k ];\n\n\t\t\t\t\tif ( currentCell.flotDelta || k &amp;gt; 0 &amp;amp;&amp;amp;\n\t\t\t\t\t\tcurrentCell.uid === currentVectorHead.cell[ k - 1 ].uid ) {\n\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !( currentCell.type === 1 || currentCell.type === 7 ) ) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\n\t\t\t\t\tcumulativeValue = 0;\n\t\t\t\t\tfor ( m = 0, mLen = currentCell.child.length; m !== mLen; m += 1 ) {\n\t\t\t\t\t\tcurrentCellChild = currentCell.child[ m ];\n\n\t\t\t\t\t\tcumulativeValue = currentCellChild.flotDelta;\n\t\t\t\t\t\tif ( !currentCell.flotValue ) {\n\t\t\t\t\t\t\tcurrentCell.flotValue = currentCellChild.flotValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tcurrentCell.flotDelta = cumulativeValue;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t/**\n\t\t * Get labels for a specific vector\n\t\t *\n\t\t * @method getLabels\n\t\t * @param {object} labelVector - Vector Header Object from the table parser\n\t\t * @param {number} dataColgroupStart - Column position where the column data group start\n\t\t */\n\t\tfunction getLabels( labelVector, dataColgroupStart ) {\n\t\t\tvar labels = [],\n\t\t\t\ti, iLen, currentCell;\n\n\t\t\tfor ( i = 0, iLen = labelVector.cell.length; i !== iLen; i += 1 ) {\n\t\t\t\tcurrentCell = labelVector.cell[ i ];\n\n\t\t\t\tif ( ( i !== 0 &amp;amp;&amp;amp; currentCell.uid === labelVector.cell[ i - 1 ].uid ) ||\n\t\t\t\t\t\t( !( currentCell.type === 1 || currentCell.type === 7 ) ) ||\n\t\t\t\t\t\t( dataColgroupStart &amp;amp;&amp;amp; currentCell.colpos &amp;lt; dataColgroupStart ) ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\n\t\t\t\tlabels.push( [ currentCell.flotValue, $( currentCell.elem ).text() ] );\n\t\t\t}\n\t\t\treturn labels;\n\t\t}\n\n\t\t/**\n\t\t * Get the vector that would be used for labelling x-axis\n\t\t *\n\t\t * @method getlabelsVectorPosition\n\t\t * @param {object[]} arrVectorHeaders - Collection of vector headers\n\t\t */\n\t\tfunction getlabelsVectorPosition( arrVectorHeaders ) {\n\t\t\tvar labelPosition = optionsCharts.labelposition;\n\t\t\treturn ( !labelPosition || ( labelPosition &amp;amp;&amp;amp; labelPosition &amp;gt; arrVectorHeaders.length ) ?\n\t\t\t\tparsedData.theadRowStack.length : labelPosition ) - 1;\n\t\t}\n\n\t\t/**\n\t\t * Get the vertical label and set the appropriate header cell x-axis Value\n\t\t *\n\t\t * @method verticalLabels\n\t\t * @param {object} parsedData - Generic object generated by the table parser\n\t\t */\n\t\tfunction verticalLabels( parsedData ) {\n\n\t\t\t// Get the appropriate ticks\n\t\t\tvar headerlevel = 0,\n\t\t\t\tlabelsVectorPosition, stepsValue, columnReferenceValue;\n\n\t\t\tif ( !reverseTblParsing || ( reverseTblParsing &amp;amp;&amp;amp; optionsCharts.referencevalue === false ) ) {\n\t\t\t\tcolumnReferenceValue = parsedData.colgrouphead.col.length;\n\t\t\t} else {\n\t\t\t\tcolumnReferenceValue = optionsCharts.referencevalue;\n\t\t\t}\n\n\t\t\tcolumnReferenceValue = columnReferenceValue - 1;\n\n\t\t\tstepsValue = getColumnGroupHeaderCalculateSteps( parsedData.colgrouphead, columnReferenceValue );\n\n\t\t\tif ( !reverseTblParsing ) {\n\t\t\t\tlabelsVectorPosition = parsedData.colgrouphead.col.length - 1;\n\t\t\t} else {\n\t\t\t\tlabelsVectorPosition = getlabelsVectorPosition( parsedData.colgrouphead.col );\n\t\t\t}\n\n\t\t\theaderlevel = columnReferenceValue;\n\n\t\t\t// Calculate inner-step for cells that are more precise than the reference value vector\n\t\t\tsetInnerStepValues( parsedData.colgrouphead.col[ columnReferenceValue ], headerlevel, stepsValue, columnReferenceValue );\n\n\t\t\t// Calculate upper-step for cells that are less precise than the reference value vector\n\t\t\tsetUpperStepValues( parsedData.colgrouphead.col, columnReferenceValue );\n\n\t\t\t// Get the labelling\n\t\t\treturn getLabels( parsedData.colgrouphead.col[ labelsVectorPosition ] );\n\t\t}\n\n\t\t/**\n\t\t * Get the horizontal label and set the appropriate header cell x-axis Value\n\t\t *\n\t\t * @method horizontalLabels\n\t\t * @param {object} parsedData - Generic object generated by the table parser\n\t\t */\n\t\tfunction horizontalLabels( parsedData ) {\n\n\t\t\t// Find the range of the first data colgroup\n\t\t\tvar dataColgroupStart = -1,\n\t\t\t\theaderlevel = 0,\n\t\t\t\ttheadRowStack = parsedData.theadRowStack,\n\t\t\t\ti, iLength, labelsVectorPosition,\n\t\t\t\tstepsValue, rowReferenceValue;\n\n\t\t\tif ( !theadRowStack ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tfor ( i = 0, iLength = parsedData.colgroup.length; i !== iLength; i += 1 ) {\n\t\t\t\tif ( parsedData.colgroup[ i ].type === 2 ) {\n\t\t\t\t\tdataColgroupStart = parsedData.colgroup[ i ].start;\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( ( !reverseTblParsing &amp;amp;&amp;amp; optionsCharts.referencevalue === false ) || reverseTblParsing ) {\n\t\t\t\trowReferenceValue = theadRowStack.length;\n\t\t\t} else {\n\t\t\t\trowReferenceValue = optionsCharts.referencevalue;\n\t\t\t}\n\n\t\t\trowReferenceValue = rowReferenceValue - 1;\n\n\t\t\tstepsValue = getRowGroupHeaderCalculateSteps( theadRowStack, rowReferenceValue, dataColgroupStart );\n\n\t\t\tif ( !reverseTblParsing ) {\n\t\t\t\tlabelsVectorPosition = getlabelsVectorPosition( theadRowStack );\n\t\t\t} else {\n\t\t\t\tlabelsVectorPosition = theadRowStack.length - 1;\n\t\t\t}\n\n\t\t\theaderlevel = rowReferenceValue;\n\n\t\t\t// Calculate inner-step for cells that are more precise than the reference value vector\n\t\t\tsetInnerStepValues( theadRowStack[ rowReferenceValue ], headerlevel, stepsValue, rowReferenceValue, dataColgroupStart );\n\n\t\t\t// Calculate upper-step for cells that are less precise than the reference value vector\n\t\t\tsetUpperStepValues( theadRowStack, rowReferenceValue );\n\n\t\t\t// Get the labelling\n\t\t\treturn getLabels( theadRowStack[ labelsVectorPosition ], dataColgroupStart );\n\n\t\t}\n\n\t\t/**\n\t\t * Wrap the table into a smart details/summary element\n\t\t *\n\t\t * @method wrapTableIntoDetails\n\t\t */\n\t\tfunction wrapTableIntoDetails() {\n\t\t\tvar $summary;\n\n\t\t\tif ( !captionHtml.length ) {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t$summary = $( \"\" + captionHtml + i18nText.tableMention + \"\" );\n\t\t\t$elm\n\t\t\t\t.wrap( \"\n\" )\n\t\t\t\t.before( $summary );\n\n\t\t\t$summary.trigger( \"wb-init.wb-details\" );\n\t\t}\n\n\t\tfunction createContainer( withDimension ) {\n\t\t\t$elm\n\t\t\t\t.wrap( \"\n\" )\n\t\t\t\t.before(\n\n\t\t\t\t\t// Copy to the inner table caption\n\t\t\t\t\t( captionHtml.length ? \"\n\" + captionHtml + \"\" : \"\" ) +\n\n\t\t\t\t\t// Image Container\n\t\t\t\t\t\"\n\"\n\t\t\t\t);\n\n\t\t\treturn $( \"div:eq(0)\", $elm.parent() );\n\t\t}\n\n\t\t// Retrieve the parsed data\n\t\tparsedData = $elm.data().tblparser;\n\n\t\t// Reverse table parsing\n\t\treverseTblParsing = optionsCharts.reversettblparsing;\n\n\t\t// first data row group\n\t\tcurrentRowGroup = parsedData.lstrowgroup[ 0 ];\n\n\t\tif ( optionFlot.series &amp;amp;&amp;amp; optionFlot.series.pie ) {\n\n\t\t\t// WET Charts placeholder\n\t\t\t$wetChartContainer = createContainer( false );\n\n\t\t\t// Flot pie chart placeholder\n\t\t\thtmlPlaceHolder = \"\n\";\n\n\t\t\tif ( !reverseTblParsing ) {\n\n\t\t\t\t// If normal parsing\n\t\t\t\tdataGroup = parsedData.colgroup[ 0 ].type === 1 ?\n\t\t\t\t\tparsedData.colgroup[ 1 ] :\n\t\t\t\t\tparsedData.colgroup[ 0 ];\n\n\t\t\t\trIndex = currentRowGroup.row.length - 1;\n\t\t\t} else {\n\n\t\t\t\t// If reverse parsing\n\t\t\t\tdataGroup = currentRowGroup;\n\t\t\t\trIndex = ( parsedData.colgroup[ 0 ].type === 1 ?\n\t\t\t\t\tparsedData.colgroup[ 1 ].col.length :\n\t\t\t\t\tparsedData.colgroup[ 0 ].col.length ) - 1;\n\t\t\t}\n\n\t\t\tfor ( rIndex; rIndex &amp;gt;= 0; rIndex -= 1 ) {\n\n\t\t\t\tdataGroupVector = !reverseTblParsing ? dataGroup.col : dataGroup.row;\n\n\t\t\t\t// For each row or column\n\t\t\t\tfor ( i = 0, iLength = dataGroupVector.length; i !== iLength; i += 1 ) {\n\t\t\t\t\tdataSeries = [];\n\t\t\t\t\tvaluePoint = 0;\n\t\t\t\t\tcurrentDataGroupVector = dataGroupVector[ i ];\n\n\t\t\t\t\t// For each cells\n\t\t\t\t\tfor ( j = 0, jLength = currentDataGroupVector.cell.length; j !== jLength; j += 1 ) {\n\n\t\t\t\t\t\tdataCell = currentDataGroupVector.cell[ j ];\n\n\t\t\t\t\t\t// Skip the column if\n\t\t\t\t\t\tif ( reverseTblParsing &amp;amp;&amp;amp; dataCell.col.type === 1 ) {\n\t\t\t\t\t\t\tcontinue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tpreviousDataCell = undefined;\n\t\t\t\t\t\tif ( j !== 0 ) {\n\t\t\t\t\t\t\tpreviousDataCell = currentDataGroupVector.cell[ j - 1 ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Verify if the selected cell still in the scope of a data group in his another axes (eg. row/col)\n\t\t\t\t\t\t// Verify if we are still in the same datagroup as the previous data cell\n\t\t\t\t\t\tif ( ( !reverseTblParsing &amp;amp;&amp;amp; ( dataCell.row.type !== 2  || ( previousDataCell &amp;amp;&amp;amp;\n\t\t\t\t\t\t\t\tpreviousDataCell.rowgroup.uid !== dataCell.rowgroup.uid ) ) ) ||\n\t\t\t\t\t\t\t\t( reverseTblParsing &amp;amp;&amp;amp; ( dataCell.col.type !== 2 ) || ( previousDataCell &amp;amp;&amp;amp;\n\t\t\t\t\t\t\t\tpreviousDataCell.col.type !== 1 &amp;amp;&amp;amp;\n\t\t\t\t\t\t\t\tpreviousDataCell.col.groupstruct.uid !== dataCell.col.groupstruct.uid ) ) ) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Gets the value\n\t\t\t\t\t\theader = !reverseTblParsing ? dataCell.row.header : dataCell.col.header;\n\n\t\t\t\t\t\tcellValue = optionsCharts.getcellvalue( !reverseTblParsing ?\n\t\t\t\t\t\t\tcurrentDataGroupVector.cell[ rIndex ].elem :\n\t\t\t\t\t\t\tcurrentDataGroupVector.datacell[ rIndex ].elem );\n\n\t\t\t\t\t\tdataSeries.push(\n\t\t\t\t\t\t\t[\n\t\t\t\t\t\t\t\tvaluePoint,\n\t\t\t\t\t\t\t\ttypeof cellValue === \"object\" ?\n\t\t\t\t\t\t\t\t\tcellValue[ 0 ] :\n\t\t\t\t\t\t\t\t\tcellValue\n\t\t\t\t\t\t\t]\n\t\t\t\t\t\t);\n\n\t\t\t\t\t\tvaluePoint += header[ header.length - 1 ].flotDelta;\n\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tpieQuaterFlotSeries = { };\n\n\t\t\t\t\t// Get the setting from the associative cell header\n\t\t\t\t\tdataCell = !reverseTblParsing ?\n\t\t\t\t\t\tcurrentDataGroupVector.cell[ rIndex ] :\n\t\t\t\t\t\tcurrentDataGroupVector.datacell[ rIndex ];\n\t\t\t\t\theader = !reverseTblParsing ?\n\t\t\t\t\t\tdataCell.col.header :\n\t\t\t\t\t\tdataCell.row.header;\n\t\t\t\t\theader = header[ header.length - 1 ];\n\n\t\t\t\t\t// Apply any preset\n\t\t\t\t\tpieQuaterFlotSeries = applyPreset( defaultsOptions.series, $( header.elem ), \"flot\" );\n\n\t\t\t\t\t// Set the data issue from the table\n\t\t\t\t\tpieQuaterFlotSeries.data = dataSeries;\n\t\t\t\t\tpieQuaterFlotSeries.label = ( !reverseTblParsing ?\n\t\t\t\t\t\t$( currentDataGroupVector.dataheader[ currentDataGroupVector.dataheader.length - 1 ].elem ).text() :\n\t\t\t\t\t\t$( currentDataGroupVector.header[ currentDataGroupVector.header.length - 1 ].elem ).text() );\n\n\t\t\t\t\t// Add the series\n\t\t\t\t\tallSeries.push( pieQuaterFlotSeries );\n\t\t\t\t}\n\n\t\t\t\t// Create a sub Figure or use the main one\n\t\t\t\tif ( currentRowGroup.row.length === 1 &amp;amp;&amp;amp;\n\t\t\t\t\t( currentRowGroup.row[ 0 ].header[ 0 ].elem.innerHTML === captionHtml ||\n\t\t\t\t\tcurrentRowGroup.row[ 0 ].header.length === 0 ) ) {\n\n\t\t\t\t\t$placeHolder = $wetChartContainer;\n\t\t\t\t\t$placeHolder.css( {\n\t\t\t\t\t\theight: optionsCharts.height,\n\t\t\t\t\t\twidth: optionsCharts.width\n\t\t\t\t\t} );\n\n\t\t\t\t} else {\n\n\t\t\t\t\theader = !reverseTblParsing ? dataCell.row.header : dataCell.col.header;\n\n\t\t\t\t\tfigurehtml = \"\n\n\" +\n\t\t\t\t\t\theader[ header.length - 1 ].elem.innerHTML +\n\t\t\t\t\t\t\"\" + htmlPlaceHolder + \"\";\n\n\t\t\t\t\t$wetChartContainer.append( $( figurehtml ) );\n\n\t\t\t\t\t$placeHolder = $( \"div:last()\", $wetChartContainer );\n\t\t\t\t}\n\n\t\t\t\t// Create the graphic\n\t\t\t\t$.plot( $placeHolder, allSeries, optionFlot );\n\n\t\t\t\tif ( !optionsCharts.legendinline ) {\n\n\t\t\t\t\t// Move the legend under the graphic\n\t\t\t\t\t$( \".legend\", $placeHolder ).appendTo( $wetChartContainer );\n\t\t\t\t}\n\n\t\t\t\tallSeries = [];\n\t\t\t}\n\n\t\t\tif ( optionsCharts.nolegend ) {\n\n\t\t\t\t// Remove the legend\n\t\t\t\t$( \".legend\", $wetChartContainer ).remove();\n\t\t\t}\n\t\t\tif ( !optionsCharts.legendinline ) {\n\n\t\t\t\t// Fix the legend that appear under the graphic\n\t\t\t\t$( \".legend &amp;gt; div\", $wetChartContainer ).remove();\n\t\t\t\t$( \".legend &amp;gt; table\", $wetChartContainer ).removeAttr( \"style\" ).addClass( \"font-small\" );\n\t\t\t\t$( \".legend\", $placeHolder ).appendTo( $imgContainer );\n\t\t\t}\n\n\t\t\t// Remove any \"pieLabel\" ids set by the flotPie.js plugin at line #457\n\t\t\t$( \".pieLabel\" ).removeAttr( \"id\" );\n\n\t\t\tif ( !optionsCharts.noencapsulation ) {\n\t\t\t\twrapTableIntoDetails();\n\t\t\t}\n\n\t\t\treturn;\n\t\t}\n\n\t\tif ( !reverseTblParsing ) {\n\n\t\t\t// If normal parsing\n\t\t\tdataGroup = currentRowGroup;\n\t\t\trIndex = ( parsedData.colgroup[ 0 ].type === 1 ?\n\t\t\t\tparsedData.colgroup[ 1 ].col.length :\n\t\t\t\tparsedData.colgroup[ 0 ].col.length ) - 1;\n\t\t\tchartslabels = horizontalLabels( parsedData );\n\t\t} else {\n\n\t\t\t// If reverse parsing\n\t\t\tdataGroup = parsedData.colgroup[ 0 ].type === 1 ?\n\t\t\t\tparsedData.colgroup[ 1 ] :\n\t\t\t\tparsedData.colgroup[ 0 ];\n\t\t\trIndex = currentRowGroup.row.length - 1;\n\t\t\tchartslabels = verticalLabels( parsedData );\n\t\t}\n\n\t\t// Add the labels at the Flot options\n\t\toptionFlot.xaxis.ticks = chartslabels;\n\n\t\tdataGroupVector = !reverseTblParsing ? dataGroup.row : dataGroup.col;\n\n\t\t// Count the number of bar charts,\n\t\tfor ( i = 0, iLength = dataGroupVector.length; i !== iLength; i += 1 ) {\n\t\t\tcurrentDataGroupVector = dataGroupVector[ i ];\n\t\t\tcurrDataVector = currentDataGroupVector.header[ currentDataGroupVector.header.length - 1 ];\n\n\t\t\t// Apply any preset\n\t\t\tcurrVectorOptions = applyPreset( defaultsOptions.series, $( currDataVector.elem ), \"flot\" );\n\n\t\t\tif ( currVectorOptions.bars || ( optionFlot.bars &amp;amp;&amp;amp; !currVectorOptions.lines ) ) {\n\n\t\t\t\t// Count number of bars, this number is use to calculate the bar width.\n\t\t\t\tnbBarChart += 1;\n\n\t\t\t\t// Set a default setting specially for bar charts\n\t\t\t\tif ( !currVectorOptions.bars ) {\n\t\t\t\t\tcurrVectorOptions.bars = { show: true, barWidth: 0.9 };\n\t\t\t\t}\n\n\t\t\t\t// Set a default order for orderBars flot plugin\n\t\t\t\tif ( !currVectorOptions.bars.order ) {\n\t\t\t\t\tcurrVectorOptions.bars.order = nbBarChart;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// cache the compiled setting\n\t\t\tcurrDataVector.chartOption = currVectorOptions;\n\t\t}\n\n\t\t// First rowgroup assume is a data row group.\n\t\t// For all row....\n\t\tfor ( i = 0, iLength = dataGroupVector.length; i !== iLength; i += 1 ) {\n\t\t\tdataSeries = [];\n\t\t\tdatacolgroupfound = 0;\n\t\t\tvaluePoint = 0;\n\t\t\tcurrDataVector = dataGroupVector[ i ];\n\n\t\t\tcurrVectorOptions = currDataVector.header[ currDataVector.header.length - 1 ].chartOption;\n\n\t\t\t// For each cells\n\t\t\tfor ( j = 0, jLength = currDataVector.cell.length; j !== jLength; j += 1 ) {\n\n\t\t\t\tdataCell = currDataVector.cell[ j ];\n\n\t\t\t\tif ( datacolgroupfound &amp;gt; 1 &amp;amp;&amp;amp; dataCell.col.groupstruct.type !== 2 ) {\n\t\t\t\t\tbreak;\n\t\t\t\t}\n\n\t\t\t\tif ( ( !reverseTblParsing &amp;amp;&amp;amp; dataCell.col.groupstruct.type === 2 ) ||\n\t\t\t\t\t\t( reverseTblParsing &amp;amp;&amp;amp; dataCell.row.rowgroup.type === 2 ) ) {\n\n\t\t\t\t\t// Gets the value\n\t\t\t\t\theader = !reverseTblParsing ? dataCell.col.header : dataCell.row.header;\n\n\t\t\t\t\tcellValue = optionsCharts.getcellvalue( dataCell.elem );\n\n\t\t\t\t\t// Add the data point\n\t\t\t\t\tdataSeries.push(\n\t\t\t\t\t\t[\n\t\t\t\t\t\t\tvaluePoint,\n\t\t\t\t\t\t\ttypeof cellValue === \"object\" ?\n\t\t\t\t\t\t\t\tcellValue[ 0 ] :\n\t\t\t\t\t\t\t\tcellValue\n\t\t\t\t\t\t]\n\t\t\t\t\t);\n\t\t\t\t\tvaluePoint += header[ header.length - 1 ].flotDelta;\n\t\t\t\t\tdatacolgroupfound += 1;\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tcurrVectorOptions.data = dataSeries;\n\t\t\tcurrVectorOptions.label = $( currDataVector.header[ currDataVector.header.length - 1 ].elem ).text();\n\n\t\t\tif ( currVectorOptions.bars ) {\n\n\t\t\t\t// Adjust the bars width\n\t\t\t\tcurrVectorOptions.bars.barWidth = currVectorOptions.bars.barWidth * ( 1 / nbBarChart );\n\t\t\t}\n\n\t\t\tallSeries.push( currVectorOptions );\n\n\t\t}\n\n\t\tif ( optionFlot.bars ) {\n\n\t\t\t// Adjust the bars width\n\t\t\toptionFlot.bars.barWidth = optionFlot.bars.barWidth * ( 1 / nbBarChart );\n\t\t}\n\n\t\t// WET Charts Placeholder\n\t\t$placeHolder = createContainer( true );\n\n\t\t// Maximum width\n\t\t$placeHolder.css( \"width\", \"100%\" );\n\n\t\t// Create the graphic\n\t\t$.plot( $placeHolder, allSeries, optionFlot );\n\n\t\tif ( !optionsCharts.legendinline ) {\n\n\t\t\t// Move the legend under the graphic\n\t\t\t$( \".legend &amp;gt; div\", $placeHolder ).remove();\n\t\t\t$( \".legend &amp;gt; table\", $placeHolder ).removeAttr( \"style\" ).addClass( \"font-small\" );\n\t\t\t$placeHolder.css( \"height\", \"auto\" );\n\t\t}\n\t\tif ( optionsCharts.nolegend ) {\n\n\t\t\t// Remove the legend\n\t\t\t$( \".legend\", $placeHolder ).remove();\n\t\t}\n\n\t\tif ( !optionsCharts.noencapsulation ) {\n\t\t\twrapTableIntoDetails();\n\t\t}\n\n\t\t$( \"canvas:eq(1)\", $placeHolder ).css( \"position\", \"static\" );\n\t\t$( \"canvas:eq(0)\", $placeHolder ).css( \"width\", \"100%\" );\n\n\t\t$elm.trigger( \"wb-updated\" + selector );\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered this handler\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\tsettings = window[ componentName ],\n\t\t\telmId, modeJS, deps;\n\n\t\tif ( elm ) {\n\t\t\telmId = elm.id;\n\t\t\tmodeJS = wb.getMode() + \".js\";\n\t\t\tdeps = [\n\t\t\t\t\"site!deps/jquery.flot\" + modeJS,\n\t\t\t\t\"site!deps/jquery.flot.pie\" + modeJS,\n\t\t\t\t\"site!deps/jquery.flot.canvas\" + modeJS,\n\t\t\t\t\"site!deps/jquery.flot.orderBars\" + modeJS,\n\t\t\t\t\"site!deps/tableparser\" + modeJS\n\t\t\t];\n\n\t\t\t//TODO: Revisit this in the new plugin structure\n\t\t\tif ( settings &amp;amp;&amp;amp; settings.plugins ) {\n\t\t\t\tdeps = deps.concat( settings.plugins );\n\t\t\t}\n\n\t\t\t// Only initialize the i18nText once\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\ttableMention: i18n( \"hyphen\" ) + i18n( \"tbl-txt\" ),\n\t\t\t\t\ttableFollowing: i18n( \"hyphen\" ) + i18n( \"tbl-dtls\" ),\n\t\t\t\t\tslicelegend: i18n( \"chrt-cmbslc\" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Load the required dependencies\n\t\t\tModernizr.load( {\n\n\t\t\t\t// For loading multiple dependencies\n\t\t\t\tload: deps,\n\t\t\t\tcomplete: function() {\n\t\t\t\t\tvar $elm = $( \"#\" + elmId );\n\n\t\t\t\t\t// Let's parse the table\n\t\t\t\t\t$elm.trigger( tableParsingEvent );\n\n\t\t\t\t\t// Identify that initialization has completed\n\t\t\t\t\twb.ready( $elm, componentName );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent + \" \" + tableParsingCompleteEvent, selector, function( event ) {\n\tvar eventType = event.type,\n\t\telm = event.target;\n\n\tswitch ( eventType ) {\n\n\t\t/*\n\t\t * Init\n\t\t */\n\t\tcase \"timerpoke\":\n\t\tcase \"wb-init\":\n\t\t\tinit( event );\n\t\t\tbreak;\n\n\t\t/*\n\t\t * Data table parsed\n\t\t */\n\t\tcase \"parsecomplete\":\n\t\t\tif ( event.currentTarget === elm ) {\n\t\t\t\tcreateCharts( $( elm ) );\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\t/*\n\t * Since we are working with events we want to ensure that we are being passive about our control,\n\t * so returning true allows for events to always continue\n\t */\n\treturn true;\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, document, wb );\n\n/**\n * @title WET-BOEW Collapsible alerts plugin\n * @overview Collapsible alerts (details/summary)\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author WET community\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the event - meaning that they will be initialized once per page,\n * not once per instance of event on the page.\n */\nvar componentName = \"wb-collapsible\",\n\tselector = \"details.alert\",\n\tinitEvent = \"wb-init.\" + componentName,\n\t$document = wb.doc,\n\tkey,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar details = wb.init( event, componentName, selector ),\n\t\t\t$details;\n\n\t\tif ( details ) {\n\t\t\t$details = $( details );\n\n\t\t\tkey = \"alert-collapsible-state-\" + details.getAttribute( \"id\" );\n\n\t\t\ttry {\n\t\t\t\tif ( localStorage.getItem( key ) ) {\n\n\t\t\t\t\t// Set open/closed state for existing localStorage keys\n\t\t\t\t\tif ( localStorage.getItem( key ) === \"open\" ) {\n\t\t\t\t\t\tdetails.setAttribute( \"open\", \"open\" );\n\t\t\t\t\t\tdetails.className += \" open\";\n\t\t\t\t\t} else if ( localStorage.getItem( key ) === \"closed\" ) {\n\t\t\t\t\t\tdetails.removeAttribute( \"open\" );\n\t\t\t\t\t\tdetails.className = details.className.replace( \" open\", \"\" );\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\t// Set new localStorage values\n\t\t\t\t\tif ( details.hasAttribute( \"open\" ) ) {\n\t\t\t\t\t\tlocalStorage.setItem( key, \"open\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlocalStorage.setItem( key, \"closed\" );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t} catch ( e ) {\n\t\t\t\t/* swallow error */}\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $details, componentName );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Do not bind events if details polyfill is active\nif ( Modernizr.details ) {\n\n\t// Bind the the event handlers of the plugin\n\t$document.on( \"click keydown toggle.\" + componentName, selector + \" summary\", function( event ) {\n\t\tvar which = event.which,\n\t\t\tcurrentTarget = event.currentTarget,\n\t\t\tisClosed,\n\t\t\tdetails;\n\n\t\t// Ignore middle/right mouse buttons and wb-toggle enhanced summary elements (except for toggle)\n\t\tif ( ( !which || which === 1 ) &amp;amp;&amp;amp;\n\t\t\t( currentTarget.className.indexOf( \"wb-toggle\" ) === -1 ||\n\t\t\t( event.type === \"toggle\" &amp;amp;&amp;amp; event.namespace === componentName ) ) ) {\n\n\t\t\tdetails = currentTarget.parentNode;\n\t\t\tisClosed = details.getAttribute( \"open\" ) === null;\n\t\t\tkey = \"alert-collapsible-state-\" + details.getAttribute( \"id\" );\n\n\t\t\tif ( isClosed ) {\n\t\t\t\ttry {\n\t\t\t\t\tlocalStorage.setItem( key, \"open\" );\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\t/* swallow error */}\n\t\t\t} else {\n\t\t\t\ttry {\n\t\t\t\t\tlocalStorage.setItem( key, \"closed\" );\n\t\t\t\t} catch ( e ) {\n\t\t\t\t\t/* swallow error */}\n\t\t\t}\n\t\t} else if ( which === 13 || which === 32 ) {\n\t\t\tevent.preventDefault();\n\t\t\t$( currentTarget ).trigger( \"click\" );\n\t\t}\n\n\t\t/*\n\t\t * Since we are working with events we want to ensure that we are being passive about our control,\n\t\t * so returning true allows for events to always continue\n\t\t */\n\t\treturn true;\n\t} );\n}\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Country Content\n * @overview A basic AjaxLoader wrapper that inserts AJAXed in content based on a visitors country as resolved by freegeoip.app\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @nschonni\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once\n * per page, not once per instance of plugin on the page. So, this is a good\n * place to define variables that are common to all instances of the plugin on a\n * page.\n */\nvar componentName = \"wb-ctrycnt\",\n\tselector = \"[data-ctrycnt]\",\n\tinitEvent = \"wb-init.\" + componentName,\n\t$document = wb.doc,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered this handler\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm, url;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\t\t\turl = $elm.data( \"ctrycnt\" );\n\n\t\t\t$.when( getCountry() ).then( function( countryCode ) {\n\n\t\t\t\tif ( countryCode === \"\" ) {\n\n\t\t\t\t\t// Leave default content since we couldn't find the country\n\t\t\t\t\treturn;\n\t\t\t\t} else {\n\n\t\t\t\t\t// @TODO: Handle bad country values or any whitelist of countries.\n\t\t\t\t}\n\n\t\t\t\turl = url.replace( \"{country}\", countryCode.toLowerCase() );\n\n\t\t\t\t$elm.load( url, function() {\n\n\t\t\t\t\t// Identify that initialization has completed\n\t\t\t\t\twb.ready( $elm, componentName );\n\t\t\t\t} );\n\t\t\t} );\n\t\t}\n\t},\n\tgetCountry = function() {\n\t\tvar dfd = $.Deferred(),\n\t\t\tcountryCode = localStorage.getItem( \"countryCode\" );\n\n\t\t// Couldn't find a value in the session\n\t\tif ( countryCode === null ) {\n\n\t\t\t// From https://github.com/aFarkas/webshim/blob/master/src/shims/geolocation.js#L89-L127\n\t\t\t$.ajax( {\n\t\t\t\turl: \"https://api.country.is/\",\n\t\t\t\tdataType: \"json\",\n\t\t\t\tcache: true,\n\t\t\t\tsuccess: function( data ) {\n\t\t\t\t\tif ( data ) {\n\t\t\t\t\t\tcountryCode = data.country;\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tlocalStorage.setItem( \"countryCode\", countryCode );\n\t\t\t\t\t\t} catch ( error ) {\n\n\t\t\t\t\t\t\t/* swallow error */\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tdfd.resolve( countryCode );\n\t\t\t\t},\n\t\t\t\terror: function() {\n\t\t\t\t\tdfd.reject( \"\" );\n\t\t\t\t}\n\t\t\t} );\n\t\t} else {\n\t\t\tdfd.resolve( countryCode );\n\t\t}\n\n\t\treturn dfd.promise();\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Data Ajax [data-ajax-after], [data-ajax-append],\n * [data-ajax-before], [data-ajax-prepend] and [data-ajax-replace]\n * @overview A basic AjaxLoader wrapper that inserts AJAXed-in content\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author WET Community\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once\n * per page, not once per instance of plugin on the page. So, this is a good\n * place to define variables that are common to all instances of the plugin on a\n * page.\n */\nvar componentName = \"wb-data-ajax\",\n\tshortName = \"wb-ajax\",\n\tselectors = [\n\t\t\"[data-ajax-after]\",\n\t\t\"[data-ajax-append]\",\n\t\t\"[data-ajax-before]\",\n\t\t\"[data-ajax-prepend]\",\n\t\t\"[data-ajax-replace]\",\n\t\t\"[data-\" + shortName + \"]\"\n\t],\n\tajaxTypes = [\n\t\t\"before\",\n\t\t\"replace\",\n\t\t\"after\",\n\t\t\"append\",\n\t\t\"prepend\"\n\t],\n\tselectorsLength = selectors.length,\n\tselector = selectors.join( \",\" ),\n\tinitEvent = \"wb-init.\" + componentName,\n\tupdateEvent = \"wb-update.\" + componentName,\n\tcontentUpdatedEvent = \"wb-contentupdated\",\n\t$document = wb.doc,\n\ts,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered this handler\n\t * @param {string} ajaxType The type of AJAX operation, either after, append, before or replace\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar ajxInfo = getAjxInfo( event.target ),\n\t\t\tajaxType = ajxInfo.type,\n\t\t\telm = wb.init( event, componentName + \"-\" + ajaxType, selector );\n\n\t\tif ( elm &amp;amp;&amp;amp; ajxInfo.url ) {\n\n\t\t\tajax.call( this, event, ajxInfo );\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $( elm ), componentName, [ ajaxType ] );\n\t\t}\n\t},\n\n\tajax = function( event, ajxInfo ) {\n\t\tvar elm = event.target,\n\t\t\t$elm = $( elm ),\n\t\t\tsettings = window[ componentName ],\n\t\t\turl,\n\t\t\tfetchObj,\n\t\t\turlParts;\n\n\t\tif ( !ajxInfo ) {\n\t\t\tajxInfo = getAjxInfo( elm );\n\t\t}\n\t\turl = ajxInfo.url;\n\t\tfetchObj = {\n\t\t\turl: url,\n\t\t\tnocache: ajxInfo.nocache,\n\t\t\tnocachekey: ajxInfo.nocachekey\n\t\t};\n\n\t\t// Detect CORS requests.\n\t\tif ( settings &amp;amp;&amp;amp; ( url.substr( 0, 4 ) === \"http\" || url.substr( 0, 2 ) === \"//\" ) ) {\n\t\t\turlParts = wb.getUrlParts( url );\n\t\t\tif ( ( wb.pageUrlParts.protocol !== urlParts.protocol || wb.pageUrlParts.host !== urlParts.host ) &amp;amp;&amp;amp; ( !Modernizr.cors || settings.forceCorsFallback ) ) {\n\t\t\t\tif ( typeof settings.corsFallback === \"function\" ) {\n\t\t\t\t\tfetchObj.dataType = \"jsonp\";\n\t\t\t\t\tfetchObj.jsonp = \"callback\";\n\t\t\t\t\tfetchObj = settings.corsFallback( fetchObj );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t$elm.trigger( {\n\t\t\ttype: \"ajax-fetch.wb\",\n\t\t\tfetch: fetchObj\n\t\t} );\n\t},\n\n\t// Get Info and return { \"url\": \"the/ajax/URL\", \"atype\" }\n\tgetAjxInfo = function( elm ) {\n\t\tvar ajaxType,\n\t\t\tlen = ajaxTypes.length,\n\t\t\ti, url, dtAttr, nocache, nocachekey;\n\n\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\tajaxType = ajaxTypes[ i ];\n\t\t\turl = elm.getAttribute( \"data-ajax-\" + ajaxType );\n\t\t\tif ( url ) {\n\t\t\t\tbreak;\n\t\t\t}\n\t\t}\n\n\t\tif ( !url ) {\n\t\t\tdtAttr = wb.getData( $( elm ), shortName );\n\n\t\t\t// Abort the init when called on an invalid element (related to #8058)\n\t\t\tif ( !dtAttr ) {\n\t\t\t\treturn {};\n\t\t\t}\n\n\t\t\tajaxType = dtAttr.type;\n\t\t\tif ( ajaxTypes.indexOf( ajaxType ) === -1 ) {\n\t\t\t\tthrow \"Invalid ajax type\";\n\t\t\t}\n\n\t\t\turl = getURL( dtAttr.url, dtAttr.httpref );\n\t\t\tif ( !url ) {\n\t\t\t\treturn { \"type\": ajaxType };\n\t\t\t}\n\n\t\t\tnocache = dtAttr.nocache;\n\t\t\tnocachekey = dtAttr.nocachekey;\n\t\t}\n\n\t\treturn {\n\t\t\t\"url\": url,\n\t\t\t\"type\": ajaxType,\n\t\t\t\"nocache\": nocache,\n\t\t\t\"nocachekey\": nocachekey\n\t\t};\n\t},\n\n\t// Return url for conditional display if regexp match http refer\n\tgetURL = function( url, referer ) {\n\t\tvar refers, httpRef, regHttpRef,\n\t\t\ti, i_len;\n\n\t\tif ( referer ) {\n\t\t\tif ( !Array.isArray( referer ) ) {\n\t\t\t\trefers = [];\n\t\t\t\trefers.push( referer );\n\t\t\t} else {\n\t\t\t\trefers = referer;\n\t\t\t}\n\n\t\t\thttpRef = window.document.referrer;\n\t\t\ti_len = refers.length;\n\t\t\tfor ( i = 0; i !== i_len; i += 1 ) {\n\t\t\t\tregHttpRef = new RegExp( refers[ i ] );\n\t\t\t\tif ( regHttpRef.test( httpRef ) ) {\n\t\t\t\t\tif ( Array.isArray( url ) &amp;amp;&amp;amp; url.length === i_len ) {\n\t\t\t\t\t\treturn url[ i ];\n\t\t\t\t\t} else {\n\t\t\t\t\t\treturn url;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\treturn url;\n\t\t}\n\t\treturn \"\";\n\t},\n\n\tajxFetched = function( elm, fetchObj ) {\n\t\tvar $elm = $( elm ),\n\t\t\tajxInfo = getAjxInfo( elm ),\n\t\t\tajaxType = ajxInfo.type,\n\t\t\tcontent, jQueryCaching,\n\t\t\tsettings = wb.getData( $( elm ), shortName ) || {},\n\t\t\tdoEncode = settings.encode,\n\t\t\thasSelector = fetchObj.hasSelector,\n\t\t\tresultString = \"\";\n\n\t\t// ajax-fetched event\n\t\tcontent = fetchObj.response;\n\t\tif ( content &amp;amp;&amp;amp;  content.length &amp;gt; 0 ) {\n\n\t\t\t// If the fetched content need to be encoded\n\t\t\tif ( doEncode &amp;amp;&amp;amp; hasSelector ) {\n\t\t\t\tif ( content.length &amp;gt; 1 ) {\n\t\t\t\t\tcontent.each( function( idx, itm ) {\n\t\t\t\t\t\tresultString += itm.outerHTML + \"\\n\";\n\t\t\t\t\t} );\n\n\t\t\t\t\tcontent = resultString;\n\t\t\t\t} else {\n\t\t\t\t\tcontent = content.html();\n\t\t\t\t}\n\n\t\t\t\tcontent = content.replaceAll( \"&amp;lt;\", \"&amp;lt;\" );\n\t\t\t} else if ( doEncode &amp;amp;&amp;amp; !hasSelector ) {\n\t\t\t\tcontent = fetchObj.xhr.responseText.replaceAll( \"&amp;lt;\", \"&amp;lt;\" );\n\t\t\t}\n\n\t\t\t//Prevents the force caching of nested resources\n\t\t\tjQueryCaching = jQuery.ajaxSettings.cache;\n\t\t\tjQuery.ajaxSettings.cache = true;\n\n\t\t\t// \"replace\" is the only event that doesn't map to a jQuery function\n\t\t\tif ( ajaxType === \"replace\" ) {\n\t\t\t\t$elm.html( content );\n\t\t\t} else {\n\t\t\t\t$elm[ ajaxType ]( content );\n\t\t\t}\n\n\t\t\t//Resets the initial jQuery caching setting\n\t\t\tjQuery.ajaxSettings.cache = jQueryCaching;\n\n\t\t\t$elm.trigger( contentUpdatedEvent, { \"ajax-type\": ajaxType, \"content\": content } );\n\t\t}\n\t};\n\n$document.on( \"timerpoke.wb \" + initEvent + \" \" + updateEvent + \" ajax-fetched.wb\", selector, function( event ) {\n\tvar eventTarget = event.target;\n\n\tswitch ( event.type ) {\n\n\t\tcase \"timerpoke\":\n\t\tcase \"wb-init\":\n\t\t\tinit( event );\n\t\t\tbreak;\n\t\tcase \"wb-update\":\n\t\t\tajax( event );\n\t\t\tbreak;\n\t\tdefault:\n\n\t\t\t// Filter out any events triggered by descendants\n\t\t\tif ( event.currentTarget === eventTarget ) {\n\t\t\t\tajxFetched( eventTarget, event.fetch );\n\t\t\t}\n\t}\n\n\t/*\n\t * Since we are working with events we want to ensure that we are being\n\t * passive about our control, so returning true allows for events to always\n\t * continue\n\t */\n\treturn true;\n} );\n\n// Re-run WET for elements that have just been loaded if WET is already done initializing\n$document.on( contentUpdatedEvent, function( event ) {\n\tif ( !wb.isDisabled ) {\n\t\tlet updtElm = event.target;\n\n\t\t$( updtElm )\n\t\t\t.find( wb.allSelectors )\n\t\t\t.addClass( \"wb-init\" )\n\t\t\t.filter( \":not(#\" + updtElm.id + \" .wb-init .wb-init)\" )\n\t\t\t.trigger( \"timerpoke.wb\" );\n\t}\n} );\n\n// Add the timerpoke to initialize the plugin\nfor ( s = 0; s !== selectorsLength; s += 1 ) {\n\twb.add( selectors[ s ] );\n}\n\n} )( jQuery, window, wb );\n\n/**\n * Web Experience Toolkit (WET) / Bo\u00eete \u00e0 outils de l'exp\u00e9rience Web (BOEW)\n * @title Data Fusion Query\n * @overview Map a query parameter value into an input value\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @duboisp\n *\n */\n( function( document, $, wb ) {\n\"use strict\";\n\n/**\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-data-fusion-query\",\n\tselector = \"[data-fusion-query][name]\",\n\tinitEvent = \"wb-init.\" + componentName,\n\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm,\n\t\t\tinputName,\n\t\t\tqueryParamValue;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\n\t\t\t// Retrieve the query parameter value and set it on the input\n\t\t\tinputName = $elm.attr( \"name\" );\n\t\t\tqueryParamValue = wb.pageUrlParts.params[ inputName ];\n\t\t\tif ( queryParamValue ) {\n\t\t\t\t$elm.val( queryParamValue.replace( /\\+/g, \" \" ) );\n\t\t\t}\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\nwb.doc.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( document, jQuery, wb );\n\n/**\n * @title WET-BOEW Data InView\n * @overview A simplified data-attribute driven plugin that responds to moving in and out of the viewport.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author WET Community\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-inview\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tscrollEvent = \"scroll\" + selector,\n\t$document = wb.doc,\n\t$window = wb.win,\n\t$elms = $(),\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered this handler\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\t\t\t$elms = $elms.add( $elm );\n\n\t\t\t// Allow other plugins to run first\n\t\t\tsetTimeout( function() {\n\t\t\t\tonInView( $elm );\n\n\t\t\t\t// Identify that initialization has completed\n\t\t\t\twb.ready( $elm, componentName );\n\t\t\t}, 1 );\n\t\t}\n\t},\n\n\t/**\n\t * @method onInView\n\t * @param {jQuery DOM element} $elm The plugin element\n\t */\n\tonInView = function( $elm ) {\n\t\tvar elementWidth = $elm.outerWidth(),\n\t\t\telementHeight = $elm.outerHeight(),\n\t\t\tscrollTop = $window.scrollTop(),\n\t\t\tscrollBottom = scrollTop + $window.height(),\n\t\t\tscrollRight = $window.scrollLeft() + elementWidth,\n\t\t\tx1 = $elm.offset().left,\n\t\t\tx2 = x1 + elementWidth,\n\t\t\ty1 = $elm.offset().top,\n\t\t\ty2 = y1 + elementHeight,\n\t\t\toldViewState = $elm.attr( \"data-inviewstate\" ),\n\t\t\tinView = ( scrollBottom &amp;lt; y1 || scrollTop &amp;gt; y2 ) || ( scrollRight &amp;lt; x1 || scrollRight &amp;gt; x2 ),\n\n\t\t\t// this is a bit of a play on true/false to get the desired effect. In short this variable depicts\n\t\t\t// the view state of the element\n\t\t\t// all - the whole element is in the viewport\n\t\t\t// partial - part of the element is in the viewport\n\t\t\t// none - no part of the element is in the viewport\n\t\t\tviewState = ( scrollBottom &amp;gt; y2 &amp;amp;&amp;amp; scrollTop &amp;lt; y1 ) ? \"all\" : inView ? \"none\" : \"partial\",\n\t\t\t$dataInView = $( \"#\" + $elm.attr( \"data-inview\" ) ),\n\t\t\tshow;\n\n\t\t// Remove any element that no longer exists in the DOM\n\t\tif ( elementWidth === 0 || elementHeight === 0 ) {\n\t\t\t$elms = $elms.not( $elm );\n\t\t\t$dataInView.addClass( \"user-closed\" );\n\t\t\t$dataInView.trigger( {\n\t\t\t\ttype: ( \"close\" ),\n\t\t\t\tnamespace: \"wb-overlay\",\n\t\t\t\tnoFocus: true\n\t\t\t} );\n\n\t\t\treturn;\n\t\t}\n\n\t\t// Link the overlay close button to the dismiss action if the inview content is dismissable\n\t\tif ( $elm.hasClass( \"wb-dismissable\" ) ) {\n\t\t\tif ( $dataInView.hasClass( \"wb-overlay\" ) ) {\n\t\t\t\t$dataInView.children( \".overlay-close\" ).on( \"click\", function( event ) {\n\t\t\t\t\tvar which = event.which;\n\n\t\t\t\t\t// Ignore middle/right mouse buttons\n\t\t\t\t\tif ( !which || which === 1 ) {\n\t\t\t\t\t\t$elm.parent().siblings( \".content-dismiss\" ).trigger( \"click\" );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\t// Only if the view state has changed\n\t\tif ( viewState !== oldViewState ) {\n\n\t\t\t// Show on \"partial\"/\"none\" (default) or just \"none\" (requires \"show-none\" class)\n\t\t\tshow = inView || ( $elm.hasClass( \"show-none\" ) ? false : viewState === \"partial\" );\n\n\t\t\t$elm.attr( \"data-inviewstate\", viewState );\n\n\t\t\tif ( $dataInView.length !== 0 ) {\n\n\t\t\t\t// Keep closed if the user closed the inView result\n\t\t\t\tif ( !$dataInView.hasClass( \"user-closed\" ) ) {\n\t\t\t\t\tif ( $dataInView.hasClass( \"wb-overlay\" ) ) {\n\t\t\t\t\t\tif ( !oldViewState ) {\n\t\t\t\t\t\t\t$dataInView.addClass( \"outside-off\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$dataInView.trigger( {\n\t\t\t\t\t\t\ttype: ( show ? \"open\" : \"close\" ),\n\t\t\t\t\t\t\tnamespace: \"wb-overlay\",\n\t\t\t\t\t\t\tnoFocus: true\n\t\t\t\t\t\t} );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( !$dataInView.attr( \"data-hasPlayed\" ) ) {\n\t\t\t\t\t\t\t$dataInView.toggleClass( \"in\", !show );\n\t\t\t\t\t\t\tif ( !$dataInView.hasClass( \"in-only\" ) ) {\n\t\t\t\t\t\t\t\t$dataInView.toggleClass( \"out\", show );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( wb.isReady &amp;amp;&amp;amp; viewState === \"all\" &amp;amp;&amp;amp; $dataInView.hasClass( \"in-only\" ) ) {\n\t\t\t\t\t\t\t$dataInView.attr( \"data-hasPlayed\", \"true\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Trigger an event on the element identifying that the view state has changed\n\t\t\t// (e.g., \"all.wb-inview\", \"partial.wb-inview\", \"none.wb-inview\")\n\t\t\t$elm.trigger( viewState + selector );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent + \" \" + scrollEvent, selector, function( event ) {\n\tvar eventTarget = event.target,\n\t\teventType = event.type;\n\n\tswitch ( eventType ) {\n\t\tcase \"timerpoke\":\n\t\tcase \"wb-init\":\n\t\t\tinit( event );\n\t\t\tbreak;\n\n\t\tcase \"scroll\":\n\n\t\t\t// Filter out any events triggered by descendants\n\t\t\tif ( event.currentTarget === eventTarget ) {\n\t\t\t\tonInView( $( eventTarget ) );\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\t/*\n\t * Since we are working with events we want to ensure that we are being passive about our control,\n\t * so returning true allows for events to always continue\n\t */\n\treturn true;\n} );\n\n$window.on( \"scroll scrollstop\", function() {\n\t$elms.trigger( scrollEvent );\n} );\n\n$document.on( \"txt-rsz.wb win-rsz-width.wb win-rsz-height.wb\", function() {\n\t$elms.trigger( scrollEvent );\n} );\n\n$document.on( \"refresh.wb\", function() {\n\t$elms.each( function() {\n\t\tonInView( $( this ) );\n\t} );\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Data Picture\n * @overview Event driven port of the Picturefill library: https://github.com/scottjehl/picturefill\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @patheard\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar imgClass,\n\tcomponentName = \"wb-pic\",\n\tselector = \"[data-pic]\",\n\tinitEvent = \"wb-init.\" + componentName,\n\tpicturefillEvent = \"picfill.\" + componentName,\n\t$document = wb.doc,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered this handler\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\n\t\t\t// Store the class attribute of the plugin element.  It\n\t\t\t// will be added to the image created by the plugin.\n\t\t\timgClass = $elm.data( \"class\" ) || \"\";\n\n\t\t\t$elm.trigger( picturefillEvent );\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t},\n\n\t/**\n\t * Updates the image displayed according to media queries.\n\t * This is the logic ported from Picturefill.\n\t * @method picturefill\n\t * @param {DOM element} elm The element containing the images to be updated\n\t */\n\tpicturefill = function( elm ) {\n\t\tvar matches = [],\n\t\t\timg = elm.getElementsByTagName( \"img\" )[ 0 ],\n\t\t\tsources = elm.getElementsByTagName( \"span\" ),\n\t\t\ti, len, matchedElm, media;\n\n\t\t// Loop over the data-media elements and find matching media queries\n\t\tfor ( i = 0, len = sources.length; i !== len; i += 1 ) {\n\t\t\tmedia = sources[ i ].getAttribute( \"data-media\" );\n\n\t\t\t// Check if the media query matches or if no media query is defined.\n\t\t\t// V\u00e9rifie si le media query correspond ou si aucun media query n'est d\u00e9fini.\n\t\t\tif ( !media || window.matchMedia( media ).matches ) {\n\t\t\t\tmatches.push( sources[ i ] );\n\t\t\t}\n\t\t}\n\n\t\t// If a media query match was found, add the image to the page\n\t\tif ( matches.length !== 0 ) {\n\t\t\tmatchedElm = matches.pop();\n\t\t\tif ( !img ) {\n\t\t\t\timg = $document[ 0 ].createElement( \"img\" );\n\t\t\t\timg.alt = elm.getAttribute( \"data-alt\" );\n\t\t\t\timg.className = imgClass;\n\t\t\t}\n\t\t\timg.src = matchedElm.getAttribute( \"data-src\" );\n\t\t\tmatchedElm.appendChild( img );\n\n\t\t// No match and an image exists: delete it\n\t\t} else if ( img ) {\n\t\t\timg.parentNode.removeChild( img );\n\t\t}\n\n\t\t// Identify that the picture has been updated\n\t\t$( elm ).trigger( \"wb-updated.\" + componentName );\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent + \" \" + picturefillEvent, selector, function( event ) {\n\tvar eventTarget = event.target,\n\t\teventType = event.type;\n\n\tswitch ( eventType ) {\n\t\tcase \"timerpoke\":\n\t\tcase \"wb-init\":\n\t\t\tinit( event );\n\t\t\tbreak;\n\n\t\tcase \"picfill\":\n\n\t\t\t// Filter out any events triggered by descendants\n\t\t\tif ( event.currentTarget === eventTarget ) {\n\t\t\t\tpicturefill( eventTarget );\n\t\t\t}\n\t\t\tbreak;\n\t}\n} );\n\n// Handles window resize so images can be updated as new media queries match\n$document.on( \"txt-rsz.wb win-rsz-width.wb win-rsz-height.wb\", function() {\n\t$( selector ).trigger( picturefillEvent );\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Details closed on small screen\n * @overview Closes details on defined viewport and down if they were not engaged, default is small\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @thomasgohard\n */\n( function( $, wb ) {\n\"use strict\";\n\n/*\n* Variable and function definitions.\n* These are global to the plugin - meaning that they will be initialized once per page,\n* not once per instance of plugin on the page. So, this is a good place to define\n* variables that are common to all instances of the plugin on a page.\n*/\nconst componentName = \"wb-details-close\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\tviews = [ \"xxs\", \"xs\", \"sm\", \"md\", \"lg\", \"xl\" ],\n\tviewsClasses = [ \"xxsmallview\", \"xsmallview\", \"smallview\", \"mediumview\", \"largeview\", \"xlargeview\" ],\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tlet elm = wb.init( event, componentName, selector );\n\n\t\tif ( elm ) {\n\t\t\tlet $elm = $( elm ),\n\t\t\t\tbreakpoint = elm.dataset.breakpoint || \"sm\", // Get the target breakpoint from data attribute or default to \"sm\"\n\t\t\t\tviewBreakpointIndex = views.indexOf( breakpoint ), // Get the index of the target breakpoint\n\t\t\t\tviewBreakpoint = viewsClasses.slice( 0, viewBreakpointIndex + 1 ), // Get the target and smaller view classes\n\t\t\t\tviewsSelector = \"html.\" + viewBreakpoint.join( \", html.\" ); // Create a selector for the target and smaller views\n\n\t\t\t// If within the targetted views, keep details closed. If not, keep opened.\n\t\t\tif ( document.querySelector( viewsSelector ) ) {\n\t\t\t\telm.removeAttribute( \"open\" );\n\t\t\t} else {\n\t\t\t\telm.setAttribute( \"open\", \"\" );\n\t\t\t}\n\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, wb );\n\n/**\n * @title WET-BOEW Dismissable content plugin\n * @overview Enables content to be dismissed\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @thomasgohard\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the event - meaning that they will be initialized once per page,\n * not once per instance of event on the page.\n */\nvar componentName = \"wb-dismissable\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init.\" + componentName,\n\tcontainerClass = \"wb-dismissable-container\",\n\twrapperClass = \"wb-dismissable-wrapper\",\n\tdismissClass = \"content-dismiss\",\n\tidKey = \"dismissable-item-id\",\n\t$document = wb.doc,\n\ti18n, i18nText,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\titemId, dismissedState, contentContainer, contentWrapper, dismissButton;\n\n\t\tif ( elm ) {\n\n\t\t\t// Only initialize the i18nText once\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\tdismiss: i18n( \"dismiss\" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Give the dismissable element a unique ID\n\t\t\tif ( elm.hasAttribute( \"id\" ) ) {\n\t\t\t\titemId = elm.getAttribute( \"id\" );\n\n\t\t\t\t// Ignore an ID assigned by wb\n\t\t\t\tif ( itemId.indexOf( \"wb-auto-\" ) === 0 ) {\n\t\t\t\t\titemId = undefined;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( itemId === undefined ) {\n\t\t\t\titemId = wb.hashString( wb.stripWhitespace( elm.innerHTML ) );\n\t\t\t}\n\n\t\t\tdismissedState = getDismissedState( itemId );\n\n\t\t\tif ( dismissedState === \"true\" ) {\n\n\t\t\t\t// Remove the element if it has been dismissed\n\t\t\t\tif ( elm.parentNode ) {\n\t\t\t\t\telm.parentNode.removeChild( elm );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$( elm ).wrap( \"\n\" );\n\t\t\t\tcontentWrapper = elm.parentNode;\n\n\t\t\t\t$( contentWrapper ).wrap( \"\n\" );\n\t\t\t\tcontentContainer = contentWrapper.parentNode;\n\n\t\t\t\tdismissButton = \"&amp;#xd7; \" +\n\t\t\t\t\ti18nText.dismiss + \"\";\n\t\t\t\t$( contentContainer ).append( dismissButton );\n\n\t\t\t\tcontentContainer.setAttribute( \"data-\" + idKey, itemId );\n\t\t\t}\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $document, componentName );\n\t\t}\n\t},\n\n\tgetDismissedState = function( id ) {\n\t\tvar dismissState = localStorage.getItem( id );\n\n\t\tif ( dismissState === null ) {\n\t\t\treturn false;\n\t\t}\n\n\t\treturn dismissState;\n\t},\n\n\tdismissContent = function( elm ) {\n\t\tlocalStorage.setItem( elm.getAttribute( \"data-\" + idKey ), true );\n\t\telm.parentNode.removeChild( elm );\n\t\t$document.trigger( \"refresh.wb\" );\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Handler for clicking on the dismiss button\n$document.on( \"click\", \".\" + dismissClass, function( event ) {\n\tvar elm = event.currentTarget,\n\t\twhich = event.which;\n\n\t// Ignore middle/right mouse buttons\n\tif ( !which || which === 1 ) {\n\t\tdismissContent( elm.parentNode );\n\t}\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title eqht\n * @overview Provide ability to have equal height containers and nested containers inside a WET-BOEW grid\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @luc-bertrand-hrsdc\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-eqht-grd\",\n\tselector = \".\" + componentName + \" .eqht-trgt\",\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm,\n\t\t\t$eqhtParents;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\t\t\t$elm.addClass( \"hght-inhrt\" );\n\t\t\t$eqhtParents = $elm.parentsUntil( \"[class*='\" + componentName + \"']\" );\n\t\t\t$eqhtParents.addClass( \"hght-inhrt\" );\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Responsive equal height\n * @overview Sets the same height for all elements in a container that are rendered on the same baseline (row). Adapted from https://codepen.io/micahgodbolt/pen/FgqLc.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @thomasgohard\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-eqht\",\n\tselector = \".\" + componentName,\n\t$document = wb.doc,\n\teventTimerpoke = \"timerpoke.wb\",\n\tinitEvent = \"wb-init\" + selector,\n\tvAlignCSS = \"vertical-align\",\n\tvAlignDefault = \"top\",\n\tcontentUpdatedEvent = \"wb-contentupdated\",\n\tminHeightCSS = \"min-height\",\n\tminHeightDefault = \"0\",\n\tcssValueSeparator = \":\",\n\tcssPropertySeparator = \";\",\n\tregexCSSValue = \" ?[^;]+\",\n\tregexVAlign = new RegExp( vAlignCSS + cssValueSeparator + \" ?\" + regexCSSValue + cssPropertySeparator + \"?\", \"i\" ),\n\tregexMinHeight = new RegExp( minHeightCSS + cssValueSeparator + \" ?\" + regexCSSValue + cssPropertySeparator + \"?\", \"i\" ),\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector );\n\n\t\tif ( elm ) {\n\n\t\t\t// Remove the event handler since only want init fired once per page (not per element)\n\t\t\t$document.off( eventTimerpoke, selector );\n\n\t\t\tonResize();\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $document, componentName );\n\t\t}\n\t},\n\n\t/**\n\t * Re-equalise any time the window/document or a child element of 'selector' is resized.\n\t * @method onResize\n\t */\n\tonResize = function() {\n\t\tvar $elm, $children, $anchor, currentChild, childCSS, i, j,\n\t\t\t$elms = $( selector ),\n\t\t\trow = [],\n\t\t\trowTop = -1,\n\t\t\tcurrentChildTop = -1,\n\t\t\tcurrentChildHeight = -1,\n\t\t\ttallestHeight = -1;\n\n\t\tfor ( i = $elms.length - 1; i !== -1; i -= 1 ) {\n\t\t\t$elm = $elms.eq( i );\n\t\t\t$children = $elm.find( \".eqht-trgt\" );\n\t\t\tif ( !$children.length ) {\n\t\t\t\t$children = $elm.children();\n\t\t\t}\n\n\t\t\t// Reinitialize the row at the beginning of each section of equal height\n\t\t\trow = [];\n\n\t\t\t$anchor = detachElement( $elm );\n\t\t\tfor ( j = $children.length - 1; j !== -1; j -= 1 ) {\n\t\t\t\tcurrentChild = $children[ j ];\n\t\t\t\tchildCSS = currentChild.style.cssText.toLowerCase();\n\n\t\t\t\t//Ensure the CSS string ends by a separator\n\t\t\t\tif ( childCSS.length &amp;gt; 0 &amp;amp;&amp;amp; childCSS.substr( childCSS.length - 1 ) !== cssPropertySeparator ) {\n\t\t\t\t\tchildCSS += cssPropertySeparator;\n\t\t\t\t}\n\n\t\t\t\t// Ensure all children that are on the same baseline have the same 'top' value.\n\t\t\t\tif ( childCSS.indexOf( vAlignCSS ) !== -1 ) {\n\t\t\t\t\tchildCSS = childCSS.replace( regexVAlign, vAlignCSS + cssValueSeparator + vAlignDefault + cssPropertySeparator );\n\t\t\t\t} else {\n\t\t\t\t\tchildCSS += \" \" + vAlignCSS + cssValueSeparator + vAlignDefault + cssPropertySeparator;\n\t\t\t\t}\n\n\t\t\t\t// Remove any previously set min height\n\t\t\t\tif ( childCSS.indexOf( minHeightCSS ) !== -1 ) {\n\t\t\t\t\tchildCSS = childCSS.replace( regexMinHeight, minHeightCSS + cssValueSeparator + minHeightDefault + cssPropertySeparator );\n\t\t\t\t} else {\n\t\t\t\t\tchildCSS += \" \" + minHeightCSS + cssValueSeparator + minHeightDefault + cssPropertySeparator;\n\t\t\t\t}\n\n\t\t\t\tcurrentChild.style.cssText = childCSS;\n\t\t\t\t$children.eq( j ).data( minHeightCSS, minHeightDefault );\n\t\t\t}\n\t\t\t$elm = reattachElement( $anchor );\n\n\t\t\t// set the top offset and tallest height to the first element\n\t\t\trowTop = $children[ 0 ] ? $children[ 0 ].getBoundingClientRect().top + window.pageYOffset : 0;\n\t\t\ttallestHeight = $children[ 0 ] ? $children[ 0 ].offsetHeight : 0;\n\n\t\t\t// first, the loop MUST be from start to end to work.\n\t\t\tfor ( j = 0; j &amp;lt; $children.length; j++ ) {\n\t\t\t\tcurrentChild = $children[ j ];\n\n\t\t\t\tcurrentChildTop = currentChild.getBoundingClientRect().top + window.pageYOffset;\n\t\t\t\tcurrentChildHeight = currentChild.offsetHeight;\n\n\t\t\t\t// if the current element is visible...\n\t\t\t\t// note: hidden elements need to be excluded since they have a different top offset than visible ones\n\t\t\t\tif ( currentChildHeight ) {\n\n\t\t\t\t\t// as soon as we find an element not on this row (not the same top offset)...\n\t\t\t\t\tif ( currentChildTop !== rowTop ) {\n\n\t\t\t\t\t\t// we need to equalize each item in that row to align the next row\n\t\t\t\t\t\tequalize( row, tallestHeight );\n\n\t\t\t\t\t\t// since the elements of the previous row was equalized\n\t\t\t\t\t\t// we need to get the new top offset of the current element\n\t\t\t\t\t\tcurrentChildTop = currentChild.getBoundingClientRect().top + window.pageYOffset;\n\n\t\t\t\t\t\t// reset the row, rowTop and tallestHeight\n\t\t\t\t\t\trow.length = 0;\n\t\t\t\t\t\trowTop = currentChildTop;\n\t\t\t\t\t\ttallestHeight = currentChildHeight;\n\t\t\t\t\t}\n\n\t\t\t\t\ttallestHeight = Math.max( currentChildHeight, tallestHeight );\n\t\t\t\t\trow.push( $children.eq( j ) );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// equalize the last row\n\t\t\tequalize( row, tallestHeight );\n\n\t\t\t// Identify that the height equalization was updated\n\t\t\t$document.trigger( \"wb-updated\" + selector );\n\t\t}\n\t},\n\n\t/**\n\t* @method equalize\n\t* @param {array} row the array of items to be equalized\n\t* @param {int} tallestHeight the tallest height to use to equalize\n\t*/\n\tequalize = function( row, tallestHeight ) {\n\t\tfor ( var i = 0; i &amp;lt; row.length; i++ ) {\n\n\t\t\t// added a +1 because some floated element got stuck if the\n\t\t\t// shortest element was the last element in the row\n\t\t\tvar minHeight = tallestHeight + 1;\n\t\t\trow[ i ][ 0 ].style.minHeight = minHeight + \"px\";\n\t\t}\n\t},\n\n\t/**\n\t * @method detachElement\n\t * @param {jQuery object} $elm The element to detach\n\t * @returns {object} The detached element\n\t */\n\tdetachElement = function( $elm ) {\n\t\tvar $prev = $elm.prev(),\n\t\t\t$next = $elm.next(),\n\t\t\t$parent = $elm.parent();\n\n\t\tif ( $prev.length ) {\n\t\t\t$elm.data( { anchor: $prev, anchorRel: \"prev\" } );\n\t\t} else if ( $next.length ) {\n\t\t\t$elm.data( { anchor: $next, anchorRel: \"next\" } );\n\t\t} else if ( $parent.length ) {\n\t\t\t$elm.data( { anchor: $parent, anchorRel: \"parent\" } );\n\t\t}\n\n\t\treturn $elm.detach();\n\t},\n\n\t/**\n\t * @method reattachElement\n\t * @param {jQuery object} $elm The element to reattach\n\t * @returns {object} The reattached element\n\t */\n\treattachElement = function( $elm ) {\n\t\tvar $anchor = $elm.data( \"anchor\" ),\n\t\t\tanchorRel = $elm.data( \"anchorRel\" );\n\n\t\tswitch ( anchorRel ) {\n\t\t\tcase \"prev\":\n\t\t\t\t$anchor.after( $elm );\n\t\t\t\tbreak;\n\t\t\tcase \"next\":\n\t\t\t\t$anchor.before( $elm );\n\t\t\t\tbreak;\n\t\t\tcase \"parent\":\n\t\t\t\t$anchor.append( $elm );\n\t\t\t\tbreak;\n\t\t}\n\n\t\treturn $elm;\n\t};\n\n// Bind the init event of the plugin\n$document.on( eventTimerpoke + \" \" + initEvent, selector, init );\n\n// Handle text and window resizing\n$document.on( \"txt-rsz.wb win-rsz-width.wb win-rsz-height.wb \" + contentUpdatedEvent + \" wb-updated.wb-tables wb-update\" + selector, onResize );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n* @title WET-BOEW Exit script plugin\n* @overview Plugin redirects users to non secure site\n* @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n* @author @ipaksc\n*/\n( function( $, window, wb, crypto ) {\n\"use strict\";\nvar componentName = \"wb-exitscript\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\texiturlparam = componentName + \"-urlparam\",\n\tkeyForKeyHolder = componentName + \"key\",\n\tmoDalId = componentName + \"-modal\",\n\ti18n,\n\ti18nDict = {\n\t\ten: {\n\t\t\t\"msgboxHeader\": \"Warning\",\n\t\t\t\"exitMsg\": \"You are about to leave a secure site, do you wish to continue?\",\n\t\t\t\"targetWarning\": \"The link will open in a new browser window.\",\n\t\t\t\"yesBtn\": \"Yes\",\n\t\t\t\"cancelBtn\": \"Cancel\"\n\n\t\t},\n\t\tfr: {\n\t\t\t\"msgboxHeader\": \"Avertissement\",\n\t\t\t\"exitMsg\": \"Vous \u00eates sur le point de quitter un site s\u00e9curis\u00e9. Voulez-vous continuer?\",\n\t\t\t\"targetWarning\": \"Le lien s'ouvrira dans une nouvelle fen\u00eatre de navigateur.\",\n\t\t\t\"yesBtn\": \"Oui\",\n\t\t\t\"cancelBtn\": \"Annuler\"\n\n\t\t}\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\tsettings,\n\t\t\tqueryString = window.location.search,\n\t\t\turlParams = new URLSearchParams( queryString ),\n\t\t\tcounterInUrl = wb.string.fromHexString( urlParams.get( \"exturl\" ) ),\n\t\t\tencryptedUrl = localStorage.getItem( componentName ),\n\t\t\tjwt = JSON.parse( localStorage.getItem( keyForKeyHolder ) ),\n\t\t\t$elm;\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\t\t\tsettings = $.extend(\n\t\t\t\ttrue,\n\t\t\t\twindow[ componentName ],\n\t\t\t\twb.getData( $elm, componentName )\n\n\t\t\t);\n\n\t\t\t$elm.data( componentName, settings );\n\n\t\t\tif ( settings.url &amp;amp;&amp;amp; crypto ) {\n\n\t\t\t\tcrypto.subtle.generateKey(\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"AES-CTR\",\n\t\t\t\t\t\tlength: 256\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t\t[ \"encrypt\", \"decrypt\" ]\n\t\t\t\t).then( function( keyToEncrypt ) {\n\n\t\t\t\t\tvar enc, messageEncoded, counter;\n\n\t\t\t\t\t// Save the key in the anchor\n\t\t\t\t\tcrypto.subtle.exportKey( \"jwk\", keyToEncrypt )\n\t\t\t\t\t\t.then( function( exportedJwtKey ) {\n\t\t\t\t\t\t\telm[ keyForKeyHolder ] = exportedJwtKey;\n\t\t\t\t\t\t} );\n\n\t\t\t\t\t// Encrypt the URL\n\t\t\t\t\tenc = new TextEncoder();\n\t\t\t\t\tmessageEncoded = enc.encode( elm.href );\n\t\t\t\t\tcounter = crypto.getRandomValues( new Uint8Array( 16 ) );\n\t\t\t\t\tcrypto.subtle.encrypt(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: \"AES-CTR\",\n\t\t\t\t\t\t\tcounter: counter,\n\t\t\t\t\t\t\tlength: 64\n\t\t\t\t\t\t},\n\t\t\t\t\t\tkeyToEncrypt,\n\t\t\t\t\t\tmessageEncoded\n\t\t\t\t\t).then( function( ciphertext ) {\n\t\t\t\t\t\telm[ componentName ] = ciphertext;\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Change the link URL by passing the counter as a key\n\t\t\t\t\t$elm.attr( \"href\", settings.url + \"?exturl=\" + wb.string.toHexString( counter ) );\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\ti18n = i18nDict[ wb.lang || \"en\" ];\n\n\t\t\t// This conditional statement for a middle static exit page, to retrieve the URL to the non-secure site.\n\t\t\tif ( $elm.hasClass( exiturlparam ) &amp;amp;&amp;amp; encryptedUrl !== null &amp;amp;&amp;amp; jwt !== null ) {\n\n\t\t\t\tcrypto.subtle.importKey(\n\t\t\t\t\t\"jwk\",\n\t\t\t\t\tjwt,\n\t\t\t\t\t{\n\t\t\t\t\t\tname: \"AES-CTR\",\n\t\t\t\t\t\tlength: 256\n\t\t\t\t\t},\n\t\t\t\t\ttrue,\n\t\t\t\t\t[ \"decrypt\" ]\n\t\t\t\t).then( function( key ) {\n\n\t\t\t\t\tcrypto.subtle.decrypt(\n\t\t\t\t\t\t{\n\t\t\t\t\t\t\tname: \"AES-CTR\",\n\t\t\t\t\t\t\tcounter: counterInUrl,\n\t\t\t\t\t\t\tlength: 64\n\t\t\t\t\t\t},\n\t\t\t\t\t\tkey,\n\t\t\t\t\t\twb.string.base64ToArrayBuffer( encryptedUrl )\n\t\t\t\t\t).then( function( decrypted ) {\n\n\t\t\t\t\t\tvar dec = new TextDecoder(),\n\t\t\t\t\t\t\turlToRedirect = dec.decode( decrypted );\n\n\t\t\t\t\t\t// Check if the decrypted message is an valid URL and silently fail if the pattern don't match\n\t\t\t\t\t\tif ( urlToRedirect.match( /^(http|https):\\/\\//g ) ) {\n\t\t\t\t\t\t\telm.outerHTML = \"\" + urlToRedirect + \"\";\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} );\n\t\t\t\t} );\n\n\t\t\t}\n\n\t\t\t// Remove the plugin data and ensure it is removed from the localStorage\n\t\t\tlocalStorage.removeItem( componentName );\n\t\t\tlocalStorage.removeItem( keyForKeyHolder );\n\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t};\n\n$document.on( \"click\", selector, function( event ) {\n\n\tvar elm = event.currentTarget,\n\t\t$elm = $( elm ),\n\t\twrapper,\n\t\ttargetAttribute = \"\",\n\t\tmoDal = document.createDocumentFragment(),\n\t\ttpl = document.createElement( \"div\" ),\n\t\tsettings =  $elm.data( componentName ),\n\t\tmsgboxHeader = i18n.msgboxHeader,\n\t\tyesBtn = i18n.yesBtn,\n\t\tcancelBtn = i18n.cancelBtn,\n\t\texitMsg = i18n.exitMsg,\n\t\ttargetWarning = i18n.targetWarning;\n\n\tif ( settings.i18n ) {\n\t\tmsgboxHeader =  settings.i18n.msgboxHeader || i18n.msgboxHeader;\n\t\tyesBtn = settings.i18n.yesBtn || i18n.yesBtn;\n\t\tcancelBtn = settings.i18n.cancelBtn || i18n.cancelBtn;\n\t\texitMsg = settings.i18n.exitMsg || i18n.exitMsg;\n\t\ttargetWarning = settings.i18n.targetWarning || i18n.targetWarning;\n\t}\n\n\tif ( !settings.url ) {\n\n\t\tevent.preventDefault();\n\t}\n\n\tif ( this.hasAttribute( \"target\" ) ) {\n\t\ttargetAttribute = \"target='\" + this.getAttribute( \"target\" ) + \"'\";\n\t} else {\n\t\ttargetAttribute = \"target='\" + targetAttribute + \"'\";\n\t}\n\n\tif ( this.getAttribute( \"target\" ) === \"_blank\" ) {\n\t\texitMsg = exitMsg  + \" \" + targetWarning;\n\t}\n\n\tif ( document.getElementById( moDalId ) ) {\n\t\tdocument.getElementById( moDalId ).remove();\n\n\t}\n\n\tif ( !settings.url ) {\n\t\ttpl.innerHTML = \"\n\" +\n\t\t\t\"\n\n\" + msgboxHeader + \"\" +\n\t\t\t\"\n\" +\n\t\t\t\"\n\" + exitMsg + \"\" +\n\t\t\t\"\" +\n\t\t\t\"\n\" +\n\t\t\t\"\n\" +\n\t\t\t\"\n\" + yesBtn + \"\" +\n\t\t\t\"\n\" + cancelBtn + \"\" +\n\t\t\t\"\";\n\t\tmoDal.appendChild( tpl );\n\t\twrapper = moDal.firstChild;\n\t\twrapper = wrapper.firstChild;\n\t\tdocument.body.appendChild( wrapper );\n\n\t\t$( wrapper ).trigger( \"open.wb-lbx\", [\n\t\t\t[ {\n\t\t\t\tsrc: \"#\" + moDalId,\n\t\t\t\ttype: \"inline\"\n\t\t\t} ],\n\n\t\t\ttrue\n\n\t\t] );\n\n\t} else if ( crypto &amp;amp;&amp;amp; this[ componentName ] ) {\n\n\t\t// Save to localStorage, the plugin init will ensure this data is only used once\n\t\tlocalStorage.setItem( componentName, wb.string.arrayBufferToBase64( this[ componentName ] ) );\n\t\tlocalStorage.setItem( keyForKeyHolder, JSON.stringify( this[ keyForKeyHolder ] ) );\n\t}\n\n} );\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb, crypto );\n\n/**\n* @title WET-BOEW Facebook embedded page\n* @overview Helps with implementing Facebook embedded pages.\n* @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n* @author @pjackson28\n*/\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n* Variable and function definitions.\n* These are global to the plugin - meaning that they will be initialized once per page,\n* not once per instance of plugin on the page. So, this is a good place to define\n* variables that are common to all instances of the plugin on a page.\n*/\nvar componentName = \"wb-facebook\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\tfbinited = false,\n\n\t/**\n\t* @method init\n\t* @param {jQuery Event} event Event that triggered the function call\n\t*/\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar ele = wb.init( event, componentName, selector ),\n\t\t\tprotocol = wb.pageUrlParts.protocol;\n\n\t\tif ( ele ) {\n\t\t\tModernizr.load(\n\t\t\t\t{\n\t\t\t\t\tload: [ ( protocol.indexOf( \"http\" ) === -1 ? \"http:\" : protocol ) + \"//connect.facebook.net/\" + wb.lang + \"_US/sdk.js\" ],\n\t\t\t\t\tcomplete: function() {\n\t\t\t\t\t\tif ( !fbinited ) {\n\t\t\t\t\t\t\twindow.FB.init( {\n\t\t\t\t\t\t\t\tversion: \"v2.4\"\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\tfbinited = true;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\twindow.FB.XFBML.parse( ele[ 0 ] );\n\t\t\t\t\t\twb.ready( $( ele ), componentName );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t);\n\t\t}\n\t};\n\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Favicon Plugin\n * @overview Provides the ability to add and update a page's favicons\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @patheard\n *\n * This plugin provides the ability to add and update the favicon's on a web page. Its default behaviour is to add a mobile favicon to web pages that have a favicon defined by a `` element.\n *\n * The mobile favicon's file name, rel, path and sizes can be set with data attributes on the ``:\n *\n * -**data-filename:** filename of the mobile favicon (defaults to \"favicon-mobile.png\"). This will be appended to the favicon's path.\n * -**data-path:** path to the mobile favicon (defaults to using the same path as the shortcut icon).\n * -**data-rel:** rel attribute of the mobile favicon (defaults to \"apple-touch-icon\").\n * -**data-sizes:** sizes attribute of the mobile favicon (defaults to \"57x57 72x72 114x114 144x144 150x150\").\n *\n * For example, the following overrides the rel and file name attributes of the mobile favicon:\n *\n *     \n */\n( function( $, document, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-favicon\",\n\tselector = \"link[rel='icon']\",\n\tinitEvent = \"wb-init.\" + componentName,\n\tupdatedEvent = \"wb-updated.\" + componentName,\n\tmobileEvent = \"mobile.\" + componentName,\n\ticonEvent = \"icon.\" + componentName,\n\t$document = wb.doc,\n\n\t/*\n\t * Plugin users can override these defaults by setting attributes on the html elements that the\n\t * selector matches.\n\t * For example, adding the attribute data-option1=\"false\", will override option1 for that plugin instance.\n\t */\n\tdefaults = {\n\t\tfilename: \"favicon-mobile.png\",\n\t\tpath: null,\n\t\trel: \"apple-touch-icon\",\n\t\tsizes: \"57x57 72x72 114x114 144x144 150x150\"\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector, true ),\n\t\t\t$favicon, settings;\n\n\t\tif ( elm ) {\n\t\t\t$favicon = $( elm );\n\n\t\t\t// Merge default settings with overrides from the selected plugin element.\n\t\t\tsettings = $.extend( {}, defaults, $favicon.data() );\n\n\t\t\t$favicon.trigger( mobileEvent, settings );\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $document, componentName );\n\t\t}\n\t},\n\n\t/**\n\t * Adds, or updates, the mobile favicon on a page. Mobile favicons are identified by the\n\t * `apple` prefix in the `` elements rel attribute.\n\t * @method mobile\n\t * @param {DOM element} favicon Favicon element\n\t * @param {jQuery Event} event Event that triggered this handler\n\t * @param {Object} data Key-value data object passed with the event\n\t */\n\tmobile = function( favicon, event, data ) {\n\t\tvar faviconPath,\n\t\t\tfaviconMobile = $( \"link[rel^='apple']\" ),\n\t\t\tisFaviconMobile = faviconMobile.length !== 0;\n\n\t\t// Create the mobile favicon if it doesn't exist\n\t\tif ( !isFaviconMobile ) {\n\t\t\tvar lnk = document.createElement( \"link\" );\n\t\t\tlnk.setAttribute( \"rel\", data.rel  );\n\t\t\tlnk.setAttribute( \"sizes\", data.sizes );\n\t\t\tlnk.setAttribute( \"class\", componentName );\n\n\t\t\tdocument.head.appendChild( lnk );\n\n\t\t\tfaviconMobile = $( lnk );\n\t\t}\n\n\t\t// Only add/update a mobile favicon that was created by the plugin\n\t\tif ( faviconMobile.hasClass( componentName ) ) {\n\t\t\tfaviconPath = data.path !== null ? data.path : getPath( favicon.getAttribute( \"href\" ) );\n\t\t\tfaviconMobile.attr( \"href\", faviconPath + data.filename );\n\n\t\t\tif ( !isFaviconMobile ) {\n\t\t\t\tfavicon.parentNode.insertBefore( faviconMobile[ 0 ], favicon );\n\t\t\t}\n\t\t}\n\n\t\t$document.trigger( updatedEvent, [ \"mobile\" ] );\n\t},\n\n\t/**\n\t * Updates the the page's shortcut icon\n\t * @method icon\n\t * @param {DOM element} favicon Favicon element\n\t * @param {jQuery Event} event Event that triggered this handler\n\t * @param {Object} data Key-value data object passed with the event\n\t */\n\ticon = function( favicon, event, data ) {\n\t\tvar faviconPath = data.path !== null ? data.path : getPath( favicon.getAttribute( \"href\" ) );\n\t\tfavicon.setAttribute( \"href\", faviconPath + data.filename );\n\n\t\t$document.trigger( updatedEvent, [ \"icon\" ] );\n\t},\n\n\t/**\n\t * Given a full file path, returns the path without the filename\n\t * @method getPath\n\t * @param {string} filepath The full path to file, including filename\n\t * @returns {string} The path to the file\n\t */\n\tgetPath = function( filepath ) {\n\t\treturn filepath.substring( 0, filepath.lastIndexOf( \"/\" ) + 1 );\n\t};\n\n// Bind the init event\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Bind the mobile and icon events\n$document.on( mobileEvent + \" \" + iconEvent, selector, function( event, data ) {\n\tvar eventTarget = event.target;\n\n\t// Filter out any events triggered by descendants\n\tif ( event.currentTarget === eventTarget ) {\n\t\tswitch ( event.type ) {\n\t\t\tcase \"mobile\":\n\t\t\t\tmobile( eventTarget, event, data );\n\t\t\t\tbreak;\n\n\t\t\tcase \"icon\":\n\t\t\t\ticon( eventTarget, event, data );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t * Since we are working with events we want to ensure that we are being passive about our control,\n\t * so returning true allows for events to always continue\n\t */\n\treturn true;\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, document, wb );\n\n/**\n * @title WET-BOEW Feeds\n * @overview Aggregates and displays entries from one or more Web feeds.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @pjackson28\n */\n( function( $, window, wb, undef ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-feeds\",\n\tselector = \".\" + componentName,\n\tfeedLinkSelector = \"li &amp;gt; a\",\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\tpatt = /\\\\u([\\d\\w]{4})/g,\n\n\t/**\n\t * @object Templates\n\t * @properties {function}\n\t * @param {object} requires a entry object of various ATOM based properties\n\t * @returns {string} modified string with appropriate markup/format for a entry object\n\t */\n\tTemplates = {\n\n\t\t/**\n\t\t * [flickr template]\n\t\t * @param  {entry object} data\n\t\t * @return {string}\tHTML string for creating a photowall effect\n\t\t */\n\t\tflickr: function( data ) {\n\t\t\tvar media = data.media.m,\n\t\t\t\tflickrData = {\n\t\t\t\t\ttitle: data.title,\n\t\t\t\t\tthumbnail: media.replace( \"_m.\", \"_s.\" ),\n\t\t\t\t\timage: media.replace( \"_m\", \"\" ),\n\t\t\t\t\tdescription: data.description.replace( /^\\s*\n(.*?)&amp;lt;\\/p&amp;gt;\\s*\n(.*?)&amp;lt;\\/p&amp;gt;/i, \"\" )\n\t\t\t\t};\n\n\t\t\t// due to CORS we cannot default to simple ajax pulls of the image. We have to inline the content box\n\t\t\treturn \"\n\";\n\t\t},\n\n\t\t/**\n\t\t * [YouTube template]\n\t\t * @param  {entry object} data\n\t\t * @return {string}\tHTML string for creating a photowall effect\n\t\t */\n\t\tyoutube: function( data ) {\n\t\t\tvar youtubeDate = {\n\t\t\t\ttitle: data.title,\n\t\t\t\tvideoId: data.id\n\t\t\t};\n\n\t\t\t// Due to CORS we cannot default to simple ajax pulls of the image. We have to inline the content box\n\t\t\treturn \"\n\";\n\t\t},\n\n\t\t/**\n\t\t * [pinterest template]\n\t\t * @param  {entry object}    data\n\t\t * @return {string}    HTML string of formatted using a simple list / anchor view\n\t\t */\n\t\tpinterest: function( data ) {\n\t\t\tvar content = fromCharCode( data.description ).replace( /]*)&amp;gt;&amp;lt;\\/a&amp;gt;([^&amp;lt;]*)($2$3\" );\n\t\t\treturn \"\n\" + content +\n\t\t\t( data.publishedDate !== \"\" ? \" \" +\n\t\t\twb.date.toDateISO( data.publishedDate, true ) + \"\" : \"\" ) + \"\";\n\t\t},\n\n\t\t/**\n\t\t * [generic template]\n\t\t * @param  {entry object}\tdata\n\t\t * @return {string}\tHTML string of formatted using a simple list / anchor view\n\t\t */\n\t\tgeneric: function( data ) {\n\t\t\tvar title = data.title;\n\n\t\t\tif ( typeof( title ) === \"object\" ) {\n\t\t\t\tif ( title.content ) {\n\t\t\t\t\ttitle = title.content;\n\t\t\t\t} else if ( title.type === \"xhtml\" &amp;amp;&amp;amp; title.div ) {\n\t\t\t\t\ttitle = title.div.content;\n\t\t\t\t}\n\t\t\t}\n\t\t\treturn \"\n\" + title + \"\" +\n\t\t\t\t( data.publishedDate !== \"\" ? \" \" +\n\t\t\t\twb.date.toDateISO( data.publishedDate, true ) + \"\" : \"\" ) + \"\";\n\t\t}\n\t},\n\n\t/**\n\t * Helper function that returns the string representation of a unicode character\n\t * @method decode\n\t * @param  {regex} match  unicode pattern\n\t * @param  {string} code  string where unicode is needed to be converted\n\t * @return {string}\tunicode string character\n\t */\n\tdecode = function( match, code ) {\n\t\treturn String.fromCharCode( parseInt( code, 16 ) );\n\t},\n\n\t/**\n\t * Helper wrapper function that performs unicode decodes on a string\n\t * @method fromCharCode\n\t * @param  {string} s string to sanitize with escaped unicode characters\n\t * @return {string}\tsanitized string\n\t */\n\tfromCharCode = function( s ) {\n\t\treturn s.replace( patt, decode );\n\t},\n\n\t/**\n\t * Helper function that returns a class-based set limit on plugin instances\n\t * @method getLimit\n\t * @param {DOM object} elm The element to search for a class of the form limit-5\n\t * @return {number} 0 if none found, which means the plugin default\n\t */\n\tgetLimit = function( elm ) {\n\t\tvar count = elm.className.match( /\\blimit-\\d+/ );\n\t\tif ( !count ) {\n\t\t\treturn 0;\n\t\t}\n\t\treturn Number( count[ 0 ].replace( /limit-/i, \"\" ) );\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\tfetch, url, $content, limit, feeds, fType, last, i, callback, fElem, fIcon, youtubeData, $elm;\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\t\t\t$content = $elm.find( \".feeds-cont\" );\n\t\t\tlimit = getLimit( elm );\n\t\t\tfeeds = $content.find( feedLinkSelector );\n\t\t\tlast = feeds.length - 1;\n\n\t\t\t// Lets bind some variables to the node to ensure safe ajax thread counting\n\n\t\t\t$content.data( \"toProcess\", feeds.length )\n\t\t\t\t.data( \"feedLimit\", limit )\n\t\t\t\t.data( \"entries\", [] );\n\n\t\t\tfor ( i = last; i !== -1; i -= 1 ) {\n\t\t\t\tfElem = feeds.eq( i );\n\t\t\t\tfIcon = fElem.find( \"&amp;gt; img\" );\n\n\t\t\t\tfetch = {\n\t\t\t\t\tdataType: \"jsonp\",\n\t\t\t\t\ttimeout: 10000\n\t\t\t\t};\n\n\t\t\t\tif ( fElem.attr( \"data-ajax\" ) ) {\n\n\t\t\t\t\tif ( fElem.attr( \"href\" ).indexOf( \"flickr\" ) !== -1 ) {\n\t\t\t\t\t\tfType =  \"flickr\";\n\t\t\t\t\t\tcallback = \"jsoncallback\";\n\t\t\t\t\t\t$content.data( componentName + \"-postProcess\", [ \".wb-lbx\" ] );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfType = \"generic\";\n\t\t\t\t\t\tcallback = false;\n\t\t\t\t\t\tfetch.dataType = \"json\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// We need a Gallery so lets add another plugin\n\t\t\t\t\t// #TODO: Lightbox review for more abstraction we should not have to add a wb.add() for overlaying\n\t\t\t\t\tfetch.url = fElem.attr( \"data-ajax\" );\n\t\t\t\t\tfetch.jsonp = callback;\n\t\t\t\t} else if ( fElem.attr( \"data-youtube\" ) ) {\n\t\t\t\t\tyoutubeData = wb.getData( fElem, \"youtube\" );\n\n\t\t\t\t\t$content.data( componentName + \"-postProcess\", [ \".wb-lbx\", \".wb-mltmd\" ] );\n\n\t\t\t\t\tif ( youtubeData.playlist ) {\n\t\t\t\t\t\tfElem.trigger( {\n\t\t\t\t\t\t\ttype: \"data-ready.wb-feeds\",\n\t\t\t\t\t\t\tfeedsData: youtubeData.playlist\n\t\t\t\t\t\t}, {\n\t\t\t\t\t\t\tfeedType: \"youtube\",\n\t\t\t\t\t\t\t_content: $content\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\n\t\t\t\t} else {\n\n\t\t\t\t\turl = fElem.attr( \"href\" );\n\t\t\t\t\tfetch.dataType = \"xml\";\n\t\t\t\t\tfetch.url = url;\n\n\t\t\t\t\t// Let's bind the template to the Entries\n\t\t\t\t\tif ( url.indexOf( \"pinterest.com\" ) &amp;gt; -1  ) {\n\t\t\t\t\t\tfType = \"pinterest\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\tfType = \"generic\";\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tfetch.jsonp = callback;\n\n\t\t\t\tfetch.context = {\n\t\t\t\t\tfIcon: ( fIcon.length !== 0 ) ? fIcon.attr( \"src\" ) : \"\",\n\t\t\t\t\tfeedType: fType,\n\t\t\t\t\t_content: $content\n\t\t\t\t};\n\n\t\t\t\tfElem.trigger( {\n\t\t\t\t\ttype: \"ajax-fetch.wb\",\n\t\t\t\t\tfetch: fetch\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Process Feed/JSON Entries for CORS Enabled\n\t * @method corsEntry\n\t */\n\tcorsEntry = function( xmlDoc, limit ) {\n\t\tvar entries = xmlDoc.getElementsByTagName( \"entry\" ).length,\n\t\t\tarr_entry = [],\n\t\t\tcorsObj = {},\n\t\t\tjsonString = JSON.stringify( xmlToJson( xmlDoc ) ),\n\t\t\tjsonObj = JSON.parse( jsonString ),\n\t\t\ti, iCache;\n\t\tif ( limit &amp;gt; entries || limit === 0 || limit === null ) {\n\t\t\tlimit = entries;\n\t\t}\n\t\tif ( entries === 1 ) {\n\t\t\tiCache = jsonObj.feed.entry;\n\t\t\tcorsObj = {\n\t\t\t\ttitle: iCache.title[ \"#text\" ],\n\t\t\t\tlink: ( iCache.link ? iCache.link[ \"@attributes\" ].href : iCache.id[ \"#text\" ] ),\n\t\t\t\tupdated: iCache.updated[ \"#text\" ]\n\t\t\t};\n\t\t\tarr_entry.push( corsObj );\n\t\t} else if ( entries ) {\n\t\t\tfor ( i = 0; i &amp;lt; limit; i++ ) {\n\t\t\t\tiCache = jsonObj.feed.entry[ i ];\n\t\t\t\tcorsObj = {\n\t\t\t\t\ttitle: iCache.title[ \"#text\" ],\n\t\t\t\t\tlink: ( iCache.link ? iCache.link[ \"@attributes\" ].href : iCache.id[ \"#text\" ] ),\n\t\t\t\t\tupdated: iCache.updated[ \"#text\" ]\n\t\t\t\t};\n\t\t\t\tarr_entry.push( corsObj );\n\t\t\t}\n\t\t}\n\t\treturn arr_entry;\n\t},\n\n\t/**\n\t * Process XML to JSON\n\t * @method xmlToJson\n\t * @param  {xml}\n\t */\n\txmlToJson = function( xml ) {\n\n\t\tvar obj = {},\n\t\t\ti, iCache, nodeName, old,\n\t\t\txmlAttributes, xmlChildNodes,\n\t\t\txmlNodeType = xml.nodeType;\n\n\t\tif ( xmlNodeType === 1 ) {\n\t\t\txmlAttributes = xml.attributes;\n\t\t\tif ( xmlAttributes.length ) {\n\t\t\t\tobj[ \"@attributes\" ] = {};\n\t\t\t\tfor ( i = 0; i &amp;lt; xmlAttributes.length; i++ ) {\n\t\t\t\t\tiCache = xmlAttributes.item( i );\n\t\t\t\t\tobj[ \"@attributes\" ][ iCache.nodeName ] = iCache.nodeValue;\n\t\t\t\t}\n\t\t\t}\n\t\t} else if ( xmlNodeType === 3 ) {\n\t\t\tobj = xml.nodeValue;\n\t\t}\n\n\t\tif ( xml.hasChildNodes() ) {\n\t\t\txmlChildNodes = xml.childNodes;\n\t\t\tfor ( i = 0; i &amp;lt; xmlChildNodes.length; i++ ) {\n\t\t\t\tiCache = xmlChildNodes.item( i );\n\t\t\t\tnodeName = iCache.nodeName;\n\t\t\t\tif ( typeof( obj[ nodeName ] ) === \"undefined\" ) {\n\t\t\t\t\tobj[ nodeName ] = xmlToJson( iCache );\n\t\t\t\t} else {\n\t\t\t\t\tif ( typeof( obj[ nodeName ].push ) === \"undefined\" ) {\n\t\t\t\t\t\told = obj[ nodeName ];\n\t\t\t\t\t\tobj[ nodeName ] = [];\n\t\t\t\t\t\tobj[ nodeName ].push( old );\n\t\t\t\t\t}\n\t\t\t\t\tobj[ nodeName ].push( xmlToJson( iCache ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn obj;\n\t},\n\n\t/**\n\t * Process Feed/JSON Entries\n\t * @method processEntries\n\t * @param  {data} JSON formatted data to process\n\t * @return {string} of HTML output\n\t */\n\tprocessEntries = function( data ) {\n\t\tvar items = data,\n\t\t\tentries = [],\n\t\t\ticon = this.fIcon,\n\t\t\t$content = this._content,\n\t\t\ttoProcess = $content.data( \"toProcess\" ),\n\t\t\ti, len;\n\n\t\tlen = items.length;\n\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\titems[ i ].fIcon =  icon;\n\n\t\t\tif ( items[ i ].publishedDate === undef ) {\n\t\t\t\titems[ i ].publishedDate = ( items[ i ].published || items[ i ].pubDate || items[ i ].updated || \"\" );\n\t\t\t}\n\n\t\t\tvar link = items[ i ].link;\n\n\t\t\tif ( link &amp;amp;&amp;amp; link.href ) {\n\t\t\t\titems[ i ].link = link.href;\n\t\t\t}\n\n\t\t\tentries.push( items[ i ] );\n\t\t}\n\n\t\t// lets merge with latest entries\n\t\tentries = $.merge( entries, $content.data( \"entries\" ) );\n\n\t\tif ( toProcess === 1 ) {\n\t\t\tparseEntries( entries, $content.data( \"feedLimit\" ), $content, this.feedType );\n\t\t\treturn 0;\n\t\t}\n\n\t\ttoProcess -= 1;\n\t\t$content.data( {\n\t\t\t\"toProcess\": toProcess,\n\t\t\t\"entries\": entries\n\t\t} );\n\n\t\treturn toProcess;\n\t},\n\n\t/**\n\t * Parses the results from a JSON request and appends to an element\n\t * @method parseEntries\n\t * @param {object} entries Results from a JSON request.\n\t * @param {integer} limit Limit on the number of results to append to the element.\n\t * @param {jQuery DOM element} $elm Element to which the elements will be appended.\n\t * @return {url} The URL for the JSON request\n\t */\n\tparseEntries = function( entries, limit, $elm, feedtype ) {\n\t\tvar cap = ( limit &amp;gt; 0 &amp;amp;&amp;amp; limit &amp;lt; entries.length ? limit : entries.length ),\n\t\t\tresult = \"\",\n\t\t\tcompare = wb.date.compare,\n\t\t\t$details = $elm.closest( \"details\" ),\n\t\t\tactivate = true,\n\t\t\tfeedContSelector = \".feeds-cont\",\n\t\t\thasVisibilityHandler = \"vis-handler\",\n\t\t\ti, sorted, sortedEntry, $tabs;\n\n\t\tif ( feedtype !== \"youtube\" ) {\n\t\t\tsorted = entries.sort( function( a, b ) {\n\t\t\t\treturn compare( b.publishedDate, a.publishedDate );\n\t\t\t} );\n\t\t} else {\n\t\t\tsorted = entries;\n\t\t}\n\n\t\tfor ( i = 0; i !== cap; i += 1 ) {\n\t\t\tsortedEntry = sorted[ i ];\n\t\t\tresult += Templates[ feedtype ]( sortedEntry );\n\t\t}\n\t\t$elm.data( componentName + \"-result\", result );\n\n\t\t// Check to see if feed should be activated (only if visible)\n\t\t// and add handler to determine visibility\n\t\tif ( $details.length !== 0 ) {\n\t\t\tif ( $details.attr( \"role\" ) === \"tabpanel\" ) {\n\t\t\t\tif ( $details.attr( \"aria-hidden\" ) === \"true\" ) {\n\t\t\t\t\tactivate = false;\n\t\t\t\t\t$elm.empty().addClass( \"waiting\" );\n\t\t\t\t\t$tabs = $details.closest( \".wb-tabs\" );\n\t\t\t\t\tif ( !$tabs.hasClass( hasVisibilityHandler ) ) {\n\t\t\t\t\t\t$tabs\n\t\t\t\t\t\t\t.on( \"wb-updated.wb-tabs\", function( event, $newPanel ) {\n\t\t\t\t\t\t\t\tvar $feedCont = $newPanel.find( feedContSelector );\n\t\t\t\t\t\t\t\tif ( !$feedCont.hasClass( \"feed-active\" ) ) {\n\t\t\t\t\t\t\t\t\tactivateFeed( $feedCont );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t\t.addClass( hasVisibilityHandler );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( !$details.attr( \"open\" ) ) {\n\t\t\t\tactivate = false;\n\t\t\t\t$elm.empty().addClass( \"waiting\" );\n\t\t\t\t$details\n\t\t\t\t\t.children( \"summary\" )\n\t\t\t\t\t.on( \"click.wb-feeds\", function( event ) {\n\t\t\t\t\t\tvar $summary = $( event.currentTarget ).off( \"click.wb-feeds\" );\n\t\t\t\t\t\tactivateFeed( $summary.parent().find( feedContSelector ) );\n\t\t\t\t\t} );\n\t\t\t}\n\t\t}\n\n\t\tif ( activate ) {\n\t\t\tactivateFeed( $elm );\n\t\t}\n\n\t\treturn true;\n\t},\n\n\t/**\n\t * Activates feed results view\n\t * @method activateFeed\n\t * @param = {jQuery object} $elm Feed container\n\t */\n\tactivateFeed = function( $elm ) {\n\t\tvar result = $elm.data( componentName + \"-result\" ),\n\t\t\tpostProcess = $elm.data( componentName + \"-postProcess\" ),\n\t\t\ti, postProcessSelector;\n\n\t\tif ( !result ) {\n\t\t\treturn;\n\t\t}\n\n\t\t$elm.empty()\n\t\t\t.removeClass( \"waiting\" )\n\t\t\t.addClass( \"feed-active\" )\n\t\t\t.append( result );\n\n\t\tif ( postProcess ) {\n\t\t\tfor ( i = postProcess.length - 1; i !== -1; i -= 1 ) {\n\t\t\t\tpostProcessSelector = postProcess[ i ];\n\t\t\t\t$elm.find( postProcessSelector )\n\t\t\t\t\t.trigger( \"wb-init\" + postProcessSelector );\n\t\t\t}\n\t\t}\n\n\t\t// Identify that the feed has now been displayed\n\t\t$elm.trigger( \"wb-feed-ready\" + selector );\n\t};\n\n$document.on( \"ajax-fetched.wb data-ready.wb-feeds\", selector + \" \" + feedLinkSelector, function( event, context ) {\n\tvar eventTarget = event.target,\n\t\tdata, response, responseRaw,\n\t\t$emlRss, limit, results;\n\n\t// Filter out any events triggered by descendants\n\tif ( event.currentTarget === eventTarget ) {\n\t\t$emlRss = $( eventTarget ).parentsUntil( selector ).parent();\n\t\tswitch ( event.type ) {\n\t\t\tcase \"ajax-fetched\":\n\t\t\t\tresponseRaw = event.fetch.response;\n\t\t\t\tif ( typeof responseRaw === \"string\" ) {\n\t\t\t\t\tresponse = JSON.parse( responseRaw ); // Assuming we have fetch a JSON document, try to parse it.\n\t\t\t\t} else {\n\t\t\t\t\tresponse = responseRaw.get( 0 ); // fetched an HTML or XML document which has been parsed by jQuery and sanitized by DomPurify\n\t\t\t\t}\n\t\t\t\tif ( response.documentElement ) {\n\t\t\t\t\tlimit = getLimit( $emlRss[ Object.keys( $emlRss )[ 0 ] ] );\n\t\t\t\t\tdata = corsEntry( response, limit );\n\t\t\t\t} else if ( response.query ) {\n\t\t\t\t\tresults = response.query.results;\n\t\t\t\t\tif ( !results ) {\n\t\t\t\t\t\tdata = results.item; // Flicker feeds\n\t\t\t\t\t\tif ( !Array.isArray( data ) ) {\n\t\t\t\t\t\t\tdata = [ data ];\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdata = [];\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tdata = ( response.responseData ) ? response.responseData.feed.entries : response.items || response.feed.entry;\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tdata = event.feedsData;\n\t\t}\n\n\t\t// Identify that initialization has completed\n\t\t// if there are no entries left to process\n\t\tif ( processEntries.apply( context, [ data ] ) === 0 ) {\n\t\t\twb.ready( $( eventTarget ).closest( selector ), componentName );\n\t\t}\n\t}\n} );\n\n$document.on( \"click\", selector + \" .feed-youtube\", function( event ) {\n\tvar youTubeOverlaySelector  = \"#wb-feeds-youtube-lbx\",\n\t\t$youTubeOverlay = $( youTubeOverlaySelector ),\n\t\tyoutubeData = wb.getData( event.currentTarget, \"youtube\" ),\n\t\tvideoUrl = wb.pageUrlParts.protocol + \"//www.youtube.com/watch?v=\" + youtubeData.videoId,\n\t\tvideoSource = \"\n\" +\n\t\t\t\"\" +\n\t\t\t\"\n\n\" +  youtubeData.title + \"\" +\n\t\t\t\"\";\n\n\tif ( $youTubeOverlay.length === 0 ) {\n\t\t$youTubeOverlay = $( \"\n\" +\n\t\t\t\"\n\n\" + youtubeData.title + \"\" +\n\t\t\t\"\n\" +\n\t\t\tvideoSource +\n\t\t\t\"\" ).insertAfter( \"main\" );\n\t} else {\n\n\t\t//Modify lightbox\n\t\t$youTubeOverlay.find( \".modal-title\" ).text( youtubeData.title );\n\t\t$youTubeOverlay.find( \".modal-body\" ).empty().append( videoSource );\n\t}\n\n\t//Temporary fix until lightbox auto initialize the multimedia player\n\t$youTubeOverlay.find( \".wb-mltmd\" ).trigger( \"wb-init.wb-mltmd\" );\n\n\t$( document ).trigger( \"open.wb-lbx\", [ {\n\t\tsrc: youTubeOverlaySelector,\n\t\ttype: \"inline\"\n\t} ] );\n} );\n\n$document.on( \"click\", selector + \" .feed-flickr\", function( event ) {\n\tvar flickrOverlaySelector  = \"#wb-feeds-flick-lbx\",\n\t\t$flickrOverlay = $( flickrOverlaySelector ),\n\t\tflickrData = wb.getData( event.currentTarget, \"flickr\" ),\n\t\tbody = \"\" +\n\t\t\tflickrData.description + \"\";\n\n\tif ( $flickrOverlay.length === 0 ) {\n\t\t$flickrOverlay = $( \"\n\" +\n\t\t\t\"\n\n\" + flickrData.title + \"\" +\n\t\t\t\"\n\" + body + \"\" ).insertAfter( \"main\" );\n\t} else {\n\n\t\t//Modify lightbox\n\t\t$flickrOverlay.find( \".modal-title\" ).text( flickrData.title );\n\t\t$flickrOverlay.find( \".modal-body\" ).empty().append( body );\n\t}\n\n\t$( document ).trigger( \"open.wb-lbx\", [ {\n\t\tsrc: flickrOverlaySelector,\n\t\ttype: \"inline\"\n\t} ] );\n} );\n\n// Bind the init event to the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n( function( $, window, wb ) {\n\"use strict\";\n\nvar componentName = \"wb-filter\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\tfilterClass = \"wb-fltr-out\",\n\ttagFilterClass = \"wb-tgfltr-out\",\n\tnotFilterClassSel = \":not(.\" + filterClass + \"):not(.\" + tagFilterClass + \")\",\n\tinputClass = \"wb-fltr-inpt\",\n\tdtNameFltrArea = \"wbfltrid\",\n\tselectorInput = \".\" + inputClass,\n\tdefaults = {\n\t\tstd: {\n\t\t\tselector: \"li\"\n\t\t},\n\t\tgrp: {\n\t\t\tselector: \"li\",\n\t\t\tsection: \"&amp;gt;section\"\n\t\t},\n\t\ttbl: {\n\t\t\tselector: \"tr\",\n\t\t\tsection: \"&amp;gt;tbody\"\n\t\t},\n\t\ttblgrp: {\n\t\t\tselector: \"th:not([scope])\",\n\t\t\thdnparentuntil: \"tbody\",\n\t\t\tsection: \"&amp;gt;tbody\"\n\t\t}\n\t},\n\ti18n, i18nText,\n\twait,\n\n\tinit = function( event ) {\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm, elmTagName, filterUI, prependUI,\n\t\t\tsettings, setDefault,\n\t\t\titemsObserver,\n\t\t\tinptId, totalEntries,\n\t\t\tsecSelector,\n\t\t\tuiTemplate, uiInpt, uiInfo,\n\t\t\tuiNbItems, uiTotal, uiInfoID;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\t\t\telmTagName = elm.nodeName;\n\t\t\tuiInfoID = elm.id + \"-info\";\n\n\t\t\tif ( [ \"DIV\", \"SECTION\", \"ARTICLE\" ].indexOf( elmTagName ) &amp;gt;= 0 ) {\n\t\t\t\tsetDefault = defaults.grp;\n\t\t\t\tprependUI = true;\n\t\t\t} else if ( elmTagName === \"TABLE\" ) {\n\t\t\t\tif ( $elm.find( \"tbody\" ).length &amp;gt; 1 ) {\n\t\t\t\t\tsetDefault = defaults.tblgrp;\n\t\t\t\t} else {\n\t\t\t\t\tsetDefault = defaults.tbl;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tsetDefault = defaults.std;\n\t\t\t}\n\n\t\t\tsettings = $.extend( true, {}, setDefault, window[ componentName ], wb.getData( $elm, componentName ) );\n\t\t\t$elm.data( settings );\n\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\tfilter_label: i18n( \"fltr-lbl\" ),\n\t\t\t\t\tfltr_info: i18n( \"fltr-info\" ),\n\t\t\t\t\titemsFound: i18n( \"items-found\" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif ( !elm.id ) {\n\t\t\t\telm.id = wb.getId();\n\t\t\t}\n\n\t\t\tif ( settings.uiTemplate ) {\n\t\t\t\tuiTemplate = document.querySelector( settings.uiTemplate );\n\t\t\t\tuiInpt = uiTemplate.querySelector( \"input[type=search]\" );\n\n\t\t\t\tif ( uiInpt ) {\n\t\t\t\t\tuiInfo = uiTemplate.querySelector( \".wb-fltr-info\" );\n\n\t\t\t\t\tuiInpt.classList.add( inputClass );\n\t\t\t\t\tuiInpt.setAttribute( \"data-\" + dtNameFltrArea, elm.id );\n\t\t\t\t\tuiInpt.setAttribute( \"aria-controls\", elm.id );\n\n\t\t\t\t\tif ( uiInfo ) {\n\t\t\t\t\t\tuiInfoID = uiInfo.id || uiInfoID;\n\t\t\t\t\t\tuiInfo.id = uiInfoID;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tconsole.error( componentName + \": \" + \"an  is required in your UI template.\" );\n\t\t\t\t}\n\n\t\t\t\tif ( settings.source ) {\n\t\t\t\t\tconsole.warn( componentName + \": \" + \"the 'source' option is not compatible with the 'uiTemplate' option. If both options are defined, only 'uiTemplate' will be registered.\" );\n\t\t\t\t}\n\t\t\t} else if ( !document.querySelector( \"input#\" + elm.id + \"-inpt\" ) ) {\n\t\t\t\tinptId = elm.id + \"-inpt\";\n\t\t\t\tfilterUI = $( \"\n\" +\n\t\t\t\t\t\" \" + i18nText.filter_label + \"\" +\n\t\t\t\t\t\"\" +\n\t\t\t\t\t\"\" +\n\t\t\t\t\t\"\n\" + i18nText.fltr_info + \"\" );\n\n\t\t\t\tif ( settings.source ) {\n\t\t\t\t\t$( settings.source ).prepend( filterUI );\n\t\t\t\t} else if ( prependUI ) {\n\t\t\t\t\t$elm.prepend( filterUI );\n\t\t\t\t} else {\n\t\t\t\t\t$elm.before( filterUI );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tsecSelector = ( settings.section || \"\" ) + \" \";\n\t\t\ttotalEntries = $elm.find( secSelector + settings.selector ).length;\n\t\t\tuiNbItems = document.querySelector( \"#\" + uiInfoID + \" [data-nbitem]\" );\n\t\t\tuiTotal = document.querySelector( \"#\" + uiInfoID + \" [data-total]\" );\n\n\t\t\tif ( uiNbItems ) {\n\t\t\t\tuiNbItems.textContent = totalEntries;\n\n\t\t\t\titemsObserver = new MutationObserver( function() {\n\t\t\t\t\tuiNbItems.textContent = $elm.find( secSelector + settings.selector + notFilterClassSel ).length;\n\t\t\t\t} );\n\n\t\t\t\titemsObserver.observe( elm, { attributes: true, subtree: true } );\n\t\t\t}\n\n\t\t\tif ( uiTotal ) {\n\t\t\t\tuiTotal.textContent = totalEntries;\n\t\t\t}\n\n\t\t\tvar statusMessageId = elm.id + \"-status\",\n\t\t\t\tstatusMessage = document.getElementById( statusMessageId );\n\n\t\t\t// Create a hidden status message for screen readers which is separate from the\n\t\t\t// visual status element to ensure consistent behaviour from screen readers\n\t\t\tif ( !statusMessage ) {\n\t\t\t\tstatusMessage = document.createElement( \"p\" );\n\t\t\t\tstatusMessage.id = statusMessageId;\n\t\t\t\tstatusMessage.className = \"wb-inv\";\n\t\t\t\tstatusMessage.setAttribute( \"role\", \"status\" );\n\t\t\t\t$elm.prepend( statusMessage );\n\t\t\t}\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t},\n\n\t/*\n\t * Takes in the text from the filter box\n\t * Returns:\n\t *  An array of search words\n\t *      Special characters are escaped\n\t *      Double and single quotes removed\n\t */\n\tfilterQueryParser = function( filter ) {\n\n\t\t// Pattern to separate the filter text into \"words\"\n\t\tvar pattern = /[^\\s\"]+|\"([^\"]*)\"/gi;\n\n\t\t// Make strings safe again for regex\n\t\t// Source: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Regular_Expressions\n\t\tfilter = filter.replace( /[.*+?^${}()|[\\]\\\\]/g, \"\\\\$&amp;amp;\" );\n\n\t\t// Apply the word match pattern and return\n\t\treturn filter.match( pattern );\n\t},\n\n\t/**\n\t * Build the Regular Expression that we are going\n\t * to use to filter content\n\t * This involves identifying the type of search being\n\t * applied and then breaking up the search string into\n\t * words\n\t */\n\tbuildSearchFilterRegularExp =  function( filterType, filter ) {\n\n\t\tvar words, wordRegExFilter = filter,\n\t\t\ti, i_len;\n\n\t\tswitch ( filterType ) {\n\n\t\t\tcase \"and\":\n\t\t\t\twords = filterQueryParser( filter );\n\t\t\t\tif ( words ) {\n\t\t\t\t\twordRegExFilter = \".*\";\n\t\t\t\t\ti_len = words.length;\n\t\t\t\t\tfor ( i = 0; i &amp;lt; i_len; i++ ) {\n\t\t\t\t\t\twordRegExFilter = wordRegExFilter + ( \"(?=.*\" + words[ i ] + \")\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase \"or\": // If one word fall back on default\n\t\t\t\twords = filterQueryParser( filter );\n\t\t\t\tif ( words ) {\n\t\t\t\t\twordRegExFilter =  words.join( \"|\" );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\tbreak;\n\n\t\t}\n\n\t\treturn new RegExp( wordRegExFilter, \"i\" );\n\n\t},\n\n\tfilter = function( $field, $elm, settings ) {\n\t\tvar unAccent = function( str ) {\n\t\t\t\treturn str.normalize( \"NFD\" ).replace( /[\\u0300-\\u036f]/g, \"\" );\n\t\t\t},\n\t\t\tfilter = unAccent( $field.val().trim() ),\n\t\t\tfCallBack = settings.filterCallback,\n\t\t\tsecSelector = ( settings.section || \"\" )  + \" \",\n\t\t\thdnParentSelector = settings.hdnparentuntil,\n\t\t\t$items = $elm.find( secSelector + settings.selector ),\n\t\t\titemsLength = $items.length,\n\t\t\ti, $item, text, searchFilterRegularExp;\n\n\t\t$elm.find( \".\" + filterClass ).removeClass( filterClass );\n\n\t\tsearchFilterRegularExp = buildSearchFilterRegularExp( settings.filterType, filter );\n\n\t\tfor ( i = 0; i &amp;lt; itemsLength; i += 1 ) {\n\t\t\t$item = $items.eq( i );\n\n\t\t\t// Get the text content of the item, either from the shadow DOM or directly\n\t\t\tif ( $item[ 0 ].shadowRoot ) {\n\t\t\t\ttext = unAccent( $item[ 0 ].shadowRoot.textContent );\n\t\t\t} else {\n\t\t\t\ttext = unAccent( $item.text() );\n\t\t\t}\n\n\t\t\tif ( !searchFilterRegularExp.test( text ) ) {\n\t\t\t\tif ( hdnParentSelector ) {\n\t\t\t\t\t$item.parentsUntil( hdnParentSelector ).addClass( filterClass );\n\t\t\t\t}\n\t\t\t\t$item.addClass( filterClass );\n\t\t\t}\n\t\t}\n\n\t\tif ( !fCallBack || typeof fCallBack !== \"function\"  ) {\n\t\t\tfCallBack = filterCallback;\n\t\t}\n\t\tfCallBack.apply( this, arguments );\n\n\t\t$elm.trigger( \"wb-filtered\" );\n\t},\n\n\tfilterCallback = function( $field, $elm, settings ) {\n\t\tvar $sections =\t$elm.find( settings.section ),\n\t\t\tsectionsLength = $sections.length,\n\t\t\tfndSelector = settings.selector + notFilterClassSel,\n\t\t\ts, $section;\n\n\t\tfor ( s = 0; s &amp;lt; sectionsLength; s += 1 ) {\n\t\t\t$section = $sections.eq( s );\n\t\t\tif ( $section.find( fndSelector ).length === 0 ) {\n\t\t\t\t$section.addClass( filterClass );\n\t\t\t}\n\t\t}\n\n\t\tvar sectionSelector = settings.section || \"\",\n\t\t\tstatusMessage = document.getElementById( $elm.attr( \"id\" ) + \"-status\" );\n\n\t\t// Build the status message using a string to avoid inconsistencies across different screen readers when reading content from dynamic markup\n\t\tif ( statusMessage ) {\n\t\t\tvar cleanSelector = settings.selector.replace( notFilterClassSel, \"\" ),\n\t\t\t\ttotalItems = $elm.find( sectionSelector + \" \" + cleanSelector ).length,\n\t\t\t\tfoundItems = $elm.find( sectionSelector + \" \" + settings.selector + notFilterClassSel ).length;\n\n\t\t\tsetTimeout( function() {\n\t\t\t\tstatusMessage.textContent = foundItems + \" \" + i18nText.itemsFound + \" \" + totalItems;\n\t\t\t}, 900 );\n\t\t}\n\t};\n\n$document.on( \"keyup\", selectorInput, function( event ) {\n\tvar target = event.target,\n\t\t$input = $( target ),\n\t\t$elm = $( \"#\" + $input.data( dtNameFltrArea ) );\n\n\tif ( wait ) {\n\t\tclearTimeout( wait );\n\t}\n\n\twait = setTimeout( filter.bind( this, $input, $elm, $elm.data() ), 250 );\n} );\n\n// Reinitialize filter if content on the page has been updated by another plugin\n$document.on( \"wb-contentupdated\", selector + \", \" + selector + \" *\", function()  {\n\tlet that = this;\n\n\tif ( wait ) {\n\t\tclearTimeout( wait );\n\t}\n\n\twait = setTimeout( function() {\n\t\tthat.classList.remove( \"wb-init\", componentName + \"-inited\" );\n\t\t$( that ).trigger( \"wb-init.\" + componentName );\n\t}, 100 );\n} );\n\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\nwb.add( selector );\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Footnotes\n * @overview Provides a consistent, accessible way of handling footnotes across websites.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @EricDunsworth\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-fnote\",\n\tselector = \".\" + componentName,\n\tmodFlag = \"data-\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tsetFocusEvent = \"setfocus.wb\",\n\t$document = wb.doc,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm, footnoteDd, footnoteDt, i, len, dd, dt;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\t\t\tfootnoteDd = elm.getElementsByTagName( \"dd\" );\n\t\t\tfootnoteDt = elm.getElementsByTagName( \"dt\" );\n\n\t\t\t// Set initial event handlers for return to referrer links\n\t\t\tlen = footnoteDd.length;\n\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\tdd = footnoteDd[ i ];\n\t\t\t\tdt = footnoteDt[ i ];\n\t\t\t\tdd.setAttribute( \"tabindex\", \"-1\" );\n\t\t\t\tdt.id = dd.id + \"-dt\";\n\t\t\t}\n\n\t\t\t// Remove \"first/premier/etc\"-style text from certain footnote return links (via the child spans that hold those bits of text)\n\t\t\t$elm.find( \"dd p.fn-rtn a span span\" ).remove();\n\n\t\t\t// Listen for footnote reference links that get clicked\n\t\t\t$document.on( \"click\", \"main :not(\" + selector + \") sup a.fn-lnk\", function( event ) {\n\t\t\t\tvar eventTarget = event.target,\n\t\t\t\t\twhich = event.which,\n\t\t\t\t\trefId, $refLinkDest;\n\n\t\t\t\t// Ignore middle/right mouse button\n\t\t\t\tif ( !which || which === 1 ) {\n\t\t\t\t\trefId = \"#\" + wb.jqEscape( eventTarget.getAttribute( \"href\" ).substring( 1 ) );\n\t\t\t\t\t$refLinkDest = $document.find( refId );\n\n\t\t\t\t\t$refLinkDest.find( \"p.fn-rtn a\" )\n\t\t\t\t\t\t.attr( \"href\", \"#\" + eventTarget.parentNode.id )\n\t\t\t\t\t\t.attr( modFlag, true );\n\n\t\t\t\t\t// Assign focus to $refLinkDest\n\t\t\t\t\t$refLinkDest.trigger( setFocusEvent );\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// Listen for footnote return links that get clicked\n\t\t\t$document.on( \"click\", selector + \" dd p.fn-rtn a\", function( event ) {\n\t\t\t\tvar which = event.which,\n\t\t\t\t\t$elmTarget = $( event.target ),\n\t\t\t\t\tref,\n\t\t\t\t\trefId,\n\t\t\t\t\trefIdSrc,\n\t\t\t\t\trefIdDashIdx,\n\t\t\t\t\tsearchRefId;\n\n\t\t\t\t// Ignore middle/right mouse button\n\t\t\t\tif ( !which || which === 1 ) {\n\t\t\t\t\tref = $elmTarget.attr( \"href\" );\n\n\t\t\t\t\t// Focus on associated referrer link (if the return link points to an ID)\n\t\t\t\t\tif ( ref.charAt( 0 ) === \"#\" ) {\n\t\t\t\t\t\trefId = wb.jqEscape( ref.substring( 1 ) );\n\n\t\t\t\t\t\t// When first clicked, ensure we send the user on the first instance when the id follow the recommend pattern\n\t\t\t\t\t\trefIdDashIdx = refId.indexOf( \"-\" );\n\t\t\t\t\t\tif ( refIdDashIdx !== -1 &amp;amp;&amp;amp; !$elmTarget.attr( modFlag ) ) {\n\t\t\t\t\t\t\tsearchRefId = refId.substring( 0, refIdDashIdx + 1 );\n\t\t\t\t\t\t\trefIdSrc = wb.jqEscape( $( \"sup[id^='\" + searchRefId + \"']:first()\" ).attr( \"id\" ) );\n\t\t\t\t\t\t\tif ( !refIdSrc || refId !== refIdSrc ) {\n\t\t\t\t\t\t\t\tconsole.warn( componentName + \" - Relink first reference of \" + ref + \" for #\" + refIdSrc );\n\t\t\t\t\t\t\t\trefId = refIdSrc;\n\t\t\t\t\t\t\t\t$elmTarget\n\t\t\t\t\t\t\t\t\t.attr( \"href\", \"#\" + refId )\n\t\t\t\t\t\t\t\t\t.attr( modFlag, true );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Assign focus to the link\n\t\t\t\t\t\t$document.find( \"#\" + refId + \" a\" ).trigger( setFocusEvent );\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Form validation\n * @overview Provides generic validation and error message handling for Web forms.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @pjackson28\n */\n( function( $, window, document, wb ) {\n\"use strict\";\n\n/*\n* Variable and function definitions.\n* These are global to the plugin - meaning that they will be initialized once per page,\n* not once per instance of plugin on the page. So, this is a good place to define\n* variables that are common to all instances of the plugin on a page.\n*/\nvar componentName = \"wb-frmvld\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tsetFocusEvent = \"setfocus.wb\",\n\t$document = wb.doc,\n\tidCount = 0,\n\ti18n, i18nText,\n\n\tdefaults = {\n\t\thdLvl: \"h2\",\n\t\tignore: \":hidden\"\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar eventTarget = wb.init( event, componentName, selector ),\n\t\t\telmId, modeJS;\n\n\t\tif ( eventTarget ) {\n\t\t\telmId = eventTarget.id;\n\n\t\t\t// Ensure there is a unique id on the element\n\t\t\tif ( !elmId ) {\n\t\t\t\telmId = componentName + \"-id-\" + idCount;\n\t\t\t\tidCount += 1;\n\t\t\t\teventTarget.id = elmId;\n\t\t\t}\n\n\t\t\t// Read the selector node for parameters\n\t\t\tmodeJS = wb.getMode() + \".js\";\n\n\t\t\t// Only initialize the i18nText once\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\tcolon: i18n( \"colon\" ),\n\t\t\t\t\thyphen: i18n( \"hyphen\" ),\n\t\t\t\t\terror: i18n( \"err\" ),\n\t\t\t\t\terrorFound: i18n( \"err-fnd\" ),\n\t\t\t\t\terrorsFound: i18n( \"errs-fnd\" ),\n\t\t\t\t\tformNotSubmitted: i18n( \"frm-nosubmit\" ),\n\t\t\t\t\terrorCorrect: i18n( \"err-correct\" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tModernizr.load( {\n\t\t\t\tload: [ \"site!deps/jquery.validate\" + modeJS ],\n\t\t\t\ttestReady: function() {\n\t\t\t\t\treturn ( $.validator );\n\t\t\t\t},\n\t\t\t\tcomplete: function() {\n\t\t\t\t\tModernizr.load( {\n\n\t\t\t\t\t\t// For loading multiple dependencies\n\t\t\t\t\t\tload: [ \"site!deps/additional-methods\" + modeJS ],\n\t\t\t\t\t\ttestReady: function() {\n\t\t\t\t\t\t\treturn ( $.validator.methods.bic );\n\t\t\t\t\t\t},\n\t\t\t\t\t\tcomplete: function() {\n\t\t\t\t\t\t\tvar $elm = $( \"#\" + elmId ),\n\t\t\t\t\t\t\t\t$form = $elm.find( \"form\" ),\n\t\t\t\t\t\t\t\tformDOM = $form.get( 0 ),\n\t\t\t\t\t\t\t\tformId = $form.attr( \"id\" ),\n\t\t\t\t\t\t\t\tlabels = formDOM.getElementsByTagName( \"label\" ),\n\t\t\t\t\t\t\t\tsubmitted = false,\n\t\t\t\t\t\t\t\tshowSummary = false,\n\t\t\t\t\t\t\t\terrorFormId = \"errors-\" + ( !formId ? \"default\" : formId ),\n\t\t\t\t\t\t\t\tsettings = $.extend(\n\t\t\t\t\t\t\t\t\ttrue,\n\t\t\t\t\t\t\t\t\t{},\n\t\t\t\t\t\t\t\t\tdefaults,\n\t\t\t\t\t\t\t\t\twindow[ componentName ],\n\t\t\t\t\t\t\t\t\twb.getData( $elm, componentName )\n\t\t\t\t\t\t\t\t),\n\t\t\t\t\t\t\t\tsummaryHeading = settings.hdLvl,\n\t\t\t\t\t\t\t\ti, len, validator;\n\n\t\t\t\t\t\t\tif ( wb.lang === \"fr\" ) {\n\n\t\t\t\t\t\t\t\t// alphanumeric regex is changed to allow french characters;\n\t\t\t\t\t\t\t\t$.validator.addMethod( \"alphanumeric\", function( value, element ) {\n\t\t\t\t\t\t\t\t\treturn this.optional( element ) || /^[a-z\u00e0\u00e2\u00e7\u00e9\u00e8\u00ea\u00eb\u00ee\u00ef\u00f4\u00fb\u00f9\u00fc\u00ff\u00e6\u01530-9_]+$/i.test( value );\n\t\t\t\t\t\t\t\t}, \"Letters, numbers, and underscores only please.\" );\n\n\t\t\t\t\t\t\t\t// error french text is adjusted to remove the word \"spaces\"\n\t\t\t\t\t\t\t\t$.extend( $.validator.messages, {\n\t\t\t\t\t\t\t\t\talphanumeric: \"Veuillez fournir seulement des lettres, nombres et soulignages.\"\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Append the aria-live region (for provide message updates to screen readers)\n\t\t\t\t\t\t\t$elm.append( \"\n\" );\n\n\t\t\t\t\t\t\t// Add space to the end of the labels (so separation between label and error when CSS turned off)\n\t\t\t\t\t\t\tlen = labels.length;\n\t\t\t\t\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t\t\t\t\tlabels[ i ].insertAdjacentHTML( \"beforeend\", \" \" );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Hide \"required\" label text in older forms from screen readers\n\t\t\t\t\t\t\t// Prevents redundant \"required\" announcements on semantically-required fields whose labels mention they're required\n\t\t\t\t\t\t\t$form.find( \"strong.required:not([aria-hidden='true'])\" ).each( function() {\n\t\t\t\t\t\t\t\tconst $requiredText = $( this ),\n\t\t\t\t\t\t\t\t\t$label = $requiredText.closest( \"label\" ),\n\t\t\t\t\t\t\t\t\tfieldId = $label.attr( \"for\" );\n\t\t\t\t\t\t\t\tlet $field = fieldId ? $( \"#\" + fieldId ) : $label.find( \":input\" ).first();\n\n\t\t\t\t\t\t\t\t// If the label's field has yet to be found, look for fields that refer to the label via aria-labelledby\n\t\t\t\t\t\t\t\tif ( !$field.length ) {\n\t\t\t\t\t\t\t\t\tconst labelId = $label.attr( \"id\" ) || $requiredText.closest( \"id\" );\n\t\t\t\t\t\t\t\t\t$field = $form.find( \"[aria-labelledby~='\" + labelId + \"']:input\" ).first();\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t// Hide the \"required\" text if its field is semantically-required\n\t\t\t\t\t\t\t\tif ( $field.is( \"[required], [aria-required='true']\" ) ) {\n\t\t\t\t\t\t\t\t\t$requiredText.attr( \"aria-hidden\", \"true\" );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\t// Override the default jQuery validation method for Canadian postal codes to allow for trailing/leading whitespace\n\t\t\t\t\t\t\t$.validator.addMethod( \"postalCodeCA\", function( value, element ) {\n\t\t\t\t\t\t\t\tvar trimmed = value.replace( /\\u00a0/g, \" \" ).trim();\n\t\t\t\t\t\t\t\treturn this.optional( element ) || /^[ABCEGHJKLMNPRSTVXY]\\d[ABCEGHJKLMNPRSTVWXYZ] *\\d[ABCEGHJKLMNPRSTVWXYZ]\\d$/i.test( trimmed );\n\t\t\t\t\t\t\t}, \"Please specify a valid Canadian postal code.\" );\n\n\t\t\t\t\t\t\t// The jQuery validation plug-in in action\n\t\t\t\t\t\t\tvalidator = $form.validate( {\n\t\t\t\t\t\t\t\tmeta: \"validate\",\n\t\t\t\t\t\t\t\tfocusInvalid: false,\n\t\t\t\t\t\t\t\tignore: settings.ignore,\n\n\t\t\t\t\t\t\t\t// Set the element which will wrap the inline error messages\n\t\t\t\t\t\t\t\terrorElement: \"strong\",\n\n\t\t\t\t\t\t\t\t// Location for the inline error messages\n\t\t\t\t\t\t\t\t// In this case we will place them in the associated label element\n\t\t\t\t\t\t\t\terrorPlacement: function( $error, $element ) {\n\t\t\t\t\t\t\t\t\tvar type = $element.attr( \"type\" ),\n\t\t\t\t\t\t\t\t\t\tgroup = $element.attr( \"data-rule-require_from_group\" ),\n\t\t\t\t\t\t\t\t\t\t$fieldset, $legend;\n\n\t\t\t\t\t\t\t\t\t$error.data( \"element-id\", $element.attr( \"id\" ) );\n\t\t\t\t\t\t\t\t\tif ( type ) {\n\t\t\t\t\t\t\t\t\t\ttype = type.toLowerCase();\n\t\t\t\t\t\t\t\t\t\tif ( type === \"radio\" || type === \"checkbox\" ) {\n\t\t\t\t\t\t\t\t\t\t\t$fieldset = $element.closest( \"fieldset\" );\n\t\t\t\t\t\t\t\t\t\t\tif ( $fieldset.length !== 0 ) {\n\t\t\t\t\t\t\t\t\t\t\t\t$legend = $fieldset.find( \"legend\" ).first();\n\t\t\t\t\t\t\t\t\t\t\t\tif ( $legend.length !== 0 &amp;amp;&amp;amp; $fieldset.find( \"input[name='\" + $element.attr( \"name\" ) + \"']\" ) !== 1 ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$error.appendTo( $legend );\n\t\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\tif ( group ) {\n\t\t\t\t\t\t\t\t\t\t$fieldset = $element.closest( \"fieldset\" );\n\t\t\t\t\t\t\t\t\t\tif ( $fieldset.length !== 0 ) {\n\t\t\t\t\t\t\t\t\t\t\t$legend = $fieldset.find( \"legend\" ).first();\n\t\t\t\t\t\t\t\t\t\t\tif ( $legend.length !== 0 &amp;amp;&amp;amp; $fieldset.find( \"input[name='\" + $element.attr( \"name\" ) + \"']\" ) !== 1 ) {\n\t\t\t\t\t\t\t\t\t\t\t\tvar $strong = $legend.find( \"strong.error\" ),\n\t\t\t\t\t\t\t\t\t\t\t\t\tid = $legend.attr( \"id\" );\n\n\t\t\t\t\t\t\t\t\t\t\t\tif ( $strong.length &amp;gt; 0 ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$strong.remove();\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\tif ( !id ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tid = \"required-group-\" + idCount;\n\t\t\t\t\t\t\t\t\t\t\t\t\tidCount += 1;\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t$legend.attr( \"id\", id );\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t$error.data( \"element-id\", id );\n\t\t\t\t\t\t\t\t\t\t\t\t$error.attr( \"id\", id );\n\t\t\t\t\t\t\t\t\t\t\t\t$error.appendTo( $legend );\n\n\t\t\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t//Std If we have a label and the input field is inside the label\n\t\t\t\t\t\t\t\t\t// need to add a css-implicite-input\n\t\t\t\t\t\t\t\t\tif ( $form.find( \"label\" ).find( \".wb-server-error + input.css-implicite-input[name='\" + $element.attr( \"name\" ) + \"']\" ).length &amp;gt; 0 ) {\n\t\t\t\t\t\t\t\t\t\t$error.insertBefore( $form.find( \".wb-server-error + input.css-implicite-input[name='\" + $element.attr( \"name\" ) + \"']\" ) );\n\t\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t$error.appendTo( $form.find( \"label[for='\" + $element.attr( \"id\" ) + \"']\" ) );\n\t\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t// Create our error summary that will appear before the form\n\t\t\t\t\t\t\t\tshowErrors: function( errorMap ) {\n\t\t\t\t\t\t\t\t\tthis.defaultShowErrors();\n\t\t\t\t\t\t\t\t\tvar $errors = $form.find( \".wb-server-error, strong.error\" ).filter( \":not(:hidden)\" ),\n\t\t\t\t\t\t\t\t\t\t$errorfields = $form.find( \"input.error, select.error, textarea.error\" ),\n\t\t\t\t\t\t\t\t\t\tprefixStart = \"\" + i18nText.error + \"&amp;#160;\",\n\t\t\t\t\t\t\t\t\t\tprefixEnd = i18nText.colon + \" \",\n\t\t\t\t\t\t\t\t\t\tseparator = i18nText.hyphen,\n\t\t\t\t\t\t\t\t\t\tariaLive = $form.closest( \".wb-frmvld\" ).find( \".arialive\" )[ 0 ],\n\t\t\t\t\t\t\t\t\t\t$summaryContainer, summary, key, i, len, $error, prefix, $fieldName, $fieldset, label, labelString, el;\n\n\t\t\t\t\t\t\t\t\t// Correct the colouring of fields that are no longer invalid\n\t\t\t\t\t\t\t\t\t$form\n\t\t\t\t\t\t\t\t\t\t.find( \".has-error [aria-invalid=false]\" )\n\t\t\t\t\t\t\t\t\t\t.closest( \".has-error\" )\n\t\t\t\t\t\t\t\t\t\t.removeClass( \"has-error\" );\n\n\t\t\t\t\t\t\t\t\tif ( $errors.length !== 0 ) {\n\n\t\t\t\t\t\t\t\t\t\t// Post process\n\t\t\t\t\t\t\t\t\t\tsummary = \"&amp;lt;\" + summaryHeading + \"&amp;gt;\" +\n\t\t\t\t\t\t\t\t\t\t\ti18nText.formNotSubmitted + $errors.length +\n\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t$errors.length !== 1 ?\n\t\t\t\t\t\t\t\t\t\t\t\t\ti18nText.errorsFound :\n\t\t\t\t\t\t\t\t\t\t\t\t\ti18nText.errorFound\n\t\t\t\t\t\t\t\t\t\t\t) + \"&amp;lt;/\" + summaryHeading + \"&amp;gt;\n\";\n\t\t\t\t\t\t\t\t\t\t$errorfields\n\t\t\t\t\t\t\t\t\t\t\t.closest( \".form-group\" )\n\t\t\t\t\t\t\t\t\t\t\t.addClass( \"has-error\" );\n\t\t\t\t\t\t\t\t\t\tlen = $errors.length;\n\t\t\t\t\t\t\t\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t\t\t\t\t\t\t\t$error = $errors.eq( i );\n\t\t\t\t\t\t\t\t\t\t\tprefix = prefixStart + ( i + 1 ) + prefixEnd;\n\t\t\t\t\t\t\t\t\t\t\t$fieldName = $error.closest( \"label\" ).find( \".field-name\" );\n\n\t\t\t\t\t\t\t\t\t\t\t// Try to find the field name in the legend (if one exists)\n\t\t\t\t\t\t\t\t\t\t\tif ( $fieldName.length === 0 ) {\n\t\t\t\t\t\t\t\t\t\t\t\t$fieldset = $error.closest( \"fieldset\" );\n\t\t\t\t\t\t\t\t\t\t\t\tif ( $fieldset.length !== 0 ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$fieldName = $fieldset.find( \"legend .field-name\" );\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t$error.find( \"span.prefix\" ).detach();\n\n\t\t\t\t\t\t\t\t\t\t\t//Verify if it is a wb-server-error\n\t\t\t\t\t\t\t\t\t\t\tif ( $errors[ i ].classList.contains( \"wb-server-error\" ) ) {\n\t\t\t\t\t\t\t\t\t\t\t\tif ( $errors[ i ].id ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar myParent = document.getElementById( $errors[ i ].id ).parentElement;\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( myParent === null ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tsummary += \"\n\" + prefix + ( $fieldName.length !== 0 ? $fieldName.html() + separator : \"\" ) + $error.text() + separator + i18nText.errorCorrect + \"\";\n\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( myParent.hasAttribute( \"for\" ) &amp;amp;&amp;amp; myParent.getAttribute( \"for\" ).length &amp;gt; 0 ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsummary += \"\n\" + prefix + ( $fieldName.length !== 0 ? $fieldName.html() + separator : \"\" ) + $error.text() + separator + i18nText.errorCorrect + \"\";\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( myParent.getElementsByTagName( \"input\" )[ 0 ] &amp;amp;&amp;amp; myParent.getElementsByTagName( \"input\" )[ 0 ].name.length &amp;gt; 0 ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsummary += \"\n\" + prefix + ( $fieldName.length !== 0 ? $fieldName.html() + separator : \"\" ) + $error.text() + separator + i18nText.errorCorrect + \"\";\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( myParent.tagName === ( \"LEGEND\" ) &amp;amp;&amp;amp; ( myParent.parentElement.getElementsByTagName( \"input\" )[ 0 ].type === \"checkbox\" || myParent.parentElement.getElementsByTagName( \"input\" )[ 0 ].type === \"radio\" &amp;amp;&amp;amp; myParent.parentElement.getElementsByTagName( \"input\" )[ 0 ].name.length &amp;gt; 0 ) ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsummary += \"\n\" + prefix + ( $fieldName.length !== 0 ? $fieldName.html() + separator : \"\" ) + $error.text() + separator + i18nText.errorCorrect + \"\";\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tsummary += \"\n\" + prefix + ( $fieldName.length !== 0 ? $fieldName.html() + separator : \"\" ) + $error.text() + separator + i18nText.errorCorrect + \"\";\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t$error.html( \"\" + prefix + $error.text() + \"\" );\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t//Force display of summary if wb-server-error present.\n\t\t\t\t\t\t\t\t\t\t\t\tshowSummary = true;\n\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\tsummary += \"\n\" + prefix + ( $fieldName.length !== 0 ? $fieldName.html() + separator : \"\" ) + $error.text() + \"\";\n\t\t\t\t\t\t\t\t\t\t\t\t$error.html( \"\" + prefix + $error.text() + \"\" );\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tsummary += \"\";\n\n\t\t\t\t\t\t\t\t\t\tif ( !submitted ) {\n\n\t\t\t\t\t\t\t\t\t\t\t// Update the aria-live region as necessary\n\t\t\t\t\t\t\t\t\t\t\ti = 0;\n\t\t\t\t\t\t\t\t\t\t\tfor ( key in errorMap ) {\n\t\t\t\t\t\t\t\t\t\t\t\tif ( Object.prototype.hasOwnProperty.call( errorMap, key ) ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\ti += 1;\n\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\tif ( i !== 0 ) {\n\t\t\t\t\t\t\t\t\t\t\t\tlen = $errors.length;\n\t\t\t\t\t\t\t\t\t\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\tlabel = $errors[ i ].parentNode;\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( label.getAttribute( \"for\" ) === key ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tel = document.getElementById( key );\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( el.matches( \":focus\" ) ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tariaLive.innerHTML = \"\";\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tlabelString = label.innerHTML;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tif ( labelString !== ariaLive.innerHTML ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tariaLive.innerHTML = labelString;\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t} else if ( ariaLive.innerHTML.length !== 0 ) {\n\t\t\t\t\t\t\t\t\t\t\t\tariaLive.innerHTML = \"\";\n\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\tif ( showSummary ) {\n\n\t\t\t\t\t\t\t\t\t\t\t// Delay updating the summary container in case a summary link was clicked\n\t\t\t\t\t\t\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\t\t\t\t\t\t\t$summaryContainer = $form.find( \"#\" + errorFormId );\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Output our error summary and place it in the error container\n\t\t\t\t\t\t\t\t\t\t\t\t// Create our container if one doesn't already exist\n\t\t\t\t\t\t\t\t\t\t\t\tif ( $summaryContainer.length === 0 ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t$summaryContainer = $( \"\n\" + summary + \"\" ).prependTo( $form );\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t// Replace current error summary content only if it is different\n\t\t\t\t\t\t\t\t\t\t\t\t\t// from the incoming error summary content\n\t\t\t\t\t\t\t\t\t\t\t\t} else if ( $summaryContainer.html() !== summary.replace( /'/g, \"\\\"\" ).replace( /&amp;#160;/g, \"&amp;nbsp;\" ) ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t// if the summary container is currently focused then\n\t\t\t\t\t\t\t\t\t\t\t\t\t// we will focus the last element in the summary\n\t\t\t\t\t\t\t\t\t\t\t\t\t// since we recreate the error list on blur/change\n\t\t\t\t\t\t\t\t\t\t\t\t\tvar $isFocused = $summaryContainer.find( \"a\" ).is( \":focus\" );\n\t\t\t\t\t\t\t\t\t\t\t\t\t$summaryContainer.empty().append( summary );\n\t\t\t\t\t\t\t\t\t\t\t\t\tif ( $isFocused ) {\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t$summaryContainer.find( \"a\" ).last().trigger( \"focus\" );\n\t\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t\t\t\t// Put focus on the error if the errors are generated by an attempted form submission\n\t\t\t\t\t\t\t\t\t\t\t\tif ( submitted ) {\n\n\t\t\t\t\t\t\t\t\t\t\t\t\t// Assign focus to $summaryContainer\n\t\t\t\t\t\t\t\t\t\t\t\t\t$summaryContainer.trigger( setFocusEvent );\n\t\t\t\t\t\t\t\t\t\t\t\t\tsubmitted = false;\n\t\t\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t\t}, 100 );\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t\t\t// Update the aria-live region as necessary\n\t\t\t\t\t\t\t\t\t\tif ( ariaLive.innerHTML.length !== 0 ) {\n\t\t\t\t\t\t\t\t\t\t\tariaLive.innerHTML = \"\";\n\t\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t\t\t$form.find( \"#\" + errorFormId ).detach();\n\t\t\t\t\t\t\t\t\t\tshowSummary = false;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t},\n\n\t\t\t\t\t\t\t\t/* End of showErrors() */\n\n\t\t\t\t\t\t\t\tinvalidHandler: function() {\n\t\t\t\t\t\t\t\t\tsubmitted = true;\n\t\t\t\t\t\t\t\t\tshowSummary = true;\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t} ); /* end of validate() */\n\n\t\t\t\t\t\t\t/* fixes validation issue (see PR #7913) */\n\t\t\t\t\t\t\t$form.on( \"change\", \"input[type=date], input[type=file], select\", function() {\n\t\t\t\t\t\t\t\t$form.validate().element( this );\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\t// Clear the form and remove error messages on reset\n\t\t\t\t\t\t\t$document.on( \"click\", selector + \" input[type=reset]\", function( event ) {\n\t\t\t\t\t\t\t\tvar which = event.which,\n\t\t\t\t\t\t\t\t\tariaLive;\n\n\t\t\t\t\t\t\t\t// Ignore middle/right mouse buttons\n\t\t\t\t\t\t\t\tif ( !which || which === 1 ) {\n\t\t\t\t\t\t\t\t\tvalidator.resetForm();\n\t\t\t\t\t\t\t\t\t$( \"#\" + errorFormId ).detach();\n\n\t\t\t\t\t\t\t\t\tariaLive = $form.closest( \".wb-frmvld\" ).find( \".arialive\" )[ 0 ];\n\t\t\t\t\t\t\t\t\tif ( ariaLive.innerHTML.length !== 0 ) {\n\t\t\t\t\t\t\t\t\t\tariaLive.innerHTML = \"\";\n\t\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\t\t// Correct the colouring of fields that are no longer invalid\n\t\t\t\t\t\t\t\t\t$form.find( \".has-error\" ).removeClass( \"has-error\" );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\t//Trigger validation on wb-server-error\n\t\t\t\t\t\t\t$form.find( \".wb-server-error\" ).filter( \":not( :hidden )\" ).parent().each( function() {\n\t\t\t\t\t\t\t\tif ( this.attributes.for &amp;amp;&amp;amp; this.attributes.for.value.length &amp;gt; 0 ) {\n\t\t\t\t\t\t\t\t\t$form.validate().element( $( \"[id =\" + this.attributes.for.value + \"]\" ) );\n\t\t\t\t\t\t\t\t} else if ( $( this ).find( \"input\" )[ 0 ] ) {\n\t\t\t\t\t\t\t\t\t$form.validate().element( $( this ).find( \"input\" )[ 0 ] );\n\t\t\t\t\t\t\t\t} else if ( $( this ).next( \".radio, .checkbox\" ).children( \"label\" ).children( \"input\" )[ 0 ] ) {\n\t\t\t\t\t\t\t\t\tif ( $( this ).find( $( this ).next( \".radio, .checkbox\" ).children( \"label\" ).children( \"input\" )[ 0 ].id ) ) {\n\t\t\t\t\t\t\t\t\t\t$form.validate().element( $( this ).next( \".radio, .checkbox\" ).children( \"label\" ).children( \"input\" )[ 0 ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} else if ( $( this ).next( \".radio-inline, .checkbox-inline, .label-inline\" ).children( \"input\" )[ 0 ] ) {\n\t\t\t\t\t\t\t\t\tif ( $( this ).find( $( this ).next( \".radio-inline, .checkbox-inline, .label-inline\" ).children( \"input\" )[ 0 ].id ) ) {\n\t\t\t\t\t\t\t\t\t\t$form.validate().element( $( this ).next( \".radio-inline, .checkbox-inline, .label-inline\" ).children( \"input\" )[ 0 ] );\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\t// Tell the i18n file to execute to run any $.validator extends\n\t\t\t\t\t\t\t$form.trigger( \"formLanguages.wb\" );\n\n\t\t\t\t\t\t\t// Identify that initialization has completed\n\t\t\t\t\t\t\twb.ready( $( eventTarget ), componentName );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, document, wb );\n\n/*\n * @title WET-BOEW Geomap\n * @overview Displays a dynamic map over which information from additional sources can be overlaid.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @pjackson28\n */\n( function( $, wb ) {\n\"use strict\";\n\nvar componentName = \"wb-geomap\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm, $map, $leg, modeJS;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\t\t\t$map = $elm.find( \".wb-geomap-map\" );\n\t\t\t$leg = $elm.find( \".wb-geomap-legend\" );\n\n\t\t\t// Initialize the map height for the loader\n\t\t\t$map.height( $map.width() * 0.8 );\n\t\t\t$map.append( \"\n\" + wb.i18n( \"load\" ) + \"\" );\n\t\t\t$leg.append( \"\n\" +\n\t\t\t\t\t\"\n\" +\n\t\t\t\t\t\"\n\" +\n\t\t\t\t\t\"\n\" +\n\t\t\t\t\t\"\n\" );\n\n\t\t\tmodeJS = wb.getMode() + \".js\";\n\n\t\t\tModernizr.load( [ {\n\n\t\t\t\t// For loading multiple dependencies\n\t\t\t\tboth: [\n\t\t\t\t\t\"site!deps/proj4\" + modeJS,\n\t\t\t\t\t\"site!deps/ol\" + modeJS,\n\t\t\t\t\t\"site!deps/geomap-lib\" + modeJS\n\t\t\t\t],\n\t\t\t\tcomplete: function() {\n\t\t\t\t\t$elm.trigger( \"geomap.wb\" );\n\t\t\t\t}\n\t\t\t} ] );\n\t\t}\n\t};\n\n// Bind the init function to the timerpoke event\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, wb );\n\n/**\n * @title WET-BOEW JSON Fetch [ json-fetch ]\n * @overview Load and filter data from a JSON file\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @duboisp\n */\n/*global jsonpointer */\n( function( $, wb, DOMPurify ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar $document = wb.doc,\n\tcomponent = \"json-fetch\",\n\tfetchEvent = component + \".wb\",\n\tjsonCache = { },\n\tjsonCacheBacklog = { },\n\tcompleteJsonFetch = function( callerId, refId, response, status, xhr, selector, fetchedOpts ) {\n\t\tif ( !window.jsonpointer ) {\n\n\t\t\t// JSON pointer library is loaded but not executed in memory yet, we need to wait a tick before to continue\n\t\t\tsetTimeout( function() {\n\t\t\t\tcompleteJsonFetch( callerId, refId, response, status, xhr, selector, fetchedOpts );\n\t\t\t}, 100 );\n\t\t\treturn false;\n\t\t}\n\t\tif ( selector ) {\n\t\t\ttry {\n\t\t\t\tresponse = jsonpointer.get( response, selector );\n\t\t\t} catch ( ex ) {\n\t\t\t\tconsole.error( \"JSON fetch - Bad JSON selector: \" + selector );\n\t\t\t\tconsole.error( response );\n\t\t\t\tconsole.error( $( \"#\" + callerId ).get( 0 ) );\n\t\t\t}\n\t\t}\n\t\t$( \"#\" + callerId ).trigger( {\n\t\t\ttype: \"json-fetched.wb\",\n\t\t\tfetch: {\n\t\t\t\tresponse: response,\n\t\t\t\tstatus: status,\n\t\t\t\txhr: xhr,\n\t\t\t\trefId: refId,\n\t\t\t\tfetchedOpts: fetchedOpts\n\t\t\t}\n\t\t}, this );\n\t};\n\n// Event binding\n$document.on( fetchEvent, function( event ) {\n\n\tvar caller = event.element || event.target,\n\t\tfetchOpts = event.fetch || { url: \"\" },\n\t\turlParts = fetchOpts.url.split( \"#\" ),\n\t\turl = urlParts[ 0 ],\n\t\tfetchNoCache = fetchOpts.nocache,\n\t\tfetchNoCacheKey = fetchOpts.nocachekey || wb.cacheBustKey || \"wbCacheBust\",\n\t\tfetchNoCacheValue,\n\t\tfetchCacheURL,\n\t\thashPart,\n\t\tdatasetName,\n\t\tselector = urlParts[ 1 ] || false,\n\t\tcallerId, refId = fetchOpts.refId,\n\t\tcachedResponse;\n\n\t// Filter out any events triggered by descendants\n\tif ( caller === event.target || event.currentTarget === event.target ) {\n\n\t\tif ( !caller.id ) {\n\t\t\tcaller.id = wb.getId();\n\t\t}\n\t\tcallerId = caller.id;\n\n\t\tif ( selector ) {\n\n\t\t\t// If a Dataset Name exist let it managed by wb-jsonpatch plugin\n\t\t\thashPart = selector.split( \"/\" );\n\t\t\tdatasetName = hashPart[ 0 ];\n\n\t\t\t// A dataset name must start with \"[\" character, if it is a letter, then follow JSON Schema (to be implemented)\n\t\t\tif ( datasetName.charCodeAt( 0 ) === 91 ) {\n\n\t\t\t\t// Let the wb-jsonpatch plugin to manage it\n\t\t\t\t$( \"#\" + callerId ).trigger( {\n\t\t\t\t\ttype: \"postpone.wb-jsonmanager\",\n\t\t\t\t\tpostpone: {\n\t\t\t\t\t\tcallerId: callerId,\n\t\t\t\t\t\trefId: refId,\n\t\t\t\t\t\tdsname: datasetName,\n\t\t\t\t\t\tselector: selector.substring( datasetName.length )\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t\treturn;\n\t\t\t}\n\t\t\tfetchOpts.url = url;\n\t\t}\n\n\t\tif ( fetchNoCache ) {\n\t\t\tif ( fetchNoCache === \"nocache\" ) {\n\t\t\t\tfetchNoCacheValue = wb.guid();\n\t\t\t} else {\n\t\t\t\tfetchNoCacheValue = wb.sessionGUID();\n\t\t\t}\n\t\t\tfetchCacheURL = fetchNoCacheKey + \"=\" + fetchNoCacheValue;\n\n\t\t\tif ( url.indexOf( \"?\" ) !== -1 ) {\n\t\t\t\turl = url + \"&amp;amp;\" + fetchCacheURL;\n\t\t\t} else {\n\t\t\t\turl = url + \"?\" + fetchCacheURL;\n\t\t\t}\n\t\t\tfetchOpts.url = url;\n\t\t}\n\n\t\tModernizr.load( {\n\t\t\tload: \"site!deps/jsonpointer\" + wb.getMode() + \".js\",\n\t\t\tcomplete: function() {\n\n\t\t\t\t// Ensure this fetch has an URL. There is no URL when only using dataset name (a virtual JSON file).\n\t\t\t\tif ( !url ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\tif ( !fetchOpts.nocache ) {\n\t\t\t\t\tcachedResponse = jsonCache[ url ];\n\n\t\t\t\t\tif ( cachedResponse ) {\n\t\t\t\t\t\tcompleteJsonFetch( callerId, refId, cachedResponse, \"success\", undefined, selector, fetchOpts );\n\t\t\t\t\t\treturn;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( !jsonCacheBacklog[ url ] ) {\n\t\t\t\t\t\t\tjsonCacheBacklog[ url ] = [ ];\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjsonCacheBacklog[ url ].push( {\n\t\t\t\t\t\t\t\t\"callerId\": callerId,\n\t\t\t\t\t\t\t\t\"refId\": refId,\n\t\t\t\t\t\t\t\t\"selector\": selector\n\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Ensure we only receive JSON data and don't allow jsonp\n\t\t\t\t// jQuery will raise an error if other data format is received\n\t\t\t\tfetchOpts.dataType = \"json\";\n\t\t\t\tif ( fetchOpts.jsonp ) {\n\t\t\t\t\tfetchOpts.jsonp = false;\n\t\t\t\t}\n\n\t\t\t\t// Sending Data\n\t\t\t\tif ( fetchOpts.data ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tfetchOpts.data = ( typeof fetchOpts.data === \"string\" ? fetchOpts.data : JSON.stringify( fetchOpts.data ) );\n\t\t\t\t\t} catch ( err ) {\n\t\t\t\t\t\tthrow \"JSON fetch - Data being sent to server - \" + err;\n\t\t\t\t\t}\n\n\t\t\t\t\tfetchOpts.method = fetchOpts.method || \"POST\";\n\t\t\t\t\tfetchOpts.contentType = fetchOpts.contentType || \"application/json\";\n\t\t\t\t}\n\n\t\t\t\t$.ajax( fetchOpts )\n\t\t\t\t\t.done( function( response, status, xhr ) {\n\t\t\t\t\t\tvar i, i_len, i_cache, backlog;\n\n\t\t\t\t\t\tif ( !fetchOpts.nocache ) {\n\t\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\t\tjsonCache[ url ] = response;\n\t\t\t\t\t\t\t} catch ( error ) {\n\t\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tcompleteJsonFetch( callerId, refId, response, status, xhr, selector, fetchOpts );\n\n\t\t\t\t\t\tif ( jsonCacheBacklog[ url ] ) {\n\t\t\t\t\t\t\tbacklog = jsonCacheBacklog[ url ];\n\n\t\t\t\t\t\t\ti_len = backlog.length;\n\n\t\t\t\t\t\t\tfor ( i = 0; i !== i_len; i += 1 ) {\n\t\t\t\t\t\t\t\ti_cache = backlog[ i ];\n\t\t\t\t\t\t\t\tcompleteJsonFetch( i_cache.callerId, i_cache.refId, response, status, xhr, i_cache.selector, fetchOpts );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} )\n\t\t\t\t\t.fail( function( xhr, status, error ) {\n\t\t\t\t\t\txhr.responseText = DOMPurify.sanitize( xhr.responseText );\n\t\t\t\t\t\t$( \"#\" + callerId ).trigger( {\n\t\t\t\t\t\t\ttype: \"json-failed.wb\",\n\t\t\t\t\t\t\tfetch: {\n\t\t\t\t\t\t\t\txhr: xhr,\n\t\t\t\t\t\t\t\tstatus: status,\n\t\t\t\t\t\t\t\terror: error,\n\t\t\t\t\t\t\t\trefId: refId,\n\t\t\t\t\t\t\t\tfetchOpts: fetchOpts\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}, this );\n\t\t\t\t\t}, this );\n\t\t\t}\n\t\t} );\n\t}\n} );\n\n} )( jQuery, wb, DOMPurify );\n\n/**\n * @title WET-BOEW Lightbox\n * @overview Helps build a photo gallery on a web page.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @pjackson28\n */\n( function( $, DOMPurify, window, document, wb, undef ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-lbx\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tsetFocusEvent = \"setfocus.wb\",\n\tdependenciesLoadedEvent = \"deps-loaded\" + selector,\n\tmodalHideSelector = \"#wb-tphp, body &amp;gt; header, body &amp;gt; main, body &amp;gt; footer\",\n\t$document = wb.doc,\n\tcallbacks, i18n, i18nText,\n\tdefaults = {\n\n\t\t// exclude 'times' from screen reader with aria-hidden span\n\t\tcloseMarkup: \"&amp;times;%title%\"\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\telmId;\n\n\t\tif ( elm ) {\n\t\t\telmId = elm.id;\n\n\t\t\t// Ensure the dependencies are loaded first\n\t\t\t$document.one( dependenciesLoadedEvent, function() {\n\t\t\t\tvar elm = document.getElementById( elmId ),\n\t\t\t\t\t$elm = $( elm ),\n\t\t\t\t\tsettings = {},\n\t\t\t\t\tfirstLink;\n\n\t\t\t\tif ( !elm ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\n\t\t\t\t// TODO: Add swipe support\n\n\t\t\t\tsettings.callbacks = callbacks;\n\n\t\t\t\tif ( elm.nodeName.toLowerCase() !== \"a\" ) {\n\t\t\t\t\tsettings.delegate = \"a:not(\" + selector + \"-skip)\";\n\t\t\t\t\tfirstLink = elm.getElementsByTagName( \"a\" )[ 0 ];\n\n\t\t\t\t\t// Is the element a gallery?\n\t\t\t\t\tif ( elm.className.indexOf( \"-gal\" ) !== -1 ) {\n\t\t\t\t\t\tsettings.gallery = {\n\t\t\t\t\t\t\tenabled: true\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tfirstLink = elm;\n\t\t\t\t}\n\n\t\t\t\tif ( firstLink ) {\n\t\t\t\t\tif ( firstLink.getAttribute( \"href\" ).charAt( 0 ) === \"#\" ) {\n\t\t\t\t\t\tsettings.type = \"inline\";\n\t\t\t\t\t} else if ( firstLink.className.indexOf( \"lbx-iframe\" ) !== -1 ) {\n\t\t\t\t\t\tsettings.type = \"iframe\";\n\t\t\t\t\t} else if ( firstLink.getElementsByTagName( \"img\" ).length === 0 ) {\n\t\t\t\t\t\tsettings.type = \"ajax\";\n\t\t\t\t\t} else {\n\t\t\t\t\t\tsettings.type = \"image\";\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( elm.className.indexOf( \"lbx-modal\" ) !== -1 ) {\n\t\t\t\t\t\tsettings.modal = true;\n\t\t\t\t\t}\n\t\t\t\t\tif ( elm.className.indexOf( \"lbx-ajax\" ) !== -1 ) {\n\t\t\t\t\t\tsettings.type = \"ajax\";\n\t\t\t\t\t}\n\t\t\t\t\tif ( elm.className.indexOf( \"lbx-image\" ) !== -1 ) {\n\t\t\t\t\t\tsettings.type = \"image\";\n\t\t\t\t\t}\n\t\t\t\t\tif ( elm.className.indexOf( \"lbx-inline\" ) !== -1 ) {\n\t\t\t\t\t\tsettings.type = \"inline\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Extend the settings with window[ \"wb-lbx\" ] then data-wb-lbx\n\t\t\t\t\tsettings = $.extend(\n\t\t\t\t\t\ttrue,\n\t\t\t\t\t\tsettings,\n\t\t\t\t\t\twindow[ componentName ],\n\t\t\t\t\t\twb.getData( $elm, componentName )\n\t\t\t\t\t);\n\t\t\t\t\t$elm.magnificPopup(\n\t\t\t\t\t\tsettings\n\t\t\t\t\t).data( \"wbLbxFilter\", settings.filter );\n\t\t\t\t}\n\n\t\t\t\t// Identify that initialization has completed\n\t\t\t\twb.ready( $elm, componentName );\n\t\t\t} );\n\n\t\t\t// Load dependencies as needed\n\t\t\tsetup();\n\t\t}\n\t},\n\n\t/**\n\t * @method setup\n\t */\n\tsetup = function() {\n\n\t\t// Only initialize the i18nText and callbacks once\n\t\tif ( !i18nText ) {\n\t\t\ti18n = wb.i18n;\n\t\t\ti18nText = {\n\t\t\t\tclose: i18n( \"close\" ),\n\t\t\t\toClose: i18n( \"overlay-close\" ),\n\t\t\t\ttClose: i18n( \"close\" ) + i18n( \"space\" ) + i18n( \"overlay-close\" ) + i18n( \"space\" ) + i18n( \"esc-key\" ),\n\t\t\t\ttLoading: i18n( \"load\" ),\n\t\t\t\tgallery: {\n\t\t\t\t\ttPrev: i18n( \"prv-l\" ),\n\t\t\t\t\ttNext: i18n( \"nxt-r\" ),\n\t\t\t\t\ttCounter: i18n( \"lb-curr\" )\n\t\t\t\t},\n\t\t\t\timage: {\n\t\t\t\t\ttError: i18n( \"lb-img-err\" ) + \" ()\"\n\t\t\t\t},\n\t\t\t\tajax: {\n\t\t\t\t\ttError: i18n( \"lb-xhr-err\" ) + \" ()\"\n\t\t\t\t}\n\t\t\t};\n\n\t\t\tcallbacks = {\n\t\t\t\topen: function() {\n\n\t\t\t\t\t// TODO: Better if dealt with upstream by Magnific popup\n\t\t\t\t\tvar $item = this.currItem,\n\t\t\t\t\t\t$content = this.contentContainer,\n\t\t\t\t\t\t$wrap = this.wrap,\n\t\t\t\t\t\t$container = $wrap.find( \".mfp-container\" ),\n\t\t\t\t\t\t$containerParent = $container.parent(),\n\t\t\t\t\t\t$modal = $wrap.find( \".modal-dialog\" ),\n\t\t\t\t\t\t$buttons = $wrap.find( \".mfp-arrow\" ),\n\t\t\t\t\t\tlen = $buttons.length,\n\t\t\t\t\t\ti, button;\n\n\t\t\t\t\tcreateCloseButton( $modal );\n\n\t\t\t\t\t$document.find( \"body\" ).addClass( \"wb-modal\" );\n\t\t\t\t\t$document.find( modalHideSelector ).attr( \"aria-hidden\", \"true\" );\n\t\t\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t\t\tbutton = $buttons[ i ];\n\t\t\t\t\t\tbutton.innerHTML += \" \" + button.title + \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( $item.type === \"image\" ) {\n\t\t\t\t\t\t$content.find( \".mfp-bottom-bar\" ).attr( \"id\", \"lbx-title\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$content.attr( \"role\", \"document\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tthis.contentContainer.attr( \"data-pgtitle\", document.getElementsByTagName( \"H1\" )[ 0 ].textContent );\n\n\t\t\t\t\ttrapTabbing( $wrap );\n\n\t\t\t\t\tif ( !$containerParent.is( \"dialog\" ) ) {\n\t\t\t\t\t\t$container.wrap( \"\n\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$containerParent.attr( \"open\", \"open\" );\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tclose: function() {\n\t\t\t\t\t$document.find( \"body\" ).removeClass( \"wb-modal\" );\n\t\t\t\t\t$document.find( modalHideSelector ).removeAttr( \"aria-hidden\" );\n\t\t\t\t\tthis.wrap.find( \"dialog\" ).removeAttr( \"open\" );\n\n\t\t\t\t},\n\t\t\t\tchange: function() {\n\t\t\t\t\tvar $item = this.currItem,\n\t\t\t\t\t\t$content = this.contentContainer,\n\t\t\t\t\t\t$el, $bottomBar, $source, $target,\n\t\t\t\t\t\tdescription, altTitleId, altTitle;\n\n\t\t\t\t\tif ( $item.type === \"image\" ) {\n\t\t\t\t\t\t$el = $item.el;\n\t\t\t\t\t\t$target = $item.img;\n\t\t\t\t\t\t$bottomBar = $content.find( \".mfp-bottom-bar\" );\n\n\t\t\t\t\t\tif ( $el ) {\n\t\t\t\t\t\t\t$source = $el.find( \"img\" );\n\t\t\t\t\t\t\t$target.attr( \"alt\", $source.attr( \"alt\" ) );\n\n\t\t\t\t\t\t\t// Replicate aria-describedby if it exists\n\t\t\t\t\t\t\tdescription = $source.attr( \"aria-describedby\" );\n\t\t\t\t\t\t\tif ( description ) {\n\t\t\t\t\t\t\t\t$target.attr( \"aria-describedby\", description );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Replicate longdesc if it exists\n\t\t\t\t\t\t\tdescription = $source.attr( \"longdesc\" );\n\t\t\t\t\t\t\tif ( description ) {\n\t\t\t\t\t\t\t\t$target.attr( \"longdesc\", description );\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Handle alternate titles\n\t\t\t\t\t\t\taltTitleId = $el.attr( \"data-title\" );\n\t\t\t\t\t\t\tif ( altTitleId ) {\n\t\t\t\t\t\t\t\taltTitle = document.getElementById( altTitleId );\n\t\t\t\t\t\t\t\tif ( altTitle !== null ) {\n\t\t\t\t\t\t\t\t\t$bottomBar.find( \".mfp-title\" ).html( altTitle.innerHTML );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$target.attr( \"alt\", $bottomBar.find( \".mfp-title\" ).html() );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$content\n\t\t\t\t\t\t\t.find( \".modal-title, h1\" )\n\t\t\t\t\t\t\t.first()\n\t\t\t\t\t\t\t.attr( \"id\", \"lbx-title\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t$content.attr( \"aria-labelledby\", \"lbx-title\" );\n\t\t\t\t},\n\t\t\t\tparseAjax: function( mfpResponse ) {\n\t\t\t\t\tvar currItem = this.currItem,\n\t\t\t\t\t\tcurrEl = currItem.el,\n\t\t\t\t\t\turlHash = currItem.src.split( \"#\" )[ 1 ],\n\t\t\t\t\t\tfilter = currEl ? currEl.data( \"wbLbxFilter\" ) : undef,\n\t\t\t\t\t\tselector = filter || ( urlHash ? \"#\" + urlHash : false ),\n\t\t\t\t\t\t$response;\n\n\t\t\t\t\t// Sanitize the response\n\t\t\t\t\tmfpResponse.data = DOMPurify.sanitize( mfpResponse.data );\n\n\t\t\t\t\t// Provide the ability to filter the AJAX response HTML\n\t\t\t\t\t// by the URL hash or a selector\n\t\t\t\t\t// TODO: Should be dealt with upstream by Magnific Popup\n\t\t\t\t\tif ( selector ) {\n\t\t\t\t\t\t$response = $( \"\n\" + mfpResponse.data + \"\" ).find( selector );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$response = $( mfpResponse.data );\n\t\t\t\t\t}\n\t\t\t\t\tcreateCloseButton( $response );\n\n\t\t\t\t\t$response\n\t\t\t\t\t\t.find( \".modal-title, h1\" )\n\t\t\t\t\t\t.first()\n\t\t\t\t\t\t.attr( \"id\", \"lbx-title\" );\n\n\t\t\t\t\tmfpResponse.data = $response;\n\t\t\t\t},\n\t\t\t\tajaxContentAdded: function() {\n\t\t\t\t\ttrapTabbing( this.wrap );\n\t\t\t\t}\n\t\t\t};\n\t\t}\n\n\t\t// Load Magnific Popup dependency and bind the init event handler\n\t\tModernizr.load( {\n\t\t\tload: \"site!deps/jquery.magnific-popup\" + wb.getMode() + \".js\",\n\t\t\ttestReady: function() {\n\t\t\t\treturn $.magnificPopup;\n\t\t\t},\n\t\t\tcomplete: function() {\n\n\t\t\t\t// Set the dependency i18nText only once\n\t\t\t\t$.extend( true, $.magnificPopup.defaults, i18nText, defaults );\n\n\t\t\t\t$document.trigger( dependenciesLoadedEvent );\n\t\t\t}\n\t\t} );\n\t},\n\tcreateCloseButton = function( $modal ) {\n\t\tif ( $modal !== null &amp;amp;&amp;amp; $modal.hasClass( \"modal-dialog\" ) ) {\n\t\t\tvar footer = $modal.find( \".modal-footer\" ).first(),\n\t\t\t\thasFooter = footer.length,\n\t\t\t\thasButton = hasFooter &amp;amp;&amp;amp; $( footer ).find( \".popup-modal-dismiss\" ).length !== 0,\n\t\t\t\tcloseClassFtr = \"popup-modal-dismiss\",\n\t\t\t\tcloseTextFtr = i18nText.close,\n\t\t\t\tspanTextFtr = i18nText.oClose,\n\t\t\t\toverlayCloseFtr;\n\n\t\t\tif ( !hasButton ) {\n\t\t\t\tif ( !hasFooter ) {\n\t\t\t\t\tfooter = document.createElement( \"div\" );\n\t\t\t\t\tfooter.setAttribute( \"class\", \"modal-footer\" );\n\t\t\t\t}\n\n\t\t\t\toverlayCloseFtr = \"\" +\n\t\t\t\t\tcloseTextFtr +\n\t\t\t\t\t\"\" + spanTextFtr + \"\";\n\n\t\t\t\t$( footer ).append( overlayCloseFtr );\n\t\t\t\tif ( !hasFooter ) {\n\t\t\t\t\t$( footer ).insertAfter( $modal.find( \".modal-body\" ) );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\ttrapTabbing = function( $wrap ) {\n\n\t\t$wrap.on( \"keydown\", function( e ) {\n\t\t\tif ( e.which === 9 ) {\n\t\t\t\tvar tabbable = $wrap.find( \".mfp-container :tabbable\" ),\n\t\t\t\t\tfirstTabbable = tabbable.first()[ 0 ],\n\t\t\t\t\tlastTabbable = tabbable.last()[ 0 ],\n\t\t\t\t\tcurrentFocus = $( document.activeElement )[ 0 ];\n\n\t\t\t\tif ( !e.shiftKey &amp;amp;&amp;amp; currentFocus === lastTabbable ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tfirstTabbable.focus();\n\t\t\t\t} else if ( e.shiftKey &amp;amp;&amp;amp; ( currentFocus === firstTabbable || currentFocus === $wrap[ 0 ] ) ) {\n\t\t\t\t\te.preventDefault();\n\t\t\t\t\tlastTabbable.focus();\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Handler for clicking on a same page link within the overlay to outside the overlay\n$document.on( \"click\", \".mfp-wrap a[href^='#']\", function( event ) {\n\tvar which = event.which,\n\t\teventTarget = event.currentTarget,\n\t\t$lightbox, linkTarget;\n\n\t// Ignore middle/right mouse buttons\n\tif ( !which || which === 1 ) {\n\t\t$lightbox = $( eventTarget ).closest( \".mfp-wrap\" );\n\t\tlinkTarget = document.getElementById( eventTarget.getAttribute( \"href\" ).substring( 1 ) );\n\n\t\t// Ignore same page links to within the overlay\n\t\tif ( linkTarget &amp;amp;&amp;amp; !$.contains( $lightbox[ 0 ], linkTarget ) ) {\n\n\t\t\t// Stop propagation of the click event\n\t\t\tif ( event.stopPropagation ) {\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t} else {\n\t\t\t\tevent.cancelBubble = true;\n\t\t\t}\n\n\t\t\t// Close the overlay and set focus to the same page link\n\t\t\t$.magnificPopup.close();\n\t\t\t$( linkTarget ).trigger( setFocusEvent );\n\t\t}\n\t}\n} );\n\n// Event handler for closing a modal popup via the close button\n$( document ).on( \"click\", \".popup-modal-dismiss\", function( event ) {\n\tif ( !this.hasAttribute( \"target\" ) ) {\n\t\tevent.preventDefault();\n\t}\n\n\t$.magnificPopup.close();\n} );\n\n// Event handler for closing a modal popup via the Escape key\n$( document ).on( \"keydown\", \".mfp-wrap:not(.mfp-close-btn-in)\", function( event ) {\n\n\t// If the Escape key was pressed...\n\tif ( event.key === \"Escape\" ) {\n\t\tconst closeButtons = event.currentTarget.querySelectorAll( \".popup-modal-dismiss\" );\n\n\t\t// Trigger a \"fake\" click on the last close button\n\t\t// Notes:\n\t\t// -Allows Escape key presses to \"piggyback\" on additional functionality in close button click handlers (such as preventDefault and the session timeout plugin's confirm method)\n\t\t// -Targets the last close button link to accomodate plugins that use multiple close buttons (such as exit script)... the last button is more likely to represent no in those scenarios\n\t\t$( closeButtons[ closeButtons.length - 1 ] ).trigger( \"click\" );\n\t}\n} );\n\n// Event handler for opening a popup via a button link and the spacebar key\n$( document ).on( \"keydown\", \".\" + componentName, function( event ) {\n\tconst sourceLink = event.currentTarget;\n\n\t// If the link contains a role=\"button\" attribute and the spacebar key was pressed...\n\tif ( sourceLink.getAttribute( \"role\" ) === \"button\" &amp;amp;&amp;amp; event.key === \" \" ) {\n\n\t\t// Don't scroll down (typical spacebar behaviour)\n\t\tevent.preventDefault();\n\n\t\t// Trigger a \"fake\" click on the button link\n\t\t$( sourceLink ).trigger( \"click\" );\n\t}\n} );\n\n// Event handler for opening a popup without a link\n$( document ).on( \"open\" + selector, function( event, items, modal, title, ajax ) {\n\tif ( event.namespace === componentName ) {\n\t\tvar isGallery = items.length &amp;gt; 1,\n\t\t\tisModal = modal &amp;amp;&amp;amp; !isGallery ? modal : false,\n\t\t\ttitleSrc = title ? function() {\n\t\t\t\treturn title[ $.magnificPopup.instance.index ];\n\t\t\t} : \"title\";\n\n\t\tevent.preventDefault();\n\n\t\t// Ensure the dependencies are loaded first\n\t\t$document.one( dependenciesLoadedEvent, function() {\n\t\t\t$.magnificPopup.open( {\n\t\t\t\titems: items,\n\t\t\t\tmodal: isModal,\n\t\t\t\tgallery: {\n\t\t\t\t\tenabled: isGallery\n\t\t\t\t},\n\t\t\t\timage: {\n\t\t\t\t\ttitleSrc: titleSrc\n\t\t\t\t},\n\t\t\t\tcallbacks: callbacks,\n\t\t\t\tajax: ajax\n\t\t\t} );\n\n\t\t\twb.ready( undef, componentName );\n\t\t} );\n\n\t\t// Load dependencies as needed\n\t\tsetup();\n\t}\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, DOMPurify, window, document, wb );\n\n/**\n * @title WET-BOEW Menu plugin\n * @overview A Menu plugin for WET\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author WET community\n */\n( function( $, window, document, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-menu\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tbreadcrumb = document.getElementById( \"wb-bc\" ),\n\tnavCurrentEvent = \"navcurr.wb\",\n\tfocusEvent = \"setfocus.wb\",\n\tdetailsInitEvent = \"wb-init.wb-details\",\n\tmenuItemSelector = \"&amp;gt; a, &amp;gt; details &amp;gt; summary\",\n\t$document = wb.doc,\n\n\t// Used for half second delay on showing/hiding menus because of mouse hover\n\thoverDelay = 500,\n\tmenuCount = 0,\n\tglobalTimeout,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm, ajaxFetch;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\n\t\t\t// Ensure the container has an id attribute\n\t\t\tif ( !$elm.attr( \"id\" ) ) {\n\t\t\t\t$elm.attr( \"id\", componentName + \"-\" + menuCount );\n\t\t\t}\n\t\t\tmenuCount += 1;\n\n\t\t\t// Lets test to see if we have any menus to fetch\n\t\t\t// This is required for backwards compatibility. In previous versions, the menu was not integrated with the data ajax plugin.\n\t\t\tajaxFetch = $elm.data( \"ajax-fetch\" );\n\t\t\tif ( ajaxFetch ) {\n\t\t\t\t$elm.trigger( {\n\t\t\t\t\ttype: \"ajax-fetch.wb\",\n\t\t\t\t\tfetch: {\n\t\t\t\t\t\turl: ajaxFetch\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} else {\n\n\t\t\t\t//Enhance menus that don't rely on the data-ajax plugin\n\t\t\t\tajaxFetch = $elm.data( \"ajax-replace\" ) || $elm.data( \"ajax-append\" ) || $elm.data( \"ajax-prepend\" );\n\t\t\t\tif ( !ajaxFetch ) {\n\t\t\t\t\tonAjaxLoaded( $elm, $elm );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Lets set some aria states and attributes\n\t * @method drizzleAria\n\t * @param {jQuery DOM elements} $elements The collection of elements\n\t */\n\tdrizzleAria = function( $elements ) {\n\t\tvar length = $elements.length,\n\t\t\t$elm, $subMenu, i;\n\n\t\t// Lets tweak for aria\n\t\tfor ( i = 0; i !== length; i += 1 ) {\n\t\t\t$elm = $elements.eq( i );\n\t\t\t$subMenu = $elm.siblings( \"ul\" );\n\n\t\t\t$elm.attr( {\n\t\t\t\t\"aria-posinset\": ( i + 1 ),\n\t\t\t\t\"aria-setsize\": length,\n\t\t\t\trole: \"menuitem\"\n\t\t\t} );\n\n\t\t\t// if there is a submenu lets put in the aria for it\n\t\t\tif ( $subMenu.length !== 0 ) {\n\n\t\t\t\t$elm.attr( \"aria-haspopup\", \"true\" );\n\n\t\t\t\t$subMenu.attr( {\n\t\t\t\t\t\"aria-expanded\": \"false\",\n\t\t\t\t\t\"aria-hidden\": \"true\"\n\t\t\t\t} );\n\n\t\t\t\t// recurse into submenu\n\t\t\t\tdrizzleAria( $subMenu.children( \"li\" ).find( menuItemSelector ) );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * @method createCollapsibleSection\n\t * @return {string}\n\t */\n\tcreateCollapsibleSection = function( section, sectionIndex, sectionsLength, $items, itemsLength ) {\n\n\t\t// Use details/summary for the collapsible mechanism\n\t\tvar k, $elm, elm, $item, $subItems, subItemsLength,\n\t\t\t$section = $( section ),\n\t\t\tposinset = \"' aria-posinset='\",\n\t\t\tmenuitem = \" role='menuitem' aria-setsize='\",\n\t\t\tsectionHtml = \"\n\n\" + \"\" + $section.text() + \"\" +\n\t\t\t\t\"\n\";\n\n\t\t// Convert each of the list items into WAI-ARIA menuitems\n\t\tfor ( k = 0; k !== itemsLength; k += 1 ) {\n\t\t\t$item = $items.eq( k );\n\t\t\t$elm = $item.find( menuItemSelector );\n\t\t\telm = $elm[ 0 ];\n\t\t\t$subItems = $elm.parent().find( \"&amp;gt; ul &amp;gt; li\" );\n\t\t\tsubItemsLength = $subItems.length;\n\n\t\t\tif ( elm &amp;amp;&amp;amp; subItemsLength === 0 &amp;amp;&amp;amp; elm.nodeName.toLowerCase() === \"a\" ) {\n\t\t\t\tsectionHtml += \"\n\" + $item[ 0 ].innerHTML.replace(\n\t\t\t\t\t/(\";\n\t\t\t} else {\n\t\t\t\tsectionHtml += createCollapsibleSection( elm, k, itemsLength, $subItems, $subItems.length );\n\t\t\t}\n\t\t}\n\n\t\treturn sectionHtml + \"\";\n\t},\n\n\t/**\n\t * @method createMobilePanelMenu\n\t * @param {array} allProperties Properties used to build the menu system\n\t * @return {string}\n\t */\n\tcreateMobilePanelMenu = function( allProperties ) {\n\t\tvar panel = \"\",\n\t\t\tsectionHtml, properties, sections, section, parent, $items,\n\t\t\tlinkHtml, i, j, len, sectionsLength, itemsLength;\n\n\t\t// Process the secondary and site menus\n\t\tlen = allProperties.length;\n\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\tproperties = allProperties[ i ];\n\t\t\tsectionHtml = \"\";\n\t\t\tsections = properties[ 0 ];\n\t\t\tsectionsLength = sections.length;\n\t\t\tfor ( j = 0; j !== sectionsLength; j += 1 ) {\n\t\t\t\tsection = sections[ j ];\n\t\t\t\t$items = $( section.parentNode ).find( \"&amp;gt; ul &amp;gt; li\" );\n\t\t\t\titemsLength = $items.length;\n\n\t\t\t\t// Collapsible section\n\t\t\t\tif ( itemsLength !== 0 ) {\n\t\t\t\t\tsectionHtml += createCollapsibleSection( section, j, sectionsLength, $items, itemsLength );\n\t\t\t\t} else {\n\t\t\t\t\tparent = section.parentNode;\n\n\t\t\t\t\t// Menu item without a section\n\t\t\t\t\tif ( parent.nodeName.toLowerCase() === \"li\" ) {\n\t\t\t\t\t\tlinkHtml = parent.innerHTML;\n\n\t\t\t\t\t// Non-list menu items without a section and that contain their own link\n\t\t\t\t\t} else if ( parent.getElementsByTagName( \"a\" )[ 0 ] === section.getElementsByTagName( \"a\" )[ 0 ] ) {\n\t\t\t\t\t\tlinkHtml = section.innerHTML;\n\n\t\t\t\t\t// Non-list menu item without a section and whose siblings contain a link\n\t\t\t\t\t} else {\n\t\t\t\t\t\tlinkHtml = \"\" +\n\t\t\t\t\t\t\tsection.innerHTML + \"\";\n\t\t\t\t\t}\n\n\t\t\t\t\t// Convert the list item to a WAI-ARIA menuitem\n\t\t\t\t\tsectionHtml += \"\n\" +\n\t\t\t\t\t\tlinkHtml.replace(\n\t\t\t\t\t\t\t/(\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Create the panel section\n\t\t\tpanel += \"\n\" +\n\t\t\t\t\"\n\" + properties[ 2 ] + \"\" +\n\t\t\t\t\"\n\" +\n\t\t\t\tsectionHtml + \"\";\n\t\t}\n\n\t\treturn panel.replace( /['\"]?list-group-item['\"]?/gi, \"\\\"\\\"\" );\n\t},\n\n\t/**\n\t * @method onAjaxLoaded\n\t * @param {jQuery DOM element} $elm The plugin element\n\t * @param {jQuery DOM element} $ajaxResult The AJAXed in menu content to import\n\t */\n\tonAjaxLoaded = function( $elm, $ajaxResult ) {\n\t\tvar $info = $( \"#wb-info\" ),\n\t\t\tinner = function() {\n\t\t\t\tvar $ajaxed = $ajaxResult &amp;amp;&amp;amp; $ajaxResult.attr( \"data-type\" ) === \"string\" ? $ajaxResult : $elm,\n\t\t\t\t\t$menubar = $ajaxed.find( \".menu\" ),\n\t\t\t\t\t$menu = $menubar.find( \"&amp;gt; li &amp;gt; a\" ),\n\t\t\t\t\ttarget = $elm.data( \"trgt\" ),\n\t\t\t\t\t$secnav = $( \"#wb-sec\" ),\n\t\t\t\t\t$language = $( \"#wb-lng\" ),\n\t\t\t\t\tsearch = document.getElementById( \"wb-srch\" ),\n\t\t\t\t\tpanel = \"\",\n\t\t\t\t\tpanelDOM = document.getElementById( target ),\n\t\t\t\t\t$panel = $( panelDOM ),\n\t\t\t\t\tallProperties = [],\n\t\t\t\t\t$navCurr, $menuItem, $langItems, len, i;\n\n\t\t\t\t/*\n\t\t\t\t * Build the mobile panel\n\t\t\t\t */\n\n\t\t\t\t// Add search\n\t\t\t\tif ( search !== null ) {\n\t\t\t\t\tpanel += \"\n\" +\n\t\t\t\t\t\tsearch.innerHTML\n\t\t\t\t\t\t\t.replace( /h2&amp;gt;/i, \"h3&amp;gt;\" )\n\t\t\t\t\t\t\t.replace( /(for|id)=\"([^\"]+)\"/gi, \"$1='$2-imprt'\" ) +\n\t\t\t\t\t\t\"\";\n\t\t\t\t}\n\n\t\t\t\t// Add active language offer\n\t\t\t\tif ( $language.length !== 0 ) {\n\t\t\t\t\t$langItems = $language.find( \"li:not(.curr)\" );\n\t\t\t\t\tlen = $langItems.length;\n\t\t\t\t\tpanel += \"\n\" +\n\t\t\t\t\t\t\"\n\" + $language.children( \"h2\" ).html() + \"\" +\n\t\t\t\t\t\t\"\n\";\n\t\t\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t\t\tpanel += $langItems[ i ].innerHTML\n\t\t\t\t\t\t\t.replace( /(?)/, \"\n$1\" );\n\t\t\t\t\t}\n\t\t\t\t\tpanel += \"\";\n\t\t\t\t}\n\n\t\t\t\t// Create menu system\n\t\t\t\tif ( $secnav.length !== 0 || $menubar.length !== 0 || $info.length !== 0 ) {\n\n\t\t\t\t\t// Add the secondary menu\n\t\t\t\t\tif ( $secnav.length !== 0 ) {\n\t\t\t\t\t\tallProperties.push( [\n\t\t\t\t\t\t\t$secnav.find( \"ul\" ).filter( \":not(li &amp;gt; ul)\" ).find( \" &amp;gt; li &amp;gt; *:first-child\" ).get(),\n\t\t\t\t\t\t\t\"sec-pnl\",\n\t\t\t\t\t\t\t$secnav.find( \"h2\" ).html()\n\t\t\t\t\t\t] );\n\n\t\t\t\t\t\tif ( $secnav.find( \".wb-navcurr\" ).length === 0 ) {\n\n\t\t\t\t\t\t\t// Trigger the navcurrent plugin\n\t\t\t\t\t\t\t$secnav.trigger( navCurrentEvent, breadcrumb );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add the site menu\n\t\t\t\t\tif ( $menubar.length !== 0 ) {\n\n\t\t\t\t\t\t// Add the menubar role if it is missing\n\t\t\t\t\t\tif ( !$menubar.attr( \"role\" ) ) {\n\t\t\t\t\t\t\t$menubar.attr( \"role\", \"menubar\" );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\tallProperties.push( [\n\t\t\t\t\t\t\t$menu.get(),\n\t\t\t\t\t\t\t\"sm-pnl\",\n\t\t\t\t\t\t\t$ajaxed.find( \"h2\" ).html()\n\t\t\t\t\t\t] );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Add the site information\n\t\t\t\t\tif ( $info.length !== 0 ) {\n\t\t\t\t\t\tallProperties.push( [\n\t\t\t\t\t\t\t$info.find( \"h3, a\" ).not( \"section a\" ),\n\t\t\t\t\t\t\t\"info-pnl\",\n\t\t\t\t\t\t\t$info.find( \"h2\" ).html()\n\t\t\t\t\t\t] );\n\n\t\t\t\t\t\tif ( $info.find( \".wb-navcurr\" ).length === 0 ) {\n\n\t\t\t\t\t\t\t// Trigger the navcurrent plugin\n\t\t\t\t\t\t\t$info.trigger( navCurrentEvent, breadcrumb );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tpanel += createMobilePanelMenu( allProperties );\n\t\t\t\t}\n\n\t\t\t\t// Let's now populate the DOM since we have done all the work in a documentFragment\n\t\t\t\tpanelDOM.innerHTML = \"\n\n\" +\n\t\t\t\t\t\tdocument.getElementById( \"wb-glb-mn\" )\n\t\t\t\t\t\t\t.getElementsByTagName( \"h2\" )[ 0 ]\n\t\t\t\t\t\t\t.innerHTML +\n\t\t\t\t\t\t\"\n\" + panel + \"\";\n\t\t\t\tpanelDOM.className += \" wb-overlay modal-content overlay-def wb-panel-r\";\n\n\t\t\t\t// fix #8241\n\t\t\t\tif ( $.active &amp;gt; 0 ) {\n\t\t\t\t\t$( document ).ajaxStop( function() {\n\t\t\t\t\t\tinitOverlay( $panel );\n\t\t\t\t\t} );\n\t\t\t\t} else {\n\t\t\t\t\tinitOverlay( $panel );\n\t\t\t\t}\n\n\t\t\t\t/*\n\t\t\t\t * Build the regular mega menu\n\t\t\t\t */\n\t\t\t\t$ajaxed\n\t\t\t\t\t.find( \":discoverable\" )\n\t\t\t\t\t.attr( \"tabindex\", \"-1\" );\n\n\t\t\t\tif ( $menu.length !== 0 ) {\n\t\t\t\t\t$menu[ 0 ].setAttribute( \"tabindex\", \"0\" );\n\t\t\t\t\tdrizzleAria( $menu );\n\t\t\t\t\t$menu\n\t\t\t\t\t\t.filter( \"[aria-haspopup=true]\" )\n\t\t\t\t\t\t.append( \"\" );\n\t\t\t\t}\n\n\t\t\t\t// Replace elements\n\t\t\t\t$elm.html( $ajaxed.html() );\n\n\t\t\t\t// Trigger the navcurrent plugin\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t$elm.trigger( navCurrentEvent, breadcrumb );\n\t\t\t\t\t$panel.find( \"#sm-pnl\" ).trigger( navCurrentEvent, breadcrumb );\n\n\t\t\t\t\t// Ensure that wb-navcurr is reflected in the top level\n\t\t\t\t\t$navCurr = $panel.find( \".wb-navcurr\" );\n\t\t\t\t\tlen = $navCurr.length;\n\t\t\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t\t\t$menuItem = $navCurr.eq( i );\n\n\t\t\t\t\t\t// If not at the top level, then add wb-navcurr to the top level\n\t\t\t\t\t\tif ( !$menuItem.hasClass( \".mb-item\" ) ) {\n\t\t\t\t\t\t\t$menuItem = $menuItem\n\t\t\t\t\t\t\t\t.closest( \"details\" )\n\t\t\t\t\t\t\t\t.children( \"summary\" )\n\t\t\t\t\t\t\t\t.addClass( \"wb-navcurr\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\t// Open up the secondary menu if it has wb-navcurr and has a submenu\n\t\t\t\t\t$menuItem = $panel.find( \"#sec-pnl .wb-navcurr.mb-item\" );\n\t\t\t\t\tif ( $menuItem.attr( \"aria-haspopup\" ) === \"true\" ) {\n\t\t\t\t\t\t$menuItem\n\t\t\t\t\t\t\t.trigger( \"click\" )\n\t\t\t\t\t\t\t.parent()\n\t\t\t\t\t\t\t.prop( \"open\", \"open\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Identify that initialization has completed\n\t\t\t\t\twb.ready( $elm, componentName );\n\t\t\t\t}, 1 );\n\t\t\t},\n\t\t\t$footerAjax  = $info.find( \"[data-ajax-replace],[data-ajax-append],[data-ajax-prepend]\" ),\n\t\t\tfooterAjaxLength = $footerAjax.length,\n\t\t\tajaxCount = 0;\n\n\t\t//Delay the execution the menu until any ajaxed footer content is in\n\t\tif ( footerAjaxLength === 0 ) {\n\t\t\tinner();\n\t\t} else {\n\t\t\t$info.on( \"wb-contentupdated ajax-failed.wb\", function() {\n\t\t\t\tajaxCount += 1;\n\t\t\t\tif ( ajaxCount === footerAjaxLength ) {\n\t\t\t\t\tinner();\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t},\n\n\t// fix #8517\n\t/**\n\t * @method initOverlay\n\t * @param {jQuery object} $panel Current panel\n\t */\n\tinitOverlay = function( $panel ) {\n\t\t$panel\n\t\t\t.trigger( \"wb-init.wb-overlay\" )\n\t\t\t.find( \"summary\" )\n\t\t\t.attr( \"tabindex\", \"-1\" )\n\t\t\t.trigger( detailsInitEvent );\n\t\t$panel\n\t\t\t.find( \".mb-menu &amp;gt; li:first-child\" )\n\t\t\t.find( \".mb-item\" )\n\t\t\t.attr( \"tabindex\", \"0\" );\n\t},\n\n\t/**\n\t * @method menuIncrement\n\t * @param {jQuery object} $menuItems Collection of of menu items to move between\n\t * @param {jQuery object} $current Current menu item\n\t * @param {integer} indexChange Requested relative change to the menu item index\n\t */\n\tmenuIncrement = function( $menuItems, $current, indexChange ) {\n\t\tvar menuItemsLength = $menuItems.length,\n\t\t\tindex = $menuItems.index( $current ) + indexChange;\n\n\t\t// Correct out-of-range indexes\n\t\tindex = index === menuItemsLength ? 0 : index === -1 ? menuItemsLength - 1 : index;\n\n\t\t// Move to the new menu item\n\t\t$menuItems.eq( index ).trigger( focusEvent );\n\t},\n\n\t/**\n\t * @method menuClose\n\t * @param {jQuery DOM element} $elm Parent of the element to close\n\t * @param {boolean} removeActive Whether or not to keep the active class\n\t */\n\tmenuClose = function( $elm, removeActive ) {\n\t\t$elm\n\t\t\t.removeClass( \"sm-open\" )\n\t\t\t.children( \".open\" )\n\t\t\t.removeClass( \"open\" )\n\t\t\t.attr( {\n\t\t\t\t\"aria-hidden\": \"true\",\n\t\t\t\t\"aria-expanded\": \"false\"\n\t\t\t} )\n\n\t\t// Close nested submenus\n\t\t\t.find( \"details\" )\n\t\t\t.removeAttr( \"open\" )\n\t\t\t.children( \"ul\" )\n\t\t\t.attr( {\n\t\t\t\t\"aria-hidden\": \"true\",\n\t\t\t\t\"aria-expanded\": \"false\"\n\t\t\t} );\n\n\t\tif ( removeActive ) {\n\t\t\t$elm.removeClass( \"active\" );\n\t\t}\n\t},\n\n\t/**\n\t * @method menuDisplay\n\t * @param {jQuery DOM element} $elm The plugin element\n\t * @param {jQuery DOM element} $menu The menu to display\n\t */\n\tmenuDisplay = function( $elm, $menu ) {\n\t\tvar $menuLink = $menu.children( \"a\" );\n\n\t\tmenuClose( $elm.find( \".active\" ), true );\n\n\t\t$menu.addClass( \"active\" );\n\n\t\t// Ignore if doesn't have a submenu\n\t\tif ( $menuLink.attr( \"aria-haspopup\" ) === \"true\" ) {\n\n\t\t\t// Add the open state classes\n\t\t\t$menu\n\t\t\t\t.addClass( \"sm-open\" )\n\t\t\t\t.children( \".sm\" )\n\t\t\t\t.addClass( \"open\" )\n\t\t\t\t.attr( {\n\t\t\t\t\t\"aria-hidden\": \"false\",\n\t\t\t\t\t\"aria-expanded\": \"true\"\n\t\t\t\t} );\n\t\t}\n\t},\n\n\t/**\n\t * Searches for the next link that has link text starting with a specific letter\n\t * @method selectByLetter\n\t * @param {integer} charCode The charCode of the letter to search for\n\t * @param {DOM elements} links Collection of links to search\n\t */\n\tselectByLetter = function( charCode, links ) {\n\t\tvar len = links.length,\n\t\t\tkeyChar = String.fromCharCode( charCode ),\n\t\t\tlink, i;\n\n\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\tlink = links[ i ];\n\t\t\tif ( link.innerHTML.charAt( 0 ) === keyChar ) {\n\t\t\t\t$( link ).trigger( focusEvent );\n\t\t\t\treturn true;\n\t\t\t}\n\t\t}\n\n\t\treturn false;\n\t};\n\n// Bind the events of the plugin\n$document.on( \"timerpoke.wb \" + initEvent + \" ajax-fetched.wb ajax-failed.wb\", selector, function( event ) {\n\n\tvar eventType = event.type,\n\t\telm, $elm;\n\n\tswitch ( eventType ) {\n\t\tcase \"ajax-fetched\":\n\t\tcase \"ajax-failed\":\n\t\t\telm = event.target;\n\n\t\t\t// Filter out any events triggered by descendants\n\t\t\tif ( event.currentTarget === elm ) {\n\t\t\t\t$elm = $( elm );\n\n\t\t\t\t// Only replace the menu if there isn't an error\n\t\t\t\tonAjaxLoaded(\n\t\t\t\t\t$elm,\n\t\t\t\t\teventType === \"ajax-fetched\" ? event.fetch.pointer : $elm\n\t\t\t\t);\n\t\t\t}\n\t\t\treturn false;\n\n\t\tcase \"timerpoke\":\n\t\tcase \"wb-init\":\n\t\t\tinit( event );\n\t\t\tbreak;\n\t}\n\n\t/*\n\t * Since we are working with events we want to ensure that we are being passive about our control,\n\t * so returning true allows for events to always continue\n\t */\n\treturn true;\n} );\n\n$document.on( \"mouseleave\", selector + \" .menu\", function( event ) {\n\tvar $currentTarget = $( event.currentTarget );\n\n\t// Clear the timeout for open/closing menus\n\tclearTimeout( globalTimeout );\n\n\tglobalTimeout = setTimeout( function() {\n\t\tmenuClose( $currentTarget.find( \".active\" ), true );\n\t}, hoverDelay );\n} );\n\n// Prevent opening another menu if mouse re-enters already opened menu\n$document.on( \"mouseenter\", selector + \" .sm\", function() {\n\tif ( $( this ).attr( \"aria-expanded\" ) === \"true\" ) {\n\t\tclearTimeout( globalTimeout );\n\t}\n} );\n\n// Touchscreen \"touches\" on menubar items should close the submenu if it is open\n$document.on( \"click\", selector + \" .item[aria-haspopup=true]\", function( event ) {\n\tvar which = event.which,\n\t\t$this, $parent;\n\n\t// Ignore middle and right mouse buttons\n\tif ( !which || which === 1 ) {\n\t\tevent.preventDefault();\n\t\t$this = $( this );\n\t\t$parent = $this.parent();\n\n\t\t// Open the submenu if it is closed\n\t\tif ( !$parent.hasClass( \"sm-open\" ) ) {\n\t\t\t$this.trigger( \"focusin\" );\n\t\t}\n\t}\n} );\n\n// Click on menu items with submenus should open and close those submenus\n$document.on( \"click\", selector + \" [role=menu] [aria-haspopup=true]\", function( event ) {\n\tvar menuItem = event.currentTarget,\n\t\tparent = menuItem.parentNode,\n\t\tsubmenu = parent.getElementsByTagName( \"ul\" )[ 0 ],\n\t\tisOpen = submenu.getAttribute( \"aria-hidden\" ) === \"false\",\n\t\tmenuItemOffsetTop, menuContainer;\n\n\t// Close any other open menus\n\tif ( !isOpen ) {\n\t\t$( parent )\n\t\t\t.closest( \"[role^='menu']\" )\n\t\t\t.find( \"[aria-hidden=false]\" )\n\t\t\t.parent()\n\t\t\t.find( \"[aria-haspopup=true]\" )\n\t\t\t.not( menuItem )\n\t\t\t.trigger( \"click\" );\n\n\t\t// Ensure the opened menu is in view if in a mobile panel\n\t\tmenuContainer = document.getElementById( \"mb-pnl\" );\n\t\tmenuItemOffsetTop = menuItem.offsetTop;\n\t\tif ( $.contains( menuContainer, menuItem ) &amp;amp;&amp;amp;\n\t\t\tmenuItemOffsetTop &amp;lt; menuContainer.scrollTop ) {\n\n\t\t\tmenuContainer.scrollTop = menuItemOffsetTop;\n\t\t}\n\t}\n\n\tsubmenu.setAttribute( \"aria-expanded\", !isOpen );\n\tsubmenu.setAttribute( \"aria-hidden\", isOpen );\n} );\n\n// Clicks and touches outside of menus should close any open menus\n$document.on( \"click\", function( event ) {\n\tvar $openMenus,\n\t\twhich = event.which;\n\n\t// Ignore middle and right mouse buttons\n\tif ( event.type === \"\" || ( !which || which === 1 ) ) {\n\t\t$openMenus = $( selector + \" .sm-open\" );\n\t\tif ( $openMenus.length !== 0 &amp;amp;&amp;amp;\n\t\t\t$( event.target ).closest( selector ).length === 0 ) {\n\n\t\t\tmenuClose( $openMenus, true );\n\t\t}\n\t}\n} );\n\n$document.on( \"mouseover focusin\", selector + \" .item\", function( event ) {\n\tvar $elm = $( event.currentTarget ),\n\t\t$parent = $elm.parent(),\n\t\t$container = $parent.closest( selector );\n\n\t// Clear the timeout for open/closing menus\n\tclearTimeout( globalTimeout );\n\n\tif ( event.type === \"focusin\" ) {\n\t\tmenuDisplay( $container, $parent );\n\t} else {\n\t\tglobalTimeout = setTimeout( function() {\n\t\t\tmenuDisplay( $container, $parent );\n\t\t}, hoverDelay );\n\t}\n} );\n\n/*\n * Keyboard bindings\n */\n$document.on( \"keydown\", selector + \" [role=menuitem]\", function( event ) {\n\tvar menuItem = event.currentTarget,\n\t\twhich = event.which,\n\t\t$menuItem = $( menuItem ),\n\t\thasPopup = $menuItem.attr( \"aria-haspopup\" ) === \"true\",\n\t\t$menu = $menuItem.parent().closest( \"[role^='menu']\" ),\n\t\tinMenuBar = $menu.attr( \"role\" ) === \"menubar\",\n\t\t$menuLink, $parentMenu, $parent, $subMenu, result,\n\t\tisOpen, menuItemOffsetTop, menuContainer;\n\n\t// Define keycodes. (Make const when WET supports ES6)\n\tvar TAB_KC = 9,\n\t\tENTER_KC = 13,\n\t\tESC_KC = 27,\n\t\tLEFT_KC = 37,\n\t\tUP_KC = 38,\n\t\tRIGHT_KC = 39,\n\t\tDOWN_KC = 40,\n\t\tSPACE_KC = 32;\n\n\tif ( !( event.ctrlKey || event.altKey || event.metaKey ) ) {\n\n\t\t// Tab key = Hide all sub-menus\n\t\tif ( which === TAB_KC ) {\n\t\t\tmenuClose( $( selector + \" .active\" ), true );\n\n\t\t//Enter or spacebar on a link = follow the link and close menus\n\t\t} else if ( menuItem.nodeName === \"A\" &amp;amp;&amp;amp; menuItem.hasAttribute( \"href\" ) &amp;amp;&amp;amp;\n\t\t\t( which === ENTER_KC || which === SPACE_KC ) ) {\n\n\t\t\tevent.preventDefault();\n\t\t\tmenuItem.click();\n\t\t\tmenuClose( $( selector + \" .active\" ), true );\n\n\t\t// Menu item is within a menu bar\n\t\t} else if ( inMenuBar ) {\n\n\t\t\t// Left / right arrow = Previous / next menu item\n\t\t\tif ( which === LEFT_KC || which === RIGHT_KC ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tmenuIncrement(\n\t\t\t\t\t$menu.find( \"&amp;gt; li &amp;gt; a\" ),\n\t\t\t\t\t$menuItem,\n\t\t\t\t\twhich === LEFT_KC ? -1 : 1\n\t\t\t\t);\n\n\t\t\t// Enter sub-menu\n\t\t\t} else if ( hasPopup &amp;amp;&amp;amp; ( which === ENTER_KC || which === SPACE_KC || which === UP_KC || which === DOWN_KC ) ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\t$parent = $menuItem.parent();\n\t\t\t\t$subMenu = $parent.find( \".sm\" );\n\n\t\t\t\t// Open the submenu if it is not already open\n\t\t\t\tif ( !$subMenu.hasClass( \"open\" ) ) {\n\t\t\t\t\tmenuDisplay( $menu.closest( selector ), $parent );\n\t\t\t\t}\n\n\t\t\t\t// Set focus on the first submenu item\n\t\t\t\t$subMenu.children( \"li\" ).eq( 0 ).find( menuItemSelector ).trigger( focusEvent );\n\n\t\t\t// Hide sub-menus and set focus\n\t\t\t} else if ( which === ESC_KC ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tmenuClose( $menu.closest( selector ).find( \".active\" ), false );\n\n\t\t\t// Letters only\n\t\t\t} else if ( which &amp;gt; 64 &amp;amp;&amp;amp; which &amp;lt; 91 ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tselectByLetter(\n\t\t\t\t\twhich,\n\t\t\t\t\t$menuItem.parent().find( \"&amp;gt; ul &amp;gt; li &amp;gt; a, &amp;gt; ul &amp;gt; li &amp;gt; details &amp;gt; summary\" ).get()\n\t\t\t\t);\n\t\t\t}\n\n\t\t// Menu item is not within a menu bar\n\t\t} else {\n\n\t\t\t// Up / down arrow = Previous / next menu item\n\t\t\tif ( which === UP_KC || which === DOWN_KC ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\tmenuIncrement(\n\t\t\t\t\t$menu.children( \"li\" ).find( menuItemSelector ),\n\t\t\t\t\t$menuItem,\n\t\t\t\t\twhich === UP_KC ? -1 : 1\n\t\t\t\t);\n\n\t\t\t// Enter, space, or right arrow with a submenu\n\t\t\t} else if ( hasPopup &amp;amp;&amp;amp; ( which === ENTER_KC || which === SPACE_KC || which === RIGHT_KC ) ) {\n\t\t\t\t$parent = $menuItem.parent();\n\n\t\t\t\t// Prevent handling by details.js polyfill\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t\tevent.preventDefault();\n\n\t\t\t\t// If the menu item is a summary element\n\t\t\t\tif ( menuItem.nodeName.toLowerCase( \"summary\" ) ) {\n\t\t\t\t\tisOpen = !!$parent.attr( \"open\" );\n\n\t\t\t\t\t// Close any other open menus\n\t\t\t\t\tif ( !isOpen ) {\n\t\t\t\t\t\t$( parent )\n\t\t\t\t\t\t\t.closest( \"[role^='menu']\" )\n\t\t\t\t\t\t\t.find( \"[aria-hidden=false]\" )\n\t\t\t\t\t\t\t.parent()\n\t\t\t\t\t\t\t.find( \"[aria-haspopup=true]\" )\n\t\t\t\t\t\t\t.not( menuItem )\n\t\t\t\t\t\t\t.trigger( \"click\" );\n\n\t\t\t\t\t\t// Ensure the opened menu is in view if in a mobile panel\n\t\t\t\t\t\tmenuContainer = document.getElementById( \"mb-pnl\" );\n\t\t\t\t\t\tmenuItemOffsetTop = menuItem.offsetTop;\n\t\t\t\t\t\tif ( $.contains( menuContainer, menuItem ) &amp;amp;&amp;amp;\n\t\t\t\t\t\t\tmenuItemOffsetTop &amp;lt; menuContainer.scrollTop ) {\n\n\t\t\t\t\t\t\tmenuContainer.scrollTop = menuItemOffsetTop;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Ensure the menu is opened or stays open\n\t\t\t\t\t\t$menuItem.trigger( \"click\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Update the WAI-ARIA states and move focus to\n\t\t\t\t\t// the first submenu item\n\t\t\t\t\t$parent.children( \"ul\" )\n\t\t\t\t\t\t.attr( {\n\t\t\t\t\t\t\t\"aria-expanded\": \"true\",\n\t\t\t\t\t\t\t\"aria-hidden\": \"false\"\n\t\t\t\t\t\t} )\n\t\t\t\t\t\t.find( \"[role=menuitem]:first\" )\n\t\t\t\t\t\t.trigger( focusEvent );\n\t\t\t\t}\n\n\t\t\t// Escape, left / right arrow without a submenu\n\t\t\t} else if ( which === ESC_KC || which === LEFT_KC || which === RIGHT_KC ) {\n\t\t\t\t$parent = $menu.parent();\n\t\t\t\t$parentMenu = $parent.closest( \"[role^='menu']\" );\n\t\t\t\tif ( which === LEFT_KC || which === RIGHT_KC ) {\n\t\t\t\t\tevent.preventDefault();\n\t\t\t\t}\n\n\t\t\t\t// If the parent menu is a menubar\n\t\t\t\tif ( $parentMenu.attr( \"role\" ) === \"menubar\" ) {\n\t\t\t\t\t$menuLink = $menu.siblings( \"a\" );\n\n\t\t\t\t\t// Escape key = Close menu and return to menu bar item\n\t\t\t\t\tif ( which === ESC_KC ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t$menuLink.trigger( focusEvent );\n\n\t\t\t\t\t\t// Close the menu but keep the referring link active\n\t\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\t\tmenuClose( $menuLink.parent(), false );\n\t\t\t\t\t\t}, 100 );\n\n\t\t\t\t\t// Left / right key = Next / previous menu bar item\n\t\t\t\t\t} else if ( $parentMenu.attr( \"role\" ) === \"menubar\" ) {\n\t\t\t\t\t\tmenuIncrement(\n\t\t\t\t\t\t\t$parentMenu.find( \"&amp;gt; li &amp;gt; a\" ),\n\t\t\t\t\t\t\t$menuLink,\n\t\t\t\t\t\t\twhich === LEFT_KC ? -1 : 1\n\t\t\t\t\t\t);\n\t\t\t\t\t}\n\n\t\t\t\t// Escape or left arrow: Go up a level if there is a higher-level\n\t\t\t\t// menu or close the current submenu if there isn't\n\t\t\t\t} else if ( which !== RIGHT_KC ) {\n\t\t\t\t\t$subMenu = $parentMenu.length !== 0 ? $menu : $menuItem;\n\n\t\t\t\t\t// There is a higher-level menu\n\t\t\t\t\tif ( $parentMenu.length !== 0 ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t$menu.closest( \"li\" )\n\t\t\t\t\t\t\t.find( menuItemSelector )\n\t\t\t\t\t\t\t.trigger( \"click\" )\n\t\t\t\t\t\t\t.trigger( focusEvent );\n\n\t\t\t\t\t// No higher-level menu but the current submenu is open\n\t\t\t\t\t} else if ( $menuItem.parent().children( \"ul\" ).attr( \"aria-hidden\" ) === \"false\" ) {\n\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t$menuItem\n\t\t\t\t\t\t\t.trigger( \"click\" )\n\t\t\t\t\t\t\t.trigger( focusEvent );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t// Select a menu item in the current menu by the first letter\n\t\t\t} else if ( which &amp;gt; 64 &amp;amp;&amp;amp; which &amp;lt; 91 ) {\n\t\t\t\tevent.preventDefault();\n\t\t\t\t$parent = $menuItem.closest( \"li\" );\n\n\t\t\t\t// Try to find a match in the next siblings\n\t\t\t\tresult = selectByLetter(\n\t\t\t\t\twhich,\n\t\t\t\t\t$parent.nextAll().find( menuItemSelector ).get()\n\t\t\t\t);\n\n\t\t\t\t// If couldn't find a match, try the previous siblings\n\t\t\t\tif ( !result ) {\n\t\t\t\t\tresult = selectByLetter(\n\t\t\t\t\t\twhich,\n\t\t\t\t\t\t$parent.prevAll().find( menuItemSelector ).get()\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Prevent Firefox from double-triggering menu behaviour\n$document.on( \"keyup\", selector + \" [role=menuitem]\", function( event ) {\n\tevent.preventDefault();\n\treturn false;\n} );\n\n// Close the mobile panel if switching to medium, large or extra large view\n$document.on( \"mediumview.wb largeview.wb xlargeview.wb\", function() {\n\tvar mobilePanel = document.getElementById( \"mb-pnl\" );\n\tif ( mobilePanel &amp;amp;&amp;amp; mobilePanel.getAttribute( \"aria-hidden\" ) === \"false\" ) {\n\t\t$( mobilePanel ).trigger( {\n\t\t\ttype: ( \"close\" ),\n\t\t\tnamespace: \"wb-overlay\",\n\t\t\tnoFocus: true\n\t\t} );\n\t}\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, document, wb );\n\n/**\n * @title WET-BOEW Multimedia PLayer\n * @overview An accessible multimedia player for  and  tags\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author WET Community\n */\n/* globals YT */\n( function( $, DOMPurify, window, wb, undef ) {\n\"use strict\";\n\n/* Local scoped variables*/\nvar componentName = \"wb-mltmd\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tctrls = selector + \" .wb-mm-ctrls\",\n\tdispCtrls = selector + \" .display,\" + ctrls,\n\ttemplate,\n\ti18n, i18nText,\n\tyoutubeReadyEvent = \"ready.youtube\",\n\tcaptionsLoadedEvent = \"ccloaded\" + selector,\n\tcaptionsLoadFailedEvent = \"ccloadfail\" + selector,\n\tcaptionsVisibleChangeEvent = \"ccvischange\" + selector,\n\trenderUIEvent = \"renderui\" + selector,\n\tinitializedEvent = \"inited\" + selector,\n\tyoutubeEvent = \"youtube\" + selector,\n\tresizeEvent = \"resize\" + selector,\n\ttemplateLoadedEvent = \"templateloaded\" + selector,\n\tcuepointEvent = \"cuepoint\" + selector,\n\tcaptionClass = \"cc_on\",\n\tfirstPlayClass = \"played\",\n\tdefaultCaptions = false,\n\tmultimediaEvents = [\n\t\t\"durationchange\",\n\t\t\"playing\",\n\t\t\"pause\",\n\t\t\"ended\",\n\t\t\"volumechange\",\n\t\t\"timeupdate\",\n\t\t\"waiting\",\n\t\t\"canplay\",\n\t\t\"seeked\",\n\t\t\"progress\",\n\t\tcaptionsLoadedEvent,\n\t\tcaptionsLoadFailedEvent,\n\t\tcaptionsVisibleChangeEvent,\n\t\tcuepointEvent\n\t].join( \" \" ),\n\t$document = wb.doc,\n\t$window = wb.win,\n\n\t/**\n\t * @function init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar eventTarget = wb.init( event, componentName, selector );\n\n\t\tif ( eventTarget ) {\n\n\t\t\t// Only initialize the i18nText once\n\t\t\tif ( !i18nText ) {\n\n\t\t\t\t// YT workaround for when played inside a modal dialog, like with lightbox\n\t\t\t\t//\n\t\t\t\t// the issue is when the iFrame is moved, it reloads and then it doesn't emit the right event to\n\t\t\t\t// adjust the WET multimedia controller to represent its current state.\n\t\t\t\t//\n\t\t\t\t// This needs to be executed only once, that is why it is in the i18nText conditional\n\t\t\t\twindow.addEventListener( \"message\", function( e ) {\n\t\t\t\t\tvar data, frames, i, i_len, i_cache;\n\n\t\t\t\t\t// Ensure we don't conflict with other postMessage listener\n\t\t\t\t\ttry {\n\t\t\t\t\t\tdata = JSON.parse( e.data );\n\n\t\t\t\t\t\t// Only for a specific YT message\n\t\t\t\t\t\tif ( data.event &amp;amp;&amp;amp; data.event === \"infoDelivery\" &amp;amp;&amp;amp; data.info &amp;amp;&amp;amp; data.info.playerState ) {\n\n\t\t\t\t\t\t\t// Find the iFrame and evaluate if it needs to be reposted\n\t\t\t\t\t\t\tframes = document.getElementsByTagName( \"iframe\" );\n\n\t\t\t\t\t\t\ti_len = frames.length;\n\t\t\t\t\t\t\tfor ( i = 0; i &amp;lt; i_len; i++ ) {\n\t\t\t\t\t\t\t\ti_cache = frames[ i ];\n\t\t\t\t\t\t\t\tif ( i_cache.dataset.L2 &amp;amp;&amp;amp; i_cache.contentWindow === e.source  ) {\n\n\t\t\t\t\t\t\t\t\t// Prepare the event data and emulate the YT object for our event management need\n\t\t\t\t\t\t\t\t\tyouTubeEvents.call( i_cache, {\n\t\t\t\t\t\t\t\t\t\ttarget: i_cache.parentElement.parentElement.object,\n\t\t\t\t\t\t\t\t\t\tdata: data.info.playerState\n\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} catch ( err ) {\n\n\t\t\t\t\t\t/* swallow error */\n\t\t\t\t\t}\n\t\t\t\t} );\n\n\t\t\t\t//\n\t\t\t\t// END YT workaround\n\t\t\t\t//\n\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\tplay: i18n( \"mmp-play\" ),\n\t\t\t\t\tpause: i18n( \"pause\" ),\n\t\t\t\t\tvolume: i18n( \"volume\" ),\n\t\t\t\t\tcc_on: i18n( \"cc\", \"on\" ),\n\t\t\t\t\tcc_off: i18n( \"cc\", \"off\" ),\n\t\t\t\t\tcc_error: i18n( \"cc-err\" ),\n\t\t\t\t\tfs: i18n( \"fs\" ),\n\t\t\t\t\tmute_on: i18n( \"mute\", \"on\" ),\n\t\t\t\t\tmute_off: i18n( \"mute\", \"off\" ),\n\t\t\t\t\tduration: i18n( \"dur\" ),\n\t\t\t\t\tposition: i18n( \"pos\" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tif ( template === undef ) {\n\t\t\t\ttemplate = \"\";\n\t\t\t\t$( eventTarget ).trigger( {\n\t\t\t\t\ttype: \"ajax-fetch.wb\",\n\t\t\t\t\tfetch: {\n\t\t\t\t\t\turl: wb.getPath( \"/assets\" ) + \"/mediacontrols.html\"\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t} else if ( template !== \"\" ) {\n\t\t\t\t$( eventTarget ).trigger( templateLoadedEvent );\n\t\t\t}\n\t\t}\n\t},\n\n\t/* helper functions*/\n\n\t/**\n\t * @method formatTime\n\t * @description format a number of seconds to SMTPE Timecode format (HH:MM:SS.FF)\n\t * @param {Float} time The time to format\n\t * @returns {String} the formatted time\n\t */\n\tformatTime = function( time ) {\n\t\tvar index = 2,\n\t\t\ttimecode = \"\",\n\t\t\tsecondsIn, current, pad;\n\n\t\tpad = function( number, digits ) {\n\t\t\treturn new Array( Math.max( digits - String( number ).length + 1, 0 ) ).join( 0 ) + number;\n\t\t};\n\n\t\ttime = Math.floor( time );\n\n\t\t//Loop to extract hours, minutes and seconds\n\t\twhile ( index &amp;gt;= 0 ) {\n\n\t\t\t//Get the number of seconds for the current iteration (hour, minute or second)\n\t\t\tsecondsIn = Math.pow( 60, index );\n\t\t\tcurrent = Math.floor( time / secondsIn );\n\n\t\t\tif ( timecode !== \"\" ) {\n\t\t\t\ttimecode += \":\";\n\t\t\t}\n\n\t\t\ttimecode += pad( current, 2 );\n\t\t\ttime -= secondsIn * current;\n\t\t\tindex -= 1;\n\t\t}\n\t\treturn timecode;\n\t},\n\n\t/**\n\t * @method parseTime\n\t * @description parse an SMTPE Timecode string (HH:MM:SS.FF) or duration (45s) and returns the number of seconds for the timecode\n\t * @param {String} time The timecode or duration string to parse\n\t * @returns {Float} the number of seconds in time\n\t */\n\tparseTime = function( time ) {\n\t\tvar i, parts, timeStringPortion, partLength, seconds;\n\n\t\tif ( time !== undef ) {\n\t\t\tif ( time.charAt( time.length - 1 ) === \"s\" ) {\n\n\t\t\t\t//Duration parsing\n\t\t\t\treturn parseFloat( time.substring( 0, time.length - 1 ) );\n\t\t\t} else {\n\n\t\t\t\t//SMTPE Timecode Parsing\n\t\t\t\tparts = time.split( \":\" ).reverse();\n\t\t\t\tseconds = 0;\n\n\t\t\t\tfor ( i = 0, partLength = parts.length; i &amp;lt; partLength; i += 1 ) {\n\t\t\t\t\ttimeStringPortion = i === 0 ?\n\t\t\t\t\t\tparseFloat( parts[ i ] ) :\n\t\t\t\t\t\tparseInt( parts[ i ], 10 );\n\t\t\t\t\tseconds += timeStringPortion * Math.pow( 60, i );\n\t\t\t\t}\n\t\t\t\treturn seconds;\n\t\t\t}\n\t\t}\n\t\treturn -1;\n\t},\n\n\t/*\n\t * Performant micro templater\n\t * @credit: https://github.com/premasagar/tim/blob/master/tinytim.js\n\t * @todo: caching\n\t */\n\ttmpl = ( function() {\n\t\tvar start = \"{{\",\n\t\t\tend = \"}}\",\n\n\t\t\t// e.g. config.person.name\n\t\t\tpath = \"[a-z0-9_$][\\\\.a-z0-9_]*\",\n\t\t\tpattern = new RegExp( start + \"\\\\s*(\" + path + \")\\\\s*\" + end, \"gi\" );\n\t\treturn function( template, data ) {\n\n\t\t\t// Merge data into the template string\n\t\t\treturn template.replace( pattern, function( tag, token ) {\n\t\t\t\tvar path = token.split( \".\" ),\n\t\t\t\t\tlen = path.length,\n\t\t\t\t\tlookup = data,\n\t\t\t\t\ti = 0;\n\t\t\t\tfor ( ; i &amp;lt; len; i += 1 ) {\n\t\t\t\t\tlookup = lookup[ path[ i ] ];\n\n\t\t\t\t\t// Property not found\n\t\t\t\t\tif ( lookup === undef ) {\n\t\t\t\t\t\tthrow \"tim: '\" + path[ i ] + \"' not found in \" + tag;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Return the required value\n\t\t\t\t\tif ( i === len - 1 ) {\n\t\t\t\t\t\treturn lookup;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t};\n\t}() ),\n\n\t/**\n\t * @method parseHtml\n\t * @description parse an HTML fragment and extract embed captions\n\t * @param {String} content The HTML fragment containing the captions\n\t * @returns {Array} An array of captions objects (ex: {text: \"Caption\", begin: 0, end :10})\n\t */\n\tparseHtml = function( content ) {\n\t\tvar captions = [],\n\t\t\tcaptionSelector = \".wb-tmtxt\",\n\t\t\tcaptionElements = content.find( captionSelector ),\n\t\t\tlen = captionElements.length,\n\t\t\ti, captionElement, json, begin, end;\n\n\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\tcaptionElement = $( captionElements[ i ] );\n\t\t\tbegin = -1;\n\t\t\tend = -1;\n\n\t\t\tif ( captionElement.attr( \"data-begin\" ) !== undef ) {\n\t\t\t\tbegin = parseTime( captionElement.attr( \"data-begin\" ) );\n\t\t\t\tend = captionElement.attr( \"data-end\" ) !== undef ?\n\t\t\t\t\tparseTime( captionElement.attr( \"data-end\" ) ) :\n\t\t\t\t\tparseTime( captionElement.attr( \"data-dur\" ) ) + begin;\n\t\t\t} else if ( captionElement.attr( \"data\" ) !== undef ) {\n\t\t\t\tjson = captionElement.attr( \"data\" )\n\t\t\t\t\t.replace( /(begin|dur|end)/g, \"\\\"$1\\\"\" )\n\t\t\t\t\t.replace( /'/g, \"\\\"\" );\n\t\t\t\tjson = $.parseJSON( json );\n\t\t\t\tbegin = parseTime( json.begin );\n\t\t\t\tend = json.end !== undef ?\n\t\t\t\t\tparseTime( json.end ) :\n\t\t\t\t\tparseTime( json.dur ) + begin;\n\t\t\t}\n\n\t\t\t//Removes nested captions if an\n\t\t\tcaptionElement = captionElement.clone();\n\t\t\tcaptionElement.find( captionSelector ).detach();\n\n\t\t\tcaptions[ captions.length ] = {\n\t\t\t\ttext: captionElement.html(),\n\t\t\t\tbegin: begin,\n\t\t\t\tend: end\n\t\t\t};\n\t\t}\n\t\treturn captions;\n\t},\n\n\t/**\n\t * @method parseXml\n\t * @description parse an TTML (Xml) document and extract captions\n\t * @param {String} content The TTML fragment containing the captions\n\t * @returns {Array} An array of captions objects (ex: {text: \"Caption\", begin: 0, end :10})\n\t */\n\tparseXml = function( content ) {\n\t\tvar captions = [],\n\t\t\tcaptionSelector = \"[begin]\",\n\t\t\tparser = new DOMParser(),\n\t\t\tdoc = parser.parseFromString( content, \"application/xml\" ),\n\t\t\tcaptionElements = doc.querySelectorAll( captionSelector ),\n\t\t\tlen = captionElements.length,\n\t\t\ti, captionElement, begin, end;\n\n\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\tcaptionElement = captionElements[ i ];\n\n\t\t\tbegin = parseTime( captionElement.getAttribute( \"begin\" ) + \"\" );\n\t\t\tend = captionElement.hasAttribute( \"end\" ) ?\n\t\t\t\tparseTime( captionElement.getAttribute( \"end\" ) + \"\" ) :\n\t\t\t\tparseTime( captionElement.getAttribute( \"dur\" ) + \"\" ) + begin;\n\n\t\t\tcaptions[ captions.length ] = {\n\t\t\t\ttext: DOMPurify.sanitize( captionElement.textContent ),\n\t\t\t\tbegin: begin,\n\t\t\t\tend: end\n\t\t\t};\n\t\t}\n\t\treturn captions;\n\t},\n\n\t/**\n\t * @method loadCaptionsExternal\n\t * @description Loads captions from an external source (HTML embed or TTML)\n\t * @param {Object} elm The jQuery object for the multimedia player loading the captions\n\t * @param {String} url The url for the captions resource to load\n\t * @fires ccloaded.wb-mltmd\n\t * @fires ccloadfail.wb-mltmd\n\t */\n\tloadCaptionsExternal = function( elm, url ) {\n\t\t$.ajax( {\n\t\t\turl: url,\n\t\t\tdataType: \"html\",\n\n\t\t\t//Filters out images and objects from the content to avoid loading them\n\t\t\tdataFilter: function( data ) {\n\t\t\t\treturn data.replace( /]*&amp;gt;/g, \"\" );\n\t\t\t},\n\t\t\tsuccess: function( data ) {\n\n\t\t\t\tvar captionItems;\n\n\t\t\t\tif ( data.indexOf( \"= caption.begin &amp;amp;&amp;amp; seconds &amp;lt;= caption.end ) {\n\t\t\t\tarea.html( $( \"\n\" + caption.text + \"\" ) );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * @method playerApi\n\t * @description Normalizes the calls to the HTML5 media API\n\t * @param {String} fn The function to call\n\t * @param {object} args The arguments to send to the function call\n\t */\n\tplayerApi = function( fn, args ) {\n\t\tvar $this, method;\n\n\t\tswitch ( fn ) {\n\t\t\tcase \"play\":\n\t\t\t\ttry {\n\t\t\t\t\tthis.object.play();\n\t\t\t\t} catch ( ex ) {\n\t\t\t\t\tthis.object.doPlay();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"pause\":\n\t\t\t\ttry {\n\t\t\t\t\tthis.object.pause();\n\t\t\t\t} catch ( ex ) {\n\t\t\t\t\tthis.object.doPause();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"getCaptionsVisible\":\n\t\t\t\treturn $( this ).hasClass( captionClass );\n\t\t\tcase \"setCaptionsVisible\":\n\t\t\t\t$this = $( this );\n\t\t\t\tif ( args ) {\n\t\t\t\t\t$this.addClass( captionClass );\n\t\t\t\t} else {\n\t\t\t\t\t$this.removeClass( captionClass );\n\t\t\t\t}\n\t\t\t\t$this.trigger( captionsVisibleChangeEvent );\n\t\t\t\tbreak;\n\t\t\tcase \"fullscreen\":\n\t\t\t\tif ( this.object.requestFullscreen ) {\n\t\t\t\t\tthis.object.requestFullscreen();\n\t\t\t\t} else if ( this.object.webkitRequestFullscreen ) { /* Safari */\n\t\t\t\t\tthis.object.webkitRequestFullscreen();\n\t\t\t\t} else if ( this.object.msRequestFullscreen ) { /* IE11 */\n\t\t\t\t\tthis.object.msRequestFullscreen();\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase \"getBuffering\":\n\t\t\t\treturn this.object.buffering || false;\n\t\t\tcase \"setBuffering\":\n\t\t\t\tthis.object.buffering = args;\n\t\t\t\tbreak;\n\t\t\tcase \"getPreviousTime\":\n\t\t\t\treturn this.object.previousTime;\n\t\t\tcase \"setPreviousTime\":\n\t\t\t\tthis.object.previousTime = args;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tmethod = fn.charAt( 3 ).toLowerCase() + fn.substr( 4 );\n\t\t\t\tswitch ( fn.substr( 0, 3 ) ) {\n\t\t\t\t\tcase \"get\":\n\t\t\t\t\t\treturn typeof this.object[ method ] !== \"function\" ?\n\t\t\t\t\t\t\tthis.object[ method ] :\n\t\t\t\t\t\t\tthis.object[ method ]();\n\t\t\t\t\tcase \"set\":\n\t\t\t\t\t\ttypeof this.object[ method ] !== \"function\" ?\n\t\t\t\t\t\t\tthis.object[ method ] = args :\n\t\t\t\t\t\t\tthis.object[ fn ]( args );\n\t\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * @method youTubeApi\n\t * @description Normalizes the calls to the YouTube API\n\t * @param {String} fn The function to call\n\t * @param {object} args The arguments to send to the function call\n\t */\n\tyouTubeApi = function( fn, args ) {\n\t\tvar $media = $( this.object.getIframe() ),\n\t\t\tstate;\n\n\t\tswitch ( fn ) {\n\t\t\tcase \"play\":\n\t\t\t\tthis.object.wasMutedPlay = this.object.isMuted();\n\t\t\t\treturn this.object.playVideo();\n\t\t\tcase \"pause\":\n\t\t\t\treturn this.object.pauseVideo();\n\t\t\tcase \"getPaused\":\n\t\t\t\tstate = this.object.getPlayerState();\n\t\t\t\treturn state === -1 || state === 0 || state === 2 || state === 5;\n\t\t\tcase \"getPlayed\":\n\t\t\t\treturn this.object.getPlayerState() &amp;gt; -1;\n\t\t\tcase \"getEnded\":\n\t\t\t\treturn this.object.getPlayerState() === 0;\n\t\t\tcase \"getDuration\":\n\t\t\t\treturn this.object.getDuration();\n\t\t\tcase \"getCurrentTime\":\n\t\t\t\treturn this.object.getCurrentTime();\n\t\t\tcase \"setCurrentTime\":\n\t\t\t\treturn this.object.seekTo( args, true );\n\t\t\tcase \"fullscreen\":\n\t\t\t\treturn this.object.getIframe().requestFullscreen();\n\t\t\tcase \"getMuted\":\n\t\t\t\tif ( !this.object.playedOnce &amp;amp;&amp;amp; this.object.wasMutedPlay ) {\n\t\t\t\t\tstate = this.object.wasMutedPlay;\n\t\t\t\t\tthis.object.playedOnce = true;\n\t\t\t\t\treturn state;\n\t\t\t\t} else {\n\t\t\t\t\treturn this.object.isMuted();\n\t\t\t\t}\n\t\t\tcase \"setMuted\":\n\t\t\t\tif ( args ) {\n\t\t\t\t\tthis.object.mute();\n\t\t\t\t} else {\n\t\t\t\t\tthis.object.unMute();\n\t\t\t\t}\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t$media.trigger( \"volumechange\" );\n\t\t\t\t}, ( wb.isReady ? 50 : 500 ) );\n\t\t\t\tbreak;\n\t\t\tcase \"getVolume\":\n\t\t\t\treturn this.object.getVolume() / 100;\n\t\t\tcase \"setVolume\":\n\t\t\t\tthis.object.setVolume( args * 100 );\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t$media.trigger( \"volumechange\" );\n\t\t\t\t}, 50 );\n\t\t\t\tbreak;\n\t\t\tcase \"getCaptionsVisible\":\n\t\t\t\treturn $( this ).hasClass( captionClass );\n\t\t\tcase \"setCaptionsVisible\":\n\t\t\t\tif ( args ) {\n\t\t\t\t\t$( this ).addClass( captionClass );\n\t\t\t\t\tthis.object.loadModule( \"cc\" );\n\t\t\t\t\tvar ccList = this.object.getOption( \"cc\", \"tracklist\" );\n\t\t\t\t\tif ( ccList &amp;amp;&amp;amp; ccList.length &amp;gt; 0 ) {\n\t\t\t\t\t\tthis.object.setOption( \"cc\", \"track\", { languageCode: this.object.getOption( \"cc\", \"tracklist\" )[ 0 ].languageCode } );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthis.object.loadModule( \"captions\" );\n\t\t\t\t\t\tvar captionsList = this.object.getOption( \"captions\", \"tracklist\" );\n\t\t\t\t\t\tif ( captionsList &amp;amp;&amp;amp; captionsList.length &amp;gt; 0 ) {\n\t\t\t\t\t\t\tthis.object.setOption( \"captions\", \"track\", { languageCode: this.object.getOption( \"captions\", \"tracklist\" )[ 0 ].languageCode } );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\t$( this ).removeClass( captionClass );\n\t\t\t\t\tthis.object.unloadModule( \"cc\" );\n\t\t\t\t\tthis.object.unloadModule( \"captions\" );\n\t\t\t\t}\n\t\t\t\t$( this ).trigger( captionsVisibleChangeEvent );\n\t\t}\n\t},\n\n\t/**\n\t * @method youTubeEvents\n\t * @description YouTube API event manager\n\t * @param {object} event The event object for the triggered event\n\t */\n\tyouTubeEvents = function( event ) {\n\t\tvar media = event.target.getIframe(),\n\t\t\t$media = $( media ),\n\t\t\ttimeline = function() {\n\t\t\t\t$media.trigger( \"timeupdate\" );\n\t\t\t},\n\t\t\t$mltmPlayerElm,\n\t\t\tmltmPlayerElm,\n\t\t\tisMuted,\n\t\t\tsettings,\n\t\t\t$ccButton;\n\n\t\tswitch ( event.data ) {\n\t\t\tcase null: // init\n\t\t\t\t$media\n\t\t\t\t\t.trigger( \"canplay\" )\n\t\t\t\t\t.trigger( \"durationchange\" );\n\n\t\t\t\t// Put video on mute if the video is muted on init, run once\n\t\t\t\t$mltmPlayerElm = $media.parentsUntil( selector ).parent();\n\t\t\t\tmltmPlayerElm = $mltmPlayerElm.get( 0 );\n\n\n\t\t\t\t// Mute the player, GUI\n\t\t\t\tif ( $mltmPlayerElm.data( \"putMutedOnInit\" ) ) {\n\t\t\t\t\tyouTubeApi.call( $mltmPlayerElm.get( 0 ), \"setMuted\", true );\n\t\t\t\t\t$mltmPlayerElm.data( \"putMutedOnInit\", false );\n\t\t\t\t}\n\n\t\t\t\t// Check if closed captions should be enabled by default\n\t\t\t\tsettings = wb.getData( mltmPlayerElm, componentName );\n\n\t\t\t\tif ( settings !== undef ) {\n\t\t\t\t\tif ( settings.closedCaptions !== null &amp;amp;&amp;amp; settings.closedCaptions === true ) {\n\t\t\t\t\t\tyouTubeApi.call( mltmPlayerElm, \"setCaptionsVisible\", true );\n\n\t\t\t\t\t\t$ccButton = $( mltmPlayerElm ).find( \".cc\" );\n\n\t\t\t\t\t\t$ccButton.attr( {\n\t\t\t\t\t\t\t\"title\": i18nText.cc_off,\n\t\t\t\t\t\t\t\"aria-pressed\": true\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t\tcase -1:\n\t\t\t\tevent.target.unMute();\n\t\t\t\t$media.trigger( \"durationchange\" );\n\t\t\t\tbreak;\n\t\t\tcase 0:\n\t\t\t\t$media.trigger( \"ended\" );\n\t\t\t\tmedia.timeline = clearInterval( media.timeline );\n\t\t\t\tbreak;\n\t\t\tcase 1: // play\n\n\t\t\t\t// Get the media player\n\t\t\t\t$mltmPlayerElm = $media.parentsUntil( selector ).parent();\n\t\t\t\tmltmPlayerElm = $mltmPlayerElm.get( 0 );\n\n\t\t\t\t// Need to be muted here\n\t\t\t\tisMuted = mltmPlayerElm.player( \"getMuted\" );\n\n\t\t\t\t// Reset the close caption state when iframe was reloaded\n\t\t\t\tif ( media.dataset.L2 ) {\n\t\t\t\t\tyouTubeApi.call( mltmPlayerElm, \"setCaptionsVisible\", $mltmPlayerElm.hasClass( captionClass ) );\n\t\t\t\t}\n\n\t\t\t\t// Play\n\t\t\t\t$media\n\t\t\t\t\t.trigger( \"canplay\" )\n\t\t\t\t\t.trigger( \"play\" )\n\t\t\t\t\t.trigger( \"playing\" );\n\n\t\t\t\t// Reset muted as needed because youtube onMute by default when playing\n\t\t\t\tif ( isMuted ) {\n\t\t\t\t\tyouTubeApi.call( mltmPlayerElm, \"setMuted\", true );\n\t\t\t\t}\n\n\t\t\t\tmedia.timeline = setInterval( timeline, 250 );\n\t\t\t\tbreak;\n\t\t\tcase 2:\n\t\t\t\t$media.trigger( \"pause\" );\n\t\t\t\tmedia.timeline = clearInterval( media.timeline );\n\t\t\t\tbreak;\n\t\t\tcase 3:\n\t\t\t\tmedia.timeline = clearInterval( media.timeline );\n\t\t\t\tbreak;\n\t\t}\n\t},\n\n\tyouTubeAPIReady = function() {\n\t\tvar youTube = window.youTube;\n\t\tyouTube.ready = true;\n\t\t$document.trigger( youtubeReadyEvent );\n\t},\n\n\tonResize = function() {\n\t\t$( selector + \" object, \" + selector + \" iframe, \" +  selector + \" video\" ).trigger( resizeEvent );\n\t};\n\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n$window.on( \"resize\", onResize );\n\n$document.on( \"ajax-fetched.wb \" + templateLoadedEvent, selector, function( event ) {\n\tvar $this = $( this );\n\n\tif ( event.type === \"ajax-fetched\" ) {\n\t\ttemplate = event.fetch.pointer.html();\n\n\t\t//Notify all player waiting for the controls to load\n\t\t$this = $( selector );\n\t}\n\n\t$this.trigger( {\n\t\ttype: initializedEvent\n\t} );\n} );\n\n$document.on( initializedEvent, selector, function( event ) {\n\tif ( event.namespace === componentName ) {\n\t\tvar $this = $( this ),\n\t\t\t$media = $this.children( \"audio, video\" ).eq( 0 ),\n\t\t\tcaptions = $media.children( \"track[kind='captions']\" ).attr( \"src\" ) || undef,\n\t\t\tid = $this.attr( \"id\" ),\n\t\t\tmId = $media.attr( \"id\" ) || id + \"-md\",\n\t\t\ttype = $media.is( \"audio\" ) ? \"audio\" : \"video\",\n\t\t\ttitle = $media.attr( \"title\" ) || \"\",\n\t\t\twidth = type === \"video\" ? $media.attr( \"width\" ) || $media.width() : 0,\n\t\t\theight = type === \"video\" ? $media.attr( \"height\" ) || $media.height() : 0,\n\t\t\tsettings = wb.getData( $this, componentName ),\n\t\t\tdata = $.extend( {\n\t\t\t\tmedia: $media,\n\t\t\t\tcaptions: captions,\n\t\t\t\tid: id,\n\t\t\t\tmId: mId,\n\t\t\t\ttype: type,\n\t\t\t\ttitle: title,\n\t\t\t\theight: height,\n\t\t\t\twidth: width\n\t\t\t}, i18nText ),\n\t\t\tmedia = $media.get( 0 ),\n\t\t\tyouTube = window.youTube,\n\t\t\turl,\n\t\t\ti18n = wb.i18n;\n\n\t\tif ( $media.attr( \"id\" ) === undef ) {\n\t\t\t$media.attr( \"id\", mId );\n\t\t}\n\n\t\tif ( settings !== undef ) {\n\t\t\tdata.shareUrl = settings.shareUrl;\n\t\t\tdata.fullscreen = settings.fullscreenBtn || false;\n\t\t\tdata.closedCaptions = settings.closedCaptions || false;\n\t\t\tif ( data.closedCaptions !== undef ) {\n\t\t\t\tdefaultCaptions = data.closedCaptions;\n\t\t\t}\n\t\t}\n\n\t\t$this.addClass( type );\n\n\t\tif ( $media.find( \"[type='video/youtube']\" ).length &amp;gt; 0 ) {\n\n\t\t\t// lets tweak some variables and start the load sequence\n\t\t\turl = wb.getUrlParts( $this.find( \"[type='video/youtube']\" ).attr( \"src\" ) );\n\n\t\t\t// lets set the flag for the call back\n\t\t\tdata.youTubeId = url.params.v ? url.params.v : url.pathname.substr( 1 );\n\n\t\t\t// Defaults config set on the video element\n\t\t\tdata.isInitMuted = $media.get( 0 ).muted;\n\n\t\t\t// Set default Youtube video dimensions if none specified\n\t\t\tif ( $media[ 0 ].width &amp;amp;&amp;amp; $media[ 0 ].height ) {\n\t\t\t\tdata.width = $media[ 0 ].width;\n\t\t\t\tdata.height = $media[ 0 ].height;\n\t\t\t} else {\n\t\t\t\tdata.width = 640;\n\t\t\t\tdata.height = 360;\n\t\t\t}\n\n\t\t\tif ( youTube.ready === false ) {\n\t\t\t\t$document.one( youtubeReadyEvent, function() {\n\t\t\t\t\t$this.trigger( youtubeEvent, data );\n\t\t\t\t} );\n\t\t\t} else {\n\t\t\t\t$this.trigger( youtubeEvent, data );\n\t\t\t}\n\n\t\t\t// finally lets load safely\n\t\t\treturn Modernizr.load( {\n\t\t\t\tload: \"https://www.youtube.com/iframe_api\",\n\n\t\t\t\t//possible solution for multimedia and doaction conflict in corporate network\n\t\t\t\tcomplete: function() {\n\n\t\t\t\t\t// Ensure that YouTube API is loading the iframe and if it fails, ensure that it will show a message, like accessing the web via our GC network.\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\tvar resources, arrIframesYt, $notifText;\n\n\t\t\t\t\t\tresources = window.performance.getEntriesByType( \"resource\" );\n\n\t\t\t\t\t\t/* get all the iframe initiators that have the same YT url id */\n\t\t\t\t\t\tarrIframesYt  = resources.filter( function( obj ) {\n\n\t\t\t\t\t\t\treturn obj.initiatorType === \"iframe\" &amp;amp;&amp;amp; obj.name.includes( data.youTubeId );\n\n\t\t\t\t\t\t} );\n\n\n\t\t\t\t\t\t/* if none found, most probably wb is loaded in restricted network so wb.ready() is triggered for not preventing other wb components to load*/\n\t\t\t\t\t\tif ( arrIframesYt.length &amp;lt; 1 ) {\n\t\t\t\t\t\t\tif ( !wb.isReady ) {\n\n\t\t\t\t\t\t\t\t// show the video notification error\n\t\t\t\t\t\t\t\t$notifText = $( \"\n\n\" + i18n( \"msgYoutubeNotLoad\" ) + \"\" );\n\t\t\t\t\t\t\t\t$this.prepend( $notifText );\n\t\t\t\t\t\t\t\tdata.notifyText = $notifText;\n\t\t\t\t\t\t\t\twb.ready( $this, componentName );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}, 1000 );\n\n\t\t\t\t}\n\t\t\t} );\n\n\t\t} else if ( media.error === null &amp;amp;&amp;amp; media.currentSrc !== \"\" &amp;amp;&amp;amp; media.currentSrc !== undef ) {\n\t\t\t$this.trigger( renderUIEvent, [ type, data ] );\n\t\t\tonResize();\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $this, componentName );\n\t\t}\n\t}\n} );\n\n/*\n *  YouTube Video mode Event\n */\n$document.on( youtubeEvent, selector, function( event, data ) {\n\tif ( event.namespace === componentName ) {\n\t\tvar mId = data.mId,\n\t\t\t$this = $( event.currentTarget ),\n\t\t\t$media, ytPlayer;\n\n\t\tytPlayer = new YT.Player( mId, {\n\t\t\tvideoId: data.youTubeId,\n\t\t\twidth: data.width,\n\t\t\theight: data.height,\n\t\t\tplayerVars: {\n\t\t\t\tautoplay: 0,\n\t\t\t\tcontrols: 0,\n\t\t\t\thl: wb.lang,\n\t\t\t\torigin: wb.pageUrlParts.host,\n\t\t\t\trel: 0,\n\t\t\t\tcc_load_policy: 1\n\t\t\t},\n\t\t\tevents: {\n\t\t\t\tonReady: function( event ) {\n\t\t\t\t\tif ( data.notifyText ) {\n\t\t\t\t\t\tdata.notifyText.hide();\n\t\t\t\t\t}\n\t\t\t\t\tonResize();\n\t\t\t\t\tyouTubeEvents( event );\n\t\t\t\t\tif ( !wb.isReady ) {\n\t\t\t\t\t\twb.ready( $this, componentName );\n\t\t\t\t\t}\n\t\t\t\t},\n\t\t\t\tonStateChange: youTubeEvents,\n\t\t\t\tonApiChange: function() {\n\n\t\t\t\t\t//If captions were enabled before the module was ready, re-enable them\n\t\t\t\t\tvar t = $this.get( 0 );\n\t\t\t\t\tt.player( \"setCaptionsVisible\", t.player( \"getCaptionsVisible\" ) );\n\t\t\t\t},\n\t\t\t\tonError: function() {\n\t\t\t\t\tconsole.warn( \"There is an issue loading the YouTube player\" );\n\t\t\t\t}\n\t\t\t}\n\t\t} );\n\n\t\t$this.addClass( \"youtube\" );\n\n\t\t$media = $this.find( \"#\" + mId );\n\n\t\tdata.media = $media;\n\t\tdata.ytPlayer = ytPlayer;\n\n\t\t// The fullscreen button is not visible by default because there are no controls when in full screen.\n\t\tif ( data.fullscreen ) {\n\t\t\t$this.attr( \"data-fullscreen-btn\", true );\n\t\t}\n\n\t\t// Detect if the YT player reloads, like when magnific Popup show the modal, because it moves the iframe\n\t\t// and then the iframe gets refreshed and reloaded. So the issue is that the iframe stops emitting the event\n\t\t// needed to adjust the multimedia player controller, like the \"onStateChange\" event.\n\t\t$media.on( \"load\", function( evt ) {\n\n\t\t\tvar elm = evt.currentTarget,\n\t\t\t\tds = elm.dataset;\n\n\t\t\t// Do nothing on the first load and add a flag to indicate it is loaded a second time\n\t\t\tif ( ds.L1 ) {\n\t\t\t\tds.L2 = true;\n\t\t\t} else {\n\t\t\t\tds.L1 = true;\n\t\t\t}\n\t\t} );\n\n\t\t$this.trigger( renderUIEvent, [ \"youtube\", data ] );\n\t}\n} );\n\n$document.on( renderUIEvent, selector, function( event, type, data ) {\n\tif ( event.namespace === componentName ) {\n\t\tvar $this = $( event.currentTarget ),\n\t\t\tcaptionsUrl = wb.getUrlParts( data.captions ),\n\t\t\tcurrentUrl = wb.getUrlParts( window.location.href ),\n\t\t\t$media = data.media,\n\t\t\t$eventReceiver,\n\t\t\t$button,\n\t\t\t$buttonSpan;\n\n\t\t$media\n\t\t\t.after( tmpl( template, data ) )\n\t\t\t.wrap( \"\n\" );\n\n\t\t$eventReceiver = $media.is( \"object\" ) ? $media.children( \":first-child\" ) : $media;\n\n\t\t// Create an adapter for the event management\n\t\t$eventReceiver.on( multimediaEvents, function( event ) {\n\t\t\t$this.trigger( event );\n\t\t} );\n\n\t\tthis.object = data.ytPlayer || $media.get( 0 );\n\t\tthis.player = ( data.ytPlayer ) ? youTubeApi : playerApi;\n\n\t\t// Trigger the duration change for cases where the event was called before the event binding\n\t\tif ( type !== \"youtube\" &amp;amp;&amp;amp; !isNaN( this.player( \"getDuration\" ) ) ) {\n\t\t\t$eventReceiver.trigger( \"durationchange\" );\n\t\t}\n\n\t\t// Load the progress polyfill if needed\n\t\t$this.find( \"progress\" ).trigger( \"wb-init.wb-progress\" );\n\n\t\t// Load the slider polyfill if needed\n\t\t$this.find( \"input[type='range']\" ).trigger( \"wb-init.wb-slider\" );\n\n\t\t// Create the share widgets if needed\n\t\tif ( data.shareUrl !== undef ) {\n\t\t\t$( \"\n\" )\n\t\t\t\t.insertBefore( $media.parent() )\n\t\t\t\t.trigger( \"wb-init.wb-share\" );\n\t\t}\n\n\t\tif ( data.isInitMuted ) {\n\t\t\t$this.data( \"putMutedOnInit\", true );\n\t\t} else if ( !data.ytPlayer &amp;amp;&amp;amp; this.object.muted ) {\n\t\t\t$media.trigger( \"volumechange\" );\n\t\t}\n\n\t\tif ( data.captions === undef ) {\n\t\t\treturn 1;\n\t\t}\n\n\t\t// Load the captions\n\t\tif ( currentUrl.absolute.replace( currentUrl.hash || \"#\", \"\" ) !== captionsUrl.absolute.replace( captionsUrl.hash || \"#\", \"\" ) ) {\n\t\t\tloadCaptionsExternal( $media, captionsUrl.absolute );\n\t\t} else {\n\t\t\tloadCaptionsInternal( $media, $( \"#\" + wb.jqEscape( captionsUrl.hash.substring( 1 ) ) ) );\n\t\t}\n\n\t\t// The fullscreen button is not visible by default because there are no controls when in full screen.\n\t\tif ( data.fullscreen ) {\n\t\t\t$this.attr( \"data-fullscreen-btn\", true );\n\t\t}\n\n\t\t// Show captions by default if configured to do so\n\t\tlet captionStatus;\n\n\t\tif ( $this.data( \"wbMltmd\" ) !== undef ) {\n\t\t\tcaptionStatus = $this.data( \"wbMltmd\" ).closedCaptions;\n\t\t}\n\n\t\tif ( captionStatus !== undef &amp;amp;&amp;amp; defaultCaptions !== undef  &amp;amp;&amp;amp; defaultCaptions === true ) {\n\n\t\t\t$this.addClass( captionClass );\n\n\t\t\t// Trigger caption visibility change event only on the first time the video plays\n\t\t\tdefaultCaptions = true;\n\n\t\t\t$button = $this.find( \".cc\" );\n\t\t\t$button\n\t\t\t\t.attr( {\n\t\t\t\t\t\"title\": i18nText.cc_off,\n\t\t\t\t\t\"aria-pressed\": true\n\t\t\t\t} );\n\n\t\t\t$buttonSpan = $button.find( \".wb-inv\" );\n\t\t\t$buttonSpan.text( i18nText.cc_off );\n\t\t}\n\t}\n} );\n\n/*\n * UI Bindings\n */\n\n$document.on( \"click\", selector, function( event ) {\n\tvar $target = $( event.target ),\n\t\tclassName = $target.attr( \"class\" ) || \"\";\n\n\t// Ignore middle and right mouse buttons\n\tif ( event.which === 2 || event.which === 3 ) {\n\t\treturn true;\n\t}\n\n\t// Optimized multiple class tests to include child glyphicon because Safari was reporting the click event\n\t// from the child span not the parent button, forcing us to have to check for both elements\n\t// JSPerf for multiple class matching https://jsperf.com/hasclass-vs-is-stackoverflow/7\n\tif (  /playpause|-play|-pause|display/.test( className ) || $target.is( \"object\" ) || $target.is( \"video\" ) ) {\n\t\tthis.player( \"getPaused\" ) || this.player( \"getEnded\" ) ? this.player( \"play\" ) : this.player( \"pause\" );\n\t} else if ( /(^|\\s)cc\\b|-subtitles/.test( className ) &amp;amp;&amp;amp; !$target.attr( \"disabled\" ) &amp;amp;&amp;amp; !$target.parent().attr( \"disabled\" ) ) {\n\t\tthis.player( \"setCaptionsVisible\", !this.player( \"getCaptionsVisible\" ) );\n\t} else if ( /\\bmute\\b|-volume-(up|off)/.test( className ) ) {\n\t\tthis.player( \"setMuted\", !this.player( \"getMuted\" ) );\n\t} else if ( $target.is( \"progress\" ) || $target.hasClass( \"progress\" ) || $target.hasClass( \"progress-bar\" ) ) {\n\t\tthis.player( \"setCurrentTime\", this.player( \"getDuration\" ) * ( ( event.pageX - $target.offset().left ) / $target.width() ) );\n\t} else if ( /\\brewind\\b|-backward/.test( className ) ) {\n\t\tthis.player( \"setCurrentTime\", this.player( \"getCurrentTime\" ) - this.player( \"getDuration\" ) * 0.05 );\n\t} else if ( /\\bfastforward\\b|-forward/.test( className ) ) {\n\t\tthis.player( \"setCurrentTime\", this.player( \"getCurrentTime\" ) + this.player( \"getDuration\" ) * 0.05 );\n\t} else if ( className.includes( \"cuepoint\" ) ) {\n\t\t$( this ).trigger( { type: \"cuepoint\", cuepoint: $target.data( \"cuepoint\" ) } );\n\t} else if ( /fullscreen|fs/.test( className ) ) {\n\t\tthis.player( \"fullscreen\" );\n\t}\n} );\n\n$document.on( \"input change\", selector, function( event ) {\n\tvar target = event.target;\n\n\tif ( $( target ).hasClass( \"volume\" ) ) {\n\t\tevent.currentTarget.player( \"setMuted\", false );\n\t\tevent.currentTarget.player( \"setVolume\", target.value / 100 );\n\t}\n} );\n\n$document.on( \"keydown\", dispCtrls, function( event ) {\n\tvar playerTarget = event.currentTarget.parentNode,\n\t\twhich = event.which,\n\t\tvolume = 0,\n\t\tstep = 0.05,\n\t\t$playerTarget = $( playerTarget );\n\n\tif ( !( event.ctrlKey || event.altKey || event.metaKey ) ) {\n\t\tswitch ( which ) {\n\t\t\tcase 32:\n\n\t\t\t\t// Mute/unmute if focused on the mute/unmute button or volume input.\n\t\t\t\tif ( $( event.target ).hasClass( \"mute\" ) || event.target.nodeName === \"INPUT\" ) {\n\t\t\t\t\t$playerTarget.find( \".mute\" ).trigger( \"click\" );\n\t\t\t\t} else if ( $( event.target ).hasClass( \"fs\" ) ) {\n\n\t\t\t\t\t// Enter full screen if focused on the full screen button\n\t\t\t\t\t$playerTarget.find( \".fs\" ).trigger( \"click\" );\n\t\t\t\t} else if ( $( event.target ).hasClass( \"cc\" ) ) {\n\n\t\t\t\t\t// Show/hide captions if focused on the closed captions button.\n\t\t\t\t\t$playerTarget.find( \".cc\" ).trigger( \"click\" );\n\t\t\t\t} else {\n\n\t\t\t\t\t// Play/pause if focused on anything else (i.e. the video itself, play/pause button or progress bar).\n\t\t\t\t\t$playerTarget.find( \".playpause\" ).trigger( \"click\" );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\tcase 37:\n\t\t\t\tplayerTarget.player( \"setCurrentTime\", this.parentNode.player( \"getCurrentTime\" ) - this.parentNode.player( \"getDuration\" ) * 0.05 );\n\t\t\t\tbreak;\n\n\t\t\tcase 39:\n\t\t\t\tplayerTarget.player( \"setCurrentTime\", this.parentNode.player( \"getCurrentTime\" ) + this.parentNode.player( \"getDuration\" ) * 0.05 );\n\t\t\t\tbreak;\n\n\t\t\tcase 38:\n\t\t\t\tvolume = Math.round( playerTarget.player( \"getVolume\" ) * 100 ) / 100 + step;\n\t\t\t\tplayerTarget.player( \"setVolume\", volume &amp;lt; 1 ? volume : 1 );\n\t\t\t\tbreak;\n\n\t\t\tcase 40:\n\t\t\t\tvolume = Math.round( playerTarget.player( \"getVolume\" ) * 100 ) / 100 - step;\n\t\t\t\tplayerTarget.player( \"setVolume\", volume &amp;gt; 0 ? volume : 0 );\n\t\t\t\tbreak;\n\n\t\t\tdefault:\n\t\t\t\treturn true;\n\t\t}\n\t\treturn false;\n\t}\n} );\n\n$document.on( \"keyup\", ctrls, function( event ) {\n\tif ( event.which === 32 &amp;amp;&amp;amp; !( event.ctrlKey || event.altKey || event.metaKey ) ) {\n\n\t\t// Allows the spacebar to be used for play/pause without double triggering\n\t\treturn false;\n\t}\n} );\n\n$document.on( \"wb-activate\", selector, function() {\n\tthis.player( \"play\" );\n} );\n\n$document.on( \"closed.wb-overlay\", \".wb-overlay\", function( event ) {\n\tvar mltmdPlayer = event.currentTarget.querySelector( selector );\n\tif ( mltmdPlayer ) {\n\t\tmltmdPlayer.player( \"pause\" );\n\t}\n} );\n\n$document.on( multimediaEvents, selector, function( event, simulated ) {\n\tvar eventTarget = event.currentTarget,\n\t\teventType = event.type,\n\t\teventNamespace = event.namespace,\n\t\t$this = $( eventTarget ),\n\t\tinvStart = \"\",\n\t\tinvEnd = \"\",\n\t\tcurrentTime, $button, $slider, buttonData, isPlay, isMuted, isCCVisible, skipTo, volume,\n\t\tfirstPlay = false;\n\tswitch ( eventType ) {\n\t\tcase \"playing\":\n\t\tcase \"pause\":\n\t\tcase \"ended\":\n\t\t\tisPlay = eventType === \"playing\";\n\t\t\t$button = $this.find( \".playpause\" );\n\t\t\tbuttonData = $button.data( \"state-\" + ( isPlay ? \"off\" : \"on\" ) );\n\t\t\tif ( isPlay ) {\n\t\t\t\t$this.addClass( \"playing\" );\n\t\t\t\t$this.find( \".progress\" ).addClass( \"active\" );\n\n\t\t\t\tif ( firstPlay === false ) {\n\t\t\t\t\t$this.addClass( firstPlayClass );\n\t\t\t\t\tfirstPlay = true;\n\t\t\t\t}\n\n\t\t\t} else {\n\t\t\t\tif ( eventType === \"ended\" ) {\n\t\t\t\t\tthis.loading = clearTimeout( this.loading );\n\t\t\t\t}\n\t\t\t\t$this.removeClass( \"playing\" );\n\t\t\t}\n\t\t\t$button\n\t\t\t\t.attr( \"title\", buttonData )\n\t\t\t\t.children( \"span\" )\n\t\t\t\t.toggleClass( \"glyphicon-play\", !isPlay )\n\t\t\t\t.toggleClass( \"glyphicon-pause\", isPlay )\n\t\t\t\t.html( invStart + buttonData + invEnd );\n\t\t\tbreak;\n\n\t\tcase \"volumechange\":\n\t\t\tisMuted = eventTarget.player( \"getMuted\" );\n\t\t\t$button = $this.find( \".mute\" );\n\t\t\tbuttonData = $button.data( \"state-\" + ( isMuted ? \"off\" : \"on\" ) );\n\t\t\tvolume = eventTarget.player( \"getVolume\" ) * 100;\n\t\t\t$button\n\t\t\t\t.attr( {\n\t\t\t\t\ttitle: buttonData,\n\t\t\t\t\t\"aria-pressed\": isMuted\n\t\t\t\t} )\n\t\t\t\t.children( \"span\" )\n\t\t\t\t.toggleClass( \"glyphicon-volume-up\", !isMuted )\n\t\t\t\t.toggleClass( \"glyphicon-volume-off\", isMuted )\n\t\t\t\t.html( invStart + buttonData + invEnd );\n\t\t\t$slider = $this.find( \"input[type='range']\" );\n\t\t\t$slider[ 0 ].value = isMuted ? 0 : volume;\n\t\t\t$slider.trigger( \"wb-update.wb-slider\" );\n\t\t\tbreak;\n\n\t\tcase \"timeupdate\":\n\t\t\tcurrentTime = eventTarget.player( \"getCurrentTime\" );\n\t\t\t$this.find( \"progress\" )\n\t\t\t\t.attr(\n\t\t\t\t\t\"value\",\n\t\t\t\t\tMath.round( currentTime / eventTarget.player( \"getDuration\" ) * 1000 ) / 10\n\t\t\t\t).trigger( \"wb-update.wb-progress\" );\n\n\t\t\t$this.find( \".wb-mm-tmln-crrnt span:nth-child(2)\" )\n\t\t\t\t.text( formatTime( currentTime ) );\n\n\t\t\tif ( $this.hasClass( captionClass ) &amp;amp;&amp;amp; $.data( eventTarget, \"captions\" ) !== undef ) {\n\t\t\t\tupdateCaptions(\n\t\t\t\t\t$this.find( \".wb-mm-cc\" ),\n\t\t\t\t\tcurrentTime,\n\t\t\t\t\t$.data( eventTarget, \"captions\" )\n\t\t\t\t);\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase \"durationchange\":\n\t\t\t$this.find( \".wb-mm-tmln-ttl span:nth-child(2)\" )\n\t\t\t\t.text( formatTime( eventTarget.player( \"getDuration\" ) ) );\n\n\t\t\t// Skip to pointer from the querystring\n\t\t\tskipTo = wb.pageUrlParts.params[ event.target.id ];\n\t\t\tif ( skipTo ) {\n\t\t\t\tskipTo = parseTime( skipTo );\n\t\t\t\teventTarget.player( \"setCurrentTime\", skipTo );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase \"ccloaded\":\n\t\t\tif ( eventNamespace === componentName ) {\n\t\t\t\t$.data( eventTarget, \"captions\", event.captions );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase \"ccloadfail\":\n\t\t\tif ( eventNamespace === componentName ) {\n\t\t\t\tif ( !$this.hasClass( \"errmsg\" ) ) {\n\t\t\t\t\t$this.addClass( \"cc_on errmsg\" )\n\t\t\t\t\t\t.find( \".wb-mm-cc\" )\n\t\t\t\t\t\t.append( \"\n\" + i18nText.cc_error + \"\" )\n\t\t\t\t\t\t.end()\n\t\t\t\t\t\t.find( \".cc\" )\n\t\t\t\t\t\t.attr( \"disabled\", \"\" )\n\t\t\t\t\t\t.removeAttr( \"aria-pressed\" );\n\t\t\t\t}\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase \"ccvischange\":\n\t\t\tif ( eventNamespace === componentName ) {\n\t\t\t\tisCCVisible = eventTarget.player( \"getCaptionsVisible\" );\n\t\t\t\t$button = $this.find( \".cc\" );\n\t\t\t\tbuttonData = $button.data( \"state-\" + ( isCCVisible ? \"off\" : \"on\" ) );\n\t\t\t\t$button.attr( {\n\t\t\t\t\ttitle: buttonData,\n\t\t\t\t\t\"aria-pressed\": isCCVisible\n\t\t\t\t} ).children( \"span\" ).html( invStart + buttonData + invEnd );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase \"waiting\":\n\t\t\tif ( !simulated ) {\n\t\t\t\t$document.off( \"progress\", selector );\n\t\t\t}\n\t\t\tthis.loading = setTimeout( function() {\n\t\t\t\t$this.addClass( \"waiting\" );\n\t\t\t}, 500 );\n\t\t\tbreak;\n\n\t\tcase \"canplay\":\n\t\tcase \"seeked\":\n\t\t\tthis.loading = clearTimeout( this.loading );\n\t\t\t$this.removeClass( \"waiting\" );\n\t\t\tbreak;\n\t\tcase \"cuepoint\":\n\t\t\teventTarget.player( \"setCurrentTime\", parseTime( event.cuepoint ) );\n\t\t\tbreak;\n\t}\n} );\n\n// Fallback for browsers that don't implement the waiting events\n$document.on( \"progress\", selector, function( event ) {\n\tvar eventTarget = event.currentTarget,\n\t\t$this = $( eventTarget );\n\n\t// Waiting detected\n\tif ( this.player( \"getPaused\" ) === false &amp;amp;&amp;amp; this.player( \"getCurrentTime\" ) === this.player( \"getPreviousTime\" ) ) {\n\t\tif ( eventTarget.player( \"getBuffering\" ) === false ) {\n\t\t\teventTarget.player( \"setBuffering\", true );\n\t\t\t$this.trigger( \"waiting\", true );\n\t\t}\n\n\t// Waiting has ended\n\t} else if ( eventTarget.player( \"getBuffering\" ) === true ) {\n\t\teventTarget.player( \"setBuffering\", false );\n\t\t$this.trigger( \"canplay\", true );\n\t}\n\teventTarget.player( \"setPreviousTime\", eventTarget.player( \"getCurrentTime\" ) );\n} );\n\n$document.on( resizeEvent, selector, function( event ) {\n\tif ( event.namespace === componentName ) {\n\t\tvar media = event.target,\n\t\t\t$media = $( media ),\n\t\t\tfigure = event.currentTarget,\n\t\t\tratio, newHeight,\n\t\t\theightDiff;\n\n\t\tratio = $media.attr( \"height\" ) / $media.attr( \"width\" );\n\n\t\t// Calculate the new height based on the specified ratio or assume a default 16:9 ratio\n\t\tnewHeight = Math.round( $media.width() * ( !isNaN( ratio ) ? ratio : 0.5625 ) );\n\n\t\tif ( newHeight &amp;gt; window.innerHeight ) {\n\t\t\theightDiff = figure.offsetHeight - window.innerHeight;\n\t\t\tnewHeight = $media.height() - heightDiff;\n\t\t}\n\n\t\t$media.css( \"height\", newHeight + \"px\" );\n\t}\n} );\n\nwindow.onYouTubeIframeAPIReady = youTubeAPIReady;\n\nwindow.youTube = {\n\tready: false\n};\n\nwb.add( selector );\n\n} )( jQuery, DOMPurify, window, wb );\n\n/**\n * @title WET-BOEW NavCurrent\n * @overview Identify URL in a navigation system that matches current page URL or a URL in the breadcrumb trail. Call by applying .trigger( \"navcurr.wb\", breadcrumb ) where the breadcrumb parameter is an optional object (DOM or jQuery)\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @pjackson28\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-navcurr\",\n\tselector = \".\" + componentName,\n\t$document = wb.doc,\n\tbreadcrumbLinksArray, breadcrumbLinksUrlArray,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t * @param {jQuery DOM element | DOM element} breadcrumb Optional breadcrumb element\n\t * @param {string} classNameOverride Optional class name override (default is wb-navcurr)\n\t */\n\tinit = function( event, breadcrumb, classNameOverride ) {\n\t\tif ( event.namespace === \"wb\" ) {\n\n\t\t\t// Start initialization\n\t\t\t// returns DOM object = proceed with init\n\t\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\t\tvar menu = wb.init( event.target, componentName, selector ),\n\t\t\t\tmenuLinks = menu.getElementsByTagName( \"a\" ),\n\t\t\t\tmenuLinksArray = [],\n\t\t\t\tmenuLinksUrlArray = [],\n\t\t\t\twindowLocation = window.location,\n\t\t\t\tpageUrl = windowLocation.hostname + windowLocation.pathname.replace( /^([^/])/, \"/$1\" ),\n\t\t\t\tpageUrlQuery = windowLocation.search,\n\t\t\t\tmatch = false,\n\t\t\t\tclassName = classNameOverride ? classNameOverride : componentName,\n\t\t\t\tchild, len, i, j, link, linkHref, linkUrl, linkQuery, linkQueryLen,\n\t\t\t\tlocalBreadcrumbLinks, localBreadcrumbLinksArray, localBreadcrumbLinksUrlArray,\n\t\t\t\tlocalBreadcrumbQuery, localBreadcrumbLinkUrl;\n\n\t\t\tif ( menu ) {\n\n\t\t\t\t// Try to find a match with the page Url and cache link + Url for later if no match found\n\t\t\t\t// Perform the check and caching in reverse to go from more specific links to more general links\n\t\t\t\tfor ( i = menuLinks.length - 1; i !== -1; i -= 1 ) {\n\t\t\t\t\tlink = menuLinks[ i ];\n\t\t\t\t\tlinkHref = link.getAttribute( \"href\" );\n\t\t\t\t\tif ( linkHref !== null ) {\n\t\t\t\t\t\tif ( linkHref.length !== 0 &amp;amp;&amp;amp; linkHref.charAt( 0 ) !== \"#\" ) {\n\t\t\t\t\t\t\tlinkUrl = link.hostname + link.pathname.replace( /^([^/])/, \"/$1\" );\n\t\t\t\t\t\t\tlinkQuery = link.search;\n\t\t\t\t\t\t\tlinkQueryLen = linkQuery.length;\n\t\t\t\t\t\t\tif ( pageUrl.slice( -linkUrl.length ) === linkUrl &amp;amp;&amp;amp; ( linkQueryLen === 0 || pageUrlQuery.slice( -linkQueryLen ) === linkQuery ) ) {\n\t\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tmenuLinksArray.push( link );\n\t\t\t\t\t\t\tmenuLinksUrlArray.push( linkUrl );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// No page Url match found, try a breadcrumb link match instead\n\t\t\t\tif ( !match &amp;amp;&amp;amp; breadcrumb ) {\n\n\t\t\t\t\t// Check to see if the data has been cached already\n\t\t\t\t\tif ( !breadcrumbLinksArray ) {\n\n\t\t\t\t\t\t// Pre-process the breadcrumb links\n\t\t\t\t\t\tlocalBreadcrumbLinksArray = [];\n\t\t\t\t\t\tlocalBreadcrumbLinksUrlArray = [];\n\t\t\t\t\t\tlocalBreadcrumbLinks = ( breadcrumb.jquery ? breadcrumb[ 0 ] : breadcrumb ).getElementsByTagName( \"li\" );\n\t\t\t\t\t\tlen = localBreadcrumbLinks.length;\n\t\t\t\t\t\tif ( len ) {\n\t\t\t\t\t\t\tlink = localBreadcrumbLinks[ len - 1 ];\n\t\t\t\t\t\t\tchild = link.firstChild;\n\t\t\t\t\t\t\tlinkHref = ( child &amp;amp;&amp;amp; child.nodeName === \"A\" ) ? child.getAttribute( \"href\" ) : \"\";\n\t\t\t\t\t\t\tif ( linkHref &amp;amp;&amp;amp; linkHref.charAt( 0 ) !== \"#\" ) {\n\t\t\t\t\t\t\t\tlocalBreadcrumbLinksArray.push( child );\n\t\t\t\t\t\t\t\tlocalBreadcrumbLinksUrlArray.push( child.hostname + child.pathname.replace( /^([^/])/, \"/$1\" ) );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Cache the data in case of more than one execution (e.g., site menu + secondary navigation)\n\t\t\t\t\t\tbreadcrumbLinksArray = localBreadcrumbLinksArray;\n\t\t\t\t\t\tbreadcrumbLinksUrlArray = localBreadcrumbLinksUrlArray;\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// Retrieve the cached data\n\t\t\t\t\t\tlocalBreadcrumbLinksArray = breadcrumbLinksArray;\n\t\t\t\t\t\tlocalBreadcrumbLinksUrlArray = breadcrumbLinksUrlArray;\n\t\t\t\t\t}\n\n\t\t\t\t\t// Try to match each breadcrumb link\n\t\t\t\t\tlen = menuLinksArray.length;\n\t\t\t\t\tfor ( j = localBreadcrumbLinksArray.length - 1; j !== -1; j -= 1 ) {\n\t\t\t\t\t\tlocalBreadcrumbLinkUrl = localBreadcrumbLinksUrlArray[ j ];\n\t\t\t\t\t\tlocalBreadcrumbQuery = localBreadcrumbLinksArray[ j ].search;\n\n\t\t\t\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t\t\t\tlink = menuLinksArray[ i ];\n\t\t\t\t\t\t\tlinkUrl = menuLinksUrlArray[ i ];\n\t\t\t\t\t\t\tlinkQuery = link.search;\n\t\t\t\t\t\t\tlinkQueryLen = linkQuery.length;\n\n\t\t\t\t\t\t\tif ( localBreadcrumbLinkUrl.slice( -linkUrl.length ) === linkUrl &amp;amp;&amp;amp; ( linkQueryLen === 0 || localBreadcrumbQuery.slice( -linkQueryLen ) === linkQuery ) ) {\n\t\t\t\t\t\t\t\tmatch = true;\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( match ) {\n\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tif ( match ) {\n\t\t\t\t\tlink.className += \" \" + className;\n\t\t\t\t\tif ( menu.className.indexOf( \"wb-menu\" ) !== -1 &amp;amp;&amp;amp; link.className.indexOf( \"item\" ) === -1 ) {\n\t\t\t\t\t\t$( link ).closest( \".sm\" ).parent().children( \"a\" ).addClass( className );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Identify that initialization has completed\n\t\t\t\twb.ready( $( menu ), componentName );\n\t\t\t}\n\t\t}\n\t};\n\n// Bind the navcurrent event of the plugin\n$document.on( \"navcurr.wb\", init );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Overlay\n * @overview Provides multiple styles of overlays such as panels and pop-ups\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @thomasgohard, @pjackson28\n */\n( function( $, window, document, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-overlay\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tcloseClass = \"overlay-close\",\n\tlinkClass = \"overlay-lnk\",\n\tignoreOutsideClass = \"outside-off\",\n\tOverlayOpenFlag = \"wb-overlay-dlg\",\n\tinitialized = false,\n\tsourceLinks = {},\n\tsetFocusEvent = \"setfocus.wb\",\n\t$document = wb.doc,\n\ti18n, i18nText,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm, footer, $header, closeText, overlayClose;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\n\t\t\t// Only initialize the i18nText once\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\tclose: i18n( \"close\" ),\n\t\t\t\t\tcolon: i18n( \"colon\" ),\n\t\t\t\t\tspace: i18n( \"space\" ),\n\t\t\t\t\tesc: i18n( \"esc-key\" ),\n\t\t\t\t\tcloseOverlay: i18n( closeClass )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// One left and right panels add close button\n\t\t\tvar isPanel = ( $elm.attr( \"class\" ).indexOf( \"wb-panel\" ) &amp;gt; -1 ) ? true : false,\n\t\t\t\tisPopup = ( $elm.attr( \"class\" ).indexOf( \"wb-popup\" ) &amp;gt; -1 ) ? true : false;\n\t\t\tif ( isPanel || isPopup ) {\n\t\t\t\tfooter = $elm.find( \".modal-footer\" )[ 0 ];\n\n\t\t\t\tvar hasFooter = ( footer &amp;amp;&amp;amp; footer.length !== 0 ) ? true : false,\n\t\t\t\t\thasButton = hasFooter &amp;amp;&amp;amp; $( footer ).find( \".\" + closeClass ).length !== 0,\n\t\t\t\t\tcloseClassFtr = ( $elm.hasClass( \"wb-panel-l\" ) ? \"pull-right \" : \"pull-left \" )  + closeClass,\n\t\t\t\t\tcloseTextFtr = i18nText.close,\n\t\t\t\t\tspanTextFtr = i18nText.closeOverlay,\n\t\t\t\t\toverlayCloseFtr;\n\n\t\t\t\tif ( !hasButton ) {\n\t\t\t\t\tif ( !hasFooter ) {\n\t\t\t\t\t\tfooter = document.createElement( \"div\" );\n\t\t\t\t\t\tfooter.setAttribute( \"class\", \"modal-footer\" );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( isPopup ) {\n\t\t\t\t\t\tfooter.style.border = \"0\";\n\t\t\t\t\t}\n\n\t\t\t\t\toverlayCloseFtr = \"\" +\n\t\t\t\t\t\tcloseTextFtr +\n\t\t\t\t\t\t\"\" + spanTextFtr + \"\";\n\n\t\t\t\t\t$( footer ).append( overlayCloseFtr );\n\t\t\t\t\tif ( !hasFooter ) {\n\t\t\t\t\t\t$elm.append( footer );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Add close button\n\t\t\t$header = $elm.find( \".modal-title\" );\n\t\t\tif ( $header.length !== 0 ) {\n\t\t\t\tcloseText = i18nText.close + i18nText.colon + i18nText.space +\n\t\t\t\t\t$header.text() + i18nText.space + i18nText.esc;\n\t\t\t} else {\n\t\t\t\tcloseText = i18nText.closeOverlay;\n\t\t\t}\n\t\t\tcloseText = closeText.replaceAll( \"'\", \"&amp;#39;\" );\n\t\t\toverlayClose = \"&amp;#xd7; \" +\n\t\t\t\tcloseText + \"\";\n\n\t\t\t$elm.append( overlayClose );\n\t\t\telm.setAttribute( \"aria-hidden\", \"true\" );\n\n\t\t\t// Identify that initialization has completed\n\t\t\tinitialized = true;\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t},\n\n\topenOverlay = function( overlayId, noFocus ) {\n\t\tvar $overlay = $( \"#\" + wb.jqEscape( overlayId ) );\n\n\t\t$overlay\n\t\t\t.addClass( \"open\" )\n\t\t\t.attr( \"role\", \"dialog\" )\n\t\t\t.attr( \"aria-hidden\", \"false\" );\n\n\t\tif ( $overlay.hasClass( \"wb-popup-full\" ) || $overlay.hasClass( \"wb-popup-mid\" ) ) {\n\t\t\t$overlay.attr( \"data-pgtitle\", document.getElementsByTagName( \"H1\" )[ 0 ].textContent );\n\t\t\t$document.find( \"body\" ).addClass( OverlayOpenFlag );\n\t\t}\n\n\t\tif ( !noFocus ) {\n\t\t\t$overlay\n\t\t\t\t.scrollTop( 0 )\n\t\t\t\t.trigger( setFocusEvent );\n\t\t}\n\n\t\t// Register the overlay if it wasn't previously registered\n\t\t// (only required when opening through an event)\n\t\tif ( !sourceLinks[ overlayId ] ) {\n\t\t\tsetTimeout( function() {\n\t\t\t\tsourceLinks[ overlayId ] = null;\n\t\t\t}, 1 );\n\t\t}\n\n\t\t$overlay.trigger( \"opened\" + selector );\n\t},\n\n\tcloseOverlay = function( overlayId, noFocus, userClosed ) {\n\t\tvar $overlay = $( \"#\" + overlayId ),\n\t\t\tsourceLink = sourceLinks[ overlayId ];\n\n\t\t$overlay\n\t\t\t.removeClass( \"open\" )\n\t\t\t.removeAttr( \"role\" )\n\t\t\t.attr( \"aria-hidden\", \"true\" );\n\n\t\tif ( $overlay.hasClass( \"wb-popup-full\" ) || $overlay.hasClass( \"wb-popup-mid\" ) ) {\n\t\t\t$document.find( \"body\" ).removeClass( OverlayOpenFlag );\n\t\t}\n\n\t\tif ( userClosed ) {\n\t\t\t$overlay.addClass( \"user-closed\" );\n\t\t}\n\n\t\tif ( !noFocus &amp;amp;&amp;amp; sourceLink ) {\n\n\t\t\t// Returns focus to the source link for the overlay\n\t\t\t$( sourceLink ).trigger( setFocusEvent );\n\t\t}\n\n\t\t// Delete the source link reference\n\t\tdelete sourceLinks[ overlayId ];\n\n\t\t$overlay.trigger( \"closed\" + selector );\n\t};\n\n$document.on( \"timerpoke.wb \" + initEvent + \" keydown open\" + selector +\n\" close\" + selector, selector, function( event ) {\n\n\tvar eventType = event.type,\n\t\twhich = event.which,\n\t\teventTarget = event.target,\n\t\teventCurrentTarget = event.currentTarget,\n\t\toverlayId = eventCurrentTarget.id,\n\t\toverlay, $focusable, index, length;\n\n\tswitch ( eventType ) {\n\t\tcase \"timerpoke\":\n\t\tcase \"wb-init\":\n\t\t\tinit( event );\n\t\t\tbreak;\n\n\t\tcase \"open\":\n\t\t\tif ( eventCurrentTarget === eventTarget ) {\n\t\t\t\topenOverlay( overlayId, event.noFocus );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tcase \"close\":\n\t\t\tif ( eventCurrentTarget === eventTarget ) {\n\t\t\t\tcloseOverlay( overlayId, event.noFocus );\n\t\t\t}\n\t\t\tbreak;\n\n\t\tdefault:\n\t\t\toverlay = document.getElementById( overlayId );\n\n\t\t\tswitch ( which ) {\n\n\t\t\t\t// Tab key\n\t\t\t\tcase 9:\n\n\t\t\t\t\t// No special tab handling when ignoring outside activity\n\t\t\t\t\tif ( overlay.className.indexOf( ignoreOutsideClass ) === -1 ) {\n\t\t\t\t\t\t$focusable = $( overlay ).find( \":tabbable\" );\n\t\t\t\t\t\tlength = $focusable.length;\n\t\t\t\t\t\tindex = $focusable.index( event.target ) + ( event.shiftKey ? -1 : 1 );\n\n\t\t\t\t\t\tif ( event.target === overlay || index === -1 || index === length ) {\n\t\t\t\t\t\t\tevent.preventDefault();\n\t\t\t\t\t\t\t$focusable.eq( index &amp;lt; 0 ? length - 1 : 0 )\n\t\t\t\t\t\t\t\t.trigger( setFocusEvent );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\n\t\t\t\t// Escape key\n\t\t\t\tcase 27:\n\t\t\t\t\tif ( !event.isDefaultPrevented() ) {\n\t\t\t\t\t\tcloseOverlay( overlayId, false, true );\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t}\n} );\n\n// Handler for clicking on the close button of the overlay\n$document.on( \"click\", \".\" + closeClass, function( event ) {\n\tvar which = event.which;\n\n\t// Ignore if not initialized and middle/right mouse buttons\n\tif ( initialized &amp;amp;&amp;amp; ( !which || which === 1 ) ) {\n\t\tcloseOverlay(\n\t\t\t$( event.currentTarget ).closest( selector ).attr( \"id\" ),\n\t\t\tfalse,\n\t\t\ttrue\n\t\t);\n\t}\n} );\n\n// Handler for clicking on a source link for the overlay\n$document.on( \"click keydown\", \".\" + linkClass, function( event ) {\n\tvar which = event.which,\n\t\tsourceLink = event.currentTarget,\n\t\toverlayId = sourceLink.hash.substring( 1 );\n\n\t// Ignore if not initialized and middle/right mouse buttons\n\tif ( initialized &amp;amp;&amp;amp; ( !which || which === 1 || which === 32 ) ) {\n\t\tevent.preventDefault();\n\n\t\t// Introduce a delay to prevent outside activity detection\n\t\tsetTimeout( function() {\n\n\t\t\t// Stores the source link for the overlay\n\t\t\tsourceLinks[ overlayId ] = sourceLink;\n\n\t\t\t// Opens the overlay\n\t\t\topenOverlay( overlayId );\n\t\t}, 1 );\n\t}\n} );\n\n// Handler for clicking on a same page link within the overlay to outside the overlay\n$document.on( \"click\", selector + \" a[href^='#']\", function( event ) {\n\tvar which = event.which,\n\t\teventTarget = event.target,\n\t\thref, overlay, linkTarget;\n\n\t// Ignore if not initialized and middle/right mouse buttons\n\tif ( initialized &amp;amp;&amp;amp; ( !which || which === 1 ) ) {\n\t\toverlay = $( eventTarget ).closest( selector )[ 0 ];\n\t\thref = eventTarget.getAttribute( \"href\" );\n\t\tlinkTarget = document.getElementById( href.substring( 1 ) );\n\n\t\t// Ignore same page links to within the overlay\n\t\tif ( href.length &amp;gt; 1 &amp;amp;&amp;amp; !$.contains( overlay, linkTarget ) ) {\n\n\t\t\t// Stop propagation of the click event\n\t\t\tif ( event.stopPropagation ) {\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t} else {\n\t\t\t\tevent.cancelBubble = true;\n\t\t\t}\n\n\t\t\t// Close the overlay and set focus to the same page link\n\t\t\tcloseOverlay( overlay.id, true );\n\t\t\t$( linkTarget ).trigger( setFocusEvent );\n\t\t}\n\t}\n} );\n\n// Outside activity detection\n$document.on( \"click focusin\", \"body\", function( event ) {\n\tvar eventTarget = event.target,\n\t\twhich = event.which,\n\t\toverlayId, overlay;\n\n\t// Ignore if not initialized and middle/right mouse buttons\n\tif ( initialized &amp;amp;&amp;amp; ( !which || which === 1 ) ) {\n\n\t\t// Close any overlays with outside activity\n\t\tfor ( overlayId in sourceLinks ) {\n\t\t\toverlay = document.getElementById( overlayId );\n\t\t\tif ( overlay &amp;amp;&amp;amp; overlay.getAttribute( \"aria-hidden\" ) === \"false\" &amp;amp;&amp;amp;\n\t\t\t\teventTarget.id !== overlayId &amp;amp;&amp;amp;\n\t\t\t\toverlay.className.indexOf( ignoreOutsideClass ) === -1 &amp;amp;&amp;amp;\n\t\t\t\t!$.contains( overlay, eventTarget ) ) {\n\n\t\t\t\t// Close the overlay\n\t\t\t\tcloseOverlay( overlayId );\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// Ensure any element in focus outside an overlay is visible\n$document.on( \"keyup\", function( ) {\n\tvar elmInFocus, elmInFocusRect, focusAreaBelow, focusAreaAbove,\n\t\toverlayId, overlay, overlayRect;\n\n\t// Ignore if not initialized\n\tif ( initialized ) {\n\t\telmInFocus = document.activeElement;\n\t\telmInFocusRect = elmInFocus.getBoundingClientRect();\n\t\tfocusAreaBelow = 0;\n\t\tfocusAreaAbove = window.innerHeight;\n\n\t\t// Ensure that at least one overlay is visible, and that the element in focus is not an overlay,\n\t\t// a child of an overlay, or the body element\n\t\tif ( $.isEmptyObject( sourceLinks ) || elmInFocus.className.indexOf( componentName ) !== -1 ||\n\t\t\t$( elmInFocus ).parents( selector ).length !== 0 || elmInFocus === document.body ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Determine the vertical portion of the viewport that is not obscured by an overlay\n\t\tfor ( overlayId in sourceLinks ) {\n\t\t\toverlay = document.getElementById( overlayId );\n\t\t\tif ( overlay &amp;amp;&amp;amp; overlay.getAttribute( \"aria-hidden\" ) === \"false\" ) {\n\t\t\t\toverlayRect = overlay.getBoundingClientRect();\n\t\t\t\tif ( overlay.className.indexOf( \"wb-bar-t\" ) !== -1 ) {\n\t\t\t\t\tfocusAreaBelow = Math.max( overlayRect.bottom, focusAreaBelow );\n\t\t\t\t} else if ( overlay.className.indexOf( \"wb-bar-b\" ) !== -1 ) {\n\t\t\t\t\tfocusAreaAbove = Math.min( overlayRect.top, focusAreaAbove );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Ensure the element in focus is visible\n\t\t// TODO: Find a solution for when there isn't enough page to scroll up or down\n\t\tif ( elmInFocusRect.top &amp;lt; focusAreaBelow ) {\n\n\t\t\t// Scroll down till the top of the element is visible\n\t\t\twindow.scrollBy( 0, focusAreaBelow - elmInFocusRect.top );\n\t\t} else if ( elmInFocusRect.bottom &amp;gt; focusAreaAbove ) {\n\n\t\t\t// Scroll up till the bottom of the element is visible\n\t\t\twindow.scrollBy( 0, elmInFocusRect.bottom - focusAreaAbove );\n\t\t}\n\t}\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, document, wb );\n\n/**\n * @title WET-BOEW Paginate Plugin\n * @overview This plugin provides pagination functionality for lists, tables, and groups of elements.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @duboisp\n */\n( function( $, window, document, wb ) {\n\"use strict\";\n\nlet i18n, i18nText;\n\nconst componentName = \"wb-paginate\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\tfilterClass = \"wb-fltr-out\",\n\tpgFilterOutClass = \"wb-pgfltr-out\",\n\ttagFilterClass = \"wb-tgfltr-out\",\n\tpagerClass = \"wb-paginate-pager\",\n\tpageData = \"data-pagination-idx\",\n\tnotFilterClassSel = \":not(.\" + filterClass + \"):not(.\" + tagFilterClass + \")\",\n\tdefaults = {\n\t\tlst: {\n\t\t\tselector: \"li\"\n\t\t},\n\t\tgrp: {\n\t\t\tselector: \"&amp;gt; *\"\n\t\t},\n\t\ttbl: {\n\t\t\tselector: \"tr\",\n\t\t\tsection: \":scope &amp;gt; tbody\"\n\t\t},\n\t\titemsPerPage: 10\n\t},\n\n\tinit = function( event ) {\n\t\tconst elm = wb.init( event, componentName, selector );\n\n\t\tif ( elm ) {\n\t\t\tvar $elm = $( elm ),\n\t\t\t\tpaginationElm,\n\t\t\t\telmTagName = elm.nodeName,\n\t\t\t\tsetDefault,\n\t\t\t\tuiTargetElm;\n\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\tprv: i18n( \"prv\" ),\n\t\t\t\t\tnxt: i18n( \"nxt\" ),\n\t\t\t\t\tpaginationLabel: i18n( \"pagination-label\" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Setup configurations\n\t\t\tswitch ( elmTagName ) {\n\t\t\t\tcase \"UL\":\n\t\t\t\t\tsetDefault = defaults.lst;\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"TABLE\":\n\t\t\t\t\tsetDefault = defaults.tbl;\n\t\t\t\t\tbreak;\n\t\t\t\tdefault:\n\t\t\t\t\tsetDefault = defaults.grp;\n\t\t\t\t\tbreak;\n\t\t\t}\n\n\t\t\telm.id = elm.id || wb.getId();\n\t\t\telm.pgSettings = $.extend( true, {}, setDefault, window[ componentName ], wb.getData( $elm, componentName ) );\n\t\t\telm.pgSettings.currPage = 1;\n\t\t\telm.pgSettings.itemsPerPage = elm.pgSettings.itemsPerPage || defaults.itemsPerPage;\n\t\t\telm.pgSettings.items = elm.querySelectorAll( ( elm.pgSettings.section || \":scope\" ) + \" \" + elm.pgSettings.selector + notFilterClassSel );\n\n\t\t\t// Setup pagination container\n\t\t\tpaginationElm = document.createElement( \"nav\" );\n\t\t\tpaginationElm.id = componentName + \"-\" + elm.id;\n\t\t\tpaginationElm.classList.add( pagerClass );\n\t\t\tpaginationElm.setAttribute( \"aria-label\", i18nText.paginationLabel );\n\n\t\t\t// Add pagination container\n\t\t\tif ( elm.pgSettings.uiTarget ) {\n\t\t\t\tuiTargetElm = document.querySelector( elm.pgSettings.uiTarget );\n\t\t\t\tuiTargetElm.appendChild( paginationElm );\n\t\t\t} else if ( elm.pgSettings.section ) {\n\t\t\t\tif ( elmTagName === \"UL\" || elmTagName === \"TABLE\" ) {\n\t\t\t\t\telm.after( paginationElm );\n\t\t\t\t} else {\n\t\t\t\t\telm.querySelector( elm.pgSettings.section ).after( paginationElm );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\telm.after( paginationElm );\n\t\t\t}\n\n\t\t\t// Show/hide items and generate pagination\n\t\t\tupdateItems( elm );\n\t\t\tgenerateUI( elm );\n\n\t\t\twb.ready( $( elm ), componentName );\n\t\t}\n\t},\n\n\t// Set or reset pagination UI\n\tgenerateUI = function( elm ) {\n\t\tvar paginationUI = \"\",\n\t\t\tcurrPage = elm.pgSettings.currPage,\n\t\t\tpagesCount = elm.pgSettings.pagesCount,\n\t\t\tpaginationElm = document.querySelector( \"#\" + componentName + \"-\" + elm.id ),\n\t\t\ti = 1;\n\n\t\t// Make sure the defined current page is not bigger than the total pages\n\t\tif ( currPage &amp;gt; pagesCount ) {\n\t\t\tcurrPage = pagesCount;\n\t\t}\n\n\t\t// Only add pagination if there is more than one page\n\t\tif ( pagesCount &amp;gt; 1 ) {\n\t\t\tpaginationUI = \"\n\";\n\n\t\t\t// Add Previous page button\n\t\t\tvar prevLI = \"\";\n\t\t\tprevLI += \"\";\n\t\t\tprevLI += \"\" + i18nText.prv + \"\";\n\t\t\tprevLI += \"\";\n\n\t\t\tpaginationUI += prevLI;\n\n\t\t\t// Add pages buttons\n\t\t\tfor ( i; i &amp;lt;= pagesCount; i++ ) {\n\t\t\t\tvar pageButtonLI = \"\";\n\t\t\t\tpageButtonLI += \"\n\";\n\t\t\t\tpageButtonLI += \"Page \" + i + \"\";\n\t\t\t\tpageButtonLI += \"\";\n\t\t\t\tpaginationUI += pageButtonLI;\n\t\t\t}\n\n\t\t\t// Add Next page button\n\t\t\tvar nextLI = \"\";\n\t\t\tnextLI += \"\";\n\t\t\tnextLI += \"\" + i18nText.nxt + \"\";\n\t\t\tnextLI += \"\";\n\t\t\tpaginationUI += nextLI;\n\t\t\tpaginationUI += \"\";\n\t\t}\n\n\t\t// Insert HTML\n\t\tpaginationElm.innerHTML = paginationUI;\n\t},\n\n\t// Show/hide items to reflect current page\n\tupdateItems = function( elm ) {\n\t\tlet currPage = elm.pgSettings.currPage,\n\t\t\titems = elm.pgSettings.items,\n\t\t\titemsPerPage = elm.pgSettings.itemsPerPage;\n\n\t\titems.forEach( function( item, index ) {\n\t\t\tif ( ( index &amp;lt; ( itemsPerPage * currPage ) ) &amp;amp;&amp;amp; ( index &amp;gt;= ( itemsPerPage * currPage ) - itemsPerPage ) ) {\n\t\t\t\titem.classList.remove( pgFilterOutClass );\n\t\t\t} else {\n\t\t\t\titem.classList.add( pgFilterOutClass );\n\t\t\t}\n\t\t} );\n\n\t\telm.pgSettings.pagesCount = Math.ceil( items.length / itemsPerPage );\n\t},\n\n\t// Update pagination to reflect current page\n\tgoToPage = function( elm ) {\n\t\tlet paginationElm = document.querySelector( \"#\" + componentName + \"-\" + elm.id ),\n\t\t\tpageItems = paginationElm.querySelectorAll( \"li\" ),\n\t\t\titemClass,\n\t\t\tpageLink,\n\t\t\tcurrPage = elm.pgSettings.currPage,\n\t\t\tpagesCount = elm.pgSettings.pagesCount;\n\n\t\tpageItems.forEach( function( pageItem, i ) {\n\t\t\tpageLink = pageItem.querySelector( \"button\" );\n\n\t\t\tif ( pageLink.classList.contains( \"paginate-prev\" ) ) {\n\t\t\t\tcurrPage &amp;gt; 1 ? pageItem.classList.remove( \"disabled\" ) : pageItem.classList.add( \"disabled\" );\n\t\t\t} else if ( pageLink.classList.contains( \"paginate-next\" ) ) {\n\t\t\t\tcurrPage &amp;lt; pagesCount ? pageItem.classList.remove( \"disabled\" ) : pageItem.classList.add( \"disabled\" );\n\t\t\t} else {\n\t\t\t\tpageItem.className = \"\";\n\t\t\t\tpageItem.children[ 0 ].removeAttribute( \"aria-current\" );\n\n\t\t\t\titemClass = returnItemClass( currPage, pagesCount, i );\n\n\t\t\t\tif ( i === currPage ) {\n\t\t\t\t\tpageItem.children[ 0 ].setAttribute( \"aria-current\", \"true\" );\n\t\t\t\t}\n\n\t\t\t\tpageItem.className = itemClass;\n\t\t\t}\n\t\t} );\n\t},\n\n\t// Return the list item classname\n\treturnItemClass = function( currPage, pagesCount, i ) {\n\t\tlet itemClass = \"\";\n\n\t\tif ( currPage &amp;gt; 1 &amp;amp;&amp;amp; currPage &amp;lt; pagesCount ) {\n\t\t\tif ( Math.abs( currPage - i ) &amp;gt; 1 ) {\n\t\t\t\titemClass += \"hidden-xs hidden-sm\";\n\n\t\t\t\tif ( Math.abs( currPage - i ) &amp;gt; 2 ) {\n\t\t\t\t\titemClass += \" hidden-md\";\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\tif ( Math.abs( currPage - i ) &amp;gt; 2 ) {\n\t\t\t\titemClass += \"hidden-xs hidden-sm\";\n\n\t\t\t\tif ( Math.abs( currPage - i ) &amp;gt; 4 ) {\n\t\t\t\t\titemClass += \" hidden-md\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( pagesCount &amp;gt; 10 ) {\n\t\t\tif ( currPage &amp;lt;= 5 ) {\n\t\t\t\tif ( i &amp;gt; 10 ) {\n\t\t\t\t\titemClass += \" hidden\";\n\t\t\t\t}\n\t\t\t} else if ( ( currPage &amp;gt; 5 ) &amp;amp;&amp;amp; ( currPage &amp;lt; pagesCount - 5 ) ) {\n\t\t\t\tif ( ( i &amp;lt; currPage - 4 ) || ( i &amp;gt; currPage + 5 ) ) {\n\t\t\t\t\titemClass += \" hidden\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tif ( i &amp;lt;= pagesCount - 10 ) {\n\t\t\t\t\titemClass += \" hidden\";\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\tif ( i === currPage ) {\n\t\t\titemClass += \" active\";\n\t\t}\n\n\t\treturn itemClass;\n\t};\n\n// When a page button is clicked\n$document.on( \"click\", \".\" + pagerClass + \" button\", function()  {\n\tlet elm = document.querySelector( \"#\" + this.getAttribute( \"aria-controls\" ) ),\n\t\tpageDest = ( ( this.getAttribute( pageData ) ) * 1 ) || elm.pgSettings.currPage;\n\n\tif ( this.classList.contains( \"paginate-next\" ) ) {\n\t\tpageDest++;\n\t} else if ( this.classList.contains( \"paginate-prev\" ) ) {\n\t\tpageDest--;\n\t}\n\n\tif ( pageDest !== elm.pgSettings.currPage &amp;amp;&amp;amp; pageDest &amp;gt; 0 &amp;amp;&amp;amp; pageDest &amp;lt;= elm.pgSettings.pagesCount ) {\n\t\telm.pgSettings.currPage = pageDest;\n\n\t\tupdateItems( elm );\n\t\tgoToPage( elm );\n\n\t\t$( elm ).trigger( \"setfocus.wb\" );\n\t\tif ( elm.getBoundingClientRect().top &amp;lt; 0 ) {\n\t\t\telm.scrollIntoView( { behavior: \"smooth\" }, true );\n\t\t}\n\t}\n\n\n} );\n\n// Resets items and pagination on filter or if content is updated\n$document.on( \"wb-contentupdated wb-filtered\", selector, function() {\n\tthis.pgSettings.currPage = 1;\n\tthis.pgSettings.items = this.querySelectorAll( ( this.pgSettings.section || \":scope\" ) + \" \" + this.pgSettings.selector + notFilterClassSel );\n\n\tupdateItems( this );\n\tgenerateUI( this );\n} );\n\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\nwb.add( selector );\n\n} )( jQuery, window, document, wb );\n\n/**\n * @title WET-BOEW wb-pii-scrub\n * @overview This plugin delete Personal Identifiable Information (PII) from the flagged form fields before form submit\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @polmih, @duboisp, @GormFrank\n **/\n( function( $, wb ) {\n\"use strict\";\n\nvar $document = wb.doc,\n\tcomponentName = \"wb-pii-scrub\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tattrPIIBlocked = \"data-wb-pii-blocked\",\n\tattrScrubField = \"data-scrub-field\",\n\tattrScrubSubmit = \"data-scrub-submit\",\n\tpiiModalID = componentName + \"-modal\",\n\tdefaults = {\n\t\tscrubChar: \"********\"\n\t},\n\ti18n, i18nText,\n\tcurrSubmitter,\n\tbtnAsInput,\n\n\tinit = function( event ) {\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm = $( elm );\n\n\t\tif ( elm ) {\n\t\t\tvar settings = elm.getAttribute( \"data-\" + componentName );\n\n\t\t\t// Initialize i18n strings\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\theader: i18n( \"pii-header\" ),\n\t\t\t\t\tintro: i18n( \"pii-intro\" ),\n\t\t\t\t\tviewMore: i18n( \"pii-view-more\" ),\n\t\t\t\t\tviewMoreInfo: i18n( \"pii-view-more-info\" ),\n\t\t\t\t\tconfirmBtn: i18n( \"pii-yes-btn\" ),\n\t\t\t\t\tcancelBtn: i18n( \"pii-cancel-btn\" ),\n\t\t\t\t\tredacted: i18n( \"redacted\" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Parse settings defined on element\n\t\t\tif ( settings ) {\n\t\t\t\tsettings = JSON.parse( settings );\n\t\t\t}\n\n\t\t\t// Initialize settings\n\t\t\telm.settings = { ...defaults, ...settings };\n\n\t\t\t// Ensure the form has an ID\n\t\t\telm.id = elm.id ? elm.id : wb.getId();\n\n\t\t\t// Block form submission for Postback forms by default\n\t\t\telm.setAttribute( attrPIIBlocked, \"true\" );\n\n\t\t\telm.addEventListener( \"submit\", function( e ) {\n\t\t\t\te.preventDefault(); // This is needed because of the setTimeout\n\n\t\t\t\t// Go through form values\n\t\t\t\tcheckFormValues( elm );\n\n\t\t\t\t// Check if form has validation errors before showing PII popup or submitting\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tlet errorElm = elm.querySelector( \".error .label.label-danger\" );\n\n\t\t\t\t\tif ( !errorElm ) {\n\t\t\t\t\t\tcurrSubmitter = e.submitter;\n\n\t\t\t\t\t\t// Add submitter data if it is present (only if not a Postback form as it has its own method)\n\t\t\t\t\t\tif ( currSubmitter.name &amp;amp;&amp;amp; !elm.classList.contains( \"wb-postback\" ) ) {\n\t\t\t\t\t\t\tbtnAsInput = document.createElement( \"input\" );\n\t\t\t\t\t\t\tbtnAsInput.type = \"hidden\";\n\t\t\t\t\t\t\tbtnAsInput.name = currSubmitter.name;\n\t\t\t\t\t\t\tbtnAsInput.value = currSubmitter.value;\n\t\t\t\t\t\t\telm.appendChild( btnAsInput );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Open modal\n\t\t\t\t\t\tif ( elm.PIIFields.length &amp;gt; 0 ) {\n\t\t\t\t\t\t\tgenerateModal( elm );\n\n\t\t\t\t\t\t\t$( \"#\" + piiModalID ).trigger( \"open.wb-lbx\", [\n\t\t\t\t\t\t\t\t[ {\n\t\t\t\t\t\t\t\t\tsrc: \"#\" + piiModalID,\n\t\t\t\t\t\t\t\t\ttype: \"inline\"\n\t\t\t\t\t\t\t\t} ],\n\t\t\t\t\t\t\t\ttrue\n\t\t\t\t\t\t\t] );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif ( elm.classList.contains( \"wb-postback\" ) ) {\n\t\t\t\t\t\t\t\t$( elm ).trigger( \"wb-postback.submit\", currSubmitter );\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\telm.submit();\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}, 50 );\n\t\t\t} );\n\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t},\n\n\t/*\n\t* Log all PII positive fields inside the form's \"PIIFields\" property\n\t* @param form: a reference to the form containing PII fields\n\t*/\n\tcheckFormValues = function( form ) {\n\t\tlet fieldsToScrub = form.querySelectorAll( \"[\" + attrScrubField + \"]\" );\n\n\t\tform.PIIFields = [];\n\n\t\t// identify form elements that were assigned to be scrubbed\n\t\tfieldsToScrub.forEach( ( field ) =&amp;gt; {\n\n\t\t\t// If the field contains PII add field to list\n\t\t\tif ( wb.findPotentialPII( field.value, false ) ) {\n\t\t\t\tlet fieldLabel = form.querySelector( \"[for=\" + field.id + \"] &amp;gt; span.field-name\" ),\n\t\t\t\t\tfieldLabelText = fieldLabel ? fieldLabel.innerText : form.querySelector( \"[for=\" + field.id + \"]\" ).innerText,\n\t\t\t\t\tscrubbedFieldValue = wb.findPotentialPII( field.value, true, { replaceWith: form.settings.scrubChar } ),\n\t\t\t\t\tscrubValHTML = wb.findPotentialPII( field.value.replace( /\" + form.settings.scrubChar + \"\" } );\n\n\t\t\t\tform.PIIFields.push( {\n\t\t\t\t\telm: field,\n\t\t\t\t\tscrubVal: scrubbedFieldValue,\n\t\t\t\t\tscrubValHTML: scrubValHTML,\n\t\t\t\t\tlabel: fieldLabelText\n\t\t\t\t} );\n\t\t\t}\n\t\t} );\n\n\t\tif ( form.PIIFields.length === 1 ) {\n\t\t\tdocument.getElementById( form.PIIFields[ 0 ].elm.id ).focus();\n\t\t}\n\n\t\t// If PII is found, block Postback form submission\n\t\tform.PIIFields.length &amp;gt; 0 ? form.setAttribute( attrPIIBlocked, \"true\" ) : form.setAttribute( attrPIIBlocked, \"false\" );\n\t},\n\n\t/*\n\t* Scrub all PII positive fields\n\t* @param form: a reference to the form containing PII fields\n\t*/\n\tscrubFormValues = function( form ) {\n\n\t\t// Scrub the value of each PII positive fields\n\t\tform.PIIFields.forEach( ( field ) =&amp;gt; {\n\t\t\tfield.elm.value = field.scrubVal;\n\t\t} );\n\n\t\t// Clear PII fields as their value has been replaced by the scrubbed value\n\t\tform.PIIFields = [];\n\t},\n\n\t/*\n\t* Generate the modal UI\n\t* @param form: a reference to the form containing PII fields\n\t*/\n\tgenerateModal = function( form ) {\n\t\tlet piiModalFields = \"\",\n\t\t\tpiiModal = document.createElement( \"section\" ),\n\t\t\tmoreInfoContent = form.settings.moreInfo ? form.settings.moreInfo : i18nText.viewMoreInfo,\n\t\t\tmodalTemplate = form.querySelector( \"template\" + form.settings.modalTemplate );\n\n\t\t// Destroy modal if present\n\t\tif ( document.getElementById( piiModalID ) ) {\n\t\t\tdocument.getElementById( piiModalID ).remove();\n\t\t}\n\n\t\t// Generate PII fields list\n\t\tif ( form.PIIFields.length &amp;gt; 1 ) {\n\t\t\tpiiModalFields += \"\n\";\n\t\t\tform.PIIFields.forEach( ( field ) =&amp;gt; {\n\t\t\t\tpiiModalFields += \"\n\" + field.label + \"\n\" + field.scrubValHTML.replace( /\\n/g, \"\" ) + \"\";\n\t\t\t} );\n\t\t\tpiiModalFields += \"\";\n\t\t} else {\n\t\t\tpiiModalFields += \"\n\" + form.PIIFields[ 0 ].scrubValHTML.replace( /\\n/g, \"\" ) + \"\";\n\t\t}\n\n\t\tpiiModal.id = piiModalID;\n\t\tpiiModal.className = \"modal-dialog modal-content overlay-def\";\n\t\tpiiModal.setAttribute( \"data-form\", form.id );\n\n\t\tif ( modalTemplate ) {\n\t\t\tpiiModal.appendChild( modalTemplate.content.cloneNode( true ) );\n\t\t} else {\n\t\t\tpiiModal.innerHTML = `\n\n\t\t\t\t\t\n${ i18nText.header }\n\t\t\t\t\n\t\t\t\t\n\n\t\t\t\t\t\n${ i18nText.intro }\n\t\t\t\t\t${ piiModalFields }\n\t\t\t\t\t\n\n\t\t\t\t\t\t${ i18nText.viewMore }\n\t\t\t\t\t\t${ moreInfoContent }\n\t\t\t\t\t\n\t\t\t\t\n\t\t\t\t\n\n\t\t\t\t\t\n\n\t\t\t\t\t\t\n${ i18nText.cancelBtn }\n\t\t\t\t\t\t\n${ i18nText.confirmBtn }\n\t\t\t\t\t\n\t\t\t\t`;\n\t\t}\n\n\t\t// Using jQuery here to pass the content through DOMpurify\n\t\t$( \"body\" ).append( piiModal );\n\n\t\t// Add PII fields HTML if using a custom UI template\n\t\tif ( modalTemplate ) {\n\n\t\t\t// Fix for implementers that added the \"popup-modal-dismiss\" class to the submit button\n\t\t\t$( \".popup-modal-dismiss[\" + attrScrubSubmit + \"]\" ).removeClass( \"popup-modal-dismiss\" );\n\n\t\t\t$( \"#\" + piiModalID + \" [data-scrub-modal-fields]\" ).html( piiModalFields );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Scrub the form fields on click of the \"Confirm\" button\n$document.on( \"click\", \"#\" + piiModalID + \" [\" + attrScrubSubmit + \"]\", function( ) {\n\tlet modal = document.getElementById( piiModalID ),\n\t\tform = document.getElementById( modal.dataset.form );\n\n\tscrubFormValues( form );\n\n\tif ( form.classList.contains( \"wb-postback\" ) ) {\n\t\t$( form ).trigger( \"wb-postback.submit\", currSubmitter );\n\t} else {\n\t\tform.submit();\n\t}\n\n\t$.magnificPopup.close();\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, wb );\n\n/**\n * @title WET-BOEW Prettify Plugin\n * @overview Wrapper for Google Code Prettify library: https://github.com/google/code-prettify\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @patheard\n */\n/*\n * Syntax highlighting of source code snippets in an html page using [google-code-prettify](https://github.com/google/code-prettify).\n *\n * 1. Apply `class=\"prettyprint\"` to a `pre` or `code` element to apply syntax highlighting. Alternatively use `class=\"all-pre\"` to apply syntax highlighting to all `pre` elements on the page.\n * 2. Apply `class=\"linenums\"` to a `pre` or `code` element to add line numbers. Alternatively use `class=\"all-linenums\"` to all applicable `pre` elements. Specify the starting number by adding `linenums:#` before `linenums`.\n * 3. Add extra language support by applying `class=\"lang-*\"` to each applicable `pre` or `code` element. Supported language syntax CSS classes are as follows:\n *    - lang-apollo\n *    - lang-clj\n *    - lang-css\n *    - lang-dart\n *    - lang-go\n *    - lang-hs\n *    - lang-lisp\n *    - lang-lua\n *    - lang-ml\n *    - lang-n\n *    - lang-proto\n *    - lang-scala\n *    - lang-sql\n *    - lang-tex\n *    - lang-vb\n *    - lang-vhdl\n *    - lang-wiki\n *    - lang-xq\n *    - lang-yaml\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-prettify\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tprettyPrintEvent = \"prettyprint\" + selector,\n\t$document = wb.doc,\n\n\t/*\n\t * Plugin users can override these defaults by setting attributes on the html elements that the\n\t * selector matches.\n\t */\n\tdefaults = {\n\t\tlinenums: false,\n\t\tallpre: false\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\tmodeJS = wb.getMode() + \".js\",\n\t\t\tdeps = [ \"site!deps/prettify\" + modeJS ],\n\t\t\t$elm, classes, settings, i, len, $pre;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\t\t\tclasses = elm.className.split( \" \" );\n\n\t\t\t// Merge default settings with overrides from the selected plugin element. There may be more than one, so don't override defaults globally!\n\t\t\tsettings = $.extend( {}, defaults, $elm.data() );\n\n\t\t\t// Check the element for `lang-*` syntax CSS classes\n\t\t\tfor ( i = 0, len = classes.length; i !== len; i += 1 ) {\n\t\t\t\tif ( classes[ i ].indexOf( \"lang-\" ) === 0 ) {\n\t\t\t\t\tdeps.push( \"site!deps/\" + classes[ i ] + modeJS );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// CSS class overrides of settings\n\t\t\tsettings.allpre = settings.allpre || $elm.hasClass( \"all-pre\" );\n\t\t\tsettings.linenums = settings.linenums || $elm.hasClass( \"linenums\" );\n\n\t\t\t// Apply global settings\n\t\t\tif ( settings.allpre || settings.linenums ) {\n\t\t\t\t$pre = $document.find( \"pre\" );\n\t\t\t\tif ( settings.allpre ) {\n\t\t\t\t\t$pre.addClass( \"prettyprint\" );\n\t\t\t\t}\n\t\t\t\tif ( settings.linenums ) {\n\t\t\t\t\t$pre.filter( \".prettyprint\" ).addClass( \"linenums\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Load the required dependencies and prettify the code once finished\n\t\t\tModernizr.load( {\n\t\t\t\tload: deps,\n\t\t\t\tcomplete: function() {\n\t\t\t\t\t$document.trigger( prettyPrintEvent );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t},\n\n\tprettifyDone = function() {\n\n\t\t// Identify that initialization has completed\n\t\twb.ready( $document, componentName );\n\t},\n\n\t/*\n\t * Invoke the Google pretty print library if it has been initialized\n\t * @method prettyprint\n\t */\n\tprettyprint = function( event ) {\n\t\tif ( event.namespace === componentName &amp;amp;&amp;amp;\n\t\t\ttypeof window.prettyPrint === \"function\" ) {\n\n\t\t\twindow.prettyPrint( prettifyDone );\n\t\t}\n\t};\n\n// Bind the plugin events\n$document\n\t.on( \"timerpoke.wb \" + initEvent, selector, init )\n\t.on( prettyPrintEvent, prettyprint );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Resize\n * @overview Text and window resizing event handler\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @pjackson28\n */\n( function( $, window, document, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-rsz\",\n\tselector = \"#\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\tsizes = [],\n\tevents = [\n\t\t\"txt-rsz.wb\",\n\t\t\"win-rsz-width.wb\",\n\t\t\"win-rsz-height.wb\"\n\t],\n\n\t// Breakpoint names and lower pixel limits\n\tbreakpoints = {\n\t\txxsmallview: 0,\n\t\txsmallview: 480,\n\t\tsmallview: 768,\n\t\tmediumview: 992,\n\t\tlargeview: 1200,\n\t\txlargeview: 1600\n\t},\n\tresizeTest, currentView,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\tlocalResizeTest;\n\n\t\tif ( elm ) {\n\n\t\t\t// Set up the DOM element used for resize testing\n\t\t\tlocalResizeTest = document.createElement( \"span\" );\n\t\t\tlocalResizeTest.innerHTML = \"&amp;#160;\";\n\t\t\tlocalResizeTest.setAttribute( \"id\", componentName );\n\t\t\tdocument.body.appendChild( localResizeTest );\n\t\t\tresizeTest = localResizeTest;\n\n\t\t\t// Get a snapshot of the current sizes\n\t\t\tsizes = [\n\t\t\t\tlocalResizeTest.offsetHeight,\n\t\t\t\twindow.innerWidth || $document.width(),\n\t\t\t\twindow.innerHeight || $document.height()\n\t\t\t];\n\n\t\t\t// Determine the current view\n\t\t\tviewChange( sizes[ 1 ] );\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $document, componentName );\n\t\t}\n\t},\n\n\tviewChange = function( viewportWidth ) {\n\t\tvar breakpoint, viewName;\n\n\t\t// Check for a change between views\n\t\tfor ( breakpoint in breakpoints ) {\n\n\t\t\t// Determine the current view\n\t\t\tif ( viewportWidth &amp;lt; breakpoints[ breakpoint ] ) {\n\t\t\t\tbreak;\n\t\t\t} else {\n\t\t\t\tviewName = breakpoint;\n\t\t\t}\n\t\t}\n\n\t\t// Determine if the current view is different than the previous view\n\t\tif ( viewName !== currentView ) {\n\n\t\t\t// Change the breakpoint class on the html element\n\t\t\twb.html\n\t\t\t\t.removeClass( currentView || \"\" )\n\t\t\t\t.addClass( viewName );\n\n\t\t\t// Update the current view\n\t\t\tcurrentView = viewName;\n\n\t\t\t// Trigger the view event\n\t\t\t$document.trigger( viewName + \".wb\" );\n\t\t}\n\t},\n\n\t/**\n\t * Tests for text size, window width and window height changes and triggers an event when a change is found\n\t * @method test\n\t */\n\ttest = function() {\n\t\tvar currentSizes = [\n\t\t\t\tresizeTest.offsetHeight,\n\t\t\t\twindow.innerWidth || $document.width(),\n\t\t\t\twindow.innerHeight || $document.height()\n\t\t\t],\n\t\t\tlen = currentSizes.length,\n\t\t\ti;\n\n\t\t// Check for a viewport or text size change\n\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\tif ( currentSizes[ i ] !== sizes[ i ] ) {\n\n\t\t\t\t// Change detected so trigger related event\n\t\t\t\t$document.trigger( events[ i ], currentSizes );\n\n\t\t\t\t// Check for a view change\n\t\t\t\tviewChange( currentSizes[ 1 ] );\n\t\t\t}\n\t\t}\n\t\tsizes = currentSizes;\n\n\t\treturn;\n\t};\n\n// Bind the init event to the plugin\n$document.on( initEvent, init );\n\n// Re-test on each timerpoke\n$document.on( \"timerpoke.wb\", selector, test );\n\n// Initialize the resources\n$document.trigger( initEvent );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, document, wb );\n\n/**\n * @title WET-BOEW Session Timeout\n * @overview Helps Web asset owners to provide session timeout and inactivity timeout functionality.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @patheard\n */\n( function( $, DOMPurify, window, document, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar $modal, $modalLink, countdownInterval, i18n, i18nText,\n\t$document = wb.doc,\n\tcomponentName = \"wb-sessto\",\n\tselector = \".\" + componentName,\n\tconfirmClass = componentName + \"-confirm\",\n\tinitEvent = \"wb-init\" + selector,\n\tresetEvent = \"reset\" + selector,\n\tkeepaliveEvent = \"keepalive\" + selector,\n\tinactivityEvent = \"inactivity\" + selector,\n\tdataAttr = componentName,\n\n\t/*\n\t * Plugin users can override these defaults by setting attributes on the html elements that the\n\t * selector matches.\n\t * For example, adding the attribute data-option1=\"false\", will override option1 for that plugin instance.\n\t */\n\tdefaults = {\n\t\tinactivity: 1200000,\t\t/* default inactivity period 20 minutes */\n\t\treactionTime: 180000,\t\t/* default confirmation period of 3 minutes */\n\t\tsessionalive: 1200000,\t\t/* default keepalive period of 20 minutes */\n\t\trefreshCallbackUrl: null,\t/* refresh callback if using AJAX keepalive (no default) */\n\t\tlogouturl: \"./\",\t\t\t/* logout URL to end the session */\n\t\tsignInUrl: null,\t\t\t/* sign-in URL once the session has expired */\n\t\trefreshOnClick: true,\t\t/* refresh session if user clicks on the page */\n\t\trefreshLimit: 120000,\t\t/* default period of 2 minutes (ajax calls happen only once during this period) */\n\t\tmethod: \"POST\",\t\t\t\t/* the request method to use */\n\t\ttextOverrides: null,\t\t/* text overrides (no default) */\n\t\tadditionalData: null,\t\t/* additional data to send with the request */\n\t\trefreshCallback: function( response ) {\t/* callback function used to check the server response */\n\t\t\treturn response.replace( /\\s/g, \"\" ) === \"true\";\n\t\t}\n\t},\n\n\t/**\n\t * @function init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm, settings, onReady;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\n\t\t\t// For backwards compatibility where data-wet-boew was used instead of data-wb-sessto\n\t\t\tif ( !$elm.attr( \"data-\" + componentName ) ) {\n\t\t\t\tdataAttr = \"wet-boew\";\n\t\t\t}\n\n\t\t\t// Merge default settings with overrides from the plugin element\n\t\t\t// and save back to the element for future reference\n\t\t\tsettings = $.extend( {}, defaults, window[ componentName ], $elm.data( dataAttr ) );\n\t\t\t$elm.data( dataAttr, settings );\n\n\t\t\t// Only initialize the i18nText once\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\tconst textOverrides = settings.textOverrides;\n\t\t\t\tif ( textOverrides ) {\n\t\t\t\t\ti18nText = {\n\t\t\t\t\t\tbuttonContinue: Object.hasOwn( textOverrides, \"buttonContinue\" ) ? DOMPurify.sanitize( textOverrides.buttonContinue ) : i18n( \"st-btn-cont\" ),\n\t\t\t\t\t\tbuttonEnd: Object.hasOwn( textOverrides, \"buttonEnd\" ) ? DOMPurify.sanitize( textOverrides.buttonEnd ) : i18n( \"st-btn-end\" ),\n\t\t\t\t\t\tbuttonSignin: Object.hasOwn( textOverrides, \"buttonSignin\" ) ? DOMPurify.sanitize( textOverrides.buttonSignin ) : i18n( \"tmpl-signin\" ),\n\t\t\t\t\t\ttimeoutBegin: i18n( \"st-to-msg-bgn\" ),\n\t\t\t\t\t\ttimeoutEnd: Object.hasOwn( textOverrides, \"timeoutEnd\" ) ? DOMPurify.sanitize( textOverrides.timeoutEnd ) : i18n( \"st-to-msg-end\" ),\n\t\t\t\t\t\ttimeoutTitle: i18n( \"st-msgbx-ttl\" ),\n\t\t\t\t\t\ttimeoutAlready: Object.hasOwn( textOverrides, \"timeoutAlready\" ) ? DOMPurify.sanitize( textOverrides.timeoutAlready ) : i18n( \"st-alrdy-to-msg\" )\n\t\t\t\t\t};\n\t\t\t\t} else {\n\t\t\t\t\ti18nText = {\n\t\t\t\t\t\tbuttonContinue: i18n( \"st-btn-cont\" ),\n\t\t\t\t\t\tbuttonEnd: i18n( \"st-btn-end\" ),\n\t\t\t\t\t\tbuttonSignin: i18n( \"tmpl-signin\" ),\n\t\t\t\t\t\ttimeoutBegin: i18n( \"st-to-msg-bgn\" ),\n\t\t\t\t\t\ttimeoutEnd: i18n( \"st-to-msg-end\" ),\n\t\t\t\t\t\ttimeoutTitle: i18n( \"st-msgbx-ttl\" ),\n\t\t\t\t\t\ttimeoutAlready: i18n( \"st-alrdy-to-msg\" )\n\t\t\t\t\t};\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tonReady = function() {\n\n\t\t\t\t// Setup the refresh on click behaviour\n\t\t\t\tinitRefreshOnClick( $elm, settings );\n\n\t\t\t\t// Initialize the keepalive and inactive timeouts of the plugin\n\t\t\t\t$elm.trigger( resetEvent, settings );\n\n\t\t\t\t// Identify that initialization has completed\n\t\t\t\twb.ready( $elm, componentName );\n\t\t\t};\n\n\t\t\t// Create the modal dialog\n\t\t\tinitModalDialog( onReady );\n\t\t}\n\t},\n\n\t/**\n\t * Initializes a timeout that triggers an event\n\t * @function initEventTimeout\n\t * @param {jQuery DOM Element} $elm Element to trigger the event on\n\t * @param {string} eventName Name of the event to trigger on setTimeout\n\t * @param {mixed} time Time to wait before triggering the event\n\t * @param {Object} settings Key-value object\n\t */\n\tinitEventTimeout = function( $elm, eventName, time, settings ) {\n\t\tvar duration = parseTime( time );\n\n\t\t// Clear any existing timeout for the event\n\t\tclearTimeout( $elm.data( eventName ) );\n\n\t\t// Create the new timeout that will trigger the event\n\t\t$elm.data( eventName, setTimeout( function() {\n\t\t\t$elm.trigger( eventName, settings );\n\t\t}, duration ) );\n\t},\n\n\t/**\n\t * Creates the modal dialog element, appends to the  and initializes the lightbox plugin\n\t * that is used to create the dialog behaviour.\n\t * @function initModalDialog\n\t */\n\tinitModalDialog = function( callback ) {\n\t\tvar modalID = \"#\" + componentName + \"-modal\",\n\t\t\tchild, modal, temp;\n\n\t\tif ( $document.find( modalID ).length === 0 ) {\n\t\t\tmodal = document.createDocumentFragment();\n\t\t\ttemp = document.createElement( \"div\" );\n\n\t\t\t// Create the modal dialog.  A temp \n element is used so that its innerHTML can be set as a string.\n\t\t\ttemp.innerHTML = \"\" + i18nText.timeoutTitle + \"\" +\n\t\t\t\t\"\n\" +\n\t\t\t\t\"\n\n\" + i18nText.timeoutTitle + \"\" +\n\t\t\t\t\"\n\" +\n\t\t\t\t\"\n\" +\n\t\t\t\t\"\";\n\n\t\t\t// Get the temporary \n's top level children and append to the fragment\n\t\t\twhile ( ( child = temp.firstChild ) !== null ) {\n\t\t\t\tmodal.appendChild( child );\n\t\t\t}\n\t\t\tdocument.body.appendChild( modal );\n\n\t\t\t$modal = $document.find( modalID );\n\n\t\t\t// Get object references to the modal and its triggering link\n\t\t\t$modalLink = $modal.prev()\n\t\t\t\t.one( \"wb-ready.wb-lbx\", callback )\n\t\t\t\t.trigger( \"wb-init.wb-lbx\" );\n\t\t} else {\n\t\t\tcallback();\n\t\t}\n\t},\n\n\t/**\n\t * Initialize the refresh on click keepalive behaviour. This will cause a `keepalive.wb-sessto`\n\t * event to be triggered when the document is clicked, limited by the settings.refreshLimit value.\n\t * @function initRefreshOnClick\n\t * @param {jQuery DOM Element} $elm DOM element to trigger the event on\n\t * @param {Object} settings Key-value object that will be passed when event is triggered.\n\t */\n\tinitRefreshOnClick = function( $elm, settings ) {\n\t\tif ( settings.refreshOnClick ) {\n\t\t\t$document.on( \"click\", function( event ) {\n\t\t\t\tvar className = event.target.className,\n\t\t\t\t\tlastActivity, currentTime;\n\n\t\t\t\t// Ignore clicks when the modal dialog is open\n\t\t\t\tif ( ( !className || className.indexOf( confirmClass ) === -1 ) &amp;amp;&amp;amp;\n\t\t\t\t\t$( \".mfp-ready .\" + confirmClass ).length === 0 ) {\n\n\t\t\t\t\tlastActivity = $elm.data( \"lastActivity\" );\n\t\t\t\t\tcurrentTime = getCurrentTime();\n\t\t\t\t\tif ( !lastActivity || ( currentTime - lastActivity ) &amp;gt; settings.refreshLimit ) {\n\t\t\t\t\t\t$elm\n\t\t\t\t\t\t\t.trigger( resetEvent, settings )\n\t\t\t\t\t\t\t.trigger( keepaliveEvent, settings );\n\t\t\t\t\t\t$elm.data( \"lastActivity\", currentTime );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t},\n\n\t/**\n\t * Keepalive session event handler. Sends the POST request to determine if the session is still alive.\n\t * @function keepalive\n\t * @param {jQuery Event} event `keepalive.wb-sessto` event that triggered the function call\n\t * @param {Object} settings Key-value object\n\t */\n\tkeepalive = function( event, settings ) {\n\t\tvar $elm = $( event.target );\n\t\tif ( settings.refreshCallbackUrl !== null ) {\n\t\t\t$.ajax( {\n\t\t\t\turl: settings.refreshCallbackUrl,\n\t\t\t\tdata: settings.additionalData,\n\t\t\t\tdataType: \"text\",\n\t\t\t\tmethod: settings.method,\n\t\t\t\tsuccess: function( response ) {\n\n\t\t\t\t\t// Sanitize the response\n\t\t\t\t\tresponse = DOMPurify.sanitize( response );\n\n\t\t\t\t\t// Session is valid\n\t\t\t\t\tif ( response &amp;amp;&amp;amp; settings.refreshCallback( response ) ) {\n\t\t\t\t\t\t$elm.trigger( resetEvent, settings );\n\n\t\t\t\t\t// Session has timed out - let the user know they need to sign in again\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t// End the inactivity timeouts since the session is already kaput\n\t\t\t\t\t\tclearTimeout( $elm.data( inactivityEvent ) );\n\t\t\t\t\t\tclearTimeout( $elm.data( keepaliveEvent ) );\n\n\t\t\t\t\t\topenModal( {\n\t\t\t\t\t\t\tbody: \"\n\" + i18nText.timeoutAlready + \"\",\n\t\t\t\t\t\t\tbuttons: $( \"\" + i18nText.buttonSignin + \"\" )\n\t\t\t\t\t\t\t\t.data( \"logouturl\", settings.logouturl )\n\t\t\t\t\t\t} );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t},\n\n\t/**\n\t * Inactivity check event handler. Displays the modal dialog to allow the user to confirm their activity.\n\t * @function inactivity\n\t * @param {jQuery Event} event `inactivity.wb-sessto` event that triggered the function call\n\t * @param {Object} settings Key-value object\n\t */\n\tinactivity = function( event, settings ) {\n\t\tvar $buttonContinue, $buttonEnd,\n\t\t\ttime = getTime( settings.reactionTime ),\n\t\t\tstartTime = getCurrentTime(),\n\t\t\ttimeoutBegin = i18nText.timeoutBegin\n\t\t\t\t.replace( \"#min#\", \"\" + time.minutes + \"\" )\n\t\t\t\t.replace( \"#sec#\", \"\" + time.seconds + \"\" ),\n\t\t\tbuttonStart = \"\" + i18nText.buttonContinue + buttonEnd )\n\t\t\t.data( settings )\n\t\t\t.data( \"start\", startTime );\n\t\t$buttonEnd = $( buttonStart + confirmClass + \" btn btn-default'&amp;gt;\" +\n\t\t\ti18nText.buttonEnd + buttonEnd )\n\t\t\t.data( \"logouturl\", settings.logouturl );\n\n\t\topenModal( {\n\t\t\tbody: \"\n\" + timeoutBegin + \"\" + i18nText.timeoutEnd + \"\",\n\t\t\tbuttons: [ $buttonContinue, $buttonEnd ],\n\t\t\topen: function() {\n\t\t\t\tvar $minutes = $modal.find( \".min\" ),\n\t\t\t\t\t$seconds = $modal.find( \".sec\" ),\n\t\t\t\t\tendDuration = settings.reactionTime;\n\n\t\t\t\tcountdownInterval = setInterval( function() {\n\t\t\t\t\tif ( countdown( $minutes, $seconds, startTime, endDuration ) ) {\n\t\t\t\t\t\tclearInterval( countdownInterval );\n\n\t\t\t\t\t\t// Let the user know their session has timed out\n\t\t\t\t\t\t$modal.find( \"p\" ).text( i18nText.timeoutAlready );\n\t\t\t\t\t\t$buttonContinue.text( i18nText.buttonSignin );\n\t\t\t\t\t\t$buttonEnd.hide();\n\t\t\t\t\t}\n\t\t\t\t}, 500 );\n\t\t\t}\n\t\t} );\n\t},\n\n\t/**\n\t * Initialize the inactivity and keepalive timeouts of the plugin\n\t * @function reset\n\t * @param {jQuery Event} event `reset.wb-sessto` event that triggered the function call\n\t * @param {Object} settings Key-value object\n\t */\n\treset = function( event, settings ) {\n\t\tvar $elm = $( event.target );\n\n\t\tinitEventTimeout( $elm, inactivityEvent, settings.inactivity, settings );\n\t\tif ( settings.refreshCallbackUrl !== null ) {\n\t\t\tinitEventTimeout( $elm, keepaliveEvent, settings.sessionalive, settings );\n\t\t}\n\t},\n\n\t/**\n\t * Checks if the user wants to keep their session alive.\n\t * @function inactivity\n\t * @param {jQuery Event} event `confirm.wb-sessto` event that triggered the function call\n\t */\n\tconfirm = function( event ) {\n\t\tvar elm = event.target,\n\t\t\t$elm = $( elm ),\n\t\t\tsettings = $elm.data();\n\n\t\tevent.preventDefault();\n\t\t$.magnificPopup.close();\n\t\tclearInterval( countdownInterval );\n\n\t\t// User wants their session maintained\n\t\tif ( settings.start !== undefined &amp;amp;&amp;amp; ( getCurrentTime() - settings.start ) &amp;lt;= settings.reactionTime ) {\n\t\t\t$( selector )\n\t\t\t\t.trigger( resetEvent, settings )\n\t\t\t\t.trigger( keepaliveEvent, settings );\n\n\t\t// Negative confirmation or the user took too long; logout\n\t\t} else {\n\n\t\t\t// Use setTimeout() to navigate asynchronously (to support lightbox Escape key presses)\n\t\t\tsetTimeout( function() {\n\t\t\t\twindow.location.href = settings.signInUrl ? settings.signInUrl : settings.logouturl;\n\t\t\t} );\n\t\t}\n\t},\n\n\t/**\n\t * Add the modal dialog's content and display it to the user\n\t * @function openModal\n\t * @param {Object} data Key-value object\n\t */\n\topenModal = function( data ) {\n\n\t\t// Detach the modal to prevent reflows while updating the element\n\t\t$modal = $modal.detach();\n\t\t$modal.find( \".modal-body\" ).html( data.body );\n\t\t$modal.find( \".modal-footer\" ).empty().append( data.buttons );\n\n\t\t// Re-attach the modal and open the dialog\n\t\t$modal = $modal.insertAfter( $modalLink );\n\t\t$modalLink.magnificPopup( \"open\" );\n\n\t\t// Execute the open callback if it exists\n\t\tif ( data.open ) {\n\t\t\tdata.open();\n\t\t}\n\t},\n\n\t/**\n\t * Returns the current time in milliseconds\n\t * @function getCurrentTime\n\t * @returns {integer} Current time in milliseconds\n\t */\n\tgetCurrentTime = function() {\n\t\treturn ( new Date() ).getTime();\n\t},\n\n\t/**\n\t * Parses a time value into a milliseconds integer value.\n\t * @function parseTime\n\t * @param {Mixed} value The time value to parse (integer or string)\n\t * @returns {integer} Millisecond integer value parsed from the time value\n\t */\n\tparseTime = function( value ) {\n\t\tvar result, num, mult,\n\t\t\tpowers = {\n\t\t\t\tms: 1,\n\t\t\t\tcs: 10,\n\t\t\t\tds: 100,\n\t\t\t\ts: 1000,\n\t\t\t\tdas: 10000,\n\t\t\t\ths: 100000,\n\t\t\t\tks: 1000000\n\t\t\t};\n\n\t\tif ( value == null ) { //eslint-disable-line no-eq-null\n\t\t\treturn null;\n\t\t}\n\n\t\tresult = /^([0-9]+(?:\\.[0-9]*)?)\\s*(.*s)?$/.exec( value.toString().trim() );\n\t\tif ( result[ 2 ] ) {\n\t\t\tnum = parseFloat( result[ 1 ] );\n\t\t\tmult = powers[ result[ 2 ] ] || 1;\n\t\t\treturn num * mult;\n\t\t}\n\t\treturn value;\n\t},\n\n\t/**\n\t * Converts a millisecond value into minutes and seconds\n\t * @function getTime\n\t * @param {integer} milliseconds The time value in milliseconds\n\t * @returns {Object} An object with a seconds and minutes property\n\t */\n\tgetTime = function( milliseconds ) {\n\t\tvar time = { minutes: \"\", seconds: \"\" };\n\n\t\tif ( milliseconds != null ) { //eslint-disable-line no-eq-null\n\t\t\ttime.minutes = parseInt( ( milliseconds / ( 1000 * 60 ) ) % 60, 10 );\n\t\t\ttime.seconds = parseInt( ( milliseconds / 1000 ) % 60, 10 );\n\t\t}\n\t\treturn time;\n\t},\n\n\t/**\n\t * Given 2 elements representing minutes and seconds, decrement their time value by 1 second\n\t * @function countdown\n\t * @param {jQuery DOM Element} $minutes Element that contains the minute value\n\t * @param {jQuery DOM Element} $seconds Element that contains the second value\n\t * @param { integer } startTime The time value of when the countdown started in milliseconds\n\t * @param { integer } endDuration The time value of the duration of the countdown in milliseconds\n\t * @returns {boolean} Is the countdown finished?\n\t */\n\tcountdown = function( $minutes, $seconds, startTime, endDuration ) {\n\t\tvar newTime = getTime( endDuration - ( getCurrentTime() - startTime ) );\n\n\t\t// Update the DOM elements\n\t\t$minutes.text( newTime.minutes );\n\t\t$seconds.text( newTime.seconds );\n\n\t\treturn newTime.minutes &amp;lt;= 0 &amp;amp;&amp;amp; newTime.seconds &amp;lt;= 0;\n\t};\n\n// Bind the plugin events\n$document.on( \"timerpoke.wb \" + initEvent + \" \" + keepaliveEvent + \" \" +\ninactivityEvent + \" \" + resetEvent, selector, function( event, settings ) {\n\n\tvar eventType = event.type;\n\n\tswitch ( eventType ) {\n\t\tcase \"timerpoke\":\n\t\tcase \"wb-init\":\n\t\t\tinit( event );\n\t\t\tbreak;\n\n\t\tcase \"keepalive\":\n\t\t\tkeepalive( event, settings );\n\t\t\tbreak;\n\n\t\tcase \"inactivity\":\n\t\t\tinactivity( event, settings );\n\t\t\tbreak;\n\n\t\tcase \"reset\":\n\t\t\treset( event, settings );\n\t\t\tbreak;\n\t}\n} );\n\n$document.on( \"click\", \".\" + confirmClass, confirm );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, DOMPurify, window, document, wb );\n\n/**\n * @title WET-BOEW Share widget\n * @overview Facilitates sharing Web content on social media platforms.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @pjackson28\n */\n( function( $, window, document, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-share\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tshareLink = \"shr-lnk\",\n\tpanelCount = 0,\n\t$document = wb.doc,\n\ti18n, i18nText,\n\n\t/*\n\t * Plugin users can override these defaults by setting attributes on the html elements that the\n\t * selector matches.\n\t */\n\tdefaults = {\n\t\thdLvl: \"h2\",\n\n\t\t// Supported types are: \"page\", \"video\" and \"audio\"\n\t\ttype: \"page\",\n\n\t\t// For custom types\n\t\t// custType = \" this comment\" results in \"Share this comment\"\n\t\tcustType: \"\",\n\n\t\turl: wb.pageUrlParts.href,\n\t\ttitle: document.title || $document.find( \"h1:first\" ).text(),\n\n\t\tpnlId: \"\",\n\t\tlnkClass: \"\",\n\t\timg: \"\",\n\t\tdesc: \"\",\n\n\t\t// For filtering the sites that area displayed and controlling the order\n\t\t// they are displayed. Empty array displays all sites in the default order.\n\t\t// Otherwise, it displays the sites in the order in the array using the\n\t\t// keys used by the sites object.\n\t\tfilter: [],\n\n\t\tsites: {\n\n\t\t\t// The definitions of the available bookmarking sites, in URL use\n\t\t\t// '{u}' for the page URL, '{t}' for the page title, {i} for the image, and '{d}' for the description\n\t\t\tblogger: {\n\t\t\t\tname: \"Blogger\",\n\t\t\t\turl: \"https://www.blogger.com/blog_this.pyra?t=&amp;amp;u={u}&amp;amp;n={t}\"\n\t\t\t},\n\t\t\tbluesky: {\n\t\t\t\tname: \"Bluesky\",\n\t\t\t\turl: \"https://bsky.app/intent/compose?text={t}+{u}\"\n\t\t\t},\n\t\t\tdiigo: {\n\t\t\t\tname: \"Diigo\",\n\t\t\t\turl: \"https://www.diigo.com/post?url={u}&amp;amp;title={t}\"\n\t\t\t},\n\t\t\tfacebook: {\n\t\t\t\tname: \"Facebook\",\n\t\t\t\turl: \"https://www.facebook.com/sharer.php?u={u}&amp;amp;t={t}\"\n\t\t\t},\n\t\t\tgmail: {\n\t\t\t\tname: \"Gmail\",\n\t\t\t\turl: \"https://mail.google.com/mail/?view=cm&amp;amp;fs=1&amp;amp;tf=1&amp;amp;to=&amp;amp;su={t}&amp;amp;body={u}%0A{d}\"\n\t\t\t},\n\t\t\tlinkedin: {\n\t\t\t\tname: \"LinkedIn\u00ae\",\n\t\t\t\turl: \"https://www.linkedin.com/shareArticle?mini=true&amp;amp;url={u}&amp;amp;title={t}&amp;amp;ro=false&amp;amp;summary={d}&amp;amp;source=\"\n\t\t\t},\n\t\t\tmastodon: {\n\t\t\t\tname: \"Mastodon\",\n\t\t\t\turl: \"https://share.joinmastodon.org/#text={t}%20{u}\"\n\t\t\t},\n\t\t\tmyspace: {\n\t\t\t\tname: \"MySpace\",\n\t\t\t\turl: \"https://www.myspace.com/Modules/PostTo/Pages/?u={u}&amp;amp;t={t}\"\n\t\t\t},\n\t\t\tpinterest: {\n\t\t\t\tname: \"Pinterest\",\n\t\t\t\turl: \"https://www.pinterest.com/pin/create/button/?url={u}&amp;amp;media={i}&amp;amp;description={t}\"\n\t\t\t},\n\t\t\treddit: {\n\t\t\t\tname: \"reddit\",\n\t\t\t\turl: \"https://reddit.com/submit?url={u}&amp;amp;title={t}\"\n\t\t\t},\n\t\t\ttinyurl: {\n\t\t\t\tname: \"TinyURL\",\n\t\t\t\turl: \"https://tinyurl.com/create.php?url={u}\"\n\t\t\t},\n\t\t\ttumblr: {\n\t\t\t\tname: \"tumblr\",\n\t\t\t\turl: \"https://www.tumblr.com/share/link?url={u}&amp;amp;name={t}&amp;amp;description={d}\"\n\t\t\t},\n\t\t\ttwitter: {\n\t\t\t\tname: \"X\",\n\t\t\t\turl: \"https://twitter.com/intent/tweet?text={t}&amp;amp;url={u}\"\n\t\t\t},\n\t\t\tx: {\n\t\t\t\tname: \"X\",\n\t\t\t\turl: \"https://twitter.com/intent/tweet?text={t}&amp;amp;url={u}\"\n\t\t\t},\n\t\t\tyahoomail: {\n\t\t\t\tname: \"Yahoo! Mail\",\n\t\t\t\turl: \"https://compose.mail.yahoo.com/?to=&amp;amp;subject={t}&amp;amp;body={u}%0A{d}\"\n\t\t\t},\n\t\t\twhatsapp: {\n\t\t\t\tname: \"WhatsApp\",\n\t\t\t\turl: \"https://api.whatsapp.com/send?text={t}%0A{d}%0A{u}\"\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\tsites, heading, settings, panel, link, $share, $elm,\n\t\t\tpageHref, pageTitle, pageImage, pageDescription,\n\t\t\tsiteProperties, url, shareText, id, pnlId, regex,\n\t\t\tfilter, i, len, keys, key;\n\n\t\tif ( elm ) {\n\n\t\t\t// Only initialize the i18nText once\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\tshareText: i18n( \"shr-txt\" ),\n\t\t\t\t\tpage: i18n( \"shr-pg\" ),\n\t\t\t\t\tvideo: i18n( \"shr-vid\" ),\n\t\t\t\t\taudio: i18n( \"shr-aud\" ),\n\t\t\t\t\tdisclaimer: i18n( \"shr-disc\" ),\n\t\t\t\t\temail: i18n( \"email\" )\n\t\t\t\t};\n\n\t\t\t\t// Add an email mailto option\n\t\t\t\tdefaults.sites.email = {\n\t\t\t\t\tname: i18nText.email,\n\t\t\t\t\turl: \"mailto:?subject={t}&amp;amp;body={u}%0A{d}\",\n\t\t\t\t\tisMailto: true\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t$elm = $( elm );\n\t\t\tsettings = $.extend(\n\t\t\t\ttrue,\n\t\t\t\t{},\n\t\t\t\tdefaults,\n\t\t\t\twindow[ componentName ],\n\t\t\t\twb.getData( $elm, componentName )\n\t\t\t);\n\t\t\tsites = settings.sites;\n\t\t\tfilter = settings.filter;\n\t\t\theading = settings.hdLvl;\n\n\t\t\tshareText = i18nText.shareText + ( settings.custType.length !== 0 ? settings.custType : i18nText[ settings.type ] );\n\t\t\tpnlId = settings.pnlId;\n\t\t\tid = \"shr-pg\" + ( pnlId.length !== 0 ? \"-\" + pnlId : panelCount );\n\t\t\tpageHref = encodeURIComponent( settings.url );\n\n\t\t\tregex = /'|&amp;#39;|&amp;apos;/g;\n\t\t\tpageTitle = encodeURIComponent( settings.title )\n\t\t\t\t.replace( regex, \"%27\" );\n\t\t\tpageImage = encodeURIComponent( settings.img );\n\t\t\tpageDescription = encodeURIComponent( settings.desc )\n\t\t\t\t.replace( regex, \"%27\" );\n\n\t\t\t// Don't create the panel for the second link (class=\"link-only\")\n\t\t\tif ( elm.className.indexOf( \"link-only\" ) === -1 ) {\n\t\t\t\tpanel = \"\n\n&amp;lt;\" + heading + \" class='modal-title'&amp;gt;\" +\n\t\t\t\t\tshareText + \"&amp;lt;/\" + heading + \"&amp;gt;\n\" +\n\t\t\t\t\t\"\n\";\n\n\t\t\t\t// If there is no filter array of site keys, then generate an array of site keys\n\t\t\t\tif ( !filter || filter.length === 0 ) {\n\t\t\t\t\tkeys = [];\n\t\t\t\t\tfor ( key in sites ) {\n\t\t\t\t\t\tif ( Object.prototype.hasOwnProperty.call( sites, key ) ) {\n\t\t\t\t\t\t\tkeys.push( key );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tkeys = filter;\n\t\t\t\t}\n\n\t\t\t\t// i18n-friendly sort of the site keys\n\t\t\t\tkeys.sort( function( x, y ) {\n\t\t\t\t\treturn wb.normalizeDiacritics( x ).localeCompare( wb.normalizeDiacritics( y ) );\n\t\t\t\t} );\n\n\t\t\t\t// If Twitter and X are both present, only keep X\n\t\t\t\tif ( keys.includes( \"twitter\" ) &amp;amp;&amp;amp; keys.includes( \"x\" ) ) {\n\t\t\t\t\tkeys = keys.filter( function( item ) {\n\t\t\t\t\t\treturn item !== \"twitter\";\n\t\t\t\t\t} );\n\t\t\t\t}\n\n\t\t\t\tlen = keys.length;\n\n\t\t\t\t// Generate the panel\n\t\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t\tkey = keys[ i ];\n\t\t\t\t\tsiteProperties = sites[ key ];\n\t\t\t\t\turl = siteProperties.url\n\t\t\t\t\t\t.replace( /\\{u\\}/, pageHref )\n\t\t\t\t\t\t.replace( /\\{t\\}/, pageTitle )\n\t\t\t\t\t\t.replace( /\\{i\\}/, pageImage )\n\t\t\t\t\t\t.replace( /\\{d\\}/, pageDescription );\n\t\t\t\t\tpanel += \"\n\" +\n\t\t\t\t\t\tsiteProperties.name + \"\";\n\t\t\t\t}\n\n\t\t\t\tpanel += \"\n\" + i18nText.disclaimer +\n\t\t\t\t\t\"\n\";\n\t\t\t\tpanelCount += 1;\n\t\t\t}\n\t\t\tlink = \"\" +\n\t\t\t\tshareText + \"\";\n\n\t\t\t$share = $( ( panel ? panel : \"\" ) + link );\n\n\t\t\t$elm.append( $share );\n\n\t\t\t$share\n\t\t\t\t.trigger( \"wb-init.wb-lbx\" );\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, document, wb );\n\n/**\n * @title WET-BOEW step form\n * @overview Provide ability for a form to be broken into steps.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @kodecount\n */\n( function( $, window, document, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-steps\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\ti18n, i18nText,\n\tbtnPrevious, btnNext, btnSubmit,\n\tquizSelector = selector + \".quiz\",\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} evt Event that triggered the function call\n\t */\n\tinit = function( evt ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( evt, componentName, selector );\n\n\t\tif ( elm ) {\n\n\t\t\t// Ensure there is a unique id on the element\n\t\t\tif ( !elm.id ) {\n\t\t\t\telm.id = wb.getId();\n\t\t\t}\n\n\t\t\t// Only initialize the i18nText once\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\tprv: i18n( \"prv\" ),\n\t\t\t\t\tnxt: i18n( \"nxt\" ),\n\t\t\t\t\trelpreposition: i18n( \"rel-preposition\" ),\n\t\t\t\t\tprogresslabel: i18n( \"progress-label\" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * Variable and function definitions\n\t\t\t * These will be initialized once per instance of plugin.\n\t\t\t */\n\t\t\tvar form = elm.getElementsByTagName( \"FORM\" )[ 0 ],\n\t\t\t\tfieldsets = ( form ) ? $( form ).children( \"fieldset\" ) : 0,\n\t\t\t\thasStepsInitialized;\n\n\t\t\t// Initialize navigation buttons\n\t\t\tbtnPrevious = createStepsButton( \"prev\", \"mrgn-rght-sm mrgn-bttm-md\", i18nText.prv );\n\t\t\tbtnNext = createStepsButton( \"next\", \"mrgn-bttm-md\", i18nText.nxt );\n\t\t\tbtnSubmit = form.querySelector( \"input[type=submit], button[type=submit]\" );\n\t\t\tbtnSubmit.classList.add( \"mrgn-bttm-md\" );\n\n\t\t\t/*\n\t\t\t * Determines if html is correctly formatted and initialize all fieldsets/legend combinations into steps.\n\t\t\t */\n\t\t\tfor ( var i = 0, len = fieldsets.length; i &amp;lt; len; i++ ) {\n\n\t\t\t\t/*\n\t\t\t\t * Variable and function definitions\n\t\t\t\t * These well be initialized once per instance of each fieldset.\n\t\t\t\t * Determines the following business rules:\n\t\t\t\t *  -Only allow steps if elements are in proper order fieldset -&amp;gt; legend -&amp;gt; div\n\t\t\t\t *  -Only allow NEXT button on first step\n\t\t\t\t *  -Only allow final SUBMIT button on last step\n\t\t\t\t */\n\t\t\t\tvar fieldset = fieldsets[ i ],\n\t\t\t\t\tisFirstFieldset = ( i === 0 ) ? true : false,\n\t\t\t\t\tisLastFieldset = ( i === ( len - 1 ) ) ? true : false,\n\t\t\t\t\tlegend = fieldset.firstElementChild,\n\t\t\t\t\tdiv = ( legend &amp;amp;&amp;amp; legend.tagName === \"LEGEND\" ) ? legend.nextElementSibling : false,\n\t\t\t\t\tbuttonGroup = document.createElement( \"div\" ),\n\t\t\t\t\twrapper = document.createElement( \"div\" ),\n\t\t\t\t\tbuttonGroupClassList = buttonGroup.classList,\n\t\t\t\t\tdivClassList = div.classList;\n\n\t\t\t\tbuttonGroupClassList.add( \"buttons\" );\n\t\t\t\tfieldset.parentNode.insertBefore( wrapper, fieldset );\n\t\t\t\twrapper.appendChild( fieldset );\n\t\t\t\twrapper.classList.add( \"steps-wrapper\" );\n\n\t\t\t\tif ( div &amp;amp;&amp;amp; div.tagName === \"DIV\" ) {\n\t\t\t\t\tvar btnClone;\n\t\t\t\t\thasStepsInitialized = true;\n\n\t\t\t\t\tif ( !isFirstFieldset ) {\n\t\t\t\t\t\tbtnClone = btnPrevious.cloneNode( true );\n\t\t\t\t\t\tsetStepsBtnEvent( btnClone );\n\t\t\t\t\t\tbuttonGroup.appendChild( btnClone );\n\t\t\t\t\t\twrapper.appendChild( buttonGroup );\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !isLastFieldset ) {\n\t\t\t\t\t\tbtnClone = btnNext.cloneNode( true );\n\t\t\t\t\t\tsetStepsBtnEvent( btnClone );\n\t\t\t\t\t\tbuttonGroup.appendChild( btnClone );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tbuttonGroup.appendChild( btnSubmit );\n\t\t\t\t\t}\n\n\t\t\t\t\twrapper.appendChild( buttonGroup );\n\n\t\t\t\t\tfieldset.classList.add( \"wb-tggle-fildst\" );\n\t\t\t\t\tdivClassList.add( \"hidden\" );\n\t\t\t\t\tbuttonGroupClassList.add( \"hidden\" );\n\n\t\t\t\t\tif ( isFirstFieldset ) {\n\t\t\t\t\t\tlegend.classList.add( \"wb-steps-active\" );\n\t\t\t\t\t\tbtnClone.classList.remove( \"hidden\" );\n\t\t\t\t\t\tdivClassList.remove( \"hidden\" );\n\t\t\t\t\t\tbuttonGroupClassList.remove( \"hidden\" );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t/*\n\t\t\t * if steps has initialized hide any precreated submit or reset buttons\n\t\t\t */\n\t\t\tif ( form &amp;amp;&amp;amp; hasStepsInitialized ) {\n\t\t\t\t$( form ).children( \"input\" ).hide();\n\t\t\t\twb.ready( $( elm ), componentName );\n\t\t\t}\n\n\t\t\t//Quiz code\n\t\t\tif ( elm.classList.contains( \"quiz\" ) ) {\n\n\t\t\t\t//Initialize all instances\n\t\t\t\tlet $elm = $( elm ),\n\t\t\t\t\tnumQuestion = $( \".steps-wrapper\", $elm ).length; // Calculate number of questions\n\n\t\t\t\t// Addition to UI (Ex: progress bar)\n\t\t\t\tif ( !elm.querySelector( \"progress\" ) ) {\n\t\t\t\t\t$( \"form\", $elm ).prepend( \"\" + i18nText.progresslabel + \"\n\" );\n\t\t\t\t}\n\n\t\t\t\tupdateQuizStep( evt );\n\n\t\t\t\t$( document ).on( \"click\", quizSelector + \" .steps-wrapper div.buttons &amp;gt; :button\", updateQuizStep );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * @method updateQuizStep\n\t * @param {JavaScript element} e\n\t */\n\tupdateQuizStep = function( e ) {\n\n\t\t// Get wb-steps component\n\t\tlet quizElement,\n\t\t\tcurrentElement = e.currentTarget;\n\n\t\tif ( currentElement.classList.contains( \"quiz\" ) ) {\n\t\t\tquizElement = currentElement;\n\t\t} else {\n\t\t\tquizElement = $( currentElement ).parentsUntil( quizSelector ).parent().get( 0 );\n\t\t}\n\n\t\t// Find the steps form context and validate it is a quiz\n\t\tlet currentTabId = $( \"legend.wb-steps-active:first-child\", quizElement ).parents().prevAll( \".steps-wrapper\" ).length + 1,\n\t\t\t$progressBar = $( \".progressBar\", quizElement ), // Get progress bar\n\t\t\tnumQuestion = $progressBar.attr( \"max\" ); // Get number of questions\n\n\t\t// Set the progress label\n\t\t$( \"p.progressText\", quizElement ).text( currentTabId + i18nText.relpreposition + numQuestion );\n\n\t\t// Update progress bar\n\t\t$progressBar.val( currentTabId );\n\n\t\t// Hide other steps that are not active\n\t\t$( \".steps-wrapper\", quizElement ).removeClass( \"hidden\" );\n\t\t$( \".steps-wrapper:has( div.hidden )\", quizElement ).addClass( \"hidden\" );\n\t},\n\n\n\t/**\n\t * @method createStepsButton\n\t * @param {string var} tagName, {string var} type, {boolean var} isPrimary, {string var} style, {string var} text\n\t * @returns {Object} A ready-to-use button element\n\t */\n\tcreateStepsButton = function( type, style, text ) {\n\t\tvar control = document.createElement( \"BUTTON\" );\n\n\t\t// set default attributes\n\t\tcontrol.className = ( type === \"prev\" ? \"btn btn-md btn-default\" : \"btn btn-md btn-primary\" ) + \" \" + style;\n\t\tcontrol.setAttribute( \"type\", \"button\" );\n\t\tcontrol.innerHTML = text;\n\n\t\treturn control;\n\t},\n\n\t/**\n\t * @method setStepsBtnEvent\n\t * @param {JavaScript element} elm\n\t */\n\tsetStepsBtnEvent = function( elm ) {\n\t\telm.addEventListener( \"click\", function( evt ) {\n\t\t\tevt.preventDefault();\n\t\t\tvar classes = ( this.className ) ? this.className : false,\n\t\t\t\tisNext = ( classes &amp;amp;&amp;amp; classes.indexOf( \"btn-primary\" ) &amp;gt; -1 ),\n\t\t\t\tisFormValid = true,\n\t\t\t\tparentElement = this.parentElement,\n\t\t\t\tparentParentElement = parentElement.parentElement,\n\t\t\t\tparentPreviousClassList = parentElement.previousElementSibling.classList;\n\n\t\t\t// confirm if form is valid\n\t\t\tif ( isNext &amp;amp;&amp;amp; jQuery.validator &amp;amp;&amp;amp; jQuery.validator !== \"undefined\" ) {\n\t\t\t\tisFormValid =  $( \"#\" + parentParentElement.parentElement.id ).valid();\n\t\t\t}\n\n\t\t\t// continue if valid\n\t\t\tif ( isFormValid ) {\n\t\t\t\tshowSteps( parentParentElement, isNext );\n\t\t\t\tif ( isNext ) {\n\t\t\t\t\tparentPreviousClassList.remove( \"wb-steps-error\" );\n\t\t\t\t}\n\t\t\t} else if ( isNext &amp;amp;&amp;amp; !isFormValid ) {\n\t\t\t\tparentPreviousClassList.add( \"wb-steps-error\" );\n\t\t\t}\n\t\t} );\n\t},\n\n\t/**\n\t * @method showSteps\n\t * @param {JavaScript element} elm and {boolean var} isNext\n\t */\n\tshowSteps = function( elm, isNext ) {\n\t\tvar fieldsetElement = elm.getElementsByTagName( \"FIELDSET\" )[ 0 ],\n\t\t\tfields = fieldsetElement.getElementsByTagName( \"div\" )[ 0 ],\n\t\t\tlegend = fieldsetElement.getElementsByTagName( \"legend\" )[ 0 ],\n\t\t\tbuttonGroup = elm.querySelector( \"div.buttons\" ),\n\t\t\tfieldset;\n\n\t\tif ( elm ) {\n\t\t\tfields.classList.add( \"hidden\" );\n\t\t\tbuttonGroup.classList.add( \"hidden\" );\n\n\t\t\tif ( legend ) {\n\t\t\t\tlegend.classList.remove( \"wb-steps-active\" );\n\t\t\t}\n\n\t\t\tfieldset = ( !isNext ) ? elm.previousElementSibling : elm.nextElementSibling;\n\t\t\tif ( fieldset ) {\n\t\t\t\tlegend = fieldset.getElementsByTagName( \"LEGEND\" )[ 0 ];\n\t\t\t\telm = fieldset.getElementsByTagName( \"DIV\" )[ 0 ];\n\t\t\t\tbuttonGroup = fieldset.querySelector( \"div.buttons\" );\n\t\t\t\tif ( legend ) {\n\t\t\t\t\tlegend.classList.add( \"wb-steps-active\" );\n\t\t\t\t\tlegend.tabIndex = 0;\n\t\t\t\t\tlegend.focus();\n\t\t\t\t\tlegend.tabIndex = -1;\n\t\t\t\t}\n\t\t\t\tif ( elm ) {\n\t\t\t\t\telm.classList.remove( \"hidden\" );\n\t\t\t\t}\n\t\t\t\tif ( buttonGroup ) {\n\t\t\t\t\tbuttonGroup.classList.remove( \"hidden\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, document, wb );\n\n/**\n * @title WET-BOEW Tables\n * @overview Integrates the DataTables plugin into WET providing searching, sorting, filtering, pagination and other advanced features for tables.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @jeresiv\n */\n/*jshint scripturl:true*/\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-tables\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\tidCount = 0,\n\ti18n, i18nText, defaults,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\telmId;\n\n\t\tif ( elm ) {\n\t\t\telmId = elm.id;\n\n\t\t\t// Ensure there is a unique id on the element\n\t\t\tif ( !elmId ) {\n\t\t\t\telmId = componentName + \"-id-\" + idCount;\n\t\t\t\tidCount += 1;\n\t\t\t\telm.id = elmId;\n\t\t\t}\n\n\t\t\t// Only initialize the i18nText once\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\taria: {\n\t\t\t\t\t\tsortAscending: i18n( \"sortAsc\" ),\n\t\t\t\t\t\tsortDescending: i18n( \"sortDesc\" )\n\t\t\t\t\t},\n\t\t\t\t\temptyTable: i18n( \"emptyTbl\" ),\n\t\t\t\t\tinfo: i18n( \"infoEntr\" ),\n\t\t\t\t\tinfoEmpty: i18n( \"infoEmpty\" ),\n\t\t\t\t\tinfoFiltered: i18n( \"infoFilt\" ),\n\t\t\t\t\tlengthMenu: i18n( \"lenMenu\" ),\n\t\t\t\t\tloadingRecords: i18n( \"load\" ),\n\t\t\t\t\tpaginate: {\n\t\t\t\t\t\tfirst: i18n( \"first\" ),\n\t\t\t\t\t\tlast: i18n( \"last\" ),\n\t\t\t\t\t\tnext: i18n( \"nxt\" ),\n\t\t\t\t\t\tprevious: i18n( \"prv\" ),\n\t\t\t\t\t\tpage: i18n( \"page\" )\n\t\t\t\t\t},\n\t\t\t\t\tprocessing: i18n( \"process\" ),\n\t\t\t\t\tsearch: i18n( \"filter\" ),\n\t\t\t\t\tthousands: i18n( \"info1000\" ),\n\t\t\t\t\tzeroRecords: i18n( \"infoEmpty\" ),\n\t\t\t\t\ttblFilterInstruction: i18n( \"tbFilterInst\" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\tdefaults = {\n\t\t\t\tasStripeClasses: [],\n\t\t\t\tlanguage: i18nText,\n\t\t\t\tdom: \"&amp;lt;'top'fil&amp;gt;rt&amp;lt;'bottom'p&amp;gt;&amp;lt;'clear'&amp;gt;\"\n\t\t\t};\n\n\t\t\tModernizr.load( {\n\t\t\t\tload: [ \"site!deps/jquery.dataTables\" + wb.getMode() + \".js\" ],\n\t\t\t\ttestReady: function() {\n\t\t\t\t\treturn ( $.fn.dataTable &amp;amp;&amp;amp; $.fn.dataTable.version );\n\t\t\t\t},\n\t\t\t\tcomplete: function() {\n\t\t\t\t\tvar $elm = $( \"#\" + elmId ),\n\t\t\t\t\t\tdataTableExt = $.fn.dataTableExt,\n\t\t\t\t\t\tsettings = wb.getData( $elm, componentName ) || {};\n\n\t\t\t\t\t// Explicitly deactivate the paging for the filterEmphasis provisional feature/styling when not configured\n\t\t\t\t\tif ( $elm.hasClass( \"provisional\" ) &amp;amp;&amp;amp; $elm.hasClass( \"filterEmphasis\" ) ) {\n\t\t\t\t\t\tsettings.paging = settings.paging ? settings.paging : false;\n\t\t\t\t\t}\n\n\t\t\t\t\t/*\n\t\t\t\t\t * Extend sorting support\n\t\t\t\t\t */\n\t\t\t\t\t$.extend( dataTableExt.type.order, {\n\n\t\t\t\t\t\t// Enable internationalization support in the sorting\n\t\t\t\t\t\t\"html-pre\": function( a ) {\n\t\t\t\t\t\t\treturn wb.normalizeDiacritics(\n\t\t\t\t\t\t\t\t!a ? \"\" : a.replace ?\n\t\t\t\t\t\t\t\t\ta.replace( /&amp;lt;.*?&amp;gt;/g, \"\" ).toLowerCase() : a + \"\"\n\t\t\t\t\t\t\t);\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"string-case-pre\": function( a ) {\n\t\t\t\t\t\t\treturn wb.normalizeDiacritics( a );\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"string-pre\": function( a ) {\n\t\t\t\t\t\t\treturn wb.normalizeDiacritics( a );\n\t\t\t\t\t\t},\n\n\t\t\t\t\t\t// Formatted number sorting\n\t\t\t\t\t\t\"formatted-num-asc\": function( a, b ) {\n\t\t\t\t\t\t\treturn wb.formattedNumCompare( a, b );\n\t\t\t\t\t\t},\n\t\t\t\t\t\t\"formatted-num-desc\": function( a, b ) {\n\t\t\t\t\t\t\treturn wb.formattedNumCompare( b, a );\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\n\t\t\t\t\t// Create the DataTable object\n\t\t\t\t\t$elm.dataTable( $.extend( true, {}, defaults, window[ componentName ], settings ) );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t},\n\tupdatePaginationMarkup = function( $pagination, setFocusOnId ) {\n\n\t\tvar ol = document.createElement( \"OL\" ),\n\t\t\tli = document.createElement( \"LI\" ),\n\t\t\tpaginate_buttons = $pagination.find( \".paginate_button\" ),\n\t\t\tnavFocusOnId;\n\n\t\tif ( $pagination.length === 0 ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Set the element to get the focus upon navigation\n\t\tnavFocusOnId = setFocusOnId || $pagination.get( 0 ).id;\n\n\t\t// Update Pagination List\n\t\tfor ( var i = 0; i &amp;lt; paginate_buttons.length; i++ ) {\n\t\t\tvar item = li.cloneNode( true );\n\t\t\titem.appendChild( paginate_buttons[ i ] );\n\t\t\tol.appendChild( item );\n\t\t}\n\n\t\tol.className = \"pagination mrgn-tp-0 mrgn-bttm-0\";\n\t\t$pagination.empty();\n\t\t$pagination.append( ol );\n\n\t\t// Prefix each page number with an invisible \"Page\" so the link reads as\n\t\t// \"Page 2\" rather than a bare \"2\".\n\t\t//\n\t\t// The current page is not marked here. DataTables sets aria-current=\"page\"\n\t\t// on it, which is the correct pattern for pagination. This used to add\n\t\t// aria-pressed as well, from a time when DataTables did not, but these are\n\t\t// anchors carrying an explicit role=\"link\" and aria-pressed is not allowed\n\t\t// on that role, so it was an axe aria-allowed-attr error on every page\n\t\t// button.\n\t\t$pagination.find( \".paginate_button\" )\n\t\t\t.attr( {\n\t\t\t\t\"href\": \"#\" + navFocusOnId\n\t\t\t} )\n\n\t\t\t// This is required to override the datatable.js (v1.10.13) behavior to cancel the event propagation on anchor element.\n\t\t\t.on( \"keypress\", function( evn ) {\n\t\t\t\tif ( evn.keyCode === 13 ) {\n\t\t\t\t\twindow.location = evn.target.href;\n\t\t\t\t}\n\t\t\t} )\n\n\t\t\t.not( \".previous, .next\" )\n\t\t\t.html( function( index, oldHtml ) {\n\t\t\t\treturn \"\" + i18nText.paginate.page + \" \" + oldHtml;\n\t\t\t} );\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Handle the draw.dt event\n$document.on( \"draw.dt\", selector, function( event, settings ) {\n\tvar $elm = $( event.target ),\n\t\tpagination = $elm.next( \".bottom\" ).find( \"div:first-child\" ),\n\t\tpagination_top = $elm.prevAll( \".top\" ).find( \"div.dataTables_paginate\" ),\n\t\tpaginate_buttons = $elm.next( \".bottom\" ).find( \".paginate_button\" ),\n\t\tpbLength = paginate_buttons.length,\n\t\tpHasLF = pagination.find( \".last, .first\" ).length === 2,\n\t\tpHasPN = pagination.find( \".previous, .next\" ).length === 2;\n\n\t// Handle sorting/ordering\n\tvar order = $elm.dataTable( { \"retrieve\": true } ).api().order();\n\t$elm.find( \"th\" ).each( function( index ) {\n\t\tvar $th = $( this ),\n\t\t\t$btn = $th.find( \"button\" );\n\t\tif ( order &amp;amp;&amp;amp; order.length &amp;amp;&amp;amp; order[ 0 ][ 0 ] === index ) {\n\t\t\tvar label = ( order[ 0 ][ 1 ] === \"desc\" ) ? i18nText.aria.sortAscending : i18nText.aria.sortDescending;\n\t\t\tlabel = $btn.text() + label.replace( /&amp;#160;/g, \" \" );\n\t\t\t$btn.attr( \"title\", label );\n\t\t}\n\t\t$th.removeAttr( \"aria-label\" );\n\t} );\n\n\t// Determine if Pagination required\n\tif (\n\t\tpbLength === 1 ||\n\t\t(\n\t\t\tpbLength === 3 &amp;amp;&amp;amp;\n\t\t\t(\n\t\t\t\tpHasLF ||\n\t\t\t\tpHasPN\n\t\t\t)\n\t\t) ||\n\t\t(\n\t\t\tpbLength === 5 &amp;amp;&amp;amp;\n\t\t\tpHasLF &amp;amp;&amp;amp;\n\t\t\tpHasPN\n\t\t)\n\t) {\n\t\tpagination.addClass( \"hidden\" );\n\t\tpagination_top.addClass( \"hidden\" );\n\t} else {\n\n\t\t// Make sure Pagination is visible\n\t\tpagination.removeClass( \"hidden\" );\n\t\tpagination_top.removeClass( \"hidden\" );\n\n\t\tupdatePaginationMarkup( pagination, $elm.get( 0 ).id );\n\t\tupdatePaginationMarkup( pagination_top );\n\t}\n\n\tif ( wb.isReady ) {\n\t\t$elm\n\t\t\t.find( wb.allSelectors )\n\t\t\t.addClass( \"wb-init\" )\n\t\t\t.filter( \":not(#\" + $elm.id + \" .wb-init .wb-init)\" )\n\t\t\t.trigger( \"timerpoke.wb\" );\n\t}\n\n\t// Identify that the table has been updated\n\t$elm.trigger( \"wb-updated\" + selector, [ settings ] );\n} );\n\n// Identify that initialization has completed\n$document.on( \"init.dt\", selector, function( event ) {\n\tvar $elm = $( event.target ),\n\t\tsettings = $.extend( true, {}, defaults, window[ componentName ], wb.getData( $elm, componentName ) );\n\n\t// Handle sorting/ordering\n\tvar ordering = ( settings &amp;amp;&amp;amp; settings.ordering === false ) ? false : true;\n\tif ( ordering ) {\n\t\t$elm.find( \"thead th\" ).each( function() {\n\t\t\tvar $th = $( this ),\n\t\t\t\tlabel = ( $th.attr( \"aria-sort\" ) === \"ascending\" ) ? i18nText.aria.sortDescending : i18nText.aria.sortAscending;\n\t\t\tif ( ( $th.attr( \"data-orderable\" ) !== \"false\" ) &amp;amp;&amp;amp; !( $th.hasClass( \"sorting_disabled\" ) ) ) {\n\t\t\t\t$th.html( \"\" + $th.html() + \"\" );\n\t\t\t\t$th.removeAttr( \"aria-label tabindex aria-controls\" );\n\t\t\t}\n\t\t} );\n\t\t$elm.attr( \"aria-label\", i18nText.tblFilterInstruction );\n\t}\n\n\t// Apply the filter emphasis style\n\tif ( $elm.hasClass( \"provisional\" ) &amp;amp;&amp;amp; $elm.hasClass( \"filterEmphasis\" ) ) {\n\t\t$elm.parent().addClass( \"provisional filterEmphasis\" );\n\t}\n\n\twb.ready( $( event.target ), componentName );\n} );\n\n// Handle the draw.dt event\n$document.on( \"submit\", \".wb-tables-filter\", function( event ) {\n\n\tevent.preventDefault();\n\n\tvar $form = $( this ),\n\t\t$datatable = $( \"#\" + $form.data( \"bind-to\" ) ).dataTable( { \"retrieve\": true } ).api(),\n\t\t$toNumber = function stringToNumber( number ) {\n\t\t\tnumber = number.replace( /[^0-9\\-,.]+/g, \"\" );\n\t\t\tif ( /[,]\\d{1,2}$/.test( number ) ) {\n\t\t\t\tnumber = number.replace( /(\\d{2})$/, \".$1\" );\n\t\t\t}\n\t\t\tnumber = number.replace( /,/g, \"\" );\n\t\t\treturn parseFloat( number );\n\t\t},\n\t\t$isDate = function isDate( date ) {\n\t\t\treturn date instanceof Date &amp;amp;&amp;amp; !isNaN( date );\n\t\t};\n\n\t// Lets reset the search\n\t$datatable.search( \"\" ).columns().search( \"\" );\n\n\t// Lets loop through all options\n\tvar $prevCol = -1, $cachedVal = \"\";\n\t$form.find( \"[name]\" ).each( function() {\n\t\tvar $elm = $( this ),\n\t\t\t$val = $elm.val(),\n\t\t\t$value = \"\",\n\t\t\t$regex = \"\",\n\t\t\t$column = parseInt( $elm.attr( \"data-column\" ), 10 ),\n\t\t\t$isAopts = $elm.data( \"aopts\" ),\n\t\t\t$aoptsSelector = \"[data-aopts*='\\\"column\\\": \\\"\" + $column + \"\\\"']:checked\",\n\t\t\t$aopts = $( $aoptsSelector ),\n\t\t\t$aoType = ( $aopts &amp;amp;&amp;amp; $aopts.data( \"aopts\" ) ) ? $aopts.data( \"aopts\" ).type.toLowerCase() : \"\",\n\t\t\t$fData;\n\n\t\t// Ignore the advanced options fields\n\t\tif ( $isAopts ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Verifies if filtering the same column\n\t\tif ( $column !== $prevCol || $prevCol === -1 ) {\n\t\t\t$cachedVal = \"\";\n\t\t}\n\t\t$prevCol = $column;\n\n\t\t// Filters based on input type\n\t\tif ( $elm.is( \"select\" ) ) {\n\t\t\t$value = $elm.find( \"option:selected\" ).val();\n\t\t} else if ( $elm.is( \"input[type='number']\" ) ) {\n\t\t\tvar $minNum, $maxNum = null;\n\n\t\t\t// Retain minimum number (always the first number input)\n\t\t\tif ( $cachedVal === \"\" ) {\n\t\t\t\t$cachedVal = parseFloat( $val );\n\t\t\t\t$cachedVal = ( $cachedVal ) ? $cachedVal : \"-0\";\n\t\t\t} else {\n\t\t\t\t$maxNum = parseFloat( $val );\n\t\t\t\t$maxNum = ( $maxNum ) ? $maxNum : \"-0\";\n\t\t\t}\n\t\t\t$minNum = $cachedVal;\n\n\t\t\t//Number filtering logic needs to be reviewed in order to remove the \"-0\" value (issue #9235)\n\t\t\t// Generates a list of numbers (within the min and max number)\n\t\t\tif ( !isNaN( $minNum ) &amp;amp;&amp;amp; !isNaN( $maxNum ) ) {\n\t\t\t\t$fData = $datatable.column( $column ).data().filter( function( obj ) {\n\t\t\t\t\tvar $num = $toNumber( obj.toString() );\n\n\t\t\t\t\tif ( !isNaN( $num ) ) {\n\t\t\t\t\t\tif ( $aoType === \"and\" ) {\n\t\t\t\t\t\t\tif ( $cachedVal !== $maxNum &amp;amp;&amp;amp; $cachedVal !== \"-0\" &amp;amp;&amp;amp; $maxNum !== \"0\" &amp;amp;&amp;amp; $num &amp;gt;= $minNum &amp;amp;&amp;amp; $num &amp;lt;= $maxNum ) {\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tif ( $maxNum === null ) { // only one input number\n\t\t\t\t\t\t\t\treturn $minNum === \"-0\" || $minNum === $num;\n\t\t\t\t\t\t\t} else if ( $maxNum === $cachedVal &amp;amp;&amp;amp; $cachedVal === \"-0\" ) { // both are empty\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t} else if ( $maxNum !== \"-0\" &amp;amp;&amp;amp; $minNum === $maxNum &amp;amp;&amp;amp; $num === $maxNum ) { // min and max are the same\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t} else if ( $maxNum === \"-0\" &amp;amp;&amp;amp; $num &amp;gt;= $minNum ) { // max number is missing\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t} else if ( $cachedVal === \"-0\" &amp;amp;&amp;amp; $num &amp;lt;= $maxNum ) { // min number is missing\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t} else if ( $cachedVal !== \"-0\" &amp;amp;&amp;amp; $num &amp;gt;= $minNum &amp;amp;&amp;amp; $num &amp;lt;= $maxNum ) { // min and max are present\n\t\t\t\t\t\t\t\treturn true;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn false;\n\t\t\t\t} );\n\t\t\t\t$fData = $fData.join( \"|\" );\n\n\t\t\t\t// If no numbers match set as -0, so no results return\n\t\t\t\t$value = ( $fData ) ? $fData : \"-0\";\n\t\t\t\t$regex = \"(\" + $value.replace( /&amp;nbsp;|\\s/g, \"\\\\s\" ).replace( /\\$/g, \"\\\\$\" ) + \")\";\n\t\t\t}\n\t\t} else if ( $elm.is( \"input[type='date']\" ) &amp;amp;&amp;amp; $val ) {\n\t\t\tvar $minDate, $maxDate;\n\n\t\t\t// Retain minimum date (always the first date input)\n\t\t\tif ( $cachedVal === \"\" ) {\n\t\t\t\t$cachedVal = new Date( $val );\n\t\t\t\t$cachedVal.setDate( $cachedVal.getDate() + 1 );\n\t\t\t\t$cachedVal.setHours( 0, 0, 0, 0 );\n\t\t\t}\n\t\t\t$minDate = $cachedVal;\n\n\t\t\t// Maximum date is always the current selected date\n\t\t\t$maxDate = new Date( $val );\n\t\t\t$maxDate.setDate( $maxDate.getDate() + 1 );\n\t\t\t$maxDate.setHours( 23, 59, 59, 999 );\n\n\t\t\t// Generates a list of date strings (within the min and max date)\n\t\t\t$fData = $datatable.column( $column ).data().filter( function( obj ) {\n\t\t\t\tvar $date = obj.replace( /[0-9]{2}\\s[0-9]{2}:/g, function( e ) {\n\t\t\t\t\treturn e.replace( /\\s/g, \"T\" );\n\t\t\t\t} );\n\n\t\t\t\tif ( !$date.includes( \"T\" ) ) {\n\t\t\t\t\t$date = $date + \"T00:00:00\";\n\t\t\t\t}\n\t\t\t\t$date = new Date( $date );\n\t\t\t\t$date.setHours( 0, 0, 0, 0 );\n\n\t\t\t\tif ( !$isDate( $minDate ) || !$isDate( $maxDate ) || !$isDate( $date ) ) {\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t\treturn ( $date &amp;gt;= $minDate &amp;amp;&amp;amp; $date &amp;lt;= $maxDate );\n\t\t\t} );\n\t\t\t$fData = $fData.join( \"|\" );\n\n\t\t\t// If no dates match set as element value, so no results return\n\t\t\t$value = ( $fData ? $fData : $val );\n\t\t} else if ( $elm.is( \":checkbox\" ) ) {\n\n\t\t\t// Verifies if checkbox is checked before setting value\n\t\t\tif ( $elm.is( \":checked\" ) ) {\n\t\t\t\tif ( $aoType === \"both\" ) {\n\t\t\t\t\t$cachedVal += \"(?=.*\\\\b\" + $val + \"\\\\b)\";\n\t\t\t\t} else {\n\t\t\t\t\t$cachedVal += ( $cachedVal.length &amp;gt; 0 ) ? \"|\" : \"\";\n\t\t\t\t\t$cachedVal += $val;\n\t\t\t\t}\n\n\t\t\t\t$value = $cachedVal;\n\t\t\t\t$value = $value.replace( /\\s/g, \"\\\\s*\" );\n\n\t\t\t\t// Adjust regex based on advanced options\n\t\t\t\tswitch ( $aoType ) {\n\t\t\t\t\tcase \"both\":\n\t\t\t\t\t\t$regex = \"(\" + $value + \").*\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"either\":\n\t\t\t\t\t\t$regex = \"^(\" + $value + \")$\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"and\":\n\t\t\t\t\t\t$regex = ( $value.indexOf( \"|\" ) &amp;gt; -1 ) ? \"^(\" + $value + \"|[,\\\\s])(\" + $value + \"|[,\\\\s])+$\" : \"(\" + $value + \")\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t\tcase \"any\":\n\t\t\t\t\tdefault:\n\t\t\t\t\t\t$regex = \"(\" + $value + \")\";\n\t\t\t\t\t\tbreak;\n\t\t\t\t}\n\t\t\t}\n\t\t} else {\n\t\t\t$value = $val;\n\t\t}\n\n\t\tif ( $value ) {\n\n\t\t\t// Verifies if regex was preset, if not preset use 'contains value' as default\n\t\t\tif ( !$regex ) {\n\t\t\t\tif ( $elm[ 0 ].getAttribute( \"data-exact\" ) ) {\n\t\t\t\t\t$regex = \"^\" + $value + \"$\";\n\t\t\t\t} else {\n\t\t\t\t\t$value = $value.replace( /\\s/g, \"\\\\s*\" );\n\t\t\t\t\t$regex = \"(\" + $value + \")\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t$datatable.column( $column ).search( $regex, true );\n\t\t}\n\t} );\n\t$datatable.draw();\n\treturn false;\n} );\n\n$document.on( \"click\", \".wb-tables-filter [type='reset']\", function( event ) {\n\tevent.preventDefault();\n\n\tvar $form = $( this ).closest( \".wb-tables-filter\" ),\n\t\t$datatable = $( \"#\" + $form.data( \"bind-to\" ) ).dataTable( { \"retrieve\": true } ).api();\n\n\t$datatable.search( \"\" ).columns().search( \"\" ).draw();\n\n\t$form.find( \"select\" ).prop( \"selectedIndex\", 0 );\n\t$form.find( \"input:checkbox, input:radio\" ).prop( \"checked\", false );\n\t$form.find( \":input\" ).not( \":button, :submit, :reset, :hidden, :checkbox, :radio\" ).val( \"\" );\n\treturn false;\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Tabbed interface\n * @overview Dynamically stacks multiple sections of content, transforming them into a tabbed interface.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author WET Community\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-tabs\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tshiftEvent = \"wb-shift\" + selector,\n\tselectEvent = \"wb-select\" + selector,\n\tupdatedEvent = \"wb-updated\" + selector,\n\tsetFocusEvent = \"setfocus.wb\",\n\tcontrols = selector + \" ul[role=tablist] a, \" + selector + \" ul[role=tablist] .tab-count\",\n\tinitialized = false,\n\ttabsAccordionClass = \"tabs-acc\",\n\tnestedTglPanelSelector = \"&amp;gt; .tabpanels &amp;gt; details &amp;gt; .tgl-panel\",\n\tactivePanel = \"-activePanel\",\n\tactivateEvent = \"click keydown\",\n\tpagePath = wb.pageUrlParts.pathname + \"#\",\n\t$document = wb.doc,\n\ti18n, i18nText,\n\n\t// Includes \"smallview\", \"xsmallview\" and \"xxsmallview\"\n\tsmallViewPattern = \"smallview\",\n\tisSmallView, oldIsSmallView,\n\n\tdefaults = {\n\t\texcludePlay: false,\n\t\tinterval: 6,\n\t\tupdateHash: false,\n\t\tignoreSession: false\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\tisCarousel = true,\n\t\t\topen = \"open\",\n\t\t\thashTargetLen = 0,\n\t\t\t$panels, $tablist, activeId, $openPanel, $elm, elmId, $hashTarget,\n\t\t\tsettings, $panel, i, len, tablist, isOpen, hashFocus,\n\t\t\tnewId, positionY, groupClass, $tabPanels, openByHash;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\n\t\t\t// For backwards compatibility. Should be removed in WET v4.1\n\t\t\tif ( $elm.children( \".tabpanels\" ).length === 0 ) {\n\t\t\t\t$elm.children( \"[role=tabpanel], details\" ).wrapAll( \"\n\" );\n\t\t\t}\n\n\t\t\t$panels = $elm.find( \"&amp;gt; .tabpanels &amp;gt; [role=tabpanel], &amp;gt; .tabpanels &amp;gt; details\" );\n\t\t\t$tablist = $elm.children( \"[role=tablist]\" );\n\t\t\tisCarousel = $tablist.length !== 0;\n\n\t\t\t// If a carousel contains only 1 panel, remove its controls, visually-hide its thumbnails and prevent it from attempting to play\n\t\t\tif ( isCarousel &amp;amp;&amp;amp; $panels.length === 1 ) {\n\n\t\t\t\t$elm.removeClass( \"show-thumbs playing\" );\n\t\t\t\t$elm.addClass( \"exclude-controls\" );\n\t\t\t}\n\n\t\t\tactiveId = wb.jqEscape( wb.pageUrlParts.hash.substring( 1 ) );\n\t\t\thashFocus = activeId.length !== 0;\n\t\t\t$openPanel = hashFocus ? $panels.filter( \"#\" + activeId ) : undefined;\n\t\t\topenByHash = $openPanel &amp;amp;&amp;amp; $openPanel.length !== 0;\n\t\t\telmId = elm.id;\n\n\t\t\tsettings = $.extend(\n\t\t\t\ttrue,\n\t\t\t\t{},\n\t\t\t\tdefaults,\n\t\t\t\t{\n\t\t\t\t\tinterval: $elm.hasClass( \"slow\" ) ?\n\t\t\t\t\t\t9 : $elm.hasClass( \"fast\" ) ?\n\t\t\t\t\t\t\t3 : defaults.interval,\n\t\t\t\t\texcludeControls: $elm.hasClass( \"exclude-controls\" ),\n\t\t\t\t\texcludePlay: $elm.hasClass( \"exclude-play\" ),\n\t\t\t\t\tupdateHash: $elm.hasClass( \"update-hash\" ),\n\t\t\t\t\tplaying: $elm.hasClass( \"playing\" ),\n\t\t\t\t\tignoreSession: $elm.hasClass( \"ignore-session\" )\n\t\t\t\t},\n\t\t\t\twindow[ componentName ],\n\t\t\t\twb.getData( $elm, componentName )\n\t\t\t);\n\n\t\t\ttry {\n\n\t\t\t\t// If the panel was not set by URL hash\n\t\t\t\tif ( !openByHash ) {\n\t\t\t\t\tif ( hashFocus ) {\n\t\t\t\t\t\t$hashTarget = $panels.find( \"#\" + activeId );\n\t\t\t\t\t\thashTargetLen = $hashTarget.length;\n\t\t\t\t\t}\n\n\t\t\t\t\t// If the anchor target is within a panel, then open that panel\n\t\t\t\t\tif ( hashTargetLen !== 0 ) {\n\t\t\t\t\t\tactiveId = $hashTarget.closest( \"[role=tabpanel]\" ).attr( \"id\" );\n\n\t\t\t\t\t// Attempt to retrieve active panel from sessionStorage\n\t\t\t\t\t} else {\n\t\t\t\t\t\tif ( !settings.ignoreSession ) {\n\t\t\t\t\t\t\tactiveId = sessionStorage.getItem( pagePath + elmId + activePanel );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( activeId ) {\n\t\t\t\t\t\t$openPanel = $panels.filter( \"#\" + activeId );\n\t\t\t\t\t}\n\n\t\t\t\t// If the panel was set by URL hash, then store in sessionStorage\n\t\t\t\t} else {\n\t\t\t\t\tif ( !settings.ignoreSession ) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tsessionStorage.setItem( pagePath + elmId + activePanel, activeId );\n\t\t\t\t\t\t} catch ( error ) {\n\n\t\t\t\t\t\t\t/* swallow error */\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} catch ( error ) {\n\n\t\t\t\t/* swallow error */\n\t\t\t}\n\n\t\t\t// Determine the current view\n\t\t\tisSmallView = document.documentElement.className.indexOf( smallViewPattern ) !== -1;\n\n\t\t\t// Only initialize the i18nText once\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\tprev: i18n( \"prv\" ),\n\t\t\t\t\tnext: i18n( \"nxt\" ),\n\t\t\t\t\tplay: i18n( \"tab-play\" ),\n\t\t\t\t\trotStart: i18n( \"tab-rot\" ).on,\n\t\t\t\t\trotStop: i18n( \"tab-rot\" ).off,\n\t\t\t\t\tspace: i18n( \"space\" ),\n\t\t\t\t\thyphen: i18n( \"hyphen\" ),\n\t\t\t\t\tpause: i18n( \"pause\" ),\n\t\t\t\t\ttabCount: i18n( \"lb-curr\" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Build the tablist and enhance the panels as needed for details/summary\n\t\t\tif ( !isCarousel ) {\n\t\t\t\t$elm.addClass( tabsAccordionClass );\n\t\t\t\tgroupClass = elmId + \"-grp\";\n\t\t\t\t$tabPanels = $elm.children( \".tabpanels\" );\n\t\t\t\t$panels = $tabPanels.children( \"details\" );\n\t\t\t\tlen = $panels.length;\n\n\t\t\t\t$tabPanels.detach();\n\n\t\t\t\t// Ensure there is only one panel open\n\t\t\t\t// Order of priority is hash, open property, first details\n\t\t\t\tif ( !$openPanel || $openPanel.length === 0 ) {\n\t\t\t\t\t$openPanel = $panels.filter( \"[open]\" ).first();\n\t\t\t\t\tif ( $openPanel.length === 0 ) {\n\t\t\t\t\t\t$openPanel = $panels.eq( 0 );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\t$panels.removeAttr( open );\n\t\t\t\t$openPanel.attr( open, open );\n\n\t\t\t\t// Hide the tablist in small view and the summary elements in large view\n\t\t\t\ttablist = \"\n\";\n\n\t\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t\t$panel = $panels.eq( i );\n\t\t\t\t\t$panel\n\t\t\t\t\t\t.addClass( groupClass )\n\t\t\t\t\t\t.html(\n\t\t\t\t\t\t\t$panel.html()\n\t\t\t\t\t\t\t\t.replace( /(&amp;lt;\\/summary&amp;gt;)/i, \"$1\n\" ) +\n\t\t\t\t\t\t\t\"\"\n\t\t\t\t\t\t);\n\n\t\t\t\t\tnewId = $panel.attr( \"id\" );\n\t\t\t\t\tif ( !newId ) {\n\t\t\t\t\t\tnewId = wb.getId();\n\t\t\t\t\t\t$panel.attr( \"id\", newId );\n\t\t\t\t\t}\n\t\t\t\t\tisOpen = !!$panel.attr( open );\n\n\t\t\t\t\tif ( isSmallView ) {\n\t\t\t\t\t\tif ( !wb.supportsDetails ) {\n\t\t\t\t\t\t\t$panel.toggleClass( \"open\", isOpen );\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$panel.attr( {\n\t\t\t\t\t\t\trole: \"tabpanel\",\n\t\t\t\t\t\t\topen: open\n\t\t\t\t\t\t} );\n\t\t\t\t\t\t$panel.addClass( ( wb.supportsDetails ? \"\" : open + \" \" ) + \"fade \" + ( isOpen ? \"in\" : \"noheight out wb-inv\" ) );\n\t\t\t\t\t}\n\n\t\t\t\t\ttablist += \"\" +\n\t\t\t\t\t\t$panel.children( \"summary\" ).html() + \"\";\n\t\t\t\t}\n\n\t\t\t\t$tablist = $( tablist + \"\" );\n\t\t\t\t$tabPanels.find( \"&amp;gt; details &amp;gt; summary\" )\n\t\t\t\t\t.addClass( \"wb-toggle tgl-tab\" )\n\t\t\t\t\t.attr( \"data-toggle\", \"{\\\"parent\\\": \\\"#\" + elmId +\n\t\t\t\t\t\t\"\\\", \\\"group\\\": \\\".\" + groupClass + \"\\\"}\" );\n\n\t\t\t\t$elm\n\t\t\t\t\t.prepend( $tablist )\n\t\t\t\t\t.append( $tabPanels )\n\t\t\t\t\t.trigger( \"wb-init.wb-toggle\" );\n\t\t\t} else if ( $openPanel &amp;amp;&amp;amp; $openPanel.length !== 0 ) {\n\t\t\t\t$panels.filter( \".in\" )\n\t\t\t\t\t.addClass( \"out noheight\" )\n\t\t\t\t\t.removeClass( \"in\" );\n\t\t\t\t$openPanel\n\t\t\t\t\t.addClass( \"in\" )\n\t\t\t\t\t.removeClass( \"out noheight\" );\n\t\t\t\t$tablist.find( \".active\" )\n\t\t\t\t\t.removeClass( \"active\" );\n\t\t\t\t$tablist.find( \"a\" )\n\t\t\t\t\t.filter( \"[href$='\" + activeId + \"']\" )\n\t\t\t\t\t.parent()\n\t\t\t\t\t.addClass( \"active\" );\n\t\t\t}\n\n\t\t\tdrizzleAria( $panels, $tablist );\n\n\t\t\tif ( isCarousel ) {\n\n\t\t\t\t// Returns true if the tabs should be rotating automatically\n\t\t\t\tif ( createControls( $tablist, settings ) ) {\n\n\t\t\t\t\t// Register this specific tabs instance for timerpoke.wb events\n\t\t\t\t\twb.add( \"#\" + elmId + selector );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// If focus is being set by the URL hash, then ensure the tabs are\n\t\t\t// not above the top of the viewport (if the panel was the target),\n\t\t\t// or the anchor is not above the top of viewport (if the anchor was\n\t\t\t// the target)\n\t\t\tif ( hashFocus ) {\n\n\t\t\t\t// Need a slight delay to allow for the reflow\n\t\t\t\tsetTimeout( function() {\n\t\t\t\t\tif ( openByHash ) {\n\t\t\t\t\t\tpositionY = $tablist.offset().top;\n\t\t\t\t\t} else if ( hashTargetLen !== 0 ) {\n\t\t\t\t\t\tpositionY = $hashTarget.offset().top;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tpositionY = -1;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( positionY !== -1 &amp;amp;&amp;amp; positionY &amp;lt; document.body.scrollTop ) {\n\t\t\t\t\t\tdocument.body.scrollTop = positionY;\n\t\t\t\t\t}\n\t\t\t\t}, 1 );\n\t\t\t}\n\n\t\t\t$elm.data( {\n\t\t\t\t\"wb-tabs\": {\n\t\t\t\t\tpanels: $panels,\n\t\t\t\t\ttablist: $tablist,\n\t\t\t\t\tsettings: settings,\n\t\t\t\t\tctime: 0\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\tinitialized = true;\n\t\t\tonResize( $elm );\n\n\t\t\t// Update the URL hash if needed\n\t\t\tif ( settings.updateHash ) {\n\t\t\t\tupdateHash( $openPanel[ 0 ] );\n\t\t\t}\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t},\n\n\t/**\n\t * @method onTimerPoke\n\t * @param {jQuery DOM element} $elm The plugin element\n\t */\n\tonTimerPoke = function( $elm ) {\n\t\tvar data = $elm.data( componentName ),\n\t\t\tdelayCurrent = parseFloat( data.ctime ) + 0.5;\n\n\t\t// Check if we need to rotate panels\n\t\tif ( parseFloat( data.settings.interval ) &amp;lt;= delayCurrent ) {\n\t\t\t$elm.trigger( shiftEvent );\n\t\t\tdelayCurrent = 0;\n\t\t}\n\n\t\tdata.ctime = delayCurrent;\n\t\t$elm.data( componentName, data );\n\t},\n\n\t/**\n\t * @method createControls\n\t * @param {jQuery DOM element} $tablist The plugin element\n\t * @param {object} settings Settings for the tabs instance\n\t * @returns {boolean} Whether or not the tabs should be rotating initially\n\t */\n\tcreateControls = function( $tablist, settings ) {\n\t\tvar prevText = i18nText.prev,\n\t\t\tnextText = i18nText.next,\n\t\t\tspaceText = i18nText.space,\n\t\t\texcludeControls = settings.excludeControls,\n\t\t\texcludePlay = settings.excludePlay,\n\t\t\tisPlaying = !excludeControls &amp;amp;&amp;amp; !excludePlay &amp;amp;&amp;amp; settings.playing,\n\t\t\tstate = isPlaying ? i18nText.pause : i18nText.play,\n\t\t\thidden = isPlaying ? i18nText.rotStop : i18nText.rotStart,\n\t\t\tglyphiconStart = \"\",\n\t\t\ttabsToggleStart = \"\n\",\n\t\t\t$tabs = $tablist.find( \"[role=tab]\" ),\n\t\t\tcurrentIndex = $tabs.index( $tabs.filter( \"[aria-selected=true]\" ) ) + 1,\n\t\t\ti18nTabCount = i18nText.tabCount,\n\t\t\tfirstReplaceIndex = i18nTabCount.indexOf( \"%\" ),\n\t\t\tlastReplaceIndex = i18nTabCount.lastIndexOf( \"%\" ) + 1,\n\t\t\tprevControl = tabsToggleStart + \"prv'&amp;gt;\" + glyphiconStart + \"chevron-left'&amp;gt;\" +\n\t\t\t\twbInvStart + prevText + btnEnd,\n\t\t\ttabCount = tabsToggleStart + \" tab-count' tabindex='0'&amp;gt;\n\" +\n\t\t\t\ti18nTabCount.substring( 0, firstReplaceIndex ) +\n\t\t\t\t\"\n\" +\n\t\t\t\ti18nTabCount.substring( firstReplaceIndex, lastReplaceIndex )\n\t\t\t\t\t.replace( \"%curr%\", \"\" + currentIndex + \"\" )\n\t\t\t\t\t.replace( \"%total%\", $tabs.length ) +\n\t\t\t\t\"\" + i18nTabCount.substring( lastReplaceIndex ) +\n\t\t\t\t\"\",\n\t\t\tnextControl = tabsToggleStart + \"nxt'&amp;gt;\" + glyphiconStart + \"chevron-right'&amp;gt;\" +\n\t\t\t\twbInvStart + nextText + btnEnd,\n\t\t\tplayControl =  tabsToggleStart + \"plypause'&amp;gt;\" + iconState + \" \" + state +\n\t\t\t\t\"\" + wbInvStart + spaceText + i18nText.hyphen + spaceText +\n\t\t\t\thidden + btnEnd;\n\n\t\tif ( !excludeControls ) {\n\t\t\t$tablist.prepend( prevControl + tabCount + nextControl );\n\t\t}\n\n\t\tif ( !excludeControls &amp;amp;&amp;amp; !excludePlay ) {\n\t\t\t$tablist.append( playControl );\n\t\t}\n\t\t$tablist.find( \"a[role=button]\" ).attr( \"href\", \"javascript:;\" );\n\n\t\treturn isPlaying;\n\t},\n\n\t/**\n\t * @method drizzleAria\n\t * @param {jQuery DOM element} $panels Tabpanel groupings\n\t * @param {jQuery DOM element} $tablist Pointers to the groupings\n\t */\n\tdrizzleAria = function( $panels, $tabList ) {\n\n\t\t// Let's process the elements for aria\n\t\tvar panels = $panels.get(),\n\t\t\ttabCounter = panels.length - 1,\n\t\t\tlistItems = $tabList.children().get(),\n\t\t\tlistCounter = listItems.length - 1,\n\t\t\tisDetails = $panels[ 0 ].nodeName.toLowerCase() === \"details\",\n\t\t\tisActive, item, link, panelId, activeFound;\n\n\t\tfor ( ; tabCounter !== -1; tabCounter -= 1 ) {\n\t\t\titem = panels[ tabCounter ];\n\t\t\tisActive = item.className.indexOf( \"out\" ) === -1;\n\n\t\t\tif ( !isDetails || !isSmallView ) {\n\t\t\t\titem.setAttribute( \"aria-hidden\", isActive ? \"false\" : \"true\" );\n\t\t\t\titem.setAttribute( \"aria-expanded\", isActive ? \"true\" : \"false\" );\n\t\t\t}\n\t\t\titem.setAttribute( \"aria-labelledby\", item.id + \"-lnk\" );\n\t\t}\n\n\t\tactiveFound = false;\n\t\tfor ( ; listCounter !== -1; listCounter -= 1 ) {\n\t\t\titem = listItems[ listCounter ];\n\t\t\titem.setAttribute( \"role\", \"presentation\" );\n\n\t\t\tisActive = item.className.indexOf( \"active\" ) !== -1;\n\t\t\tif ( isActive ) {\n\t\t\t\tactiveFound = true;\n\t\t\t} else if ( listCounter === 0 &amp;amp;&amp;amp; !activeFound ) {\n\t\t\t\tisActive = true;\n\t\t\t\titem.className += \" active\";\n\t\t\t}\n\n\t\t\tlink = item.getElementsByTagName( \"a\" )[ 0 ];\n\t\t\tpanelId = link.getAttribute( \"href\" ).substring( 1 );\n\n\t\t\tlink.tabIndex = isActive ? \"0\" : \"-1\";\n\t\t\tlink.setAttribute( \"role\", \"tab\" );\n\t\t\tlink.setAttribute( \"aria-selected\", isActive ? \"true\" : \"false\" );\n\t\t\tlink.setAttribute( \"aria-controls\", panelId );\n\t\t\tlink.id = panelId + \"-lnk\";\n\t\t}\n\t\t$tabList.attr( \"aria-live\", \"off\" );\n\t},\n\n\t/**\n\t * @method updateHash\n\t * @param {DOM element} elm Tabpanel to be referenced in the URL hash\n\t */\n\tupdateHash = function( elm ) {\n\t\tvar elmId = elm.id;\n\n\t\twb.ignoreHashChange = true;\n\t\telm.id += \"-off\";\n\t\twindow.location.hash = elmId;\n\t\telm.id = elmId;\n\t\twb.ignoreHashChange = false;\n\t},\n\n\tupdateNodes = function( $panels, $controls, $next, $control ) {\n\t\tvar $tabs = $controls.find( \"[role=tab]\" ),\n\t\t\tnewIndex = $tabs.index( $control ) + 1,\n\t\t\t$currPanel = $panels.filter( \".in\" ),\n\t\t\t$container = $next.closest( selector ),\n\t\t\ttabSettings = $container.data( componentName ).settings,\n\t\t\tmPlayers = $currPanel.find( \".wb-mltmd-inited\" ).get(),\n\t\t\tmPlayersLen = mPlayers.length,\n\t\t\tmPlayer, i, j, last;\n\n\t\t// Handle the direction of the slide transitions\n\t\tif ( $currPanel[ 0 ].className.indexOf( \"slide\" ) !== -1 ) {\n\t\t\ti = $panels.index( $currPanel );\n\t\t\tj = $panels.index( $next );\n\t\t\tlast = $panels.length - 1;\n\n\t\t\t$panels.toggleClass(\n\t\t\t\t\"reverse\",\n\t\t\t\t( i &amp;gt; j &amp;amp;&amp;amp; ( i !== last || j !== 0 ) ) || ( i === 0 &amp;amp;&amp;amp; j === last )\n\t\t\t);\n\t\t}\n\n\t\t$currPanel\n\t\t\t.removeClass( \"in\" )\n\t\t\t.addClass( \"out noheight\" )\n\t\t\t.attr( {\n\t\t\t\t\"aria-hidden\": \"true\",\n\t\t\t\t\"aria-expanded\": \"false\"\n\t\t\t} );\n\n\t\t// Pause all multimedia players in the current panel\n\t\tfor ( i = 0; i !== mPlayersLen; i += 1 ) {\n\t\t\tmPlayer = mPlayers[ i ];\n\t\t\tif ( mPlayer.player ) {\n\t\t\t\tmPlayer.player( \"pause\" );\n\t\t\t}\n\t\t}\n\n\t\t$next\n\t\t\t.removeClass( \"out noheight\" )\n\t\t\t.addClass( \"in\" )\n\t\t\t.attr( {\n\t\t\t\t\"aria-hidden\": \"false\",\n\t\t\t\t\"aria-expanded\": \"true\"\n\t\t\t} );\n\n\t\t$controls\n\t\t\t.find( \".active\" )\n\t\t\t.removeClass( \"active\" )\n\t\t\t.children( \"a\" )\n\t\t\t.attr( {\n\t\t\t\t\"aria-selected\": \"false\",\n\t\t\t\ttabindex: \"-1\"\n\t\t\t} );\n\n\t\t// Update the Item x of n\n\t\t$controls\n\t\t\t.find( \".curr-index\" )\n\t\t\t.html( newIndex );\n\n\t\t$control\n\t\t\t.attr( {\n\t\t\t\t\"aria-selected\": \"true\",\n\t\t\t\ttabindex: \"0\"\n\t\t\t} )\n\t\t\t.parent()\n\t\t\t.addClass( \"active\" );\n\n\t\t// Update sessionStorage with the current active panel\n\t\tif ( !tabSettings.ignoreSession ) {\n\t\t\ttry {\n\t\t\t\tsessionStorage.setItem(\n\t\t\t\t\tpagePath + $container.attr( \"id\" ) + activePanel,\n\t\t\t\t\t$next.attr( \"id\" )\n\t\t\t\t);\n\t\t\t} catch ( error ) {\n\n\t\t\t\t/* swallow error */\n\t\t\t}\n\t\t}\n\n\t\t// Update the URL hash if needed\n\t\tif ( tabSettings.updateHash ) {\n\t\t\tupdateHash( $next[ 0 ] );\n\t\t}\n\n\t\t// Identify that the tabbed interface/carousel was updated\n\t\t$container.trigger( updatedEvent, [ $next ] );\n\t},\n\n\t/**\n\t * @method onPick\n\t * @param {jQuery DOM element} $sldr The plugin element\n\t * @param {jQuery DOM element} $elm The selected link from the tablist\n\t */\n\tonPick = function( $sldr, $elm ) {\n\t\tvar data = $sldr.data( componentName ),\n\t\t\t$panels = data.panels,\n\t\t\t$controls = data.tablist,\n\t\t\t$next = $panels.filter( \"#\" + $elm.attr( \"aria-controls\" ) );\n\n\t\tupdateNodes( $panels, $controls, $next, $elm );\n\t},\n\n\t/**\n\t * @method onShift\n\t * @param (jQuery event} event Current event\n\t * @param {jQuery DOM element} $elm The plugin element\n\t */\n\tonShift = function( event, $elm ) {\n\t\tvar data = $elm.data( componentName ),\n\t\t\t$panels = data.panels,\n\t\t\tlen = $panels.length,\n\t\t\tcurrent = $elm.find( \"&amp;gt; .tabpanels &amp;gt; .in\" ).prevAll( \"[role=tabpanel]\" ).length,\n\t\t\tautoCycle = !event.shiftto,\n\t\t\tnext = current &amp;gt; len ? 0 : current + ( autoCycle ? 1 : event.shiftto );\n\n\t\tonSelect( $panels[ ( next &amp;gt; len - 1 ) ? 0 : ( next &amp;lt; 0 ) ? len - 1 : next ].id, autoCycle );\n\t},\n\n\t/**\n\t * @method onSelect\n\t * @param (string) id Id attribute of the panel\n\t * @param (boolean) autoCycle Whether change is caused by an auto cycle\n\t */\n\tonSelect = function( id, autoCycle ) {\n\t\tvar panelSelector = \"#\" + id,\n\t\t\t$panel = $( panelSelector ),\n\t\t\t$panelSelectorLink;\n\n\t\tif ( isSmallView &amp;amp;&amp;amp; $panel[ 0 ].nodeName.toLowerCase() === \"details\" ) {\n\t\t\t$panel.children( \"summary\" ).trigger( $panel.attr( \"open\" ) ? setFocusEvent : \"click\" );\n\t\t} else {\n\t\t\t$panelSelectorLink = $( panelSelector + \"-lnk\" );\n\t\t\t$panelSelectorLink.trigger( {\n\t\t\t\ttype: \"click\",\n\t\t\t\twhich: autoCycle ? undefined : 1\n\t\t\t} );\n\n\t\t\t// Don't change the focus if change is cause by an auto cycle\n\t\t\tif ( !autoCycle ) {\n\t\t\t\t$panelSelectorLink.trigger( setFocusEvent );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * @method onCycle\n\t * @param {jQuery DOM element} $elm The plugin element\n\t * @param {integer} shiftto The item to shift to\n\t */\n\tonCycle = function( $elm, shiftto ) {\n\t\t$elm.trigger( {\n\t\t\ttype: shiftEvent,\n\t\t\tshiftto: shiftto\n\t\t} );\n\t},\n\n\t/**\n\t * @method onResize\n\t * @param {jQuery Object} $currentElm Element being initialized (only during initialization process).\n\t */\n\tonResize = function( $currentElm ) {\n\t\tvar $elms, $elm, $tabPanels, $details, $detailsElm, $tablist,\n\t\t\t$openDetails, openDetailsId, activeId, $summary, $panelElm,\n\t\t\ti, len, j, len2, viewChange, isInit, isActive;\n\n\t\tif ( initialized ) {\n\t\t\tisSmallView = document.documentElement.className.indexOf( smallViewPattern ) !== -1;\n\t\t\tviewChange = isSmallView !== oldIsSmallView;\n\t\t\tisInit = $currentElm.length ? true : false;\n\n\t\t\tif ( viewChange || isInit ) {\n\t\t\t\t$elms = isInit ? $currentElm : $( selector );\n\t\t\t\tlen = $elms.length;\n\n\t\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t\t$elm = $elms.eq( i );\n\t\t\t\t\t$tabPanels = $elm.children( \".tabpanels\" );\n\t\t\t\t\t$details = $tabPanels.children( \"details\" );\n\t\t\t\t\tlen2 = $details.length;\n\n\t\t\t\t\tif ( $details.length !== 0 ) {\n\t\t\t\t\t\t$tabPanels.detach();\n\t\t\t\t\t\t$summary = $details.children( \"summary\" );\n\t\t\t\t\t\t$tablist = $elm.children( \"ul\" );\n\n\t\t\t\t\t\tif ( isSmallView ) {\n\n\t\t\t\t\t\t\t// Switch to small view\n\t\t\t\t\t\t\tactiveId = $tablist.find( \".active a\" ).attr( \"href\" ).substring( 1 );\n\t\t\t\t\t\t\tfor ( j = 0; j !== len2; j += 1 ) {\n\t\t\t\t\t\t\t\t$detailsElm = $details.eq( j );\n\t\t\t\t\t\t\t\t$panelElm = $detailsElm.children( \".tgl-panel\" );\n\t\t\t\t\t\t\t\tisActive = $detailsElm.attr( \"id\" ) === activeId;\n\n\t\t\t\t\t\t\t\t$detailsElm\n\t\t\t\t\t\t\t\t\t.removeAttr( \"role aria-expanded aria-hidden\" )\n\t\t\t\t\t\t\t\t\t.removeClass( \"fade out noheight in\" )\n\t\t\t\t\t\t\t\t\t.toggleClass( \"open\", isActive );\n\n\t\t\t\t\t\t\t\t$panelElm\n\t\t\t\t\t\t\t\t\t.attr( \"role\", \"tabpanel\" )\n\t\t\t\t\t\t\t\t\t.removeAttr( \"aria-expanded\" )\n\t\t\t\t\t\t\t\t\t.removeAttr( \"aria-hidden\" );\n\n\t\t\t\t\t\t\t\tif ( isActive ) {\n\t\t\t\t\t\t\t\t\t$detailsElm.attr( \"open\", \"open\" );\n\t\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\t\t$detailsElm.removeAttr( \"open\" );\n\t\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t\tif ( !isInit ) {\n\t\t\t\t\t\t\t\t\t$detailsElm\n\t\t\t\t\t\t\t\t\t\t.children( \"summary\" )\n\t\t\t\t\t\t\t\t\t\t.attr( {\n\t\t\t\t\t\t\t\t\t\t\t\"aria-expanded\": isActive,\n\t\t\t\t\t\t\t\t\t\t\t\"aria-selected\": isActive\n\t\t\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} else if ( oldIsSmallView ) {\n\n\t\t\t\t\t\t\t// Switch to large view\n\t\t\t\t\t\t\t$openDetails = $details.filter( \"[open]\" );\n\t\t\t\t\t\t\topenDetailsId = $openDetails.attr( \"id\" );\n\n\t\t\t\t\t\t\t$openDetails = ( $openDetails.length === 0 ? $details : $openDetails ).eq( 0 );\n\n\t\t\t\t\t\t\t$details\n\t\t\t\t\t\t\t\t.attr( {\n\t\t\t\t\t\t\t\t\trole: \"tabpanel\",\n\t\t\t\t\t\t\t\t\topen: \"open\"\n\t\t\t\t\t\t\t\t} )\n\t\t\t\t\t\t\t\t.not( $openDetails )\n\t\t\t\t\t\t\t\t.addClass( \"fade out noheight wb-inv\" )\n\t\t\t\t\t\t\t\t.attr( {\n\t\t\t\t\t\t\t\t\t\"aria-hidden\": \"true\",\n\t\t\t\t\t\t\t\t\t\"aria-expanded\": \"false\"\n\t\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\t$details.children( \".tgl-panel\" ).removeAttr( \"role\" );\n\n\t\t\t\t\t\t\t$openDetails\n\t\t\t\t\t\t\t\t.addClass( \"fade in\" )\n\t\t\t\t\t\t\t\t.attr( {\n\t\t\t\t\t\t\t\t\t\"aria-hidden\": \"false\",\n\t\t\t\t\t\t\t\t\t\"aria-expanded\": \"true\"\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t$summary.attr( \"aria-hidden\", !isSmallView );\n\t\t\t\t\t\t$tablist.attr( \"aria-hidden\", isSmallView );\n\n\t\t\t\t\t\t$elm.append( $tabPanels );\n\n\t\t\t\t\t\t// Update the tablist role\n\t\t\t\t\t\tif ( isSmallView &amp;amp;&amp;amp; !isInit ) {\n\t\t\t\t\t\t\t$elm.attr( \"role\", \"tablist\" );\n\t\t\t\t\t\t} else if ( oldIsSmallView ) {\n\t\t\t\t\t\t\t$elm\n\t\t\t\t\t\t\t\t.removeAttr( \"role\" )\n\t\t\t\t\t\t\t\t.find( nestedTglPanelSelector ).removeAttr( \"role\" );\n\n\t\t\t\t\t\t\t$elm.find( \"&amp;gt; ul [href$='\" + openDetailsId + \"']\" ).trigger( \"click\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Need timeout to account for Toggle changes\n\t\t\t\tif ( isInit &amp;amp;&amp;amp; !isSmallView &amp;amp;&amp;amp; $elms.hasClass( tabsAccordionClass ) ) {\n\t\t\t\t\tsetTimeout( function() {\n\t\t\t\t\t\t$elms\n\t\t\t\t\t\t\t.removeAttr( \"role\" )\n\t\t\t\t\t\t\t.find( nestedTglPanelSelector ).removeAttr( \"role\" );\n\t\t\t\t\t}, 1 );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\toldIsSmallView = isSmallView;\n\t\t}\n\n\t\tif ( viewChange || isInit ) {\n\n\t\t\t// Remove wb-inv from regular tabs that were used to prevent FOUC (after 300ms delay)\n\t\t\tsetTimeout( function() {\n\t\t\t\t$( selector + \" .tabpanels &amp;gt; details.wb-inv\" ).removeClass( \"wb-inv\" );\n\t\t\t}, 300 );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent + \" \" + shiftEvent + \" \" + selectEvent, selector, function( event ) {\n\tvar eventTarget = event.target,\n\t\teventCurrentTarget = event.currentTarget,\n\t\t$elm;\n\n\t// Filter out any events triggered by descendants\n\tif ( eventCurrentTarget === eventTarget ) {\n\t\tswitch ( event.type ) {\n\t\t\tcase \"timerpoke\":\n\t\t\t\t$elm = $( eventTarget );\n\t\t\t\tif ( !$elm.hasClass( componentName + \"-inited\" ) ) {\n\t\t\t\t\tinit( event );\n\t\t\t\t} else if ( $elm.hasClass( \"playing\" ) ) {\n\t\t\t\t\tonTimerPoke( $elm );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t * Init\n\t\t\t */\n\t\t\tcase \"wb-init\":\n\t\t\t\tinit( event );\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t * Change tab panels by a delta\n\t\t\t */\n\t\t\tcase \"wb-shift\":\n\t\t\t\tonShift( event, $( eventTarget ) );\n\t\t\t\tbreak;\n\n\t\t\t/*\n\t\t\t * Select a specific tab panel\n\t\t\t */\n\t\t\tcase \"wb-select\":\n\t\t\t\tonSelect( event.id );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\t/*\n\t * Since we are working with events we want to ensure that we are being passive about our control,\n\t * so returning true allows for events to always continue\n\t */\n\treturn true;\n} );\n\n/*\n * Tabs, next, previous and play/pause\n */\n$document.on( activateEvent, controls, function( event ) {\n\tvar which = event.which,\n\t\telm = event.currentTarget,\n\t\tclassName = elm.className,\n\t\tspaceText = i18nText.space,\n\t\t$elm, $sldr, sldrId, plypause, buttonText, data, isPlaying, isPlayPause;\n\n\t// No control, alt or meta keys and only left mouse button, enter key,\n\t// space bar, escape key and arrow keys\n\tif ( !( event.ctrlKey || event.altKey || event.metaKey ) &amp;amp;&amp;amp;\n\t\t\t( !which || which === 1 || which === 13 || which === 27 ||\n\t\t\twhich === 32 || ( which &amp;gt; 36 &amp;amp;&amp;amp; which &amp;lt; 41 ) ) ) {\n\n\t\t// Stop propagation of the activate event\n\t\tevent.preventDefault();\n\t\tif ( event.stopPropagation ) {\n\t\t\tevent.stopImmediatePropagation();\n\t\t} else {\n\t\t\tevent.cancelBubble = true;\n\t\t}\n\n\t\t$elm = $( elm );\n\t\t$sldr = $elm.closest( selector );\n\t\tsldrId = $sldr[ 0 ].id;\n\t\tisPlaying = $sldr.hasClass( \"playing\" );\n\t\tisPlayPause = className.indexOf( \"plypause\" ) !== -1;\n\n\t\t// Reset ctime to 0\n\t\tdata = $sldr.data( componentName );\n\t\tdata.ctime = 0;\n\t\t$sldr.data( componentName, data );\n\n\t\t// Stop the slider from playing unless it is already stopped\n\t\t// and the play button is activated\n\t\tif ( ( isPlaying &amp;amp;&amp;amp; which ) || ( isPlayPause &amp;amp;&amp;amp; !( which &amp;gt; 36 &amp;amp;&amp;amp; which &amp;lt; 41 ) ) ) {\n\t\t\tif ( isPlaying ) {\n\t\t\t\twb.remove( \"#\" + sldrId + selector );\n\t\t\t} else {\n\t\t\t\twb.add( \"#\" + sldrId + selector );\n\t\t\t}\n\n\t\t\t$sldr.toggleClass( \"playing\" );\n\t\t\tisPlaying = !isPlaying;\n\t\t\tbuttonText = isPlaying ? i18nText.pause : i18nText.play;\n\n\t\t\tplypause = $sldr.find( \"a.plypause\" )[ 0 ];\n\t\t\tplypause.setAttribute( \"title\", buttonText );\n\t\t\tplypause.innerHTML = \" \" +\n\t\t\t\t\"\" + buttonText + \"\" +\n\t\t\t\tspaceText + i18nText.hyphen + spaceText +\n\t\t\t\t( isPlaying ? i18nText.rotStop : i18nText.rotStart ) + \"\";\n\t\t}\n\n\t\t// Arrow keys\n\t\tif ( which &amp;gt; 36 ) {\n\t\t\tonCycle( $sldr, which &amp;lt; 39 ? -1 : 1 );\n\t\t\t$sldr.find( \"&amp;gt; [role=tablist] .active a\" ).trigger( setFocusEvent );\n\n\t\t// Not the escape key\n\t\t} else if ( which !== 27 ) {\n\n\t\t\t// If the target is a tab\n\t\t\tif ( elm.getAttribute( \"role\" ) === \"tab\" ) {\n\n\t\t\t\t// Only change the tabpanel if the tab is not currently selected\n\t\t\t\tif ( elm.getAttribute( \"aria-selected\" ) !== \"true\" ) {\n\t\t\t\t\tonPick( $sldr, $elm );\n\t\t\t\t}\n\n\t\t\t\t// Put focus on the tab panel if the enter key or space bar are used\n\t\t\t\tif ( which === 13 || which === 32 ) {\n\t\t\t\t\t$sldr.find( elm.getAttribute( \"href\" ) )\n\t\t\t\t\t\t.trigger( setFocusEvent );\n\t\t\t\t}\n\n\t\t\t// If the target is next, previous or tab count\n\t\t\t} else if ( !isPlayPause ) {\n\t\t\t\tonCycle( $sldr, className.indexOf( \"prv\" ) !== -1 ? -1 : 1 );\n\t\t\t}\n\t\t}\n\t}\n\n\t/*\n\t * Since we are working with events we want to ensure that we are being passive about our control,\n\t * so returning true allows for events to always continue\n\t */\n\treturn true;\n} );\n\n$document.on( activateEvent, selector + \" [role=tabpanel]\", function( event ) {\n\tvar currentTarget = event.currentTarget,\n\t\twhich = event.which,\n\t\t$container;\n\n\t// Stop propagation of the click/keydown event\n\tif ( event.stopPropagation ) {\n\t\tevent.stopImmediatePropagation();\n\t} else {\n\t\tevent.cancelBubble = true;\n\t}\n\n\t// Ctrl + Up arrow\n\tif ( event.ctrlKey &amp;amp;&amp;amp; event.which === 38 ) {\n\n\t\t// Move focus to the tab or summary element\n\t\tif ( isSmallView ) {\n\t\t\t$( currentTarget ).prev().trigger( setFocusEvent );\n\t\t} else {\n\t\t\t$( currentTarget )\n\t\t\t\t.closest( selector )\n\t\t\t\t.find( \"[href$='#\" + currentTarget.id + \"']\" )\n\t\t\t\t.trigger( setFocusEvent );\n\t\t}\n\n\t// Left mouse button click or escape key\n\t} else if ( !which || which === 1 || which === 27 ) {\n\t\t$container = $( event.currentTarget ).closest( selector );\n\n\t\t// Stop the carousel\n\t\tif ( $container.hasClass( \"playing\" ) ) {\n\t\t\t$container.find( \".plypause\" ).trigger( \"click\" );\n\t\t}\n\t}\n} );\n\n// Handling for links to tabs from within a panel\n$document.on( \"click\", selector + \" [role=tabpanel] a\", function( event ) {\n\tvar currentTarget = event.currentTarget,\n\t\thref = currentTarget.getAttribute( \"href\" ),\n\t\twhich = event.which,\n\t\t$tabpanels, $panel, $summary;\n\n\t// Ignore middle and right mouse buttons\n\tif ( ( !which || which === 1 ) &amp;amp;&amp;amp; href.charAt( 0 ) === \"#\" ) {\n\t\t$tabpanels = $( currentTarget ).closest( \".tabpanels\" );\n\t\t$panel = $tabpanels.children( \"#\" + wb.jqEscape( href.substring( 1 ) ) );\n\t\tif ( $panel.length !== 0 ) {\n\t\t\tevent.preventDefault();\n\t\t\t$summary = $panel.children( \"summary\" );\n\t\t\tif ( $summary.length !== 0 &amp;amp;&amp;amp; $summary.attr( \"aria-hidden\" ) !== \"true\" ) {\n\t\t\t\t$summary.trigger( \"click\" );\n\t\t\t} else {\n\t\t\t\t$tabpanels.parent().find( href + \"-lnk\" ).trigger( \"click\" );\n\t\t\t}\n\t\t}\n\t}\n} );\n\n// These events only fire at the document level\n$document.on( wb.resizeEvents, onResize );\n\n$document.on( activateEvent, selector + \" &amp;gt; .tabpanels &amp;gt; details &amp;gt; summary\", function( event ) {\n\tvar which = event.which,\n\t\tdetails = event.currentTarget.parentNode,\n\t\t$details, $container, tabSettings;\n\n\tif ( !( event.ctrlKey || event.altKey || event.metaKey ) &amp;amp;&amp;amp;\n\t\t( !which || which === 1 || which === 13 || which === 32 ) ) {\n\n\t\t$container = $( details.parentNode.parentNode );\n\t\t$details = $( details );\n\t\ttabSettings = $container.data( componentName ).settings;\n\n\t\t// Update sessionStorage with the current active panel\n\t\tif ( !tabSettings.ignoreSession ) {\n\t\t\ttry {\n\t\t\t\tsessionStorage.setItem(\n\t\t\t\t\tpagePath + $container.attr( \"id\" ) + activePanel,\n\t\t\t\t\tdetails.id\n\t\t\t\t);\n\t\t\t} catch ( error ) {\n\n\t\t\t\t/* swallow error */\n\t\t\t}\n\t\t}\n\n\t\t// Update the URL hash if needed\n\t\tif ( tabSettings.updateHash ) {\n\t\t\tupdateHash( details );\n\t\t}\n\n\t\t// Identify that the tabbed interface accordion was updated\n\t\t// if the panel was not already open\n\t\tif ( !$details.attr( \"open\" ) ) {\n\t\t\t$container.trigger( updatedEvent, [ $details ] );\n\t\t}\n\t}\n} );\n\n// Change the panel based upon an external link click\n$document.on( \"click\", \".wb-tabs-ext\", function( event ) {\n\tvar which = event.which;\n\n\t// Ignore middle and right mouse buttons\n\tif ( !which || which === 1 ) {\n\t\tevent.preventDefault();\n\t\tonSelect( event.currentTarget.getAttribute( \"href\" ).substring( 1 ) );\n\t}\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Tag filter\n * @overview Filter based content tagging\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @duboisp\n */\n( function( $, window, document, wb ) {\n\"use strict\";\n\nlet wait, i18n;\n\nconst componentName = \"wb-tagfilter\",\n\tselector = \".\" + componentName,\n\tselectorCtrl = \".\" + componentName + \"-ctrl\",\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\ttgFilterOutClass = \"wb-tgfltr-out\",\n\titemsWrapperClass = componentName + \"-items\",\n\tnoResultWrapperClass =  componentName + \"-noresult\",\n\tstatusWrapperClass = componentName + \"-status\",\n\n\tinit = function( event ) {\n\t\tconst elm = wb.init( event, componentName, selector );\n\n\t\tif ( elm ) {\n\t\t\tconst filterControls = elm.querySelectorAll( selectorCtrl ),\n\t\t\t\ttaggedItems = elm.querySelectorAll( \"[data-wb-tags]\" ),\n\t\t\t\ttaggedItemsWrapper = elm.querySelector( \".\" + itemsWrapperClass ),\n\t\t\t\tnoResultWrapper = elm.querySelector( \".\" + noResultWrapperClass );\n\n\t\t\telm.items = [];\n\t\t\telm.filters = {};\n\t\t\telm.activeFilters = [];\n\n\t\t\tif ( taggedItemsWrapper ) {\n\t\t\t\ttaggedItemsWrapper.id = taggedItemsWrapper.id || wb.getId(); // Ensure the element has an ID\n\t\t\t}\n\n\t\t\t// Initialize i18n\n\t\t\ti18n = wb.i18n;\n\n\t\t\t// Handle filters\n\t\t\tif ( filterControls.length ) {\n\t\t\t\telm.filters = buildFiltersObj( filterControls );\n\n\t\t\t\tfilterControls.forEach( function( item ) {\n\t\t\t\t\titem.setAttribute( \"aria-controls\", taggedItemsWrapper.id );\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// Handle tagged items\n\t\t\tif ( taggedItems.length ) {\n\t\t\t\telm.items = buildTaggedItemsArr( taggedItems );\n\t\t\t}\n\n\t\t\t// Build a status element if there's not already one (this element will be used to announce the number of items found)\n\t\t\tif ( !elm.querySelector( \".wb-fltr-info\" ) &amp;amp;&amp;amp; !elm.querySelector( \".\" + statusWrapperClass ) ) {\n\n\t\t\t\t// Build the wrapper for the status message\n\t\t\t\tconst statusWrapper = document.createElement( \"div\" );\n\t\t\t\tstatusWrapper.classList.add( statusWrapperClass, \"wb-inv\" );\n\t\t\t\tstatusWrapper.setAttribute( \"role\", \"status\" );\n\n\t\t\t\t// Build the status message element\n\t\t\t\tconst statusMessage = document.createElement( \"p\" );\n\t\t\t\tstatusWrapper.appendChild( statusMessage );\n\n\t\t\t\t// Append status element after the no result wrapper if it exists, otherwise after the tagged items wrapper\n\t\t\t\t( noResultWrapper || taggedItemsWrapper ).after( statusWrapper );\n\t\t\t}\n\n\t\t\t// Update list of visible items (in case of predefined filters)\n\t\t\tupdate( elm );\n\n\t\t\twb.ready( $( elm ), componentName );\n\t\t}\n\t},\n\n\t// Add every tagged item to an array of objects with their DOM ID, list of associated tags, and default isMatched attribute\n\tbuildTaggedItemsArr = function( taggedItems ) {\n\t\tlet taggedItemsArr = [];\n\n\t\ttaggedItems.forEach( function( taggedItem ) {\n\t\t\tlet tagsList = taggedItem.dataset.wbTags.split( \" \" ),\n\t\t\t\ttimeElm = taggedItem.querySelector( \"time\" ),\n\t\t\t\tdateStr = timeElm ? timeElm.getAttribute( \"datetime\" ) : null;\n\n\t\t\tif ( !taggedItem.id ) {\n\t\t\t\ttaggedItem.setAttribute( \"id\", wb.getId() );\n\t\t\t}\n\n\t\t\ttaggedItemsArr.push( {\n\t\t\t\tid: taggedItem.id,\n\t\t\t\ttags: tagsList,\n\t\t\t\tisMatched: true,\n\t\t\t\titemText: taggedItem.innerText.toLowerCase(),\n\t\t\t\tdate: dateStr\n\t\t\t} );\n\t\t} );\n\t\treturn taggedItemsArr;\n\t},\n\n\t// Build list of available filters using all filters grouped by filter name\n\tbuildFiltersObj = function( filterControls ) {\n\t\tlet filtersObj = {};\n\n\t\tfilterControls.forEach( function( control ) {\n\t\t\tif ( !control.name ) {\n\t\t\t\tconsole.error( componentName + \": Filter controls require an attribute 'name'.\" );\n\t\t\t}\n\n\t\t\tswitch ( control.type ) {\n\t\t\t\tcase \"checkbox\":\n\t\t\t\tcase \"radio\":\n\t\t\t\t\tif ( !( control.name in filtersObj ) ) {\n\t\t\t\t\t\tfiltersObj[ control.name ] = [ ];\n\t\t\t\t\t}\n\n\t\t\t\t\tfiltersObj[ control.name ].push( {\n\t\t\t\t\t\tisChecked: control.checked,\n\t\t\t\t\t\ttype: control.type,\n\t\t\t\t\t\tvalue: control.value\n\t\t\t\t\t} );\n\n\t\t\t\t\tbreak;\n\t\t\t\tcase \"select-one\":\n\t\t\t\tcase \"date\":\n\t\t\t\t\tfiltersObj[ control.name ] = [ {\n\t\t\t\t\t\ttype: control.type,\n\t\t\t\t\t\tvalue: control.value\n\t\t\t\t\t} ];\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t} );\n\n\t\treturn filtersObj;\n\t},\n\n\t// Update array of active filters according to UI selected controls\n\trefineFilters = function( instance ) {\n\t\tinstance.activeFilters = [ ]; // Clear active filters\n\n\t\tfor ( let filterGroupName in instance.filters ) {\n\n\t\t\t// Skip date filters here\n\t\t\tif ( filterGroupName === \"startDate\" || filterGroupName === \"endDate\" ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tlet filterGroup = instance.filters[ filterGroupName ],\n\t\t\t\ttype = filterGroup[ 0 ].type, // All types in a group should be the same, so we can just check the first one\n\t\t\t\tselectedFilters = [ ];\n\n\n\t\t\tswitch ( type ) {\n\t\t\t\tcase \"checkbox\":\n\t\t\t\t\tselectedFilters = filterGroup\n\t\t\t\t\t\t.filter( item =&amp;gt; item.isChecked )\n\t\t\t\t\t\t.map( item =&amp;gt; item.value );\n\t\t\t\t\tbreak;\n\n\t\t\t\tcase \"radio\":\n\t\t\t\t{\n\t\t\t\t\tlet selectedItem = filterGroup.find( item =&amp;gt; item.isChecked );\n\n\t\t\t\t\tif ( !selectedItem ) {\n\t\t\t\t\t\tconsole.warn( componentName + \": Radio button groups must have a default selected value. If you want to display all items, add an option called \\\"All\\\" with an empty value.\" );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else if ( selectedItem.value === \"\" ) { // If the \"All\" option is selected\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t} else {\n\t\t\t\t\t\tselectedFilters.push( selectedItem.value );\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\tcase \"select-one\":\n\t\t\t\t\tif ( filterGroup[ 0 ].value !== \"\" ) {\n\t\t\t\t\t\tselectedFilters.push( filterGroup[ 0 ].value );\n\t\t\t\t\t}\n\t\t\t\t\tbreak;\n\t\t\t}\n\t\t\tinstance.activeFilters.push( selectedFilters );\n\t\t}\n\t},\n\n\t// Match tagged items to active filters and only return items that have an active filter in every filter group\n\tmatchItemsToFilters = function( instance ) {\n\n\t\t// Count tag filter groups only (ignore dates here)\n\t\tlet filtersGroups = instance.activeFilters.length,\n\t\t\tstartDate = ( instance.filters.startDate &amp;amp;&amp;amp; instance.filters.startDate[ 0 ] &amp;amp;&amp;amp; instance.filters.startDate[ 0 ].value ) || \"\",\n\t\t\tendDate   = ( instance.filters.endDate &amp;amp;&amp;amp; instance.filters.endDate[ 0 ] &amp;amp;&amp;amp; instance.filters.endDate[ 0 ].value ) || \"\";\n\n\t\tinstance.items.forEach( item =&amp;gt; {\n\t\t\tlet matchCount = 0,\n\t\t\t\tdateMatch = true; // Default is true unless proven otherwise\n\n\t\t\t// --- DATE FILTERING ---\n\t\t\tif ( item.date ) {\n\n\t\t\t\t// If only startDate is set, item must be after or on the startDate\n\t\t\t\tif ( startDate !== \"\" &amp;amp;&amp;amp; endDate === \"\" ) {\n\t\t\t\t\tdateMatch = wb.date.compare( item.date, startDate ) &amp;gt;= 0;\n\t\t\t\t}\n\n\t\t\t\t// If only endDate is set, item must be before or on the endDate\n\t\t\t\tif ( endDate !== \"\" &amp;amp;&amp;amp; startDate === \"\" ) {\n\t\t\t\t\tdateMatch = wb.date.compare( item.date, endDate ) &amp;lt;= 0;\n\t\t\t\t}\n\n\t\t\t\t// If both startDate and endDate are set, item must be between startDate and endDate (inclusive)\n\t\t\t\tif ( startDate !== \"\" &amp;amp;&amp;amp; endDate !== \"\" ) {\n\t\t\t\t\tdateMatch = (\n\t\t\t\t\t\twb.date.compare( item.date, startDate ) &amp;gt;= 0 &amp;amp;&amp;amp;\n\t\t\t\t\t\twb.date.compare( item.date, endDate ) &amp;lt;= 0\n\t\t\t\t\t);\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// --- TAG FILTERING ---\n\t\t\tif ( dateMatch ) {\n\t\t\t\tinstance.activeFilters.forEach( ( filterGroup ) =&amp;gt; {\n\t\t\t\t\tif ( filterGroup.length === 0 || filterGroup.some( filter =&amp;gt; {\n\t\t\t\t\t\treturn item.tags.includes( filter );\n\t\t\t\t\t} ) ) {\n\t\t\t\t\t\tmatchCount++;\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\n\t\t\t// Show item if it matches any filter and is within date range\n\t\t\titem.isMatched = ( matchCount === filtersGroups &amp;amp;&amp;amp; dateMatch );\n\t\t} );\n\t},\n\n\t// Update list of visible items according to their \"isMatched\" property\n\tupdateDOMItems = function( instance ) {\n\t\tconst updatedItemsList = instance.items.forEach( function( item ) {\n\t\t\tlet domItem = instance.querySelector( \"#\" + item.id );\n\n\t\t\tif ( item.isMatched ) {\n\t\t\t\tdomItem.classList.remove( tgFilterOutClass );\n\t\t\t} else {\n\t\t\t\tdomItem.classList.add( tgFilterOutClass );\n\t\t\t}\n\t\t} );\n\t\treturn updatedItemsList;\n\t},\n\n\t// Update the status message element with the number of items found or no items found\n\tupdateStatusMessage = function( instance ) {\n\t\tconst statusWrapper = instance.querySelector( \".\" + statusWrapperClass ),\n\t\t\tnoResultWrapper = instance.querySelector( \".\" + noResultWrapperClass ),\n\t\t\tstatusMessageElm = statusWrapper ? statusWrapper.querySelector( \"p\" ) : null,\n\t\t\titemsFoundText = i18n ? i18n( \"items-found\" ) : \"items found out of / \u00e9l\u00e9ments trouv\u00e9s sur\";\n\n\t\tif ( statusWrapper &amp;amp;&amp;amp; statusMessageElm ) {\n\t\t\tconst matchedCount = instance.items.filter( item =&amp;gt; item.isMatched ).length,\n\t\t\t\ttotalCount = instance.items.length;\n\n\t\t\tlet statusMessageText;\n\n\t\t\t//  If there are no items and the no result wrapper exists, copy its message to the screen reader status message, otherwise build a new message\n\t\t\t//  Note: Since the no result wrapper text is not dynamic, it wouldn't get announced by screen readers when the filter changes.\n\t\t\t//  This is why we copy it to the status message element.\n\t\t\tif ( matchedCount === 0 ) {\n\t\t\t\tstatusMessageText = noResultWrapper ? noResultWrapper.textContent : i18n ? i18n( \"no-items-found\" ) : \"No items found / Aucun \u00e9l\u00e9ment trouv\u00e9\";\n\t\t\t} else {\n\t\t\t\tstatusMessageText = `${ matchedCount } ${ itemsFoundText } ${ totalCount }`;\n\t\t\t}\n\t\t\tstatusMessageElm.textContent = statusMessageText;\n\t\t}\n\t},\n\n\t// Utility method to update stored active filters, update stored items, update visibility of tagged items and update status message\n\tupdate = function( instance ) {\n\t\trefineFilters( instance );\n\t\tmatchItemsToFilters( instance );\n\t\tupdateDOMItems( instance );\n\t\tupdateStatusMessage( instance );\n\n\t\t$( instance ).trigger( \"wb-filtered\", [ { source: componentName } ] );\n\t};\n\n// When a filter is updated\n$document.on( \"change\", selectorCtrl, function( event )  {\n\tlet control = event.currentTarget,\n\t\tfilterType = control.type,\n\t\tfilterName = control.name,\n\t\tfilterValue = control.value,\n\t\telm = control.closest( selector ),\n\t\tfilterGroup = elm.filters[ filterName ];\n\n\tswitch ( filterType ) {\n\t\tcase \"checkbox\":\n\n\t\t\t// Update virtual filter to the new state\n\t\t\tfilterGroup.find( function( filter ) {\n\t\t\t\treturn filter.value === filterValue;\n\t\t\t} ).isChecked = !!control.checked;\n\t\t\tbreak;\n\n\t\tcase \"radio\":\n\n\t\t\t// Set all virtual radio items to unchecked\n\t\t\tfilterGroup.forEach( function( filterItem ) {\n\t\t\t\tfilterItem.isChecked = false;\n\t\t\t} );\n\n\t\t\t// Set selected radio button's associated virtual filter to checked\n\t\t\tfilterGroup.find( function( filter ) {\n\t\t\t\treturn filter.value === filterValue;\n\t\t\t} ).isChecked = true;\n\t\t\tbreak;\n\n\t\tcase \"select-one\":\n\t\tcase \"date\":\n\n\t\t\t// Update virtual filter to the new value\n\t\t\tfilterGroup[ 0 ].value = filterValue;\n\t\t\tbreak;\n\t}\n\n\t// Update list of visible items\n\tupdate( elm );\n} );\n\n// Reinitialize tagfilter if content on the page has been updated by another plugin\n$document.on( \"wb-contentupdated\", selector + \", \" + selector + \" *\", function()  {\n\tlet that = this;\n\n\tif ( wait ) {\n\t\tclearTimeout( wait );\n\t}\n\n\twait = setTimeout( function() {\n\t\tthat.classList.remove( \"wb-init\", componentName + \"-inited\" );\n\t\t$( that ).trigger( \"wb-init.\" + componentName );\n\t}, 100 );\n} );\n\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\nwb.add( selector );\n\n} )( jQuery, window, document, wb );\n\n/**\n * @title WET-BOEW Text highlighting\n * @overview Automatically highlights certain words on a Web page. The highlighted words can be selected via the query string.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @pjackson28\n */\n( function( $, window, document, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-txthl\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\tparams = wb.pageUrlParts.params,\n\t\t\tsearchCriteria, newText;\n\n\t\tif ( elm ) {\n\t\t\tif ( event.txthl ) {\n\t\t\t\tsearchCriteria = Array.isArray( event.txthl ) ? event.txthl.join( \"|\" ) : event.txthl;\n\t\t\t} else if ( params &amp;amp;&amp;amp; params.txthl ) {\n\t\t\t\tsearchCriteria = decodeURIComponent(\n\t\t\t\t\twb.pageUrlParts.params.txthl\n\t\t\t\t\t\t.replace( /^\\s+|\\s+$|\\|+|\"|\\(|\\)/g, \"\" ).replace( /\\++/g, \"|\" )\n\t\t\t\t);\n\t\t\t}\n\n\t\t\tif ( searchCriteria ) {\n\n\t\t\t\t// Strip html\n\t\t\t\tvar map = { \"&amp;amp;\": \"&amp;amp;\", \"&amp;lt;\": \"&amp;lt;\", \"&amp;gt;\": \"&amp;gt;\", \"\\\"\": \"&amp;quot;\", \"'\": \"&amp;#039;\" };\n\t\t\t\tsearchCriteria = searchCriteria.replace( /[&amp;amp;&amp;lt;&amp;gt;\"']/g, function( m ) {\n\t\t\t\t\treturn map[ m ];\n\t\t\t\t} );\n\n\t\t\t\t// Make sure that we're not checking for text within a tag; only the text outside of tags.\n\t\t\t\tsearchCriteria = \"(?=([^&amp;gt;]*&amp;lt;))([\\\\s'])?(\" + searchCriteria + \")(?!&amp;gt;)\";\n\n\t\t\t\tnewText = elm.innerHTML.replace( new RegExp( searchCriteria, \"gi\" ), function( match, group1, group2, group3 ) {\n\t\t\t\t\treturn ( !group2 ? \"\" : group2 ) + \"\" + group3 + \"\";\n\t\t\t\t} );\n\t\t\t\telm.innerHTML = newText;\n\t\t\t}\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $( elm ), componentName );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, document, wb );\n\n/**\n * @title WET-BOEW Toggle\n * @overview Plugin that allows a link to toggle elements between on and off states.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @patheard\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-toggle\",\n\tselector = \".\" + componentName,\n\tselectorPanel = \".tgl-panel\",\n\tselectorTab = \".tgl-tab\",\n\tinitEvent = \"wb-init\" + selector,\n\ttoggleEvent = \"toggle\" + selector,\n\ttoggledEvent = \"toggled\" + selector,\n\tsetFocusEvent = \"setfocus.wb\",\n\tstates = {},\n\t$document = wb.doc,\n\t$window = wb.win,\n\n\tdefaults = {\n\t\tstateOn: \"on\",\n\t\tstateOff: \"off\"\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar link = wb.init( event, componentName, selector, true ),\n\t\t\t$link, data, persistState;\n\n\t\tif ( link ) {\n\n\t\t\t// Merge the elements settings with the defaults\n\t\t\t$link = $( link );\n\t\t\tdata = $.extend( {}, defaults, $link.data( \"toggle\" ) );\n\t\t\t$link.data( \"toggle\", data );\n\n\t\t\t// Add aria attributes of the toggle element\n\t\t\tinitAria( link, data );\n\n\t\t\t// Persist toggle state across page loads\n\t\t\tif ( data.persist ) {\n\t\t\t\tpersistState = initPersist( $link, data );\n\t\t\t}\n\n\t\t\t// Toggle behaviour when the page is printed\n\t\t\tif ( data.print ) {\n\t\t\t\tinitPrint( $link, data );\n\t\t\t}\n\n\t\t\t// Set the initial state if the state has been specified and\n\t\t\t// the persistent state has not been set\n\t\t\tif ( !persistState &amp;amp;&amp;amp; data.state ) {\n\t\t\t\tsetState( $link, data, data.state );\n\t\t\t}\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $link, componentName );\n\t\t}\n\t},\n\n\t/**\n\t * Initialize the aria attributes for a given toggle element\n\t * @param {DOM element} link The toggle element to initialize\n\t * @param {Object} data Simple key/value data object passed when the event was triggered\n\t */\n\tinitAria = function( link, data ) {\n\t\tvar i, len, elm, elms, parent, tabs, tab, panel, isOpen, wrapper,\n\t\t\tariaControls = \"\",\n\t\t\thasOpen = false;\n\n\t\t// Group toggle elements with a parent are assumed to be a tablist\n\t\tif ( data.group != null &amp;amp;&amp;amp; data.parent != null ) { //eslint-disable-line no-eq-null\n\t\t\tparent = document.querySelector( data.parent );\n\n\t\t\t// Check that the tablist widget hasn't already been initialized\n\t\t\tif ( parent.getAttribute( \"role\" ) !== \"tablist\" ) {\n\n\t\t\t\t// Only apply the tablist role if the parent is not the tabbed interface container\n\t\t\t\t// or the page is currently in \"smallview\", \"xsmallview\" or \"xxsmallview\"\n\t\t\t\tif ( parent.className.indexOf( \"wb-tabs\" ) === -1 ||\n\t\t\t\t\tdocument.documentElement.className.indexOf( \"smallview\" ) !== -1 ) {\n\t\t\t\t\tparent.setAttribute( \"role\", \"tablist\" );\n\t\t\t\t}\n\n\t\t\t\telms = parent.querySelectorAll( data.group );\n\t\t\t\ttabs = parent.querySelectorAll( data.group + \" \" + selectorTab );\n\n\t\t\t\t// Set the tab and panel aria attributes\n\t\t\t\tfor ( i = 0, len = elms.length; i !== len; i += 1 ) {\n\t\t\t\t\telm = elms[ i ];\n\t\t\t\t\ttab = tabs[ i ];\n\t\t\t\t\tpanel = elm.querySelector( selectorPanel );\n\n\t\t\t\t\t// Check if the element is toggled on based on the\n\t\t\t\t\t// open attribute or \"on\" CSS class\n\t\t\t\t\tisOpen = elm.nodeName.toLowerCase() === \"details\" ?\n\t\t\t\t\t\t!!elm.hasAttribute( \"open\" ) :\n\t\t\t\t\t\t( \" \" + tab.className + \" \" ).indexOf( \" \" + data.stateOn + \" \" );\n\t\t\t\t\tif ( isOpen ) {\n\t\t\t\t\t\thasOpen = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( !tab.getAttribute( \"id\" ) ) {\n\t\t\t\t\t\ttab.setAttribute( \"id\", wb.getId() );\n\t\t\t\t\t}\n\n\t\t\t\t\t//Details and summary don't support aria roles and some aria attribute that is why they are wrapped in a div\n\t\t\t\t\tif ( elm.nodeName.toLowerCase() === \"details\" &amp;amp;&amp;amp; elm.parentNode.className.toLowerCase().indexOf( \"accordion\" ) &amp;gt; -1 ) {\n\t\t\t\t\t\twrapper = document.createElement( \"div\" );\n\t\t\t\t\t\twrapper.classList.add( \"tgl-tab\" );\n\t\t\t\t\t\twrapper.setAttribute( \"role\", \"tab\" );\n\t\t\t\t\t\twrapper.setAttribute( \"aria-selected\", isOpen );\n\t\t\t\t\t\twrapper.setAttribute( \"tabindex\", isOpen ? \"0\" : \"-1\" );\n\t\t\t\t\t\twrapper.setAttribute( \"aria-posinset\", i + 1 );\n\t\t\t\t\t\twrapper.setAttribute( \"aria-setsize\", len );\n\t\t\t\t\t\tparent.replaceChild( wrapper, elm );\n\t\t\t\t\t\twrapper.appendChild( elm );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttab.setAttribute( \"role\", \"tab\" );\n\t\t\t\t\t\ttab.setAttribute( \"aria-selected\", isOpen );\n\t\t\t\t\t\ttab.setAttribute( \"tabindex\", isOpen ? \"0\" : \"-1\" );\n\t\t\t\t\t\ttab.setAttribute( \"aria-posinset\", i + 1 );\n\t\t\t\t\t\ttab.setAttribute( \"aria-setsize\", len );\n\t\t\t\t\t}\n\t\t\t\t\tpanel.setAttribute( \"role\", \"tabpanel\" );\n\t\t\t\t\tpanel.setAttribute( \"aria-labelledby\", tab.getAttribute( \"id\" ) );\n\t\t\t\t\tpanel.setAttribute( \"aria-expanded\", isOpen );\n\t\t\t\t\tpanel.setAttribute( \"aria-hidden\", !isOpen );\n\t\t\t\t}\n\n\t\t\t\t// No open panels so put the first summary in the tab order\n\t\t\t\tif ( !hasOpen ) {\n\t\t\t\t\ttabs[ 0 ].setAttribute( \"tabindex\", \"0\" );\n\t\t\t\t}\n\t\t\t}\n\n\t\t// Set the elements this link controls\n\t\t} else {\n\t\t\telms = getElements( link, data );\n\t\t\tfor ( i = 0, len = elms.length; i !== len; i += 1 ) {\n\t\t\t\telm = elms[ i ];\n\t\t\t\tif ( !elm.id ) {\n\t\t\t\t\telm.id = wb.getId();\n\t\t\t\t}\n\t\t\t\tariaControls += elm.id + \" \";\n\t\t\t}\n\t\t\tlink.setAttribute( \"aria-controls\", ariaControls.slice( 0, -1 ) );\n\t\t}\n\t},\n\n\t/**\n\t * Initializes persistent behaviour of the toggle element\n\t * @param {jQuery Object} $link The toggle element to initialize\n\t * @param {Object} data Simple key/value data object passed when the event was triggered\n\t * @returns {string} Persistent state\n\t */\n\tinitPersist = function( $link, data ) {\n\t\tvar state,\n\t\t\tlink = $link[ 0 ];\n\n\t\t// Store the persistence type and key for later use\n\t\tdata.persist = data.persist === \"session\" ? sessionStorage : localStorage;\n\t\tdata.persistKey = componentName + ( data.group ? data.group : \"\" ) + link.id;\n\n\t\t// If there's a saved toggle state, trigger the change to that state\n\t\tstate = data.persist.getItem( data.persistKey );\n\t\tif ( state ) {\n\t\t\t$link.trigger( toggleEvent, $.extend( {}, data, { type: state } ) );\n\t\t}\n\n\t\treturn state;\n\t},\n\n\t/**\n\t * Initialize open on print behaviour of the toggle element\n\t * @param {jQuery Object} $link The toggle element to initialize\n\t * @param {Object} data Simple key/value data object passed when the event was triggered\n\t */\n\tinitPrint = function( $link, data ) {\n\t\tvar mediaQuery,\n\t\t\tprintEvent = \"beforeprint\";\n\n\t\t$window.on( printEvent, function() {\n\t\t\t$link.trigger( toggleEvent, $.extend( {}, data, { type: data.print } ) );\n\t\t} );\n\n\t\t// Fallback for browsers that don't support print events\n\t\tif ( window.matchMedia ) {\n\t\t\tmediaQuery = window.matchMedia( \"print\" );\n\t\t\tif ( mediaQuery.addListener ) {\n\t\t\t\tmediaQuery.addListener( function( query ) {\n\t\t\t\t\tif ( query.matches ) {\n\t\t\t\t\t\t$window.trigger( printEvent );\n\t\t\t\t\t}\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Click handler for the toggle links\n\t * @param {jQuery Event} event The event that triggered this invocation\n\t */\n\tclick = function( event ) {\n\t\tvar $link = $( event.currentTarget );\n\n\t\t$link.trigger( toggleEvent, $link.data( \"toggle\" ) );\n\t\tevent.preventDefault();\n\n\t\t// Assign focus to eventTarget\n\t\t$link.trigger( setFocusEvent );\n\t},\n\n\t/**\n\t * Toggles the elements a link controls between the on and off states.\n\t * @param {jQuery Event} event The event that triggered this invocation\n\t * @param {Object} data Simple key/value data object passed when the event was triggered\n\t */\n\ttoggle = function( event, data ) {\n\t\tif ( event.namespace === componentName ) {\n\t\t\tvar dataGroup, key, $elmsGroup,\n\t\t\t\tisGroup = !!data.group,\n\t\t\t\tisPersist = !!data.persist,\n\t\t\t\tisTablist = isGroup &amp;amp;&amp;amp; !!data.parent,\n\t\t\t\tlink = event.currentTarget,\n\t\t\t\t$link = $( link ),\n\t\t\t\tstateFrom = getState( $link, data ),\n\t\t\t\tisToggleOn = stateFrom === data.stateOff,\n\t\t\t\tstateTo = isToggleOn ? data.stateOn : data.stateOff,\n\t\t\t\t$elms = isTablist ?\t$link.parent( data.group ) : getElements( link, data );\n\n\t\t\t// Group toggle behaviour: only one element in the group open at a time.\n\t\t\tif ( isGroup ) {\n\n\t\t\t\t// Get the grouped elements using data.group as the CSS selector\n\t\t\t\tdataGroup = $.extend( {}, data, { selector: data.group } );\n\t\t\t\t$elmsGroup = getElements( link, dataGroup );\n\n\t\t\t\t// Set the toggle state to \"off\".  For tab lists, this is stored on the tab element\n\t\t\t\tsetState( isTablist ? $( data.parent ).find( selectorTab ) : $elmsGroup,\n\t\t\t\t\tdataGroup, data.stateOff );\n\n\t\t\t\t// Toggle all grouped elements to \"off\"\n\t\t\t\t$elmsGroup.wb( \"toggle\", data.stateOff, data.stateOn );\n\t\t\t\t$elmsGroup.trigger( toggledEvent, {\n\t\t\t\t\tisOn: false,\n\t\t\t\t\tisTablist: isTablist,\n\t\t\t\t\telms: $elmsGroup\n\t\t\t\t} );\n\n\t\t\t\t// Remove all grouped persistence keys\n\t\t\t\tif ( isPersist ) {\n\t\t\t\t\tfor ( key in data.persist ) {\n\t\t\t\t\t\tif ( key.indexOf( componentName + data.group ) === 0 ) {\n\t\t\t\t\t\t\tdata.persist.removeItem( key );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Set the toggle state. For tab lists, this is set on the tab element\n\t\t\tsetState( isTablist ? $link : $elms, data, stateTo );\n\n\t\t\t// Toggle all elements to the requested state\n\t\t\t$elms.wb( \"toggle\", stateTo, stateFrom );\n\t\t\t$elms.trigger( toggledEvent, {\n\t\t\t\tisOn: isToggleOn,\n\t\t\t\tisTablist: isTablist,\n\t\t\t\telms: $elms\n\t\t\t} );\n\n\t\t\t// Ensure that last focused element in the accordion remains keyboard focusable\n\t\t\t// whether it is collapsed or not\n\t\t\tif ( isGroup ) {\n\t\t\t\t$elms.find( \"summary\" ).attr( { \"tabindex\": \"0\" } );\n\t\t\t}\n\n\t\t\t// Store the toggle link's current state if persistence is turned on.\n\t\t\t// Try/catch is required to address exceptions thrown when using BB10 or\n\t\t\t// private browsing in iOS.\n\t\t\tif ( isPersist ) {\n\t\t\t\ttry {\n\t\t\t\t\tdata.persist.setItem( data.persistKey, stateTo );\n\t\t\t\t} catch ( error ) {\n\n\t\t\t\t\t/* swallow error */\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Sets the required property and attribute for toggling open/closed a details element\n\t * @param {jQuery Event} event The event that triggered this invocation\n\t * @param {Object} data Simple key/value data object passed when the event was triggered\n\t */\n\ttoggleDetails = function( event, data ) {\n\t\tif ( event.namespace === componentName &amp;amp;&amp;amp; event.target === event.currentTarget ) {\n\t\t\tvar top,\n\t\t\t\tisOn = data.isOn,\n\t\t\t\t$elms = data.elms,\n\t\t\t\t$this = $( this ),\n\t\t\t\t$detail = $this.is( \"summary\" ) ? $this.parent() : $this;\n\n\t\t\t// Stop propagation of the toggleDetails event\n\t\t\tif ( event.stopPropagation ) {\n\t\t\t\tevent.stopImmediatePropagation();\n\t\t\t} else {\n\t\t\t\tevent.cancelBubble = true;\n\t\t\t}\n\n\t\t\t$detail.prop( \"open\", isOn );\n\n\t\t\tif ( data.isTablist ) {\n\n\t\t\t\t// Set the required aria attributes\n\t\t\t\t$elms.find( selectorTab ).parents( selectorTab ).attr( {\n\t\t\t\t\t\"aria-selected\": isOn,\n\t\t\t\t\ttabindex: isOn ? \"0\" : \"-1\"\n\t\t\t\t} );\n\t\t\t\t$elms.find( selectorPanel ).attr( {\n\t\t\t\t\t\"aria-hidden\": !isOn,\n\t\t\t\t\t\"aria-expanded\": isOn\n\t\t\t\t} );\n\n\t\t\t\t// Check that the top of the open element is in view.\n\t\t\t\tif ( isOn &amp;amp;&amp;amp; $elms.length === 1 ) {\n\t\t\t\t\ttop = $elms.offset().top;\n\t\t\t\t\tif ( top &amp;lt; $window.scrollTop() ) {\n\t\t\t\t\t\t$window.scrollTop( top );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t/**\n\t * Returns the elements a given toggle element controls.\n\t * @param {DOM element} link Toggle element that was clicked\n\t * @param {Object} data Simple key/value data object passed when the event was triggered\n\t * @returns {jQuery Object} DOM elements the toggle link controls\n\t */\n\tgetElements = function( link, data ) {\n\t\tvar selector = data.selector || link,\n\t\t\tparent = data.parent || null;\n\n\t\treturn parent !== null ? $( parent ).find( selector ) : $( selector );\n\t},\n\n\t/**\n\t * Gets the current toggle state of elements controlled by the given link.\n\t * @param {jQuery Object} $link Toggle link that was clicked\n\t * @param {Object} data Simple key/value data object passed when the event was triggered\n\t */\n\tgetState = function( $link, data ) {\n\t\tvar parent = data.parent,\n\t\t\tselector = data.selector,\n\t\t\ttype = data.type;\n\n\t\t// Get opposite state of the type. Toggle reverses this\n\t\t// to the requested state.\n\t\tif ( type ) {\n\t\t\treturn type === \"on\" ? data.stateOff : data.stateOn;\n\n\t\t// \n elements use the open attribute to determine state\n\t\t} else if ( $link[ 0 ].nodeName.toLowerCase() === \"summary\" ) {\n\t\t\treturn $link.parent().attr( \"open\" ) ? data.stateOn : data.stateOff;\n\n\t\t// When no selector, use the data attribute of the link\n\t\t} else if ( !selector ) {\n\t\t\treturn $link.data( componentName + \"-state\" ) || data.stateOff;\n\n\t\t// When toggling multiple \n elements, state is \"off\" if any are collapsed\n\t\t} else if ( selector === \"details\" &amp;amp;&amp;amp; !type ) {\n\t\t\tvar anyCollapsed = false;\n\t\t\tgetElements( $link, data ).each( function() {\n\t\t\t\tif ( !$( this ).attr( \"open\" ) ) {\n\t\t\t\t\tanyCollapsed = true;\n\t\t\t\t}\n\t\t\t} );\n\t\t\treturn anyCollapsed ? data.stateOff : data.stateOn;\n\n\t\t// Get the current on/off state of the elements specified by the selector and parent\n\t\t} else if ( Object.prototype.hasOwnProperty.call( states, selector ) ) {\n\t\t\treturn Object.prototype.hasOwnProperty.call( states[ selector ], parent ) ?\n\t\t\t\tstates[ selector ][ parent ] :\n\t\t\t\tstates[ selector ].all;\n\t\t}\n\t\treturn data.stateOff;\n\t},\n\n\t/*\n\t * Sets the current toggle state of elements controlled by the given link.\n\t * @param {DOM element} link Toggle link that was clicked\n\t * @param {Object} data Simple key/value data object passed when the event was triggered\n\t * @param {String} state The current state of the elements: \"on\" or \"off\"\n\t */\n\tsetState = function( $elms, data, state ) {\n\t\tvar prop,\n\t\t\tparent = data.parent,\n\t\t\tselector = data.selector,\n\t\t\telmsState = states[ selector ];\n\n\t\tif ( selector ) {\n\n\t\t\t// Check the selector object has been created\n\t\t\tif ( !elmsState ) {\n\t\t\t\telmsState = { all: data.stateOff };\n\t\t\t\tstates[ selector ] = elmsState;\n\t\t\t}\n\n\t\t\t// If there's a parent, set its state\n\t\t\tif ( parent ) {\n\t\t\t\telmsState[ parent ] = state;\n\n\t\t\t// No parent means set all states for the given selector. This is\n\t\t\t// because toggle links that apply to the entire DOM also affect\n\t\t\t// links that are restricted by parent.\n\t\t\t} else {\n\t\t\t\tfor ( prop in elmsState ) {\n\t\t\t\t\tif ( Object.prototype.hasOwnProperty.call( elmsState, prop ) ) {\n\t\t\t\t\t\telmsState[ prop ] = state;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Store the state on the elements as well. This allows a link to toggle itself.\n\t\t$elms.data( componentName + \"-state\", state );\n\t};\n\n// Bind the plugin's events\n$document.on( \"timerpoke.wb \" + initEvent + \" \" + toggleEvent +\n\" click\", selector, function( event, data ) {\n\n\tvar eventType = event.type;\n\n\tswitch ( eventType ) {\n\t\tcase \"click\":\n\t\t\tclick( event );\n\t\t\tbreak;\n\n\t\tcase \"toggle\":\n\t\t\ttoggle( event, data );\n\t\t\tbreak;\n\n\t\tcase \"timerpoke\":\n\t\tcase \"wb-init\":\n\t\t\tinit( event );\n\t\t\tbreak;\n\t}\n} );\n\n$document.on( toggledEvent, \"summary, details\", toggleDetails );\n\n// Keyboard handling for the accordion\n$document.on( \"keydown\", selectorTab, function( event ) {\n\tvar which = event.which,\n\t\tdata, $elm, $parent, $group, $newPanel, index;\n\n\tif ( !event.ctrlKey &amp;amp;&amp;amp; which &amp;gt; 34 &amp;amp;&amp;amp; which &amp;lt; 41 ) {\n\t\tevent.preventDefault();\n\t\t$elm = $( event.currentTarget );\n\t\tdata = $elm.data( \"toggle\" );\n\t\t$parent = $document.find( data.parent );\n\t\t$group = $parent.find( data.group );\n\t\tindex = $group.index( $elm.parent() );\n\n\t\tswitch ( which ) {\n\n\t\t\t// End\n\t\t\tcase 35:\n\t\t\t\t$newPanel = $group.last();\n\t\t\t\tbreak;\n\n\t\t\t// Home\n\t\t\tcase 36:\n\t\t\t\t$newPanel = $group.first();\n\t\t\t\tbreak;\n\n\t\t\t// Left / up arrow\n\t\t\tcase 37:\n\t\t\tcase 38:\n\t\t\t\tif ( index === 0 ) {\n\t\t\t\t\t$newPanel = $group.last();\n\t\t\t\t} else {\n\t\t\t\t\t$newPanel = $group.eq( index - 1 );\n\t\t\t\t}\n\t\t\t\tbreak;\n\n\t\t\t// Right / down arrow\n\t\t\tcase 39:\n\t\t\tcase 40:\n\t\t\t\tif ( index === $group.length - 1 ) {\n\t\t\t\t\t$newPanel = $group.first();\n\t\t\t\t} else {\n\t\t\t\t\t$newPanel = $group.eq( index + 1 );\n\t\t\t\t}\n\t\t\t\tbreak;\n\t\t}\n\n\t\t$newPanel\n\t\t\t.children( \"summary\" )\n\t\t\t.trigger( setFocusEvent );\n\t}\n} );\n\n$document.on( \"keydown\", selectorPanel, function( event ) {\n\n\t// Ctrl + Up arrow\n\tif ( event.ctrlKey &amp;amp;&amp;amp; event.which === 38 ) {\n\n\t\t// Move focus to the summary element\n\t\t$( event.currentTarget )\n\t\t\t.prev()\n\t\t\t.trigger( setFocusEvent );\n\t}\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Twitter embedded timeline\n * @overview Helps with implementing Twitter embedded timelines.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @pjackson28\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-twitter\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\t$document = wb.doc,\n\ti18n, i18nText,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar eventTarget = wb.init( event, componentName, selector ),\n\t\t\tprotocol = wb.pageUrlParts.protocol;\n\n\t\tif ( eventTarget ) {\n\t\t\tconst twitterLink = eventTarget.querySelector( \"a.twitter-timeline\" );\n\n\t\t\t// Ignore IE11\n\t\t\t// Note: Twitter's widget no longer supports it...\n\t\t\tif ( wb.ie11 ) {\n\t\t\t\twb.ready( $( eventTarget ), componentName );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Process the Twitter link\n\t\t\tif ( twitterLink ) {\n\t\t\t\tlet observer;\n\n\t\t\t\t// Only initialize the i18nText once\n\t\t\t\tif ( !i18nText ) {\n\t\t\t\t\ti18n = wb.i18n;\n\t\t\t\t\ti18nText = {\n\t\t\t\t\t\tstartNotice: i18n( \"twitter-start-notice\" ),\n\t\t\t\t\t\tendNotice: i18n( \"twitter-end-notice\" ),\n\t\t\t\t\t\tskipEnd: i18n( \"twitter-skip-end\" ),\n\t\t\t\t\t\tskipStart: i18n( \"twitter-skip-start\" ),\n\t\t\t\t\t\ttimelineTitle: i18n( \"twitter-timeline-title\" )\n\t\t\t\t\t};\n\t\t\t\t}\n\n\t\t\t\t// Show a warning if the timelineTitle variable isn't a string\n\t\t\t\tif ( typeof i18nText.startNotice !== \"string\" ) {\n\t\t\t\t\tconsole.warn( componentName + \": i18n text is missing. Iframe title override and skip links will be disabled.\" );\n\t\t\t\t}\n\n\t\t\t\t// Set Chinese (Simplified)'s language code to \"zh-cn\"\n\t\t\t\t// If the link doesn't specify a widget language and its \"in-page\" language code is \"zh-Hans\"...\n\t\t\t\t// Notes:\n\t\t\t\t// -WET uses \"zh-Hans\", Twitter uses \"zh-ch\" and falls back to English if the former is used\n\t\t\t\t// -Language code sourced from https://developer.twitter.com/en/docs/twitter-for-websites/supported-languages\n\t\t\t\tif ( !twitterLink.dataset.lang &amp;amp;&amp;amp; twitterLink.closest( \"[lang='zh-Hans']\" ) ) {\n\t\t\t\t\ttwitterLink.dataset.lang = \"zh-cn\";\n\t\t\t\t}\n\n\t\t\t\t// Match the Facebook page plugin's default height\n\t\t\t\t// If data-height is set to \"fb-page\" OR the widget has a tweet limit and lacks a custom height...\n\t\t\t\t// Notes:\n\t\t\t\t// -Counteracts enormous default widget heights that can reach tens of thousands of pixels without a scrollbar\n\t\t\t\t// -Timeline widgets stopped honouring tweet limits on July 21, 2023 and began showing up to 100 tweets at a time (\"verified\" accounts only)\n\t\t\t\t// -Facebook page plugin's default height is documented in https://developers.facebook.com/docs/plugins/page-plugin#settings\n\t\t\t\tif ( twitterLink.dataset.height === \"fb-page\" || ( twitterLink.dataset.tweetLimit &amp;amp;&amp;amp; !twitterLink.dataset.height ) ) {\n\t\t\t\t\ttwitterLink.dataset.height = \"500\";\n\t\t\t\t}\n\n\t\t\t\t// Add a \"do not track\" parameter (i.e. data-dnt=\"true\" attribute) unless it's already been set\n\t\t\t\t// Note: Covered in https://developer.twitter.com/en/docs/twitter-for-websites/webpage-properties\n\t\t\t\tif ( !twitterLink.dataset.dnt ) {\n\t\t\t\t\ttwitterLink.dataset.dnt = \"true\";\n\t\t\t\t}\n\n\t\t\t\t// Observe DOM mutations\n\t\t\t\tobserver = new MutationObserver( function( mutations ) {\n\t\t\t\t\tmutations.forEach( function( mutation ) {\n\t\t\t\t\t\tswitch ( mutation.type ) {\n\n\t\t\t\t\t\t\t// Check for attribute changes\n\t\t\t\t\t\t\tcase \"attributes\": {\n\t\t\t\t\t\t\t\tconst mutationTarget = mutation.target;\n\n\t\t\t\t\t\t\t\t// Override the timeline iframe's title right after Twitter's widget script adds it\n\t\t\t\t\t\t\t\t// Notes:\n\t\t\t\t\t\t\t\t// -The timeline's iframe title is English-only, uses \"Twitter\" and is written in title case (\"Twitter Timeline\")... This replaces it with an i18n version that uses \"X\" and is written in sentence case.\n\t\t\t\t\t\t\t\t// -Only proceed if the i18n variable is a string... otherwise this'll trigger an infinite loop of attribute mutations\n\t\t\t\t\t\t\t\tif ( mutationTarget.nodeName === \"IFRAME\" &amp;amp;&amp;amp; mutationTarget.title !== i18nText.timelineTitle &amp;amp;&amp;amp; typeof i18nText.timelineTitle === \"string\" ) {\n\t\t\t\t\t\t\t\t\tmutationTarget.title = i18nText.timelineTitle;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Check for node removals\n\t\t\t\t\t\t\tcase \"childList\": {\n\t\t\t\t\t\t\t\tmutation.removedNodes.forEach( function( removedNode ) {\n\n\t\t\t\t\t\t\t\t\t// If the removed node was a Twitter link add skip links and stop observing\n\t\t\t\t\t\t\t\t\t// Note: Twitter's widget script removes \"a.twitter-timeline\" upon displaying the timeline iframe's content\n\t\t\t\t\t\t\t\t\tif ( removedNode === twitterLink ) {\n\t\t\t\t\t\t\t\t\t\tconst iframeContainer = eventTarget.querySelector( \"div.twitter-timeline\" );\n\n\t\t\t\t\t\t\t\t\t\taddSkipLinks( iframeContainer );\n\n\t\t\t\t\t\t\t\t\t\t// The following 2 lines were added as a workaround in Safari where the iFrame is not displayed\n\t\t\t\t\t\t\t\t\t\teventTarget.style.opacity = 1;\n\t\t\t\t\t\t\t\t\t\teventTarget.style.opacity = \"\";\n\n\t\t\t\t\t\t\t\t\t\tobserver.disconnect();\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t} );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} );\n\t\t\t\t} );\n\n\t\t\t\t// Observe changes to the plugin container's child elements and title attributes\n\t\t\t\tobserver.observe( eventTarget, {\n\t\t\t\t\tattributeFilter: [ \"title\" ],\n\t\t\t\t\tchildList: true,\n\t\t\t\t\tsubtree: true\n\t\t\t\t} );\n\n\t\t\t\t// Handle the case where the iframe never loads - wait 5 seconds before displaying a fallback message\n\t\t\t\tsetTimeout( () =&amp;gt; {\n\t\t\t\t\tconst iframe = eventTarget.querySelector( \"iframe.twitter-timeline\" );\n\t\t\t\t\tif ( !iframe ) {\n\t\t\t\t\t\tconst fallbackMessage = \"Twitter timeline is currently unavailable.\";\n\t\t\t\t\t\tconsole.warn( componentName + \": \" + fallbackMessage );\n\t\t\t\t\t\tobserver.disconnect();\n\t\t\t\t\t}\n\t\t\t\t}, 5000 ); // 5 seconds\n\n\t\t\t}\n\n\t\t\t// If the Twitter script has not been loaded yet\n\t\t\tif ( !document.querySelector( \"script[src*='platform.twitter.com/widgets.js']\" ) ) {\n\n\t\t\t\t// Load the Twitter widget script\n\t\t\t\tconst script = document.createElement( \"script\" );\n\t\t\t\tscript.src = ( protocol.indexOf( \"http\" ) === -1 ? \"http:\" : protocol ) + \"//platform.twitter.com/widgets.js\";\n\t\t\t\tscript.onload = function() {\n\t\t\t\t\twb.ready( $( eventTarget ), componentName );\n\t\t\t\t};\n\t\t\t\tdocument.head.appendChild( script );\n\t\t\t}\n\n\t\t}\n\t},\n\n\t// Add skip links immediately before and after the timeline widget\n\t// Note: Verified account timelines may contain several hundred interactive elements... this provides a mechanism to spare keyboard-only users from needing to tab through everything to move past the widget.\n\taddSkipLinks = function( iframeContainer ) {\n\t\tconst timelineIframe = iframeContainer.getElementsByTagName( \"iframe\" )[ 0 ];\n\t\tconst username = getTwitterUsername( timelineIframe.src );\n\t\tconst noticeClass = componentName + \"-\" + \"notice\";\n\t\tconst skipClass = componentName + \"-\" + \"skip\";\n\t\tconst startText = \"start\";\n\t\tconst endText = \"end\";\n\t\tlet startNotice;\n\t\tlet endNotice;\n\t\tlet skipToEndLink;\n\t\tlet skipToStartLink;\n\n\t\t// Abort if Twitter username is falsy or i18n variables aren't strings\n\t\tif ( !username || typeof i18nText.timelineTitle !== \"string\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Add a start of timeline notice\n\t\tstartNotice = createNotice( i18nText.startNotice, username, timelineIframe.id, noticeClass, startText );\n\t\tiframeContainer.before( startNotice );\n\n\t\t// Add an end of timeline notice\n\t\tendNotice = createNotice( i18nText.endNotice, username, timelineIframe.id, noticeClass, endText );\n\t\tiframeContainer.after( endNotice );\n\n\t\t// Add a skip to end link\n\t\tskipToEndLink = createSkipLink( i18nText.skipEnd, username, endNotice.id, skipClass, endText );\n\t\tstartNotice.after( skipToEndLink );\n\n\t\t// Add a skip to start link\n\t\tskipToStartLink = createSkipLink( i18nText.skipStart, username, startNotice.id, skipClass, startText );\n\t\tendNotice.before( skipToStartLink );\n\t},\n\n\t// Extract a Twitter username from the iframe's timeline URL\n\tgetTwitterUsername = function( iframeSrc ) {\n\t\tlet username = iframeSrc.match( /\\/screen-name\\/([^?]+)/ );\n\t\tusername = username ? username[ 1 ] : null;\n\n\t\treturn username;\n\t},\n\n\t// Create a timeline notice\n\tcreateNotice = function( textTemplate, username, iframeId, noticeClass, position ) {\n\t\tconst spanElm = document.createElement( \"span\" );\n\t\tconst pElm = document.createElement( \"p\" );\n\n\t\tspanElm.innerHTML = textTemplate.replace( \"%username%\", username );\n\n\t\tpElm.id = iframeId + \"-\" + position;\n\t\tpElm.className = noticeClass + \"-\" + position;\n\t\tpElm.prepend( spanElm );\n\n\t\t// Hide the notice upon losing focus\n\t\t// Removes its tabindex attribute to make its CSS hide it from screen readers\n\t\tpElm.addEventListener( \"blur\", function( e ) {\n\t\t\te.target.removeAttribute( \"tabindex\" );\n\t\t} );\n\n\t\treturn pElm;\n\t},\n\n\t// Create a skip link\n\tcreateSkipLink = function( textTemplate, username, linkDestId, skipClass, linkDir ) {\n\t\tconst spanElm = document.createElement( \"span\" );\n\t\tconst aElm = document.createElement( \"a\" );\n\t\tconst pElm = document.createElement( \"p\" );\n\n\t\tspanElm.innerHTML = textTemplate.replace( \"%username%\", username );\n\n\t\taElm.href = \"#\" + linkDestId;\n\t\taElm.prepend( spanElm );\n\n\t\t// Focus onto the destination of a clicked link\n\t\t$( aElm ).on( \"click\", function( event ) {\n\t\t\tconst currentTarget = event.currentTarget;\n\t\t\tconst linkDestId = \"#\" + wb.jqEscape( currentTarget.getAttribute( \"href\" ).substring( 1 ) );\n\t\t\tconst $linkDest = $document.find( linkDestId );\n\n\t\t\t// Assign focus to the link's destination\n\t\t\t// Note: The focus event's scrolling behaviour is more graceful than \"jumping\" to an anchor link's destination\n\t\t\t$linkDest.trigger( \"setfocus.wb\" );\n\n\t\t\t// Don't engage normal link navigation behaviour (i.e. \"jumping\" to the link destination, changing address/navigation history)\n\t\t\treturn false;\n\t\t} );\n\n\t\tpElm.className = skipClass + \" \" + skipClass + \"-\" + linkDir;\n\t\tpElm.prepend( aElm );\n\n\t\treturn pElm;\n\t};\n\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Data Json [data-json-after], [data-json-append],\n * [data-json-before], [data-json-prepend], [data-json-replace], [data-json-replacewith] and [data-wb-json]\n * @overview Insert content extracted from JSON file.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @duboisp\n */\n/*global jsonpointer */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-data-json\",\n\tshortName = \"wb-json\",\n\tselectors = [\n\t\t\"[data-json-after]\",\n\t\t\"[data-json-append]\",\n\t\t\"[data-json-before]\",\n\t\t\"[data-json-prepend]\",\n\t\t\"[data-json-replace]\",\n\t\t\"[data-json-replacewith]\",\n\t\t\"[data-\" + shortName + \"]\"\n\t],\n\tallowJsonTypes = [ \"after\", \"append\", \"before\", \"prepend\", \"val\" ],\n\tallowAttrNames = /(href|src|data-*|aria-*|role|pattern|min|max|step|low|high|lang|hreflang|action)/,\n\tallowPropNames = /(checked|selected|disabled|required|readonly|multiple|hidden)/,\n\tselectorsLength = selectors.length,\n\tselector = selectors.join( \",\" ),\n\tinitEvent = \"wb-init.\" + componentName,\n\tupdateEvent = \"wb-update.\" + componentName,\n\tcontentUpdatedEvent = \"wb-contentupdated\",\n\tdataQueue = componentName + \"-queue\",\n\t$document = wb.doc,\n\tisExtensionRegistered,\n\ts,\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered this handler\n\t * @param {string} ajaxType The type of JSON operation, either after, append, before or replace\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\tjsSettings = window[ componentName ] || { },\n\t\t\tprop,\n\t\t\t$elm;\n\n\t\tif ( elm ) {\n\n\t\t\tvar jsonCoreTypes = [\n\t\t\t\t\t\"before\",\n\t\t\t\t\t\"replace\",\n\t\t\t\t\t\"replacewith\",\n\t\t\t\t\t\"after\",\n\t\t\t\t\t\"append\",\n\t\t\t\t\t\"prepend\"\n\t\t\t\t],\n\t\t\t\tjsonType, jsondata,\n\t\t\t\ti, i_len = jsonCoreTypes.length, i_cache,\n\t\t\t\tlstCall = [],\n\t\t\t\turl;\n\n\t\t\t$elm = $( elm );\n\n\t\t\tfor ( i = 0; i !== i_len; i += 1 ) {\n\t\t\t\tjsonType = jsonCoreTypes[ i ];\n\t\t\t\turl = elm.getAttribute( \"data-json-\" + jsonType );\n\t\t\t\tif ( url !== null ) {\n\t\t\t\t\tlstCall.push( {\n\t\t\t\t\t\ttype: jsonType,\n\t\t\t\t\t\turl: url\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Extend but not overwrite the functionTest and the functionForOperand if some was added\n\t\t\tif ( !isExtensionRegistered ) {\n\t\t\t\tif ( jsSettings.functionForTest ) {\n\t\t\t\t\tfor ( prop in jsSettings.functionForTest ) {\n\t\t\t\t\t\tif ( !functionForTest[ prop ] ) {\n\t\t\t\t\t\t\tfunctionForTest[ prop ] = jsSettings.functionForTest[ prop ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tif ( jsSettings.functionForOperand ) {\n\t\t\t\t\tfor ( prop in jsSettings.functionForOperand ) {\n\t\t\t\t\t\tif ( !functionForOperand[ prop ] ) {\n\t\t\t\t\t\t\tfunctionForOperand[ prop ] = jsSettings.functionForOperand[ prop ];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\tisExtensionRegistered = true;\n\t\t\t}\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $elm, componentName );\n\n\t\t\tjsondata = wb.getData( $elm, shortName );\n\n\t\t\tif ( jsondata &amp;amp;&amp;amp; jsondata.url ) {\n\t\t\t\tlstCall.push( jsondata );\n\t\t\t} else if ( jsondata &amp;amp;&amp;amp; Array.isArray( jsondata ) ) {\n\t\t\t\ti_len = jsondata.length;\n\t\t\t\tfor ( i = 0; i !== i_len; i += 1 ) {\n\t\t\t\t\tlstCall.push( jsondata[ i ] );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\t// Save it to the dataJSON object.\n\t\t\t$elm.data( dataQueue, lstCall );\n\n\t\t\ti_len = lstCall.length;\n\t\t\tfor ( i = 0; i !== i_len; i += 1 ) {\n\t\t\t\ti_cache = lstCall[ i ];\n\t\t\t\tloadJSON( elm, i_cache.url, i, i_cache.nocache, i_cache.nocachekey, i_cache.data, i_cache.contenttype, i_cache.method );\n\t\t\t}\n\n\t\t}\n\t},\n\n\tloadJSON = function( elm, url, refId, nocache, nocachekey, data, contentType, method ) {\n\t\tvar $elm = $( elm ),\n\t\t\tfetchObj = {\n\t\t\t\turl: url,\n\t\t\t\trefId: refId,\n\t\t\t\tnocache: nocache,\n\t\t\t\tnocachekey: nocachekey,\n\t\t\t\tdata: data,\n\t\t\t\tcontentType: contentType,\n\t\t\t\tmethod: method\n\t\t\t};\n\n\t\t$elm.trigger( {\n\t\t\ttype: \"json-fetch.wb\",\n\t\t\tfetch: fetchObj\n\t\t} );\n\t},\n\n\n\t// Manage JSON value After the json data has been fetched. This function can deal with array.\n\tjsonFetched = function( event ) {\n\n\t\tvar elm = event.target,\n\t\t\t$elm = $( elm ),\n\t\t\tlstCall = $elm.data( dataQueue ),\n\t\t\tfetchObj = event.fetch,\n\t\t\titmSettings = lstCall[ fetchObj.refId ],\n\t\t\tjsonType = itmSettings.type,\n\t\t\tattrname = itmSettings.prop || itmSettings.attr,\n\t\t\tshowEmpty = itmSettings.showempty,\n\t\t\tcontent = fetchObj.response,\n\t\t\ttypeOfContent = typeof content,\n\t\t\tjQueryCaching;\n\n\t\tif ( showEmpty || typeOfContent !== \"undefined\" ) {\n\n\t\t\tif ( showEmpty &amp;amp;&amp;amp; typeOfContent === \"undefined\" ) {\n\t\t\t\tcontent = \"\";\n\t\t\t}\n\n\t\t\t//Prevents the force caching of nested resources\n\t\t\tjQueryCaching = jQuery.ajaxSettings.cache;\n\t\t\tjQuery.ajaxSettings.cache = true;\n\n\t\t\t// \"replace\" and \"replaceWith\" doesn't map to a jQuery function\n\t\t\tif ( !jsonType ) {\n\t\t\t\tjsonType = \"template\";\n\t\t\t\tapplyTemplate( elm, itmSettings, content );\n\n\t\t\t\t// Trigger wet\n\t\t\t\tif ( itmSettings.trigger &amp;amp;&amp;amp; !wb.isDisabled ) {\n\t\t\t\t\t$elm\n\t\t\t\t\t\t.find( wb.allSelectors )\n\t\t\t\t\t\t.addClass( \"wb-init\" )\n\t\t\t\t\t\t.filter( \":not(#\" + elm.id + \" .wb-init .wb-init)\" )\n\t\t\t\t\t\t.trigger( \"timerpoke.wb\" );\n\t\t\t\t}\n\t\t\t} else if ( jsonType === \"replace\" ) {\n\t\t\t\t$elm.html( content );\n\t\t\t} else if ( jsonType === \"replacewith\" ) {\n\t\t\t\t$elm.replaceWith( content );\n\t\t\t} else if ( jsonType === \"addclass\" ) {\n\t\t\t\t$elm.addClass( content );\n\t\t\t} else if ( jsonType === \"removeclass\" ) {\n\t\t\t\t$elm.removeClass( content );\n\t\t\t} else if ( jsonType === \"prop\" &amp;amp;&amp;amp; attrname &amp;amp;&amp;amp; allowPropNames.test( attrname ) ) {\n\t\t\t\t$elm.prop( attrname, content );\n\t\t\t} else if ( jsonType === \"attr\" &amp;amp;&amp;amp; attrname &amp;amp;&amp;amp; allowAttrNames.test( attrname ) ) {\n\t\t\t\t$elm.attr( attrname, content );\n\t\t\t} else if ( typeof $elm[ jsonType ] === \"function\" &amp;amp;&amp;amp; allowJsonTypes.indexOf( jsonType ) !== -1 ) {\n\t\t\t\t$elm[ jsonType ]( content );\n\t\t\t} else {\n\t\t\t\tthrow componentName + \" do not support type: \" + jsonType;\n\t\t\t}\n\n\t\t\t//Resets the initial jQuery caching setting\n\t\t\tjQuery.ajaxSettings.cache = jQueryCaching;\n\n\t\t\t$elm.trigger( contentUpdatedEvent, { \"json-type\": jsonType, \"content\": content } );\n\t\t}\n\t},\n\n\t// Apply the template as per the configuration\n\tapplyTemplate = function( elm, settings, content ) {\n\n\t\tvar elmClass = elm.className,\n\t\t\tdataTable,\n\t\t\tdataTableAddRow,\n\t\t\ttemplate = settings.source ? document.querySelector( settings.source ) : elm.querySelector( \"template\" );\n\n\t\t// If combined with wb-tables plugin\n\t\tif ( elm.tagName === \"TABLE\" &amp;amp;&amp;amp; elmClass.indexOf( \"wb-tables\" ) !== -1 ) {\n\n\t\t\t//  Wait for its initialization before to applyTemplate\n\t\t\tif ( elmClass.indexOf( \"wb-tables-inited\" ) === -1 || !$.fn.dataTable || !$.fn.dataTable.isDataTable( elm ) ) {\n\t\t\t\t$( elm ).one( \"wb-ready.wb-tables\", function( ) {\n\t\t\t\t\tapplyTemplate( elm, settings, content );\n\t\t\t\t} );\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\tdataTable = $( elm ).dataTable( { \"retrieve\": true } ).api();\n\t\t\tdataTableAddRow = dataTable.row.add;\n\t\t\tsettings.tobeclone = \"tr\"; // Only table row can be added\n\t\t}\n\n\t\tif ( !template ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Needed when executing sub-template that wasn't polyfill, like in IE11\n\t\tif ( !template.content ) {\n\t\t\twb.tmplPolyfill( template );\n\t\t}\n\n\t\tif ( !settings.streamline ) {\n\t\t\tdataIterator( elm, content, settings );\n\t\t} else {\n\t\t\tprocessMapping( elm, elm, content, settings );\n\t\t}\n\n\t\t// Refresh the dataTable display\n\t\tif ( dataTableAddRow ) {\n\t\t\tdataTable.draw();\n\t\t}\n\t},\n\n\t// Iterate over the dataset\n\tdataIterator = function( elm, content, mappingConfig, useClone ) {\n\n\t\tvar i, i_len, i_cache,\n\t\t\telmAppendTo = elm,\n\t\t\tclone, template,\n\t\t\tdataTable, dataTableAddRow;\n\n\t\tif ( mappingConfig.appendto ) {\n\t\t\telmAppendTo = $( mappingConfig.appendto ).get( 0 );\n\t\t}\n\n\t\t// Connection with data table plugin\n\t\tif ( elm.tagName === \"TABLE\" &amp;amp;&amp;amp; elm.className.indexOf( \"wb-tables\" ) !== -1 ) {\n\t\t\tdataTable = $( elm ).dataTable( { \"retrieve\": true } ).api();\n\t\t\tdataTableAddRow = dataTable.row.add;\n\t\t\tmappingConfig.tobeclone = \"tr\";\n\t\t}\n\n\n\t\t// if content is object, transform into array @id and @value\n\t\tif ( !Array.isArray( content ) ) {\n\t\t\tif ( typeof content !== \"object\" ) {\n\t\t\t\tcontent = [ content ];\n\t\t\t} else {\n\t\t\t\tcontent = $.map( content, function( val, index ) {\n\t\t\t\t\tif ( val &amp;amp;&amp;amp; typeof val === \"object\" &amp;amp;&amp;amp; !Array.isArray( val ) ) {\n\t\t\t\t\t\tif ( !val[ \"@id\" ] ) {\n\t\t\t\t\t\t\tval[ \"@id\" ] = index;\n\t\t\t\t\t\t}\n\t\t\t\t\t} else {\n\t\t\t\t\t\tval = {\n\t\t\t\t\t\t\t\"@id\": index,\n\t\t\t\t\t\t\t\"@value\": val\n\t\t\t\t\t\t};\n\t\t\t\t\t}\n\t\t\t\t\treturn [ val ];\n\t\t\t\t} );\n\t\t\t}\n\t\t}\n\t\ti_len = content.length;\n\n\t\t// Get the template to be iterated.\n\t\tif ( !useClone &amp;amp;&amp;amp; mappingConfig.source ) {\n\t\t\ttemplate = document.querySelector( mappingConfig.source );\n\t\t} else if ( !useClone &amp;amp;&amp;amp; mappingConfig.template ) {\n\t\t\ttemplate = elm.querySelector( mappingConfig.template );\n\t\t} else if ( !useClone ) {\n\t\t\ttemplate = elm.querySelectorAll( \":scope &amp;gt; template\" );\n\t\t\tif ( template.length === 1 || template[ 0 ].attributes.length === 0 ) {\n\n\t\t\t\t// Only when there is one choice or take the first one only if only there is no attribute set on the element\n\t\t\t\ttemplate = template[ 0 ];\n\t\t\t} else {\n\n\t\t\t\t// let the mapping instructions to define which template to use\n\t\t\t\ttemplate = false;\n\t\t\t}\n\t\t}\n\n\t\t// Iterate the data array\n\t\tfor ( i = 0; i &amp;lt; i_len; i += 1 ) {\n\t\t\ti_cache = content[ i ];\n\n\n\t\t\t// If the data are filtered. This is deprecated and are only for backward compatible purpose\n\t\t\tif ( !filterPassJSON( i_cache, mappingConfig.filter, mappingConfig.filternot ) ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Get the template (if applicable)\n\t\t\tif ( !clone &amp;amp;&amp;amp; useClone ) {\n\t\t\t\tclone = useClone;\n\t\t\t}\n\n\t\t\t// Create a clone if one unique template is found\n\t\t\tif ( !useClone &amp;amp;&amp;amp; template &amp;amp;&amp;amp; !mappingConfig.tobeclone ) {\n\t\t\t\tclone = template.content.cloneNode( true );\n\t\t\t} else if ( !useClone &amp;amp;&amp;amp; template ) {\n\t\t\t\tclone = template.content.querySelector( mappingConfig.tobeclone ).cloneNode( true );\n\t\t\t}\n\n\t\t\t// process the mapping, return value is the new clone object if applicable\n\t\t\tvar tmpClone;\n\t\t\ttmpClone = processMapping( elm, clone, i_cache, mappingConfig );\n\n\t\t\t// Remove the template flag, to ensure we do reuse it for the subsequent iteration\n\t\t\tif ( tmpClone ) {\n\t\t\t\tdelete mappingConfig.template;\n\t\t\t\tclone = tmpClone;\n\t\t\t}\n\n\t\t\t// Add the clone object\n\t\t\tif ( dataTableAddRow ) {\n\t\t\t\tdataTableAddRow( $( clone ) ); // If wb-tables, use its API to add rows\n\t\t\t} else if ( !useClone &amp;amp;&amp;amp; template ) {\n\t\t\t\telmAppendTo.appendChild( clone );\n\t\t\t}\n\t\t}\n\n\t\t// Refresh the dataTable display (if applicable)\n\t\tif ( dataTableAddRow ) {\n\t\t\tdataTable.draw();\n\t\t}\n\n\t},\n\n\t// Check if the mapping are met or not\n\tcanProcessMapping = function( content, mappingConfig ) {\n\n\t\tvar rawValue, value,\n\t\t\ttestableData,\n\t\t\toperand = mappingConfig.operand || \"softEq\",\n\t\t\toperandOutcome;\n\n\t\tif ( !mappingConfig.test ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Get the value to be tested\n\t\ttry {\n\t\t\trawValue = getRawValue( content, mappingConfig.assess || mappingConfig.value );\n\t\t\tvalue = getValue( rawValue );\n\t\t} catch ( ex ) {\n\n\t\t\t// If this is an error, the path probably don't exist\n\t\t\trawValue = undefined;\n\t\t\tvalue = undefined;\n\t\t}\n\n\t\t// Get the function to use\n\t\tif ( !functionForTest[ mappingConfig.test ] ) {\n\t\t\tconsole.error( \"The test function '\" + mappingConfig.test + \"' don't exist. Default to false test result\" );\n\t\t\tconsole.error( mappingConfig );\n\t\t\treturn false;\n\t\t}\n\t\ttestableData = functionForTest[ mappingConfig.test ].call( mappingConfig, value, rawValue );\n\n\t\t// Run the operand\n\t\tif ( !functionForOperand[ operand ] ) {\n\t\t\tconsole.error( \"The operand '\" + operand + \"' don't exist\" );\n\t\t\tconsole.error( mappingConfig );\n\t\t\toperand = \"softEq\";\n\t\t}\n\t\toperandOutcome = functionForOperand[ operand ].call( mappingConfig, testableData, mappingConfig.expect );\n\n\t\t// If not true, go next\n\t\tif ( !operandOutcome ) {\n\t\t\treturn false;\n\t\t}\n\n\t\t// Run mapping if satisfied\n\t\treturn true;\n\t},\n\n\t// Special mapping typed function\n\tfunctionForTypedMapping = {\n\n\t\t\"rdf:Alt\": function( elm, clone, content, mappingConfig ) {\n\n\t\t\tvar mapping = mappingConfig.mapping,\n\t\t\t\ti, i_cache,\n\t\t\t\ti_len = mapping.length,\n\t\t\t\tvalue = content;\n\n\t\t\tfor ( i = 0; i &amp;lt; i_len || i === 0; i += 1 ) {\n\t\t\t\ti_cache = mapping[ i ];\n\n\t\t\t\tif ( canProcessMapping( content, i_cache ) ) {\n\n\t\t\t\t\t// Clone the object to avoid conflict when it is reused for other data\n\t\t\t\t\ti_cache = $.extend( true, {}, i_cache );\n\n\t\t\t\t\t// Remove the test, because it was checked\n\t\t\t\t\tdelete i_cache.test;\n\n\t\t\t\t\t// Navigate the content if specified\n\t\t\t\t\tif ( i_cache.value ) {\n\t\t\t\t\t\tvalue = getValue( content, i_cache.value );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Process the mapping\n\t\t\t\t\tprocessMapping( elm, clone, value, i_cache );\n\n\t\t\t\t\t// End\n\t\t\t\t\treturn;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t},\n\n\t// Function called for testing the mapping condition, which can be extend via the js configuration\n\tfunctionForTest = {\n\n\t\t\"fn:isArray\": function( value ) {\n\t\t\treturn Array.isArray( value );\n\t\t},\n\n\t\t\"fn:isLiteral\": function( value ) {\n\n\t\t\t// Check if the value are set under the JSON-LD parameter @value\n\t\t\tif ( value &amp;amp;&amp;amp; value[ \"@value\" ] ) {\n\t\t\t\tvalue = value[ \"@value\" ];\n\t\t\t}\n\n\t\t\tif ( value &amp;amp;&amp;amp; typeof value !== \"object\" ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\t\"fn:getType\": function( value, rawValue ) {\n\n\t\t\tvar tp = value[ \"@type\" ] || rawValue[ \"@type\" ];\n\n\t\t\tif ( tp === \"@json\" ) {\n\t\t\t\treturn \"rdf:JSON\";\n\t\t\t} else if ( Array.isArray( tp ) &amp;amp;&amp;amp; tp.indexOf( \"@json\" ) !== -1 ) {\n\t\t\t\ttp[ tp.indexOf( \"@json\" ) ] = \"rdf:JSON\";\n\t\t\t}\n\n\t\t\tif ( tp ) {\n\t\t\t\treturn tp;\n\t\t\t} else {\n\t\t\t\treturn typeof value;\n\t\t\t}\n\t\t},\n\n\t\t\"fn:getValue\": function( value ) {\n\n\t\t\treturn value;\n\n\t\t},\n\n\t\t\"fn:guessType\": function( value, rawValue ) {\n\n\t\t\tvar guessType;\n\n\t\t\tif ( !value ) {\n\t\t\t\tguessType = \"undefined\";\n\t\t\t} else if ( value[ \"@type\" ] ) {\n\t\t\t\tguessType = value[ \"@type\" ];\n\t\t\t} else if ( rawValue[ \"@type\" ] ) {\n\t\t\t\tguessType = rawValue[ \"@type\" ];\n\t\t\t} else if ( value[ \"@value\" ] ) {\n\n\t\t\t\t// Only if we are in JSON ld mode\n\t\t\t\t// Check if the value are set under the JSON-LD parameter @value\n\t\t\t\tvalue = value[ \"@value\" ];\n\t\t\t}\n\n\t\t\t// Edge case to convert the @json data type into its RDF form\n\t\t\tif ( guessType &amp;amp;&amp;amp; guessType !== \"undefined\" ) {\n\t\t\t\tif ( guessType === \"@json\" ) {\n\t\t\t\t\tguessType = \"rdf:JSON\";\n\t\t\t\t} else if ( Array.isArray( guessType ) &amp;amp;&amp;amp; guessType.indexOf( \"@json\" ) !== -1 ) {\n\t\t\t\t\tguessType[ guessType.indexOf( \"@json\" ) ] = \"rdf:JSON\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\tif ( !guessType ) {\n\t\t\t\tif ( typeof value === \"string\" &amp;amp;&amp;amp; value.match( /^([a-z][a-z0-9+\\-.]*):/i ) ) {\n\t\t\t\t\tguessType = [ \"xsd:anyURI\", \"rdfs:Literal\" ];\n\t\t\t\t} else if ( typeof value === \"string\" ) {\n\t\t\t\t\tguessType = [ \"xsd:string\", \"rdfs:Literal\" ];\n\t\t\t\t} else if ( typeof value === \"boolean\" ) {\n\t\t\t\t\tguessType = [ \"xsd:boolean\", \"rdfs:Literal\" ];\n\t\t\t\t} else if ( typeof value === \"number\" ) {\n\t\t\t\t\tguessType = [ \"xsd:double\", \"rdfs:Literal\" ];\n\t\t\t\t} else if ( typeof value === \"undefined\" ) {\n\t\t\t\t\tguessType = \"undefined\";\n\t\t\t\t} else if ( Array.isArray( value ) ) {\n\t\t\t\t\tguessType = \"rdfs:Container\";\n\t\t\t\t} else {\n\n\t\t\t\t\t// The type is a generic Object\n\t\t\t\t\tguessType = \"rdfs:Resource\";\n\t\t\t\t}\n\t\t\t}\n\n\t\t\treturn guessType;\n\t\t}\n\n\t},\n\n\t// Operand used to evaluate the testable output from functionForTest to determine if the mapping condition is met or not, which can be extend via the js configuration\n\tfunctionForOperand = {\n\n\t\t\"softEq\": function( value, expect ) {\n\t\t\tvar i, i_len;\n\n\t\t\tif ( Array.isArray( value ) &amp;amp;&amp;amp; !Array.isArray( expect ) &amp;amp;&amp;amp; value.indexOf( expect ) !== -1 ) {\n\t\t\t\treturn true;\n\t\t\t} else if ( Array.isArray( value ) &amp;amp;&amp;amp;  Array.isArray( expect ) ) {\n\t\t\t\ti_len = expect.length;\n\t\t\t\tfor ( i = 0; i !== i_len; i++ ) {\n\t\t\t\t\tif ( value.indexOf( expect[ i ] ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( expect &amp;amp;&amp;amp; value === expect ) {\n\t\t\t\treturn true;\n\t\t\t} else if ( !expect &amp;amp;&amp;amp; value ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\n\t\t},\n\n\t\t\"eq\": function( value, expect ) {\n\n\t\t\tif ( _equalsJSON( value, expect ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\t\"neq\": function( value, expect ) {\n\t\t\tif ( !_equalsJSON( value, expect ) ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\t\"in\": function( value, expect ) {\n\n\t\t\tvar i;\n\n\t\t\tif ( !expect ) {\n\t\t\t\tconsole.error( \"Expected value is missing. Defaulting to false.\" );\n\t\t\t\tconsole.error( this );\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tif ( Array.isArray( value ) &amp;amp;&amp;amp; !Array.isArray( expect ) &amp;amp;&amp;amp; value.indexOf( expect ) !== -1 ) {\n\t\t\t\treturn true;\n\t\t\t} else if ( Array.isArray( value ) &amp;amp;&amp;amp;  Array.isArray( expect ) ) {\n\t\t\t\tfor ( i = 0; i !== expect.length; i++ ) {\n\t\t\t\t\tif ( value.indexOf( expect[ i ] ) ) {\n\t\t\t\t\t\treturn true;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( !Array.isArray( value ) &amp;amp;&amp;amp;  Array.isArray( expect ) &amp;amp;&amp;amp; expect.indexOf( value ) !== -1  ) {\n\t\t\t\treturn true;\n\t\t\t} else if ( value === expect ) {\n\t\t\t\treturn true;\n\t\t\t}\n\n\t\t\treturn false;\n\t\t},\n\n\t\t\"nin\": function( value, expect ) {\n\t\t\treturn !functionForOperand.in.call( this, value, expect );\n\t\t}\n\t},\n\n\t// Mapping the data into a template or into a node\n\tprocessMapping = function( elm, clone, content, mappingConfig ) {\n\n\t\tvar j, j_cache,\n\t\t\tcached_node, cached_value,\n\t\t\tcached_value_is_HTML, cached_value_is_JSON, cached_value_is_IRI,\n\t\t\tqueryAll = mappingConfig.queryall,\n\t\t\tselElements,\n\t\t\tmapping = mappingConfig.mapping,\n\t\t\tmapping_len,\n\t\t\tupstreamClone, template;\n\n\n\t\t// Is this mapping a special mapping type?\n\t\tif ( mappingConfig[ \"@type\" ] ) {\n\t\t\tfunctionForTypedMapping[ mappingConfig[ \"@type\" ] ].call( content, elm, clone, content, mappingConfig );\n\t\t\treturn;\n\t\t}\n\n\t\t// Can we proceed?\n\t\tif ( mappingConfig.test &amp;amp;&amp;amp; !canProcessMapping( content, mappingConfig ) ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Check if there is some mapping configuration\n\t\tif ( !mapping &amp;amp;&amp;amp; !queryAll &amp;amp;&amp;amp; !mappingConfig.template &amp;amp;&amp;amp; typeof mapping !== \"object\" ) {\n\t\t\treturn;\n\t\t}\n\n\t\t// Clone mappingConfig to ensure it don't interfere with subsequent data iteration\n\t\tmappingConfig = $.extend( true, {}, mappingConfig );\n\n\t\t// If there is no clone, let use the element (parent)\n\t\tclone = clone || elm;\n\n\t\t// If there is a \"template\" property, get the inner template\n\t\tif ( mappingConfig.template ) {\n\t\t\ttemplate = clone.querySelector( mappingConfig.template );\n\n\t\t\tupstreamClone = clone; // Keep reference of the top clone\n\n\t\t\tclone = template.content.cloneNode( true );\n\n\t\t\t// Ensure we don't recreated it if during a subsequent iteration\n\t\t\tdelete mappingConfig.template;\n\t\t}\n\n\n\t\t// Is content an array? then iterate the content\n\t\tif ( Array.isArray( content ) ) {\n\n\n\t\t\tdataIterator( clone, content, mappingConfig, clone );\n\n\t\t\t// Case of where a template is associated with this mapping action\n\t\t\tif ( template ) {\n\t\t\t\tif ( template.parentNode ) {\n\n\t\t\t\t\tif ( !mappingConfig.append ) {\n\t\t\t\t\t\ttemplate.parentNode.insertBefore( clone, template );\n\t\t\t\t\t} else {\n\t\t\t\t\t\ttemplate.parentNode.appendChild( clone );\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tupstreamClone.appendChild( clone );\n\t\t\t\t}\n\n\t\t\t\treturn elm;\n\n\t\t\t}\n\t\t\treturn;\n\t\t}\n\n\t\t// Prepare the mapping object to be iterated\n\t\tif ( !mapping ) {\n\t\t\tmapping = [ {} ];\n\t\t}\n\t\tif ( !Array.isArray( mapping ) ) {\n\t\t\tmapping = [ mapping ];\n\t\t}\n\t\tmapping_len = mapping.length;\n\n\t\t// Ensure the mapping is an array of Mapping Object\n\t\tfor ( j = 0; j &amp;lt; mapping_len || j === 0; j += 1 ) {\n\t\t\tif ( typeof mapping[ j ] === \"string\" ) {\n\t\t\t\tmapping[ j ] = {\n\t\t\t\t\tvalue: mapping[ j ]\n\t\t\t\t};\n\t\t\t}\n\t\t}\n\n\t\tif ( queryAll ) {\n\t\t\tselElements = clone.querySelectorAll( queryAll );\n\n\t\t\t// Replicate this setting the in the mapping\n\t\t\tfor ( j = 0; j &amp;lt; selElements.length || j === 0; j += 1 ) {\n\t\t\t\tif ( !mapping[ j ].selector &amp;amp;&amp;amp; queryAll.indexOf( \"nth-child\" ) === -1 ) {\n\t\t\t\t\tmapping[ j ].selector = queryAll + \":nth-child(\" + ( j + 1 ) + \")\";\n\t\t\t\t} else if ( !mapping[ j ].selector ) {\n\t\t\t\t\tmapping[ j ].selector = queryAll;\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\n\t\t//\n\t\t// Process the mapping\n\t\t//\n\t\tfor ( j = 0; j &amp;lt; mapping_len || j === 0; j += 1 ) {\n\t\t\tj_cache = mapping[ j ];\n\n\t\t\t// Reset the cache value special type flag\n\t\t\tcached_value_is_IRI = false;\n\t\t\tcached_value_is_HTML = false;\n\t\t\tcached_value_is_JSON = false;\n\n\t\t\t// Get the element to be updated\n\t\t\tif ( j_cache.selector ) {\n\t\t\t\tcached_node = clone.querySelector( j_cache.selector );\n\t\t\t} else {\n\t\t\t\tcached_node = clone;\n\t\t\t}\n\n\t\t\t// Get the value to be set\n\t\t\ttry {\n\t\t\t\tcached_value = getRawValue( content, j_cache );\n\t\t\t} catch ( ex ) {\n\n\t\t\t\t// The path don't exist, let continue to the next mapping item\n\t\t\t\tconsole.info( \"JSON selector path for mapping don't exist in content\" );\n\t\t\t\tconsole.info( j_cache );\n\t\t\t\tconsole.info( content );\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Go to the next mapping if the value of JSON node don't exist to ensure we keep the default text set in the template, but move ahead if empty or null\n\t\t\tif ( typeof cached_value === \"undefined\" ) {\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\t// Do the cache value contain special @type\n\t\t\tif ( cached_value &amp;amp;&amp;amp; cached_value[ \"@value\" ] &amp;amp;&amp;amp; cached_value[ \"@type\" ] ) {\n\t\t\t\tif ( !Array.isArray( cached_value[ \"@type\" ] ) ) {\n\t\t\t\t\tcached_value[ \"@type\" ] = [ cached_value[ \"@type\" ] ];\n\t\t\t\t}\n\t\t\t\tcached_value_is_IRI = cached_value[ \"@type\" ].indexOf( \"@id\" ) !== -1;\n\t\t\t\tcached_value_is_HTML = cached_value[ \"@type\" ].indexOf( \"rdf:HTML\" ) !== -1;\n\t\t\t\tcached_value_is_JSON = cached_value[ \"@type\" ].indexOf( \"rdf:JSON\" ) !== -1 || cached_value[ \"@type\" ].indexOf( \"@json\" ) !== -1;\n\t\t\t}\n\n\t\t\t// Action the value\n\t\t\tif ( Array.isArray( cached_value ) &amp;amp;&amp;amp; ( j_cache.mapping || j_cache.queryall ) ) {\n\n\t\t\t\t// Deep dive into the content if a mapping exist\n\t\t\t\tdataIterator( cached_node, cached_value, j_cache );\n\n\t\t\t} else if ( j_cache.mapping || j_cache.queryall || !j_cache.mapping &amp;amp;&amp;amp; typeof j_cache.mapping === \"object\" ) {\n\t\t\t\ttry {\n\n\t\t\t\t\t// Map the inner mapping\n\t\t\t\t\tprocessMapping( template || elm, cached_node, cached_value, j_cache );\n\t\t\t\t} catch ( ex ) {\n\n\t\t\t\t\tif ( ex === \"cached_node: null\" &amp;amp;&amp;amp; typeof cached_value === \"object\" ) {\n\n\t\t\t\t\t\t// If it fail, let iterate the cached_value object\n\t\t\t\t\t\tdataIterator( cached_node, cached_value, j_cache );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tthrow ex;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t} else if ( cached_value_is_IRI &amp;amp;&amp;amp; cached_value_is_HTML ) {\n\n\t\t\t\t// The import file type are expected to be HTML\n\t\t\t\t// Add the data-ajax instruction so the content would be added once the JSON mapping is completed and added on the page.\n\t\t\t\tcached_node.dataset.wbAjax = JSON.stringify( {\n\t\t\t\t\turl: cached_value[ \"@value\" ],\n\t\t\t\t\ttype: \"replace\",\n\t\t\t\t\tdataType: cached_value_is_JSON ? \"json\" : null,\n\t\t\t\t\tencode: j_cache.encode\n\t\t\t\t} );\n\t\t\t} else if ( cached_value_is_HTML &amp;amp;&amp;amp; cached_value_is_JSON &amp;amp;&amp;amp; !cached_value_is_IRI ) {\n\n\t\t\t\t// Get content from the \"@value\" property which contain JSON value and use it as a string value\n\t\t\t\tcached_value = JSON.stringify( cached_value[ \"@value\" ] );\n\n\t\t\t\t// Map the value in the element\n\t\t\t\tmapValue( cached_node, cached_value, j_cache );\n\n\t\t\t} else if ( !cached_node &amp;amp;&amp;amp; typeof cached_value === \"object\" ) {\n\t\t\t\tthrow \"cached_node: null\";\n\t\t\t} else if ( mappingConfig.mapping !== null ) {\n\n\t\t\t\tcached_value = getValue( cached_value );\n\n\t\t\t\t// Serialize the value if it is an JS object and its not a null object\n\t\t\t\tif ( typeof cached_value === \"object\" &amp;amp;&amp;amp;  cached_value !== null ) {\n\t\t\t\t\tcached_value = JSON.stringify( cached_value );\n\t\t\t\t}\n\n\t\t\t\t// Map the value in the element\n\t\t\t\tmapValue( cached_node, cached_value, j_cache );\n\t\t\t}\n\n\t\t}\n\n\t\t// Add the template, if applicable\n\t\tif ( template ) {\n\t\t\tif ( template.parentNode ) {\n\n\t\t\t\tif ( !mappingConfig.append ) {\n\t\t\t\t\ttemplate.parentNode.insertBefore( clone, template );\n\t\t\t\t} else {\n\t\t\t\t\ttemplate.parentNode.appendChild( clone );\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tupstreamClone.appendChild( clone );\n\t\t\t}\n\n\t\t\treturn elm;\n\t\t}\n\n\t},\n\n\t// Extract the value of an JS object\n\tgetValue = function( source, pointer ) {\n\n\t\tvar value = getRawValue( source, pointer );\n\n\t\t// for JSON-LD @value support\n\t\tif ( typeof value === \"object\" &amp;amp;&amp;amp; value !== null &amp;amp;&amp;amp; Object.prototype.hasOwnProperty.call( value, \"@value\" ) ) {\n\t\t\tvalue = value[ \"@value\" ];\n\t\t}\n\n\t\treturn value;\n\t},\n\n\t// Extract the value without considering it possible JSON-LD value\n\tgetRawValue = function( source, pointer ) {\n\n\t\tvar value;\n\t\tpointer = pointer || false; // Ensure pointer is defined\n\n\t\t// Get the value if source is string or pointer is pointing to root\n\t\tif ( typeof source === \"string\" || pointer === \"/\" || pointer === \"/@value\" || pointer.value === \"/\" || pointer.value === \"/@value\" ) {\n\t\t\tvalue = source;\n\t\t} else if ( typeof pointer === \"string\" ) {\n\t\t\tvalue = jsonpointer.get( source, pointer );\n\t\t} else if ( pointer.value ) {\n\t\t\tvalue = jsonpointer.get( source, pointer.value );\n\t\t} else {\n\t\t\tvalue = source;\n\t\t}\n\n\t\treturn value;\n\t},\n\n\t// Map a value into an HTML element or attribute\n\tmapValue = function( element, value, mappingConfig ) {\n\n\t\tvar attributeName, placeholderText;\n\n\t\tattributeName = mappingConfig.attr;\n\t\tif ( attributeName ) {\n\t\t\tif ( !element.hasAttribute( attributeName ) ) {\n\t\t\t\telement.setAttribute( attributeName, \"\" );\n\t\t\t}\n\t\t\telement = element.getAttributeNode( attributeName );\n\t\t}\n\n\t\t// Placeholder text replacement if any\n\t\tif ( mappingConfig.placeholder ) {\n\t\t\tplaceholderText = element.textContent || \"\";\n\t\t\tvalue = placeholderText.replace( mappingConfig.placeholder, value );\n\t\t}\n\n\t\t// Exclude null values and replace with default text\n\t\tif ( value !== null ) {\n\t\t\tif ( mappingConfig.isHTML ) {\n\t\t\t\telement.innerHTML = value;\n\t\t\t} else {\n\t\t\t\telement.textContent = value;\n\t\t\t}\n\t\t}\n\t},\n\n\n\t// Filtering a JSON\n\t// Return true if trueness &amp;amp;&amp;amp; falseness\n\t// Return false if !( trueness &amp;amp;&amp;amp; falseness )\n\t// trueness and falseness is an array of { \"path\": \"\", \"value\": \"\" } object\n\tfilterPassJSON = function( obj, trueness, falseness ) {\n\t\tvar i, i_cache,\n\t\t\ttrueness_len = trueness ? trueness.length : 0,\n\t\t\tfalseness_len = falseness ? falseness.length : 0,\n\t\t\tcompareResult = false,\n\t\t\tisEqual;\n\n\t\tif ( trueness_len || falseness_len ) {\n\n\t\t\tfor ( i = 0; i &amp;lt; trueness_len; i += 1 ) {\n\t\t\t\ti_cache = trueness[ i ];\n\t\t\t\tisEqual = _equalsJSON( jsonpointer.get( obj, i_cache.path ), i_cache.value );\n\n\t\t\t\tif ( i_cache.optional ) {\n\t\t\t\t\tcompareResult = compareResult || isEqual;\n\t\t\t\t} else if ( !isEqual ) {\n\t\t\t\t\treturn false;\n\t\t\t\t} else {\n\t\t\t\t\tcompareResult = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( trueness_len &amp;amp;&amp;amp; !compareResult ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor ( i = 0; i &amp;lt; falseness_len; i += 1 ) {\n\t\t\t\ti_cache = falseness[ i ];\n\t\t\t\tisEqual = _equalsJSON( jsonpointer.get( obj, i_cache.path ), i_cache.value );\n\n\t\t\t\tif ( isEqual &amp;amp;&amp;amp; !i_cache.optional || isEqual &amp;amp;&amp;amp; i_cache.optional ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t\treturn true;\n\t},\n\n\t//\n\t_equalsJSON = function( a, b ) {\n\t\tswitch ( typeof a ) {\n\t\t\tcase \"undefined\":\n\t\t\t\treturn false;\n\t\t\tcase \"boolean\":\n\t\t\tcase \"string\":\n\t\t\tcase \"number\":\n\t\t\t\treturn a === b;\n\t\t\tcase \"object\":\n\t\t\t\tif ( a === null ) {\n\t\t\t\t\treturn b === null;\n\t\t\t\t}\n\t\t\t\tvar i, l;\n\t\t\t\tif ( Array.isArray( a ) ) {\n\t\t\t\t\tif (  !Array.isArray( b ) || a.length !== b.length ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tfor ( i = 0, l = a.length; i &amp;lt; l; i++ ) {\n\t\t\t\t\t\tif ( !_equalsJSON( a[ i ], b[ i ] ) ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tvar bKeys = _objectKeys( b ),\n\t\t\t\t\tbLength = bKeys.length;\n\t\t\t\tif ( _objectKeys( a ).length !== bLength ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tfor ( i in a ) {\n\t\t\t\t\tif ( !_equalsJSON( a[ i ], b[ i ] ) ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t},\n\t_objectKeys = function( obj ) {\n\t\tvar keys;\n\t\tif ( Array.isArray( obj ) ) {\n\t\t\tkeys = new Array( obj.length );\n\t\t\tfor ( var k = 0; k &amp;lt; keys.length; k++ ) {\n\t\t\t\tkeys[ k ] = \"\" + k;\n\t\t\t}\n\t\t\treturn keys;\n\t\t}\n\t\tif ( Object.keys ) {\n\t\t\treturn Object.keys( obj );\n\t\t}\n\t\tkeys = [];\n\t\tfor ( var i in obj ) {\n\t\t\tif ( Object.prototype.hasOwnProperty.call( obj, i ) ) {\n\t\t\t\tkeys.push( i );\n\t\t\t}\n\t\t}\n\t\treturn keys;\n\t},\n\n\t// Manage JSON value After the json data has been fetched\n\tjsonUpdate = function( event ) {\n\t\tvar elm = event.target,\n\t\t\t$elm = $( elm ),\n\t\t\tlstCall = $elm.data( dataQueue ),\n\t\t\trefId = lstCall.length,\n\t\t\twbJsonConfig = event[ \"wb-json\" ];\n\n\t\tif ( !( wbJsonConfig.url &amp;amp;&amp;amp; ( wbJsonConfig.type || wbJsonConfig.source ) ) ) {\n\t\t\tthrow \"Data JSON update not configured properly\";\n\t\t}\n\n\t\tlstCall.push( wbJsonConfig );\n\t\t$elm.data( dataQueue, lstCall );\n\n\t\tloadJSON( elm, wbJsonConfig.url, refId );\n\t};\n\n$document.on( \"json-failed.wb\", selector, function( event ) {\n\n\tvar elm = event.currentTarget,\n\t\t$elm = $( elm ),\n\t\tlstCall = $elm.data( dataQueue ),\n\t\tfetchObj = event.fetch,\n\t\txhrResponse = fetchObj.xhr,\n\t\titmSettings = lstCall[ fetchObj.refId ],\n\t\tfailSettings = itmSettings.fail;\n\n\tif ( failSettings ) {\n\n\t\t// Mapping is always streamline because the data structure is a static object not an array\n\t\tfailSettings.streamline = true;\n\n\t\t// apply the template to display an error message\n\t\tapplyTemplate( elm, failSettings, {\n\t\t\terror: fetchObj.error.message || xhrResponse.statusText,\n\t\t\tstatus: fetchObj.status,\n\t\t\turl: fetchObj.fetchOpts.url,\n\t\t\tresponse: {\n\t\t\t\ttext: xhrResponse.responseText || \"\",\n\t\t\t\tstatus: xhrResponse.status,\n\t\t\t\tstatusText: xhrResponse.statusText\n\t\t\t}\n\t\t} );\n\t}\n\n\tconsole.info( event.currentTarget );\n\tconsole.error( \"Error or bad JSON Fetched from url in \" + componentName );\n} );\n\n// Load template polyfill\nModernizr.load( {\n\ttest: ( \"content\" in document.createElement( \"template\" ) ),\n\tnope: \"site!deps/template\" + wb.getMode() + \".js\"\n} );\n\n$document.on( \"timerpoke.wb \" + initEvent + \" \" + updateEvent + \" json-fetched.wb\", selector, function( event ) {\n\n\tif ( event.currentTarget === event.target ) {\n\t\tswitch ( event.type ) {\n\n\t\t\tcase \"timerpoke\":\n\t\t\tcase \"wb-init\":\n\t\t\t\tinit( event );\n\t\t\t\tbreak;\n\t\t\tcase \"wb-update\":\n\t\t\t\tjsonUpdate( event );\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\tjsonFetched( event );\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\treturn true;\n} );\n\n// Add the timerpoke to initialize the plugin\nfor ( s = 0; s !== selectorsLength; s += 1 ) {\n\twb.add( selectors[ s ] );\n}\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Disable Event\n * @overview Event creates the active offer for users that have disabled the event.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @gc\n */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the event - meaning that they will be initialized once per page,\n * not once per instance of event on the page.\n */\nvar componentName = \"wb-disable\",\n\tselector = \"#wb-tphp\",\n\t$document = wb.doc,\n\tallowOnDisableClass = \"wb-disable-allow\",\n\tallowedPlugins = [\n\t\t{\n\t\t\tselectors: \"[data-wb-jsonmanager]\",\n\t\t\tinitEvent: \"wb-jsonmanager\"\n\t\t},\n\t\t{\n\t\t\tselectors: \"[data-wb-postback]\",\n\t\t\tinitEvent: \"wb-postback\"\n\t\t},\n\t\t{\n\t\t\tselectors: [\n\t\t\t\t\"[data-ajax-after]\",\n\t\t\t\t\"[data-ajax-append]\",\n\t\t\t\t\"[data-ajax-before]\",\n\t\t\t\t\"[data-ajax-prepend]\",\n\t\t\t\t\"[data-ajax-replace]\",\n\t\t\t\t\"[data-wb-ajax]\"\n\t\t\t],\n\t\t\tinitEvent: \"wb-data-ajax\"\n\t\t},\n\t\t{\n\t\t\tselectors: [\n\t\t\t\t\"[data-json-after]\",\n\t\t\t\t\"[data-json-append]\",\n\t\t\t\t\"[data-json-before]\",\n\t\t\t\t\"[data-json-prepend]\",\n\t\t\t\t\"[data-json-replace]\",\n\t\t\t\t\"[data-json-replacewith]\",\n\t\t\t\t\"[data-wb-json]\"\n\t\t\t],\n\t\t\tinitEvent: \"wb-data-json\"\n\t\t}\n\t],\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector, true ),\n\t\t\tnQuery = \"?\",\n\t\t\t$html = wb.html,\n\t\t\ti18n = wb.i18n,\n\t\t\tpageUrl = wb.pageUrlParts,\n\t\t\tparam,\n\t\t\tnoticeHeader = i18n( \"disable-notice-h\" ),\n\t\t\tnoticeBody = i18n( \"disable-notice\" ),\n\t\t\tnoticehtml = \"\n\" + noticeHeader + \"\n\" + noticeBody + \"\n\" + i18n( \"wb-enable\" ) + noticehtmlend;\n\t\t\t\t\t$( elm ).after( noticehtml );\n\t\t\t\t\tdocument.querySelector( \"#\" + significantLinkId ).setAttribute( \"property\", \"significantLink\" );\n\t\t\t\t\treturn true;\n\t\t\t\t} else {\n\t\t\t\t\t$html.addClass( \"wb-enable\" );\n\n\t\t\t\t\tif ( localStorage ) {\n\n\t\t\t\t\t\t// Store preference for WET plugins and polyfills to be enabled in localStorage\n\t\t\t\t\t\tlocalStorage.setItem( \"wbdisable\", \"false\" );\n\t\t\t\t\t}\n\n\t\t\t\t\t// Remove variable from URL\n\t\t\t\t\tvar lc = window.location.href.replace( /&amp;amp;?wbdisable=false/gi, \"\" ).replace( \"?&amp;amp;\", \"?\" ).replace( \"?#\", \"#\" );\n\t\t\t\t\tif ( lc.indexOf( \"?\" ) === ( lc.length - 1 ) ) {\n\t\t\t\t\t\tlc = lc.replace( \"?\", \"\" );\n\t\t\t\t\t}\n\t\t\t\t\twindow.history.replaceState( \"\", \"\", lc );\n\t\t\t\t}\n\t\t\t} catch ( error ) {\n\n\t\t\t\t/* swallow error */\n\t\t\t}\n\n\t\t\t// Append the Basic HTML version link version\n\t\t\t// Add link to disable WET plugins and polyfills\n\t\t\twb.addSkipLink( i18n( \"wb-disable\" ), {\n\t\t\t\thref: nQuery + \"wbdisable=true\",\n\t\t\t\trel: \"alternate\"\n\t\t\t}, false, true );\n\n\t\t\t// Identify that initialization has completed\n\t\t\twb.ready( $document, componentName );\n\t\t}\n\t},\n\n\t// Trigger initialization of plugins that are needed in basic mode\n\t// TODO: Remove once basic initialization is implemented at the core level\n\trunAllowedPlugins = function() {\n\t\tallowedPlugins.forEach( allowedPlugin =&amp;gt; {\n\t\t\tif ( typeof( allowedPlugin.selectors ) === \"object\" ) {\n\t\t\t\tallowedPlugin.selectors = allowedPlugin.selectors.join( \".\" + allowOnDisableClass + \",\" );\n\t\t\t}\n\n\t\t\tallowedPlugin.selectors = allowedPlugin.selectors + \".\" + allowOnDisableClass;\n\n\t\t\t$( allowedPlugin.selectors ).trigger( \"wb-init.\" + allowedPlugin.initEvent );\n\t\t} );\n\t};\n\n// Bind the events\n$document.on( \"timerpoke.wb\", selector, init );\n\n// Go through allowed plugins once again when content has been added dynamically\n$document.on( \"wb-contentupdated\", function() {\n\trunAllowedPlugins();\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW Focus\n * @overview User agent safe way of assigning focus to an element\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @pjackson28\n */\n( function( $, wb ) {\n\"use strict\";\n\nvar $document = wb.doc,\n\t$window = wb.win,\n\tclickEvents = \"click\",\n\tsetFocusEvent = \"setfocus.wb\",\n\tlinkSelector = \"a[href]\",\n\t$linkTarget,\n\n\t/**\n\t * @method processHash\n\t */\n\tprocessHash = function() {\n\t\tvar hash = wb.pageUrlParts.hash;\n\n\t\tif ( hash &amp;amp;&amp;amp; ( $linkTarget = $( \"#\" + wb.jqEscape( hash.substring( 1 ) ) ) ).length !== 0 ) {\n\t\t\t$linkTarget.trigger( setFocusEvent );\n\t\t}\n\t};\n\n// Bind the setfocus event\n$document.on( setFocusEvent, function( event ) {\n\tif ( event.namespace === \"wb\" ) {\n\t\tvar elm = event.target,\n\t\t\t$elm = $( elm ),\n\t\t\t$closedParents = $elm.not( \"summary\" ).parents( \"details, [role='tabpanel']\" ),\n\t\t\t$closedPanels, $closedPanel, len, i;\n\n\t\tif ( $closedParents.length !== 0 ) {\n\n\t\t\t// Open any closed ancestor details elements\n\t\t\t$closedParents.not( \"[open]\" ).children( \"summary\" ).trigger( \"click\" );\n\n\t\t\t// Open any closed tabpanels\n\t\t\t$closedPanels = $closedParents.filter( \"[aria-hidden='true']\" );\n\t\t\tlen = $closedPanels.length;\n\t\t\tfor ( i = 0; i !== len; i += 1 ) {\n\t\t\t\t$closedPanel = $closedPanels.eq( i );\n\t\t\t\t$closedPanel.closest( \".wb-tabs\" )\n\t\t\t\t\t.find( \"#\" + $closedPanel.attr( \"aria-labelledby\" ) )\n\t\t\t\t\t.trigger( \"click\" );\n\t\t\t}\n\t\t}\n\n\t\t// Assigns focus to an element (delay allows for revealing of hidden content)\n\t\tsetTimeout( function() {\n\t\t\tlet addedTabIndexAttr = false;\n\n\t\t\t$elm.trigger( \"focus\" );\n\n\t\t\t// If the element hasn't gained focus, retry with a tabindex attribute...\n\t\t\tif ( elm !== document.activeElement &amp;amp;&amp;amp; elm.getAttribute( \"tabindex\" ) === null ) {\n\n\t\t\t\t// Add a tabindex=\"-1\" attribute and keep track of it for later\n\t\t\t\telm.setAttribute( \"tabindex\", \"-1\" );\n\t\t\t\taddedTabIndexAttr = true;\n\n\t\t\t\t// Try re-focusing\n\t\t\t\t$elm.trigger( \"focus\" );\n\t\t\t}\n\n\t\t\t// If the element has gained focus...\n\t\t\tif ( elm === document.activeElement ) {\n\t\t\t\tconst $topBar = $( \".wb-bar-t[aria-hidden=false]\" );\n\n\t\t\t\t// Ensure the top bar overlay does not conceal the focus target\n\t\t\t\tif ( $topBar.length !== 0 ) {\n\t\t\t\t\tdocument.documentElement.scrollTop -= $topBar.outerHeight();\n\t\t\t\t}\n\t\t\t} else {\n\n\t\t\t\t// Remove the element's tabindex attribute (no point in keeping it if it didn't help)\n\t\t\t\tif ( addedTabIndexAttr ) {\n\t\t\t\t\telm.removeAttribute( \"tabindex\" );\n\t\t\t\t}\n\n\t\t\t\t// Show a console error\n\t\t\t\tconsole.error( setFocusEvent + \": Unable to focus onto the destination element... maybe it's hidden?\" );\n\t\t\t\tconsole.error( elm );\n\t\t\t}\n\n\t\t\treturn $elm;\n\t\t}, 100 );\n\t}\n} );\n\n// Set focus to the target of a deep link from a different page\n// (helps browsers that can't set the focus on their own)\n$document.on( \"wb-ready.wb\", processHash );\n\n// Handle any changes to the URL hash after the page has loaded\n$window.on( \"hashchange\", function() {\n\twb.pageUrlParts.hash = window.location.hash;\n\tif ( !wb.ignoreHashChange ) {\n\t\tprocessHash();\n\t}\n} );\n\n// Helper for browsers that can't change keyboard and/or event focus on a same page link click\n$document.on( clickEvents, linkSelector, function( event ) {\n\tvar testHref = event.currentTarget.getAttribute( \"href\" );\n\n\t// Same page links only\n\tif ( testHref.length &amp;gt; 1 &amp;amp;&amp;amp; testHref.charAt( 0 ) === \"#\" &amp;amp;&amp;amp; !event.isDefaultPrevented() &amp;amp;&amp;amp;\n\t\t( $linkTarget = $( \"#\" + wb.jqEscape( testHref.substring( 1 ) ) ) ).length !== 0 ) {\n\t\twb.ignoreHashChange = true;\n\t\t$linkTarget.trigger( setFocusEvent );\n\t}\n} );\n\n} )( jQuery, wb );\n\n/**\n * @title WET-BOEW JSON Manager\n * @overview Manage JSON dataset, execute JSON patch operation.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @duboisp\n */\n/*global jsonpointer, jsonpatch */\n( function( $, window, wb ) {\n\"use strict\";\n\n/*\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-jsonmanager\",\n\tselector = \"[data-\" + componentName + \"]\",\n\tinitEvent = \"wb-init.\" + componentName,\n\tpostponeEvent = \"postpone.\" + componentName,\n\tpatchesEvent = \"patches.\" + componentName,\n\tjsonFailedClass = \"jsonfail\",\n\treloadFlag = \"data-\" + componentName + \"-reload\",\n\tdsNameRegistered = [],\n\tdatasetCache = {},\n\tdatasetCacheSettings = {},\n\tdsDelayed = {},\n\tdsPostponePatches = {},\n\tdsFetching = {},\n\tdsFetchIsArray = {},\n\tdsFetchMerged = {},\n\t$document = wb.doc,\n\tdefaults = {\n\t\tops: [\n\t\t\t{\n\t\t\t\tname: \"patches\",\n\t\t\t\tfn: function( obj, key, tree ) {\n\t\t\t\t\tvar path = this.path,\n\t\t\t\t\t\tpatches = this.patches,\n\t\t\t\t\t\tnewTree = jsonpointer.get( tree, path );\n\n\t\t\t\t\tpatches.forEach( ( patchConf ) =&amp;gt; {\n\t\t\t\t\t\tpatchConf.mainTree = tree;\n\t\t\t\t\t\tpatchConf.pathParent = path;\n\t\t\t\t\t\tjsonpatch.apply( newTree, [ patchConf ] );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"wb-count\",\n\t\t\t\tfn: function( obj, key, tree ) {\n\t\t\t\t\tvar countme = obj[ key ],\n\t\t\t\t\t\tlen = 0, i_len, i,\n\t\t\t\t\t\tfilter = this.filter || [ ],\n\t\t\t\t\t\tfilternot = this.filternot || [ ];\n\n\t\t\t\t\tif ( !Array.isArray( filter ) ) {\n\t\t\t\t\t\tfilter = [ filter ];\n\t\t\t\t\t}\n\t\t\t\t\tif ( !Array.isArray( filternot ) ) {\n\t\t\t\t\t\tfilternot = [ filternot ];\n\t\t\t\t\t}\n\n\t\t\t\t\tif ( ( filter.length || filternot.length ) &amp;amp;&amp;amp; Array.isArray( countme ) ) {\n\n\t\t\t\t\t\t// Iterate in obj[key] / item and check if is true for the given path is any.\n\t\t\t\t\t\ti_len = countme.length;\n\n\t\t\t\t\t\tfor ( i = 0; i !== i_len; i = i + 1 ) {\n\t\t\t\t\t\t\tif ( filterPassJSON( countme[ i ], filter, filternot ) ) {\n\t\t\t\t\t\t\t\tlen = len + 1;\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( Array.isArray( countme ) ) {\n\t\t\t\t\t\tlen = countme.length;\n\t\t\t\t\t}\n\t\t\t\t\tapplyPatch( tree, \"add\", this.set, len );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"wb-first\",\n\t\t\t\tfn: function( obj, key, tree ) {\n\t\t\t\t\tvar currObj = obj[ key ];\n\t\t\t\t\tif ( !Array.isArray( currObj ) || currObj.length === 0 ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tapplyPatch( tree, \"add\", this.set, currObj[ 0 ] );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"wb-last\",\n\t\t\t\tfn: function( obj, key, tree ) {\n\t\t\t\t\tvar currObj = obj[ key ];\n\t\t\t\t\tif ( !Array.isArray( currObj ) || currObj.length === 0 ) {\n\t\t\t\t\t\treturn;\n\t\t\t\t\t}\n\n\t\t\t\t\tapplyPatch( tree, \"add\", this.set, currObj[ currObj.length - 1 ] );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"wb-nbtolocal\",\n\t\t\t\tfn: function( obj, key, tree ) {\n\t\t\t\t\tvar val = obj[ key ],\n\t\t\t\t\t\tloc = this.locale || window.wb.lang,\n\t\t\t\t\t\tsuffix = this.suffix || \"\",\n\t\t\t\t\t\tprefix = this.prefix || \"\";\n\n\t\t\t\t\tif ( typeof val === \"string\" ) {\n\t\t\t\t\t\tval = parseFloat( val );\n\t\t\t\t\t\tif ( isNaN( val ) ) {\n\t\t\t\t\t\t\treturn;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\n\t\t\t\t\tapplyPatch( tree, \"replace\", this.path, prefix + val.toLocaleString( loc ) + suffix );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"wb-decodeUTF8Base64\",\n\t\t\t\tfn: function( obj, key, tree ) {\n\t\t\t\t\tvar val = obj[ key ];\n\n\t\t\t\t\tif ( !this.set ) {\n\t\t\t\t\t\tapplyPatch( tree, \"replace\", this.path, wb.decodeUTF8Base64( val ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tapplyPatch( tree, \"add\", this.set, wb.decodeUTF8Base64( val ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"wb-escapeHTML\",\n\t\t\t\tfn: function( obj, key, tree ) {\n\t\t\t\t\tvar val = obj[ key ];\n\n\t\t\t\t\tif ( !this.set ) {\n\t\t\t\t\t\tapplyPatch( tree, \"replace\", this.path, wb.escapeHTML( val ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tapplyPatch( tree, \"add\", this.set, wb.escapeHTML( val ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"wb-toDateISO\",\n\t\t\t\tfn: function( obj, key, tree ) {\n\t\t\t\t\tif ( !this.set ) {\n\t\t\t\t\t\tapplyPatch( tree, \"replace\", this.path, wb.date.toDateISO( obj[ key ] ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tapplyPatch( tree, \"add\", this.set, wb.date.toDateISO( obj[ key ] ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"wb-toDateTimeISO\",\n\t\t\t\tfn: function( obj, key, tree ) {\n\t\t\t\t\tif ( !this.set ) {\n\t\t\t\t\t\tapplyPatch( tree, \"replace\", this.path, wb.date.toDateISO( obj[ key ], true ) );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tapplyPatch( tree, \"add\", this.set, wb.date.toDateISO( obj[ key ], true ) );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"wb-swap\",\n\t\t\t\tfn: function( obj, key, tree ) {\n\t\t\t\t\tvar val = obj[ key ],\n\t\t\t\t\t\tref = this.ref,\n\t\t\t\t\t\tmainTree = this.mainTree || obj,\n\t\t\t\t\t\tpath = this.path,\n\t\t\t\t\t\tnewVal,\n\t\t\t\t\t\trefObject, refIsArray, valWasArray,\n\t\t\t\t\t\ti, i_len, i_item,\n\t\t\t\t\t\tj, j_len, j_item;\n\n\t\t\t\t\tif ( val ) {\n\n\t\t\t\t\t\trefObject = jsonpointer.get( mainTree, ref );\n\t\t\t\t\t\trefIsArray = Array.isArray( refObject );\n\t\t\t\t\t\tvalWasArray = Array.isArray( val );\n\n\t\t\t\t\t\tif ( !valWasArray ) {\n\t\t\t\t\t\t\tval =  [ val ];\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\ti_len = val.length;\n\n\t\t\t\t\t\tfor ( i = 0; i !== i_len; i++ ) {\n\t\t\t\t\t\t\ti_item = val[ i ];\n\t\t\t\t\t\t\tnewVal = undefined; // Reinit\n\t\t\t\t\t\t\tif ( !refIsArray ) {\n\t\t\t\t\t\t\t\ti_item = i_item.replaceAll( \"~\", \"~0\" ).replaceAll( \"/\", \"~1\" ); // Escape slashed and tilde in val when the key is an IRI for JSON pointer compatibility\n\t\t\t\t\t\t\t\tnewVal = mainTree ? jsonpointer.get( mainTree, ref + \"/\" + i_item ) : jsonpointer.get( tree, ref + \"/\" + i_item );\n\t\t\t\t\t\t\t} else {\n\n\t\t\t\t\t\t\t\t// Iterate until we found a corresponding value in the property \"@id\"\n\t\t\t\t\t\t\t\tj_len = refObject.length;\n\t\t\t\t\t\t\t\tfor ( j = 0; j !== j_len; j++ ) {\n\t\t\t\t\t\t\t\t\tj_item = refObject[ j ];\n\t\t\t\t\t\t\t\t\tif ( j_item[ \"@id\" ] &amp;amp;&amp;amp; j_item[ \"@id\" ] === i_item ) {\n\t\t\t\t\t\t\t\t\t\tnewVal = j_item;\n\t\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t\tif ( !newVal ) {\n\t\t\t\t\t\t\t\t\tconsole.error( \"wb-swap: Unable to find a corresponding value for: \" + val + \" in reference \" + ref );\n\t\t\t\t\t\t\t\t\tbreak;\n\t\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t\tif ( newVal &amp;amp;&amp;amp; !valWasArray ) {\n\t\t\t\t\t\t\t\tapplyPatch( tree, \"replace\", path, newVal );\n\t\t\t\t\t\t\t} else if ( newVal ) {\n\t\t\t\t\t\t\t\tapplyPatch( tree, \"replace\", path + \"/\" + i, newVal );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\topsArray: [\n\t\t\t{\n\t\t\t\tname: \"wb-toDateISO\",\n\t\t\t\tfn: function( arr )  {\n\t\t\t\t\tvar setval = this.set,\n\t\t\t\t\t\tpathval = this.path,\n\t\t\t\t\t\ti, i_len = arr.length;\n\t\t\t\t\tfor ( i = 0; i !== i_len; i += 1 ) {\n\t\t\t\t\t\tif ( setval ) {\n\t\t\t\t\t\t\tjsonpatch.apply( arr, [\n\t\t\t\t\t\t\t\t{ op: \"wb-toDateISO\", set: \"/\" + i + setval, path: \"/\" + i + pathval }\n\t\t\t\t\t\t\t] );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjsonpatch.apply( arr, [\n\t\t\t\t\t\t\t\t{ op: \"wb-toDateISO\", path: \"/\" + i + pathval }\n\t\t\t\t\t\t\t] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"wb-toDateTimeISO\",\n\t\t\t\tfn: function( arr ) {\n\t\t\t\t\tvar setval = this.set,\n\t\t\t\t\t\tpathval = this.path,\n\t\t\t\t\t\ti, i_len = arr.length;\n\t\t\t\t\tfor ( i = 0; i !== i_len; i += 1 ) {\n\t\t\t\t\t\tif ( setval ) {\n\t\t\t\t\t\t\tjsonpatch.apply( arr, [\n\t\t\t\t\t\t\t\t{ op: \"wb-toDateTimeISO\", set: \"/\" + i + setval, path: \"/\" + i + pathval }\n\t\t\t\t\t\t\t] );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjsonpatch.apply( arr, [\n\t\t\t\t\t\t\t\t{ op: \"wb-toDateTimeISO\", path: \"/\" + i + pathval }\n\t\t\t\t\t\t\t] );\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"wb-swap\",\n\t\t\t\tfn: function( arr ) {\n\t\t\t\t\tarr.forEach( ( item, i ) =&amp;gt; {\n\t\t\t\t\t\tjsonpatch.apply( arr, [\n\t\t\t\t\t\t\t{ op: \"wb-swap\", path: \"/\" + i + this.path, ref: this.ref, mainTree: this.mainTree }\n\t\t\t\t\t\t] );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t},\n\t\t\t{\n\t\t\t\tname: \"patches\",\n\t\t\t\tfn: function( arr ) {\n\t\t\t\t\tarr.forEach( ( item, i ) =&amp;gt; {\n\t\t\t\t\t\tjsonpatch.apply( this.mainTree || arr, [\n\t\t\t\t\t\t\t{ op: \"patches\", path: ( this.pathParent || \"\" ) + \"/\" + i + this.path, patches: this.patches }\n\t\t\t\t\t\t] );\n\t\t\t\t\t} );\n\t\t\t\t}\n\t\t\t}\n\t\t],\n\t\topsRoot: [],\n\t\tsettings: { },\n\t\tdocMapKeys: { \"referer\": document.referrer, \"locationHref\": location.href }\n\t},\n\n\t// Add debug information after the JSON manager element\n\tdebugPrintOut = function( $elm, name, json, patches ) {\n\t\t$elm.after( \"\nJSON Manager Debug (\" +  name + \")\n\nJSON: \n\" + JSON.stringify( json ) + \"\nPatches: \n\" + JSON.stringify( patches ) + \"\" );\n\t\tconsole.log( json );\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm,\n\t\t\tjsSettings = window[ componentName ] || { },\n\t\t\tops, opsArray, opsRoot,\n\t\t\ti, i_len, i_cache,\n\t\t\turl, urlActual, dsName,\n\t\t\tfetchOpts = { };\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\n\t\t\t// Load handlebars\n\t\t\tModernizr.load( {\n\n\t\t\t\t// For loading multiple dependencies\n\t\t\t\tload: [\n\t\t\t\t\t\"site!deps/json-patch\" + wb.getMode() + \".js\",\n\t\t\t\t\t\"site!deps/jsonpointer\" + wb.getMode() + \".js\"\n\t\t\t\t],\n\t\t\t\ttestReady: function() {\n\t\t\t\t\treturn window.jsonpatch &amp;amp;&amp;amp; window.jsonpointer;\n\t\t\t\t},\n\t\t\t\tcomplete: function() {\n\t\t\t\t\tvar elmData = wb.getData( $elm, componentName );\n\n\t\t\t\t\tif ( !defaults.registered ) {\n\t\t\t\t\t\tops = defaults.ops.concat( jsSettings.ops || [ ] );\n\t\t\t\t\t\topsArray = defaults.opsArray.concat( jsSettings.opsArray || [ ] );\n\t\t\t\t\t\topsRoot = defaults.opsRoot.concat( jsSettings.opsRoot || [ ] );\n\n\t\t\t\t\t\tif ( ops.length ) {\n\t\t\t\t\t\t\tfor ( i = 0, i_len = ops.length; i !== i_len; i++ ) {\n\t\t\t\t\t\t\t\ti_cache = ops[ i ];\n\t\t\t\t\t\t\t\tjsonpatch.registerOps( i_cache.name, i_cache.fn );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( opsArray.length ) {\n\t\t\t\t\t\t\tfor ( i = 0, i_len = opsArray.length; i !== i_len; i++ ) {\n\t\t\t\t\t\t\t\ti_cache = opsArray[ i ];\n\t\t\t\t\t\t\t\tjsonpatch.registerOpsArray( i_cache.name, i_cache.fn );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( opsRoot.length ) {\n\t\t\t\t\t\t\tfor ( i = 0, i_len = opsRoot.length; i !== i_len; i++ ) {\n\t\t\t\t\t\t\t\ti_cache = opsRoot[ i ];\n\t\t\t\t\t\t\t\tjsonpatch.registerOpsRoot( i_cache.name, i_cache.fn );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t\tdefaults.settings = $.extend( {}, defaults.settings, jsSettings.settings || {} );\n\t\t\t\t\t\tdefaults.registered = true;\n\t\t\t\t\t}\n\n\t\t\t\t\tdsName = elmData.name;\n\t\t\t\t\tif ( !dsName || dsName in dsNameRegistered ) {\n\t\t\t\t\t\tthrow \"Dataset name must be unique\";\n\t\t\t\t\t}\n\t\t\t\t\tdsNameRegistered.push( dsName );\n\n\t\t\t\t\turl = elmData.url;\n\n\t\t\t\t\tif ( url ) {\n\n\t\t\t\t\t\turl = typeof url === \"string\" ? [ url ] : url;\n\t\t\t\t\t\ti_len = url.length;\n\n\t\t\t\t\t\tdsFetching[ dsName ] = i_len;\n\n\t\t\t\t\t\tfor ( i = 0; i !== i_len; i++ ) {\n\n\t\t\t\t\t\t\turlActual = url[ i ];\n\n\t\t\t\t\t\t\t// Fetch default configuration\n\t\t\t\t\t\t\tfetchOpts = {\n\t\t\t\t\t\t\t\tnocache: elmData.nocache,\n\t\t\t\t\t\t\t\tnocachekey: elmData.nocachekey,\n\t\t\t\t\t\t\t\tdata: elmData.data,\n\t\t\t\t\t\t\t\tcontentType: elmData.contenttype,\n\t\t\t\t\t\t\t\tmethod: elmData.method\n\t\t\t\t\t\t\t};\n\n\t\t\t\t\t\t\t// When the \"url\" is an extended configuration\n\t\t\t\t\t\t\tif ( urlActual.url ) {\n\t\t\t\t\t\t\t\tfetchOpts.savingPath = urlActual.path || \"\";\n\t\t\t\t\t\t\t\tfetchOpts.url = urlActual.url;\n\t\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t\tfetchOpts.url = urlActual;\n\t\t\t\t\t\t\t}\n\n\t\t\t\t\t\t\t// Fetch the JSON\n\t\t\t\t\t\t\t$elm.trigger( {\n\t\t\t\t\t\t\t\ttype: \"json-fetch.wb\",\n\t\t\t\t\t\t\t\tfetch: fetchOpts\n\t\t\t\t\t\t\t} );\n\n\t\t\t\t\t\t\t// If the URL is a dataset, make it ready\n\t\t\t\t\t\t\tif ( fetchOpts.url.charCodeAt( 0 ) === 35 &amp;amp;&amp;amp; fetchOpts.url.charCodeAt( 1 ) === 91 ) {\n\t\t\t\t\t\t\t\twb.ready( $elm, componentName );\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t}\n\t\t\t\t\t} else if ( !url &amp;amp;&amp;amp; elmData.extractor ) {\n\t\t\t\t\t\t$elm.trigger( {\n\t\t\t\t\t\t\ttype: \"json-fetched.wb\",\n\t\t\t\t\t\t\tfetch: {\n\t\t\t\t\t\t\t\tresponse: {}\n\t\t\t\t\t\t\t}\n\t\t\t\t\t\t} );\n\t\t\t\t\t\twb.ready( $elm, componentName );\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\t$elm.trigger( {\n\t\t\t\t\t\t\ttype: \"json-fetch.wb\"\n\t\t\t\t\t\t} );\n\t\t\t\t\t\twb.ready( $elm, componentName );\n\t\t\t\t\t}\n\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t},\n\textractData = function( elmObj ) {\n\n\t\tvar isGroup = false,\n\t\t\tselectedTag,\n\t\t\ttargetTag,\n\t\t\tlastIndex = [],\n\t\t\tj_tag = \"\",\n\t\t\tgroup = {},\n\t\t\tarrMap = [],\n\t\t\tnode_children = [],\n\t\t\tj_node = 0,\n\t\t\tarrRepeatPath = [],\n\t\t\tcombineToObj = function( cur_obj ) {\n\t\t\t\tif ( cur_obj.selector === j_tag ) {\n\t\t\t\t\tif ( !lastIndex.includes( j_tag ) ) {\n\t\t\t\t\t\tgroup[ cur_obj.path ] = cur_obj.attr &amp;amp;&amp;amp; node_children[ j_node ].getAttributeNode( cur_obj.attr ) ?\n\t\t\t\t\t\t\tnode_children[ j_node ].getAttributeNode( cur_obj.attr ).textContent :\n\t\t\t\t\t\t\tnode_children[ j_node ].textContent;\n\t\t\t\t\t\tlastIndex.push( j_tag );\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tmanageObjDir = function( selector, selectedValue, json_return ) {\n\t\t\t\tvar arrPath = selector.path.split( \"/\" ).filter( Boolean );\n\n\t\t\t\t// Check if selectedValue is an empty value returned by querySelectorAll\n\t\t\t\tif ( selectedValue &amp;amp;&amp;amp; selectedValue instanceof NodeList &amp;amp;&amp;amp; selectedValue.length === 0 ) {\n\t\t\t\t\tselectedValue = null;\n\t\t\t\t}\n\n\t\t\t\tif ( arrPath.length &amp;gt; 1 ) {\n\t\t\t\t\tvar pointer = \"\";\n\t\t\t\t\tpointer = arrPath.pop();\n\n\t\t\t\t\tif ( arrPath[ 0 ] &amp;amp;&amp;amp; arrPath[ 0 ] !== \"\" ) {\n\n\t\t\t\t\t\tif ( !json_return[ arrPath[ 0 ] ] &amp;amp;&amp;amp; !arrRepeatPath.includes( arrPath[ 0 ] ) ) {\n\t\t\t\t\t\t\tarrRepeatPath.push( arrPath[ 0 ] );\n\t\t\t\t\t\t\tjson_return[ arrPath[ 0 ] ] = {};\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selector.selectAll &amp;amp;&amp;amp; !json_return[ arrPath[ 0 ] ] [ pointer ]  ) {\n\t\t\t\t\t\t\tjson_return[ arrPath[ 0 ] ] [ pointer ] = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tif ( selector.selectAll ) {\n\t\t\t\t\t\t\tjson_return[ arrPath[ 0 ] ] [ pointer ].push( selectedValue );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjson_return[ arrPath[ 0 ] ] [ pointer ] = selectedValue;\n\t\t\t\t\t\t}\n\n\t\t\t\t\t} else {\n\n\t\t\t\t\t\tif ( selector.selectAll ) {\n\t\t\t\t\t\t\tjson_return[ arrPath[ 0 ] ].push( selectedValue );\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\tjson_return[ pointer ] = selectedValue;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t} else {\n\n\t\t\t\t\tif ( selector.selectAll ) {\n\t\t\t\t\t\tif ( !json_return[ selectedTag.path ] ) {\n\t\t\t\t\t\t\tjson_return[ selectedTag.path ] = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t\tjson_return[ selectedTag.path ].push( selectedValue );\n\t\t\t\t\t} else {\n\t\t\t\t\t\tjson_return[ selectedTag.path ] = selectedValue;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t},\n\t\t\tjsonSource = {};\n\n\n\t\tfor ( var tag = 0; tag &amp;lt;= elmObj.length - 1; tag++ ) {\n\n\t\t\tselectedTag = elmObj[ tag ];\n\n\t\t\tif ( !selectedTag.interface ) {\n\n\t\t\t\ttargetTag = document.querySelectorAll( selectedTag.selector || \"\" );\n\t\t\t\tisGroup = selectedTag.extractor &amp;amp;&amp;amp; selectedTag.extractor.length &amp;gt;= 1 ? true : false;\n\n\t\t\t\tif ( selectedTag.selectAll ) {\n\n\t\t\t\t\tfor ( var i_node = 0; i_node &amp;lt;= targetTag.length - 1; i_node++ ) {\n\n\t\t\t\t\t\tvar selectedTagValue = selectedTag.attr &amp;amp;&amp;amp; targetTag [ i_node ].getAttributeNode( selectedTag.attr ) ?\n\t\t\t\t\t\t\ttargetTag [ i_node ].getAttributeNode( selectedTag.attr ).textContent :\n\t\t\t\t\t\t\ttargetTag [ i_node ].textContent;\n\n\t\t\t\t\t\tmanageObjDir( selectedTag, selectedTagValue, jsonSource );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// extract from combined selectors and group the values e.g dt with dd\n\t\t\t\tif ( isGroup ) {\n\n\t\t\t\t\tjsonSource[ selectedTag.path ] = [];\n\n\t\t\t\t\tnode_children = targetTag[ 0 ].children;\n\n\t\t\t\t\tvar extractorLength = Object.keys( selectedTag.extractor ).length;\n\n\t\t\t\t\tfor ( j_node = 0; j_node &amp;lt;= node_children.length - 1; j_node++ ) {\n\n\t\t\t\t\t\tj_tag = node_children[ j_node ].tagName.toLowerCase();\n\n\t\t\t\t\t\tselectedTag.extractor.find( combineToObj );\n\t\t\t\t\t\tif ( Object.keys( group ).length === extractorLength ) {\n\t\t\t\t\t\t\tarrMap.push( group );\n\t\t\t\t\t\t\tgroup = {};\n\t\t\t\t\t\t\tlastIndex = [];\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\t$.extend( jsonSource[ selectedTag.path ], arrMap );\n\t\t\t\t}\n\n\t\t\t\tif ( targetTag.length ) {\n\t\t\t\t\ttargetTag = selectedTag.attr &amp;amp;&amp;amp; targetTag [ 0 ].getAttributeNode( selectedTag.attr ) ?\n\t\t\t\t\t\ttargetTag [ 0 ].getAttributeNode( selectedTag.attr ).textContent :\n\t\t\t\t\t\ttargetTag [ 0 ].textContent;\n\t\t\t\t}\n\n\t\t\t} else {\n\n\t\t\t\ttargetTag = defaults.docMapKeys[ selectedTag.interface ];\n\n\t\t\t\tmanageObjDir( selectedTag, targetTag, jsonSource );\n\t\t\t}\n\n\t\t\tif ( !selectedTag.selectAll  ) {\n\t\t\t\tif ( isGroup === false ) {\n\t\t\t\t\tmanageObjDir( selectedTag, targetTag, jsonSource );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\treturn jsonSource;\n\t},\n\n\t// Filtering a JSON\n\t// Return true if trueness &amp;amp;&amp;amp; falseness\n\t// Return false if !( trueness &amp;amp;&amp;amp; falseness )\n\t// trueness and falseness is an array of { \"path\": \"\", \"value\": \"\" } object\n\tfilterPassJSON = function( obj, trueness, falseness ) {\n\t\tvar i, i_cache,\n\t\t\ttrueness_len = trueness.length,\n\t\t\tfalseness_len = falseness.length,\n\t\t\tcompareResult = false,\n\t\t\tisEqual;\n\n\t\tif ( trueness_len || falseness_len ) {\n\n\t\t\tfor ( i = 0; i &amp;lt; trueness_len; i += 1 ) {\n\t\t\t\ti_cache = trueness[ i ];\n\t\t\t\tisEqual = _equalsJSON( jsonpointer.get( obj, i_cache.path ), i_cache.value );\n\n\t\t\t\tif ( i_cache.optional ) {\n\t\t\t\t\tcompareResult = compareResult || isEqual;\n\t\t\t\t} else if ( !isEqual ) {\n\t\t\t\t\treturn false;\n\t\t\t\t} else {\n\t\t\t\t\tcompareResult = true;\n\t\t\t\t}\n\t\t\t}\n\t\t\tif ( trueness_len &amp;amp;&amp;amp; !compareResult ) {\n\t\t\t\treturn false;\n\t\t\t}\n\n\t\t\tfor ( i = 0; i &amp;lt; falseness_len; i += 1 ) {\n\t\t\t\ti_cache = falseness[ i ];\n\t\t\t\tisEqual = _equalsJSON( jsonpointer.get( obj, i_cache.path ), i_cache.value );\n\n\t\t\t\tif ( isEqual &amp;amp;&amp;amp; !i_cache.optional || isEqual &amp;amp;&amp;amp; i_cache.optional ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t}\n\n\t\t}\n\t\treturn true;\n\t},\n\n\t// Utility function to compare two JSON value\n\t_equalsJSON = function( a, b ) {\n\t\tswitch ( typeof a ) {\n\t\t\tcase \"undefined\":\n\t\t\t\treturn false;\n\t\t\tcase \"boolean\":\n\t\t\tcase \"string\":\n\t\t\tcase \"number\":\n\t\t\t\treturn a === b;\n\t\t\tcase \"object\":\n\t\t\t\tif ( a === null ) {\n\t\t\t\t\treturn b === null;\n\t\t\t\t}\n\t\t\t\tvar i, l;\n\t\t\t\tif ( Array.isArray( a ) ) {\n\t\t\t\t\tif (  Array.isArray( b ) || a.length !== b.length ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t\tfor ( i = 0, l = a.length; i &amp;lt; l; i++ ) {\n\t\t\t\t\t\tif ( !_equalsJSON( a[ i ], b[ i ] ) ) {\n\t\t\t\t\t\t\treturn false;\n\t\t\t\t\t\t}\n\t\t\t\t\t}\n\t\t\t\t\treturn true;\n\t\t\t\t}\n\t\t\t\tvar bKeys = _objectKeys( b ),\n\t\t\t\t\tbLength = bKeys.length;\n\t\t\t\tif ( _objectKeys( a ).length !== bLength ) {\n\t\t\t\t\treturn false;\n\t\t\t\t}\n\t\t\t\tfor ( i = 0; i &amp;lt; bLength; i++ ) {\n\t\t\t\t\tif ( !_equalsJSON( a[ i ], b[ i ] ) ) {\n\t\t\t\t\t\treturn false;\n\t\t\t\t\t}\n\t\t\t\t}\n\t\t\t\treturn true;\n\t\t\tdefault:\n\t\t\t\treturn false;\n\t\t}\n\t},\n\t_objectKeys = function( obj ) {\n\t\tvar keys;\n\t\tif ( Array.isArray( obj ) ) {\n\t\t\tkeys = new Array( obj.length );\n\t\t\tfor ( var k = 0; k &amp;lt; keys.length; k++ ) {\n\t\t\t\tkeys[ k ] = \"\" + k;\n\t\t\t}\n\t\t\treturn keys;\n\t\t}\n\t\tif ( Object.keys ) {\n\t\t\treturn Object.keys( obj );\n\t\t}\n\t\tkeys = [];\n\t\tfor ( var i in obj ) {\n\t\t\tif ( Object.prototype.hasOwnProperty.call( obj, i ) ) {\n\t\t\t\tkeys.push( i );\n\t\t\t}\n\t\t}\n\t\treturn keys;\n\t},\n\n\t// Utility function to apply a JSON patch\n\tapplyPatch = function( tree, op, path, value ) {\n\t\tjsonpatch.apply( tree, [\n\t\t\t{ op: op, path: path, value: value }\n\t\t] );\n\t},\n\n\t// Create series of patches for filtering\n\tgetPatchesToFilter = function( JSONsource, filterPath, filterTrueness, filterFalseness ) {\n\t\tvar filterObj,\n\t\t\ti, i_len;\n\n\t\tif ( !Array.isArray( filterTrueness ) ) {\n\t\t\tfilterTrueness = [ filterTrueness ];\n\t\t}\n\t\tif ( !Array.isArray( filterFalseness ) ) {\n\t\t\tfilterFalseness = [ filterFalseness ];\n\t\t}\n\n\t\tfilterObj = jsonpointer.get( JSONsource, filterPath );\n\t\tif ( Array.isArray( filterObj ) ) {\n\t\t\ti_len = filterObj.length - 1;\n\t\t\tfor ( i = i_len; i !== -1; i -= 1 ) {\n\t\t\t\tif ( !filterPassJSON( filterObj[ i ], filterTrueness, filterFalseness ) ) {\n\t\t\t\t\tjsonpatch.apply( JSONsource, [ { op: \"remove\", path: filterPath + \"/\" + i } ] );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t\treturn JSONsource;\n\t};\n\n$document.on( \"json-failed.wb\", selector, function( event ) {\n\tvar elm = event.target,\n\t\t$elm;\n\n\tif ( elm === event.currentTarget ) {\n\t\t$elm = $( elm );\n\t\t$elm.addClass( jsonFailedClass );\n\n\t\t// Identify that initialization has completed\n\t\twb.ready( $elm, componentName );\n\t}\n} );\n\n$document.on( \"json-fetched.wb\", selector, function( event ) {\n\tvar elm = event.target,\n\t\t$elm = $( elm ),\n\t\tsettings,\n\t\tfetchedOpts = event.fetch.fetchedOpts,\n\t\tisReloading = elm.hasAttribute( reloadFlag ),\n\t\tdsName,\n\t\tJSONresponse = event.fetch.response,\n\t\tisArrayResponse,\n\t\tresultSet,\n\t\ti, i_len, i_cache, backlog, selector,\n\t\tobjIterator, savingPathSplit,\n\t\tpatches, filterTrueness, filterFalseness, filterPath, extractor;\n\n\tif ( elm === event.currentTarget ) {\n\t\tsettings = wb.getData( $elm, componentName );\n\n\t\t// Is the fetched JSON need to be wrap in another plain object\n\t\tif ( fetchedOpts &amp;amp;&amp;amp; fetchedOpts.savingPath ) {\n\t\t\tsavingPathSplit = fetchedOpts.savingPath.split( \"/\" );\n\n\t\t\tfor ( i = savingPathSplit.length - 1; i &amp;gt; 0; i-- ) {\n\t\t\t\tif ( !savingPathSplit[ i ] ) {\n\t\t\t\t\tcontinue;\n\t\t\t\t}\n\t\t\t\tobjIterator = {};\n\t\t\t\tobjIterator[ savingPathSplit[ i ] ] = JSONresponse;\n\t\t\t\tJSONresponse = objIterator;\n\t\t\t}\n\t\t}\n\n\t\t// Determine if the response is an array\n\t\tisArrayResponse = Array.isArray( JSONresponse );\n\n\t\t// Ensure the response is an independent clone\n\t\tif ( isArrayResponse ) {\n\t\t\tJSONresponse = $.extend( true, [], JSONresponse );\n\t\t} else {\n\t\t\tJSONresponse = $.extend( true, {}, JSONresponse );\n\t\t}\n\n\t\tdsName = settings.name;\n\t\tdsFetching[ dsName ]--;\n\n\t\t// Ensure that we do have fetched and merged all urls everything before to move ahead\n\t\tdsFetchIsArray[ dsName ] = dsFetchIsArray[ dsName ] ? dsFetchIsArray[ dsName ] : isArrayResponse;\n\n\t\tif ( dsFetchIsArray[ dsName ] !== isArrayResponse ) {\n\t\t\tthrow \"Can't merge, incompatible JSON type (array vs object)\";\n\t\t}\n\n\t\tif ( !dsFetchMerged[ dsName ] ) {\n\t\t\tdsFetchMerged[ dsName ] = JSONresponse;\n\t\t} else if ( dsFetchMerged[ dsName ] &amp;amp;&amp;amp; isArrayResponse ) {\n\t\t\tdsFetchMerged[ dsName ] = dsFetchMerged[ dsName ].concat( JSONresponse );\n\t\t} else {\n\t\t\tdsFetchMerged[ dsName ] = $.extend( dsFetchMerged[ dsName ], JSONresponse );\n\t\t}\n\n\t\t// Quit and wait for the next fetch\n\t\tif ( !isReloading &amp;amp;&amp;amp; dsFetching[ dsName ] ) {\n\t\t\treturn;\n\t\t}\n\n\t\tJSONresponse = dsFetchMerged[ dsName ];\n\n\t\textractor = settings.extractor;\n\t\tif ( extractor ) {\n\t\t\tif ( !Array.isArray( extractor ) ) {\n\t\t\t\textractor = [ extractor ];\n\t\t\t}\n\t\t\tJSONresponse = $.extend( JSONresponse, extractData( extractor ) );\n\n\t\t}\n\n\t\tdsName = \"[\" + dsName + \"]\";\n\t\tpatches = settings.patches || [];\n\t\tfilterPath = settings.fpath;\n\t\tfilterTrueness = settings.filter || [];\n\t\tfilterFalseness = settings.filternot || [];\n\n\t\tif ( !Array.isArray( patches ) ) {\n\t\t\tpatches = [ patches ];\n\t\t}\n\n\t\t// Apply a filtering\n\t\tif ( filterPath ) {\n\t\t\tJSONresponse = getPatchesToFilter( JSONresponse, filterPath, filterTrueness, filterFalseness );\n\t\t}\n\n\t\t// Apply the wraproot\n\t\tif ( settings.wraproot  ) {\n\t\t\ti_cache = { };\n\t\t\ti_cache[ settings.wraproot ] = JSONresponse;\n\t\t\tJSONresponse = i_cache;\n\t\t}\n\n\t\t// Apply the patches\n\t\tif ( patches.length ) {\n\t\t\tjsonpatch.apply( JSONresponse, patches );\n\t\t}\n\n\t\tif ( settings.debug ) {\n\t\t\tdebugPrintOut( $elm, \"initEvent\", JSONresponse, patches );\n\t\t}\n\n\t\ttry {\n\t\t\tdatasetCache[ dsName ] = JSONresponse;\n\t\t} catch ( error ) {\n\t\t\treturn;\n\t\t}\n\t\tdatasetCacheSettings[ dsName ] = settings;\n\n\t\tif ( isReloading ) {\n\t\t\telm.removeAttribute( reloadFlag );\n\t\t\ti_cache = dsPostponePatches[ dsName ];\n\t\t\tif ( i_cache ) {\n\t\t\t\t$elm.trigger( i_cache );\n\t\t\t}\n\t\t}\n\n\t\tif ( !settings.wait &amp;amp;&amp;amp; dsDelayed[ dsName ] ) {\n\t\t\tbacklog = dsDelayed[ dsName ];\n\t\t\ti_len = backlog.length;\n\t\t\tfor ( i = 0; i !== i_len; i += 1 ) {\n\t\t\t\ti_cache = backlog[ i ];\n\t\t\t\tselector = i_cache.selector;\n\t\t\t\tif ( selector.length ) {\n\t\t\t\t\ttry {\n\t\t\t\t\t\tresultSet = jsonpointer.get( JSONresponse, selector );\n\t\t\t\t\t} catch  ( e ) {\n\t\t\t\t\t\tthrow dsName + \" - JSON selector not found: \" + selector;\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\tresultSet = JSONresponse;\n\t\t\t\t}\n\t\t\t\t$( \"#\" + i_cache.callerId ).trigger( {\n\t\t\t\t\ttype: \"json-fetched.wb\",\n\t\t\t\t\tfetch: {\n\t\t\t\t\t\tresponse: resultSet,\n\t\t\t\t\t\tstatus: \"200\",\n\t\t\t\t\t\trefId: i_cache.refId,\n\t\t\t\t\t\txhr: null\n\t\t\t\t\t}\n\t\t\t\t}, this );\n\t\t\t}\n\t\t}\n\n\t\t// Identify that initialization has completed\n\t\twb.ready( $elm, componentName );\n\t}\n} );\n\n// Apply patches to a preloaded JSON data\n$document.on( patchesEvent, selector, function( event ) {\n\tvar elm = event.target,\n\t\t$elm = $( elm ),\n\t\tpatches = event.patches,\n\t\tfilterPath = event.fpath,\n\t\tfilterTrueness = event.filter || [],\n\t\tfilterFalseness = event.filternot || [],\n\t\tisCumulative = !!event.cumulative,\n\t\tsettings,\n\t\tdsName,\n\t\tdsJSON, resultSet,\n\t\tdelayedLst,\n\t\ti, i_len, i_cache, pntrSelector;\n\n\tif ( elm === event.currentTarget &amp;amp;&amp;amp; Array.isArray( patches ) ) {\n\t\tsettings = wb.getData( $elm, componentName );\n\n\t\tif ( !settings ) {\n\t\t\treturn true;\n\t\t}\n\t\tdsName = \"[\" + settings.name + \"]\";\n\n\t\t// Check if the patches need to be hold until the next json-fetch event\n\t\tif ( elm.hasAttribute( reloadFlag ) ) {\n\t\t\tdsPostponePatches[ dsName ] = event;\n\t\t\treturn true;\n\t\t}\n\n\t\tif ( !dsDelayed[ dsName ] ) {\n\t\t\tthrow \"Applying patched on undefined dataset name: \" + dsName;\n\t\t}\n\n\t\tdsJSON = datasetCache[ dsName ];\n\t\tif ( !isCumulative ) {\n\t\t\tdsJSON = $.extend( true, ( Array.isArray( dsJSON ) ? [] : {} ), dsJSON );\n\t\t}\n\n\t\t// Apply a filtering\n\t\tif ( filterPath ) {\n\t\t\tdsJSON = getPatchesToFilter( dsJSON, filterPath, filterTrueness, filterFalseness );\n\t\t}\n\n\t\tjsonpatch.apply( dsJSON, patches );\n\n\t\tif ( settings.debug ) {\n\t\t\tdebugPrintOut( $elm, \"patchesEvent\", dsJSON, patches );\n\t\t}\n\n\t\tdelayedLst = dsDelayed[ dsName ];\n\t\ti_len = delayedLst.length;\n\t\tfor ( i = 0; i !== i_len; i += 1 ) {\n\t\t\ti_cache = delayedLst[ i ];\n\t\t\tpntrSelector = i_cache.selector;\n\t\t\tif ( pntrSelector.length ) {\n\t\t\t\ttry {\n\t\t\t\t\tresultSet = jsonpointer.get( dsJSON, pntrSelector );\n\t\t\t\t} catch  ( e ) {\n\t\t\t\t\tthrow dsName + \" - JSON selector not found: \" + pntrSelector;\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\tresultSet = dsJSON;\n\t\t\t}\n\t\t\t$( \"#\" + i_cache.callerId ).trigger( {\n\t\t\t\ttype: \"json-fetched.wb\",\n\t\t\t\tfetch: {\n\t\t\t\t\tresponse: resultSet,\n\t\t\t\t\tstatus: \"200\",\n\t\t\t\t\trefId: i_cache.refId,\n\t\t\t\t\txhr: null\n\t\t\t\t}\n\t\t\t}, this );\n\t\t}\n\t}\n} );\n\n\n// Used by the JSON-fetch plugin for when trying fetching a resource that is mapped a dataset name\n$document.on( postponeEvent, function( event ) {\n\tvar jsonPostpone = event.postpone,\n\t\tdsName = jsonPostpone.dsname,\n\t\tcallerId = jsonPostpone.callerId,\n\t\trefId = jsonPostpone.refId,\n\t\tselector = jsonPostpone.selector,\n\t\tresultSet;\n\n\tif ( !dsDelayed[ dsName ] ) {\n\t\tdsDelayed[ dsName ] = [ ];\n\t}\n\n\t// Add to the delayed updates list\n\tdsDelayed[ dsName ].push( {\n\t\t\"callerId\": callerId,\n\t\t\"refId\": refId,\n\t\t\"selector\": selector\n\t} );\n\n\t// Send the data if the dataset is ready?\n\tif ( datasetCache[ dsName ] &amp;amp;&amp;amp; !datasetCacheSettings[ dsName ].wait ) {\n\t\tresultSet = datasetCache[ dsName ];\n\t\tif ( selector.length ) {\n\t\t\ttry {\n\t\t\t\tresultSet = jsonpointer.get( resultSet, selector );\n\t\t\t} catch  ( e ) {\n\t\t\t\tthrow dsName + \" - JSON selector not found: \" + selector;\n\t\t\t}\n\t\t}\n\t\t$( \"#\" + callerId ).trigger( {\n\t\t\ttype: \"json-fetched.wb\",\n\t\t\tfetch: {\n\t\t\t\tresponse: resultSet,\n\t\t\t\tstatus: \"200\",\n\t\t\t\trefId: refId,\n\t\t\t\txhr: null\n\t\t\t}\n\t\t}, this );\n\t}\n\n} );\n\n/*\n * Integration with wb-fieldflow\n *\n */\nfunction pushData( $elm, prop, data, reset ) {\n\tvar dtCache = $elm.data( prop );\n\tif ( !dtCache || reset ) {\n\t\tdtCache = [];\n\t}\n\tdtCache.push( data );\n\treturn $elm.data( prop, dtCache );\n}\n\n// Fieldflow \"op\" action\n$document.on( \"op.action.wb-fieldflow\", \".wb-fieldflow\", function( event, data ) {\n\n\tif ( !data.op ) {\n\t\treturn;\n\t}\n\n\t// Postpone the event for form submission\n\tdata.preventSubmit = true;\n\tpushData( $( data.provEvt ), \"wb-fieldflow-submit\", data );\n} );\n\n// Fieldflow \"op\" submit\n$document.on( \"op.submit.wb-fieldflow\", \".wb-fieldflow\", function( event, data ) {\n\n\t// Get the hbs Plugin\n\tvar op = data.op,\n\t\tsource = data.source,\n\t\tops;\n\n\tif ( !op ) {\n\t\treturn true;\n\t}\n\n\tif ( !Array.isArray( op ) ) {\n\t\tops = [];\n\t\tops.push( op );\n\t} else {\n\t\tops = op;\n\t}\n\n\t$( source ).trigger( {\n\t\ttype: \"patches.wb-jsonmanager\",\n\t\tpatches: ops\n\t} );\n} );\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * @title WET-BOEW wb-postback\n * @overview This plugin implements AJAX request for form data to submit on same page without refresh\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @masterbee, @namjohn920, @GormFrank\n **/\n( function( $, wb ) {\n\"use strict\";\n\nvar $document = wb.doc,\n\tcomponentName = \"wb-postback\",\n\tselector = \".\" + componentName,\n\tinitEvent = \"wb-init\" + selector,\n\tfailEvent = \"fail\" + selector,\n\tsuccessEvent = \"success\" + selector,\n\tdefaults = {},\n\n\tinit = function( event ) {\n\t\tvar elm = wb.init( event, componentName, selector );\n\n\t\tif ( elm ) {\n\t\t\tvar $elm = $( elm ),\n\t\t\t\tsettings = $.extend(\n\t\t\t\t\ttrue,\n\t\t\t\t\t{},\n\t\t\t\t\tdefaults,\n\t\t\t\t\twb.getData( $elm, componentName )\n\t\t\t\t),\n\t\t\t\tmultiple = typeof $elm.data( componentName + \"-multiple\" ) !== \"undefined\",\n\t\t\t\tclassToggle = settings.toggle || \"hide\",\n\t\t\t\tselectorSuccess = settings.success,\n\t\t\t\tselectorFailure = settings.failure || selectorSuccess;\n\t\t\tconst attrBlocked = \"data-wb-blocked\",\n\t\t\t\tattrPIIBlocked = \"data-wb-pii-blocked\",\n\t\t\t\tattrSending = \"data-wb-sending\";\n\n\t\t\telm.addEventListener( \"submit\", function( e ) {\n\n\t\t\t\t// Prevent regular form submit\n\t\t\t\te.preventDefault();\n\n\t\t\t\t//Check if the form use the validation plugin\n\t\t\t\tif ( elm.parentElement.classList.contains( \"wb-frmvld\" ) ) {\n\n\t\t\t\t\t// Block invalid forms and allow valid ones\n\t\t\t\t\tif ( !$elm.valid() ) {\n\t\t\t\t\t\t$( this ).attr( attrBlocked, \"true\" );\n\t\t\t\t\t} else {\n\t\t\t\t\t\t$( this ).removeAttr( attrBlocked );\n\t\t\t\t\t}\n\t\t\t\t}\n\n\t\t\t\t// Submit the form unless it's blocked or currently being sent\n\t\t\t\tif ( !$( this ).attr( attrBlocked ) &amp;amp;&amp;amp; !$( this ).attr( attrSending ) &amp;amp;&amp;amp; !$( this ).attr( attrPIIBlocked ) ) {\n\t\t\t\t\t$elm.trigger( componentName + \".submit\", e.submitter );\n\t\t\t\t}\n\t\t\t} );\n\n\t\t\t$elm.on( componentName + \".submit\", function( event, submitter ) {\n\t\t\t\tvar data = $elm.serializeArray(),\n\t\t\t\t\t$selectorSuccess = $( selectorSuccess ),\n\t\t\t\t\t$selectorFailure = $( selectorFailure );\n\n\t\t\t\t// Indicate that the form is currently being sent (to prevent multiple submissions in parallel)\n\t\t\t\t$( this ).attr( attrSending, true );\n\n\t\t\t\t// If the submit button contains a variable, add it to the form's parameters\n\t\t\t\t// Note: Submitting a form via Enter will act as if the FIRST submit button was pressed. Therefore, that button's variable will be added (as opposed to nothing). This is in line with default form submission behaviour.\n\t\t\t\tif ( submitter &amp;amp;&amp;amp; submitter.name ) {\n\t\t\t\t\tdata.push( { name: submitter.name, value: submitter.value } );\n\t\t\t\t}\n\n\t\t\t\t// Hide feedback messages\n\t\t\t\t$selectorFailure.addClass( classToggle );\n\t\t\t\t$selectorSuccess.addClass( classToggle );\n\n\t\t\t\t// Send the form through ajax and ignore the response body.\n\t\t\t\t$.ajax( {\n\t\t\t\t\ttype: this.method,\n\t\t\t\t\turl: this.action,\n\t\t\t\t\tdata: $.param( data )\n\t\t\t\t} )\n\n\t\t\t\t\t// If the successURL is set and the success parameter is not defined, redirect to the successURL\n\t\t\t\t\t.done( function() {\n\t\t\t\t\t\tif ( settings.successURL &amp;amp;&amp;amp; !settings.success ) {\n\t\t\t\t\t\t\twindow.location.href = settings.successURL;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$selectorSuccess.removeClass( classToggle ).trigger( \"setfocus.wb\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$elm.trigger( successEvent );\n\t\t\t\t\t} )\n\n\t\t\t\t\t// If the failureURL is set and the failure parameter is not defined, redirect to the failureURL\n\t\t\t\t\t.fail( function( response ) {\n\t\t\t\t\t\tif ( settings.failureURL &amp;amp;&amp;amp; !settings.failure ) {\n\t\t\t\t\t\t\twindow.location.href = settings.failureURL;\n\t\t\t\t\t\t} else {\n\t\t\t\t\t\t\t$selectorFailure.removeClass( classToggle ).trigger( \"setfocus.wb\" );\n\t\t\t\t\t\t}\n\t\t\t\t\t\t$elm.trigger( failEvent, response );\n\t\t\t\t\t} )\n\t\t\t\t\t.always( function() {\n\n\t\t\t\t\t\t// Hide the form unless multiple submits are allowed\n\t\t\t\t\t\tif ( !multiple ) {\n\t\t\t\t\t\t\t$elm.addClass( classToggle );\n\t\t\t\t\t\t}\n\n\t\t\t\t\t\t// Remove the sending indicator now that submission is fully complete (i.e. HTTP response code has been received)\n\t\t\t\t\t\t$elm.removeAttr( attrSending );\n\t\t\t\t\t} );\n\t\t\t} );\n\n\t\t\twb.ready( $( elm ), componentName );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, wb );\n\n/**\n * @title WET-BOEW Randomize\n * @overview This plugin randomly picks one of the child component to be shown on the browser.\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @masterbee @namjohn920\n */\n( function( $, window, wb ) {\n\"use strict\";\n\nvar $document = wb.doc,\n\tcomponentName = \"wb-randomize\",\n\tselector = \"[data-wb-randomize]\",\n\tinitEvent = \"wb-init\" + selector,\n\tdefaults = {},\n\n\tinit = function( event ) {\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\t$elm, settings, $selectedElm, valuesList;\n\n\t\tif ( elm ) {\n\t\t\t$elm = $( elm );\n\t\t\tsettings = $.extend(\n\t\t\t\ttrue,\n\t\t\t\t{},\n\t\t\t\tdefaults,\n\t\t\t\twindow[ componentName ],\n\t\t\t\twb.getData( $elm, componentName )\n\t\t\t);\n\n\t\t\tif ( settings.attribute ) {\n\t\t\t\tif ( settings.values &amp;amp;&amp;amp; Array.isArray( settings.values ) ) {\n\t\t\t\t\tvaluesList = settings.values;\n\t\t\t\t\tshuffleArray( valuesList );\n\t\t\t\t\telm.setAttribute( settings.attribute, valuesList[ 0 ] );\n\t\t\t\t} else {\n\t\t\t\t\tthrow componentName + \": You must define the property \\\"values\\\" to an array of strings when \\\"attribute\\\" property is defined.\";\n\t\t\t\t}\n\t\t\t} else {\n\t\t\t\t$selectedElm = settings.selector ? $( settings.selector, $elm ) : $elm.children();\n\n\t\t\t\tif ( !$selectedElm.length ) {\n\t\t\t\t\tthrow componentName + \" selector setting is invalid or no children\";\n\t\t\t\t}\n\n\t\t\t\tif ( settings.shuffle ) {\n\t\t\t\t\t$selectedElm = wb.shuffleDOM( $selectedElm );\n\t\t\t\t}\n\n\t\t\t\tif ( settings.toggle ) {\n\t\t\t\t\t$selectedElm = wb.pickElements( $selectedElm, settings.number );\n\t\t\t\t\t$selectedElm.toggleClass( settings.toggle );\n\t\t\t\t}\n\t\t\t}\n\n\t\t\twb.ready( $elm, componentName );\n\t\t}\n\t},\n\n\tshuffleArray = function( array ) {\n\t\tfor ( let i = array.length - 1; i &amp;gt; 0; i-- ) {\n\t\t\tconst j = Math.floor( Math.random() * ( i + 1 ) );\n\t\t\t[ array[ i ], array[ j ] ] = [ array[ j ], array[ i ] ];\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent, selector, init );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, wb );\n\n/**\n * Web Experience Toolkit (WET) / Bo\u00eete \u00e0 outils de l'exp\u00e9rience Web (BOEW)\n * @title Zebra\n * @overview Apply Zebra stripping on a complex data table and simulate column hovering effect\n * @license wet-boew.github.io/wet-boew/License-en.html / wet-boew.github.io/wet-boew/Licence-fr.html\n * @author @duboisp\n *\n */\n( function( $, window, document, wb ) {\n\"use strict\";\n\n/**\n * Variable and function definitions.\n * These are global to the plugin - meaning that they will be initialized once per page,\n * not once per instance of plugin on the page. So, this is a good place to define\n * variables that are common to all instances of the plugin on a page.\n */\nvar componentName = \"wb-zebra\",\n\tselector = \".\" + componentName,\n\thoverColClass = componentName + \"-col-hover\",\n\tselectorHoverCol = \".\" + hoverColClass + \" td, \" + hoverColClass + \" th\",\n\tinitEvent = \"wb-init\" + selector,\n\ttableParsingEvent = \"passiveparse.wb-tableparser\",\n\ttableParsingCompleteEvent = \"parsecomplete.wb-tableparser\",\n\t$document = wb.doc,\n\tidCount = 0,\n\ti18n, i18nText,\n\n\t/**\n\t * Main Entry function to apply the complex zebra stripping\n\t * @method zebraTable\n\t * @param {jQuery DOM element} $elm table element use to apply complex zebra stripping\n\t */\n\tzebraTable = function( $elm ) {\n\t\tvar i, iLength, tblGroup,\n\n\t\t\t// Cache the table parsed results\n\t\t\ttblparser = $elm.data().tblparser;\n\n\t\tfunction addCellClass( arr, className ) {\n\t\t\tvar i, iLength;\n\n\t\t\tfor ( i = 0, iLength = arr.length; i !== iLength; i += 1 ) {\n\t\t\t\t$( arr[ i ].elem ).addClass( className );\n\t\t\t}\n\t\t}\n\n\t\t// Key Cell\n\t\tif ( tblparser.keycell ) {\n\t\t\taddCellClass( tblparser.keycell, \"wb-cell-key\" );\n\t\t}\n\n\t\t// Description Cell\n\t\tif ( tblparser.desccell ) {\n\t\t\taddCellClass( tblparser.desccell, \"wb-cell-desc\" );\n\t\t}\n\n\t\t// Layout Cell\n\t\tif ( tblparser.layoutCell ) {\n\t\t\taddCellClass( tblparser.layoutCell, \"wb-cell-layout\" );\n\t\t}\n\n\t\t// Summary Row Group\n\t\tif ( tblparser.lstrowgroup ) {\n\t\t\tfor ( i = 0, iLength = tblparser.lstrowgroup.length; i !== iLength; i += 1 ) {\n\t\t\t\ttblGroup = tblparser.lstrowgroup[ i ];\n\n\t\t\t\t// Add a class to the row\n\t\t\t\tif ( tblGroup.type === 3 || tblGroup.row[ 0 ].type === 3 ) {\n\t\t\t\t\t$( tblGroup.elem ).addClass( \"wb-group-summary\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Summary Column Group\n\t\tif ( tblparser.colgroup ) {\n\t\t\tfor ( i = 0, iLength = tblparser.colgroup.length; i !== iLength; i += 1 ) {\n\t\t\t\ttblGroup = tblparser.colgroup[ i ];\n\n\t\t\t\t// Add a class to the row\n\t\t\t\tif ( tblGroup.type === 3 ) {\n\t\t\t\t\t$( tblGroup.elem ).addClass( \"wb-group-summary\" );\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\n\t\t// Identify that initialization has completed\n\t\twb.ready( $elm, componentName );\n\t},\n\n\t/**\n\t * @method init\n\t * @param {jQuery Event} event Event that triggered the function call\n\t */\n\tinit = function( event ) {\n\n\t\t// Start initialization\n\t\t// returns DOM object = proceed with init\n\t\t// returns undefined = do not proceed with init (e.g., already initialized)\n\t\tvar elm = wb.init( event, componentName, selector ),\n\t\t\tdeps = [\n\t\t\t\t\"site!deps/tableparser\" + wb.getMode() + \".js\"\n\t\t\t],\n\t\t\telmId;\n\n\t\tif ( elm ) {\n\t\t\telmId = elm.id;\n\n\t\t\t// Ensure there is a unique id on the element\n\t\t\tif ( !elmId ) {\n\t\t\t\telmId = componentName + \"-id-\" + idCount;\n\t\t\t\tidCount += 1;\n\t\t\t\telm.id = elmId;\n\t\t\t}\n\n\t\t\t// Only initialize the i18nText once\n\t\t\tif ( !i18nText ) {\n\t\t\t\ti18n = wb.i18n;\n\t\t\t\ti18nText = {\n\t\t\t\t\ttableMention: i18n( \"hyphen\" ) + i18n( \"tbl-txt\" ),\n\t\t\t\t\ttableFollowing: i18n( \"hyphen\" ) + i18n( \"tbl-dtls\" )\n\t\t\t\t};\n\t\t\t}\n\n\t\t\t// Load the required dependencies\n\t\t\tModernizr.load( {\n\n\t\t\t\t// For loading multiple dependencies\n\t\t\t\tload: deps,\n\t\t\t\tcomplete: function() {\n\n\t\t\t\t\t// Let's parse the table\n\t\t\t\t\t$( \"#\" + elmId ).trigger( tableParsingEvent );\n\t\t\t\t}\n\t\t\t} );\n\t\t}\n\t};\n\n// Bind the init event of the plugin\n$document.on( \"timerpoke.wb \" + initEvent + \" \" + tableParsingCompleteEvent, selector, function( event ) {\n\tvar eventTarget = event.target;\n\n\tswitch ( event.type ) {\n\n\t\t/*\n\t\t * Init\n\t\t */\n\t\tcase \"timerpoke\":\n\t\tcase \"wb-init\":\n\t\t\tinit( event );\n\t\t\tbreak;\n\n\t\t/*\n\t\t * Data table parsed\n\t\t */\n\t\tcase \"parsecomplete\":\n\t\t\tif ( event.currentTarget === eventTarget ) {\n\t\t\t\tzebraTable( $( eventTarget ) );\n\t\t\t}\n\t\t\tbreak;\n\t}\n\n\t/*\n\t * Since we are working with events we want to ensure that we are being passive about our control,\n\t * so returning true allows for events to always continue\n\t */\n\treturn true;\n} );\n\n// Applying the hover, Simulate Column Hovering Effect\n$document.on( \"mouseenter focusin\", selectorHoverCol, function( event ) {\n\tvar tblparserCell = $( event.currentTarget ).data().tblparser;\n\n\tif ( tblparserCell.col &amp;amp;&amp;amp; tblparserCell.col.elem ) {\n\t\t$( tblparserCell.col.elem ).addClass( \"table-hover\" );\n\t}\n} );\n\n// Removing the hover, Simulate Column Hovering Effect\n$document.on( \"mouseleave focusout\", selectorHoverCol, function( event ) {\n\tvar tblparserCell = $( event.currentTarget ).data().tblparser;\n\n\tif ( tblparserCell.col &amp;amp;&amp;amp; tblparserCell.col.elem ) {\n\t\t$( tblparserCell.col.elem ).removeClass( \"table-hover\" );\n\t}\n} );\n\n// Add the timer poke to initialize the plugin\nwb.add( selector );\n\n} )( jQuery, window, document, wb );\n", "creation_timestamp": "2026-09-02T19:34:20.908339Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/f916a65a-6d0f-4bc2-9e53-7fe42a1f0ce5/export"/>
    <published>2026-09-02T19:34:20.908339+00:00</published>
  </entry>
  <entry>
    <id>https://vulnerability.circl.lu/sighting/5d5bb61a-056b-4ae2-bc6c-643678e770e0/export</id>
    <title>5d5bb61a-056b-4ae2-bc6c-643678e770e0</title>
    <updated>2026-09-05T20:22:09.629101+00:00</updated>
    <author>
      <name>Automation user</name>
      <uri>https://vulnerability.circl.lu/user/automation</uri>
    </author>
    <content>{"uuid": "5d5bb61a-056b-4ae2-bc6c-643678e770e0", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "GHSA-GXR4-XJJ5-5PX2", "type": "seen", "source": "Telegram/KQJ2fokDRUpEEMEdtilLJpNYW94QEwCQWFCqP7BH6XiY", "content": "", "creation_timestamp": "2024-09-12T10:16:41.000000Z"}</content>
    <link href="https://vulnerability.circl.lu/sighting/5d5bb61a-056b-4ae2-bc6c-643678e770e0/export"/>
    <published>2024-09-12T10:16:41+00:00</published>
  </entry>
</feed>
