{ "version": 3, "sources": ["../../lib/_dompurify/purify.js", "../../js/universal/debounce/debounce.js", "../../lib/_cookie-js/js.cookie.js", "../../lib/_smooth-scroll-polyfill/smoothscroll.js", "../../js/universal/jquery-plugins/do-if-exists.js", "../../js/universal/jquery-plugins/do-if-not-exists.js", "../../js/universal/jquery-plugins/flex-fade-in.js", "../../js/universal/jquery-plugins/flex-fade-out.js", "../../js/universal/jquery-plugins/safe-html.js", "../../js/universal/jquery-plugins/all.js", "../../js/universal/hover/add-class.js", "../../js/player-search/clear.js", "../../js/player-search/events.js", "../../js/player-search/handle-keyboard-nav.js", "../../js/universal/hover/remove-class.js", "../../js/player-search/show-mobile-search-box.js", "../../js/player-search/build-search-result.js", "../../js/universal/error-handling/remove-error-notification-bar.js", "../../js/universal/error-handling/show-error-notification-bar.js", "../../js/player-search/search.js", "../../js/player-search/trigger-search.js", "../../js/nav/display-screen.js", "../../js/nav/section-nav-sub.js", "../../js/nav/open-section-menu.js", "../../js/nav/close-section-menu.js", "../../js/nav/events.js", "../../js/navigation/events.js", "../../js/navigation/scroll-tabs/arrows/adjust.js", "../../js/navigation/scroll-tabs/arrows/add.js", "../../js/navigation/side/search/clear.js", "../../js/navigation/side/close.js", "../../js/universal/window-resize/do-on-window-resize.js", "../../js/navigation/side/search/add-to-nav.js", "../../js/navigation/side/open.js", "../../js/navigation/scroll-tabs/toggle-sub-pages.js", "../../js/navigation/scroll-tabs/toggle-default-sub-pages.js", "../../js/navigation/section/close-dropdown.js", "../../js/navigation/section/calculate-dropdown-pos.js", "../../js/navigation/section/toggle-dropdown.js", "../../js/navigation/side/sub-section/toggle.js", "../../js/navigation/section/trigger-close-dropdown.js", "../../js/navigation/section/trigger-item-link.js", "../../js/navigation/scroll-tabs/arrows/trigger-scroll.js", "../../js/navigation/scroll-tabs/trigger-toggle-sub-pages.js", "../../js/navigation/side/search/get-no-results-html.js", "../../js/navigation/side/search/watch.js", "../../js/universal/cloudinary/hide-hidden-images.js", "../../js/universal/cloudinary/restore-hidden-images.js", "../../js/universal/cloudinary/activate.js", "../../js/universal/ripple-effect/activate.js", "../../js/universal/smart-anchor-tags/remove-hashes-from-url.js", "../../js/universal/smart-anchor-tags/activate.js", "../../js/universal/button-state/automatic-button-processing.js", "../../js/universal/articles/cancel-comment-reply.js", "../../js/universal/ads/check-for-wallpaper.js", "../../js/universal/player-news/expand-update.js", "../../js/universal/player-outlooks/expand.js", "../../js/universal/widows/fix-all.js", "../../js/universal/button-state/remove-button-processing-state.js", "../../js/universal/toggle-tabs/get-tab-settings.js", "../../js/universal/toggle-tabs/perform-actions.js", "../../js/universal/toggle-tabs/switch-tab.js", "../../js/universal/player-news/get.js", "../../js/universal/css-grid/set-min-grid-width.js", "../../js/universal/player-rankings/get.js", "../../js/universal/player-rumors/get.js", "../../js/universal/ads/hide-ad-containers.js", "../../js/universal/filter-tabs/check-for-match.js", "../../js/universal/filter-checkboxes/filter-items.js", "../../js/universal/filter-checkboxes/get-settings.js", "../../js/universal/filter-checkboxes/update-filter.js", "../../js/universal/filter-checkboxes/initialize.js", "../../lib/_lozad/lozad.es.js", "../../js/universal/cloudinary/lazy-loader.js", "../../js/universal/ads/insert-freestar-sticky-ads.js", "../../js/universal/ads/insert-connatix.js", "../../js/universal/ads/insert-stn.js", "../../js/universal/ads/insert-video-ads.js", "../../js/universal/ajax-loader/get-data.js", "../../js/universal/player-news/minimize-update.js", "../../js/universal/charts/on-data.js", "../../js/universal/charts/get-key-data-points.js", "../../js/universal/charts/get-limit-mode.js", "../../js/universal/charts/on-draw.js", "../../js/universal/modal-window/get-presets-confirmation.js", "../../js/universal/modal-window/build-modal-confirmation.js", "../../js/universal/modal-window/open-confirmation.js", "../../js/universal/modal-window/build-modal-item-editor.js", "../../js/universal/modal-window/open-item-editor.js", "../../js/universal/jump-bar/activate.js", "../../js/universal/reveal/reveal-element.js", "../../js/universal/filter-links/reveal-selected-filter.js", "../../js/universal/scroll-on-load/scroll-to-element-on-load.js", "../../js/universal/radio-button/select-radio-button-in-row.js", "../../js/universal/userlist/send-activity-event.js", "../../js/universal/events.js", "../../js/universal/checkboxes/toggle.js", "../../js/universal/filter-checkboxes/trigger-filter-update.js", "../../js/universal/data-filter/clear.js", "../../js/universal/data-filter/trigger-clear.js", "../../js/universal/input-with-clear/clear.js", "../../js/universal/input-with-clear/trigger-clear.js", "../../js/universal/filter-links/trigger-close-sub-nav.js", "../../js/universal/modal-window/close.js", "../../js/universal/modal-window/trigger-close.js", "../../js/universal/articles/trigger-comment-reply.js", "../../js/universal/filter-links/open-range-editor.js", "../../js/universal/filter-links/trigger-range-editor.js", "../../js/universal/filter-links/trigger-sub-nav.js", "../../js/universal/filter-tabs/manage-empty-state.js", "../../js/universal/filter-tabs/filter-items.js", "../../js/universal/filter-tabs/get-filter-settings.js", "../../js/universal/filter-tabs/get-tab-settings.js", "../../js/universal/filter-tabs/switch-tab.js", "../../js/universal/filter-tabs/trigger-tab-open.js", "../../js/universal/filter-tabs/trigger-tab-switch.js", "../../js/universal/articles/get-articles.js", "../../js/universal/articles/trigger-get-articles.js", "../../js/universal/custom-lists/get-content.js", "../../js/universal/custom-lists/trigger-get-content.js", "../../lib/_idb-keyval/idb-keyval.js", "../../js/universal/breakpoints/get-data.js", "../../js/universal/toggle-tabs/trigger-selected-tab.js", "../../js/universal/toggle-tabs/trigger-selected-on-resize.js", "../../js/universal/time-period-selector/change-time-period.js", "../../js/universal/time-period-selector/trigger-time-period-change.js", "../../js/universal/toggle-tabs/trigger-tab-switch.js", "../../js/universal/bet-calc/update-winnings.js", "../../js/universal/bet-calc/trigger-update-winnings.js", "../../js/universal/window-resize/trigger-window-resized-listener.js", "../../js/universal/filter-tabs/get-all-tabs.js", "../../js/universal/filter-tabs/update-filter-counts.js", "../../js/universal/filter-links/update-range-editor.js", "../../js/universal/data-filter/watch-input.js", "../../js/universal/filter-tabs/watch-items.js", "../../js/universal/input-with-clear/watch-input.js", "../../js/universal/modal-window/build-modal.js", "../../js/sport-specific/nfl/open-team-vs-pos-modal.js", "../../js/sport-specific/nfl/open-team-trends-modal.js", "../../js/sport-specific/nfl/open-win-rate-modal.js", "../../js/sport-specific/nfl/open-win-rate-by-season-modal.js", "../../js/sport-specific/nfl/events.js", "../../js/sport-specific/nba/add-court-on-off-player.js", "../../js/sport-specific/nba/clear-injury-archive-search.js", "../../js/sport-specific/nba/events.js", "../../js/sport-specific/nba/load-court-on-off-table.js", "../../js/sport-specific/nba/open-court-on-off-modal.js", "../../js/sport-specific/nba/open-injury-archive-modal.js", "../../js/sport-specific/nba/open-team-trends-modal.js", "../../js/sport-specific/nba/remove-court-on-off-player.js", "../../js/sport-specific/nba/injury-archive-search.js", "../../js/sport-specific/nba/trigger-injury-archive-search.js", "../../js/sport-specific/nhl/open-team-trends-modal.js", "../../js/sport-specific/nhl/events.js", "../../js/sport-specific/pga/open-scorecard-modal.js", "../../js/sport-specific/pga/events.js", "../../js/sport-specific/cbb/open-team-preview-modal.js", "../../js/sport-specific/cbb/events.js", "../../js/sport-specific/cfb/open-team-vs-pos-modal.js", "../../js/sport-specific/cfb/open-team-trends-modal.js", "../../js/sport-specific/cfb/events.js", "../../js/sport-specific/soccer/open-team-trends-modal.js", "../../js/sport-specific/soccer/events.js", "../../js/sport-specific/mlb/open-team-trends-modal.js", "../../js/sport-specific/mlb/events.js", "../../js/sport-specific/wnba/open-team-trends-modal.js", "../../js/sport-specific/wnba/events.js", "../../js/sport-specific/euro/open-team-trends-modal.js", "../../js/sport-specific/euro/events.js", "../../js/rotowire.js"], "sourcesContent": [";(function(factory) {\n 'use strict';\n /* global window: false, define: false, module: false */\n var root = typeof window === 'undefined' ? null : window;\n\n if (typeof define === 'function' && define.amd) {\n define(function(){ return factory(root); });\n } else if (typeof module !== 'undefined') {\n module.exports = factory(root);\n } else {\n root.DOMPurify = factory(root);\n }\n}(function factory(window) {\n 'use strict';\n\n var DOMPurify = function(window) {\n return factory(window);\n };\n\n /**\n * Version label, exposed for easier checks\n * if DOMPurify is up to date or not\n */\n DOMPurify.version = '0.8.9';\n\n /**\n * Array of elements that DOMPurify removed during sanitation.\n * Empty if nothing was removed.\n */\n DOMPurify.removed = [];\n\n if (!window || !window.document || window.document.nodeType !== 9) {\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\n var document = window.document;\n var originalDocument = document;\n var DocumentFragment = window.DocumentFragment;\n var HTMLTemplateElement = window.HTMLTemplateElement;\n var Node = window.Node;\n var NodeFilter = window.NodeFilter;\n var NamedNodeMap = window.NamedNodeMap || window.MozNamedAttrMap;\n var Text = window.Text;\n var Comment = window.Comment;\n var DOMParser = window.DOMParser;\n var useDOMParser = false; // See comment below\n\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 var template = document.createElement('template');\n if (template.content && template.content.ownerDocument) {\n document = template.content.ownerDocument;\n }\n }\n var implementation = document.implementation;\n var createNodeIterator = document.createNodeIterator;\n var getElementsByTagName = document.getElementsByTagName;\n var createDocumentFragment = document.createDocumentFragment;\n var importNode = originalDocument.importNode;\n\n var hooks = {};\n\n /**\n * Expose whether this browser supports running the full DOMPurify.\n */\n DOMPurify.isSupported =\n typeof implementation.createHTMLDocument !== 'undefined' &&\n document.documentMode !== 9;\n\n /* Add properties to a lookup table */\n var _addToSet = function(set, array) {\n var l = array.length;\n while (l--) {\n if (typeof array[l] === 'string') {\n array[l] = array[l].toLowerCase();\n }\n set[array[l]] = true;\n }\n return set;\n };\n\n /* Shallow clone an object */\n var _cloneObj = function(object) {\n var newObject = {};\n var property;\n for (property in object) {\n if (object.hasOwnProperty(property)) {\n newObject[property] = object[property];\n }\n }\n return newObject;\n };\n\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\n /* allowed element names */\n var ALLOWED_TAGS = null;\n var DEFAULT_ALLOWED_TAGS = _addToSet({}, [\n\n // HTML\n 'a','abbr','acronym','address','area','article','aside','audio','b',\n 'bdi','bdo','big','blink','blockquote','body','br','button','canvas',\n 'caption','center','cite','code','col','colgroup','content','data',\n 'datalist','dd','decorator','del','details','dfn','dir','div','dl','dt',\n 'element','em','fieldset','figcaption','figure','font','footer','form',\n 'h1','h2','h3','h4','h5','h6','head','header','hgroup','hr','html','i',\n 'img','input','ins','kbd','label','legend','li','main','map','mark',\n 'marquee','menu','menuitem','meter','nav','nobr','ol','optgroup',\n 'option','output','p','pre','progress','q','rp','rt','ruby','s','samp',\n 'section','select','shadow','small','source','spacer','span','strike',\n 'strong','style','sub','summary','sup','table','tbody','td','template',\n 'textarea','tfoot','th','thead','time','tr','track','tt','u','ul','var',\n 'video','wbr',\n\n // SVG\n 'svg','altglyph','altglyphdef','altglyphitem','animatecolor',\n 'animatemotion','animatetransform','circle','clippath','defs','desc',\n 'ellipse','filter','font','g','glyph','glyphref','hkern','image','line',\n 'lineargradient','marker','mask','metadata','mpath','path','pattern',\n 'polygon','polyline','radialgradient','rect','stop','switch','symbol',\n 'text','textpath','title','tref','tspan','view','vkern',\n\n // SVG Filters\n 'feBlend','feColorMatrix','feComponentTransfer','feComposite',\n 'feConvolveMatrix','feDiffuseLighting','feDisplacementMap',\n 'feFlood','feFuncA','feFuncB','feFuncG','feFuncR','feGaussianBlur',\n 'feMerge','feMergeNode','feMorphology','feOffset',\n 'feSpecularLighting','feTile','feTurbulence',\n\n //MathML\n 'math','menclose','merror','mfenced','mfrac','mglyph','mi','mlabeledtr',\n 'mmuliscripts','mn','mo','mover','mpadded','mphantom','mroot','mrow',\n 'ms','mpspace','msqrt','mystyle','msub','msup','msubsup','mtable','mtd',\n 'mtext','mtr','munder','munderover',\n\n //Text\n '#text'\n ]);\n\n /* Allowed attribute names */\n var ALLOWED_ATTR = null;\n var DEFAULT_ALLOWED_ATTR = _addToSet({}, [\n\n // HTML\n 'accept','action','align','alt','autocomplete','background','bgcolor',\n 'border','cellpadding','cellspacing','checked','cite','class','clear','color',\n 'cols','colspan','coords','datetime','default','dir','disabled',\n 'download','enctype','face','for','headers','height','hidden','high','href',\n 'hreflang','id','ismap','label','lang','list','loop', 'low','max',\n 'maxlength','media','method','min','multiple','name','noshade','novalidate',\n 'nowrap','open','optimum','pattern','placeholder','poster','preload','pubdate',\n 'radiogroup','readonly','rel','required','rev','reversed','role','rows',\n 'rowspan','spellcheck','scope','selected','shape','size','span',\n 'srclang','start','src','step','style','summary','tabindex','title',\n 'type','usemap','valign','value','width','xmlns',\n\n // SVG\n 'accent-height','accumulate','additivive','alignment-baseline',\n 'ascent','attributename','attributetype','azimuth','basefrequency',\n 'baseline-shift','begin','bias','by','clip','clip-path','clip-rule',\n 'color','color-interpolation','color-interpolation-filters','color-profile',\n 'color-rendering','cx','cy','d','dx','dy','diffuseconstant','direction',\n 'display','divisor','dur','edgemode','elevation','end','fill','fill-opacity',\n 'fill-rule','filter','flood-color','flood-opacity','font-family','font-size',\n 'font-size-adjust','font-stretch','font-style','font-variant','font-weight',\n 'fx', 'fy','g1','g2','glyph-name','glyphref','gradientunits','gradienttransform',\n 'image-rendering','in','in2','k','k1','k2','k3','k4','kerning','keypoints',\n 'keysplines','keytimes','lengthadjust','letter-spacing','kernelmatrix',\n 'kernelunitlength','lighting-color','local','marker-end','marker-mid',\n 'marker-start','markerheight','markerunits','markerwidth','maskcontentunits',\n 'maskunits','max','mask','mode','min','numoctaves','offset','operator',\n 'opacity','order','orient','orientation','origin','overflow','paint-order',\n 'path','pathlength','patterncontentunits','patterntransform','patternunits',\n 'points','preservealpha','r','rx','ry','radius','refx','refy','repeatcount',\n 'repeatdur','restart','result','rotate','scale','seed','shape-rendering',\n 'specularconstant','specularexponent','spreadmethod','stddeviation','stitchtiles',\n 'stop-color','stop-opacity','stroke-dasharray','stroke-dashoffset','stroke-linecap',\n 'stroke-linejoin','stroke-miterlimit','stroke-opacity','stroke','stroke-width',\n 'surfacescale','targetx','targety','transform','text-anchor','text-decoration',\n 'text-rendering','textlength','u1','u2','unicode','values','viewbox',\n 'visibility','vert-adv-y','vert-origin-x','vert-origin-y','word-spacing',\n 'wrap','writing-mode','xchannelselector','ychannelselector','x','x1','x2',\n 'y','y1','y2','z','zoomandpan',\n\n // MathML\n 'accent','accentunder','bevelled','close','columnsalign','columnlines',\n 'columnspan','denomalign','depth','display','displaystyle','fence',\n 'frame','largeop','length','linethickness','lspace','lquote',\n 'mathbackground','mathcolor','mathsize','mathvariant','maxsize',\n 'minsize','movablelimits','notation','numalign','open','rowalign',\n 'rowlines','rowspacing','rowspan','rspace','rquote','scriptlevel',\n 'scriptminsize','scriptsizemultiplier','selection','separator',\n 'separators','stretchy','subscriptshift','supscriptshift','symmetric',\n 'voffset',\n\n // XML\n 'xlink:href','xml:id','xlink:title','xml:space','xmlns:xlink'\n ]);\n\n /* Explicitly forbidden tags (overrides ALLOWED_TAGS/ADD_TAGS) */\n var FORBID_TAGS = null;\n\n /* Explicitly forbidden attributes (overrides ALLOWED_ATTR/ADD_ATTR) */\n var FORBID_ATTR = null;\n\n /* Decide if ARIA attributes are okay */\n var ALLOW_ARIA_ATTR = true;\n\n /* Decide if custom data attributes are okay */\n var ALLOW_DATA_ATTR = true;\n\n /* Decide if unknown protocols are okay */\n var ALLOW_UNKNOWN_PROTOCOLS = false;\n\n /* Output should be safe for jQuery's $() factory? */\n var SAFE_FOR_JQUERY = false;\n\n /* Output should be safe for common template engines.\n * This means, DOMPurify removes data attributes, mustaches and ERB\n */\n var SAFE_FOR_TEMPLATES = false;\n\n /* Specify template detection regex for SAFE_FOR_TEMPLATES mode */\n var MUSTACHE_EXPR = /\\{\\{[\\s\\S]*|[\\s\\S]*\\}\\}/gm;\n var ERB_EXPR = /<%[\\s\\S]*|[\\s\\S]*%>/gm;\n\n /* Decide if document with ... should be returned */\n var WHOLE_DOCUMENT = false;\n\n /* Track whether config is already set on this instance of DOMPurify. */\n var SET_CONFIG = false;\n\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 var FORCE_BODY = false;\n\n /* Decide if a DOM `HTMLBodyElement` should be returned, instead of a html string.\n * If `WHOLE_DOCUMENT` is enabled a `HTMLHtmlElement` will be returned instead\n */\n var RETURN_DOM = false;\n\n /* Decide if a DOM `DocumentFragment` should be returned, instead of a html string */\n var RETURN_DOM_FRAGMENT = false;\n\n /* If `RETURN_DOM` or `RETURN_DOM_FRAGMENT` is enabled, decide if the returned DOM\n * `Node` is imported into the current `Document`. If this flag is not enabled the\n * `Node` will belong (its ownerDocument) to a fresh `HTMLDocument`, created by\n * DOMPurify. */\n var RETURN_DOM_IMPORT = false;\n\n /* Output should be free from DOM clobbering attacks? */\n var SANITIZE_DOM = true;\n\n /* Keep element content when removing element? */\n var KEEP_CONTENT = true;\n\n /* Tags to ignore content of when KEEP_CONTENT is true */\n var FORBID_CONTENTS = _addToSet({}, [\n 'audio', 'head', 'math', 'script', 'style', 'template', 'svg', 'video'\n ]);\n\n /* Tags that are safe for data: URIs */\n var DATA_URI_TAGS = _addToSet({}, [\n 'audio', 'video', 'img', 'source', 'image'\n ]);\n\n /* Attributes safe for values like \"javascript:\" */\n var URI_SAFE_ATTRIBUTES = _addToSet({}, [\n 'alt','class','for','id','label','name','pattern','placeholder',\n 'summary','title','value','style','xmlns'\n ]);\n\n /* Keep a reference to config to pass to hooks */\n var CONFIG = null;\n\n /* Ideally, do not touch anything below this line */\n /* ______________________________________________ */\n\n var formElement = document.createElement('form');\n\n /**\n * _parseConfig\n *\n * @param optional config literal\n */\n var _parseConfig = function(cfg) {\n /* Shield configuration object from tampering */\n if (typeof cfg !== 'object') {\n cfg = {};\n }\n\n /* Set configuration parameters */\n ALLOWED_TAGS = 'ALLOWED_TAGS' in cfg ?\n _addToSet({}, cfg.ALLOWED_TAGS) : DEFAULT_ALLOWED_TAGS;\n ALLOWED_ATTR = 'ALLOWED_ATTR' in cfg ?\n _addToSet({}, cfg.ALLOWED_ATTR) : DEFAULT_ALLOWED_ATTR;\n FORBID_TAGS = 'FORBID_TAGS' in cfg ?\n _addToSet({}, cfg.FORBID_TAGS) : {};\n FORBID_ATTR = 'FORBID_ATTR' in cfg ?\n _addToSet({}, cfg.FORBID_ATTR) : {};\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 SAFE_FOR_JQUERY = cfg.SAFE_FOR_JQUERY || false; // Default false\n SAFE_FOR_TEMPLATES = cfg.SAFE_FOR_TEMPLATES || false; // Default false\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_DOM_IMPORT = cfg.RETURN_DOM_IMPORT || false; // Default false\n FORCE_BODY = cfg.FORCE_BODY || false; // Default false\n SANITIZE_DOM = cfg.SANITIZE_DOM !== false; // Default true\n KEEP_CONTENT = cfg.KEEP_CONTENT !== false; // Default true\n\n if (SAFE_FOR_TEMPLATES) {\n ALLOW_DATA_ATTR = false;\n }\n\n if (RETURN_DOM_FRAGMENT) {\n RETURN_DOM = true;\n }\n\n /* Merge configuration parameters */\n if (cfg.ADD_TAGS) {\n if (ALLOWED_TAGS === DEFAULT_ALLOWED_TAGS) {\n ALLOWED_TAGS = _cloneObj(ALLOWED_TAGS);\n }\n _addToSet(ALLOWED_TAGS, cfg.ADD_TAGS);\n }\n if (cfg.ADD_ATTR) {\n if (ALLOWED_ATTR === DEFAULT_ALLOWED_ATTR) {\n ALLOWED_ATTR = _cloneObj(ALLOWED_ATTR);\n }\n _addToSet(ALLOWED_ATTR, cfg.ADD_ATTR);\n }\n if (cfg.ADD_URI_SAFE_ATTR) {\n _addToSet(URI_SAFE_ATTRIBUTES, cfg.ADD_URI_SAFE_ATTR);\n }\n\n /* Add #text in case KEEP_CONTENT is set to true */\n if (KEEP_CONTENT) { ALLOWED_TAGS['#text'] = true; }\n\n // Prevent further manipulation of configuration.\n // Not available in IE8, Safari 5, etc.\n if (Object && 'freeze' in Object) { Object.freeze(cfg); }\n\n CONFIG = cfg;\n };\n\n /**\n * _forceRemove\n *\n * @param a DOM node\n */\n var _forceRemove = function(node) {\n DOMPurify.removed.push({element: node});\n try {\n node.parentNode.removeChild(node);\n } catch (e) {\n node.outerHTML = '';\n }\n };\n\n /**\n * _removeAttribute\n *\n * @param an Attribute name\n * @param a DOM node\n */\n var _removeAttribute = function(name, node) {\n DOMPurify.removed.push({\n attribute: node.getAttributeNode(name),\n from: node\n });\n node.removeAttribute(name);\n };\n\n /**\n * _initDocument\n *\n * @param a string of dirty markup\n * @return a DOM, filled with the dirty markup\n */\n var _initDocument = function(dirty) {\n /* Create a HTML document */\n var doc, body;\n\n /* Fill body with bogus element */\n if (FORCE_BODY) {\n dirty = '' + dirty;\n }\n\n /* Use DOMParser to workaround Firefox bug (see comment below) */\n if (useDOMParser) {\n try {\n doc = new DOMParser().parseFromString(dirty, 'text/html');\n } catch (e) {}\n }\n\n /* Otherwise use createHTMLDocument, because DOMParser is unsafe in\n Safari (see comment below) */\n if (!doc || !doc.documentElement) {\n doc = implementation.createHTMLDocument('');\n body = doc.body;\n body.parentNode.removeChild(body.parentNode.firstElementChild);\n body.outerHTML = dirty;\n }\n\n /* Work on whole document or just its body */\n return getElementsByTagName.call(doc,\n WHOLE_DOCUMENT ? 'html' : 'body')[0];\n };\n\n // Safari 10.1+ (unfixed as of time of writing) has a catastrophic bug in\n // its implementation of DOMParser such that the following executes the\n // JavaScript:\n //\n // new DOMParser()\n // .parseFromString('', 'text/html');\n //\n // However, Firefox uses a different parser for innerHTML rather than\n // DOMParser (see https://bugzilla.mozilla.org/show_bug.cgi?id=1205631)\n // which means that you *must* use DOMParser, otherwise the output may\n // not be safe if used in a document.write context later.\n //\n // So we feature detect the Firefox bug and use the DOMParser if necessary.\n if (DOMPurify.isSupported) {\n (function () {\n var doc = _initDocument('

');\n if (doc.querySelector('svg img')) {\n useDOMParser = true;\n }\n }());\n }\n\n /**\n * _createIterator\n *\n * @param document/fragment to create iterator for\n * @return iterator instance\n */\n var _createIterator = function(root) {\n return createNodeIterator.call(root.ownerDocument || root,\n root,\n NodeFilter.SHOW_ELEMENT\n | NodeFilter.SHOW_COMMENT\n | NodeFilter.SHOW_TEXT,\n function() { return NodeFilter.FILTER_ACCEPT; },\n false\n );\n };\n\n /**\n * _isClobbered\n *\n * @param element to check for clobbering attacks\n * @return true if clobbered, false if safe\n */\n var _isClobbered = function(elm) {\n if (elm instanceof Text || elm instanceof Comment) {\n return false;\n }\n if ( typeof elm.nodeName !== 'string'\n || typeof elm.textContent !== 'string'\n || typeof elm.removeChild !== 'function'\n || !(elm.attributes instanceof NamedNodeMap)\n || typeof elm.removeAttribute !== 'function'\n || typeof elm.setAttribute !== 'function'\n ) {\n return true;\n }\n return false;\n };\n\n /**\n * _isNode\n *\n * @param object to check whether it's a DOM node\n * @return true is object is a DOM node\n */\n var _isNode = function(obj) {\n return (\n typeof Node === \"object\" ? obj instanceof Node : obj\n && typeof obj === \"object\" && typeof obj.nodeType === \"number\"\n && typeof obj.nodeName===\"string\"\n );\n };\n\n /**\n * _sanitizeElements\n *\n * @protect nodeName\n * @protect textContent\n * @protect removeChild\n *\n * @param node to check for permission to exist\n * @return true if node was killed, false if left alive\n */\n var _sanitizeElements = function(currentNode) {\n var tagName, content;\n\n /* Execute a hook if present */\n _executeHook('beforeSanitizeElements', currentNode, null);\n\n /* Check if element is clobbered or can clobber */\n if (_isClobbered(currentNode)) {\n _forceRemove(currentNode);\n return true;\n }\n\n /* Now let's check the element's type and name */\n tagName = currentNode.nodeName.toLowerCase();\n\n /* Execute a hook if present */\n _executeHook('uponSanitizeElement', currentNode, {\n tagName: tagName,\n allowedTags: ALLOWED_TAGS\n });\n\n /* Remove element if anything forbids its presence */\n if (!ALLOWED_TAGS[tagName] || FORBID_TAGS[tagName]) {\n /* Keep content except for black-listed elements */\n if (KEEP_CONTENT && !FORBID_CONTENTS[tagName]\n && typeof currentNode.insertAdjacentHTML === 'function') {\n try {\n currentNode.insertAdjacentHTML('AfterEnd', currentNode.innerHTML);\n } catch (e) {}\n }\n _forceRemove(currentNode);\n return true;\n }\n\n /* Convert markup to cover jQuery behavior */\n if (SAFE_FOR_JQUERY && !currentNode.firstElementChild &&\n (!currentNode.content || !currentNode.content.firstElementChild) &&\n / tag that has an \"id\"\n // attribute at the time.\n if (lcName === 'name' &&\n currentNode.nodeName === 'IMG' && attributes.id) {\n idAttr = attributes.id;\n attributes = Array.prototype.slice.apply(attributes);\n _removeAttribute('id', currentNode);\n _removeAttribute(name, currentNode);\n if (attributes.indexOf(idAttr) > l) {\n currentNode.setAttribute('id', idAttr.value);\n }\n } else if (\n // This works around a bug in Safari, where input[type=file]\n // cannot be dynamically set after type has been removed\n currentNode.nodeName === 'INPUT' && lcName === 'type' &&\n value === 'file' && (ALLOWED_ATTR[lcName] || !FORBID_ATTR[lcName])) {\n continue;\n } else {\n // This avoids a crash in Safari v9.0 with double-ids.\n // The trick is to first set the id to be empty and then to\n // remove the attribute\n if (name === 'id') {\n currentNode.setAttribute(name, '');\n }\n _removeAttribute(name, currentNode);\n }\n\n /* Did the hooks approve of the attribute? */\n if (!hookEvent.keepAttr) {\n continue;\n }\n\n /* Make sure attribute cannot clobber */\n if (SANITIZE_DOM &&\n (lcName === 'id' || lcName === 'name') &&\n (value in window || value in document || value in formElement)) {\n continue;\n }\n\n /* Sanitize attribute content to be template-safe */\n if (SAFE_FOR_TEMPLATES) {\n value = value.replace(MUSTACHE_EXPR, ' ');\n value = value.replace(ERB_EXPR, ' ');\n }\n\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 && DATA_ATTR.test(lcName)) {\n // This attribute is safe\n }\n else if (ALLOW_ARIA_ATTR && ARIA_ATTR.test(lcName)) {\n // This attribute is safe\n }\n /* Otherwise, check the name is permitted */\n else if (!ALLOWED_ATTR[lcName] || FORBID_ATTR[lcName]) {\n continue;\n }\n /* Check value is safe. First, is attr inert? If so, is safe */\n else if (URI_SAFE_ATTRIBUTES[lcName]) {\n // This attribute is safe\n }\n /* Check no script, data or unknown possibly unsafe URI\n unless we know URI values are safe for that attribute */\n else if (IS_ALLOWED_URI.test(value.replace(ATTR_WHITESPACE,''))) {\n // This attribute is safe\n }\n /* Keep image data URIs alive if src/xlink:href is allowed */\n else if (\n (lcName === 'src' || lcName === 'xlink:href') &&\n value.indexOf('data:') === 0 &&\n DATA_URI_TAGS[currentNode.nodeName.toLowerCase()]) {\n // This attribute is safe\n }\n /* Allow unknown protocols: This provides support for links that\n are handled by protocol handlers which may be unknown ahead of\n time, e.g. fb:, spotify: */\n else if (\n ALLOW_UNKNOWN_PROTOCOLS &&\n !IS_SCRIPT_OR_DATA.test(value.replace(ATTR_WHITESPACE,''))) {\n // This attribute is safe\n }\n /* Check for binary attributes */\n else if (!value) {\n // binary attributes are safe at this point\n }\n /* Anything else, presume unsafe, do not add it back */\n else {\n continue;\n }\n\n /* Handle invalid data-* attribute set by try-catching it */\n try {\n currentNode.setAttribute(name, value);\n DOMPurify.removed.pop();\n } catch (e) {}\n }\n\n /* Execute a hook if present */\n _executeHook('afterSanitizeAttributes', currentNode, null);\n };\n\n /**\n * _sanitizeShadowDOM\n *\n * @param fragment to iterate over recursively\n * @return void\n */\n var _sanitizeShadowDOM = function(fragment) {\n var shadowNode;\n var shadowIterator = _createIterator(fragment);\n\n /* Execute a hook if present */\n _executeHook('beforeSanitizeShadowDOM', fragment, null);\n\n while ( (shadowNode = shadowIterator.nextNode()) ) {\n /* Execute a hook if present */\n _executeHook('uponSanitizeShadowNode', shadowNode, null);\n\n /* Sanitize tags and elements */\n if (_sanitizeElements(shadowNode)) {\n continue;\n }\n\n /* Deep shadow DOM detected */\n if (shadowNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(shadowNode.content);\n }\n\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(shadowNode);\n }\n\n /* Execute a hook if present */\n _executeHook('afterSanitizeShadowDOM', fragment, null);\n };\n\n /**\n * _executeHook\n * Execute user configurable hooks\n *\n * @param {String} entryPoint Name of the hook's entry point\n * @param {Node} currentNode\n */\n var _executeHook = function(entryPoint, currentNode, data) {\n if (!hooks[entryPoint]) { return; }\n\n hooks[entryPoint].forEach(function(hook) {\n hook.call(DOMPurify, currentNode, data, CONFIG);\n });\n };\n\n /**\n * sanitize\n * Public method providing core sanitation functionality\n *\n * @param {String|Node} dirty string or DOM node\n * @param {Object} configuration object\n */\n DOMPurify.sanitize = function(dirty, cfg) {\n var body, importedNode, currentNode, oldNode, nodeIterator, returnNode;\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 if (!dirty) {\n dirty = '';\n }\n\n /* Stringify, in case dirty is an object */\n if (typeof dirty !== 'string' && !_isNode(dirty)) {\n if (typeof dirty.toString !== 'function') {\n throw new TypeError('toString is not a function');\n } else {\n dirty = dirty.toString();\n }\n }\n\n /* Check we can run. Otherwise fall back or ignore */\n if (!DOMPurify.isSupported) {\n if (typeof window.toStaticHTML === 'object'\n || typeof window.toStaticHTML === 'function') {\n if (typeof dirty === 'string') {\n return window.toStaticHTML(dirty);\n } else if (_isNode(dirty)) {\n return window.toStaticHTML(dirty.outerHTML);\n }\n }\n return dirty;\n }\n\n /* Assign config vars */\n if (!SET_CONFIG) {\n _parseConfig(cfg);\n }\n\n /* Clean up removed elements */\n DOMPurify.removed = [];\n\n 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 === 1 && importedNode.nodeName === 'BODY') {\n /* Node is already a body, use as is */\n body = importedNode;\n } else {\n body.appendChild(importedNode);\n }\n } else {\n /* Exit directly if we have nothing to do */\n if (!RETURN_DOM && !WHOLE_DOCUMENT && dirty.indexOf('<') === -1) {\n return dirty;\n }\n\n /* Initialize the document to work on */\n body = _initDocument(dirty);\n\n /* Check we have a DOM node from the data */\n if (!body) {\n return RETURN_DOM ? null : '';\n }\n }\n\n /* Remove first element node (ours) if FORCE_BODY is set */\n if (FORCE_BODY) {\n _forceRemove(body.firstChild);\n }\n\n /* Get node iterator */\n nodeIterator = _createIterator(body);\n\n /* Now start iterating over the created document */\n while ( (currentNode = nodeIterator.nextNode()) ) {\n\n /* Fix IE's strange behavior with manipulated textNodes #89 */\n if (currentNode.nodeType === 3 && currentNode === oldNode) {\n continue;\n }\n\n /* Sanitize tags and elements */\n if (_sanitizeElements(currentNode)) {\n continue;\n }\n\n /* Shadow DOM detected, sanitize it */\n if (currentNode.content instanceof DocumentFragment) {\n _sanitizeShadowDOM(currentNode.content);\n }\n\n /* Check attributes, sanitize if necessary */\n _sanitizeAttributes(currentNode);\n\n oldNode = currentNode;\n }\n\n /* Return sanitized string or DOM */\n if (RETURN_DOM) {\n\n if (RETURN_DOM_FRAGMENT) {\n returnNode = createDocumentFragment.call(body.ownerDocument);\n\n while (body.firstChild) {\n returnNode.appendChild(body.firstChild);\n }\n } else {\n returnNode = body;\n }\n\n if (RETURN_DOM_IMPORT) {\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 returnNode = importNode.call(originalDocument, returnNode, true);\n }\n\n return returnNode;\n }\n\n return WHOLE_DOCUMENT ? body.outerHTML : body.innerHTML;\n };\n\n /**\n * setConfig\n * Public method to set the configuration once\n *\n * @param {Object} configuration object\n * @return void\n */\n DOMPurify.setConfig = function(cfg) {\n _parseConfig(cfg);\n SET_CONFIG = true;\n };\n\n /**\n * clearConfig\n * Public method to remove the configuration\n *\n * @return void\n */\n DOMPurify.clearConfig = function() {\n CONFIG = null;\n SET_CONFIG = false;\n };\n\n /**\n * addHook\n * Public method to add DOMPurify hooks\n *\n * @param {String} entryPoint\n * @param {Function} hookFunction\n */\n DOMPurify.addHook = function(entryPoint, hookFunction) {\n if (typeof hookFunction !== 'function') { return; }\n hooks[entryPoint] = hooks[entryPoint] || [];\n hooks[entryPoint].push(hookFunction);\n };\n\n /**\n * removeHook\n * Public method to remove a DOMPurify hook at a given entryPoint\n * (pops it from the stack of hooks if more are present)\n *\n * @param {String} entryPoint\n * @return void\n */\n DOMPurify.removeHook = function(entryPoint) {\n if (hooks[entryPoint]) {\n hooks[entryPoint].pop();\n }\n };\n\n /**\n * removeHooks\n * Public method to remove all DOMPurify hooks at a given entryPoint\n *\n * @param {String} entryPoint\n * @return void\n */\n DOMPurify.removeHooks = function(entryPoint) {\n if (hooks[entryPoint]) {\n hooks[entryPoint] = [];\n }\n };\n\n /**\n * removeAllHooks\n * Public method to remove all DOMPurify hooks\n *\n * @return void\n */\n DOMPurify.removeAllHooks = function() {\n hooks = {};\n };\n\n return DOMPurify;\n}));\n", "/* eslint-disable */\n/**\n * lodash (Custom Build) \n * Build: `lodash modularize exports=\"npm\" -o ./`\n * Copyright jQuery Foundation and other contributors \n * Released under MIT license \n * Based on Underscore.js 1.8.3 \n * Copyright Jeremy Ashkenas, DocumentCloud and Investigative Reporters & Editors\n */\n\n/** Used as the `TypeError` message for \"Functions\" methods. */\nvar FUNC_ERROR_TEXT = 'Expected a function';\n\n/** Used as references for various `Number` constants. */\nvar NAN = 0 / 0;\n\n/** `Object#toString` result references. */\nvar symbolTag = '[object Symbol]';\n\n/** Used to match leading and trailing whitespace. */\nvar reTrim = /^\\s+|\\s+$/g;\n\n/** Used to detect bad signed hexadecimal string values. */\nvar reIsBadHex = /^[-+]0x[0-9a-f]+$/i;\n\n/** Used to detect binary string values. */\nvar reIsBinary = /^0b[01]+$/i;\n\n/** Used to detect octal string values. */\nvar reIsOctal = /^0o[0-7]+$/i;\n\n/** Built-in method references without a dependency on `root`. */\nvar freeParseInt = parseInt;\n\n/** Detect free variable `global` from Node.js. */\nvar freeGlobal = typeof global == 'object' && global && global.Object === Object && global;\n\n/** Detect free variable `self`. */\nvar freeSelf = typeof self == 'object' && self && self.Object === Object && self;\n\n/** Used as a reference to the global object. */\nvar root = freeGlobal || freeSelf || Function('return this')();\n\n/** Used for built-in method references. */\nvar objectProto = Object.prototype;\n\n/**\n * Used to resolve the\n * [`toStringTag`](http://ecma-international.org/ecma-262/7.0/#sec-object.prototype.tostring)\n * of values.\n */\nvar objectToString = objectProto.toString;\n\n/* Built-in method references for those with the same name as other `lodash` methods. */\nvar nativeMax = Math.max,\n nativeMin = Math.min;\n\n/**\n * Gets the timestamp of the number of milliseconds that have elapsed since\n * the Unix epoch (1 January 1970 00:00:00 UTC).\n *\n * @static\n * @memberOf _\n * @since 2.4.0\n * @category Date\n * @returns {number} Returns the timestamp.\n * @example\n *\n * _.defer(function(stamp) {\n * console.log(_.now() - stamp);\n * }, _.now());\n * // => Logs the number of milliseconds it took for the deferred invocation.\n */\nvar now = function() {\n return root.Date.now();\n};\n\n/**\n * Creates a debounced function that delays invoking `func` until after `wait`\n * milliseconds have elapsed since the last time the debounced function was\n * invoked. The debounced function comes with a `cancel` method to cancel\n * delayed `func` invocations and a `flush` method to immediately invoke them.\n * Provide `options` to indicate whether `func` should be invoked on the\n * leading and/or trailing edge of the `wait` timeout. The `func` is invoked\n * with the last arguments provided to the debounced function. Subsequent\n * calls to the debounced function return the result of the last `func`\n * invocation.\n *\n * **Note:** If `leading` and `trailing` options are `true`, `func` is\n * invoked on the trailing edge of the timeout only if the debounced function\n * is invoked more than once during the `wait` timeout.\n *\n * If `wait` is `0` and `leading` is `false`, `func` invocation is deferred\n * until to the next tick, similar to `setTimeout` with a timeout of `0`.\n *\n * See [David Corbacho's article](https://css-tricks.com/debouncing-throttling-explained-examples/)\n * for details over the differences between `_.debounce` and `_.throttle`.\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Function\n * @param {Function} func The function to debounce.\n * @param {number} [wait=0] The number of milliseconds to delay.\n * @param {Object} [options={}] The options object.\n * @param {boolean} [options.leading=false]\n * Specify invoking on the leading edge of the timeout.\n * @param {number} [options.maxWait]\n * The maximum time `func` is allowed to be delayed before it's invoked.\n * @param {boolean} [options.trailing=true]\n * Specify invoking on the trailing edge of the timeout.\n * @returns {Function} Returns the new debounced function.\n * @example\n *\n * // Avoid costly calculations while the window size is in flux.\n * jQuery(window).on('resize', _.debounce(calculateLayout, 150));\n *\n * // Invoke `sendMail` when clicked, debouncing subsequent calls.\n * jQuery(element).on('click', _.debounce(sendMail, 300, {\n * 'leading': true,\n * 'trailing': false\n * }));\n *\n * // Ensure `batchLog` is invoked once after 1 second of debounced calls.\n * var debounced = _.debounce(batchLog, 250, { 'maxWait': 1000 });\n * var source = new EventSource('/stream');\n * jQuery(source).on('message', debounced);\n *\n * // Cancel the trailing debounced invocation.\n * jQuery(window).on('popstate', debounced.cancel);\n */\nfunction debounce(func, wait, options) {\n var lastArgs,\n lastThis,\n maxWait,\n result,\n timerId,\n lastCallTime,\n lastInvokeTime = 0,\n leading = false,\n maxing = false,\n trailing = true;\n\n if (typeof func != 'function') {\n throw new TypeError(FUNC_ERROR_TEXT);\n }\n wait = toNumber(wait) || 0;\n if (isObject(options)) {\n leading = !!options.leading;\n maxing = 'maxWait' in options;\n maxWait = maxing ? nativeMax(toNumber(options.maxWait) || 0, wait) : maxWait;\n trailing = 'trailing' in options ? !!options.trailing : trailing;\n }\n\n function invokeFunc(time) {\n var args = lastArgs,\n thisArg = lastThis;\n\n lastArgs = lastThis = undefined;\n lastInvokeTime = time;\n result = func.apply(thisArg, args);\n return result;\n }\n\n function leadingEdge(time) {\n // Reset any `maxWait` timer.\n lastInvokeTime = time;\n // Start the timer for the trailing edge.\n timerId = setTimeout(timerExpired, wait);\n // Invoke the leading edge.\n return leading ? invokeFunc(time) : result;\n }\n\n function remainingWait(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime,\n result = wait - timeSinceLastCall;\n\n return maxing ? nativeMin(result, maxWait - timeSinceLastInvoke) : result;\n }\n\n function shouldInvoke(time) {\n var timeSinceLastCall = time - lastCallTime,\n timeSinceLastInvoke = time - lastInvokeTime;\n\n // Either this is the first call, activity has stopped and we're at the\n // trailing edge, the system time has gone backwards and we're treating\n // it as the trailing edge, or we've hit the `maxWait` limit.\n return (lastCallTime === undefined || (timeSinceLastCall >= wait) ||\n (timeSinceLastCall < 0) || (maxing && timeSinceLastInvoke >= maxWait));\n }\n\n function timerExpired() {\n var time = now();\n if (shouldInvoke(time)) {\n return trailingEdge(time);\n }\n // Restart the timer.\n timerId = setTimeout(timerExpired, remainingWait(time));\n }\n\n function trailingEdge(time) {\n timerId = undefined;\n\n // Only invoke if we have `lastArgs` which means `func` has been\n // debounced at least once.\n if (trailing && lastArgs) {\n return invokeFunc(time);\n }\n lastArgs = lastThis = undefined;\n return result;\n }\n\n function cancel() {\n if (timerId !== undefined) {\n clearTimeout(timerId);\n }\n lastInvokeTime = 0;\n lastArgs = lastCallTime = lastThis = timerId = undefined;\n }\n\n function flush() {\n return timerId === undefined ? result : trailingEdge(now());\n }\n\n function debounced() {\n var time = now(),\n isInvoking = shouldInvoke(time);\n\n lastArgs = arguments;\n lastThis = this;\n lastCallTime = time;\n\n if (isInvoking) {\n if (timerId === undefined) {\n return leadingEdge(lastCallTime);\n }\n if (maxing) {\n // Handle invocations in a tight loop.\n timerId = setTimeout(timerExpired, wait);\n return invokeFunc(lastCallTime);\n }\n }\n if (timerId === undefined) {\n timerId = setTimeout(timerExpired, wait);\n }\n return result;\n }\n debounced.cancel = cancel;\n debounced.flush = flush;\n return debounced;\n}\n\n/**\n * Checks if `value` is the\n * [language type](http://www.ecma-international.org/ecma-262/7.0/#sec-ecmascript-language-types)\n * of `Object`. (e.g. arrays, functions, objects, regexes, `new Number(0)`, and `new String('')`)\n *\n * @static\n * @memberOf _\n * @since 0.1.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is an object, else `false`.\n * @example\n *\n * _.isObject({});\n * // => true\n *\n * _.isObject([1, 2, 3]);\n * // => true\n *\n * _.isObject(_.noop);\n * // => true\n *\n * _.isObject(null);\n * // => false\n */\nfunction isObject(value) {\n var type = typeof value;\n return !!value && (type == 'object' || type == 'function');\n}\n\n/**\n * Checks if `value` is object-like. A value is object-like if it's not `null`\n * and has a `typeof` result of \"object\".\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is object-like, else `false`.\n * @example\n *\n * _.isObjectLike({});\n * // => true\n *\n * _.isObjectLike([1, 2, 3]);\n * // => true\n *\n * _.isObjectLike(_.noop);\n * // => false\n *\n * _.isObjectLike(null);\n * // => false\n */\nfunction isObjectLike(value) {\n return !!value && typeof value == 'object';\n}\n\n/**\n * Checks if `value` is classified as a `Symbol` primitive or object.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to check.\n * @returns {boolean} Returns `true` if `value` is a symbol, else `false`.\n * @example\n *\n * _.isSymbol(Symbol.iterator);\n * // => true\n *\n * _.isSymbol('abc');\n * // => false\n */\nfunction isSymbol(value) {\n return typeof value == 'symbol' ||\n (isObjectLike(value) && objectToString.call(value) == symbolTag);\n}\n\n/**\n * Converts `value` to a number.\n *\n * @static\n * @memberOf _\n * @since 4.0.0\n * @category Lang\n * @param {*} value The value to process.\n * @returns {number} Returns the number.\n * @example\n *\n * _.toNumber(3.2);\n * // => 3.2\n *\n * _.toNumber(Number.MIN_VALUE);\n * // => 5e-324\n *\n * _.toNumber(Infinity);\n * // => Infinity\n *\n * _.toNumber('3.2');\n * // => 3.2\n */\nfunction toNumber(value) {\n if (typeof value == 'number') {\n return value;\n }\n if (isSymbol(value)) {\n return NAN;\n }\n if (isObject(value)) {\n var other = typeof value.valueOf == 'function' ? value.valueOf() : value;\n value = isObject(other) ? (other + '') : other;\n }\n if (typeof value != 'string') {\n return value === 0 ? value : +value;\n }\n value = value.replace(reTrim, '');\n var isBinary = reIsBinary.test(value);\n return (isBinary || reIsOctal.test(value))\n ? freeParseInt(value.slice(2), isBinary ? 2 : 8)\n : (reIsBadHex.test(value) ? NAN : +value);\n}\n\nmodule.exports = debounce;\n", "/*!\n * JavaScript Cookie v2.2.0\n * https://github.com/js-cookie/js-cookie\n *\n * Copyright 2006, 2015 Klaus Hartl & Fagner Brack\n * Released under the MIT license\n */\n;(function (factory) {\n\tvar registeredInModuleLoader = false;\n\tif (typeof define === 'function' && define.amd) {\n\t\tdefine(factory);\n\t\tregisteredInModuleLoader = true;\n\t}\n\tif (typeof exports === 'object') {\n\t\tmodule.exports = factory();\n\t\tregisteredInModuleLoader = true;\n\t}\n\tif (!registeredInModuleLoader) {\n\t\tvar OldCookies = window.Cookies;\n\t\tvar api = window.Cookies = factory();\n\t\tapi.noConflict = function () {\n\t\t\twindow.Cookies = OldCookies;\n\t\t\treturn api;\n\t\t};\n\t}\n}(function () {\n\tfunction extend () {\n\t\tvar i = 0;\n\t\tvar result = {};\n\t\tfor (; i < arguments.length; i++) {\n\t\t\tvar attributes = arguments[ i ];\n\t\t\tfor (var key in attributes) {\n\t\t\t\tresult[key] = attributes[key];\n\t\t\t}\n\t\t}\n\t\treturn result;\n\t}\n\n\tfunction init (converter) {\n\t\tfunction api (key, value, attributes) {\n\t\t\tvar result;\n\t\t\tif (typeof document === 'undefined') {\n\t\t\t\treturn;\n\t\t\t}\n\n\t\t\t// Write\n\n\t\t\tif (arguments.length > 1) {\n\t\t\t\tattributes = extend({\n\t\t\t\t\tpath: '/'\n\t\t\t\t}, api.defaults, attributes);\n\n\t\t\t\tif (typeof attributes.expires === 'number') {\n\t\t\t\t\tvar expires = new Date();\n\t\t\t\t\texpires.setMilliseconds(expires.getMilliseconds() + attributes.expires * 864e+5);\n\t\t\t\t\tattributes.expires = expires;\n\t\t\t\t}\n\n\t\t\t\t// We're using \"expires\" because \"max-age\" is not supported by IE\n\t\t\t\tattributes.expires = attributes.expires ? attributes.expires.toUTCString() : '';\n\n\t\t\t\ttry {\n\t\t\t\t\tresult = JSON.stringify(value);\n\t\t\t\t\tif (/^[\\{\\[]/.test(result)) {\n\t\t\t\t\t\tvalue = result;\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {}\n\n\t\t\t\tif (!converter.write) {\n\t\t\t\t\tvalue = encodeURIComponent(String(value))\n\t\t\t\t\t\t.replace(/%(23|24|26|2B|3A|3C|3E|3D|2F|3F|40|5B|5D|5E|60|7B|7D|7C)/g, decodeURIComponent);\n\t\t\t\t} else {\n\t\t\t\t\tvalue = converter.write(value, key);\n\t\t\t\t}\n\n\t\t\t\tkey = encodeURIComponent(String(key));\n\t\t\t\tkey = key.replace(/%(23|24|26|2B|5E|60|7C)/g, decodeURIComponent);\n\t\t\t\tkey = key.replace(/[\\(\\)]/g, escape);\n\n\t\t\t\tvar stringifiedAttributes = '';\n\n\t\t\t\tfor (var attributeName in attributes) {\n\t\t\t\t\tif (!attributes[attributeName]) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tstringifiedAttributes += '; ' + attributeName;\n\t\t\t\t\tif (attributes[attributeName] === true) {\n\t\t\t\t\t\tcontinue;\n\t\t\t\t\t}\n\t\t\t\t\tstringifiedAttributes += '=' + attributes[attributeName];\n\t\t\t\t}\n\t\t\t\treturn (document.cookie = key + '=' + value + stringifiedAttributes);\n\t\t\t}\n\n\t\t\t// Read\n\n\t\t\tif (!key) {\n\t\t\t\tresult = {};\n\t\t\t}\n\n\t\t\t// To prevent the for loop in the first place assign an empty array\n\t\t\t// in case there are no cookies at all. Also prevents odd result when\n\t\t\t// calling \"get()\"\n\t\t\tvar cookies = document.cookie ? document.cookie.split('; ') : [];\n\t\t\tvar rdecode = /(%[0-9A-Z]{2})+/g;\n\t\t\tvar i = 0;\n\n\t\t\tfor (; i < cookies.length; i++) {\n\t\t\t\tvar parts = cookies[i].split('=');\n\t\t\t\tvar cookie = parts.slice(1).join('=');\n\n\t\t\t\tif (!this.json && cookie.charAt(0) === '\"') {\n\t\t\t\t\tcookie = cookie.slice(1, -1);\n\t\t\t\t}\n\n\t\t\t\ttry {\n\t\t\t\t\tvar name = parts[0].replace(rdecode, decodeURIComponent);\n\t\t\t\t\tcookie = converter.read ?\n\t\t\t\t\t\tconverter.read(cookie, name) : converter(cookie, name) ||\n\t\t\t\t\t\tcookie.replace(rdecode, decodeURIComponent);\n\n\t\t\t\t\tif (this.json) {\n\t\t\t\t\t\ttry {\n\t\t\t\t\t\t\tcookie = JSON.parse(cookie);\n\t\t\t\t\t\t} catch (e) {}\n\t\t\t\t\t}\n\n\t\t\t\t\tif (key === name) {\n\t\t\t\t\t\tresult = cookie;\n\t\t\t\t\t\tbreak;\n\t\t\t\t\t}\n\n\t\t\t\t\tif (!key) {\n\t\t\t\t\t\tresult[name] = cookie;\n\t\t\t\t\t}\n\t\t\t\t} catch (e) {}\n\t\t\t}\n\n\t\t\treturn result;\n\t\t}\n\n\t\tapi.set = api;\n\t\tapi.get = function (key) {\n\t\t\treturn api.call(api, key);\n\t\t};\n\t\tapi.getJSON = function () {\n\t\t\treturn api.apply({\n\t\t\t\tjson: true\n\t\t\t}, [].slice.call(arguments));\n\t\t};\n\t\tapi.defaults = {};\n\n\t\tapi.remove = function (key, attributes) {\n\t\t\tapi(key, '', extend(attributes, {\n\t\t\t\texpires: -1\n\t\t\t}));\n\t\t};\n\n\t\tapi.withConverter = init;\n\n\t\treturn api;\n\t}\n\n\treturn init(function () {});\n}));\n", "/* eslint-disable */\n/* smoothscroll v0.4.0 - 2018 - Dustan Kasten, Jeremias Menichelli - MIT License */\n(function () {\n 'use strict';\n\n // polyfill\n function polyfill() {\n // aliases\n var w = window;\n var d = document;\n\n // return if scroll behavior is supported and polyfill is not forced\n if (\n 'scrollBehavior' in d.documentElement.style &&\n w.__forceSmoothScrollPolyfill__ !== true\n ) {\n return;\n }\n\n // globals\n var Element = w.HTMLElement || w.Element;\n var SCROLL_TIME = 468;\n\n // object gathering original scroll methods\n var original = {\n scroll: w.scroll || w.scrollTo,\n scrollBy: w.scrollBy,\n elementScroll: Element.prototype.scroll || scrollElement,\n scrollIntoView: Element.prototype.scrollIntoView\n };\n\n // define timing method\n var now =\n w.performance && w.performance.now\n ? w.performance.now.bind(w.performance)\n : Date.now;\n\n /**\n * indicates if a the current browser is made by Microsoft\n * @method isMicrosoftBrowser\n * @param {String} userAgent\n * @returns {Boolean}\n */\n function isMicrosoftBrowser(userAgent) {\n var userAgentPatterns = ['MSIE ', 'Trident/', 'Edge/'];\n\n return new RegExp(userAgentPatterns.join('|')).test(userAgent);\n }\n\n /*\n * IE has rounding bug rounding down clientHeight and clientWidth and\n * rounding up scrollHeight and scrollWidth causing false positives\n * on hasScrollableSpace\n */\n var ROUNDING_TOLERANCE = isMicrosoftBrowser(w.navigator.userAgent) ? 1 : 0;\n\n /**\n * changes scroll position inside an element\n * @method scrollElement\n * @param {Number} x\n * @param {Number} y\n * @returns {undefined}\n */\n function scrollElement(x, y) {\n this.scrollLeft = x;\n this.scrollTop = y;\n }\n\n /**\n * returns result of applying ease math function to a number\n * @method ease\n * @param {Number} k\n * @returns {Number}\n */\n function ease(k) {\n return 0.5 * (1 - Math.cos(Math.PI * k));\n }\n\n /**\n * indicates if a smooth behavior should be applied\n * @method shouldBailOut\n * @param {Number|Object} firstArg\n * @returns {Boolean}\n */\n function shouldBailOut(firstArg) {\n if (\n firstArg === null ||\n typeof firstArg !== 'object' ||\n firstArg.behavior === undefined ||\n firstArg.behavior === 'auto' ||\n firstArg.behavior === 'instant'\n ) {\n // first argument is not an object/null\n // or behavior is auto, instant or undefined\n return true;\n }\n\n if (typeof firstArg === 'object' && firstArg.behavior === 'smooth') {\n // first argument is an object and behavior is smooth\n return false;\n }\n\n // throw error when behavior is not supported\n throw new TypeError(\n 'behavior member of ScrollOptions ' +\n firstArg.behavior +\n ' is not a valid value for enumeration ScrollBehavior.'\n );\n }\n\n /**\n * indicates if an element has scrollable space in the provided axis\n * @method hasScrollableSpace\n * @param {Node} el\n * @param {String} axis\n * @returns {Boolean}\n */\n function hasScrollableSpace(el, axis) {\n if (axis === 'Y') {\n return el.clientHeight + ROUNDING_TOLERANCE < el.scrollHeight;\n }\n\n if (axis === 'X') {\n return el.clientWidth + ROUNDING_TOLERANCE < el.scrollWidth;\n }\n }\n\n /**\n * indicates if an element has a scrollable overflow property in the axis\n * @method canOverflow\n * @param {Node} el\n * @param {String} axis\n * @returns {Boolean}\n */\n function canOverflow(el, axis) {\n var overflowValue = w.getComputedStyle(el, null)['overflow' + axis];\n\n return overflowValue === 'auto' || overflowValue === 'scroll';\n }\n\n /**\n * indicates if an element can be scrolled in either axis\n * @method isScrollable\n * @param {Node} el\n * @param {String} axis\n * @returns {Boolean}\n */\n function isScrollable(el) {\n var isScrollableY = hasScrollableSpace(el, 'Y') && canOverflow(el, 'Y');\n var isScrollableX = hasScrollableSpace(el, 'X') && canOverflow(el, 'X');\n\n return isScrollableY || isScrollableX;\n }\n\n /**\n * finds scrollable parent of an element\n * @method findScrollableParent\n * @param {Node} el\n * @returns {Node} el\n */\n function findScrollableParent(el) {\n var isBody;\n\n do {\n el = el.parentNode;\n\n isBody = el === d.body;\n } while (isBody === false && isScrollable(el) === false);\n\n isBody = null;\n\n return el;\n }\n\n /**\n * self invoked function that, given a context, steps through scrolling\n * @method step\n * @param {Object} context\n * @returns {undefined}\n */\n function step(context) {\n var time = now();\n var value;\n var currentX;\n var currentY;\n var elapsed = (time - context.startTime) / SCROLL_TIME;\n\n // avoid elapsed times higher than one\n elapsed = elapsed > 1 ? 1 : elapsed;\n\n // apply easing to elapsed time\n value = ease(elapsed);\n\n currentX = context.startX + (context.x - context.startX) * value;\n currentY = context.startY + (context.y - context.startY) * value;\n\n context.method.call(context.scrollable, currentX, currentY);\n\n // scroll more if we have not reached our destination\n if (currentX !== context.x || currentY !== context.y) {\n w.requestAnimationFrame(step.bind(w, context));\n }\n }\n\n /**\n * scrolls window or element with a smooth behavior\n * @method smoothScroll\n * @param {Object|Node} el\n * @param {Number} x\n * @param {Number} y\n * @returns {undefined}\n */\n function smoothScroll(el, x, y) {\n var scrollable;\n var startX;\n var startY;\n var method;\n var startTime = now();\n\n // define scroll context\n if (el === d.body) {\n scrollable = w;\n startX = w.scrollX || w.pageXOffset;\n startY = w.scrollY || w.pageYOffset;\n method = original.scroll;\n } else {\n scrollable = el;\n startX = el.scrollLeft;\n startY = el.scrollTop;\n method = scrollElement;\n }\n\n // scroll looping over a frame\n step({\n scrollable: scrollable,\n method: method,\n startTime: startTime,\n startX: startX,\n startY: startY,\n x: x,\n y: y\n });\n }\n\n // ORIGINAL METHODS OVERRIDES\n // w.scroll and w.scrollTo\n w.scroll = w.scrollTo = function() {\n // avoid action when no arguments are passed\n if (arguments[0] === undefined) {\n return;\n }\n\n // avoid smooth behavior if not required\n if (shouldBailOut(arguments[0]) === true) {\n original.scroll.call(\n w,\n arguments[0].left !== undefined\n ? arguments[0].left\n : typeof arguments[0] !== 'object'\n ? arguments[0]\n : w.scrollX || w.pageXOffset,\n // use top prop, second argument if present or fallback to scrollY\n arguments[0].top !== undefined\n ? arguments[0].top\n : arguments[1] !== undefined\n ? arguments[1]\n : w.scrollY || w.pageYOffset\n );\n\n return;\n }\n\n // LET THE SMOOTHNESS BEGIN!\n smoothScroll.call(\n w,\n d.body,\n arguments[0].left !== undefined\n ? ~~arguments[0].left\n : w.scrollX || w.pageXOffset,\n arguments[0].top !== undefined\n ? ~~arguments[0].top\n : w.scrollY || w.pageYOffset\n );\n };\n\n // w.scrollBy\n w.scrollBy = function() {\n // avoid action when no arguments are passed\n if (arguments[0] === undefined) {\n return;\n }\n\n // avoid smooth behavior if not required\n if (shouldBailOut(arguments[0])) {\n original.scrollBy.call(\n w,\n arguments[0].left !== undefined\n ? arguments[0].left\n : typeof arguments[0] !== 'object' ? arguments[0] : 0,\n arguments[0].top !== undefined\n ? arguments[0].top\n : arguments[1] !== undefined ? arguments[1] : 0\n );\n\n return;\n }\n\n // LET THE SMOOTHNESS BEGIN!\n smoothScroll.call(\n w,\n d.body,\n ~~arguments[0].left + (w.scrollX || w.pageXOffset),\n ~~arguments[0].top + (w.scrollY || w.pageYOffset)\n );\n };\n\n // Element.prototype.scroll and Element.prototype.scrollTo\n Element.prototype.scroll = Element.prototype.scrollTo = function() {\n // avoid action when no arguments are passed\n if (arguments[0] === undefined) {\n return;\n }\n\n // avoid smooth behavior if not required\n if (shouldBailOut(arguments[0]) === true) {\n // if one number is passed, throw error to match Firefox implementation\n if (typeof arguments[0] === 'number' && arguments[1] === undefined) {\n throw new SyntaxError('Value could not be converted');\n }\n\n original.elementScroll.call(\n this,\n // use left prop, first number argument or fallback to scrollLeft\n arguments[0].left !== undefined\n ? ~~arguments[0].left\n : typeof arguments[0] !== 'object' ? ~~arguments[0] : this.scrollLeft,\n // use top prop, second argument or fallback to scrollTop\n arguments[0].top !== undefined\n ? ~~arguments[0].top\n : arguments[1] !== undefined ? ~~arguments[1] : this.scrollTop\n );\n\n return;\n }\n\n var left = arguments[0].left;\n var top = arguments[0].top;\n\n // LET THE SMOOTHNESS BEGIN!\n smoothScroll.call(\n this,\n this,\n typeof left === 'undefined' ? this.scrollLeft : ~~left,\n typeof top === 'undefined' ? this.scrollTop : ~~top\n );\n };\n\n // Element.prototype.scrollBy\n Element.prototype.scrollBy = function() {\n // avoid action when no arguments are passed\n if (arguments[0] === undefined) {\n return;\n }\n\n // avoid smooth behavior if not required\n if (shouldBailOut(arguments[0]) === true) {\n original.elementScroll.call(\n this,\n arguments[0].left !== undefined\n ? ~~arguments[0].left + this.scrollLeft\n : ~~arguments[0] + this.scrollLeft,\n arguments[0].top !== undefined\n ? ~~arguments[0].top + this.scrollTop\n : ~~arguments[1] + this.scrollTop\n );\n\n return;\n }\n\n this.scroll({\n left: ~~arguments[0].left + this.scrollLeft,\n top: ~~arguments[0].top + this.scrollTop,\n behavior: arguments[0].behavior\n });\n };\n\n // Element.prototype.scrollIntoView\n Element.prototype.scrollIntoView = function() {\n // avoid smooth behavior if not required\n if (shouldBailOut(arguments[0]) === true) {\n original.scrollIntoView.call(\n this,\n arguments[0] === undefined ? true : arguments[0]\n );\n\n return;\n }\n\n // LET THE SMOOTHNESS BEGIN!\n var scrollableParent = findScrollableParent(this);\n var parentRects = scrollableParent.getBoundingClientRect();\n var clientRects = this.getBoundingClientRect();\n\n if (scrollableParent !== d.body) {\n // reveal element inside parent\n smoothScroll.call(\n this,\n scrollableParent,\n scrollableParent.scrollLeft + clientRects.left - parentRects.left,\n scrollableParent.scrollTop + clientRects.top - parentRects.top\n );\n\n // reveal parent in viewport unless is fixed\n if (w.getComputedStyle(scrollableParent).position !== 'fixed') {\n w.scrollBy({\n left: parentRects.left,\n top: parentRects.top,\n behavior: 'smooth'\n });\n }\n } else {\n // reveal element in viewport\n w.scrollBy({\n left: clientRects.left,\n top: clientRects.top,\n behavior: 'smooth'\n });\n }\n };\n }\n\n if (typeof exports === 'object' && typeof module !== 'undefined') {\n // commonjs\n module.exports = { polyfill: polyfill };\n } else {\n // global\n polyfill();\n }\n\n}());\n", "/*******************************************************************************\nDO IF EXISTS\nTake action on an element if it exists and return the element so it can be chained.\n*******************************************************************************/\n\nexport default function addjQueryPlugin() {\n jQuery.fn.doIfExists = function dIfE(func) {\n if (this.length) { func.apply(this); }\n return this;\n };\n}\n", "/*******************************************************************************\nDO IF NOT EXISTS\nTake action if an element does not exists and return the element so it can be chained.\n*******************************************************************************/\n\nexport default function addjQueryPlugin() {\n jQuery.fn.doIfNotExists = function difNE(func) {\n if (this.length === 0) { func.apply(this); }\n return this;\n };\n}\n", "/*******************************************************************************\nFADE IN FLEXBOX ELEMENT\n*******************************************************************************/\n\nexport default function addjQueryPlugin() {\n $.fn.flexFadeIn = function flexFadeIn(hideClasses, speed, callback) {\n callback = callback || function emptyCallback() {};\n hideClasses = hideClasses || 'hide';\n this.css('opacity', '0').removeClass(hideClasses).animate({ opacity: 1 }, speed || '300');\n callback();\n return this;\n };\n}\n", "/*******************************************************************************\nFADE OUT FLEXBOX ELEMENT\n*******************************************************************************/\n\nexport default function addjQueryPlugin() {\n $.fn.flexFadeOut = function flexFadeOut(hideClasses, speed, callback) {\n callback = callback || function emptyCallback() {};\n hideClasses = hideClasses || 'hide';\n this.animate({ opacity: 0 }, speed || '300', function hide() { $(this).addClass(hideClasses); callback(this); });\n\n return this;\n };\n}\n", "/*******************************************************************************\nOUTPUT SANITIZED HTML\nThis is a custom plugin written to replace jQuery's built-in html() method with something\nthat's more resistant to XSS attacks when user-generated data is added to the page.\n*******************************************************************************/\n\nimport { sanitize } from '../../../lib/_dompurify/purify';\n\nexport default function addPluginSafeHTML() {\n\n // Sanitize the HTML string before sending it through jQuery's .html() method\n jQuery.fn.safehtml = function safeHTML(htmlString) {\n const safeHTMLString = sanitize(htmlString, { SAFE_FOR_JQUERY: true });\n $(this).html(safeHTMLString);\n return this;\n };\n}\n", "/*******************************************************************************\nADD ALL jQUERY PLUGINS\nLoad all the jQuery plugins.\n*******************************************************************************/\n\nimport doIfExists from './do-if-exists';\nimport doIfNotExists from './do-if-not-exists';\nimport flexFadeIn from './flex-fade-in';\nimport flexFadeOut from './flex-fade-out';\nimport safeHTML from './safe-html';\n\nexport default function addAlljQueryPlugins() {\n doIfExists();\n doIfNotExists();\n flexFadeIn();\n flexFadeOut();\n safeHTML();\n}\n", "/*******************************************************************************\nAdd the Hover Class To An Element\nAdds the hover class to an element. Prevents touch events from triggering the hover state.\n*******************************************************************************/\n\nlet touchDetected = false;\n\nexport default function addHoverClass(e) {\n\n // 'touchstart' comes through before 'mousenter', but both will fire on IOS\n // If 'touchstart' is fired, we can set the global touchDetected variable to true\n // That way we know when to avoid trigging the hover state (which is sticky on IOS)\n if (e.type === 'touchstart') { touchDetected = true; }\n\n // As long as a touch was not detected, add the 'hovering' class which creates the hover state\n if (!touchDetected) { $(this).addClass('hovering'); }\n\n // Reset the global touchDetected variable to false so it's ready for the next time\n if (e.type === 'mouseenter') { touchDetected = false; }\n}\n", "/*******************************************************\nCLEAR SEARCH\nClears the search box and results.\n********************************************************/\n\nexport default function clearSearch() {\n\n // Clear the input, clear the last search, and remove the clear button\n $(\"input[name='playersearch']\")\n .val('')\n .data('lastsearch', '')\n .siblings('#player-search-clear').remove(); // eslint-disable-line newline-per-chained-call\n\n // Remove the search results\n $('#player-search-results').remove();\n}\n", "/*******************************************************\r\nPLAYER SEARCH EVENT HANDLERS\r\nThis handles events related to the player search boxes.\r\n********************************************************/\r\n\r\nimport addHoverClass from '../universal/hover/add-class';\r\nimport clearSearch from './clear';\r\nimport debounce from '../universal/debounce/debounce';\r\nimport handleKeyboardNavigation from './handle-keyboard-nav';\r\nimport removeHoverClass from '../universal/hover/remove-class';\r\nimport showMobileSearchBox from './show-mobile-search-box';\r\n//import showTopNavSearch from './show-top-nav-search';\r\nimport triggerSearchPlayers from './trigger-search';\r\n\r\nexport default function addPlayerSearchEventHandlers() {\r\n\r\n // Show the search box on small devices when the search icon button is tapped\r\n $(document).on('click', '.top-nav-section__search-icon', showMobileSearchBox);\r\n\r\n // Show the search input box in the top navigation when the button is clicked\r\n //$(document).on('click', '.t-nav__search-button', showTopNavSearch);\r\n\r\n // Watch for typing inside the gamer search box\r\n $(document).on('input', \"input[name='playersearch']\", debounce(triggerSearchPlayers, 300));\r\n\r\n // Watch for keyboard navigation events inside the gamer search box\r\n $(document).on('keyup', \"input[name='playersearch']\", handleKeyboardNavigation);\r\n\r\n // Clear player search box and results\r\n $(document).on('click', '#player-search-clear', clearSearch);\r\n\r\n // Control when hover effects are used on search results\r\n $(document).on('touchstart mouseenter', '.search-result', addHoverClass);\r\n $(document).on('mouseleave', '.search-result', removeHoverClass);\r\n\r\n}\r\n", "/*******************************************************\nHANDLE KEYBOARD NAVIGATION\nHandle navigating search results via keyboard and triggering actual search.\n********************************************************/\n\nimport clearSearch from './clear';\n\nexport default function handleKeyboardNavigation(e) {\n\n // Exit out if any key other than enter, esc, up or down is pressed\n if (![13, 27, 38, 40].includes(e.which)) { return; }\n\n // Get the search data\n const $input = $(e.currentTarget);\n const searchTerm = $input.val() || '';\n const sport = $input.data('sport') || '';\n\n // Check for various keyboard actions\n const keyPressed = {\n enter: (e.which === 13),\n esc : (e.which === 27),\n down : (e.which === 40),\n up : (e.which === 38),\n };\n\n // If the input is empty or the ESC key is pressed,\n // then reset everything to its initial state and exit out\n if (!searchTerm || keyPressed.esc) { clearSearch(); return; }\n\n const activeClass = 'is-active';\n const $results = $('.search-result');\n const $current = $(`.search-result.${activeClass}`);\n const aResultExists = ($results.length > 0);\n const aResultIsSelected = ($current.length > 0);\n let $next;\n\n // If the enter key is pressed while a search result is selected, go to the selected player\n // If the entry key is pressed while a search result is not selected, go the search page\n if (keyPressed.enter) {\n if(aResultIsSelected){\n window.location.href = $current.find('a').attr('href');\n return;\n } else{\n\n // The link to the search page should awlays include the current search term\n let searchPage = '/search.php?term=' + String(searchTerm).toLowerCase().replace(/[\\u2018\\u2019]/g, \"'\").replace(/[\\u201C\\u201D]/g, '\"');\n\n // Add the sport if one exists\n searchPage += ('&sport=' + sport);\n\n window.location.href = searchPage;\n return;\n }\n }\n\n // If the key pressed is up/down and a result exists\n if( (keyPressed.down || keyPressed.up) && aResultExists){\n\n // If the down key is pressed, go to the next result in the list. If we're already at the end, move to the start.\n if (keyPressed.down) {\n $next = (aResultIsSelected && $current.next().length) ? $current.next() : $results.first();\n }\n\n // If the up key is pressed, go to the previous result in the list. If we're already at the beginning, move to the end.\n if (keyPressed.up) {\n $next = (aResultIsSelected && $current.prev().length) ? $current.prev() : $results.last();\n }\n\n // Remove the active class from the current element and add to the next one\n if ($current) { $current.removeClass(activeClass); }\n $next.addClass(activeClass);\n\n // Scroll to the active search result\n const $resultsContainer = $('#player-search-results');\n $resultsContainer.animate({\n scrollTop: $next.position().top + $resultsContainer.scrollTop(),\n }, 50);\n\n }\n\n}\n", "/*******************************************************************************\nRemove Hover Class From An Element\nRemoves the 'hovering' class from an element.\n*******************************************************************************/\n\nexport default function removeHoverClass() {\n $(this).removeClass('hovering');\n}\n", "/*******************************************************\r\nShow Search Box on Devices with Small Screens\r\nShows the hidden search box on small devices when the search icon button is tapped.\r\n********************************************************/\r\n\r\nexport default function showMobileSearchBox(e) {\r\n\r\n // Hide the search icon button\r\n $(e.currentTarget).remove();\r\n\r\n // Show the expanded search box and focus the cursor inside\r\n $('.top-nav-section__search').addClass('is-visible-mobile').find('input').focus();\r\n\r\n // Add this class to the section bar so we can switch from flex row to column\r\n $('.section-bar').addClass('search-is-visible');\r\n}\r\n", "/*******************************************************\nBUILD SEARCH RESULT\nBuilds the HTML for a player search resultsHTML.\n********************************************************/\n\nexport default function buildSearchResult(sport,playerObject) {\n const { link, logo, alt, name, span, text } = playerObject;\n\n // If viewing all sports, the default logo should be at least an empty div. Othwerise it can be empty\n const logoDefault = (sport == 'All') ? '

' : '';\n const logoHTML = logo ? `` : logoDefault;\n\n // Specific handler for cases where the text is not set and thus we should not have any left-margins\n const spanStyle = text ? '' : 'style=\"padding-left:0px;\"';\n\n return `\n
  • \n \n ` + logoHTML + `\n
    \n
    ${name}
    \n
    ${text}${span}
    \n
    \n
    \n
  • `;\n}\n", "/*******************************************************************************\nREMOVE ERROR NOTIFICATION\nRemoves any error notifications from the screen.\n*******************************************************************************/\n\nexport default function removeErrorNotification() {\n\n const $notification = $('.error-notification-bar');\n\n // Handle notifications in the daily section differently than the typical notification\n if ($notification.hasClass('daily-error') || $notification.hasClass('daily-success')) {\n\n // Hide notification bar\n $('.notification-bar.full-width').addClass('hide');\n\n // Hide and reset error and success message\n $notification.find('.daily-error').addClass('hide').text();\n $notification.find('.daily-success').addClass('hide').text();\n }\n\n\n // All other notification bars\n else {\n\n // Remove notification bar element\n $notification.remove();\n }\n}\n", "/*******************************************************************************\nSHOW ERROR NOTIFICATION\nShow an error notification at the bottom of the screen.\n*******************************************************************************/\n\nimport removeErrorNotificationBar from './remove-error-notification-bar';\n\nexport default function showErrorNotification(message, duration = 'forever') {\n\n // Remove any existing error bars (just in case they trigger multiple errors quickly)\n removeErrorNotificationBar();\n\n // Build the error message html\n const errorHTML = `
    ${message}
    `;\n\n // Show an error message at the bottom of the screen\n $('body').append(errorHTML);\n\n // Remove the error bar from the page after a set amount of time\n // Unless the duration is set to 'forever'\n if (duration !== 'forever') { setTimeout(() => { removeErrorNotificationBar(); }, duration); }\n}\n", "/*******************************************************\nSEARCH FOR PLAYERS\nSearches for players and returns the results.\n********************************************************/\n\nimport showErrorNotificationBar from '../universal/error-handling/show-error-notification-bar';\n\nexport default async function searchPlayers(settings) {\n try {\n const response = await $.ajax({\n type : 'GET',\n url : '/frontend/ajax/search-players.php',\n data : settings,\n timeout: 8000,\n });\n\n // Check for errors with the data\n if (response.error || !response.success) { throw new Error(response.error); }\n\n // Return the data\n return {\n players: response.players,\n };\n }\n catch (error) {\n showErrorNotificationBar(error.message || 'We were unable to search for players. Please try again.', 3000);\n }\n}\n", "/*******************************************************\nWATCH PLAYER SEARCH INPUT\nHandle keyboard events with the player search input.\n********************************************************/\n\nimport buildSearchResult from './build-search-result';\nimport searchPlayers from './search';\n\nexport default async function triggerSearchPlayers(e) {\n\n // Searchable sports\n const searchableSports = ['All','MLB','NFL','NBA','EUR','NHL','PGA','RAC','CFB','CBB','SOC','MMA','DAY','MYROTOWIRE','CFL','WNB','TEN', 'XFL', 'ESP', 'CRI', 'KBO', 'CPB', 'AFL', 'NPB', 'USF', 'F1'];\n\n // Get the input\n const $input = $(e.currentTarget);\n\n // Get the search class from the input\n const searchClass = $input.data('search');\n\n // Get the container element\n const $searchSection = $('.'+searchClass);\n\n // Get the sport from the input\n let sport = $input.data('sport') || '';\n\n // If the sport is not searchable simply return\n if( $.inArray(sport,searchableSports) === -1 ){ return; }\n\n // Cast the special DAY and MYROTOWIRE cases to All\n if(sport === \"DAY\" || sport === \"MYROTOWIRE\"){ sport = \"All\"; }\n\n // Get the search term and convert to lowercase (to improve probability of using Redis cache) and remove any curly quotes (common problem with iPhones)\n const searchTerm = String($input.val() || '').toLowerCase().replace(/[\\u2018\\u2019]/g, \"'\").replace(/[\\u201C\\u201D]/g, '\"');\n\n // Store the last search\n const lastSearch = $input.data('lastsearch') || '';\n\n // If the last search is the same as the current search, don't run it again\n if (searchTerm === lastSearch || !searchTerm) { return; }\n\n // Add the clear button to the search box if it doesn't already exist\n const $clearButton = $('
    ', { \n class: searchClass ? searchClass + '-clear' : '',\n id : 'player-search-clear',\n }).html('×');\n if ($('#player-search-clear').length === 0) { $searchSection.append($clearButton); }\n\n // Add the container for the search results if it doesn't already exist\n let $searchResults = $('