From 420f19ef474c11e2fa55dc8302e67c823e3a9ffb Mon Sep 17 00:00:00 2001 From: Kevin Fitzgerald Date: Thu, 11 Nov 2021 14:45:25 -0600 Subject: [PATCH] Added option to disable CSS injection entirely - Placement.js: Added `no_css` option to disable template css injection - examples/dfp*.html: Added `beforeLoad` optional hook for executing or injecting custom templates before loading placements (v3.2.0) - package.json: Bumped to 1.20.0 --- dist/okanjo-bundle.js | 20 +++++++++++++++----- dist/okanjo-bundle.min.js | 12 ++++++------ dist/okanjo-bundle.min.js.map | 2 +- dist/okanjo-metrics.js | 4 ++-- dist/okanjo-metrics.min.js | 4 ++-- dist/okanjo-metrics.min.js.map | 2 +- dist/okanjo-templates.js | 2 +- dist/okanjo-templates.min.js | 4 ++-- dist/okanjo-templates.min.js.map | 2 +- dist/okanjo.js | 18 ++++++++++++++---- dist/okanjo.min.js | 8 ++++---- dist/okanjo.min.js.map | 2 +- examples/dfp.html | 10 +++++++++- examples/dfp.min.html | 9 ++++++--- package.json | 2 +- src/Placement.js | 14 ++++++++++++-- 16 files changed, 78 insertions(+), 37 deletions(-) diff --git a/dist/okanjo-bundle.js b/dist/okanjo-bundle.js index 25f2ee5..c43c0ca 100644 --- a/dist/okanjo-bundle.js +++ b/dist/okanjo-bundle.js @@ -1,4 +1,4 @@ -/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ (function(root, factory) { if (typeof define === 'function' && define.amd) { define([], factory); @@ -323,7 +323,7 @@ var okanjo = function (window, document) { /** * Okanjo version */ - version: "1.19.1", + version: "1.20.0", /** * Placeholder @@ -3207,6 +3207,7 @@ var okanjo = function (window, document) { // Functional settings key: string().strip(), // don't need to resend key on all our requests no_init: bool().strip(), // don't automatically load the placement, do it manually (e.g. (new Placement({no_init:true})).init() + no_css: bool().strip(), // don't automatically include stylesheets proxy_url: string().strip(), expandable: bool().strip().default(true), disable_inline_buy: bool().strip().default(false), // stops inline buy functionality @@ -3793,8 +3794,12 @@ var okanjo = function (window, document) { offer._index = index; }); + var model = { + css: !this.config.no_css + }; + // Render and display the results - this.setMarkup(okanjo.ui.engine.render(templateName, this)); + this.setMarkup(okanjo.ui.engine.render(templateName, this, model)); // Track widget impression if (data.results.length === 0) { @@ -3995,8 +4000,12 @@ var okanjo = function (window, document) { article._index = index; }); + var model = { + css: !this.config.no_css + }; + // Render and display the results - this.setMarkup(okanjo.ui.engine.render(templateName, this)); + this.setMarkup(okanjo.ui.engine.render(templateName, this, model)); // Track widget impression if (data.results.length === 0) { @@ -4129,6 +4138,7 @@ var okanjo = function (window, document) { // Pass along what the template needs to know to display the ad var renderContext = { + css: !this.config.no_css, size: size, adUnitPath: adUnitPath }; @@ -5082,7 +5092,7 @@ var okanjo = function (window, document) { return okanjo; })); -/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ (function(okanjo) {(function (window) { var okanjo = window.okanjo; diff --git a/dist/okanjo-bundle.min.js b/dist/okanjo-bundle.min.js index b04169b..4d515e3 100644 --- a/dist/okanjo-bundle.min.js +++ b/dist/okanjo-bundle.min.js @@ -1,11 +1,11 @@ -/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ -/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ -!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.okanjo=t()}(this,function(){function e(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function t(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var n=function(){function e(e,t){for(var o=0;o0?1:-1)*Math.floor(Math.abs(t)):t},n=Math.pow(2,53)-1,i=function(e){var t=o(e);return Math.min(Math.max(t,0),n)};return function(e){var o=this,n=Object(e);if(null==e)throw new TypeError("Array.from requires an array-like object - not null or undefined");var a,r=arguments.length>1?arguments[1]:void 0;if("undefined"!=typeof r){if(!t(r))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(a=arguments[2])}for(var s,c=i(n.length),l=t(o)?Object(new o(c)):new Array(c),u=0;u>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var n=arguments[1],i=0;i>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var n=arguments[1],i=0;i>>0;if(0===i)return!1;for(var a=0|t,r=Math.max(a>=0?a:i-Math.abs(a),0);r=0&&t.splice(a,1)}l.error("[Okanjo v"+d.version+"]: "+n.stack),t.length&&l.error.apply(l,["Additional information:"].concat(t))},warn:function(e){for(var t=arguments.length,o=Array(t>1?t-1:0),n=1;n1&&void 0!==arguments[1]?arguments[1]:{},o={};return void 0!==e&&null!==e&&Object.keys(e).forEach(function(n){if(e[n]instanceof Date)t.dateToIso?o[n]=e[n].toISOString():o[n]=e[n];else if("object"===i(e[n])&&null!==e[n])if(Array.isArray(e[n])&&t.ignoreArrays===!0)o[n]=e[n];else if(Array.isArray(e[n])&&t.arrayToCsv===!0)o[n]=e[n].join(",");else{var a=d.util.flatten(e[n],t);Object.keys(a).forEach(function(e){o[n+"_"+e]=a[e]})}else o[n]=e[n]}),o},d.util.shortid=function(t){var o="ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC",n=e.crypto||e.msCrypto||"function"==typeof require&&require("crypto"),i=function(){if(n&&n.randomBytes)return 48&n.randomBytes(1)[0];if(!n||!n.getRandomValues)return 48&Math.floor(256*Math.random());var e=new Uint8Array(1);return n.getRandomValues(e),48&e[0]},a=function(e){for(var t=0,n=void 0,a="";!n;)a+=o[e>>4*t&15|i()],n=e0&&(e+=a(c)),e+=a(o)}}(),d.util.getLocation=function(){return e.location!==e.parent.location?t.referrer:t.location.href},d.ui={getScrollPosition:function(){return{x:o?e.pageXOffset:n?t.documentElement.scrollLeft:t.body.scrollLeft,y:o?e.pageYOffset:n?t.documentElement.scrollTop:t.body.scrollTop}},getElementSize:function(t,o){var n={height:t.offsetHeight,width:t.offsetWidth},i=t.currentStyle||e.getComputedStyle(t);return o&&(n.height+=parseInt(i.marginTop)+parseInt(i.marginBottom),n.width+=parseInt(i.marginLeft)+parseInt(i.marginRight)),n},getPageSize:function(){var e=t.querySelector("body"),o=t.documentElement;return{w:Math.max(e.scrollWidth,e.offsetWidth,o.clientWidth,o.scrollWidth,o.offsetWidth),h:Math.max(e.scrollHeight,e.offsetHeight,o.clientHeight,o.scrollHeight,o.offsetHeight)}},getViewportSize:function(){var o=n?t.documentElement:t.body,i=o.clientWidth,a=o.clientHeight,r=e.innerWidth||0,s=e.innerHeight||0,c=r&&i>r||s&&a>s;return{vw:c?r:i,vh:c?s:a}},getEventPosition:function(e){var o=e.pageX,n=e.pageY,i=t.body,a=t.documentElement,r="scrollLeft",s="scrollTop",c=e.__proto__.constructor.name;return{et:c,ex:void 0===o?e.clientX+i[r]+a[r]:o,ey:void 0===n?e.clientY+i[s]+a[s]:n}},getElementPosition:function(e){var o="Could not get position of element. Did you attach the element to the DOM before initializing?";try{var n=e.getBoundingClientRect(),i=t.body.getBoundingClientRect();return t.body.contains(e)||d.report(o,e),{x1:n.left-i.left,y1:n.top-i.top,x2:n.right-i.left,y2:n.bottom-i.top}}catch(a){return d.report(o,{exception:a,element:e}),{x1:0,y1:0,x2:0,y2:0,err:1}}},_getIntersection:function(e,t,o){var n=Math.max(e.x1,t.x),i=Math.min(e.x2,t.x+o.vw),a=Math.max(e.y1,t.y),r=Math.min(e.y2,t.y+o.vh),s=Math.max(0,i-n)*Math.max(0,r-a),c=(e.x2-e.x1)*(e.y2-e.y1);return{intersectionArea:s,elementArea:c}},isElementVisible:function(e){return e.offsetWidth>0&&e.offsetHeight>0},getPercentageInViewport:function(e){var t=d.ui.getElementPosition(e),o=d.ui.getScrollPosition(),n=d.ui.getViewportSize();if(t.err)return 0;var i=d.ui._getIntersection(t,o,n),a=i.intersectionArea,r=i.elementArea;return r<=0?0:a/r}},d.ui.ellipsify=function(e,o){for(var n=o||e.parentNode,i=d.ui.getElementSize(n).height,a=void 0!==e.textContent,s=a?e.textContent:e.innerText,c="",l=5e3,u=function(e){return c=e.substr(0,e.length-3)+c,"..."};d.ui.getElementSize(e).height>i&&s.length>0&&l-- >0;)s=a?e.textContent:e.innerText,s=s.replace(r,u),a?e.textContent=s:e.innerText=s;if(c.length>0){var p=t.createElement("span"),h=t.createElement("span");p.setAttribute("class","okanjo-ellipses"),h.setAttribute("class","okanjo-visually-hidden"),a?(p.textContent=s.substr(0,s.length-3),h.textContent=c):(p.innerText=s.substr(0,s.length-3),h.innerText=c),e.innerHTML="",e.appendChild(p),e.appendChild(h)}},d.ui.fitImages=function(e){"objectFit"in t.documentElement.style==!1&&e.querySelectorAll("img.okanjo-fit").forEach(function(e){e.style.display="none";var t=e.parentNode;t.style.backgroundSize="cover",t.style.backgroundImage="url("+e.src+")",t.style.backgroundposition="center center"})},e.okanjo=d}(window,document);return function(e){var t=/^application\/json/,o=e.okanjo;o.net.request=function(n,i,a,r){"function"==typeof a&&(r=a,a=void 0);var s=new(e.XMLHttpRequest||e.ActiveXObject)("MSXML2.XMLHTTP.3.0"),c=!1,l=function(e,t){c||(c=!0,r(e,t))};o.net.request.timeout&&(s.timeout=o.net.request.timeout),s.ontimeout=function(e){l({statusCode:504,error:"Request timed out",message:"Something went wrong",attributes:{event:e,xhr:s}})},s.onreadystatechange=function(e){if(4===s.readyState)if(s.status>0){var o=void 0;o=t.test(s.getResponseHeader("Content-Type"))?JSON.parse(s.responseText):{statusCode:s.status,data:s.responseText},s.status>=200&&s.status<300?l(null,o):l(o)}else l({statusCode:503,error:"Request failed",message:"Something went wrong",attributes:{event:e,xhr:s}})},s.open(n.toUpperCase(),i),s.withCredentials=!0,["POST","PUT","PATCH"].includes(n.toUpperCase())&&(s.setRequestHeader("Content-Type","application/json; charset=utf-8"),void 0!==a&&(a=JSON.stringify(a))),s.send(a||void 0)},o.net.request.get=o.net.request.bind(this,"GET"),o.net.request.post=o.net.request.bind(this,"POST"),o.net.request.put=o.net.request.bind(this,"PUT"),o.net.request["delete"]=o.net.request.bind(this,"DELETE");var n=function(e){return null===e||void 0===e?"":encodeURIComponent(""+e)},a=function(e,t){return t?t+"["+n(e)+"]":n(e)};o.net.request.stringify=function(e,t){var r=[];return t=t||"",Object.keys(e).forEach(function(s){var c=e[s];if(Array.isArray(c))c.forEach(function(e){return r.push(a(s,t)+"="+n(e))});else if("object"===("undefined"==typeof c?"undefined":i(c))&&null!==c){var l=o.net.request.stringify(c,a(s,t));l&&r.push(l)}else void 0!==c&&r.push(a(s,t)+"="+n(c))}),r.join("&")}}(window),function(e,t){e.okanjo.util.cookie={set:function(o,n,i){var a=new Date;a.setDate(a.getDate()+i);var r=i?" Expires="+a.toUTCString()+";":"",s=" Path=/",c="https:"===e.location.protocol?" Secure;":"",l=encodeURI(n)+";"+r+c+" SameSite=None;"+s;t.cookie=o+"="+l},get:function(e){var o=null;return t.cookie.split(";").find(function(t){var n=t.substr(0,t.indexOf("=")).trim(),i=t.substr(t.indexOf("=")+1);return n===e&&(o=decodeURI(i),!0)}),o}}}(window,document),function(e,t){var a=e.okanjo,r=function(){function e(){o(this,e),this._templates={},this._css={},this.classDetects=""}return n(e,[{key:"registerTemplate",value:function(e,t,o,n){if("object"===("undefined"==typeof t?"undefined":i(t))){if(void 0===t.nodeType)throw new Error("Parameter template must be a string or a DOM element");t=t.innerHTML,a.lib.Mustache.parse(t)}else if("string"!=typeof t)throw new Error("Parameter template must be a string or a DOM element");if(3===arguments.length&&"object"===("undefined"==typeof o?"undefined":i(o))?(n=o,o=null):n=n||{},o&&"function"!=typeof o)throw new Error("Parameter beforeRender must be a function");this._templates[e]={markup:t,options:n,beforeRender:o}}},{key:"registerCss",value:function(e,t,o){if(o=o||{},"object"===("undefined"==typeof t?"undefined":i(t))){if(void 0===t.nodeType)throw new Error("Parameter css must be a string or a DOM element")}else if("string"!=typeof t)throw new Error("Parameter css must be a string or a DOM element");this._css[e]={markup:t,options:o}}},{key:"isTemplateRegistered",value:function(e){return!!this._templates[e]}},{key:"isCssRegistered",value:function(e){return!!this._css[e]}},{key:"ensureCss",value:function(e){if(this._css[e]){var o=this._css[e],n=void 0===o.markup.nodeType?o.options.id||"okanjo-css-"+e:null;if(n){var i=t.querySelector("#"+n.replace(/\./g,"\\."));if(!i){var r=t.head,s=t.createElement("style");if(s.id=n,s.setAttribute("type","text/css"),s.hasOwnProperty?s.innerHTML=o.markup:s.styleSheet.cssText=o.markup,r)r.appendChild(s);else{var c=t.body;c?c.appendChild(s):a.report("Cannot add CSS template to document. Does it not have a body or head?")}}}}else a.report('Attempted to add CSS template "'+e+'" to the DOM, however it does not appear to be registered?')}},{key:"render",value:function(e,t,o){var n=this;o=o||{};var i=this._templates[e];return i.beforeRender&&(o=i.beforeRender.call(t,o)),o.okanjo=a,o.okanjoMetricUrl=a.net.endpoint.replace(/^https?:\/\//,""),o.now=function(){return(new Date).getTime()},o.classDetects=this.classDetects,o.blockClasses&&Array.isArray(o.blockClasses)&&(o.classDetects+=" "+o.blockClasses.join(" "),delete o.blockClasses),o.css!==!1&&i.options.css&&i.options.css.length>0&&(i.options.css.forEach(function(e){return n.ensureCss(e)}),delete o.css),a.lib.Mustache.render(i.markup,o)}}]),e}();r.formatCurrency=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:".",n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:",",i=e<0?"-":"",a=parseInt(e=Math.abs(+e||0).toFixed(t))+"",r=a.length;return r=r>3?r%3:0,i+(r?a.substr(0,r)+n:"")+a.substr(r).replace(/(\d{3})(?=\d)/g,"$1"+n)+(t?o+Math.abs(e-a).toFixed(t).slice(2):"")},a.ui.engine=new r}(window,document),function(e,t){var o=e.okanjo,n=o.util.isMobile(),i=!1,a=void 0,r=void 0,s=void 0,c=void 0,l=void 0,u=void 0,d=void 0,p=void 0,h=void 0,k=function(){a=t.documentElement||t.querySelector("html"),r=t.body||t.querySelector("body"),s=t.createElement("div"),c=t.createElement("div"),l=t.createElement("div"),u=t.createElement("div"),d=t.createElement("div"),p=t.createElement("div"),h=t.createElement("iframe"),s.setAttribute("class","okanjo-modal-container okanjo-modal-hidden "),c.setAttribute("class","okanjo-modal-window"),l.setAttribute("class","okanjo-modal-window-skin"),u.setAttribute("class","okanjo-modal-window-outer"),d.setAttribute("class","okanjo-modal-window-inner"),p.setAttribute("class","okanjo-modal-close-button"),h.setAttribute("class","okanjo-inline-buy-frame"),h.setAttribute("frameborder","0"),h.setAttribute("vspace","0"),h.setAttribute("hspace","0"),h.setAttribute("webkitallowfullscreen",""),h.setAttribute("mozallowfullscreen",""),h.setAttribute("allowfullscreen",""),h.setAttribute("scrolling","auto"),p.innerHTML="×",d.appendChild(h),u.appendChild(d),l.appendChild(u),c.appendChild(l),c.appendChild(p),s.appendChild(c),r.appendChild(s)},f=function(e,t,o){e.addEventListener?e.addEventListener(t,o,!1):e.attachEvent("on"+t,o)},g=function(){return e.innerHeight||t.documentElement.clientHeight},m=function(){c.style.height=g()-80+"px"},b=function(){f(e,"orientationchange",function(){for(var e=0;e<2;e++)setTimeout(m,1e3*e+10)}),f(e,"resize",function(){setTimeout(m,100)}),f(s,"click",y),f(c,"click",function(e){e.preventDefault(),e.stopPropagation()}),f(p,"click",function(e){e.preventDefault(),e.stopPropagation(),y()})},j=function(e,t){e.className+=" "+t},v=function(e,t){e.className=e.className.replace(new RegExp(" *?"+t),"")},_=function(){v(s,"okanjo-modal-hidden"),j(s,"okanjo-modal-fade-out"),m(),j(a,"okanjo-modal-active"),n||j(a,"okanjo-modal-margin-fix"),setTimeout(function(){v(s,"okanjo-modal-fade-out")},10)},y=function(){j(s,"okanjo-modal-fade-out"),setTimeout(function(){v(s,"okanjo-modal-fade-out"),j(s,"okanjo-modal-hidden"),v(a,"okanjo-modal-active"),n||v(a,"okanjo-modal-margin-fix")},210)},w=function(e){d.innerHTML="","string"==typeof e?d.innerHTML=e:d.appendChild(e)};return o.ui.modal={show:function(e){i||(i=!0,k(),b()),w(e),_()},hide:function(){y()}},o.ui.modal}(window,document),function(e,t){var i=e.okanjo,a=function(){function a(){o(this,a),this._queue=this._getStoredQueue(),this._processTimeout=null,this.pageId=i.util.shortid(),this.defaultChannel=a.Channel.external,this.sid=null,this.sourceCh=null,this.sourceCx=null,this._checkUrlForReferral()}return n(a,[{key:"_getStoredQueue",value:function(){if(!e.localStorage[a.Params.queue])return[];try{var t=JSON.parse(e.localStorage[a.Params.queue]);return Array.isArray(t)?t:(i.report("Stored queue is not a queue",{queue:t}),[])}catch(o){return i.report("Failed to load metric queue from storage",{err:o}),[]}}},{key:"_saveQueue",value:function(t){var o=this;t?(this._saveQueueTimeout&&clearTimeout(this._saveQueueTimeout),this._saveQueueTimeout=setTimeout(function(){o._saveQueue(!1),o._saveQueueTimeout=null},100)):e.localStorage[a.Params.queue]=JSON.stringify(this._queue)}},{key:"_checkUrlForReferral",value:function(){var t=i.util.getPageArguments(!0),o=t[a.Params.name],n=e.localStorage[a.Params.name]||i.util.cookie.get(a.Params.name),r=t[a.Params.context],s=t[a.Params.channel];o&&n&&o!==n&&this.trackEvent({object_type:a.Object.metric_session,event_type:a.Event.correlation,id:o+"_"+n,ch:this.defaultChannel,_noProcess:!0}),this.sid=n||o||null,this.sourceCh=s||null,this.sourceCx=r||null}},{key:"trackEvent",value:function(e,t){return e.object_type&&e.event_type?void this._push(e,t):void i.report("Invalid metric to track (missing object_type or event_type)",{event:e})}},{key:"trackPageView",value:function(e,t){e=e||{},e.object_type=a.Object.page,e.event_type=a.Event.view,e.id=e.id||i.util.getLocation(),e.ch=e.ch||this.defaultChannel,this.trackEvent(e,t)}},{key:"_push",value:function(e,t){this._queue.push({event:e,callback:t}),this._saveQueue(!0),e._noProcess?delete e._noProcess:this._processQueue()}},{key:"_processQueue",value:function(){var e=this;!this._processTimeout&&this._queue.length>0&&(this._processTimeout=setTimeout(function(){var t=e._queue.splice(0,255);e._saveQueue(!1),e._batchSend(t,function(o,n){n&&n.data&&n.data.sid&&e._updateSid(n.data.sid),e._processTimeout=null,e._processQueue(),t.forEach(function(e){e.callback&&e.callback(o,n)})})},0))}},{key:"_batchSend",value:function(e,t){var o=this,n=e.map(function(e){return o._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),a={events:n,win:i.util.getLocation()},r=i.net.getRoute(i.net.routes.metrics_batch);this.sid&&(a.sid=this.sid),i.net.request.post(r,a,function(o,n){o&&i.report("Failed to send metrics batch",{err:o,res:n,items:e,route:r}),t&&t(o,n)})}},{key:"_normalizeEvent",value:function(e){e.m=e.m||{},e.key=e.key||e.m.key||i.key||void 0,this.sid&&(e.sid=this.sid),e.m=Object.assign({},e.m),Object.keys(a.Meta.exclude).forEach(function(t){return delete e.m[t]}),this.sourceCh&&(e.m.ref_ch=this.sourceCh),this.sourceCx&&(e.m.ref_cx=this.sourceCx),e.m.pgid=this.pageId,e.m.ok_ver=i.version,e.m=i.util.flatten(e.m,{arrayToCsv:!0}),Object.keys(e.m).forEach(function(t){"string"==typeof e.m[t]&&(e.m[t]=e.m[t].substr(0,255))}),t.referrer&&(e.ref=t.referrer),e.win=i.util.getLocation()}},{key:"_updateSid",value:function(t){!t||this.sid&&this.sid===t||(this.sid=t,e.localStorage[a.Params.name]=t,i.util.cookie.set(a.Params.name,t,a.Params.ttl))}},{key:"create",value:function(){for(var e=arguments.length,t=Array(e),o=0;ot?e:t},h=function(e,t){return"undefined"==typeof e?t:e};return n.forEach(function(e){a=i.ui.getElementPosition(e),r=d(a.x1,r),s=d(a.y1,s),c=p(a.x2,c),l=p(a.y2,l),u.push(a.x1,a.y1,a.x2,a.y2)}),t.m.wix1=h(r,o.x1),t.m.wiy1=h(s,o.y1),t.m.wix2=h(c,o.x2),t.m.wiy2=h(l,o.y2),t.m.wrps=u.map(function(e){return Math.floor(e)}).join(","),t}},{key:"addViewportInfo",value:function(e){var t=i.ui.getViewportSize(),o=i.ui.getScrollPosition();return e=e||{},e.m=e.m||{},e.m.vx1=o.x,e.m.vy1=o.y,e.m.vx2=o.x+t.vw,e.m.vy2=o.y+t.vh,e}},{key:"addEventInfo",value:function(e,t){var o=i.ui.getEventPosition(e);return t=t||{},t.m=t.m||{},t.m.et=o.et,t.m.ex=o.ex,t.m.ey=o.ey,t}},{key:"addEventMeta",value:function(e){e=e||{},e.m=e.m||{};for(var t=arguments.length,o=Array(t>1?t-1:0),n=1;n1?t-1:0),n=1;n=0&&this._events[e].splice(o,1)}}},{key:"emit",value:function(e){var t=void 0,o=void 0,n=void 0,i=[].slice.call(arguments,1);if(this._events[e])for(o=this._events[e].slice(),n=o.length,t=0;t1&&void 0!==arguments[1])||arguments[1];if(!this._strip||!t)return void 0!==e&&this._convert&&(e=this._convert(e)),void 0!==e?e:this._default}}],[{key:"array",value:function(t){return(new e).array(t)}},{key:"string",value:function(){return(new e).string()}},{key:"bool",value:function(){return(new e).bool()}},{key:"strip",value:function(){return(new e).strip()}},{key:"int",value:function(){return(new e)["int"]()}},{key:"float",value:function(){return(new e)["float"]()}}]),e}(),r._Widget=l}(window),function(i){var a=i.okanjo,r=a._Widget.Field,s=r.string,c=r.array,l=r["float"],u=r["int"],d=r.bool,p=a.metrics.constructor,h=a.ui.engine.constructor,k="filters",f="display",g="article_meta",m=.5,b=1e3,j=2,v=function(r){function v(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};o(this,v),n=a.util.flatten(n,{ignoreArrays:!0});var i=e(this,(v.__proto__||Object.getPrototypeOf(v)).call(this,t,n));return i.name="Placement",i._metricBase={},i._response=null,i._viewWatcherIv=null,i._viewedWatchers=[],n.no_init||i.init(),i}return t(v,r),n(v,[{key:"getSettings",value:function(){return{type:s().group(k),ids:c().group(k),q:s().group(k),url:s().group(k),url_referrer:s().group(k).strip(),url_selectors:s().group(k),url_paths:c().group(k),not_url_paths:c().group(k),organization_id:s().group(k),property_id:s().group(k),store_id:s().group(k),organization_name:s().group(k),property_name:s().group(k),store_name:s().group(k),external_id:s().group(k),sku:s().group(k),external_store_id:s().group(k),condition:s().group(k),manufacturer:s().group(k),upc:s().group(k),isbn:s().group(k),tags:c().group(k),category:c().group(k),pools:c().group(k),min_price:l().group(k),max_price:l().group(k),min_donation_percent:l().group(k),max_donation_percent:l().group(k),donation_to:s().group(k),sort_by:s().group(k),sort_direction:s().group(k),skip:u().group(k),take:u().group(k),placement_tests_only:d(),size:s().group(f),template_name:s().group(f),template_layout:s().group(f),template_theme:s().group(f),template_variant:s().group(f),template_cta_style:s().group(f),template_cta_text:s().group(f),template_cta_color:s().group(f),adx_unit_path:s().group(f),url_category:c().group(g),url_keywords:c().group(g),key:s().strip(),no_init:d().strip(),proxy_url:s().strip(),expandable:d().strip()["default"](!0),disable_inline_buy:d().strip()["default"](!1),disable_popup:d().strip()["default"](!1),backwards:s().strip(),testing:d().strip()}}},{key:"getConfig",value:function(){var e=this,t=this.getSettings(),o={filters:{},display:{},backfill:{},shortfill:{},article_meta:{}},n=/^backfill_(.+)$/,i=/^shortfill_(.+)$/;return Object.keys(this.config).forEach(function(a){var r=e.config[a],s=a,c=!1,l=!1,u=null,d=n.exec(a);d?(s=d[1],c=!0):(d=i.exec(a),d&&(s=d[1],l=!0)),t[s]&&(r=t[s].value(r),u=t[s].getGroup());var p=o;c?p=o.backfill:l&&(p=o.shortfill),!l&&u&&(p[u]=p[u]||{},p=p[u]),null===r?p[s]="":void 0!==r&&(p[s]=r)}),o}},{key:"load",value:function(){var e=this;this._setMetricBase(),this._fetchContent(function(t){t?e._reportWidgetLoad("fetch failed: "+t.statusCode||t.toString()):(e._mergeResponseSettings(),e._updateBaseMetaFromResponse(),e._showContent())})}},{key:"_setMetricBase",value:function(){var e=this._metricBase;e.ch=p.Channel.placement,e.cx=this.config.backwards||"auto",e.key=this.config.key,e.m=e.m||{},e.m.wgid=this.instanceId,this.config.testing&&(e.env=p.Environment.testing)}},{key:"_reportWidgetLoad",value:function(e){var t=this,o=this._response||{},n=o.data||{results:[]};this._metricBase.m.decl=e||"0",this._metricBase.m.res_bf=n.backfilled?1:0,this._metricBase.m.res_sf=n.shortfilled?1:0,this._metricBase.m.res_spltfl=n.splitfilled?1:0,this._metricBase.m.res_total=n.total||0,this._metricBase.m.res_type=n.type,this._metricBase.m.res_length=n.results.length,a.metrics.create(this._metricBase).type(p.Object.widget,p.Event.impression).meta(this.getConfig()).element(this.element).viewport().widget(this.element).send(),this._addOnceViewedHandler(this.element,function(){a.metrics.create(t._metricBase).type(p.Object.widget,p.Event.view).meta(t.getConfig()).element(t.element).viewport().widget(t.element).send()})}},{key:"_fetchContent",value:function(e){var t=this,o=this.getConfig(),n=this.config.key;a.metrics.sid&&(o.sid=a.metrics.sid),o.filters.url_referrer=this.config.url_referrer||i.location.href,o.wgid=this.instanceId,o.pgid=a.metrics.pageId,a.net.request.post(a.net.getRoute(a.net.routes.ads,null,this.config.sandbox?"sandbox":"live")+"?key="+encodeURIComponent(n),o,function(o,n){o?(a.report("Failed to retrieve placement content",o,{placement:t}),t.setMarkup(""),t.emit("error",o),e&&e(o)):(t._response=n,t.emit("data"),e&&e())})}},{key:"_mergeResponseSettings",value:function(){var e=this,t=this._response,o=t.data||{},n=o.settings||{};n.filters&&Object.keys(n.filters).forEach(function(t){e.config[t]=n.filters[t]}),n.display&&Object.keys(n.display).forEach(function(t){e.config[t]=n.display[t]})}},{key:"_updateBaseMetaFromResponse",value:function(){var e=(this._response||{}).data||{};this._metricBase.m=this._metricBase.m||{};var t=this._metricBase.m;e.article&&(t.aid=e.article.id),e.test&&e.test.enabled?(t.pten=1,t.ptid=e.test.id,t.ptseed=e.test.seed):t.pten=0}},{key:"_showContent",value:function(){var e=(this._response||{}).data||{};if(e.type===v.ContentTypes.products)this._showProducts();else if(e.type===v.ContentTypes.articles)this._showArticles();else if(e.type===v.ContentTypes.adx)this._showADX();else{var t="Unknown response content type: "+e.type;a.report(t,{placement:this}),this.setMarkup(""),this.emit("error",t),this._reportWidgetLoad(t)}}},{key:"_getClickThroughURL",value:function(e,t,o){var n=t.indexOf("?")>=0?"&":"?";return o=o||{},o.ok_msid=a.metrics.sid||"unknown",o.ok_ch=this._metricBase.ch,o.ok_cx=this._metricBase.cx,o._okjr=i.location.href.split(/[?#]/)[0],o.utm_source="okanjo",o.utm_campaign="smartserve",o.utm_medium="smartserve",t+=n+Object.keys(o).map(function(e){return encodeURIComponent(e)+"="+encodeURIComponent(o[e])}).join("&"),this.config.proxy_url&&(t=this.config.proxy_url+encodeURIComponent(t)),e.data({u:t}),e.toUrl()}},{key:"_handleResourceMouseDown",value:function(e,t,o){var n=t._cid,i=a.metrics.create(this._metricBase,{id:t.id}).type(e,p.Event.interaction).meta(this.getConfig()).meta({cid:n}).meta({bf:t.backfill?1:0,sf:t.shortfill?1:0,spltfl_seg:t.splitfill_segment||null}).event(o).element(o.currentTarget).viewport().widget(this.element),r="url_track_param",s="url";e===p.Object.product&&(r="buy_url_track_param",s="buy_url");var c={ok_cid:n};t[r]&&(c[t[r]]=n),i.data({ea:p.Action.click}),o.currentTarget.href=this._getClickThroughURL(i,t[s],c),t._clickId=n,t._event=i,t._additionalParams=c}},{key:"_getTemplate",value:function(e,t){var o=this.config.template_name;return o&&a.ui.engine.isTemplateRegistered(e+"."+o)||(o=t),e+"."+o}},{key:"_enforceLayoutOptions",value:function(){"leaderboard"===this.config.size||"large_mobile_banner"===this.config.size?(this.config.template_layout="list",this.config.template_cta_style="link"):"half_page"!==this.config.size&&"auto"!==this.config.size||(this.config.template_layout="list")}},{key:"_enforceSlabLayoutOptions",value:function(){"medium_rectangle"===this.config.size||"billboard"===this.config.size?(this.config.template_layout="grid","button"===this.config.template_cta_style&&(this.config.template_cta_style="link")):"half_page"===this.config.size?this.config.template_layout="grid":"leaderboard"===this.config.size||"large_mobile_banner"===this.config.size?(this.config.template_layout="list","button"===this.config.template_cta_style&&(this.config.template_cta_style="link")):"auto"===this.config.size?this.config.template_layout="list":"responsive"===this.config.size&&"button"===this.config.template_cta_style&&(this.config.template_cta_style="link")}},{key:"_registerCustomBranding",value:function(){var e=this.config.template_cta_color;if(e){var t=void 0,o="okanjo-wgid-"+this.instanceId;t="\n .okanjo-block2."+o+" .okanjo-resource-cta-button, .okanjo-block2."+o+" .okanjo-resource-buy-button { color: "+e+" !important; } \n .okanjo-block2."+o+".okanjo-cta-style-button .okanjo-resource-cta-button, .okanjo-block2."+o+".okanjo-cta-style-button .okanjo-resource-buy-button { border-color: "+e+" !important; } \n .okanjo-block2."+o+".okanjo-cta-style-button .okanjo-resource-cta-button:hover, .okanjo-block2."+o+".okanjo-cta-style-button .okanjo-resource-buy-button:hover { background: "+e+" !important; color: #fff !important; } \n ", -a.ui.engine.registerCss(o,t,{id:o}),a.ui.engine.ensureCss(o)}}},{key:"_addOnceViewedHandler",value:function(e,t){var o={element:e,successfulCount:0,handler:t};this._viewedWatchers.push(o),this._toggleViewWatcher(!0)}},{key:"_checkViewWatchers",value:function(){for(var e,t=0;t=m&&e.successfulCount++,e.successfulCount>=j&&(e.handler(),this._viewedWatchers.splice(t,1),t--);0===this._viewedWatchers.length&&this._toggleViewWatcher(!1)}},{key:"_toggleViewWatcher",value:function(e){e?null===this._viewWatcherIv&&(this._viewWatcherIv=setInterval(this._checkViewWatchers.bind(this),b/j)):(clearInterval(this._viewWatcherIv),this._viewWatcherIv=null)}},{key:"_showProducts",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},o=this._getTemplate(v.ContentTypes.products,v.DefaultTemplates.products);t.results.forEach(function(t,o){e.config.disable_inline_buy&&(t.inline_buy_url=null),t.inline_buy_url&&(t._escaped_inline_buy_url=encodeURIComponent(t.inline_buy_url)),t._image_url=t.image_urls?t.image_urls[0]:"",t._escaped_buy_url=encodeURIComponent(t.buy_url),t._price_formatted=h.formatCurrency(t.price),t._index=o}),this.setMarkup(a.ui.engine.render(o,this)),0===t.results.length?(this.emit("empty"),this._reportWidgetLoad("empty")):this._reportWidgetLoad(),this.element.querySelectorAll("a").forEach(function(t){var o=t.getAttribute("data-id"),n=t.getAttribute("data-index");if(o&&n>=0){var i=e._response.data.results[n];i&&(t.addEventListener("mousedown",e._handleResourceMouseDown.bind(e,p.Object.product,i)),t.addEventListener("click",e._handleProductClick.bind(e,i)),a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.product,p.Event.impression).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.product,p.Event.view).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(".okanjo-resource-title").forEach(function(e){a.ui.ellipsify(e)}),a.ui.fitImages(this.element),this.emit("load")}},{key:"_handleProductClick",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(p.Object.product,e,t);var o=e._event,n=e._additionalParams;o.event(t);var r=!!e.inline_buy_url,s=!this.config.disable_popup&&r&&a.util.isMobile();if(s){t.preventDefault(),o.data({ea:p.Action.inline_click}).meta({popup:"true"});var c=this._getClickThroughURL(o,e.inline_buy_url,n);this._popupFrame=i.open(c,"okanjo-inline-buy-frame","width=400,height=400,location=yes,resizable=yes,scrollbars=yes"),this._popupFrame||(a.report("Popup blocker stopped buy experience from showing",{placement:this}),i.location.href=c)}else if(r){t.preventDefault();var l=document.createElement("iframe"),u={"class":"okanjo-inline-buy-frame",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:"",mozallowfullscreen:"",allowfullscreen:"",scrolling:"auto"};if(Object.keys(u).forEach(function(e){return l.setAttribute(e,u[e])}),n.expandable=this.config.expandable?1:0,!this.config.expandable){var d=this.element.querySelector(".okanjo-expansion-root");if(d){l.className+=" okanjo-ad-in-unit",l.setAttribute("height","100%"),l.setAttribute("width","100%"),d.appendChild(l);var h=a.ui.getElementSize(d);n.frame_height=h.height,n.frame_width=h.width,this.config.size&&(n.ad_size=this.config.size)}}o.data({ea:p.Action.inline_click}).meta({expandable:this.config.expandable?"true":"false"}),l.src=this._getClickThroughURL(o,e.inline_buy_url,n),l.parentNode||a.ui.modal.show(l)}else t.currentTarget.href=this._getClickThroughURL(o,e.buy_url,n)}},{key:"_showArticles",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},o=this._getTemplate(v.ContentTypes.articles,v.DefaultTemplates.articles);t.results.forEach(function(e,t){e._escaped_url=encodeURIComponent(e.url),e._index=t}),this.setMarkup(a.ui.engine.render(o,this)),0===t.results.length?(this.emit("empty"),this._reportWidgetLoad("empty")):this._reportWidgetLoad(),this.element.querySelectorAll("a").forEach(function(t){var o=t.getAttribute("data-id"),n=t.getAttribute("data-index");if(o&&n>=0){var i=e._response.data.results[n];i&&(t.addEventListener("mousedown",e._handleResourceMouseDown.bind(e,p.Object.article,i)),t.addEventListener("click",e._handleArticleClick.bind(e,i)),a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.article,p.Event.impression).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.article,p.Event.view).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(".okanjo-resource-title").forEach(function(e){a.ui.ellipsify(e)}),a.ui.fitImages(this.element),this.emit("load")}},{key:"_handleArticleClick",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(p.Object.article,e,t);var o=e._event,n=e._additionalParams;o.event(t),t.currentTarget.href=this._getClickThroughURL(o,e.url,n)}},{key:"_showADX",value:function(){var e=this,t=(this._response||{data:{settings:{}}}).data||{settings:{}},o=this._getTemplate(v.ContentTypes.adx,v.DefaultTemplates.adx),n=null;if(this.config.size)if(v.Sizes[this.config.size])n=v.Sizes[this.config.size];else{var i=/^([0-9]+)x([0-9]+)$/i.exec(this.config.size);i&&(n={width:i[1],height:i[2]})}n||(n=v.Sizes["default"]);var r="/90447967/okanjo:",s=void 0;t.settings.display&&t.settings.display.adx_unit_path&&(r=t.settings.display.adx_unit_path,s="custom_ad_unit");var c={size:n,adUnitPath:r};this.setMarkup(a.ui.engine.render(o,this,c)),this._reportWidgetLoad(s);var l=this.element.querySelector(".okanjo-adx-container");if(l){var u=document.createElement("iframe"),d={"class":"okanjo-adx-frame",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:"",mozallowfullscreen:"",allowfullscreen:"",scrolling:"auto",width:n.width,height:n.height};Object.keys(d).forEach(function(e){return u.setAttribute(e,d[e])}),l.appendChild(u);var h=a.metrics.create(this._metricBase).type(p.Object.thirdparty_ad,p.Event.interaction).meta(this.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(this.element).toUrl();u.contentWindow.trackImpression=function(){a.metrics.create(e._metricBase).type(p.Object.thirdparty_ad,p.Event.impression).meta(e.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(e.element).send(),e._addOnceViewedHandler(u,function(){a.metrics.create(e._metricBase).type(p.Object.thirdparty_ad,p.Event.view).meta(e.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(e.element).send()})},u.contentWindow.document.open(),u.contentWindow.document.write('\n<'+('script type="text/javascript" src="https://www.googletagservices.com/tag/js/gpt.js">\n googletag.pubads().addEventListener(\'slotRenderEnded\', function(e) { \n trackImpression(e);\n });\n googletag.pubads()\n .definePassback("'+r.replace(/"/g,'\\"')+'", [['+n.width+", "+n.height+']])\n .setClickUrl("'+h+'&u=")\n .display();\n<')+"/script>\n"),u.contentWindow.document.close()}this.emit("load")}}]),v}(a._Widget);return v.Sizes={medium_rectangle:{width:300,height:250},leaderboard:{width:728,height:90},large_mobile_banner:{width:320,height:100},half_page:{width:300,height:600},billboard:{width:970,height:250},button_2:{width:120,height:60},micro_bar:{width:88,height:31},portrait:{width:300,height:1050},rectangle:{width:180,height:150},super_leaderboard:{width:970,height:90},wide_skyscraper:{width:160,height:600},mobile_leaderboard:{width:320,height:50},small_square:{width:200,height:200},button_1:{width:120,height:90},full_banner:{width:468,height:60},half_banner:{width:234,height:60},large_rectangle:{width:336,height:280},pop_under:{width:720,height:300},three_to_one_rectangle:{width:300,height:100},skyscraper:{width:120,height:600},square:{width:250,height:250},square_button:{width:125,height:125},vertical_banner:{width:120,height:240},vertical_rectangle:{width:240,height:400}},v.Sizes["default"]=v.Sizes.medium_rectangle,v.ContentTypes={products:"products",articles:"articles",adx:"adx"},v.DefaultTemplates={products:"block2",articles:"block2",adx:"block2"},a.Placement=v}(window),function(i){var a=i.okanjo,r=function(i){function r(t,n){o(this,r),n=n||{};var i=n.no_init;n.no_init=!0;var s=e(this,(r.__proto__||Object.getPrototypeOf(r)).call(this,t,n));return a.warn("Product widget has been deprecated. Use Placement instead (may require configuration changes)",{widget:s}),i||(delete s.config.no_init,s.init()),s}return t(r,i),n(r,[{key:"_setCompatibilityOptions",value:function(){this.config.backwards="Product",this.config.type=a.Placement.ContentTypes.products,"sense"===this.config.mode?(this.config.url=this.config.url||"referrer",this.config.take=this.config.take||5):"single"===this.config.mode?(this.config.url=null,this.config.id&&(this.config.ids=[this.config.id]),this.config.take=1,delete this.config.id):(this.config.url=null,this.config.take=this.config.take||25),delete this.config.mode,this.config.sold_by&&(this.config.store_name=this.config.sold_by,delete this.config.sold_by),this.config.selectors&&(this.config.url_selectors=this.config.selectors,delete this.config.selectors),this.config.marketplace_id&&(this.config.property_id=this.config.marketplace_id,delete this.config.marketplace_id),"testing"===this.config.marketplace_status&&(this.config.sandbox=!0),delete this.config.marketplace_status,delete this.config.suboptimal,delete this.config.text}}]),r}(a.Placement);return a.Product=r}(window),function(i){var a=i.okanjo,r=function(i){function r(t,n){o(this,r),n=n||{};var i=n.no_init;n.no_init=!0;var s=e(this,(r.__proto__||Object.getPrototypeOf(r)).call(this,t,n));return a.warn("Ad widget has been deprecated. Use Placement instead (may require configuration changes)",{widget:s}),i||(delete s.config.no_init,s.init()),s}return t(r,i),n(r,[{key:"_setCompatibilityOptions",value:function(){this.config.backwards="Ad",this.config.type=a.Placement.ContentTypes.products,this.config.url=null,this.config.id?this.config.ids=[this.config.id]:a.warn("Ad widget should have parameter `id` set."),this.config.take=1,delete this.config.id,delete this.config.content}}]),r}(a.Placement);return a.Ad=r}(window),function(){/*! +/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.okanjo=t()}(this,function(){function e(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function t(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function o(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var n=function(){function e(e,t){for(var o=0;o0?1:-1)*Math.floor(Math.abs(t)):t},n=Math.pow(2,53)-1,i=function(e){var t=o(e);return Math.min(Math.max(t,0),n)};return function(e){var o=this,n=Object(e);if(null==e)throw new TypeError("Array.from requires an array-like object - not null or undefined");var a,r=arguments.length>1?arguments[1]:void 0;if("undefined"!=typeof r){if(!t(r))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(a=arguments[2])}for(var s,c=i(n.length),l=t(o)?Object(new o(c)):new Array(c),u=0;u>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var n=arguments[1],i=0;i>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var n=arguments[1],i=0;i>>0;if(0===i)return!1;for(var a=0|t,r=Math.max(a>=0?a:i-Math.abs(a),0);r=0&&t.splice(a,1)}l.error("[Okanjo v"+d.version+"]: "+n.stack),t.length&&l.error.apply(l,["Additional information:"].concat(t))},warn:function(e){for(var t=arguments.length,o=Array(t>1?t-1:0),n=1;n1&&void 0!==arguments[1]?arguments[1]:{},o={};return void 0!==e&&null!==e&&Object.keys(e).forEach(function(n){if(e[n]instanceof Date)t.dateToIso?o[n]=e[n].toISOString():o[n]=e[n];else if("object"===i(e[n])&&null!==e[n])if(Array.isArray(e[n])&&t.ignoreArrays===!0)o[n]=e[n];else if(Array.isArray(e[n])&&t.arrayToCsv===!0)o[n]=e[n].join(",");else{var a=d.util.flatten(e[n],t);Object.keys(a).forEach(function(e){o[n+"_"+e]=a[e]})}else o[n]=e[n]}),o},d.util.shortid=function(t){var o="ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC",n=e.crypto||e.msCrypto||"function"==typeof require&&require("crypto"),i=function(){if(n&&n.randomBytes)return 48&n.randomBytes(1)[0];if(!n||!n.getRandomValues)return 48&Math.floor(256*Math.random());var e=new Uint8Array(1);return n.getRandomValues(e),48&e[0]},a=function(e){for(var t=0,n=void 0,a="";!n;)a+=o[e>>4*t&15|i()],n=e0&&(e+=a(c)),e+=a(o)}}(),d.util.getLocation=function(){return e.location!==e.parent.location?t.referrer:t.location.href},d.ui={getScrollPosition:function(){return{x:o?e.pageXOffset:n?t.documentElement.scrollLeft:t.body.scrollLeft,y:o?e.pageYOffset:n?t.documentElement.scrollTop:t.body.scrollTop}},getElementSize:function(t,o){var n={height:t.offsetHeight,width:t.offsetWidth},i=t.currentStyle||e.getComputedStyle(t);return o&&(n.height+=parseInt(i.marginTop)+parseInt(i.marginBottom),n.width+=parseInt(i.marginLeft)+parseInt(i.marginRight)),n},getPageSize:function(){var e=t.querySelector("body"),o=t.documentElement;return{w:Math.max(e.scrollWidth,e.offsetWidth,o.clientWidth,o.scrollWidth,o.offsetWidth),h:Math.max(e.scrollHeight,e.offsetHeight,o.clientHeight,o.scrollHeight,o.offsetHeight)}},getViewportSize:function(){var o=n?t.documentElement:t.body,i=o.clientWidth,a=o.clientHeight,r=e.innerWidth||0,s=e.innerHeight||0,c=r&&i>r||s&&a>s;return{vw:c?r:i,vh:c?s:a}},getEventPosition:function(e){var o=e.pageX,n=e.pageY,i=t.body,a=t.documentElement,r="scrollLeft",s="scrollTop",c=e.__proto__.constructor.name;return{et:c,ex:void 0===o?e.clientX+i[r]+a[r]:o,ey:void 0===n?e.clientY+i[s]+a[s]:n}},getElementPosition:function(e){var o="Could not get position of element. Did you attach the element to the DOM before initializing?";try{var n=e.getBoundingClientRect(),i=t.body.getBoundingClientRect();return t.body.contains(e)||d.report(o,e),{x1:n.left-i.left,y1:n.top-i.top,x2:n.right-i.left,y2:n.bottom-i.top}}catch(a){return d.report(o,{exception:a,element:e}),{x1:0,y1:0,x2:0,y2:0,err:1}}},_getIntersection:function(e,t,o){var n=Math.max(e.x1,t.x),i=Math.min(e.x2,t.x+o.vw),a=Math.max(e.y1,t.y),r=Math.min(e.y2,t.y+o.vh),s=Math.max(0,i-n)*Math.max(0,r-a),c=(e.x2-e.x1)*(e.y2-e.y1);return{intersectionArea:s,elementArea:c}},isElementVisible:function(e){return e.offsetWidth>0&&e.offsetHeight>0},getPercentageInViewport:function(e){var t=d.ui.getElementPosition(e),o=d.ui.getScrollPosition(),n=d.ui.getViewportSize();if(t.err)return 0;var i=d.ui._getIntersection(t,o,n),a=i.intersectionArea,r=i.elementArea;return r<=0?0:a/r}},d.ui.ellipsify=function(e,o){for(var n=o||e.parentNode,i=d.ui.getElementSize(n).height,a=void 0!==e.textContent,s=a?e.textContent:e.innerText,c="",l=5e3,u=function(e){return c=e.substr(0,e.length-3)+c,"..."};d.ui.getElementSize(e).height>i&&s.length>0&&l-- >0;)s=a?e.textContent:e.innerText,s=s.replace(r,u),a?e.textContent=s:e.innerText=s;if(c.length>0){var p=t.createElement("span"),h=t.createElement("span");p.setAttribute("class","okanjo-ellipses"),h.setAttribute("class","okanjo-visually-hidden"),a?(p.textContent=s.substr(0,s.length-3),h.textContent=c):(p.innerText=s.substr(0,s.length-3),h.innerText=c),e.innerHTML="",e.appendChild(p),e.appendChild(h)}},d.ui.fitImages=function(e){"objectFit"in t.documentElement.style==!1&&e.querySelectorAll("img.okanjo-fit").forEach(function(e){e.style.display="none";var t=e.parentNode;t.style.backgroundSize="cover",t.style.backgroundImage="url("+e.src+")",t.style.backgroundposition="center center"})},e.okanjo=d}(window,document);return function(e){var t=/^application\/json/,o=e.okanjo;o.net.request=function(n,i,a,r){"function"==typeof a&&(r=a,a=void 0);var s=new(e.XMLHttpRequest||e.ActiveXObject)("MSXML2.XMLHTTP.3.0"),c=!1,l=function(e,t){c||(c=!0,r(e,t))};o.net.request.timeout&&(s.timeout=o.net.request.timeout),s.ontimeout=function(e){l({statusCode:504,error:"Request timed out",message:"Something went wrong",attributes:{event:e,xhr:s}})},s.onreadystatechange=function(e){if(4===s.readyState)if(s.status>0){var o=void 0;o=t.test(s.getResponseHeader("Content-Type"))?JSON.parse(s.responseText):{statusCode:s.status,data:s.responseText},s.status>=200&&s.status<300?l(null,o):l(o)}else l({statusCode:503,error:"Request failed",message:"Something went wrong",attributes:{event:e,xhr:s}})},s.open(n.toUpperCase(),i),s.withCredentials=!0,["POST","PUT","PATCH"].includes(n.toUpperCase())&&(s.setRequestHeader("Content-Type","application/json; charset=utf-8"),void 0!==a&&(a=JSON.stringify(a))),s.send(a||void 0)},o.net.request.get=o.net.request.bind(this,"GET"),o.net.request.post=o.net.request.bind(this,"POST"),o.net.request.put=o.net.request.bind(this,"PUT"),o.net.request["delete"]=o.net.request.bind(this,"DELETE");var n=function(e){return null===e||void 0===e?"":encodeURIComponent(""+e)},a=function(e,t){return t?t+"["+n(e)+"]":n(e)};o.net.request.stringify=function(e,t){var r=[];return t=t||"",Object.keys(e).forEach(function(s){var c=e[s];if(Array.isArray(c))c.forEach(function(e){return r.push(a(s,t)+"="+n(e))});else if("object"===("undefined"==typeof c?"undefined":i(c))&&null!==c){var l=o.net.request.stringify(c,a(s,t));l&&r.push(l)}else void 0!==c&&r.push(a(s,t)+"="+n(c))}),r.join("&")}}(window),function(e,t){e.okanjo.util.cookie={set:function(o,n,i){var a=new Date;a.setDate(a.getDate()+i);var r=i?" Expires="+a.toUTCString()+";":"",s=" Path=/",c="https:"===e.location.protocol?" Secure;":"",l=encodeURI(n)+";"+r+c+" SameSite=None;"+s;t.cookie=o+"="+l},get:function(e){var o=null;return t.cookie.split(";").find(function(t){var n=t.substr(0,t.indexOf("=")).trim(),i=t.substr(t.indexOf("=")+1);return n===e&&(o=decodeURI(i),!0)}),o}}}(window,document),function(e,t){var a=e.okanjo,r=function(){function e(){o(this,e),this._templates={},this._css={},this.classDetects=""}return n(e,[{key:"registerTemplate",value:function(e,t,o,n){if("object"===("undefined"==typeof t?"undefined":i(t))){if(void 0===t.nodeType)throw new Error("Parameter template must be a string or a DOM element");t=t.innerHTML,a.lib.Mustache.parse(t)}else if("string"!=typeof t)throw new Error("Parameter template must be a string or a DOM element");if(3===arguments.length&&"object"===("undefined"==typeof o?"undefined":i(o))?(n=o,o=null):n=n||{},o&&"function"!=typeof o)throw new Error("Parameter beforeRender must be a function");this._templates[e]={markup:t,options:n,beforeRender:o}}},{key:"registerCss",value:function(e,t,o){if(o=o||{},"object"===("undefined"==typeof t?"undefined":i(t))){if(void 0===t.nodeType)throw new Error("Parameter css must be a string or a DOM element")}else if("string"!=typeof t)throw new Error("Parameter css must be a string or a DOM element");this._css[e]={markup:t,options:o}}},{key:"isTemplateRegistered",value:function(e){return!!this._templates[e]}},{key:"isCssRegistered",value:function(e){return!!this._css[e]}},{key:"ensureCss",value:function(e){if(this._css[e]){var o=this._css[e],n=void 0===o.markup.nodeType?o.options.id||"okanjo-css-"+e:null;if(n){var i=t.querySelector("#"+n.replace(/\./g,"\\."));if(!i){var r=t.head,s=t.createElement("style");if(s.id=n,s.setAttribute("type","text/css"),s.hasOwnProperty?s.innerHTML=o.markup:s.styleSheet.cssText=o.markup,r)r.appendChild(s);else{var c=t.body;c?c.appendChild(s):a.report("Cannot add CSS template to document. Does it not have a body or head?")}}}}else a.report('Attempted to add CSS template "'+e+'" to the DOM, however it does not appear to be registered?')}},{key:"render",value:function(e,t,o){var n=this;o=o||{};var i=this._templates[e];return i.beforeRender&&(o=i.beforeRender.call(t,o)),o.okanjo=a,o.okanjoMetricUrl=a.net.endpoint.replace(/^https?:\/\//,""),o.now=function(){return(new Date).getTime()},o.classDetects=this.classDetects,o.blockClasses&&Array.isArray(o.blockClasses)&&(o.classDetects+=" "+o.blockClasses.join(" "),delete o.blockClasses),o.css!==!1&&i.options.css&&i.options.css.length>0&&(i.options.css.forEach(function(e){return n.ensureCss(e)}),delete o.css),a.lib.Mustache.render(i.markup,o)}}]),e}();r.formatCurrency=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:".",n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:",",i=e<0?"-":"",a=parseInt(e=Math.abs(+e||0).toFixed(t))+"",r=a.length;return r=r>3?r%3:0,i+(r?a.substr(0,r)+n:"")+a.substr(r).replace(/(\d{3})(?=\d)/g,"$1"+n)+(t?o+Math.abs(e-a).toFixed(t).slice(2):"")},a.ui.engine=new r}(window,document),function(e,t){var o=e.okanjo,n=o.util.isMobile(),i=!1,a=void 0,r=void 0,s=void 0,c=void 0,l=void 0,u=void 0,d=void 0,p=void 0,h=void 0,k=function(){a=t.documentElement||t.querySelector("html"),r=t.body||t.querySelector("body"),s=t.createElement("div"),c=t.createElement("div"),l=t.createElement("div"),u=t.createElement("div"),d=t.createElement("div"),p=t.createElement("div"),h=t.createElement("iframe"),s.setAttribute("class","okanjo-modal-container okanjo-modal-hidden "),c.setAttribute("class","okanjo-modal-window"),l.setAttribute("class","okanjo-modal-window-skin"),u.setAttribute("class","okanjo-modal-window-outer"),d.setAttribute("class","okanjo-modal-window-inner"),p.setAttribute("class","okanjo-modal-close-button"),h.setAttribute("class","okanjo-inline-buy-frame"),h.setAttribute("frameborder","0"),h.setAttribute("vspace","0"),h.setAttribute("hspace","0"),h.setAttribute("webkitallowfullscreen",""),h.setAttribute("mozallowfullscreen",""),h.setAttribute("allowfullscreen",""),h.setAttribute("scrolling","auto"),p.innerHTML="×",d.appendChild(h),u.appendChild(d),l.appendChild(u),c.appendChild(l),c.appendChild(p),s.appendChild(c),r.appendChild(s)},f=function(e,t,o){e.addEventListener?e.addEventListener(t,o,!1):e.attachEvent("on"+t,o)},g=function(){return e.innerHeight||t.documentElement.clientHeight},m=function(){c.style.height=g()-80+"px"},b=function(){f(e,"orientationchange",function(){for(var e=0;e<2;e++)setTimeout(m,1e3*e+10)}),f(e,"resize",function(){setTimeout(m,100)}),f(s,"click",y),f(c,"click",function(e){e.preventDefault(),e.stopPropagation()}),f(p,"click",function(e){e.preventDefault(),e.stopPropagation(),y()})},j=function(e,t){e.className+=" "+t},v=function(e,t){e.className=e.className.replace(new RegExp(" *?"+t),"")},_=function(){v(s,"okanjo-modal-hidden"),j(s,"okanjo-modal-fade-out"),m(),j(a,"okanjo-modal-active"),n||j(a,"okanjo-modal-margin-fix"),setTimeout(function(){v(s,"okanjo-modal-fade-out")},10)},y=function(){j(s,"okanjo-modal-fade-out"),setTimeout(function(){v(s,"okanjo-modal-fade-out"),j(s,"okanjo-modal-hidden"),v(a,"okanjo-modal-active"),n||v(a,"okanjo-modal-margin-fix")},210)},w=function(e){d.innerHTML="","string"==typeof e?d.innerHTML=e:d.appendChild(e)};return o.ui.modal={show:function(e){i||(i=!0,k(),b()),w(e),_()},hide:function(){y()}},o.ui.modal}(window,document),function(e,t){var i=e.okanjo,a=function(){function a(){o(this,a),this._queue=this._getStoredQueue(),this._processTimeout=null,this.pageId=i.util.shortid(),this.defaultChannel=a.Channel.external,this.sid=null,this.sourceCh=null,this.sourceCx=null,this._checkUrlForReferral()}return n(a,[{key:"_getStoredQueue",value:function(){if(!e.localStorage[a.Params.queue])return[];try{var t=JSON.parse(e.localStorage[a.Params.queue]);return Array.isArray(t)?t:(i.report("Stored queue is not a queue",{queue:t}),[])}catch(o){return i.report("Failed to load metric queue from storage",{err:o}),[]}}},{key:"_saveQueue",value:function(t){var o=this;t?(this._saveQueueTimeout&&clearTimeout(this._saveQueueTimeout),this._saveQueueTimeout=setTimeout(function(){o._saveQueue(!1),o._saveQueueTimeout=null},100)):e.localStorage[a.Params.queue]=JSON.stringify(this._queue)}},{key:"_checkUrlForReferral",value:function(){var t=i.util.getPageArguments(!0),o=t[a.Params.name],n=e.localStorage[a.Params.name]||i.util.cookie.get(a.Params.name),r=t[a.Params.context],s=t[a.Params.channel];o&&n&&o!==n&&this.trackEvent({object_type:a.Object.metric_session,event_type:a.Event.correlation,id:o+"_"+n,ch:this.defaultChannel,_noProcess:!0}),this.sid=n||o||null,this.sourceCh=s||null,this.sourceCx=r||null}},{key:"trackEvent",value:function(e,t){return e.object_type&&e.event_type?void this._push(e,t):void i.report("Invalid metric to track (missing object_type or event_type)",{event:e})}},{key:"trackPageView",value:function(e,t){e=e||{},e.object_type=a.Object.page,e.event_type=a.Event.view,e.id=e.id||i.util.getLocation(),e.ch=e.ch||this.defaultChannel,this.trackEvent(e,t)}},{key:"_push",value:function(e,t){this._queue.push({event:e,callback:t}),this._saveQueue(!0),e._noProcess?delete e._noProcess:this._processQueue()}},{key:"_processQueue",value:function(){var e=this;!this._processTimeout&&this._queue.length>0&&(this._processTimeout=setTimeout(function(){var t=e._queue.splice(0,255);e._saveQueue(!1),e._batchSend(t,function(o,n){n&&n.data&&n.data.sid&&e._updateSid(n.data.sid),e._processTimeout=null,e._processQueue(),t.forEach(function(e){e.callback&&e.callback(o,n)})})},0))}},{key:"_batchSend",value:function(e,t){var o=this,n=e.map(function(e){return o._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),a={events:n,win:i.util.getLocation()},r=i.net.getRoute(i.net.routes.metrics_batch);this.sid&&(a.sid=this.sid),i.net.request.post(r,a,function(o,n){o&&i.report("Failed to send metrics batch",{err:o,res:n,items:e,route:r}),t&&t(o,n)})}},{key:"_normalizeEvent",value:function(e){e.m=e.m||{},e.key=e.key||e.m.key||i.key||void 0,this.sid&&(e.sid=this.sid),e.m=Object.assign({},e.m),Object.keys(a.Meta.exclude).forEach(function(t){return delete e.m[t]}),this.sourceCh&&(e.m.ref_ch=this.sourceCh),this.sourceCx&&(e.m.ref_cx=this.sourceCx),e.m.pgid=this.pageId,e.m.ok_ver=i.version,e.m=i.util.flatten(e.m,{arrayToCsv:!0}),Object.keys(e.m).forEach(function(t){"string"==typeof e.m[t]&&(e.m[t]=e.m[t].substr(0,255))}),t.referrer&&(e.ref=t.referrer),e.win=i.util.getLocation()}},{key:"_updateSid",value:function(t){!t||this.sid&&this.sid===t||(this.sid=t,e.localStorage[a.Params.name]=t,i.util.cookie.set(a.Params.name,t,a.Params.ttl))}},{key:"create",value:function(){for(var e=arguments.length,t=Array(e),o=0;ot?e:t},h=function(e,t){return"undefined"==typeof e?t:e};return n.forEach(function(e){a=i.ui.getElementPosition(e),r=d(a.x1,r),s=d(a.y1,s),c=p(a.x2,c),l=p(a.y2,l),u.push(a.x1,a.y1,a.x2,a.y2)}),t.m.wix1=h(r,o.x1),t.m.wiy1=h(s,o.y1),t.m.wix2=h(c,o.x2),t.m.wiy2=h(l,o.y2),t.m.wrps=u.map(function(e){return Math.floor(e)}).join(","),t}},{key:"addViewportInfo",value:function(e){var t=i.ui.getViewportSize(),o=i.ui.getScrollPosition();return e=e||{},e.m=e.m||{},e.m.vx1=o.x,e.m.vy1=o.y,e.m.vx2=o.x+t.vw,e.m.vy2=o.y+t.vh,e}},{key:"addEventInfo",value:function(e,t){var o=i.ui.getEventPosition(e);return t=t||{},t.m=t.m||{},t.m.et=o.et,t.m.ex=o.ex,t.m.ey=o.ey,t}},{key:"addEventMeta",value:function(e){e=e||{},e.m=e.m||{};for(var t=arguments.length,o=Array(t>1?t-1:0),n=1;n1?t-1:0),n=1;n=0&&this._events[e].splice(o,1)}}},{key:"emit",value:function(e){var t=void 0,o=void 0,n=void 0,i=[].slice.call(arguments,1);if(this._events[e])for(o=this._events[e].slice(),n=o.length,t=0;t1&&void 0!==arguments[1])||arguments[1];if(!this._strip||!t)return void 0!==e&&this._convert&&(e=this._convert(e)),void 0!==e?e:this._default}}],[{key:"array",value:function(t){return(new e).array(t)}},{key:"string",value:function(){return(new e).string()}},{key:"bool",value:function(){return(new e).bool()}},{key:"strip",value:function(){return(new e).strip()}},{key:"int",value:function(){return(new e)["int"]()}},{key:"float",value:function(){return(new e)["float"]()}}]),e}(),r._Widget=l}(window),function(i){var a=i.okanjo,r=a._Widget.Field,s=r.string,c=r.array,l=r["float"],u=r["int"],d=r.bool,p=a.metrics.constructor,h=a.ui.engine.constructor,k="filters",f="display",g="article_meta",m=.5,b=1e3,j=2,v=function(r){function v(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};o(this,v),n=a.util.flatten(n,{ignoreArrays:!0});var i=e(this,(v.__proto__||Object.getPrototypeOf(v)).call(this,t,n));return i.name="Placement",i._metricBase={},i._response=null,i._viewWatcherIv=null,i._viewedWatchers=[],n.no_init||i.init(),i}return t(v,r),n(v,[{key:"getSettings",value:function(){return{type:s().group(k),ids:c().group(k),q:s().group(k),url:s().group(k),url_referrer:s().group(k).strip(),url_selectors:s().group(k),url_paths:c().group(k),not_url_paths:c().group(k),organization_id:s().group(k),property_id:s().group(k),store_id:s().group(k),organization_name:s().group(k),property_name:s().group(k),store_name:s().group(k),external_id:s().group(k),sku:s().group(k),external_store_id:s().group(k),condition:s().group(k),manufacturer:s().group(k),upc:s().group(k),isbn:s().group(k),tags:c().group(k),category:c().group(k),pools:c().group(k),min_price:l().group(k),max_price:l().group(k),min_donation_percent:l().group(k),max_donation_percent:l().group(k),donation_to:s().group(k),sort_by:s().group(k),sort_direction:s().group(k),skip:u().group(k),take:u().group(k),placement_tests_only:d(),size:s().group(f),template_name:s().group(f),template_layout:s().group(f),template_theme:s().group(f),template_variant:s().group(f),template_cta_style:s().group(f),template_cta_text:s().group(f),template_cta_color:s().group(f),adx_unit_path:s().group(f),url_category:c().group(g),url_keywords:c().group(g),key:s().strip(),no_init:d().strip(),no_css:d().strip(),proxy_url:s().strip(),expandable:d().strip()["default"](!0),disable_inline_buy:d().strip()["default"](!1),disable_popup:d().strip()["default"](!1),backwards:s().strip(),testing:d().strip()}}},{key:"getConfig",value:function(){var e=this,t=this.getSettings(),o={filters:{},display:{},backfill:{},shortfill:{},article_meta:{}},n=/^backfill_(.+)$/,i=/^shortfill_(.+)$/;return Object.keys(this.config).forEach(function(a){var r=e.config[a],s=a,c=!1,l=!1,u=null,d=n.exec(a);d?(s=d[1],c=!0):(d=i.exec(a),d&&(s=d[1],l=!0)),t[s]&&(r=t[s].value(r),u=t[s].getGroup());var p=o;c?p=o.backfill:l&&(p=o.shortfill),!l&&u&&(p[u]=p[u]||{},p=p[u]),null===r?p[s]="":void 0!==r&&(p[s]=r)}),o}},{key:"load",value:function(){var e=this;this._setMetricBase(),this._fetchContent(function(t){t?e._reportWidgetLoad("fetch failed: "+t.statusCode||t.toString()):(e._mergeResponseSettings(),e._updateBaseMetaFromResponse(),e._showContent())})}},{key:"_setMetricBase",value:function(){var e=this._metricBase;e.ch=p.Channel.placement,e.cx=this.config.backwards||"auto",e.key=this.config.key,e.m=e.m||{},e.m.wgid=this.instanceId,this.config.testing&&(e.env=p.Environment.testing)}},{key:"_reportWidgetLoad",value:function(e){var t=this,o=this._response||{},n=o.data||{results:[]};this._metricBase.m.decl=e||"0",this._metricBase.m.res_bf=n.backfilled?1:0,this._metricBase.m.res_sf=n.shortfilled?1:0,this._metricBase.m.res_spltfl=n.splitfilled?1:0,this._metricBase.m.res_total=n.total||0,this._metricBase.m.res_type=n.type,this._metricBase.m.res_length=n.results.length,a.metrics.create(this._metricBase).type(p.Object.widget,p.Event.impression).meta(this.getConfig()).element(this.element).viewport().widget(this.element).send(),this._addOnceViewedHandler(this.element,function(){a.metrics.create(t._metricBase).type(p.Object.widget,p.Event.view).meta(t.getConfig()).element(t.element).viewport().widget(t.element).send()})}},{key:"_fetchContent",value:function(e){var t=this,o=this.getConfig(),n=this.config.key;a.metrics.sid&&(o.sid=a.metrics.sid),o.filters.url_referrer=this.config.url_referrer||i.location.href,o.wgid=this.instanceId,o.pgid=a.metrics.pageId,a.net.request.post(a.net.getRoute(a.net.routes.ads,null,this.config.sandbox?"sandbox":"live")+"?key="+encodeURIComponent(n),o,function(o,n){o?(a.report("Failed to retrieve placement content",o,{placement:t}),t.setMarkup(""),t.emit("error",o),e&&e(o)):(t._response=n,t.emit("data"),e&&e())})}},{key:"_mergeResponseSettings",value:function(){var e=this,t=this._response,o=t.data||{},n=o.settings||{};n.filters&&Object.keys(n.filters).forEach(function(t){e.config[t]=n.filters[t]}),n.display&&Object.keys(n.display).forEach(function(t){e.config[t]=n.display[t]})}},{key:"_updateBaseMetaFromResponse",value:function(){var e=(this._response||{}).data||{};this._metricBase.m=this._metricBase.m||{};var t=this._metricBase.m;e.article&&(t.aid=e.article.id),e.test&&e.test.enabled?(t.pten=1,t.ptid=e.test.id,t.ptseed=e.test.seed):t.pten=0}},{key:"_showContent",value:function(){var e=(this._response||{}).data||{};if(e.type===v.ContentTypes.products)this._showProducts();else if(e.type===v.ContentTypes.articles)this._showArticles();else if(e.type===v.ContentTypes.adx)this._showADX();else{var t="Unknown response content type: "+e.type;a.report(t,{placement:this}),this.setMarkup(""),this.emit("error",t),this._reportWidgetLoad(t)}}},{key:"_getClickThroughURL",value:function(e,t,o){var n=t.indexOf("?")>=0?"&":"?";return o=o||{},o.ok_msid=a.metrics.sid||"unknown",o.ok_ch=this._metricBase.ch,o.ok_cx=this._metricBase.cx,o._okjr=i.location.href.split(/[?#]/)[0],o.utm_source="okanjo",o.utm_campaign="smartserve",o.utm_medium="smartserve",t+=n+Object.keys(o).map(function(e){return encodeURIComponent(e)+"="+encodeURIComponent(o[e])}).join("&"),this.config.proxy_url&&(t=this.config.proxy_url+encodeURIComponent(t)),e.data({u:t}),e.toUrl()}},{key:"_handleResourceMouseDown",value:function(e,t,o){var n=t._cid,i=a.metrics.create(this._metricBase,{id:t.id}).type(e,p.Event.interaction).meta(this.getConfig()).meta({cid:n}).meta({bf:t.backfill?1:0,sf:t.shortfill?1:0,spltfl_seg:t.splitfill_segment||null}).event(o).element(o.currentTarget).viewport().widget(this.element),r="url_track_param",s="url";e===p.Object.product&&(r="buy_url_track_param",s="buy_url");var c={ok_cid:n};t[r]&&(c[t[r]]=n),i.data({ea:p.Action.click}),o.currentTarget.href=this._getClickThroughURL(i,t[s],c),t._clickId=n,t._event=i,t._additionalParams=c}},{key:"_getTemplate",value:function(e,t){var o=this.config.template_name;return o&&a.ui.engine.isTemplateRegistered(e+"."+o)||(o=t),e+"."+o}},{key:"_enforceLayoutOptions",value:function(){"leaderboard"===this.config.size||"large_mobile_banner"===this.config.size?(this.config.template_layout="list",this.config.template_cta_style="link"):"half_page"!==this.config.size&&"auto"!==this.config.size||(this.config.template_layout="list")}},{key:"_enforceSlabLayoutOptions",value:function(){"medium_rectangle"===this.config.size||"billboard"===this.config.size?(this.config.template_layout="grid","button"===this.config.template_cta_style&&(this.config.template_cta_style="link")):"half_page"===this.config.size?this.config.template_layout="grid":"leaderboard"===this.config.size||"large_mobile_banner"===this.config.size?(this.config.template_layout="list","button"===this.config.template_cta_style&&(this.config.template_cta_style="link")):"auto"===this.config.size?this.config.template_layout="list":"responsive"===this.config.size&&"button"===this.config.template_cta_style&&(this.config.template_cta_style="link")}},{key:"_registerCustomBranding",value:function(){var e=this.config.template_cta_color;if(e){var t=void 0,o="okanjo-wgid-"+this.instanceId;t="\n .okanjo-block2."+o+" .okanjo-resource-cta-button, .okanjo-block2."+o+" .okanjo-resource-buy-button { color: "+e+" !important; } \n .okanjo-block2."+o+".okanjo-cta-style-button .okanjo-resource-cta-button, .okanjo-block2."+o+".okanjo-cta-style-button .okanjo-resource-buy-button { border-color: "+e+" !important; } \n .okanjo-block2."+o+".okanjo-cta-style-button .okanjo-resource-cta-button:hover, .okanjo-block2."+o+".okanjo-cta-style-button .okanjo-resource-buy-button:hover { background: "+e+" !important; color: #fff !important; } \n ", +a.ui.engine.registerCss(o,t,{id:o}),a.ui.engine.ensureCss(o)}}},{key:"_addOnceViewedHandler",value:function(e,t){var o={element:e,successfulCount:0,handler:t};this._viewedWatchers.push(o),this._toggleViewWatcher(!0)}},{key:"_checkViewWatchers",value:function(){for(var e,t=0;t=m&&e.successfulCount++,e.successfulCount>=j&&(e.handler(),this._viewedWatchers.splice(t,1),t--);0===this._viewedWatchers.length&&this._toggleViewWatcher(!1)}},{key:"_toggleViewWatcher",value:function(e){e?null===this._viewWatcherIv&&(this._viewWatcherIv=setInterval(this._checkViewWatchers.bind(this),b/j)):(clearInterval(this._viewWatcherIv),this._viewWatcherIv=null)}},{key:"_showProducts",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},o=this._getTemplate(v.ContentTypes.products,v.DefaultTemplates.products);t.results.forEach(function(t,o){e.config.disable_inline_buy&&(t.inline_buy_url=null),t.inline_buy_url&&(t._escaped_inline_buy_url=encodeURIComponent(t.inline_buy_url)),t._image_url=t.image_urls?t.image_urls[0]:"",t._escaped_buy_url=encodeURIComponent(t.buy_url),t._price_formatted=h.formatCurrency(t.price),t._index=o});var n={css:!this.config.no_css};this.setMarkup(a.ui.engine.render(o,this,n)),0===t.results.length?(this.emit("empty"),this._reportWidgetLoad("empty")):this._reportWidgetLoad(),this.element.querySelectorAll("a").forEach(function(t){var o=t.getAttribute("data-id"),n=t.getAttribute("data-index");if(o&&n>=0){var i=e._response.data.results[n];i&&(t.addEventListener("mousedown",e._handleResourceMouseDown.bind(e,p.Object.product,i)),t.addEventListener("click",e._handleProductClick.bind(e,i)),a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.product,p.Event.impression).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.product,p.Event.view).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(".okanjo-resource-title").forEach(function(e){a.ui.ellipsify(e)}),a.ui.fitImages(this.element),this.emit("load")}},{key:"_handleProductClick",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(p.Object.product,e,t);var o=e._event,n=e._additionalParams;o.event(t);var r=!!e.inline_buy_url,s=!this.config.disable_popup&&r&&a.util.isMobile();if(s){t.preventDefault(),o.data({ea:p.Action.inline_click}).meta({popup:"true"});var c=this._getClickThroughURL(o,e.inline_buy_url,n);this._popupFrame=i.open(c,"okanjo-inline-buy-frame","width=400,height=400,location=yes,resizable=yes,scrollbars=yes"),this._popupFrame||(a.report("Popup blocker stopped buy experience from showing",{placement:this}),i.location.href=c)}else if(r){t.preventDefault();var l=document.createElement("iframe"),u={"class":"okanjo-inline-buy-frame",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:"",mozallowfullscreen:"",allowfullscreen:"",scrolling:"auto"};if(Object.keys(u).forEach(function(e){return l.setAttribute(e,u[e])}),n.expandable=this.config.expandable?1:0,!this.config.expandable){var d=this.element.querySelector(".okanjo-expansion-root");if(d){l.className+=" okanjo-ad-in-unit",l.setAttribute("height","100%"),l.setAttribute("width","100%"),d.appendChild(l);var h=a.ui.getElementSize(d);n.frame_height=h.height,n.frame_width=h.width,this.config.size&&(n.ad_size=this.config.size)}}o.data({ea:p.Action.inline_click}).meta({expandable:this.config.expandable?"true":"false"}),l.src=this._getClickThroughURL(o,e.inline_buy_url,n),l.parentNode||a.ui.modal.show(l)}else t.currentTarget.href=this._getClickThroughURL(o,e.buy_url,n)}},{key:"_showArticles",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},o=this._getTemplate(v.ContentTypes.articles,v.DefaultTemplates.articles);t.results.forEach(function(e,t){e._escaped_url=encodeURIComponent(e.url),e._index=t});var n={css:!this.config.no_css};this.setMarkup(a.ui.engine.render(o,this,n)),0===t.results.length?(this.emit("empty"),this._reportWidgetLoad("empty")):this._reportWidgetLoad(),this.element.querySelectorAll("a").forEach(function(t){var o=t.getAttribute("data-id"),n=t.getAttribute("data-index");if(o&&n>=0){var i=e._response.data.results[n];i&&(t.addEventListener("mousedown",e._handleResourceMouseDown.bind(e,p.Object.article,i)),t.addEventListener("click",e._handleArticleClick.bind(e,i)),a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.article,p.Event.impression).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.article,p.Event.view).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(".okanjo-resource-title").forEach(function(e){a.ui.ellipsify(e)}),a.ui.fitImages(this.element),this.emit("load")}},{key:"_handleArticleClick",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(p.Object.article,e,t);var o=e._event,n=e._additionalParams;o.event(t),t.currentTarget.href=this._getClickThroughURL(o,e.url,n)}},{key:"_showADX",value:function(){var e=this,t=(this._response||{data:{settings:{}}}).data||{settings:{}},o=this._getTemplate(v.ContentTypes.adx,v.DefaultTemplates.adx),n=null;if(this.config.size)if(v.Sizes[this.config.size])n=v.Sizes[this.config.size];else{var i=/^([0-9]+)x([0-9]+)$/i.exec(this.config.size);i&&(n={width:i[1],height:i[2]})}n||(n=v.Sizes["default"]);var r="/90447967/okanjo:",s=void 0;t.settings.display&&t.settings.display.adx_unit_path&&(r=t.settings.display.adx_unit_path,s="custom_ad_unit");var c={css:!this.config.no_css,size:n,adUnitPath:r};this.setMarkup(a.ui.engine.render(o,this,c)),this._reportWidgetLoad(s);var l=this.element.querySelector(".okanjo-adx-container");if(l){var u=document.createElement("iframe"),d={"class":"okanjo-adx-frame",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:"",mozallowfullscreen:"",allowfullscreen:"",scrolling:"auto",width:n.width,height:n.height};Object.keys(d).forEach(function(e){return u.setAttribute(e,d[e])}),l.appendChild(u);var h=a.metrics.create(this._metricBase).type(p.Object.thirdparty_ad,p.Event.interaction).meta(this.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(this.element).toUrl();u.contentWindow.trackImpression=function(){a.metrics.create(e._metricBase).type(p.Object.thirdparty_ad,p.Event.impression).meta(e.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(e.element).send(),e._addOnceViewedHandler(u,function(){a.metrics.create(e._metricBase).type(p.Object.thirdparty_ad,p.Event.view).meta(e.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(e.element).send()})},u.contentWindow.document.open(),u.contentWindow.document.write('\n<'+('script type="text/javascript" src="https://www.googletagservices.com/tag/js/gpt.js">\n googletag.pubads().addEventListener(\'slotRenderEnded\', function(e) { \n trackImpression(e);\n });\n googletag.pubads()\n .definePassback("'+r.replace(/"/g,'\\"')+'", [['+n.width+", "+n.height+']])\n .setClickUrl("'+h+'&u=")\n .display();\n<')+"/script>\n"),u.contentWindow.document.close()}this.emit("load")}}]),v}(a._Widget);return v.Sizes={medium_rectangle:{width:300,height:250},leaderboard:{width:728,height:90},large_mobile_banner:{width:320,height:100},half_page:{width:300,height:600},billboard:{width:970,height:250},button_2:{width:120,height:60},micro_bar:{width:88,height:31},portrait:{width:300,height:1050},rectangle:{width:180,height:150},super_leaderboard:{width:970,height:90},wide_skyscraper:{width:160,height:600},mobile_leaderboard:{width:320,height:50},small_square:{width:200,height:200},button_1:{width:120,height:90},full_banner:{width:468,height:60},half_banner:{width:234,height:60},large_rectangle:{width:336,height:280},pop_under:{width:720,height:300},three_to_one_rectangle:{width:300,height:100},skyscraper:{width:120,height:600},square:{width:250,height:250},square_button:{width:125,height:125},vertical_banner:{width:120,height:240},vertical_rectangle:{width:240,height:400}},v.Sizes["default"]=v.Sizes.medium_rectangle,v.ContentTypes={products:"products",articles:"articles",adx:"adx"},v.DefaultTemplates={products:"block2",articles:"block2",adx:"block2"},a.Placement=v}(window),function(i){var a=i.okanjo,r=function(i){function r(t,n){o(this,r),n=n||{};var i=n.no_init;n.no_init=!0;var s=e(this,(r.__proto__||Object.getPrototypeOf(r)).call(this,t,n));return a.warn("Product widget has been deprecated. Use Placement instead (may require configuration changes)",{widget:s}),i||(delete s.config.no_init,s.init()),s}return t(r,i),n(r,[{key:"_setCompatibilityOptions",value:function(){this.config.backwards="Product",this.config.type=a.Placement.ContentTypes.products,"sense"===this.config.mode?(this.config.url=this.config.url||"referrer",this.config.take=this.config.take||5):"single"===this.config.mode?(this.config.url=null,this.config.id&&(this.config.ids=[this.config.id]),this.config.take=1,delete this.config.id):(this.config.url=null,this.config.take=this.config.take||25),delete this.config.mode,this.config.sold_by&&(this.config.store_name=this.config.sold_by,delete this.config.sold_by),this.config.selectors&&(this.config.url_selectors=this.config.selectors,delete this.config.selectors),this.config.marketplace_id&&(this.config.property_id=this.config.marketplace_id,delete this.config.marketplace_id),"testing"===this.config.marketplace_status&&(this.config.sandbox=!0),delete this.config.marketplace_status,delete this.config.suboptimal,delete this.config.text}}]),r}(a.Placement);return a.Product=r}(window),function(i){var a=i.okanjo,r=function(i){function r(t,n){o(this,r),n=n||{};var i=n.no_init;n.no_init=!0;var s=e(this,(r.__proto__||Object.getPrototypeOf(r)).call(this,t,n));return a.warn("Ad widget has been deprecated. Use Placement instead (may require configuration changes)",{widget:s}),i||(delete s.config.no_init,s.init()),s}return t(r,i),n(r,[{key:"_setCompatibilityOptions",value:function(){this.config.backwards="Ad",this.config.type=a.Placement.ContentTypes.products,this.config.url=null,this.config.id?this.config.ids=[this.config.id]:a.warn("Ad widget should have parameter `id` set."),this.config.take=1,delete this.config.id,delete this.config.content}}]),r}(a.Placement);return a.Ad=r}(window),function(){/*! * mustache.js - Logic-less {{mustache}} templates with JavaScript * http://github.com/janl/mustache.js */ -!function(e,t){"object"===("undefined"==typeof exports?"undefined":i(exports))&&exports&&"string"!=typeof exports.nodeName?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):(e.Mustache={},t(e.Mustache))}(this,function(e){function t(e){return"function"==typeof e}function o(e){return g(e)?"array":"undefined"==typeof e?"undefined":i(e)}function n(e){return e.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g,"\\$&")}function a(e,t){return null!=e&&"object"===("undefined"==typeof e?"undefined":i(e))&&t in e}function r(e,t){return m.call(e,t)}function s(e){return!r(b,e)}function c(e){return String(e).replace(/[&<>"'`=\/]/g,function(e){return j[e]})}function l(t,o){function i(){if(m&&!b)for(;f.length;)delete k[f.pop()];else f=[];m=!1,b=!1}function a(e){if("string"==typeof e&&(e=e.split(_,2)),!g(e)||2!==e.length)throw new Error("Invalid tags: "+e);r=new RegExp(n(e[0])+"\\s*"),c=new RegExp("\\s*"+n(e[1])),l=new RegExp("\\s*"+n("}"+e[1]))}if(!t)return[];var r,c,l,h=[],k=[],f=[],m=!1,b=!1;a(o||e.tags);for(var j,C,E,A,O,T,P=new p(t);!P.eos();){if(j=P.pos,E=P.scanUntil(r))for(var z=0,S=E.length;z0?a[a.length-1][4]:n;break;default:i.push(t)}return n}function p(e){this.string=e,this.tail=e,this.pos=0}function h(e,t){this.view=e,this.cache={".":this.view},this.parent=t}function k(){this.cache={}}var f=Object.prototype.toString,g=Array.isArray||function(e){return"[object Array]"===f.call(e)},m=RegExp.prototype.test,b=/\S/,j={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="},v=/\s*/,_=/\s+/,y=/\s*=/,w=/\s*\}/,x=/#|\^|\/|>|\{|&|=|!/;p.prototype.eos=function(){return""===this.tail},p.prototype.scan=function(e){var t=this.tail.match(e);if(!t||0!==t.index)return"";var o=t[0];return this.tail=this.tail.substring(o.length),this.pos+=o.length,o},p.prototype.scanUntil=function(e){var t,o=this.tail.search(e);switch(o){case-1:t=this.tail,this.tail="";break;case 0:t="";break;default:t=this.tail.substring(0,o),this.tail=this.tail.substring(o)}return this.pos+=t.length,t},h.prototype.push=function(e){return new h(e,this)},h.prototype.lookup=function(e){var o,n=this.cache;if(n.hasOwnProperty(e))o=n[e];else{for(var i,r,s=this,c=!1;s;){if(e.indexOf(".")>0)for(o=s.view,i=e.split("."),r=0;null!=o&&r"===a?r=this.renderPartial(i,t,o,n):"&"===a?r=this.unescapedValue(i,t):"name"===a?r=this.escapedValue(i,t):"text"===a&&(r=this.rawValue(i)),void 0!==r&&(s+=r);return s},k.prototype.renderSection=function(e,o,n,a){function r(e){return s.render(e,o,n)}var s=this,c="",l=o.lookup(e[1]);if(l){if(g(l))for(var u=0,d=l.length;u"'`=\/]/g,function(e){return j[e]})}function l(t,o){function i(){if(m&&!b)for(;f.length;)delete k[f.pop()];else f=[];m=!1,b=!1}function a(e){if("string"==typeof e&&(e=e.split(_,2)),!g(e)||2!==e.length)throw new Error("Invalid tags: "+e);r=new RegExp(n(e[0])+"\\s*"),c=new RegExp("\\s*"+n(e[1])),l=new RegExp("\\s*"+n("}"+e[1]))}if(!t)return[];var r,c,l,h=[],k=[],f=[],m=!1,b=!1;a(o||e.tags);for(var j,C,E,A,O,T,P=new p(t);!P.eos();){if(j=P.pos,E=P.scanUntil(r))for(var z=0,S=E.length;z0?a[a.length-1][4]:n;break;default:i.push(t)}return n}function p(e){this.string=e,this.tail=e,this.pos=0}function h(e,t){this.view=e,this.cache={".":this.view},this.parent=t}function k(){this.cache={}}var f=Object.prototype.toString,g=Array.isArray||function(e){return"[object Array]"===f.call(e)},m=RegExp.prototype.test,b=/\S/,j={"&":"&","<":"<",">":">",'"':""","'":"'","/":"/","`":"`","=":"="},v=/\s*/,_=/\s+/,y=/\s*=/,w=/\s*\}/,x=/#|\^|\/|>|\{|&|=|!/;p.prototype.eos=function(){return""===this.tail},p.prototype.scan=function(e){var t=this.tail.match(e);if(!t||0!==t.index)return"";var o=t[0];return this.tail=this.tail.substring(o.length),this.pos+=o.length,o},p.prototype.scanUntil=function(e){var t,o=this.tail.search(e);switch(o){case-1:t=this.tail,this.tail="";break;case 0:t="";break;default:t=this.tail.substring(0,o),this.tail=this.tail.substring(o)}return this.pos+=t.length,t},h.prototype.push=function(e){return new h(e,this)},h.prototype.lookup=function(e){var o,n=this.cache;if(n.hasOwnProperty(e))o=n[e];else{for(var i,r,s=this,c=!1;s;){if(e.indexOf(".")>0)for(o=s.view,i=e.split("."),r=0;null!=o&&r"===a?r=this.renderPartial(i,t,o,n):"&"===a?r=this.unescapedValue(i,t):"name"===a?r=this.escapedValue(i,t):"text"===a&&(r=this.rawValue(i)),void 0!==r&&(s+=r);return s},k.prototype.renderSection=function(e,o,n,a){function r(e){return s.render(e,o,n)}var s=this,c="",l=o.lookup(e[1]);if(l){if(g(l))for(var u=0,d=l.length;u
',function(e){return e.config=this.config,e.instanceId=this.instanceId,e.metricParams=t.net.request.stringify(this._metricBase),e},{css:["adx.block2","okanjo.block2"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss("articles.block2",".okanjo-block2 .okanjo-article.okanjo-cta-style-button .okanjo-resource-title-container{height:52px}.okanjo-block2 .okanjo-article .okanjo-resource-title-container.modern{height:44px}.okanjo-block2.leaderboard .okanjo-article .okanjo-resource-title-container{margin-top:2px;margin-bottom:4px}",{id:"okanjo-article-block2"}),t.ui.__article_block2='',t.ui.engine.registerTemplate("articles.block2",t.ui.__article_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.articles=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),this._enforceLayoutOptions(),this._registerCustomBranding(".okanjo-article","button"),e},{css:["articles.block2","okanjo.block2"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss("articles.slab","",{id:"okanjo-article-slab"}),t.ui.engine.registerTemplate("articles.slab",t.ui.__article_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.blockClasses=["okanjo-slab"],e.articles=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),e.fitImage="okanjo-fit",this._enforceSlabLayoutOptions(),this._registerCustomBranding(".okanjo-article","button"),e},{css:["articles.slab","okanjo.slab","okanjo.block2"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss("okanjo.block2",'.okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2{color:#333;font-size:10px;font-family:inherit}.okanjo-block2:after,.okanjo-block2:before{content:" ";display:table}.okanjo-block2:after{clear:both}.okanjo-block2.theme-newsprint .okanjo-resource-seller-container{font-family:Georgia,serif}.okanjo-block2.theme-newsprint .okanjo-resource-title-container{font:13px/15px Georgia,serif}.okanjo-block2.theme-modern,.okanjo-block2.theme-newsprint .okanjo-resource-buy-button,.okanjo-block2.theme-newsprint .okanjo-resource-cta-button,.okanjo-block2.theme-newsprint .okanjo-resource-price-container{font-family:"Helvetica Neue",Helvetica,Roboto,Arial,sans-serif}.okanjo-block2 .okanjo-ellipses:after{content:"..."}.okanjo-block2 .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2 .okanjo-resource{display:block;float:left;background-color:#fff;box-sizing:content-box;width:148px;border:1px solid #e6e6e6;margin:0 -1px -1px 0}.okanjo-block2 .okanjo-resource:last-child{margin:0}.okanjo-block2 a{display:block;overflow:hidden;color:#333;text-decoration:none;padding:10px}.okanjo-block2 a:hover{color:inherit;text-decoration:none}.okanjo-block2 .okanjo-resource-image-container{float:left;overflow:hidden;text-align:center;vertical-align:middle;width:100%;height:128px;line-height:127px;margin:0 0 3px}.okanjo-block2 .okanjo-resource-image{max-width:100%;max-height:100%;border:none;vertical-align:middle}.okanjo-block2 .okanjo-resource-info-container{float:left;height:auto;width:100%}.okanjo-block2 .okanjo-resource-publisher-container,.okanjo-block2 .okanjo-resource-seller-container{color:#999;font-size:11px;line-height:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource-title-container{overflow:hidden;margin-top:3px;margin-bottom:4px;font-weight:700;font-size:12px;line-height:14px;height:45px;word-wrap:break-word}.okanjo-block2 .okanjo-resource-title-container span{display:inline-block}.lt-ie8.okanjo-block2 .okanjo-resource-title-container span{display:inline;zoom:1}.okanjo-block2 .okanjo-resource-price-container{font-size:15px;line-height:1;margin-bottom:5px}.okanjo-block2 .okanjo-resource-buy-button,.okanjo-block2 .okanjo-resource-cta-button{color:#09f;font-size:12px;line-height:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource.list{width:298px;height:122px}.okanjo-block2 .okanjo-resource.list a{padding:11px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-title-container{margin-top:4px;margin-bottom:6px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px;margin:0 11px 0 0}.okanjo-block2 .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-title-container{height:30px}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button{display:block;text-align:center;line-height:26px;padding:0 8px;border:1px solid #09f;border-radius:2px;transition:50ms ease}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:hover,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:hover{background:#09f;color:#fff}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:active,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:active{box-shadow:inset 0 3px 10px rgba(0,0,0,.15)}.okanjo-block2.medium_rectangle{width:300px;height:250px;overflow:hidden}.okanjo-block2.medium_rectangle .okanjo-resource{width:148px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource:first-child{width:149px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource.list{width:298px;height:123px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child{height:124px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child a{padding-top:12px}.okanjo-block2.leaderboard{width:728px;height:90px;overflow:hidden}.okanjo-block2.leaderboard .okanjo-resource{width:241px;height:88px}.okanjo-block2.leaderboard .okanjo-resource:first-child{width:242px}.okanjo-block2.leaderboard .okanjo-resource a{padding:7px}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-image-container{width:74px;height:74px;line-height:1px;margin:0 7px 0 0}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:11px;line-height:13px;height:26px;margin-top:1px;margin-bottom:4px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-price-container{margin-bottom:3px}.okanjo-block2.leaderboard.theme-newsprint .okanjo-resource-title-container{font:700 11px/13px Georgia,serif}.okanjo-block2.half_page{width:300px;height:600px;overflow:hidden}.okanjo-block2.half_page .okanjo-resource{height:118px}.okanjo-block2.half_page .okanjo-resource:nth-last-child(n+2){height:119px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-image-container{width:96px;height:96px}.okanjo-block2.large_mobile_banner{width:320px;height:100px;overflow:hidden}.okanjo-block2.large_mobile_banner .okanjo-resource{width:318px;height:98px}.okanjo-block2.large_mobile_banner .okanjo-resource a{padding:6px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-image-container{width:86px;height:86px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-title-container{height:30px}.okanjo-block2.billboard{width:970px;height:250px;overflow:hidden}.okanjo-block2.billboard .okanjo-resource{width:160px;height:248px}.okanjo-block2.billboard .okanjo-resource:first-child{width:163px;height:248px}.okanjo-block2.billboard .okanjo-resource.list{width:322px;height:123px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.auto{font-size:1em;width:100%}.okanjo-block2.auto .okanjo-resource{width:100%;height:auto;border-left:none;border-right:none}.okanjo-block2.auto .okanjo-resource a{max-width:500px;width:95%;margin:0 auto;padding:2.5%}.okanjo-block2.auto .okanjo-resource.list{height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-image-container{width:18%;height:auto;line-height:1px}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none;margin-left:21%;width:79%}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-publisher-container,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-seller-container{height:auto;font-size:12px;line-height:1.2}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-price-container{height:auto;font-size:15px;line-height:1.5}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-title-container{font-size:15px;line-height:1.4;height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-cta-button{display:inline-block;font-size:14px;line-height:1.8;margin-bottom:-1.7%}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-price-container{line-height:1.3}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-title-container{line-height:1.25}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-cta-button{font-size:13px}.okanjo-inline-buy-frame{display:block;height:100%;width:100%}',{id:"okanjo-block2"})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss("okanjo.core","",{id:"okanjo-core"}),t.ui.engine.registerCss("okanjo.modal",'.okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}html.okanjo-modal-active{overflow:hidden!important}html.okanjo-modal-active body{overflow:hidden!important;margin:0}.okanjo-modal-margin-fix{margin-right:15px!important}.okanjo-modal-container{position:fixed;top:0;right:0;left:0;bottom:0;z-index:2147483647;background-color:rgba(0,0,0,.65);transition-duration:210ms;transition-property:background-color}.okanjo-modal-container.lt-ie9{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNiWAoAAK4AqL41IDIAAAAASUVORK5CYII=)}.okanjo-modal-container.okanjo-modal-fade-out{background-color:rgba(0,0,0,0)}.okanjo-modal-container.okanjo-modal-fade-out .okanjo-modal-window{opacity:0;transform:scale(.95,.95) translateY(50px)}.okanjo-modal-container.okanjo-modal-hidden{display:none!important}.okanjo-modal-container .okanjo-modal-window{position:relative;max-width:900px;width:90%;background:0 0;margin:56px auto 40px;opacity:1;transform:scale(1,1) translateY(0);transition-duration:210ms;transition-timing-function:cubic-bezier(.13,.025,.15,1);transition-timing-function:cubic-bezier(.13,.025,.15,1.15);transition-property:opacity}.okanjo-modal-container .okanjo-modal-window:after,.okanjo-modal-container .okanjo-modal-window:before{content:" ";display:table}.okanjo-modal-container .okanjo-modal-window:after{clear:both}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header{padding-top:5px;padding-bottom:5px;border-bottom:1px solid #d7d7d7}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header img{height:50px;width:auto}.okanjo-modal-container .okanjo-modal-window-skin{width:auto;height:auto;box-shadow:0 10px 25px rgba(0,0,0,.5);position:absolute;background:#fff;border-radius:4px;top:0;bottom:0;left:0;right:0}.okanjo-modal-container .okanjo-modal-window-outer{position:absolute;top:15px;left:15px;bottom:15px;right:15px;vertical-align:top}.okanjo-modal-container .okanjo-modal-window-inner{position:relative;width:100%;height:100%;-webkit-overflow-scrolling:touch;overflow:auto}.okanjo-modal-container .okanjo-modal-window-inner iframe{height:100%;width:100%;margin-right:-15px}.okanjo-modal-container .okanjo-modal-close-button{color:#fff;cursor:pointer;position:absolute;right:0;top:-48px;text-align:right;font-size:40px;line-height:1em;overflow:visible;width:40px;height:40px}',{id:"okanjo-modal"}),t.ui.engine.registerTemplate("okanjo.error",'{{ message }} {{#code}} Reference: {{ code }} {{/code}}',{css:["okanjo.core"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss("okanjo.slab",".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab img.okanjo-fit{height:100%;width:100%;object-fit:cover}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.list .okanjo-resource-title-container{height:95px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource{width:298px}.okanjo-block2.okanjo-slab .okanjo-resource-publisher-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab .okanjo-resource-title-container{height:58px;font-size:16px;line-height:19px}.okanjo-block2.okanjo-slab .okanjo-resource.list .okanjo-resource-title-container{font-size:14px;height:60px}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource-title-container{font:16px/19px Georgia,serif}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource.list .okanjo-resource-title-container{font-size:15px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource-list{display:flex;flex-wrap:wrap;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource{width:inherit;flex-grow:1;flex-shrink:0;flex-basis:33.3333%;flex-basis:200px;display:flex;align-items:center;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list{flex-basis:33.3333%;flex-basis:250px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list a{width:100%}.okanjo-block2.okanjo-slab.responsive .okanjo-resource:last-child{margin:0 -1px -1px 0}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource,.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource:first-child{width:298px;height:248px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:13px;line-height:15px;height:50px;margin-top:1px;margin-bottom:4px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard.theme-newsprint .okanjo-resource .okanjo-resource-title-container{font:700 13px/15px Georgia,serif}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource-title-container{height:80px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource{width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:nth-last-child(n+2){width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:first-child{height:299px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-image-container{width:100%;height:180px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-title-container{margin-bottom:3px;height:77px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource-title-container{height:57px;margin-bottom:8px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource-title-container{height:116px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource{width:298px;height:198px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:nth-last-child(n+2){width:298px;height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:first-child{height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-image-container{width:100%;height:136px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-title-container{height:42px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource,.okanjo-block2.okanjo-slab.billboard .okanjo-resource:first-child{width:322px;height:248px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-info-container{margin-left:111px;width:auto}",{id:"okanjo-slab"})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss("products.block2","",{id:"okanjo-product-block2"}),t.ui.__product_block2='',t.ui.engine.registerTemplate("products.block2",t.ui.__product_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.products=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),this._enforceLayoutOptions(),this._registerCustomBranding(".okanjo-product","buy-button"),e},{css:["products.block2","okanjo.block2","okanjo.modal"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss("products.slab",".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:14px;height:40px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:30px;font-size:12px;line-height:14px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button.theme-newsprint .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:13px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:0;height:32px;font-size:14px}.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:47px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;font-size:14px;line-height:16px;margin-bottom:2px}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:50px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;margin-bottom:0;line-height:15px;font-size:15px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:33px;font-size:15px;line-height:15px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-button-container,.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-price-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:auto;margin-bottom:2px;line-height:20px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-price-container{margin-bottom:0}.okanjo-block2.okanjo-slab.auto.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-price-container{margin-bottom:3px}",{id:"okanjo-product-slab"}),t.ui.engine.registerTemplate("products.slab",t.ui.__product_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.blockClasses=["okanjo-slab"],e.products=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),e.fitImage="okanjo-fit",this._enforceSlabLayoutOptions(),this._registerCustomBranding(".okanjo-product","button"),e},{css:["products.slab","okanjo.slab","okanjo.block2"]})}(window)}(okanjo); //# sourceMappingURL=okanjo-bundle.min.js.map diff --git a/dist/okanjo-bundle.min.js.map b/dist/okanjo-bundle.min.js.map index a970938..f4e9b57 100644 --- a/dist/okanjo-bundle.min.js.map +++ b/dist/okanjo-bundle.min.js.map @@ -1 +1 @@ -{"version":3,"names":[],"mappings":"","sources":["okanjo-bundle.js"],"sourcesContent":["/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */\n/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */\n!function(e,t){\"function\"==typeof define&&define.amd?define([],t):\"object\"==typeof exports?module.exports=t():e.okanjo=t()}(this,function(){function e(e,t){if(!e)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!t||\"object\"!=typeof t&&\"function\"!=typeof t?e:t}function t(e,t){if(\"function\"!=typeof t&&null!==t)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function o(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}var n=function(){function e(e,t){for(var o=0;o0?1:-1)*Math.floor(Math.abs(t)):t},n=Math.pow(2,53)-1,i=function(e){var t=o(e);return Math.min(Math.max(t,0),n)};return function(e){var o=this,n=Object(e);if(null==e)throw new TypeError(\"Array.from requires an array-like object - not null or undefined\");var a,r=arguments.length>1?arguments[1]:void 0;if(\"undefined\"!=typeof r){if(!t(r))throw new TypeError(\"Array.from: when provided, the second argument must be a function\");arguments.length>2&&(a=arguments[2])}for(var s,c=i(n.length),l=t(o)?Object(new o(c)):new Array(c),u=0;u>>0;if(\"function\"!=typeof e)throw new TypeError(\"predicate must be a function\");for(var n=arguments[1],i=0;i>>0;if(\"function\"!=typeof e)throw new TypeError(\"predicate must be a function\");for(var n=arguments[1],i=0;i>>0;if(0===i)return!1;for(var a=0|t,r=Math.max(a>=0?a:i-Math.abs(a),0);r=0&&t.splice(a,1)}l.error(\"[Okanjo v\"+d.version+\"]: \"+n.stack),t.length&&l.error.apply(l,[\"Additional information:\"].concat(t))},warn:function(e){for(var t=arguments.length,o=Array(t>1?t-1:0),n=1;n1&&void 0!==arguments[1]?arguments[1]:{},o={};return void 0!==e&&null!==e&&Object.keys(e).forEach(function(n){if(e[n]instanceof Date)t.dateToIso?o[n]=e[n].toISOString():o[n]=e[n];else if(\"object\"===i(e[n])&&null!==e[n])if(Array.isArray(e[n])&&t.ignoreArrays===!0)o[n]=e[n];else if(Array.isArray(e[n])&&t.arrayToCsv===!0)o[n]=e[n].join(\",\");else{var a=d.util.flatten(e[n],t);Object.keys(a).forEach(function(e){o[n+\"_\"+e]=a[e]})}else o[n]=e[n]}),o},d.util.shortid=function(t){var o=\"ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC\",n=e.crypto||e.msCrypto||\"function\"==typeof require&&require(\"crypto\"),i=function(){if(n&&n.randomBytes)return 48&n.randomBytes(1)[0];if(!n||!n.getRandomValues)return 48&Math.floor(256*Math.random());var e=new Uint8Array(1);return n.getRandomValues(e),48&e[0]},a=function(e){for(var t=0,n=void 0,a=\"\";!n;)a+=o[e>>4*t&15|i()],n=e0&&(e+=a(c)),e+=a(o)}}(),d.util.getLocation=function(){return e.location!==e.parent.location?t.referrer:t.location.href},d.ui={getScrollPosition:function(){return{x:o?e.pageXOffset:n?t.documentElement.scrollLeft:t.body.scrollLeft,y:o?e.pageYOffset:n?t.documentElement.scrollTop:t.body.scrollTop}},getElementSize:function(t,o){var n={height:t.offsetHeight,width:t.offsetWidth},i=t.currentStyle||e.getComputedStyle(t);return o&&(n.height+=parseInt(i.marginTop)+parseInt(i.marginBottom),n.width+=parseInt(i.marginLeft)+parseInt(i.marginRight)),n},getPageSize:function(){var e=t.querySelector(\"body\"),o=t.documentElement;return{w:Math.max(e.scrollWidth,e.offsetWidth,o.clientWidth,o.scrollWidth,o.offsetWidth),h:Math.max(e.scrollHeight,e.offsetHeight,o.clientHeight,o.scrollHeight,o.offsetHeight)}},getViewportSize:function(){var o=n?t.documentElement:t.body,i=o.clientWidth,a=o.clientHeight,r=e.innerWidth||0,s=e.innerHeight||0,c=r&&i>r||s&&a>s;return{vw:c?r:i,vh:c?s:a}},getEventPosition:function(e){var o=e.pageX,n=e.pageY,i=t.body,a=t.documentElement,r=\"scrollLeft\",s=\"scrollTop\",c=e.__proto__.constructor.name;return{et:c,ex:void 0===o?e.clientX+i[r]+a[r]:o,ey:void 0===n?e.clientY+i[s]+a[s]:n}},getElementPosition:function(e){var o=\"Could not get position of element. Did you attach the element to the DOM before initializing?\";try{var n=e.getBoundingClientRect(),i=t.body.getBoundingClientRect();return t.body.contains(e)||d.report(o,e),{x1:n.left-i.left,y1:n.top-i.top,x2:n.right-i.left,y2:n.bottom-i.top}}catch(a){return d.report(o,{exception:a,element:e}),{x1:0,y1:0,x2:0,y2:0,err:1}}},_getIntersection:function(e,t,o){var n=Math.max(e.x1,t.x),i=Math.min(e.x2,t.x+o.vw),a=Math.max(e.y1,t.y),r=Math.min(e.y2,t.y+o.vh),s=Math.max(0,i-n)*Math.max(0,r-a),c=(e.x2-e.x1)*(e.y2-e.y1);return{intersectionArea:s,elementArea:c}},isElementVisible:function(e){return e.offsetWidth>0&&e.offsetHeight>0},getPercentageInViewport:function(e){var t=d.ui.getElementPosition(e),o=d.ui.getScrollPosition(),n=d.ui.getViewportSize();if(t.err)return 0;var i=d.ui._getIntersection(t,o,n),a=i.intersectionArea,r=i.elementArea;return r<=0?0:a/r}},d.ui.ellipsify=function(e,o){for(var n=o||e.parentNode,i=d.ui.getElementSize(n).height,a=void 0!==e.textContent,s=a?e.textContent:e.innerText,c=\"\",l=5e3,u=function(e){return c=e.substr(0,e.length-3)+c,\"...\"};d.ui.getElementSize(e).height>i&&s.length>0&&l-- >0;)s=a?e.textContent:e.innerText,s=s.replace(r,u),a?e.textContent=s:e.innerText=s;if(c.length>0){var p=t.createElement(\"span\"),h=t.createElement(\"span\");p.setAttribute(\"class\",\"okanjo-ellipses\"),h.setAttribute(\"class\",\"okanjo-visually-hidden\"),a?(p.textContent=s.substr(0,s.length-3),h.textContent=c):(p.innerText=s.substr(0,s.length-3),h.innerText=c),e.innerHTML=\"\",e.appendChild(p),e.appendChild(h)}},d.ui.fitImages=function(e){\"objectFit\"in t.documentElement.style==!1&&e.querySelectorAll(\"img.okanjo-fit\").forEach(function(e){e.style.display=\"none\";var t=e.parentNode;t.style.backgroundSize=\"cover\",t.style.backgroundImage=\"url(\"+e.src+\")\",t.style.backgroundposition=\"center center\"})},e.okanjo=d}(window,document);return function(e){var t=/^application\\/json/,o=e.okanjo;o.net.request=function(n,i,a,r){\"function\"==typeof a&&(r=a,a=void 0);var s=new(e.XMLHttpRequest||e.ActiveXObject)(\"MSXML2.XMLHTTP.3.0\"),c=!1,l=function(e,t){c||(c=!0,r(e,t))};o.net.request.timeout&&(s.timeout=o.net.request.timeout),s.ontimeout=function(e){l({statusCode:504,error:\"Request timed out\",message:\"Something went wrong\",attributes:{event:e,xhr:s}})},s.onreadystatechange=function(e){if(4===s.readyState)if(s.status>0){var o=void 0;o=t.test(s.getResponseHeader(\"Content-Type\"))?JSON.parse(s.responseText):{statusCode:s.status,data:s.responseText},s.status>=200&&s.status<300?l(null,o):l(o)}else l({statusCode:503,error:\"Request failed\",message:\"Something went wrong\",attributes:{event:e,xhr:s}})},s.open(n.toUpperCase(),i),s.withCredentials=!0,[\"POST\",\"PUT\",\"PATCH\"].includes(n.toUpperCase())&&(s.setRequestHeader(\"Content-Type\",\"application/json; charset=utf-8\"),void 0!==a&&(a=JSON.stringify(a))),s.send(a||void 0)},o.net.request.get=o.net.request.bind(this,\"GET\"),o.net.request.post=o.net.request.bind(this,\"POST\"),o.net.request.put=o.net.request.bind(this,\"PUT\"),o.net.request[\"delete\"]=o.net.request.bind(this,\"DELETE\");var n=function(e){return null===e||void 0===e?\"\":encodeURIComponent(\"\"+e)},a=function(e,t){return t?t+\"[\"+n(e)+\"]\":n(e)};o.net.request.stringify=function(e,t){var r=[];return t=t||\"\",Object.keys(e).forEach(function(s){var c=e[s];if(Array.isArray(c))c.forEach(function(e){return r.push(a(s,t)+\"=\"+n(e))});else if(\"object\"===(\"undefined\"==typeof c?\"undefined\":i(c))&&null!==c){var l=o.net.request.stringify(c,a(s,t));l&&r.push(l)}else void 0!==c&&r.push(a(s,t)+\"=\"+n(c))}),r.join(\"&\")}}(window),function(e,t){e.okanjo.util.cookie={set:function(o,n,i){var a=new Date;a.setDate(a.getDate()+i);var r=i?\" Expires=\"+a.toUTCString()+\";\":\"\",s=\" Path=/\",c=\"https:\"===e.location.protocol?\" Secure;\":\"\",l=encodeURI(n)+\";\"+r+c+\" SameSite=None;\"+s;t.cookie=o+\"=\"+l},get:function(e){var o=null;return t.cookie.split(\";\").find(function(t){var n=t.substr(0,t.indexOf(\"=\")).trim(),i=t.substr(t.indexOf(\"=\")+1);return n===e&&(o=decodeURI(i),!0)}),o}}}(window,document),function(e,t){var a=e.okanjo,r=function(){function e(){o(this,e),this._templates={},this._css={},this.classDetects=\"\"}return n(e,[{key:\"registerTemplate\",value:function(e,t,o,n){if(\"object\"===(\"undefined\"==typeof t?\"undefined\":i(t))){if(void 0===t.nodeType)throw new Error(\"Parameter template must be a string or a DOM element\");t=t.innerHTML,a.lib.Mustache.parse(t)}else if(\"string\"!=typeof t)throw new Error(\"Parameter template must be a string or a DOM element\");if(3===arguments.length&&\"object\"===(\"undefined\"==typeof o?\"undefined\":i(o))?(n=o,o=null):n=n||{},o&&\"function\"!=typeof o)throw new Error(\"Parameter beforeRender must be a function\");this._templates[e]={markup:t,options:n,beforeRender:o}}},{key:\"registerCss\",value:function(e,t,o){if(o=o||{},\"object\"===(\"undefined\"==typeof t?\"undefined\":i(t))){if(void 0===t.nodeType)throw new Error(\"Parameter css must be a string or a DOM element\")}else if(\"string\"!=typeof t)throw new Error(\"Parameter css must be a string or a DOM element\");this._css[e]={markup:t,options:o}}},{key:\"isTemplateRegistered\",value:function(e){return!!this._templates[e]}},{key:\"isCssRegistered\",value:function(e){return!!this._css[e]}},{key:\"ensureCss\",value:function(e){if(this._css[e]){var o=this._css[e],n=void 0===o.markup.nodeType?o.options.id||\"okanjo-css-\"+e:null;if(n){var i=t.querySelector(\"#\"+n.replace(/\\./g,\"\\\\.\"));if(!i){var r=t.head,s=t.createElement(\"style\");if(s.id=n,s.setAttribute(\"type\",\"text/css\"),s.hasOwnProperty?s.innerHTML=o.markup:s.styleSheet.cssText=o.markup,r)r.appendChild(s);else{var c=t.body;c?c.appendChild(s):a.report(\"Cannot add CSS template to document. Does it not have a body or head?\")}}}}else a.report('Attempted to add CSS template \"'+e+'\" to the DOM, however it does not appear to be registered?')}},{key:\"render\",value:function(e,t,o){var n=this;o=o||{};var i=this._templates[e];return i.beforeRender&&(o=i.beforeRender.call(t,o)),o.okanjo=a,o.okanjoMetricUrl=a.net.endpoint.replace(/^https?:\\/\\//,\"\"),o.now=function(){return(new Date).getTime()},o.classDetects=this.classDetects,o.blockClasses&&Array.isArray(o.blockClasses)&&(o.classDetects+=\" \"+o.blockClasses.join(\" \"),delete o.blockClasses),o.css!==!1&&i.options.css&&i.options.css.length>0&&(i.options.css.forEach(function(e){return n.ensureCss(e)}),delete o.css),a.lib.Mustache.render(i.markup,o)}}]),e}();r.formatCurrency=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:\".\",n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:\",\",i=e<0?\"-\":\"\",a=parseInt(e=Math.abs(+e||0).toFixed(t))+\"\",r=a.length;return r=r>3?r%3:0,i+(r?a.substr(0,r)+n:\"\")+a.substr(r).replace(/(\\d{3})(?=\\d)/g,\"$1\"+n)+(t?o+Math.abs(e-a).toFixed(t).slice(2):\"\")},a.ui.engine=new r}(window,document),function(e,t){var o=e.okanjo,n=o.util.isMobile(),i=!1,a=void 0,r=void 0,s=void 0,c=void 0,l=void 0,u=void 0,d=void 0,p=void 0,h=void 0,k=function(){a=t.documentElement||t.querySelector(\"html\"),r=t.body||t.querySelector(\"body\"),s=t.createElement(\"div\"),c=t.createElement(\"div\"),l=t.createElement(\"div\"),u=t.createElement(\"div\"),d=t.createElement(\"div\"),p=t.createElement(\"div\"),h=t.createElement(\"iframe\"),s.setAttribute(\"class\",\"okanjo-modal-container okanjo-modal-hidden \"),c.setAttribute(\"class\",\"okanjo-modal-window\"),l.setAttribute(\"class\",\"okanjo-modal-window-skin\"),u.setAttribute(\"class\",\"okanjo-modal-window-outer\"),d.setAttribute(\"class\",\"okanjo-modal-window-inner\"),p.setAttribute(\"class\",\"okanjo-modal-close-button\"),h.setAttribute(\"class\",\"okanjo-inline-buy-frame\"),h.setAttribute(\"frameborder\",\"0\"),h.setAttribute(\"vspace\",\"0\"),h.setAttribute(\"hspace\",\"0\"),h.setAttribute(\"webkitallowfullscreen\",\"\"),h.setAttribute(\"mozallowfullscreen\",\"\"),h.setAttribute(\"allowfullscreen\",\"\"),h.setAttribute(\"scrolling\",\"auto\"),p.innerHTML=\"×\",d.appendChild(h),u.appendChild(d),l.appendChild(u),c.appendChild(l),c.appendChild(p),s.appendChild(c),r.appendChild(s)},f=function(e,t,o){e.addEventListener?e.addEventListener(t,o,!1):e.attachEvent(\"on\"+t,o)},g=function(){return e.innerHeight||t.documentElement.clientHeight},m=function(){c.style.height=g()-80+\"px\"},b=function(){f(e,\"orientationchange\",function(){for(var e=0;e<2;e++)setTimeout(m,1e3*e+10)}),f(e,\"resize\",function(){setTimeout(m,100)}),f(s,\"click\",y),f(c,\"click\",function(e){e.preventDefault(),e.stopPropagation()}),f(p,\"click\",function(e){e.preventDefault(),e.stopPropagation(),y()})},j=function(e,t){e.className+=\" \"+t},v=function(e,t){e.className=e.className.replace(new RegExp(\" *?\"+t),\"\")},_=function(){v(s,\"okanjo-modal-hidden\"),j(s,\"okanjo-modal-fade-out\"),m(),j(a,\"okanjo-modal-active\"),n||j(a,\"okanjo-modal-margin-fix\"),setTimeout(function(){v(s,\"okanjo-modal-fade-out\")},10)},y=function(){j(s,\"okanjo-modal-fade-out\"),setTimeout(function(){v(s,\"okanjo-modal-fade-out\"),j(s,\"okanjo-modal-hidden\"),v(a,\"okanjo-modal-active\"),n||v(a,\"okanjo-modal-margin-fix\")},210)},w=function(e){d.innerHTML=\"\",\"string\"==typeof e?d.innerHTML=e:d.appendChild(e)};return o.ui.modal={show:function(e){i||(i=!0,k(),b()),w(e),_()},hide:function(){y()}},o.ui.modal}(window,document),function(e,t){var i=e.okanjo,a=function(){function a(){o(this,a),this._queue=this._getStoredQueue(),this._processTimeout=null,this.pageId=i.util.shortid(),this.defaultChannel=a.Channel.external,this.sid=null,this.sourceCh=null,this.sourceCx=null,this._checkUrlForReferral()}return n(a,[{key:\"_getStoredQueue\",value:function(){if(!e.localStorage[a.Params.queue])return[];try{var t=JSON.parse(e.localStorage[a.Params.queue]);return Array.isArray(t)?t:(i.report(\"Stored queue is not a queue\",{queue:t}),[])}catch(o){return i.report(\"Failed to load metric queue from storage\",{err:o}),[]}}},{key:\"_saveQueue\",value:function(t){var o=this;t?(this._saveQueueTimeout&&clearTimeout(this._saveQueueTimeout),this._saveQueueTimeout=setTimeout(function(){o._saveQueue(!1),o._saveQueueTimeout=null},100)):e.localStorage[a.Params.queue]=JSON.stringify(this._queue)}},{key:\"_checkUrlForReferral\",value:function(){var t=i.util.getPageArguments(!0),o=t[a.Params.name],n=e.localStorage[a.Params.name]||i.util.cookie.get(a.Params.name),r=t[a.Params.context],s=t[a.Params.channel];o&&n&&o!==n&&this.trackEvent({object_type:a.Object.metric_session,event_type:a.Event.correlation,id:o+\"_\"+n,ch:this.defaultChannel,_noProcess:!0}),this.sid=n||o||null,this.sourceCh=s||null,this.sourceCx=r||null}},{key:\"trackEvent\",value:function(e,t){return e.object_type&&e.event_type?void this._push(e,t):void i.report(\"Invalid metric to track (missing object_type or event_type)\",{event:e})}},{key:\"trackPageView\",value:function(e,t){e=e||{},e.object_type=a.Object.page,e.event_type=a.Event.view,e.id=e.id||i.util.getLocation(),e.ch=e.ch||this.defaultChannel,this.trackEvent(e,t)}},{key:\"_push\",value:function(e,t){this._queue.push({event:e,callback:t}),this._saveQueue(!0),e._noProcess?delete e._noProcess:this._processQueue()}},{key:\"_processQueue\",value:function(){var e=this;!this._processTimeout&&this._queue.length>0&&(this._processTimeout=setTimeout(function(){var t=e._queue.splice(0,255);e._saveQueue(!1),e._batchSend(t,function(o,n){n&&n.data&&n.data.sid&&e._updateSid(n.data.sid),e._processTimeout=null,e._processQueue(),t.forEach(function(e){e.callback&&e.callback(o,n)})})},0))}},{key:\"_batchSend\",value:function(e,t){var o=this,n=e.map(function(e){return o._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),a={events:n,win:i.util.getLocation()},r=i.net.getRoute(i.net.routes.metrics_batch);this.sid&&(a.sid=this.sid),i.net.request.post(r,a,function(o,n){o&&i.report(\"Failed to send metrics batch\",{err:o,res:n,items:e,route:r}),t&&t(o,n)})}},{key:\"_normalizeEvent\",value:function(e){e.m=e.m||{},e.key=e.key||e.m.key||i.key||void 0,this.sid&&(e.sid=this.sid),e.m=Object.assign({},e.m),Object.keys(a.Meta.exclude).forEach(function(t){return delete e.m[t]}),this.sourceCh&&(e.m.ref_ch=this.sourceCh),this.sourceCx&&(e.m.ref_cx=this.sourceCx),e.m.pgid=this.pageId,e.m.ok_ver=i.version,e.m=i.util.flatten(e.m,{arrayToCsv:!0}),Object.keys(e.m).forEach(function(t){\"string\"==typeof e.m[t]&&(e.m[t]=e.m[t].substr(0,255))}),t.referrer&&(e.ref=t.referrer),e.win=i.util.getLocation()}},{key:\"_updateSid\",value:function(t){!t||this.sid&&this.sid===t||(this.sid=t,e.localStorage[a.Params.name]=t,i.util.cookie.set(a.Params.name,t,a.Params.ttl))}},{key:\"create\",value:function(){for(var e=arguments.length,t=Array(e),o=0;ot?e:t},h=function(e,t){return\"undefined\"==typeof e?t:e};return n.forEach(function(e){a=i.ui.getElementPosition(e),r=d(a.x1,r),s=d(a.y1,s),c=p(a.x2,c),l=p(a.y2,l),u.push(a.x1,a.y1,a.x2,a.y2)}),t.m.wix1=h(r,o.x1),t.m.wiy1=h(s,o.y1),t.m.wix2=h(c,o.x2),t.m.wiy2=h(l,o.y2),t.m.wrps=u.map(function(e){return Math.floor(e)}).join(\",\"),t}},{key:\"addViewportInfo\",value:function(e){var t=i.ui.getViewportSize(),o=i.ui.getScrollPosition();return e=e||{},e.m=e.m||{},e.m.vx1=o.x,e.m.vy1=o.y,e.m.vx2=o.x+t.vw,e.m.vy2=o.y+t.vh,e}},{key:\"addEventInfo\",value:function(e,t){var o=i.ui.getEventPosition(e);return t=t||{},t.m=t.m||{},t.m.et=o.et,t.m.ex=o.ex,t.m.ey=o.ey,t}},{key:\"addEventMeta\",value:function(e){e=e||{},e.m=e.m||{};for(var t=arguments.length,o=Array(t>1?t-1:0),n=1;n1?t-1:0),n=1;n=0&&this._events[e].splice(o,1)}}},{key:\"emit\",value:function(e){var t=void 0,o=void 0,n=void 0,i=[].slice.call(arguments,1);if(this._events[e])for(o=this._events[e].slice(),n=o.length,t=0;t1&&void 0!==arguments[1])||arguments[1];if(!this._strip||!t)return void 0!==e&&this._convert&&(e=this._convert(e)),void 0!==e?e:this._default}}],[{key:\"array\",value:function(t){return(new e).array(t)}},{key:\"string\",value:function(){return(new e).string()}},{key:\"bool\",value:function(){return(new e).bool()}},{key:\"strip\",value:function(){return(new e).strip()}},{key:\"int\",value:function(){return(new e)[\"int\"]()}},{key:\"float\",value:function(){return(new e)[\"float\"]()}}]),e}(),r._Widget=l}(window),function(i){var a=i.okanjo,r=a._Widget.Field,s=r.string,c=r.array,l=r[\"float\"],u=r[\"int\"],d=r.bool,p=a.metrics.constructor,h=a.ui.engine.constructor,k=\"filters\",f=\"display\",g=\"article_meta\",m=.5,b=1e3,j=2,v=function(r){function v(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};o(this,v),n=a.util.flatten(n,{ignoreArrays:!0});var i=e(this,(v.__proto__||Object.getPrototypeOf(v)).call(this,t,n));return i.name=\"Placement\",i._metricBase={},i._response=null,i._viewWatcherIv=null,i._viewedWatchers=[],n.no_init||i.init(),i}return t(v,r),n(v,[{key:\"getSettings\",value:function(){return{type:s().group(k),ids:c().group(k),q:s().group(k),url:s().group(k),url_referrer:s().group(k).strip(),url_selectors:s().group(k),url_paths:c().group(k),not_url_paths:c().group(k),organization_id:s().group(k),property_id:s().group(k),store_id:s().group(k),organization_name:s().group(k),property_name:s().group(k),store_name:s().group(k),external_id:s().group(k),sku:s().group(k),external_store_id:s().group(k),condition:s().group(k),manufacturer:s().group(k),upc:s().group(k),isbn:s().group(k),tags:c().group(k),category:c().group(k),pools:c().group(k),min_price:l().group(k),max_price:l().group(k),min_donation_percent:l().group(k),max_donation_percent:l().group(k),donation_to:s().group(k),sort_by:s().group(k),sort_direction:s().group(k),skip:u().group(k),take:u().group(k),placement_tests_only:d(),size:s().group(f),template_name:s().group(f),template_layout:s().group(f),template_theme:s().group(f),template_variant:s().group(f),template_cta_style:s().group(f),template_cta_text:s().group(f),template_cta_color:s().group(f),adx_unit_path:s().group(f),url_category:c().group(g),url_keywords:c().group(g),key:s().strip(),no_init:d().strip(),proxy_url:s().strip(),expandable:d().strip()[\"default\"](!0),disable_inline_buy:d().strip()[\"default\"](!1),disable_popup:d().strip()[\"default\"](!1),backwards:s().strip(),testing:d().strip()}}},{key:\"getConfig\",value:function(){var e=this,t=this.getSettings(),o={filters:{},display:{},backfill:{},shortfill:{},article_meta:{}},n=/^backfill_(.+)$/,i=/^shortfill_(.+)$/;return Object.keys(this.config).forEach(function(a){var r=e.config[a],s=a,c=!1,l=!1,u=null,d=n.exec(a);d?(s=d[1],c=!0):(d=i.exec(a),d&&(s=d[1],l=!0)),t[s]&&(r=t[s].value(r),u=t[s].getGroup());var p=o;c?p=o.backfill:l&&(p=o.shortfill),!l&&u&&(p[u]=p[u]||{},p=p[u]),null===r?p[s]=\"\":void 0!==r&&(p[s]=r)}),o}},{key:\"load\",value:function(){var e=this;this._setMetricBase(),this._fetchContent(function(t){t?e._reportWidgetLoad(\"fetch failed: \"+t.statusCode||t.toString()):(e._mergeResponseSettings(),e._updateBaseMetaFromResponse(),e._showContent())})}},{key:\"_setMetricBase\",value:function(){var e=this._metricBase;e.ch=p.Channel.placement,e.cx=this.config.backwards||\"auto\",e.key=this.config.key,e.m=e.m||{},e.m.wgid=this.instanceId,this.config.testing&&(e.env=p.Environment.testing)}},{key:\"_reportWidgetLoad\",value:function(e){var t=this,o=this._response||{},n=o.data||{results:[]};this._metricBase.m.decl=e||\"0\",this._metricBase.m.res_bf=n.backfilled?1:0,this._metricBase.m.res_sf=n.shortfilled?1:0,this._metricBase.m.res_spltfl=n.splitfilled?1:0,this._metricBase.m.res_total=n.total||0,this._metricBase.m.res_type=n.type,this._metricBase.m.res_length=n.results.length,a.metrics.create(this._metricBase).type(p.Object.widget,p.Event.impression).meta(this.getConfig()).element(this.element).viewport().widget(this.element).send(),this._addOnceViewedHandler(this.element,function(){a.metrics.create(t._metricBase).type(p.Object.widget,p.Event.view).meta(t.getConfig()).element(t.element).viewport().widget(t.element).send()})}},{key:\"_fetchContent\",value:function(e){var t=this,o=this.getConfig(),n=this.config.key;a.metrics.sid&&(o.sid=a.metrics.sid),o.filters.url_referrer=this.config.url_referrer||i.location.href,o.wgid=this.instanceId,o.pgid=a.metrics.pageId,a.net.request.post(a.net.getRoute(a.net.routes.ads,null,this.config.sandbox?\"sandbox\":\"live\")+\"?key=\"+encodeURIComponent(n),o,function(o,n){o?(a.report(\"Failed to retrieve placement content\",o,{placement:t}),t.setMarkup(\"\"),t.emit(\"error\",o),e&&e(o)):(t._response=n,t.emit(\"data\"),e&&e())})}},{key:\"_mergeResponseSettings\",value:function(){var e=this,t=this._response,o=t.data||{},n=o.settings||{};n.filters&&Object.keys(n.filters).forEach(function(t){e.config[t]=n.filters[t]}),n.display&&Object.keys(n.display).forEach(function(t){e.config[t]=n.display[t]})}},{key:\"_updateBaseMetaFromResponse\",value:function(){var e=(this._response||{}).data||{};this._metricBase.m=this._metricBase.m||{};var t=this._metricBase.m;e.article&&(t.aid=e.article.id),e.test&&e.test.enabled?(t.pten=1,t.ptid=e.test.id,t.ptseed=e.test.seed):t.pten=0}},{key:\"_showContent\",value:function(){var e=(this._response||{}).data||{};if(e.type===v.ContentTypes.products)this._showProducts();else if(e.type===v.ContentTypes.articles)this._showArticles();else if(e.type===v.ContentTypes.adx)this._showADX();else{var t=\"Unknown response content type: \"+e.type;a.report(t,{placement:this}),this.setMarkup(\"\"),this.emit(\"error\",t),this._reportWidgetLoad(t)}}},{key:\"_getClickThroughURL\",value:function(e,t,o){var n=t.indexOf(\"?\")>=0?\"&\":\"?\";return o=o||{},o.ok_msid=a.metrics.sid||\"unknown\",o.ok_ch=this._metricBase.ch,o.ok_cx=this._metricBase.cx,o._okjr=i.location.href.split(/[?#]/)[0],o.utm_source=\"okanjo\",o.utm_campaign=\"smartserve\",o.utm_medium=\"smartserve\",t+=n+Object.keys(o).map(function(e){return encodeURIComponent(e)+\"=\"+encodeURIComponent(o[e])}).join(\"&\"),this.config.proxy_url&&(t=this.config.proxy_url+encodeURIComponent(t)),e.data({u:t}),e.toUrl()}},{key:\"_handleResourceMouseDown\",value:function(e,t,o){var n=t._cid,i=a.metrics.create(this._metricBase,{id:t.id}).type(e,p.Event.interaction).meta(this.getConfig()).meta({cid:n}).meta({bf:t.backfill?1:0,sf:t.shortfill?1:0,spltfl_seg:t.splitfill_segment||null}).event(o).element(o.currentTarget).viewport().widget(this.element),r=\"url_track_param\",s=\"url\";e===p.Object.product&&(r=\"buy_url_track_param\",s=\"buy_url\");var c={ok_cid:n};t[r]&&(c[t[r]]=n),i.data({ea:p.Action.click}),o.currentTarget.href=this._getClickThroughURL(i,t[s],c),t._clickId=n,t._event=i,t._additionalParams=c}},{key:\"_getTemplate\",value:function(e,t){var o=this.config.template_name;return o&&a.ui.engine.isTemplateRegistered(e+\".\"+o)||(o=t),e+\".\"+o}},{key:\"_enforceLayoutOptions\",value:function(){\"leaderboard\"===this.config.size||\"large_mobile_banner\"===this.config.size?(this.config.template_layout=\"list\",this.config.template_cta_style=\"link\"):\"half_page\"!==this.config.size&&\"auto\"!==this.config.size||(this.config.template_layout=\"list\")}},{key:\"_enforceSlabLayoutOptions\",value:function(){\"medium_rectangle\"===this.config.size||\"billboard\"===this.config.size?(this.config.template_layout=\"grid\",\"button\"===this.config.template_cta_style&&(this.config.template_cta_style=\"link\")):\"half_page\"===this.config.size?this.config.template_layout=\"grid\":\"leaderboard\"===this.config.size||\"large_mobile_banner\"===this.config.size?(this.config.template_layout=\"list\",\"button\"===this.config.template_cta_style&&(this.config.template_cta_style=\"link\")):\"auto\"===this.config.size?this.config.template_layout=\"list\":\"responsive\"===this.config.size&&\"button\"===this.config.template_cta_style&&(this.config.template_cta_style=\"link\")}},{key:\"_registerCustomBranding\",value:function(){var e=this.config.template_cta_color;if(e){var t=void 0,o=\"okanjo-wgid-\"+this.instanceId;t=\"\\n .okanjo-block2.\"+o+\" .okanjo-resource-cta-button, .okanjo-block2.\"+o+\" .okanjo-resource-buy-button { color: \"+e+\" !important; } \\n .okanjo-block2.\"+o+\".okanjo-cta-style-button .okanjo-resource-cta-button, .okanjo-block2.\"+o+\".okanjo-cta-style-button .okanjo-resource-buy-button { border-color: \"+e+\" !important; } \\n .okanjo-block2.\"+o+\".okanjo-cta-style-button .okanjo-resource-cta-button:hover, .okanjo-block2.\"+o+\".okanjo-cta-style-button .okanjo-resource-buy-button:hover { background: \"+e+\" !important; color: #fff !important; } \\n \",\na.ui.engine.registerCss(o,t,{id:o}),a.ui.engine.ensureCss(o)}}},{key:\"_addOnceViewedHandler\",value:function(e,t){var o={element:e,successfulCount:0,handler:t};this._viewedWatchers.push(o),this._toggleViewWatcher(!0)}},{key:\"_checkViewWatchers\",value:function(){for(var e,t=0;t=m&&e.successfulCount++,e.successfulCount>=j&&(e.handler(),this._viewedWatchers.splice(t,1),t--);0===this._viewedWatchers.length&&this._toggleViewWatcher(!1)}},{key:\"_toggleViewWatcher\",value:function(e){e?null===this._viewWatcherIv&&(this._viewWatcherIv=setInterval(this._checkViewWatchers.bind(this),b/j)):(clearInterval(this._viewWatcherIv),this._viewWatcherIv=null)}},{key:\"_showProducts\",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},o=this._getTemplate(v.ContentTypes.products,v.DefaultTemplates.products);t.results.forEach(function(t,o){e.config.disable_inline_buy&&(t.inline_buy_url=null),t.inline_buy_url&&(t._escaped_inline_buy_url=encodeURIComponent(t.inline_buy_url)),t._image_url=t.image_urls?t.image_urls[0]:\"\",t._escaped_buy_url=encodeURIComponent(t.buy_url),t._price_formatted=h.formatCurrency(t.price),t._index=o}),this.setMarkup(a.ui.engine.render(o,this)),0===t.results.length?(this.emit(\"empty\"),this._reportWidgetLoad(\"empty\")):this._reportWidgetLoad(),this.element.querySelectorAll(\"a\").forEach(function(t){var o=t.getAttribute(\"data-id\"),n=t.getAttribute(\"data-index\");if(o&&n>=0){var i=e._response.data.results[n];i&&(t.addEventListener(\"mousedown\",e._handleResourceMouseDown.bind(e,p.Object.product,i)),t.addEventListener(\"click\",e._handleProductClick.bind(e,i)),a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.product,p.Event.impression).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.product,p.Event.view).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(\".okanjo-resource-title\").forEach(function(e){a.ui.ellipsify(e)}),a.ui.fitImages(this.element),this.emit(\"load\")}},{key:\"_handleProductClick\",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(p.Object.product,e,t);var o=e._event,n=e._additionalParams;o.event(t);var r=!!e.inline_buy_url,s=!this.config.disable_popup&&r&&a.util.isMobile();if(s){t.preventDefault(),o.data({ea:p.Action.inline_click}).meta({popup:\"true\"});var c=this._getClickThroughURL(o,e.inline_buy_url,n);this._popupFrame=i.open(c,\"okanjo-inline-buy-frame\",\"width=400,height=400,location=yes,resizable=yes,scrollbars=yes\"),this._popupFrame||(a.report(\"Popup blocker stopped buy experience from showing\",{placement:this}),i.location.href=c)}else if(r){t.preventDefault();var l=document.createElement(\"iframe\"),u={\"class\":\"okanjo-inline-buy-frame\",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:\"\",mozallowfullscreen:\"\",allowfullscreen:\"\",scrolling:\"auto\"};if(Object.keys(u).forEach(function(e){return l.setAttribute(e,u[e])}),n.expandable=this.config.expandable?1:0,!this.config.expandable){var d=this.element.querySelector(\".okanjo-expansion-root\");if(d){l.className+=\" okanjo-ad-in-unit\",l.setAttribute(\"height\",\"100%\"),l.setAttribute(\"width\",\"100%\"),d.appendChild(l);var h=a.ui.getElementSize(d);n.frame_height=h.height,n.frame_width=h.width,this.config.size&&(n.ad_size=this.config.size)}}o.data({ea:p.Action.inline_click}).meta({expandable:this.config.expandable?\"true\":\"false\"}),l.src=this._getClickThroughURL(o,e.inline_buy_url,n),l.parentNode||a.ui.modal.show(l)}else t.currentTarget.href=this._getClickThroughURL(o,e.buy_url,n)}},{key:\"_showArticles\",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},o=this._getTemplate(v.ContentTypes.articles,v.DefaultTemplates.articles);t.results.forEach(function(e,t){e._escaped_url=encodeURIComponent(e.url),e._index=t}),this.setMarkup(a.ui.engine.render(o,this)),0===t.results.length?(this.emit(\"empty\"),this._reportWidgetLoad(\"empty\")):this._reportWidgetLoad(),this.element.querySelectorAll(\"a\").forEach(function(t){var o=t.getAttribute(\"data-id\"),n=t.getAttribute(\"data-index\");if(o&&n>=0){var i=e._response.data.results[n];i&&(t.addEventListener(\"mousedown\",e._handleResourceMouseDown.bind(e,p.Object.article,i)),t.addEventListener(\"click\",e._handleArticleClick.bind(e,i)),a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.article,p.Event.impression).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.article,p.Event.view).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(\".okanjo-resource-title\").forEach(function(e){a.ui.ellipsify(e)}),a.ui.fitImages(this.element),this.emit(\"load\")}},{key:\"_handleArticleClick\",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(p.Object.article,e,t);var o=e._event,n=e._additionalParams;o.event(t),t.currentTarget.href=this._getClickThroughURL(o,e.url,n)}},{key:\"_showADX\",value:function(){var e=this,t=(this._response||{data:{settings:{}}}).data||{settings:{}},o=this._getTemplate(v.ContentTypes.adx,v.DefaultTemplates.adx),n=null;if(this.config.size)if(v.Sizes[this.config.size])n=v.Sizes[this.config.size];else{var i=/^([0-9]+)x([0-9]+)$/i.exec(this.config.size);i&&(n={width:i[1],height:i[2]})}n||(n=v.Sizes[\"default\"]);var r=\"/90447967/okanjo:\",s=void 0;t.settings.display&&t.settings.display.adx_unit_path&&(r=t.settings.display.adx_unit_path,s=\"custom_ad_unit\");var c={size:n,adUnitPath:r};this.setMarkup(a.ui.engine.render(o,this,c)),this._reportWidgetLoad(s);var l=this.element.querySelector(\".okanjo-adx-container\");if(l){var u=document.createElement(\"iframe\"),d={\"class\":\"okanjo-adx-frame\",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:\"\",mozallowfullscreen:\"\",allowfullscreen:\"\",scrolling:\"auto\",width:n.width,height:n.height};Object.keys(d).forEach(function(e){return u.setAttribute(e,d[e])}),l.appendChild(u);var h=a.metrics.create(this._metricBase).type(p.Object.thirdparty_ad,p.Event.interaction).meta(this.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(this.element).toUrl();u.contentWindow.trackImpression=function(){a.metrics.create(e._metricBase).type(p.Object.thirdparty_ad,p.Event.impression).meta(e.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(e.element).send(),e._addOnceViewedHandler(u,function(){a.metrics.create(e._metricBase).type(p.Object.thirdparty_ad,p.Event.view).meta(e.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(e.element).send()})},u.contentWindow.document.open(),u.contentWindow.document.write('\\n<'+('script type=\"text/javascript\" src=\"https://www.googletagservices.com/tag/js/gpt.js\">\\n googletag.pubads().addEventListener(\\'slotRenderEnded\\', function(e) { \\n trackImpression(e);\\n });\\n googletag.pubads()\\n .definePassback(\"'+r.replace(/\"/g,'\\\\\"')+'\", [['+n.width+\", \"+n.height+']])\\n .setClickUrl(\"'+h+'&u=\")\\n .display();\\n<')+\"/script>\\n\"),u.contentWindow.document.close()}this.emit(\"load\")}}]),v}(a._Widget);return v.Sizes={medium_rectangle:{width:300,height:250},leaderboard:{width:728,height:90},large_mobile_banner:{width:320,height:100},half_page:{width:300,height:600},billboard:{width:970,height:250},button_2:{width:120,height:60},micro_bar:{width:88,height:31},portrait:{width:300,height:1050},rectangle:{width:180,height:150},super_leaderboard:{width:970,height:90},wide_skyscraper:{width:160,height:600},mobile_leaderboard:{width:320,height:50},small_square:{width:200,height:200},button_1:{width:120,height:90},full_banner:{width:468,height:60},half_banner:{width:234,height:60},large_rectangle:{width:336,height:280},pop_under:{width:720,height:300},three_to_one_rectangle:{width:300,height:100},skyscraper:{width:120,height:600},square:{width:250,height:250},square_button:{width:125,height:125},vertical_banner:{width:120,height:240},vertical_rectangle:{width:240,height:400}},v.Sizes[\"default\"]=v.Sizes.medium_rectangle,v.ContentTypes={products:\"products\",articles:\"articles\",adx:\"adx\"},v.DefaultTemplates={products:\"block2\",articles:\"block2\",adx:\"block2\"},a.Placement=v}(window),function(i){var a=i.okanjo,r=function(i){function r(t,n){o(this,r),n=n||{};var i=n.no_init;n.no_init=!0;var s=e(this,(r.__proto__||Object.getPrototypeOf(r)).call(this,t,n));return a.warn(\"Product widget has been deprecated. Use Placement instead (may require configuration changes)\",{widget:s}),i||(delete s.config.no_init,s.init()),s}return t(r,i),n(r,[{key:\"_setCompatibilityOptions\",value:function(){this.config.backwards=\"Product\",this.config.type=a.Placement.ContentTypes.products,\"sense\"===this.config.mode?(this.config.url=this.config.url||\"referrer\",this.config.take=this.config.take||5):\"single\"===this.config.mode?(this.config.url=null,this.config.id&&(this.config.ids=[this.config.id]),this.config.take=1,delete this.config.id):(this.config.url=null,this.config.take=this.config.take||25),delete this.config.mode,this.config.sold_by&&(this.config.store_name=this.config.sold_by,delete this.config.sold_by),this.config.selectors&&(this.config.url_selectors=this.config.selectors,delete this.config.selectors),this.config.marketplace_id&&(this.config.property_id=this.config.marketplace_id,delete this.config.marketplace_id),\"testing\"===this.config.marketplace_status&&(this.config.sandbox=!0),delete this.config.marketplace_status,delete this.config.suboptimal,delete this.config.text}}]),r}(a.Placement);return a.Product=r}(window),function(i){var a=i.okanjo,r=function(i){function r(t,n){o(this,r),n=n||{};var i=n.no_init;n.no_init=!0;var s=e(this,(r.__proto__||Object.getPrototypeOf(r)).call(this,t,n));return a.warn(\"Ad widget has been deprecated. Use Placement instead (may require configuration changes)\",{widget:s}),i||(delete s.config.no_init,s.init()),s}return t(r,i),n(r,[{key:\"_setCompatibilityOptions\",value:function(){this.config.backwards=\"Ad\",this.config.type=a.Placement.ContentTypes.products,this.config.url=null,this.config.id?this.config.ids=[this.config.id]:a.warn(\"Ad widget should have parameter `id` set.\"),this.config.take=1,delete this.config.id,delete this.config.content}}]),r}(a.Placement);return a.Ad=r}(window),function(){/*!\n * mustache.js - Logic-less {{mustache}} templates with JavaScript\n * http://github.com/janl/mustache.js\n */\n!function(e,t){\"object\"===(\"undefined\"==typeof exports?\"undefined\":i(exports))&&exports&&\"string\"!=typeof exports.nodeName?t(exports):\"function\"==typeof define&&define.amd?define([\"exports\"],t):(e.Mustache={},t(e.Mustache))}(this,function(e){function t(e){return\"function\"==typeof e}function o(e){return g(e)?\"array\":\"undefined\"==typeof e?\"undefined\":i(e)}function n(e){return e.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g,\"\\\\$&\")}function a(e,t){return null!=e&&\"object\"===(\"undefined\"==typeof e?\"undefined\":i(e))&&t in e}function r(e,t){return m.call(e,t)}function s(e){return!r(b,e)}function c(e){return String(e).replace(/[&<>\"'`=\\/]/g,function(e){return j[e]})}function l(t,o){function i(){if(m&&!b)for(;f.length;)delete k[f.pop()];else f=[];m=!1,b=!1}function a(e){if(\"string\"==typeof e&&(e=e.split(_,2)),!g(e)||2!==e.length)throw new Error(\"Invalid tags: \"+e);r=new RegExp(n(e[0])+\"\\\\s*\"),c=new RegExp(\"\\\\s*\"+n(e[1])),l=new RegExp(\"\\\\s*\"+n(\"}\"+e[1]))}if(!t)return[];var r,c,l,h=[],k=[],f=[],m=!1,b=!1;a(o||e.tags);for(var j,C,E,A,O,T,P=new p(t);!P.eos();){if(j=P.pos,E=P.scanUntil(r))for(var z=0,S=E.length;z0?a[a.length-1][4]:n;break;default:i.push(t)}return n}function p(e){this.string=e,this.tail=e,this.pos=0}function h(e,t){this.view=e,this.cache={\".\":this.view},this.parent=t}function k(){this.cache={}}var f=Object.prototype.toString,g=Array.isArray||function(e){return\"[object Array]\"===f.call(e)},m=RegExp.prototype.test,b=/\\S/,j={\"&\":\"&\",\"<\":\"<\",\">\":\">\",'\"':\""\",\"'\":\"'\",\"/\":\"/\",\"`\":\"`\",\"=\":\"=\"},v=/\\s*/,_=/\\s+/,y=/\\s*=/,w=/\\s*\\}/,x=/#|\\^|\\/|>|\\{|&|=|!/;p.prototype.eos=function(){return\"\"===this.tail},p.prototype.scan=function(e){var t=this.tail.match(e);if(!t||0!==t.index)return\"\";var o=t[0];return this.tail=this.tail.substring(o.length),this.pos+=o.length,o},p.prototype.scanUntil=function(e){var t,o=this.tail.search(e);switch(o){case-1:t=this.tail,this.tail=\"\";break;case 0:t=\"\";break;default:t=this.tail.substring(0,o),this.tail=this.tail.substring(o)}return this.pos+=t.length,t},h.prototype.push=function(e){return new h(e,this)},h.prototype.lookup=function(e){var o,n=this.cache;if(n.hasOwnProperty(e))o=n[e];else{for(var i,r,s=this,c=!1;s;){if(e.indexOf(\".\")>0)for(o=s.view,i=e.split(\".\"),r=0;null!=o&&r\"===a?r=this.renderPartial(i,t,o,n):\"&\"===a?r=this.unescapedValue(i,t):\"name\"===a?r=this.escapedValue(i,t):\"text\"===a&&(r=this.rawValue(i)),void 0!==r&&(s+=r);return s},k.prototype.renderSection=function(e,o,n,a){function r(e){return s.render(e,o,n)}var s=this,c=\"\",l=o.lookup(e[1]);if(l){if(g(l))for(var u=0,d=l.length;u
',function(e){return e.config=this.config,e.instanceId=this.instanceId,e.metricParams=t.net.request.stringify(this._metricBase),e},{css:[\"adx.block2\",\"okanjo.block2\"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"articles.block2\",\".okanjo-block2 .okanjo-article.okanjo-cta-style-button .okanjo-resource-title-container{height:52px}.okanjo-block2 .okanjo-article .okanjo-resource-title-container.modern{height:44px}.okanjo-block2.leaderboard .okanjo-article .okanjo-resource-title-container{margin-top:2px;margin-bottom:4px}\",{id:\"okanjo-article-block2\"}),t.ui.__article_block2='',t.ui.engine.registerTemplate(\"articles.block2\",t.ui.__article_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.articles=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),this._enforceLayoutOptions(),this._registerCustomBranding(\".okanjo-article\",\"button\"),e},{css:[\"articles.block2\",\"okanjo.block2\"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"articles.slab\",\"\",{id:\"okanjo-article-slab\"}),t.ui.engine.registerTemplate(\"articles.slab\",t.ui.__article_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.blockClasses=[\"okanjo-slab\"],e.articles=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),e.fitImage=\"okanjo-fit\",this._enforceSlabLayoutOptions(),this._registerCustomBranding(\".okanjo-article\",\"button\"),e},{css:[\"articles.slab\",\"okanjo.slab\",\"okanjo.block2\"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"okanjo.block2\",'.okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2{color:#333;font-size:10px;font-family:inherit}.okanjo-block2:after,.okanjo-block2:before{content:\" \";display:table}.okanjo-block2:after{clear:both}.okanjo-block2.theme-newsprint .okanjo-resource-seller-container{font-family:Georgia,serif}.okanjo-block2.theme-newsprint .okanjo-resource-title-container{font:13px/15px Georgia,serif}.okanjo-block2.theme-modern,.okanjo-block2.theme-newsprint .okanjo-resource-buy-button,.okanjo-block2.theme-newsprint .okanjo-resource-cta-button,.okanjo-block2.theme-newsprint .okanjo-resource-price-container{font-family:\"Helvetica Neue\",Helvetica,Roboto,Arial,sans-serif}.okanjo-block2 .okanjo-ellipses:after{content:\"...\"}.okanjo-block2 .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2 .okanjo-resource{display:block;float:left;background-color:#fff;box-sizing:content-box;width:148px;border:1px solid #e6e6e6;margin:0 -1px -1px 0}.okanjo-block2 .okanjo-resource:last-child{margin:0}.okanjo-block2 a{display:block;overflow:hidden;color:#333;text-decoration:none;padding:10px}.okanjo-block2 a:hover{color:inherit;text-decoration:none}.okanjo-block2 .okanjo-resource-image-container{float:left;overflow:hidden;text-align:center;vertical-align:middle;width:100%;height:128px;line-height:127px;margin:0 0 3px}.okanjo-block2 .okanjo-resource-image{max-width:100%;max-height:100%;border:none;vertical-align:middle}.okanjo-block2 .okanjo-resource-info-container{float:left;height:auto;width:100%}.okanjo-block2 .okanjo-resource-publisher-container,.okanjo-block2 .okanjo-resource-seller-container{color:#999;font-size:11px;line-height:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource-title-container{overflow:hidden;margin-top:3px;margin-bottom:4px;font-weight:700;font-size:12px;line-height:14px;height:45px;word-wrap:break-word}.okanjo-block2 .okanjo-resource-title-container span{display:inline-block}.lt-ie8.okanjo-block2 .okanjo-resource-title-container span{display:inline;zoom:1}.okanjo-block2 .okanjo-resource-price-container{font-size:15px;line-height:1;margin-bottom:5px}.okanjo-block2 .okanjo-resource-buy-button,.okanjo-block2 .okanjo-resource-cta-button{color:#09f;font-size:12px;line-height:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource.list{width:298px;height:122px}.okanjo-block2 .okanjo-resource.list a{padding:11px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-title-container{margin-top:4px;margin-bottom:6px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px;margin:0 11px 0 0}.okanjo-block2 .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-title-container{height:30px}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button{display:block;text-align:center;line-height:26px;padding:0 8px;border:1px solid #09f;border-radius:2px;transition:50ms ease}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:hover,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:hover{background:#09f;color:#fff}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:active,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:active{box-shadow:inset 0 3px 10px rgba(0,0,0,.15)}.okanjo-block2.medium_rectangle{width:300px;height:250px;overflow:hidden}.okanjo-block2.medium_rectangle .okanjo-resource{width:148px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource:first-child{width:149px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource.list{width:298px;height:123px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child{height:124px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child a{padding-top:12px}.okanjo-block2.leaderboard{width:728px;height:90px;overflow:hidden}.okanjo-block2.leaderboard .okanjo-resource{width:241px;height:88px}.okanjo-block2.leaderboard .okanjo-resource:first-child{width:242px}.okanjo-block2.leaderboard .okanjo-resource a{padding:7px}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-image-container{width:74px;height:74px;line-height:1px;margin:0 7px 0 0}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:11px;line-height:13px;height:26px;margin-top:1px;margin-bottom:4px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-price-container{margin-bottom:3px}.okanjo-block2.leaderboard.theme-newsprint .okanjo-resource-title-container{font:700 11px/13px Georgia,serif}.okanjo-block2.half_page{width:300px;height:600px;overflow:hidden}.okanjo-block2.half_page .okanjo-resource{height:118px}.okanjo-block2.half_page .okanjo-resource:nth-last-child(n+2){height:119px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-image-container{width:96px;height:96px}.okanjo-block2.large_mobile_banner{width:320px;height:100px;overflow:hidden}.okanjo-block2.large_mobile_banner .okanjo-resource{width:318px;height:98px}.okanjo-block2.large_mobile_banner .okanjo-resource a{padding:6px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-image-container{width:86px;height:86px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-title-container{height:30px}.okanjo-block2.billboard{width:970px;height:250px;overflow:hidden}.okanjo-block2.billboard .okanjo-resource{width:160px;height:248px}.okanjo-block2.billboard .okanjo-resource:first-child{width:163px;height:248px}.okanjo-block2.billboard .okanjo-resource.list{width:322px;height:123px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.auto{font-size:1em;width:100%}.okanjo-block2.auto .okanjo-resource{width:100%;height:auto;border-left:none;border-right:none}.okanjo-block2.auto .okanjo-resource a{max-width:500px;width:95%;margin:0 auto;padding:2.5%}.okanjo-block2.auto .okanjo-resource.list{height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-image-container{width:18%;height:auto;line-height:1px}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none;margin-left:21%;width:79%}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-publisher-container,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-seller-container{height:auto;font-size:12px;line-height:1.2}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-price-container{height:auto;font-size:15px;line-height:1.5}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-title-container{font-size:15px;line-height:1.4;height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-cta-button{display:inline-block;font-size:14px;line-height:1.8;margin-bottom:-1.7%}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-price-container{line-height:1.3}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-title-container{line-height:1.25}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-cta-button{font-size:13px}.okanjo-inline-buy-frame{display:block;height:100%;width:100%}',{id:\"okanjo-block2\"})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"okanjo.core\",\"\",{id:\"okanjo-core\"}),t.ui.engine.registerCss(\"okanjo.modal\",'.okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}html.okanjo-modal-active{overflow:hidden!important}html.okanjo-modal-active body{overflow:hidden!important;margin:0}.okanjo-modal-margin-fix{margin-right:15px!important}.okanjo-modal-container{position:fixed;top:0;right:0;left:0;bottom:0;z-index:2147483647;background-color:rgba(0,0,0,.65);transition-duration:210ms;transition-property:background-color}.okanjo-modal-container.lt-ie9{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNiWAoAAK4AqL41IDIAAAAASUVORK5CYII=)}.okanjo-modal-container.okanjo-modal-fade-out{background-color:rgba(0,0,0,0)}.okanjo-modal-container.okanjo-modal-fade-out .okanjo-modal-window{opacity:0;transform:scale(.95,.95) translateY(50px)}.okanjo-modal-container.okanjo-modal-hidden{display:none!important}.okanjo-modal-container .okanjo-modal-window{position:relative;max-width:900px;width:90%;background:0 0;margin:56px auto 40px;opacity:1;transform:scale(1,1) translateY(0);transition-duration:210ms;transition-timing-function:cubic-bezier(.13,.025,.15,1);transition-timing-function:cubic-bezier(.13,.025,.15,1.15);transition-property:opacity}.okanjo-modal-container .okanjo-modal-window:after,.okanjo-modal-container .okanjo-modal-window:before{content:\" \";display:table}.okanjo-modal-container .okanjo-modal-window:after{clear:both}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header{padding-top:5px;padding-bottom:5px;border-bottom:1px solid #d7d7d7}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header img{height:50px;width:auto}.okanjo-modal-container .okanjo-modal-window-skin{width:auto;height:auto;box-shadow:0 10px 25px rgba(0,0,0,.5);position:absolute;background:#fff;border-radius:4px;top:0;bottom:0;left:0;right:0}.okanjo-modal-container .okanjo-modal-window-outer{position:absolute;top:15px;left:15px;bottom:15px;right:15px;vertical-align:top}.okanjo-modal-container .okanjo-modal-window-inner{position:relative;width:100%;height:100%;-webkit-overflow-scrolling:touch;overflow:auto}.okanjo-modal-container .okanjo-modal-window-inner iframe{height:100%;width:100%;margin-right:-15px}.okanjo-modal-container .okanjo-modal-close-button{color:#fff;cursor:pointer;position:absolute;right:0;top:-48px;text-align:right;font-size:40px;line-height:1em;overflow:visible;width:40px;height:40px}',{id:\"okanjo-modal\"}),t.ui.engine.registerTemplate(\"okanjo.error\",'{{ message }} {{#code}} Reference: {{ code }} {{/code}}',{css:[\"okanjo.core\"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"okanjo.slab\",\".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab img.okanjo-fit{height:100%;width:100%;object-fit:cover}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.list .okanjo-resource-title-container{height:95px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource{width:298px}.okanjo-block2.okanjo-slab .okanjo-resource-publisher-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab .okanjo-resource-title-container{height:58px;font-size:16px;line-height:19px}.okanjo-block2.okanjo-slab .okanjo-resource.list .okanjo-resource-title-container{font-size:14px;height:60px}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource-title-container{font:16px/19px Georgia,serif}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource.list .okanjo-resource-title-container{font-size:15px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource-list{display:flex;flex-wrap:wrap;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource{width:inherit;flex-grow:1;flex-shrink:0;flex-basis:33.3333%;flex-basis:200px;display:flex;align-items:center;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list{flex-basis:33.3333%;flex-basis:250px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list a{width:100%}.okanjo-block2.okanjo-slab.responsive .okanjo-resource:last-child{margin:0 -1px -1px 0}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource,.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource:first-child{width:298px;height:248px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:13px;line-height:15px;height:50px;margin-top:1px;margin-bottom:4px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard.theme-newsprint .okanjo-resource .okanjo-resource-title-container{font:700 13px/15px Georgia,serif}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource-title-container{height:80px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource{width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:nth-last-child(n+2){width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:first-child{height:299px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-image-container{width:100%;height:180px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-title-container{margin-bottom:3px;height:77px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource-title-container{height:57px;margin-bottom:8px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource-title-container{height:116px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource{width:298px;height:198px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:nth-last-child(n+2){width:298px;height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:first-child{height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-image-container{width:100%;height:136px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-title-container{height:42px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource,.okanjo-block2.okanjo-slab.billboard .okanjo-resource:first-child{width:322px;height:248px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-info-container{margin-left:111px;width:auto}\",{id:\"okanjo-slab\"})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"products.block2\",\"\",{id:\"okanjo-product-block2\"}),t.ui.__product_block2='',t.ui.engine.registerTemplate(\"products.block2\",t.ui.__product_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.products=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),this._enforceLayoutOptions(),this._registerCustomBranding(\".okanjo-product\",\"buy-button\"),e},{css:[\"products.block2\",\"okanjo.block2\",\"okanjo.modal\"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"products.slab\",\".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:14px;height:40px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:30px;font-size:12px;line-height:14px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button.theme-newsprint .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:13px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:0;height:32px;font-size:14px}.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:47px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;font-size:14px;line-height:16px;margin-bottom:2px}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:50px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;margin-bottom:0;line-height:15px;font-size:15px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:33px;font-size:15px;line-height:15px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-button-container,.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-price-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:auto;margin-bottom:2px;line-height:20px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-price-container{margin-bottom:0}.okanjo-block2.okanjo-slab.auto.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-price-container{margin-bottom:3px}\",{id:\"okanjo-product-slab\"}),t.ui.engine.registerTemplate(\"products.slab\",t.ui.__product_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.blockClasses=[\"okanjo-slab\"],e.products=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),e.fitImage=\"okanjo-fit\",this._enforceSlabLayoutOptions(),this._registerCustomBranding(\".okanjo-product\",\"button\"),e},{css:[\"products.slab\",\"okanjo.slab\",\"okanjo.block2\"]})}(window)}(okanjo);"],"file":"okanjo-bundle.min.js","sourceRoot":"./"} \ No newline at end of file +{"version":3,"names":[],"mappings":"","sources":["okanjo-bundle.js"],"sourcesContent":["/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */\n/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */\n!function(e,t){\"function\"==typeof define&&define.amd?define([],t):\"object\"==typeof exports?module.exports=t():e.okanjo=t()}(this,function(){function e(e,t){if(!e)throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\");return!t||\"object\"!=typeof t&&\"function\"!=typeof t?e:t}function t(e,t){if(\"function\"!=typeof t&&null!==t)throw new TypeError(\"Super expression must either be null or a function, not \"+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function o(e,t){if(!(e instanceof t))throw new TypeError(\"Cannot call a class as a function\")}var n=function(){function e(e,t){for(var o=0;o0?1:-1)*Math.floor(Math.abs(t)):t},n=Math.pow(2,53)-1,i=function(e){var t=o(e);return Math.min(Math.max(t,0),n)};return function(e){var o=this,n=Object(e);if(null==e)throw new TypeError(\"Array.from requires an array-like object - not null or undefined\");var a,r=arguments.length>1?arguments[1]:void 0;if(\"undefined\"!=typeof r){if(!t(r))throw new TypeError(\"Array.from: when provided, the second argument must be a function\");arguments.length>2&&(a=arguments[2])}for(var s,c=i(n.length),l=t(o)?Object(new o(c)):new Array(c),u=0;u>>0;if(\"function\"!=typeof e)throw new TypeError(\"predicate must be a function\");for(var n=arguments[1],i=0;i>>0;if(\"function\"!=typeof e)throw new TypeError(\"predicate must be a function\");for(var n=arguments[1],i=0;i>>0;if(0===i)return!1;for(var a=0|t,r=Math.max(a>=0?a:i-Math.abs(a),0);r=0&&t.splice(a,1)}l.error(\"[Okanjo v\"+d.version+\"]: \"+n.stack),t.length&&l.error.apply(l,[\"Additional information:\"].concat(t))},warn:function(e){for(var t=arguments.length,o=Array(t>1?t-1:0),n=1;n1&&void 0!==arguments[1]?arguments[1]:{},o={};return void 0!==e&&null!==e&&Object.keys(e).forEach(function(n){if(e[n]instanceof Date)t.dateToIso?o[n]=e[n].toISOString():o[n]=e[n];else if(\"object\"===i(e[n])&&null!==e[n])if(Array.isArray(e[n])&&t.ignoreArrays===!0)o[n]=e[n];else if(Array.isArray(e[n])&&t.arrayToCsv===!0)o[n]=e[n].join(\",\");else{var a=d.util.flatten(e[n],t);Object.keys(a).forEach(function(e){o[n+\"_\"+e]=a[e]})}else o[n]=e[n]}),o},d.util.shortid=function(t){var o=\"ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC\",n=e.crypto||e.msCrypto||\"function\"==typeof require&&require(\"crypto\"),i=function(){if(n&&n.randomBytes)return 48&n.randomBytes(1)[0];if(!n||!n.getRandomValues)return 48&Math.floor(256*Math.random());var e=new Uint8Array(1);return n.getRandomValues(e),48&e[0]},a=function(e){for(var t=0,n=void 0,a=\"\";!n;)a+=o[e>>4*t&15|i()],n=e0&&(e+=a(c)),e+=a(o)}}(),d.util.getLocation=function(){return e.location!==e.parent.location?t.referrer:t.location.href},d.ui={getScrollPosition:function(){return{x:o?e.pageXOffset:n?t.documentElement.scrollLeft:t.body.scrollLeft,y:o?e.pageYOffset:n?t.documentElement.scrollTop:t.body.scrollTop}},getElementSize:function(t,o){var n={height:t.offsetHeight,width:t.offsetWidth},i=t.currentStyle||e.getComputedStyle(t);return o&&(n.height+=parseInt(i.marginTop)+parseInt(i.marginBottom),n.width+=parseInt(i.marginLeft)+parseInt(i.marginRight)),n},getPageSize:function(){var e=t.querySelector(\"body\"),o=t.documentElement;return{w:Math.max(e.scrollWidth,e.offsetWidth,o.clientWidth,o.scrollWidth,o.offsetWidth),h:Math.max(e.scrollHeight,e.offsetHeight,o.clientHeight,o.scrollHeight,o.offsetHeight)}},getViewportSize:function(){var o=n?t.documentElement:t.body,i=o.clientWidth,a=o.clientHeight,r=e.innerWidth||0,s=e.innerHeight||0,c=r&&i>r||s&&a>s;return{vw:c?r:i,vh:c?s:a}},getEventPosition:function(e){var o=e.pageX,n=e.pageY,i=t.body,a=t.documentElement,r=\"scrollLeft\",s=\"scrollTop\",c=e.__proto__.constructor.name;return{et:c,ex:void 0===o?e.clientX+i[r]+a[r]:o,ey:void 0===n?e.clientY+i[s]+a[s]:n}},getElementPosition:function(e){var o=\"Could not get position of element. Did you attach the element to the DOM before initializing?\";try{var n=e.getBoundingClientRect(),i=t.body.getBoundingClientRect();return t.body.contains(e)||d.report(o,e),{x1:n.left-i.left,y1:n.top-i.top,x2:n.right-i.left,y2:n.bottom-i.top}}catch(a){return d.report(o,{exception:a,element:e}),{x1:0,y1:0,x2:0,y2:0,err:1}}},_getIntersection:function(e,t,o){var n=Math.max(e.x1,t.x),i=Math.min(e.x2,t.x+o.vw),a=Math.max(e.y1,t.y),r=Math.min(e.y2,t.y+o.vh),s=Math.max(0,i-n)*Math.max(0,r-a),c=(e.x2-e.x1)*(e.y2-e.y1);return{intersectionArea:s,elementArea:c}},isElementVisible:function(e){return e.offsetWidth>0&&e.offsetHeight>0},getPercentageInViewport:function(e){var t=d.ui.getElementPosition(e),o=d.ui.getScrollPosition(),n=d.ui.getViewportSize();if(t.err)return 0;var i=d.ui._getIntersection(t,o,n),a=i.intersectionArea,r=i.elementArea;return r<=0?0:a/r}},d.ui.ellipsify=function(e,o){for(var n=o||e.parentNode,i=d.ui.getElementSize(n).height,a=void 0!==e.textContent,s=a?e.textContent:e.innerText,c=\"\",l=5e3,u=function(e){return c=e.substr(0,e.length-3)+c,\"...\"};d.ui.getElementSize(e).height>i&&s.length>0&&l-- >0;)s=a?e.textContent:e.innerText,s=s.replace(r,u),a?e.textContent=s:e.innerText=s;if(c.length>0){var p=t.createElement(\"span\"),h=t.createElement(\"span\");p.setAttribute(\"class\",\"okanjo-ellipses\"),h.setAttribute(\"class\",\"okanjo-visually-hidden\"),a?(p.textContent=s.substr(0,s.length-3),h.textContent=c):(p.innerText=s.substr(0,s.length-3),h.innerText=c),e.innerHTML=\"\",e.appendChild(p),e.appendChild(h)}},d.ui.fitImages=function(e){\"objectFit\"in t.documentElement.style==!1&&e.querySelectorAll(\"img.okanjo-fit\").forEach(function(e){e.style.display=\"none\";var t=e.parentNode;t.style.backgroundSize=\"cover\",t.style.backgroundImage=\"url(\"+e.src+\")\",t.style.backgroundposition=\"center center\"})},e.okanjo=d}(window,document);return function(e){var t=/^application\\/json/,o=e.okanjo;o.net.request=function(n,i,a,r){\"function\"==typeof a&&(r=a,a=void 0);var s=new(e.XMLHttpRequest||e.ActiveXObject)(\"MSXML2.XMLHTTP.3.0\"),c=!1,l=function(e,t){c||(c=!0,r(e,t))};o.net.request.timeout&&(s.timeout=o.net.request.timeout),s.ontimeout=function(e){l({statusCode:504,error:\"Request timed out\",message:\"Something went wrong\",attributes:{event:e,xhr:s}})},s.onreadystatechange=function(e){if(4===s.readyState)if(s.status>0){var o=void 0;o=t.test(s.getResponseHeader(\"Content-Type\"))?JSON.parse(s.responseText):{statusCode:s.status,data:s.responseText},s.status>=200&&s.status<300?l(null,o):l(o)}else l({statusCode:503,error:\"Request failed\",message:\"Something went wrong\",attributes:{event:e,xhr:s}})},s.open(n.toUpperCase(),i),s.withCredentials=!0,[\"POST\",\"PUT\",\"PATCH\"].includes(n.toUpperCase())&&(s.setRequestHeader(\"Content-Type\",\"application/json; charset=utf-8\"),void 0!==a&&(a=JSON.stringify(a))),s.send(a||void 0)},o.net.request.get=o.net.request.bind(this,\"GET\"),o.net.request.post=o.net.request.bind(this,\"POST\"),o.net.request.put=o.net.request.bind(this,\"PUT\"),o.net.request[\"delete\"]=o.net.request.bind(this,\"DELETE\");var n=function(e){return null===e||void 0===e?\"\":encodeURIComponent(\"\"+e)},a=function(e,t){return t?t+\"[\"+n(e)+\"]\":n(e)};o.net.request.stringify=function(e,t){var r=[];return t=t||\"\",Object.keys(e).forEach(function(s){var c=e[s];if(Array.isArray(c))c.forEach(function(e){return r.push(a(s,t)+\"=\"+n(e))});else if(\"object\"===(\"undefined\"==typeof c?\"undefined\":i(c))&&null!==c){var l=o.net.request.stringify(c,a(s,t));l&&r.push(l)}else void 0!==c&&r.push(a(s,t)+\"=\"+n(c))}),r.join(\"&\")}}(window),function(e,t){e.okanjo.util.cookie={set:function(o,n,i){var a=new Date;a.setDate(a.getDate()+i);var r=i?\" Expires=\"+a.toUTCString()+\";\":\"\",s=\" Path=/\",c=\"https:\"===e.location.protocol?\" Secure;\":\"\",l=encodeURI(n)+\";\"+r+c+\" SameSite=None;\"+s;t.cookie=o+\"=\"+l},get:function(e){var o=null;return t.cookie.split(\";\").find(function(t){var n=t.substr(0,t.indexOf(\"=\")).trim(),i=t.substr(t.indexOf(\"=\")+1);return n===e&&(o=decodeURI(i),!0)}),o}}}(window,document),function(e,t){var a=e.okanjo,r=function(){function e(){o(this,e),this._templates={},this._css={},this.classDetects=\"\"}return n(e,[{key:\"registerTemplate\",value:function(e,t,o,n){if(\"object\"===(\"undefined\"==typeof t?\"undefined\":i(t))){if(void 0===t.nodeType)throw new Error(\"Parameter template must be a string or a DOM element\");t=t.innerHTML,a.lib.Mustache.parse(t)}else if(\"string\"!=typeof t)throw new Error(\"Parameter template must be a string or a DOM element\");if(3===arguments.length&&\"object\"===(\"undefined\"==typeof o?\"undefined\":i(o))?(n=o,o=null):n=n||{},o&&\"function\"!=typeof o)throw new Error(\"Parameter beforeRender must be a function\");this._templates[e]={markup:t,options:n,beforeRender:o}}},{key:\"registerCss\",value:function(e,t,o){if(o=o||{},\"object\"===(\"undefined\"==typeof t?\"undefined\":i(t))){if(void 0===t.nodeType)throw new Error(\"Parameter css must be a string or a DOM element\")}else if(\"string\"!=typeof t)throw new Error(\"Parameter css must be a string or a DOM element\");this._css[e]={markup:t,options:o}}},{key:\"isTemplateRegistered\",value:function(e){return!!this._templates[e]}},{key:\"isCssRegistered\",value:function(e){return!!this._css[e]}},{key:\"ensureCss\",value:function(e){if(this._css[e]){var o=this._css[e],n=void 0===o.markup.nodeType?o.options.id||\"okanjo-css-\"+e:null;if(n){var i=t.querySelector(\"#\"+n.replace(/\\./g,\"\\\\.\"));if(!i){var r=t.head,s=t.createElement(\"style\");if(s.id=n,s.setAttribute(\"type\",\"text/css\"),s.hasOwnProperty?s.innerHTML=o.markup:s.styleSheet.cssText=o.markup,r)r.appendChild(s);else{var c=t.body;c?c.appendChild(s):a.report(\"Cannot add CSS template to document. Does it not have a body or head?\")}}}}else a.report('Attempted to add CSS template \"'+e+'\" to the DOM, however it does not appear to be registered?')}},{key:\"render\",value:function(e,t,o){var n=this;o=o||{};var i=this._templates[e];return i.beforeRender&&(o=i.beforeRender.call(t,o)),o.okanjo=a,o.okanjoMetricUrl=a.net.endpoint.replace(/^https?:\\/\\//,\"\"),o.now=function(){return(new Date).getTime()},o.classDetects=this.classDetects,o.blockClasses&&Array.isArray(o.blockClasses)&&(o.classDetects+=\" \"+o.blockClasses.join(\" \"),delete o.blockClasses),o.css!==!1&&i.options.css&&i.options.css.length>0&&(i.options.css.forEach(function(e){return n.ensureCss(e)}),delete o.css),a.lib.Mustache.render(i.markup,o)}}]),e}();r.formatCurrency=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,o=arguments.length>2&&void 0!==arguments[2]?arguments[2]:\".\",n=arguments.length>3&&void 0!==arguments[3]?arguments[3]:\",\",i=e<0?\"-\":\"\",a=parseInt(e=Math.abs(+e||0).toFixed(t))+\"\",r=a.length;return r=r>3?r%3:0,i+(r?a.substr(0,r)+n:\"\")+a.substr(r).replace(/(\\d{3})(?=\\d)/g,\"$1\"+n)+(t?o+Math.abs(e-a).toFixed(t).slice(2):\"\")},a.ui.engine=new r}(window,document),function(e,t){var o=e.okanjo,n=o.util.isMobile(),i=!1,a=void 0,r=void 0,s=void 0,c=void 0,l=void 0,u=void 0,d=void 0,p=void 0,h=void 0,k=function(){a=t.documentElement||t.querySelector(\"html\"),r=t.body||t.querySelector(\"body\"),s=t.createElement(\"div\"),c=t.createElement(\"div\"),l=t.createElement(\"div\"),u=t.createElement(\"div\"),d=t.createElement(\"div\"),p=t.createElement(\"div\"),h=t.createElement(\"iframe\"),s.setAttribute(\"class\",\"okanjo-modal-container okanjo-modal-hidden \"),c.setAttribute(\"class\",\"okanjo-modal-window\"),l.setAttribute(\"class\",\"okanjo-modal-window-skin\"),u.setAttribute(\"class\",\"okanjo-modal-window-outer\"),d.setAttribute(\"class\",\"okanjo-modal-window-inner\"),p.setAttribute(\"class\",\"okanjo-modal-close-button\"),h.setAttribute(\"class\",\"okanjo-inline-buy-frame\"),h.setAttribute(\"frameborder\",\"0\"),h.setAttribute(\"vspace\",\"0\"),h.setAttribute(\"hspace\",\"0\"),h.setAttribute(\"webkitallowfullscreen\",\"\"),h.setAttribute(\"mozallowfullscreen\",\"\"),h.setAttribute(\"allowfullscreen\",\"\"),h.setAttribute(\"scrolling\",\"auto\"),p.innerHTML=\"×\",d.appendChild(h),u.appendChild(d),l.appendChild(u),c.appendChild(l),c.appendChild(p),s.appendChild(c),r.appendChild(s)},f=function(e,t,o){e.addEventListener?e.addEventListener(t,o,!1):e.attachEvent(\"on\"+t,o)},g=function(){return e.innerHeight||t.documentElement.clientHeight},m=function(){c.style.height=g()-80+\"px\"},b=function(){f(e,\"orientationchange\",function(){for(var e=0;e<2;e++)setTimeout(m,1e3*e+10)}),f(e,\"resize\",function(){setTimeout(m,100)}),f(s,\"click\",y),f(c,\"click\",function(e){e.preventDefault(),e.stopPropagation()}),f(p,\"click\",function(e){e.preventDefault(),e.stopPropagation(),y()})},j=function(e,t){e.className+=\" \"+t},v=function(e,t){e.className=e.className.replace(new RegExp(\" *?\"+t),\"\")},_=function(){v(s,\"okanjo-modal-hidden\"),j(s,\"okanjo-modal-fade-out\"),m(),j(a,\"okanjo-modal-active\"),n||j(a,\"okanjo-modal-margin-fix\"),setTimeout(function(){v(s,\"okanjo-modal-fade-out\")},10)},y=function(){j(s,\"okanjo-modal-fade-out\"),setTimeout(function(){v(s,\"okanjo-modal-fade-out\"),j(s,\"okanjo-modal-hidden\"),v(a,\"okanjo-modal-active\"),n||v(a,\"okanjo-modal-margin-fix\")},210)},w=function(e){d.innerHTML=\"\",\"string\"==typeof e?d.innerHTML=e:d.appendChild(e)};return o.ui.modal={show:function(e){i||(i=!0,k(),b()),w(e),_()},hide:function(){y()}},o.ui.modal}(window,document),function(e,t){var i=e.okanjo,a=function(){function a(){o(this,a),this._queue=this._getStoredQueue(),this._processTimeout=null,this.pageId=i.util.shortid(),this.defaultChannel=a.Channel.external,this.sid=null,this.sourceCh=null,this.sourceCx=null,this._checkUrlForReferral()}return n(a,[{key:\"_getStoredQueue\",value:function(){if(!e.localStorage[a.Params.queue])return[];try{var t=JSON.parse(e.localStorage[a.Params.queue]);return Array.isArray(t)?t:(i.report(\"Stored queue is not a queue\",{queue:t}),[])}catch(o){return i.report(\"Failed to load metric queue from storage\",{err:o}),[]}}},{key:\"_saveQueue\",value:function(t){var o=this;t?(this._saveQueueTimeout&&clearTimeout(this._saveQueueTimeout),this._saveQueueTimeout=setTimeout(function(){o._saveQueue(!1),o._saveQueueTimeout=null},100)):e.localStorage[a.Params.queue]=JSON.stringify(this._queue)}},{key:\"_checkUrlForReferral\",value:function(){var t=i.util.getPageArguments(!0),o=t[a.Params.name],n=e.localStorage[a.Params.name]||i.util.cookie.get(a.Params.name),r=t[a.Params.context],s=t[a.Params.channel];o&&n&&o!==n&&this.trackEvent({object_type:a.Object.metric_session,event_type:a.Event.correlation,id:o+\"_\"+n,ch:this.defaultChannel,_noProcess:!0}),this.sid=n||o||null,this.sourceCh=s||null,this.sourceCx=r||null}},{key:\"trackEvent\",value:function(e,t){return e.object_type&&e.event_type?void this._push(e,t):void i.report(\"Invalid metric to track (missing object_type or event_type)\",{event:e})}},{key:\"trackPageView\",value:function(e,t){e=e||{},e.object_type=a.Object.page,e.event_type=a.Event.view,e.id=e.id||i.util.getLocation(),e.ch=e.ch||this.defaultChannel,this.trackEvent(e,t)}},{key:\"_push\",value:function(e,t){this._queue.push({event:e,callback:t}),this._saveQueue(!0),e._noProcess?delete e._noProcess:this._processQueue()}},{key:\"_processQueue\",value:function(){var e=this;!this._processTimeout&&this._queue.length>0&&(this._processTimeout=setTimeout(function(){var t=e._queue.splice(0,255);e._saveQueue(!1),e._batchSend(t,function(o,n){n&&n.data&&n.data.sid&&e._updateSid(n.data.sid),e._processTimeout=null,e._processQueue(),t.forEach(function(e){e.callback&&e.callback(o,n)})})},0))}},{key:\"_batchSend\",value:function(e,t){var o=this,n=e.map(function(e){return o._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),a={events:n,win:i.util.getLocation()},r=i.net.getRoute(i.net.routes.metrics_batch);this.sid&&(a.sid=this.sid),i.net.request.post(r,a,function(o,n){o&&i.report(\"Failed to send metrics batch\",{err:o,res:n,items:e,route:r}),t&&t(o,n)})}},{key:\"_normalizeEvent\",value:function(e){e.m=e.m||{},e.key=e.key||e.m.key||i.key||void 0,this.sid&&(e.sid=this.sid),e.m=Object.assign({},e.m),Object.keys(a.Meta.exclude).forEach(function(t){return delete e.m[t]}),this.sourceCh&&(e.m.ref_ch=this.sourceCh),this.sourceCx&&(e.m.ref_cx=this.sourceCx),e.m.pgid=this.pageId,e.m.ok_ver=i.version,e.m=i.util.flatten(e.m,{arrayToCsv:!0}),Object.keys(e.m).forEach(function(t){\"string\"==typeof e.m[t]&&(e.m[t]=e.m[t].substr(0,255))}),t.referrer&&(e.ref=t.referrer),e.win=i.util.getLocation()}},{key:\"_updateSid\",value:function(t){!t||this.sid&&this.sid===t||(this.sid=t,e.localStorage[a.Params.name]=t,i.util.cookie.set(a.Params.name,t,a.Params.ttl))}},{key:\"create\",value:function(){for(var e=arguments.length,t=Array(e),o=0;ot?e:t},h=function(e,t){return\"undefined\"==typeof e?t:e};return n.forEach(function(e){a=i.ui.getElementPosition(e),r=d(a.x1,r),s=d(a.y1,s),c=p(a.x2,c),l=p(a.y2,l),u.push(a.x1,a.y1,a.x2,a.y2)}),t.m.wix1=h(r,o.x1),t.m.wiy1=h(s,o.y1),t.m.wix2=h(c,o.x2),t.m.wiy2=h(l,o.y2),t.m.wrps=u.map(function(e){return Math.floor(e)}).join(\",\"),t}},{key:\"addViewportInfo\",value:function(e){var t=i.ui.getViewportSize(),o=i.ui.getScrollPosition();return e=e||{},e.m=e.m||{},e.m.vx1=o.x,e.m.vy1=o.y,e.m.vx2=o.x+t.vw,e.m.vy2=o.y+t.vh,e}},{key:\"addEventInfo\",value:function(e,t){var o=i.ui.getEventPosition(e);return t=t||{},t.m=t.m||{},t.m.et=o.et,t.m.ex=o.ex,t.m.ey=o.ey,t}},{key:\"addEventMeta\",value:function(e){e=e||{},e.m=e.m||{};for(var t=arguments.length,o=Array(t>1?t-1:0),n=1;n1?t-1:0),n=1;n=0&&this._events[e].splice(o,1)}}},{key:\"emit\",value:function(e){var t=void 0,o=void 0,n=void 0,i=[].slice.call(arguments,1);if(this._events[e])for(o=this._events[e].slice(),n=o.length,t=0;t1&&void 0!==arguments[1])||arguments[1];if(!this._strip||!t)return void 0!==e&&this._convert&&(e=this._convert(e)),void 0!==e?e:this._default}}],[{key:\"array\",value:function(t){return(new e).array(t)}},{key:\"string\",value:function(){return(new e).string()}},{key:\"bool\",value:function(){return(new e).bool()}},{key:\"strip\",value:function(){return(new e).strip()}},{key:\"int\",value:function(){return(new e)[\"int\"]()}},{key:\"float\",value:function(){return(new e)[\"float\"]()}}]),e}(),r._Widget=l}(window),function(i){var a=i.okanjo,r=a._Widget.Field,s=r.string,c=r.array,l=r[\"float\"],u=r[\"int\"],d=r.bool,p=a.metrics.constructor,h=a.ui.engine.constructor,k=\"filters\",f=\"display\",g=\"article_meta\",m=.5,b=1e3,j=2,v=function(r){function v(t){var n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};o(this,v),n=a.util.flatten(n,{ignoreArrays:!0});var i=e(this,(v.__proto__||Object.getPrototypeOf(v)).call(this,t,n));return i.name=\"Placement\",i._metricBase={},i._response=null,i._viewWatcherIv=null,i._viewedWatchers=[],n.no_init||i.init(),i}return t(v,r),n(v,[{key:\"getSettings\",value:function(){return{type:s().group(k),ids:c().group(k),q:s().group(k),url:s().group(k),url_referrer:s().group(k).strip(),url_selectors:s().group(k),url_paths:c().group(k),not_url_paths:c().group(k),organization_id:s().group(k),property_id:s().group(k),store_id:s().group(k),organization_name:s().group(k),property_name:s().group(k),store_name:s().group(k),external_id:s().group(k),sku:s().group(k),external_store_id:s().group(k),condition:s().group(k),manufacturer:s().group(k),upc:s().group(k),isbn:s().group(k),tags:c().group(k),category:c().group(k),pools:c().group(k),min_price:l().group(k),max_price:l().group(k),min_donation_percent:l().group(k),max_donation_percent:l().group(k),donation_to:s().group(k),sort_by:s().group(k),sort_direction:s().group(k),skip:u().group(k),take:u().group(k),placement_tests_only:d(),size:s().group(f),template_name:s().group(f),template_layout:s().group(f),template_theme:s().group(f),template_variant:s().group(f),template_cta_style:s().group(f),template_cta_text:s().group(f),template_cta_color:s().group(f),adx_unit_path:s().group(f),url_category:c().group(g),url_keywords:c().group(g),key:s().strip(),no_init:d().strip(),no_css:d().strip(),proxy_url:s().strip(),expandable:d().strip()[\"default\"](!0),disable_inline_buy:d().strip()[\"default\"](!1),disable_popup:d().strip()[\"default\"](!1),backwards:s().strip(),testing:d().strip()}}},{key:\"getConfig\",value:function(){var e=this,t=this.getSettings(),o={filters:{},display:{},backfill:{},shortfill:{},article_meta:{}},n=/^backfill_(.+)$/,i=/^shortfill_(.+)$/;return Object.keys(this.config).forEach(function(a){var r=e.config[a],s=a,c=!1,l=!1,u=null,d=n.exec(a);d?(s=d[1],c=!0):(d=i.exec(a),d&&(s=d[1],l=!0)),t[s]&&(r=t[s].value(r),u=t[s].getGroup());var p=o;c?p=o.backfill:l&&(p=o.shortfill),!l&&u&&(p[u]=p[u]||{},p=p[u]),null===r?p[s]=\"\":void 0!==r&&(p[s]=r)}),o}},{key:\"load\",value:function(){var e=this;this._setMetricBase(),this._fetchContent(function(t){t?e._reportWidgetLoad(\"fetch failed: \"+t.statusCode||t.toString()):(e._mergeResponseSettings(),e._updateBaseMetaFromResponse(),e._showContent())})}},{key:\"_setMetricBase\",value:function(){var e=this._metricBase;e.ch=p.Channel.placement,e.cx=this.config.backwards||\"auto\",e.key=this.config.key,e.m=e.m||{},e.m.wgid=this.instanceId,this.config.testing&&(e.env=p.Environment.testing)}},{key:\"_reportWidgetLoad\",value:function(e){var t=this,o=this._response||{},n=o.data||{results:[]};this._metricBase.m.decl=e||\"0\",this._metricBase.m.res_bf=n.backfilled?1:0,this._metricBase.m.res_sf=n.shortfilled?1:0,this._metricBase.m.res_spltfl=n.splitfilled?1:0,this._metricBase.m.res_total=n.total||0,this._metricBase.m.res_type=n.type,this._metricBase.m.res_length=n.results.length,a.metrics.create(this._metricBase).type(p.Object.widget,p.Event.impression).meta(this.getConfig()).element(this.element).viewport().widget(this.element).send(),this._addOnceViewedHandler(this.element,function(){a.metrics.create(t._metricBase).type(p.Object.widget,p.Event.view).meta(t.getConfig()).element(t.element).viewport().widget(t.element).send()})}},{key:\"_fetchContent\",value:function(e){var t=this,o=this.getConfig(),n=this.config.key;a.metrics.sid&&(o.sid=a.metrics.sid),o.filters.url_referrer=this.config.url_referrer||i.location.href,o.wgid=this.instanceId,o.pgid=a.metrics.pageId,a.net.request.post(a.net.getRoute(a.net.routes.ads,null,this.config.sandbox?\"sandbox\":\"live\")+\"?key=\"+encodeURIComponent(n),o,function(o,n){o?(a.report(\"Failed to retrieve placement content\",o,{placement:t}),t.setMarkup(\"\"),t.emit(\"error\",o),e&&e(o)):(t._response=n,t.emit(\"data\"),e&&e())})}},{key:\"_mergeResponseSettings\",value:function(){var e=this,t=this._response,o=t.data||{},n=o.settings||{};n.filters&&Object.keys(n.filters).forEach(function(t){e.config[t]=n.filters[t]}),n.display&&Object.keys(n.display).forEach(function(t){e.config[t]=n.display[t]})}},{key:\"_updateBaseMetaFromResponse\",value:function(){var e=(this._response||{}).data||{};this._metricBase.m=this._metricBase.m||{};var t=this._metricBase.m;e.article&&(t.aid=e.article.id),e.test&&e.test.enabled?(t.pten=1,t.ptid=e.test.id,t.ptseed=e.test.seed):t.pten=0}},{key:\"_showContent\",value:function(){var e=(this._response||{}).data||{};if(e.type===v.ContentTypes.products)this._showProducts();else if(e.type===v.ContentTypes.articles)this._showArticles();else if(e.type===v.ContentTypes.adx)this._showADX();else{var t=\"Unknown response content type: \"+e.type;a.report(t,{placement:this}),this.setMarkup(\"\"),this.emit(\"error\",t),this._reportWidgetLoad(t)}}},{key:\"_getClickThroughURL\",value:function(e,t,o){var n=t.indexOf(\"?\")>=0?\"&\":\"?\";return o=o||{},o.ok_msid=a.metrics.sid||\"unknown\",o.ok_ch=this._metricBase.ch,o.ok_cx=this._metricBase.cx,o._okjr=i.location.href.split(/[?#]/)[0],o.utm_source=\"okanjo\",o.utm_campaign=\"smartserve\",o.utm_medium=\"smartserve\",t+=n+Object.keys(o).map(function(e){return encodeURIComponent(e)+\"=\"+encodeURIComponent(o[e])}).join(\"&\"),this.config.proxy_url&&(t=this.config.proxy_url+encodeURIComponent(t)),e.data({u:t}),e.toUrl()}},{key:\"_handleResourceMouseDown\",value:function(e,t,o){var n=t._cid,i=a.metrics.create(this._metricBase,{id:t.id}).type(e,p.Event.interaction).meta(this.getConfig()).meta({cid:n}).meta({bf:t.backfill?1:0,sf:t.shortfill?1:0,spltfl_seg:t.splitfill_segment||null}).event(o).element(o.currentTarget).viewport().widget(this.element),r=\"url_track_param\",s=\"url\";e===p.Object.product&&(r=\"buy_url_track_param\",s=\"buy_url\");var c={ok_cid:n};t[r]&&(c[t[r]]=n),i.data({ea:p.Action.click}),o.currentTarget.href=this._getClickThroughURL(i,t[s],c),t._clickId=n,t._event=i,t._additionalParams=c}},{key:\"_getTemplate\",value:function(e,t){var o=this.config.template_name;return o&&a.ui.engine.isTemplateRegistered(e+\".\"+o)||(o=t),e+\".\"+o}},{key:\"_enforceLayoutOptions\",value:function(){\"leaderboard\"===this.config.size||\"large_mobile_banner\"===this.config.size?(this.config.template_layout=\"list\",this.config.template_cta_style=\"link\"):\"half_page\"!==this.config.size&&\"auto\"!==this.config.size||(this.config.template_layout=\"list\")}},{key:\"_enforceSlabLayoutOptions\",value:function(){\"medium_rectangle\"===this.config.size||\"billboard\"===this.config.size?(this.config.template_layout=\"grid\",\"button\"===this.config.template_cta_style&&(this.config.template_cta_style=\"link\")):\"half_page\"===this.config.size?this.config.template_layout=\"grid\":\"leaderboard\"===this.config.size||\"large_mobile_banner\"===this.config.size?(this.config.template_layout=\"list\",\"button\"===this.config.template_cta_style&&(this.config.template_cta_style=\"link\")):\"auto\"===this.config.size?this.config.template_layout=\"list\":\"responsive\"===this.config.size&&\"button\"===this.config.template_cta_style&&(this.config.template_cta_style=\"link\")}},{key:\"_registerCustomBranding\",value:function(){var e=this.config.template_cta_color;if(e){var t=void 0,o=\"okanjo-wgid-\"+this.instanceId;t=\"\\n .okanjo-block2.\"+o+\" .okanjo-resource-cta-button, .okanjo-block2.\"+o+\" .okanjo-resource-buy-button { color: \"+e+\" !important; } \\n .okanjo-block2.\"+o+\".okanjo-cta-style-button .okanjo-resource-cta-button, .okanjo-block2.\"+o+\".okanjo-cta-style-button .okanjo-resource-buy-button { border-color: \"+e+\" !important; } \\n .okanjo-block2.\"+o+\".okanjo-cta-style-button .okanjo-resource-cta-button:hover, .okanjo-block2.\"+o+\".okanjo-cta-style-button .okanjo-resource-buy-button:hover { background: \"+e+\" !important; color: #fff !important; } \\n \",\na.ui.engine.registerCss(o,t,{id:o}),a.ui.engine.ensureCss(o)}}},{key:\"_addOnceViewedHandler\",value:function(e,t){var o={element:e,successfulCount:0,handler:t};this._viewedWatchers.push(o),this._toggleViewWatcher(!0)}},{key:\"_checkViewWatchers\",value:function(){for(var e,t=0;t=m&&e.successfulCount++,e.successfulCount>=j&&(e.handler(),this._viewedWatchers.splice(t,1),t--);0===this._viewedWatchers.length&&this._toggleViewWatcher(!1)}},{key:\"_toggleViewWatcher\",value:function(e){e?null===this._viewWatcherIv&&(this._viewWatcherIv=setInterval(this._checkViewWatchers.bind(this),b/j)):(clearInterval(this._viewWatcherIv),this._viewWatcherIv=null)}},{key:\"_showProducts\",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},o=this._getTemplate(v.ContentTypes.products,v.DefaultTemplates.products);t.results.forEach(function(t,o){e.config.disable_inline_buy&&(t.inline_buy_url=null),t.inline_buy_url&&(t._escaped_inline_buy_url=encodeURIComponent(t.inline_buy_url)),t._image_url=t.image_urls?t.image_urls[0]:\"\",t._escaped_buy_url=encodeURIComponent(t.buy_url),t._price_formatted=h.formatCurrency(t.price),t._index=o});var n={css:!this.config.no_css};this.setMarkup(a.ui.engine.render(o,this,n)),0===t.results.length?(this.emit(\"empty\"),this._reportWidgetLoad(\"empty\")):this._reportWidgetLoad(),this.element.querySelectorAll(\"a\").forEach(function(t){var o=t.getAttribute(\"data-id\"),n=t.getAttribute(\"data-index\");if(o&&n>=0){var i=e._response.data.results[n];i&&(t.addEventListener(\"mousedown\",e._handleResourceMouseDown.bind(e,p.Object.product,i)),t.addEventListener(\"click\",e._handleProductClick.bind(e,i)),a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.product,p.Event.impression).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.product,p.Event.view).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(\".okanjo-resource-title\").forEach(function(e){a.ui.ellipsify(e)}),a.ui.fitImages(this.element),this.emit(\"load\")}},{key:\"_handleProductClick\",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(p.Object.product,e,t);var o=e._event,n=e._additionalParams;o.event(t);var r=!!e.inline_buy_url,s=!this.config.disable_popup&&r&&a.util.isMobile();if(s){t.preventDefault(),o.data({ea:p.Action.inline_click}).meta({popup:\"true\"});var c=this._getClickThroughURL(o,e.inline_buy_url,n);this._popupFrame=i.open(c,\"okanjo-inline-buy-frame\",\"width=400,height=400,location=yes,resizable=yes,scrollbars=yes\"),this._popupFrame||(a.report(\"Popup blocker stopped buy experience from showing\",{placement:this}),i.location.href=c)}else if(r){t.preventDefault();var l=document.createElement(\"iframe\"),u={\"class\":\"okanjo-inline-buy-frame\",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:\"\",mozallowfullscreen:\"\",allowfullscreen:\"\",scrolling:\"auto\"};if(Object.keys(u).forEach(function(e){return l.setAttribute(e,u[e])}),n.expandable=this.config.expandable?1:0,!this.config.expandable){var d=this.element.querySelector(\".okanjo-expansion-root\");if(d){l.className+=\" okanjo-ad-in-unit\",l.setAttribute(\"height\",\"100%\"),l.setAttribute(\"width\",\"100%\"),d.appendChild(l);var h=a.ui.getElementSize(d);n.frame_height=h.height,n.frame_width=h.width,this.config.size&&(n.ad_size=this.config.size)}}o.data({ea:p.Action.inline_click}).meta({expandable:this.config.expandable?\"true\":\"false\"}),l.src=this._getClickThroughURL(o,e.inline_buy_url,n),l.parentNode||a.ui.modal.show(l)}else t.currentTarget.href=this._getClickThroughURL(o,e.buy_url,n)}},{key:\"_showArticles\",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},o=this._getTemplate(v.ContentTypes.articles,v.DefaultTemplates.articles);t.results.forEach(function(e,t){e._escaped_url=encodeURIComponent(e.url),e._index=t});var n={css:!this.config.no_css};this.setMarkup(a.ui.engine.render(o,this,n)),0===t.results.length?(this.emit(\"empty\"),this._reportWidgetLoad(\"empty\")):this._reportWidgetLoad(),this.element.querySelectorAll(\"a\").forEach(function(t){var o=t.getAttribute(\"data-id\"),n=t.getAttribute(\"data-index\");if(o&&n>=0){var i=e._response.data.results[n];i&&(t.addEventListener(\"mousedown\",e._handleResourceMouseDown.bind(e,p.Object.article,i)),t.addEventListener(\"click\",e._handleArticleClick.bind(e,i)),a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.article,p.Event.impression).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){a.metrics.create(e._metricBase,{id:i.id}).type(p.Object.article,p.Event.view).meta(e.getConfig()).meta({bf:i.backfill?1:0,sf:i.shortfill?1:0,spltfl_seg:i.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(\".okanjo-resource-title\").forEach(function(e){a.ui.ellipsify(e)}),a.ui.fitImages(this.element),this.emit(\"load\")}},{key:\"_handleArticleClick\",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(p.Object.article,e,t);var o=e._event,n=e._additionalParams;o.event(t),t.currentTarget.href=this._getClickThroughURL(o,e.url,n)}},{key:\"_showADX\",value:function(){var e=this,t=(this._response||{data:{settings:{}}}).data||{settings:{}},o=this._getTemplate(v.ContentTypes.adx,v.DefaultTemplates.adx),n=null;if(this.config.size)if(v.Sizes[this.config.size])n=v.Sizes[this.config.size];else{var i=/^([0-9]+)x([0-9]+)$/i.exec(this.config.size);i&&(n={width:i[1],height:i[2]})}n||(n=v.Sizes[\"default\"]);var r=\"/90447967/okanjo:\",s=void 0;t.settings.display&&t.settings.display.adx_unit_path&&(r=t.settings.display.adx_unit_path,s=\"custom_ad_unit\");var c={css:!this.config.no_css,size:n,adUnitPath:r};this.setMarkup(a.ui.engine.render(o,this,c)),this._reportWidgetLoad(s);var l=this.element.querySelector(\".okanjo-adx-container\");if(l){var u=document.createElement(\"iframe\"),d={\"class\":\"okanjo-adx-frame\",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:\"\",mozallowfullscreen:\"\",allowfullscreen:\"\",scrolling:\"auto\",width:n.width,height:n.height};Object.keys(d).forEach(function(e){return u.setAttribute(e,d[e])}),l.appendChild(u);var h=a.metrics.create(this._metricBase).type(p.Object.thirdparty_ad,p.Event.interaction).meta(this.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(this.element).toUrl();u.contentWindow.trackImpression=function(){a.metrics.create(e._metricBase).type(p.Object.thirdparty_ad,p.Event.impression).meta(e.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(e.element).send(),e._addOnceViewedHandler(u,function(){a.metrics.create(e._metricBase).type(p.Object.thirdparty_ad,p.Event.view).meta(e.getConfig()).meta({ta_s:r,ta_w:n.width,ta_h:n.height}).element(u).viewport().widget(e.element).send()})},u.contentWindow.document.open(),u.contentWindow.document.write('\\n<'+('script type=\"text/javascript\" src=\"https://www.googletagservices.com/tag/js/gpt.js\">\\n googletag.pubads().addEventListener(\\'slotRenderEnded\\', function(e) { \\n trackImpression(e);\\n });\\n googletag.pubads()\\n .definePassback(\"'+r.replace(/\"/g,'\\\\\"')+'\", [['+n.width+\", \"+n.height+']])\\n .setClickUrl(\"'+h+'&u=\")\\n .display();\\n<')+\"/script>\\n\"),u.contentWindow.document.close()}this.emit(\"load\")}}]),v}(a._Widget);return v.Sizes={medium_rectangle:{width:300,height:250},leaderboard:{width:728,height:90},large_mobile_banner:{width:320,height:100},half_page:{width:300,height:600},billboard:{width:970,height:250},button_2:{width:120,height:60},micro_bar:{width:88,height:31},portrait:{width:300,height:1050},rectangle:{width:180,height:150},super_leaderboard:{width:970,height:90},wide_skyscraper:{width:160,height:600},mobile_leaderboard:{width:320,height:50},small_square:{width:200,height:200},button_1:{width:120,height:90},full_banner:{width:468,height:60},half_banner:{width:234,height:60},large_rectangle:{width:336,height:280},pop_under:{width:720,height:300},three_to_one_rectangle:{width:300,height:100},skyscraper:{width:120,height:600},square:{width:250,height:250},square_button:{width:125,height:125},vertical_banner:{width:120,height:240},vertical_rectangle:{width:240,height:400}},v.Sizes[\"default\"]=v.Sizes.medium_rectangle,v.ContentTypes={products:\"products\",articles:\"articles\",adx:\"adx\"},v.DefaultTemplates={products:\"block2\",articles:\"block2\",adx:\"block2\"},a.Placement=v}(window),function(i){var a=i.okanjo,r=function(i){function r(t,n){o(this,r),n=n||{};var i=n.no_init;n.no_init=!0;var s=e(this,(r.__proto__||Object.getPrototypeOf(r)).call(this,t,n));return a.warn(\"Product widget has been deprecated. Use Placement instead (may require configuration changes)\",{widget:s}),i||(delete s.config.no_init,s.init()),s}return t(r,i),n(r,[{key:\"_setCompatibilityOptions\",value:function(){this.config.backwards=\"Product\",this.config.type=a.Placement.ContentTypes.products,\"sense\"===this.config.mode?(this.config.url=this.config.url||\"referrer\",this.config.take=this.config.take||5):\"single\"===this.config.mode?(this.config.url=null,this.config.id&&(this.config.ids=[this.config.id]),this.config.take=1,delete this.config.id):(this.config.url=null,this.config.take=this.config.take||25),delete this.config.mode,this.config.sold_by&&(this.config.store_name=this.config.sold_by,delete this.config.sold_by),this.config.selectors&&(this.config.url_selectors=this.config.selectors,delete this.config.selectors),this.config.marketplace_id&&(this.config.property_id=this.config.marketplace_id,delete this.config.marketplace_id),\"testing\"===this.config.marketplace_status&&(this.config.sandbox=!0),delete this.config.marketplace_status,delete this.config.suboptimal,delete this.config.text}}]),r}(a.Placement);return a.Product=r}(window),function(i){var a=i.okanjo,r=function(i){function r(t,n){o(this,r),n=n||{};var i=n.no_init;n.no_init=!0;var s=e(this,(r.__proto__||Object.getPrototypeOf(r)).call(this,t,n));return a.warn(\"Ad widget has been deprecated. Use Placement instead (may require configuration changes)\",{widget:s}),i||(delete s.config.no_init,s.init()),s}return t(r,i),n(r,[{key:\"_setCompatibilityOptions\",value:function(){this.config.backwards=\"Ad\",this.config.type=a.Placement.ContentTypes.products,this.config.url=null,this.config.id?this.config.ids=[this.config.id]:a.warn(\"Ad widget should have parameter `id` set.\"),this.config.take=1,delete this.config.id,delete this.config.content}}]),r}(a.Placement);return a.Ad=r}(window),function(){/*!\n * mustache.js - Logic-less {{mustache}} templates with JavaScript\n * http://github.com/janl/mustache.js\n */\n!function(e,t){\"object\"===(\"undefined\"==typeof exports?\"undefined\":i(exports))&&exports&&\"string\"!=typeof exports.nodeName?t(exports):\"function\"==typeof define&&define.amd?define([\"exports\"],t):(e.Mustache={},t(e.Mustache))}(this,function(e){function t(e){return\"function\"==typeof e}function o(e){return g(e)?\"array\":\"undefined\"==typeof e?\"undefined\":i(e)}function n(e){return e.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g,\"\\\\$&\")}function a(e,t){return null!=e&&\"object\"===(\"undefined\"==typeof e?\"undefined\":i(e))&&t in e}function r(e,t){return m.call(e,t)}function s(e){return!r(b,e)}function c(e){return String(e).replace(/[&<>\"'`=\\/]/g,function(e){return j[e]})}function l(t,o){function i(){if(m&&!b)for(;f.length;)delete k[f.pop()];else f=[];m=!1,b=!1}function a(e){if(\"string\"==typeof e&&(e=e.split(_,2)),!g(e)||2!==e.length)throw new Error(\"Invalid tags: \"+e);r=new RegExp(n(e[0])+\"\\\\s*\"),c=new RegExp(\"\\\\s*\"+n(e[1])),l=new RegExp(\"\\\\s*\"+n(\"}\"+e[1]))}if(!t)return[];var r,c,l,h=[],k=[],f=[],m=!1,b=!1;a(o||e.tags);for(var j,C,E,A,O,T,P=new p(t);!P.eos();){if(j=P.pos,E=P.scanUntil(r))for(var z=0,S=E.length;z0?a[a.length-1][4]:n;break;default:i.push(t)}return n}function p(e){this.string=e,this.tail=e,this.pos=0}function h(e,t){this.view=e,this.cache={\".\":this.view},this.parent=t}function k(){this.cache={}}var f=Object.prototype.toString,g=Array.isArray||function(e){return\"[object Array]\"===f.call(e)},m=RegExp.prototype.test,b=/\\S/,j={\"&\":\"&\",\"<\":\"<\",\">\":\">\",'\"':\""\",\"'\":\"'\",\"/\":\"/\",\"`\":\"`\",\"=\":\"=\"},v=/\\s*/,_=/\\s+/,y=/\\s*=/,w=/\\s*\\}/,x=/#|\\^|\\/|>|\\{|&|=|!/;p.prototype.eos=function(){return\"\"===this.tail},p.prototype.scan=function(e){var t=this.tail.match(e);if(!t||0!==t.index)return\"\";var o=t[0];return this.tail=this.tail.substring(o.length),this.pos+=o.length,o},p.prototype.scanUntil=function(e){var t,o=this.tail.search(e);switch(o){case-1:t=this.tail,this.tail=\"\";break;case 0:t=\"\";break;default:t=this.tail.substring(0,o),this.tail=this.tail.substring(o)}return this.pos+=t.length,t},h.prototype.push=function(e){return new h(e,this)},h.prototype.lookup=function(e){var o,n=this.cache;if(n.hasOwnProperty(e))o=n[e];else{for(var i,r,s=this,c=!1;s;){if(e.indexOf(\".\")>0)for(o=s.view,i=e.split(\".\"),r=0;null!=o&&r\"===a?r=this.renderPartial(i,t,o,n):\"&\"===a?r=this.unescapedValue(i,t):\"name\"===a?r=this.escapedValue(i,t):\"text\"===a&&(r=this.rawValue(i)),void 0!==r&&(s+=r);return s},k.prototype.renderSection=function(e,o,n,a){function r(e){return s.render(e,o,n)}var s=this,c=\"\",l=o.lookup(e[1]);if(l){if(g(l))for(var u=0,d=l.length;u
',function(e){return e.config=this.config,e.instanceId=this.instanceId,e.metricParams=t.net.request.stringify(this._metricBase),e},{css:[\"adx.block2\",\"okanjo.block2\"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"articles.block2\",\".okanjo-block2 .okanjo-article.okanjo-cta-style-button .okanjo-resource-title-container{height:52px}.okanjo-block2 .okanjo-article .okanjo-resource-title-container.modern{height:44px}.okanjo-block2.leaderboard .okanjo-article .okanjo-resource-title-container{margin-top:2px;margin-bottom:4px}\",{id:\"okanjo-article-block2\"}),t.ui.__article_block2='',t.ui.engine.registerTemplate(\"articles.block2\",t.ui.__article_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.articles=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),this._enforceLayoutOptions(),this._registerCustomBranding(\".okanjo-article\",\"button\"),e},{css:[\"articles.block2\",\"okanjo.block2\"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"articles.slab\",\"\",{id:\"okanjo-article-slab\"}),t.ui.engine.registerTemplate(\"articles.slab\",t.ui.__article_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.blockClasses=[\"okanjo-slab\"],e.articles=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),e.fitImage=\"okanjo-fit\",this._enforceSlabLayoutOptions(),this._registerCustomBranding(\".okanjo-article\",\"button\"),e},{css:[\"articles.slab\",\"okanjo.slab\",\"okanjo.block2\"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"okanjo.block2\",'.okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2{color:#333;font-size:10px;font-family:inherit}.okanjo-block2:after,.okanjo-block2:before{content:\" \";display:table}.okanjo-block2:after{clear:both}.okanjo-block2.theme-newsprint .okanjo-resource-seller-container{font-family:Georgia,serif}.okanjo-block2.theme-newsprint .okanjo-resource-title-container{font:13px/15px Georgia,serif}.okanjo-block2.theme-modern,.okanjo-block2.theme-newsprint .okanjo-resource-buy-button,.okanjo-block2.theme-newsprint .okanjo-resource-cta-button,.okanjo-block2.theme-newsprint .okanjo-resource-price-container{font-family:\"Helvetica Neue\",Helvetica,Roboto,Arial,sans-serif}.okanjo-block2 .okanjo-ellipses:after{content:\"...\"}.okanjo-block2 .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2 .okanjo-resource{display:block;float:left;background-color:#fff;box-sizing:content-box;width:148px;border:1px solid #e6e6e6;margin:0 -1px -1px 0}.okanjo-block2 .okanjo-resource:last-child{margin:0}.okanjo-block2 a{display:block;overflow:hidden;color:#333;text-decoration:none;padding:10px}.okanjo-block2 a:hover{color:inherit;text-decoration:none}.okanjo-block2 .okanjo-resource-image-container{float:left;overflow:hidden;text-align:center;vertical-align:middle;width:100%;height:128px;line-height:127px;margin:0 0 3px}.okanjo-block2 .okanjo-resource-image{max-width:100%;max-height:100%;border:none;vertical-align:middle}.okanjo-block2 .okanjo-resource-info-container{float:left;height:auto;width:100%}.okanjo-block2 .okanjo-resource-publisher-container,.okanjo-block2 .okanjo-resource-seller-container{color:#999;font-size:11px;line-height:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource-title-container{overflow:hidden;margin-top:3px;margin-bottom:4px;font-weight:700;font-size:12px;line-height:14px;height:45px;word-wrap:break-word}.okanjo-block2 .okanjo-resource-title-container span{display:inline-block}.lt-ie8.okanjo-block2 .okanjo-resource-title-container span{display:inline;zoom:1}.okanjo-block2 .okanjo-resource-price-container{font-size:15px;line-height:1;margin-bottom:5px}.okanjo-block2 .okanjo-resource-buy-button,.okanjo-block2 .okanjo-resource-cta-button{color:#09f;font-size:12px;line-height:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource.list{width:298px;height:122px}.okanjo-block2 .okanjo-resource.list a{padding:11px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-title-container{margin-top:4px;margin-bottom:6px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px;margin:0 11px 0 0}.okanjo-block2 .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-title-container{height:30px}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button{display:block;text-align:center;line-height:26px;padding:0 8px;border:1px solid #09f;border-radius:2px;transition:50ms ease}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:hover,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:hover{background:#09f;color:#fff}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:active,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:active{box-shadow:inset 0 3px 10px rgba(0,0,0,.15)}.okanjo-block2.medium_rectangle{width:300px;height:250px;overflow:hidden}.okanjo-block2.medium_rectangle .okanjo-resource{width:148px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource:first-child{width:149px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource.list{width:298px;height:123px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child{height:124px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child a{padding-top:12px}.okanjo-block2.leaderboard{width:728px;height:90px;overflow:hidden}.okanjo-block2.leaderboard .okanjo-resource{width:241px;height:88px}.okanjo-block2.leaderboard .okanjo-resource:first-child{width:242px}.okanjo-block2.leaderboard .okanjo-resource a{padding:7px}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-image-container{width:74px;height:74px;line-height:1px;margin:0 7px 0 0}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:11px;line-height:13px;height:26px;margin-top:1px;margin-bottom:4px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-price-container{margin-bottom:3px}.okanjo-block2.leaderboard.theme-newsprint .okanjo-resource-title-container{font:700 11px/13px Georgia,serif}.okanjo-block2.half_page{width:300px;height:600px;overflow:hidden}.okanjo-block2.half_page .okanjo-resource{height:118px}.okanjo-block2.half_page .okanjo-resource:nth-last-child(n+2){height:119px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-image-container{width:96px;height:96px}.okanjo-block2.large_mobile_banner{width:320px;height:100px;overflow:hidden}.okanjo-block2.large_mobile_banner .okanjo-resource{width:318px;height:98px}.okanjo-block2.large_mobile_banner .okanjo-resource a{padding:6px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-image-container{width:86px;height:86px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-title-container{height:30px}.okanjo-block2.billboard{width:970px;height:250px;overflow:hidden}.okanjo-block2.billboard .okanjo-resource{width:160px;height:248px}.okanjo-block2.billboard .okanjo-resource:first-child{width:163px;height:248px}.okanjo-block2.billboard .okanjo-resource.list{width:322px;height:123px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.auto{font-size:1em;width:100%}.okanjo-block2.auto .okanjo-resource{width:100%;height:auto;border-left:none;border-right:none}.okanjo-block2.auto .okanjo-resource a{max-width:500px;width:95%;margin:0 auto;padding:2.5%}.okanjo-block2.auto .okanjo-resource.list{height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-image-container{width:18%;height:auto;line-height:1px}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none;margin-left:21%;width:79%}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-publisher-container,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-seller-container{height:auto;font-size:12px;line-height:1.2}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-price-container{height:auto;font-size:15px;line-height:1.5}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-title-container{font-size:15px;line-height:1.4;height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-cta-button{display:inline-block;font-size:14px;line-height:1.8;margin-bottom:-1.7%}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-price-container{line-height:1.3}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-title-container{line-height:1.25}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-cta-button{font-size:13px}.okanjo-inline-buy-frame{display:block;height:100%;width:100%}',{id:\"okanjo-block2\"})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"okanjo.core\",\"\",{id:\"okanjo-core\"}),t.ui.engine.registerCss(\"okanjo.modal\",'.okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}html.okanjo-modal-active{overflow:hidden!important}html.okanjo-modal-active body{overflow:hidden!important;margin:0}.okanjo-modal-margin-fix{margin-right:15px!important}.okanjo-modal-container{position:fixed;top:0;right:0;left:0;bottom:0;z-index:2147483647;background-color:rgba(0,0,0,.65);transition-duration:210ms;transition-property:background-color}.okanjo-modal-container.lt-ie9{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNiWAoAAK4AqL41IDIAAAAASUVORK5CYII=)}.okanjo-modal-container.okanjo-modal-fade-out{background-color:rgba(0,0,0,0)}.okanjo-modal-container.okanjo-modal-fade-out .okanjo-modal-window{opacity:0;transform:scale(.95,.95) translateY(50px)}.okanjo-modal-container.okanjo-modal-hidden{display:none!important}.okanjo-modal-container .okanjo-modal-window{position:relative;max-width:900px;width:90%;background:0 0;margin:56px auto 40px;opacity:1;transform:scale(1,1) translateY(0);transition-duration:210ms;transition-timing-function:cubic-bezier(.13,.025,.15,1);transition-timing-function:cubic-bezier(.13,.025,.15,1.15);transition-property:opacity}.okanjo-modal-container .okanjo-modal-window:after,.okanjo-modal-container .okanjo-modal-window:before{content:\" \";display:table}.okanjo-modal-container .okanjo-modal-window:after{clear:both}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header{padding-top:5px;padding-bottom:5px;border-bottom:1px solid #d7d7d7}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header img{height:50px;width:auto}.okanjo-modal-container .okanjo-modal-window-skin{width:auto;height:auto;box-shadow:0 10px 25px rgba(0,0,0,.5);position:absolute;background:#fff;border-radius:4px;top:0;bottom:0;left:0;right:0}.okanjo-modal-container .okanjo-modal-window-outer{position:absolute;top:15px;left:15px;bottom:15px;right:15px;vertical-align:top}.okanjo-modal-container .okanjo-modal-window-inner{position:relative;width:100%;height:100%;-webkit-overflow-scrolling:touch;overflow:auto}.okanjo-modal-container .okanjo-modal-window-inner iframe{height:100%;width:100%;margin-right:-15px}.okanjo-modal-container .okanjo-modal-close-button{color:#fff;cursor:pointer;position:absolute;right:0;top:-48px;text-align:right;font-size:40px;line-height:1em;overflow:visible;width:40px;height:40px}',{id:\"okanjo-modal\"}),t.ui.engine.registerTemplate(\"okanjo.error\",'{{ message }} {{#code}} Reference: {{ code }} {{/code}}',{css:[\"okanjo.core\"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"okanjo.slab\",\".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab img.okanjo-fit{height:100%;width:100%;object-fit:cover}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.list .okanjo-resource-title-container{height:95px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource{width:298px}.okanjo-block2.okanjo-slab .okanjo-resource-publisher-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab .okanjo-resource-title-container{height:58px;font-size:16px;line-height:19px}.okanjo-block2.okanjo-slab .okanjo-resource.list .okanjo-resource-title-container{font-size:14px;height:60px}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource-title-container{font:16px/19px Georgia,serif}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource.list .okanjo-resource-title-container{font-size:15px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource-list{display:flex;flex-wrap:wrap;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource{width:inherit;flex-grow:1;flex-shrink:0;flex-basis:33.3333%;flex-basis:200px;display:flex;align-items:center;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list{flex-basis:33.3333%;flex-basis:250px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list a{width:100%}.okanjo-block2.okanjo-slab.responsive .okanjo-resource:last-child{margin:0 -1px -1px 0}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource,.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource:first-child{width:298px;height:248px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:13px;line-height:15px;height:50px;margin-top:1px;margin-bottom:4px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard.theme-newsprint .okanjo-resource .okanjo-resource-title-container{font:700 13px/15px Georgia,serif}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource-title-container{height:80px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource{width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:nth-last-child(n+2){width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:first-child{height:299px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-image-container{width:100%;height:180px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-title-container{margin-bottom:3px;height:77px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource-title-container{height:57px;margin-bottom:8px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource-title-container{height:116px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource{width:298px;height:198px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:nth-last-child(n+2){width:298px;height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:first-child{height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-image-container{width:100%;height:136px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-title-container{height:42px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource,.okanjo-block2.okanjo-slab.billboard .okanjo-resource:first-child{width:322px;height:248px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-info-container{margin-left:111px;width:auto}\",{id:\"okanjo-slab\"})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"products.block2\",\"\",{id:\"okanjo-product-block2\"}),t.ui.__product_block2='',t.ui.engine.registerTemplate(\"products.block2\",t.ui.__product_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.products=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),this._enforceLayoutOptions(),this._registerCustomBranding(\".okanjo-product\",\"buy-button\"),e},{css:[\"products.block2\",\"okanjo.block2\",\"okanjo.modal\"]})}(window),function(e){var t=e.okanjo;t.ui.engine.registerCss(\"products.slab\",\".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:14px;height:40px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:30px;font-size:12px;line-height:14px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button.theme-newsprint .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:13px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:0;height:32px;font-size:14px}.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:47px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;font-size:14px;line-height:16px;margin-bottom:2px}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:50px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;margin-bottom:0;line-height:15px;font-size:15px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:33px;font-size:15px;line-height:15px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-button-container,.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-price-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:auto;margin-bottom:2px;line-height:20px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-price-container{margin-bottom:0}.okanjo-block2.okanjo-slab.auto.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-price-container{margin-bottom:3px}\",{id:\"okanjo-product-slab\"}),t.ui.engine.registerTemplate(\"products.slab\",t.ui.__product_block2,function(e){var o=(this._response||{data:{results:[]}}).data||{results:[]};return e.blockClasses=[\"okanjo-slab\"],e.products=o.results,e.config=this.config,e.instanceId=this.instanceId,e.metricChannel=this._metricBase.ch,e.metricContext=this._metricBase.cx,e.metricParams=t.net.request.stringify(this._metricBase),e.fitImage=\"okanjo-fit\",this._enforceSlabLayoutOptions(),this._registerCustomBranding(\".okanjo-product\",\"button\"),e},{css:[\"products.slab\",\"okanjo.slab\",\"okanjo.block2\"]})}(window)}(okanjo);"],"file":"okanjo-bundle.min.js","sourceRoot":"./"} \ No newline at end of file diff --git a/dist/okanjo-metrics.js b/dist/okanjo-metrics.js index 9a675f2..5d7c8a0 100644 --- a/dist/okanjo-metrics.js +++ b/dist/okanjo-metrics.js @@ -1,4 +1,4 @@ -/*! okanjo-metrics.js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-metrics.js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ (function(root, factory) { if (typeof define === 'function' && define.amd) { define([], factory); @@ -319,7 +319,7 @@ var okanjo = function (window, document) { /** * Okanjo version */ - version: "1.19.1", + version: "1.20.0", /** * Placeholder diff --git a/dist/okanjo-metrics.min.js b/dist/okanjo-metrics.min.js index 9407672..b2751b0 100644 --- a/dist/okanjo-metrics.min.js +++ b/dist/okanjo-metrics.min.js @@ -1,4 +1,4 @@ -/*! okanjo-metrics.js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ -!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.okanjo=t()}(this,function(){function e(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var t=function(){function e(e,t){for(var n=0;n0?1:-1)*Math.floor(Math.abs(t)):t},r=Math.pow(2,53)-1,o=function(e){var t=n(e);return Math.min(Math.max(t,0),r)};return function(e){var n=this,r=Object(e);if(null==e)throw new TypeError("Array.from requires an array-like object - not null or undefined");var i,a=arguments.length>1?arguments[1]:void 0;if("undefined"!=typeof a){if(!t(a))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(i=arguments[2])}for(var u,s=o(r.length),c=t(n)?Object(new n(s)):new Array(s),l=0;l>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var r=arguments[1],o=0;o>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var r=arguments[1],o=0;o>>0;if(0===o)return!1;for(var i=0|t,a=Math.max(i>=0?i:o-Math.abs(i),0);a=0&&t.splice(i,1)}c.error("[Okanjo v"+f.version+"]: "+r.stack),t.length&&c.error.apply(c,["Additional information:"].concat(t))},warn:function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r0?1:-1)*Math.floor(Math.abs(t)):t},r=Math.pow(2,53)-1,o=function(e){var t=n(e);return Math.min(Math.max(t,0),r)};return function(e){var n=this,r=Object(e);if(null==e)throw new TypeError("Array.from requires an array-like object - not null or undefined");var i,a=arguments.length>1?arguments[1]:void 0;if("undefined"!=typeof a){if(!t(a))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(i=arguments[2])}for(var u,s=o(r.length),c=t(n)?Object(new n(s)):new Array(s),l=0;l>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var r=arguments[1],o=0;o>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var r=arguments[1],o=0;o>>0;if(0===o)return!1;for(var i=0|t,a=Math.max(i>=0?i:o-Math.abs(i),0);a=0&&t.splice(i,1)}c.error("[Okanjo v"+f.version+"]: "+r.stack),t.length&&c.error.apply(c,["Additional information:"].concat(t))},warn:function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r1&&void 0!==arguments[1]?arguments[1]:{},r={};return void 0!==e&&null!==e&&Object.keys(e).forEach(function(o){if(e[o]instanceof Date)t.dateToIso?r[o]=e[o].toISOString():r[o]=e[o];else if("object"===n(e[o])&&null!==e[o])if(Array.isArray(e[o])&&t.ignoreArrays===!0)r[o]=e[o];else if(Array.isArray(e[o])&&t.arrayToCsv===!0)r[o]=e[o].join(",");else{var i=f.util.flatten(e[o],t);Object.keys(i).forEach(function(e){r[o+"_"+e]=i[e]})}else r[o]=e[o]}),r},f.util.shortid=function(t){var n="ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC",r=e.crypto||e.msCrypto||"function"==typeof require&&require("crypto"),o=function(){if(r&&r.randomBytes)return 48&r.randomBytes(1)[0];if(!r||!r.getRandomValues)return 48&Math.floor(256*Math.random());var e=new Uint8Array(1);return r.getRandomValues(e),48&e[0]},i=function(e){for(var t=0,r=void 0,i="";!r;)i+=n[e>>4*t&15|o()],r=e0&&(e+=i(s)),e+=i(n)}}(),f.util.getLocation=function(){return e.location!==e.parent.location?t.referrer:t.location.href},f.ui={getScrollPosition:function(){return{x:r?e.pageXOffset:o?t.documentElement.scrollLeft:t.body.scrollLeft,y:r?e.pageYOffset:o?t.documentElement.scrollTop:t.body.scrollTop}},getElementSize:function(t,n){var r={height:t.offsetHeight,width:t.offsetWidth},o=t.currentStyle||e.getComputedStyle(t);return n&&(r.height+=parseInt(o.marginTop)+parseInt(o.marginBottom),r.width+=parseInt(o.marginLeft)+parseInt(o.marginRight)),r},getPageSize:function(){var e=t.querySelector("body"),n=t.documentElement;return{w:Math.max(e.scrollWidth,e.offsetWidth,n.clientWidth,n.scrollWidth,n.offsetWidth),h:Math.max(e.scrollHeight,e.offsetHeight,n.clientHeight,n.scrollHeight,n.offsetHeight)}},getViewportSize:function(){var n=o?t.documentElement:t.body,r=n.clientWidth,i=n.clientHeight,a=e.innerWidth||0,u=e.innerHeight||0,s=a&&r>a||u&&i>u;return{vw:s?a:r,vh:s?u:i}},getEventPosition:function(e){var n=e.pageX,r=e.pageY,o=t.body,i=t.documentElement,a="scrollLeft",u="scrollTop",s=e.__proto__.constructor.name;return{et:s,ex:void 0===n?e.clientX+o[a]+i[a]:n,ey:void 0===r?e.clientY+o[u]+i[u]:r}},getElementPosition:function(e){var n="Could not get position of element. Did you attach the element to the DOM before initializing?";try{var r=e.getBoundingClientRect(),o=t.body.getBoundingClientRect();return t.body.contains(e)||f.report(n,e),{x1:r.left-o.left,y1:r.top-o.top,x2:r.right-o.left,y2:r.bottom-o.top}}catch(i){return f.report(n,{exception:i,element:e}),{x1:0,y1:0,x2:0,y2:0,err:1}}},_getIntersection:function(e,t,n){var r=Math.max(e.x1,t.x),o=Math.min(e.x2,t.x+n.vw),i=Math.max(e.y1,t.y),a=Math.min(e.y2,t.y+n.vh),u=Math.max(0,o-r)*Math.max(0,a-i),s=(e.x2-e.x1)*(e.y2-e.y1);return{intersectionArea:u,elementArea:s}},isElementVisible:function(e){return e.offsetWidth>0&&e.offsetHeight>0},getPercentageInViewport:function(e){var t=f.ui.getElementPosition(e),n=f.ui.getScrollPosition(),r=f.ui.getViewportSize();if(t.err)return 0;var o=f.ui._getIntersection(t,n,r),i=o.intersectionArea,a=o.elementArea;return a<=0?0:i/a}},f.ui.ellipsify=function(e,n){for(var r=n||e.parentNode,o=f.ui.getElementSize(r).height,i=void 0!==e.textContent,u=i?e.textContent:e.innerText,s="",c=5e3,l=function(e){return s=e.substr(0,e.length-3)+s,"..."};f.ui.getElementSize(e).height>o&&u.length>0&&c-- >0;)u=i?e.textContent:e.innerText,u=u.replace(a,l),i?e.textContent=u:e.innerText=u;if(s.length>0){var d=t.createElement("span"),h=t.createElement("span");d.setAttribute("class","okanjo-ellipses"),h.setAttribute("class","okanjo-visually-hidden"),i?(d.textContent=u.substr(0,u.length-3),h.textContent=s):(d.innerText=u.substr(0,u.length-3),h.innerText=s),e.innerHTML="",e.appendChild(d),e.appendChild(h)}},f.ui.fitImages=function(e){"objectFit"in t.documentElement.style==!1&&e.querySelectorAll("img.okanjo-fit").forEach(function(e){e.style.display="none";var t=e.parentNode;t.style.backgroundSize="cover",t.style.backgroundImage="url("+e.src+")",t.style.backgroundposition="center center"})},e.okanjo=f}(window,document);return function(e){var t=/^application\/json/,r=e.okanjo;r.net.request=function(n,o,i,a){"function"==typeof i&&(a=i,i=void 0);var u=new(e.XMLHttpRequest||e.ActiveXObject)("MSXML2.XMLHTTP.3.0"),s=!1,c=function(e,t){s||(s=!0,a(e,t))};r.net.request.timeout&&(u.timeout=r.net.request.timeout),u.ontimeout=function(e){c({statusCode:504,error:"Request timed out",message:"Something went wrong",attributes:{event:e,xhr:u}})},u.onreadystatechange=function(e){if(4===u.readyState)if(u.status>0){var n=void 0;n=t.test(u.getResponseHeader("Content-Type"))?JSON.parse(u.responseText):{statusCode:u.status,data:u.responseText},u.status>=200&&u.status<300?c(null,n):c(n)}else c({statusCode:503,error:"Request failed",message:"Something went wrong",attributes:{event:e,xhr:u}})},u.open(n.toUpperCase(),o),u.withCredentials=!0,["POST","PUT","PATCH"].includes(n.toUpperCase())&&(u.setRequestHeader("Content-Type","application/json; charset=utf-8"),void 0!==i&&(i=JSON.stringify(i))),u.send(i||void 0)},r.net.request.get=r.net.request.bind(this,"GET"),r.net.request.post=r.net.request.bind(this,"POST"),r.net.request.put=r.net.request.bind(this,"PUT"),r.net.request["delete"]=r.net.request.bind(this,"DELETE");var o=function(e){return null===e||void 0===e?"":encodeURIComponent(""+e)},i=function(e,t){return t?t+"["+o(e)+"]":o(e)};r.net.request.stringify=function(e,t){var a=[];return t=t||"",Object.keys(e).forEach(function(u){var s=e[u];if(Array.isArray(s))s.forEach(function(e){return a.push(i(u,t)+"="+o(e))});else if("object"===("undefined"==typeof s?"undefined":n(s))&&null!==s){var c=r.net.request.stringify(s,i(u,t));c&&a.push(c)}else void 0!==s&&a.push(i(u,t)+"="+o(s))}),a.join("&")}}(window),function(e,t){e.okanjo.util.cookie={set:function(n,r,o){var i=new Date;i.setDate(i.getDate()+o);var a=o?" Expires="+i.toUTCString()+";":"",u=" Path=/",s="https:"===e.location.protocol?" Secure;":"",c=encodeURI(r)+";"+a+s+" SameSite=None;"+u;t.cookie=n+"="+c},get:function(e){var n=null;return t.cookie.split(";").find(function(t){var r=t.substr(0,t.indexOf("=")).trim(),o=t.substr(t.indexOf("=")+1);return r===e&&(n=decodeURI(o),!0)}),n}}}(window,document),function(n,r){var o=n.okanjo,i=function(){function i(){e(this,i),this._queue=this._getStoredQueue(),this._processTimeout=null,this.pageId=o.util.shortid(),this.defaultChannel=i.Channel.external,this.sid=null,this.sourceCh=null,this.sourceCx=null,this._checkUrlForReferral()}return t(i,[{key:"_getStoredQueue",value:function(){if(!n.localStorage[i.Params.queue])return[];try{var e=JSON.parse(n.localStorage[i.Params.queue]);return Array.isArray(e)?e:(o.report("Stored queue is not a queue",{queue:e}),[])}catch(t){return o.report("Failed to load metric queue from storage",{err:t}),[]}}},{key:"_saveQueue",value:function(e){var t=this;e?(this._saveQueueTimeout&&clearTimeout(this._saveQueueTimeout),this._saveQueueTimeout=setTimeout(function(){t._saveQueue(!1),t._saveQueueTimeout=null},100)):n.localStorage[i.Params.queue]=JSON.stringify(this._queue)}},{key:"_checkUrlForReferral",value:function(){var e=o.util.getPageArguments(!0),t=e[i.Params.name],r=n.localStorage[i.Params.name]||o.util.cookie.get(i.Params.name),a=e[i.Params.context],u=e[i.Params.channel];t&&r&&t!==r&&this.trackEvent({object_type:i.Object.metric_session,event_type:i.Event.correlation,id:t+"_"+r,ch:this.defaultChannel,_noProcess:!0}),this.sid=r||t||null,this.sourceCh=u||null,this.sourceCx=a||null}},{key:"trackEvent",value:function(e,t){return e.object_type&&e.event_type?void this._push(e,t):void o.report("Invalid metric to track (missing object_type or event_type)",{event:e})}},{key:"trackPageView",value:function(e,t){e=e||{},e.object_type=i.Object.page,e.event_type=i.Event.view,e.id=e.id||o.util.getLocation(),e.ch=e.ch||this.defaultChannel,this.trackEvent(e,t)}},{key:"_push",value:function(e,t){this._queue.push({event:e,callback:t}),this._saveQueue(!0),e._noProcess?delete e._noProcess:this._processQueue()}},{key:"_processQueue",value:function(){var e=this;!this._processTimeout&&this._queue.length>0&&(this._processTimeout=setTimeout(function(){var t=e._queue.splice(0,255);e._saveQueue(!1),e._batchSend(t,function(n,r){r&&r.data&&r.data.sid&&e._updateSid(r.data.sid),e._processTimeout=null,e._processQueue(),t.forEach(function(e){e.callback&&e.callback(n,r)})})},0))}},{key:"_batchSend",value:function(e,t){var n=this,r=e.map(function(e){return n._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),i={events:r,win:o.util.getLocation()},a=o.net.getRoute(o.net.routes.metrics_batch);this.sid&&(i.sid=this.sid),o.net.request.post(a,i,function(n,r){n&&o.report("Failed to send metrics batch",{err:n,res:r,items:e,route:a}),t&&t(n,r)})}},{key:"_normalizeEvent",value:function(e){e.m=e.m||{},e.key=e.key||e.m.key||o.key||void 0,this.sid&&(e.sid=this.sid),e.m=Object.assign({},e.m),Object.keys(i.Meta.exclude).forEach(function(t){return delete e.m[t]}),this.sourceCh&&(e.m.ref_ch=this.sourceCh),this.sourceCx&&(e.m.ref_cx=this.sourceCx),e.m.pgid=this.pageId,e.m.ok_ver=o.version,e.m=o.util.flatten(e.m,{arrayToCsv:!0}),Object.keys(e.m).forEach(function(t){"string"==typeof e.m[t]&&(e.m[t]=e.m[t].substr(0,255))}),r.referrer&&(e.ref=r.referrer),e.win=o.util.getLocation()}},{key:"_updateSid",value:function(e){!e||this.sid&&this.sid===e||(this.sid=e,n.localStorage[i.Params.name]=e,o.util.cookie.set(i.Params.name,e,i.Params.ttl))}},{key:"create",value:function(){for(var e=arguments.length,t=Array(e),n=0;nt?e:t},h=function(e,t){return"undefined"==typeof e?t:e};return r.forEach(function(e){i=o.ui.getElementPosition(e),a=f(i.x1,a),u=f(i.y1,u),s=d(i.x2,s),c=d(i.y2,c),l.push(i.x1,i.y1,i.x2,i.y2)}),t.m.wix1=h(a,n.x1),t.m.wiy1=h(u,n.y1),t.m.wix2=h(s,n.x2),t.m.wiy2=h(c,n.y2),t.m.wrps=l.map(function(e){return Math.floor(e)}).join(","),t}},{key:"addViewportInfo",value:function(e){var t=o.ui.getViewportSize(),n=o.ui.getScrollPosition();return e=e||{},e.m=e.m||{},e.m.vx1=n.x,e.m.vy1=n.y,e.m.vx2=n.x+t.vw,e.m.vy2=n.y+t.vh,e}},{key:"addEventInfo",value:function(e,t){var n=o.ui.getEventPosition(e);return t=t||{},t.m=t.m||{},t.m.et=n.et,t.m.ex=n.ex,t.m.ey=n.ey,t}},{key:"addEventMeta",value:function(e){e=e||{},e.m=e.m||{};for(var t=arguments.length,n=Array(t>1?t-1:0),r=1;r1?t-1:0),r=1;r 0 ? 1 : -1) * Math.floor(Math.abs(number));\n };\n var maxSafeInteger = Math.pow(2, 53) - 1;\n var toLength = function toLength(value) {\n var len = toInteger(value);\n return Math.min(Math.max(len, 0), maxSafeInteger);\n };\n\n // The length property of the from method is 1.\n return function from(arrayLike /*, mapFn, thisArg */) {\n // 1. Let C be the this value.\n var C = this;\n\n // 2. Let items be ToObject(arrayLike).\n var items = Object(arrayLike);\n\n // 3. ReturnIfAbrupt(items).\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object - not null or undefined');\n }\n\n // 4. If mapfn is undefined, then let mapping be false.\n var mapFn = arguments.length > 1 ? arguments[1] : void undefined;\n var T;\n if (typeof mapFn !== 'undefined') {\n // 5. else\n // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.\n if (!isCallable(mapFn)) {\n throw new TypeError('Array.from: when provided, the second argument must be a function');\n }\n\n // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.\n if (arguments.length > 2) {\n T = arguments[2];\n }\n }\n\n // 10. Let lenValue be Get(items, \"length\").\n // 11. Let len be ToLength(lenValue).\n var len = toLength(items.length);\n\n // 13. If IsConstructor(C) is true, then\n // 13. a. Let A be the result of calling the [[Construct]] internal method\n // of C with an argument list containing the single item len.\n // 14. a. Else, Let A be ArrayCreate(len).\n var A = isCallable(C) ? Object(new C(len)) : new Array(len);\n\n // 16. Let k be 0.\n var k = 0;\n // 17. Repeat, while k < len… (also steps a - h)\n var kValue;\n while (k < len) {\n kValue = items[k];\n if (mapFn) {\n A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);\n } else {\n A[k] = kValue;\n }\n k += 1;\n }\n // 18. Let putStatus be Put(A, \"length\", len, true).\n A.length = len;\n // 20. Return A.\n return A;\n };\n }();\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.find\nif (!Array.prototype.find) {\n Object.defineProperty(Array.prototype, 'find', {\n value: function value(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return kValue.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return kValue;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return undefined.\n return undefined;\n }\n });\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex\nif (!Array.prototype.findIndex) {\n Object.defineProperty(Array.prototype, 'findIndex', {\n value: function value(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return k.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return k;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return -1.\n return -1;\n }\n });\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.includes\nif (!Array.prototype.includes) {\n Object.defineProperty(Array.prototype, 'includes', {\n value: function value(searchElement, fromIndex) {\n\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n // 1. Let O be ? ToObject(this value).\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If len is 0, return false.\n if (len === 0) {\n return false;\n }\n\n // 4. Let n be ? ToInteger(fromIndex).\n // (If fromIndex is undefined, this step produces the value 0.)\n var n = fromIndex | 0;\n\n // 5. If n ≥ 0, then\n // a. Let k be n.\n // 6. Else n < 0,\n // a. Let k be len + n.\n // b. If k < 0, let k be 0.\n var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\n\n function sameValueZero(x, y) {\n return x === y || typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y);\n }\n\n // 7. Repeat, while k < len\n while (k < len) {\n // a. Let elementK be the result of ? Get(O, ! ToString(k)).\n // b. If SameValueZero(searchElement, elementK) is true, return true.\n if (sameValueZero(o[k], searchElement)) {\n return true;\n }\n // c. Increase k by 1.\n k++;\n }\n\n // 8. Return false\n return false;\n }\n });\n}\n// https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach\nif (window.NodeList && !NodeList.prototype.forEach) {\n NodeList.prototype.forEach = function (callback, thisArg) {\n thisArg = thisArg || window;\n for (var i = 0; i < this.length; i++) {\n callback.call(thisArg, this[i], i, this);\n }\n };\n}\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\nif (typeof Object.assign != 'function') {\n // Must be writable: true, enumerable: false, configurable: true\n Object.defineProperty(Object, \"assign\", {\n value: function assign(target, varArgs) {\n // .length of function is 2\n 'use strict';\n\n if (target == null) {\n // TypeError if undefined or null\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n var to = Object(target);\n\n for (var index = 1; index < arguments.length; index++) {\n var nextSource = arguments[index];\n\n if (nextSource != null) {\n // Skip over if undefined or null\n for (var nextKey in nextSource) {\n // Avoid bugs when hasOwnProperty is shadowed\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n },\n writable: true,\n configurable: true\n });\n}\n\"use strict\";\n\n/* exported okanjo */\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/**\n * Okanjo widget framework namespace\n * @global okanjo\n */\nvar okanjo = function (window, document) {\n\n //region Constants\n\n // Environment Vars\n var SUPPORTS_PAGE_OFFSET = window.pageXOffset !== undefined;\n var CSS1_COMPATIBLE = (document.compatMode /* istanbul ignore next: out of scope */ || \"\") === \"CSS1Compat\";\n var AGENT = window.navigator.userAgent;\n var ELLIPSIFY_PATTERN = /[\\s\\S](?:\\.\\.\\.)?$/;\n var MOBILE_PATTERN = /(iPhone|iPad|iPod|Android|blackberry)/i;\n var NOOP = function NOOP() {};\n var Console = window.console;\n\n // Place to pull defaults, if already set\n var settings = window.okanjo || {};\n\n //endregion\n\n //region Okanjo Core\n\n\n //noinspection JSValidateJSDoc,JSClosureCompilerSyntax - idk phpStorm generated it so why would it be wrong? :P\n /**\n * Okanjo namespace\n * @global\n * @type {{version: string, metrics: null, key: null, report: ((...p1?:*[])), warn: ((p1?:*, ...p2?:*[])), qwery: ((p1?:*, p2?:*))}}\n */\n var okanjo = {\n\n /**\n * Okanjo version\n */\n version: \"1.19.1\",\n\n /**\n * Placeholder\n */\n metrics: null,\n\n /**\n * Global/default placement key\n */\n key: settings.key || null,\n\n /**\n * Reports an error to the console and possibly Raven in the future\n * @param args\n */\n report: function report() {\n for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n var err = args.find(function (arg) {\n return arg instanceof Error;\n });\n if (!err) {\n var messageIndex = args.findIndex(function (arg) {\n return typeof arg === \"string\";\n });\n err = new Error(args[messageIndex] || \"Okanjo Error\");\n if (messageIndex >= 0) args.splice(messageIndex, 1);\n } else {\n // Grow our own stack so we can figure out what async thing did it\n var stack = new Error().stack.split('\\n');\n stack.shift();\n stack.shift();\n args.push({ reportStack: stack.join('\\n') });\n args = args.filter(function (a) {\n return a !== err;\n });\n }\n\n Console.error('[Okanjo v' + okanjo.version + ']: ' + err.stack);\n args.length && Console.error.apply(Console, ['Additional information:'].concat(args));\n\n // TODO - integrate with Raven\n },\n\n /**\n * Warn developers of their misdeeds\n * @param message\n * @param args\n */\n warn: function warn(message) {\n for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n\n var err = new Error(message);\n\n Console.warn('[Okanjo v' + okanjo.version + ']: ' + err.stack);\n args.length && Console.warn.apply(Console, ['Additional information:'].concat(args));\n },\n\n // Backwards compatibility when we shipped with qwery, cuz querySelector[All] wasn't mainstream enough\n qwery: function qwery(selector, parent) {\n\n // If parent is a selector, select the parent first!\n if (typeof parent === \"string\") {\n parent = document.querySelector(parent);\n\n // If parent is not found, there are obviously no results\n if (!parent) return [];\n }\n\n if (!parent) parent = document;\n\n return parent.querySelectorAll(selector);\n }\n };\n\n //endregion\n\n //region Vendor Libs\n\n /**\n * Placeholder for where vendor libraries get no-conflict loaded\n * @type {{}}\n */\n okanjo.lib = {};\n\n //endregion\n\n //region Networking\n\n /**\n * Networking methods\n * @type {{getRoute: *, exec: *}}\n */\n okanjo.net = {\n\n /**\n * API Endpoints\n */\n endpoint: 'https://api2.okanjo.com',\n sandboxEndpoint: 'https://sandbox-api2.okanjo.com',\n\n /**\n * API routes\n */\n routes: {\n ads: '/content',\n metrics: '/metrics/:object_type/:event_type',\n metrics_batch: '/metrics'\n },\n\n /**\n * Compiles a route and parameters into a final URL\n * @param {string} route - Route constant\n * @param {*} [params] - Key value hash\n * @param {*} [env] - Optional environment to use instead of live\n * @return {string} - Route\n */\n getRoute: function getRoute(route, params, env) {\n if (params) {\n Object.keys(params).forEach(function (key) {\n route = route.replace(':' + key, params[key] + \"\");\n });\n }\n env = env || okanjo.env || 'live';\n return (env === 'sandbox' ? okanjo.net.sandboxEndpoint : okanjo.net.endpoint) + route;\n },\n\n // placeholder, xhr request extension\n request: NOOP\n };\n\n //endregion\n\n // region Utilities\n\n //noinspection JSClosureCompilerSyntax,JSValidateJSDoc\n /**\n * Utility functions and helpers\n * @type {{isEmpty: ((p1?:*)=>boolean), isMobile: (()), getPageArguments: ((p1:boolean))}}\n */\n okanjo.util = {\n\n /**\n * Checks whether a value is _really_ empty (trims)\n * @param val\n * @return {boolean}\n */\n isEmpty: function isEmpty(val) {\n return val === null || val === undefined || typeof val === \"string\" && val.trim().length === 0;\n },\n\n /**\n * Checks if the current user agent identifies as a mobile device\n * @returns {boolean}\n */\n isMobile: function isMobile() {\n // KludgyAF™, but let's go with it\n return MOBILE_PATTERN.test(AGENT);\n },\n\n /**\n * Returns an object hashmap of query and hash parameters\n * @param {boolean} includeHashArguments - Whether to include the hash arguments, if any\n * @return {*}\n */\n getPageArguments: function getPageArguments(includeHashArguments) {\n\n var split = function split(query) {\n query = query || \"\";\n var params = {};\n var parts = query.split('&');\n parts.forEach(function (part) {\n var eqIndex = part.indexOf('=');\n var key = void 0,\n value = void 0;\n if (eqIndex < 0) {\n key = decodeURIComponent(part);\n value = null;\n } else {\n key = decodeURIComponent(part.substring(0, eqIndex));\n value = decodeURIComponent(part.substring(eqIndex + 1));\n }\n if (key) params[key] = value;\n });\n return params;\n };\n\n var queryArgs = split(window.location.search.substring(window.location.search.indexOf('?') + 1));\n var hashArgs = includeHashArguments ? split(window.location.hash.substring(Math.max(window.location.hash.indexOf('#') + 1, window.location.hash.indexOf('#!') + 2))) : {};\n Object.keys(hashArgs).forEach(function (key) {\n return queryArgs[key] = hashArgs[key];\n });\n\n return queryArgs;\n }\n\n };\n\n /**\n * Deep clones an object by breaking references, unlike Object.assign\n * @param mixed – Source to clone (object, array, value)\n * @param [out] - Existing output, if any\n * @return {*}\n */\n okanjo.util.deepClone = function (mixed, out) {\n if (Array.isArray(mixed)) {\n // Array reference\n out = out || [];\n out = out.concat(mixed.map(function (val) {\n return okanjo.util.deepClone(val);\n }));\n } else if ((typeof mixed === 'undefined' ? 'undefined' : _typeof(mixed)) === \"object\" && mixed !== null) {\n // Object reference\n out = out || {};\n Object.keys(mixed).forEach(function (key) {\n out[key] = okanjo.util.deepClone(mixed[key]);\n });\n } else {\n // Value\n out = mixed;\n }\n\n return out;\n };\n\n /**\n * Flattens a multi-dimensional object into a single object\n * @param input\n * @param [options]\n * @return {{}}\n */\n okanjo.util.flatten = function (input) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n var output = {};\n\n if (input !== undefined && input !== null) {\n Object.keys(input).forEach(function (key) {\n // Convert object ids to hex strings\n if (input[key] instanceof Date) {\n if (options.dateToIso) {\n output[key] = input[key].toISOString(); // convert to iso\n } else {\n output[key] = input[key]; // as-is\n }\n } else if (_typeof(input[key]) === 'object' && input[key] !== null) {\n // Allow ignoring arrays if desired\n if (Array.isArray(input[key]) && options.ignoreArrays === true) {\n output[key] = input[key];\n } else if (Array.isArray(input[key]) && options.arrayToCsv === true) {\n output[key] = input[key].join(',');\n } else {\n // Make child objects flat too (always returns object so Object.keys is safe)\n var childObject = okanjo.util.flatten(input[key], options);\n Object.keys(childObject).forEach(function (childKey) {\n output[key + '_' + childKey] = childObject[childKey];\n });\n }\n } else {\n // Copy value references\n output[key] = input[key];\n }\n });\n }\n\n return output;\n };\n\n /*! based on shortid https://github.com/dylang/shortid */\n okanjo.util.shortid = function (clusterWorkerId) {\n\n var shuffled = 'ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC',\n crypto = window.crypto || window.msCrypto || typeof require === \"function\" && require('crypto'),\n randomByte = function randomByte() {\n /* istanbul ignore next: platform diffs out of scope */\n if (crypto && crypto.randomBytes) {\n return crypto.randomBytes(1)[0] & 0x30;\n } else if (!crypto || !crypto.getRandomValues) {\n return Math.floor(Math.random() * 256) & 0x30;\n }\n /* istanbul ignore next: platform diffs out of scope */\n var dest = new Uint8Array(1);\n /* istanbul ignore next: platform diffs out of scope */\n crypto.getRandomValues(dest);\n /* istanbul ignore next: platform diffs out of scope */\n return dest[0] & 0x30;\n },\n encode = function encode(number) {\n var loopCounter = 0,\n done = void 0,\n str = '';\n\n while (!done) {\n str = str + shuffled[number >> 4 * loopCounter & 0x0f | randomByte()];\n done = number < Math.pow(16, loopCounter + 1);\n loopCounter++;\n }\n return str;\n },\n\n\n // Ignore all milliseconds before a certain time to reduce the size of the date entropy without sacrificing uniqueness.\n // This number should be updated every year or so to keep the generated id short.\n // To regenerate `new Date() - 0` and bump the version. Always bump the version!\n\n REDUCE_TIME = 1490384907498,\n version = 7;\n\n var counter = void 0,\n previousSeconds = void 0;\n\n clusterWorkerId = clusterWorkerId || 0;\n\n return function () {\n var str = '',\n seconds = Math.floor((new Date().getTime() - REDUCE_TIME) * 0.001);\n\n if (seconds === previousSeconds) {\n counter++;\n } else {\n counter = 0;\n previousSeconds = seconds;\n }\n\n str = str + encode(version) + encode(clusterWorkerId);\n if (counter > 0) {\n str = str + encode(counter);\n }\n str = str + encode(seconds);\n\n return str;\n };\n }();\n\n /**\n * Gets the best URL for where we are operating\n * @returns {string|*}\n */\n okanjo.util.getLocation = function () {\n return window.location !== window.parent.location ? /* istanbul ignore next: oos */document.referrer : document.location.href;\n };\n\n //endregion\n\n //region User Interface\n\n okanjo.ui = {\n\n /**\n * Gets the current page scroll position\n * @returns {{x: Number, y: Number}}\n */\n getScrollPosition: function getScrollPosition() {\n return {\n x: SUPPORTS_PAGE_OFFSET ? window.pageXOffset : /* istanbul ignore next: old browsers */CSS1_COMPATIBLE ? document.documentElement.scrollLeft : document.body.scrollLeft,\n y: SUPPORTS_PAGE_OFFSET ? window.pageYOffset : /* istanbul ignore next: old browsers */CSS1_COMPATIBLE ? document.documentElement.scrollTop : document.body.scrollTop\n };\n },\n\n /**\n * Gets the height and width of the given element\n * @param {HTMLElement|Node} element – The DOM element to get the size of\n * @param {boolean} [includeMargin] – Whether to include the margins of the element in the size\n * @returns {{height: number, width: number}}\n */\n getElementSize: function getElementSize(element, includeMargin) {\n var size = {\n height: element.offsetHeight,\n width: element.offsetWidth\n };\n var style = element.currentStyle || window.getComputedStyle(element);\n\n if (includeMargin) {\n size.height += parseInt(style.marginTop) + parseInt(style.marginBottom);\n size.width += parseInt(style.marginLeft) + parseInt(style.marginRight);\n }\n\n return size;\n },\n\n /**\n * Gets the current page size\n * @return {{w: number, h: number}}\n */\n getPageSize: function getPageSize() {\n var body = document.querySelector('body');\n var html = document.documentElement;\n\n return {\n w: Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth),\n\n h: Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight)\n };\n },\n\n /**\n * Gets the current viewport size\n * @return {{vw: number, vh: number}}\n */\n getViewportSize: function getViewportSize() {\n var element = CSS1_COMPATIBLE ? document.documentElement /* istanbul ignore next: browser diffs */ : document.body;\n var width = element.clientWidth;\n var height = element.clientHeight;\n var inWidth = window.innerWidth /* istanbul ignore next: browser diffs */ || 0;\n var inHeight = window.innerHeight /* istanbul ignore next: browser diffs */ || 0;\n var isMobileZoom = inWidth && width > inWidth || inHeight && height > inHeight;\n\n return {\n vw: isMobileZoom /* istanbul ignore next: browser diffs */ ? inWidth : width,\n vh: isMobileZoom /* istanbul ignore next: browser diffs */ ? inHeight : height\n };\n },\n\n /**\n * Gets the x, y location of the event relative to the page\n * @param event – Mouse/Touch Event\n * @return {{ex: number, ey: number}}\n */\n getEventPosition: function getEventPosition(event) {\n var ex = event.pageX;\n var ey = event.pageY;\n var body = document.body;\n var el = document.documentElement;\n var scrollLeft = 'scrollLeft';\n var scrollTop = 'scrollTop';\n var type = event.__proto__.constructor.name;\n\n return {\n et: type, // mouse? touch? keyboard? robot?\n ex: ex === undefined /* istanbul ignore next: browser diffs */ ? event.clientX + body[scrollLeft] + el[scrollLeft] : ex,\n ey: ey === undefined /* istanbul ignore next: browser diffs */ ? event.clientY + body[scrollTop] + el[scrollTop] : ey\n };\n },\n\n /**\n * Gets the element's rectangle coordinates on the page\n * @param element\n * @return {{x1: number, y1: number, x2: number, y2: number}}\n */\n getElementPosition: function getElementPosition(element) {\n\n // Wrapped in try-catch because IE is super strict about the\n // element being on the DOM before you call this. Other browsers\n // let it slide, but oh well.\n\n var err = 'Could not get position of element. Did you attach the element to the DOM before initializing?';\n try {\n var rect = element.getBoundingClientRect();\n var body = document.body.getBoundingClientRect();\n // let pos = okanjo.ui.getScrollPosition();\n\n /* istanbul ignore else: jsdom doesn't mock this */\n if (!document.body.contains(element)) {\n okanjo.report(err, element);\n }\n return {\n // x1: rect.left + pos.x,\n // y1: rect.top + pos.y,\n // x2: rect.right + pos.x,\n // y2: rect.bottom + pos.y\n\n // This might fix\n x1: rect.left - body.left,\n y1: rect.top - body.top,\n x2: rect.right - body.left,\n y2: rect.bottom - body.top\n\n };\n } catch (e) {\n okanjo.report(err, { exception: e, element: element });\n return {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: 0,\n err: 1\n };\n }\n },\n\n /**\n * Gets the intersection information given the element, viewport and scroll positions\n * @param e – Element position\n * @param s - Scroll position\n * @param v - Viewport size\n * @return {{intersectionArea: number, elementArea: number}}\n * @private\n */\n _getIntersection: function _getIntersection(e, s, v) {\n var iLeft = Math.max(e.x1, s.x),\n iRight = Math.min(e.x2, s.x + v.vw),\n iTop = Math.max(e.y1, s.y),\n iBottom = Math.min(e.y2, s.y + v.vh),\n intersectionArea = Math.max(0, iRight - iLeft) * Math.max(0, iBottom - iTop),\n elementArea = (e.x2 - e.x1) * (e.y2 - e.y1);\n\n return {\n intersectionArea: intersectionArea,\n elementArea: elementArea\n };\n },\n\n /**\n * Checks whether the element is actually displayed on the DOM\n * @param element\n * @return {boolean}\n */\n isElementVisible: function isElementVisible(element) {\n /* istanbul ignore next: jsdom won't trigger this */\n return element.offsetWidth > 0 && element.offsetHeight > 0;\n },\n\n /**\n * Gets the percentage of the element pixels currently within the viewport\n * @param {HTMLElement|Node} element\n * @return {number}\n */\n getPercentageInViewport: function getPercentageInViewport(element) {\n var e = okanjo.ui.getElementPosition(element),\n s = okanjo.ui.getScrollPosition(),\n v = okanjo.ui.getViewportSize();\n\n // If there was a problem getting the element position, fail fast\n if (e.err) return 0;\n\n // Get intersection rectangle\n\n var _okanjo$ui$_getInters = okanjo.ui._getIntersection(e, s, v),\n intersectionArea = _okanjo$ui$_getInters.intersectionArea,\n elementArea = _okanjo$ui$_getInters.elementArea;\n\n // Don't let it return NaN\n /* istanbul ignore else: jsdom no love positional data */\n\n\n if (elementArea <= 0) return 0;\n\n /* istanbul ignore next: jsdom no love positional data, area tested with helper fn tho */\n return intersectionArea / elementArea;\n }\n };\n\n /**\n * Splits the text in the element to fit within the visible height of its container, and separates with an ellipses\n * @param {HTMLElement|Node} element – The DOM element containing the text to fit\n * @param {HTMLElement} [container] – Optional container to compute fit on. Defaults to the element's parent\n */\n okanjo.ui.ellipsify = function (element, container) {\n\n // It's a sad day when you have to resort to JS because CSS kludges are too hacky to work down to IE8, programmatically\n\n //noinspection JSValidateTypes\n var parent = container || element.parentNode,\n targetHeight = okanjo.ui.getElementSize(parent).height,\n useTextContent = element.textContent !== undefined;\n\n var text = useTextContent ? element.textContent /* istanbul ignore next: browser diffs */ : element.innerText,\n replacedText = \"\",\n safety = 5000,\n // Safety switch to bust out of the loop in the event something goes terribly wrong\n replacer = function replacer(match) {\n /* istanbul ignore next: n/a to jsdom */\n replacedText = match.substr(0, match.length - 3) + replacedText;\n /* istanbul ignore next: n/a to jsdom */\n return '...';\n };\n\n // Trim off characters until we can fit the text and ellipses\n // If the text already fits, this loop is ignored\n /* istanbul ignore next: jsdom doesn't do element size computing stuff */\n while (okanjo.ui.getElementSize(element).height > targetHeight && text.length > 0 && safety-- > 0) {\n text = useTextContent ? element.textContent : element.innerText;\n\n text = text.replace(ELLIPSIFY_PATTERN, replacer);\n\n if (useTextContent) {\n element.textContent = text;\n } else {\n element.innerText = text;\n }\n }\n\n // If there is work to do, split the content into two span tags\n // Like so: [content]...[hidden content]\n /* istanbul ignore if: n/a to jsdom */\n if (replacedText.length > 0) {\n\n var content = document.createElement('span'),\n span = document.createElement('span');\n\n content.setAttribute('class', 'okanjo-ellipses');\n span.setAttribute('class', 'okanjo-visually-hidden');\n\n if (useTextContent) {\n content.textContent = text.substr(0, text.length - 3);\n span.textContent = replacedText;\n } else {\n content.innerText = text.substr(0, text.length - 3);\n span.innerText = replacedText;\n }\n\n element.innerHTML = '';\n element.appendChild(content);\n element.appendChild(span);\n }\n };\n\n /**\n * Locates images with the class okanjo-fit and ensures that they get filled.\n * This is basically a object-fit hacky workaround\n * @param element\n */\n okanjo.ui.fitImages = function (element) {\n // Detect objectFit support\n /* istanbul ignore else: n/a to jsdom */\n if ('objectFit' in document.documentElement.style === false) {\n // Find images to fit\n element.querySelectorAll('img.okanjo-fit').forEach(function (img) {\n\n // Hide the image\n img.style.display = 'none';\n\n // Update the parent w/ the background\n var parent = img.parentNode;\n parent.style.backgroundSize = 'cover';\n parent.style.backgroundImage = 'url(' + img.src + ')';\n parent.style.backgroundposition = 'center center';\n });\n }\n };\n\n //endregion\n\n // Export the root namespace\n return window.okanjo = okanjo;\n}(window, document);\n\"use strict\";\n\n(function (window) {\n\n var JSON_TEST = /^application\\/json/;\n var okanjo = window.okanjo;\n\n /**\n * Performs a reliable XHR request\n * @param {string} method - Request method\n * @param {string} url - URL\n * @param [payload] optional payload\n * @param callback Fired on when completed (err, res), normalized to standard response format\n */\n okanjo.net.request = function (method, url, payload, callback) {\n\n // payload is not required\n if (typeof payload === \"function\") {\n callback = payload;\n payload = undefined;\n }\n\n // Create a new instance\n var req = new (window.XMLHttpRequest /* istanbul ignore next: old ie */ || window.ActiveXObject)('MSXML2.XMLHTTP.3.0');\n\n // Flag to prevent duplicate callbacks / races\n var calledBack = false;\n\n // Normalized done handler\n var done = function done(err, res) {\n /* istanbul ignore else: out of scope */\n if (!calledBack) {\n calledBack = true;\n callback(err, res);\n }\n };\n\n // Apply timeout if configured globally\n if (okanjo.net.request.timeout) {\n req.timeout = okanjo.net.request.timeout;\n }\n\n // Catch timeout errors\n req.ontimeout = function (e) {\n /* istanbul ignore next: idk if jsdom can mock this, also readystatechange may fire before this anyway */\n done({\n statusCode: 504,\n error: \"Request timed out\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n };\n\n // Handle the response\n req.onreadystatechange = function (e) {\n // 4 = completed / failed\n if (req.readyState === 4) {\n // Do we have a response?\n if (req.status > 0) {\n var res = void 0;\n\n // Check if we got JSON and parse it right away\n if (JSON_TEST.test(req.getResponseHeader('Content-Type'))) {\n res = JSON.parse(req.responseText);\n } else {\n // Not JSON, normalize it instead\n res = {\n statusCode: req.status,\n data: req.responseText\n };\n }\n\n // Put the response in the proper slot (err for non success responses)\n if (req.status >= 200 && req.status < 300) {\n done(null, res);\n } else {\n done(res);\n }\n } else {\n // Request failed - e.g. CORS or network issues\n done({\n statusCode: 503,\n error: \"Request failed\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n }\n }\n };\n\n // Open the request\n req.open(method.toUpperCase(), url);\n\n // Include credentials\n req.withCredentials = true;\n\n // Handle post payloads\n if (['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {\n req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n if (payload !== undefined) {\n payload = JSON.stringify(payload);\n }\n }\n\n // Ship it\n req.send(payload || undefined);\n };\n\n // Bind helpers to make things easy as pie\n okanjo.net.request.get = okanjo.net.request.bind(this, 'GET');\n okanjo.net.request.post = okanjo.net.request.bind(this, 'POST');\n okanjo.net.request.put = okanjo.net.request.bind(this, 'PUT');\n okanjo.net.request.delete = okanjo.net.request.bind(this, 'DELETE');\n\n /**\n * Helper to aid in minificiation+querystringify and redundant encodeURIComponent stuff\n * @param val\n * @return {*}\n */\n var encode = function encode(val) {\n if (val === null || val === undefined) return '';\n return encodeURIComponent('' + val);\n };\n\n /**\n * Helper to aid in getting a query string key using a prefix and keyname\n * @param key\n * @param keyPrefix\n * @return {*}\n */\n var getKey = function getKey(key, keyPrefix) {\n if (keyPrefix) {\n return keyPrefix + '[' + encode(key) + ']';\n } else {\n return encode(key);\n }\n };\n\n /**\n * Super basic querystringify helper. It handles deep objects, but not for array values\n * @param obj\n * @param [keyPrefix]\n * @return {string}\n */\n okanjo.net.request.stringify = function (obj, keyPrefix) {\n var pairs = [];\n keyPrefix = keyPrefix || \"\";\n Object.keys(obj).forEach(function (key) {\n var value = obj[key];\n if (Array.isArray(value)) {\n value.forEach(function (v) {\n return pairs.push(getKey(key, keyPrefix) + '=' + encode(v));\n }); // Does not do that PHP garbage with key[]=val\n } else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === \"object\" && value !== null) {\n // Recurse\n var res = okanjo.net.request.stringify(value, getKey(key, keyPrefix));\n if (res) pairs.push(res);\n } else if (value !== undefined) {\n pairs.push(getKey(key, keyPrefix) + '=' + encode(value));\n }\n });\n return pairs.join('&');\n };\n})(window);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function (window, document) {\n\n /**\n * Okanjo cookie utility helpers\n */\n window.okanjo.util.cookie = {\n\n /**\n * Sets a cookie\n * @param cookieName\n * @param value\n * @param expireDays\n */\n set: function set(cookieName, value, expireDays) {\n var expireDate = new Date();\n expireDate.setDate(expireDate.getDate() + expireDays);\n var expires = expireDays ? \" Expires=\" + expireDate.toUTCString() + \";\" : \"\";\n var path = \" Path=/\";\n var secure = window.location.protocol === 'https:' ? ' Secure;' : '';\n // const secure = ' Secure;';\n var cookieValue = encodeURI(value) + ';' + expires + secure + ' SameSite=None;' + path;\n // console.log('setting cookie', cookieName, cookieValue)\n document.cookie = cookieName + \"=\" + cookieValue;\n },\n\n /**\n * Gets a cookie\n * @param cookieName\n * @return {*}\n */\n get: function get(cookieName) {\n var output = null;\n document.cookie.split(\";\").find(function (cookie) {\n var nameTest = cookie.substr(0, cookie.indexOf(\"=\")).trim();\n var value = cookie.substr(cookie.indexOf(\"=\") + 1);\n if (nameTest === cookieName) {\n output = decodeURI(value);\n return true;\n } else {\n return false;\n }\n });\n return output;\n }\n };\n})(window, document);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window, document) {\n\n var okanjo = window.okanjo;\n\n /**\n * Event tracking class\n * @type {Metrics}\n */\n\n var Metrics = function () {\n\n //noinspection JSUnusedGlobalSymbols\n function Metrics() {\n _classCallCheck(this, Metrics);\n\n /**\n * Events queued here before submission\n * @type {Array}\n * @private\n */\n this._queue = this._getStoredQueue();\n this._processTimeout = null; // queue event loop timeout pointer\n\n /**\n * Unique page grouping event identifier\n */\n this.pageId = okanjo.util.shortid();\n this.defaultChannel = Metrics.Channel.external;\n\n this.sid = null;\n this.sourceCh = null;\n this.sourceCx = null;\n\n // Extract referral data, if set\n this._checkUrlForReferral();\n\n // TODO - look into iframe session correlation system\n }\n\n //noinspection JSMethodCanBeStatic\n /**\n * Gets the storage backed metric queue, in case we did not send everything last time\n * @return {Array}\n * @private\n */\n\n\n _createClass(Metrics, [{\n key: '_getStoredQueue',\n value: function _getStoredQueue() {\n if (window.localStorage[Metrics.Params.queue]) {\n try {\n var queue = JSON.parse(window.localStorage[Metrics.Params.queue]);\n if (Array.isArray(queue)) {\n return queue;\n } else {\n okanjo.report('Stored queue is not a queue', { queue: queue });\n return [];\n }\n } catch (e) {\n okanjo.report('Failed to load metric queue from storage', { err: e });\n return [];\n }\n } else {\n // not stored\n return [];\n }\n }\n\n /**\n * Updates the queue stored in storage, in the event we can't complete our submissions\n * @param delay - Whether to delay updating the queue for a bit, to let other metrics pile in\n * @private\n */\n\n }, {\n key: '_saveQueue',\n value: function _saveQueue(delay) {\n var _this = this;\n\n if (delay) {\n if (this._saveQueueTimeout) clearTimeout(this._saveQueueTimeout);\n this._saveQueueTimeout = setTimeout(function () {\n _this._saveQueue(false);\n _this._saveQueueTimeout = null;\n }, 100);\n } else {\n window.localStorage[Metrics.Params.queue] = JSON.stringify(this._queue);\n }\n }\n\n /**\n * Extract contextual pass-through data from the URL, if present\n * @private\n */\n\n }, {\n key: '_checkUrlForReferral',\n value: function _checkUrlForReferral() {\n var pageArgs = okanjo.util.getPageArguments(true),\n urlSid = pageArgs[Metrics.Params.name],\n localSid = window.localStorage[Metrics.Params.name] || okanjo.util.cookie.get(Metrics.Params.name),\n // pull from storage or cookie\n sourceContext = pageArgs[Metrics.Params.context],\n sourceChannel = pageArgs[Metrics.Params.channel];\n\n // If for some reason, both are set, record the incident as a possible correlation\n if (urlSid && localSid && urlSid !== localSid) {\n this.trackEvent({\n object_type: Metrics.Object.metric_session,\n event_type: Metrics.Event.correlation,\n id: urlSid + \"_\" + localSid,\n ch: this.defaultChannel,\n _noProcess: true\n });\n }\n\n // Update local values\n this.sid = localSid || urlSid || null; // prefer local over remote (changed in 1.0)\n this.sourceCh = sourceChannel || null;\n this.sourceCx = sourceContext || null;\n }\n\n /**\n * Submits an individual event metric\n * @param event\n * @param callback\n */\n\n }, {\n key: 'trackEvent',\n value: function trackEvent(event, callback) {\n // Ensure the event contains the required fields\n if (!event.object_type || !event.event_type) {\n okanjo.report('Invalid metric to track (missing object_type or event_type)', { event: event });\n return;\n }\n\n // Queue the event for publishing\n this._push(event, callback);\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Submits a page view metric\n * @param event\n * @param callback\n */\n\n }, {\n key: 'trackPageView',\n value: function trackPageView(event, callback) {\n event = event || {};\n event.object_type = Metrics.Object.page;\n event.event_type = Metrics.Event.view;\n event.id = event.id || okanjo.util.getLocation();\n event.ch = event.ch || this.defaultChannel;\n\n // Queue the event for publishing\n this.trackEvent(event, callback);\n }\n\n /**\n * Adds an event to the queue\n * @param event\n * @param callback\n * @private\n */\n\n }, {\n key: '_push',\n value: function _push(event, callback) {\n this._queue.push({ event: event, callback: callback });\n\n // Save the queue\n this._saveQueue(true);\n\n // Start burning down the queue, unless the event says not to\n if (event._noProcess) {\n delete event._noProcess;\n } else {\n this._processQueue();\n }\n }\n\n /**\n * Burn down the queue\n * @private\n */\n\n }, {\n key: '_processQueue',\n value: function _processQueue() {\n var _this2 = this;\n\n // If the queue is not already being processed, and there's stuff to process, continue sending them\n if (!this._processTimeout && this._queue.length > 0) {\n this._processTimeout = setTimeout(function () {\n\n // Pull the items we're going to batch out of the queue\n var items = _this2._queue.splice(0, 255);\n _this2._saveQueue(false);\n\n // Track the item\n _this2._batchSend(items, function (err, res) {\n // TODO: If there was an error, consider splicing the batch back into the queue\n\n // Update / Set the metric sid on the publisher\n /* istanbul ignore else: server barks */\n if (res && res.data && res.data.sid) _this2._updateSid(res.data.sid);\n\n // When this batch is done being tracked, iterate to the next metric then fire it's callback if set\n _this2._processTimeout = null;\n _this2._processQueue();\n\n // Fire the event callbacks if there are any\n items.forEach(function (item) {\n item.callback && item.callback(err, res);\n });\n });\n }, 0); // break event loop, maybe\n }\n }\n\n /**\n * Sends a bunch of queued metric events\n * @param items\n * @param callback\n * @private\n */\n\n }, {\n key: '_batchSend',\n value: function _batchSend(items, callback) {\n var _this3 = this;\n\n // Normalize event data\n var events = items.map(function (item) {\n _this3._normalizeEvent(item.event);\n\n // Strip duplicated data from event batch\n delete item.event.sid;\n delete item.event.win;\n\n return item.event;\n });\n\n var payload = {\n events: events,\n win: okanjo.util.getLocation()\n };\n\n var route = okanjo.net.getRoute(okanjo.net.routes.metrics_batch);\n\n // Set sid if present\n if (this.sid) {\n payload.sid = this.sid;\n }\n\n // Send it\n okanjo.net.request.post(route, payload, function (err, res) {\n /* istanbul ignore if: out of scope */\n if (err) {\n okanjo.report('Failed to send metrics batch', { err: err, res: res, items: items, route: route });\n }\n callback && callback(err, res);\n });\n }\n\n /**\n * Normaizes events so that they contain consistent data values\n * @param event\n * @private\n */\n\n }, {\n key: '_normalizeEvent',\n value: function _normalizeEvent(event) {\n\n // Ensure meta is ready to receive values\n event.m = event.m || {};\n\n // Set key\n event.key = event.key || event.m.key || okanjo.key || undefined;\n\n // Set session\n if (this.sid) event.sid = this.sid;\n\n // Clone the metadata, since it might be a direct reference to a widget property\n // Deleting properties on the meta object could be very destructive\n event.m = Object.assign({}, event.m); // event.m should be flat\n\n // Strip meta keys that should be excluded\n Object.keys(Metrics.Meta.exclude).forEach(function (key) {\n return delete event.m[key];\n });\n\n // Set referral channel / context\n if (this.sourceCh) {\n event.m.ref_ch = this.sourceCh;\n }\n if (this.sourceCx) {\n event.m.ref_cx = this.sourceCx;\n }\n\n // Set page group id\n event.m.pgid = this.pageId;\n\n // Set okanjo version\n event.m.ok_ver = okanjo.version;\n\n // Finalize metadata\n event.m = okanjo.util.flatten(event.m, { arrayToCsv: true });\n\n // Ensure metadata strings won't exceed the imposed limit\n Object.keys(event.m).forEach(function (key) {\n if (typeof event.m[key] === \"string\") {\n event.m[key] = event.m[key].substr(0, 255);\n }\n });\n\n // Set page source reference\n if (document.referrer) {\n event.ref = document.referrer;\n }\n\n // Set the window location\n event.win = okanjo.util.getLocation();\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n\n }, {\n key: '_updateSid',\n value: function _updateSid(sid) {\n // Not set or changed?\n if (sid && (!this.sid || this.sid !== sid)) {\n this.sid = sid;\n window.localStorage[Metrics.Params.name] = sid;\n okanjo.util.cookie.set(Metrics.Params.name, sid, Metrics.Params.ttl);\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'create',\n\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Helper to create a new fluent event structure\n * @param args\n * @return {*}\n */\n value: function create() {\n for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n args[_key3] = arguments[_key3];\n }\n\n return Metrics.create.apply(null, args);\n }\n }], [{\n key: 'addElementInfo',\n value: function addElementInfo(element, event) {\n var page = okanjo.ui.getPageSize(),\n size = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n event.m.pw = page.w;\n event.m.ph = page.h;\n event.m.x1 = size.x1;\n event.m.y1 = size.y1;\n event.m.x2 = size.x2;\n event.m.y2 = size.y2;\n\n return event;\n }\n }, {\n key: 'addWidgetInfo',\n value: function addWidgetInfo(element, event) {\n var containerSize = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n\n // placement div size\n event.m.wox1 = containerSize.x1;\n event.m.woy1 = containerSize.y1;\n event.m.wox2 = containerSize.x2;\n event.m.woy2 = containerSize.y2;\n\n // Inner size is the min/max of the child elements since they may be floating and have no official height/width\n var resources = okanjo.qwery('.okanjo-resource, .okanjo-adx-container', element);\n var size = void 0,\n wix1 = void 0,\n wiy1 = void 0,\n wix2 = void 0,\n wiy2 = void 0,\n boxes = [];\n var getMin = function getMin(val, current) {\n return typeof current === \"undefined\" || val < current ? val : current;\n };\n var getMax = function getMax(val, current) {\n return typeof current === \"undefined\" || val > current ? val : current;\n };\n var fallback = function fallback(val, _fallback) {\n return typeof val === \"undefined\" ? _fallback : val;\n };\n\n resources.forEach(function (e) {\n size = okanjo.ui.getElementPosition(e);\n wix1 = getMin(size.x1, wix1);\n wiy1 = getMin(size.y1, wiy1);\n wix2 = getMax(size.x2, wix2);\n wiy2 = getMax(size.y2, wiy2);\n boxes.push(size.x1, size.y1, size.x2, size.y2);\n });\n\n // inner size (might be centered or something)\n // noinspection JSUnusedAssignment\n event.m.wix1 = fallback(wix1, containerSize.x1); // noinspection JSUnusedAssignment\n event.m.wiy1 = fallback(wiy1, containerSize.y1); // noinspection JSUnusedAssignment\n event.m.wix2 = fallback(wix2, containerSize.x2); // noinspection JSUnusedAssignment\n event.m.wiy2 = fallback(wiy2, containerSize.y2);\n event.m.wrps = boxes.map(function (v) {\n return Math.floor(v);\n }).join(','); // all resource positions x1,y1,x2,y2,...\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds viewport dimensions / positional data to the event\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'addViewportInfo',\n value: function addViewportInfo(event) {\n var vp = okanjo.ui.getViewportSize(),\n pos = okanjo.ui.getScrollPosition();\n\n event = event || {};\n event.m = event.m || {};\n event.m.vx1 = pos.x;\n event.m.vy1 = pos.y;\n event.m.vx2 = pos.x + vp.vw;\n event.m.vy2 = pos.y + vp.vh;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'addEventInfo',\n value: function addEventInfo(jsEvent, event) {\n var pos = okanjo.ui.getEventPosition(jsEvent);\n\n event = event || {};\n event.m = event.m || {};\n event.m.et = pos.et;\n event.m.ex = pos.ex;\n event.m.ey = pos.ey;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param event\n * @param args\n * @return {*|{}}\n */\n\n }, {\n key: 'addEventMeta',\n value: function addEventMeta(event) {\n event = event || {};\n event.m = event.m || {};\n\n for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {\n args[_key4 - 1] = arguments[_key4];\n }\n\n event.m = Object.assign.apply(Object, [event.m].concat(args));\n\n return event;\n }\n\n /**\n * Helper to create a new fluent event structure\n * @param data\n * @param args\n * @return {MetricEvent}\n */\n\n }, {\n key: 'create',\n value: function create(data) {\n for (var _len5 = arguments.length, args = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {\n args[_key5 - 1] = arguments[_key5];\n }\n\n // return okanjo.util.deepClone(Object.assign.apply(Object, [{}].concat(args)));\n return new MetricEvent(data, args);\n }\n }]);\n\n return Metrics;\n }();\n\n /**\n * The storage/cookie/url param names\n * @type {{queue: string, name: string, channel: string, context: string, ttl: number}}\n */\n\n\n Metrics.Params = {\n queue: '_ok_q',\n name: 'ok_msid',\n channel: 'ok_ch',\n context: 'ok_cx',\n ttl: 1460 // 4 years\n };\n\n /**\n * Event Metadata configuration\n * @type {{exclude: [*]}}\n */\n Metrics.Meta = {\n exclude: ['key', 'callback', 'metrics_channel_context', 'metrics_context', 'mode']\n };\n\n /**\n * Event Types\n * @type {{view: string, impression: string, interaction: string, correlation: string}}\n */\n Metrics.Event = {\n view: 'vw',\n impression: 'imp',\n interaction: 'int',\n correlation: 'cor'\n };\n\n /**\n * Event Action Types\n * @type {{click: string, inline_click: string}}\n */\n Metrics.Action = {\n click: \"click\",\n inline_click: \"inline_click\"\n };\n\n /**\n * Event Object Types\n * @type {{article: string, thirdparty_ad: string, cart: string, page: string, widget: string, product: string, store: string, cause: string, marketplace: string, order: string, order_item: string, user: string, metric_session: string}}\n */\n Metrics.Object = {\n article: 'am',\n thirdparty_ad: 'ta',\n cart: 'ct',\n page: 'pg',\n widget: 'wg',\n product: 'pr',\n store: 'st',\n cause: 'ca',\n marketplace: 'mp',\n order: 'or',\n order_item: 'oi',\n user: 'ur',\n metric_session: 'mt'\n };\n\n /**\n * Event Channels\n * @type {{product_widget: string, ad_widget: string, store_widget: string, marketplace: string, external: string}}\n */\n Metrics.Channel = {\n placement: 'pw',\n marketplace: 'mp',\n external: 'ex',\n\n // Deprecated:\n product_widget: 'pw',\n ad_widget: 'aw',\n store_widget: 'sw'\n };\n\n /**\n * Event Environments\n * @type {{live: string, testing: string}}\n */\n Metrics.Environment = {\n live: \"live\",\n testing: \"testing\"\n };\n\n /**\n * Fluent wrapper around making events simple\n */\n\n var MetricEvent = function () {\n function MetricEvent(data, others) {\n var _this4 = this;\n\n _classCallCheck(this, MetricEvent);\n\n // Merge the data and other data sets into this object\n data = data || {};\n this.data(data);\n /* istanbul ignore else: metrics.create is the only way to create this right now */\n if (Array.isArray(others)) {\n others.forEach(function (data) {\n _this4.data(data);\n });\n }\n }\n\n /**\n * Sets event parameter key-values\n * @param data\n */\n\n\n _createClass(MetricEvent, [{\n key: 'data',\n value: function data(_data) {\n Object.assign(this, okanjo.util.deepClone(_data));\n return this;\n }\n\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @return {MetricEvent}\n */\n\n }, {\n key: 'event',\n value: function event(jsEvent) {\n Metrics.addEventInfo(jsEvent, this);\n return this;\n }\n\n /**\n * Adds viewport dimensions / positional data to the event\n * @return {MetricEvent}\n */\n\n }, {\n key: 'viewport',\n value: function viewport() {\n Metrics.addViewportInfo(this);\n return this;\n }\n\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @return {MetricEvent}\n */\n\n }, {\n key: 'element',\n value: function element(_element) {\n Metrics.addElementInfo(_element, this);\n return this;\n }\n\n /**\n * Adds widget DOM element dimensions / positional data to the event\n * @param element\n * @returns {MetricEvent}\n */\n\n }, {\n key: 'widget',\n value: function widget(element) {\n Metrics.addWidgetInfo(element, this);\n return this;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param args\n * @return {MetricEvent}\n */\n\n }, {\n key: 'meta',\n value: function meta() {\n for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {\n args[_key6] = arguments[_key6];\n }\n\n Metrics.addEventMeta.apply(null, [this].concat(args));\n return this;\n }\n\n /**\n * Sets the object and event type on the event w/o having to use .data\n * @param object_type\n * @param event_type\n * @return {MetricEvent}\n */\n\n }, {\n key: 'type',\n value: function type(object_type, event_type) {\n this.object_type = object_type;\n this.event_type = event_type;\n return this;\n }\n\n /**\n * Finalizes and sends the event\n * @param callback\n */\n\n }, {\n key: 'send',\n value: function send(callback) {\n okanjo.metrics.trackEvent(this, callback);\n // DONT RETURN - BREAK THE CHAIN HERE\n }\n\n /**\n * Gets the single-metric tracking url for this event\n * @return {string}\n */\n\n }, {\n key: 'toUrl',\n value: function toUrl() {\n // Copy data w/o modifying it\n var event = Object.assign({}, this);\n\n // Extract params\n var object_type = event.object_type,\n event_type = event.event_type;\n\n delete event.object_type;\n delete event.event_type;\n\n // Normalize event data\n okanjo.metrics._normalizeEvent(event);\n\n // Get the URL\n return okanjo.net.getRoute(okanjo.net.routes.metrics, { object_type: object_type, event_type: event_type }) + '?' + okanjo.net.request.stringify(event);\n }\n }]);\n\n return MetricEvent;\n }();\n\n // Export / initialize\n\n\n okanjo.metrics = new Metrics();\n})(window, document);\nreturn okanjo;\n}));\n","// Production steps of ECMA-262, Edition 6, 22.1.2.1\nif (!Array.from) {\n Array.from = (function () {\n var toStr = Object.prototype.toString;\n var isCallable = function (fn) {\n return typeof fn === 'function' || toStr.call(fn) === '[object Function]';\n };\n var toInteger = function (value) {\n var number = Number(value);\n if (isNaN(number)) { return 0; }\n if (number === 0 || !isFinite(number)) { return number; }\n return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));\n };\n var maxSafeInteger = Math.pow(2, 53) - 1;\n var toLength = function (value) {\n var len = toInteger(value);\n return Math.min(Math.max(len, 0), maxSafeInteger);\n };\n\n // The length property of the from method is 1.\n return function from(arrayLike/*, mapFn, thisArg */) {\n // 1. Let C be the this value.\n var C = this;\n\n // 2. Let items be ToObject(arrayLike).\n var items = Object(arrayLike);\n\n // 3. ReturnIfAbrupt(items).\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object - not null or undefined');\n }\n\n // 4. If mapfn is undefined, then let mapping be false.\n var mapFn = arguments.length > 1 ? arguments[1] : void undefined;\n var T;\n if (typeof mapFn !== 'undefined') {\n // 5. else\n // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.\n if (!isCallable(mapFn)) {\n throw new TypeError('Array.from: when provided, the second argument must be a function');\n }\n\n // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.\n if (arguments.length > 2) {\n T = arguments[2];\n }\n }\n\n // 10. Let lenValue be Get(items, \"length\").\n // 11. Let len be ToLength(lenValue).\n var len = toLength(items.length);\n\n // 13. If IsConstructor(C) is true, then\n // 13. a. Let A be the result of calling the [[Construct]] internal method\n // of C with an argument list containing the single item len.\n // 14. a. Else, Let A be ArrayCreate(len).\n var A = isCallable(C) ? Object(new C(len)) : new Array(len);\n\n // 16. Let k be 0.\n var k = 0;\n // 17. Repeat, while k < len… (also steps a - h)\n var kValue;\n while (k < len) {\n kValue = items[k];\n if (mapFn) {\n A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);\n } else {\n A[k] = kValue;\n }\n k += 1;\n }\n // 18. Let putStatus be Put(A, \"length\", len, true).\n A.length = len;\n // 20. Return A.\n return A;\n };\n }());\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.find\nif (!Array.prototype.find) {\n Object.defineProperty(Array.prototype, 'find', {\n value: function(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return kValue.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return kValue;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return undefined.\n return undefined;\n }\n });\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex\nif (!Array.prototype.findIndex) {\n Object.defineProperty(Array.prototype, 'findIndex', {\n value: function(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return k.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return k;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return -1.\n return -1;\n }\n });\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.includes\nif (!Array.prototype.includes) {\n Object.defineProperty(Array.prototype, 'includes', {\n value: function(searchElement, fromIndex) {\n\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n // 1. Let O be ? ToObject(this value).\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If len is 0, return false.\n if (len === 0) {\n return false;\n }\n\n // 4. Let n be ? ToInteger(fromIndex).\n // (If fromIndex is undefined, this step produces the value 0.)\n var n = fromIndex | 0;\n\n // 5. If n ≥ 0, then\n // a. Let k be n.\n // 6. Else n < 0,\n // a. Let k be len + n.\n // b. If k < 0, let k be 0.\n var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\n\n function sameValueZero(x, y) {\n return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));\n }\n\n // 7. Repeat, while k < len\n while (k < len) {\n // a. Let elementK be the result of ? Get(O, ! ToString(k)).\n // b. If SameValueZero(searchElement, elementK) is true, return true.\n if (sameValueZero(o[k], searchElement)) {\n return true;\n }\n // c. Increase k by 1.\n k++;\n }\n\n // 8. Return false\n return false;\n }\n });\n}","// https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach\nif (window.NodeList && !NodeList.prototype.forEach) {\n NodeList.prototype.forEach = function (callback, thisArg) {\n thisArg = thisArg || window;\n for (var i = 0; i < this.length; i++) {\n callback.call(thisArg, this[i], i, this);\n }\n };\n}","// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\nif (typeof Object.assign != 'function') {\n // Must be writable: true, enumerable: false, configurable: true\n Object.defineProperty(Object, \"assign\", {\n value: function assign(target, varArgs) { // .length of function is 2\n 'use strict';\n if (target == null) { // TypeError if undefined or null\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n var to = Object(target);\n\n for (var index = 1; index < arguments.length; index++) {\n var nextSource = arguments[index];\n\n if (nextSource != null) { // Skip over if undefined or null\n for (var nextKey in nextSource) {\n // Avoid bugs when hasOwnProperty is shadowed\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n },\n writable: true,\n configurable: true\n });\n}","\"use strict\";\n\n/* exported okanjo */\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/**\n * Okanjo widget framework namespace\n * @global okanjo\n */\nconst okanjo = (function(window, document) {\n\n //region Constants\n\n // Environment Vars\n const SUPPORTS_PAGE_OFFSET = window.pageXOffset !== undefined;\n const CSS1_COMPATIBLE = (document.compatMode /* istanbul ignore next: out of scope */ || \"\") === \"CSS1Compat\";\n const AGENT = window.navigator.userAgent;\n const ELLIPSIFY_PATTERN = /[\\s\\S](?:\\.\\.\\.)?$/;\n const MOBILE_PATTERN = /(iPhone|iPad|iPod|Android|blackberry)/i;\n const NOOP = () => {};\n const Console = window.console;\n\n // Place to pull defaults, if already set\n const settings = window.okanjo || {};\n\n //endregion\n\n //region Okanjo Core\n\n\n //noinspection JSValidateJSDoc,JSClosureCompilerSyntax - idk phpStorm generated it so why would it be wrong? :P\n /**\n * Okanjo namespace\n * @global\n * @type {{version: string, metrics: null, key: null, report: ((...p1?:*[])), warn: ((p1?:*, ...p2?:*[])), qwery: ((p1?:*, p2?:*))}}\n */\n const okanjo = {\n\n /**\n * Okanjo version\n */\n version: \"%%OKANJO_VERSION\",\n\n /**\n * Placeholder\n */\n metrics: null,\n\n /**\n * Global/default placement key\n */\n key: settings.key || null,\n\n /**\n * Reports an error to the console and possibly Raven in the future\n * @param args\n */\n report: (...args) => {\n let err = args.find((arg) => arg instanceof Error);\n if (!err) {\n let messageIndex = args.findIndex((arg) => typeof arg === \"string\");\n err = new Error(args[messageIndex] || \"Okanjo Error\");\n if (messageIndex >= 0) args.splice(messageIndex, 1);\n } else {\n // Grow our own stack so we can figure out what async thing did it\n let stack = (new Error()).stack.split('\\n');\n stack.shift();\n stack.shift();\n args.push({ reportStack: stack.join('\\n') });\n args = args.filter((a) => a !== err);\n }\n\n Console.error(`[Okanjo v${okanjo.version}]: ${err.stack}`);\n args.length && Console.error.apply(Console, ['Additional information:'].concat(args));\n\n // TODO - integrate with Raven\n },\n\n /**\n * Warn developers of their misdeeds\n * @param message\n * @param args\n */\n warn: (message, ...args) => {\n const err = new Error(message);\n\n Console.warn(`[Okanjo v${okanjo.version}]: ${err.stack}`);\n args.length && Console.warn.apply(Console, ['Additional information:'].concat(args));\n },\n\n // Backwards compatibility when we shipped with qwery, cuz querySelector[All] wasn't mainstream enough\n qwery: (selector, parent) => {\n\n // If parent is a selector, select the parent first!\n if (typeof parent === \"string\") {\n parent = document.querySelector(parent);\n\n // If parent is not found, there are obviously no results\n if (!parent) return [];\n }\n\n if (!parent) parent = document;\n\n return parent.querySelectorAll(selector);\n }\n };\n\n //endregion\n\n //region Vendor Libs\n\n /**\n * Placeholder for where vendor libraries get no-conflict loaded\n * @type {{}}\n */\n okanjo.lib = {};\n\n //endregion\n\n //region Networking\n\n /**\n * Networking methods\n * @type {{getRoute: *, exec: *}}\n */\n okanjo.net = {\n\n /**\n * API Endpoints\n */\n endpoint: 'https://api2.okanjo.com',\n sandboxEndpoint: 'https://sandbox-api2.okanjo.com',\n\n /**\n * API routes\n */\n routes: {\n ads: '/content',\n metrics: '/metrics/:object_type/:event_type',\n metrics_batch: '/metrics'\n },\n\n /**\n * Compiles a route and parameters into a final URL\n * @param {string} route - Route constant\n * @param {*} [params] - Key value hash\n * @param {*} [env] - Optional environment to use instead of live\n * @return {string} - Route\n */\n getRoute: (route, params, env) => {\n if (params) {\n Object.keys(params).forEach((key) => {\n route = route.replace(`:${key}`, params[key]+\"\");\n });\n }\n env = env || okanjo.env || 'live';\n return (env === 'sandbox' ? okanjo.net.sandboxEndpoint : okanjo.net.endpoint) + route;\n },\n\n // placeholder, xhr request extension\n request: NOOP\n };\n\n //endregion\n\n // region Utilities\n\n //noinspection JSClosureCompilerSyntax,JSValidateJSDoc\n /**\n * Utility functions and helpers\n * @type {{isEmpty: ((p1?:*)=>boolean), isMobile: (()), getPageArguments: ((p1:boolean))}}\n */\n okanjo.util = {\n\n /**\n * Checks whether a value is _really_ empty (trims)\n * @param val\n * @return {boolean}\n */\n isEmpty: (val) => val === null || val === undefined || (typeof val === \"string\" && val.trim().length === 0),\n\n /**\n * Checks if the current user agent identifies as a mobile device\n * @returns {boolean}\n */\n isMobile: () => {\n // KludgyAF™, but let's go with it\n return MOBILE_PATTERN.test(AGENT);\n },\n\n /**\n * Returns an object hashmap of query and hash parameters\n * @param {boolean} includeHashArguments - Whether to include the hash arguments, if any\n * @return {*}\n */\n getPageArguments: (includeHashArguments) => {\n\n const split = (query) => {\n query = query || \"\";\n const params = {};\n const parts = query.split('&');\n parts.forEach((part) => {\n const eqIndex = part.indexOf('=');\n let key, value;\n if (eqIndex < 0) {\n key = decodeURIComponent(part);\n value = null;\n } else {\n key = decodeURIComponent(part.substring(0, eqIndex));\n value = decodeURIComponent(part.substring(eqIndex + 1));\n }\n if (key) params[key] = value;\n });\n return params;\n };\n\n const queryArgs = split(window.location.search.substring(window.location.search.indexOf('?') + 1));\n const hashArgs = includeHashArguments ? split(window.location.hash.substring(Math.max(window.location.hash.indexOf('#') + 1, window.location.hash.indexOf('#!') + 2))) : {};\n Object.keys(hashArgs).forEach((key) => queryArgs[key] = hashArgs[key]);\n\n return queryArgs;\n }\n\n };\n\n /**\n * Deep clones an object by breaking references, unlike Object.assign\n * @param mixed – Source to clone (object, array, value)\n * @param [out] - Existing output, if any\n * @return {*}\n */\n okanjo.util.deepClone = (mixed, out) => {\n if (Array.isArray(mixed)) {\n // Array reference\n out = out || [];\n out = out.concat(mixed.map((val) => okanjo.util.deepClone(val)));\n } else if (typeof mixed === \"object\" && mixed !== null) {\n // Object reference\n out = out || {};\n Object.keys(mixed).forEach((key) => {\n out[key] = okanjo.util.deepClone(mixed[key]);\n });\n } else {\n // Value\n out = mixed;\n }\n\n return out;\n };\n\n /**\n * Flattens a multi-dimensional object into a single object\n * @param input\n * @param [options]\n * @return {{}}\n */\n okanjo.util.flatten = (input, options = {}) => {\n const output = {};\n\n if (input !== undefined && input !== null) {\n Object\n .keys(input)\n .forEach((key) => {\n // Convert object ids to hex strings\n if (input[key] instanceof Date) {\n if (options.dateToIso) {\n output[key] = input[key].toISOString(); // convert to iso\n } else {\n output[key] = input[key]; // as-is\n }\n } else if (typeof input[key] === 'object' && input[key] !== null) {\n // Allow ignoring arrays if desired\n if (Array.isArray(input[key]) && options.ignoreArrays === true) {\n output[key] = input[key];\n } else if (Array.isArray(input[key]) && options.arrayToCsv === true) {\n output[key] = input[key].join(',');\n } else {\n // Make child objects flat too (always returns object so Object.keys is safe)\n const childObject = okanjo.util.flatten(input[key], options);\n Object\n .keys(childObject)\n .forEach((childKey) => {\n output[key + '_' + childKey] = childObject[childKey];\n })\n ;\n }\n } else {\n // Copy value references\n output[key] = input[key];\n }\n })\n ;\n }\n\n return output;\n };\n\n /*! based on shortid https://github.com/dylang/shortid */\n okanjo.util.shortid = (function(clusterWorkerId) {\n\n const shuffled = 'ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC',\n\n crypto = window.crypto || window.msCrypto || (typeof require === \"function\" && require('crypto')),\n\n randomByte = () => {\n /* istanbul ignore next: platform diffs out of scope */\n if (crypto && crypto.randomBytes) {\n return crypto.randomBytes(1)[0] & 0x30;\n } else if (!crypto || !crypto.getRandomValues) {\n return Math.floor(Math.random() * 256) & 0x30;\n }\n /* istanbul ignore next: platform diffs out of scope */\n const dest = new Uint8Array(1);\n /* istanbul ignore next: platform diffs out of scope */\n crypto.getRandomValues(dest);\n /* istanbul ignore next: platform diffs out of scope */\n return dest[0] & 0x30;\n },\n\n encode = (number) => {\n let loopCounter = 0,\n done,\n str = '';\n\n while (!done) {\n str = str + shuffled[ ( (number >> (4 * loopCounter)) & 0x0f ) | randomByte() ];\n done = number < (Math.pow(16, loopCounter + 1 ) );\n loopCounter++;\n }\n return str;\n },\n\n // Ignore all milliseconds before a certain time to reduce the size of the date entropy without sacrificing uniqueness.\n // This number should be updated every year or so to keep the generated id short.\n // To regenerate `new Date() - 0` and bump the version. Always bump the version!\n\n REDUCE_TIME = 1490384907498,\n version = 7;\n\n let counter,\n previousSeconds;\n\n clusterWorkerId = clusterWorkerId || 0;\n\n return function() {\n let str = '',\n seconds = Math.floor(((new Date()).getTime() - REDUCE_TIME) * 0.001);\n\n if (seconds === previousSeconds) {\n counter++;\n } else {\n counter = 0;\n previousSeconds = seconds;\n }\n\n str = str + encode(version) + encode(clusterWorkerId);\n if (counter > 0) {\n str = str + encode(counter);\n }\n str = str + encode(seconds);\n\n return str;\n };\n })();\n\n /**\n * Gets the best URL for where we are operating\n * @returns {string|*}\n */\n okanjo.util.getLocation = () => window.location !== window.parent.location ? /* istanbul ignore next: oos */ document.referrer : document.location.href;\n\n //endregion\n\n //region User Interface\n\n okanjo.ui = {\n\n /**\n * Gets the current page scroll position\n * @returns {{x: Number, y: Number}}\n */\n getScrollPosition: () => {\n return {\n x: SUPPORTS_PAGE_OFFSET ? window.pageXOffset : /* istanbul ignore next: old browsers */ CSS1_COMPATIBLE ? document.documentElement.scrollLeft : document.body.scrollLeft,\n y: SUPPORTS_PAGE_OFFSET ? window.pageYOffset : /* istanbul ignore next: old browsers */ CSS1_COMPATIBLE ? document.documentElement.scrollTop : document.body.scrollTop\n };\n },\n\n /**\n * Gets the height and width of the given element\n * @param {HTMLElement|Node} element – The DOM element to get the size of\n * @param {boolean} [includeMargin] – Whether to include the margins of the element in the size\n * @returns {{height: number, width: number}}\n */\n getElementSize: (element, includeMargin) => {\n const size = {\n height: element.offsetHeight,\n width : element.offsetWidth\n };\n const style = element.currentStyle || window.getComputedStyle(element);\n\n if (includeMargin) {\n size.height += parseInt(style.marginTop) + parseInt(style.marginBottom);\n size.width += parseInt(style.marginLeft) + parseInt(style.marginRight);\n }\n\n return size;\n },\n\n /**\n * Gets the current page size\n * @return {{w: number, h: number}}\n */\n getPageSize: () => {\n const body = document.querySelector('body');\n const html = document.documentElement;\n\n return {\n w: Math.max(\n body.scrollWidth,\n body.offsetWidth,\n html.clientWidth,\n html.scrollWidth,\n html.offsetWidth\n ),\n\n h: Math.max(\n body.scrollHeight,\n body.offsetHeight,\n html.clientHeight,\n html.scrollHeight,\n html.offsetHeight\n )\n };\n },\n\n /**\n * Gets the current viewport size\n * @return {{vw: number, vh: number}}\n */\n getViewportSize: () => {\n const element = CSS1_COMPATIBLE ? document.documentElement /* istanbul ignore next: browser diffs */: document.body;\n const width = element.clientWidth;\n const height = element.clientHeight;\n const inWidth = window.innerWidth /* istanbul ignore next: browser diffs */ || 0;\n const inHeight = window.innerHeight /* istanbul ignore next: browser diffs */ || 0;\n const isMobileZoom = (inWidth && width > inWidth) || (inHeight && height > inHeight);\n\n return {\n vw: isMobileZoom /* istanbul ignore next: browser diffs */ ? inWidth : width,\n vh: isMobileZoom /* istanbul ignore next: browser diffs */ ? inHeight : height\n };\n },\n\n /**\n * Gets the x, y location of the event relative to the page\n * @param event – Mouse/Touch Event\n * @return {{ex: number, ey: number}}\n */\n getEventPosition: (event) => {\n const ex = event.pageX;\n const ey = event.pageY;\n const body = document.body;\n const el = document.documentElement;\n const scrollLeft = 'scrollLeft';\n const scrollTop = 'scrollTop';\n const type = event.__proto__.constructor.name;\n\n return {\n et: type, // mouse? touch? keyboard? robot?\n ex: ex === undefined /* istanbul ignore next: browser diffs */ ? event.clientX + body[scrollLeft] + el[scrollLeft] : ex,\n ey: ey === undefined /* istanbul ignore next: browser diffs */ ? event.clientY + body[scrollTop] + el[scrollTop] : ey\n };\n },\n\n /**\n * Gets the element's rectangle coordinates on the page\n * @param element\n * @return {{x1: number, y1: number, x2: number, y2: number}}\n */\n getElementPosition: (element) => {\n\n // Wrapped in try-catch because IE is super strict about the\n // element being on the DOM before you call this. Other browsers\n // let it slide, but oh well.\n\n const err = 'Could not get position of element. Did you attach the element to the DOM before initializing?';\n try {\n let rect = element.getBoundingClientRect();\n let body = document.body.getBoundingClientRect();\n // let pos = okanjo.ui.getScrollPosition();\n\n /* istanbul ignore else: jsdom doesn't mock this */\n if (!document.body.contains(element)) {\n okanjo.report(err, element);\n }\n return {\n // x1: rect.left + pos.x,\n // y1: rect.top + pos.y,\n // x2: rect.right + pos.x,\n // y2: rect.bottom + pos.y\n\n // This might fix\n x1: rect.left - body.left,\n y1: rect.top - body.top,\n x2: rect.right - body.left,\n y2: rect.bottom - body.top,\n\n };\n } catch (e) {\n okanjo.report(err, { exception: e, element });\n return {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: 0,\n err: 1\n };\n }\n },\n\n /**\n * Gets the intersection information given the element, viewport and scroll positions\n * @param e – Element position\n * @param s - Scroll position\n * @param v - Viewport size\n * @return {{intersectionArea: number, elementArea: number}}\n * @private\n */\n _getIntersection: (e, s, v) => {\n let iLeft = Math.max(e.x1, s.x),\n iRight = Math.min(e.x2, s.x+v.vw),\n iTop = Math.max(e.y1, s.y),\n iBottom = Math.min(e.y2, s.y+v.vh),\n\n intersectionArea = Math.max(0, iRight - iLeft) * Math.max(0, iBottom - iTop),\n elementArea = (e.x2 - e.x1) * (e.y2 - e.y1);\n\n return {\n intersectionArea,\n elementArea\n };\n },\n\n /**\n * Checks whether the element is actually displayed on the DOM\n * @param element\n * @return {boolean}\n */\n isElementVisible: (element) => {\n /* istanbul ignore next: jsdom won't trigger this */\n return element.offsetWidth > 0 && element.offsetHeight > 0;\n },\n\n /**\n * Gets the percentage of the element pixels currently within the viewport\n * @param {HTMLElement|Node} element\n * @return {number}\n */\n getPercentageInViewport: (element) => {\n let e = okanjo.ui.getElementPosition(element),\n s = okanjo.ui.getScrollPosition(),\n v = okanjo.ui.getViewportSize();\n\n // If there was a problem getting the element position, fail fast\n if (e.err) return 0;\n\n // Get intersection rectangle\n let { intersectionArea, elementArea } = okanjo.ui._getIntersection(e,s,v);\n\n // Don't let it return NaN\n /* istanbul ignore else: jsdom no love positional data */\n if (elementArea <= 0) return 0;\n\n /* istanbul ignore next: jsdom no love positional data, area tested with helper fn tho */\n return intersectionArea / elementArea;\n }\n };\n\n /**\n * Splits the text in the element to fit within the visible height of its container, and separates with an ellipses\n * @param {HTMLElement|Node} element – The DOM element containing the text to fit\n * @param {HTMLElement} [container] – Optional container to compute fit on. Defaults to the element's parent\n */\n okanjo.ui.ellipsify = function(element, container) {\n\n // It's a sad day when you have to resort to JS because CSS kludges are too hacky to work down to IE8, programmatically\n\n //noinspection JSValidateTypes\n const parent = container || element.parentNode,\n targetHeight = okanjo.ui.getElementSize(parent).height,\n useTextContent = element.textContent !== undefined;\n\n let text = useTextContent ? element.textContent /* istanbul ignore next: browser diffs */ : element.innerText,\n replacedText = \"\",\n safety = 5000, // Safety switch to bust out of the loop in the event something goes terribly wrong\n replacer = (match) => {\n /* istanbul ignore next: n/a to jsdom */\n replacedText = match.substr(0, match.length-3) + replacedText;\n /* istanbul ignore next: n/a to jsdom */\n return '...';\n };\n\n // Trim off characters until we can fit the text and ellipses\n // If the text already fits, this loop is ignored\n /* istanbul ignore next: jsdom doesn't do element size computing stuff */\n while (okanjo.ui.getElementSize(element).height > targetHeight && text.length > 0 && (safety-- > 0)) {\n text = useTextContent ? element.textContent : element.innerText;\n\n text = text.replace(ELLIPSIFY_PATTERN, replacer);\n\n if (useTextContent) {\n element.textContent = text;\n } else {\n element.innerText = text;\n }\n }\n\n // If there is work to do, split the content into two span tags\n // Like so: [content]...[hidden content]\n /* istanbul ignore if: n/a to jsdom */\n if (replacedText.length > 0) {\n\n let content = document.createElement('span'),\n span = document.createElement('span');\n\n content.setAttribute('class','okanjo-ellipses');\n span.setAttribute('class','okanjo-visually-hidden');\n\n if (useTextContent) {\n content.textContent = text.substr(0, text.length-3);\n span.textContent = replacedText;\n } else {\n content.innerText = text.substr(0, text.length-3);\n span.innerText = replacedText;\n }\n\n element.innerHTML = '';\n element.appendChild(content);\n element.appendChild(span);\n }\n\n };\n\n /**\n * Locates images with the class okanjo-fit and ensures that they get filled.\n * This is basically a object-fit hacky workaround\n * @param element\n */\n okanjo.ui.fitImages = function(element) {\n // Detect objectFit support\n /* istanbul ignore else: n/a to jsdom */\n if ('objectFit' in document.documentElement.style === false) {\n // Find images to fit\n element.querySelectorAll('img.okanjo-fit').forEach((img) => {\n\n // Hide the image\n img.style.display = 'none';\n\n // Update the parent w/ the background\n let parent = img.parentNode;\n parent.style.backgroundSize = 'cover';\n parent.style.backgroundImage = 'url('+img.src+')';\n parent.style.backgroundposition = 'center center';\n });\n }\n };\n\n //endregion\n\n // Export the root namespace\n return window.okanjo = okanjo;\n\n})(window, document);","\"use strict\";\n\n(function(window) {\n\n const JSON_TEST = /^application\\/json/;\n const okanjo = window.okanjo;\n\n /**\n * Performs a reliable XHR request\n * @param {string} method - Request method\n * @param {string} url - URL\n * @param [payload] optional payload\n * @param callback Fired on when completed (err, res), normalized to standard response format\n */\n okanjo.net.request = function (method, url, payload, callback) {\n\n // payload is not required\n if (typeof payload === \"function\") {\n callback = payload;\n payload = undefined;\n }\n\n // Create a new instance\n const req = new (window.XMLHttpRequest /* istanbul ignore next: old ie */ || window.ActiveXObject)('MSXML2.XMLHTTP.3.0');\n\n // Flag to prevent duplicate callbacks / races\n let calledBack = false;\n\n // Normalized done handler\n const done = function(err, res) {\n /* istanbul ignore else: out of scope */\n if (!calledBack) {\n calledBack = true;\n callback(err, res);\n }\n };\n\n // Apply timeout if configured globally\n if (okanjo.net.request.timeout) {\n req.timeout = okanjo.net.request.timeout;\n }\n\n // Catch timeout errors\n req.ontimeout = function(e) {\n /* istanbul ignore next: idk if jsdom can mock this, also readystatechange may fire before this anyway */\n done({\n statusCode: 504,\n error: \"Request timed out\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n };\n\n // Handle the response\n req.onreadystatechange = function(e) {\n // 4 = completed / failed\n if (req.readyState === 4) {\n // Do we have a response?\n if (req.status > 0) {\n let res;\n\n // Check if we got JSON and parse it right away\n if (JSON_TEST.test(req.getResponseHeader('Content-Type'))) {\n res = JSON.parse(req.responseText);\n } else {\n // Not JSON, normalize it instead\n res = {\n statusCode: req.status,\n data: req.responseText\n };\n }\n\n // Put the response in the proper slot (err for non success responses)\n if (req.status >= 200 && req.status < 300) {\n done(null, res);\n } else {\n done(res);\n }\n } else {\n // Request failed - e.g. CORS or network issues\n done({\n statusCode: 503,\n error: \"Request failed\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n }\n }\n };\n\n // Open the request\n req.open(method.toUpperCase(), url);\n\n // Include credentials\n req.withCredentials = true;\n\n // Handle post payloads\n if (['POST','PUT','PATCH'].includes(method.toUpperCase())) {\n req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n if (payload !== undefined) {\n payload = JSON.stringify(payload);\n }\n }\n\n // Ship it\n req.send(payload || undefined);\n };\n\n // Bind helpers to make things easy as pie\n okanjo.net.request.get = okanjo.net.request.bind(this, 'GET');\n okanjo.net.request.post = okanjo.net.request.bind(this, 'POST');\n okanjo.net.request.put = okanjo.net.request.bind(this, 'PUT');\n okanjo.net.request.delete = okanjo.net.request.bind(this, 'DELETE');\n\n /**\n * Helper to aid in minificiation+querystringify and redundant encodeURIComponent stuff\n * @param val\n * @return {*}\n */\n const encode = (val) => {\n if (val === null || val === undefined) return '';\n return encodeURIComponent(''+val);\n };\n\n /**\n * Helper to aid in getting a query string key using a prefix and keyname\n * @param key\n * @param keyPrefix\n * @return {*}\n */\n const getKey = (key, keyPrefix) => {\n if (keyPrefix) {\n return `${keyPrefix}[${encode(key)}]`;\n } else {\n return encode(key)\n }\n };\n\n /**\n * Super basic querystringify helper. It handles deep objects, but not for array values\n * @param obj\n * @param [keyPrefix]\n * @return {string}\n */\n okanjo.net.request.stringify = (obj, keyPrefix) => {\n let pairs = [];\n keyPrefix = keyPrefix || \"\";\n Object.keys(obj).forEach((key) => {\n let value = obj[key];\n if (Array.isArray(value)) {\n value.forEach((v) => pairs.push(getKey(key, keyPrefix) + '=' + encode(v))); // Does not do that PHP garbage with key[]=val\n } else if (typeof value === \"object\" && value !== null) {\n // Recurse\n let res = okanjo.net.request.stringify(value, getKey(key, keyPrefix));\n if (res) pairs.push(res);\n } else if (value !== undefined) {\n pairs.push(getKey(key, keyPrefix) + '=' + encode(value));\n }\n });\n return pairs.join('&');\n };\n\n})(window);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function(window, document) {\n\n /**\n * Okanjo cookie utility helpers\n */\n window.okanjo.util.cookie = {\n\n /**\n * Sets a cookie\n * @param cookieName\n * @param value\n * @param expireDays\n */\n set: (cookieName, value, expireDays) => {\n const expireDate = new Date();\n expireDate.setDate(expireDate.getDate() + expireDays);\n const expires = expireDays ? \" Expires=\" + expireDate.toUTCString() + \";\" : \"\";\n const path = \" Path=/\";\n const secure = window.location.protocol === 'https:' ? ' Secure;' : '';\n // const secure = ' Secure;';\n const cookieValue = `${encodeURI(value)};${expires}${secure} SameSite=None;${path}`;\n // console.log('setting cookie', cookieName, cookieValue)\n document.cookie = cookieName + \"=\" + cookieValue;\n },\n\n /**\n * Gets a cookie\n * @param cookieName\n * @return {*}\n */\n get: (cookieName) => {\n let output = null;\n document.cookie\n .split(\";\")\n .find((cookie) => {\n let nameTest = cookie.substr(0, cookie.indexOf(\"=\")).trim();\n let value = cookie.substr(cookie.indexOf(\"=\") + 1);\n if (nameTest === cookieName) {\n output = decodeURI(value);\n return true;\n } else {\n return false;\n }\n })\n ;\n return output;\n }\n };\n\n})(window, document);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window, document) {\n\n const okanjo = window.okanjo;\n\n /**\n * Event tracking class\n * @type {Metrics}\n */\n class Metrics {\n\n //noinspection JSUnusedGlobalSymbols\n constructor() {\n\n /**\n * Events queued here before submission\n * @type {Array}\n * @private\n */\n this._queue = this._getStoredQueue();\n this._processTimeout = null; // queue event loop timeout pointer\n\n /**\n * Unique page grouping event identifier\n */\n this.pageId = okanjo.util.shortid();\n this.defaultChannel = Metrics.Channel.external;\n\n this.sid = null;\n this.sourceCh = null;\n this.sourceCx = null;\n\n // Extract referral data, if set\n this._checkUrlForReferral();\n\n // TODO - look into iframe session correlation system\n }\n\n //noinspection JSMethodCanBeStatic\n /**\n * Gets the storage backed metric queue, in case we did not send everything last time\n * @return {Array}\n * @private\n */\n _getStoredQueue() {\n if (window.localStorage[Metrics.Params.queue]) {\n try {\n let queue = JSON.parse(window.localStorage[Metrics.Params.queue]);\n if (Array.isArray(queue)) {\n return queue;\n } else {\n okanjo.report('Stored queue is not a queue', {queue});\n return [];\n }\n } catch (e) {\n okanjo.report('Failed to load metric queue from storage', {err: e});\n return [];\n }\n } else {\n // not stored\n return [];\n }\n }\n\n /**\n * Updates the queue stored in storage, in the event we can't complete our submissions\n * @param delay - Whether to delay updating the queue for a bit, to let other metrics pile in\n * @private\n */\n _saveQueue(delay) {\n if (delay) {\n if (this._saveQueueTimeout) clearTimeout(this._saveQueueTimeout);\n this._saveQueueTimeout = setTimeout(() => {\n this._saveQueue(false);\n this._saveQueueTimeout = null;\n }, 100);\n } else {\n window.localStorage[Metrics.Params.queue] = JSON.stringify(this._queue);\n }\n }\n\n /**\n * Extract contextual pass-through data from the URL, if present\n * @private\n */\n _checkUrlForReferral() {\n const pageArgs = okanjo.util.getPageArguments(true),\n urlSid = pageArgs[Metrics.Params.name],\n localSid = window.localStorage[Metrics.Params.name] || okanjo.util.cookie.get(Metrics.Params.name), // pull from storage or cookie\n sourceContext = pageArgs[Metrics.Params.context],\n sourceChannel = pageArgs[Metrics.Params.channel];\n\n // If for some reason, both are set, record the incident as a possible correlation\n if (urlSid && localSid && urlSid !== localSid) {\n this.trackEvent({\n object_type: Metrics.Object.metric_session,\n event_type: Metrics.Event.correlation,\n id: urlSid+\"_\"+localSid,\n ch: this.defaultChannel,\n _noProcess: true\n });\n }\n\n // Update local values\n this.sid = localSid || urlSid || null; // prefer local over remote (changed in 1.0)\n this.sourceCh = sourceChannel || null;\n this.sourceCx = sourceContext || null;\n }\n\n /**\n * Submits an individual event metric\n * @param event\n * @param callback\n */\n trackEvent(event, callback) {\n // Ensure the event contains the required fields\n if (!event.object_type || !event.event_type) {\n okanjo.report('Invalid metric to track (missing object_type or event_type)', {event});\n return;\n }\n\n // Queue the event for publishing\n this._push(event, callback);\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Submits a page view metric\n * @param event\n * @param callback\n */\n trackPageView(event, callback) {\n event = event || {};\n event.object_type = Metrics.Object.page;\n event.event_type = Metrics.Event.view;\n event.id = event.id || okanjo.util.getLocation();\n event.ch = event.ch || this.defaultChannel;\n\n // Queue the event for publishing\n this.trackEvent(event, callback);\n }\n\n /**\n * Adds an event to the queue\n * @param event\n * @param callback\n * @private\n */\n _push(event, callback) {\n this._queue.push({ event, callback });\n\n // Save the queue\n this._saveQueue(true);\n\n // Start burning down the queue, unless the event says not to\n if (event._noProcess) {\n delete event._noProcess;\n } else {\n this._processQueue();\n }\n }\n\n /**\n * Burn down the queue\n * @private\n */\n _processQueue() {\n // If the queue is not already being processed, and there's stuff to process, continue sending them\n if (!this._processTimeout && this._queue.length > 0) {\n this._processTimeout = setTimeout(() => {\n\n // Pull the items we're going to batch out of the queue\n const items = this._queue.splice(0, 255);\n this._saveQueue(false);\n\n // Track the item\n this._batchSend(items, (err, res) => {\n // TODO: If there was an error, consider splicing the batch back into the queue\n\n // Update / Set the metric sid on the publisher\n /* istanbul ignore else: server barks */\n if (res && res.data && res.data.sid) this._updateSid(res.data.sid);\n\n // When this batch is done being tracked, iterate to the next metric then fire it's callback if set\n this._processTimeout = null;\n this._processQueue();\n\n // Fire the event callbacks if there are any\n items.forEach((item) => {\n item.callback && item.callback(err, res);\n });\n });\n\n }, 0); // break event loop, maybe\n }\n }\n\n /**\n * Sends a bunch of queued metric events\n * @param items\n * @param callback\n * @private\n */\n _batchSend(items, callback) {\n\n // Normalize event data\n const events = items.map((item) => {\n this._normalizeEvent(item.event);\n\n // Strip duplicated data from event batch\n delete item.event.sid;\n delete item.event.win;\n\n return item.event;\n });\n\n const payload = {\n events,\n win: okanjo.util.getLocation()\n };\n\n const route = okanjo.net.getRoute(okanjo.net.routes.metrics_batch);\n\n // Set sid if present\n if (this.sid) {\n payload.sid = this.sid;\n }\n\n // Send it\n okanjo.net.request.post(\n route,\n payload,\n (err, res) => {\n /* istanbul ignore if: out of scope */\n if (err) {\n okanjo.report('Failed to send metrics batch', { err, res, items, route });\n }\n callback && callback(err, res);\n }\n );\n }\n\n /**\n * Normaizes events so that they contain consistent data values\n * @param event\n * @private\n */\n _normalizeEvent(event) {\n\n // Ensure meta is ready to receive values\n event.m = event.m || {};\n\n // Set key\n event.key = event.key || event.m.key || okanjo.key || undefined;\n\n // Set session\n if (this.sid) event.sid = this.sid;\n\n // Clone the metadata, since it might be a direct reference to a widget property\n // Deleting properties on the meta object could be very destructive\n event.m = Object.assign({}, event.m); // event.m should be flat\n\n // Strip meta keys that should be excluded\n Object.keys(Metrics.Meta.exclude).forEach((key) => delete event.m[key]);\n\n // Set referral channel / context\n if (this.sourceCh) { event.m.ref_ch = this.sourceCh; }\n if (this.sourceCx) { event.m.ref_cx = this.sourceCx; }\n\n // Set page group id\n event.m.pgid = this.pageId;\n\n // Set okanjo version\n event.m.ok_ver = okanjo.version;\n\n // Finalize metadata\n event.m = okanjo.util.flatten(event.m, { arrayToCsv: true });\n\n // Ensure metadata strings won't exceed the imposed limit\n Object.keys(event.m).forEach((key) => {\n if (typeof event.m[key] === \"string\") {\n event.m[key] = event.m[key].substr(0, 255);\n }\n });\n\n // Set page source reference\n if (document.referrer) {\n event.ref = document.referrer;\n }\n\n // Set the window location\n event.win = okanjo.util.getLocation();\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n _updateSid(sid) {\n // Not set or changed?\n if (sid && (!this.sid || this.sid !== sid) ) {\n this.sid = sid;\n window.localStorage[Metrics.Params.name] = sid;\n okanjo.util.cookie.set(Metrics.Params.name, sid, Metrics.Params.ttl);\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @param event\n * @return {*|{}}\n */\n static addElementInfo(element, event) {\n const page = okanjo.ui.getPageSize(),\n size = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n event.m.pw = page.w;\n event.m.ph = page.h;\n event.m.x1 = size.x1;\n event.m.y1 = size.y1;\n event.m.x2 = size.x2;\n event.m.y2 = size.y2;\n\n return event;\n }\n\n static addWidgetInfo(element, event) {\n const containerSize = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n\n // placement div size\n event.m.wox1 = containerSize.x1;\n event.m.woy1 = containerSize.y1;\n event.m.wox2 = containerSize.x2;\n event.m.woy2 = containerSize.y2;\n\n // Inner size is the min/max of the child elements since they may be floating and have no official height/width\n const resources = okanjo.qwery('.okanjo-resource, .okanjo-adx-container', element);\n let size, wix1, wiy1, wix2, wiy2, boxes = [];\n const getMin = (val, current) => typeof current === \"undefined\" || val < current ? val : current;\n const getMax = (val, current) => typeof current === \"undefined\" || val > current ? val : current;\n const fallback = (val, fallback) => typeof val === \"undefined\" ? fallback : val;\n\n resources.forEach(e => {\n size = okanjo.ui.getElementPosition(e);\n wix1 = getMin(size.x1, wix1);\n wiy1 = getMin(size.y1, wiy1);\n wix2 = getMax(size.x2, wix2);\n wiy2 = getMax(size.y2, wiy2);\n boxes.push(size.x1, size.y1, size.x2, size.y2);\n });\n\n // inner size (might be centered or something)\n // noinspection JSUnusedAssignment\n event.m.wix1 = fallback(wix1, containerSize.x1); // noinspection JSUnusedAssignment\n event.m.wiy1 = fallback(wiy1, containerSize.y1); // noinspection JSUnusedAssignment\n event.m.wix2 = fallback(wix2, containerSize.x2); // noinspection JSUnusedAssignment\n event.m.wiy2 = fallback(wiy2, containerSize.y2);\n event.m.wrps = boxes.map(v => Math.floor(v)).join(','); // all resource positions x1,y1,x2,y2,...\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds viewport dimensions / positional data to the event\n * @param event\n * @return {*|{}}\n */\n static addViewportInfo(event) {\n const vp = okanjo.ui.getViewportSize(),\n pos = okanjo.ui.getScrollPosition();\n\n event = event || {};\n event.m = event.m || {};\n event.m.vx1 = pos.x;\n event.m.vy1 = pos.y;\n event.m.vx2 = pos.x+vp.vw;\n event.m.vy2 = pos.y+vp.vh;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @param event\n * @return {*|{}}\n */\n static addEventInfo(jsEvent, event) {\n const pos = okanjo.ui.getEventPosition(jsEvent);\n\n event = event || {};\n event.m = event.m || {};\n event.m.et = pos.et;\n event.m.ex = pos.ex;\n event.m.ey = pos.ey;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param event\n * @param args\n * @return {*|{}}\n */\n static addEventMeta(event, ...args) {\n event = event || {};\n event.m = event.m || {};\n event.m = Object.assign.apply(Object, [event.m].concat(args));\n \n return event;\n }\n\n /**\n * Helper to create a new fluent event structure\n * @param data\n * @param args\n * @return {MetricEvent}\n */\n static create(data, ...args) {\n // return okanjo.util.deepClone(Object.assign.apply(Object, [{}].concat(args)));\n return new MetricEvent(data, args);\n }\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Helper to create a new fluent event structure\n * @param args\n * @return {*}\n */\n create(...args) {\n return Metrics.create.apply(null, args);\n }\n\n }\n\n /**\n * The storage/cookie/url param names\n * @type {{queue: string, name: string, channel: string, context: string, ttl: number}}\n */\n Metrics.Params = {\n queue: '_ok_q',\n name: 'ok_msid',\n channel: 'ok_ch',\n context: 'ok_cx',\n ttl: 1460 // 4 years\n };\n\n /**\n * Event Metadata configuration\n * @type {{exclude: [*]}}\n */\n Metrics.Meta = {\n exclude: ['key','callback','metrics_channel_context','metrics_context','mode']\n };\n\n /**\n * Event Types\n * @type {{view: string, impression: string, interaction: string, correlation: string}}\n */\n Metrics.Event = {\n view: 'vw',\n impression: 'imp',\n interaction: 'int',\n correlation: 'cor'\n };\n\n /**\n * Event Action Types\n * @type {{click: string, inline_click: string}}\n */\n Metrics.Action = {\n click: \"click\",\n inline_click: \"inline_click\"\n };\n\n /**\n * Event Object Types\n * @type {{article: string, thirdparty_ad: string, cart: string, page: string, widget: string, product: string, store: string, cause: string, marketplace: string, order: string, order_item: string, user: string, metric_session: string}}\n */\n Metrics.Object = {\n article: 'am',\n thirdparty_ad: 'ta',\n cart: 'ct',\n page: 'pg',\n widget: 'wg',\n product: 'pr',\n store: 'st',\n cause: 'ca',\n marketplace: 'mp',\n order: 'or',\n order_item: 'oi',\n user: 'ur',\n metric_session: 'mt'\n };\n\n /**\n * Event Channels\n * @type {{product_widget: string, ad_widget: string, store_widget: string, marketplace: string, external: string}}\n */\n Metrics.Channel = {\n placement: 'pw',\n marketplace: 'mp',\n external: 'ex',\n\n // Deprecated:\n product_widget: 'pw',\n ad_widget: 'aw',\n store_widget: 'sw'\n };\n\n /**\n * Event Environments\n * @type {{live: string, testing: string}}\n */\n Metrics.Environment = {\n live: \"live\",\n testing: \"testing\"\n };\n\n /**\n * Fluent wrapper around making events simple\n */\n class MetricEvent {\n constructor(data, others) {\n // Merge the data and other data sets into this object\n data = data || {};\n this.data(data);\n /* istanbul ignore else: metrics.create is the only way to create this right now */\n if (Array.isArray(others)) {\n others.forEach((data) => {\n this.data(data);\n });\n }\n }\n\n /**\n * Sets event parameter key-values\n * @param data\n */\n data(data) {\n Object.assign(this, okanjo.util.deepClone(data));\n return this;\n }\n\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @return {MetricEvent}\n */\n event(jsEvent) {\n Metrics.addEventInfo(jsEvent, this);\n return this;\n }\n\n /**\n * Adds viewport dimensions / positional data to the event\n * @return {MetricEvent}\n */\n viewport() {\n Metrics.addViewportInfo(this);\n return this;\n }\n\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @return {MetricEvent}\n */\n element(element) {\n Metrics.addElementInfo(element, this);\n return this;\n }\n\n /**\n * Adds widget DOM element dimensions / positional data to the event\n * @param element\n * @returns {MetricEvent}\n */\n widget(element) {\n Metrics.addWidgetInfo(element, this);\n return this;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param args\n * @return {MetricEvent}\n */\n meta(...args) {\n Metrics.addEventMeta.apply(null, [this].concat(args));\n return this;\n }\n\n /**\n * Sets the object and event type on the event w/o having to use .data\n * @param object_type\n * @param event_type\n * @return {MetricEvent}\n */\n type(object_type, event_type) {\n this.object_type = object_type;\n this.event_type = event_type;\n return this;\n }\n\n /**\n * Finalizes and sends the event\n * @param callback\n */\n send(callback) {\n okanjo.metrics.trackEvent(this, callback);\n // DONT RETURN - BREAK THE CHAIN HERE\n }\n\n /**\n * Gets the single-metric tracking url for this event\n * @return {string}\n */\n toUrl() {\n // Copy data w/o modifying it\n const event = Object.assign({}, this);\n\n // Extract params\n const {\n object_type,\n event_type\n } = event;\n delete event.object_type;\n delete event.event_type;\n\n // Normalize event data\n okanjo.metrics._normalizeEvent(event);\n\n // Get the URL\n return okanjo.net.getRoute(okanjo.net.routes.metrics, { object_type, event_type }) + '?' +\n okanjo.net.request.stringify(event);\n }\n }\n\n // Export / initialize\n okanjo.metrics = new Metrics();\n\n})(window, document);"],"sourceRoot":"./"} \ No newline at end of file +{"version":3,"sources":["okanjo-metrics.js","Array.from.js","Array.prototype.find.js","Array.prototype.findIndex.js","Array.prototype.includes.js","NodeList.prototype.forEach.js","Object.Assign.js","Okanjo.js","Request.js","Cookie.js","Metrics.js"],"names":["root","factory","define","amd","exports","module","Array","this","_classCallCheck","Number","value","instance","Constructor","TypeError","_createClass","isCallable","target","props","i","length","descriptor","enumerable","configurable","writable","Object","defineProperty","key","protoProps","staticProps","defineProperties","prototype","_typeof","Symbol","iterator","obj","constructor","from","number","toStr","toString","fn","Math","call","maxSafeInteger","toLength","len","toInteger","isFinite","floor","abs","pow","items","arrayLike","min","max","C","mapFn","T","arguments","A","kValue","k","find","predicate","o","thisArg","findIndex","includes","searchElement","fromIndex","sameValueZero","x","y","isNaN","n","window","NodeList","forEach","callback","assign","varArgs","nextSource","to","index","nextKey","hasOwnProperty","okanjo","NOOP","document","SUPPORTS_PAGE_OFFSET","undefined","pageXOffset","CSS1_COMPATIBLE","compatMode","AGENT","navigator","userAgent","ELLIPSIFY_PATTERN","MOBILE_PATTERN","Console","console","settings","metrics","report","_len","args","_key","err","Error","messageIndex","arg","stack","split","shift","push","reportStack","join","filter","a","splice","error","version","warn","apply","concat","message","_len2","_key2","selector","parent","qwery","querySelector","querySelectorAll","net","endpoint","sandboxEndpoint","routes","ads","getRoute","route","params","env","request","keys","replace","util","isEmpty","test","val","trim","getPageArguments","query","eqIndex","includeHashArguments","decodeURIComponent","parts","part","indexOf","queryArgs","hashArgs","substring","location","search","hash","mixed","out","map","deepClone","options","output","input","isArray","toISOString","childObject","childKey","ignoreArrays","arrayToCsv","flatten","shortid","clusterWorkerId","shuffled","crypto","msCrypto","require","getRandomValues","randomBytes","encode","loopCounter","random","dest","Uint8Array","str","done","randomByte","REDUCE_TIME","seconds","counter","previousSeconds","Date","getTime","getLocation","referrer","href","ui","getScrollPosition","documentElement","scrollLeft","body","getElementSize","element","scrollTop","includeMargin","size","height","offsetHeight","width","offsetWidth","style","currentStyle","getComputedStyle","parseInt","marginTop","marginBottom","getPageSize","marginLeft","marginRight","html","getViewportSize","scrollWidth","clientWidth","clientHeight","scrollHeight","vh","isMobileZoom","inWidth","innerWidth","inHeight","innerHeight","getEventPosition","ex","et","event","ey","el","type","__proto__","name","getElementPosition","clientX","clientY","rect","getBoundingClientRect","y2","x1","left","contains","y1","x2","top","right","bottom","e","exception","elementArea","iLeft","s","iRight","v","vw","iTop","iBottom","intersectionArea","isElementVisible","getPercentageInViewport","_okanjo$ui$_getInters","_getIntersection","replacedText","container","substr","parentNode","targetHeight","useTextContent","textContent","text","innerText","safety","replacer","match","span","createElement","content","setAttribute","innerHTML","fitImages","appendChild","backgroundImage","src","img","display","backgroundposition","method","url","payload","res","ActiveXObject","calledBack","req","timeout","ontimeout","attributes","statusCode","onreadystatechange","status","data","JSON_TEST","getResponseHeader","parse","responseText","xhr","toUpperCase","open","withCredentials","setRequestHeader","post","send","get","bind","encodeURIComponent","getKey","keyPrefix","stringify","pairs","expireDate","setDate","set","cookieName","expireDays","getDate","expires","toUTCString","path","secure","protocol","cookieValue","cookie","nameTest","decodeURI","Metrics","sourceCh","_getStoredQueue","sourceCx","pageId","defaultChannel","Channel","external","sid","_checkUrlForReferral","queue","Params","JSON","localStorage","delay","_this","_saveQueueTimeout","clearTimeout","setTimeout","_saveQueue","_queue","object_type","metric_session","event_type","Event","correlation","id","urlSid","_noProcess","context","sourceChannel","pageArgs","channel","localSid","trackEvent","sourceContext","ch","_push","page","view","_processQueue","_this2","_processTimeout","_batchSend","_updateSid","item","_this3","events","win","metrics_batch","m","exclude","Meta","ok_ver","pgid","ref","ttl","_len3","_key3","pw","w","ph","h","containerSize","resources","wix2","wiy2","boxes","getMin","getMax","wix1","fallback","current","wiy1","_fallback","wrps","vp","pos","vx1","vy1","vx2","vy2","jsEvent","_len4","_key4","_len5","_key5","MetricEvent","impression","interaction","Action","click","inline_click","article","thirdparty_ad","cart","order","order_item","user","widget","product","store","cause","marketplace","placement","live","testing","store_widget","Environment","others","_this4","_data","addEventInfo","addViewportInfo","_element","addElementInfo","addWidgetInfo","_len6","_key6","addEventMeta","_normalizeEvent"],"mappings":"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","file":"okanjo-metrics.min.js","sourcesContent":["/*! okanjo-metrics.js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */\n(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.okanjo = factory();\n }\n}(this, function() {\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n// Production steps of ECMA-262, Edition 6, 22.1.2.1\nif (!Array.from) {\n Array.from = function () {\n var toStr = Object.prototype.toString;\n var isCallable = function isCallable(fn) {\n return typeof fn === 'function' || toStr.call(fn) === '[object Function]';\n };\n var toInteger = function toInteger(value) {\n var number = Number(value);\n if (isNaN(number)) {\n return 0;\n }\n if (number === 0 || !isFinite(number)) {\n return number;\n }\n return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));\n };\n var maxSafeInteger = Math.pow(2, 53) - 1;\n var toLength = function toLength(value) {\n var len = toInteger(value);\n return Math.min(Math.max(len, 0), maxSafeInteger);\n };\n\n // The length property of the from method is 1.\n return function from(arrayLike /*, mapFn, thisArg */) {\n // 1. Let C be the this value.\n var C = this;\n\n // 2. Let items be ToObject(arrayLike).\n var items = Object(arrayLike);\n\n // 3. ReturnIfAbrupt(items).\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object - not null or undefined');\n }\n\n // 4. If mapfn is undefined, then let mapping be false.\n var mapFn = arguments.length > 1 ? arguments[1] : void undefined;\n var T;\n if (typeof mapFn !== 'undefined') {\n // 5. else\n // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.\n if (!isCallable(mapFn)) {\n throw new TypeError('Array.from: when provided, the second argument must be a function');\n }\n\n // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.\n if (arguments.length > 2) {\n T = arguments[2];\n }\n }\n\n // 10. Let lenValue be Get(items, \"length\").\n // 11. Let len be ToLength(lenValue).\n var len = toLength(items.length);\n\n // 13. If IsConstructor(C) is true, then\n // 13. a. Let A be the result of calling the [[Construct]] internal method\n // of C with an argument list containing the single item len.\n // 14. a. Else, Let A be ArrayCreate(len).\n var A = isCallable(C) ? Object(new C(len)) : new Array(len);\n\n // 16. Let k be 0.\n var k = 0;\n // 17. Repeat, while k < len… (also steps a - h)\n var kValue;\n while (k < len) {\n kValue = items[k];\n if (mapFn) {\n A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);\n } else {\n A[k] = kValue;\n }\n k += 1;\n }\n // 18. Let putStatus be Put(A, \"length\", len, true).\n A.length = len;\n // 20. Return A.\n return A;\n };\n }();\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.find\nif (!Array.prototype.find) {\n Object.defineProperty(Array.prototype, 'find', {\n value: function value(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return kValue.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return kValue;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return undefined.\n return undefined;\n }\n });\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex\nif (!Array.prototype.findIndex) {\n Object.defineProperty(Array.prototype, 'findIndex', {\n value: function value(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return k.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return k;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return -1.\n return -1;\n }\n });\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.includes\nif (!Array.prototype.includes) {\n Object.defineProperty(Array.prototype, 'includes', {\n value: function value(searchElement, fromIndex) {\n\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n // 1. Let O be ? ToObject(this value).\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If len is 0, return false.\n if (len === 0) {\n return false;\n }\n\n // 4. Let n be ? ToInteger(fromIndex).\n // (If fromIndex is undefined, this step produces the value 0.)\n var n = fromIndex | 0;\n\n // 5. If n ≥ 0, then\n // a. Let k be n.\n // 6. Else n < 0,\n // a. Let k be len + n.\n // b. If k < 0, let k be 0.\n var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\n\n function sameValueZero(x, y) {\n return x === y || typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y);\n }\n\n // 7. Repeat, while k < len\n while (k < len) {\n // a. Let elementK be the result of ? Get(O, ! ToString(k)).\n // b. If SameValueZero(searchElement, elementK) is true, return true.\n if (sameValueZero(o[k], searchElement)) {\n return true;\n }\n // c. Increase k by 1.\n k++;\n }\n\n // 8. Return false\n return false;\n }\n });\n}\n// https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach\nif (window.NodeList && !NodeList.prototype.forEach) {\n NodeList.prototype.forEach = function (callback, thisArg) {\n thisArg = thisArg || window;\n for (var i = 0; i < this.length; i++) {\n callback.call(thisArg, this[i], i, this);\n }\n };\n}\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\nif (typeof Object.assign != 'function') {\n // Must be writable: true, enumerable: false, configurable: true\n Object.defineProperty(Object, \"assign\", {\n value: function assign(target, varArgs) {\n // .length of function is 2\n 'use strict';\n\n if (target == null) {\n // TypeError if undefined or null\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n var to = Object(target);\n\n for (var index = 1; index < arguments.length; index++) {\n var nextSource = arguments[index];\n\n if (nextSource != null) {\n // Skip over if undefined or null\n for (var nextKey in nextSource) {\n // Avoid bugs when hasOwnProperty is shadowed\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n },\n writable: true,\n configurable: true\n });\n}\n\"use strict\";\n\n/* exported okanjo */\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/**\n * Okanjo widget framework namespace\n * @global okanjo\n */\nvar okanjo = function (window, document) {\n\n //region Constants\n\n // Environment Vars\n var SUPPORTS_PAGE_OFFSET = window.pageXOffset !== undefined;\n var CSS1_COMPATIBLE = (document.compatMode /* istanbul ignore next: out of scope */ || \"\") === \"CSS1Compat\";\n var AGENT = window.navigator.userAgent;\n var ELLIPSIFY_PATTERN = /[\\s\\S](?:\\.\\.\\.)?$/;\n var MOBILE_PATTERN = /(iPhone|iPad|iPod|Android|blackberry)/i;\n var NOOP = function NOOP() {};\n var Console = window.console;\n\n // Place to pull defaults, if already set\n var settings = window.okanjo || {};\n\n //endregion\n\n //region Okanjo Core\n\n\n //noinspection JSValidateJSDoc,JSClosureCompilerSyntax - idk phpStorm generated it so why would it be wrong? :P\n /**\n * Okanjo namespace\n * @global\n * @type {{version: string, metrics: null, key: null, report: ((...p1?:*[])), warn: ((p1?:*, ...p2?:*[])), qwery: ((p1?:*, p2?:*))}}\n */\n var okanjo = {\n\n /**\n * Okanjo version\n */\n version: \"1.20.0\",\n\n /**\n * Placeholder\n */\n metrics: null,\n\n /**\n * Global/default placement key\n */\n key: settings.key || null,\n\n /**\n * Reports an error to the console and possibly Raven in the future\n * @param args\n */\n report: function report() {\n for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n var err = args.find(function (arg) {\n return arg instanceof Error;\n });\n if (!err) {\n var messageIndex = args.findIndex(function (arg) {\n return typeof arg === \"string\";\n });\n err = new Error(args[messageIndex] || \"Okanjo Error\");\n if (messageIndex >= 0) args.splice(messageIndex, 1);\n } else {\n // Grow our own stack so we can figure out what async thing did it\n var stack = new Error().stack.split('\\n');\n stack.shift();\n stack.shift();\n args.push({ reportStack: stack.join('\\n') });\n args = args.filter(function (a) {\n return a !== err;\n });\n }\n\n Console.error('[Okanjo v' + okanjo.version + ']: ' + err.stack);\n args.length && Console.error.apply(Console, ['Additional information:'].concat(args));\n\n // TODO - integrate with Raven\n },\n\n /**\n * Warn developers of their misdeeds\n * @param message\n * @param args\n */\n warn: function warn(message) {\n for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n\n var err = new Error(message);\n\n Console.warn('[Okanjo v' + okanjo.version + ']: ' + err.stack);\n args.length && Console.warn.apply(Console, ['Additional information:'].concat(args));\n },\n\n // Backwards compatibility when we shipped with qwery, cuz querySelector[All] wasn't mainstream enough\n qwery: function qwery(selector, parent) {\n\n // If parent is a selector, select the parent first!\n if (typeof parent === \"string\") {\n parent = document.querySelector(parent);\n\n // If parent is not found, there are obviously no results\n if (!parent) return [];\n }\n\n if (!parent) parent = document;\n\n return parent.querySelectorAll(selector);\n }\n };\n\n //endregion\n\n //region Vendor Libs\n\n /**\n * Placeholder for where vendor libraries get no-conflict loaded\n * @type {{}}\n */\n okanjo.lib = {};\n\n //endregion\n\n //region Networking\n\n /**\n * Networking methods\n * @type {{getRoute: *, exec: *}}\n */\n okanjo.net = {\n\n /**\n * API Endpoints\n */\n endpoint: 'https://api2.okanjo.com',\n sandboxEndpoint: 'https://sandbox-api2.okanjo.com',\n\n /**\n * API routes\n */\n routes: {\n ads: '/content',\n metrics: '/metrics/:object_type/:event_type',\n metrics_batch: '/metrics'\n },\n\n /**\n * Compiles a route and parameters into a final URL\n * @param {string} route - Route constant\n * @param {*} [params] - Key value hash\n * @param {*} [env] - Optional environment to use instead of live\n * @return {string} - Route\n */\n getRoute: function getRoute(route, params, env) {\n if (params) {\n Object.keys(params).forEach(function (key) {\n route = route.replace(':' + key, params[key] + \"\");\n });\n }\n env = env || okanjo.env || 'live';\n return (env === 'sandbox' ? okanjo.net.sandboxEndpoint : okanjo.net.endpoint) + route;\n },\n\n // placeholder, xhr request extension\n request: NOOP\n };\n\n //endregion\n\n // region Utilities\n\n //noinspection JSClosureCompilerSyntax,JSValidateJSDoc\n /**\n * Utility functions and helpers\n * @type {{isEmpty: ((p1?:*)=>boolean), isMobile: (()), getPageArguments: ((p1:boolean))}}\n */\n okanjo.util = {\n\n /**\n * Checks whether a value is _really_ empty (trims)\n * @param val\n * @return {boolean}\n */\n isEmpty: function isEmpty(val) {\n return val === null || val === undefined || typeof val === \"string\" && val.trim().length === 0;\n },\n\n /**\n * Checks if the current user agent identifies as a mobile device\n * @returns {boolean}\n */\n isMobile: function isMobile() {\n // KludgyAF™, but let's go with it\n return MOBILE_PATTERN.test(AGENT);\n },\n\n /**\n * Returns an object hashmap of query and hash parameters\n * @param {boolean} includeHashArguments - Whether to include the hash arguments, if any\n * @return {*}\n */\n getPageArguments: function getPageArguments(includeHashArguments) {\n\n var split = function split(query) {\n query = query || \"\";\n var params = {};\n var parts = query.split('&');\n parts.forEach(function (part) {\n var eqIndex = part.indexOf('=');\n var key = void 0,\n value = void 0;\n if (eqIndex < 0) {\n key = decodeURIComponent(part);\n value = null;\n } else {\n key = decodeURIComponent(part.substring(0, eqIndex));\n value = decodeURIComponent(part.substring(eqIndex + 1));\n }\n if (key) params[key] = value;\n });\n return params;\n };\n\n var queryArgs = split(window.location.search.substring(window.location.search.indexOf('?') + 1));\n var hashArgs = includeHashArguments ? split(window.location.hash.substring(Math.max(window.location.hash.indexOf('#') + 1, window.location.hash.indexOf('#!') + 2))) : {};\n Object.keys(hashArgs).forEach(function (key) {\n return queryArgs[key] = hashArgs[key];\n });\n\n return queryArgs;\n }\n\n };\n\n /**\n * Deep clones an object by breaking references, unlike Object.assign\n * @param mixed – Source to clone (object, array, value)\n * @param [out] - Existing output, if any\n * @return {*}\n */\n okanjo.util.deepClone = function (mixed, out) {\n if (Array.isArray(mixed)) {\n // Array reference\n out = out || [];\n out = out.concat(mixed.map(function (val) {\n return okanjo.util.deepClone(val);\n }));\n } else if ((typeof mixed === 'undefined' ? 'undefined' : _typeof(mixed)) === \"object\" && mixed !== null) {\n // Object reference\n out = out || {};\n Object.keys(mixed).forEach(function (key) {\n out[key] = okanjo.util.deepClone(mixed[key]);\n });\n } else {\n // Value\n out = mixed;\n }\n\n return out;\n };\n\n /**\n * Flattens a multi-dimensional object into a single object\n * @param input\n * @param [options]\n * @return {{}}\n */\n okanjo.util.flatten = function (input) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n var output = {};\n\n if (input !== undefined && input !== null) {\n Object.keys(input).forEach(function (key) {\n // Convert object ids to hex strings\n if (input[key] instanceof Date) {\n if (options.dateToIso) {\n output[key] = input[key].toISOString(); // convert to iso\n } else {\n output[key] = input[key]; // as-is\n }\n } else if (_typeof(input[key]) === 'object' && input[key] !== null) {\n // Allow ignoring arrays if desired\n if (Array.isArray(input[key]) && options.ignoreArrays === true) {\n output[key] = input[key];\n } else if (Array.isArray(input[key]) && options.arrayToCsv === true) {\n output[key] = input[key].join(',');\n } else {\n // Make child objects flat too (always returns object so Object.keys is safe)\n var childObject = okanjo.util.flatten(input[key], options);\n Object.keys(childObject).forEach(function (childKey) {\n output[key + '_' + childKey] = childObject[childKey];\n });\n }\n } else {\n // Copy value references\n output[key] = input[key];\n }\n });\n }\n\n return output;\n };\n\n /*! based on shortid https://github.com/dylang/shortid */\n okanjo.util.shortid = function (clusterWorkerId) {\n\n var shuffled = 'ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC',\n crypto = window.crypto || window.msCrypto || typeof require === \"function\" && require('crypto'),\n randomByte = function randomByte() {\n /* istanbul ignore next: platform diffs out of scope */\n if (crypto && crypto.randomBytes) {\n return crypto.randomBytes(1)[0] & 0x30;\n } else if (!crypto || !crypto.getRandomValues) {\n return Math.floor(Math.random() * 256) & 0x30;\n }\n /* istanbul ignore next: platform diffs out of scope */\n var dest = new Uint8Array(1);\n /* istanbul ignore next: platform diffs out of scope */\n crypto.getRandomValues(dest);\n /* istanbul ignore next: platform diffs out of scope */\n return dest[0] & 0x30;\n },\n encode = function encode(number) {\n var loopCounter = 0,\n done = void 0,\n str = '';\n\n while (!done) {\n str = str + shuffled[number >> 4 * loopCounter & 0x0f | randomByte()];\n done = number < Math.pow(16, loopCounter + 1);\n loopCounter++;\n }\n return str;\n },\n\n\n // Ignore all milliseconds before a certain time to reduce the size of the date entropy without sacrificing uniqueness.\n // This number should be updated every year or so to keep the generated id short.\n // To regenerate `new Date() - 0` and bump the version. Always bump the version!\n\n REDUCE_TIME = 1490384907498,\n version = 7;\n\n var counter = void 0,\n previousSeconds = void 0;\n\n clusterWorkerId = clusterWorkerId || 0;\n\n return function () {\n var str = '',\n seconds = Math.floor((new Date().getTime() - REDUCE_TIME) * 0.001);\n\n if (seconds === previousSeconds) {\n counter++;\n } else {\n counter = 0;\n previousSeconds = seconds;\n }\n\n str = str + encode(version) + encode(clusterWorkerId);\n if (counter > 0) {\n str = str + encode(counter);\n }\n str = str + encode(seconds);\n\n return str;\n };\n }();\n\n /**\n * Gets the best URL for where we are operating\n * @returns {string|*}\n */\n okanjo.util.getLocation = function () {\n return window.location !== window.parent.location ? /* istanbul ignore next: oos */document.referrer : document.location.href;\n };\n\n //endregion\n\n //region User Interface\n\n okanjo.ui = {\n\n /**\n * Gets the current page scroll position\n * @returns {{x: Number, y: Number}}\n */\n getScrollPosition: function getScrollPosition() {\n return {\n x: SUPPORTS_PAGE_OFFSET ? window.pageXOffset : /* istanbul ignore next: old browsers */CSS1_COMPATIBLE ? document.documentElement.scrollLeft : document.body.scrollLeft,\n y: SUPPORTS_PAGE_OFFSET ? window.pageYOffset : /* istanbul ignore next: old browsers */CSS1_COMPATIBLE ? document.documentElement.scrollTop : document.body.scrollTop\n };\n },\n\n /**\n * Gets the height and width of the given element\n * @param {HTMLElement|Node} element – The DOM element to get the size of\n * @param {boolean} [includeMargin] – Whether to include the margins of the element in the size\n * @returns {{height: number, width: number}}\n */\n getElementSize: function getElementSize(element, includeMargin) {\n var size = {\n height: element.offsetHeight,\n width: element.offsetWidth\n };\n var style = element.currentStyle || window.getComputedStyle(element);\n\n if (includeMargin) {\n size.height += parseInt(style.marginTop) + parseInt(style.marginBottom);\n size.width += parseInt(style.marginLeft) + parseInt(style.marginRight);\n }\n\n return size;\n },\n\n /**\n * Gets the current page size\n * @return {{w: number, h: number}}\n */\n getPageSize: function getPageSize() {\n var body = document.querySelector('body');\n var html = document.documentElement;\n\n return {\n w: Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth),\n\n h: Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight)\n };\n },\n\n /**\n * Gets the current viewport size\n * @return {{vw: number, vh: number}}\n */\n getViewportSize: function getViewportSize() {\n var element = CSS1_COMPATIBLE ? document.documentElement /* istanbul ignore next: browser diffs */ : document.body;\n var width = element.clientWidth;\n var height = element.clientHeight;\n var inWidth = window.innerWidth /* istanbul ignore next: browser diffs */ || 0;\n var inHeight = window.innerHeight /* istanbul ignore next: browser diffs */ || 0;\n var isMobileZoom = inWidth && width > inWidth || inHeight && height > inHeight;\n\n return {\n vw: isMobileZoom /* istanbul ignore next: browser diffs */ ? inWidth : width,\n vh: isMobileZoom /* istanbul ignore next: browser diffs */ ? inHeight : height\n };\n },\n\n /**\n * Gets the x, y location of the event relative to the page\n * @param event – Mouse/Touch Event\n * @return {{ex: number, ey: number}}\n */\n getEventPosition: function getEventPosition(event) {\n var ex = event.pageX;\n var ey = event.pageY;\n var body = document.body;\n var el = document.documentElement;\n var scrollLeft = 'scrollLeft';\n var scrollTop = 'scrollTop';\n var type = event.__proto__.constructor.name;\n\n return {\n et: type, // mouse? touch? keyboard? robot?\n ex: ex === undefined /* istanbul ignore next: browser diffs */ ? event.clientX + body[scrollLeft] + el[scrollLeft] : ex,\n ey: ey === undefined /* istanbul ignore next: browser diffs */ ? event.clientY + body[scrollTop] + el[scrollTop] : ey\n };\n },\n\n /**\n * Gets the element's rectangle coordinates on the page\n * @param element\n * @return {{x1: number, y1: number, x2: number, y2: number}}\n */\n getElementPosition: function getElementPosition(element) {\n\n // Wrapped in try-catch because IE is super strict about the\n // element being on the DOM before you call this. Other browsers\n // let it slide, but oh well.\n\n var err = 'Could not get position of element. Did you attach the element to the DOM before initializing?';\n try {\n var rect = element.getBoundingClientRect();\n var body = document.body.getBoundingClientRect();\n // let pos = okanjo.ui.getScrollPosition();\n\n /* istanbul ignore else: jsdom doesn't mock this */\n if (!document.body.contains(element)) {\n okanjo.report(err, element);\n }\n return {\n // x1: rect.left + pos.x,\n // y1: rect.top + pos.y,\n // x2: rect.right + pos.x,\n // y2: rect.bottom + pos.y\n\n // This might fix\n x1: rect.left - body.left,\n y1: rect.top - body.top,\n x2: rect.right - body.left,\n y2: rect.bottom - body.top\n\n };\n } catch (e) {\n okanjo.report(err, { exception: e, element: element });\n return {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: 0,\n err: 1\n };\n }\n },\n\n /**\n * Gets the intersection information given the element, viewport and scroll positions\n * @param e – Element position\n * @param s - Scroll position\n * @param v - Viewport size\n * @return {{intersectionArea: number, elementArea: number}}\n * @private\n */\n _getIntersection: function _getIntersection(e, s, v) {\n var iLeft = Math.max(e.x1, s.x),\n iRight = Math.min(e.x2, s.x + v.vw),\n iTop = Math.max(e.y1, s.y),\n iBottom = Math.min(e.y2, s.y + v.vh),\n intersectionArea = Math.max(0, iRight - iLeft) * Math.max(0, iBottom - iTop),\n elementArea = (e.x2 - e.x1) * (e.y2 - e.y1);\n\n return {\n intersectionArea: intersectionArea,\n elementArea: elementArea\n };\n },\n\n /**\n * Checks whether the element is actually displayed on the DOM\n * @param element\n * @return {boolean}\n */\n isElementVisible: function isElementVisible(element) {\n /* istanbul ignore next: jsdom won't trigger this */\n return element.offsetWidth > 0 && element.offsetHeight > 0;\n },\n\n /**\n * Gets the percentage of the element pixels currently within the viewport\n * @param {HTMLElement|Node} element\n * @return {number}\n */\n getPercentageInViewport: function getPercentageInViewport(element) {\n var e = okanjo.ui.getElementPosition(element),\n s = okanjo.ui.getScrollPosition(),\n v = okanjo.ui.getViewportSize();\n\n // If there was a problem getting the element position, fail fast\n if (e.err) return 0;\n\n // Get intersection rectangle\n\n var _okanjo$ui$_getInters = okanjo.ui._getIntersection(e, s, v),\n intersectionArea = _okanjo$ui$_getInters.intersectionArea,\n elementArea = _okanjo$ui$_getInters.elementArea;\n\n // Don't let it return NaN\n /* istanbul ignore else: jsdom no love positional data */\n\n\n if (elementArea <= 0) return 0;\n\n /* istanbul ignore next: jsdom no love positional data, area tested with helper fn tho */\n return intersectionArea / elementArea;\n }\n };\n\n /**\n * Splits the text in the element to fit within the visible height of its container, and separates with an ellipses\n * @param {HTMLElement|Node} element – The DOM element containing the text to fit\n * @param {HTMLElement} [container] – Optional container to compute fit on. Defaults to the element's parent\n */\n okanjo.ui.ellipsify = function (element, container) {\n\n // It's a sad day when you have to resort to JS because CSS kludges are too hacky to work down to IE8, programmatically\n\n //noinspection JSValidateTypes\n var parent = container || element.parentNode,\n targetHeight = okanjo.ui.getElementSize(parent).height,\n useTextContent = element.textContent !== undefined;\n\n var text = useTextContent ? element.textContent /* istanbul ignore next: browser diffs */ : element.innerText,\n replacedText = \"\",\n safety = 5000,\n // Safety switch to bust out of the loop in the event something goes terribly wrong\n replacer = function replacer(match) {\n /* istanbul ignore next: n/a to jsdom */\n replacedText = match.substr(0, match.length - 3) + replacedText;\n /* istanbul ignore next: n/a to jsdom */\n return '...';\n };\n\n // Trim off characters until we can fit the text and ellipses\n // If the text already fits, this loop is ignored\n /* istanbul ignore next: jsdom doesn't do element size computing stuff */\n while (okanjo.ui.getElementSize(element).height > targetHeight && text.length > 0 && safety-- > 0) {\n text = useTextContent ? element.textContent : element.innerText;\n\n text = text.replace(ELLIPSIFY_PATTERN, replacer);\n\n if (useTextContent) {\n element.textContent = text;\n } else {\n element.innerText = text;\n }\n }\n\n // If there is work to do, split the content into two span tags\n // Like so: [content]...[hidden content]\n /* istanbul ignore if: n/a to jsdom */\n if (replacedText.length > 0) {\n\n var content = document.createElement('span'),\n span = document.createElement('span');\n\n content.setAttribute('class', 'okanjo-ellipses');\n span.setAttribute('class', 'okanjo-visually-hidden');\n\n if (useTextContent) {\n content.textContent = text.substr(0, text.length - 3);\n span.textContent = replacedText;\n } else {\n content.innerText = text.substr(0, text.length - 3);\n span.innerText = replacedText;\n }\n\n element.innerHTML = '';\n element.appendChild(content);\n element.appendChild(span);\n }\n };\n\n /**\n * Locates images with the class okanjo-fit and ensures that they get filled.\n * This is basically a object-fit hacky workaround\n * @param element\n */\n okanjo.ui.fitImages = function (element) {\n // Detect objectFit support\n /* istanbul ignore else: n/a to jsdom */\n if ('objectFit' in document.documentElement.style === false) {\n // Find images to fit\n element.querySelectorAll('img.okanjo-fit').forEach(function (img) {\n\n // Hide the image\n img.style.display = 'none';\n\n // Update the parent w/ the background\n var parent = img.parentNode;\n parent.style.backgroundSize = 'cover';\n parent.style.backgroundImage = 'url(' + img.src + ')';\n parent.style.backgroundposition = 'center center';\n });\n }\n };\n\n //endregion\n\n // Export the root namespace\n return window.okanjo = okanjo;\n}(window, document);\n\"use strict\";\n\n(function (window) {\n\n var JSON_TEST = /^application\\/json/;\n var okanjo = window.okanjo;\n\n /**\n * Performs a reliable XHR request\n * @param {string} method - Request method\n * @param {string} url - URL\n * @param [payload] optional payload\n * @param callback Fired on when completed (err, res), normalized to standard response format\n */\n okanjo.net.request = function (method, url, payload, callback) {\n\n // payload is not required\n if (typeof payload === \"function\") {\n callback = payload;\n payload = undefined;\n }\n\n // Create a new instance\n var req = new (window.XMLHttpRequest /* istanbul ignore next: old ie */ || window.ActiveXObject)('MSXML2.XMLHTTP.3.0');\n\n // Flag to prevent duplicate callbacks / races\n var calledBack = false;\n\n // Normalized done handler\n var done = function done(err, res) {\n /* istanbul ignore else: out of scope */\n if (!calledBack) {\n calledBack = true;\n callback(err, res);\n }\n };\n\n // Apply timeout if configured globally\n if (okanjo.net.request.timeout) {\n req.timeout = okanjo.net.request.timeout;\n }\n\n // Catch timeout errors\n req.ontimeout = function (e) {\n /* istanbul ignore next: idk if jsdom can mock this, also readystatechange may fire before this anyway */\n done({\n statusCode: 504,\n error: \"Request timed out\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n };\n\n // Handle the response\n req.onreadystatechange = function (e) {\n // 4 = completed / failed\n if (req.readyState === 4) {\n // Do we have a response?\n if (req.status > 0) {\n var res = void 0;\n\n // Check if we got JSON and parse it right away\n if (JSON_TEST.test(req.getResponseHeader('Content-Type'))) {\n res = JSON.parse(req.responseText);\n } else {\n // Not JSON, normalize it instead\n res = {\n statusCode: req.status,\n data: req.responseText\n };\n }\n\n // Put the response in the proper slot (err for non success responses)\n if (req.status >= 200 && req.status < 300) {\n done(null, res);\n } else {\n done(res);\n }\n } else {\n // Request failed - e.g. CORS or network issues\n done({\n statusCode: 503,\n error: \"Request failed\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n }\n }\n };\n\n // Open the request\n req.open(method.toUpperCase(), url);\n\n // Include credentials\n req.withCredentials = true;\n\n // Handle post payloads\n if (['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {\n req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n if (payload !== undefined) {\n payload = JSON.stringify(payload);\n }\n }\n\n // Ship it\n req.send(payload || undefined);\n };\n\n // Bind helpers to make things easy as pie\n okanjo.net.request.get = okanjo.net.request.bind(this, 'GET');\n okanjo.net.request.post = okanjo.net.request.bind(this, 'POST');\n okanjo.net.request.put = okanjo.net.request.bind(this, 'PUT');\n okanjo.net.request.delete = okanjo.net.request.bind(this, 'DELETE');\n\n /**\n * Helper to aid in minificiation+querystringify and redundant encodeURIComponent stuff\n * @param val\n * @return {*}\n */\n var encode = function encode(val) {\n if (val === null || val === undefined) return '';\n return encodeURIComponent('' + val);\n };\n\n /**\n * Helper to aid in getting a query string key using a prefix and keyname\n * @param key\n * @param keyPrefix\n * @return {*}\n */\n var getKey = function getKey(key, keyPrefix) {\n if (keyPrefix) {\n return keyPrefix + '[' + encode(key) + ']';\n } else {\n return encode(key);\n }\n };\n\n /**\n * Super basic querystringify helper. It handles deep objects, but not for array values\n * @param obj\n * @param [keyPrefix]\n * @return {string}\n */\n okanjo.net.request.stringify = function (obj, keyPrefix) {\n var pairs = [];\n keyPrefix = keyPrefix || \"\";\n Object.keys(obj).forEach(function (key) {\n var value = obj[key];\n if (Array.isArray(value)) {\n value.forEach(function (v) {\n return pairs.push(getKey(key, keyPrefix) + '=' + encode(v));\n }); // Does not do that PHP garbage with key[]=val\n } else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === \"object\" && value !== null) {\n // Recurse\n var res = okanjo.net.request.stringify(value, getKey(key, keyPrefix));\n if (res) pairs.push(res);\n } else if (value !== undefined) {\n pairs.push(getKey(key, keyPrefix) + '=' + encode(value));\n }\n });\n return pairs.join('&');\n };\n})(window);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function (window, document) {\n\n /**\n * Okanjo cookie utility helpers\n */\n window.okanjo.util.cookie = {\n\n /**\n * Sets a cookie\n * @param cookieName\n * @param value\n * @param expireDays\n */\n set: function set(cookieName, value, expireDays) {\n var expireDate = new Date();\n expireDate.setDate(expireDate.getDate() + expireDays);\n var expires = expireDays ? \" Expires=\" + expireDate.toUTCString() + \";\" : \"\";\n var path = \" Path=/\";\n var secure = window.location.protocol === 'https:' ? ' Secure;' : '';\n // const secure = ' Secure;';\n var cookieValue = encodeURI(value) + ';' + expires + secure + ' SameSite=None;' + path;\n // console.log('setting cookie', cookieName, cookieValue)\n document.cookie = cookieName + \"=\" + cookieValue;\n },\n\n /**\n * Gets a cookie\n * @param cookieName\n * @return {*}\n */\n get: function get(cookieName) {\n var output = null;\n document.cookie.split(\";\").find(function (cookie) {\n var nameTest = cookie.substr(0, cookie.indexOf(\"=\")).trim();\n var value = cookie.substr(cookie.indexOf(\"=\") + 1);\n if (nameTest === cookieName) {\n output = decodeURI(value);\n return true;\n } else {\n return false;\n }\n });\n return output;\n }\n };\n})(window, document);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window, document) {\n\n var okanjo = window.okanjo;\n\n /**\n * Event tracking class\n * @type {Metrics}\n */\n\n var Metrics = function () {\n\n //noinspection JSUnusedGlobalSymbols\n function Metrics() {\n _classCallCheck(this, Metrics);\n\n /**\n * Events queued here before submission\n * @type {Array}\n * @private\n */\n this._queue = this._getStoredQueue();\n this._processTimeout = null; // queue event loop timeout pointer\n\n /**\n * Unique page grouping event identifier\n */\n this.pageId = okanjo.util.shortid();\n this.defaultChannel = Metrics.Channel.external;\n\n this.sid = null;\n this.sourceCh = null;\n this.sourceCx = null;\n\n // Extract referral data, if set\n this._checkUrlForReferral();\n\n // TODO - look into iframe session correlation system\n }\n\n //noinspection JSMethodCanBeStatic\n /**\n * Gets the storage backed metric queue, in case we did not send everything last time\n * @return {Array}\n * @private\n */\n\n\n _createClass(Metrics, [{\n key: '_getStoredQueue',\n value: function _getStoredQueue() {\n if (window.localStorage[Metrics.Params.queue]) {\n try {\n var queue = JSON.parse(window.localStorage[Metrics.Params.queue]);\n if (Array.isArray(queue)) {\n return queue;\n } else {\n okanjo.report('Stored queue is not a queue', { queue: queue });\n return [];\n }\n } catch (e) {\n okanjo.report('Failed to load metric queue from storage', { err: e });\n return [];\n }\n } else {\n // not stored\n return [];\n }\n }\n\n /**\n * Updates the queue stored in storage, in the event we can't complete our submissions\n * @param delay - Whether to delay updating the queue for a bit, to let other metrics pile in\n * @private\n */\n\n }, {\n key: '_saveQueue',\n value: function _saveQueue(delay) {\n var _this = this;\n\n if (delay) {\n if (this._saveQueueTimeout) clearTimeout(this._saveQueueTimeout);\n this._saveQueueTimeout = setTimeout(function () {\n _this._saveQueue(false);\n _this._saveQueueTimeout = null;\n }, 100);\n } else {\n window.localStorage[Metrics.Params.queue] = JSON.stringify(this._queue);\n }\n }\n\n /**\n * Extract contextual pass-through data from the URL, if present\n * @private\n */\n\n }, {\n key: '_checkUrlForReferral',\n value: function _checkUrlForReferral() {\n var pageArgs = okanjo.util.getPageArguments(true),\n urlSid = pageArgs[Metrics.Params.name],\n localSid = window.localStorage[Metrics.Params.name] || okanjo.util.cookie.get(Metrics.Params.name),\n // pull from storage or cookie\n sourceContext = pageArgs[Metrics.Params.context],\n sourceChannel = pageArgs[Metrics.Params.channel];\n\n // If for some reason, both are set, record the incident as a possible correlation\n if (urlSid && localSid && urlSid !== localSid) {\n this.trackEvent({\n object_type: Metrics.Object.metric_session,\n event_type: Metrics.Event.correlation,\n id: urlSid + \"_\" + localSid,\n ch: this.defaultChannel,\n _noProcess: true\n });\n }\n\n // Update local values\n this.sid = localSid || urlSid || null; // prefer local over remote (changed in 1.0)\n this.sourceCh = sourceChannel || null;\n this.sourceCx = sourceContext || null;\n }\n\n /**\n * Submits an individual event metric\n * @param event\n * @param callback\n */\n\n }, {\n key: 'trackEvent',\n value: function trackEvent(event, callback) {\n // Ensure the event contains the required fields\n if (!event.object_type || !event.event_type) {\n okanjo.report('Invalid metric to track (missing object_type or event_type)', { event: event });\n return;\n }\n\n // Queue the event for publishing\n this._push(event, callback);\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Submits a page view metric\n * @param event\n * @param callback\n */\n\n }, {\n key: 'trackPageView',\n value: function trackPageView(event, callback) {\n event = event || {};\n event.object_type = Metrics.Object.page;\n event.event_type = Metrics.Event.view;\n event.id = event.id || okanjo.util.getLocation();\n event.ch = event.ch || this.defaultChannel;\n\n // Queue the event for publishing\n this.trackEvent(event, callback);\n }\n\n /**\n * Adds an event to the queue\n * @param event\n * @param callback\n * @private\n */\n\n }, {\n key: '_push',\n value: function _push(event, callback) {\n this._queue.push({ event: event, callback: callback });\n\n // Save the queue\n this._saveQueue(true);\n\n // Start burning down the queue, unless the event says not to\n if (event._noProcess) {\n delete event._noProcess;\n } else {\n this._processQueue();\n }\n }\n\n /**\n * Burn down the queue\n * @private\n */\n\n }, {\n key: '_processQueue',\n value: function _processQueue() {\n var _this2 = this;\n\n // If the queue is not already being processed, and there's stuff to process, continue sending them\n if (!this._processTimeout && this._queue.length > 0) {\n this._processTimeout = setTimeout(function () {\n\n // Pull the items we're going to batch out of the queue\n var items = _this2._queue.splice(0, 255);\n _this2._saveQueue(false);\n\n // Track the item\n _this2._batchSend(items, function (err, res) {\n // TODO: If there was an error, consider splicing the batch back into the queue\n\n // Update / Set the metric sid on the publisher\n /* istanbul ignore else: server barks */\n if (res && res.data && res.data.sid) _this2._updateSid(res.data.sid);\n\n // When this batch is done being tracked, iterate to the next metric then fire it's callback if set\n _this2._processTimeout = null;\n _this2._processQueue();\n\n // Fire the event callbacks if there are any\n items.forEach(function (item) {\n item.callback && item.callback(err, res);\n });\n });\n }, 0); // break event loop, maybe\n }\n }\n\n /**\n * Sends a bunch of queued metric events\n * @param items\n * @param callback\n * @private\n */\n\n }, {\n key: '_batchSend',\n value: function _batchSend(items, callback) {\n var _this3 = this;\n\n // Normalize event data\n var events = items.map(function (item) {\n _this3._normalizeEvent(item.event);\n\n // Strip duplicated data from event batch\n delete item.event.sid;\n delete item.event.win;\n\n return item.event;\n });\n\n var payload = {\n events: events,\n win: okanjo.util.getLocation()\n };\n\n var route = okanjo.net.getRoute(okanjo.net.routes.metrics_batch);\n\n // Set sid if present\n if (this.sid) {\n payload.sid = this.sid;\n }\n\n // Send it\n okanjo.net.request.post(route, payload, function (err, res) {\n /* istanbul ignore if: out of scope */\n if (err) {\n okanjo.report('Failed to send metrics batch', { err: err, res: res, items: items, route: route });\n }\n callback && callback(err, res);\n });\n }\n\n /**\n * Normaizes events so that they contain consistent data values\n * @param event\n * @private\n */\n\n }, {\n key: '_normalizeEvent',\n value: function _normalizeEvent(event) {\n\n // Ensure meta is ready to receive values\n event.m = event.m || {};\n\n // Set key\n event.key = event.key || event.m.key || okanjo.key || undefined;\n\n // Set session\n if (this.sid) event.sid = this.sid;\n\n // Clone the metadata, since it might be a direct reference to a widget property\n // Deleting properties on the meta object could be very destructive\n event.m = Object.assign({}, event.m); // event.m should be flat\n\n // Strip meta keys that should be excluded\n Object.keys(Metrics.Meta.exclude).forEach(function (key) {\n return delete event.m[key];\n });\n\n // Set referral channel / context\n if (this.sourceCh) {\n event.m.ref_ch = this.sourceCh;\n }\n if (this.sourceCx) {\n event.m.ref_cx = this.sourceCx;\n }\n\n // Set page group id\n event.m.pgid = this.pageId;\n\n // Set okanjo version\n event.m.ok_ver = okanjo.version;\n\n // Finalize metadata\n event.m = okanjo.util.flatten(event.m, { arrayToCsv: true });\n\n // Ensure metadata strings won't exceed the imposed limit\n Object.keys(event.m).forEach(function (key) {\n if (typeof event.m[key] === \"string\") {\n event.m[key] = event.m[key].substr(0, 255);\n }\n });\n\n // Set page source reference\n if (document.referrer) {\n event.ref = document.referrer;\n }\n\n // Set the window location\n event.win = okanjo.util.getLocation();\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n\n }, {\n key: '_updateSid',\n value: function _updateSid(sid) {\n // Not set or changed?\n if (sid && (!this.sid || this.sid !== sid)) {\n this.sid = sid;\n window.localStorage[Metrics.Params.name] = sid;\n okanjo.util.cookie.set(Metrics.Params.name, sid, Metrics.Params.ttl);\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'create',\n\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Helper to create a new fluent event structure\n * @param args\n * @return {*}\n */\n value: function create() {\n for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n args[_key3] = arguments[_key3];\n }\n\n return Metrics.create.apply(null, args);\n }\n }], [{\n key: 'addElementInfo',\n value: function addElementInfo(element, event) {\n var page = okanjo.ui.getPageSize(),\n size = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n event.m.pw = page.w;\n event.m.ph = page.h;\n event.m.x1 = size.x1;\n event.m.y1 = size.y1;\n event.m.x2 = size.x2;\n event.m.y2 = size.y2;\n\n return event;\n }\n }, {\n key: 'addWidgetInfo',\n value: function addWidgetInfo(element, event) {\n var containerSize = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n\n // placement div size\n event.m.wox1 = containerSize.x1;\n event.m.woy1 = containerSize.y1;\n event.m.wox2 = containerSize.x2;\n event.m.woy2 = containerSize.y2;\n\n // Inner size is the min/max of the child elements since they may be floating and have no official height/width\n var resources = okanjo.qwery('.okanjo-resource, .okanjo-adx-container', element);\n var size = void 0,\n wix1 = void 0,\n wiy1 = void 0,\n wix2 = void 0,\n wiy2 = void 0,\n boxes = [];\n var getMin = function getMin(val, current) {\n return typeof current === \"undefined\" || val < current ? val : current;\n };\n var getMax = function getMax(val, current) {\n return typeof current === \"undefined\" || val > current ? val : current;\n };\n var fallback = function fallback(val, _fallback) {\n return typeof val === \"undefined\" ? _fallback : val;\n };\n\n resources.forEach(function (e) {\n size = okanjo.ui.getElementPosition(e);\n wix1 = getMin(size.x1, wix1);\n wiy1 = getMin(size.y1, wiy1);\n wix2 = getMax(size.x2, wix2);\n wiy2 = getMax(size.y2, wiy2);\n boxes.push(size.x1, size.y1, size.x2, size.y2);\n });\n\n // inner size (might be centered or something)\n // noinspection JSUnusedAssignment\n event.m.wix1 = fallback(wix1, containerSize.x1); // noinspection JSUnusedAssignment\n event.m.wiy1 = fallback(wiy1, containerSize.y1); // noinspection JSUnusedAssignment\n event.m.wix2 = fallback(wix2, containerSize.x2); // noinspection JSUnusedAssignment\n event.m.wiy2 = fallback(wiy2, containerSize.y2);\n event.m.wrps = boxes.map(function (v) {\n return Math.floor(v);\n }).join(','); // all resource positions x1,y1,x2,y2,...\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds viewport dimensions / positional data to the event\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'addViewportInfo',\n value: function addViewportInfo(event) {\n var vp = okanjo.ui.getViewportSize(),\n pos = okanjo.ui.getScrollPosition();\n\n event = event || {};\n event.m = event.m || {};\n event.m.vx1 = pos.x;\n event.m.vy1 = pos.y;\n event.m.vx2 = pos.x + vp.vw;\n event.m.vy2 = pos.y + vp.vh;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'addEventInfo',\n value: function addEventInfo(jsEvent, event) {\n var pos = okanjo.ui.getEventPosition(jsEvent);\n\n event = event || {};\n event.m = event.m || {};\n event.m.et = pos.et;\n event.m.ex = pos.ex;\n event.m.ey = pos.ey;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param event\n * @param args\n * @return {*|{}}\n */\n\n }, {\n key: 'addEventMeta',\n value: function addEventMeta(event) {\n event = event || {};\n event.m = event.m || {};\n\n for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {\n args[_key4 - 1] = arguments[_key4];\n }\n\n event.m = Object.assign.apply(Object, [event.m].concat(args));\n\n return event;\n }\n\n /**\n * Helper to create a new fluent event structure\n * @param data\n * @param args\n * @return {MetricEvent}\n */\n\n }, {\n key: 'create',\n value: function create(data) {\n for (var _len5 = arguments.length, args = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {\n args[_key5 - 1] = arguments[_key5];\n }\n\n // return okanjo.util.deepClone(Object.assign.apply(Object, [{}].concat(args)));\n return new MetricEvent(data, args);\n }\n }]);\n\n return Metrics;\n }();\n\n /**\n * The storage/cookie/url param names\n * @type {{queue: string, name: string, channel: string, context: string, ttl: number}}\n */\n\n\n Metrics.Params = {\n queue: '_ok_q',\n name: 'ok_msid',\n channel: 'ok_ch',\n context: 'ok_cx',\n ttl: 1460 // 4 years\n };\n\n /**\n * Event Metadata configuration\n * @type {{exclude: [*]}}\n */\n Metrics.Meta = {\n exclude: ['key', 'callback', 'metrics_channel_context', 'metrics_context', 'mode']\n };\n\n /**\n * Event Types\n * @type {{view: string, impression: string, interaction: string, correlation: string}}\n */\n Metrics.Event = {\n view: 'vw',\n impression: 'imp',\n interaction: 'int',\n correlation: 'cor'\n };\n\n /**\n * Event Action Types\n * @type {{click: string, inline_click: string}}\n */\n Metrics.Action = {\n click: \"click\",\n inline_click: \"inline_click\"\n };\n\n /**\n * Event Object Types\n * @type {{article: string, thirdparty_ad: string, cart: string, page: string, widget: string, product: string, store: string, cause: string, marketplace: string, order: string, order_item: string, user: string, metric_session: string}}\n */\n Metrics.Object = {\n article: 'am',\n thirdparty_ad: 'ta',\n cart: 'ct',\n page: 'pg',\n widget: 'wg',\n product: 'pr',\n store: 'st',\n cause: 'ca',\n marketplace: 'mp',\n order: 'or',\n order_item: 'oi',\n user: 'ur',\n metric_session: 'mt'\n };\n\n /**\n * Event Channels\n * @type {{product_widget: string, ad_widget: string, store_widget: string, marketplace: string, external: string}}\n */\n Metrics.Channel = {\n placement: 'pw',\n marketplace: 'mp',\n external: 'ex',\n\n // Deprecated:\n product_widget: 'pw',\n ad_widget: 'aw',\n store_widget: 'sw'\n };\n\n /**\n * Event Environments\n * @type {{live: string, testing: string}}\n */\n Metrics.Environment = {\n live: \"live\",\n testing: \"testing\"\n };\n\n /**\n * Fluent wrapper around making events simple\n */\n\n var MetricEvent = function () {\n function MetricEvent(data, others) {\n var _this4 = this;\n\n _classCallCheck(this, MetricEvent);\n\n // Merge the data and other data sets into this object\n data = data || {};\n this.data(data);\n /* istanbul ignore else: metrics.create is the only way to create this right now */\n if (Array.isArray(others)) {\n others.forEach(function (data) {\n _this4.data(data);\n });\n }\n }\n\n /**\n * Sets event parameter key-values\n * @param data\n */\n\n\n _createClass(MetricEvent, [{\n key: 'data',\n value: function data(_data) {\n Object.assign(this, okanjo.util.deepClone(_data));\n return this;\n }\n\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @return {MetricEvent}\n */\n\n }, {\n key: 'event',\n value: function event(jsEvent) {\n Metrics.addEventInfo(jsEvent, this);\n return this;\n }\n\n /**\n * Adds viewport dimensions / positional data to the event\n * @return {MetricEvent}\n */\n\n }, {\n key: 'viewport',\n value: function viewport() {\n Metrics.addViewportInfo(this);\n return this;\n }\n\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @return {MetricEvent}\n */\n\n }, {\n key: 'element',\n value: function element(_element) {\n Metrics.addElementInfo(_element, this);\n return this;\n }\n\n /**\n * Adds widget DOM element dimensions / positional data to the event\n * @param element\n * @returns {MetricEvent}\n */\n\n }, {\n key: 'widget',\n value: function widget(element) {\n Metrics.addWidgetInfo(element, this);\n return this;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param args\n * @return {MetricEvent}\n */\n\n }, {\n key: 'meta',\n value: function meta() {\n for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {\n args[_key6] = arguments[_key6];\n }\n\n Metrics.addEventMeta.apply(null, [this].concat(args));\n return this;\n }\n\n /**\n * Sets the object and event type on the event w/o having to use .data\n * @param object_type\n * @param event_type\n * @return {MetricEvent}\n */\n\n }, {\n key: 'type',\n value: function type(object_type, event_type) {\n this.object_type = object_type;\n this.event_type = event_type;\n return this;\n }\n\n /**\n * Finalizes and sends the event\n * @param callback\n */\n\n }, {\n key: 'send',\n value: function send(callback) {\n okanjo.metrics.trackEvent(this, callback);\n // DONT RETURN - BREAK THE CHAIN HERE\n }\n\n /**\n * Gets the single-metric tracking url for this event\n * @return {string}\n */\n\n }, {\n key: 'toUrl',\n value: function toUrl() {\n // Copy data w/o modifying it\n var event = Object.assign({}, this);\n\n // Extract params\n var object_type = event.object_type,\n event_type = event.event_type;\n\n delete event.object_type;\n delete event.event_type;\n\n // Normalize event data\n okanjo.metrics._normalizeEvent(event);\n\n // Get the URL\n return okanjo.net.getRoute(okanjo.net.routes.metrics, { object_type: object_type, event_type: event_type }) + '?' + okanjo.net.request.stringify(event);\n }\n }]);\n\n return MetricEvent;\n }();\n\n // Export / initialize\n\n\n okanjo.metrics = new Metrics();\n})(window, document);\nreturn okanjo;\n}));\n","// Production steps of ECMA-262, Edition 6, 22.1.2.1\nif (!Array.from) {\n Array.from = (function () {\n var toStr = Object.prototype.toString;\n var isCallable = function (fn) {\n return typeof fn === 'function' || toStr.call(fn) === '[object Function]';\n };\n var toInteger = function (value) {\n var number = Number(value);\n if (isNaN(number)) { return 0; }\n if (number === 0 || !isFinite(number)) { return number; }\n return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));\n };\n var maxSafeInteger = Math.pow(2, 53) - 1;\n var toLength = function (value) {\n var len = toInteger(value);\n return Math.min(Math.max(len, 0), maxSafeInteger);\n };\n\n // The length property of the from method is 1.\n return function from(arrayLike/*, mapFn, thisArg */) {\n // 1. Let C be the this value.\n var C = this;\n\n // 2. Let items be ToObject(arrayLike).\n var items = Object(arrayLike);\n\n // 3. ReturnIfAbrupt(items).\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object - not null or undefined');\n }\n\n // 4. If mapfn is undefined, then let mapping be false.\n var mapFn = arguments.length > 1 ? arguments[1] : void undefined;\n var T;\n if (typeof mapFn !== 'undefined') {\n // 5. else\n // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.\n if (!isCallable(mapFn)) {\n throw new TypeError('Array.from: when provided, the second argument must be a function');\n }\n\n // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.\n if (arguments.length > 2) {\n T = arguments[2];\n }\n }\n\n // 10. Let lenValue be Get(items, \"length\").\n // 11. Let len be ToLength(lenValue).\n var len = toLength(items.length);\n\n // 13. If IsConstructor(C) is true, then\n // 13. a. Let A be the result of calling the [[Construct]] internal method\n // of C with an argument list containing the single item len.\n // 14. a. Else, Let A be ArrayCreate(len).\n var A = isCallable(C) ? Object(new C(len)) : new Array(len);\n\n // 16. Let k be 0.\n var k = 0;\n // 17. Repeat, while k < len… (also steps a - h)\n var kValue;\n while (k < len) {\n kValue = items[k];\n if (mapFn) {\n A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);\n } else {\n A[k] = kValue;\n }\n k += 1;\n }\n // 18. Let putStatus be Put(A, \"length\", len, true).\n A.length = len;\n // 20. Return A.\n return A;\n };\n }());\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.find\nif (!Array.prototype.find) {\n Object.defineProperty(Array.prototype, 'find', {\n value: function(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return kValue.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return kValue;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return undefined.\n return undefined;\n }\n });\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex\nif (!Array.prototype.findIndex) {\n Object.defineProperty(Array.prototype, 'findIndex', {\n value: function(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return k.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return k;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return -1.\n return -1;\n }\n });\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.includes\nif (!Array.prototype.includes) {\n Object.defineProperty(Array.prototype, 'includes', {\n value: function(searchElement, fromIndex) {\n\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n // 1. Let O be ? ToObject(this value).\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If len is 0, return false.\n if (len === 0) {\n return false;\n }\n\n // 4. Let n be ? ToInteger(fromIndex).\n // (If fromIndex is undefined, this step produces the value 0.)\n var n = fromIndex | 0;\n\n // 5. If n ≥ 0, then\n // a. Let k be n.\n // 6. Else n < 0,\n // a. Let k be len + n.\n // b. If k < 0, let k be 0.\n var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\n\n function sameValueZero(x, y) {\n return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));\n }\n\n // 7. Repeat, while k < len\n while (k < len) {\n // a. Let elementK be the result of ? Get(O, ! ToString(k)).\n // b. If SameValueZero(searchElement, elementK) is true, return true.\n if (sameValueZero(o[k], searchElement)) {\n return true;\n }\n // c. Increase k by 1.\n k++;\n }\n\n // 8. Return false\n return false;\n }\n });\n}","// https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach\nif (window.NodeList && !NodeList.prototype.forEach) {\n NodeList.prototype.forEach = function (callback, thisArg) {\n thisArg = thisArg || window;\n for (var i = 0; i < this.length; i++) {\n callback.call(thisArg, this[i], i, this);\n }\n };\n}","// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\nif (typeof Object.assign != 'function') {\n // Must be writable: true, enumerable: false, configurable: true\n Object.defineProperty(Object, \"assign\", {\n value: function assign(target, varArgs) { // .length of function is 2\n 'use strict';\n if (target == null) { // TypeError if undefined or null\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n var to = Object(target);\n\n for (var index = 1; index < arguments.length; index++) {\n var nextSource = arguments[index];\n\n if (nextSource != null) { // Skip over if undefined or null\n for (var nextKey in nextSource) {\n // Avoid bugs when hasOwnProperty is shadowed\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n },\n writable: true,\n configurable: true\n });\n}","\"use strict\";\n\n/* exported okanjo */\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/**\n * Okanjo widget framework namespace\n * @global okanjo\n */\nconst okanjo = (function(window, document) {\n\n //region Constants\n\n // Environment Vars\n const SUPPORTS_PAGE_OFFSET = window.pageXOffset !== undefined;\n const CSS1_COMPATIBLE = (document.compatMode /* istanbul ignore next: out of scope */ || \"\") === \"CSS1Compat\";\n const AGENT = window.navigator.userAgent;\n const ELLIPSIFY_PATTERN = /[\\s\\S](?:\\.\\.\\.)?$/;\n const MOBILE_PATTERN = /(iPhone|iPad|iPod|Android|blackberry)/i;\n const NOOP = () => {};\n const Console = window.console;\n\n // Place to pull defaults, if already set\n const settings = window.okanjo || {};\n\n //endregion\n\n //region Okanjo Core\n\n\n //noinspection JSValidateJSDoc,JSClosureCompilerSyntax - idk phpStorm generated it so why would it be wrong? :P\n /**\n * Okanjo namespace\n * @global\n * @type {{version: string, metrics: null, key: null, report: ((...p1?:*[])), warn: ((p1?:*, ...p2?:*[])), qwery: ((p1?:*, p2?:*))}}\n */\n const okanjo = {\n\n /**\n * Okanjo version\n */\n version: \"%%OKANJO_VERSION\",\n\n /**\n * Placeholder\n */\n metrics: null,\n\n /**\n * Global/default placement key\n */\n key: settings.key || null,\n\n /**\n * Reports an error to the console and possibly Raven in the future\n * @param args\n */\n report: (...args) => {\n let err = args.find((arg) => arg instanceof Error);\n if (!err) {\n let messageIndex = args.findIndex((arg) => typeof arg === \"string\");\n err = new Error(args[messageIndex] || \"Okanjo Error\");\n if (messageIndex >= 0) args.splice(messageIndex, 1);\n } else {\n // Grow our own stack so we can figure out what async thing did it\n let stack = (new Error()).stack.split('\\n');\n stack.shift();\n stack.shift();\n args.push({ reportStack: stack.join('\\n') });\n args = args.filter((a) => a !== err);\n }\n\n Console.error(`[Okanjo v${okanjo.version}]: ${err.stack}`);\n args.length && Console.error.apply(Console, ['Additional information:'].concat(args));\n\n // TODO - integrate with Raven\n },\n\n /**\n * Warn developers of their misdeeds\n * @param message\n * @param args\n */\n warn: (message, ...args) => {\n const err = new Error(message);\n\n Console.warn(`[Okanjo v${okanjo.version}]: ${err.stack}`);\n args.length && Console.warn.apply(Console, ['Additional information:'].concat(args));\n },\n\n // Backwards compatibility when we shipped with qwery, cuz querySelector[All] wasn't mainstream enough\n qwery: (selector, parent) => {\n\n // If parent is a selector, select the parent first!\n if (typeof parent === \"string\") {\n parent = document.querySelector(parent);\n\n // If parent is not found, there are obviously no results\n if (!parent) return [];\n }\n\n if (!parent) parent = document;\n\n return parent.querySelectorAll(selector);\n }\n };\n\n //endregion\n\n //region Vendor Libs\n\n /**\n * Placeholder for where vendor libraries get no-conflict loaded\n * @type {{}}\n */\n okanjo.lib = {};\n\n //endregion\n\n //region Networking\n\n /**\n * Networking methods\n * @type {{getRoute: *, exec: *}}\n */\n okanjo.net = {\n\n /**\n * API Endpoints\n */\n endpoint: 'https://api2.okanjo.com',\n sandboxEndpoint: 'https://sandbox-api2.okanjo.com',\n\n /**\n * API routes\n */\n routes: {\n ads: '/content',\n metrics: '/metrics/:object_type/:event_type',\n metrics_batch: '/metrics'\n },\n\n /**\n * Compiles a route and parameters into a final URL\n * @param {string} route - Route constant\n * @param {*} [params] - Key value hash\n * @param {*} [env] - Optional environment to use instead of live\n * @return {string} - Route\n */\n getRoute: (route, params, env) => {\n if (params) {\n Object.keys(params).forEach((key) => {\n route = route.replace(`:${key}`, params[key]+\"\");\n });\n }\n env = env || okanjo.env || 'live';\n return (env === 'sandbox' ? okanjo.net.sandboxEndpoint : okanjo.net.endpoint) + route;\n },\n\n // placeholder, xhr request extension\n request: NOOP\n };\n\n //endregion\n\n // region Utilities\n\n //noinspection JSClosureCompilerSyntax,JSValidateJSDoc\n /**\n * Utility functions and helpers\n * @type {{isEmpty: ((p1?:*)=>boolean), isMobile: (()), getPageArguments: ((p1:boolean))}}\n */\n okanjo.util = {\n\n /**\n * Checks whether a value is _really_ empty (trims)\n * @param val\n * @return {boolean}\n */\n isEmpty: (val) => val === null || val === undefined || (typeof val === \"string\" && val.trim().length === 0),\n\n /**\n * Checks if the current user agent identifies as a mobile device\n * @returns {boolean}\n */\n isMobile: () => {\n // KludgyAF™, but let's go with it\n return MOBILE_PATTERN.test(AGENT);\n },\n\n /**\n * Returns an object hashmap of query and hash parameters\n * @param {boolean} includeHashArguments - Whether to include the hash arguments, if any\n * @return {*}\n */\n getPageArguments: (includeHashArguments) => {\n\n const split = (query) => {\n query = query || \"\";\n const params = {};\n const parts = query.split('&');\n parts.forEach((part) => {\n const eqIndex = part.indexOf('=');\n let key, value;\n if (eqIndex < 0) {\n key = decodeURIComponent(part);\n value = null;\n } else {\n key = decodeURIComponent(part.substring(0, eqIndex));\n value = decodeURIComponent(part.substring(eqIndex + 1));\n }\n if (key) params[key] = value;\n });\n return params;\n };\n\n const queryArgs = split(window.location.search.substring(window.location.search.indexOf('?') + 1));\n const hashArgs = includeHashArguments ? split(window.location.hash.substring(Math.max(window.location.hash.indexOf('#') + 1, window.location.hash.indexOf('#!') + 2))) : {};\n Object.keys(hashArgs).forEach((key) => queryArgs[key] = hashArgs[key]);\n\n return queryArgs;\n }\n\n };\n\n /**\n * Deep clones an object by breaking references, unlike Object.assign\n * @param mixed – Source to clone (object, array, value)\n * @param [out] - Existing output, if any\n * @return {*}\n */\n okanjo.util.deepClone = (mixed, out) => {\n if (Array.isArray(mixed)) {\n // Array reference\n out = out || [];\n out = out.concat(mixed.map((val) => okanjo.util.deepClone(val)));\n } else if (typeof mixed === \"object\" && mixed !== null) {\n // Object reference\n out = out || {};\n Object.keys(mixed).forEach((key) => {\n out[key] = okanjo.util.deepClone(mixed[key]);\n });\n } else {\n // Value\n out = mixed;\n }\n\n return out;\n };\n\n /**\n * Flattens a multi-dimensional object into a single object\n * @param input\n * @param [options]\n * @return {{}}\n */\n okanjo.util.flatten = (input, options = {}) => {\n const output = {};\n\n if (input !== undefined && input !== null) {\n Object\n .keys(input)\n .forEach((key) => {\n // Convert object ids to hex strings\n if (input[key] instanceof Date) {\n if (options.dateToIso) {\n output[key] = input[key].toISOString(); // convert to iso\n } else {\n output[key] = input[key]; // as-is\n }\n } else if (typeof input[key] === 'object' && input[key] !== null) {\n // Allow ignoring arrays if desired\n if (Array.isArray(input[key]) && options.ignoreArrays === true) {\n output[key] = input[key];\n } else if (Array.isArray(input[key]) && options.arrayToCsv === true) {\n output[key] = input[key].join(',');\n } else {\n // Make child objects flat too (always returns object so Object.keys is safe)\n const childObject = okanjo.util.flatten(input[key], options);\n Object\n .keys(childObject)\n .forEach((childKey) => {\n output[key + '_' + childKey] = childObject[childKey];\n })\n ;\n }\n } else {\n // Copy value references\n output[key] = input[key];\n }\n })\n ;\n }\n\n return output;\n };\n\n /*! based on shortid https://github.com/dylang/shortid */\n okanjo.util.shortid = (function(clusterWorkerId) {\n\n const shuffled = 'ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC',\n\n crypto = window.crypto || window.msCrypto || (typeof require === \"function\" && require('crypto')),\n\n randomByte = () => {\n /* istanbul ignore next: platform diffs out of scope */\n if (crypto && crypto.randomBytes) {\n return crypto.randomBytes(1)[0] & 0x30;\n } else if (!crypto || !crypto.getRandomValues) {\n return Math.floor(Math.random() * 256) & 0x30;\n }\n /* istanbul ignore next: platform diffs out of scope */\n const dest = new Uint8Array(1);\n /* istanbul ignore next: platform diffs out of scope */\n crypto.getRandomValues(dest);\n /* istanbul ignore next: platform diffs out of scope */\n return dest[0] & 0x30;\n },\n\n encode = (number) => {\n let loopCounter = 0,\n done,\n str = '';\n\n while (!done) {\n str = str + shuffled[ ( (number >> (4 * loopCounter)) & 0x0f ) | randomByte() ];\n done = number < (Math.pow(16, loopCounter + 1 ) );\n loopCounter++;\n }\n return str;\n },\n\n // Ignore all milliseconds before a certain time to reduce the size of the date entropy without sacrificing uniqueness.\n // This number should be updated every year or so to keep the generated id short.\n // To regenerate `new Date() - 0` and bump the version. Always bump the version!\n\n REDUCE_TIME = 1490384907498,\n version = 7;\n\n let counter,\n previousSeconds;\n\n clusterWorkerId = clusterWorkerId || 0;\n\n return function() {\n let str = '',\n seconds = Math.floor(((new Date()).getTime() - REDUCE_TIME) * 0.001);\n\n if (seconds === previousSeconds) {\n counter++;\n } else {\n counter = 0;\n previousSeconds = seconds;\n }\n\n str = str + encode(version) + encode(clusterWorkerId);\n if (counter > 0) {\n str = str + encode(counter);\n }\n str = str + encode(seconds);\n\n return str;\n };\n })();\n\n /**\n * Gets the best URL for where we are operating\n * @returns {string|*}\n */\n okanjo.util.getLocation = () => window.location !== window.parent.location ? /* istanbul ignore next: oos */ document.referrer : document.location.href;\n\n //endregion\n\n //region User Interface\n\n okanjo.ui = {\n\n /**\n * Gets the current page scroll position\n * @returns {{x: Number, y: Number}}\n */\n getScrollPosition: () => {\n return {\n x: SUPPORTS_PAGE_OFFSET ? window.pageXOffset : /* istanbul ignore next: old browsers */ CSS1_COMPATIBLE ? document.documentElement.scrollLeft : document.body.scrollLeft,\n y: SUPPORTS_PAGE_OFFSET ? window.pageYOffset : /* istanbul ignore next: old browsers */ CSS1_COMPATIBLE ? document.documentElement.scrollTop : document.body.scrollTop\n };\n },\n\n /**\n * Gets the height and width of the given element\n * @param {HTMLElement|Node} element – The DOM element to get the size of\n * @param {boolean} [includeMargin] – Whether to include the margins of the element in the size\n * @returns {{height: number, width: number}}\n */\n getElementSize: (element, includeMargin) => {\n const size = {\n height: element.offsetHeight,\n width : element.offsetWidth\n };\n const style = element.currentStyle || window.getComputedStyle(element);\n\n if (includeMargin) {\n size.height += parseInt(style.marginTop) + parseInt(style.marginBottom);\n size.width += parseInt(style.marginLeft) + parseInt(style.marginRight);\n }\n\n return size;\n },\n\n /**\n * Gets the current page size\n * @return {{w: number, h: number}}\n */\n getPageSize: () => {\n const body = document.querySelector('body');\n const html = document.documentElement;\n\n return {\n w: Math.max(\n body.scrollWidth,\n body.offsetWidth,\n html.clientWidth,\n html.scrollWidth,\n html.offsetWidth\n ),\n\n h: Math.max(\n body.scrollHeight,\n body.offsetHeight,\n html.clientHeight,\n html.scrollHeight,\n html.offsetHeight\n )\n };\n },\n\n /**\n * Gets the current viewport size\n * @return {{vw: number, vh: number}}\n */\n getViewportSize: () => {\n const element = CSS1_COMPATIBLE ? document.documentElement /* istanbul ignore next: browser diffs */: document.body;\n const width = element.clientWidth;\n const height = element.clientHeight;\n const inWidth = window.innerWidth /* istanbul ignore next: browser diffs */ || 0;\n const inHeight = window.innerHeight /* istanbul ignore next: browser diffs */ || 0;\n const isMobileZoom = (inWidth && width > inWidth) || (inHeight && height > inHeight);\n\n return {\n vw: isMobileZoom /* istanbul ignore next: browser diffs */ ? inWidth : width,\n vh: isMobileZoom /* istanbul ignore next: browser diffs */ ? inHeight : height\n };\n },\n\n /**\n * Gets the x, y location of the event relative to the page\n * @param event – Mouse/Touch Event\n * @return {{ex: number, ey: number}}\n */\n getEventPosition: (event) => {\n const ex = event.pageX;\n const ey = event.pageY;\n const body = document.body;\n const el = document.documentElement;\n const scrollLeft = 'scrollLeft';\n const scrollTop = 'scrollTop';\n const type = event.__proto__.constructor.name;\n\n return {\n et: type, // mouse? touch? keyboard? robot?\n ex: ex === undefined /* istanbul ignore next: browser diffs */ ? event.clientX + body[scrollLeft] + el[scrollLeft] : ex,\n ey: ey === undefined /* istanbul ignore next: browser diffs */ ? event.clientY + body[scrollTop] + el[scrollTop] : ey\n };\n },\n\n /**\n * Gets the element's rectangle coordinates on the page\n * @param element\n * @return {{x1: number, y1: number, x2: number, y2: number}}\n */\n getElementPosition: (element) => {\n\n // Wrapped in try-catch because IE is super strict about the\n // element being on the DOM before you call this. Other browsers\n // let it slide, but oh well.\n\n const err = 'Could not get position of element. Did you attach the element to the DOM before initializing?';\n try {\n let rect = element.getBoundingClientRect();\n let body = document.body.getBoundingClientRect();\n // let pos = okanjo.ui.getScrollPosition();\n\n /* istanbul ignore else: jsdom doesn't mock this */\n if (!document.body.contains(element)) {\n okanjo.report(err, element);\n }\n return {\n // x1: rect.left + pos.x,\n // y1: rect.top + pos.y,\n // x2: rect.right + pos.x,\n // y2: rect.bottom + pos.y\n\n // This might fix\n x1: rect.left - body.left,\n y1: rect.top - body.top,\n x2: rect.right - body.left,\n y2: rect.bottom - body.top,\n\n };\n } catch (e) {\n okanjo.report(err, { exception: e, element });\n return {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: 0,\n err: 1\n };\n }\n },\n\n /**\n * Gets the intersection information given the element, viewport and scroll positions\n * @param e – Element position\n * @param s - Scroll position\n * @param v - Viewport size\n * @return {{intersectionArea: number, elementArea: number}}\n * @private\n */\n _getIntersection: (e, s, v) => {\n let iLeft = Math.max(e.x1, s.x),\n iRight = Math.min(e.x2, s.x+v.vw),\n iTop = Math.max(e.y1, s.y),\n iBottom = Math.min(e.y2, s.y+v.vh),\n\n intersectionArea = Math.max(0, iRight - iLeft) * Math.max(0, iBottom - iTop),\n elementArea = (e.x2 - e.x1) * (e.y2 - e.y1);\n\n return {\n intersectionArea,\n elementArea\n };\n },\n\n /**\n * Checks whether the element is actually displayed on the DOM\n * @param element\n * @return {boolean}\n */\n isElementVisible: (element) => {\n /* istanbul ignore next: jsdom won't trigger this */\n return element.offsetWidth > 0 && element.offsetHeight > 0;\n },\n\n /**\n * Gets the percentage of the element pixels currently within the viewport\n * @param {HTMLElement|Node} element\n * @return {number}\n */\n getPercentageInViewport: (element) => {\n let e = okanjo.ui.getElementPosition(element),\n s = okanjo.ui.getScrollPosition(),\n v = okanjo.ui.getViewportSize();\n\n // If there was a problem getting the element position, fail fast\n if (e.err) return 0;\n\n // Get intersection rectangle\n let { intersectionArea, elementArea } = okanjo.ui._getIntersection(e,s,v);\n\n // Don't let it return NaN\n /* istanbul ignore else: jsdom no love positional data */\n if (elementArea <= 0) return 0;\n\n /* istanbul ignore next: jsdom no love positional data, area tested with helper fn tho */\n return intersectionArea / elementArea;\n }\n };\n\n /**\n * Splits the text in the element to fit within the visible height of its container, and separates with an ellipses\n * @param {HTMLElement|Node} element – The DOM element containing the text to fit\n * @param {HTMLElement} [container] – Optional container to compute fit on. Defaults to the element's parent\n */\n okanjo.ui.ellipsify = function(element, container) {\n\n // It's a sad day when you have to resort to JS because CSS kludges are too hacky to work down to IE8, programmatically\n\n //noinspection JSValidateTypes\n const parent = container || element.parentNode,\n targetHeight = okanjo.ui.getElementSize(parent).height,\n useTextContent = element.textContent !== undefined;\n\n let text = useTextContent ? element.textContent /* istanbul ignore next: browser diffs */ : element.innerText,\n replacedText = \"\",\n safety = 5000, // Safety switch to bust out of the loop in the event something goes terribly wrong\n replacer = (match) => {\n /* istanbul ignore next: n/a to jsdom */\n replacedText = match.substr(0, match.length-3) + replacedText;\n /* istanbul ignore next: n/a to jsdom */\n return '...';\n };\n\n // Trim off characters until we can fit the text and ellipses\n // If the text already fits, this loop is ignored\n /* istanbul ignore next: jsdom doesn't do element size computing stuff */\n while (okanjo.ui.getElementSize(element).height > targetHeight && text.length > 0 && (safety-- > 0)) {\n text = useTextContent ? element.textContent : element.innerText;\n\n text = text.replace(ELLIPSIFY_PATTERN, replacer);\n\n if (useTextContent) {\n element.textContent = text;\n } else {\n element.innerText = text;\n }\n }\n\n // If there is work to do, split the content into two span tags\n // Like so: [content]...[hidden content]\n /* istanbul ignore if: n/a to jsdom */\n if (replacedText.length > 0) {\n\n let content = document.createElement('span'),\n span = document.createElement('span');\n\n content.setAttribute('class','okanjo-ellipses');\n span.setAttribute('class','okanjo-visually-hidden');\n\n if (useTextContent) {\n content.textContent = text.substr(0, text.length-3);\n span.textContent = replacedText;\n } else {\n content.innerText = text.substr(0, text.length-3);\n span.innerText = replacedText;\n }\n\n element.innerHTML = '';\n element.appendChild(content);\n element.appendChild(span);\n }\n\n };\n\n /**\n * Locates images with the class okanjo-fit and ensures that they get filled.\n * This is basically a object-fit hacky workaround\n * @param element\n */\n okanjo.ui.fitImages = function(element) {\n // Detect objectFit support\n /* istanbul ignore else: n/a to jsdom */\n if ('objectFit' in document.documentElement.style === false) {\n // Find images to fit\n element.querySelectorAll('img.okanjo-fit').forEach((img) => {\n\n // Hide the image\n img.style.display = 'none';\n\n // Update the parent w/ the background\n let parent = img.parentNode;\n parent.style.backgroundSize = 'cover';\n parent.style.backgroundImage = 'url('+img.src+')';\n parent.style.backgroundposition = 'center center';\n });\n }\n };\n\n //endregion\n\n // Export the root namespace\n return window.okanjo = okanjo;\n\n})(window, document);","\"use strict\";\n\n(function(window) {\n\n const JSON_TEST = /^application\\/json/;\n const okanjo = window.okanjo;\n\n /**\n * Performs a reliable XHR request\n * @param {string} method - Request method\n * @param {string} url - URL\n * @param [payload] optional payload\n * @param callback Fired on when completed (err, res), normalized to standard response format\n */\n okanjo.net.request = function (method, url, payload, callback) {\n\n // payload is not required\n if (typeof payload === \"function\") {\n callback = payload;\n payload = undefined;\n }\n\n // Create a new instance\n const req = new (window.XMLHttpRequest /* istanbul ignore next: old ie */ || window.ActiveXObject)('MSXML2.XMLHTTP.3.0');\n\n // Flag to prevent duplicate callbacks / races\n let calledBack = false;\n\n // Normalized done handler\n const done = function(err, res) {\n /* istanbul ignore else: out of scope */\n if (!calledBack) {\n calledBack = true;\n callback(err, res);\n }\n };\n\n // Apply timeout if configured globally\n if (okanjo.net.request.timeout) {\n req.timeout = okanjo.net.request.timeout;\n }\n\n // Catch timeout errors\n req.ontimeout = function(e) {\n /* istanbul ignore next: idk if jsdom can mock this, also readystatechange may fire before this anyway */\n done({\n statusCode: 504,\n error: \"Request timed out\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n };\n\n // Handle the response\n req.onreadystatechange = function(e) {\n // 4 = completed / failed\n if (req.readyState === 4) {\n // Do we have a response?\n if (req.status > 0) {\n let res;\n\n // Check if we got JSON and parse it right away\n if (JSON_TEST.test(req.getResponseHeader('Content-Type'))) {\n res = JSON.parse(req.responseText);\n } else {\n // Not JSON, normalize it instead\n res = {\n statusCode: req.status,\n data: req.responseText\n };\n }\n\n // Put the response in the proper slot (err for non success responses)\n if (req.status >= 200 && req.status < 300) {\n done(null, res);\n } else {\n done(res);\n }\n } else {\n // Request failed - e.g. CORS or network issues\n done({\n statusCode: 503,\n error: \"Request failed\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n }\n }\n };\n\n // Open the request\n req.open(method.toUpperCase(), url);\n\n // Include credentials\n req.withCredentials = true;\n\n // Handle post payloads\n if (['POST','PUT','PATCH'].includes(method.toUpperCase())) {\n req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n if (payload !== undefined) {\n payload = JSON.stringify(payload);\n }\n }\n\n // Ship it\n req.send(payload || undefined);\n };\n\n // Bind helpers to make things easy as pie\n okanjo.net.request.get = okanjo.net.request.bind(this, 'GET');\n okanjo.net.request.post = okanjo.net.request.bind(this, 'POST');\n okanjo.net.request.put = okanjo.net.request.bind(this, 'PUT');\n okanjo.net.request.delete = okanjo.net.request.bind(this, 'DELETE');\n\n /**\n * Helper to aid in minificiation+querystringify and redundant encodeURIComponent stuff\n * @param val\n * @return {*}\n */\n const encode = (val) => {\n if (val === null || val === undefined) return '';\n return encodeURIComponent(''+val);\n };\n\n /**\n * Helper to aid in getting a query string key using a prefix and keyname\n * @param key\n * @param keyPrefix\n * @return {*}\n */\n const getKey = (key, keyPrefix) => {\n if (keyPrefix) {\n return `${keyPrefix}[${encode(key)}]`;\n } else {\n return encode(key)\n }\n };\n\n /**\n * Super basic querystringify helper. It handles deep objects, but not for array values\n * @param obj\n * @param [keyPrefix]\n * @return {string}\n */\n okanjo.net.request.stringify = (obj, keyPrefix) => {\n let pairs = [];\n keyPrefix = keyPrefix || \"\";\n Object.keys(obj).forEach((key) => {\n let value = obj[key];\n if (Array.isArray(value)) {\n value.forEach((v) => pairs.push(getKey(key, keyPrefix) + '=' + encode(v))); // Does not do that PHP garbage with key[]=val\n } else if (typeof value === \"object\" && value !== null) {\n // Recurse\n let res = okanjo.net.request.stringify(value, getKey(key, keyPrefix));\n if (res) pairs.push(res);\n } else if (value !== undefined) {\n pairs.push(getKey(key, keyPrefix) + '=' + encode(value));\n }\n });\n return pairs.join('&');\n };\n\n})(window);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function(window, document) {\n\n /**\n * Okanjo cookie utility helpers\n */\n window.okanjo.util.cookie = {\n\n /**\n * Sets a cookie\n * @param cookieName\n * @param value\n * @param expireDays\n */\n set: (cookieName, value, expireDays) => {\n const expireDate = new Date();\n expireDate.setDate(expireDate.getDate() + expireDays);\n const expires = expireDays ? \" Expires=\" + expireDate.toUTCString() + \";\" : \"\";\n const path = \" Path=/\";\n const secure = window.location.protocol === 'https:' ? ' Secure;' : '';\n // const secure = ' Secure;';\n const cookieValue = `${encodeURI(value)};${expires}${secure} SameSite=None;${path}`;\n // console.log('setting cookie', cookieName, cookieValue)\n document.cookie = cookieName + \"=\" + cookieValue;\n },\n\n /**\n * Gets a cookie\n * @param cookieName\n * @return {*}\n */\n get: (cookieName) => {\n let output = null;\n document.cookie\n .split(\";\")\n .find((cookie) => {\n let nameTest = cookie.substr(0, cookie.indexOf(\"=\")).trim();\n let value = cookie.substr(cookie.indexOf(\"=\") + 1);\n if (nameTest === cookieName) {\n output = decodeURI(value);\n return true;\n } else {\n return false;\n }\n })\n ;\n return output;\n }\n };\n\n})(window, document);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window, document) {\n\n const okanjo = window.okanjo;\n\n /**\n * Event tracking class\n * @type {Metrics}\n */\n class Metrics {\n\n //noinspection JSUnusedGlobalSymbols\n constructor() {\n\n /**\n * Events queued here before submission\n * @type {Array}\n * @private\n */\n this._queue = this._getStoredQueue();\n this._processTimeout = null; // queue event loop timeout pointer\n\n /**\n * Unique page grouping event identifier\n */\n this.pageId = okanjo.util.shortid();\n this.defaultChannel = Metrics.Channel.external;\n\n this.sid = null;\n this.sourceCh = null;\n this.sourceCx = null;\n\n // Extract referral data, if set\n this._checkUrlForReferral();\n\n // TODO - look into iframe session correlation system\n }\n\n //noinspection JSMethodCanBeStatic\n /**\n * Gets the storage backed metric queue, in case we did not send everything last time\n * @return {Array}\n * @private\n */\n _getStoredQueue() {\n if (window.localStorage[Metrics.Params.queue]) {\n try {\n let queue = JSON.parse(window.localStorage[Metrics.Params.queue]);\n if (Array.isArray(queue)) {\n return queue;\n } else {\n okanjo.report('Stored queue is not a queue', {queue});\n return [];\n }\n } catch (e) {\n okanjo.report('Failed to load metric queue from storage', {err: e});\n return [];\n }\n } else {\n // not stored\n return [];\n }\n }\n\n /**\n * Updates the queue stored in storage, in the event we can't complete our submissions\n * @param delay - Whether to delay updating the queue for a bit, to let other metrics pile in\n * @private\n */\n _saveQueue(delay) {\n if (delay) {\n if (this._saveQueueTimeout) clearTimeout(this._saveQueueTimeout);\n this._saveQueueTimeout = setTimeout(() => {\n this._saveQueue(false);\n this._saveQueueTimeout = null;\n }, 100);\n } else {\n window.localStorage[Metrics.Params.queue] = JSON.stringify(this._queue);\n }\n }\n\n /**\n * Extract contextual pass-through data from the URL, if present\n * @private\n */\n _checkUrlForReferral() {\n const pageArgs = okanjo.util.getPageArguments(true),\n urlSid = pageArgs[Metrics.Params.name],\n localSid = window.localStorage[Metrics.Params.name] || okanjo.util.cookie.get(Metrics.Params.name), // pull from storage or cookie\n sourceContext = pageArgs[Metrics.Params.context],\n sourceChannel = pageArgs[Metrics.Params.channel];\n\n // If for some reason, both are set, record the incident as a possible correlation\n if (urlSid && localSid && urlSid !== localSid) {\n this.trackEvent({\n object_type: Metrics.Object.metric_session,\n event_type: Metrics.Event.correlation,\n id: urlSid+\"_\"+localSid,\n ch: this.defaultChannel,\n _noProcess: true\n });\n }\n\n // Update local values\n this.sid = localSid || urlSid || null; // prefer local over remote (changed in 1.0)\n this.sourceCh = sourceChannel || null;\n this.sourceCx = sourceContext || null;\n }\n\n /**\n * Submits an individual event metric\n * @param event\n * @param callback\n */\n trackEvent(event, callback) {\n // Ensure the event contains the required fields\n if (!event.object_type || !event.event_type) {\n okanjo.report('Invalid metric to track (missing object_type or event_type)', {event});\n return;\n }\n\n // Queue the event for publishing\n this._push(event, callback);\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Submits a page view metric\n * @param event\n * @param callback\n */\n trackPageView(event, callback) {\n event = event || {};\n event.object_type = Metrics.Object.page;\n event.event_type = Metrics.Event.view;\n event.id = event.id || okanjo.util.getLocation();\n event.ch = event.ch || this.defaultChannel;\n\n // Queue the event for publishing\n this.trackEvent(event, callback);\n }\n\n /**\n * Adds an event to the queue\n * @param event\n * @param callback\n * @private\n */\n _push(event, callback) {\n this._queue.push({ event, callback });\n\n // Save the queue\n this._saveQueue(true);\n\n // Start burning down the queue, unless the event says not to\n if (event._noProcess) {\n delete event._noProcess;\n } else {\n this._processQueue();\n }\n }\n\n /**\n * Burn down the queue\n * @private\n */\n _processQueue() {\n // If the queue is not already being processed, and there's stuff to process, continue sending them\n if (!this._processTimeout && this._queue.length > 0) {\n this._processTimeout = setTimeout(() => {\n\n // Pull the items we're going to batch out of the queue\n const items = this._queue.splice(0, 255);\n this._saveQueue(false);\n\n // Track the item\n this._batchSend(items, (err, res) => {\n // TODO: If there was an error, consider splicing the batch back into the queue\n\n // Update / Set the metric sid on the publisher\n /* istanbul ignore else: server barks */\n if (res && res.data && res.data.sid) this._updateSid(res.data.sid);\n\n // When this batch is done being tracked, iterate to the next metric then fire it's callback if set\n this._processTimeout = null;\n this._processQueue();\n\n // Fire the event callbacks if there are any\n items.forEach((item) => {\n item.callback && item.callback(err, res);\n });\n });\n\n }, 0); // break event loop, maybe\n }\n }\n\n /**\n * Sends a bunch of queued metric events\n * @param items\n * @param callback\n * @private\n */\n _batchSend(items, callback) {\n\n // Normalize event data\n const events = items.map((item) => {\n this._normalizeEvent(item.event);\n\n // Strip duplicated data from event batch\n delete item.event.sid;\n delete item.event.win;\n\n return item.event;\n });\n\n const payload = {\n events,\n win: okanjo.util.getLocation()\n };\n\n const route = okanjo.net.getRoute(okanjo.net.routes.metrics_batch);\n\n // Set sid if present\n if (this.sid) {\n payload.sid = this.sid;\n }\n\n // Send it\n okanjo.net.request.post(\n route,\n payload,\n (err, res) => {\n /* istanbul ignore if: out of scope */\n if (err) {\n okanjo.report('Failed to send metrics batch', { err, res, items, route });\n }\n callback && callback(err, res);\n }\n );\n }\n\n /**\n * Normaizes events so that they contain consistent data values\n * @param event\n * @private\n */\n _normalizeEvent(event) {\n\n // Ensure meta is ready to receive values\n event.m = event.m || {};\n\n // Set key\n event.key = event.key || event.m.key || okanjo.key || undefined;\n\n // Set session\n if (this.sid) event.sid = this.sid;\n\n // Clone the metadata, since it might be a direct reference to a widget property\n // Deleting properties on the meta object could be very destructive\n event.m = Object.assign({}, event.m); // event.m should be flat\n\n // Strip meta keys that should be excluded\n Object.keys(Metrics.Meta.exclude).forEach((key) => delete event.m[key]);\n\n // Set referral channel / context\n if (this.sourceCh) { event.m.ref_ch = this.sourceCh; }\n if (this.sourceCx) { event.m.ref_cx = this.sourceCx; }\n\n // Set page group id\n event.m.pgid = this.pageId;\n\n // Set okanjo version\n event.m.ok_ver = okanjo.version;\n\n // Finalize metadata\n event.m = okanjo.util.flatten(event.m, { arrayToCsv: true });\n\n // Ensure metadata strings won't exceed the imposed limit\n Object.keys(event.m).forEach((key) => {\n if (typeof event.m[key] === \"string\") {\n event.m[key] = event.m[key].substr(0, 255);\n }\n });\n\n // Set page source reference\n if (document.referrer) {\n event.ref = document.referrer;\n }\n\n // Set the window location\n event.win = okanjo.util.getLocation();\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n _updateSid(sid) {\n // Not set or changed?\n if (sid && (!this.sid || this.sid !== sid) ) {\n this.sid = sid;\n window.localStorage[Metrics.Params.name] = sid;\n okanjo.util.cookie.set(Metrics.Params.name, sid, Metrics.Params.ttl);\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @param event\n * @return {*|{}}\n */\n static addElementInfo(element, event) {\n const page = okanjo.ui.getPageSize(),\n size = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n event.m.pw = page.w;\n event.m.ph = page.h;\n event.m.x1 = size.x1;\n event.m.y1 = size.y1;\n event.m.x2 = size.x2;\n event.m.y2 = size.y2;\n\n return event;\n }\n\n static addWidgetInfo(element, event) {\n const containerSize = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n\n // placement div size\n event.m.wox1 = containerSize.x1;\n event.m.woy1 = containerSize.y1;\n event.m.wox2 = containerSize.x2;\n event.m.woy2 = containerSize.y2;\n\n // Inner size is the min/max of the child elements since they may be floating and have no official height/width\n const resources = okanjo.qwery('.okanjo-resource, .okanjo-adx-container', element);\n let size, wix1, wiy1, wix2, wiy2, boxes = [];\n const getMin = (val, current) => typeof current === \"undefined\" || val < current ? val : current;\n const getMax = (val, current) => typeof current === \"undefined\" || val > current ? val : current;\n const fallback = (val, fallback) => typeof val === \"undefined\" ? fallback : val;\n\n resources.forEach(e => {\n size = okanjo.ui.getElementPosition(e);\n wix1 = getMin(size.x1, wix1);\n wiy1 = getMin(size.y1, wiy1);\n wix2 = getMax(size.x2, wix2);\n wiy2 = getMax(size.y2, wiy2);\n boxes.push(size.x1, size.y1, size.x2, size.y2);\n });\n\n // inner size (might be centered or something)\n // noinspection JSUnusedAssignment\n event.m.wix1 = fallback(wix1, containerSize.x1); // noinspection JSUnusedAssignment\n event.m.wiy1 = fallback(wiy1, containerSize.y1); // noinspection JSUnusedAssignment\n event.m.wix2 = fallback(wix2, containerSize.x2); // noinspection JSUnusedAssignment\n event.m.wiy2 = fallback(wiy2, containerSize.y2);\n event.m.wrps = boxes.map(v => Math.floor(v)).join(','); // all resource positions x1,y1,x2,y2,...\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds viewport dimensions / positional data to the event\n * @param event\n * @return {*|{}}\n */\n static addViewportInfo(event) {\n const vp = okanjo.ui.getViewportSize(),\n pos = okanjo.ui.getScrollPosition();\n\n event = event || {};\n event.m = event.m || {};\n event.m.vx1 = pos.x;\n event.m.vy1 = pos.y;\n event.m.vx2 = pos.x+vp.vw;\n event.m.vy2 = pos.y+vp.vh;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @param event\n * @return {*|{}}\n */\n static addEventInfo(jsEvent, event) {\n const pos = okanjo.ui.getEventPosition(jsEvent);\n\n event = event || {};\n event.m = event.m || {};\n event.m.et = pos.et;\n event.m.ex = pos.ex;\n event.m.ey = pos.ey;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param event\n * @param args\n * @return {*|{}}\n */\n static addEventMeta(event, ...args) {\n event = event || {};\n event.m = event.m || {};\n event.m = Object.assign.apply(Object, [event.m].concat(args));\n \n return event;\n }\n\n /**\n * Helper to create a new fluent event structure\n * @param data\n * @param args\n * @return {MetricEvent}\n */\n static create(data, ...args) {\n // return okanjo.util.deepClone(Object.assign.apply(Object, [{}].concat(args)));\n return new MetricEvent(data, args);\n }\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Helper to create a new fluent event structure\n * @param args\n * @return {*}\n */\n create(...args) {\n return Metrics.create.apply(null, args);\n }\n\n }\n\n /**\n * The storage/cookie/url param names\n * @type {{queue: string, name: string, channel: string, context: string, ttl: number}}\n */\n Metrics.Params = {\n queue: '_ok_q',\n name: 'ok_msid',\n channel: 'ok_ch',\n context: 'ok_cx',\n ttl: 1460 // 4 years\n };\n\n /**\n * Event Metadata configuration\n * @type {{exclude: [*]}}\n */\n Metrics.Meta = {\n exclude: ['key','callback','metrics_channel_context','metrics_context','mode']\n };\n\n /**\n * Event Types\n * @type {{view: string, impression: string, interaction: string, correlation: string}}\n */\n Metrics.Event = {\n view: 'vw',\n impression: 'imp',\n interaction: 'int',\n correlation: 'cor'\n };\n\n /**\n * Event Action Types\n * @type {{click: string, inline_click: string}}\n */\n Metrics.Action = {\n click: \"click\",\n inline_click: \"inline_click\"\n };\n\n /**\n * Event Object Types\n * @type {{article: string, thirdparty_ad: string, cart: string, page: string, widget: string, product: string, store: string, cause: string, marketplace: string, order: string, order_item: string, user: string, metric_session: string}}\n */\n Metrics.Object = {\n article: 'am',\n thirdparty_ad: 'ta',\n cart: 'ct',\n page: 'pg',\n widget: 'wg',\n product: 'pr',\n store: 'st',\n cause: 'ca',\n marketplace: 'mp',\n order: 'or',\n order_item: 'oi',\n user: 'ur',\n metric_session: 'mt'\n };\n\n /**\n * Event Channels\n * @type {{product_widget: string, ad_widget: string, store_widget: string, marketplace: string, external: string}}\n */\n Metrics.Channel = {\n placement: 'pw',\n marketplace: 'mp',\n external: 'ex',\n\n // Deprecated:\n product_widget: 'pw',\n ad_widget: 'aw',\n store_widget: 'sw'\n };\n\n /**\n * Event Environments\n * @type {{live: string, testing: string}}\n */\n Metrics.Environment = {\n live: \"live\",\n testing: \"testing\"\n };\n\n /**\n * Fluent wrapper around making events simple\n */\n class MetricEvent {\n constructor(data, others) {\n // Merge the data and other data sets into this object\n data = data || {};\n this.data(data);\n /* istanbul ignore else: metrics.create is the only way to create this right now */\n if (Array.isArray(others)) {\n others.forEach((data) => {\n this.data(data);\n });\n }\n }\n\n /**\n * Sets event parameter key-values\n * @param data\n */\n data(data) {\n Object.assign(this, okanjo.util.deepClone(data));\n return this;\n }\n\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @return {MetricEvent}\n */\n event(jsEvent) {\n Metrics.addEventInfo(jsEvent, this);\n return this;\n }\n\n /**\n * Adds viewport dimensions / positional data to the event\n * @return {MetricEvent}\n */\n viewport() {\n Metrics.addViewportInfo(this);\n return this;\n }\n\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @return {MetricEvent}\n */\n element(element) {\n Metrics.addElementInfo(element, this);\n return this;\n }\n\n /**\n * Adds widget DOM element dimensions / positional data to the event\n * @param element\n * @returns {MetricEvent}\n */\n widget(element) {\n Metrics.addWidgetInfo(element, this);\n return this;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param args\n * @return {MetricEvent}\n */\n meta(...args) {\n Metrics.addEventMeta.apply(null, [this].concat(args));\n return this;\n }\n\n /**\n * Sets the object and event type on the event w/o having to use .data\n * @param object_type\n * @param event_type\n * @return {MetricEvent}\n */\n type(object_type, event_type) {\n this.object_type = object_type;\n this.event_type = event_type;\n return this;\n }\n\n /**\n * Finalizes and sends the event\n * @param callback\n */\n send(callback) {\n okanjo.metrics.trackEvent(this, callback);\n // DONT RETURN - BREAK THE CHAIN HERE\n }\n\n /**\n * Gets the single-metric tracking url for this event\n * @return {string}\n */\n toUrl() {\n // Copy data w/o modifying it\n const event = Object.assign({}, this);\n\n // Extract params\n const {\n object_type,\n event_type\n } = event;\n delete event.object_type;\n delete event.event_type;\n\n // Normalize event data\n okanjo.metrics._normalizeEvent(event);\n\n // Get the URL\n return okanjo.net.getRoute(okanjo.net.routes.metrics, { object_type, event_type }) + '?' +\n okanjo.net.request.stringify(event);\n }\n }\n\n // Export / initialize\n okanjo.metrics = new Metrics();\n\n})(window, document);"],"sourceRoot":"./"} \ No newline at end of file diff --git a/dist/okanjo-templates.js b/dist/okanjo-templates.js index cee4d82..a0a26ab 100644 --- a/dist/okanjo-templates.js +++ b/dist/okanjo-templates.js @@ -1,4 +1,4 @@ -/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ (function(okanjo) {(function (window) { var okanjo = window.okanjo; diff --git a/dist/okanjo-templates.min.js b/dist/okanjo-templates.min.js index e2ccc37..d7f9f19 100644 --- a/dist/okanjo-templates.min.js +++ b/dist/okanjo-templates.min.js @@ -1,4 +1,4 @@ -/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ -/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ !function(o){!function(o){var e=o.okanjo;e.ui.engine.registerCss("adx.block2",'.okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-adx{padding:0}.okanjo-block2.okanjo-adx:after,.okanjo-block2.okanjo-adx:before{content:" ";display:table}.okanjo-block2.okanjo-adx:after{clear:both}.okanjo-block2.okanjo-adx .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-adx .okanjo-adx-container{text-align:center;padding:0}.okanjo-block2.okanjo-adx .okanjo-adx-frame{margin:0}',{id:"okanjo-adx-block2"}),e.ui.engine.registerTemplate("adx.block2",'
',function(o){return o.config=this.config,o.instanceId=this.instanceId,o.metricParams=e.net.request.stringify(this._metricBase),o},{css:["adx.block2","okanjo.block2"]})}(window),function(o){var e=o.okanjo;e.ui.engine.registerCss("articles.block2",".okanjo-block2 .okanjo-article.okanjo-cta-style-button .okanjo-resource-title-container{height:52px}.okanjo-block2 .okanjo-article .okanjo-resource-title-container.modern{height:44px}.okanjo-block2.leaderboard .okanjo-article .okanjo-resource-title-container{margin-top:2px;margin-bottom:4px}",{id:"okanjo-article-block2"}),e.ui.__article_block2='',e.ui.engine.registerTemplate("articles.block2",e.ui.__article_block2,function(o){var a=(this._response||{data:{results:[]}}).data||{results:[]};return o.articles=a.results,o.config=this.config,o.instanceId=this.instanceId,o.metricChannel=this._metricBase.ch,o.metricContext=this._metricBase.cx,o.metricParams=e.net.request.stringify(this._metricBase),this._enforceLayoutOptions(),this._registerCustomBranding(".okanjo-article","button"),o},{css:["articles.block2","okanjo.block2"]})}(window),function(o){var e=o.okanjo;e.ui.engine.registerCss("articles.slab","",{id:"okanjo-article-slab"}),e.ui.engine.registerTemplate("articles.slab",e.ui.__article_block2,function(o){var a=(this._response||{data:{results:[]}}).data||{results:[]};return o.blockClasses=["okanjo-slab"],o.articles=a.results,o.config=this.config,o.instanceId=this.instanceId,o.metricChannel=this._metricBase.ch,o.metricContext=this._metricBase.cx,o.metricParams=e.net.request.stringify(this._metricBase),o.fitImage="okanjo-fit",this._enforceSlabLayoutOptions(),this._registerCustomBranding(".okanjo-article","button"),o},{css:["articles.slab","okanjo.slab","okanjo.block2"]})}(window),function(o){var e=o.okanjo;e.ui.engine.registerCss("okanjo.block2",'.okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2{color:#333;font-size:10px;font-family:inherit}.okanjo-block2:after,.okanjo-block2:before{content:" ";display:table}.okanjo-block2:after{clear:both}.okanjo-block2.theme-newsprint .okanjo-resource-seller-container{font-family:Georgia,serif}.okanjo-block2.theme-newsprint .okanjo-resource-title-container{font:13px/15px Georgia,serif}.okanjo-block2.theme-modern,.okanjo-block2.theme-newsprint .okanjo-resource-buy-button,.okanjo-block2.theme-newsprint .okanjo-resource-cta-button,.okanjo-block2.theme-newsprint .okanjo-resource-price-container{font-family:"Helvetica Neue",Helvetica,Roboto,Arial,sans-serif}.okanjo-block2 .okanjo-ellipses:after{content:"..."}.okanjo-block2 .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2 .okanjo-resource{display:block;float:left;background-color:#fff;box-sizing:content-box;width:148px;border:1px solid #e6e6e6;margin:0 -1px -1px 0}.okanjo-block2 .okanjo-resource:last-child{margin:0}.okanjo-block2 a{display:block;overflow:hidden;color:#333;text-decoration:none;padding:10px}.okanjo-block2 a:hover{color:inherit;text-decoration:none}.okanjo-block2 .okanjo-resource-image-container{float:left;overflow:hidden;text-align:center;vertical-align:middle;width:100%;height:128px;line-height:127px;margin:0 0 3px}.okanjo-block2 .okanjo-resource-image{max-width:100%;max-height:100%;border:none;vertical-align:middle}.okanjo-block2 .okanjo-resource-info-container{float:left;height:auto;width:100%}.okanjo-block2 .okanjo-resource-publisher-container,.okanjo-block2 .okanjo-resource-seller-container{color:#999;font-size:11px;line-height:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource-title-container{overflow:hidden;margin-top:3px;margin-bottom:4px;font-weight:700;font-size:12px;line-height:14px;height:45px;word-wrap:break-word}.okanjo-block2 .okanjo-resource-title-container span{display:inline-block}.lt-ie8.okanjo-block2 .okanjo-resource-title-container span{display:inline;zoom:1}.okanjo-block2 .okanjo-resource-price-container{font-size:15px;line-height:1;margin-bottom:5px}.okanjo-block2 .okanjo-resource-buy-button,.okanjo-block2 .okanjo-resource-cta-button{color:#09f;font-size:12px;line-height:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource.list{width:298px;height:122px}.okanjo-block2 .okanjo-resource.list a{padding:11px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-title-container{margin-top:4px;margin-bottom:6px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px;margin:0 11px 0 0}.okanjo-block2 .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-title-container{height:30px}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button{display:block;text-align:center;line-height:26px;padding:0 8px;border:1px solid #09f;border-radius:2px;transition:50ms ease}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:hover,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:hover{background:#09f;color:#fff}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:active,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:active{box-shadow:inset 0 3px 10px rgba(0,0,0,.15)}.okanjo-block2.medium_rectangle{width:300px;height:250px;overflow:hidden}.okanjo-block2.medium_rectangle .okanjo-resource{width:148px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource:first-child{width:149px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource.list{width:298px;height:123px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child{height:124px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child a{padding-top:12px}.okanjo-block2.leaderboard{width:728px;height:90px;overflow:hidden}.okanjo-block2.leaderboard .okanjo-resource{width:241px;height:88px}.okanjo-block2.leaderboard .okanjo-resource:first-child{width:242px}.okanjo-block2.leaderboard .okanjo-resource a{padding:7px}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-image-container{width:74px;height:74px;line-height:1px;margin:0 7px 0 0}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:11px;line-height:13px;height:26px;margin-top:1px;margin-bottom:4px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-price-container{margin-bottom:3px}.okanjo-block2.leaderboard.theme-newsprint .okanjo-resource-title-container{font:700 11px/13px Georgia,serif}.okanjo-block2.half_page{width:300px;height:600px;overflow:hidden}.okanjo-block2.half_page .okanjo-resource{height:118px}.okanjo-block2.half_page .okanjo-resource:nth-last-child(n+2){height:119px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-image-container{width:96px;height:96px}.okanjo-block2.large_mobile_banner{width:320px;height:100px;overflow:hidden}.okanjo-block2.large_mobile_banner .okanjo-resource{width:318px;height:98px}.okanjo-block2.large_mobile_banner .okanjo-resource a{padding:6px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-image-container{width:86px;height:86px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-title-container{height:30px}.okanjo-block2.billboard{width:970px;height:250px;overflow:hidden}.okanjo-block2.billboard .okanjo-resource{width:160px;height:248px}.okanjo-block2.billboard .okanjo-resource:first-child{width:163px;height:248px}.okanjo-block2.billboard .okanjo-resource.list{width:322px;height:123px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.auto{font-size:1em;width:100%}.okanjo-block2.auto .okanjo-resource{width:100%;height:auto;border-left:none;border-right:none}.okanjo-block2.auto .okanjo-resource a{max-width:500px;width:95%;margin:0 auto;padding:2.5%}.okanjo-block2.auto .okanjo-resource.list{height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-image-container{width:18%;height:auto;line-height:1px}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none;margin-left:21%;width:79%}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-publisher-container,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-seller-container{height:auto;font-size:12px;line-height:1.2}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-price-container{height:auto;font-size:15px;line-height:1.5}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-title-container{font-size:15px;line-height:1.4;height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-cta-button{display:inline-block;font-size:14px;line-height:1.8;margin-bottom:-1.7%}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-price-container{line-height:1.3}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-title-container{line-height:1.25}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-cta-button{font-size:13px}.okanjo-inline-buy-frame{display:block;height:100%;width:100%}',{id:"okanjo-block2"})}(window),function(o){var e=o.okanjo;e.ui.engine.registerCss("okanjo.core","",{id:"okanjo-core"}),e.ui.engine.registerCss("okanjo.modal",'.okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}html.okanjo-modal-active{overflow:hidden!important}html.okanjo-modal-active body{overflow:hidden!important;margin:0}.okanjo-modal-margin-fix{margin-right:15px!important}.okanjo-modal-container{position:fixed;top:0;right:0;left:0;bottom:0;z-index:2147483647;background-color:rgba(0,0,0,.65);transition-duration:210ms;transition-property:background-color}.okanjo-modal-container.lt-ie9{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNiWAoAAK4AqL41IDIAAAAASUVORK5CYII=)}.okanjo-modal-container.okanjo-modal-fade-out{background-color:rgba(0,0,0,0)}.okanjo-modal-container.okanjo-modal-fade-out .okanjo-modal-window{opacity:0;transform:scale(.95,.95) translateY(50px)}.okanjo-modal-container.okanjo-modal-hidden{display:none!important}.okanjo-modal-container .okanjo-modal-window{position:relative;max-width:900px;width:90%;background:0 0;margin:56px auto 40px;opacity:1;transform:scale(1,1) translateY(0);transition-duration:210ms;transition-timing-function:cubic-bezier(.13,.025,.15,1);transition-timing-function:cubic-bezier(.13,.025,.15,1.15);transition-property:opacity}.okanjo-modal-container .okanjo-modal-window:after,.okanjo-modal-container .okanjo-modal-window:before{content:" ";display:table}.okanjo-modal-container .okanjo-modal-window:after{clear:both}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header{padding-top:5px;padding-bottom:5px;border-bottom:1px solid #d7d7d7}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header img{height:50px;width:auto}.okanjo-modal-container .okanjo-modal-window-skin{width:auto;height:auto;box-shadow:0 10px 25px rgba(0,0,0,.5);position:absolute;background:#fff;border-radius:4px;top:0;bottom:0;left:0;right:0}.okanjo-modal-container .okanjo-modal-window-outer{position:absolute;top:15px;left:15px;bottom:15px;right:15px;vertical-align:top}.okanjo-modal-container .okanjo-modal-window-inner{position:relative;width:100%;height:100%;-webkit-overflow-scrolling:touch;overflow:auto}.okanjo-modal-container .okanjo-modal-window-inner iframe{height:100%;width:100%;margin-right:-15px}.okanjo-modal-container .okanjo-modal-close-button{color:#fff;cursor:pointer;position:absolute;right:0;top:-48px;text-align:right;font-size:40px;line-height:1em;overflow:visible;width:40px;height:40px}',{id:"okanjo-modal"}),e.ui.engine.registerTemplate("okanjo.error",'{{ message }} {{#code}} Reference: {{ code }} {{/code}}',{css:["okanjo.core"]})}(window),function(o){var e=o.okanjo;e.ui.engine.registerCss("okanjo.slab",".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab img.okanjo-fit{height:100%;width:100%;object-fit:cover}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.list .okanjo-resource-title-container{height:95px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource{width:298px}.okanjo-block2.okanjo-slab .okanjo-resource-publisher-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab .okanjo-resource-title-container{height:58px;font-size:16px;line-height:19px}.okanjo-block2.okanjo-slab .okanjo-resource.list .okanjo-resource-title-container{font-size:14px;height:60px}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource-title-container{font:16px/19px Georgia,serif}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource.list .okanjo-resource-title-container{font-size:15px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource-list{display:flex;flex-wrap:wrap;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource{width:inherit;flex-grow:1;flex-shrink:0;flex-basis:33.3333%;flex-basis:200px;display:flex;align-items:center;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list{flex-basis:33.3333%;flex-basis:250px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list a{width:100%}.okanjo-block2.okanjo-slab.responsive .okanjo-resource:last-child{margin:0 -1px -1px 0}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource,.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource:first-child{width:298px;height:248px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:13px;line-height:15px;height:50px;margin-top:1px;margin-bottom:4px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard.theme-newsprint .okanjo-resource .okanjo-resource-title-container{font:700 13px/15px Georgia,serif}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource-title-container{height:80px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource{width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:nth-last-child(n+2){width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:first-child{height:299px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-image-container{width:100%;height:180px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-title-container{margin-bottom:3px;height:77px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource-title-container{height:57px;margin-bottom:8px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource-title-container{height:116px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource{width:298px;height:198px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:nth-last-child(n+2){width:298px;height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:first-child{height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-image-container{width:100%;height:136px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-title-container{height:42px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource,.okanjo-block2.okanjo-slab.billboard .okanjo-resource:first-child{width:322px;height:248px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-info-container{margin-left:111px;width:auto}",{id:"okanjo-slab"})}(window),function(o){var e=o.okanjo;e.ui.engine.registerCss("products.block2","",{id:"okanjo-product-block2"}),e.ui.__product_block2='',e.ui.engine.registerTemplate("products.block2",e.ui.__product_block2,function(o){var a=(this._response||{data:{results:[]}}).data||{results:[]};return o.products=a.results,o.config=this.config,o.instanceId=this.instanceId,o.metricChannel=this._metricBase.ch,o.metricContext=this._metricBase.cx,o.metricParams=e.net.request.stringify(this._metricBase),this._enforceLayoutOptions(),this._registerCustomBranding(".okanjo-product","buy-button"),o},{css:["products.block2","okanjo.block2","okanjo.modal"]})}(window),function(o){var e=o.okanjo;e.ui.engine.registerCss("products.slab",".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:14px;height:40px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:30px;font-size:12px;line-height:14px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button.theme-newsprint .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:13px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:0;height:32px;font-size:14px}.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:47px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;font-size:14px;line-height:16px;margin-bottom:2px}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:50px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;margin-bottom:0;line-height:15px;font-size:15px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:33px;font-size:15px;line-height:15px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-button-container,.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-price-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:auto;margin-bottom:2px;line-height:20px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-price-container{margin-bottom:0}.okanjo-block2.okanjo-slab.auto.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-price-container{margin-bottom:3px}",{id:"okanjo-product-slab"}),e.ui.engine.registerTemplate("products.slab",e.ui.__product_block2,function(o){var a=(this._response||{data:{results:[]}}).data||{results:[]};return o.blockClasses=["okanjo-slab"],o.products=a.results,o.config=this.config,o.instanceId=this.instanceId,o.metricChannel=this._metricBase.ch,o.metricContext=this._metricBase.cx,o.metricParams=e.net.request.stringify(this._metricBase),o.fitImage="okanjo-fit",this._enforceSlabLayoutOptions(),this._registerCustomBranding(".okanjo-product","button"),o},{css:["products.slab","okanjo.slab","okanjo.block2"]})}(window)}(okanjo); //# sourceMappingURL=okanjo-templates.min.js.map diff --git a/dist/okanjo-templates.min.js.map b/dist/okanjo-templates.min.js.map index e1101e0..5f79ddb 100644 --- a/dist/okanjo-templates.min.js.map +++ b/dist/okanjo-templates.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["okanjo-templates.js","adx.block2.js","articles.block2.js","articles.slab.js","okanjo.block2.js","okanjo.core.js","okanjo.slab.js","products.block2.js","products.slab.js"],"names":["okanjo","window","engine","registerCss","ui","id","registerTemplate","model","instanceId","config","metricParams","this","net","request","stringify","_metricBase","css","__article_block2","data","articles","results","metricChannel","metricContext","cx","_enforceLayoutOptions","_registerCustomBranding","blockClasses","fitImage","_enforceSlabLayoutOptions","__product_block2","products"],"mappings":"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","file":"okanjo-templates.min.js","sourcesContent":["/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */\n(function(okanjo) {(function (window) {\n\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"adx.block2\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-adx{padding:0}.okanjo-block2.okanjo-adx:after,.okanjo-block2.okanjo-adx:before{content:\\\" \\\";display:table}.okanjo-block2.okanjo-adx:after{clear:both}.okanjo-block2.okanjo-adx .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-adx .okanjo-adx-container{text-align:center;padding:0}.okanjo-block2.okanjo-adx .okanjo-adx-frame{margin:0}\", { id: 'okanjo-adx-block2' });\n\n okanjo.ui.engine.registerTemplate(\"adx.block2\", \"
\", function (model) {\n\n // Attach required properties\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n return model;\n }, {\n css: ['adx.block2', 'okanjo.block2']\n });\n})(window);\n(function (window) {\n\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"articles.block2\", \".okanjo-block2 .okanjo-article.okanjo-cta-style-button .okanjo-resource-title-container{height:52px}.okanjo-block2 .okanjo-article .okanjo-resource-title-container.modern{height:44px}.okanjo-block2.leaderboard .okanjo-article .okanjo-resource-title-container{margin-top:2px;margin-bottom:4px}\", { id: 'okanjo-article-block2' });\n\n okanjo.ui.__article_block2 = \"\";\n\n okanjo.ui.engine.registerTemplate(\"articles.block2\", okanjo.ui.__article_block2, function (model) {\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.articles = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n // Enforce format restrictions\n this._enforceLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-article', 'button');\n\n return model;\n }, {\n css: [/*'okanjo.core',*/'articles.block2', 'okanjo.block2' /*, 'okanjo.modal'*/]\n });\n})(window);\n(function (window) {\n\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"articles.slab\", \"\", { id: 'okanjo-article-slab' });\n\n // Reuses block2 markup layout, extended css\n okanjo.ui.engine.registerTemplate(\"articles.slab\", okanjo.ui.__article_block2, function (model) {\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.blockClasses = ['okanjo-slab'];\n model.articles = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n model.fitImage = 'okanjo-fit';\n\n // Enforce format restrictions\n // this._enforceLayoutOptions();\n this._enforceSlabLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-article', 'button');\n\n return model;\n }, {\n css: ['articles.slab', 'okanjo.slab', 'okanjo.block2']\n });\n})(window);\n(function (window) {\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.block2\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2{color:#333;font-size:10px;font-family:inherit}.okanjo-block2:after,.okanjo-block2:before{content:\\\" \\\";display:table}.okanjo-block2:after{clear:both}.okanjo-block2.theme-newsprint .okanjo-resource-seller-container{font-family:Georgia,serif}.okanjo-block2.theme-newsprint .okanjo-resource-title-container{font:13px/15px Georgia,serif}.okanjo-block2.theme-modern,.okanjo-block2.theme-newsprint .okanjo-resource-buy-button,.okanjo-block2.theme-newsprint .okanjo-resource-cta-button,.okanjo-block2.theme-newsprint .okanjo-resource-price-container{font-family:\\\"Helvetica Neue\\\",Helvetica,Roboto,Arial,sans-serif}.okanjo-block2 .okanjo-ellipses:after{content:\\\"...\\\"}.okanjo-block2 .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2 .okanjo-resource{display:block;float:left;background-color:#fff;box-sizing:content-box;width:148px;border:1px solid #e6e6e6;margin:0 -1px -1px 0}.okanjo-block2 .okanjo-resource:last-child{margin:0}.okanjo-block2 a{display:block;overflow:hidden;color:#333;text-decoration:none;padding:10px}.okanjo-block2 a:hover{color:inherit;text-decoration:none}.okanjo-block2 .okanjo-resource-image-container{float:left;overflow:hidden;text-align:center;vertical-align:middle;width:100%;height:128px;line-height:127px;margin:0 0 3px}.okanjo-block2 .okanjo-resource-image{max-width:100%;max-height:100%;border:none;vertical-align:middle}.okanjo-block2 .okanjo-resource-info-container{float:left;height:auto;width:100%}.okanjo-block2 .okanjo-resource-publisher-container,.okanjo-block2 .okanjo-resource-seller-container{color:#999;font-size:11px;line-height:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource-title-container{overflow:hidden;margin-top:3px;margin-bottom:4px;font-weight:700;font-size:12px;line-height:14px;height:45px;word-wrap:break-word}.okanjo-block2 .okanjo-resource-title-container span{display:inline-block}.lt-ie8.okanjo-block2 .okanjo-resource-title-container span{display:inline;zoom:1}.okanjo-block2 .okanjo-resource-price-container{font-size:15px;line-height:1;margin-bottom:5px}.okanjo-block2 .okanjo-resource-buy-button,.okanjo-block2 .okanjo-resource-cta-button{color:#09f;font-size:12px;line-height:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource.list{width:298px;height:122px}.okanjo-block2 .okanjo-resource.list a{padding:11px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-title-container{margin-top:4px;margin-bottom:6px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px;margin:0 11px 0 0}.okanjo-block2 .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-title-container{height:30px}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button{display:block;text-align:center;line-height:26px;padding:0 8px;border:1px solid #09f;border-radius:2px;transition:50ms ease}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:hover,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:hover{background:#09f;color:#fff}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:active,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:active{box-shadow:inset 0 3px 10px rgba(0,0,0,.15)}.okanjo-block2.medium_rectangle{width:300px;height:250px;overflow:hidden}.okanjo-block2.medium_rectangle .okanjo-resource{width:148px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource:first-child{width:149px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource.list{width:298px;height:123px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child{height:124px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child a{padding-top:12px}.okanjo-block2.leaderboard{width:728px;height:90px;overflow:hidden}.okanjo-block2.leaderboard .okanjo-resource{width:241px;height:88px}.okanjo-block2.leaderboard .okanjo-resource:first-child{width:242px}.okanjo-block2.leaderboard .okanjo-resource a{padding:7px}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-image-container{width:74px;height:74px;line-height:1px;margin:0 7px 0 0}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:11px;line-height:13px;height:26px;margin-top:1px;margin-bottom:4px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-price-container{margin-bottom:3px}.okanjo-block2.leaderboard.theme-newsprint .okanjo-resource-title-container{font:700 11px/13px Georgia,serif}.okanjo-block2.half_page{width:300px;height:600px;overflow:hidden}.okanjo-block2.half_page .okanjo-resource{height:118px}.okanjo-block2.half_page .okanjo-resource:nth-last-child(n+2){height:119px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-image-container{width:96px;height:96px}.okanjo-block2.large_mobile_banner{width:320px;height:100px;overflow:hidden}.okanjo-block2.large_mobile_banner .okanjo-resource{width:318px;height:98px}.okanjo-block2.large_mobile_banner .okanjo-resource a{padding:6px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-image-container{width:86px;height:86px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-title-container{height:30px}.okanjo-block2.billboard{width:970px;height:250px;overflow:hidden}.okanjo-block2.billboard .okanjo-resource{width:160px;height:248px}.okanjo-block2.billboard .okanjo-resource:first-child{width:163px;height:248px}.okanjo-block2.billboard .okanjo-resource.list{width:322px;height:123px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.auto{font-size:1em;width:100%}.okanjo-block2.auto .okanjo-resource{width:100%;height:auto;border-left:none;border-right:none}.okanjo-block2.auto .okanjo-resource a{max-width:500px;width:95%;margin:0 auto;padding:2.5%}.okanjo-block2.auto .okanjo-resource.list{height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-image-container{width:18%;height:auto;line-height:1px}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none;margin-left:21%;width:79%}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-publisher-container,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-seller-container{height:auto;font-size:12px;line-height:1.2}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-price-container{height:auto;font-size:15px;line-height:1.5}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-title-container{font-size:15px;line-height:1.4;height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-cta-button{display:inline-block;font-size:14px;line-height:1.8;margin-bottom:-1.7%}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-price-container{line-height:1.3}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-title-container{line-height:1.25}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-cta-button{font-size:13px}.okanjo-inline-buy-frame{display:block;height:100%;width:100%}\", { id: 'okanjo-block2' });\n})(window);\n(function (window) {\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.core\", \"\", { id: 'okanjo-core' });\n okanjo.ui.engine.registerCss(\"okanjo.modal\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}html.okanjo-modal-active{overflow:hidden!important}html.okanjo-modal-active body{overflow:hidden!important;margin:0}.okanjo-modal-margin-fix{margin-right:15px!important}.okanjo-modal-container{position:fixed;top:0;right:0;left:0;bottom:0;z-index:2147483647;background-color:rgba(0,0,0,.65);transition-duration:210ms;transition-property:background-color}.okanjo-modal-container.lt-ie9{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNiWAoAAK4AqL41IDIAAAAASUVORK5CYII=)}.okanjo-modal-container.okanjo-modal-fade-out{background-color:rgba(0,0,0,0)}.okanjo-modal-container.okanjo-modal-fade-out .okanjo-modal-window{opacity:0;transform:scale(.95,.95) translateY(50px)}.okanjo-modal-container.okanjo-modal-hidden{display:none!important}.okanjo-modal-container .okanjo-modal-window{position:relative;max-width:900px;width:90%;background:0 0;margin:56px auto 40px;opacity:1;transform:scale(1,1) translateY(0);transition-duration:210ms;transition-timing-function:cubic-bezier(.13,.025,.15,1);transition-timing-function:cubic-bezier(.13,.025,.15,1.15);transition-property:opacity}.okanjo-modal-container .okanjo-modal-window:after,.okanjo-modal-container .okanjo-modal-window:before{content:\\\" \\\";display:table}.okanjo-modal-container .okanjo-modal-window:after{clear:both}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header{padding-top:5px;padding-bottom:5px;border-bottom:1px solid #d7d7d7}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header img{height:50px;width:auto}.okanjo-modal-container .okanjo-modal-window-skin{width:auto;height:auto;box-shadow:0 10px 25px rgba(0,0,0,.5);position:absolute;background:#fff;border-radius:4px;top:0;bottom:0;left:0;right:0}.okanjo-modal-container .okanjo-modal-window-outer{position:absolute;top:15px;left:15px;bottom:15px;right:15px;vertical-align:top}.okanjo-modal-container .okanjo-modal-window-inner{position:relative;width:100%;height:100%;-webkit-overflow-scrolling:touch;overflow:auto}.okanjo-modal-container .okanjo-modal-window-inner iframe{height:100%;width:100%;margin-right:-15px}.okanjo-modal-container .okanjo-modal-close-button{color:#fff;cursor:pointer;position:absolute;right:0;top:-48px;text-align:right;font-size:40px;line-height:1em;overflow:visible;width:40px;height:40px}\", { id: 'okanjo-modal' });\n\n okanjo.ui.engine.registerTemplate(\"okanjo.error\", \"{{ message }} {{#code}} Reference: {{ code }} {{/code}}\", { css: ['okanjo.core'] });\n})(window);\n(function (window) {\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.slab\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab img.okanjo-fit{height:100%;width:100%;object-fit:cover}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.list .okanjo-resource-title-container{height:95px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource{width:298px}.okanjo-block2.okanjo-slab .okanjo-resource-publisher-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab .okanjo-resource-title-container{height:58px;font-size:16px;line-height:19px}.okanjo-block2.okanjo-slab .okanjo-resource.list .okanjo-resource-title-container{font-size:14px;height:60px}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource-title-container{font:16px/19px Georgia,serif}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource.list .okanjo-resource-title-container{font-size:15px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource-list{display:flex;flex-wrap:wrap;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource{width:inherit;flex-grow:1;flex-shrink:0;flex-basis:33.3333%;flex-basis:200px;display:flex;align-items:center;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list{flex-basis:33.3333%;flex-basis:250px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list a{width:100%}.okanjo-block2.okanjo-slab.responsive .okanjo-resource:last-child{margin:0 -1px -1px 0}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource,.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource:first-child{width:298px;height:248px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:13px;line-height:15px;height:50px;margin-top:1px;margin-bottom:4px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard.theme-newsprint .okanjo-resource .okanjo-resource-title-container{font:700 13px/15px Georgia,serif}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource-title-container{height:80px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource{width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:nth-last-child(n+2){width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:first-child{height:299px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-image-container{width:100%;height:180px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-title-container{margin-bottom:3px;height:77px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource-title-container{height:57px;margin-bottom:8px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource-title-container{height:116px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource{width:298px;height:198px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:nth-last-child(n+2){width:298px;height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:first-child{height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-image-container{width:100%;height:136px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-title-container{height:42px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource,.okanjo-block2.okanjo-slab.billboard .okanjo-resource:first-child{width:322px;height:248px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-info-container{margin-left:111px;width:auto}\", { id: 'okanjo-slab' });\n})(window);\n(function (window) {\n\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"products.block2\", \"\", { id: 'okanjo-product-block2' });\n\n okanjo.ui.__product_block2 = \"\";\n\n okanjo.ui.engine.registerTemplate(\"products.block2\", okanjo.ui.__product_block2, function (model) {\n\n // Attach placement properties\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.products = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n // Enforce format restrictions\n this._enforceLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-product', 'buy-button');\n\n return model;\n }, {\n css: [/*'okanjo.core',*/'products.block2', 'okanjo.block2', 'okanjo.modal']\n });\n})(window);\n(function (window) {\n\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"products.slab\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:14px;height:40px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:30px;font-size:12px;line-height:14px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button.theme-newsprint .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:13px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:0;height:32px;font-size:14px}.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:47px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;font-size:14px;line-height:16px;margin-bottom:2px}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:50px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;margin-bottom:0;line-height:15px;font-size:15px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:33px;font-size:15px;line-height:15px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-button-container,.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-price-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:auto;margin-bottom:2px;line-height:20px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-price-container{margin-bottom:0}.okanjo-block2.okanjo-slab.auto.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-price-container{margin-bottom:3px}\", { id: 'okanjo-product-slab' });\n\n // Reuses block2 markup layout, extended css\n okanjo.ui.engine.registerTemplate(\"products.slab\", okanjo.ui.__product_block2, function (model) {\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.blockClasses = ['okanjo-slab'];\n model.products = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n model.fitImage = 'okanjo-fit';\n\n // Enforce format restrictions\n // this._enforceLayoutOptions();\n this._enforceSlabLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-product', 'button');\n\n return model;\n }, {\n css: ['products.slab', 'okanjo.slab', 'okanjo.block2']\n });\n})(window);})(okanjo);","(function(window) {\n\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"adx.block2\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-adx{padding:0}.okanjo-block2.okanjo-adx:after,.okanjo-block2.okanjo-adx:before{content:\\\" \\\";display:table}.okanjo-block2.okanjo-adx:after{clear:both}.okanjo-block2.okanjo-adx .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-adx .okanjo-adx-container{text-align:center;padding:0}.okanjo-block2.okanjo-adx .okanjo-adx-frame{margin:0}\", {id: 'okanjo-adx-block2'});\n\n okanjo.ui.engine.registerTemplate(\"adx.block2\", \"
\", function (model) {\n\n // Attach required properties\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n return model;\n }, {\n css: ['adx.block2','okanjo.block2']\n });\n\n})(window);","(function(window) {\n\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"articles.block2\", \".okanjo-block2 .okanjo-article.okanjo-cta-style-button .okanjo-resource-title-container{height:52px}.okanjo-block2 .okanjo-article .okanjo-resource-title-container.modern{height:44px}.okanjo-block2.leaderboard .okanjo-article .okanjo-resource-title-container{margin-top:2px;margin-bottom:4px}\", {id: 'okanjo-article-block2'});\n\n okanjo.ui.__article_block2 = \"\";\n\n okanjo.ui.engine.registerTemplate(\"articles.block2\", okanjo.ui.__article_block2, function (model) {\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.articles = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n // Enforce format restrictions\n this._enforceLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-article', 'button');\n\n return model;\n }, {\n css: [/*'okanjo.core',*/ 'articles.block2', 'okanjo.block2' /*, 'okanjo.modal'*/]\n });\n\n})(window);","(function(window) {\n\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"articles.slab\", \"\", {id: 'okanjo-article-slab'});\n\n // Reuses block2 markup layout, extended css\n okanjo.ui.engine.registerTemplate(\"articles.slab\", okanjo.ui.__article_block2, function (model) {\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.blockClasses = ['okanjo-slab'];\n model.articles = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n model.fitImage = 'okanjo-fit';\n\n // Enforce format restrictions\n // this._enforceLayoutOptions();\n this._enforceSlabLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-article', 'button');\n\n return model;\n }, {\n css: [ 'articles.slab', 'okanjo.slab', 'okanjo.block2' ]\n });\n\n})(window);","(function(window) {\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.block2\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2{color:#333;font-size:10px;font-family:inherit}.okanjo-block2:after,.okanjo-block2:before{content:\\\" \\\";display:table}.okanjo-block2:after{clear:both}.okanjo-block2.theme-newsprint .okanjo-resource-seller-container{font-family:Georgia,serif}.okanjo-block2.theme-newsprint .okanjo-resource-title-container{font:13px/15px Georgia,serif}.okanjo-block2.theme-modern,.okanjo-block2.theme-newsprint .okanjo-resource-buy-button,.okanjo-block2.theme-newsprint .okanjo-resource-cta-button,.okanjo-block2.theme-newsprint .okanjo-resource-price-container{font-family:\\\"Helvetica Neue\\\",Helvetica,Roboto,Arial,sans-serif}.okanjo-block2 .okanjo-ellipses:after{content:\\\"...\\\"}.okanjo-block2 .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2 .okanjo-resource{display:block;float:left;background-color:#fff;box-sizing:content-box;width:148px;border:1px solid #e6e6e6;margin:0 -1px -1px 0}.okanjo-block2 .okanjo-resource:last-child{margin:0}.okanjo-block2 a{display:block;overflow:hidden;color:#333;text-decoration:none;padding:10px}.okanjo-block2 a:hover{color:inherit;text-decoration:none}.okanjo-block2 .okanjo-resource-image-container{float:left;overflow:hidden;text-align:center;vertical-align:middle;width:100%;height:128px;line-height:127px;margin:0 0 3px}.okanjo-block2 .okanjo-resource-image{max-width:100%;max-height:100%;border:none;vertical-align:middle}.okanjo-block2 .okanjo-resource-info-container{float:left;height:auto;width:100%}.okanjo-block2 .okanjo-resource-publisher-container,.okanjo-block2 .okanjo-resource-seller-container{color:#999;font-size:11px;line-height:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource-title-container{overflow:hidden;margin-top:3px;margin-bottom:4px;font-weight:700;font-size:12px;line-height:14px;height:45px;word-wrap:break-word}.okanjo-block2 .okanjo-resource-title-container span{display:inline-block}.lt-ie8.okanjo-block2 .okanjo-resource-title-container span{display:inline;zoom:1}.okanjo-block2 .okanjo-resource-price-container{font-size:15px;line-height:1;margin-bottom:5px}.okanjo-block2 .okanjo-resource-buy-button,.okanjo-block2 .okanjo-resource-cta-button{color:#09f;font-size:12px;line-height:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource.list{width:298px;height:122px}.okanjo-block2 .okanjo-resource.list a{padding:11px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-title-container{margin-top:4px;margin-bottom:6px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px;margin:0 11px 0 0}.okanjo-block2 .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-title-container{height:30px}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button{display:block;text-align:center;line-height:26px;padding:0 8px;border:1px solid #09f;border-radius:2px;transition:50ms ease}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:hover,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:hover{background:#09f;color:#fff}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:active,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:active{box-shadow:inset 0 3px 10px rgba(0,0,0,.15)}.okanjo-block2.medium_rectangle{width:300px;height:250px;overflow:hidden}.okanjo-block2.medium_rectangle .okanjo-resource{width:148px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource:first-child{width:149px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource.list{width:298px;height:123px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child{height:124px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child a{padding-top:12px}.okanjo-block2.leaderboard{width:728px;height:90px;overflow:hidden}.okanjo-block2.leaderboard .okanjo-resource{width:241px;height:88px}.okanjo-block2.leaderboard .okanjo-resource:first-child{width:242px}.okanjo-block2.leaderboard .okanjo-resource a{padding:7px}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-image-container{width:74px;height:74px;line-height:1px;margin:0 7px 0 0}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:11px;line-height:13px;height:26px;margin-top:1px;margin-bottom:4px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-price-container{margin-bottom:3px}.okanjo-block2.leaderboard.theme-newsprint .okanjo-resource-title-container{font:700 11px/13px Georgia,serif}.okanjo-block2.half_page{width:300px;height:600px;overflow:hidden}.okanjo-block2.half_page .okanjo-resource{height:118px}.okanjo-block2.half_page .okanjo-resource:nth-last-child(n+2){height:119px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-image-container{width:96px;height:96px}.okanjo-block2.large_mobile_banner{width:320px;height:100px;overflow:hidden}.okanjo-block2.large_mobile_banner .okanjo-resource{width:318px;height:98px}.okanjo-block2.large_mobile_banner .okanjo-resource a{padding:6px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-image-container{width:86px;height:86px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-title-container{height:30px}.okanjo-block2.billboard{width:970px;height:250px;overflow:hidden}.okanjo-block2.billboard .okanjo-resource{width:160px;height:248px}.okanjo-block2.billboard .okanjo-resource:first-child{width:163px;height:248px}.okanjo-block2.billboard .okanjo-resource.list{width:322px;height:123px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.auto{font-size:1em;width:100%}.okanjo-block2.auto .okanjo-resource{width:100%;height:auto;border-left:none;border-right:none}.okanjo-block2.auto .okanjo-resource a{max-width:500px;width:95%;margin:0 auto;padding:2.5%}.okanjo-block2.auto .okanjo-resource.list{height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-image-container{width:18%;height:auto;line-height:1px}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none;margin-left:21%;width:79%}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-publisher-container,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-seller-container{height:auto;font-size:12px;line-height:1.2}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-price-container{height:auto;font-size:15px;line-height:1.5}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-title-container{font-size:15px;line-height:1.4;height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-cta-button{display:inline-block;font-size:14px;line-height:1.8;margin-bottom:-1.7%}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-price-container{line-height:1.3}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-title-container{line-height:1.25}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-cta-button{font-size:13px}.okanjo-inline-buy-frame{display:block;height:100%;width:100%}\", {id: 'okanjo-block2'});\n})(window);","(function(window) {\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.core\", \"\", {id: 'okanjo-core'});\n okanjo.ui.engine.registerCss(\"okanjo.modal\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}html.okanjo-modal-active{overflow:hidden!important}html.okanjo-modal-active body{overflow:hidden!important;margin:0}.okanjo-modal-margin-fix{margin-right:15px!important}.okanjo-modal-container{position:fixed;top:0;right:0;left:0;bottom:0;z-index:2147483647;background-color:rgba(0,0,0,.65);transition-duration:210ms;transition-property:background-color}.okanjo-modal-container.lt-ie9{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNiWAoAAK4AqL41IDIAAAAASUVORK5CYII=)}.okanjo-modal-container.okanjo-modal-fade-out{background-color:rgba(0,0,0,0)}.okanjo-modal-container.okanjo-modal-fade-out .okanjo-modal-window{opacity:0;transform:scale(.95,.95) translateY(50px)}.okanjo-modal-container.okanjo-modal-hidden{display:none!important}.okanjo-modal-container .okanjo-modal-window{position:relative;max-width:900px;width:90%;background:0 0;margin:56px auto 40px;opacity:1;transform:scale(1,1) translateY(0);transition-duration:210ms;transition-timing-function:cubic-bezier(.13,.025,.15,1);transition-timing-function:cubic-bezier(.13,.025,.15,1.15);transition-property:opacity}.okanjo-modal-container .okanjo-modal-window:after,.okanjo-modal-container .okanjo-modal-window:before{content:\\\" \\\";display:table}.okanjo-modal-container .okanjo-modal-window:after{clear:both}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header{padding-top:5px;padding-bottom:5px;border-bottom:1px solid #d7d7d7}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header img{height:50px;width:auto}.okanjo-modal-container .okanjo-modal-window-skin{width:auto;height:auto;box-shadow:0 10px 25px rgba(0,0,0,.5);position:absolute;background:#fff;border-radius:4px;top:0;bottom:0;left:0;right:0}.okanjo-modal-container .okanjo-modal-window-outer{position:absolute;top:15px;left:15px;bottom:15px;right:15px;vertical-align:top}.okanjo-modal-container .okanjo-modal-window-inner{position:relative;width:100%;height:100%;-webkit-overflow-scrolling:touch;overflow:auto}.okanjo-modal-container .okanjo-modal-window-inner iframe{height:100%;width:100%;margin-right:-15px}.okanjo-modal-container .okanjo-modal-close-button{color:#fff;cursor:pointer;position:absolute;right:0;top:-48px;text-align:right;font-size:40px;line-height:1em;overflow:visible;width:40px;height:40px}\", {id: 'okanjo-modal'});\n\n okanjo.ui.engine.registerTemplate(\"okanjo.error\", \"{{ message }} {{#code}} Reference: {{ code }} {{/code}}\", {css: ['okanjo.core']});\n})(window);","(function(window) {\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.slab\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab img.okanjo-fit{height:100%;width:100%;object-fit:cover}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.list .okanjo-resource-title-container{height:95px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource{width:298px}.okanjo-block2.okanjo-slab .okanjo-resource-publisher-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab .okanjo-resource-title-container{height:58px;font-size:16px;line-height:19px}.okanjo-block2.okanjo-slab .okanjo-resource.list .okanjo-resource-title-container{font-size:14px;height:60px}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource-title-container{font:16px/19px Georgia,serif}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource.list .okanjo-resource-title-container{font-size:15px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource-list{display:flex;flex-wrap:wrap;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource{width:inherit;flex-grow:1;flex-shrink:0;flex-basis:33.3333%;flex-basis:200px;display:flex;align-items:center;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list{flex-basis:33.3333%;flex-basis:250px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list a{width:100%}.okanjo-block2.okanjo-slab.responsive .okanjo-resource:last-child{margin:0 -1px -1px 0}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource,.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource:first-child{width:298px;height:248px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:13px;line-height:15px;height:50px;margin-top:1px;margin-bottom:4px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard.theme-newsprint .okanjo-resource .okanjo-resource-title-container{font:700 13px/15px Georgia,serif}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource-title-container{height:80px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource{width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:nth-last-child(n+2){width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:first-child{height:299px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-image-container{width:100%;height:180px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-title-container{margin-bottom:3px;height:77px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource-title-container{height:57px;margin-bottom:8px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource-title-container{height:116px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource{width:298px;height:198px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:nth-last-child(n+2){width:298px;height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:first-child{height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-image-container{width:100%;height:136px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-title-container{height:42px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource,.okanjo-block2.okanjo-slab.billboard .okanjo-resource:first-child{width:322px;height:248px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-info-container{margin-left:111px;width:auto}\", {id: 'okanjo-slab'});\n})(window);","(function(window){\n\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"products.block2\", \"\", { id: 'okanjo-product-block2' });\n\n okanjo.ui.__product_block2 = \"\";\n\n okanjo.ui.engine.registerTemplate(\"products.block2\", okanjo.ui.__product_block2, function(model) {\n\n // Attach placement properties\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.products = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n // Enforce format restrictions\n this._enforceLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-product', 'buy-button');\n\n return model;\n }, {\n css: [ /*'okanjo.core',*/ 'products.block2', 'okanjo.block2', 'okanjo.modal']\n });\n})(window);","(function(window) {\n\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"products.slab\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:14px;height:40px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:30px;font-size:12px;line-height:14px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button.theme-newsprint .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:13px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:0;height:32px;font-size:14px}.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:47px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;font-size:14px;line-height:16px;margin-bottom:2px}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:50px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;margin-bottom:0;line-height:15px;font-size:15px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:33px;font-size:15px;line-height:15px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-button-container,.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-price-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:auto;margin-bottom:2px;line-height:20px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-price-container{margin-bottom:0}.okanjo-block2.okanjo-slab.auto.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-price-container{margin-bottom:3px}\", {id: 'okanjo-product-slab'});\n\n // Reuses block2 markup layout, extended css\n okanjo.ui.engine.registerTemplate(\"products.slab\", okanjo.ui.__product_block2, function (model) {\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.blockClasses = ['okanjo-slab'];\n model.products = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n model.fitImage = 'okanjo-fit';\n\n // Enforce format restrictions\n // this._enforceLayoutOptions();\n this._enforceSlabLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-product', 'button');\n\n return model;\n }, {\n css: [ 'products.slab', 'okanjo.slab', 'okanjo.block2' ]\n });\n\n})(window);"],"sourceRoot":"./"} \ No newline at end of file +{"version":3,"sources":["okanjo-templates.js","adx.block2.js","articles.block2.js","articles.slab.js","okanjo.block2.js","okanjo.core.js","okanjo.slab.js","products.block2.js","products.slab.js"],"names":["okanjo","window","engine","registerCss","ui","id","registerTemplate","model","instanceId","config","metricParams","this","net","request","stringify","_metricBase","css","__article_block2","data","articles","results","metricChannel","metricContext","cx","_enforceLayoutOptions","_registerCustomBranding","blockClasses","fitImage","_enforceSlabLayoutOptions","__product_block2","products"],"mappings":"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","file":"okanjo-templates.min.js","sourcesContent":["/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */\n(function(okanjo) {(function (window) {\n\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"adx.block2\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-adx{padding:0}.okanjo-block2.okanjo-adx:after,.okanjo-block2.okanjo-adx:before{content:\\\" \\\";display:table}.okanjo-block2.okanjo-adx:after{clear:both}.okanjo-block2.okanjo-adx .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-adx .okanjo-adx-container{text-align:center;padding:0}.okanjo-block2.okanjo-adx .okanjo-adx-frame{margin:0}\", { id: 'okanjo-adx-block2' });\n\n okanjo.ui.engine.registerTemplate(\"adx.block2\", \"
\", function (model) {\n\n // Attach required properties\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n return model;\n }, {\n css: ['adx.block2', 'okanjo.block2']\n });\n})(window);\n(function (window) {\n\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"articles.block2\", \".okanjo-block2 .okanjo-article.okanjo-cta-style-button .okanjo-resource-title-container{height:52px}.okanjo-block2 .okanjo-article .okanjo-resource-title-container.modern{height:44px}.okanjo-block2.leaderboard .okanjo-article .okanjo-resource-title-container{margin-top:2px;margin-bottom:4px}\", { id: 'okanjo-article-block2' });\n\n okanjo.ui.__article_block2 = \"\";\n\n okanjo.ui.engine.registerTemplate(\"articles.block2\", okanjo.ui.__article_block2, function (model) {\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.articles = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n // Enforce format restrictions\n this._enforceLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-article', 'button');\n\n return model;\n }, {\n css: [/*'okanjo.core',*/'articles.block2', 'okanjo.block2' /*, 'okanjo.modal'*/]\n });\n})(window);\n(function (window) {\n\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"articles.slab\", \"\", { id: 'okanjo-article-slab' });\n\n // Reuses block2 markup layout, extended css\n okanjo.ui.engine.registerTemplate(\"articles.slab\", okanjo.ui.__article_block2, function (model) {\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.blockClasses = ['okanjo-slab'];\n model.articles = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n model.fitImage = 'okanjo-fit';\n\n // Enforce format restrictions\n // this._enforceLayoutOptions();\n this._enforceSlabLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-article', 'button');\n\n return model;\n }, {\n css: ['articles.slab', 'okanjo.slab', 'okanjo.block2']\n });\n})(window);\n(function (window) {\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.block2\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2{color:#333;font-size:10px;font-family:inherit}.okanjo-block2:after,.okanjo-block2:before{content:\\\" \\\";display:table}.okanjo-block2:after{clear:both}.okanjo-block2.theme-newsprint .okanjo-resource-seller-container{font-family:Georgia,serif}.okanjo-block2.theme-newsprint .okanjo-resource-title-container{font:13px/15px Georgia,serif}.okanjo-block2.theme-modern,.okanjo-block2.theme-newsprint .okanjo-resource-buy-button,.okanjo-block2.theme-newsprint .okanjo-resource-cta-button,.okanjo-block2.theme-newsprint .okanjo-resource-price-container{font-family:\\\"Helvetica Neue\\\",Helvetica,Roboto,Arial,sans-serif}.okanjo-block2 .okanjo-ellipses:after{content:\\\"...\\\"}.okanjo-block2 .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2 .okanjo-resource{display:block;float:left;background-color:#fff;box-sizing:content-box;width:148px;border:1px solid #e6e6e6;margin:0 -1px -1px 0}.okanjo-block2 .okanjo-resource:last-child{margin:0}.okanjo-block2 a{display:block;overflow:hidden;color:#333;text-decoration:none;padding:10px}.okanjo-block2 a:hover{color:inherit;text-decoration:none}.okanjo-block2 .okanjo-resource-image-container{float:left;overflow:hidden;text-align:center;vertical-align:middle;width:100%;height:128px;line-height:127px;margin:0 0 3px}.okanjo-block2 .okanjo-resource-image{max-width:100%;max-height:100%;border:none;vertical-align:middle}.okanjo-block2 .okanjo-resource-info-container{float:left;height:auto;width:100%}.okanjo-block2 .okanjo-resource-publisher-container,.okanjo-block2 .okanjo-resource-seller-container{color:#999;font-size:11px;line-height:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource-title-container{overflow:hidden;margin-top:3px;margin-bottom:4px;font-weight:700;font-size:12px;line-height:14px;height:45px;word-wrap:break-word}.okanjo-block2 .okanjo-resource-title-container span{display:inline-block}.lt-ie8.okanjo-block2 .okanjo-resource-title-container span{display:inline;zoom:1}.okanjo-block2 .okanjo-resource-price-container{font-size:15px;line-height:1;margin-bottom:5px}.okanjo-block2 .okanjo-resource-buy-button,.okanjo-block2 .okanjo-resource-cta-button{color:#09f;font-size:12px;line-height:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource.list{width:298px;height:122px}.okanjo-block2 .okanjo-resource.list a{padding:11px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-title-container{margin-top:4px;margin-bottom:6px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px;margin:0 11px 0 0}.okanjo-block2 .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-title-container{height:30px}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button{display:block;text-align:center;line-height:26px;padding:0 8px;border:1px solid #09f;border-radius:2px;transition:50ms ease}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:hover,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:hover{background:#09f;color:#fff}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:active,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:active{box-shadow:inset 0 3px 10px rgba(0,0,0,.15)}.okanjo-block2.medium_rectangle{width:300px;height:250px;overflow:hidden}.okanjo-block2.medium_rectangle .okanjo-resource{width:148px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource:first-child{width:149px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource.list{width:298px;height:123px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child{height:124px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child a{padding-top:12px}.okanjo-block2.leaderboard{width:728px;height:90px;overflow:hidden}.okanjo-block2.leaderboard .okanjo-resource{width:241px;height:88px}.okanjo-block2.leaderboard .okanjo-resource:first-child{width:242px}.okanjo-block2.leaderboard .okanjo-resource a{padding:7px}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-image-container{width:74px;height:74px;line-height:1px;margin:0 7px 0 0}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:11px;line-height:13px;height:26px;margin-top:1px;margin-bottom:4px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-price-container{margin-bottom:3px}.okanjo-block2.leaderboard.theme-newsprint .okanjo-resource-title-container{font:700 11px/13px Georgia,serif}.okanjo-block2.half_page{width:300px;height:600px;overflow:hidden}.okanjo-block2.half_page .okanjo-resource{height:118px}.okanjo-block2.half_page .okanjo-resource:nth-last-child(n+2){height:119px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-image-container{width:96px;height:96px}.okanjo-block2.large_mobile_banner{width:320px;height:100px;overflow:hidden}.okanjo-block2.large_mobile_banner .okanjo-resource{width:318px;height:98px}.okanjo-block2.large_mobile_banner .okanjo-resource a{padding:6px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-image-container{width:86px;height:86px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-title-container{height:30px}.okanjo-block2.billboard{width:970px;height:250px;overflow:hidden}.okanjo-block2.billboard .okanjo-resource{width:160px;height:248px}.okanjo-block2.billboard .okanjo-resource:first-child{width:163px;height:248px}.okanjo-block2.billboard .okanjo-resource.list{width:322px;height:123px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.auto{font-size:1em;width:100%}.okanjo-block2.auto .okanjo-resource{width:100%;height:auto;border-left:none;border-right:none}.okanjo-block2.auto .okanjo-resource a{max-width:500px;width:95%;margin:0 auto;padding:2.5%}.okanjo-block2.auto .okanjo-resource.list{height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-image-container{width:18%;height:auto;line-height:1px}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none;margin-left:21%;width:79%}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-publisher-container,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-seller-container{height:auto;font-size:12px;line-height:1.2}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-price-container{height:auto;font-size:15px;line-height:1.5}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-title-container{font-size:15px;line-height:1.4;height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-cta-button{display:inline-block;font-size:14px;line-height:1.8;margin-bottom:-1.7%}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-price-container{line-height:1.3}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-title-container{line-height:1.25}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-cta-button{font-size:13px}.okanjo-inline-buy-frame{display:block;height:100%;width:100%}\", { id: 'okanjo-block2' });\n})(window);\n(function (window) {\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.core\", \"\", { id: 'okanjo-core' });\n okanjo.ui.engine.registerCss(\"okanjo.modal\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}html.okanjo-modal-active{overflow:hidden!important}html.okanjo-modal-active body{overflow:hidden!important;margin:0}.okanjo-modal-margin-fix{margin-right:15px!important}.okanjo-modal-container{position:fixed;top:0;right:0;left:0;bottom:0;z-index:2147483647;background-color:rgba(0,0,0,.65);transition-duration:210ms;transition-property:background-color}.okanjo-modal-container.lt-ie9{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNiWAoAAK4AqL41IDIAAAAASUVORK5CYII=)}.okanjo-modal-container.okanjo-modal-fade-out{background-color:rgba(0,0,0,0)}.okanjo-modal-container.okanjo-modal-fade-out .okanjo-modal-window{opacity:0;transform:scale(.95,.95) translateY(50px)}.okanjo-modal-container.okanjo-modal-hidden{display:none!important}.okanjo-modal-container .okanjo-modal-window{position:relative;max-width:900px;width:90%;background:0 0;margin:56px auto 40px;opacity:1;transform:scale(1,1) translateY(0);transition-duration:210ms;transition-timing-function:cubic-bezier(.13,.025,.15,1);transition-timing-function:cubic-bezier(.13,.025,.15,1.15);transition-property:opacity}.okanjo-modal-container .okanjo-modal-window:after,.okanjo-modal-container .okanjo-modal-window:before{content:\\\" \\\";display:table}.okanjo-modal-container .okanjo-modal-window:after{clear:both}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header{padding-top:5px;padding-bottom:5px;border-bottom:1px solid #d7d7d7}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header img{height:50px;width:auto}.okanjo-modal-container .okanjo-modal-window-skin{width:auto;height:auto;box-shadow:0 10px 25px rgba(0,0,0,.5);position:absolute;background:#fff;border-radius:4px;top:0;bottom:0;left:0;right:0}.okanjo-modal-container .okanjo-modal-window-outer{position:absolute;top:15px;left:15px;bottom:15px;right:15px;vertical-align:top}.okanjo-modal-container .okanjo-modal-window-inner{position:relative;width:100%;height:100%;-webkit-overflow-scrolling:touch;overflow:auto}.okanjo-modal-container .okanjo-modal-window-inner iframe{height:100%;width:100%;margin-right:-15px}.okanjo-modal-container .okanjo-modal-close-button{color:#fff;cursor:pointer;position:absolute;right:0;top:-48px;text-align:right;font-size:40px;line-height:1em;overflow:visible;width:40px;height:40px}\", { id: 'okanjo-modal' });\n\n okanjo.ui.engine.registerTemplate(\"okanjo.error\", \"{{ message }} {{#code}} Reference: {{ code }} {{/code}}\", { css: ['okanjo.core'] });\n})(window);\n(function (window) {\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.slab\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab img.okanjo-fit{height:100%;width:100%;object-fit:cover}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.list .okanjo-resource-title-container{height:95px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource{width:298px}.okanjo-block2.okanjo-slab .okanjo-resource-publisher-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab .okanjo-resource-title-container{height:58px;font-size:16px;line-height:19px}.okanjo-block2.okanjo-slab .okanjo-resource.list .okanjo-resource-title-container{font-size:14px;height:60px}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource-title-container{font:16px/19px Georgia,serif}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource.list .okanjo-resource-title-container{font-size:15px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource-list{display:flex;flex-wrap:wrap;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource{width:inherit;flex-grow:1;flex-shrink:0;flex-basis:33.3333%;flex-basis:200px;display:flex;align-items:center;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list{flex-basis:33.3333%;flex-basis:250px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list a{width:100%}.okanjo-block2.okanjo-slab.responsive .okanjo-resource:last-child{margin:0 -1px -1px 0}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource,.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource:first-child{width:298px;height:248px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:13px;line-height:15px;height:50px;margin-top:1px;margin-bottom:4px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard.theme-newsprint .okanjo-resource .okanjo-resource-title-container{font:700 13px/15px Georgia,serif}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource-title-container{height:80px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource{width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:nth-last-child(n+2){width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:first-child{height:299px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-image-container{width:100%;height:180px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-title-container{margin-bottom:3px;height:77px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource-title-container{height:57px;margin-bottom:8px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource-title-container{height:116px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource{width:298px;height:198px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:nth-last-child(n+2){width:298px;height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:first-child{height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-image-container{width:100%;height:136px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-title-container{height:42px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource,.okanjo-block2.okanjo-slab.billboard .okanjo-resource:first-child{width:322px;height:248px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-info-container{margin-left:111px;width:auto}\", { id: 'okanjo-slab' });\n})(window);\n(function (window) {\n\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"products.block2\", \"\", { id: 'okanjo-product-block2' });\n\n okanjo.ui.__product_block2 = \"\";\n\n okanjo.ui.engine.registerTemplate(\"products.block2\", okanjo.ui.__product_block2, function (model) {\n\n // Attach placement properties\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.products = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n // Enforce format restrictions\n this._enforceLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-product', 'buy-button');\n\n return model;\n }, {\n css: [/*'okanjo.core',*/'products.block2', 'okanjo.block2', 'okanjo.modal']\n });\n})(window);\n(function (window) {\n\n var okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"products.slab\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:14px;height:40px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:30px;font-size:12px;line-height:14px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button.theme-newsprint .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:13px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:0;height:32px;font-size:14px}.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:47px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;font-size:14px;line-height:16px;margin-bottom:2px}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:50px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;margin-bottom:0;line-height:15px;font-size:15px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:33px;font-size:15px;line-height:15px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-button-container,.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-price-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:auto;margin-bottom:2px;line-height:20px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-price-container{margin-bottom:0}.okanjo-block2.okanjo-slab.auto.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-price-container{margin-bottom:3px}\", { id: 'okanjo-product-slab' });\n\n // Reuses block2 markup layout, extended css\n okanjo.ui.engine.registerTemplate(\"products.slab\", okanjo.ui.__product_block2, function (model) {\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.blockClasses = ['okanjo-slab'];\n model.products = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n model.fitImage = 'okanjo-fit';\n\n // Enforce format restrictions\n // this._enforceLayoutOptions();\n this._enforceSlabLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-product', 'button');\n\n return model;\n }, {\n css: ['products.slab', 'okanjo.slab', 'okanjo.block2']\n });\n})(window);})(okanjo);","(function(window) {\n\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"adx.block2\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-adx{padding:0}.okanjo-block2.okanjo-adx:after,.okanjo-block2.okanjo-adx:before{content:\\\" \\\";display:table}.okanjo-block2.okanjo-adx:after{clear:both}.okanjo-block2.okanjo-adx .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-adx .okanjo-adx-container{text-align:center;padding:0}.okanjo-block2.okanjo-adx .okanjo-adx-frame{margin:0}\", {id: 'okanjo-adx-block2'});\n\n okanjo.ui.engine.registerTemplate(\"adx.block2\", \"
\", function (model) {\n\n // Attach required properties\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n return model;\n }, {\n css: ['adx.block2','okanjo.block2']\n });\n\n})(window);","(function(window) {\n\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"articles.block2\", \".okanjo-block2 .okanjo-article.okanjo-cta-style-button .okanjo-resource-title-container{height:52px}.okanjo-block2 .okanjo-article .okanjo-resource-title-container.modern{height:44px}.okanjo-block2.leaderboard .okanjo-article .okanjo-resource-title-container{margin-top:2px;margin-bottom:4px}\", {id: 'okanjo-article-block2'});\n\n okanjo.ui.__article_block2 = \"\";\n\n okanjo.ui.engine.registerTemplate(\"articles.block2\", okanjo.ui.__article_block2, function (model) {\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.articles = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n // Enforce format restrictions\n this._enforceLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-article', 'button');\n\n return model;\n }, {\n css: [/*'okanjo.core',*/ 'articles.block2', 'okanjo.block2' /*, 'okanjo.modal'*/]\n });\n\n})(window);","(function(window) {\n\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"articles.slab\", \"\", {id: 'okanjo-article-slab'});\n\n // Reuses block2 markup layout, extended css\n okanjo.ui.engine.registerTemplate(\"articles.slab\", okanjo.ui.__article_block2, function (model) {\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.blockClasses = ['okanjo-slab'];\n model.articles = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n model.fitImage = 'okanjo-fit';\n\n // Enforce format restrictions\n // this._enforceLayoutOptions();\n this._enforceSlabLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-article', 'button');\n\n return model;\n }, {\n css: [ 'articles.slab', 'okanjo.slab', 'okanjo.block2' ]\n });\n\n})(window);","(function(window) {\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.block2\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2{color:#333;font-size:10px;font-family:inherit}.okanjo-block2:after,.okanjo-block2:before{content:\\\" \\\";display:table}.okanjo-block2:after{clear:both}.okanjo-block2.theme-newsprint .okanjo-resource-seller-container{font-family:Georgia,serif}.okanjo-block2.theme-newsprint .okanjo-resource-title-container{font:13px/15px Georgia,serif}.okanjo-block2.theme-modern,.okanjo-block2.theme-newsprint .okanjo-resource-buy-button,.okanjo-block2.theme-newsprint .okanjo-resource-cta-button,.okanjo-block2.theme-newsprint .okanjo-resource-price-container{font-family:\\\"Helvetica Neue\\\",Helvetica,Roboto,Arial,sans-serif}.okanjo-block2 .okanjo-ellipses:after{content:\\\"...\\\"}.okanjo-block2 .okanjo-visually-hidden{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2 .okanjo-resource{display:block;float:left;background-color:#fff;box-sizing:content-box;width:148px;border:1px solid #e6e6e6;margin:0 -1px -1px 0}.okanjo-block2 .okanjo-resource:last-child{margin:0}.okanjo-block2 a{display:block;overflow:hidden;color:#333;text-decoration:none;padding:10px}.okanjo-block2 a:hover{color:inherit;text-decoration:none}.okanjo-block2 .okanjo-resource-image-container{float:left;overflow:hidden;text-align:center;vertical-align:middle;width:100%;height:128px;line-height:127px;margin:0 0 3px}.okanjo-block2 .okanjo-resource-image{max-width:100%;max-height:100%;border:none;vertical-align:middle}.okanjo-block2 .okanjo-resource-info-container{float:left;height:auto;width:100%}.okanjo-block2 .okanjo-resource-publisher-container,.okanjo-block2 .okanjo-resource-seller-container{color:#999;font-size:11px;line-height:12px;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource-title-container{overflow:hidden;margin-top:3px;margin-bottom:4px;font-weight:700;font-size:12px;line-height:14px;height:45px;word-wrap:break-word}.okanjo-block2 .okanjo-resource-title-container span{display:inline-block}.lt-ie8.okanjo-block2 .okanjo-resource-title-container span{display:inline;zoom:1}.okanjo-block2 .okanjo-resource-price-container{font-size:15px;line-height:1;margin-bottom:5px}.okanjo-block2 .okanjo-resource-buy-button,.okanjo-block2 .okanjo-resource-cta-button{color:#09f;font-size:12px;line-height:13px;font-weight:700;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.okanjo-block2 .okanjo-resource.list{width:298px;height:122px}.okanjo-block2 .okanjo-resource.list a{padding:11px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-title-container{margin-top:4px;margin-bottom:6px}.okanjo-block2 .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px;margin:0 11px 0 0}.okanjo-block2 .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-title-container{height:30px}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button{display:block;text-align:center;line-height:26px;padding:0 8px;border:1px solid #09f;border-radius:2px;transition:50ms ease}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:hover,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:hover{background:#09f;color:#fff}.okanjo-block2.okanjo-cta-style-button .okanjo-resource-buy-button:active,.okanjo-block2.okanjo-cta-style-button .okanjo-resource-cta-button:active{box-shadow:inset 0 3px 10px rgba(0,0,0,.15)}.okanjo-block2.medium_rectangle{width:300px;height:250px;overflow:hidden}.okanjo-block2.medium_rectangle .okanjo-resource{width:148px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource:first-child{width:149px;height:248px}.okanjo-block2.medium_rectangle .okanjo-resource.list{width:298px;height:123px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.medium_rectangle .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child{height:124px}.okanjo-block2.medium_rectangle .okanjo-resource.list:first-child a{padding-top:12px}.okanjo-block2.leaderboard{width:728px;height:90px;overflow:hidden}.okanjo-block2.leaderboard .okanjo-resource{width:241px;height:88px}.okanjo-block2.leaderboard .okanjo-resource:first-child{width:242px}.okanjo-block2.leaderboard .okanjo-resource a{padding:7px}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-image-container{width:74px;height:74px;line-height:1px;margin:0 7px 0 0}.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:11px;line-height:13px;height:26px;margin-top:1px;margin-bottom:4px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.leaderboard .okanjo-resource .okanjo-resource-price-container{margin-bottom:3px}.okanjo-block2.leaderboard.theme-newsprint .okanjo-resource-title-container{font:700 11px/13px Georgia,serif}.okanjo-block2.half_page{width:300px;height:600px;overflow:hidden}.okanjo-block2.half_page .okanjo-resource{height:118px}.okanjo-block2.half_page .okanjo-resource:nth-last-child(n+2){height:119px}.okanjo-block2.half_page .okanjo-resource .okanjo-resource-image-container{width:96px;height:96px}.okanjo-block2.large_mobile_banner{width:320px;height:100px;overflow:hidden}.okanjo-block2.large_mobile_banner .okanjo-resource{width:318px;height:98px}.okanjo-block2.large_mobile_banner .okanjo-resource a{padding:6px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-image-container{width:86px;height:86px}.okanjo-block2.large_mobile_banner .okanjo-resource .okanjo-resource-title-container{height:30px}.okanjo-block2.billboard{width:970px;height:250px;overflow:hidden}.okanjo-block2.billboard .okanjo-resource{width:160px;height:248px}.okanjo-block2.billboard .okanjo-resource:first-child{width:163px;height:248px}.okanjo-block2.billboard .okanjo-resource.list{width:322px;height:123px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px;line-height:1px}.okanjo-block2.billboard .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:left;width:165px}.okanjo-block2.auto{font-size:1em;width:100%}.okanjo-block2.auto .okanjo-resource{width:100%;height:auto;border-left:none;border-right:none}.okanjo-block2.auto .okanjo-resource a{max-width:500px;width:95%;margin:0 auto;padding:2.5%}.okanjo-block2.auto .okanjo-resource.list{height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-image-container{width:18%;height:auto;line-height:1px}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-info-container{height:auto;float:none;margin-left:21%;width:79%}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-publisher-container,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-seller-container{height:auto;font-size:12px;line-height:1.2}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-price-container{height:auto;font-size:15px;line-height:1.5}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-title-container{font-size:15px;line-height:1.4;height:auto}.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto .okanjo-resource.list .okanjo-resource-cta-button{display:inline-block;font-size:14px;line-height:1.8;margin-bottom:-1.7%}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-price-container{line-height:1.3}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-title-container{line-height:1.25}.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-buy-button,.okanjo-block2.auto.okanjo-cta-style-button .okanjo-resource.list .okanjo-resource-cta-button{font-size:13px}.okanjo-inline-buy-frame{display:block;height:100%;width:100%}\", {id: 'okanjo-block2'});\n})(window);","(function(window) {\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.core\", \"\", {id: 'okanjo-core'});\n okanjo.ui.engine.registerCss(\"okanjo.modal\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}html.okanjo-modal-active{overflow:hidden!important}html.okanjo-modal-active body{overflow:hidden!important;margin:0}.okanjo-modal-margin-fix{margin-right:15px!important}.okanjo-modal-container{position:fixed;top:0;right:0;left:0;bottom:0;z-index:2147483647;background-color:rgba(0,0,0,.65);transition-duration:210ms;transition-property:background-color}.okanjo-modal-container.lt-ie9{background-image:url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVR4nGNiWAoAAK4AqL41IDIAAAAASUVORK5CYII=)}.okanjo-modal-container.okanjo-modal-fade-out{background-color:rgba(0,0,0,0)}.okanjo-modal-container.okanjo-modal-fade-out .okanjo-modal-window{opacity:0;transform:scale(.95,.95) translateY(50px)}.okanjo-modal-container.okanjo-modal-hidden{display:none!important}.okanjo-modal-container .okanjo-modal-window{position:relative;max-width:900px;width:90%;background:0 0;margin:56px auto 40px;opacity:1;transform:scale(1,1) translateY(0);transition-duration:210ms;transition-timing-function:cubic-bezier(.13,.025,.15,1);transition-timing-function:cubic-bezier(.13,.025,.15,1.15);transition-property:opacity}.okanjo-modal-container .okanjo-modal-window:after,.okanjo-modal-container .okanjo-modal-window:before{content:\\\" \\\";display:table}.okanjo-modal-container .okanjo-modal-window:after{clear:both}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header{padding-top:5px;padding-bottom:5px;border-bottom:1px solid #d7d7d7}.okanjo-modal-container .okanjo-modal-window .okanjo-modal-header img{height:50px;width:auto}.okanjo-modal-container .okanjo-modal-window-skin{width:auto;height:auto;box-shadow:0 10px 25px rgba(0,0,0,.5);position:absolute;background:#fff;border-radius:4px;top:0;bottom:0;left:0;right:0}.okanjo-modal-container .okanjo-modal-window-outer{position:absolute;top:15px;left:15px;bottom:15px;right:15px;vertical-align:top}.okanjo-modal-container .okanjo-modal-window-inner{position:relative;width:100%;height:100%;-webkit-overflow-scrolling:touch;overflow:auto}.okanjo-modal-container .okanjo-modal-window-inner iframe{height:100%;width:100%;margin-right:-15px}.okanjo-modal-container .okanjo-modal-close-button{color:#fff;cursor:pointer;position:absolute;right:0;top:-48px;text-align:right;font-size:40px;line-height:1em;overflow:visible;width:40px;height:40px}\", {id: 'okanjo-modal'});\n\n okanjo.ui.engine.registerTemplate(\"okanjo.error\", \"{{ message }} {{#code}} Reference: {{ code }} {{/code}}\", {css: ['okanjo.core']});\n})(window);","(function(window) {\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"okanjo.slab\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab img.okanjo-fit{height:100%;width:100%;object-fit:cover}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.list .okanjo-resource-title-container{height:95px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource{width:298px}.okanjo-block2.okanjo-slab .okanjo-resource-publisher-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab .okanjo-resource-title-container{height:58px;font-size:16px;line-height:19px}.okanjo-block2.okanjo-slab .okanjo-resource.list .okanjo-resource-title-container{font-size:14px;height:60px}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource-title-container{font:16px/19px Georgia,serif}.okanjo-block2.okanjo-slab.theme-newsprint .okanjo-resource.list .okanjo-resource-title-container{font-size:15px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource-list{display:flex;flex-wrap:wrap;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource{width:inherit;flex-grow:1;flex-shrink:0;flex-basis:33.3333%;flex-basis:200px;display:flex;align-items:center;justify-content:center}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list{flex-basis:33.3333%;flex-basis:250px}.okanjo-block2.okanjo-slab.responsive .okanjo-resource.list a{width:100%}.okanjo-block2.okanjo-slab.responsive .okanjo-resource:last-child{margin:0 -1px -1px 0}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource,.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource:first-child{width:298px;height:248px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource .okanjo-resource-title-container{font-size:13px;line-height:15px;height:50px;margin-top:1px;margin-bottom:4px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource .okanjo-resource-title-container,.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.leaderboard.theme-newsprint .okanjo-resource .okanjo-resource-title-container{font:700 13px/15px Georgia,serif}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource-title-container{height:80px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource{width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:nth-last-child(n+2){width:298px;height:298px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource:first-child{height:299px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-image-container{width:100%;height:180px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource .okanjo-resource-title-container{margin-bottom:3px;height:77px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource-title-container{height:57px;margin-bottom:8px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource-title-container{height:116px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource{width:298px;height:198px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:nth-last-child(n+2){width:298px;height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource:first-child{height:199px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-button-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-image-container{width:100%;height:136px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource .okanjo-resource-title-container{height:42px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource,.okanjo-block2.okanjo-slab.billboard .okanjo-resource:first-child{width:322px;height:248px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-title-container{height:40px;margin-bottom:8px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource .okanjo-resource-image-container{height:155px}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-image-container{width:100px;height:100px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.list .okanjo-resource-info-container{margin-left:111px;width:auto}\", {id: 'okanjo-slab'});\n})(window);","(function(window){\n\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"products.block2\", \"\", { id: 'okanjo-product-block2' });\n\n okanjo.ui.__product_block2 = \"\";\n\n okanjo.ui.engine.registerTemplate(\"products.block2\", okanjo.ui.__product_block2, function(model) {\n\n // Attach placement properties\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.products = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n\n // Enforce format restrictions\n this._enforceLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-product', 'buy-button');\n\n return model;\n }, {\n css: [ /*'okanjo.core',*/ 'products.block2', 'okanjo.block2', 'okanjo.modal']\n });\n})(window);","(function(window) {\n\n const okanjo = window.okanjo;\n okanjo.ui.engine.registerCss(\"products.slab\", \".okanjo-expansion-root{position:relative}.okanjo-expansion-root iframe.okanjo-ad-in-unit{position:absolute;top:0;left:0;right:0;bottom:0;z-index:1}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:14px;height:40px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:30px;font-size:12px;line-height:14px}.okanjo-block2.okanjo-slab.okanjo-cta-style-button.theme-newsprint .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{font-size:13px}.okanjo-block2.okanjo-slab.okanjo-cta-style-none .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.medium_rectangle .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.medium_rectangle.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.leaderboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:0;height:32px;font-size:14px}.okanjo-block2.okanjo-slab.leaderboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:47px}.okanjo-block2.okanjo-slab.large_mobile_banner .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;font-size:14px;line-height:16px;margin-bottom:2px}.okanjo-block2.okanjo-slab.large_mobile_banner.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:50px}.okanjo-block2.okanjo-slab.half_page .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:34px;margin-bottom:0;line-height:15px;font-size:15px}.okanjo-block2.okanjo-slab.half_page.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:60px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:33px;font-size:15px;line-height:15px}.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-button-container,.okanjo-block2.okanjo-slab.half_page.dense .okanjo-resource.okanjo-product .okanjo-resource-price-container{border:0;clip:rect(0 0 0 0);height:1px;margin:-1px;overflow:hidden;padding:0;position:absolute;width:1px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-title-container{margin-bottom:4px;margin-top:2px}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-price-container{display:inline-block}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container{display:inline-block;margin-left:10px;font-size:15px;line-height:1}.okanjo-block2.okanjo-slab.billboard .okanjo-resource.okanjo-product .okanjo-resource-button-container .okanjo-resource-buy-button{font-size:14px;overflow:inherit}.okanjo-block2.okanjo-slab.billboard.okanjo-cta-style-none .okanjo-resource.okanjo-product .okanjo-resource-title-container{height:40px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-title-container{height:auto;margin-bottom:2px;line-height:20px}.okanjo-block2.okanjo-slab.auto .okanjo-resource.okanjo-product.list .okanjo-resource-price-container{margin-bottom:0}.okanjo-block2.okanjo-slab.auto.okanjo-cta-style-button .okanjo-resource.okanjo-product .okanjo-resource-price-container{margin-bottom:3px}\", {id: 'okanjo-product-slab'});\n\n // Reuses block2 markup layout, extended css\n okanjo.ui.engine.registerTemplate(\"products.slab\", okanjo.ui.__product_block2, function (model) {\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n model.blockClasses = ['okanjo-slab'];\n model.products = data.results;\n model.config = this.config;\n model.instanceId = this.instanceId;\n model.metricChannel = this._metricBase.ch;\n model.metricContext = this._metricBase.cx;\n model.metricParams = okanjo.net.request.stringify(this._metricBase);\n model.fitImage = 'okanjo-fit';\n\n // Enforce format restrictions\n // this._enforceLayoutOptions();\n this._enforceSlabLayoutOptions();\n\n // Add branding if necessary\n this._registerCustomBranding('.okanjo-product', 'button');\n\n return model;\n }, {\n css: [ 'products.slab', 'okanjo.slab', 'okanjo.block2' ]\n });\n\n})(window);"],"sourceRoot":"./"} \ No newline at end of file diff --git a/dist/okanjo.js b/dist/okanjo.js index 1449614..1eae78a 100644 --- a/dist/okanjo.js +++ b/dist/okanjo.js @@ -1,4 +1,4 @@ -/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ (function(root, factory) { if (typeof define === 'function' && define.amd) { define([], factory); @@ -323,7 +323,7 @@ var okanjo = function (window, document) { /** * Okanjo version */ - version: "1.19.1", + version: "1.20.0", /** * Placeholder @@ -3207,6 +3207,7 @@ var okanjo = function (window, document) { // Functional settings key: string().strip(), // don't need to resend key on all our requests no_init: bool().strip(), // don't automatically load the placement, do it manually (e.g. (new Placement({no_init:true})).init() + no_css: bool().strip(), // don't automatically include stylesheets proxy_url: string().strip(), expandable: bool().strip().default(true), disable_inline_buy: bool().strip().default(false), // stops inline buy functionality @@ -3793,8 +3794,12 @@ var okanjo = function (window, document) { offer._index = index; }); + var model = { + css: !this.config.no_css + }; + // Render and display the results - this.setMarkup(okanjo.ui.engine.render(templateName, this)); + this.setMarkup(okanjo.ui.engine.render(templateName, this, model)); // Track widget impression if (data.results.length === 0) { @@ -3995,8 +4000,12 @@ var okanjo = function (window, document) { article._index = index; }); + var model = { + css: !this.config.no_css + }; + // Render and display the results - this.setMarkup(okanjo.ui.engine.render(templateName, this)); + this.setMarkup(okanjo.ui.engine.render(templateName, this, model)); // Track widget impression if (data.results.length === 0) { @@ -4129,6 +4138,7 @@ var okanjo = function (window, document) { // Pass along what the template needs to know to display the ad var renderContext = { + css: !this.config.no_css, size: size, adUnitPath: adUnitPath }; diff --git a/dist/okanjo.min.js b/dist/okanjo.min.js index 4f6a889..fad735d 100644 --- a/dist/okanjo.min.js +++ b/dist/okanjo.min.js @@ -1,7 +1,7 @@ -/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ -!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.okanjo=t()}(this,function(){function e(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function t(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var i=function(){function e(e,t){for(var n=0;n0?1:-1)*Math.floor(Math.abs(t)):t},i=Math.pow(2,53)-1,r=function(e){var t=n(e);return Math.min(Math.max(t,0),i)};return function(e){var n=this,i=Object(e);if(null==e)throw new TypeError("Array.from requires an array-like object - not null or undefined");var o,a=arguments.length>1?arguments[1]:void 0;if("undefined"!=typeof a){if(!t(a))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(o=arguments[2])}for(var s,u=r(i.length),c=t(n)?Object(new n(u)):new Array(u),l=0;l>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var i=arguments[1],r=0;r>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var i=arguments[1],r=0;r>>0;if(0===r)return!1;for(var o=0|t,a=Math.max(o>=0?o:r-Math.abs(o),0);a=0&&t.splice(o,1)}c.error("[Okanjo v"+d.version+"]: "+i.stack),t.length&&c.error.apply(c,["Additional information:"].concat(t))},warn:function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),i=1;i1&&void 0!==arguments[1]?arguments[1]:{},n={};return void 0!==e&&null!==e&&Object.keys(e).forEach(function(i){if(e[i]instanceof Date)t.dateToIso?n[i]=e[i].toISOString():n[i]=e[i];else if("object"===r(e[i])&&null!==e[i])if(Array.isArray(e[i])&&t.ignoreArrays===!0)n[i]=e[i];else if(Array.isArray(e[i])&&t.arrayToCsv===!0)n[i]=e[i].join(",");else{var o=d.util.flatten(e[i],t);Object.keys(o).forEach(function(e){n[i+"_"+e]=o[e]})}else n[i]=e[i]}),n},d.util.shortid=function(t){var n="ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC",i=e.crypto||e.msCrypto||"function"==typeof require&&require("crypto"),r=function(){if(i&&i.randomBytes)return 48&i.randomBytes(1)[0];if(!i||!i.getRandomValues)return 48&Math.floor(256*Math.random());var e=new Uint8Array(1);return i.getRandomValues(e),48&e[0]},o=function(e){for(var t=0,i=void 0,o="";!i;)o+=n[e>>4*t&15|r()],i=e0&&(e+=o(u)),e+=o(n)}}(),d.util.getLocation=function(){return e.location!==e.parent.location?t.referrer:t.location.href},d.ui={getScrollPosition:function(){return{x:n?e.pageXOffset:i?t.documentElement.scrollLeft:t.body.scrollLeft,y:n?e.pageYOffset:i?t.documentElement.scrollTop:t.body.scrollTop}},getElementSize:function(t,n){var i={height:t.offsetHeight,width:t.offsetWidth},r=t.currentStyle||e.getComputedStyle(t);return n&&(i.height+=parseInt(r.marginTop)+parseInt(r.marginBottom),i.width+=parseInt(r.marginLeft)+parseInt(r.marginRight)),i},getPageSize:function(){var e=t.querySelector("body"),n=t.documentElement;return{w:Math.max(e.scrollWidth,e.offsetWidth,n.clientWidth,n.scrollWidth,n.offsetWidth),h:Math.max(e.scrollHeight,e.offsetHeight,n.clientHeight,n.scrollHeight,n.offsetHeight)}},getViewportSize:function(){var n=i?t.documentElement:t.body,r=n.clientWidth,o=n.clientHeight,a=e.innerWidth||0,s=e.innerHeight||0,u=a&&r>a||s&&o>s;return{vw:u?a:r,vh:u?s:o}},getEventPosition:function(e){var n=e.pageX,i=e.pageY,r=t.body,o=t.documentElement,a="scrollLeft",s="scrollTop",u=e.__proto__.constructor.name;return{et:u,ex:void 0===n?e.clientX+r[a]+o[a]:n,ey:void 0===i?e.clientY+r[s]+o[s]:i}},getElementPosition:function(e){var n="Could not get position of element. Did you attach the element to the DOM before initializing?";try{var i=e.getBoundingClientRect(),r=t.body.getBoundingClientRect();return t.body.contains(e)||d.report(n,e),{x1:i.left-r.left,y1:i.top-r.top,x2:i.right-r.left,y2:i.bottom-r.top}}catch(o){return d.report(n,{exception:o,element:e}),{x1:0,y1:0,x2:0,y2:0,err:1}}},_getIntersection:function(e,t,n){var i=Math.max(e.x1,t.x),r=Math.min(e.x2,t.x+n.vw),o=Math.max(e.y1,t.y),a=Math.min(e.y2,t.y+n.vh),s=Math.max(0,r-i)*Math.max(0,a-o),u=(e.x2-e.x1)*(e.y2-e.y1);return{intersectionArea:s,elementArea:u}},isElementVisible:function(e){return e.offsetWidth>0&&e.offsetHeight>0},getPercentageInViewport:function(e){var t=d.ui.getElementPosition(e),n=d.ui.getScrollPosition(),i=d.ui.getViewportSize();if(t.err)return 0;var r=d.ui._getIntersection(t,n,i),o=r.intersectionArea,a=r.elementArea;return a<=0?0:o/a}},d.ui.ellipsify=function(e,n){for(var i=n||e.parentNode,r=d.ui.getElementSize(i).height,o=void 0!==e.textContent,s=o?e.textContent:e.innerText,u="",c=5e3,l=function(e){return u=e.substr(0,e.length-3)+u,"..."};d.ui.getElementSize(e).height>r&&s.length>0&&c-- >0;)s=o?e.textContent:e.innerText,s=s.replace(a,l),o?e.textContent=s:e.innerText=s;if(u.length>0){var h=t.createElement("span"),f=t.createElement("span");h.setAttribute("class","okanjo-ellipses"),f.setAttribute("class","okanjo-visually-hidden"),o?(h.textContent=s.substr(0,s.length-3),f.textContent=u):(h.innerText=s.substr(0,s.length-3),f.innerText=u),e.innerHTML="",e.appendChild(h),e.appendChild(f)}},d.ui.fitImages=function(e){"objectFit"in t.documentElement.style==!1&&e.querySelectorAll("img.okanjo-fit").forEach(function(e){e.style.display="none";var t=e.parentNode;t.style.backgroundSize="cover",t.style.backgroundImage="url("+e.src+")",t.style.backgroundposition="center center"})},e.okanjo=d}(window,document);return function(e){var t=/^application\/json/,n=e.okanjo;n.net.request=function(i,r,o,a){"function"==typeof o&&(a=o,o=void 0);var s=new(e.XMLHttpRequest||e.ActiveXObject)("MSXML2.XMLHTTP.3.0"),u=!1,c=function(e,t){u||(u=!0,a(e,t))};n.net.request.timeout&&(s.timeout=n.net.request.timeout),s.ontimeout=function(e){c({statusCode:504,error:"Request timed out",message:"Something went wrong",attributes:{event:e,xhr:s}})},s.onreadystatechange=function(e){if(4===s.readyState)if(s.status>0){var n=void 0;n=t.test(s.getResponseHeader("Content-Type"))?JSON.parse(s.responseText):{statusCode:s.status,data:s.responseText},s.status>=200&&s.status<300?c(null,n):c(n)}else c({statusCode:503,error:"Request failed",message:"Something went wrong",attributes:{event:e,xhr:s}})},s.open(i.toUpperCase(),r),s.withCredentials=!0,["POST","PUT","PATCH"].includes(i.toUpperCase())&&(s.setRequestHeader("Content-Type","application/json; charset=utf-8"),void 0!==o&&(o=JSON.stringify(o))),s.send(o||void 0)},n.net.request.get=n.net.request.bind(this,"GET"),n.net.request.post=n.net.request.bind(this,"POST"),n.net.request.put=n.net.request.bind(this,"PUT"),n.net.request["delete"]=n.net.request.bind(this,"DELETE");var i=function(e){return null===e||void 0===e?"":encodeURIComponent(""+e)},o=function(e,t){return t?t+"["+i(e)+"]":i(e)};n.net.request.stringify=function(e,t){var a=[];return t=t||"",Object.keys(e).forEach(function(s){var u=e[s];if(Array.isArray(u))u.forEach(function(e){return a.push(o(s,t)+"="+i(e))});else if("object"===("undefined"==typeof u?"undefined":r(u))&&null!==u){var c=n.net.request.stringify(u,o(s,t));c&&a.push(c)}else void 0!==u&&a.push(o(s,t)+"="+i(u))}),a.join("&")}}(window),function(e,t){e.okanjo.util.cookie={set:function(n,i,r){var o=new Date;o.setDate(o.getDate()+r);var a=r?" Expires="+o.toUTCString()+";":"",s=" Path=/",u="https:"===e.location.protocol?" Secure;":"",c=encodeURI(i)+";"+a+u+" SameSite=None;"+s;t.cookie=n+"="+c},get:function(e){var n=null;return t.cookie.split(";").find(function(t){var i=t.substr(0,t.indexOf("=")).trim(),r=t.substr(t.indexOf("=")+1);return i===e&&(n=decodeURI(r),!0)}),n}}}(window,document),function(e,t){var o=e.okanjo,a=function(){function e(){n(this,e),this._templates={},this._css={},this.classDetects=""}return i(e,[{key:"registerTemplate",value:function(e,t,n,i){if("object"===("undefined"==typeof t?"undefined":r(t))){if(void 0===t.nodeType)throw new Error("Parameter template must be a string or a DOM element");t=t.innerHTML,o.lib.Mustache.parse(t)}else if("string"!=typeof t)throw new Error("Parameter template must be a string or a DOM element");if(3===arguments.length&&"object"===("undefined"==typeof n?"undefined":r(n))?(i=n,n=null):i=i||{},n&&"function"!=typeof n)throw new Error("Parameter beforeRender must be a function");this._templates[e]={markup:t,options:i,beforeRender:n}}},{key:"registerCss",value:function(e,t,n){if(n=n||{},"object"===("undefined"==typeof t?"undefined":r(t))){if(void 0===t.nodeType)throw new Error("Parameter css must be a string or a DOM element")}else if("string"!=typeof t)throw new Error("Parameter css must be a string or a DOM element");this._css[e]={markup:t,options:n}}},{key:"isTemplateRegistered",value:function(e){return!!this._templates[e]}},{key:"isCssRegistered",value:function(e){return!!this._css[e]}},{key:"ensureCss",value:function(e){if(this._css[e]){var n=this._css[e],i=void 0===n.markup.nodeType?n.options.id||"okanjo-css-"+e:null;if(i){var r=t.querySelector("#"+i.replace(/\./g,"\\."));if(!r){var a=t.head,s=t.createElement("style");if(s.id=i,s.setAttribute("type","text/css"),s.hasOwnProperty?s.innerHTML=n.markup:s.styleSheet.cssText=n.markup,a)a.appendChild(s);else{var u=t.body;u?u.appendChild(s):o.report("Cannot add CSS template to document. Does it not have a body or head?")}}}}else o.report('Attempted to add CSS template "'+e+'" to the DOM, however it does not appear to be registered?')}},{key:"render",value:function(e,t,n){var i=this;n=n||{};var r=this._templates[e];return r.beforeRender&&(n=r.beforeRender.call(t,n)),n.okanjo=o,n.okanjoMetricUrl=o.net.endpoint.replace(/^https?:\/\//,""),n.now=function(){return(new Date).getTime()},n.classDetects=this.classDetects,n.blockClasses&&Array.isArray(n.blockClasses)&&(n.classDetects+=" "+n.blockClasses.join(" "),delete n.blockClasses),n.css!==!1&&r.options.css&&r.options.css.length>0&&(r.options.css.forEach(function(e){return i.ensureCss(e)}),delete n.css),o.lib.Mustache.render(r.markup,n)}}]),e}();a.formatCurrency=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:".",i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:",",r=e<0?"-":"",o=parseInt(e=Math.abs(+e||0).toFixed(t))+"",a=o.length;return a=a>3?a%3:0,r+(a?o.substr(0,a)+i:"")+o.substr(a).replace(/(\d{3})(?=\d)/g,"$1"+i)+(t?n+Math.abs(e-o).toFixed(t).slice(2):"")},o.ui.engine=new a}(window,document),function(e,t){var n=e.okanjo,i=n.util.isMobile(),r=!1,o=void 0,a=void 0,s=void 0,u=void 0,c=void 0,l=void 0,d=void 0,h=void 0,f=void 0,p=function(){o=t.documentElement||t.querySelector("html"),a=t.body||t.querySelector("body"),s=t.createElement("div"),u=t.createElement("div"),c=t.createElement("div"),l=t.createElement("div"),d=t.createElement("div"),h=t.createElement("div"),f=t.createElement("iframe"),s.setAttribute("class","okanjo-modal-container okanjo-modal-hidden "),u.setAttribute("class","okanjo-modal-window"),c.setAttribute("class","okanjo-modal-window-skin"),l.setAttribute("class","okanjo-modal-window-outer"),d.setAttribute("class","okanjo-modal-window-inner"),h.setAttribute("class","okanjo-modal-close-button"),f.setAttribute("class","okanjo-inline-buy-frame"),f.setAttribute("frameborder","0"),f.setAttribute("vspace","0"),f.setAttribute("hspace","0"),f.setAttribute("webkitallowfullscreen",""),f.setAttribute("mozallowfullscreen",""),f.setAttribute("allowfullscreen",""),f.setAttribute("scrolling","auto"),h.innerHTML="×",d.appendChild(f),l.appendChild(d),c.appendChild(l),u.appendChild(c),u.appendChild(h),s.appendChild(u),a.appendChild(s)},g=function(e,t,n){e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},m=function(){return e.innerHeight||t.documentElement.clientHeight},v=function(){u.style.height=m()-80+"px"},y=function(){g(e,"orientationchange",function(){for(var e=0;e<2;e++)setTimeout(v,1e3*e+10)}),g(e,"resize",function(){setTimeout(v,100)}),g(s,"click",w),g(u,"click",function(e){e.preventDefault(),e.stopPropagation()}),g(h,"click",function(e){e.preventDefault(),e.stopPropagation(),w()})},_=function(e,t){e.className+=" "+t},b=function(e,t){e.className=e.className.replace(new RegExp(" *?"+t),"")},k=function(){b(s,"okanjo-modal-hidden"),_(s,"okanjo-modal-fade-out"),v(),_(o,"okanjo-modal-active"),i||_(o,"okanjo-modal-margin-fix"),setTimeout(function(){b(s,"okanjo-modal-fade-out")},10)},w=function(){_(s,"okanjo-modal-fade-out"),setTimeout(function(){b(s,"okanjo-modal-fade-out"),_(s,"okanjo-modal-hidden"),b(o,"okanjo-modal-active"),i||b(o,"okanjo-modal-margin-fix")},210)},j=function(e){d.innerHTML="","string"==typeof e?d.innerHTML=e:d.appendChild(e)};return n.ui.modal={show:function(e){r||(r=!0,p(),y()),j(e),k()},hide:function(){w()}},n.ui.modal}(window,document),function(e,t){var r=e.okanjo,o=function(){function o(){n(this,o),this._queue=this._getStoredQueue(),this._processTimeout=null,this.pageId=r.util.shortid(),this.defaultChannel=o.Channel.external,this.sid=null,this.sourceCh=null,this.sourceCx=null,this._checkUrlForReferral()}return i(o,[{key:"_getStoredQueue",value:function(){if(!e.localStorage[o.Params.queue])return[];try{var t=JSON.parse(e.localStorage[o.Params.queue]);return Array.isArray(t)?t:(r.report("Stored queue is not a queue",{queue:t}),[])}catch(n){return r.report("Failed to load metric queue from storage",{err:n}),[]}}},{key:"_saveQueue",value:function(t){var n=this;t?(this._saveQueueTimeout&&clearTimeout(this._saveQueueTimeout),this._saveQueueTimeout=setTimeout(function(){n._saveQueue(!1),n._saveQueueTimeout=null},100)):e.localStorage[o.Params.queue]=JSON.stringify(this._queue)}},{key:"_checkUrlForReferral",value:function(){var t=r.util.getPageArguments(!0),n=t[o.Params.name],i=e.localStorage[o.Params.name]||r.util.cookie.get(o.Params.name),a=t[o.Params.context],s=t[o.Params.channel];n&&i&&n!==i&&this.trackEvent({object_type:o.Object.metric_session,event_type:o.Event.correlation,id:n+"_"+i,ch:this.defaultChannel,_noProcess:!0}),this.sid=i||n||null,this.sourceCh=s||null,this.sourceCx=a||null}},{key:"trackEvent",value:function(e,t){return e.object_type&&e.event_type?void this._push(e,t):void r.report("Invalid metric to track (missing object_type or event_type)",{event:e})}},{key:"trackPageView",value:function(e,t){e=e||{},e.object_type=o.Object.page,e.event_type=o.Event.view,e.id=e.id||r.util.getLocation(),e.ch=e.ch||this.defaultChannel,this.trackEvent(e,t)}},{key:"_push",value:function(e,t){this._queue.push({event:e,callback:t}),this._saveQueue(!0),e._noProcess?delete e._noProcess:this._processQueue()}},{key:"_processQueue",value:function(){var e=this;!this._processTimeout&&this._queue.length>0&&(this._processTimeout=setTimeout(function(){var t=e._queue.splice(0,255);e._saveQueue(!1),e._batchSend(t,function(n,i){i&&i.data&&i.data.sid&&e._updateSid(i.data.sid),e._processTimeout=null,e._processQueue(),t.forEach(function(e){e.callback&&e.callback(n,i)})})},0))}},{key:"_batchSend",value:function(e,t){var n=this,i=e.map(function(e){return n._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),o={events:i,win:r.util.getLocation()},a=r.net.getRoute(r.net.routes.metrics_batch);this.sid&&(o.sid=this.sid),r.net.request.post(a,o,function(n,i){n&&r.report("Failed to send metrics batch",{err:n,res:i,items:e,route:a}),t&&t(n,i)})}},{key:"_normalizeEvent",value:function(e){e.m=e.m||{},e.key=e.key||e.m.key||r.key||void 0,this.sid&&(e.sid=this.sid),e.m=Object.assign({},e.m),Object.keys(o.Meta.exclude).forEach(function(t){return delete e.m[t]}),this.sourceCh&&(e.m.ref_ch=this.sourceCh),this.sourceCx&&(e.m.ref_cx=this.sourceCx),e.m.pgid=this.pageId,e.m.ok_ver=r.version,e.m=r.util.flatten(e.m,{arrayToCsv:!0}),Object.keys(e.m).forEach(function(t){"string"==typeof e.m[t]&&(e.m[t]=e.m[t].substr(0,255))}),t.referrer&&(e.ref=t.referrer),e.win=r.util.getLocation()}},{key:"_updateSid",value:function(t){!t||this.sid&&this.sid===t||(this.sid=t,e.localStorage[o.Params.name]=t,r.util.cookie.set(o.Params.name,t,o.Params.ttl))}},{key:"create",value:function(){for(var e=arguments.length,t=Array(e),n=0;nt?e:t},f=function(e,t){return"undefined"==typeof e?t:e};return i.forEach(function(e){o=r.ui.getElementPosition(e),a=d(o.x1,a),s=d(o.y1,s),u=h(o.x2,u),c=h(o.y2,c),l.push(o.x1,o.y1,o.x2,o.y2)}),t.m.wix1=f(a,n.x1),t.m.wiy1=f(s,n.y1),t.m.wix2=f(u,n.x2),t.m.wiy2=f(c,n.y2),t.m.wrps=l.map(function(e){return Math.floor(e)}).join(","),t}},{key:"addViewportInfo",value:function(e){var t=r.ui.getViewportSize(),n=r.ui.getScrollPosition();return e=e||{},e.m=e.m||{},e.m.vx1=n.x,e.m.vy1=n.y,e.m.vx2=n.x+t.vw,e.m.vy2=n.y+t.vh,e}},{key:"addEventInfo",value:function(e,t){var n=r.ui.getEventPosition(e);return t=t||{},t.m=t.m||{},t.m.et=n.et,t.m.ex=n.ex,t.m.ey=n.ey,t}},{key:"addEventMeta",value:function(e){e=e||{},e.m=e.m||{};for(var t=arguments.length,n=Array(t>1?t-1:0),i=1;i1?t-1:0),i=1;i=0&&this._events[e].splice(n,1)}}},{key:"emit",value:function(e){var t=void 0,n=void 0,i=void 0,r=[].slice.call(arguments,1);if(this._events[e])for(n=this._events[e].slice(),i=n.length,t=0;t1&&void 0!==arguments[1])||arguments[1];if(!this._strip||!t)return void 0!==e&&this._convert&&(e=this._convert(e)),void 0!==e?e:this._default}}],[{key:"array",value:function(t){return(new e).array(t)}},{key:"string",value:function(){return(new e).string()}},{key:"bool",value:function(){return(new e).bool()}},{key:"strip",value:function(){return(new e).strip()}},{key:"int",value:function(){return(new e)["int"]()}},{key:"float",value:function(){return(new e)["float"]()}}]),e}(),a._Widget=c}(window),function(r){var o=r.okanjo,a=o._Widget.Field,s=a.string,u=a.array,c=a["float"],l=a["int"],d=a.bool,h=o.metrics.constructor,f=o.ui.engine.constructor,p="filters",g="display",m="article_meta",v=.5,y=1e3,_=2,b=function(a){function b(t){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};n(this,b),i=o.util.flatten(i,{ignoreArrays:!0});var r=e(this,(b.__proto__||Object.getPrototypeOf(b)).call(this,t,i));return r.name="Placement",r._metricBase={},r._response=null,r._viewWatcherIv=null,r._viewedWatchers=[],i.no_init||r.init(),r}return t(b,a),i(b,[{key:"getSettings",value:function(){return{type:s().group(p),ids:u().group(p),q:s().group(p),url:s().group(p),url_referrer:s().group(p).strip(),url_selectors:s().group(p),url_paths:u().group(p),not_url_paths:u().group(p),organization_id:s().group(p),property_id:s().group(p),store_id:s().group(p),organization_name:s().group(p),property_name:s().group(p),store_name:s().group(p),external_id:s().group(p),sku:s().group(p),external_store_id:s().group(p),condition:s().group(p),manufacturer:s().group(p),upc:s().group(p),isbn:s().group(p),tags:u().group(p),category:u().group(p),pools:u().group(p),min_price:c().group(p),max_price:c().group(p),min_donation_percent:c().group(p),max_donation_percent:c().group(p),donation_to:s().group(p),sort_by:s().group(p),sort_direction:s().group(p),skip:l().group(p),take:l().group(p),placement_tests_only:d(),size:s().group(g),template_name:s().group(g),template_layout:s().group(g),template_theme:s().group(g),template_variant:s().group(g),template_cta_style:s().group(g),template_cta_text:s().group(g),template_cta_color:s().group(g),adx_unit_path:s().group(g),url_category:u().group(m),url_keywords:u().group(m),key:s().strip(),no_init:d().strip(),proxy_url:s().strip(),expandable:d().strip()["default"](!0),disable_inline_buy:d().strip()["default"](!1),disable_popup:d().strip()["default"](!1),backwards:s().strip(),testing:d().strip()}}},{key:"getConfig",value:function(){var e=this,t=this.getSettings(),n={filters:{},display:{},backfill:{},shortfill:{},article_meta:{}},i=/^backfill_(.+)$/,r=/^shortfill_(.+)$/;return Object.keys(this.config).forEach(function(o){var a=e.config[o],s=o,u=!1,c=!1,l=null,d=i.exec(o);d?(s=d[1],u=!0):(d=r.exec(o),d&&(s=d[1],c=!0)),t[s]&&(a=t[s].value(a),l=t[s].getGroup());var h=n;u?h=n.backfill:c&&(h=n.shortfill),!c&&l&&(h[l]=h[l]||{},h=h[l]),null===a?h[s]="":void 0!==a&&(h[s]=a)}),n}},{key:"load",value:function(){var e=this;this._setMetricBase(),this._fetchContent(function(t){t?e._reportWidgetLoad("fetch failed: "+t.statusCode||t.toString()):(e._mergeResponseSettings(),e._updateBaseMetaFromResponse(),e._showContent())})}},{key:"_setMetricBase",value:function(){var e=this._metricBase;e.ch=h.Channel.placement,e.cx=this.config.backwards||"auto",e.key=this.config.key,e.m=e.m||{},e.m.wgid=this.instanceId,this.config.testing&&(e.env=h.Environment.testing)}},{key:"_reportWidgetLoad",value:function(e){var t=this,n=this._response||{},i=n.data||{results:[]};this._metricBase.m.decl=e||"0",this._metricBase.m.res_bf=i.backfilled?1:0,this._metricBase.m.res_sf=i.shortfilled?1:0,this._metricBase.m.res_spltfl=i.splitfilled?1:0,this._metricBase.m.res_total=i.total||0,this._metricBase.m.res_type=i.type,this._metricBase.m.res_length=i.results.length,o.metrics.create(this._metricBase).type(h.Object.widget,h.Event.impression).meta(this.getConfig()).element(this.element).viewport().widget(this.element).send(),this._addOnceViewedHandler(this.element,function(){o.metrics.create(t._metricBase).type(h.Object.widget,h.Event.view).meta(t.getConfig()).element(t.element).viewport().widget(t.element).send()})}},{key:"_fetchContent",value:function(e){var t=this,n=this.getConfig(),i=this.config.key;o.metrics.sid&&(n.sid=o.metrics.sid),n.filters.url_referrer=this.config.url_referrer||r.location.href,n.wgid=this.instanceId,n.pgid=o.metrics.pageId,o.net.request.post(o.net.getRoute(o.net.routes.ads,null,this.config.sandbox?"sandbox":"live")+"?key="+encodeURIComponent(i),n,function(n,i){n?(o.report("Failed to retrieve placement content",n,{placement:t}),t.setMarkup(""),t.emit("error",n),e&&e(n)):(t._response=i,t.emit("data"),e&&e())})}},{key:"_mergeResponseSettings",value:function(){var e=this,t=this._response,n=t.data||{},i=n.settings||{};i.filters&&Object.keys(i.filters).forEach(function(t){e.config[t]=i.filters[t]}),i.display&&Object.keys(i.display).forEach(function(t){e.config[t]=i.display[t]})}},{key:"_updateBaseMetaFromResponse",value:function(){var e=(this._response||{}).data||{};this._metricBase.m=this._metricBase.m||{};var t=this._metricBase.m;e.article&&(t.aid=e.article.id),e.test&&e.test.enabled?(t.pten=1,t.ptid=e.test.id,t.ptseed=e.test.seed):t.pten=0}},{key:"_showContent",value:function(){var e=(this._response||{}).data||{};if(e.type===b.ContentTypes.products)this._showProducts();else if(e.type===b.ContentTypes.articles)this._showArticles();else if(e.type===b.ContentTypes.adx)this._showADX();else{var t="Unknown response content type: "+e.type;o.report(t,{placement:this}),this.setMarkup(""),this.emit("error",t),this._reportWidgetLoad(t)}}},{key:"_getClickThroughURL",value:function(e,t,n){var i=t.indexOf("?")>=0?"&":"?";return n=n||{},n.ok_msid=o.metrics.sid||"unknown",n.ok_ch=this._metricBase.ch,n.ok_cx=this._metricBase.cx,n._okjr=r.location.href.split(/[?#]/)[0],n.utm_source="okanjo",n.utm_campaign="smartserve",n.utm_medium="smartserve",t+=i+Object.keys(n).map(function(e){return encodeURIComponent(e)+"="+encodeURIComponent(n[e])}).join("&"),this.config.proxy_url&&(t=this.config.proxy_url+encodeURIComponent(t)),e.data({u:t}),e.toUrl()}},{key:"_handleResourceMouseDown",value:function(e,t,n){var i=t._cid,r=o.metrics.create(this._metricBase,{id:t.id}).type(e,h.Event.interaction).meta(this.getConfig()).meta({cid:i}).meta({bf:t.backfill?1:0,sf:t.shortfill?1:0,spltfl_seg:t.splitfill_segment||null}).event(n).element(n.currentTarget).viewport().widget(this.element),a="url_track_param",s="url";e===h.Object.product&&(a="buy_url_track_param",s="buy_url");var u={ok_cid:i};t[a]&&(u[t[a]]=i),r.data({ea:h.Action.click}),n.currentTarget.href=this._getClickThroughURL(r,t[s],u),t._clickId=i,t._event=r,t._additionalParams=u}},{key:"_getTemplate",value:function(e,t){var n=this.config.template_name;return n&&o.ui.engine.isTemplateRegistered(e+"."+n)||(n=t),e+"."+n}},{key:"_enforceLayoutOptions",value:function(){"leaderboard"===this.config.size||"large_mobile_banner"===this.config.size?(this.config.template_layout="list",this.config.template_cta_style="link"):"half_page"!==this.config.size&&"auto"!==this.config.size||(this.config.template_layout="list")}},{key:"_enforceSlabLayoutOptions",value:function(){"medium_rectangle"===this.config.size||"billboard"===this.config.size?(this.config.template_layout="grid","button"===this.config.template_cta_style&&(this.config.template_cta_style="link")):"half_page"===this.config.size?this.config.template_layout="grid":"leaderboard"===this.config.size||"large_mobile_banner"===this.config.size?(this.config.template_layout="list","button"===this.config.template_cta_style&&(this.config.template_cta_style="link")):"auto"===this.config.size?this.config.template_layout="list":"responsive"===this.config.size&&"button"===this.config.template_cta_style&&(this.config.template_cta_style="link")}},{key:"_registerCustomBranding",value:function(){var e=this.config.template_cta_color;if(e){var t=void 0,n="okanjo-wgid-"+this.instanceId;t="\n .okanjo-block2."+n+" .okanjo-resource-cta-button, .okanjo-block2."+n+" .okanjo-resource-buy-button { color: "+e+" !important; } \n .okanjo-block2."+n+".okanjo-cta-style-button .okanjo-resource-cta-button, .okanjo-block2."+n+".okanjo-cta-style-button .okanjo-resource-buy-button { border-color: "+e+" !important; } \n .okanjo-block2."+n+".okanjo-cta-style-button .okanjo-resource-cta-button:hover, .okanjo-block2."+n+".okanjo-cta-style-button .okanjo-resource-buy-button:hover { background: "+e+" !important; color: #fff !important; } \n ", -o.ui.engine.registerCss(n,t,{id:n}),o.ui.engine.ensureCss(n)}}},{key:"_addOnceViewedHandler",value:function(e,t){var n={element:e,successfulCount:0,handler:t};this._viewedWatchers.push(n),this._toggleViewWatcher(!0)}},{key:"_checkViewWatchers",value:function(){for(var e,t=0;t=v&&e.successfulCount++,e.successfulCount>=_&&(e.handler(),this._viewedWatchers.splice(t,1),t--);0===this._viewedWatchers.length&&this._toggleViewWatcher(!1)}},{key:"_toggleViewWatcher",value:function(e){e?null===this._viewWatcherIv&&(this._viewWatcherIv=setInterval(this._checkViewWatchers.bind(this),y/_)):(clearInterval(this._viewWatcherIv),this._viewWatcherIv=null)}},{key:"_showProducts",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},n=this._getTemplate(b.ContentTypes.products,b.DefaultTemplates.products);t.results.forEach(function(t,n){e.config.disable_inline_buy&&(t.inline_buy_url=null),t.inline_buy_url&&(t._escaped_inline_buy_url=encodeURIComponent(t.inline_buy_url)),t._image_url=t.image_urls?t.image_urls[0]:"",t._escaped_buy_url=encodeURIComponent(t.buy_url),t._price_formatted=f.formatCurrency(t.price),t._index=n}),this.setMarkup(o.ui.engine.render(n,this)),0===t.results.length?(this.emit("empty"),this._reportWidgetLoad("empty")):this._reportWidgetLoad(),this.element.querySelectorAll("a").forEach(function(t){var n=t.getAttribute("data-id"),i=t.getAttribute("data-index");if(n&&i>=0){var r=e._response.data.results[i];r&&(t.addEventListener("mousedown",e._handleResourceMouseDown.bind(e,h.Object.product,r)),t.addEventListener("click",e._handleProductClick.bind(e,r)),o.metrics.create(e._metricBase,{id:r.id}).type(h.Object.product,h.Event.impression).meta(e.getConfig()).meta({bf:r.backfill?1:0,sf:r.shortfill?1:0,spltfl_seg:r.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){o.metrics.create(e._metricBase,{id:r.id}).type(h.Object.product,h.Event.view).meta(e.getConfig()).meta({bf:r.backfill?1:0,sf:r.shortfill?1:0,spltfl_seg:r.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(".okanjo-resource-title").forEach(function(e){o.ui.ellipsify(e)}),o.ui.fitImages(this.element),this.emit("load")}},{key:"_handleProductClick",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(h.Object.product,e,t);var n=e._event,i=e._additionalParams;n.event(t);var a=!!e.inline_buy_url,s=!this.config.disable_popup&&a&&o.util.isMobile();if(s){t.preventDefault(),n.data({ea:h.Action.inline_click}).meta({popup:"true"});var u=this._getClickThroughURL(n,e.inline_buy_url,i);this._popupFrame=r.open(u,"okanjo-inline-buy-frame","width=400,height=400,location=yes,resizable=yes,scrollbars=yes"),this._popupFrame||(o.report("Popup blocker stopped buy experience from showing",{placement:this}),r.location.href=u)}else if(a){t.preventDefault();var c=document.createElement("iframe"),l={"class":"okanjo-inline-buy-frame",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:"",mozallowfullscreen:"",allowfullscreen:"",scrolling:"auto"};if(Object.keys(l).forEach(function(e){return c.setAttribute(e,l[e])}),i.expandable=this.config.expandable?1:0,!this.config.expandable){var d=this.element.querySelector(".okanjo-expansion-root");if(d){c.className+=" okanjo-ad-in-unit",c.setAttribute("height","100%"),c.setAttribute("width","100%"),d.appendChild(c);var f=o.ui.getElementSize(d);i.frame_height=f.height,i.frame_width=f.width,this.config.size&&(i.ad_size=this.config.size)}}n.data({ea:h.Action.inline_click}).meta({expandable:this.config.expandable?"true":"false"}),c.src=this._getClickThroughURL(n,e.inline_buy_url,i),c.parentNode||o.ui.modal.show(c)}else t.currentTarget.href=this._getClickThroughURL(n,e.buy_url,i)}},{key:"_showArticles",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},n=this._getTemplate(b.ContentTypes.articles,b.DefaultTemplates.articles);t.results.forEach(function(e,t){e._escaped_url=encodeURIComponent(e.url),e._index=t}),this.setMarkup(o.ui.engine.render(n,this)),0===t.results.length?(this.emit("empty"),this._reportWidgetLoad("empty")):this._reportWidgetLoad(),this.element.querySelectorAll("a").forEach(function(t){var n=t.getAttribute("data-id"),i=t.getAttribute("data-index");if(n&&i>=0){var r=e._response.data.results[i];r&&(t.addEventListener("mousedown",e._handleResourceMouseDown.bind(e,h.Object.article,r)),t.addEventListener("click",e._handleArticleClick.bind(e,r)),o.metrics.create(e._metricBase,{id:r.id}).type(h.Object.article,h.Event.impression).meta(e.getConfig()).meta({bf:r.backfill?1:0,sf:r.shortfill?1:0,spltfl_seg:r.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){o.metrics.create(e._metricBase,{id:r.id}).type(h.Object.article,h.Event.view).meta(e.getConfig()).meta({bf:r.backfill?1:0,sf:r.shortfill?1:0,spltfl_seg:r.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(".okanjo-resource-title").forEach(function(e){o.ui.ellipsify(e)}),o.ui.fitImages(this.element),this.emit("load")}},{key:"_handleArticleClick",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(h.Object.article,e,t);var n=e._event,i=e._additionalParams;n.event(t),t.currentTarget.href=this._getClickThroughURL(n,e.url,i)}},{key:"_showADX",value:function(){var e=this,t=(this._response||{data:{settings:{}}}).data||{settings:{}},n=this._getTemplate(b.ContentTypes.adx,b.DefaultTemplates.adx),i=null;if(this.config.size)if(b.Sizes[this.config.size])i=b.Sizes[this.config.size];else{var r=/^([0-9]+)x([0-9]+)$/i.exec(this.config.size);r&&(i={width:r[1],height:r[2]})}i||(i=b.Sizes["default"]);var a="/90447967/okanjo:",s=void 0;t.settings.display&&t.settings.display.adx_unit_path&&(a=t.settings.display.adx_unit_path,s="custom_ad_unit");var u={size:i,adUnitPath:a};this.setMarkup(o.ui.engine.render(n,this,u)),this._reportWidgetLoad(s);var c=this.element.querySelector(".okanjo-adx-container");if(c){var l=document.createElement("iframe"),d={"class":"okanjo-adx-frame",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:"",mozallowfullscreen:"",allowfullscreen:"",scrolling:"auto",width:i.width,height:i.height};Object.keys(d).forEach(function(e){return l.setAttribute(e,d[e])}),c.appendChild(l);var f=o.metrics.create(this._metricBase).type(h.Object.thirdparty_ad,h.Event.interaction).meta(this.getConfig()).meta({ta_s:a,ta_w:i.width,ta_h:i.height}).element(l).viewport().widget(this.element).toUrl();l.contentWindow.trackImpression=function(){o.metrics.create(e._metricBase).type(h.Object.thirdparty_ad,h.Event.impression).meta(e.getConfig()).meta({ta_s:a,ta_w:i.width,ta_h:i.height}).element(l).viewport().widget(e.element).send(),e._addOnceViewedHandler(l,function(){o.metrics.create(e._metricBase).type(h.Object.thirdparty_ad,h.Event.view).meta(e.getConfig()).meta({ta_s:a,ta_w:i.width,ta_h:i.height}).element(l).viewport().widget(e.element).send()})},l.contentWindow.document.open(),l.contentWindow.document.write('\n<'+('script type="text/javascript" src="https://www.googletagservices.com/tag/js/gpt.js">\n googletag.pubads().addEventListener(\'slotRenderEnded\', function(e) { \n trackImpression(e);\n });\n googletag.pubads()\n .definePassback("'+a.replace(/"/g,'\\"')+'", [['+i.width+", "+i.height+']])\n .setClickUrl("'+f+'&u=")\n .display();\n<')+"/script>\n"),l.contentWindow.document.close()}this.emit("load")}}]),b}(o._Widget);return b.Sizes={medium_rectangle:{width:300,height:250},leaderboard:{width:728,height:90},large_mobile_banner:{width:320,height:100},half_page:{width:300,height:600},billboard:{width:970,height:250},button_2:{width:120,height:60},micro_bar:{width:88,height:31},portrait:{width:300,height:1050},rectangle:{width:180,height:150},super_leaderboard:{width:970,height:90},wide_skyscraper:{width:160,height:600},mobile_leaderboard:{width:320,height:50},small_square:{width:200,height:200},button_1:{width:120,height:90},full_banner:{width:468,height:60},half_banner:{width:234,height:60},large_rectangle:{width:336,height:280},pop_under:{width:720,height:300},three_to_one_rectangle:{width:300,height:100},skyscraper:{width:120,height:600},square:{width:250,height:250},square_button:{width:125,height:125},vertical_banner:{width:120,height:240},vertical_rectangle:{width:240,height:400}},b.Sizes["default"]=b.Sizes.medium_rectangle,b.ContentTypes={products:"products",articles:"articles",adx:"adx"},b.DefaultTemplates={products:"block2",articles:"block2",adx:"block2"},o.Placement=b}(window),function(r){var o=r.okanjo,a=function(r){function a(t,i){n(this,a),i=i||{};var r=i.no_init;i.no_init=!0;var s=e(this,(a.__proto__||Object.getPrototypeOf(a)).call(this,t,i));return o.warn("Product widget has been deprecated. Use Placement instead (may require configuration changes)",{widget:s}),r||(delete s.config.no_init,s.init()),s}return t(a,r),i(a,[{key:"_setCompatibilityOptions",value:function(){this.config.backwards="Product",this.config.type=o.Placement.ContentTypes.products,"sense"===this.config.mode?(this.config.url=this.config.url||"referrer",this.config.take=this.config.take||5):"single"===this.config.mode?(this.config.url=null,this.config.id&&(this.config.ids=[this.config.id]),this.config.take=1,delete this.config.id):(this.config.url=null,this.config.take=this.config.take||25),delete this.config.mode,this.config.sold_by&&(this.config.store_name=this.config.sold_by,delete this.config.sold_by),this.config.selectors&&(this.config.url_selectors=this.config.selectors,delete this.config.selectors),this.config.marketplace_id&&(this.config.property_id=this.config.marketplace_id,delete this.config.marketplace_id),"testing"===this.config.marketplace_status&&(this.config.sandbox=!0),delete this.config.marketplace_status,delete this.config.suboptimal,delete this.config.text}}]),a}(o.Placement);return o.Product=a}(window),function(r){var o=r.okanjo,a=function(r){function a(t,i){n(this,a),i=i||{};var r=i.no_init;i.no_init=!0;var s=e(this,(a.__proto__||Object.getPrototypeOf(a)).call(this,t,i));return o.warn("Ad widget has been deprecated. Use Placement instead (may require configuration changes)",{widget:s}),r||(delete s.config.no_init,s.init()),s}return t(a,r),i(a,[{key:"_setCompatibilityOptions",value:function(){this.config.backwards="Ad",this.config.type=o.Placement.ContentTypes.products,this.config.url=null,this.config.id?this.config.ids=[this.config.id]:o.warn("Ad widget should have parameter `id` set."),this.config.take=1,delete this.config.id,delete this.config.content}}]),a}(o.Placement);return o.Ad=a}(window),function(){/*! +/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +!function(e,t){"function"==typeof define&&define.amd?define([],t):"object"==typeof exports?module.exports=t():e.okanjo=t()}(this,function(){function e(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t}function t(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)}function n(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}var i=function(){function e(e,t){for(var n=0;n0?1:-1)*Math.floor(Math.abs(t)):t},i=Math.pow(2,53)-1,r=function(e){var t=n(e);return Math.min(Math.max(t,0),i)};return function(e){var n=this,i=Object(e);if(null==e)throw new TypeError("Array.from requires an array-like object - not null or undefined");var o,a=arguments.length>1?arguments[1]:void 0;if("undefined"!=typeof a){if(!t(a))throw new TypeError("Array.from: when provided, the second argument must be a function");arguments.length>2&&(o=arguments[2])}for(var s,u=r(i.length),c=t(n)?Object(new n(u)):new Array(u),l=0;l>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var i=arguments[1],r=0;r>>0;if("function"!=typeof e)throw new TypeError("predicate must be a function");for(var i=arguments[1],r=0;r>>0;if(0===r)return!1;for(var o=0|t,a=Math.max(o>=0?o:r-Math.abs(o),0);a=0&&t.splice(o,1)}c.error("[Okanjo v"+d.version+"]: "+i.stack),t.length&&c.error.apply(c,["Additional information:"].concat(t))},warn:function(e){for(var t=arguments.length,n=Array(t>1?t-1:0),i=1;i1&&void 0!==arguments[1]?arguments[1]:{},n={};return void 0!==e&&null!==e&&Object.keys(e).forEach(function(i){if(e[i]instanceof Date)t.dateToIso?n[i]=e[i].toISOString():n[i]=e[i];else if("object"===r(e[i])&&null!==e[i])if(Array.isArray(e[i])&&t.ignoreArrays===!0)n[i]=e[i];else if(Array.isArray(e[i])&&t.arrayToCsv===!0)n[i]=e[i].join(",");else{var o=d.util.flatten(e[i],t);Object.keys(o).forEach(function(e){n[i+"_"+e]=o[e]})}else n[i]=e[i]}),n},d.util.shortid=function(t){var n="ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC",i=e.crypto||e.msCrypto||"function"==typeof require&&require("crypto"),r=function(){if(i&&i.randomBytes)return 48&i.randomBytes(1)[0];if(!i||!i.getRandomValues)return 48&Math.floor(256*Math.random());var e=new Uint8Array(1);return i.getRandomValues(e),48&e[0]},o=function(e){for(var t=0,i=void 0,o="";!i;)o+=n[e>>4*t&15|r()],i=e0&&(e+=o(u)),e+=o(n)}}(),d.util.getLocation=function(){return e.location!==e.parent.location?t.referrer:t.location.href},d.ui={getScrollPosition:function(){return{x:n?e.pageXOffset:i?t.documentElement.scrollLeft:t.body.scrollLeft,y:n?e.pageYOffset:i?t.documentElement.scrollTop:t.body.scrollTop}},getElementSize:function(t,n){var i={height:t.offsetHeight,width:t.offsetWidth},r=t.currentStyle||e.getComputedStyle(t);return n&&(i.height+=parseInt(r.marginTop)+parseInt(r.marginBottom),i.width+=parseInt(r.marginLeft)+parseInt(r.marginRight)),i},getPageSize:function(){var e=t.querySelector("body"),n=t.documentElement;return{w:Math.max(e.scrollWidth,e.offsetWidth,n.clientWidth,n.scrollWidth,n.offsetWidth),h:Math.max(e.scrollHeight,e.offsetHeight,n.clientHeight,n.scrollHeight,n.offsetHeight)}},getViewportSize:function(){var n=i?t.documentElement:t.body,r=n.clientWidth,o=n.clientHeight,a=e.innerWidth||0,s=e.innerHeight||0,u=a&&r>a||s&&o>s;return{vw:u?a:r,vh:u?s:o}},getEventPosition:function(e){var n=e.pageX,i=e.pageY,r=t.body,o=t.documentElement,a="scrollLeft",s="scrollTop",u=e.__proto__.constructor.name;return{et:u,ex:void 0===n?e.clientX+r[a]+o[a]:n,ey:void 0===i?e.clientY+r[s]+o[s]:i}},getElementPosition:function(e){var n="Could not get position of element. Did you attach the element to the DOM before initializing?";try{var i=e.getBoundingClientRect(),r=t.body.getBoundingClientRect();return t.body.contains(e)||d.report(n,e),{x1:i.left-r.left,y1:i.top-r.top,x2:i.right-r.left,y2:i.bottom-r.top}}catch(o){return d.report(n,{exception:o,element:e}),{x1:0,y1:0,x2:0,y2:0,err:1}}},_getIntersection:function(e,t,n){var i=Math.max(e.x1,t.x),r=Math.min(e.x2,t.x+n.vw),o=Math.max(e.y1,t.y),a=Math.min(e.y2,t.y+n.vh),s=Math.max(0,r-i)*Math.max(0,a-o),u=(e.x2-e.x1)*(e.y2-e.y1);return{intersectionArea:s,elementArea:u}},isElementVisible:function(e){return e.offsetWidth>0&&e.offsetHeight>0},getPercentageInViewport:function(e){var t=d.ui.getElementPosition(e),n=d.ui.getScrollPosition(),i=d.ui.getViewportSize();if(t.err)return 0;var r=d.ui._getIntersection(t,n,i),o=r.intersectionArea,a=r.elementArea;return a<=0?0:o/a}},d.ui.ellipsify=function(e,n){for(var i=n||e.parentNode,r=d.ui.getElementSize(i).height,o=void 0!==e.textContent,s=o?e.textContent:e.innerText,u="",c=5e3,l=function(e){return u=e.substr(0,e.length-3)+u,"..."};d.ui.getElementSize(e).height>r&&s.length>0&&c-- >0;)s=o?e.textContent:e.innerText,s=s.replace(a,l),o?e.textContent=s:e.innerText=s;if(u.length>0){var h=t.createElement("span"),f=t.createElement("span");h.setAttribute("class","okanjo-ellipses"),f.setAttribute("class","okanjo-visually-hidden"),o?(h.textContent=s.substr(0,s.length-3),f.textContent=u):(h.innerText=s.substr(0,s.length-3),f.innerText=u),e.innerHTML="",e.appendChild(h),e.appendChild(f)}},d.ui.fitImages=function(e){"objectFit"in t.documentElement.style==!1&&e.querySelectorAll("img.okanjo-fit").forEach(function(e){e.style.display="none";var t=e.parentNode;t.style.backgroundSize="cover",t.style.backgroundImage="url("+e.src+")",t.style.backgroundposition="center center"})},e.okanjo=d}(window,document);return function(e){var t=/^application\/json/,n=e.okanjo;n.net.request=function(i,r,o,a){"function"==typeof o&&(a=o,o=void 0);var s=new(e.XMLHttpRequest||e.ActiveXObject)("MSXML2.XMLHTTP.3.0"),u=!1,c=function(e,t){u||(u=!0,a(e,t))};n.net.request.timeout&&(s.timeout=n.net.request.timeout),s.ontimeout=function(e){c({statusCode:504,error:"Request timed out",message:"Something went wrong",attributes:{event:e,xhr:s}})},s.onreadystatechange=function(e){if(4===s.readyState)if(s.status>0){var n=void 0;n=t.test(s.getResponseHeader("Content-Type"))?JSON.parse(s.responseText):{statusCode:s.status,data:s.responseText},s.status>=200&&s.status<300?c(null,n):c(n)}else c({statusCode:503,error:"Request failed",message:"Something went wrong",attributes:{event:e,xhr:s}})},s.open(i.toUpperCase(),r),s.withCredentials=!0,["POST","PUT","PATCH"].includes(i.toUpperCase())&&(s.setRequestHeader("Content-Type","application/json; charset=utf-8"),void 0!==o&&(o=JSON.stringify(o))),s.send(o||void 0)},n.net.request.get=n.net.request.bind(this,"GET"),n.net.request.post=n.net.request.bind(this,"POST"),n.net.request.put=n.net.request.bind(this,"PUT"),n.net.request["delete"]=n.net.request.bind(this,"DELETE");var i=function(e){return null===e||void 0===e?"":encodeURIComponent(""+e)},o=function(e,t){return t?t+"["+i(e)+"]":i(e)};n.net.request.stringify=function(e,t){var a=[];return t=t||"",Object.keys(e).forEach(function(s){var u=e[s];if(Array.isArray(u))u.forEach(function(e){return a.push(o(s,t)+"="+i(e))});else if("object"===("undefined"==typeof u?"undefined":r(u))&&null!==u){var c=n.net.request.stringify(u,o(s,t));c&&a.push(c)}else void 0!==u&&a.push(o(s,t)+"="+i(u))}),a.join("&")}}(window),function(e,t){e.okanjo.util.cookie={set:function(n,i,r){var o=new Date;o.setDate(o.getDate()+r);var a=r?" Expires="+o.toUTCString()+";":"",s=" Path=/",u="https:"===e.location.protocol?" Secure;":"",c=encodeURI(i)+";"+a+u+" SameSite=None;"+s;t.cookie=n+"="+c},get:function(e){var n=null;return t.cookie.split(";").find(function(t){var i=t.substr(0,t.indexOf("=")).trim(),r=t.substr(t.indexOf("=")+1);return i===e&&(n=decodeURI(r),!0)}),n}}}(window,document),function(e,t){var o=e.okanjo,a=function(){function e(){n(this,e),this._templates={},this._css={},this.classDetects=""}return i(e,[{key:"registerTemplate",value:function(e,t,n,i){if("object"===("undefined"==typeof t?"undefined":r(t))){if(void 0===t.nodeType)throw new Error("Parameter template must be a string or a DOM element");t=t.innerHTML,o.lib.Mustache.parse(t)}else if("string"!=typeof t)throw new Error("Parameter template must be a string or a DOM element");if(3===arguments.length&&"object"===("undefined"==typeof n?"undefined":r(n))?(i=n,n=null):i=i||{},n&&"function"!=typeof n)throw new Error("Parameter beforeRender must be a function");this._templates[e]={markup:t,options:i,beforeRender:n}}},{key:"registerCss",value:function(e,t,n){if(n=n||{},"object"===("undefined"==typeof t?"undefined":r(t))){if(void 0===t.nodeType)throw new Error("Parameter css must be a string or a DOM element")}else if("string"!=typeof t)throw new Error("Parameter css must be a string or a DOM element");this._css[e]={markup:t,options:n}}},{key:"isTemplateRegistered",value:function(e){return!!this._templates[e]}},{key:"isCssRegistered",value:function(e){return!!this._css[e]}},{key:"ensureCss",value:function(e){if(this._css[e]){var n=this._css[e],i=void 0===n.markup.nodeType?n.options.id||"okanjo-css-"+e:null;if(i){var r=t.querySelector("#"+i.replace(/\./g,"\\."));if(!r){var a=t.head,s=t.createElement("style");if(s.id=i,s.setAttribute("type","text/css"),s.hasOwnProperty?s.innerHTML=n.markup:s.styleSheet.cssText=n.markup,a)a.appendChild(s);else{var u=t.body;u?u.appendChild(s):o.report("Cannot add CSS template to document. Does it not have a body or head?")}}}}else o.report('Attempted to add CSS template "'+e+'" to the DOM, however it does not appear to be registered?')}},{key:"render",value:function(e,t,n){var i=this;n=n||{};var r=this._templates[e];return r.beforeRender&&(n=r.beforeRender.call(t,n)),n.okanjo=o,n.okanjoMetricUrl=o.net.endpoint.replace(/^https?:\/\//,""),n.now=function(){return(new Date).getTime()},n.classDetects=this.classDetects,n.blockClasses&&Array.isArray(n.blockClasses)&&(n.classDetects+=" "+n.blockClasses.join(" "),delete n.blockClasses),n.css!==!1&&r.options.css&&r.options.css.length>0&&(r.options.css.forEach(function(e){return i.ensureCss(e)}),delete n.css),o.lib.Mustache.render(r.markup,n)}}]),e}();a.formatCurrency=function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:2,n=arguments.length>2&&void 0!==arguments[2]?arguments[2]:".",i=arguments.length>3&&void 0!==arguments[3]?arguments[3]:",",r=e<0?"-":"",o=parseInt(e=Math.abs(+e||0).toFixed(t))+"",a=o.length;return a=a>3?a%3:0,r+(a?o.substr(0,a)+i:"")+o.substr(a).replace(/(\d{3})(?=\d)/g,"$1"+i)+(t?n+Math.abs(e-o).toFixed(t).slice(2):"")},o.ui.engine=new a}(window,document),function(e,t){var n=e.okanjo,i=n.util.isMobile(),r=!1,o=void 0,a=void 0,s=void 0,u=void 0,c=void 0,l=void 0,d=void 0,h=void 0,f=void 0,p=function(){o=t.documentElement||t.querySelector("html"),a=t.body||t.querySelector("body"),s=t.createElement("div"),u=t.createElement("div"),c=t.createElement("div"),l=t.createElement("div"),d=t.createElement("div"),h=t.createElement("div"),f=t.createElement("iframe"),s.setAttribute("class","okanjo-modal-container okanjo-modal-hidden "),u.setAttribute("class","okanjo-modal-window"),c.setAttribute("class","okanjo-modal-window-skin"),l.setAttribute("class","okanjo-modal-window-outer"),d.setAttribute("class","okanjo-modal-window-inner"),h.setAttribute("class","okanjo-modal-close-button"),f.setAttribute("class","okanjo-inline-buy-frame"),f.setAttribute("frameborder","0"),f.setAttribute("vspace","0"),f.setAttribute("hspace","0"),f.setAttribute("webkitallowfullscreen",""),f.setAttribute("mozallowfullscreen",""),f.setAttribute("allowfullscreen",""),f.setAttribute("scrolling","auto"),h.innerHTML="×",d.appendChild(f),l.appendChild(d),c.appendChild(l),u.appendChild(c),u.appendChild(h),s.appendChild(u),a.appendChild(s)},g=function(e,t,n){e.addEventListener?e.addEventListener(t,n,!1):e.attachEvent("on"+t,n)},m=function(){return e.innerHeight||t.documentElement.clientHeight},v=function(){u.style.height=m()-80+"px"},y=function(){g(e,"orientationchange",function(){for(var e=0;e<2;e++)setTimeout(v,1e3*e+10)}),g(e,"resize",function(){setTimeout(v,100)}),g(s,"click",w),g(u,"click",function(e){e.preventDefault(),e.stopPropagation()}),g(h,"click",function(e){e.preventDefault(),e.stopPropagation(),w()})},_=function(e,t){e.className+=" "+t},b=function(e,t){e.className=e.className.replace(new RegExp(" *?"+t),"")},k=function(){b(s,"okanjo-modal-hidden"),_(s,"okanjo-modal-fade-out"),v(),_(o,"okanjo-modal-active"),i||_(o,"okanjo-modal-margin-fix"),setTimeout(function(){b(s,"okanjo-modal-fade-out")},10)},w=function(){_(s,"okanjo-modal-fade-out"),setTimeout(function(){b(s,"okanjo-modal-fade-out"),_(s,"okanjo-modal-hidden"),b(o,"okanjo-modal-active"),i||b(o,"okanjo-modal-margin-fix")},210)},j=function(e){d.innerHTML="","string"==typeof e?d.innerHTML=e:d.appendChild(e)};return n.ui.modal={show:function(e){r||(r=!0,p(),y()),j(e),k()},hide:function(){w()}},n.ui.modal}(window,document),function(e,t){var r=e.okanjo,o=function(){function o(){n(this,o),this._queue=this._getStoredQueue(),this._processTimeout=null,this.pageId=r.util.shortid(),this.defaultChannel=o.Channel.external,this.sid=null,this.sourceCh=null,this.sourceCx=null,this._checkUrlForReferral()}return i(o,[{key:"_getStoredQueue",value:function(){if(!e.localStorage[o.Params.queue])return[];try{var t=JSON.parse(e.localStorage[o.Params.queue]);return Array.isArray(t)?t:(r.report("Stored queue is not a queue",{queue:t}),[])}catch(n){return r.report("Failed to load metric queue from storage",{err:n}),[]}}},{key:"_saveQueue",value:function(t){var n=this;t?(this._saveQueueTimeout&&clearTimeout(this._saveQueueTimeout),this._saveQueueTimeout=setTimeout(function(){n._saveQueue(!1),n._saveQueueTimeout=null},100)):e.localStorage[o.Params.queue]=JSON.stringify(this._queue)}},{key:"_checkUrlForReferral",value:function(){var t=r.util.getPageArguments(!0),n=t[o.Params.name],i=e.localStorage[o.Params.name]||r.util.cookie.get(o.Params.name),a=t[o.Params.context],s=t[o.Params.channel];n&&i&&n!==i&&this.trackEvent({object_type:o.Object.metric_session,event_type:o.Event.correlation,id:n+"_"+i,ch:this.defaultChannel,_noProcess:!0}),this.sid=i||n||null,this.sourceCh=s||null,this.sourceCx=a||null}},{key:"trackEvent",value:function(e,t){return e.object_type&&e.event_type?void this._push(e,t):void r.report("Invalid metric to track (missing object_type or event_type)",{event:e})}},{key:"trackPageView",value:function(e,t){e=e||{},e.object_type=o.Object.page,e.event_type=o.Event.view,e.id=e.id||r.util.getLocation(),e.ch=e.ch||this.defaultChannel,this.trackEvent(e,t)}},{key:"_push",value:function(e,t){this._queue.push({event:e,callback:t}),this._saveQueue(!0),e._noProcess?delete e._noProcess:this._processQueue()}},{key:"_processQueue",value:function(){var e=this;!this._processTimeout&&this._queue.length>0&&(this._processTimeout=setTimeout(function(){var t=e._queue.splice(0,255);e._saveQueue(!1),e._batchSend(t,function(n,i){i&&i.data&&i.data.sid&&e._updateSid(i.data.sid),e._processTimeout=null,e._processQueue(),t.forEach(function(e){e.callback&&e.callback(n,i)})})},0))}},{key:"_batchSend",value:function(e,t){var n=this,i=e.map(function(e){return n._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),o={events:i,win:r.util.getLocation()},a=r.net.getRoute(r.net.routes.metrics_batch);this.sid&&(o.sid=this.sid),r.net.request.post(a,o,function(n,i){n&&r.report("Failed to send metrics batch",{err:n,res:i,items:e,route:a}),t&&t(n,i)})}},{key:"_normalizeEvent",value:function(e){e.m=e.m||{},e.key=e.key||e.m.key||r.key||void 0,this.sid&&(e.sid=this.sid),e.m=Object.assign({},e.m),Object.keys(o.Meta.exclude).forEach(function(t){return delete e.m[t]}),this.sourceCh&&(e.m.ref_ch=this.sourceCh),this.sourceCx&&(e.m.ref_cx=this.sourceCx),e.m.pgid=this.pageId,e.m.ok_ver=r.version,e.m=r.util.flatten(e.m,{arrayToCsv:!0}),Object.keys(e.m).forEach(function(t){"string"==typeof e.m[t]&&(e.m[t]=e.m[t].substr(0,255))}),t.referrer&&(e.ref=t.referrer),e.win=r.util.getLocation()}},{key:"_updateSid",value:function(t){!t||this.sid&&this.sid===t||(this.sid=t,e.localStorage[o.Params.name]=t,r.util.cookie.set(o.Params.name,t,o.Params.ttl))}},{key:"create",value:function(){for(var e=arguments.length,t=Array(e),n=0;nt?e:t},f=function(e,t){return"undefined"==typeof e?t:e};return i.forEach(function(e){o=r.ui.getElementPosition(e),a=d(o.x1,a),s=d(o.y1,s),u=h(o.x2,u),c=h(o.y2,c),l.push(o.x1,o.y1,o.x2,o.y2)}),t.m.wix1=f(a,n.x1),t.m.wiy1=f(s,n.y1),t.m.wix2=f(u,n.x2),t.m.wiy2=f(c,n.y2),t.m.wrps=l.map(function(e){return Math.floor(e)}).join(","),t}},{key:"addViewportInfo",value:function(e){var t=r.ui.getViewportSize(),n=r.ui.getScrollPosition();return e=e||{},e.m=e.m||{},e.m.vx1=n.x,e.m.vy1=n.y,e.m.vx2=n.x+t.vw,e.m.vy2=n.y+t.vh,e}},{key:"addEventInfo",value:function(e,t){var n=r.ui.getEventPosition(e);return t=t||{},t.m=t.m||{},t.m.et=n.et,t.m.ex=n.ex,t.m.ey=n.ey,t}},{key:"addEventMeta",value:function(e){e=e||{},e.m=e.m||{};for(var t=arguments.length,n=Array(t>1?t-1:0),i=1;i1?t-1:0),i=1;i=0&&this._events[e].splice(n,1)}}},{key:"emit",value:function(e){var t=void 0,n=void 0,i=void 0,r=[].slice.call(arguments,1);if(this._events[e])for(n=this._events[e].slice(),i=n.length,t=0;t1&&void 0!==arguments[1])||arguments[1];if(!this._strip||!t)return void 0!==e&&this._convert&&(e=this._convert(e)),void 0!==e?e:this._default}}],[{key:"array",value:function(t){return(new e).array(t)}},{key:"string",value:function(){return(new e).string()}},{key:"bool",value:function(){return(new e).bool()}},{key:"strip",value:function(){return(new e).strip()}},{key:"int",value:function(){return(new e)["int"]()}},{key:"float",value:function(){return(new e)["float"]()}}]),e}(),a._Widget=c}(window),function(r){var o=r.okanjo,a=o._Widget.Field,s=a.string,u=a.array,c=a["float"],l=a["int"],d=a.bool,h=o.metrics.constructor,f=o.ui.engine.constructor,p="filters",g="display",m="article_meta",v=.5,y=1e3,_=2,b=function(a){function b(t){var i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};n(this,b),i=o.util.flatten(i,{ignoreArrays:!0});var r=e(this,(b.__proto__||Object.getPrototypeOf(b)).call(this,t,i));return r.name="Placement",r._metricBase={},r._response=null,r._viewWatcherIv=null,r._viewedWatchers=[],i.no_init||r.init(),r}return t(b,a),i(b,[{key:"getSettings",value:function(){return{type:s().group(p),ids:u().group(p),q:s().group(p),url:s().group(p),url_referrer:s().group(p).strip(),url_selectors:s().group(p),url_paths:u().group(p),not_url_paths:u().group(p),organization_id:s().group(p),property_id:s().group(p),store_id:s().group(p),organization_name:s().group(p),property_name:s().group(p),store_name:s().group(p),external_id:s().group(p),sku:s().group(p),external_store_id:s().group(p),condition:s().group(p),manufacturer:s().group(p),upc:s().group(p),isbn:s().group(p),tags:u().group(p),category:u().group(p),pools:u().group(p),min_price:c().group(p),max_price:c().group(p),min_donation_percent:c().group(p),max_donation_percent:c().group(p),donation_to:s().group(p),sort_by:s().group(p),sort_direction:s().group(p),skip:l().group(p),take:l().group(p),placement_tests_only:d(),size:s().group(g),template_name:s().group(g),template_layout:s().group(g),template_theme:s().group(g),template_variant:s().group(g),template_cta_style:s().group(g),template_cta_text:s().group(g),template_cta_color:s().group(g),adx_unit_path:s().group(g),url_category:u().group(m),url_keywords:u().group(m),key:s().strip(),no_init:d().strip(),no_css:d().strip(),proxy_url:s().strip(),expandable:d().strip()["default"](!0),disable_inline_buy:d().strip()["default"](!1),disable_popup:d().strip()["default"](!1),backwards:s().strip(),testing:d().strip()}}},{key:"getConfig",value:function(){var e=this,t=this.getSettings(),n={filters:{},display:{},backfill:{},shortfill:{},article_meta:{}},i=/^backfill_(.+)$/,r=/^shortfill_(.+)$/;return Object.keys(this.config).forEach(function(o){var a=e.config[o],s=o,u=!1,c=!1,l=null,d=i.exec(o);d?(s=d[1],u=!0):(d=r.exec(o),d&&(s=d[1],c=!0)),t[s]&&(a=t[s].value(a),l=t[s].getGroup());var h=n;u?h=n.backfill:c&&(h=n.shortfill),!c&&l&&(h[l]=h[l]||{},h=h[l]),null===a?h[s]="":void 0!==a&&(h[s]=a)}),n}},{key:"load",value:function(){var e=this;this._setMetricBase(),this._fetchContent(function(t){t?e._reportWidgetLoad("fetch failed: "+t.statusCode||t.toString()):(e._mergeResponseSettings(),e._updateBaseMetaFromResponse(),e._showContent())})}},{key:"_setMetricBase",value:function(){var e=this._metricBase;e.ch=h.Channel.placement,e.cx=this.config.backwards||"auto",e.key=this.config.key,e.m=e.m||{},e.m.wgid=this.instanceId,this.config.testing&&(e.env=h.Environment.testing)}},{key:"_reportWidgetLoad",value:function(e){var t=this,n=this._response||{},i=n.data||{results:[]};this._metricBase.m.decl=e||"0",this._metricBase.m.res_bf=i.backfilled?1:0,this._metricBase.m.res_sf=i.shortfilled?1:0,this._metricBase.m.res_spltfl=i.splitfilled?1:0,this._metricBase.m.res_total=i.total||0,this._metricBase.m.res_type=i.type,this._metricBase.m.res_length=i.results.length,o.metrics.create(this._metricBase).type(h.Object.widget,h.Event.impression).meta(this.getConfig()).element(this.element).viewport().widget(this.element).send(),this._addOnceViewedHandler(this.element,function(){o.metrics.create(t._metricBase).type(h.Object.widget,h.Event.view).meta(t.getConfig()).element(t.element).viewport().widget(t.element).send()})}},{key:"_fetchContent",value:function(e){var t=this,n=this.getConfig(),i=this.config.key;o.metrics.sid&&(n.sid=o.metrics.sid),n.filters.url_referrer=this.config.url_referrer||r.location.href,n.wgid=this.instanceId,n.pgid=o.metrics.pageId,o.net.request.post(o.net.getRoute(o.net.routes.ads,null,this.config.sandbox?"sandbox":"live")+"?key="+encodeURIComponent(i),n,function(n,i){n?(o.report("Failed to retrieve placement content",n,{placement:t}),t.setMarkup(""),t.emit("error",n),e&&e(n)):(t._response=i,t.emit("data"),e&&e())})}},{key:"_mergeResponseSettings",value:function(){var e=this,t=this._response,n=t.data||{},i=n.settings||{};i.filters&&Object.keys(i.filters).forEach(function(t){e.config[t]=i.filters[t]}),i.display&&Object.keys(i.display).forEach(function(t){e.config[t]=i.display[t]})}},{key:"_updateBaseMetaFromResponse",value:function(){var e=(this._response||{}).data||{};this._metricBase.m=this._metricBase.m||{};var t=this._metricBase.m;e.article&&(t.aid=e.article.id),e.test&&e.test.enabled?(t.pten=1,t.ptid=e.test.id,t.ptseed=e.test.seed):t.pten=0}},{key:"_showContent",value:function(){var e=(this._response||{}).data||{};if(e.type===b.ContentTypes.products)this._showProducts();else if(e.type===b.ContentTypes.articles)this._showArticles();else if(e.type===b.ContentTypes.adx)this._showADX();else{var t="Unknown response content type: "+e.type;o.report(t,{placement:this}),this.setMarkup(""),this.emit("error",t),this._reportWidgetLoad(t)}}},{key:"_getClickThroughURL",value:function(e,t,n){var i=t.indexOf("?")>=0?"&":"?";return n=n||{},n.ok_msid=o.metrics.sid||"unknown",n.ok_ch=this._metricBase.ch,n.ok_cx=this._metricBase.cx,n._okjr=r.location.href.split(/[?#]/)[0],n.utm_source="okanjo",n.utm_campaign="smartserve",n.utm_medium="smartserve",t+=i+Object.keys(n).map(function(e){return encodeURIComponent(e)+"="+encodeURIComponent(n[e])}).join("&"),this.config.proxy_url&&(t=this.config.proxy_url+encodeURIComponent(t)),e.data({u:t}),e.toUrl()}},{key:"_handleResourceMouseDown",value:function(e,t,n){var i=t._cid,r=o.metrics.create(this._metricBase,{id:t.id}).type(e,h.Event.interaction).meta(this.getConfig()).meta({cid:i}).meta({bf:t.backfill?1:0,sf:t.shortfill?1:0,spltfl_seg:t.splitfill_segment||null}).event(n).element(n.currentTarget).viewport().widget(this.element),a="url_track_param",s="url";e===h.Object.product&&(a="buy_url_track_param",s="buy_url");var u={ok_cid:i};t[a]&&(u[t[a]]=i),r.data({ea:h.Action.click}),n.currentTarget.href=this._getClickThroughURL(r,t[s],u),t._clickId=i,t._event=r,t._additionalParams=u}},{key:"_getTemplate",value:function(e,t){var n=this.config.template_name;return n&&o.ui.engine.isTemplateRegistered(e+"."+n)||(n=t),e+"."+n}},{key:"_enforceLayoutOptions",value:function(){"leaderboard"===this.config.size||"large_mobile_banner"===this.config.size?(this.config.template_layout="list",this.config.template_cta_style="link"):"half_page"!==this.config.size&&"auto"!==this.config.size||(this.config.template_layout="list")}},{key:"_enforceSlabLayoutOptions",value:function(){"medium_rectangle"===this.config.size||"billboard"===this.config.size?(this.config.template_layout="grid","button"===this.config.template_cta_style&&(this.config.template_cta_style="link")):"half_page"===this.config.size?this.config.template_layout="grid":"leaderboard"===this.config.size||"large_mobile_banner"===this.config.size?(this.config.template_layout="list","button"===this.config.template_cta_style&&(this.config.template_cta_style="link")):"auto"===this.config.size?this.config.template_layout="list":"responsive"===this.config.size&&"button"===this.config.template_cta_style&&(this.config.template_cta_style="link")}},{key:"_registerCustomBranding",value:function(){var e=this.config.template_cta_color;if(e){var t=void 0,n="okanjo-wgid-"+this.instanceId;t="\n .okanjo-block2."+n+" .okanjo-resource-cta-button, .okanjo-block2."+n+" .okanjo-resource-buy-button { color: "+e+" !important; } \n .okanjo-block2."+n+".okanjo-cta-style-button .okanjo-resource-cta-button, .okanjo-block2."+n+".okanjo-cta-style-button .okanjo-resource-buy-button { border-color: "+e+" !important; } \n .okanjo-block2."+n+".okanjo-cta-style-button .okanjo-resource-cta-button:hover, .okanjo-block2."+n+".okanjo-cta-style-button .okanjo-resource-buy-button:hover { background: "+e+" !important; color: #fff !important; } \n ", +o.ui.engine.registerCss(n,t,{id:n}),o.ui.engine.ensureCss(n)}}},{key:"_addOnceViewedHandler",value:function(e,t){var n={element:e,successfulCount:0,handler:t};this._viewedWatchers.push(n),this._toggleViewWatcher(!0)}},{key:"_checkViewWatchers",value:function(){for(var e,t=0;t=v&&e.successfulCount++,e.successfulCount>=_&&(e.handler(),this._viewedWatchers.splice(t,1),t--);0===this._viewedWatchers.length&&this._toggleViewWatcher(!1)}},{key:"_toggleViewWatcher",value:function(e){e?null===this._viewWatcherIv&&(this._viewWatcherIv=setInterval(this._checkViewWatchers.bind(this),y/_)):(clearInterval(this._viewWatcherIv),this._viewWatcherIv=null)}},{key:"_showProducts",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},n=this._getTemplate(b.ContentTypes.products,b.DefaultTemplates.products);t.results.forEach(function(t,n){e.config.disable_inline_buy&&(t.inline_buy_url=null),t.inline_buy_url&&(t._escaped_inline_buy_url=encodeURIComponent(t.inline_buy_url)),t._image_url=t.image_urls?t.image_urls[0]:"",t._escaped_buy_url=encodeURIComponent(t.buy_url),t._price_formatted=f.formatCurrency(t.price),t._index=n});var i={css:!this.config.no_css};this.setMarkup(o.ui.engine.render(n,this,i)),0===t.results.length?(this.emit("empty"),this._reportWidgetLoad("empty")):this._reportWidgetLoad(),this.element.querySelectorAll("a").forEach(function(t){var n=t.getAttribute("data-id"),i=t.getAttribute("data-index");if(n&&i>=0){var r=e._response.data.results[i];r&&(t.addEventListener("mousedown",e._handleResourceMouseDown.bind(e,h.Object.product,r)),t.addEventListener("click",e._handleProductClick.bind(e,r)),o.metrics.create(e._metricBase,{id:r.id}).type(h.Object.product,h.Event.impression).meta(e.getConfig()).meta({bf:r.backfill?1:0,sf:r.shortfill?1:0,spltfl_seg:r.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){o.metrics.create(e._metricBase,{id:r.id}).type(h.Object.product,h.Event.view).meta(e.getConfig()).meta({bf:r.backfill?1:0,sf:r.shortfill?1:0,spltfl_seg:r.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(".okanjo-resource-title").forEach(function(e){o.ui.ellipsify(e)}),o.ui.fitImages(this.element),this.emit("load")}},{key:"_handleProductClick",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(h.Object.product,e,t);var n=e._event,i=e._additionalParams;n.event(t);var a=!!e.inline_buy_url,s=!this.config.disable_popup&&a&&o.util.isMobile();if(s){t.preventDefault(),n.data({ea:h.Action.inline_click}).meta({popup:"true"});var u=this._getClickThroughURL(n,e.inline_buy_url,i);this._popupFrame=r.open(u,"okanjo-inline-buy-frame","width=400,height=400,location=yes,resizable=yes,scrollbars=yes"),this._popupFrame||(o.report("Popup blocker stopped buy experience from showing",{placement:this}),r.location.href=u)}else if(a){t.preventDefault();var c=document.createElement("iframe"),l={"class":"okanjo-inline-buy-frame",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:"",mozallowfullscreen:"",allowfullscreen:"",scrolling:"auto"};if(Object.keys(l).forEach(function(e){return c.setAttribute(e,l[e])}),i.expandable=this.config.expandable?1:0,!this.config.expandable){var d=this.element.querySelector(".okanjo-expansion-root");if(d){c.className+=" okanjo-ad-in-unit",c.setAttribute("height","100%"),c.setAttribute("width","100%"),d.appendChild(c);var f=o.ui.getElementSize(d);i.frame_height=f.height,i.frame_width=f.width,this.config.size&&(i.ad_size=this.config.size)}}n.data({ea:h.Action.inline_click}).meta({expandable:this.config.expandable?"true":"false"}),c.src=this._getClickThroughURL(n,e.inline_buy_url,i),c.parentNode||o.ui.modal.show(c)}else t.currentTarget.href=this._getClickThroughURL(n,e.buy_url,i)}},{key:"_showArticles",value:function(){var e=this,t=(this._response||{data:{results:[]}}).data||{results:[]},n=this._getTemplate(b.ContentTypes.articles,b.DefaultTemplates.articles);t.results.forEach(function(e,t){e._escaped_url=encodeURIComponent(e.url),e._index=t});var i={css:!this.config.no_css};this.setMarkup(o.ui.engine.render(n,this,i)),0===t.results.length?(this.emit("empty"),this._reportWidgetLoad("empty")):this._reportWidgetLoad(),this.element.querySelectorAll("a").forEach(function(t){var n=t.getAttribute("data-id"),i=t.getAttribute("data-index");if(n&&i>=0){var r=e._response.data.results[i];r&&(t.addEventListener("mousedown",e._handleResourceMouseDown.bind(e,h.Object.article,r)),t.addEventListener("click",e._handleArticleClick.bind(e,r)),o.metrics.create(e._metricBase,{id:r.id}).type(h.Object.article,h.Event.impression).meta(e.getConfig()).meta({bf:r.backfill?1:0,sf:r.shortfill?1:0,spltfl_seg:r.splitfill_segment||null}).element(t).viewport().widget(e.element).send(),e._addOnceViewedHandler(t,function(){o.metrics.create(e._metricBase,{id:r.id}).type(h.Object.article,h.Event.view).meta(e.getConfig()).meta({bf:r.backfill?1:0,sf:r.shortfill?1:0,spltfl_seg:r.splitfill_segment||null}).element(t).viewport().widget(e.element).send()}))}}),this.element.querySelectorAll(".okanjo-resource-title").forEach(function(e){o.ui.ellipsify(e)}),o.ui.fitImages(this.element),this.emit("load")}},{key:"_handleArticleClick",value:function(e,t){e._event&&e._additionalParams&&e._clickId||this._handleResourceMouseDown(h.Object.article,e,t);var n=e._event,i=e._additionalParams;n.event(t),t.currentTarget.href=this._getClickThroughURL(n,e.url,i)}},{key:"_showADX",value:function(){var e=this,t=(this._response||{data:{settings:{}}}).data||{settings:{}},n=this._getTemplate(b.ContentTypes.adx,b.DefaultTemplates.adx),i=null;if(this.config.size)if(b.Sizes[this.config.size])i=b.Sizes[this.config.size];else{var r=/^([0-9]+)x([0-9]+)$/i.exec(this.config.size);r&&(i={width:r[1],height:r[2]})}i||(i=b.Sizes["default"]);var a="/90447967/okanjo:",s=void 0;t.settings.display&&t.settings.display.adx_unit_path&&(a=t.settings.display.adx_unit_path,s="custom_ad_unit");var u={css:!this.config.no_css,size:i,adUnitPath:a};this.setMarkup(o.ui.engine.render(n,this,u)),this._reportWidgetLoad(s);var c=this.element.querySelector(".okanjo-adx-container");if(c){var l=document.createElement("iframe"),d={"class":"okanjo-adx-frame",frameborder:0,vspace:0,hspace:0,webkitallowfullscreen:"",mozallowfullscreen:"",allowfullscreen:"",scrolling:"auto",width:i.width,height:i.height};Object.keys(d).forEach(function(e){return l.setAttribute(e,d[e])}),c.appendChild(l);var f=o.metrics.create(this._metricBase).type(h.Object.thirdparty_ad,h.Event.interaction).meta(this.getConfig()).meta({ta_s:a,ta_w:i.width,ta_h:i.height}).element(l).viewport().widget(this.element).toUrl();l.contentWindow.trackImpression=function(){o.metrics.create(e._metricBase).type(h.Object.thirdparty_ad,h.Event.impression).meta(e.getConfig()).meta({ta_s:a,ta_w:i.width,ta_h:i.height}).element(l).viewport().widget(e.element).send(),e._addOnceViewedHandler(l,function(){o.metrics.create(e._metricBase).type(h.Object.thirdparty_ad,h.Event.view).meta(e.getConfig()).meta({ta_s:a,ta_w:i.width,ta_h:i.height}).element(l).viewport().widget(e.element).send()})},l.contentWindow.document.open(),l.contentWindow.document.write('\n<'+('script type="text/javascript" src="https://www.googletagservices.com/tag/js/gpt.js">\n googletag.pubads().addEventListener(\'slotRenderEnded\', function(e) { \n trackImpression(e);\n });\n googletag.pubads()\n .definePassback("'+a.replace(/"/g,'\\"')+'", [['+i.width+", "+i.height+']])\n .setClickUrl("'+f+'&u=")\n .display();\n<')+"/script>\n"),l.contentWindow.document.close()}this.emit("load")}}]),b}(o._Widget);return b.Sizes={medium_rectangle:{width:300,height:250},leaderboard:{width:728,height:90},large_mobile_banner:{width:320,height:100},half_page:{width:300,height:600},billboard:{width:970,height:250},button_2:{width:120,height:60},micro_bar:{width:88,height:31},portrait:{width:300,height:1050},rectangle:{width:180,height:150},super_leaderboard:{width:970,height:90},wide_skyscraper:{width:160,height:600},mobile_leaderboard:{width:320,height:50},small_square:{width:200,height:200},button_1:{width:120,height:90},full_banner:{width:468,height:60},half_banner:{width:234,height:60},large_rectangle:{width:336,height:280},pop_under:{width:720,height:300},three_to_one_rectangle:{width:300,height:100},skyscraper:{width:120,height:600},square:{width:250,height:250},square_button:{width:125,height:125},vertical_banner:{width:120,height:240},vertical_rectangle:{width:240,height:400}},b.Sizes["default"]=b.Sizes.medium_rectangle,b.ContentTypes={products:"products",articles:"articles",adx:"adx"},b.DefaultTemplates={products:"block2",articles:"block2",adx:"block2"},o.Placement=b}(window),function(r){var o=r.okanjo,a=function(r){function a(t,i){n(this,a),i=i||{};var r=i.no_init;i.no_init=!0;var s=e(this,(a.__proto__||Object.getPrototypeOf(a)).call(this,t,i));return o.warn("Product widget has been deprecated. Use Placement instead (may require configuration changes)",{widget:s}),r||(delete s.config.no_init,s.init()),s}return t(a,r),i(a,[{key:"_setCompatibilityOptions",value:function(){this.config.backwards="Product",this.config.type=o.Placement.ContentTypes.products,"sense"===this.config.mode?(this.config.url=this.config.url||"referrer",this.config.take=this.config.take||5):"single"===this.config.mode?(this.config.url=null,this.config.id&&(this.config.ids=[this.config.id]),this.config.take=1,delete this.config.id):(this.config.url=null,this.config.take=this.config.take||25),delete this.config.mode,this.config.sold_by&&(this.config.store_name=this.config.sold_by,delete this.config.sold_by),this.config.selectors&&(this.config.url_selectors=this.config.selectors,delete this.config.selectors),this.config.marketplace_id&&(this.config.property_id=this.config.marketplace_id,delete this.config.marketplace_id),"testing"===this.config.marketplace_status&&(this.config.sandbox=!0),delete this.config.marketplace_status,delete this.config.suboptimal,delete this.config.text}}]),a}(o.Placement);return o.Product=a}(window),function(r){var o=r.okanjo,a=function(r){function a(t,i){n(this,a),i=i||{};var r=i.no_init;i.no_init=!0;var s=e(this,(a.__proto__||Object.getPrototypeOf(a)).call(this,t,i));return o.warn("Ad widget has been deprecated. Use Placement instead (may require configuration changes)",{widget:s}),r||(delete s.config.no_init,s.init()),s}return t(a,r),i(a,[{key:"_setCompatibilityOptions",value:function(){this.config.backwards="Ad",this.config.type=o.Placement.ContentTypes.products,this.config.url=null,this.config.id?this.config.ids=[this.config.id]:o.warn("Ad widget should have parameter `id` set."),this.config.take=1,delete this.config.id,delete this.config.content}}]),a}(o.Placement);return o.Ad=a}(window),function(){/*! * mustache.js - Logic-less {{mustache}} templates with JavaScript * http://github.com/janl/mustache.js */ diff --git a/dist/okanjo.min.js.map b/dist/okanjo.min.js.map index f089d5f..31c4109 100644 --- a/dist/okanjo.min.js.map +++ b/dist/okanjo.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["okanjo.js","Array.from.js","Array.prototype.find.js","Array.prototype.findIndex.js","Array.prototype.includes.js","NodeList.prototype.forEach.js","Object.Assign.js","Okanjo.js","Request.js","Cookie.js","TemplateEngine.js","Modal.js","Metrics.js","AutoPageView.js","EventEmitter.js","Widget.js","Placement.js","Product.js","Ad.js","vendor.js"],"names":["root","factory","define","amd","exports","module","okanjo","this","_possibleConstructorReturn","isCallable","self","ReferenceError","call","_inherits","subClass","superClass","TypeError","prototype","Object","create","constructor","value","enumerable","writable","configurable","setPrototypeOf","__proto__","_classCallCheck","Number","instance","Constructor","_createClass","defineProperties","target","props","i","length","descriptor","defineProperty","key","protoProps","staticProps","Array","Symbol","iterator","obj","from","number","toStr","toString","fn","Math","maxSafeInteger","toLength","len","toInteger","isFinite","floor","abs","pow","items","arrayLike","min","max","C","mapFn","T","arguments","A","kValue","k","find","predicate","o","thisArg","findIndex","includes","searchElement","fromIndex","sameValueZero","x","y","isNaN","n","window","NodeList","forEach","callback","assign","varArgs","nextSource","to","index","nextKey","hasOwnProperty","NOOP","document","SUPPORTS_PAGE_OFFSET","undefined","pageXOffset","CSS1_COMPATIBLE","compatMode","AGENT","navigator","userAgent","ELLIPSIFY_PATTERN","MOBILE_PATTERN","Console","console","settings","metrics","report","_len","args","_key","err","Error","messageIndex","arg","stack","split","shift","push","reportStack","join","filter","a","splice","error","version","warn","apply","concat","message","_len2","_key2","selector","parent","qwery","querySelector","querySelectorAll","net","endpoint","sandboxEndpoint","routes","ads","getRoute","route","params","env","request","keys","replace","util","isEmpty","test","val","trim","getPageArguments","query","eqIndex","includeHashArguments","decodeURIComponent","parts","part","indexOf","queryArgs","hashArgs","substring","location","search","hash","mixed","out","map","deepClone","_typeof","options","output","input","isArray","toISOString","childObject","childKey","ignoreArrays","arrayToCsv","flatten","shortid","clusterWorkerId","shuffled","crypto","msCrypto","require","getRandomValues","randomBytes","encode","loopCounter","random","dest","Uint8Array","str","done","randomByte","REDUCE_TIME","seconds","counter","previousSeconds","Date","getTime","getLocation","referrer","href","ui","getScrollPosition","documentElement","scrollLeft","body","getElementSize","element","scrollTop","includeMargin","size","height","offsetHeight","width","offsetWidth","style","currentStyle","getComputedStyle","parseInt","marginTop","marginBottom","getPageSize","marginLeft","marginRight","html","getViewportSize","scrollWidth","clientWidth","clientHeight","scrollHeight","vh","isMobileZoom","inWidth","innerWidth","inHeight","innerHeight","getEventPosition","ex","et","event","ey","el","type","name","getElementPosition","clientX","clientY","rect","getBoundingClientRect","y2","x1","left","contains","y1","x2","top","right","bottom","e","exception","elementArea","iLeft","s","iRight","v","vw","iTop","iBottom","intersectionArea","isElementVisible","getPercentageInViewport","_okanjo$ui$_getInters","_getIntersection","replacedText","container","substr","parentNode","targetHeight","useTextContent","textContent","text","innerText","safety","replacer","match","span","createElement","content","setAttribute","innerHTML","fitImages","appendChild","backgroundImage","src","img","display","backgroundposition","method","url","payload","res","ActiveXObject","calledBack","req","timeout","ontimeout","attributes","statusCode","onreadystatechange","status","data","JSON_TEST","getResponseHeader","parse","responseText","xhr","toUpperCase","open","withCredentials","setRequestHeader","post","send","get","bind","encodeURIComponent","getKey","keyPrefix","stringify","pairs","expireDate","setDate","set","cookieName","expireDays","getDate","expires","toUTCString","path","secure","protocol","cookieValue","cookie","nameTest","decodeURI","TemplateEngine","_templates","_css","classDetects","template","beforeRender","nodeType","lib","Mustache","markup","css","head","id","styleSheet","cssText","templateName","context","model","_this","okanjoMetricUrl","now","blockClasses","ensureCss","render","formatCurrency","decimals","decimalSeparator","toFixed","j","thousandsSeparator","slice","engine","$modalContainer","$modalWindow","isMobile","$modalOuter","$html","$body","$modalSkin","$modalInner","$modalClose","$modalFrame","addListener","addEventListener","attachEvent","getWindowHeight","handler","setTimeout","handleReposition","t","closeModal","stopPropagation","preventDefault","removeClass","addClass","className","RegExp","openModal","IS_MOBILE","setContent","initialized","show","createElements","bindEvents","modal","hide","Metrics","sourceCh","_getStoredQueue","sourceCx","pageId","defaultChannel","Channel","external","sid","_checkUrlForReferral","queue","Params","JSON","localStorage","delay","_this2","_saveQueueTimeout","clearTimeout","_saveQueue","_queue","object_type","metric_session","event_type","Event","correlation","urlSid","_noProcess","sourceChannel","pageArgs","channel","localSid","trackEvent","sourceContext","ch","_push","page","view","_processQueue","_this3","_processTimeout","_batchSend","_updateSid","item","_this4","events","win","metrics_batch","m","exclude","Meta","ok_ver","pgid","ref","ttl","_len3","_key3","pw","w","ph","h","containerSize","resources","wix2","wiy2","boxes","getMin","getMax","wix1","fallback","current","wiy1","_fallback","wrps","vp","pos","vx1","vy1","vx2","vy2","jsEvent","_len4","_key4","_len5","_key5","MetricEvent","impression","interaction","Action","click","inline_click","article","thirdparty_ad","cart","order","order_item","user","widget","product","store","cause","marketplace","placement","live","testing","store_widget","Environment","others","_this5","_data","addEventInfo","addViewportInfo","_element","addElementInfo","addWidgetInfo","_len6","_key6","addEventMeta","_normalizeEvent","trackPageView","EventEmitter","_events","listener","idx","listeners","_arguments","_this6","removeListener","_EventEmitter","on","DATA_REPLACE_PATTERN","Widget","DATA_ATTRIBUTE_PATTERN","getPrototypeOf","_this7","instanceId","config","_applyConfiguration","_setCompatibilityOptions","_ensurePlacementKey","load","_this8","normalizedKey","_default","_this9","group","origKey","getGroup","showError","setMarkup","attr","exec","Field","_convert","_strip","_group","converter","toLowerCase","parseFloat","strip","bool","int","float","FILTERS","_Widget","DISPLAY","string","ARTICLE_META","array","_okanjo$_Widget$Field","MINIMUM_VIEW_PX","MINIMUM_VIEW_TIME","Placement","MINIMUM_VIEW_FREQ","_metricBase","_viewedWatchers","_this10","_response","_viewWatcherIv","no_init","init","_okanjo$_Widget","q","url_referrer","not_url_paths","organization_id","organization_name","property_name","store_name","external_id","sku","external_store_id","condition","manufacturer","upc","tags","category","min_price","max_price","isbn","max_donation_percent","pools","sort_by","min_donation_percent","skip","donation_to","template_theme","template_variant","template_cta_color","url_category","url_keywords","proxy_url","expandable","default","backwards","disable_inline_buy","disable_popup","_this11","isBackfill","getSettings","filters","backfill","shortfill","article_meta","backfillPattern","shortfillPattern","matches","isShortfill","_this12","_setMetricBase","_fetchContent","_reportWidgetLoad","_mergeResponseSettings","_updateBaseMetaFromResponse","_showContent","base","cx","wgid","_this13","res_type","decl","declined","res_bf","backfilled","res_sf","shortfilled","_addOnceViewedHandler","res_length","results","meta","getConfig","viewport","emit","sandbox","_this14","_this15","ptseed","pten","aid","enabled","ptid","seed","msg","ContentTypes","products","articles","adx","_showADX","additionalUrlParams","joiner","ok_msid","_okjr","utm_source","utm_campaign","u","toUrl","bf","sf","resource","clickId","_cid","urlParam","cid","trackParam","spltfl_seg","splitfill_segment","currentTarget","ok_cid","ea","_event","additionalParams","_getClickThroughURL","_clickId","_additionalParams","contentType","defaultName","template_name","isTemplateRegistered","template_layout","template_cta_style","brandColor","brandCSS","brandCSSId","registerCss","controller","successfulCount","_toggleViewWatcher","setInterval","_checkViewWatchers","clearInterval","inline_buy_url","_getTemplate","DefaultTemplates","offer","_price_formatted","price","_index","_escaped_inline_buy_url","_image_url","image_urls","_escaped_buy_url","buy_url","getAttribute","_this16","_handleResourceMouseDown","_handleProductClick","ellipsify","showNativeBuyUx","showPopupNativeBuyUx","popup","_popupFrame","vspace","allowfullscreen","frame","class","hspace","webkitallowfullscreen","mozallowfullscreen","scrolling","frame_height","ad_size","_escaped_url","_this17","_handleArticleClick","_this18","Sizes","adUnitPath","declineReason","adx_unit_path","renderContext","frameborder","ta_w","ta_h","ta_s","contentWindow","write","clickUrl","close","button_2","rectangle","super_leaderboard","wide_skyscraper","half_page","billboard","micro_bar","button_1","full_banner","half_banner","large_rectangle","skyscraper","square","vertical_rectangle","three_to_one_rectangle","square_button","vertical_banner","medium_rectangle","Product","_okanjo$Placement","_this19","ids","mode","take","sold_by","url_selectors","marketplace_id","selectors","marketplace_status","property_id","suboptimal","Ad","_okanjo$Placement2","_this20","global","objectToString","nodeName","isFunction","object","mustache","typeStr","escapeRegExp","hasProperty","propName","nonSpaceRe","testRegExp","re","regExpTest","isWhitespace","tagRe","String","entityMap","parseTemplate","nonSpace","hasTag","spaces","closingTagRe","closingCurlyRe","openingTagRe","compileTags","tagsToCompile","spaceRe","start","scanner","stripSpace","sections","tokens","chr","token","openSection","valueLength","scanUntil","charAt","equalsRe","scan","curlyRe","pop","squashedTokens","lastToken","numTokens","nestedTokens","nestTokens","section","collector","Scanner","tail","Context","parentContext","cache",".","Writer","&","escapeHtml","<",">","\"","'","/","whiteRe","eos","lookupHit","names","partials","renderTokens","originalTemplate","symbol","buffer","renderSection","renderInverted","renderPartial","unescapedValue","escapedValue","rawValue","subRender","lookup","escape","clearCache","defaultWriter","to_html","result"],"mappings":"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","file":"okanjo.min.js","sourcesContent":["/*! okanjo-js v1.19.1 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */\n(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.okanjo = factory();\n }\n}(this, function() {\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n// Production steps of ECMA-262, Edition 6, 22.1.2.1\nif (!Array.from) {\n Array.from = function () {\n var toStr = Object.prototype.toString;\n var isCallable = function isCallable(fn) {\n return typeof fn === 'function' || toStr.call(fn) === '[object Function]';\n };\n var toInteger = function toInteger(value) {\n var number = Number(value);\n if (isNaN(number)) {\n return 0;\n }\n if (number === 0 || !isFinite(number)) {\n return number;\n }\n return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));\n };\n var maxSafeInteger = Math.pow(2, 53) - 1;\n var toLength = function toLength(value) {\n var len = toInteger(value);\n return Math.min(Math.max(len, 0), maxSafeInteger);\n };\n\n // The length property of the from method is 1.\n return function from(arrayLike /*, mapFn, thisArg */) {\n // 1. Let C be the this value.\n var C = this;\n\n // 2. Let items be ToObject(arrayLike).\n var items = Object(arrayLike);\n\n // 3. ReturnIfAbrupt(items).\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object - not null or undefined');\n }\n\n // 4. If mapfn is undefined, then let mapping be false.\n var mapFn = arguments.length > 1 ? arguments[1] : void undefined;\n var T;\n if (typeof mapFn !== 'undefined') {\n // 5. else\n // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.\n if (!isCallable(mapFn)) {\n throw new TypeError('Array.from: when provided, the second argument must be a function');\n }\n\n // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.\n if (arguments.length > 2) {\n T = arguments[2];\n }\n }\n\n // 10. Let lenValue be Get(items, \"length\").\n // 11. Let len be ToLength(lenValue).\n var len = toLength(items.length);\n\n // 13. If IsConstructor(C) is true, then\n // 13. a. Let A be the result of calling the [[Construct]] internal method\n // of C with an argument list containing the single item len.\n // 14. a. Else, Let A be ArrayCreate(len).\n var A = isCallable(C) ? Object(new C(len)) : new Array(len);\n\n // 16. Let k be 0.\n var k = 0;\n // 17. Repeat, while k < len… (also steps a - h)\n var kValue;\n while (k < len) {\n kValue = items[k];\n if (mapFn) {\n A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);\n } else {\n A[k] = kValue;\n }\n k += 1;\n }\n // 18. Let putStatus be Put(A, \"length\", len, true).\n A.length = len;\n // 20. Return A.\n return A;\n };\n }();\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.find\nif (!Array.prototype.find) {\n Object.defineProperty(Array.prototype, 'find', {\n value: function value(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return kValue.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return kValue;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return undefined.\n return undefined;\n }\n });\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex\nif (!Array.prototype.findIndex) {\n Object.defineProperty(Array.prototype, 'findIndex', {\n value: function value(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return k.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return k;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return -1.\n return -1;\n }\n });\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.includes\nif (!Array.prototype.includes) {\n Object.defineProperty(Array.prototype, 'includes', {\n value: function value(searchElement, fromIndex) {\n\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n // 1. Let O be ? ToObject(this value).\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If len is 0, return false.\n if (len === 0) {\n return false;\n }\n\n // 4. Let n be ? ToInteger(fromIndex).\n // (If fromIndex is undefined, this step produces the value 0.)\n var n = fromIndex | 0;\n\n // 5. If n ≥ 0, then\n // a. Let k be n.\n // 6. Else n < 0,\n // a. Let k be len + n.\n // b. If k < 0, let k be 0.\n var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\n\n function sameValueZero(x, y) {\n return x === y || typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y);\n }\n\n // 7. Repeat, while k < len\n while (k < len) {\n // a. Let elementK be the result of ? Get(O, ! ToString(k)).\n // b. If SameValueZero(searchElement, elementK) is true, return true.\n if (sameValueZero(o[k], searchElement)) {\n return true;\n }\n // c. Increase k by 1.\n k++;\n }\n\n // 8. Return false\n return false;\n }\n });\n}\n// https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach\nif (window.NodeList && !NodeList.prototype.forEach) {\n NodeList.prototype.forEach = function (callback, thisArg) {\n thisArg = thisArg || window;\n for (var i = 0; i < this.length; i++) {\n callback.call(thisArg, this[i], i, this);\n }\n };\n}\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\nif (typeof Object.assign != 'function') {\n // Must be writable: true, enumerable: false, configurable: true\n Object.defineProperty(Object, \"assign\", {\n value: function assign(target, varArgs) {\n // .length of function is 2\n 'use strict';\n\n if (target == null) {\n // TypeError if undefined or null\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n var to = Object(target);\n\n for (var index = 1; index < arguments.length; index++) {\n var nextSource = arguments[index];\n\n if (nextSource != null) {\n // Skip over if undefined or null\n for (var nextKey in nextSource) {\n // Avoid bugs when hasOwnProperty is shadowed\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n },\n writable: true,\n configurable: true\n });\n}\n\"use strict\";\n\n/* exported okanjo */\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/**\n * Okanjo widget framework namespace\n * @global okanjo\n */\nvar okanjo = function (window, document) {\n\n //region Constants\n\n // Environment Vars\n var SUPPORTS_PAGE_OFFSET = window.pageXOffset !== undefined;\n var CSS1_COMPATIBLE = (document.compatMode /* istanbul ignore next: out of scope */ || \"\") === \"CSS1Compat\";\n var AGENT = window.navigator.userAgent;\n var ELLIPSIFY_PATTERN = /[\\s\\S](?:\\.\\.\\.)?$/;\n var MOBILE_PATTERN = /(iPhone|iPad|iPod|Android|blackberry)/i;\n var NOOP = function NOOP() {};\n var Console = window.console;\n\n // Place to pull defaults, if already set\n var settings = window.okanjo || {};\n\n //endregion\n\n //region Okanjo Core\n\n\n //noinspection JSValidateJSDoc,JSClosureCompilerSyntax - idk phpStorm generated it so why would it be wrong? :P\n /**\n * Okanjo namespace\n * @global\n * @type {{version: string, metrics: null, key: null, report: ((...p1?:*[])), warn: ((p1?:*, ...p2?:*[])), qwery: ((p1?:*, p2?:*))}}\n */\n var okanjo = {\n\n /**\n * Okanjo version\n */\n version: \"1.19.1\",\n\n /**\n * Placeholder\n */\n metrics: null,\n\n /**\n * Global/default placement key\n */\n key: settings.key || null,\n\n /**\n * Reports an error to the console and possibly Raven in the future\n * @param args\n */\n report: function report() {\n for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n var err = args.find(function (arg) {\n return arg instanceof Error;\n });\n if (!err) {\n var messageIndex = args.findIndex(function (arg) {\n return typeof arg === \"string\";\n });\n err = new Error(args[messageIndex] || \"Okanjo Error\");\n if (messageIndex >= 0) args.splice(messageIndex, 1);\n } else {\n // Grow our own stack so we can figure out what async thing did it\n var stack = new Error().stack.split('\\n');\n stack.shift();\n stack.shift();\n args.push({ reportStack: stack.join('\\n') });\n args = args.filter(function (a) {\n return a !== err;\n });\n }\n\n Console.error('[Okanjo v' + okanjo.version + ']: ' + err.stack);\n args.length && Console.error.apply(Console, ['Additional information:'].concat(args));\n\n // TODO - integrate with Raven\n },\n\n /**\n * Warn developers of their misdeeds\n * @param message\n * @param args\n */\n warn: function warn(message) {\n for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n\n var err = new Error(message);\n\n Console.warn('[Okanjo v' + okanjo.version + ']: ' + err.stack);\n args.length && Console.warn.apply(Console, ['Additional information:'].concat(args));\n },\n\n // Backwards compatibility when we shipped with qwery, cuz querySelector[All] wasn't mainstream enough\n qwery: function qwery(selector, parent) {\n\n // If parent is a selector, select the parent first!\n if (typeof parent === \"string\") {\n parent = document.querySelector(parent);\n\n // If parent is not found, there are obviously no results\n if (!parent) return [];\n }\n\n if (!parent) parent = document;\n\n return parent.querySelectorAll(selector);\n }\n };\n\n //endregion\n\n //region Vendor Libs\n\n /**\n * Placeholder for where vendor libraries get no-conflict loaded\n * @type {{}}\n */\n okanjo.lib = {};\n\n //endregion\n\n //region Networking\n\n /**\n * Networking methods\n * @type {{getRoute: *, exec: *}}\n */\n okanjo.net = {\n\n /**\n * API Endpoints\n */\n endpoint: 'https://api2.okanjo.com',\n sandboxEndpoint: 'https://sandbox-api2.okanjo.com',\n\n /**\n * API routes\n */\n routes: {\n ads: '/content',\n metrics: '/metrics/:object_type/:event_type',\n metrics_batch: '/metrics'\n },\n\n /**\n * Compiles a route and parameters into a final URL\n * @param {string} route - Route constant\n * @param {*} [params] - Key value hash\n * @param {*} [env] - Optional environment to use instead of live\n * @return {string} - Route\n */\n getRoute: function getRoute(route, params, env) {\n if (params) {\n Object.keys(params).forEach(function (key) {\n route = route.replace(':' + key, params[key] + \"\");\n });\n }\n env = env || okanjo.env || 'live';\n return (env === 'sandbox' ? okanjo.net.sandboxEndpoint : okanjo.net.endpoint) + route;\n },\n\n // placeholder, xhr request extension\n request: NOOP\n };\n\n //endregion\n\n // region Utilities\n\n //noinspection JSClosureCompilerSyntax,JSValidateJSDoc\n /**\n * Utility functions and helpers\n * @type {{isEmpty: ((p1?:*)=>boolean), isMobile: (()), getPageArguments: ((p1:boolean))}}\n */\n okanjo.util = {\n\n /**\n * Checks whether a value is _really_ empty (trims)\n * @param val\n * @return {boolean}\n */\n isEmpty: function isEmpty(val) {\n return val === null || val === undefined || typeof val === \"string\" && val.trim().length === 0;\n },\n\n /**\n * Checks if the current user agent identifies as a mobile device\n * @returns {boolean}\n */\n isMobile: function isMobile() {\n // KludgyAF™, but let's go with it\n return MOBILE_PATTERN.test(AGENT);\n },\n\n /**\n * Returns an object hashmap of query and hash parameters\n * @param {boolean} includeHashArguments - Whether to include the hash arguments, if any\n * @return {*}\n */\n getPageArguments: function getPageArguments(includeHashArguments) {\n\n var split = function split(query) {\n query = query || \"\";\n var params = {};\n var parts = query.split('&');\n parts.forEach(function (part) {\n var eqIndex = part.indexOf('=');\n var key = void 0,\n value = void 0;\n if (eqIndex < 0) {\n key = decodeURIComponent(part);\n value = null;\n } else {\n key = decodeURIComponent(part.substring(0, eqIndex));\n value = decodeURIComponent(part.substring(eqIndex + 1));\n }\n if (key) params[key] = value;\n });\n return params;\n };\n\n var queryArgs = split(window.location.search.substring(window.location.search.indexOf('?') + 1));\n var hashArgs = includeHashArguments ? split(window.location.hash.substring(Math.max(window.location.hash.indexOf('#') + 1, window.location.hash.indexOf('#!') + 2))) : {};\n Object.keys(hashArgs).forEach(function (key) {\n return queryArgs[key] = hashArgs[key];\n });\n\n return queryArgs;\n }\n\n };\n\n /**\n * Deep clones an object by breaking references, unlike Object.assign\n * @param mixed – Source to clone (object, array, value)\n * @param [out] - Existing output, if any\n * @return {*}\n */\n okanjo.util.deepClone = function (mixed, out) {\n if (Array.isArray(mixed)) {\n // Array reference\n out = out || [];\n out = out.concat(mixed.map(function (val) {\n return okanjo.util.deepClone(val);\n }));\n } else if ((typeof mixed === 'undefined' ? 'undefined' : _typeof(mixed)) === \"object\" && mixed !== null) {\n // Object reference\n out = out || {};\n Object.keys(mixed).forEach(function (key) {\n out[key] = okanjo.util.deepClone(mixed[key]);\n });\n } else {\n // Value\n out = mixed;\n }\n\n return out;\n };\n\n /**\n * Flattens a multi-dimensional object into a single object\n * @param input\n * @param [options]\n * @return {{}}\n */\n okanjo.util.flatten = function (input) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n var output = {};\n\n if (input !== undefined && input !== null) {\n Object.keys(input).forEach(function (key) {\n // Convert object ids to hex strings\n if (input[key] instanceof Date) {\n if (options.dateToIso) {\n output[key] = input[key].toISOString(); // convert to iso\n } else {\n output[key] = input[key]; // as-is\n }\n } else if (_typeof(input[key]) === 'object' && input[key] !== null) {\n // Allow ignoring arrays if desired\n if (Array.isArray(input[key]) && options.ignoreArrays === true) {\n output[key] = input[key];\n } else if (Array.isArray(input[key]) && options.arrayToCsv === true) {\n output[key] = input[key].join(',');\n } else {\n // Make child objects flat too (always returns object so Object.keys is safe)\n var childObject = okanjo.util.flatten(input[key], options);\n Object.keys(childObject).forEach(function (childKey) {\n output[key + '_' + childKey] = childObject[childKey];\n });\n }\n } else {\n // Copy value references\n output[key] = input[key];\n }\n });\n }\n\n return output;\n };\n\n /*! based on shortid https://github.com/dylang/shortid */\n okanjo.util.shortid = function (clusterWorkerId) {\n\n var shuffled = 'ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC',\n crypto = window.crypto || window.msCrypto || typeof require === \"function\" && require('crypto'),\n randomByte = function randomByte() {\n /* istanbul ignore next: platform diffs out of scope */\n if (crypto && crypto.randomBytes) {\n return crypto.randomBytes(1)[0] & 0x30;\n } else if (!crypto || !crypto.getRandomValues) {\n return Math.floor(Math.random() * 256) & 0x30;\n }\n /* istanbul ignore next: platform diffs out of scope */\n var dest = new Uint8Array(1);\n /* istanbul ignore next: platform diffs out of scope */\n crypto.getRandomValues(dest);\n /* istanbul ignore next: platform diffs out of scope */\n return dest[0] & 0x30;\n },\n encode = function encode(number) {\n var loopCounter = 0,\n done = void 0,\n str = '';\n\n while (!done) {\n str = str + shuffled[number >> 4 * loopCounter & 0x0f | randomByte()];\n done = number < Math.pow(16, loopCounter + 1);\n loopCounter++;\n }\n return str;\n },\n\n\n // Ignore all milliseconds before a certain time to reduce the size of the date entropy without sacrificing uniqueness.\n // This number should be updated every year or so to keep the generated id short.\n // To regenerate `new Date() - 0` and bump the version. Always bump the version!\n\n REDUCE_TIME = 1490384907498,\n version = 7;\n\n var counter = void 0,\n previousSeconds = void 0;\n\n clusterWorkerId = clusterWorkerId || 0;\n\n return function () {\n var str = '',\n seconds = Math.floor((new Date().getTime() - REDUCE_TIME) * 0.001);\n\n if (seconds === previousSeconds) {\n counter++;\n } else {\n counter = 0;\n previousSeconds = seconds;\n }\n\n str = str + encode(version) + encode(clusterWorkerId);\n if (counter > 0) {\n str = str + encode(counter);\n }\n str = str + encode(seconds);\n\n return str;\n };\n }();\n\n /**\n * Gets the best URL for where we are operating\n * @returns {string|*}\n */\n okanjo.util.getLocation = function () {\n return window.location !== window.parent.location ? /* istanbul ignore next: oos */document.referrer : document.location.href;\n };\n\n //endregion\n\n //region User Interface\n\n okanjo.ui = {\n\n /**\n * Gets the current page scroll position\n * @returns {{x: Number, y: Number}}\n */\n getScrollPosition: function getScrollPosition() {\n return {\n x: SUPPORTS_PAGE_OFFSET ? window.pageXOffset : /* istanbul ignore next: old browsers */CSS1_COMPATIBLE ? document.documentElement.scrollLeft : document.body.scrollLeft,\n y: SUPPORTS_PAGE_OFFSET ? window.pageYOffset : /* istanbul ignore next: old browsers */CSS1_COMPATIBLE ? document.documentElement.scrollTop : document.body.scrollTop\n };\n },\n\n /**\n * Gets the height and width of the given element\n * @param {HTMLElement|Node} element – The DOM element to get the size of\n * @param {boolean} [includeMargin] – Whether to include the margins of the element in the size\n * @returns {{height: number, width: number}}\n */\n getElementSize: function getElementSize(element, includeMargin) {\n var size = {\n height: element.offsetHeight,\n width: element.offsetWidth\n };\n var style = element.currentStyle || window.getComputedStyle(element);\n\n if (includeMargin) {\n size.height += parseInt(style.marginTop) + parseInt(style.marginBottom);\n size.width += parseInt(style.marginLeft) + parseInt(style.marginRight);\n }\n\n return size;\n },\n\n /**\n * Gets the current page size\n * @return {{w: number, h: number}}\n */\n getPageSize: function getPageSize() {\n var body = document.querySelector('body');\n var html = document.documentElement;\n\n return {\n w: Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth),\n\n h: Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight)\n };\n },\n\n /**\n * Gets the current viewport size\n * @return {{vw: number, vh: number}}\n */\n getViewportSize: function getViewportSize() {\n var element = CSS1_COMPATIBLE ? document.documentElement /* istanbul ignore next: browser diffs */ : document.body;\n var width = element.clientWidth;\n var height = element.clientHeight;\n var inWidth = window.innerWidth /* istanbul ignore next: browser diffs */ || 0;\n var inHeight = window.innerHeight /* istanbul ignore next: browser diffs */ || 0;\n var isMobileZoom = inWidth && width > inWidth || inHeight && height > inHeight;\n\n return {\n vw: isMobileZoom /* istanbul ignore next: browser diffs */ ? inWidth : width,\n vh: isMobileZoom /* istanbul ignore next: browser diffs */ ? inHeight : height\n };\n },\n\n /**\n * Gets the x, y location of the event relative to the page\n * @param event – Mouse/Touch Event\n * @return {{ex: number, ey: number}}\n */\n getEventPosition: function getEventPosition(event) {\n var ex = event.pageX;\n var ey = event.pageY;\n var body = document.body;\n var el = document.documentElement;\n var scrollLeft = 'scrollLeft';\n var scrollTop = 'scrollTop';\n var type = event.__proto__.constructor.name;\n\n return {\n et: type, // mouse? touch? keyboard? robot?\n ex: ex === undefined /* istanbul ignore next: browser diffs */ ? event.clientX + body[scrollLeft] + el[scrollLeft] : ex,\n ey: ey === undefined /* istanbul ignore next: browser diffs */ ? event.clientY + body[scrollTop] + el[scrollTop] : ey\n };\n },\n\n /**\n * Gets the element's rectangle coordinates on the page\n * @param element\n * @return {{x1: number, y1: number, x2: number, y2: number}}\n */\n getElementPosition: function getElementPosition(element) {\n\n // Wrapped in try-catch because IE is super strict about the\n // element being on the DOM before you call this. Other browsers\n // let it slide, but oh well.\n\n var err = 'Could not get position of element. Did you attach the element to the DOM before initializing?';\n try {\n var rect = element.getBoundingClientRect();\n var body = document.body.getBoundingClientRect();\n // let pos = okanjo.ui.getScrollPosition();\n\n /* istanbul ignore else: jsdom doesn't mock this */\n if (!document.body.contains(element)) {\n okanjo.report(err, element);\n }\n return {\n // x1: rect.left + pos.x,\n // y1: rect.top + pos.y,\n // x2: rect.right + pos.x,\n // y2: rect.bottom + pos.y\n\n // This might fix\n x1: rect.left - body.left,\n y1: rect.top - body.top,\n x2: rect.right - body.left,\n y2: rect.bottom - body.top\n\n };\n } catch (e) {\n okanjo.report(err, { exception: e, element: element });\n return {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: 0,\n err: 1\n };\n }\n },\n\n /**\n * Gets the intersection information given the element, viewport and scroll positions\n * @param e – Element position\n * @param s - Scroll position\n * @param v - Viewport size\n * @return {{intersectionArea: number, elementArea: number}}\n * @private\n */\n _getIntersection: function _getIntersection(e, s, v) {\n var iLeft = Math.max(e.x1, s.x),\n iRight = Math.min(e.x2, s.x + v.vw),\n iTop = Math.max(e.y1, s.y),\n iBottom = Math.min(e.y2, s.y + v.vh),\n intersectionArea = Math.max(0, iRight - iLeft) * Math.max(0, iBottom - iTop),\n elementArea = (e.x2 - e.x1) * (e.y2 - e.y1);\n\n return {\n intersectionArea: intersectionArea,\n elementArea: elementArea\n };\n },\n\n /**\n * Checks whether the element is actually displayed on the DOM\n * @param element\n * @return {boolean}\n */\n isElementVisible: function isElementVisible(element) {\n /* istanbul ignore next: jsdom won't trigger this */\n return element.offsetWidth > 0 && element.offsetHeight > 0;\n },\n\n /**\n * Gets the percentage of the element pixels currently within the viewport\n * @param {HTMLElement|Node} element\n * @return {number}\n */\n getPercentageInViewport: function getPercentageInViewport(element) {\n var e = okanjo.ui.getElementPosition(element),\n s = okanjo.ui.getScrollPosition(),\n v = okanjo.ui.getViewportSize();\n\n // If there was a problem getting the element position, fail fast\n if (e.err) return 0;\n\n // Get intersection rectangle\n\n var _okanjo$ui$_getInters = okanjo.ui._getIntersection(e, s, v),\n intersectionArea = _okanjo$ui$_getInters.intersectionArea,\n elementArea = _okanjo$ui$_getInters.elementArea;\n\n // Don't let it return NaN\n /* istanbul ignore else: jsdom no love positional data */\n\n\n if (elementArea <= 0) return 0;\n\n /* istanbul ignore next: jsdom no love positional data, area tested with helper fn tho */\n return intersectionArea / elementArea;\n }\n };\n\n /**\n * Splits the text in the element to fit within the visible height of its container, and separates with an ellipses\n * @param {HTMLElement|Node} element – The DOM element containing the text to fit\n * @param {HTMLElement} [container] – Optional container to compute fit on. Defaults to the element's parent\n */\n okanjo.ui.ellipsify = function (element, container) {\n\n // It's a sad day when you have to resort to JS because CSS kludges are too hacky to work down to IE8, programmatically\n\n //noinspection JSValidateTypes\n var parent = container || element.parentNode,\n targetHeight = okanjo.ui.getElementSize(parent).height,\n useTextContent = element.textContent !== undefined;\n\n var text = useTextContent ? element.textContent /* istanbul ignore next: browser diffs */ : element.innerText,\n replacedText = \"\",\n safety = 5000,\n // Safety switch to bust out of the loop in the event something goes terribly wrong\n replacer = function replacer(match) {\n /* istanbul ignore next: n/a to jsdom */\n replacedText = match.substr(0, match.length - 3) + replacedText;\n /* istanbul ignore next: n/a to jsdom */\n return '...';\n };\n\n // Trim off characters until we can fit the text and ellipses\n // If the text already fits, this loop is ignored\n /* istanbul ignore next: jsdom doesn't do element size computing stuff */\n while (okanjo.ui.getElementSize(element).height > targetHeight && text.length > 0 && safety-- > 0) {\n text = useTextContent ? element.textContent : element.innerText;\n\n text = text.replace(ELLIPSIFY_PATTERN, replacer);\n\n if (useTextContent) {\n element.textContent = text;\n } else {\n element.innerText = text;\n }\n }\n\n // If there is work to do, split the content into two span tags\n // Like so: [content]...[hidden content]\n /* istanbul ignore if: n/a to jsdom */\n if (replacedText.length > 0) {\n\n var content = document.createElement('span'),\n span = document.createElement('span');\n\n content.setAttribute('class', 'okanjo-ellipses');\n span.setAttribute('class', 'okanjo-visually-hidden');\n\n if (useTextContent) {\n content.textContent = text.substr(0, text.length - 3);\n span.textContent = replacedText;\n } else {\n content.innerText = text.substr(0, text.length - 3);\n span.innerText = replacedText;\n }\n\n element.innerHTML = '';\n element.appendChild(content);\n element.appendChild(span);\n }\n };\n\n /**\n * Locates images with the class okanjo-fit and ensures that they get filled.\n * This is basically a object-fit hacky workaround\n * @param element\n */\n okanjo.ui.fitImages = function (element) {\n // Detect objectFit support\n /* istanbul ignore else: n/a to jsdom */\n if ('objectFit' in document.documentElement.style === false) {\n // Find images to fit\n element.querySelectorAll('img.okanjo-fit').forEach(function (img) {\n\n // Hide the image\n img.style.display = 'none';\n\n // Update the parent w/ the background\n var parent = img.parentNode;\n parent.style.backgroundSize = 'cover';\n parent.style.backgroundImage = 'url(' + img.src + ')';\n parent.style.backgroundposition = 'center center';\n });\n }\n };\n\n //endregion\n\n // Export the root namespace\n return window.okanjo = okanjo;\n}(window, document);\n\"use strict\";\n\n(function (window) {\n\n var JSON_TEST = /^application\\/json/;\n var okanjo = window.okanjo;\n\n /**\n * Performs a reliable XHR request\n * @param {string} method - Request method\n * @param {string} url - URL\n * @param [payload] optional payload\n * @param callback Fired on when completed (err, res), normalized to standard response format\n */\n okanjo.net.request = function (method, url, payload, callback) {\n\n // payload is not required\n if (typeof payload === \"function\") {\n callback = payload;\n payload = undefined;\n }\n\n // Create a new instance\n var req = new (window.XMLHttpRequest /* istanbul ignore next: old ie */ || window.ActiveXObject)('MSXML2.XMLHTTP.3.0');\n\n // Flag to prevent duplicate callbacks / races\n var calledBack = false;\n\n // Normalized done handler\n var done = function done(err, res) {\n /* istanbul ignore else: out of scope */\n if (!calledBack) {\n calledBack = true;\n callback(err, res);\n }\n };\n\n // Apply timeout if configured globally\n if (okanjo.net.request.timeout) {\n req.timeout = okanjo.net.request.timeout;\n }\n\n // Catch timeout errors\n req.ontimeout = function (e) {\n /* istanbul ignore next: idk if jsdom can mock this, also readystatechange may fire before this anyway */\n done({\n statusCode: 504,\n error: \"Request timed out\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n };\n\n // Handle the response\n req.onreadystatechange = function (e) {\n // 4 = completed / failed\n if (req.readyState === 4) {\n // Do we have a response?\n if (req.status > 0) {\n var res = void 0;\n\n // Check if we got JSON and parse it right away\n if (JSON_TEST.test(req.getResponseHeader('Content-Type'))) {\n res = JSON.parse(req.responseText);\n } else {\n // Not JSON, normalize it instead\n res = {\n statusCode: req.status,\n data: req.responseText\n };\n }\n\n // Put the response in the proper slot (err for non success responses)\n if (req.status >= 200 && req.status < 300) {\n done(null, res);\n } else {\n done(res);\n }\n } else {\n // Request failed - e.g. CORS or network issues\n done({\n statusCode: 503,\n error: \"Request failed\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n }\n }\n };\n\n // Open the request\n req.open(method.toUpperCase(), url);\n\n // Include credentials\n req.withCredentials = true;\n\n // Handle post payloads\n if (['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {\n req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n if (payload !== undefined) {\n payload = JSON.stringify(payload);\n }\n }\n\n // Ship it\n req.send(payload || undefined);\n };\n\n // Bind helpers to make things easy as pie\n okanjo.net.request.get = okanjo.net.request.bind(this, 'GET');\n okanjo.net.request.post = okanjo.net.request.bind(this, 'POST');\n okanjo.net.request.put = okanjo.net.request.bind(this, 'PUT');\n okanjo.net.request.delete = okanjo.net.request.bind(this, 'DELETE');\n\n /**\n * Helper to aid in minificiation+querystringify and redundant encodeURIComponent stuff\n * @param val\n * @return {*}\n */\n var encode = function encode(val) {\n if (val === null || val === undefined) return '';\n return encodeURIComponent('' + val);\n };\n\n /**\n * Helper to aid in getting a query string key using a prefix and keyname\n * @param key\n * @param keyPrefix\n * @return {*}\n */\n var getKey = function getKey(key, keyPrefix) {\n if (keyPrefix) {\n return keyPrefix + '[' + encode(key) + ']';\n } else {\n return encode(key);\n }\n };\n\n /**\n * Super basic querystringify helper. It handles deep objects, but not for array values\n * @param obj\n * @param [keyPrefix]\n * @return {string}\n */\n okanjo.net.request.stringify = function (obj, keyPrefix) {\n var pairs = [];\n keyPrefix = keyPrefix || \"\";\n Object.keys(obj).forEach(function (key) {\n var value = obj[key];\n if (Array.isArray(value)) {\n value.forEach(function (v) {\n return pairs.push(getKey(key, keyPrefix) + '=' + encode(v));\n }); // Does not do that PHP garbage with key[]=val\n } else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === \"object\" && value !== null) {\n // Recurse\n var res = okanjo.net.request.stringify(value, getKey(key, keyPrefix));\n if (res) pairs.push(res);\n } else if (value !== undefined) {\n pairs.push(getKey(key, keyPrefix) + '=' + encode(value));\n }\n });\n return pairs.join('&');\n };\n})(window);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function (window, document) {\n\n /**\n * Okanjo cookie utility helpers\n */\n window.okanjo.util.cookie = {\n\n /**\n * Sets a cookie\n * @param cookieName\n * @param value\n * @param expireDays\n */\n set: function set(cookieName, value, expireDays) {\n var expireDate = new Date();\n expireDate.setDate(expireDate.getDate() + expireDays);\n var expires = expireDays ? \" Expires=\" + expireDate.toUTCString() + \";\" : \"\";\n var path = \" Path=/\";\n var secure = window.location.protocol === 'https:' ? ' Secure;' : '';\n // const secure = ' Secure;';\n var cookieValue = encodeURI(value) + ';' + expires + secure + ' SameSite=None;' + path;\n // console.log('setting cookie', cookieName, cookieValue)\n document.cookie = cookieName + \"=\" + cookieValue;\n },\n\n /**\n * Gets a cookie\n * @param cookieName\n * @return {*}\n */\n get: function get(cookieName) {\n var output = null;\n document.cookie.split(\";\").find(function (cookie) {\n var nameTest = cookie.substr(0, cookie.indexOf(\"=\")).trim();\n var value = cookie.substr(cookie.indexOf(\"=\") + 1);\n if (nameTest === cookieName) {\n output = decodeURI(value);\n return true;\n } else {\n return false;\n }\n });\n return output;\n }\n };\n})(window, document);\n\"use strict\";\n\n//noinspection JSUnusedLocalSymbols,ThisExpressionReferencesGlobalObjectJS\n(function (window, document) {\n\n var okanjo = window.okanjo;\n\n /**\n * UI Rendering Engine\n */\n\n var TemplateEngine = function () {\n function TemplateEngine() {\n _classCallCheck(this, TemplateEngine);\n\n // Load initial templates from options\n this._templates = {};\n this._css = {};\n\n // Hook point for adding custom styles to ui elements\n this.classDetects = '';\n }\n\n /**\n * Registers a template for use\n * @param name\n * @param template\n * @param beforeRender\n * @param options\n */\n\n\n _createClass(TemplateEngine, [{\n key: 'registerTemplate',\n value: function registerTemplate(name, template, beforeRender, options) {\n\n if ((typeof template === 'undefined' ? 'undefined' : _typeof(template)) === \"object\") {\n //noinspection JSValidateTypes\n if (template.nodeType === undefined) {\n throw new Error('Parameter template must be a string or a DOM element');\n } else {\n template = template.innerHTML;\n okanjo.lib.Mustache.parse(template);\n }\n } else if (typeof template !== \"string\") {\n throw new Error('Parameter template must be a string or a DOM element');\n }\n\n // Shift options if only have 3 params\n if (arguments.length === 3 && (typeof beforeRender === 'undefined' ? 'undefined' : _typeof(beforeRender)) === \"object\") {\n options = beforeRender;\n beforeRender = null;\n } else {\n options = options || {};\n }\n\n if (beforeRender && typeof beforeRender !== \"function\") {\n throw new Error('Parameter beforeRender must be a function');\n }\n\n // Assign the template\n this._templates[name] = {\n markup: template,\n options: options,\n beforeRender: beforeRender\n };\n }\n\n /**\n * Registers a CSS payload for use\n * @param name\n * @param css\n * @param options\n */\n\n }, {\n key: 'registerCss',\n value: function registerCss(name, css, options) {\n options = options || {};\n\n if ((typeof css === 'undefined' ? 'undefined' : _typeof(css)) === \"object\") {\n //noinspection JSValidateTypes\n if (css.nodeType === undefined) {\n throw new Error('Parameter css must be a string or a DOM element');\n }\n } else if (typeof css !== \"string\") {\n throw new Error('Parameter css must be a string or a DOM element');\n }\n\n this._css[name] = {\n markup: css,\n options: options\n };\n }\n\n /**\n * Checks whether a template is registered\n * @param name\n * @return {boolean}\n */\n\n }, {\n key: 'isTemplateRegistered',\n value: function isTemplateRegistered(name) {\n return !!this._templates[name];\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Checks whether a CSS payload is registered\n * @param name\n * @return {boolean}\n */\n\n }, {\n key: 'isCssRegistered',\n value: function isCssRegistered(name) {\n return !!this._css[name];\n }\n\n /**\n * Ensures that a CSS payload has been added to the DOM\n * @param name\n */\n\n }, {\n key: 'ensureCss',\n value: function ensureCss(name) {\n if (this._css[name]) {\n //noinspection JSValidateTypes\n var css = this._css[name],\n id = css.markup.nodeType === undefined ? css.options.id || \"okanjo-css-\" + name : null; // If it's a DOM element, just forget it cuz it's already on the page\n\n // Check for css element on page, if we have an ID to look for\n if (id) {\n var element = document.querySelector('#' + id.replace(/\\./g, '\\\\.'));\n if (!element) {\n var head = document.head,\n style = document.createElement('style');\n\n style.id = id;\n style.setAttribute('type', 'text/css');\n\n /* istanbul ignore else: old ie */\n if (style.hasOwnProperty) {\n // old ie\n style.innerHTML = css.markup;\n } else {\n style.styleSheet.cssText = css.markup;\n }\n\n if (head) {\n head.appendChild(style);\n } else {\n // NO HEAD, just prepend to body then\n var body = document.body;\n if (body) {\n body.appendChild(style);\n } else {\n // And if this doesn't work, just give up\n okanjo.report('Cannot add CSS template to document. Does it not have a body or head?');\n }\n }\n }\n }\n } else {\n okanjo.report('Attempted to add CSS template \"' + name + '\" to the DOM, however it does not appear to be registered?');\n }\n }\n\n /**\n * Renders a template and returns the markup\n * @param templateName\n * @param context\n * @param model\n * @return {string}\n */\n\n }, {\n key: 'render',\n value: function render(templateName, context, model) {\n var _this = this;\n\n model = model || {};\n var template = this._templates[templateName];\n\n // If there's a data controller closure set, and if so, run the data through there\n if (template.beforeRender) {\n model = template.beforeRender.call(context, model);\n }\n\n // Attach globals\n model.okanjo = okanjo;\n model.okanjoMetricUrl = okanjo.net.endpoint.replace(/^https?:\\/\\//, ''); // Url w/o scheme to prevent mixed-content warnings\n model.now = function () {\n return new Date().getTime();\n };\n model.classDetects = this.classDetects;\n\n //noinspection JSUnresolvedVariable\n if (model.blockClasses && Array.isArray(model.blockClasses)) {\n model.classDetects += \" \" + model.blockClasses.join(' ');\n delete model.blockClasses;\n }\n\n // Add CSS unless we are told not to\n if (model.css !== false && template.options.css && template.options.css.length > 0) {\n template.options.css.forEach(function (css) {\n return _this.ensureCss(css);\n });\n delete model.css;\n }\n\n // Render the template and return the result\n return okanjo.lib.Mustache.render(template.markup, model);\n }\n }]);\n\n return TemplateEngine;\n }();\n\n /**\n * Formats a number into a currency string (rounded, decimal points, thousands separators)\n * See: http://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-money-in-javascript\n *\n * @param value – the number to format\n * @param [decimals] - The number of decimals to show\n * @param [decimalSeparator] – The decimals separator, default: .\n * @param [thousandsSeparator] – The thousands separator, default: ,\n * @returns {string} – Formatted currency string\n */\n\n\n TemplateEngine.formatCurrency = function (value) {\n var decimals = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;\n var decimalSeparator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '.';\n var thousandsSeparator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ',';\n\n var s = value < 0 ? \"-\" : \"\",\n i = parseInt(value = Math.abs(+value || 0).toFixed(decimals)) + \"\";\n var j = i.length;\n j = j > 3 ? j % 3 : 0;\n return s + (j ? i.substr(0, j) + thousandsSeparator : \"\") + i.substr(j).replace(/(\\d{3})(?=\\d)/g, \"$1\" + thousandsSeparator) + (decimals ? decimalSeparator + Math.abs(value - i).toFixed(decimals).slice(2) : \"\");\n };\n\n // Export\n okanjo.ui.engine = new TemplateEngine();\n})(window, document);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window, document) {\n\n /*\n div .modal-container .fade-out .hidden\n | div .modal-window .clearfix\n | |\n | | div .modal-window-skin\n | | | div .modal-window-outer\n | | | | div .modal-window-inner\n | | | | | iframe .okanjo-inline-buy-frame\n | | | | /div\n | | | /div\n | | /div\n | |\n | | div .close-button\n | | | ×\n | | /div\n | |\n | /div\n /div\n */\n\n var okanjo = window.okanjo;\n var IS_MOBILE = okanjo.util.isMobile();\n\n var initialized = false,\n\n // scrollY = null,\n\n // Selectors\n $html = void 0,\n $body = void 0,\n $modalContainer = void 0,\n $modalWindow = void 0,\n $modalSkin = void 0,\n $modalOuter = void 0,\n $modalInner = void 0,\n $modalClose = void 0,\n $modalFrame = void 0,\n createElements = function createElements() {\n\n // Page elements\n //noinspection JSUnresolvedFunction\n $html = document.documentElement /* istanbul ignore next: old browsers */ || document.querySelector('html');\n //noinspection JSUnresolvedFunction\n $body = document.body /* istanbul ignore next: old browsers */ || document.querySelector('body');\n\n // Modal elements\n $modalContainer = document.createElement('div');\n $modalWindow = document.createElement('div');\n $modalSkin = document.createElement('div');\n $modalOuter = document.createElement('div');\n $modalInner = document.createElement('div');\n $modalClose = document.createElement('div');\n $modalFrame = document.createElement('iframe');\n\n $modalContainer.setAttribute('class', 'okanjo-modal-container okanjo-modal-hidden ' /*+ okanjo.util.detectClasses().join(' ')*/);\n $modalWindow.setAttribute('class', 'okanjo-modal-window');\n $modalSkin.setAttribute('class', 'okanjo-modal-window-skin');\n $modalOuter.setAttribute('class', 'okanjo-modal-window-outer');\n $modalInner.setAttribute('class', 'okanjo-modal-window-inner');\n $modalClose.setAttribute('class', 'okanjo-modal-close-button');\n\n $modalFrame.setAttribute('class', 'okanjo-inline-buy-frame');\n $modalFrame.setAttribute('frameborder', '0');\n $modalFrame.setAttribute('vspace', '0');\n $modalFrame.setAttribute('hspace', '0');\n $modalFrame.setAttribute('webkitallowfullscreen', '');\n $modalFrame.setAttribute('mozallowfullscreen', '');\n $modalFrame.setAttribute('allowfullscreen', '');\n $modalFrame.setAttribute('scrolling', 'auto');\n\n $modalClose.innerHTML = '×';\n\n // Create the modal element tree\n $modalInner.appendChild($modalFrame);\n $modalOuter.appendChild($modalInner);\n $modalSkin.appendChild($modalOuter);\n $modalWindow.appendChild($modalSkin);\n $modalWindow.appendChild($modalClose);\n $modalContainer.appendChild($modalWindow);\n\n // Add the modal stuff to the body\n $body.appendChild($modalContainer);\n },\n addListener = function addListener(el, event, handler) {\n /* istanbul ignore else: old browsers */\n if (el.addEventListener) {\n el.addEventListener(event, handler, false);\n } else {\n el.attachEvent(\"on\" + event, handler);\n }\n },\n getWindowHeight = function getWindowHeight() {\n return window.innerHeight /* istanbul ignore next: old browsers */ || document.documentElement.clientHeight;\n },\n handleReposition = function handleReposition() {\n // scrollY = okanjo.ui.getScrollPosition().y;\n //$modalWindow.style.marginTop = scrollY + 40 + \"px\";\n $modalWindow.style.height = getWindowHeight() - 80 + \"px\";\n },\n bindEvents = function bindEvents() {\n\n // If the device orientation changes, adjust the modal view port\n addListener(window, 'orientationchange', function () {\n for (var t = 0; t < 2; t++) {\n setTimeout(handleReposition, 1000 * t + 10);\n }\n });\n\n // If the window changes size, also adjust the modal view port\n addListener(window, 'resize', function () {\n setTimeout(handleReposition, 100);\n });\n\n // Click the overlay to close the modal\n addListener($modalContainer, 'click', closeModal);\n\n // If you click in the modal, don't close it!\n addListener($modalWindow, 'click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n });\n\n // Click the close button to close it\n addListener($modalClose, 'click', function (e) {\n\n // Don't close it twice\n e.preventDefault();\n e.stopPropagation();\n\n closeModal();\n });\n },\n\n\n //removeListener = function(el, event, handler) {\n // if (el.removeEventListener) {\n // el.removeEventListener(event, handler);\n // } else {\n // el.detachEvent(\"on\" + event, handler);\n // }\n //},\n\n addClass = function addClass(el, name) {\n el.className += \" \" + name;\n },\n removeClass = function removeClass(el, name) {\n el.className = el.className.replace(new RegExp(' *?' + name), '');\n },\n openModal = function openModal() {\n\n // scrollY = document.body.scrollTop;\n\n removeClass($modalContainer, 'okanjo-modal-hidden');\n addClass($modalContainer, 'okanjo-modal-fade-out');\n\n handleReposition();\n\n addClass($html, \"okanjo-modal-active\");\n\n if (!IS_MOBILE) {\n addClass($html, \"okanjo-modal-margin-fix\");\n }\n\n setTimeout(function () {\n removeClass($modalContainer, 'okanjo-modal-fade-out');\n }, 10);\n\n // Click the overlay to close the modal\n //addListener($body, 'click', closeModal);\n },\n closeModal = function closeModal() {\n addClass($modalContainer, 'okanjo-modal-fade-out');\n\n setTimeout(function () {\n removeClass($modalContainer, 'okanjo-modal-fade-out');\n addClass($modalContainer, \"okanjo-modal-hidden\");\n\n removeClass($html, \"okanjo-modal-active\");\n if (!IS_MOBILE) {\n removeClass($html, \"okanjo-modal-margin-fix\");\n }\n }, 210);\n\n // Click the overlay to close the modal\n //removeListener($body, 'click', closeModal);\n },\n\n\n /**\n * Insert an element or markup into the modal\n * @param content\n */\n setContent = function setContent(content) {\n\n // Remove existing content\n $modalInner.innerHTML = \"\";\n\n // Insert new content\n if (typeof content === \"string\") {\n $modalInner.innerHTML = content;\n } else {\n $modalInner.appendChild(content);\n }\n };\n\n // Expose the modal functions\n okanjo.ui.modal = {\n\n show: function show(content) {\n\n if (!initialized) {\n initialized = true;\n createElements();\n bindEvents();\n }\n\n setContent(content);\n openModal();\n },\n\n hide: function hide() {\n closeModal();\n }\n\n };\n\n return okanjo.ui.modal;\n})(window, document);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window, document) {\n\n var okanjo = window.okanjo;\n\n /**\n * Event tracking class\n * @type {Metrics}\n */\n\n var Metrics = function () {\n\n //noinspection JSUnusedGlobalSymbols\n function Metrics() {\n _classCallCheck(this, Metrics);\n\n /**\n * Events queued here before submission\n * @type {Array}\n * @private\n */\n this._queue = this._getStoredQueue();\n this._processTimeout = null; // queue event loop timeout pointer\n\n /**\n * Unique page grouping event identifier\n */\n this.pageId = okanjo.util.shortid();\n this.defaultChannel = Metrics.Channel.external;\n\n this.sid = null;\n this.sourceCh = null;\n this.sourceCx = null;\n\n // Extract referral data, if set\n this._checkUrlForReferral();\n\n // TODO - look into iframe session correlation system\n }\n\n //noinspection JSMethodCanBeStatic\n /**\n * Gets the storage backed metric queue, in case we did not send everything last time\n * @return {Array}\n * @private\n */\n\n\n _createClass(Metrics, [{\n key: '_getStoredQueue',\n value: function _getStoredQueue() {\n if (window.localStorage[Metrics.Params.queue]) {\n try {\n var queue = JSON.parse(window.localStorage[Metrics.Params.queue]);\n if (Array.isArray(queue)) {\n return queue;\n } else {\n okanjo.report('Stored queue is not a queue', { queue: queue });\n return [];\n }\n } catch (e) {\n okanjo.report('Failed to load metric queue from storage', { err: e });\n return [];\n }\n } else {\n // not stored\n return [];\n }\n }\n\n /**\n * Updates the queue stored in storage, in the event we can't complete our submissions\n * @param delay - Whether to delay updating the queue for a bit, to let other metrics pile in\n * @private\n */\n\n }, {\n key: '_saveQueue',\n value: function _saveQueue(delay) {\n var _this2 = this;\n\n if (delay) {\n if (this._saveQueueTimeout) clearTimeout(this._saveQueueTimeout);\n this._saveQueueTimeout = setTimeout(function () {\n _this2._saveQueue(false);\n _this2._saveQueueTimeout = null;\n }, 100);\n } else {\n window.localStorage[Metrics.Params.queue] = JSON.stringify(this._queue);\n }\n }\n\n /**\n * Extract contextual pass-through data from the URL, if present\n * @private\n */\n\n }, {\n key: '_checkUrlForReferral',\n value: function _checkUrlForReferral() {\n var pageArgs = okanjo.util.getPageArguments(true),\n urlSid = pageArgs[Metrics.Params.name],\n localSid = window.localStorage[Metrics.Params.name] || okanjo.util.cookie.get(Metrics.Params.name),\n // pull from storage or cookie\n sourceContext = pageArgs[Metrics.Params.context],\n sourceChannel = pageArgs[Metrics.Params.channel];\n\n // If for some reason, both are set, record the incident as a possible correlation\n if (urlSid && localSid && urlSid !== localSid) {\n this.trackEvent({\n object_type: Metrics.Object.metric_session,\n event_type: Metrics.Event.correlation,\n id: urlSid + \"_\" + localSid,\n ch: this.defaultChannel,\n _noProcess: true\n });\n }\n\n // Update local values\n this.sid = localSid || urlSid || null; // prefer local over remote (changed in 1.0)\n this.sourceCh = sourceChannel || null;\n this.sourceCx = sourceContext || null;\n }\n\n /**\n * Submits an individual event metric\n * @param event\n * @param callback\n */\n\n }, {\n key: 'trackEvent',\n value: function trackEvent(event, callback) {\n // Ensure the event contains the required fields\n if (!event.object_type || !event.event_type) {\n okanjo.report('Invalid metric to track (missing object_type or event_type)', { event: event });\n return;\n }\n\n // Queue the event for publishing\n this._push(event, callback);\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Submits a page view metric\n * @param event\n * @param callback\n */\n\n }, {\n key: 'trackPageView',\n value: function trackPageView(event, callback) {\n event = event || {};\n event.object_type = Metrics.Object.page;\n event.event_type = Metrics.Event.view;\n event.id = event.id || okanjo.util.getLocation();\n event.ch = event.ch || this.defaultChannel;\n\n // Queue the event for publishing\n this.trackEvent(event, callback);\n }\n\n /**\n * Adds an event to the queue\n * @param event\n * @param callback\n * @private\n */\n\n }, {\n key: '_push',\n value: function _push(event, callback) {\n this._queue.push({ event: event, callback: callback });\n\n // Save the queue\n this._saveQueue(true);\n\n // Start burning down the queue, unless the event says not to\n if (event._noProcess) {\n delete event._noProcess;\n } else {\n this._processQueue();\n }\n }\n\n /**\n * Burn down the queue\n * @private\n */\n\n }, {\n key: '_processQueue',\n value: function _processQueue() {\n var _this3 = this;\n\n // If the queue is not already being processed, and there's stuff to process, continue sending them\n if (!this._processTimeout && this._queue.length > 0) {\n this._processTimeout = setTimeout(function () {\n\n // Pull the items we're going to batch out of the queue\n var items = _this3._queue.splice(0, 255);\n _this3._saveQueue(false);\n\n // Track the item\n _this3._batchSend(items, function (err, res) {\n // TODO: If there was an error, consider splicing the batch back into the queue\n\n // Update / Set the metric sid on the publisher\n /* istanbul ignore else: server barks */\n if (res && res.data && res.data.sid) _this3._updateSid(res.data.sid);\n\n // When this batch is done being tracked, iterate to the next metric then fire it's callback if set\n _this3._processTimeout = null;\n _this3._processQueue();\n\n // Fire the event callbacks if there are any\n items.forEach(function (item) {\n item.callback && item.callback(err, res);\n });\n });\n }, 0); // break event loop, maybe\n }\n }\n\n /**\n * Sends a bunch of queued metric events\n * @param items\n * @param callback\n * @private\n */\n\n }, {\n key: '_batchSend',\n value: function _batchSend(items, callback) {\n var _this4 = this;\n\n // Normalize event data\n var events = items.map(function (item) {\n _this4._normalizeEvent(item.event);\n\n // Strip duplicated data from event batch\n delete item.event.sid;\n delete item.event.win;\n\n return item.event;\n });\n\n var payload = {\n events: events,\n win: okanjo.util.getLocation()\n };\n\n var route = okanjo.net.getRoute(okanjo.net.routes.metrics_batch);\n\n // Set sid if present\n if (this.sid) {\n payload.sid = this.sid;\n }\n\n // Send it\n okanjo.net.request.post(route, payload, function (err, res) {\n /* istanbul ignore if: out of scope */\n if (err) {\n okanjo.report('Failed to send metrics batch', { err: err, res: res, items: items, route: route });\n }\n callback && callback(err, res);\n });\n }\n\n /**\n * Normaizes events so that they contain consistent data values\n * @param event\n * @private\n */\n\n }, {\n key: '_normalizeEvent',\n value: function _normalizeEvent(event) {\n\n // Ensure meta is ready to receive values\n event.m = event.m || {};\n\n // Set key\n event.key = event.key || event.m.key || okanjo.key || undefined;\n\n // Set session\n if (this.sid) event.sid = this.sid;\n\n // Clone the metadata, since it might be a direct reference to a widget property\n // Deleting properties on the meta object could be very destructive\n event.m = Object.assign({}, event.m); // event.m should be flat\n\n // Strip meta keys that should be excluded\n Object.keys(Metrics.Meta.exclude).forEach(function (key) {\n return delete event.m[key];\n });\n\n // Set referral channel / context\n if (this.sourceCh) {\n event.m.ref_ch = this.sourceCh;\n }\n if (this.sourceCx) {\n event.m.ref_cx = this.sourceCx;\n }\n\n // Set page group id\n event.m.pgid = this.pageId;\n\n // Set okanjo version\n event.m.ok_ver = okanjo.version;\n\n // Finalize metadata\n event.m = okanjo.util.flatten(event.m, { arrayToCsv: true });\n\n // Ensure metadata strings won't exceed the imposed limit\n Object.keys(event.m).forEach(function (key) {\n if (typeof event.m[key] === \"string\") {\n event.m[key] = event.m[key].substr(0, 255);\n }\n });\n\n // Set page source reference\n if (document.referrer) {\n event.ref = document.referrer;\n }\n\n // Set the window location\n event.win = okanjo.util.getLocation();\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n\n }, {\n key: '_updateSid',\n value: function _updateSid(sid) {\n // Not set or changed?\n if (sid && (!this.sid || this.sid !== sid)) {\n this.sid = sid;\n window.localStorage[Metrics.Params.name] = sid;\n okanjo.util.cookie.set(Metrics.Params.name, sid, Metrics.Params.ttl);\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'create',\n\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Helper to create a new fluent event structure\n * @param args\n * @return {*}\n */\n value: function create() {\n for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n args[_key3] = arguments[_key3];\n }\n\n return Metrics.create.apply(null, args);\n }\n }], [{\n key: 'addElementInfo',\n value: function addElementInfo(element, event) {\n var page = okanjo.ui.getPageSize(),\n size = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n event.m.pw = page.w;\n event.m.ph = page.h;\n event.m.x1 = size.x1;\n event.m.y1 = size.y1;\n event.m.x2 = size.x2;\n event.m.y2 = size.y2;\n\n return event;\n }\n }, {\n key: 'addWidgetInfo',\n value: function addWidgetInfo(element, event) {\n var containerSize = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n\n // placement div size\n event.m.wox1 = containerSize.x1;\n event.m.woy1 = containerSize.y1;\n event.m.wox2 = containerSize.x2;\n event.m.woy2 = containerSize.y2;\n\n // Inner size is the min/max of the child elements since they may be floating and have no official height/width\n var resources = okanjo.qwery('.okanjo-resource, .okanjo-adx-container', element);\n var size = void 0,\n wix1 = void 0,\n wiy1 = void 0,\n wix2 = void 0,\n wiy2 = void 0,\n boxes = [];\n var getMin = function getMin(val, current) {\n return typeof current === \"undefined\" || val < current ? val : current;\n };\n var getMax = function getMax(val, current) {\n return typeof current === \"undefined\" || val > current ? val : current;\n };\n var fallback = function fallback(val, _fallback) {\n return typeof val === \"undefined\" ? _fallback : val;\n };\n\n resources.forEach(function (e) {\n size = okanjo.ui.getElementPosition(e);\n wix1 = getMin(size.x1, wix1);\n wiy1 = getMin(size.y1, wiy1);\n wix2 = getMax(size.x2, wix2);\n wiy2 = getMax(size.y2, wiy2);\n boxes.push(size.x1, size.y1, size.x2, size.y2);\n });\n\n // inner size (might be centered or something)\n // noinspection JSUnusedAssignment\n event.m.wix1 = fallback(wix1, containerSize.x1); // noinspection JSUnusedAssignment\n event.m.wiy1 = fallback(wiy1, containerSize.y1); // noinspection JSUnusedAssignment\n event.m.wix2 = fallback(wix2, containerSize.x2); // noinspection JSUnusedAssignment\n event.m.wiy2 = fallback(wiy2, containerSize.y2);\n event.m.wrps = boxes.map(function (v) {\n return Math.floor(v);\n }).join(','); // all resource positions x1,y1,x2,y2,...\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds viewport dimensions / positional data to the event\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'addViewportInfo',\n value: function addViewportInfo(event) {\n var vp = okanjo.ui.getViewportSize(),\n pos = okanjo.ui.getScrollPosition();\n\n event = event || {};\n event.m = event.m || {};\n event.m.vx1 = pos.x;\n event.m.vy1 = pos.y;\n event.m.vx2 = pos.x + vp.vw;\n event.m.vy2 = pos.y + vp.vh;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'addEventInfo',\n value: function addEventInfo(jsEvent, event) {\n var pos = okanjo.ui.getEventPosition(jsEvent);\n\n event = event || {};\n event.m = event.m || {};\n event.m.et = pos.et;\n event.m.ex = pos.ex;\n event.m.ey = pos.ey;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param event\n * @param args\n * @return {*|{}}\n */\n\n }, {\n key: 'addEventMeta',\n value: function addEventMeta(event) {\n event = event || {};\n event.m = event.m || {};\n\n for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {\n args[_key4 - 1] = arguments[_key4];\n }\n\n event.m = Object.assign.apply(Object, [event.m].concat(args));\n\n return event;\n }\n\n /**\n * Helper to create a new fluent event structure\n * @param data\n * @param args\n * @return {MetricEvent}\n */\n\n }, {\n key: 'create',\n value: function create(data) {\n for (var _len5 = arguments.length, args = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {\n args[_key5 - 1] = arguments[_key5];\n }\n\n // return okanjo.util.deepClone(Object.assign.apply(Object, [{}].concat(args)));\n return new MetricEvent(data, args);\n }\n }]);\n\n return Metrics;\n }();\n\n /**\n * The storage/cookie/url param names\n * @type {{queue: string, name: string, channel: string, context: string, ttl: number}}\n */\n\n\n Metrics.Params = {\n queue: '_ok_q',\n name: 'ok_msid',\n channel: 'ok_ch',\n context: 'ok_cx',\n ttl: 1460 // 4 years\n };\n\n /**\n * Event Metadata configuration\n * @type {{exclude: [*]}}\n */\n Metrics.Meta = {\n exclude: ['key', 'callback', 'metrics_channel_context', 'metrics_context', 'mode']\n };\n\n /**\n * Event Types\n * @type {{view: string, impression: string, interaction: string, correlation: string}}\n */\n Metrics.Event = {\n view: 'vw',\n impression: 'imp',\n interaction: 'int',\n correlation: 'cor'\n };\n\n /**\n * Event Action Types\n * @type {{click: string, inline_click: string}}\n */\n Metrics.Action = {\n click: \"click\",\n inline_click: \"inline_click\"\n };\n\n /**\n * Event Object Types\n * @type {{article: string, thirdparty_ad: string, cart: string, page: string, widget: string, product: string, store: string, cause: string, marketplace: string, order: string, order_item: string, user: string, metric_session: string}}\n */\n Metrics.Object = {\n article: 'am',\n thirdparty_ad: 'ta',\n cart: 'ct',\n page: 'pg',\n widget: 'wg',\n product: 'pr',\n store: 'st',\n cause: 'ca',\n marketplace: 'mp',\n order: 'or',\n order_item: 'oi',\n user: 'ur',\n metric_session: 'mt'\n };\n\n /**\n * Event Channels\n * @type {{product_widget: string, ad_widget: string, store_widget: string, marketplace: string, external: string}}\n */\n Metrics.Channel = {\n placement: 'pw',\n marketplace: 'mp',\n external: 'ex',\n\n // Deprecated:\n product_widget: 'pw',\n ad_widget: 'aw',\n store_widget: 'sw'\n };\n\n /**\n * Event Environments\n * @type {{live: string, testing: string}}\n */\n Metrics.Environment = {\n live: \"live\",\n testing: \"testing\"\n };\n\n /**\n * Fluent wrapper around making events simple\n */\n\n var MetricEvent = function () {\n function MetricEvent(data, others) {\n var _this5 = this;\n\n _classCallCheck(this, MetricEvent);\n\n // Merge the data and other data sets into this object\n data = data || {};\n this.data(data);\n /* istanbul ignore else: metrics.create is the only way to create this right now */\n if (Array.isArray(others)) {\n others.forEach(function (data) {\n _this5.data(data);\n });\n }\n }\n\n /**\n * Sets event parameter key-values\n * @param data\n */\n\n\n _createClass(MetricEvent, [{\n key: 'data',\n value: function data(_data) {\n Object.assign(this, okanjo.util.deepClone(_data));\n return this;\n }\n\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @return {MetricEvent}\n */\n\n }, {\n key: 'event',\n value: function event(jsEvent) {\n Metrics.addEventInfo(jsEvent, this);\n return this;\n }\n\n /**\n * Adds viewport dimensions / positional data to the event\n * @return {MetricEvent}\n */\n\n }, {\n key: 'viewport',\n value: function viewport() {\n Metrics.addViewportInfo(this);\n return this;\n }\n\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @return {MetricEvent}\n */\n\n }, {\n key: 'element',\n value: function element(_element) {\n Metrics.addElementInfo(_element, this);\n return this;\n }\n\n /**\n * Adds widget DOM element dimensions / positional data to the event\n * @param element\n * @returns {MetricEvent}\n */\n\n }, {\n key: 'widget',\n value: function widget(element) {\n Metrics.addWidgetInfo(element, this);\n return this;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param args\n * @return {MetricEvent}\n */\n\n }, {\n key: 'meta',\n value: function meta() {\n for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {\n args[_key6] = arguments[_key6];\n }\n\n Metrics.addEventMeta.apply(null, [this].concat(args));\n return this;\n }\n\n /**\n * Sets the object and event type on the event w/o having to use .data\n * @param object_type\n * @param event_type\n * @return {MetricEvent}\n */\n\n }, {\n key: 'type',\n value: function type(object_type, event_type) {\n this.object_type = object_type;\n this.event_type = event_type;\n return this;\n }\n\n /**\n * Finalizes and sends the event\n * @param callback\n */\n\n }, {\n key: 'send',\n value: function send(callback) {\n okanjo.metrics.trackEvent(this, callback);\n // DONT RETURN - BREAK THE CHAIN HERE\n }\n\n /**\n * Gets the single-metric tracking url for this event\n * @return {string}\n */\n\n }, {\n key: 'toUrl',\n value: function toUrl() {\n // Copy data w/o modifying it\n var event = Object.assign({}, this);\n\n // Extract params\n var object_type = event.object_type,\n event_type = event.event_type;\n\n delete event.object_type;\n delete event.event_type;\n\n // Normalize event data\n okanjo.metrics._normalizeEvent(event);\n\n // Get the URL\n return okanjo.net.getRoute(okanjo.net.routes.metrics, { object_type: object_type, event_type: event_type }) + '?' + okanjo.net.request.stringify(event);\n }\n }]);\n\n return MetricEvent;\n }();\n\n // Export / initialize\n\n\n okanjo.metrics = new Metrics();\n})(window, document);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function (window) {\n\n var okanjo = window.okanjo;\n\n // Track the page view, but don't send it right away.\n // Send it in one full second unless something else pushes an event\n // This way, we have a chance that a placement key will be set globally\n okanjo.metrics.trackPageView({ _noProcess: true });\n setTimeout(function () {\n okanjo.metrics._processQueue();\n }, 1000);\n})(window);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/** Based on https://gist.github.com/mudge/5830382 **/\n(function (window) {\n\n /**\n * Simplified EventEmitter base class\n */\n var EventEmitter = function () {\n function EventEmitter() {\n _classCallCheck(this, EventEmitter);\n\n this._events = {};\n }\n\n /**\n * Registers an event handler to fire on any occurrence of an event\n * @param event\n * @param listener\n */\n\n\n _createClass(EventEmitter, [{\n key: 'on',\n value: function on(event, listener) {\n if (!this._events[event]) {\n this._events[event] = [];\n }\n\n this._events[event].push(listener);\n }\n\n /**\n * Removes an event handler for an event\n * @param event\n * @param listener\n */\n\n }, {\n key: 'removeListener',\n value: function removeListener(event, listener) {\n\n if (this._events[event]) {\n var idx = this._events[event].indexOf(listener);\n if (idx >= 0) {\n this._events[event].splice(idx, 1);\n }\n }\n }\n\n /**\n * Emits an event\n * @param event\n */\n\n }, {\n key: 'emit',\n value: function emit(event) {\n var i = void 0,\n listeners = void 0,\n length = void 0,\n args = [].slice.call(arguments, 1);\n\n if (this._events[event]) {\n listeners = this._events[event].slice();\n length = listeners.length;\n\n for (i = 0; i < length; i++) {\n listeners[i].apply(this, args);\n }\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Registers an event handler to fire only once on an event\n * @param event\n * @param listener\n */\n\n }, {\n key: 'once',\n value: function once(event, listener) {\n var _arguments = arguments,\n _this6 = this;\n\n var callback = function callback() {\n var args = [].slice.call(_arguments, 1);\n _this6.removeListener(event, callback);\n listener.apply(_this6, args);\n };\n\n this.on(event, callback);\n }\n }]);\n\n return EventEmitter;\n }();\n\n window.okanjo._EventEmitter = EventEmitter;\n return EventEmitter;\n})(window);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window) {\n\n var okanjo = window.okanjo;\n var DATA_ATTRIBUTE_PATTERN = /^data-(.+)$/;\n var DATA_REPLACE_PATTERN = /-/g;\n\n /**\n * Base widget class\n */\n\n var Widget = function (_okanjo$_EventEmitter) {\n _inherits(Widget, _okanjo$_EventEmitter);\n\n function Widget(element, options) {\n _classCallCheck(this, Widget);\n\n // Verify element was given (we can't load unless we have one)\n var _this7 = _possibleConstructorReturn(this, (Widget.__proto__ || Object.getPrototypeOf(Widget)).call(this));\n\n if (!element || element === null || element.nodeType === undefined) {\n okanjo.report('Invalid or missing element on widget construction', { widget: _this7, element: element, options: options });\n throw new Error('Okanjo: Invalid element - make sure to pass a valid DOM element when constructing Okanjo Widgets.');\n }\n\n // Verify configuration is OK\n if (options && (typeof options === 'undefined' ? 'undefined' : _typeof(options)) !== \"object\") {\n // Warn and fix it\n okanjo.report('Invalid widget options. Expected object, got: ' + (typeof options === 'undefined' ? 'undefined' : _typeof(options)), { widget: _this7, element: element, options: options });\n options = {};\n } else {\n options = options || {};\n }\n\n // Store basics\n _this7.name = 'Widget';\n _this7.element = element;\n _this7.instanceId = okanjo.util.shortid();\n\n // Clone initial config, breaking the top-level reference\n _this7.config = Object.assign({}, options);\n return _this7;\n }\n\n /**\n * Base widget initialization procedures\n */\n\n\n _createClass(Widget, [{\n key: 'init',\n value: function init() {\n // process config attributes\n this._applyConfiguration();\n\n this._setCompatibilityOptions();\n\n // ensure placement key\n if (!this._ensurePlacementKey()) return;\n\n // Tell the widget to load\n this.load();\n }\n\n /**\n * This is for extended widgets, so they may modify the configuration before loading\n */\n\n }, {\n key: '_setCompatibilityOptions',\n value: function _setCompatibilityOptions() {}\n // By default, this does nothing. Must be overridden to be useful\n\n\n //noinspection JSMethodCanBeStatic\n /**\n * Widget configuration definitions\n * @return {{}}\n */\n\n }, {\n key: 'getSettings',\n value: function getSettings() {\n // Override this\n return {};\n }\n\n /**\n * Main widget load function.\n */\n\n }, {\n key: 'load',\n value: function load() {}\n // Override this in the widget implementation\n\n\n /**\n * Applies data attribute settings and defaults to the widget configuration\n * @private\n */\n\n }, {\n key: '_applyConfiguration',\n value: function _applyConfiguration() {\n var _this8 = this;\n\n // this.config was set to the options provided in the constructor\n // so layer data attributes on top\n\n var data = this.getDataAttributes();\n var settings = this.getSettings();\n Object.keys(data).forEach(function (key) {\n var normalizedKey = key.replace(DATA_REPLACE_PATTERN, '_');\n\n var val = data[key];\n\n // Attempt to convert the value if there's a setting for it\n if (settings[normalizedKey]) val = settings[normalizedKey].value(val, false);\n\n if (!okanjo.util.isEmpty(val)) {\n _this8.config[normalizedKey] = val;\n }\n });\n\n // Apply defaults from the widget settings\n Object.keys(settings).forEach(function (key) {\n if (_this8.config[key] === undefined && settings[key]._default !== undefined) {\n _this8.config[key] = settings[key].value(undefined, false);\n }\n });\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets a copy of the configuration, suitable for transmission\n * @return {{}}\n */\n\n }, {\n key: 'getConfig',\n value: function getConfig() {\n var _this9 = this;\n\n var settings = this.getSettings();\n var out = {};\n\n Object.keys(this.config).forEach(function (origKey) {\n var val = _this9.config[origKey];\n var key = origKey;\n var group = null;\n\n // Check if this is a known property\n if (settings[key]) {\n val = settings[key].value(val);\n group = settings[key].getGroup();\n }\n\n // Init the target/group if not already setup\n var target = out;\n if (group) {\n target[group] = target[group] || {};\n target = target[group];\n }\n\n // Set the value on the target if set\n if (val === null) {\n target[key] = ''; // format null values as empty strings for transmission\n } else if (val !== undefined) {\n target[key] = val;\n }\n });\n\n return out;\n }\n\n /**\n * Before loading, ensure that a placement key is present or abort\n * @return {boolean}\n * @private\n */\n\n }, {\n key: '_ensurePlacementKey',\n value: function _ensurePlacementKey() {\n\n // Check if set on widget or globally\n if (this.config.key) {\n return true;\n } else if (okanjo.key) {\n // Copy key from global scope,\n this.config.key = okanjo.key;\n return true;\n }\n\n // No key set, can't load.\n okanjo.report('No key provided on widget', { widget: this });\n this.showError('Error: Missing placement key.');\n return false;\n }\n\n /**\n * Displays an error in the widget element\n * @param message\n */\n\n }, {\n key: 'showError',\n value: function showError(message) {\n this.setMarkup(okanjo.ui.engine.render('okanjo.error', this, { message: message }));\n }\n\n /**\n * Sets the markup of the widget's element\n * @param markup\n */\n\n }, {\n key: 'setMarkup',\n value: function setMarkup(markup) {\n this.element.innerHTML = markup;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets the current page URL, sans query string and fragment.\n * @returns {string} - URL\n */\n\n }, {\n key: 'getDataAttributes',\n\n\n /**\n * Instead of using HTML5 dataset, just rip through attributes and return data attributes\n * @returns {*}\n */\n value: function getDataAttributes() {\n var data = {};\n Array.from(this.element.attributes).forEach(function (attr) {\n var match = DATA_ATTRIBUTE_PATTERN.exec(attr.name);\n if (match) {\n data[match[1]] = attr.value;\n }\n });\n return data;\n }\n }], [{\n key: 'getCurrentPageUrl',\n value: function getCurrentPageUrl() {\n return window.location.href.replace(/([?#].*)$/, '');\n }\n }]);\n\n return Widget;\n }(okanjo._EventEmitter);\n\n /**\n * Fluent configuration helper for organizing and formatting ad-hoc configuration values\n * @type {Field}\n */\n\n\n Widget.Field = function () {\n\n //noinspection JSUnusedGlobalSymbols\n function Field() {\n _classCallCheck(this, Field);\n\n this._convert = null;\n this._strip = false;\n this._default = undefined;\n this._group = null;\n }\n\n /**\n * Formats the value as an array of strings\n * @param converter\n * @return {Field}\n */\n\n\n _createClass(Field, [{\n key: 'array',\n value: function array(converter) {\n this._convert = function (val) {\n if (Array.isArray(val)) {\n if (converter) {\n return val.map(function (v) {\n return converter(v);\n });\n } else {\n return val;\n }\n }\n val = val.replace(/\\\\,/g, '\\0');\n return val.split(',').map(function (v) {\n var res = v.trim().replace('\\0', ',');\n if (converter) res = converter(res);\n return res;\n });\n };\n return this;\n }\n //noinspection JSUnusedGlobalSymbols\n\n }, {\n key: 'string',\n\n\n /**\n * Formats the value as a string\n * @return {Field}\n */\n value: function string() {\n this._convert = function (val) {\n if (val === null || val === undefined) return val;else return \"\" + val;\n };\n return this;\n }\n }, {\n key: 'bool',\n\n\n /**\n * Formats the value as a boolean (takes 1, 0, true, false)\n * @return {Field}\n */\n value: function bool() {\n this._convert = function (val) {\n if (typeof val === \"string\") {\n return val === \"1\" || val.toLowerCase() === \"true\";\n } else {\n return !!val;\n }\n };\n return this;\n }\n //noinspection JSUnusedGlobalSymbols\n\n }, {\n key: 'strip',\n\n\n /**\n * Indicates the field should not be passed on for transmission\n * @return {Field}\n */\n value: function strip() {\n this._strip = true;return this;\n }\n }, {\n key: 'int',\n\n\n /**\n * Formats the value as a integer (whole) number\n * @return {Field}\n */\n value: function int() {\n this._convert = function (val) {\n return parseInt(val);\n };return this;\n }\n //noinspection JSUnusedGlobalSymbols\n\n }, {\n key: 'float',\n\n\n /**\n * Formats the value as a floating point number\n * @return {Field}\n */\n value: function float() {\n this._convert = function (val) {\n return parseFloat(val);\n };return this;\n }\n //noinspection JSUnusedGlobalSymbols\n\n }, {\n key: 'default',\n\n\n //noinspection ReservedWordAsName\n /**\n * Sets the default value to use if not set\n * @param val\n * @return {Field}\n */\n value: function _default(val) {\n this._default = val;\n return this;\n }\n\n /**\n * Assigns the property to a bucket for hierarchy\n * @param name\n * @return {Field}\n */\n\n }, {\n key: 'group',\n value: function group(name) {\n this._group = name;\n return this;\n }\n\n /**\n * Gets the group the field belongs to\n * @return {*|null}\n */\n\n }, {\n key: 'getGroup',\n value: function getGroup() {\n return this._group;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets the formatted value of the field\n * @param val\n * @param strip\n * @return {*}\n */\n\n }, {\n key: 'value',\n value: function value(val) {\n var strip = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n if (this._strip && strip) return undefined;\n if (val !== undefined && this._convert) {\n val = this._convert(val);\n }\n return val !== undefined ? val : this._default;\n }\n }], [{\n key: 'array',\n value: function array(converter) {\n return new Field().array(converter);\n }\n }, {\n key: 'string',\n value: function string() {\n return new Field().string();\n }\n }, {\n key: 'bool',\n value: function bool() {\n return new Field().bool();\n }\n }, {\n key: 'strip',\n value: function strip() {\n return new Field().strip();\n }\n }, {\n key: 'int',\n value: function int() {\n return new Field().int();\n }\n }, {\n key: 'float',\n value: function float() {\n return new Field().float();\n }\n }]);\n\n return Field;\n }();\n\n // Export\n return okanjo._Widget = Widget;\n})(window);\n\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window) {\n\n //region Imports and Constants\n\n var okanjo = window.okanjo;\n var _okanjo$_Widget$Field = okanjo._Widget.Field,\n string = _okanjo$_Widget$Field.string,\n array = _okanjo$_Widget$Field.array,\n float = _okanjo$_Widget$Field.float,\n int = _okanjo$_Widget$Field.int,\n bool = _okanjo$_Widget$Field.bool;\n\n var Metrics = okanjo.metrics.constructor;\n var TemplateEngine = okanjo.ui.engine.constructor;\n\n var FILTERS = 'filters';\n var DISPLAY = 'display';\n var ARTICLE_META = 'article_meta';\n\n var MINIMUM_VIEW_PX = 0.5; // 50% of pixels must be in viewport\n var MINIMUM_VIEW_TIME = 1000; // for 1 full second\n var MINIMUM_VIEW_FREQ = 2; // time / freq = interval\n\n //endregion\n\n /**\n * Placement widget\n */\n\n var Placement = function (_okanjo$_Widget) {\n _inherits(Placement, _okanjo$_Widget);\n\n //region Configuration & Overrides\n\n /**\n * Initializes a new placement\n * @param element\n * @param options\n */\n function Placement(element) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n _classCallCheck(this, Placement);\n\n // Flatten the options before passing on\n options = okanjo.util.flatten(options, { ignoreArrays: true });\n\n var _this10 = _possibleConstructorReturn(this, (Placement.__proto__ || Object.getPrototypeOf(Placement)).call(this, element, options));\n\n _this10.name = 'Placement';\n _this10._metricBase = {}; // placeholder for metrics\n _this10._response = null;\n\n // Aggregate view watchers into a single interval fn\n _this10._viewWatcherIv = null;\n _this10._viewedWatchers = [];\n\n // Start loading content\n if (!options.no_init) _this10.init();\n return _this10;\n }\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Gets the widget settings configuration\n * @return {{type: *, ids: *, q: *, url: *, url_referrer: *, url_selectors: *, organization_id: *, property_id: *, store_id: *, organization_name: *, property_name: *, store_name: *, external_id: *, sku: *, external_store_id: *, condition: *, manufacturer: *, upc: *, isbn: *, tags: *, category: *, pools: *, min_price: *, max_price: *, min_donation_percent: *, max_donation_percent: *, donation_to: *, sort_by: *, sort_direction: *, skip: *, take: *, placement_tests_only: *, size: *, template_name: *, template_layout: *, template_theme: *, template_cta_style: *, template_cta_text: *, template_cta_color: *, adx_unit_path: *, url_category: *, url_keywords: *, no_init: *, proxy_url: *, expandable, disable_inline_buy, disable_popup, backwards: *}}\n */\n\n\n _createClass(Placement, [{\n key: 'getSettings',\n value: function getSettings() {\n return {\n\n // What type of response do you want\n type: string().group(FILTERS),\n\n // What specific products do you want\n ids: array().group(FILTERS),\n\n // Filter by generic query string\n q: string().group(FILTERS),\n\n // Filter by relation to content\n url: string().group(FILTERS),\n url_referrer: string().group(FILTERS).strip(),\n url_selectors: string().group(FILTERS),\n url_paths: array().group(FILTERS),\n not_url_paths: array().group(FILTERS),\n\n // Filter by hierarchy\n organization_id: string().group(FILTERS),\n property_id: string().group(FILTERS),\n store_id: string().group(FILTERS),\n\n // Filter by hierarchy names (use *_id where possible, this might not work as you might expect)\n organization_name: string().group(FILTERS),\n property_name: string().group(FILTERS),\n store_name: string().group(FILTERS),\n\n // Filter by integrations\n external_id: string().group(FILTERS),\n sku: string().group(FILTERS),\n external_store_id: string().group(FILTERS),\n\n // Filter by product attributes\n condition: string().group(FILTERS),\n manufacturer: string().group(FILTERS),\n upc: string().group(FILTERS),\n isbn: string().group(FILTERS),\n\n // Filter by categorization / distribution\n tags: array().group(FILTERS),\n category: array().group(FILTERS),\n pools: array().group(FILTERS),\n\n // Filter by price range\n min_price: float().group(FILTERS),\n max_price: float().group(FILTERS),\n\n // Filter by donation ranges\n min_donation_percent: float().group(FILTERS),\n max_donation_percent: float().group(FILTERS),\n\n // Filter by donation recipient\n donation_to: string().group(FILTERS),\n\n // Sorting\n sort_by: string().group(FILTERS),\n sort_direction: string().group(FILTERS),\n\n // Pagination\n skip: int().group(FILTERS),\n take: int().group(FILTERS),\n\n // Placement Testing\n placement_tests_only: bool(),\n\n // Display settings\n size: string().group(DISPLAY),\n template_name: string().group(DISPLAY),\n template_layout: string().group(DISPLAY),\n template_theme: string().group(DISPLAY),\n template_variant: string().group(DISPLAY),\n template_cta_style: string().group(DISPLAY),\n template_cta_text: string().group(DISPLAY),\n template_cta_color: string().group(DISPLAY),\n adx_unit_path: string().group(DISPLAY), // Custom DFP ad unit path\n\n // Article metadata\n url_category: array().group(ARTICLE_META),\n url_keywords: array().group(ARTICLE_META),\n\n // Functional settings\n key: string().strip(), // don't need to resend key on all our requests\n no_init: bool().strip(), // don't automatically load the placement, do it manually (e.g. (new Placement({no_init:true})).init()\n proxy_url: string().strip(),\n expandable: bool().strip().default(true),\n disable_inline_buy: bool().strip().default(false), // stops inline buy functionality\n disable_popup: bool().strip().default(false), // stops new window on mobile for inline buy functionality\n backwards: string().strip(), // internal flag indicating port from a deprecated widget\n testing: bool().strip() // metrics flag to indicate testing\n };\n }\n\n /**\n * Gets the widget configuration formatted using settings, suitable for transmission\n * @return {{filters: {}, display: {}, backfill: {}, shortfill: {}, article_meta: {}}}\n */\n\n }, {\n key: 'getConfig',\n value: function getConfig() {\n var _this11 = this;\n\n var settings = this.getSettings();\n var out = { filters: {}, display: {}, backfill: {}, shortfill: {}, article_meta: {} };\n var backfillPattern = /^backfill_(.+)$/; // backfill_property\n var shortfillPattern = /^shortfill_(.+)$/; // shortfill_property\n\n Object.keys(this.config).forEach(function (origKey) {\n var val = _this11.config[origKey];\n var key = origKey;\n var isBackfill = false;\n var isShortfill = false;\n var group = null;\n\n // Get the property name if it was prefixed with backfill\n var matches = backfillPattern.exec(origKey);\n if (matches) {\n key = matches[1];\n isBackfill = true;\n } else {\n // Get the property name if it was prefixed with shortfill\n matches = shortfillPattern.exec(origKey);\n if (matches) {\n key = matches[1];\n isShortfill = true;\n }\n }\n\n // Check if this is a known property\n if (settings[key]) {\n val = settings[key].value(val);\n group = settings[key].getGroup();\n }\n\n // Init the target/group if not already setup\n var target = out;\n if (isBackfill) {\n target = out.backfill;\n } else if (isShortfill) {\n target = out.shortfill;\n }\n\n // Set the target to the bucket in the settings container\n // except shortfill - can only apply settings directly to the bucket\n // e.g. backfill_url -> { backfill: { filters: { url: xxx } } }\n // e.g. shortfill_url-> { shortfill: { url: xxx } }\n if (!isShortfill && group) {\n target[group] = target[group] || {};\n target = target[group];\n }\n\n // Set the value on the target if set\n if (val === null) {\n target[key] = ''; // format null values as empty strings for transmission\n } else if (val !== undefined) {\n target[key] = val;\n }\n });\n\n return out;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Core load process\n */\n\n }, {\n key: 'load',\n value: function load() {\n var _this12 = this;\n\n // Set metric base data (stub for all future events emitted by the widget)\n this._setMetricBase();\n\n // Find out what we should display here\n this._fetchContent(function (err) {\n if (err) {\n // Report the widget load as declined\n _this12._reportWidgetLoad(\"fetch failed: \" + err.statusCode /* istanbul ignore next: out of scope */ || err.toString());\n } else {\n // Merge display settings from response\n _this12._mergeResponseSettings();\n\n // Merge the referential data from the response\n _this12._updateBaseMetaFromResponse();\n\n // Handle rendering based on output type\n _this12._showContent();\n }\n });\n }\n\n //endregion\n\n //region Internal Helpers\n\n /**\n * Initializes the common metric data for events emitted by the placement\n * @private\n */\n\n }, {\n key: '_setMetricBase',\n value: function _setMetricBase() {\n var base = this._metricBase;\n base.ch = Metrics.Channel.placement;\n base.cx = this.config.backwards || 'auto';\n base.key = this.config.key;\n base.m = base.m || {};\n base.m.wgid = this.instanceId;\n\n if (this.config.testing) base.env = Metrics.Environment.testing;\n }\n\n /**\n * Emits the widget impression event\n * @param declined\n * @private\n */\n\n }, {\n key: '_reportWidgetLoad',\n value: function _reportWidgetLoad(declined) {\n var _this13 = this;\n\n var res = this._response || {};\n var data = res.data || { results: [] };\n\n // If this is declined, mark future events as declined too\n this._metricBase.m.decl = declined || '0';\n\n // Attach other main response attributes to all future events\n this._metricBase.m.res_bf = data.backfilled ? 1 : 0; // whether the response used the back fill flow\n this._metricBase.m.res_sf = data.shortfilled ? 1 : 0; // whether the response used the short fill flow\n this._metricBase.m.res_spltfl = data.splitfilled ? 1 : 0; // whether the response used the short fill flow\n this._metricBase.m.res_total = data.total || 0; // how many total candidate results were available given filters\n this._metricBase.m.res_type = data.type; // what the given resource type was\n this._metricBase.m.res_length = data.results.length; // number of resources delivered\n\n // Track impression\n okanjo.metrics.create(this._metricBase).type(Metrics.Object.widget, Metrics.Event.impression).meta(this.getConfig()).element(this.element) // this might not be all that useful cuz the content hasn't been rendered yet\n .viewport().widget(this.element).send();\n\n // Start watching for a viewable impression\n this._addOnceViewedHandler(this.element, function () {\n okanjo.metrics.create(_this13._metricBase).type(Metrics.Object.widget, Metrics.Event.view).meta(_this13.getConfig()).element(_this13.element).viewport().widget(_this13.element).send();\n });\n }\n\n /**\n * Executes the request for content to fill the placement\n * @param callback\n * @private\n */\n\n }, {\n key: '_fetchContent',\n value: function _fetchContent(callback) {\n var _this14 = this;\n\n // Build request to api, starting with this placement config params\n var query = this.getConfig();\n\n // Extract the key\n var key = this.config.key;\n\n // Attach sid and referrer\n if (okanjo.metrics.sid) query.sid = okanjo.metrics.sid;\n query.filters.url_referrer = this.config.url_referrer || window.location.href;\n query.wgid = this.instanceId;\n query.pgid = okanjo.metrics.pageId;\n\n // Send it\n okanjo.net.request.post(okanjo.net.getRoute(okanjo.net.routes.ads, null, this.config.sandbox ? 'sandbox' : 'live') + '?key=' + encodeURIComponent(key), query, function (err, res) {\n if (err) {\n okanjo.report('Failed to retrieve placement content', err, { placement: _this14 });\n _this14.setMarkup(''); // Don't show anything\n _this14.emit('error', err);\n callback && callback(err);\n } else {\n\n // Store the raw response\n _this14._response = res;\n\n // Hook point for response handling\n _this14.emit('data');\n\n // Return\n callback && callback();\n }\n });\n }\n\n /**\n * Applies response filters and display settings into the widget configuration\n * @private\n */\n\n }, {\n key: '_mergeResponseSettings',\n value: function _mergeResponseSettings() {\n var _this15 = this;\n\n var res = this._response;\n var data = res.data || {};\n var settings = data.settings || {};\n\n if (settings.filters) {\n Object.keys(settings.filters).forEach(function (key) {\n _this15.config[key] = settings.filters[key];\n });\n }\n\n if (settings.display) {\n Object.keys(settings.display).forEach(function (key) {\n _this15.config[key] = settings.display[key];\n });\n }\n }\n\n /**\n * Applies response data to future metric events\n * @private\n */\n\n }, {\n key: '_updateBaseMetaFromResponse',\n value: function _updateBaseMetaFromResponse() {\n // Update the base metric data with info from the response\n var data = (this._response || {}).data || {};\n this._metricBase.m = this._metricBase.m || {};\n var meta = this._metricBase.m;\n\n // Article\n if (data.article) meta.aid = data.article.id;\n\n if (data.test && data.test.enabled) {\n meta.pten = 1;\n meta.ptid = data.test.id;\n meta.ptseed = data.test.seed;\n } else {\n meta.pten = 0;\n }\n }\n\n /**\n * Beings the render process based on the response content\n * @private\n */\n\n }, {\n key: '_showContent',\n value: function _showContent() {\n var data = (this._response || {}).data || {};\n\n // Known content types we can display\n if (data.type === Placement.ContentTypes.products) {\n this._showProducts();\n } else if (data.type === Placement.ContentTypes.articles) {\n this._showArticles();\n } else if (data.type === Placement.ContentTypes.adx) {\n this._showADX();\n } else {\n // Unknown response type!\n\n // Report the widget load as declined\n var msg = 'Unknown response content type: ' + data.type;\n okanjo.report(msg, { placement: this });\n this.setMarkup(''); // Don't show anything\n this.emit('error', msg);\n this._reportWidgetLoad(msg);\n }\n }\n\n /**\n * Generates the click url using the event, proxy_url, and additional params\n * @param event\n * @param url\n * @param additionalUrlParams\n * @return {*}\n * @private\n */\n\n }, {\n key: '_getClickThroughURL',\n value: function _getClickThroughURL(event, url, additionalUrlParams) {\n var joiner = url.indexOf('?') >= 0 ? '&' : '?';\n\n // Tack on transfer params\n additionalUrlParams = additionalUrlParams /* istanbul ignore next: paranoia */ || {};\n additionalUrlParams.ok_msid = okanjo.metrics.sid || 'unknown';\n additionalUrlParams.ok_ch = this._metricBase.ch;\n additionalUrlParams.ok_cx = this._metricBase.cx;\n additionalUrlParams._okjr = window.location.href.split(/[?#]/)[0];\n additionalUrlParams.utm_source = 'okanjo';\n additionalUrlParams.utm_campaign = 'smartserve';\n // additionalUrlParams.utm_source = window.location.hostname;\n additionalUrlParams.utm_medium = 'smartserve';\n // additionalUrlParams.utm_campaign = 'smartserve';\n\n\n url += joiner + Object.keys(additionalUrlParams).map(function (key) {\n return encodeURIComponent(key) + '=' + encodeURIComponent(additionalUrlParams[key]);\n }).join('&');\n\n // Wrap the url if we're proxying\n if (this.config.proxy_url) {\n url = this.config.proxy_url + encodeURIComponent(url);\n }\n\n // Set the url on the event\n event.data({\n u: url\n });\n\n return event.toUrl();\n }\n\n /**\n * Converts a resource's link into one suitable for tracking, making middle-click safe\n * @param type\n * @param resource\n * @param e\n * @private\n */\n\n }, {\n key: '_handleResourceMouseDown',\n value: function _handleResourceMouseDown(type, resource, e) {\n // Generate a new click id for this event\n // const clickId = okanjo.util.shortid();\n var clickId = resource._cid;\n\n // Start building the event\n var event = okanjo.metrics.create(this._metricBase, {\n id: resource.id\n }).type(type, Metrics.Event.interaction).meta(this.getConfig()).meta({ cid: clickId }).meta({\n bf: resource.backfill ? 1 : 0,\n sf: resource.shortfill ? 1 : 0,\n spltfl_seg: resource.splitfill_segment || null\n }).event(e).element(e.currentTarget).viewport().widget(this.element);\n\n // Pull the proper params out of the resource depending on it's type\n var trackParam = 'url_track_param';\n var urlParam = 'url';\n\n if (type === Metrics.Object.product) {\n trackParam = 'buy_url_track_param';\n urlParam = 'buy_url';\n }\n\n // Attach the campaign tracking identifier\n var additionalParams = {\n ok_cid: clickId\n };\n if (resource[trackParam]) additionalParams[resource[trackParam]] = clickId;\n\n // Update the link with the event data\n event.data({ ea: Metrics.Action.click });\n e.currentTarget.href = this._getClickThroughURL(event, resource[urlParam], additionalParams);\n\n // Cache this on the product\n resource._clickId = clickId;\n resource._event = event;\n resource._additionalParams = additionalParams;\n }\n\n /**\n * Gets the template to use, accounting for configured preference if available\n * @param contentType\n * @param defaultName\n * @return {string}\n * @private\n */\n\n }, {\n key: '_getTemplate',\n value: function _getTemplate(contentType, defaultName) {\n var templateName = this.config.template_name;\n if (!templateName || !okanjo.ui.engine.isTemplateRegistered(contentType + '.' + templateName)) {\n templateName = defaultName;\n }\n return contentType + '.' + templateName;\n }\n\n /**\n * Enforces size/layout/cta restrictions\n * @private\n */\n\n }, {\n key: '_enforceLayoutOptions',\n value: function _enforceLayoutOptions() {\n // Enforce format restrictions\n if (this.config.size === \"leaderboard\" || this.config.size === \"large_mobile_banner\") {\n this.config.template_layout = \"list\";\n this.config.template_cta_style = \"link\";\n } else if (this.config.size === \"half_page\" || this.config.size === \"auto\") {\n this.config.template_layout = \"list\";\n }\n }\n\n /**\n * Enforces\n * @private\n */\n\n }, {\n key: '_enforceSlabLayoutOptions',\n value: function _enforceSlabLayoutOptions() {\n if (this.config.size === \"medium_rectangle\" || this.config.size === \"billboard\") {\n // no list view\n this.config.template_layout = \"grid\";\n\n // no buttons\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n } else if (this.config.size === \"half_page\") {\n this.config.template_layout = \"grid\";\n } else if (this.config.size === \"leaderboard\" || this.config.size === \"large_mobile_banner\") {\n this.config.template_layout = \"list\";\n\n // no button\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n } else if (this.config.size === \"auto\") {\n this.config.template_layout = \"list\";\n } else if (this.config.size === \"responsive\") {\n // no button in responsive mode\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n }\n }\n\n /**\n * Register a custom\n * @private\n */\n\n }, {\n key: '_registerCustomBranding',\n value: function _registerCustomBranding() /*prefix, buttonClass*/{\n var brandColor = this.config.template_cta_color;\n if (brandColor) {\n var brandCSS = void 0,\n brandCSSId = \"okanjo-wgid-\" + this.instanceId;\n\n brandCSS = '\\n .okanjo-block2.' + brandCSSId + ' .okanjo-resource-cta-button, .okanjo-block2.' + brandCSSId + ' .okanjo-resource-buy-button { color: ' + brandColor + ' !important; } \\n .okanjo-block2.' + brandCSSId + '.okanjo-cta-style-button .okanjo-resource-cta-button, .okanjo-block2.' + brandCSSId + '.okanjo-cta-style-button .okanjo-resource-buy-button { border-color: ' + brandColor + ' !important; } \\n .okanjo-block2.' + brandCSSId + '.okanjo-cta-style-button .okanjo-resource-cta-button:hover, .okanjo-block2.' + brandCSSId + '.okanjo-cta-style-button .okanjo-resource-buy-button:hover { background: ' + brandColor + ' !important; color: #fff !important; } \\n ';\n\n okanjo.ui.engine.registerCss(brandCSSId, brandCSS, { id: brandCSSId });\n okanjo.ui.engine.ensureCss(brandCSSId);\n }\n }\n\n /**\n * When element is in view per viewability constants (50% for 1s) trigger handler once\n * @param element\n * @param handler\n * @private\n */\n\n }, {\n key: '_addOnceViewedHandler',\n value: function _addOnceViewedHandler(element, handler) {\n var controller = {\n element: element,\n successfulCount: 0,\n handler: handler\n };\n\n // Add our element to the watch list and turn on the watcher if not already on\n this._viewedWatchers.push(controller);\n this._toggleViewWatcher(true);\n }\n\n /**\n * Interval function to check viewability of registered elements\n * @private\n */\n\n }, {\n key: '_checkViewWatchers',\n value: function _checkViewWatchers() {\n\n // Check each registered watcher\n for (var i = 0, controller; i < this._viewedWatchers.length; i++) {\n controller = this._viewedWatchers[i];\n\n // Check if watcher is complete, then remove it from the list\n /* istanbul ignore next: jsdom won't trigger this */\n if (okanjo.ui.isElementVisible(controller.element) && okanjo.ui.getPercentageInViewport(controller.element) >= MINIMUM_VIEW_PX) {\n controller.successfulCount++;\n }\n\n // While this could more optimally be contained within the former condition, unit-testing blocks on this\n if (controller.successfulCount >= MINIMUM_VIEW_FREQ) {\n controller.handler();\n this._viewedWatchers.splice(i, 1);\n i--;\n }\n }\n\n // Turn off if nobody is watching\n if (this._viewedWatchers.length === 0) {\n this._toggleViewWatcher(false);\n }\n }\n\n /**\n * Turns the viewability watcher on and off\n * @param enabled\n * @private\n */\n\n }, {\n key: '_toggleViewWatcher',\n value: function _toggleViewWatcher(enabled) {\n if (enabled) {\n if (this._viewWatcherIv === null) {\n this._viewWatcherIv = setInterval(this._checkViewWatchers.bind(this), MINIMUM_VIEW_TIME / MINIMUM_VIEW_FREQ);\n }\n } else {\n clearInterval(this._viewWatcherIv);\n this._viewWatcherIv = null;\n }\n }\n\n //endregion\n\n //region Product Handling\n\n /**\n * Renders a product response\n * @private\n */\n\n }, {\n key: '_showProducts',\n value: function _showProducts() {\n var _this16 = this;\n\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n\n // Determine template to render, using custom template name if it exists\n var templateName = this._getTemplate(Placement.ContentTypes.products, Placement.DefaultTemplates.products);\n\n // - render\n\n // Format products\n data.results.forEach(function (offer, index) {\n // Disable inline buy if configured to do so\n if (_this16.config.disable_inline_buy) offer.inline_buy_url = null;\n if (offer.inline_buy_url) offer._escaped_inline_buy_url = encodeURIComponent(offer.inline_buy_url);\n\n // Set primary image\n offer._image_url = offer.image_urls ? offer.image_urls[0] : '';\n\n // Escape buy url (fixme: does not include proxy_url!)\n offer._escaped_buy_url = encodeURIComponent(offer.buy_url);\n\n // Make price tag pretty\n offer._price_formatted = TemplateEngine.formatCurrency(offer.price);\n offer._index = index;\n });\n\n // Render and display the results\n this.setMarkup(okanjo.ui.engine.render(templateName, this));\n\n // Track widget impression\n if (data.results.length === 0) {\n // Hook point for no results found\n this.emit('empty');\n this._reportWidgetLoad('empty'); // decline the impression\n } else {\n this._reportWidgetLoad();\n }\n\n // Bind interaction handlers and track impressions\n this.element.querySelectorAll('a').forEach(function (a) {\n\n var id = a.getAttribute('data-id'),\n index = a.getAttribute('data-index');\n\n // Don't bind links that are not tile links\n /* istanbul ignore else: custom templates could break it */\n if (id && index >= 0) {\n var product = _this16._response.data.results[index];\n /* istanbul ignore else: custom templates could break it */\n if (product) {\n\n // Bind interaction listener\n a.addEventListener('mousedown', _this16._handleResourceMouseDown.bind(_this16, Metrics.Object.product, product));\n a.addEventListener('click', _this16._handleProductClick.bind(_this16, product));\n\n // Track impression\n okanjo.metrics.create(_this16._metricBase, { id: product.id }).type(Metrics.Object.product, Metrics.Event.impression).meta(_this16.getConfig()).meta({\n bf: product.backfill ? 1 : 0,\n sf: product.shortfill ? 1 : 0,\n spltfl_seg: product.splitfill_segment || null\n }).element(a).viewport().widget(_this16.element).send();\n\n // Start watching for a viewable impression\n _this16._addOnceViewedHandler(a, function () {\n okanjo.metrics.create(_this16._metricBase, { id: product.id }).type(Metrics.Object.product, Metrics.Event.view).meta(_this16.getConfig()).meta({\n bf: product.backfill ? 1 : 0,\n sf: product.shortfill ? 1 : 0,\n spltfl_seg: product.splitfill_segment || null\n }).element(a).viewport().widget(_this16.element).send();\n });\n }\n }\n });\n\n // Truncate product name to fit the space\n this.element.querySelectorAll('.okanjo-resource-title').forEach(function (element) {\n okanjo.ui.ellipsify(element);\n });\n\n // Fit images\n okanjo.ui.fitImages(this.element);\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n /**\n * Handles the product click process\n * @param product\n * @param e\n * @private\n */\n\n }, {\n key: '_handleProductClick',\n value: function _handleProductClick(product, e) {\n\n // Update the event\n if (!product._event || !product._additionalParams || !product._clickId) {\n this._handleResourceMouseDown(Metrics.Object.product, product, e);\n }\n\n // Extract the already generated event and params list\n var event = product._event,\n additionalParams = product._additionalParams;\n\n // Update the event to the current one\n\n event.event(e);\n\n // Determine what we're doing - native ux or redirect\n var showNativeBuyUx = !!product.inline_buy_url,\n showPopupNativeBuyUx = !this.config.disable_popup && showNativeBuyUx && okanjo.util.isMobile();\n\n // Show the inline buy experience or redirect\n if (showPopupNativeBuyUx) {\n // Mobile native buy ux\n\n // Don't follow the link\n e.preventDefault();\n\n //\n // Mobile devices (especially iOS) have real janky UX when interacting with iframes.\n // So, we'll choose to popup a window with the native buy experience, so we can ensure\n // a positive user experience. Nobody likes bouncy form fields and really weird zooming.\n //\n\n // Update the event\n event.data({ ea: Metrics.Action.inline_click }).meta({ popup: 'true' });\n\n // Get the frame url\n var url = this._getClickThroughURL(event, product.inline_buy_url, additionalParams);\n\n // Open the window or redirect if that failed\n this._popupFrame = window.open(url, \"okanjo-inline-buy-frame\", \"width=400,height=400,location=yes,resizable=yes,scrollbars=yes\");\n /* istanbul ignore else: jsdom doesn't support window.open or setting window.location.href */\n if (!this._popupFrame) {\n // Fallback to just replacing the window with the target, since popups don't work :(\n okanjo.report('Popup blocker stopped buy experience from showing', { placement: this });\n window.location.href = url;\n }\n } else if (showNativeBuyUx) {\n // Regular native buy ux\n\n // Don't follow the link\n e.preventDefault();\n\n var frame = document.createElement('iframe');\n var attributes = {\n 'class': 'okanjo-inline-buy-frame',\n frameborder: 0,\n vspace: 0,\n hspace: 0,\n webkitallowfullscreen: '',\n mozallowfullscreen: '',\n allowfullscreen: '',\n scrolling: 'auto'\n };\n\n // Apply attributes\n Object.keys(attributes).forEach(function (key) {\n return frame.setAttribute(key, attributes[key]);\n });\n\n // Check whether we're allowed to expand past the bounds of the placement\n additionalParams.expandable = this.config.expandable ? 1 : 0;\n if (!this.config.expandable) {\n var parent = this.element.querySelector('.okanjo-expansion-root');\n /* istanbul ignore else: custom templates could break this */\n if (parent) {\n frame.className += ' okanjo-ad-in-unit';\n frame.setAttribute('height', \"100%\");\n frame.setAttribute('width', \"100%\");\n\n parent.appendChild(frame);\n\n var size = okanjo.ui.getElementSize(parent);\n additionalParams.frame_height = size.height;\n additionalParams.frame_width = size.width;\n /* istanbul ignore next: i'm not writing a whole test for this one config param */\n if (this.config.size) additionalParams.ad_size = this.config.size;\n }\n }\n\n // Update the event\n event.data({ ea: Metrics.Action.inline_click }).meta({ expandable: this.config.expandable ? 'true' : 'false' });\n\n // Set the frame url\n frame.src = this._getClickThroughURL(event, product.inline_buy_url, additionalParams);\n\n // Show the modal if it was not internally expanded\n if (!frame.parentNode) {\n okanjo.ui.modal.show(frame);\n }\n } else {\n // Update the link a second time, just in case the data changed\n e.currentTarget.href = this._getClickThroughURL(event, product.buy_url, additionalParams);\n }\n }\n\n //endregion\n\n //region Article Handling\n\n /**\n * Renders an article response\n * @private\n */\n\n }, {\n key: '_showArticles',\n value: function _showArticles() {\n var _this17 = this;\n\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n\n // Determine template to render, using custom template name if it exists\n var templateName = this._getTemplate(Placement.ContentTypes.articles, Placement.DefaultTemplates.articles);\n\n // - render\n\n // Format articles\n data.results.forEach(function (article, index) {\n // Escape url (fixme: does not include proxy_url!)\n article._escaped_url = encodeURIComponent(article.url);\n article._index = index;\n });\n\n // Render and display the results\n this.setMarkup(okanjo.ui.engine.render(templateName, this));\n\n // Track widget impression\n if (data.results.length === 0) {\n // Hook point for no results found\n this.emit('empty');\n this._reportWidgetLoad('empty'); // decline the impression\n } else {\n this._reportWidgetLoad();\n }\n\n // Bind interaction handlers and track impressions\n this.element.querySelectorAll('a').forEach(function (a) {\n\n var id = a.getAttribute('data-id'),\n index = a.getAttribute('data-index');\n\n // Don't bind links that are not tile links\n /* istanbul ignore else: custom templates could break this */\n if (id && index >= 0) {\n var article = _this17._response.data.results[index];\n /* istanbul ignore else: custom templates could break this */\n if (article) {\n\n // Bind interaction listener\n a.addEventListener('mousedown', _this17._handleResourceMouseDown.bind(_this17, Metrics.Object.article, article));\n a.addEventListener('click', _this17._handleArticleClick.bind(_this17, article));\n\n // Track impression\n okanjo.metrics.create(_this17._metricBase, { id: article.id }).type(Metrics.Object.article, Metrics.Event.impression).meta(_this17.getConfig()).meta({\n bf: article.backfill ? 1 : 0,\n sf: article.shortfill ? 1 : 0,\n spltfl_seg: article.splitfill_segment || null\n }).element(a).viewport().widget(_this17.element).send();\n\n // Start watching for a viewable impression\n _this17._addOnceViewedHandler(a, function () {\n okanjo.metrics.create(_this17._metricBase, { id: article.id }).type(Metrics.Object.article, Metrics.Event.view).meta(_this17.getConfig()).meta({\n bf: article.backfill ? 1 : 0,\n sf: article.shortfill ? 1 : 0,\n spltfl_seg: article.splitfill_segment || null\n }).element(a).viewport().widget(_this17.element).send();\n });\n }\n }\n });\n\n // Truncate product name to fit the space\n this.element.querySelectorAll('.okanjo-resource-title').forEach(function (element) {\n okanjo.ui.ellipsify(element);\n });\n\n // Fit images\n okanjo.ui.fitImages(this.element);\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n /**\n * Handles the article click process\n * @param article\n * @param e\n * @private\n */\n\n }, {\n key: '_handleArticleClick',\n value: function _handleArticleClick(article, e) {\n // Update the event\n if (!article._event || !article._additionalParams || !article._clickId) {\n this._handleResourceMouseDown(Metrics.Object.article, article, e);\n }\n\n // Extract the already generated event and params list\n var event = article._event,\n additionalParams = article._additionalParams;\n\n // Update the event to the current one\n\n event.event(e);\n\n // Update the link a second time, just in case the data changed\n e.currentTarget.href = this._getClickThroughURL(event, article.url, additionalParams);\n }\n\n //endregion\n\n //region ADX Handling\n\n /**\n * Renders a Google DFP/ADX response\n * @private\n */\n\n }, {\n key: '_showADX',\n value: function _showADX() {\n var _this18 = this;\n\n var data = (this._response || { data: { settings: {} } }).data || { settings: {} };\n\n // Get the template we should use to render the google ad\n var templateName = this._getTemplate(Placement.ContentTypes.adx, Placement.DefaultTemplates.adx);\n\n // Determine what size ad we can place here\n var size = null;\n if (this.config.size) {\n if (Placement.Sizes[this.config.size]) {\n // Defined size, use these known dimensions\n size = Placement.Sizes[this.config.size];\n } else {\n var match = /^([0-9]+)x([0-9]+)$/i.exec(this.config.size);\n if (match) {\n size = { width: match[1], height: match[2] };\n }\n }\n }\n\n // No given size, we need to guess\n if (!size) size = Placement.Sizes.default;\n\n // If we're using okanjo's ad slot, then track the impression\n // otherwise decline it because we're just passing through to the publishers account\n var adUnitPath = '/90447967/okanjo:';\n var declineReason = void 0;\n if (data.settings.display && data.settings.display.adx_unit_path) {\n adUnitPath = data.settings.display.adx_unit_path;\n declineReason = 'custom_ad_unit';\n }\n\n // Pass along what the template needs to know to display the ad\n var renderContext = {\n size: size,\n adUnitPath: adUnitPath\n };\n\n // Render the container\n this.setMarkup(okanjo.ui.engine.render(templateName, this, renderContext));\n\n // Report the impression\n this._reportWidgetLoad(declineReason);\n\n // Insert the actual ad into the container\n var container = this.element.querySelector('.okanjo-adx-container');\n /* istanbul ignore else: custom templates could break this */\n if (container) {\n\n // Make the frame element\n var frame = document.createElement('iframe');\n var attributes = {\n 'class': 'okanjo-adx-frame',\n frameborder: 0,\n vspace: 0,\n hspace: 0,\n webkitallowfullscreen: '',\n mozallowfullscreen: '',\n allowfullscreen: '',\n scrolling: 'auto',\n width: size.width,\n height: size.height\n };\n\n // Apply attributes\n Object.keys(attributes).forEach(function (key) {\n return frame.setAttribute(key, attributes[key]);\n });\n\n // Attach to dOM\n container.appendChild(frame);\n\n // Build a click-through tracking url so we know when an ad is clicked too\n var clickUrl = okanjo.metrics.create(this._metricBase).type(Metrics.Object.thirdparty_ad, Metrics.Event.interaction).meta(this.getConfig()).meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n }).element(frame).viewport().widget(this.element).toUrl();\n\n // Transfer references to the frame window\n // frame.contentWindow.okanjo = okanjo;\n // frame.contentWindow.placement = this;\n frame.contentWindow.trackImpression = function () {\n okanjo.metrics.create(_this18._metricBase).type(Metrics.Object.thirdparty_ad, Metrics.Event.impression).meta(_this18.getConfig()).meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n }).element(frame).viewport().widget(_this18.element).send();\n\n // Start watching for a viewable impression\n _this18._addOnceViewedHandler(frame, function () {\n okanjo.metrics.create(_this18._metricBase).type(Metrics.Object.thirdparty_ad, Metrics.Event.view).meta(_this18.getConfig()).meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n }).element(frame).viewport().widget(_this18.element).send();\n });\n };\n\n // Load Google ad!\n frame.contentWindow.document.open();\n frame.contentWindow.document.write('\\n<' + ('script type=\"text/javascript\" src=\"https://www.googletagservices.com/tag/js/gpt.js\">\\n googletag.pubads().addEventListener(\\'slotRenderEnded\\', function(e) { \\n trackImpression(e);\\n });\\n googletag.pubads()\\n .definePassback(\"' + adUnitPath.replace(/\"/g, '\\\\\"') + '\", [[' + size.width + ', ' + size.height + ']])\\n .setClickUrl(\"' + clickUrl + '&u=\")\\n .display();\\n<') + '/script>\\n');\n frame.contentWindow.document.close();\n\n // TODO future event hooks\n // googletag.pubads().addEventListener('impressionViewable', function(e) { future )});\n // googletag.pubads().addEventListener('slotOnload', function(e) { future });\n // googletag.pubads().addEventListener('slotVisibilityChangedEvent', function(e) { future );\n\n // Impression tracking is done from within the iframe. Crazy, right?\n }\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n //endregion\n\n }]);\n\n return Placement;\n }(okanjo._Widget);\n\n //region Enumerations\n\n /**\n * Standard ad sizes\n * @type {{billboard: {width: number, height: number}, button_2: {width: number, height: number}, half_page: {width: number, height: number}, leaderboard: {width: number, height: number}, medium_rectangle: {width: number, height: number}, micro_bar: {width: number, height: number}, portrait: {width: number, height: number}, rectangle: {width: number, height: number}, super_leaderboard: {width: number, height: number}, wide_skyscraper: {width: number, height: number}, large_mobile_banner: {width: number, height: number}, mobile_leaderboard: {width: number, height: number}, small_square: {width: number, height: number}, button_1: {width: number, height: number}, full_banner: {width: number, height: number}, half_banner: {width: number, height: number}, large_rectangle: {width: number, height: number}, pop_under: {width: number, height: number}, three_to_one_rectangle: {width: number, height: number}, skyscraper: {width: number, height: number}, square: {width: number, height: number}, square_button: {width: number, height: number}, vertical_banner: {width: number, height: number}, vertical_rectangle: {width: number, height: number}}}\n */\n\n\n Placement.Sizes = {\n\n // Supported\n medium_rectangle: { width: 300, height: 250 }, // aka: sidekick\n leaderboard: { width: 728, height: 90 },\n large_mobile_banner: { width: 320, height: 100 },\n half_page: { width: 300, height: 600 }, // aka: filmstrip, sidekick\n billboard: { width: 970, height: 250 }, // aka: sidekick\n\n // IAB / Others\n button_2: { width: 120, height: 60 },\n micro_bar: { width: 88, height: 31 },\n portrait: { width: 300, height: 1050 },\n rectangle: { width: 180, height: 150 },\n super_leaderboard: { width: 970, height: 90 }, // aka: pushdown, slider, large_leaderboard\n wide_skyscraper: { width: 160, height: 600 },\n\n // Google\n mobile_leaderboard: { width: 320, height: 50 },\n small_square: { width: 200, height: 200 },\n\n // Retired / Deprecated\n button_1: { width: 120, height: 90 },\n full_banner: { width: 468, height: 60 },\n half_banner: { width: 234, height: 60 },\n large_rectangle: { width: 336, height: 280 },\n pop_under: { width: 720, height: 300 },\n three_to_one_rectangle: { width: 300, height: 100 },\n skyscraper: { width: 120, height: 600 },\n square: { width: 250, height: 250 },\n square_button: { width: 125, height: 125 },\n vertical_banner: { width: 120, height: 240 },\n vertical_rectangle: { width: 240, height: 400 }\n };\n\n // When we should show an ad but nobody told us what size\n Placement.Sizes.default = Placement.Sizes.medium_rectangle;\n\n /**\n * Placement content types\n * @type {{products: string, articles: string, adx: string}}\n */\n Placement.ContentTypes = {\n products: 'products',\n articles: 'articles',\n adx: 'adx'\n };\n\n /**\n * Default templates for each content type\n * @type {{products: string, articles: string, adx: string}}\n */\n Placement.DefaultTemplates = {\n products: 'block2',\n articles: 'block2',\n adx: 'block2'\n };\n\n //endregion\n\n return okanjo.Placement = Placement;\n})(window);\n\"use strict\";\n\n// **********\n// DEPRECATED - USE okanjo.Placement instead!\n// **********\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window) {\n\n var okanjo = window.okanjo;\n\n /**\n * Backwards compatible interface, turning a Product widget into a placement widget\n * @deprecated\n */\n\n var Product = function (_okanjo$Placement) {\n _inherits(Product, _okanjo$Placement);\n\n function Product(element, options) {\n _classCallCheck(this, Product);\n\n // Initialize placement w/o loading (we need to jack the config)\n options = options || {};\n var no_init = options.no_init; // hold original no_init flag, if set\n options.no_init = true;\n\n var _this19 = _possibleConstructorReturn(this, (Product.__proto__ || Object.getPrototypeOf(Product)).call(this, element, options));\n\n okanjo.warn('Product widget has been deprecated. Use Placement instead (may require configuration changes)', { widget: _this19 });\n\n // Start loading content\n if (!no_init) {\n delete _this19.config.no_init;\n _this19.init();\n }\n return _this19;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Converts the old product widget configuration into a usable placement configuration\n */\n\n\n _createClass(Product, [{\n key: '_setCompatibilityOptions',\n value: function _setCompatibilityOptions() {\n // Convert the product config to a placement configuration\n this.config.backwards = 'Product';\n this.config.type = okanjo.Placement.ContentTypes.products;\n\n // Set filters based on old \"mode\"\n if (this.config.mode === 'sense') {\n // sense\n this.config.url = this.config.url || 'referrer';\n this.config.take = this.config.take || 5;\n } else if (this.config.mode === 'single') {\n // single\n this.config.url = null;\n if (this.config.id) this.config.ids = [this.config.id];\n this.config.take = 1;\n delete this.config.id;\n } else {\n // browse\n this.config.url = null;\n this.config.take = this.config.take || 25;\n }\n delete this.config.mode;\n\n // Sold by changed to store name\n if (this.config.sold_by) {\n this.config.store_name = this.config.sold_by;\n delete this.config.sold_by;\n }\n\n // Selectors is now url_selectors\n if (this.config.selectors) {\n this.config.url_selectors = this.config.selectors;\n delete this.config.selectors;\n }\n\n // Marketplace_id is no longer a thing, closest analog are properties.\n if (this.config.marketplace_id) {\n this.config.property_id = this.config.marketplace_id;\n delete this.config.marketplace_id;\n }\n\n // Marketplace status is no longer a thing, instead, use the sandbox environment for testing\n if (this.config.marketplace_status === 'testing') {\n this.config.sandbox = true;\n }\n delete this.config.marketplace_status;\n\n // Deprecated\n delete this.config.suboptimal;\n delete this.config.text;\n }\n }]);\n\n return Product;\n }(okanjo.Placement);\n\n return okanjo.Product = Product;\n})(window);\n\"use strict\";\n\n// **********\n// DEPRECATED - USE okanjo.Placement instead!\n// **********\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window) {\n\n var okanjo = window.okanjo;\n\n /**\n * Backwards compatible interface, turning an Ad widget into a placement widget\n * @deprecated\n */\n\n var Ad = function (_okanjo$Placement2) {\n _inherits(Ad, _okanjo$Placement2);\n\n function Ad(element, options) {\n _classCallCheck(this, Ad);\n\n // Initialize placement w/o loading (we need to jack the config)\n options = options || {};\n var no_init = options.no_init; // hold original no_init flag, if set\n options.no_init = true;\n\n var _this20 = _possibleConstructorReturn(this, (Ad.__proto__ || Object.getPrototypeOf(Ad)).call(this, element, options));\n\n okanjo.warn('Ad widget has been deprecated. Use Placement instead (may require configuration changes)', { widget: _this20 });\n\n // Start loading content\n if (!no_init) {\n delete _this20.config.no_init;\n _this20.init();\n }\n return _this20;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Converts the old product widget configuration into a usable placement configuration\n */\n\n\n _createClass(Ad, [{\n key: '_setCompatibilityOptions',\n value: function _setCompatibilityOptions() {\n // Convert the product config to a placement configuration\n this.config.backwards = 'Ad';\n this.config.type = okanjo.Placement.ContentTypes.products;\n\n // Id / single mode is now ids\n this.config.url = null;\n if (this.config.id) {\n this.config.ids = [this.config.id];\n } else {\n okanjo.warn('Ad widget should have parameter `id` set.');\n }\n this.config.take = 1;\n delete this.config.id;\n\n // Content is automatically determined whether the placement element contains children\n delete this.config.content;\n }\n }]);\n\n return Ad;\n }(okanjo.Placement);\n\n return okanjo.Ad = Ad;\n})(window);\n/* jshint ignore:start */\n\n(function () {\n\n /*!\n * mustache.js - Logic-less {{mustache}} templates with JavaScript\n * http://github.com/janl/mustache.js\n */\n\n /*global define: false Mustache: true*/\n\n (function defineMustache(global, factory) {\n if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object' && exports && typeof exports.nodeName !== 'string') {\n factory(exports); // CommonJS\n } else if (typeof define === 'function' && define.amd) {\n define(['exports'], factory); // AMD\n } else {\n global.Mustache = {};\n factory(global.Mustache); // script, wsh, asp\n }\n })(this, function mustacheFactory(mustache) {\n\n var objectToString = Object.prototype.toString;\n var isArray = Array.isArray || function isArrayPolyfill(object) {\n return objectToString.call(object) === '[object Array]';\n };\n\n function isFunction(object) {\n return typeof object === 'function';\n }\n\n /**\n * More correct typeof string handling array\n * which normally returns typeof 'object'\n */\n function typeStr(obj) {\n return isArray(obj) ? 'array' : typeof obj === 'undefined' ? 'undefined' : _typeof(obj);\n }\n\n function escapeRegExp(string) {\n return string.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, '\\\\$&');\n }\n\n /**\n * Null safe way of checking whether or not an object,\n * including its prototype, has a given property\n */\n function hasProperty(obj, propName) {\n return obj != null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && propName in obj;\n }\n\n // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577\n // See https://github.com/janl/mustache.js/issues/189\n var regExpTest = RegExp.prototype.test;\n function testRegExp(re, string) {\n return regExpTest.call(re, string);\n }\n\n var nonSpaceRe = /\\S/;\n function isWhitespace(string) {\n return !testRegExp(nonSpaceRe, string);\n }\n\n var entityMap = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n '/': '/',\n '`': '`',\n '=': '='\n };\n\n function escapeHtml(string) {\n return String(string).replace(/[&<>\"'`=\\/]/g, function fromEntityMap(s) {\n return entityMap[s];\n });\n }\n\n var whiteRe = /\\s*/;\n var spaceRe = /\\s+/;\n var equalsRe = /\\s*=/;\n var curlyRe = /\\s*\\}/;\n var tagRe = /#|\\^|\\/|>|\\{|&|=|!/;\n\n /**\n * Breaks up the given `template` string into a tree of tokens. If the `tags`\n * argument is given here it must be an array with two string values: the\n * opening and closing tags used in the template (e.g. [ \"<%\", \"%>\" ]). Of\n * course, the default is to use mustaches (i.e. mustache.tags).\n *\n * A token is an array with at least 4 elements. The first element is the\n * mustache symbol that was used inside the tag, e.g. \"#\" or \"&\". If the tag\n * did not contain a symbol (i.e. {{myValue}}) this element is \"name\". For\n * all text that appears outside a symbol this element is \"text\".\n *\n * The second element of a token is its \"value\". For mustache tags this is\n * whatever else was inside the tag besides the opening symbol. For text tokens\n * this is the text itself.\n *\n * The third and fourth elements of the token are the start and end indices,\n * respectively, of the token in the original template.\n *\n * Tokens that are the root node of a subtree contain two more elements: 1) an\n * array of tokens in the subtree and 2) the index in the original template at\n * which the closing tag for that section begins.\n */\n function parseTemplate(template, tags) {\n if (!template) return [];\n\n var sections = []; // Stack to hold section tokens\n var tokens = []; // Buffer to hold the tokens\n var spaces = []; // Indices of whitespace tokens on the current line\n var hasTag = false; // Is there a {{tag}} on the current line?\n var nonSpace = false; // Is there a non-space char on the current line?\n\n // Strips all whitespace tokens array for the current line\n // if there was a {{#tag}} on it and otherwise only space.\n function stripSpace() {\n if (hasTag && !nonSpace) {\n while (spaces.length) {\n delete tokens[spaces.pop()];\n }\n } else {\n spaces = [];\n }\n\n hasTag = false;\n nonSpace = false;\n }\n\n var openingTagRe, closingTagRe, closingCurlyRe;\n function compileTags(tagsToCompile) {\n if (typeof tagsToCompile === 'string') tagsToCompile = tagsToCompile.split(spaceRe, 2);\n\n if (!isArray(tagsToCompile) || tagsToCompile.length !== 2) throw new Error('Invalid tags: ' + tagsToCompile);\n\n openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\\\s*');\n closingTagRe = new RegExp('\\\\s*' + escapeRegExp(tagsToCompile[1]));\n closingCurlyRe = new RegExp('\\\\s*' + escapeRegExp('}' + tagsToCompile[1]));\n }\n\n compileTags(tags || mustache.tags);\n\n var scanner = new Scanner(template);\n\n var start, type, value, chr, token, openSection;\n while (!scanner.eos()) {\n start = scanner.pos;\n\n // Match any text between tags.\n value = scanner.scanUntil(openingTagRe);\n\n if (value) {\n for (var i = 0, valueLength = value.length; i < valueLength; ++i) {\n chr = value.charAt(i);\n\n if (isWhitespace(chr)) {\n spaces.push(tokens.length);\n } else {\n nonSpace = true;\n }\n\n tokens.push(['text', chr, start, start + 1]);\n start += 1;\n\n // Check for whitespace on the current line.\n if (chr === '\\n') stripSpace();\n }\n }\n\n // Match the opening tag.\n if (!scanner.scan(openingTagRe)) break;\n\n hasTag = true;\n\n // Get the tag type.\n type = scanner.scan(tagRe) || 'name';\n scanner.scan(whiteRe);\n\n // Get the tag value.\n if (type === '=') {\n value = scanner.scanUntil(equalsRe);\n scanner.scan(equalsRe);\n scanner.scanUntil(closingTagRe);\n } else if (type === '{') {\n value = scanner.scanUntil(closingCurlyRe);\n scanner.scan(curlyRe);\n scanner.scanUntil(closingTagRe);\n type = '&';\n } else {\n value = scanner.scanUntil(closingTagRe);\n }\n\n // Match the closing tag.\n if (!scanner.scan(closingTagRe)) throw new Error('Unclosed tag at ' + scanner.pos);\n\n token = [type, value, start, scanner.pos];\n tokens.push(token);\n\n if (type === '#' || type === '^') {\n sections.push(token);\n } else if (type === '/') {\n // Check section nesting.\n openSection = sections.pop();\n\n if (!openSection) throw new Error('Unopened section \"' + value + '\" at ' + start);\n\n if (openSection[1] !== value) throw new Error('Unclosed section \"' + openSection[1] + '\" at ' + start);\n } else if (type === 'name' || type === '{' || type === '&') {\n nonSpace = true;\n } else if (type === '=') {\n // Set the tags for the next time around.\n compileTags(value);\n }\n }\n\n // Make sure there are no open sections when we're done.\n openSection = sections.pop();\n\n if (openSection) throw new Error('Unclosed section \"' + openSection[1] + '\" at ' + scanner.pos);\n\n return nestTokens(squashTokens(tokens));\n }\n\n /**\n * Combines the values of consecutive text tokens in the given `tokens` array\n * to a single token.\n */\n function squashTokens(tokens) {\n var squashedTokens = [];\n\n var token, lastToken;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n token = tokens[i];\n\n if (token) {\n if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {\n lastToken[1] += token[1];\n lastToken[3] = token[3];\n } else {\n squashedTokens.push(token);\n lastToken = token;\n }\n }\n }\n\n return squashedTokens;\n }\n\n /**\n * Forms the given array of `tokens` into a nested tree structure where\n * tokens that represent a section have two additional items: 1) an array of\n * all tokens that appear in that section and 2) the index in the original\n * template that represents the end of that section.\n */\n function nestTokens(tokens) {\n var nestedTokens = [];\n var collector = nestedTokens;\n var sections = [];\n\n var token, section;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n token = tokens[i];\n\n switch (token[0]) {\n case '#':\n case '^':\n collector.push(token);\n sections.push(token);\n collector = token[4] = [];\n break;\n case '/':\n section = sections.pop();\n section[5] = token[2];\n collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;\n break;\n default:\n collector.push(token);\n }\n }\n\n return nestedTokens;\n }\n\n /**\n * A simple string scanner that is used by the template parser to find\n * tokens in template strings.\n */\n function Scanner(string) {\n this.string = string;\n this.tail = string;\n this.pos = 0;\n }\n\n /**\n * Returns `true` if the tail is empty (end of string).\n */\n Scanner.prototype.eos = function eos() {\n return this.tail === '';\n };\n\n /**\n * Tries to match the given regular expression at the current position.\n * Returns the matched text if it can match, the empty string otherwise.\n */\n Scanner.prototype.scan = function scan(re) {\n var match = this.tail.match(re);\n\n if (!match || match.index !== 0) return '';\n\n var string = match[0];\n\n this.tail = this.tail.substring(string.length);\n this.pos += string.length;\n\n return string;\n };\n\n /**\n * Skips all text until the given regular expression can be matched. Returns\n * the skipped string, which is the entire tail if no match can be made.\n */\n Scanner.prototype.scanUntil = function scanUntil(re) {\n var index = this.tail.search(re),\n match;\n\n switch (index) {\n case -1:\n match = this.tail;\n this.tail = '';\n break;\n case 0:\n match = '';\n break;\n default:\n match = this.tail.substring(0, index);\n this.tail = this.tail.substring(index);\n }\n\n this.pos += match.length;\n\n return match;\n };\n\n /**\n * Represents a rendering context by wrapping a view object and\n * maintaining a reference to the parent context.\n */\n function Context(view, parentContext) {\n this.view = view;\n this.cache = { '.': this.view };\n this.parent = parentContext;\n }\n\n /**\n * Creates a new context using the given view with this context\n * as the parent.\n */\n Context.prototype.push = function push(view) {\n return new Context(view, this);\n };\n\n /**\n * Returns the value of the given name in this context, traversing\n * up the context hierarchy if the value is absent in this context's view.\n */\n Context.prototype.lookup = function lookup(name) {\n var cache = this.cache;\n\n var value;\n if (cache.hasOwnProperty(name)) {\n value = cache[name];\n } else {\n var context = this,\n names,\n index,\n lookupHit = false;\n\n while (context) {\n if (name.indexOf('.') > 0) {\n value = context.view;\n names = name.split('.');\n index = 0;\n\n /**\n * Using the dot notion path in `name`, we descend through the\n * nested objects.\n *\n * To be certain that the lookup has been successful, we have to\n * check if the last object in the path actually has the property\n * we are looking for. We store the result in `lookupHit`.\n *\n * This is specially necessary for when the value has been set to\n * `undefined` and we want to avoid looking up parent contexts.\n **/\n while (value != null && index < names.length) {\n if (index === names.length - 1) lookupHit = hasProperty(value, names[index]);\n\n value = value[names[index++]];\n }\n } else {\n value = context.view[name];\n lookupHit = hasProperty(context.view, name);\n }\n\n if (lookupHit) break;\n\n context = context.parent;\n }\n\n cache[name] = value;\n }\n\n if (isFunction(value)) value = value.call(this.view);\n\n return value;\n };\n\n /**\n * A Writer knows how to take a stream of tokens and render them to a\n * string, given a context. It also maintains a cache of templates to\n * avoid the need to parse the same template twice.\n */\n function Writer() {\n this.cache = {};\n }\n\n /**\n * Clears all cached templates in this writer.\n */\n Writer.prototype.clearCache = function clearCache() {\n this.cache = {};\n };\n\n /**\n * Parses and caches the given `template` and returns the array of tokens\n * that is generated from the parse.\n */\n Writer.prototype.parse = function parse(template, tags) {\n var cache = this.cache;\n var tokens = cache[template];\n\n if (tokens == null) tokens = cache[template] = parseTemplate(template, tags);\n\n return tokens;\n };\n\n /**\n * High-level method that is used to render the given `template` with\n * the given `view`.\n *\n * The optional `partials` argument may be an object that contains the\n * names and templates of partials that are used in the template. It may\n * also be a function that is used to load partial templates on the fly\n * that takes a single argument: the name of the partial.\n */\n Writer.prototype.render = function render(template, view, partials) {\n var tokens = this.parse(template);\n var context = view instanceof Context ? view : new Context(view);\n return this.renderTokens(tokens, context, partials, template);\n };\n\n /**\n * Low-level method that renders the given array of `tokens` using\n * the given `context` and `partials`.\n *\n * Note: The `originalTemplate` is only ever used to extract the portion\n * of the original template that was contained in a higher-order section.\n * If the template doesn't use higher-order sections, this argument may\n * be omitted.\n */\n Writer.prototype.renderTokens = function renderTokens(tokens, context, partials, originalTemplate) {\n var buffer = '';\n\n var token, symbol, value;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n value = undefined;\n token = tokens[i];\n symbol = token[0];\n\n if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);else if (symbol === '&') value = this.unescapedValue(token, context);else if (symbol === 'name') value = this.escapedValue(token, context);else if (symbol === 'text') value = this.rawValue(token);\n\n if (value !== undefined) buffer += value;\n }\n\n return buffer;\n };\n\n Writer.prototype.renderSection = function renderSection(token, context, partials, originalTemplate) {\n var self = this;\n var buffer = '';\n var value = context.lookup(token[1]);\n\n // This function is used to render an arbitrary template\n // in the current context by higher-order sections.\n function subRender(template) {\n return self.render(template, context, partials);\n }\n\n if (!value) return;\n\n if (isArray(value)) {\n for (var j = 0, valueLength = value.length; j < valueLength; ++j) {\n buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);\n }\n } else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' || typeof value === 'string' || typeof value === 'number') {\n buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);\n } else if (isFunction(value)) {\n if (typeof originalTemplate !== 'string') throw new Error('Cannot use higher-order sections without the original template');\n\n // Extract the portion of the original template that the section contains.\n value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);\n\n if (value != null) buffer += value;\n } else {\n buffer += this.renderTokens(token[4], context, partials, originalTemplate);\n }\n return buffer;\n };\n\n Writer.prototype.renderInverted = function renderInverted(token, context, partials, originalTemplate) {\n var value = context.lookup(token[1]);\n\n // Use JavaScript's definition of falsy. Include empty arrays.\n // See https://github.com/janl/mustache.js/issues/186\n if (!value || isArray(value) && value.length === 0) return this.renderTokens(token[4], context, partials, originalTemplate);\n };\n\n Writer.prototype.renderPartial = function renderPartial(token, context, partials) {\n if (!partials) return;\n\n var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];\n if (value != null) return this.renderTokens(this.parse(value), context, partials, value);\n };\n\n Writer.prototype.unescapedValue = function unescapedValue(token, context) {\n var value = context.lookup(token[1]);\n if (value != null) return value;\n };\n\n Writer.prototype.escapedValue = function escapedValue(token, context) {\n var value = context.lookup(token[1]);\n if (value != null) return mustache.escape(value);\n };\n\n Writer.prototype.rawValue = function rawValue(token) {\n return token[1];\n };\n\n mustache.name = 'mustache.js';\n mustache.version = '2.3.2';\n mustache.tags = ['{{', '}}'];\n\n // All high-level mustache.* functions use this writer.\n var defaultWriter = new Writer();\n\n /**\n * Clears all cached templates in the default writer.\n */\n mustache.clearCache = function clearCache() {\n return defaultWriter.clearCache();\n };\n\n /**\n * Parses and caches the given template in the default writer and returns the\n * array of tokens it contains. Doing this ahead of time avoids the need to\n * parse templates on the fly as they are rendered.\n */\n mustache.parse = function parse(template, tags) {\n return defaultWriter.parse(template, tags);\n };\n\n /**\n * Renders the `template` with the given `view` and `partials` using the\n * default writer.\n */\n mustache.render = function render(template, view, partials) {\n if (typeof template !== 'string') {\n throw new TypeError('Invalid template! Template should be a \"string\" ' + 'but \"' + typeStr(template) + '\" was given as the first ' + 'argument for mustache#render(template, view, partials)');\n }\n\n return defaultWriter.render(template, view, partials);\n };\n\n // This is here for backwards compatibility with 0.4.x.,\n /*eslint-disable */ // eslint wants camel cased function name\n mustache.to_html = function to_html(template, view, partials, send) {\n /*eslint-enable*/\n\n var result = mustache.render(template, view, partials);\n\n if (isFunction(send)) {\n send(result);\n } else {\n return result;\n }\n };\n\n // Export the escaping function so that the user may override it.\n // See https://github.com/janl/mustache.js/issues/244\n mustache.escape = escapeHtml;\n\n // Export these mainly for testing, but also for advanced usage.\n mustache.Scanner = Scanner;\n mustache.Context = Context;\n mustache.Writer = Writer;\n\n return mustache;\n });\n}).apply(okanjo.lib);\n\n/* jshint ignore:end */\nreturn okanjo;\n}));\n","// Production steps of ECMA-262, Edition 6, 22.1.2.1\nif (!Array.from) {\n Array.from = (function () {\n var toStr = Object.prototype.toString;\n var isCallable = function (fn) {\n return typeof fn === 'function' || toStr.call(fn) === '[object Function]';\n };\n var toInteger = function (value) {\n var number = Number(value);\n if (isNaN(number)) { return 0; }\n if (number === 0 || !isFinite(number)) { return number; }\n return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));\n };\n var maxSafeInteger = Math.pow(2, 53) - 1;\n var toLength = function (value) {\n var len = toInteger(value);\n return Math.min(Math.max(len, 0), maxSafeInteger);\n };\n\n // The length property of the from method is 1.\n return function from(arrayLike/*, mapFn, thisArg */) {\n // 1. Let C be the this value.\n var C = this;\n\n // 2. Let items be ToObject(arrayLike).\n var items = Object(arrayLike);\n\n // 3. ReturnIfAbrupt(items).\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object - not null or undefined');\n }\n\n // 4. If mapfn is undefined, then let mapping be false.\n var mapFn = arguments.length > 1 ? arguments[1] : void undefined;\n var T;\n if (typeof mapFn !== 'undefined') {\n // 5. else\n // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.\n if (!isCallable(mapFn)) {\n throw new TypeError('Array.from: when provided, the second argument must be a function');\n }\n\n // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.\n if (arguments.length > 2) {\n T = arguments[2];\n }\n }\n\n // 10. Let lenValue be Get(items, \"length\").\n // 11. Let len be ToLength(lenValue).\n var len = toLength(items.length);\n\n // 13. If IsConstructor(C) is true, then\n // 13. a. Let A be the result of calling the [[Construct]] internal method\n // of C with an argument list containing the single item len.\n // 14. a. Else, Let A be ArrayCreate(len).\n var A = isCallable(C) ? Object(new C(len)) : new Array(len);\n\n // 16. Let k be 0.\n var k = 0;\n // 17. Repeat, while k < len… (also steps a - h)\n var kValue;\n while (k < len) {\n kValue = items[k];\n if (mapFn) {\n A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);\n } else {\n A[k] = kValue;\n }\n k += 1;\n }\n // 18. Let putStatus be Put(A, \"length\", len, true).\n A.length = len;\n // 20. Return A.\n return A;\n };\n }());\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.find\nif (!Array.prototype.find) {\n Object.defineProperty(Array.prototype, 'find', {\n value: function(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return kValue.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return kValue;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return undefined.\n return undefined;\n }\n });\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex\nif (!Array.prototype.findIndex) {\n Object.defineProperty(Array.prototype, 'findIndex', {\n value: function(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return k.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return k;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return -1.\n return -1;\n }\n });\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.includes\nif (!Array.prototype.includes) {\n Object.defineProperty(Array.prototype, 'includes', {\n value: function(searchElement, fromIndex) {\n\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n // 1. Let O be ? ToObject(this value).\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If len is 0, return false.\n if (len === 0) {\n return false;\n }\n\n // 4. Let n be ? ToInteger(fromIndex).\n // (If fromIndex is undefined, this step produces the value 0.)\n var n = fromIndex | 0;\n\n // 5. If n ≥ 0, then\n // a. Let k be n.\n // 6. Else n < 0,\n // a. Let k be len + n.\n // b. If k < 0, let k be 0.\n var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\n\n function sameValueZero(x, y) {\n return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));\n }\n\n // 7. Repeat, while k < len\n while (k < len) {\n // a. Let elementK be the result of ? Get(O, ! ToString(k)).\n // b. If SameValueZero(searchElement, elementK) is true, return true.\n if (sameValueZero(o[k], searchElement)) {\n return true;\n }\n // c. Increase k by 1.\n k++;\n }\n\n // 8. Return false\n return false;\n }\n });\n}","// https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach\nif (window.NodeList && !NodeList.prototype.forEach) {\n NodeList.prototype.forEach = function (callback, thisArg) {\n thisArg = thisArg || window;\n for (var i = 0; i < this.length; i++) {\n callback.call(thisArg, this[i], i, this);\n }\n };\n}","// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\nif (typeof Object.assign != 'function') {\n // Must be writable: true, enumerable: false, configurable: true\n Object.defineProperty(Object, \"assign\", {\n value: function assign(target, varArgs) { // .length of function is 2\n 'use strict';\n if (target == null) { // TypeError if undefined or null\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n var to = Object(target);\n\n for (var index = 1; index < arguments.length; index++) {\n var nextSource = arguments[index];\n\n if (nextSource != null) { // Skip over if undefined or null\n for (var nextKey in nextSource) {\n // Avoid bugs when hasOwnProperty is shadowed\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n },\n writable: true,\n configurable: true\n });\n}","\"use strict\";\n\n/* exported okanjo */\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/**\n * Okanjo widget framework namespace\n * @global okanjo\n */\nconst okanjo = (function(window, document) {\n\n //region Constants\n\n // Environment Vars\n const SUPPORTS_PAGE_OFFSET = window.pageXOffset !== undefined;\n const CSS1_COMPATIBLE = (document.compatMode /* istanbul ignore next: out of scope */ || \"\") === \"CSS1Compat\";\n const AGENT = window.navigator.userAgent;\n const ELLIPSIFY_PATTERN = /[\\s\\S](?:\\.\\.\\.)?$/;\n const MOBILE_PATTERN = /(iPhone|iPad|iPod|Android|blackberry)/i;\n const NOOP = () => {};\n const Console = window.console;\n\n // Place to pull defaults, if already set\n const settings = window.okanjo || {};\n\n //endregion\n\n //region Okanjo Core\n\n\n //noinspection JSValidateJSDoc,JSClosureCompilerSyntax - idk phpStorm generated it so why would it be wrong? :P\n /**\n * Okanjo namespace\n * @global\n * @type {{version: string, metrics: null, key: null, report: ((...p1?:*[])), warn: ((p1?:*, ...p2?:*[])), qwery: ((p1?:*, p2?:*))}}\n */\n const okanjo = {\n\n /**\n * Okanjo version\n */\n version: \"%%OKANJO_VERSION\",\n\n /**\n * Placeholder\n */\n metrics: null,\n\n /**\n * Global/default placement key\n */\n key: settings.key || null,\n\n /**\n * Reports an error to the console and possibly Raven in the future\n * @param args\n */\n report: (...args) => {\n let err = args.find((arg) => arg instanceof Error);\n if (!err) {\n let messageIndex = args.findIndex((arg) => typeof arg === \"string\");\n err = new Error(args[messageIndex] || \"Okanjo Error\");\n if (messageIndex >= 0) args.splice(messageIndex, 1);\n } else {\n // Grow our own stack so we can figure out what async thing did it\n let stack = (new Error()).stack.split('\\n');\n stack.shift();\n stack.shift();\n args.push({ reportStack: stack.join('\\n') });\n args = args.filter((a) => a !== err);\n }\n\n Console.error(`[Okanjo v${okanjo.version}]: ${err.stack}`);\n args.length && Console.error.apply(Console, ['Additional information:'].concat(args));\n\n // TODO - integrate with Raven\n },\n\n /**\n * Warn developers of their misdeeds\n * @param message\n * @param args\n */\n warn: (message, ...args) => {\n const err = new Error(message);\n\n Console.warn(`[Okanjo v${okanjo.version}]: ${err.stack}`);\n args.length && Console.warn.apply(Console, ['Additional information:'].concat(args));\n },\n\n // Backwards compatibility when we shipped with qwery, cuz querySelector[All] wasn't mainstream enough\n qwery: (selector, parent) => {\n\n // If parent is a selector, select the parent first!\n if (typeof parent === \"string\") {\n parent = document.querySelector(parent);\n\n // If parent is not found, there are obviously no results\n if (!parent) return [];\n }\n\n if (!parent) parent = document;\n\n return parent.querySelectorAll(selector);\n }\n };\n\n //endregion\n\n //region Vendor Libs\n\n /**\n * Placeholder for where vendor libraries get no-conflict loaded\n * @type {{}}\n */\n okanjo.lib = {};\n\n //endregion\n\n //region Networking\n\n /**\n * Networking methods\n * @type {{getRoute: *, exec: *}}\n */\n okanjo.net = {\n\n /**\n * API Endpoints\n */\n endpoint: 'https://api2.okanjo.com',\n sandboxEndpoint: 'https://sandbox-api2.okanjo.com',\n\n /**\n * API routes\n */\n routes: {\n ads: '/content',\n metrics: '/metrics/:object_type/:event_type',\n metrics_batch: '/metrics'\n },\n\n /**\n * Compiles a route and parameters into a final URL\n * @param {string} route - Route constant\n * @param {*} [params] - Key value hash\n * @param {*} [env] - Optional environment to use instead of live\n * @return {string} - Route\n */\n getRoute: (route, params, env) => {\n if (params) {\n Object.keys(params).forEach((key) => {\n route = route.replace(`:${key}`, params[key]+\"\");\n });\n }\n env = env || okanjo.env || 'live';\n return (env === 'sandbox' ? okanjo.net.sandboxEndpoint : okanjo.net.endpoint) + route;\n },\n\n // placeholder, xhr request extension\n request: NOOP\n };\n\n //endregion\n\n // region Utilities\n\n //noinspection JSClosureCompilerSyntax,JSValidateJSDoc\n /**\n * Utility functions and helpers\n * @type {{isEmpty: ((p1?:*)=>boolean), isMobile: (()), getPageArguments: ((p1:boolean))}}\n */\n okanjo.util = {\n\n /**\n * Checks whether a value is _really_ empty (trims)\n * @param val\n * @return {boolean}\n */\n isEmpty: (val) => val === null || val === undefined || (typeof val === \"string\" && val.trim().length === 0),\n\n /**\n * Checks if the current user agent identifies as a mobile device\n * @returns {boolean}\n */\n isMobile: () => {\n // KludgyAF™, but let's go with it\n return MOBILE_PATTERN.test(AGENT);\n },\n\n /**\n * Returns an object hashmap of query and hash parameters\n * @param {boolean} includeHashArguments - Whether to include the hash arguments, if any\n * @return {*}\n */\n getPageArguments: (includeHashArguments) => {\n\n const split = (query) => {\n query = query || \"\";\n const params = {};\n const parts = query.split('&');\n parts.forEach((part) => {\n const eqIndex = part.indexOf('=');\n let key, value;\n if (eqIndex < 0) {\n key = decodeURIComponent(part);\n value = null;\n } else {\n key = decodeURIComponent(part.substring(0, eqIndex));\n value = decodeURIComponent(part.substring(eqIndex + 1));\n }\n if (key) params[key] = value;\n });\n return params;\n };\n\n const queryArgs = split(window.location.search.substring(window.location.search.indexOf('?') + 1));\n const hashArgs = includeHashArguments ? split(window.location.hash.substring(Math.max(window.location.hash.indexOf('#') + 1, window.location.hash.indexOf('#!') + 2))) : {};\n Object.keys(hashArgs).forEach((key) => queryArgs[key] = hashArgs[key]);\n\n return queryArgs;\n }\n\n };\n\n /**\n * Deep clones an object by breaking references, unlike Object.assign\n * @param mixed – Source to clone (object, array, value)\n * @param [out] - Existing output, if any\n * @return {*}\n */\n okanjo.util.deepClone = (mixed, out) => {\n if (Array.isArray(mixed)) {\n // Array reference\n out = out || [];\n out = out.concat(mixed.map((val) => okanjo.util.deepClone(val)));\n } else if (typeof mixed === \"object\" && mixed !== null) {\n // Object reference\n out = out || {};\n Object.keys(mixed).forEach((key) => {\n out[key] = okanjo.util.deepClone(mixed[key]);\n });\n } else {\n // Value\n out = mixed;\n }\n\n return out;\n };\n\n /**\n * Flattens a multi-dimensional object into a single object\n * @param input\n * @param [options]\n * @return {{}}\n */\n okanjo.util.flatten = (input, options = {}) => {\n const output = {};\n\n if (input !== undefined && input !== null) {\n Object\n .keys(input)\n .forEach((key) => {\n // Convert object ids to hex strings\n if (input[key] instanceof Date) {\n if (options.dateToIso) {\n output[key] = input[key].toISOString(); // convert to iso\n } else {\n output[key] = input[key]; // as-is\n }\n } else if (typeof input[key] === 'object' && input[key] !== null) {\n // Allow ignoring arrays if desired\n if (Array.isArray(input[key]) && options.ignoreArrays === true) {\n output[key] = input[key];\n } else if (Array.isArray(input[key]) && options.arrayToCsv === true) {\n output[key] = input[key].join(',');\n } else {\n // Make child objects flat too (always returns object so Object.keys is safe)\n const childObject = okanjo.util.flatten(input[key], options);\n Object\n .keys(childObject)\n .forEach((childKey) => {\n output[key + '_' + childKey] = childObject[childKey];\n })\n ;\n }\n } else {\n // Copy value references\n output[key] = input[key];\n }\n })\n ;\n }\n\n return output;\n };\n\n /*! based on shortid https://github.com/dylang/shortid */\n okanjo.util.shortid = (function(clusterWorkerId) {\n\n const shuffled = 'ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC',\n\n crypto = window.crypto || window.msCrypto || (typeof require === \"function\" && require('crypto')),\n\n randomByte = () => {\n /* istanbul ignore next: platform diffs out of scope */\n if (crypto && crypto.randomBytes) {\n return crypto.randomBytes(1)[0] & 0x30;\n } else if (!crypto || !crypto.getRandomValues) {\n return Math.floor(Math.random() * 256) & 0x30;\n }\n /* istanbul ignore next: platform diffs out of scope */\n const dest = new Uint8Array(1);\n /* istanbul ignore next: platform diffs out of scope */\n crypto.getRandomValues(dest);\n /* istanbul ignore next: platform diffs out of scope */\n return dest[0] & 0x30;\n },\n\n encode = (number) => {\n let loopCounter = 0,\n done,\n str = '';\n\n while (!done) {\n str = str + shuffled[ ( (number >> (4 * loopCounter)) & 0x0f ) | randomByte() ];\n done = number < (Math.pow(16, loopCounter + 1 ) );\n loopCounter++;\n }\n return str;\n },\n\n // Ignore all milliseconds before a certain time to reduce the size of the date entropy without sacrificing uniqueness.\n // This number should be updated every year or so to keep the generated id short.\n // To regenerate `new Date() - 0` and bump the version. Always bump the version!\n\n REDUCE_TIME = 1490384907498,\n version = 7;\n\n let counter,\n previousSeconds;\n\n clusterWorkerId = clusterWorkerId || 0;\n\n return function() {\n let str = '',\n seconds = Math.floor(((new Date()).getTime() - REDUCE_TIME) * 0.001);\n\n if (seconds === previousSeconds) {\n counter++;\n } else {\n counter = 0;\n previousSeconds = seconds;\n }\n\n str = str + encode(version) + encode(clusterWorkerId);\n if (counter > 0) {\n str = str + encode(counter);\n }\n str = str + encode(seconds);\n\n return str;\n };\n })();\n\n /**\n * Gets the best URL for where we are operating\n * @returns {string|*}\n */\n okanjo.util.getLocation = () => window.location !== window.parent.location ? /* istanbul ignore next: oos */ document.referrer : document.location.href;\n\n //endregion\n\n //region User Interface\n\n okanjo.ui = {\n\n /**\n * Gets the current page scroll position\n * @returns {{x: Number, y: Number}}\n */\n getScrollPosition: () => {\n return {\n x: SUPPORTS_PAGE_OFFSET ? window.pageXOffset : /* istanbul ignore next: old browsers */ CSS1_COMPATIBLE ? document.documentElement.scrollLeft : document.body.scrollLeft,\n y: SUPPORTS_PAGE_OFFSET ? window.pageYOffset : /* istanbul ignore next: old browsers */ CSS1_COMPATIBLE ? document.documentElement.scrollTop : document.body.scrollTop\n };\n },\n\n /**\n * Gets the height and width of the given element\n * @param {HTMLElement|Node} element – The DOM element to get the size of\n * @param {boolean} [includeMargin] – Whether to include the margins of the element in the size\n * @returns {{height: number, width: number}}\n */\n getElementSize: (element, includeMargin) => {\n const size = {\n height: element.offsetHeight,\n width : element.offsetWidth\n };\n const style = element.currentStyle || window.getComputedStyle(element);\n\n if (includeMargin) {\n size.height += parseInt(style.marginTop) + parseInt(style.marginBottom);\n size.width += parseInt(style.marginLeft) + parseInt(style.marginRight);\n }\n\n return size;\n },\n\n /**\n * Gets the current page size\n * @return {{w: number, h: number}}\n */\n getPageSize: () => {\n const body = document.querySelector('body');\n const html = document.documentElement;\n\n return {\n w: Math.max(\n body.scrollWidth,\n body.offsetWidth,\n html.clientWidth,\n html.scrollWidth,\n html.offsetWidth\n ),\n\n h: Math.max(\n body.scrollHeight,\n body.offsetHeight,\n html.clientHeight,\n html.scrollHeight,\n html.offsetHeight\n )\n };\n },\n\n /**\n * Gets the current viewport size\n * @return {{vw: number, vh: number}}\n */\n getViewportSize: () => {\n const element = CSS1_COMPATIBLE ? document.documentElement /* istanbul ignore next: browser diffs */: document.body;\n const width = element.clientWidth;\n const height = element.clientHeight;\n const inWidth = window.innerWidth /* istanbul ignore next: browser diffs */ || 0;\n const inHeight = window.innerHeight /* istanbul ignore next: browser diffs */ || 0;\n const isMobileZoom = (inWidth && width > inWidth) || (inHeight && height > inHeight);\n\n return {\n vw: isMobileZoom /* istanbul ignore next: browser diffs */ ? inWidth : width,\n vh: isMobileZoom /* istanbul ignore next: browser diffs */ ? inHeight : height\n };\n },\n\n /**\n * Gets the x, y location of the event relative to the page\n * @param event – Mouse/Touch Event\n * @return {{ex: number, ey: number}}\n */\n getEventPosition: (event) => {\n const ex = event.pageX;\n const ey = event.pageY;\n const body = document.body;\n const el = document.documentElement;\n const scrollLeft = 'scrollLeft';\n const scrollTop = 'scrollTop';\n const type = event.__proto__.constructor.name;\n\n return {\n et: type, // mouse? touch? keyboard? robot?\n ex: ex === undefined /* istanbul ignore next: browser diffs */ ? event.clientX + body[scrollLeft] + el[scrollLeft] : ex,\n ey: ey === undefined /* istanbul ignore next: browser diffs */ ? event.clientY + body[scrollTop] + el[scrollTop] : ey\n };\n },\n\n /**\n * Gets the element's rectangle coordinates on the page\n * @param element\n * @return {{x1: number, y1: number, x2: number, y2: number}}\n */\n getElementPosition: (element) => {\n\n // Wrapped in try-catch because IE is super strict about the\n // element being on the DOM before you call this. Other browsers\n // let it slide, but oh well.\n\n const err = 'Could not get position of element. Did you attach the element to the DOM before initializing?';\n try {\n let rect = element.getBoundingClientRect();\n let body = document.body.getBoundingClientRect();\n // let pos = okanjo.ui.getScrollPosition();\n\n /* istanbul ignore else: jsdom doesn't mock this */\n if (!document.body.contains(element)) {\n okanjo.report(err, element);\n }\n return {\n // x1: rect.left + pos.x,\n // y1: rect.top + pos.y,\n // x2: rect.right + pos.x,\n // y2: rect.bottom + pos.y\n\n // This might fix\n x1: rect.left - body.left,\n y1: rect.top - body.top,\n x2: rect.right - body.left,\n y2: rect.bottom - body.top,\n\n };\n } catch (e) {\n okanjo.report(err, { exception: e, element });\n return {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: 0,\n err: 1\n };\n }\n },\n\n /**\n * Gets the intersection information given the element, viewport and scroll positions\n * @param e – Element position\n * @param s - Scroll position\n * @param v - Viewport size\n * @return {{intersectionArea: number, elementArea: number}}\n * @private\n */\n _getIntersection: (e, s, v) => {\n let iLeft = Math.max(e.x1, s.x),\n iRight = Math.min(e.x2, s.x+v.vw),\n iTop = Math.max(e.y1, s.y),\n iBottom = Math.min(e.y2, s.y+v.vh),\n\n intersectionArea = Math.max(0, iRight - iLeft) * Math.max(0, iBottom - iTop),\n elementArea = (e.x2 - e.x1) * (e.y2 - e.y1);\n\n return {\n intersectionArea,\n elementArea\n };\n },\n\n /**\n * Checks whether the element is actually displayed on the DOM\n * @param element\n * @return {boolean}\n */\n isElementVisible: (element) => {\n /* istanbul ignore next: jsdom won't trigger this */\n return element.offsetWidth > 0 && element.offsetHeight > 0;\n },\n\n /**\n * Gets the percentage of the element pixels currently within the viewport\n * @param {HTMLElement|Node} element\n * @return {number}\n */\n getPercentageInViewport: (element) => {\n let e = okanjo.ui.getElementPosition(element),\n s = okanjo.ui.getScrollPosition(),\n v = okanjo.ui.getViewportSize();\n\n // If there was a problem getting the element position, fail fast\n if (e.err) return 0;\n\n // Get intersection rectangle\n let { intersectionArea, elementArea } = okanjo.ui._getIntersection(e,s,v);\n\n // Don't let it return NaN\n /* istanbul ignore else: jsdom no love positional data */\n if (elementArea <= 0) return 0;\n\n /* istanbul ignore next: jsdom no love positional data, area tested with helper fn tho */\n return intersectionArea / elementArea;\n }\n };\n\n /**\n * Splits the text in the element to fit within the visible height of its container, and separates with an ellipses\n * @param {HTMLElement|Node} element – The DOM element containing the text to fit\n * @param {HTMLElement} [container] – Optional container to compute fit on. Defaults to the element's parent\n */\n okanjo.ui.ellipsify = function(element, container) {\n\n // It's a sad day when you have to resort to JS because CSS kludges are too hacky to work down to IE8, programmatically\n\n //noinspection JSValidateTypes\n const parent = container || element.parentNode,\n targetHeight = okanjo.ui.getElementSize(parent).height,\n useTextContent = element.textContent !== undefined;\n\n let text = useTextContent ? element.textContent /* istanbul ignore next: browser diffs */ : element.innerText,\n replacedText = \"\",\n safety = 5000, // Safety switch to bust out of the loop in the event something goes terribly wrong\n replacer = (match) => {\n /* istanbul ignore next: n/a to jsdom */\n replacedText = match.substr(0, match.length-3) + replacedText;\n /* istanbul ignore next: n/a to jsdom */\n return '...';\n };\n\n // Trim off characters until we can fit the text and ellipses\n // If the text already fits, this loop is ignored\n /* istanbul ignore next: jsdom doesn't do element size computing stuff */\n while (okanjo.ui.getElementSize(element).height > targetHeight && text.length > 0 && (safety-- > 0)) {\n text = useTextContent ? element.textContent : element.innerText;\n\n text = text.replace(ELLIPSIFY_PATTERN, replacer);\n\n if (useTextContent) {\n element.textContent = text;\n } else {\n element.innerText = text;\n }\n }\n\n // If there is work to do, split the content into two span tags\n // Like so: [content]...[hidden content]\n /* istanbul ignore if: n/a to jsdom */\n if (replacedText.length > 0) {\n\n let content = document.createElement('span'),\n span = document.createElement('span');\n\n content.setAttribute('class','okanjo-ellipses');\n span.setAttribute('class','okanjo-visually-hidden');\n\n if (useTextContent) {\n content.textContent = text.substr(0, text.length-3);\n span.textContent = replacedText;\n } else {\n content.innerText = text.substr(0, text.length-3);\n span.innerText = replacedText;\n }\n\n element.innerHTML = '';\n element.appendChild(content);\n element.appendChild(span);\n }\n\n };\n\n /**\n * Locates images with the class okanjo-fit and ensures that they get filled.\n * This is basically a object-fit hacky workaround\n * @param element\n */\n okanjo.ui.fitImages = function(element) {\n // Detect objectFit support\n /* istanbul ignore else: n/a to jsdom */\n if ('objectFit' in document.documentElement.style === false) {\n // Find images to fit\n element.querySelectorAll('img.okanjo-fit').forEach((img) => {\n\n // Hide the image\n img.style.display = 'none';\n\n // Update the parent w/ the background\n let parent = img.parentNode;\n parent.style.backgroundSize = 'cover';\n parent.style.backgroundImage = 'url('+img.src+')';\n parent.style.backgroundposition = 'center center';\n });\n }\n };\n\n //endregion\n\n // Export the root namespace\n return window.okanjo = okanjo;\n\n})(window, document);","\"use strict\";\n\n(function(window) {\n\n const JSON_TEST = /^application\\/json/;\n const okanjo = window.okanjo;\n\n /**\n * Performs a reliable XHR request\n * @param {string} method - Request method\n * @param {string} url - URL\n * @param [payload] optional payload\n * @param callback Fired on when completed (err, res), normalized to standard response format\n */\n okanjo.net.request = function (method, url, payload, callback) {\n\n // payload is not required\n if (typeof payload === \"function\") {\n callback = payload;\n payload = undefined;\n }\n\n // Create a new instance\n const req = new (window.XMLHttpRequest /* istanbul ignore next: old ie */ || window.ActiveXObject)('MSXML2.XMLHTTP.3.0');\n\n // Flag to prevent duplicate callbacks / races\n let calledBack = false;\n\n // Normalized done handler\n const done = function(err, res) {\n /* istanbul ignore else: out of scope */\n if (!calledBack) {\n calledBack = true;\n callback(err, res);\n }\n };\n\n // Apply timeout if configured globally\n if (okanjo.net.request.timeout) {\n req.timeout = okanjo.net.request.timeout;\n }\n\n // Catch timeout errors\n req.ontimeout = function(e) {\n /* istanbul ignore next: idk if jsdom can mock this, also readystatechange may fire before this anyway */\n done({\n statusCode: 504,\n error: \"Request timed out\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n };\n\n // Handle the response\n req.onreadystatechange = function(e) {\n // 4 = completed / failed\n if (req.readyState === 4) {\n // Do we have a response?\n if (req.status > 0) {\n let res;\n\n // Check if we got JSON and parse it right away\n if (JSON_TEST.test(req.getResponseHeader('Content-Type'))) {\n res = JSON.parse(req.responseText);\n } else {\n // Not JSON, normalize it instead\n res = {\n statusCode: req.status,\n data: req.responseText\n };\n }\n\n // Put the response in the proper slot (err for non success responses)\n if (req.status >= 200 && req.status < 300) {\n done(null, res);\n } else {\n done(res);\n }\n } else {\n // Request failed - e.g. CORS or network issues\n done({\n statusCode: 503,\n error: \"Request failed\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n }\n }\n };\n\n // Open the request\n req.open(method.toUpperCase(), url);\n\n // Include credentials\n req.withCredentials = true;\n\n // Handle post payloads\n if (['POST','PUT','PATCH'].includes(method.toUpperCase())) {\n req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n if (payload !== undefined) {\n payload = JSON.stringify(payload);\n }\n }\n\n // Ship it\n req.send(payload || undefined);\n };\n\n // Bind helpers to make things easy as pie\n okanjo.net.request.get = okanjo.net.request.bind(this, 'GET');\n okanjo.net.request.post = okanjo.net.request.bind(this, 'POST');\n okanjo.net.request.put = okanjo.net.request.bind(this, 'PUT');\n okanjo.net.request.delete = okanjo.net.request.bind(this, 'DELETE');\n\n /**\n * Helper to aid in minificiation+querystringify and redundant encodeURIComponent stuff\n * @param val\n * @return {*}\n */\n const encode = (val) => {\n if (val === null || val === undefined) return '';\n return encodeURIComponent(''+val);\n };\n\n /**\n * Helper to aid in getting a query string key using a prefix and keyname\n * @param key\n * @param keyPrefix\n * @return {*}\n */\n const getKey = (key, keyPrefix) => {\n if (keyPrefix) {\n return `${keyPrefix}[${encode(key)}]`;\n } else {\n return encode(key)\n }\n };\n\n /**\n * Super basic querystringify helper. It handles deep objects, but not for array values\n * @param obj\n * @param [keyPrefix]\n * @return {string}\n */\n okanjo.net.request.stringify = (obj, keyPrefix) => {\n let pairs = [];\n keyPrefix = keyPrefix || \"\";\n Object.keys(obj).forEach((key) => {\n let value = obj[key];\n if (Array.isArray(value)) {\n value.forEach((v) => pairs.push(getKey(key, keyPrefix) + '=' + encode(v))); // Does not do that PHP garbage with key[]=val\n } else if (typeof value === \"object\" && value !== null) {\n // Recurse\n let res = okanjo.net.request.stringify(value, getKey(key, keyPrefix));\n if (res) pairs.push(res);\n } else if (value !== undefined) {\n pairs.push(getKey(key, keyPrefix) + '=' + encode(value));\n }\n });\n return pairs.join('&');\n };\n\n})(window);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function(window, document) {\n\n /**\n * Okanjo cookie utility helpers\n */\n window.okanjo.util.cookie = {\n\n /**\n * Sets a cookie\n * @param cookieName\n * @param value\n * @param expireDays\n */\n set: (cookieName, value, expireDays) => {\n const expireDate = new Date();\n expireDate.setDate(expireDate.getDate() + expireDays);\n const expires = expireDays ? \" Expires=\" + expireDate.toUTCString() + \";\" : \"\";\n const path = \" Path=/\";\n const secure = window.location.protocol === 'https:' ? ' Secure;' : '';\n // const secure = ' Secure;';\n const cookieValue = `${encodeURI(value)};${expires}${secure} SameSite=None;${path}`;\n // console.log('setting cookie', cookieName, cookieValue)\n document.cookie = cookieName + \"=\" + cookieValue;\n },\n\n /**\n * Gets a cookie\n * @param cookieName\n * @return {*}\n */\n get: (cookieName) => {\n let output = null;\n document.cookie\n .split(\";\")\n .find((cookie) => {\n let nameTest = cookie.substr(0, cookie.indexOf(\"=\")).trim();\n let value = cookie.substr(cookie.indexOf(\"=\") + 1);\n if (nameTest === cookieName) {\n output = decodeURI(value);\n return true;\n } else {\n return false;\n }\n })\n ;\n return output;\n }\n };\n\n})(window, document);","\"use strict\";\n\n//noinspection JSUnusedLocalSymbols,ThisExpressionReferencesGlobalObjectJS\n(function(window, document) {\n\n const okanjo = window.okanjo;\n\n /**\n * UI Rendering Engine\n */\n class TemplateEngine {\n\n constructor() {\n\n // Load initial templates from options\n this._templates = {};\n this._css = {};\n\n // Hook point for adding custom styles to ui elements\n this.classDetects = '';\n }\n\n /**\n * Registers a template for use\n * @param name\n * @param template\n * @param beforeRender\n * @param options\n */\n registerTemplate(name, template, beforeRender, options) {\n\n if (typeof template === \"object\") {\n //noinspection JSValidateTypes\n if (template.nodeType === undefined) {\n throw new Error('Parameter template must be a string or a DOM element');\n } else {\n template = template.innerHTML;\n okanjo.lib.Mustache.parse(template);\n }\n } else if (typeof template !== \"string\") {\n throw new Error('Parameter template must be a string or a DOM element');\n }\n\n // Shift options if only have 3 params\n if (arguments.length === 3 && typeof beforeRender === \"object\") {\n options = beforeRender;\n beforeRender = null;\n } else {\n options = options || {};\n }\n\n if (beforeRender && typeof beforeRender !== \"function\") {\n throw new Error('Parameter beforeRender must be a function');\n }\n\n // Assign the template\n this._templates[name] = {\n markup: template,\n options,\n beforeRender\n };\n }\n\n /**\n * Registers a CSS payload for use\n * @param name\n * @param css\n * @param options\n */\n registerCss(name, css, options) {\n options = options || {};\n\n if (typeof css === \"object\") {\n //noinspection JSValidateTypes\n if (css.nodeType === undefined) {\n throw new Error('Parameter css must be a string or a DOM element');\n }\n } else if (typeof css !== \"string\") {\n throw new Error('Parameter css must be a string or a DOM element');\n }\n\n this._css[name] = {\n markup: css,\n options: options\n };\n }\n\n /**\n * Checks whether a template is registered\n * @param name\n * @return {boolean}\n */\n isTemplateRegistered(name) {\n return !!this._templates[name];\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Checks whether a CSS payload is registered\n * @param name\n * @return {boolean}\n */\n isCssRegistered(name) {\n return !!this._css[name];\n }\n\n /**\n * Ensures that a CSS payload has been added to the DOM\n * @param name\n */\n ensureCss(name) {\n if (this._css[name]) {\n //noinspection JSValidateTypes\n const css = this._css[name],\n id = css.markup.nodeType === undefined ? css.options.id || \"okanjo-css-\" + name : null; // If it's a DOM element, just forget it cuz it's already on the page\n\n // Check for css element on page, if we have an ID to look for\n if (id) {\n const element = document.querySelector('#' + id.replace(/\\./g, '\\\\.'));\n if (!element) {\n const head = document.head,\n style = document.createElement('style');\n\n style.id = id;\n style.setAttribute('type', 'text/css');\n\n /* istanbul ignore else: old ie */\n if (style.hasOwnProperty) { // old ie\n style.innerHTML = css.markup;\n } else {\n style.styleSheet.cssText = css.markup;\n }\n\n if (head) {\n head.appendChild(style);\n } else {\n // NO HEAD, just prepend to body then\n const body = document.body;\n if (body) {\n body.appendChild(style);\n } else {\n // And if this doesn't work, just give up\n okanjo.report('Cannot add CSS template to document. Does it not have a body or head?');\n }\n }\n }\n }\n } else {\n okanjo.report('Attempted to add CSS template \"'+name+'\" to the DOM, however it does not appear to be registered?');\n }\n }\n\n /**\n * Renders a template and returns the markup\n * @param templateName\n * @param context\n * @param model\n * @return {string}\n */\n render(templateName, context, model) {\n\n model = model || {};\n const template = this._templates[templateName];\n\n // If there's a data controller closure set, and if so, run the data through there\n if (template.beforeRender) {\n model = template.beforeRender.call(context, model);\n }\n\n // Attach globals\n model.okanjo = okanjo;\n model.okanjoMetricUrl = okanjo.net.endpoint.replace(/^https?:\\/\\//,''); // Url w/o scheme to prevent mixed-content warnings\n model.now = function() { return (new Date()).getTime(); };\n model.classDetects = this.classDetects;\n\n //noinspection JSUnresolvedVariable\n if (model.blockClasses && Array.isArray(model.blockClasses)) {\n model.classDetects += \" \" + model.blockClasses.join(' ');\n delete model.blockClasses;\n }\n\n // Add CSS unless we are told not to\n if (model.css !== false && template.options.css && template.options.css.length > 0) {\n template.options.css.forEach((css) => this.ensureCss(css));\n delete model.css;\n }\n\n // Render the template and return the result\n return okanjo.lib.Mustache.render(template.markup, model);\n }\n\n }\n\n /**\n * Formats a number into a currency string (rounded, decimal points, thousands separators)\n * See: http://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-money-in-javascript\n *\n * @param value – the number to format\n * @param [decimals] - The number of decimals to show\n * @param [decimalSeparator] – The decimals separator, default: .\n * @param [thousandsSeparator] – The thousands separator, default: ,\n * @returns {string} – Formatted currency string\n */\n TemplateEngine.formatCurrency = (value, decimals=2, decimalSeparator='.', thousandsSeparator=',') => {\n const s = value < 0 ? \"-\" : \"\",\n i = parseInt(value = Math.abs(+value || 0).toFixed(decimals)) + \"\";\n let j = i.length;\n j = (j) > 3 ? j % 3 : 0;\n return s + (j ? i.substr(0, j) + thousandsSeparator : \"\") + i.substr(j).replace(/(\\d{3})(?=\\d)/g, \"$1\" + thousandsSeparator) + (decimals ? decimalSeparator + Math.abs(value - i).toFixed(decimals).slice(2) : \"\");\n };\n\n // Export\n okanjo.ui.engine = new TemplateEngine();\n\n})(window, document);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window, document) {\n\n /*\n\n div .modal-container .fade-out .hidden\n | div .modal-window .clearfix\n | |\n | | div .modal-window-skin\n | | | div .modal-window-outer\n | | | | div .modal-window-inner\n | | | | | iframe .okanjo-inline-buy-frame\n | | | | /div\n | | | /div\n | | /div\n | |\n | | div .close-button\n | | | ×\n | | /div\n | |\n | /div\n /div\n\n */\n\n const okanjo = window.okanjo;\n const IS_MOBILE = okanjo.util.isMobile();\n\n let initialized = false,\n // scrollY = null,\n\n // Selectors\n $html, $body, $modalContainer, $modalWindow, $modalSkin, $modalOuter, $modalInner, $modalClose, $modalFrame,\n\n createElements = function() {\n\n // Page elements\n //noinspection JSUnresolvedFunction\n $html = document.documentElement /* istanbul ignore next: old browsers */ || document.querySelector('html');\n //noinspection JSUnresolvedFunction\n $body = document.body /* istanbul ignore next: old browsers */ || document.querySelector('body');\n\n // Modal elements\n $modalContainer = document.createElement('div');\n $modalWindow = document.createElement('div');\n $modalSkin = document.createElement('div');\n $modalOuter = document.createElement('div');\n $modalInner = document.createElement('div');\n $modalClose = document.createElement('div');\n $modalFrame = document.createElement('iframe');\n\n $modalContainer.setAttribute('class', 'okanjo-modal-container okanjo-modal-hidden ' /*+ okanjo.util.detectClasses().join(' ')*/);\n $modalWindow.setAttribute('class', 'okanjo-modal-window');\n $modalSkin.setAttribute('class', 'okanjo-modal-window-skin');\n $modalOuter.setAttribute('class', 'okanjo-modal-window-outer');\n $modalInner.setAttribute('class', 'okanjo-modal-window-inner');\n $modalClose.setAttribute('class', 'okanjo-modal-close-button');\n\n $modalFrame.setAttribute('class', 'okanjo-inline-buy-frame');\n $modalFrame.setAttribute('frameborder', '0');\n $modalFrame.setAttribute('vspace', '0');\n $modalFrame.setAttribute('hspace', '0');\n $modalFrame.setAttribute('webkitallowfullscreen', '');\n $modalFrame.setAttribute('mozallowfullscreen', '');\n $modalFrame.setAttribute('allowfullscreen', '');\n $modalFrame.setAttribute('scrolling', 'auto');\n\n $modalClose.innerHTML = '×';\n\n // Create the modal element tree\n $modalInner.appendChild($modalFrame);\n $modalOuter.appendChild($modalInner);\n $modalSkin.appendChild($modalOuter);\n $modalWindow.appendChild($modalSkin);\n $modalWindow.appendChild($modalClose);\n $modalContainer.appendChild($modalWindow);\n\n // Add the modal stuff to the body\n $body.appendChild($modalContainer);\n },\n\n addListener = function(el, event, handler) {\n /* istanbul ignore else: old browsers */\n if (el.addEventListener) {\n el.addEventListener(event, handler, false);\n } else {\n el.attachEvent(\"on\" + event, handler);\n }\n },\n\n getWindowHeight = function() {\n return window.innerHeight /* istanbul ignore next: old browsers */ || document.documentElement.clientHeight;\n },\n\n handleReposition = function() {\n // scrollY = okanjo.ui.getScrollPosition().y;\n //$modalWindow.style.marginTop = scrollY + 40 + \"px\";\n $modalWindow.style.height = (getWindowHeight() - 80) + \"px\";\n },\n\n bindEvents = function() {\n\n // If the device orientation changes, adjust the modal view port\n addListener(window, 'orientationchange', function() {\n for (let t = 0; t < 2; t++) {\n setTimeout(handleReposition, 1000 * t + 10);\n }\n });\n\n // If the window changes size, also adjust the modal view port\n addListener(window, 'resize', function() {\n setTimeout(handleReposition, 100);\n });\n\n // Click the overlay to close the modal\n addListener($modalContainer, 'click', closeModal);\n\n // If you click in the modal, don't close it!\n addListener($modalWindow, 'click', function(e) {\n e.preventDefault();\n e.stopPropagation();\n });\n\n // Click the close button to close it\n addListener($modalClose, 'click', function(e) {\n\n // Don't close it twice\n e.preventDefault();\n e.stopPropagation();\n\n closeModal();\n });\n\n },\n\n //removeListener = function(el, event, handler) {\n // if (el.removeEventListener) {\n // el.removeEventListener(event, handler);\n // } else {\n // el.detachEvent(\"on\" + event, handler);\n // }\n //},\n\n addClass = function(el, name) {\n el.className += \" \" + name;\n },\n\n removeClass = function(el, name) {\n el.className = el.className.replace(new RegExp(' *?'+name), '');\n },\n\n openModal = function() {\n\n // scrollY = document.body.scrollTop;\n\n removeClass($modalContainer, 'okanjo-modal-hidden');\n addClass($modalContainer, 'okanjo-modal-fade-out');\n\n handleReposition();\n\n addClass($html, \"okanjo-modal-active\");\n\n if (!IS_MOBILE) {\n addClass($html, \"okanjo-modal-margin-fix\");\n }\n\n setTimeout(function() {\n removeClass($modalContainer, 'okanjo-modal-fade-out');\n }, 10);\n\n // Click the overlay to close the modal\n //addListener($body, 'click', closeModal);\n\n },\n\n closeModal = function() {\n addClass($modalContainer, 'okanjo-modal-fade-out');\n\n setTimeout(function() {\n removeClass($modalContainer, 'okanjo-modal-fade-out');\n addClass($modalContainer, \"okanjo-modal-hidden\");\n\n removeClass($html, \"okanjo-modal-active\");\n if (!IS_MOBILE) {\n removeClass($html, \"okanjo-modal-margin-fix\");\n }\n }, 210);\n\n // Click the overlay to close the modal\n //removeListener($body, 'click', closeModal);\n },\n\n /**\n * Insert an element or markup into the modal\n * @param content\n */\n setContent = function(content) {\n\n // Remove existing content\n $modalInner.innerHTML = \"\";\n\n // Insert new content\n if (typeof content === \"string\") {\n $modalInner.innerHTML = content;\n } else {\n $modalInner.appendChild(content);\n }\n };\n\n\n // Expose the modal functions\n okanjo.ui.modal = {\n\n show: function(content) {\n\n if (!initialized) {\n initialized = true;\n createElements();\n bindEvents();\n }\n\n setContent(content);\n openModal();\n },\n\n hide: function() {\n closeModal();\n }\n\n };\n\n return okanjo.ui.modal;\n\n})(window, document);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window, document) {\n\n const okanjo = window.okanjo;\n\n /**\n * Event tracking class\n * @type {Metrics}\n */\n class Metrics {\n\n //noinspection JSUnusedGlobalSymbols\n constructor() {\n\n /**\n * Events queued here before submission\n * @type {Array}\n * @private\n */\n this._queue = this._getStoredQueue();\n this._processTimeout = null; // queue event loop timeout pointer\n\n /**\n * Unique page grouping event identifier\n */\n this.pageId = okanjo.util.shortid();\n this.defaultChannel = Metrics.Channel.external;\n\n this.sid = null;\n this.sourceCh = null;\n this.sourceCx = null;\n\n // Extract referral data, if set\n this._checkUrlForReferral();\n\n // TODO - look into iframe session correlation system\n }\n\n //noinspection JSMethodCanBeStatic\n /**\n * Gets the storage backed metric queue, in case we did not send everything last time\n * @return {Array}\n * @private\n */\n _getStoredQueue() {\n if (window.localStorage[Metrics.Params.queue]) {\n try {\n let queue = JSON.parse(window.localStorage[Metrics.Params.queue]);\n if (Array.isArray(queue)) {\n return queue;\n } else {\n okanjo.report('Stored queue is not a queue', {queue});\n return [];\n }\n } catch (e) {\n okanjo.report('Failed to load metric queue from storage', {err: e});\n return [];\n }\n } else {\n // not stored\n return [];\n }\n }\n\n /**\n * Updates the queue stored in storage, in the event we can't complete our submissions\n * @param delay - Whether to delay updating the queue for a bit, to let other metrics pile in\n * @private\n */\n _saveQueue(delay) {\n if (delay) {\n if (this._saveQueueTimeout) clearTimeout(this._saveQueueTimeout);\n this._saveQueueTimeout = setTimeout(() => {\n this._saveQueue(false);\n this._saveQueueTimeout = null;\n }, 100);\n } else {\n window.localStorage[Metrics.Params.queue] = JSON.stringify(this._queue);\n }\n }\n\n /**\n * Extract contextual pass-through data from the URL, if present\n * @private\n */\n _checkUrlForReferral() {\n const pageArgs = okanjo.util.getPageArguments(true),\n urlSid = pageArgs[Metrics.Params.name],\n localSid = window.localStorage[Metrics.Params.name] || okanjo.util.cookie.get(Metrics.Params.name), // pull from storage or cookie\n sourceContext = pageArgs[Metrics.Params.context],\n sourceChannel = pageArgs[Metrics.Params.channel];\n\n // If for some reason, both are set, record the incident as a possible correlation\n if (urlSid && localSid && urlSid !== localSid) {\n this.trackEvent({\n object_type: Metrics.Object.metric_session,\n event_type: Metrics.Event.correlation,\n id: urlSid+\"_\"+localSid,\n ch: this.defaultChannel,\n _noProcess: true\n });\n }\n\n // Update local values\n this.sid = localSid || urlSid || null; // prefer local over remote (changed in 1.0)\n this.sourceCh = sourceChannel || null;\n this.sourceCx = sourceContext || null;\n }\n\n /**\n * Submits an individual event metric\n * @param event\n * @param callback\n */\n trackEvent(event, callback) {\n // Ensure the event contains the required fields\n if (!event.object_type || !event.event_type) {\n okanjo.report('Invalid metric to track (missing object_type or event_type)', {event});\n return;\n }\n\n // Queue the event for publishing\n this._push(event, callback);\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Submits a page view metric\n * @param event\n * @param callback\n */\n trackPageView(event, callback) {\n event = event || {};\n event.object_type = Metrics.Object.page;\n event.event_type = Metrics.Event.view;\n event.id = event.id || okanjo.util.getLocation();\n event.ch = event.ch || this.defaultChannel;\n\n // Queue the event for publishing\n this.trackEvent(event, callback);\n }\n\n /**\n * Adds an event to the queue\n * @param event\n * @param callback\n * @private\n */\n _push(event, callback) {\n this._queue.push({ event, callback });\n\n // Save the queue\n this._saveQueue(true);\n\n // Start burning down the queue, unless the event says not to\n if (event._noProcess) {\n delete event._noProcess;\n } else {\n this._processQueue();\n }\n }\n\n /**\n * Burn down the queue\n * @private\n */\n _processQueue() {\n // If the queue is not already being processed, and there's stuff to process, continue sending them\n if (!this._processTimeout && this._queue.length > 0) {\n this._processTimeout = setTimeout(() => {\n\n // Pull the items we're going to batch out of the queue\n const items = this._queue.splice(0, 255);\n this._saveQueue(false);\n\n // Track the item\n this._batchSend(items, (err, res) => {\n // TODO: If there was an error, consider splicing the batch back into the queue\n\n // Update / Set the metric sid on the publisher\n /* istanbul ignore else: server barks */\n if (res && res.data && res.data.sid) this._updateSid(res.data.sid);\n\n // When this batch is done being tracked, iterate to the next metric then fire it's callback if set\n this._processTimeout = null;\n this._processQueue();\n\n // Fire the event callbacks if there are any\n items.forEach((item) => {\n item.callback && item.callback(err, res);\n });\n });\n\n }, 0); // break event loop, maybe\n }\n }\n\n /**\n * Sends a bunch of queued metric events\n * @param items\n * @param callback\n * @private\n */\n _batchSend(items, callback) {\n\n // Normalize event data\n const events = items.map((item) => {\n this._normalizeEvent(item.event);\n\n // Strip duplicated data from event batch\n delete item.event.sid;\n delete item.event.win;\n\n return item.event;\n });\n\n const payload = {\n events,\n win: okanjo.util.getLocation()\n };\n\n const route = okanjo.net.getRoute(okanjo.net.routes.metrics_batch);\n\n // Set sid if present\n if (this.sid) {\n payload.sid = this.sid;\n }\n\n // Send it\n okanjo.net.request.post(\n route,\n payload,\n (err, res) => {\n /* istanbul ignore if: out of scope */\n if (err) {\n okanjo.report('Failed to send metrics batch', { err, res, items, route });\n }\n callback && callback(err, res);\n }\n );\n }\n\n /**\n * Normaizes events so that they contain consistent data values\n * @param event\n * @private\n */\n _normalizeEvent(event) {\n\n // Ensure meta is ready to receive values\n event.m = event.m || {};\n\n // Set key\n event.key = event.key || event.m.key || okanjo.key || undefined;\n\n // Set session\n if (this.sid) event.sid = this.sid;\n\n // Clone the metadata, since it might be a direct reference to a widget property\n // Deleting properties on the meta object could be very destructive\n event.m = Object.assign({}, event.m); // event.m should be flat\n\n // Strip meta keys that should be excluded\n Object.keys(Metrics.Meta.exclude).forEach((key) => delete event.m[key]);\n\n // Set referral channel / context\n if (this.sourceCh) { event.m.ref_ch = this.sourceCh; }\n if (this.sourceCx) { event.m.ref_cx = this.sourceCx; }\n\n // Set page group id\n event.m.pgid = this.pageId;\n\n // Set okanjo version\n event.m.ok_ver = okanjo.version;\n\n // Finalize metadata\n event.m = okanjo.util.flatten(event.m, { arrayToCsv: true });\n\n // Ensure metadata strings won't exceed the imposed limit\n Object.keys(event.m).forEach((key) => {\n if (typeof event.m[key] === \"string\") {\n event.m[key] = event.m[key].substr(0, 255);\n }\n });\n\n // Set page source reference\n if (document.referrer) {\n event.ref = document.referrer;\n }\n\n // Set the window location\n event.win = okanjo.util.getLocation();\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n _updateSid(sid) {\n // Not set or changed?\n if (sid && (!this.sid || this.sid !== sid) ) {\n this.sid = sid;\n window.localStorage[Metrics.Params.name] = sid;\n okanjo.util.cookie.set(Metrics.Params.name, sid, Metrics.Params.ttl);\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @param event\n * @return {*|{}}\n */\n static addElementInfo(element, event) {\n const page = okanjo.ui.getPageSize(),\n size = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n event.m.pw = page.w;\n event.m.ph = page.h;\n event.m.x1 = size.x1;\n event.m.y1 = size.y1;\n event.m.x2 = size.x2;\n event.m.y2 = size.y2;\n\n return event;\n }\n\n static addWidgetInfo(element, event) {\n const containerSize = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n\n // placement div size\n event.m.wox1 = containerSize.x1;\n event.m.woy1 = containerSize.y1;\n event.m.wox2 = containerSize.x2;\n event.m.woy2 = containerSize.y2;\n\n // Inner size is the min/max of the child elements since they may be floating and have no official height/width\n const resources = okanjo.qwery('.okanjo-resource, .okanjo-adx-container', element);\n let size, wix1, wiy1, wix2, wiy2, boxes = [];\n const getMin = (val, current) => typeof current === \"undefined\" || val < current ? val : current;\n const getMax = (val, current) => typeof current === \"undefined\" || val > current ? val : current;\n const fallback = (val, fallback) => typeof val === \"undefined\" ? fallback : val;\n\n resources.forEach(e => {\n size = okanjo.ui.getElementPosition(e);\n wix1 = getMin(size.x1, wix1);\n wiy1 = getMin(size.y1, wiy1);\n wix2 = getMax(size.x2, wix2);\n wiy2 = getMax(size.y2, wiy2);\n boxes.push(size.x1, size.y1, size.x2, size.y2);\n });\n\n // inner size (might be centered or something)\n // noinspection JSUnusedAssignment\n event.m.wix1 = fallback(wix1, containerSize.x1); // noinspection JSUnusedAssignment\n event.m.wiy1 = fallback(wiy1, containerSize.y1); // noinspection JSUnusedAssignment\n event.m.wix2 = fallback(wix2, containerSize.x2); // noinspection JSUnusedAssignment\n event.m.wiy2 = fallback(wiy2, containerSize.y2);\n event.m.wrps = boxes.map(v => Math.floor(v)).join(','); // all resource positions x1,y1,x2,y2,...\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds viewport dimensions / positional data to the event\n * @param event\n * @return {*|{}}\n */\n static addViewportInfo(event) {\n const vp = okanjo.ui.getViewportSize(),\n pos = okanjo.ui.getScrollPosition();\n\n event = event || {};\n event.m = event.m || {};\n event.m.vx1 = pos.x;\n event.m.vy1 = pos.y;\n event.m.vx2 = pos.x+vp.vw;\n event.m.vy2 = pos.y+vp.vh;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @param event\n * @return {*|{}}\n */\n static addEventInfo(jsEvent, event) {\n const pos = okanjo.ui.getEventPosition(jsEvent);\n\n event = event || {};\n event.m = event.m || {};\n event.m.et = pos.et;\n event.m.ex = pos.ex;\n event.m.ey = pos.ey;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param event\n * @param args\n * @return {*|{}}\n */\n static addEventMeta(event, ...args) {\n event = event || {};\n event.m = event.m || {};\n event.m = Object.assign.apply(Object, [event.m].concat(args));\n \n return event;\n }\n\n /**\n * Helper to create a new fluent event structure\n * @param data\n * @param args\n * @return {MetricEvent}\n */\n static create(data, ...args) {\n // return okanjo.util.deepClone(Object.assign.apply(Object, [{}].concat(args)));\n return new MetricEvent(data, args);\n }\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Helper to create a new fluent event structure\n * @param args\n * @return {*}\n */\n create(...args) {\n return Metrics.create.apply(null, args);\n }\n\n }\n\n /**\n * The storage/cookie/url param names\n * @type {{queue: string, name: string, channel: string, context: string, ttl: number}}\n */\n Metrics.Params = {\n queue: '_ok_q',\n name: 'ok_msid',\n channel: 'ok_ch',\n context: 'ok_cx',\n ttl: 1460 // 4 years\n };\n\n /**\n * Event Metadata configuration\n * @type {{exclude: [*]}}\n */\n Metrics.Meta = {\n exclude: ['key','callback','metrics_channel_context','metrics_context','mode']\n };\n\n /**\n * Event Types\n * @type {{view: string, impression: string, interaction: string, correlation: string}}\n */\n Metrics.Event = {\n view: 'vw',\n impression: 'imp',\n interaction: 'int',\n correlation: 'cor'\n };\n\n /**\n * Event Action Types\n * @type {{click: string, inline_click: string}}\n */\n Metrics.Action = {\n click: \"click\",\n inline_click: \"inline_click\"\n };\n\n /**\n * Event Object Types\n * @type {{article: string, thirdparty_ad: string, cart: string, page: string, widget: string, product: string, store: string, cause: string, marketplace: string, order: string, order_item: string, user: string, metric_session: string}}\n */\n Metrics.Object = {\n article: 'am',\n thirdparty_ad: 'ta',\n cart: 'ct',\n page: 'pg',\n widget: 'wg',\n product: 'pr',\n store: 'st',\n cause: 'ca',\n marketplace: 'mp',\n order: 'or',\n order_item: 'oi',\n user: 'ur',\n metric_session: 'mt'\n };\n\n /**\n * Event Channels\n * @type {{product_widget: string, ad_widget: string, store_widget: string, marketplace: string, external: string}}\n */\n Metrics.Channel = {\n placement: 'pw',\n marketplace: 'mp',\n external: 'ex',\n\n // Deprecated:\n product_widget: 'pw',\n ad_widget: 'aw',\n store_widget: 'sw'\n };\n\n /**\n * Event Environments\n * @type {{live: string, testing: string}}\n */\n Metrics.Environment = {\n live: \"live\",\n testing: \"testing\"\n };\n\n /**\n * Fluent wrapper around making events simple\n */\n class MetricEvent {\n constructor(data, others) {\n // Merge the data and other data sets into this object\n data = data || {};\n this.data(data);\n /* istanbul ignore else: metrics.create is the only way to create this right now */\n if (Array.isArray(others)) {\n others.forEach((data) => {\n this.data(data);\n });\n }\n }\n\n /**\n * Sets event parameter key-values\n * @param data\n */\n data(data) {\n Object.assign(this, okanjo.util.deepClone(data));\n return this;\n }\n\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @return {MetricEvent}\n */\n event(jsEvent) {\n Metrics.addEventInfo(jsEvent, this);\n return this;\n }\n\n /**\n * Adds viewport dimensions / positional data to the event\n * @return {MetricEvent}\n */\n viewport() {\n Metrics.addViewportInfo(this);\n return this;\n }\n\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @return {MetricEvent}\n */\n element(element) {\n Metrics.addElementInfo(element, this);\n return this;\n }\n\n /**\n * Adds widget DOM element dimensions / positional data to the event\n * @param element\n * @returns {MetricEvent}\n */\n widget(element) {\n Metrics.addWidgetInfo(element, this);\n return this;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param args\n * @return {MetricEvent}\n */\n meta(...args) {\n Metrics.addEventMeta.apply(null, [this].concat(args));\n return this;\n }\n\n /**\n * Sets the object and event type on the event w/o having to use .data\n * @param object_type\n * @param event_type\n * @return {MetricEvent}\n */\n type(object_type, event_type) {\n this.object_type = object_type;\n this.event_type = event_type;\n return this;\n }\n\n /**\n * Finalizes and sends the event\n * @param callback\n */\n send(callback) {\n okanjo.metrics.trackEvent(this, callback);\n // DONT RETURN - BREAK THE CHAIN HERE\n }\n\n /**\n * Gets the single-metric tracking url for this event\n * @return {string}\n */\n toUrl() {\n // Copy data w/o modifying it\n const event = Object.assign({}, this);\n\n // Extract params\n const {\n object_type,\n event_type\n } = event;\n delete event.object_type;\n delete event.event_type;\n\n // Normalize event data\n okanjo.metrics._normalizeEvent(event);\n\n // Get the URL\n return okanjo.net.getRoute(okanjo.net.routes.metrics, { object_type, event_type }) + '?' +\n okanjo.net.request.stringify(event);\n }\n }\n\n // Export / initialize\n okanjo.metrics = new Metrics();\n\n})(window, document);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function(window) {\n\n const okanjo = window.okanjo;\n\n // Track the page view, but don't send it right away.\n // Send it in one full second unless something else pushes an event\n // This way, we have a chance that a placement key will be set globally\n okanjo.metrics.trackPageView({_noProcess:true});\n setTimeout(() => {\n okanjo.metrics._processQueue();\n }, 1000);\n\n})(window);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/** Based on https://gist.github.com/mudge/5830382 **/\n(function(window) {\n\n /**\n * Simplified EventEmitter base class\n */\n class EventEmitter {\n\n constructor() {\n this._events = {};\n }\n\n /**\n * Registers an event handler to fire on any occurrence of an event\n * @param event\n * @param listener\n */\n on(event, listener) {\n if (!this._events[event]) {\n this._events[event] = [];\n }\n\n this._events[event].push(listener);\n }\n\n /**\n * Removes an event handler for an event\n * @param event\n * @param listener\n */\n removeListener(event, listener) {\n\n if (this._events[event]) {\n let idx = this._events[event].indexOf(listener);\n if (idx >= 0) {\n this._events[event].splice(idx, 1);\n }\n }\n }\n\n /**\n * Emits an event\n * @param event\n */\n emit(event) {\n let i, listeners, length, args = [].slice.call(arguments, 1);\n\n if (this._events[event]) {\n listeners = this._events[event].slice();\n length = listeners.length;\n\n for (i = 0; i < length; i++) {\n listeners[i].apply(this, args);\n }\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Registers an event handler to fire only once on an event\n * @param event\n * @param listener\n */\n once(event, listener) {\n\n const callback = () => {\n let args = [].slice.call(arguments, 1);\n this.removeListener(event, callback);\n listener.apply(this, args);\n };\n\n this.on(event, callback);\n }\n\n }\n\n window.okanjo._EventEmitter = EventEmitter;\n return EventEmitter;\n\n})(window);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window) {\n\n const okanjo = window.okanjo;\n const DATA_ATTRIBUTE_PATTERN = /^data-(.+)$/;\n const DATA_REPLACE_PATTERN = /-/g;\n\n /**\n * Base widget class\n */\n class Widget extends okanjo._EventEmitter {\n\n constructor(element, options) {\n super();\n\n // Verify element was given (we can't load unless we have one)\n if (!element || element === null || element.nodeType === undefined) {\n okanjo.report('Invalid or missing element on widget construction', { widget: this, element, options });\n throw new Error('Okanjo: Invalid element - make sure to pass a valid DOM element when constructing Okanjo Widgets.');\n }\n\n // Verify configuration is OK\n if (options && typeof options !== \"object\") {\n // Warn and fix it\n okanjo.report('Invalid widget options. Expected object, got: ' + typeof options, { widget: this, element, options });\n options = {};\n } else {\n options = options || {};\n }\n\n // Store basics\n this.name = 'Widget';\n this.element = element;\n this.instanceId = okanjo.util.shortid();\n\n // Clone initial config, breaking the top-level reference\n this.config = Object.assign({}, options);\n }\n\n /**\n * Base widget initialization procedures\n */\n init() {\n // process config attributes\n this._applyConfiguration();\n\n this._setCompatibilityOptions();\n\n // ensure placement key\n if (!this._ensurePlacementKey()) return;\n\n // Tell the widget to load\n this.load();\n }\n\n /**\n * This is for extended widgets, so they may modify the configuration before loading\n */\n _setCompatibilityOptions() {\n // By default, this does nothing. Must be overridden to be useful\n }\n\n //noinspection JSMethodCanBeStatic\n /**\n * Widget configuration definitions\n * @return {{}}\n */\n getSettings() {\n // Override this\n return {};\n }\n\n /**\n * Main widget load function.\n */\n load() {\n // Override this in the widget implementation\n }\n\n /**\n * Applies data attribute settings and defaults to the widget configuration\n * @private\n */\n _applyConfiguration() {\n\n // this.config was set to the options provided in the constructor\n // so layer data attributes on top\n\n const data = this.getDataAttributes();\n const settings = this.getSettings();\n Object\n .keys(data)\n .forEach((key) => {\n let normalizedKey = key.replace(DATA_REPLACE_PATTERN, '_');\n\n let val = data[key];\n\n // Attempt to convert the value if there's a setting for it\n if (settings[normalizedKey]) val = settings[normalizedKey].value(val, false);\n\n if (!okanjo.util.isEmpty(val)) {\n this.config[normalizedKey] = val;\n }\n })\n ;\n\n // Apply defaults from the widget settings\n Object.keys(settings).forEach((key) => {\n if (this.config[key] === undefined && settings[key]._default !== undefined) {\n this.config[key] = settings[key].value(undefined, false);\n }\n });\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets a copy of the configuration, suitable for transmission\n * @return {{}}\n */\n getConfig() {\n const settings = this.getSettings();\n const out = {};\n\n Object.keys(this.config).forEach((origKey) => {\n let val = this.config[origKey];\n let key = origKey;\n let group = null;\n\n // Check if this is a known property\n if (settings[key]) {\n val = settings[key].value(val);\n group = settings[key].getGroup();\n }\n\n // Init the target/group if not already setup\n let target = out;\n if (group) {\n target[group] = target[group] || {};\n target = target[group];\n }\n\n // Set the value on the target if set\n if (val === null) {\n target[key] = ''; // format null values as empty strings for transmission\n } else if (val !== undefined) {\n target[key] = val;\n }\n });\n\n return out;\n }\n\n /**\n * Before loading, ensure that a placement key is present or abort\n * @return {boolean}\n * @private\n */\n _ensurePlacementKey() {\n\n // Check if set on widget or globally\n if (this.config.key) {\n return true;\n } else if (okanjo.key) {\n // Copy key from global scope,\n this.config.key = okanjo.key;\n return true;\n }\n\n // No key set, can't load.\n okanjo.report('No key provided on widget', { widget: this });\n this.showError('Error: Missing placement key.');\n return false;\n }\n\n /**\n * Displays an error in the widget element\n * @param message\n */\n showError(message) {\n this.setMarkup(okanjo.ui.engine.render(\n 'okanjo.error',\n this,\n { message }\n ));\n }\n\n /**\n * Sets the markup of the widget's element\n * @param markup\n */\n setMarkup(markup) {\n this.element.innerHTML = markup;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets the current page URL, sans query string and fragment.\n * @returns {string} - URL\n */\n static getCurrentPageUrl() {\n return window.location.href.replace(/([?#].*)$/, '');\n }\n\n /**\n * Instead of using HTML5 dataset, just rip through attributes and return data attributes\n * @returns {*}\n */\n getDataAttributes() {\n const data = {};\n Array\n .from(this.element.attributes)\n .forEach((attr) => {\n const match = DATA_ATTRIBUTE_PATTERN.exec(attr.name);\n if (match) {\n data[match[1]] = attr.value;\n }\n });\n return data;\n }\n\n }\n\n /**\n * Fluent configuration helper for organizing and formatting ad-hoc configuration values\n * @type {Field}\n */\n Widget.Field = class Field {\n\n //noinspection JSUnusedGlobalSymbols\n constructor() {\n this._convert = null;\n this._strip = false;\n this._default = undefined;\n this._group = null;\n }\n\n /**\n * Formats the value as an array of strings\n * @param converter\n * @return {Field}\n */\n array(converter) {\n this._convert = (val) => {\n if (Array.isArray(val)) {\n if (converter) {\n return val.map((v) => converter(v))\n } else {\n return val;\n }\n }\n val = val.replace(/\\\\,/g, '\\0');\n return val.split(',').map((v) => {\n let res = v.trim().replace('\\0', ',');\n if (converter) res = converter(res);\n return res;\n });\n };\n return this;\n }\n //noinspection JSUnusedGlobalSymbols\n static array(converter) { return (new Field()).array(converter); }\n\n /**\n * Formats the value as a string\n * @return {Field}\n */\n string() {\n this._convert = (val) => {\n if (val === null || val === undefined) return val;\n else return \"\"+val;\n };\n return this;\n }\n static string() { return (new Field()).string(); }\n\n /**\n * Formats the value as a boolean (takes 1, 0, true, false)\n * @return {Field}\n */\n bool() {\n this._convert = (val) => {\n if (typeof val === \"string\") {\n return (val === \"1\" || val.toLowerCase() === \"true\");\n } else {\n return !!val;\n }\n };\n return this;\n }\n //noinspection JSUnusedGlobalSymbols\n static bool() { return (new Field()).bool(); }\n\n /**\n * Indicates the field should not be passed on for transmission\n * @return {Field}\n */\n strip() { this._strip = true; return this; }\n static strip() { return (new Field()).strip(); }\n\n /**\n * Formats the value as a integer (whole) number\n * @return {Field}\n */\n int() { this._convert = (val) => parseInt(val); return this; }\n //noinspection JSUnusedGlobalSymbols\n static int() { return (new Field()).int(); }\n\n /**\n * Formats the value as a floating point number\n * @return {Field}\n */\n float() { this._convert = (val) => parseFloat(val); return this; }\n //noinspection JSUnusedGlobalSymbols\n static float() { return (new Field()).float(); }\n\n //noinspection ReservedWordAsName\n /**\n * Sets the default value to use if not set\n * @param val\n * @return {Field}\n */\n default(val) {\n this._default = val;\n return this;\n }\n\n /**\n * Assigns the property to a bucket for hierarchy\n * @param name\n * @return {Field}\n */\n group(name) {\n this._group = name;\n return this;\n }\n\n /**\n * Gets the group the field belongs to\n * @return {*|null}\n */\n getGroup() {\n return this._group;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets the formatted value of the field\n * @param val\n * @param strip\n * @return {*}\n */\n value(val, strip=true) {\n if (this._strip && strip) return undefined;\n if (val !== undefined && this._convert) {\n val = this._convert(val);\n }\n return val !== undefined ? val : this._default;\n }\n\n };\n\n // Export\n return okanjo._Widget = Widget;\n\n})(window);\n\n\n\n","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window) {\n\n //region Imports and Constants\n\n const okanjo = window.okanjo;\n const { string, array, float, int, bool } = okanjo._Widget.Field;\n const Metrics = okanjo.metrics.constructor;\n const TemplateEngine = okanjo.ui.engine.constructor;\n\n const FILTERS = 'filters';\n const DISPLAY = 'display';\n const ARTICLE_META = 'article_meta';\n\n const MINIMUM_VIEW_PX = 0.5; // 50% of pixels must be in viewport\n const MINIMUM_VIEW_TIME = 1000; // for 1 full second\n const MINIMUM_VIEW_FREQ = 2; // time / freq = interval\n\n //endregion\n\n /**\n * Placement widget\n */\n class Placement extends okanjo._Widget {\n\n //region Configuration & Overrides\n\n /**\n * Initializes a new placement\n * @param element\n * @param options\n */\n constructor(element, options = {}) {\n\n // Flatten the options before passing on\n options = okanjo.util.flatten(options, { ignoreArrays: true });\n super(element, options);\n\n this.name = 'Placement';\n this._metricBase = {}; // placeholder for metrics\n this._response = null;\n\n // Aggregate view watchers into a single interval fn\n this._viewWatcherIv = null;\n this._viewedWatchers = [];\n\n // Start loading content\n if (!options.no_init) this.init();\n }\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Gets the widget settings configuration\n * @return {{type: *, ids: *, q: *, url: *, url_referrer: *, url_selectors: *, organization_id: *, property_id: *, store_id: *, organization_name: *, property_name: *, store_name: *, external_id: *, sku: *, external_store_id: *, condition: *, manufacturer: *, upc: *, isbn: *, tags: *, category: *, pools: *, min_price: *, max_price: *, min_donation_percent: *, max_donation_percent: *, donation_to: *, sort_by: *, sort_direction: *, skip: *, take: *, placement_tests_only: *, size: *, template_name: *, template_layout: *, template_theme: *, template_cta_style: *, template_cta_text: *, template_cta_color: *, adx_unit_path: *, url_category: *, url_keywords: *, no_init: *, proxy_url: *, expandable, disable_inline_buy, disable_popup, backwards: *}}\n */\n getSettings() {\n return {\n\n // What type of response do you want\n type: string().group(FILTERS),\n\n // What specific products do you want\n ids: array().group(FILTERS),\n\n // Filter by generic query string\n q: string().group(FILTERS),\n\n // Filter by relation to content\n url: string().group(FILTERS),\n url_referrer: string().group(FILTERS).strip(),\n url_selectors: string().group(FILTERS),\n url_paths: array().group(FILTERS),\n not_url_paths: array().group(FILTERS),\n\n // Filter by hierarchy\n organization_id: string().group(FILTERS),\n property_id: string().group(FILTERS),\n store_id: string().group(FILTERS),\n\n // Filter by hierarchy names (use *_id where possible, this might not work as you might expect)\n organization_name: string().group(FILTERS),\n property_name: string().group(FILTERS),\n store_name: string().group(FILTERS),\n\n // Filter by integrations\n external_id: string().group(FILTERS),\n sku: string().group(FILTERS),\n external_store_id: string().group(FILTERS),\n\n // Filter by product attributes\n condition: string().group(FILTERS),\n manufacturer: string().group(FILTERS),\n upc: string().group(FILTERS),\n isbn: string().group(FILTERS),\n\n // Filter by categorization / distribution\n tags: array().group(FILTERS),\n category: array().group(FILTERS),\n pools: array().group(FILTERS),\n\n // Filter by price range\n min_price: float().group(FILTERS),\n max_price: float().group(FILTERS),\n\n // Filter by donation ranges\n min_donation_percent: float().group(FILTERS),\n max_donation_percent: float().group(FILTERS),\n\n // Filter by donation recipient\n donation_to: string().group(FILTERS),\n\n // Sorting\n sort_by: string().group(FILTERS),\n sort_direction: string().group(FILTERS),\n\n // Pagination\n skip: int().group(FILTERS),\n take: int().group(FILTERS),\n\n // Placement Testing\n placement_tests_only: bool(),\n\n // Display settings\n size: string().group(DISPLAY),\n template_name: string().group(DISPLAY),\n template_layout: string().group(DISPLAY),\n template_theme: string().group(DISPLAY),\n template_variant: string().group(DISPLAY),\n template_cta_style: string().group(DISPLAY),\n template_cta_text: string().group(DISPLAY),\n template_cta_color: string().group(DISPLAY),\n adx_unit_path: string().group(DISPLAY), // Custom DFP ad unit path\n\n // Article metadata\n url_category: array().group(ARTICLE_META),\n url_keywords: array().group(ARTICLE_META),\n\n // Functional settings\n key: string().strip(), // don't need to resend key on all our requests\n no_init: bool().strip(), // don't automatically load the placement, do it manually (e.g. (new Placement({no_init:true})).init()\n proxy_url: string().strip(),\n expandable: bool().strip().default(true),\n disable_inline_buy: bool().strip().default(false), // stops inline buy functionality\n disable_popup: bool().strip().default(false), // stops new window on mobile for inline buy functionality\n backwards: string().strip(), // internal flag indicating port from a deprecated widget\n testing: bool().strip() // metrics flag to indicate testing\n };\n }\n\n /**\n * Gets the widget configuration formatted using settings, suitable for transmission\n * @return {{filters: {}, display: {}, backfill: {}, shortfill: {}, article_meta: {}}}\n */\n getConfig() {\n const settings = this.getSettings();\n const out = { filters: {}, display: {}, backfill: {}, shortfill: {}, article_meta: {} };\n const backfillPattern = /^backfill_(.+)$/; // backfill_property\n const shortfillPattern = /^shortfill_(.+)$/; // shortfill_property\n\n Object.keys(this.config).forEach((origKey) => {\n let val = this.config[origKey];\n let key = origKey;\n let isBackfill = false;\n let isShortfill = false;\n let group = null;\n\n // Get the property name if it was prefixed with backfill\n let matches = backfillPattern.exec(origKey);\n if (matches) {\n key = matches[1];\n isBackfill = true;\n } else {\n // Get the property name if it was prefixed with shortfill\n matches = shortfillPattern.exec(origKey);\n if (matches) {\n key = matches[1];\n isShortfill = true;\n }\n }\n\n // Check if this is a known property\n if (settings[key]) {\n val = settings[key].value(val);\n group = settings[key].getGroup();\n }\n\n // Init the target/group if not already setup\n let target = out;\n if (isBackfill) {\n target = out.backfill;\n } else if (isShortfill) {\n target = out.shortfill;\n }\n\n // Set the target to the bucket in the settings container\n // except shortfill - can only apply settings directly to the bucket\n // e.g. backfill_url -> { backfill: { filters: { url: xxx } } }\n // e.g. shortfill_url-> { shortfill: { url: xxx } }\n if (!isShortfill && group) {\n target[group] = target[group] || {};\n target = target[group];\n }\n\n // Set the value on the target if set\n if (val === null) {\n target[key] = ''; // format null values as empty strings for transmission\n } else if (val !== undefined) {\n target[key] = val;\n }\n });\n\n return out;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Core load process\n */\n load() {\n // Set metric base data (stub for all future events emitted by the widget)\n this._setMetricBase();\n\n // Find out what we should display here\n this._fetchContent((err) => {\n if (err) {\n // Report the widget load as declined\n this._reportWidgetLoad(\"fetch failed: \" + err.statusCode /* istanbul ignore next: out of scope */ || err.toString());\n } else {\n // Merge display settings from response\n this._mergeResponseSettings();\n\n // Merge the referential data from the response\n this._updateBaseMetaFromResponse();\n\n // Handle rendering based on output type\n this._showContent();\n }\n });\n }\n\n //endregion\n\n //region Internal Helpers\n\n /**\n * Initializes the common metric data for events emitted by the placement\n * @private\n */\n _setMetricBase() {\n const base = this._metricBase;\n base.ch = Metrics.Channel.placement;\n base.cx = this.config.backwards || 'auto';\n base.key = this.config.key;\n base.m = base.m || {};\n base.m.wgid = this.instanceId;\n\n if (this.config.testing) base.env = Metrics.Environment.testing;\n }\n\n /**\n * Emits the widget impression event\n * @param declined\n * @private\n */\n _reportWidgetLoad(declined) {\n\n const res = this._response || {};\n const data = res.data || { results: [] };\n\n // If this is declined, mark future events as declined too\n this._metricBase.m.decl = declined || '0';\n\n // Attach other main response attributes to all future events\n this._metricBase.m.res_bf = data.backfilled ? 1 : 0; // whether the response used the back fill flow\n this._metricBase.m.res_sf = data.shortfilled ? 1 : 0; // whether the response used the short fill flow\n this._metricBase.m.res_spltfl = data.splitfilled ? 1 : 0; // whether the response used the short fill flow\n this._metricBase.m.res_total = data.total || 0; // how many total candidate results were available given filters\n this._metricBase.m.res_type = data.type; // what the given resource type was\n this._metricBase.m.res_length = data.results.length; // number of resources delivered\n\n // Track impression\n okanjo.metrics.create(this._metricBase)\n .type(Metrics.Object.widget, Metrics.Event.impression)\n .meta(this.getConfig())\n .element(this.element) // this might not be all that useful cuz the content hasn't been rendered yet\n .viewport()\n .widget(this.element)\n .send();\n\n // Start watching for a viewable impression\n this._addOnceViewedHandler(this.element, () => {\n okanjo.metrics.create(this._metricBase)\n .type(Metrics.Object.widget, Metrics.Event.view)\n .meta(this.getConfig())\n .element(this.element)\n .viewport()\n .widget(this.element)\n .send();\n });\n }\n\n /**\n * Executes the request for content to fill the placement\n * @param callback\n * @private\n */\n _fetchContent(callback) {\n // Build request to api, starting with this placement config params\n const query = this.getConfig();\n\n // Extract the key\n const key = this.config.key;\n\n // Attach sid and referrer\n if (okanjo.metrics.sid) query.sid = okanjo.metrics.sid;\n query.filters.url_referrer = this.config.url_referrer || window.location.href;\n query.wgid = this.instanceId;\n query.pgid = okanjo.metrics.pageId;\n\n // Send it\n okanjo.net.request.post(\n `${okanjo.net.getRoute(okanjo.net.routes.ads, null, this.config.sandbox ? 'sandbox' : 'live')}?key=${encodeURIComponent(key)}`,\n query,\n (err, res) => {\n if (err) {\n okanjo.report('Failed to retrieve placement content', err, { placement: this });\n this.setMarkup(''); // Don't show anything\n this.emit('error', err);\n callback && callback(err);\n } else {\n\n // Store the raw response\n this._response = res;\n\n // Hook point for response handling\n this.emit('data');\n\n // Return\n callback && callback();\n }\n }\n );\n }\n\n /**\n * Applies response filters and display settings into the widget configuration\n * @private\n */\n _mergeResponseSettings() {\n const res = this._response;\n const data = res.data || {};\n const settings = data.settings || {};\n\n if (settings.filters) {\n Object.keys(settings.filters).forEach((key) => {\n this.config[key] = settings.filters[key];\n });\n }\n\n if (settings.display) {\n Object.keys(settings.display).forEach((key) => {\n this.config[key] = settings.display[key];\n });\n }\n }\n\n /**\n * Applies response data to future metric events\n * @private\n */\n _updateBaseMetaFromResponse() {\n // Update the base metric data with info from the response\n const data = (this._response|| {}).data || {};\n this._metricBase.m = this._metricBase.m || {};\n const meta = this._metricBase.m;\n\n // Article\n if (data.article) meta.aid = data.article.id;\n\n if (data.test && data.test.enabled) {\n meta.pten = 1;\n meta.ptid = data.test.id;\n meta.ptseed = data.test.seed;\n } else {\n meta.pten = 0;\n }\n }\n\n /**\n * Beings the render process based on the response content\n * @private\n */\n _showContent() {\n const data = (this._response|| {}).data || {};\n\n // Known content types we can display\n if (data.type === Placement.ContentTypes.products) {\n this._showProducts();\n } else if (data.type === Placement.ContentTypes.articles) {\n this._showArticles();\n } else if (data.type === Placement.ContentTypes.adx) {\n this._showADX();\n } else {\n // Unknown response type!\n\n // Report the widget load as declined\n const msg = 'Unknown response content type: ' + data.type;\n okanjo.report(msg, { placement: this });\n this.setMarkup(''); // Don't show anything\n this.emit('error', msg);\n this._reportWidgetLoad(msg);\n }\n }\n\n /**\n * Generates the click url using the event, proxy_url, and additional params\n * @param event\n * @param url\n * @param additionalUrlParams\n * @return {*}\n * @private\n */\n _getClickThroughURL(event, url, additionalUrlParams) {\n const joiner = url.indexOf('?') >= 0 ? '&' : '?';\n\n // Tack on transfer params\n additionalUrlParams = additionalUrlParams /* istanbul ignore next: paranoia */ || {};\n additionalUrlParams.ok_msid = okanjo.metrics.sid || 'unknown';\n additionalUrlParams.ok_ch = this._metricBase.ch;\n additionalUrlParams.ok_cx = this._metricBase.cx;\n additionalUrlParams._okjr = window.location.href.split(/[?#]/)[0];\n additionalUrlParams.utm_source = 'okanjo';\n additionalUrlParams.utm_campaign = 'smartserve';\n // additionalUrlParams.utm_source = window.location.hostname;\n additionalUrlParams.utm_medium = 'smartserve';\n // additionalUrlParams.utm_campaign = 'smartserve';\n\n\n url += joiner + Object.keys(additionalUrlParams)\n .map((key) => encodeURIComponent(key)+'='+encodeURIComponent(additionalUrlParams[key]))\n .join('&');\n\n // Wrap the url if we're proxying\n if (this.config.proxy_url) {\n url = this.config.proxy_url + encodeURIComponent(url);\n }\n\n // Set the url on the event\n event.data({\n u: url\n });\n\n return event.toUrl();\n }\n\n /**\n * Converts a resource's link into one suitable for tracking, making middle-click safe\n * @param type\n * @param resource\n * @param e\n * @private\n */\n _handleResourceMouseDown(type, resource, e) {\n // Generate a new click id for this event\n // const clickId = okanjo.util.shortid();\n const clickId = resource._cid;\n\n // Start building the event\n const event = okanjo.metrics.create(this._metricBase, {\n id: resource.id\n })\n .type(type, Metrics.Event.interaction)\n .meta(this.getConfig())\n .meta({ cid: clickId })\n .meta({\n bf: resource.backfill ? 1 : 0,\n sf: resource.shortfill ? 1 : 0,\n spltfl_seg: resource.splitfill_segment || null\n })\n .event(e)\n .element(e.currentTarget)\n .viewport()\n .widget(this.element);\n\n // Pull the proper params out of the resource depending on it's type\n let trackParam = 'url_track_param';\n let urlParam = 'url';\n\n if (type === Metrics.Object.product) {\n trackParam = 'buy_url_track_param';\n urlParam = 'buy_url';\n }\n\n // Attach the campaign tracking identifier\n const additionalParams = {\n ok_cid: clickId\n };\n if (resource[trackParam]) additionalParams[resource[trackParam]] = clickId;\n\n // Update the link with the event data\n event.data({ ea: Metrics.Action.click });\n e.currentTarget.href = this._getClickThroughURL(event, resource[urlParam], additionalParams);\n\n // Cache this on the product\n resource._clickId = clickId;\n resource._event = event;\n resource._additionalParams = additionalParams;\n }\n\n /**\n * Gets the template to use, accounting for configured preference if available\n * @param contentType\n * @param defaultName\n * @return {string}\n * @private\n */\n _getTemplate(contentType, defaultName) {\n let templateName = this.config.template_name;\n if (!templateName ||\n !okanjo.ui.engine.isTemplateRegistered(`${contentType}.${templateName}`)) {\n templateName = defaultName;\n }\n return `${contentType}.${templateName}`;\n }\n\n /**\n * Enforces size/layout/cta restrictions\n * @private\n */\n _enforceLayoutOptions() {\n // Enforce format restrictions\n if (this.config.size === \"leaderboard\" || this.config.size === \"large_mobile_banner\") {\n this.config.template_layout = \"list\";\n this.config.template_cta_style = \"link\";\n } else if (this.config.size === \"half_page\" || this.config.size === \"auto\") {\n this.config.template_layout = \"list\";\n }\n }\n\n /**\n * Enforces\n * @private\n */\n _enforceSlabLayoutOptions() {\n if (this.config.size === \"medium_rectangle\" || this.config.size === \"billboard\") {\n // no list view\n this.config.template_layout = \"grid\";\n\n // no buttons\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n } else if (this.config.size === \"half_page\") {\n this.config.template_layout = \"grid\";\n } else if (this.config.size === \"leaderboard\" || this.config.size === \"large_mobile_banner\") {\n this.config.template_layout = \"list\";\n\n // no button\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n } else if (this.config.size === \"auto\") {\n this.config.template_layout = \"list\";\n } else if (this.config.size === \"responsive\") {\n // no button in responsive mode\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n }\n }\n\n /**\n * Register a custom\n * @private\n */\n _registerCustomBranding(/*prefix, buttonClass*/) {\n const brandColor = this.config.template_cta_color;\n if (brandColor) {\n let brandCSS,\n brandCSSId = \"okanjo-wgid-\" + this.instanceId;\n\n brandCSS = `\n .okanjo-block2.${brandCSSId} .okanjo-resource-cta-button, .okanjo-block2.${brandCSSId} .okanjo-resource-buy-button { color: ${brandColor} !important; } \n .okanjo-block2.${brandCSSId}.okanjo-cta-style-button .okanjo-resource-cta-button, .okanjo-block2.${brandCSSId}.okanjo-cta-style-button .okanjo-resource-buy-button { border-color: ${brandColor} !important; } \n .okanjo-block2.${brandCSSId}.okanjo-cta-style-button .okanjo-resource-cta-button:hover, .okanjo-block2.${brandCSSId}.okanjo-cta-style-button .okanjo-resource-buy-button:hover { background: ${brandColor} !important; color: #fff !important; } \n `;\n\n okanjo.ui.engine.registerCss(brandCSSId, brandCSS, { id: brandCSSId });\n okanjo.ui.engine.ensureCss(brandCSSId);\n }\n }\n\n /**\n * When element is in view per viewability constants (50% for 1s) trigger handler once\n * @param element\n * @param handler\n * @private\n */\n _addOnceViewedHandler(element, handler) {\n let controller = {\n element,\n successfulCount: 0,\n handler\n };\n\n // Add our element to the watch list and turn on the watcher if not already on\n this._viewedWatchers.push(controller);\n this._toggleViewWatcher(true);\n }\n\n /**\n * Interval function to check viewability of registered elements\n * @private\n */\n _checkViewWatchers() {\n\n // Check each registered watcher\n for (let i = 0, controller; i < this._viewedWatchers.length; i++) {\n controller = this._viewedWatchers[i];\n\n // Check if watcher is complete, then remove it from the list\n /* istanbul ignore next: jsdom won't trigger this */\n if (okanjo.ui.isElementVisible(controller.element) &&\n okanjo.ui.getPercentageInViewport(controller.element) >= MINIMUM_VIEW_PX) {\n controller.successfulCount++;\n }\n\n // While this could more optimally be contained within the former condition, unit-testing blocks on this\n if (controller.successfulCount >= MINIMUM_VIEW_FREQ) {\n controller.handler();\n this._viewedWatchers.splice(i, 1);\n i--;\n }\n }\n\n // Turn off if nobody is watching\n if (this._viewedWatchers.length === 0) {\n this._toggleViewWatcher(false);\n }\n }\n\n /**\n * Turns the viewability watcher on and off\n * @param enabled\n * @private\n */\n _toggleViewWatcher(enabled) {\n if (enabled) {\n if (this._viewWatcherIv === null) {\n this._viewWatcherIv = setInterval(this._checkViewWatchers.bind(this), MINIMUM_VIEW_TIME / MINIMUM_VIEW_FREQ);\n }\n } else {\n clearInterval(this._viewWatcherIv);\n this._viewWatcherIv = null;\n }\n }\n\n //endregion\n\n //region Product Handling\n\n /**\n * Renders a product response\n * @private\n */\n _showProducts() {\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n\n // Determine template to render, using custom template name if it exists\n const templateName = this._getTemplate(Placement.ContentTypes.products, Placement.DefaultTemplates.products);\n\n // - render\n\n // Format products\n data.results.forEach((offer, index) => {\n // Disable inline buy if configured to do so\n if (this.config.disable_inline_buy) offer.inline_buy_url = null;\n if (offer.inline_buy_url) offer._escaped_inline_buy_url = encodeURIComponent(offer.inline_buy_url);\n\n // Set primary image\n offer._image_url = offer.image_urls ? offer.image_urls[0] : '' ;\n\n // Escape buy url (fixme: does not include proxy_url!)\n offer._escaped_buy_url = encodeURIComponent(offer.buy_url);\n\n // Make price tag pretty\n offer._price_formatted = TemplateEngine.formatCurrency(offer.price);\n offer._index = index;\n });\n\n // Render and display the results\n this.setMarkup(okanjo.ui.engine.render(templateName, this));\n\n // Track widget impression\n if (data.results.length === 0) {\n // Hook point for no results found\n this.emit('empty');\n this._reportWidgetLoad('empty'); // decline the impression\n } else {\n this._reportWidgetLoad();\n }\n\n // Bind interaction handlers and track impressions\n this.element.querySelectorAll('a').forEach((a) => {\n\n const id = a.getAttribute('data-id'),\n index = a.getAttribute('data-index');\n\n // Don't bind links that are not tile links\n /* istanbul ignore else: custom templates could break it */\n if (id && index >= 0) {\n const product = this._response.data.results[index];\n /* istanbul ignore else: custom templates could break it */\n if (product) {\n\n // Bind interaction listener\n a.addEventListener('mousedown', this._handleResourceMouseDown.bind(this, Metrics.Object.product, product));\n a.addEventListener('click', this._handleProductClick.bind(this, product));\n\n // Track impression\n okanjo.metrics.create(this._metricBase, { id: product.id })\n .type(Metrics.Object.product, Metrics.Event.impression)\n .meta(this.getConfig())\n .meta({\n bf: product.backfill ? 1 : 0,\n sf: product.shortfill ? 1 : 0,\n spltfl_seg: product.splitfill_segment || null\n })\n .element(a)\n .viewport()\n .widget(this.element)\n .send();\n\n // Start watching for a viewable impression\n this._addOnceViewedHandler(a, () => {\n okanjo.metrics.create(this._metricBase, { id: product.id })\n .type(Metrics.Object.product, Metrics.Event.view)\n .meta(this.getConfig())\n .meta({\n bf: product.backfill ? 1 : 0,\n sf: product.shortfill ? 1 : 0,\n spltfl_seg: product.splitfill_segment || null\n })\n .element(a)\n .viewport()\n .widget(this.element)\n .send();\n });\n }\n }\n });\n\n // Truncate product name to fit the space\n this.element.querySelectorAll('.okanjo-resource-title').forEach((element) => {\n okanjo.ui.ellipsify(element);\n });\n\n // Fit images\n okanjo.ui.fitImages(this.element);\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n /**\n * Handles the product click process\n * @param product\n * @param e\n * @private\n */\n _handleProductClick(product, e) {\n\n // Update the event\n if (!product._event || !product._additionalParams || !product._clickId) {\n this._handleResourceMouseDown(Metrics.Object.product, product, e);\n }\n\n // Extract the already generated event and params list\n const {\n _event: event,\n _additionalParams: additionalParams\n } = product;\n\n // Update the event to the current one\n event.event(e);\n\n // Determine what we're doing - native ux or redirect\n const showNativeBuyUx = !!product.inline_buy_url,\n showPopupNativeBuyUx = !this.config.disable_popup && showNativeBuyUx && okanjo.util.isMobile()\n ;\n\n // Show the inline buy experience or redirect\n if (showPopupNativeBuyUx) {\n // Mobile native buy ux\n\n // Don't follow the link\n e.preventDefault();\n\n //\n // Mobile devices (especially iOS) have real janky UX when interacting with iframes.\n // So, we'll choose to popup a window with the native buy experience, so we can ensure\n // a positive user experience. Nobody likes bouncy form fields and really weird zooming.\n //\n\n // Update the event\n event\n .data({ ea: Metrics.Action.inline_click })\n .meta({ popup: 'true' });\n\n // Get the frame url\n let url = this._getClickThroughURL(event, product.inline_buy_url, additionalParams);\n\n // Open the window or redirect if that failed\n this._popupFrame = window.open(url, \"okanjo-inline-buy-frame\", \"width=400,height=400,location=yes,resizable=yes,scrollbars=yes\");\n /* istanbul ignore else: jsdom doesn't support window.open or setting window.location.href */\n if (!this._popupFrame) {\n // Fallback to just replacing the window with the target, since popups don't work :(\n okanjo.report('Popup blocker stopped buy experience from showing', { placement: this });\n window.location.href = url;\n }\n\n } else if (showNativeBuyUx) {\n // Regular native buy ux\n\n // Don't follow the link\n e.preventDefault();\n\n const frame = document.createElement('iframe');\n const attributes = {\n 'class': 'okanjo-inline-buy-frame',\n frameborder: 0,\n vspace: 0,\n hspace: 0,\n webkitallowfullscreen: '',\n mozallowfullscreen: '',\n allowfullscreen: '',\n scrolling: 'auto'\n };\n\n // Apply attributes\n Object.keys(attributes).forEach((key) => frame.setAttribute(key, attributes[key]));\n\n // Check whether we're allowed to expand past the bounds of the placement\n additionalParams.expandable = this.config.expandable ? 1: 0;\n if (!this.config.expandable) {\n const parent = this.element.querySelector('.okanjo-expansion-root');\n /* istanbul ignore else: custom templates could break this */\n if (parent) {\n frame.className += ' okanjo-ad-in-unit';\n frame.setAttribute('height', \"100%\");\n frame.setAttribute('width', \"100%\");\n\n parent.appendChild(frame);\n\n const size = okanjo.ui.getElementSize(parent);\n additionalParams.frame_height = size.height;\n additionalParams.frame_width = size.width;\n /* istanbul ignore next: i'm not writing a whole test for this one config param */\n if (this.config.size) additionalParams.ad_size = this.config.size;\n }\n }\n\n // Update the event\n event\n .data({ ea: Metrics.Action.inline_click })\n .meta({ expandable: this.config.expandable ? 'true' : 'false' });\n\n // Set the frame url\n frame.src = this._getClickThroughURL(event, product.inline_buy_url, additionalParams);\n\n // Show the modal if it was not internally expanded\n if (!frame.parentNode) {\n okanjo.ui.modal.show(frame);\n }\n\n } else {\n // Update the link a second time, just in case the data changed\n e.currentTarget.href = this._getClickThroughURL(event, product.buy_url, additionalParams);\n }\n }\n\n //endregion\n\n //region Article Handling\n\n /**\n * Renders an article response\n * @private\n */\n _showArticles() {\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n\n // Determine template to render, using custom template name if it exists\n const templateName = this._getTemplate(Placement.ContentTypes.articles, Placement.DefaultTemplates.articles);\n\n // - render\n\n // Format articles\n data.results.forEach((article, index) => {\n // Escape url (fixme: does not include proxy_url!)\n article._escaped_url = encodeURIComponent(article.url);\n article._index = index;\n });\n\n // Render and display the results\n this.setMarkup(okanjo.ui.engine.render(templateName, this));\n\n // Track widget impression\n if (data.results.length === 0) {\n // Hook point for no results found\n this.emit('empty');\n this._reportWidgetLoad('empty'); // decline the impression\n } else {\n this._reportWidgetLoad();\n }\n\n // Bind interaction handlers and track impressions\n this.element.querySelectorAll('a').forEach((a) => {\n\n const id = a.getAttribute('data-id'),\n index = a.getAttribute('data-index');\n\n // Don't bind links that are not tile links\n /* istanbul ignore else: custom templates could break this */\n if (id && index >= 0) {\n const article = this._response.data.results[index];\n /* istanbul ignore else: custom templates could break this */\n if (article) {\n\n // Bind interaction listener\n a.addEventListener('mousedown', this._handleResourceMouseDown.bind(this, Metrics.Object.article, article));\n a.addEventListener('click', this._handleArticleClick.bind(this, article));\n\n // Track impression\n okanjo.metrics.create(this._metricBase, { id: article.id })\n .type(Metrics.Object.article, Metrics.Event.impression)\n .meta(this.getConfig())\n .meta({\n bf: article.backfill ? 1 : 0,\n sf: article.shortfill ? 1 : 0,\n spltfl_seg: article.splitfill_segment || null\n })\n .element(a)\n .viewport()\n .widget(this.element)\n .send();\n\n // Start watching for a viewable impression\n this._addOnceViewedHandler(a, () => {\n okanjo.metrics.create(this._metricBase, { id: article.id })\n .type(Metrics.Object.article, Metrics.Event.view)\n .meta(this.getConfig())\n .meta({\n bf: article.backfill ? 1 : 0,\n sf: article.shortfill ? 1 : 0,\n spltfl_seg: article.splitfill_segment || null\n })\n .element(a)\n .viewport()\n .widget(this.element)\n .send();\n });\n\n }\n }\n });\n\n // Truncate product name to fit the space\n this.element.querySelectorAll('.okanjo-resource-title').forEach((element) => {\n okanjo.ui.ellipsify(element);\n });\n\n // Fit images\n okanjo.ui.fitImages(this.element);\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n /**\n * Handles the article click process\n * @param article\n * @param e\n * @private\n */\n _handleArticleClick(article, e) {\n // Update the event\n if (!article._event || !article._additionalParams || !article._clickId) {\n this._handleResourceMouseDown(Metrics.Object.article, article, e);\n }\n\n // Extract the already generated event and params list\n const {\n _event: event,\n _additionalParams: additionalParams\n } = article;\n\n // Update the event to the current one\n event.event(e);\n\n // Update the link a second time, just in case the data changed\n e.currentTarget.href = this._getClickThroughURL(event, article.url, additionalParams);\n }\n\n //endregion\n\n //region ADX Handling\n\n /**\n * Renders a Google DFP/ADX response\n * @private\n */\n _showADX() {\n const data = (this._response || { data: { settings: {} } }).data || { settings: {} };\n\n // Get the template we should use to render the google ad\n const templateName = this._getTemplate(Placement.ContentTypes.adx, Placement.DefaultTemplates.adx);\n\n // Determine what size ad we can place here\n let size = null;\n if (this.config.size) {\n if (Placement.Sizes[this.config.size]) {\n // Defined size, use these known dimensions\n size = Placement.Sizes[this.config.size];\n } else {\n let match = (/^([0-9]+)x([0-9]+)$/i).exec(this.config.size);\n if (match) {\n size = { width: match[1], height: match[2] }\n }\n }\n }\n\n // No given size, we need to guess\n if (!size) size = Placement.Sizes.default;\n\n // If we're using okanjo's ad slot, then track the impression\n // otherwise decline it because we're just passing through to the publishers account\n let adUnitPath = '/90447967/okanjo:';\n let declineReason;\n if (data.settings.display && data.settings.display.adx_unit_path) {\n adUnitPath = data.settings.display.adx_unit_path;\n declineReason = 'custom_ad_unit';\n }\n\n // Pass along what the template needs to know to display the ad\n const renderContext = {\n size,\n adUnitPath\n };\n\n // Render the container\n this.setMarkup(okanjo.ui.engine.render(templateName, this, renderContext));\n\n // Report the impression\n this._reportWidgetLoad(declineReason);\n\n // Insert the actual ad into the container\n const container = this.element.querySelector('.okanjo-adx-container');\n /* istanbul ignore else: custom templates could break this */\n if (container) {\n\n // Make the frame element\n const frame = document.createElement('iframe');\n const attributes = {\n 'class': 'okanjo-adx-frame',\n frameborder: 0,\n vspace: 0,\n hspace: 0,\n webkitallowfullscreen: '',\n mozallowfullscreen: '',\n allowfullscreen: '',\n scrolling: 'auto',\n width: size.width,\n height: size.height\n };\n\n // Apply attributes\n Object.keys(attributes).forEach((key) => frame.setAttribute(key, attributes[key]));\n\n // Attach to dOM\n container.appendChild(frame);\n\n // Build a click-through tracking url so we know when an ad is clicked too\n let clickUrl = okanjo.metrics.create(this._metricBase)\n .type(Metrics.Object.thirdparty_ad, Metrics.Event.interaction)\n .meta(this.getConfig())\n .meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n })\n .element(frame)\n .viewport()\n .widget(this.element)\n .toUrl();\n\n // Transfer references to the frame window\n // frame.contentWindow.okanjo = okanjo;\n // frame.contentWindow.placement = this;\n frame.contentWindow.trackImpression = () => {\n okanjo.metrics.create(this._metricBase)\n .type(Metrics.Object.thirdparty_ad, Metrics.Event.impression)\n .meta(this.getConfig())\n .meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n })\n .element(frame)\n .viewport()\n .widget(this.element)\n .send()\n ;\n\n // Start watching for a viewable impression\n this._addOnceViewedHandler(frame, () => {\n okanjo.metrics.create(this._metricBase)\n .type(Metrics.Object.thirdparty_ad, Metrics.Event.view)\n .meta(this.getConfig())\n .meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n })\n .element(frame)\n .viewport()\n .widget(this.element)\n .send()\n ;\n });\n };\n\n // Load Google ad!\n frame.contentWindow.document.open();\n frame.contentWindow.document.write(\n`\n<`+`script type=\"text/javascript\" src=\"https://www.googletagservices.com/tag/js/gpt.js\">\n googletag.pubads().addEventListener('slotRenderEnded', function(e) { \n trackImpression(e);\n });\n googletag.pubads()\n .definePassback(\"${adUnitPath.replace(/\"/g, '\\\\\"')}\", [[${size.width}, ${size.height}]])\n .setClickUrl(\"${clickUrl}&u=\")\n .display();\n<`+`/script>\n`);\n frame.contentWindow.document.close();\n\n // TODO future event hooks\n // googletag.pubads().addEventListener('impressionViewable', function(e) { future )});\n // googletag.pubads().addEventListener('slotOnload', function(e) { future });\n // googletag.pubads().addEventListener('slotVisibilityChangedEvent', function(e) { future );\n\n // Impression tracking is done from within the iframe. Crazy, right?\n }\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n //endregion\n }\n\n //region Enumerations\n\n /**\n * Standard ad sizes\n * @type {{billboard: {width: number, height: number}, button_2: {width: number, height: number}, half_page: {width: number, height: number}, leaderboard: {width: number, height: number}, medium_rectangle: {width: number, height: number}, micro_bar: {width: number, height: number}, portrait: {width: number, height: number}, rectangle: {width: number, height: number}, super_leaderboard: {width: number, height: number}, wide_skyscraper: {width: number, height: number}, large_mobile_banner: {width: number, height: number}, mobile_leaderboard: {width: number, height: number}, small_square: {width: number, height: number}, button_1: {width: number, height: number}, full_banner: {width: number, height: number}, half_banner: {width: number, height: number}, large_rectangle: {width: number, height: number}, pop_under: {width: number, height: number}, three_to_one_rectangle: {width: number, height: number}, skyscraper: {width: number, height: number}, square: {width: number, height: number}, square_button: {width: number, height: number}, vertical_banner: {width: number, height: number}, vertical_rectangle: {width: number, height: number}}}\n */\n Placement.Sizes = {\n\n // Supported\n medium_rectangle: { width: 300, height: 250 }, // aka: sidekick\n leaderboard: { width: 728, height: 90 },\n large_mobile_banner: { width: 320, height: 100 },\n half_page: { width: 300, height: 600 }, // aka: filmstrip, sidekick\n billboard: { width: 970, height: 250 }, // aka: sidekick\n\n // IAB / Others\n button_2: { width: 120, height: 60 },\n micro_bar: { width: 88, height: 31 },\n portrait: { width: 300, height:1050 },\n rectangle: { width: 180, height: 150 },\n super_leaderboard: { width: 970, height: 90 }, // aka: pushdown, slider, large_leaderboard\n wide_skyscraper: { width: 160, height: 600 },\n\n // Google\n mobile_leaderboard: { width: 320, height: 50 },\n small_square: { width: 200, height: 200 },\n\n // Retired / Deprecated\n button_1: { width: 120, height: 90 },\n full_banner: { width: 468, height: 60 },\n half_banner: { width: 234, height: 60 },\n large_rectangle: { width: 336, height: 280 },\n pop_under: { width: 720, height: 300 },\n three_to_one_rectangle: { width: 300, height: 100 },\n skyscraper: { width: 120, height: 600 },\n square: { width: 250, height: 250 },\n square_button: { width: 125, height: 125 },\n vertical_banner: { width: 120, height: 240 },\n vertical_rectangle: { width: 240, height: 400 }\n };\n\n // When we should show an ad but nobody told us what size\n Placement.Sizes.default = Placement.Sizes.medium_rectangle;\n\n /**\n * Placement content types\n * @type {{products: string, articles: string, adx: string}}\n */\n Placement.ContentTypes = {\n products: 'products',\n articles: 'articles',\n adx: 'adx'\n };\n\n /**\n * Default templates for each content type\n * @type {{products: string, articles: string, adx: string}}\n */\n Placement.DefaultTemplates = {\n products: 'block2',\n articles: 'block2',\n adx: 'block2'\n };\n\n //endregion\n\n return okanjo.Placement = Placement;\n\n})(window);","\"use strict\";\n\n// **********\n// DEPRECATED - USE okanjo.Placement instead!\n// **********\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window) {\n\n const okanjo = window.okanjo;\n\n /**\n * Backwards compatible interface, turning a Product widget into a placement widget\n * @deprecated\n */\n class Product extends okanjo.Placement {\n\n constructor(element, options) {\n // Initialize placement w/o loading (we need to jack the config)\n options = options || {};\n const no_init = options.no_init; // hold original no_init flag, if set\n options.no_init = true;\n super(element, options);\n\n okanjo.warn('Product widget has been deprecated. Use Placement instead (may require configuration changes)', { widget: this });\n\n // Start loading content\n if (!no_init) {\n delete this.config.no_init;\n this.init();\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Converts the old product widget configuration into a usable placement configuration\n */\n _setCompatibilityOptions() {\n // Convert the product config to a placement configuration\n this.config.backwards = 'Product';\n this.config.type = okanjo.Placement.ContentTypes.products;\n\n // Set filters based on old \"mode\"\n if (this.config.mode === 'sense') {\n // sense\n this.config.url = this.config.url || 'referrer';\n this.config.take = this.config.take || 5;\n } else if (this.config.mode === 'single') {\n // single\n this.config.url = null;\n if (this.config.id) this.config.ids = [this.config.id];\n this.config.take = 1;\n delete this.config.id;\n } else {\n // browse\n this.config.url = null;\n this.config.take = this.config.take || 25;\n }\n delete this.config.mode;\n\n // Sold by changed to store name\n if (this.config.sold_by) {\n this.config.store_name = this.config.sold_by;\n delete this.config.sold_by;\n }\n\n // Selectors is now url_selectors\n if (this.config.selectors) {\n this.config.url_selectors = this.config.selectors;\n delete this.config.selectors;\n }\n\n // Marketplace_id is no longer a thing, closest analog are properties.\n if (this.config.marketplace_id) {\n this.config.property_id = this.config.marketplace_id;\n delete this.config.marketplace_id\n }\n\n // Marketplace status is no longer a thing, instead, use the sandbox environment for testing\n if (this.config.marketplace_status === 'testing') {\n this.config.sandbox = true;\n }\n delete this.config.marketplace_status;\n\n // Deprecated\n delete this.config.suboptimal;\n delete this.config.text;\n }\n\n }\n\n return okanjo.Product = Product;\n\n})(window);","\"use strict\";\n\n// **********\n// DEPRECATED - USE okanjo.Placement instead!\n// **********\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window) {\n\n const okanjo = window.okanjo;\n\n /**\n * Backwards compatible interface, turning an Ad widget into a placement widget\n * @deprecated\n */\n class Ad extends okanjo.Placement {\n\n constructor(element, options) {\n // Initialize placement w/o loading (we need to jack the config)\n options = options || {};\n const no_init = options.no_init; // hold original no_init flag, if set\n options.no_init = true;\n super(element, options);\n\n okanjo.warn('Ad widget has been deprecated. Use Placement instead (may require configuration changes)', { widget: this });\n\n // Start loading content\n if (!no_init) {\n delete this.config.no_init;\n this.init();\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Converts the old product widget configuration into a usable placement configuration\n */\n _setCompatibilityOptions() {\n // Convert the product config to a placement configuration\n this.config.backwards = 'Ad';\n this.config.type = okanjo.Placement.ContentTypes.products;\n\n // Id / single mode is now ids\n this.config.url = null;\n if (this.config.id) {\n this.config.ids = [this.config.id];\n } else {\n okanjo.warn('Ad widget should have parameter `id` set.');\n }\n this.config.take = 1;\n delete this.config.id;\n\n // Content is automatically determined whether the placement element contains children\n delete this.config.content;\n }\n\n }\n\n return okanjo.Ad = Ad;\n\n})(window);","/* jshint ignore:start */\n\n(function() {\n\n/*!\n * mustache.js - Logic-less {{mustache}} templates with JavaScript\n * http://github.com/janl/mustache.js\n */\n\n/*global define: false Mustache: true*/\n\n(function defineMustache (global, factory) {\n if (typeof exports === 'object' && exports && typeof exports.nodeName !== 'string') {\n factory(exports); // CommonJS\n } else if (typeof define === 'function' && define.amd) {\n define(['exports'], factory); // AMD\n } else {\n global.Mustache = {};\n factory(global.Mustache); // script, wsh, asp\n }\n}(this, function mustacheFactory (mustache) {\n\n var objectToString = Object.prototype.toString;\n var isArray = Array.isArray || function isArrayPolyfill (object) {\n return objectToString.call(object) === '[object Array]';\n };\n\n function isFunction (object) {\n return typeof object === 'function';\n }\n\n /**\n * More correct typeof string handling array\n * which normally returns typeof 'object'\n */\n function typeStr (obj) {\n return isArray(obj) ? 'array' : typeof obj;\n }\n\n function escapeRegExp (string) {\n return string.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, '\\\\$&');\n }\n\n /**\n * Null safe way of checking whether or not an object,\n * including its prototype, has a given property\n */\n function hasProperty (obj, propName) {\n return obj != null && typeof obj === 'object' && (propName in obj);\n }\n\n // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577\n // See https://github.com/janl/mustache.js/issues/189\n var regExpTest = RegExp.prototype.test;\n function testRegExp (re, string) {\n return regExpTest.call(re, string);\n }\n\n var nonSpaceRe = /\\S/;\n function isWhitespace (string) {\n return !testRegExp(nonSpaceRe, string);\n }\n\n var entityMap = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n '/': '/',\n '`': '`',\n '=': '='\n };\n\n function escapeHtml (string) {\n return String(string).replace(/[&<>\"'`=\\/]/g, function fromEntityMap (s) {\n return entityMap[s];\n });\n }\n\n var whiteRe = /\\s*/;\n var spaceRe = /\\s+/;\n var equalsRe = /\\s*=/;\n var curlyRe = /\\s*\\}/;\n var tagRe = /#|\\^|\\/|>|\\{|&|=|!/;\n\n /**\n * Breaks up the given `template` string into a tree of tokens. If the `tags`\n * argument is given here it must be an array with two string values: the\n * opening and closing tags used in the template (e.g. [ \"<%\", \"%>\" ]). Of\n * course, the default is to use mustaches (i.e. mustache.tags).\n *\n * A token is an array with at least 4 elements. The first element is the\n * mustache symbol that was used inside the tag, e.g. \"#\" or \"&\". If the tag\n * did not contain a symbol (i.e. {{myValue}}) this element is \"name\". For\n * all text that appears outside a symbol this element is \"text\".\n *\n * The second element of a token is its \"value\". For mustache tags this is\n * whatever else was inside the tag besides the opening symbol. For text tokens\n * this is the text itself.\n *\n * The third and fourth elements of the token are the start and end indices,\n * respectively, of the token in the original template.\n *\n * Tokens that are the root node of a subtree contain two more elements: 1) an\n * array of tokens in the subtree and 2) the index in the original template at\n * which the closing tag for that section begins.\n */\n function parseTemplate (template, tags) {\n if (!template)\n return [];\n\n var sections = []; // Stack to hold section tokens\n var tokens = []; // Buffer to hold the tokens\n var spaces = []; // Indices of whitespace tokens on the current line\n var hasTag = false; // Is there a {{tag}} on the current line?\n var nonSpace = false; // Is there a non-space char on the current line?\n\n // Strips all whitespace tokens array for the current line\n // if there was a {{#tag}} on it and otherwise only space.\n function stripSpace () {\n if (hasTag && !nonSpace) {\n while (spaces.length)\n delete tokens[spaces.pop()];\n } else {\n spaces = [];\n }\n\n hasTag = false;\n nonSpace = false;\n }\n\n var openingTagRe, closingTagRe, closingCurlyRe;\n function compileTags (tagsToCompile) {\n if (typeof tagsToCompile === 'string')\n tagsToCompile = tagsToCompile.split(spaceRe, 2);\n\n if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)\n throw new Error('Invalid tags: ' + tagsToCompile);\n\n openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\\\s*');\n closingTagRe = new RegExp('\\\\s*' + escapeRegExp(tagsToCompile[1]));\n closingCurlyRe = new RegExp('\\\\s*' + escapeRegExp('}' + tagsToCompile[1]));\n }\n\n compileTags(tags || mustache.tags);\n\n var scanner = new Scanner(template);\n\n var start, type, value, chr, token, openSection;\n while (!scanner.eos()) {\n start = scanner.pos;\n\n // Match any text between tags.\n value = scanner.scanUntil(openingTagRe);\n\n if (value) {\n for (var i = 0, valueLength = value.length; i < valueLength; ++i) {\n chr = value.charAt(i);\n\n if (isWhitespace(chr)) {\n spaces.push(tokens.length);\n } else {\n nonSpace = true;\n }\n\n tokens.push([ 'text', chr, start, start + 1 ]);\n start += 1;\n\n // Check for whitespace on the current line.\n if (chr === '\\n')\n stripSpace();\n }\n }\n\n // Match the opening tag.\n if (!scanner.scan(openingTagRe))\n break;\n\n hasTag = true;\n\n // Get the tag type.\n type = scanner.scan(tagRe) || 'name';\n scanner.scan(whiteRe);\n\n // Get the tag value.\n if (type === '=') {\n value = scanner.scanUntil(equalsRe);\n scanner.scan(equalsRe);\n scanner.scanUntil(closingTagRe);\n } else if (type === '{') {\n value = scanner.scanUntil(closingCurlyRe);\n scanner.scan(curlyRe);\n scanner.scanUntil(closingTagRe);\n type = '&';\n } else {\n value = scanner.scanUntil(closingTagRe);\n }\n\n // Match the closing tag.\n if (!scanner.scan(closingTagRe))\n throw new Error('Unclosed tag at ' + scanner.pos);\n\n token = [ type, value, start, scanner.pos ];\n tokens.push(token);\n\n if (type === '#' || type === '^') {\n sections.push(token);\n } else if (type === '/') {\n // Check section nesting.\n openSection = sections.pop();\n\n if (!openSection)\n throw new Error('Unopened section \"' + value + '\" at ' + start);\n\n if (openSection[1] !== value)\n throw new Error('Unclosed section \"' + openSection[1] + '\" at ' + start);\n } else if (type === 'name' || type === '{' || type === '&') {\n nonSpace = true;\n } else if (type === '=') {\n // Set the tags for the next time around.\n compileTags(value);\n }\n }\n\n // Make sure there are no open sections when we're done.\n openSection = sections.pop();\n\n if (openSection)\n throw new Error('Unclosed section \"' + openSection[1] + '\" at ' + scanner.pos);\n\n return nestTokens(squashTokens(tokens));\n }\n\n /**\n * Combines the values of consecutive text tokens in the given `tokens` array\n * to a single token.\n */\n function squashTokens (tokens) {\n var squashedTokens = [];\n\n var token, lastToken;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n token = tokens[i];\n\n if (token) {\n if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {\n lastToken[1] += token[1];\n lastToken[3] = token[3];\n } else {\n squashedTokens.push(token);\n lastToken = token;\n }\n }\n }\n\n return squashedTokens;\n }\n\n /**\n * Forms the given array of `tokens` into a nested tree structure where\n * tokens that represent a section have two additional items: 1) an array of\n * all tokens that appear in that section and 2) the index in the original\n * template that represents the end of that section.\n */\n function nestTokens (tokens) {\n var nestedTokens = [];\n var collector = nestedTokens;\n var sections = [];\n\n var token, section;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n token = tokens[i];\n\n switch (token[0]) {\n case '#':\n case '^':\n collector.push(token);\n sections.push(token);\n collector = token[4] = [];\n break;\n case '/':\n section = sections.pop();\n section[5] = token[2];\n collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;\n break;\n default:\n collector.push(token);\n }\n }\n\n return nestedTokens;\n }\n\n /**\n * A simple string scanner that is used by the template parser to find\n * tokens in template strings.\n */\n function Scanner (string) {\n this.string = string;\n this.tail = string;\n this.pos = 0;\n }\n\n /**\n * Returns `true` if the tail is empty (end of string).\n */\n Scanner.prototype.eos = function eos () {\n return this.tail === '';\n };\n\n /**\n * Tries to match the given regular expression at the current position.\n * Returns the matched text if it can match, the empty string otherwise.\n */\n Scanner.prototype.scan = function scan (re) {\n var match = this.tail.match(re);\n\n if (!match || match.index !== 0)\n return '';\n\n var string = match[0];\n\n this.tail = this.tail.substring(string.length);\n this.pos += string.length;\n\n return string;\n };\n\n /**\n * Skips all text until the given regular expression can be matched. Returns\n * the skipped string, which is the entire tail if no match can be made.\n */\n Scanner.prototype.scanUntil = function scanUntil (re) {\n var index = this.tail.search(re), match;\n\n switch (index) {\n case -1:\n match = this.tail;\n this.tail = '';\n break;\n case 0:\n match = '';\n break;\n default:\n match = this.tail.substring(0, index);\n this.tail = this.tail.substring(index);\n }\n\n this.pos += match.length;\n\n return match;\n };\n\n /**\n * Represents a rendering context by wrapping a view object and\n * maintaining a reference to the parent context.\n */\n function Context (view, parentContext) {\n this.view = view;\n this.cache = { '.': this.view };\n this.parent = parentContext;\n }\n\n /**\n * Creates a new context using the given view with this context\n * as the parent.\n */\n Context.prototype.push = function push (view) {\n return new Context(view, this);\n };\n\n /**\n * Returns the value of the given name in this context, traversing\n * up the context hierarchy if the value is absent in this context's view.\n */\n Context.prototype.lookup = function lookup (name) {\n var cache = this.cache;\n\n var value;\n if (cache.hasOwnProperty(name)) {\n value = cache[name];\n } else {\n var context = this, names, index, lookupHit = false;\n\n while (context) {\n if (name.indexOf('.') > 0) {\n value = context.view;\n names = name.split('.');\n index = 0;\n\n /**\n * Using the dot notion path in `name`, we descend through the\n * nested objects.\n *\n * To be certain that the lookup has been successful, we have to\n * check if the last object in the path actually has the property\n * we are looking for. We store the result in `lookupHit`.\n *\n * This is specially necessary for when the value has been set to\n * `undefined` and we want to avoid looking up parent contexts.\n **/\n while (value != null && index < names.length) {\n if (index === names.length - 1)\n lookupHit = hasProperty(value, names[index]);\n\n value = value[names[index++]];\n }\n } else {\n value = context.view[name];\n lookupHit = hasProperty(context.view, name);\n }\n\n if (lookupHit)\n break;\n\n context = context.parent;\n }\n\n cache[name] = value;\n }\n\n if (isFunction(value))\n value = value.call(this.view);\n\n return value;\n };\n\n /**\n * A Writer knows how to take a stream of tokens and render them to a\n * string, given a context. It also maintains a cache of templates to\n * avoid the need to parse the same template twice.\n */\n function Writer () {\n this.cache = {};\n }\n\n /**\n * Clears all cached templates in this writer.\n */\n Writer.prototype.clearCache = function clearCache () {\n this.cache = {};\n };\n\n /**\n * Parses and caches the given `template` and returns the array of tokens\n * that is generated from the parse.\n */\n Writer.prototype.parse = function parse (template, tags) {\n var cache = this.cache;\n var tokens = cache[template];\n\n if (tokens == null)\n tokens = cache[template] = parseTemplate(template, tags);\n\n return tokens;\n };\n\n /**\n * High-level method that is used to render the given `template` with\n * the given `view`.\n *\n * The optional `partials` argument may be an object that contains the\n * names and templates of partials that are used in the template. It may\n * also be a function that is used to load partial templates on the fly\n * that takes a single argument: the name of the partial.\n */\n Writer.prototype.render = function render (template, view, partials) {\n var tokens = this.parse(template);\n var context = (view instanceof Context) ? view : new Context(view);\n return this.renderTokens(tokens, context, partials, template);\n };\n\n /**\n * Low-level method that renders the given array of `tokens` using\n * the given `context` and `partials`.\n *\n * Note: The `originalTemplate` is only ever used to extract the portion\n * of the original template that was contained in a higher-order section.\n * If the template doesn't use higher-order sections, this argument may\n * be omitted.\n */\n Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate) {\n var buffer = '';\n\n var token, symbol, value;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n value = undefined;\n token = tokens[i];\n symbol = token[0];\n\n if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);\n else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);\n else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);\n else if (symbol === '&') value = this.unescapedValue(token, context);\n else if (symbol === 'name') value = this.escapedValue(token, context);\n else if (symbol === 'text') value = this.rawValue(token);\n\n if (value !== undefined)\n buffer += value;\n }\n\n return buffer;\n };\n\n Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate) {\n var self = this;\n var buffer = '';\n var value = context.lookup(token[1]);\n\n // This function is used to render an arbitrary template\n // in the current context by higher-order sections.\n function subRender (template) {\n return self.render(template, context, partials);\n }\n\n if (!value) return;\n\n if (isArray(value)) {\n for (var j = 0, valueLength = value.length; j < valueLength; ++j) {\n buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);\n }\n } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') {\n buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);\n } else if (isFunction(value)) {\n if (typeof originalTemplate !== 'string')\n throw new Error('Cannot use higher-order sections without the original template');\n\n // Extract the portion of the original template that the section contains.\n value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);\n\n if (value != null)\n buffer += value;\n } else {\n buffer += this.renderTokens(token[4], context, partials, originalTemplate);\n }\n return buffer;\n };\n\n Writer.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate) {\n var value = context.lookup(token[1]);\n\n // Use JavaScript's definition of falsy. Include empty arrays.\n // See https://github.com/janl/mustache.js/issues/186\n if (!value || (isArray(value) && value.length === 0))\n return this.renderTokens(token[4], context, partials, originalTemplate);\n };\n\n Writer.prototype.renderPartial = function renderPartial (token, context, partials) {\n if (!partials) return;\n\n var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];\n if (value != null)\n return this.renderTokens(this.parse(value), context, partials, value);\n };\n\n Writer.prototype.unescapedValue = function unescapedValue (token, context) {\n var value = context.lookup(token[1]);\n if (value != null)\n return value;\n };\n\n Writer.prototype.escapedValue = function escapedValue (token, context) {\n var value = context.lookup(token[1]);\n if (value != null)\n return mustache.escape(value);\n };\n\n Writer.prototype.rawValue = function rawValue (token) {\n return token[1];\n };\n\n mustache.name = 'mustache.js';\n mustache.version = '2.3.2';\n mustache.tags = [ '{{', '}}' ];\n\n // All high-level mustache.* functions use this writer.\n var defaultWriter = new Writer();\n\n /**\n * Clears all cached templates in the default writer.\n */\n mustache.clearCache = function clearCache () {\n return defaultWriter.clearCache();\n };\n\n /**\n * Parses and caches the given template in the default writer and returns the\n * array of tokens it contains. Doing this ahead of time avoids the need to\n * parse templates on the fly as they are rendered.\n */\n mustache.parse = function parse (template, tags) {\n return defaultWriter.parse(template, tags);\n };\n\n /**\n * Renders the `template` with the given `view` and `partials` using the\n * default writer.\n */\n mustache.render = function render (template, view, partials) {\n if (typeof template !== 'string') {\n throw new TypeError('Invalid template! Template should be a \"string\" ' +\n 'but \"' + typeStr(template) + '\" was given as the first ' +\n 'argument for mustache#render(template, view, partials)');\n }\n\n return defaultWriter.render(template, view, partials);\n };\n\n // This is here for backwards compatibility with 0.4.x.,\n /*eslint-disable */ // eslint wants camel cased function name\n mustache.to_html = function to_html (template, view, partials, send) {\n /*eslint-enable*/\n\n var result = mustache.render(template, view, partials);\n\n if (isFunction(send)) {\n send(result);\n } else {\n return result;\n }\n };\n\n // Export the escaping function so that the user may override it.\n // See https://github.com/janl/mustache.js/issues/244\n mustache.escape = escapeHtml;\n\n // Export these mainly for testing, but also for advanced usage.\n mustache.Scanner = Scanner;\n mustache.Context = Context;\n mustache.Writer = Writer;\n\n return mustache;\n}));\n\n\n}).apply(okanjo.lib);\n\n/* jshint ignore:end */"],"sourceRoot":"./"} \ No newline at end of file +{"version":3,"sources":["okanjo.js","Array.from.js","Array.prototype.find.js","Array.prototype.findIndex.js","Array.prototype.includes.js","NodeList.prototype.forEach.js","Object.Assign.js","Okanjo.js","Request.js","Cookie.js","TemplateEngine.js","Modal.js","Metrics.js","AutoPageView.js","EventEmitter.js","Widget.js","Placement.js","Product.js","Ad.js","vendor.js"],"names":["root","factory","define","amd","exports","module","okanjo","this","_possibleConstructorReturn","isCallable","self","ReferenceError","call","_inherits","subClass","superClass","TypeError","prototype","Object","create","constructor","value","enumerable","writable","configurable","setPrototypeOf","__proto__","_classCallCheck","Number","instance","Constructor","_createClass","defineProperties","target","props","i","length","descriptor","defineProperty","key","protoProps","staticProps","Array","Symbol","iterator","obj","from","number","toStr","toString","fn","Math","maxSafeInteger","toLength","len","toInteger","isFinite","floor","abs","pow","items","arrayLike","min","max","C","mapFn","T","arguments","A","kValue","k","find","predicate","o","thisArg","findIndex","includes","searchElement","fromIndex","sameValueZero","x","y","isNaN","n","window","NodeList","forEach","callback","assign","varArgs","nextSource","to","index","nextKey","hasOwnProperty","NOOP","document","SUPPORTS_PAGE_OFFSET","undefined","pageXOffset","CSS1_COMPATIBLE","compatMode","AGENT","navigator","userAgent","ELLIPSIFY_PATTERN","MOBILE_PATTERN","Console","console","settings","metrics","report","_len","args","_key","err","Error","messageIndex","arg","stack","split","shift","push","reportStack","join","filter","a","splice","error","version","warn","apply","concat","message","_len2","_key2","selector","parent","qwery","querySelector","querySelectorAll","net","endpoint","sandboxEndpoint","routes","ads","getRoute","route","params","env","request","keys","replace","util","isEmpty","test","val","trim","getPageArguments","query","eqIndex","includeHashArguments","decodeURIComponent","parts","part","indexOf","queryArgs","hashArgs","substring","location","search","hash","mixed","out","map","deepClone","_typeof","options","output","input","isArray","toISOString","childObject","childKey","ignoreArrays","arrayToCsv","flatten","shortid","clusterWorkerId","shuffled","crypto","msCrypto","require","getRandomValues","randomBytes","encode","loopCounter","random","dest","Uint8Array","str","done","randomByte","REDUCE_TIME","seconds","counter","previousSeconds","Date","getTime","getLocation","referrer","href","ui","getScrollPosition","documentElement","scrollLeft","body","getElementSize","element","scrollTop","includeMargin","size","height","offsetHeight","width","offsetWidth","style","currentStyle","getComputedStyle","parseInt","marginTop","marginBottom","getPageSize","marginLeft","marginRight","html","getViewportSize","scrollWidth","clientWidth","clientHeight","scrollHeight","vh","isMobileZoom","inWidth","innerWidth","inHeight","innerHeight","getEventPosition","ex","et","event","ey","el","type","name","getElementPosition","clientX","clientY","rect","getBoundingClientRect","y2","x1","left","contains","y1","x2","top","right","bottom","e","exception","elementArea","iLeft","s","iRight","v","vw","iTop","iBottom","intersectionArea","isElementVisible","getPercentageInViewport","_okanjo$ui$_getInters","_getIntersection","replacedText","container","substr","parentNode","targetHeight","useTextContent","textContent","text","innerText","safety","replacer","match","span","createElement","content","setAttribute","innerHTML","fitImages","appendChild","backgroundImage","src","img","display","backgroundposition","method","url","payload","res","ActiveXObject","calledBack","req","timeout","ontimeout","attributes","statusCode","onreadystatechange","status","data","JSON_TEST","getResponseHeader","parse","responseText","xhr","toUpperCase","open","withCredentials","setRequestHeader","post","send","get","bind","encodeURIComponent","getKey","keyPrefix","stringify","pairs","expireDate","setDate","set","cookieName","expireDays","getDate","expires","toUTCString","path","secure","protocol","cookieValue","cookie","nameTest","decodeURI","TemplateEngine","_templates","_css","classDetects","template","beforeRender","nodeType","lib","Mustache","markup","css","head","id","styleSheet","cssText","templateName","context","model","_this","okanjoMetricUrl","now","blockClasses","ensureCss","render","formatCurrency","decimals","decimalSeparator","toFixed","j","thousandsSeparator","slice","engine","$modalContainer","$modalWindow","isMobile","$modalOuter","$html","$body","$modalSkin","$modalInner","$modalClose","$modalFrame","addListener","addEventListener","attachEvent","getWindowHeight","handler","setTimeout","handleReposition","t","closeModal","stopPropagation","preventDefault","removeClass","addClass","className","RegExp","openModal","IS_MOBILE","setContent","initialized","show","createElements","bindEvents","modal","hide","Metrics","sourceCh","_getStoredQueue","sourceCx","pageId","defaultChannel","Channel","external","sid","_checkUrlForReferral","queue","Params","JSON","localStorage","delay","_this2","_saveQueueTimeout","clearTimeout","_saveQueue","_queue","object_type","metric_session","event_type","Event","correlation","urlSid","_noProcess","sourceChannel","pageArgs","channel","localSid","trackEvent","sourceContext","ch","_push","page","view","_processQueue","_this3","_processTimeout","_batchSend","_updateSid","item","_this4","events","win","metrics_batch","m","exclude","Meta","ok_ver","pgid","ref","ttl","_len3","_key3","pw","w","ph","h","containerSize","resources","wix2","wiy2","boxes","getMin","getMax","wix1","fallback","current","wiy1","_fallback","wrps","vp","pos","vx1","vy1","vx2","vy2","jsEvent","_len4","_key4","_len5","_key5","MetricEvent","impression","interaction","Action","click","inline_click","article","thirdparty_ad","cart","order","order_item","user","widget","product","store","cause","marketplace","placement","live","testing","store_widget","Environment","others","_this5","_data","addEventInfo","addViewportInfo","_element","addElementInfo","addWidgetInfo","_len6","_key6","addEventMeta","_normalizeEvent","trackPageView","EventEmitter","_events","listener","idx","listeners","_arguments","_this6","removeListener","_EventEmitter","on","DATA_REPLACE_PATTERN","Widget","DATA_ATTRIBUTE_PATTERN","getPrototypeOf","_this7","instanceId","config","_applyConfiguration","_setCompatibilityOptions","_ensurePlacementKey","load","_this8","normalizedKey","_default","_this9","group","origKey","getGroup","showError","setMarkup","attr","exec","Field","_convert","_strip","_group","converter","toLowerCase","parseFloat","strip","bool","int","float","FILTERS","_Widget","DISPLAY","string","ARTICLE_META","array","_okanjo$_Widget$Field","MINIMUM_VIEW_PX","MINIMUM_VIEW_TIME","Placement","MINIMUM_VIEW_FREQ","_metricBase","_viewedWatchers","_this10","_response","_viewWatcherIv","no_init","init","_okanjo$_Widget","q","url_referrer","not_url_paths","organization_id","organization_name","property_name","store_name","external_id","sku","external_store_id","condition","manufacturer","upc","tags","category","min_price","max_price","isbn","max_donation_percent","pools","sort_by","min_donation_percent","skip","donation_to","template_theme","template_variant","template_cta_color","url_category","url_keywords","no_css","proxy_url","disable_popup","backwards","expandable","disable_inline_buy","_this11","isBackfill","getSettings","filters","backfill","shortfill","article_meta","backfillPattern","shortfillPattern","matches","isShortfill","_this12","_setMetricBase","_fetchContent","_reportWidgetLoad","_mergeResponseSettings","_updateBaseMetaFromResponse","_showContent","base","cx","wgid","_this13","res_type","decl","declined","res_bf","backfilled","res_sf","shortfilled","_addOnceViewedHandler","res_length","results","meta","getConfig","viewport","emit","sandbox","_this14","_this15","ptseed","pten","aid","enabled","ptid","seed","msg","ContentTypes","products","articles","adx","_showADX","additionalUrlParams","joiner","ok_msid","_okjr","utm_source","utm_campaign","u","toUrl","bf","sf","resource","clickId","_cid","urlParam","cid","trackParam","spltfl_seg","splitfill_segment","currentTarget","ok_cid","ea","_event","additionalParams","_getClickThroughURL","_clickId","_additionalParams","contentType","defaultName","template_name","isTemplateRegistered","template_layout","template_cta_style","brandColor","brandCSS","brandCSSId","registerCss","controller","successfulCount","_toggleViewWatcher","setInterval","_checkViewWatchers","clearInterval","inline_buy_url","_getTemplate","DefaultTemplates","offer","_price_formatted","price","_index","_escaped_inline_buy_url","image_urls","_escaped_buy_url","buy_url","getAttribute","_this16","_handleResourceMouseDown","_handleProductClick","ellipsify","showNativeBuyUx","showPopupNativeBuyUx","popup","_popupFrame","vspace","allowfullscreen","frame","class","hspace","webkitallowfullscreen","mozallowfullscreen","scrolling","frame_height","ad_size","_escaped_url","_this17","_handleArticleClick","_this18","Sizes","default","adUnitPath","adx_unit_path","declineReason","renderContext","frameborder","ta_w","ta_h","ta_s","contentWindow","write","clickUrl","close","button_2","rectangle","super_leaderboard","wide_skyscraper","half_page","billboard","micro_bar","button_1","full_banner","half_banner","large_rectangle","skyscraper","square","vertical_rectangle","three_to_one_rectangle","square_button","vertical_banner","medium_rectangle","Product","_okanjo$Placement","_this19","ids","mode","take","sold_by","url_selectors","marketplace_id","selectors","marketplace_status","property_id","suboptimal","Ad","_okanjo$Placement2","_this20","global","objectToString","nodeName","isFunction","object","mustache","typeStr","escapeRegExp","hasProperty","propName","nonSpaceRe","testRegExp","re","regExpTest","isWhitespace","tagRe","String","entityMap","parseTemplate","nonSpace","hasTag","spaces","closingTagRe","closingCurlyRe","openingTagRe","compileTags","tagsToCompile","spaceRe","start","scanner","stripSpace","sections","tokens","chr","token","openSection","valueLength","scanUntil","charAt","equalsRe","scan","curlyRe","pop","squashedTokens","lastToken","numTokens","nestedTokens","nestTokens","section","collector","Scanner","tail","Context","parentContext","cache",".","Writer","&","escapeHtml","<",">","\"","'","/","whiteRe","eos","lookupHit","names","partials","renderTokens","originalTemplate","symbol","buffer","renderSection","renderInverted","renderPartial","unescapedValue","escapedValue","rawValue","subRender","lookup","escape","clearCache","defaultWriter","to_html","result"],"mappings":"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","file":"okanjo.min.js","sourcesContent":["/*! okanjo-js v1.20.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */\n(function(root, factory) {\n if (typeof define === 'function' && define.amd) {\n define([], factory);\n } else if (typeof exports === 'object') {\n module.exports = factory();\n } else {\n root.okanjo = factory();\n }\n}(this, function() {\nvar _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if (\"value\" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }();\n\nvar _typeof = typeof Symbol === \"function\" && typeof Symbol.iterator === \"symbol\" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === \"function\" && obj.constructor === Symbol && obj !== Symbol.prototype ? \"symbol\" : typeof obj; };\n\nfunction _possibleConstructorReturn(self, call) { if (!self) { throw new ReferenceError(\"this hasn't been initialised - super() hasn't been called\"); } return call && (typeof call === \"object\" || typeof call === \"function\") ? call : self; }\n\nfunction _inherits(subClass, superClass) { if (typeof superClass !== \"function\" && superClass !== null) { throw new TypeError(\"Super expression must either be null or a function, not \" + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) Object.setPrototypeOf ? Object.setPrototypeOf(subClass, superClass) : subClass.__proto__ = superClass; }\n\nfunction _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError(\"Cannot call a class as a function\"); } }\n\n// Production steps of ECMA-262, Edition 6, 22.1.2.1\nif (!Array.from) {\n Array.from = function () {\n var toStr = Object.prototype.toString;\n var isCallable = function isCallable(fn) {\n return typeof fn === 'function' || toStr.call(fn) === '[object Function]';\n };\n var toInteger = function toInteger(value) {\n var number = Number(value);\n if (isNaN(number)) {\n return 0;\n }\n if (number === 0 || !isFinite(number)) {\n return number;\n }\n return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));\n };\n var maxSafeInteger = Math.pow(2, 53) - 1;\n var toLength = function toLength(value) {\n var len = toInteger(value);\n return Math.min(Math.max(len, 0), maxSafeInteger);\n };\n\n // The length property of the from method is 1.\n return function from(arrayLike /*, mapFn, thisArg */) {\n // 1. Let C be the this value.\n var C = this;\n\n // 2. Let items be ToObject(arrayLike).\n var items = Object(arrayLike);\n\n // 3. ReturnIfAbrupt(items).\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object - not null or undefined');\n }\n\n // 4. If mapfn is undefined, then let mapping be false.\n var mapFn = arguments.length > 1 ? arguments[1] : void undefined;\n var T;\n if (typeof mapFn !== 'undefined') {\n // 5. else\n // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.\n if (!isCallable(mapFn)) {\n throw new TypeError('Array.from: when provided, the second argument must be a function');\n }\n\n // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.\n if (arguments.length > 2) {\n T = arguments[2];\n }\n }\n\n // 10. Let lenValue be Get(items, \"length\").\n // 11. Let len be ToLength(lenValue).\n var len = toLength(items.length);\n\n // 13. If IsConstructor(C) is true, then\n // 13. a. Let A be the result of calling the [[Construct]] internal method\n // of C with an argument list containing the single item len.\n // 14. a. Else, Let A be ArrayCreate(len).\n var A = isCallable(C) ? Object(new C(len)) : new Array(len);\n\n // 16. Let k be 0.\n var k = 0;\n // 17. Repeat, while k < len… (also steps a - h)\n var kValue;\n while (k < len) {\n kValue = items[k];\n if (mapFn) {\n A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);\n } else {\n A[k] = kValue;\n }\n k += 1;\n }\n // 18. Let putStatus be Put(A, \"length\", len, true).\n A.length = len;\n // 20. Return A.\n return A;\n };\n }();\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.find\nif (!Array.prototype.find) {\n Object.defineProperty(Array.prototype, 'find', {\n value: function value(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return kValue.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return kValue;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return undefined.\n return undefined;\n }\n });\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex\nif (!Array.prototype.findIndex) {\n Object.defineProperty(Array.prototype, 'findIndex', {\n value: function value(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return k.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return k;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return -1.\n return -1;\n }\n });\n}\n// https://tc39.github.io/ecma262/#sec-array.prototype.includes\nif (!Array.prototype.includes) {\n Object.defineProperty(Array.prototype, 'includes', {\n value: function value(searchElement, fromIndex) {\n\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n // 1. Let O be ? ToObject(this value).\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If len is 0, return false.\n if (len === 0) {\n return false;\n }\n\n // 4. Let n be ? ToInteger(fromIndex).\n // (If fromIndex is undefined, this step produces the value 0.)\n var n = fromIndex | 0;\n\n // 5. If n ≥ 0, then\n // a. Let k be n.\n // 6. Else n < 0,\n // a. Let k be len + n.\n // b. If k < 0, let k be 0.\n var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\n\n function sameValueZero(x, y) {\n return x === y || typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y);\n }\n\n // 7. Repeat, while k < len\n while (k < len) {\n // a. Let elementK be the result of ? Get(O, ! ToString(k)).\n // b. If SameValueZero(searchElement, elementK) is true, return true.\n if (sameValueZero(o[k], searchElement)) {\n return true;\n }\n // c. Increase k by 1.\n k++;\n }\n\n // 8. Return false\n return false;\n }\n });\n}\n// https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach\nif (window.NodeList && !NodeList.prototype.forEach) {\n NodeList.prototype.forEach = function (callback, thisArg) {\n thisArg = thisArg || window;\n for (var i = 0; i < this.length; i++) {\n callback.call(thisArg, this[i], i, this);\n }\n };\n}\n// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\nif (typeof Object.assign != 'function') {\n // Must be writable: true, enumerable: false, configurable: true\n Object.defineProperty(Object, \"assign\", {\n value: function assign(target, varArgs) {\n // .length of function is 2\n 'use strict';\n\n if (target == null) {\n // TypeError if undefined or null\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n var to = Object(target);\n\n for (var index = 1; index < arguments.length; index++) {\n var nextSource = arguments[index];\n\n if (nextSource != null) {\n // Skip over if undefined or null\n for (var nextKey in nextSource) {\n // Avoid bugs when hasOwnProperty is shadowed\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n },\n writable: true,\n configurable: true\n });\n}\n\"use strict\";\n\n/* exported okanjo */\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/**\n * Okanjo widget framework namespace\n * @global okanjo\n */\nvar okanjo = function (window, document) {\n\n //region Constants\n\n // Environment Vars\n var SUPPORTS_PAGE_OFFSET = window.pageXOffset !== undefined;\n var CSS1_COMPATIBLE = (document.compatMode /* istanbul ignore next: out of scope */ || \"\") === \"CSS1Compat\";\n var AGENT = window.navigator.userAgent;\n var ELLIPSIFY_PATTERN = /[\\s\\S](?:\\.\\.\\.)?$/;\n var MOBILE_PATTERN = /(iPhone|iPad|iPod|Android|blackberry)/i;\n var NOOP = function NOOP() {};\n var Console = window.console;\n\n // Place to pull defaults, if already set\n var settings = window.okanjo || {};\n\n //endregion\n\n //region Okanjo Core\n\n\n //noinspection JSValidateJSDoc,JSClosureCompilerSyntax - idk phpStorm generated it so why would it be wrong? :P\n /**\n * Okanjo namespace\n * @global\n * @type {{version: string, metrics: null, key: null, report: ((...p1?:*[])), warn: ((p1?:*, ...p2?:*[])), qwery: ((p1?:*, p2?:*))}}\n */\n var okanjo = {\n\n /**\n * Okanjo version\n */\n version: \"1.20.0\",\n\n /**\n * Placeholder\n */\n metrics: null,\n\n /**\n * Global/default placement key\n */\n key: settings.key || null,\n\n /**\n * Reports an error to the console and possibly Raven in the future\n * @param args\n */\n report: function report() {\n for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {\n args[_key] = arguments[_key];\n }\n\n var err = args.find(function (arg) {\n return arg instanceof Error;\n });\n if (!err) {\n var messageIndex = args.findIndex(function (arg) {\n return typeof arg === \"string\";\n });\n err = new Error(args[messageIndex] || \"Okanjo Error\");\n if (messageIndex >= 0) args.splice(messageIndex, 1);\n } else {\n // Grow our own stack so we can figure out what async thing did it\n var stack = new Error().stack.split('\\n');\n stack.shift();\n stack.shift();\n args.push({ reportStack: stack.join('\\n') });\n args = args.filter(function (a) {\n return a !== err;\n });\n }\n\n Console.error('[Okanjo v' + okanjo.version + ']: ' + err.stack);\n args.length && Console.error.apply(Console, ['Additional information:'].concat(args));\n\n // TODO - integrate with Raven\n },\n\n /**\n * Warn developers of their misdeeds\n * @param message\n * @param args\n */\n warn: function warn(message) {\n for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {\n args[_key2 - 1] = arguments[_key2];\n }\n\n var err = new Error(message);\n\n Console.warn('[Okanjo v' + okanjo.version + ']: ' + err.stack);\n args.length && Console.warn.apply(Console, ['Additional information:'].concat(args));\n },\n\n // Backwards compatibility when we shipped with qwery, cuz querySelector[All] wasn't mainstream enough\n qwery: function qwery(selector, parent) {\n\n // If parent is a selector, select the parent first!\n if (typeof parent === \"string\") {\n parent = document.querySelector(parent);\n\n // If parent is not found, there are obviously no results\n if (!parent) return [];\n }\n\n if (!parent) parent = document;\n\n return parent.querySelectorAll(selector);\n }\n };\n\n //endregion\n\n //region Vendor Libs\n\n /**\n * Placeholder for where vendor libraries get no-conflict loaded\n * @type {{}}\n */\n okanjo.lib = {};\n\n //endregion\n\n //region Networking\n\n /**\n * Networking methods\n * @type {{getRoute: *, exec: *}}\n */\n okanjo.net = {\n\n /**\n * API Endpoints\n */\n endpoint: 'https://api2.okanjo.com',\n sandboxEndpoint: 'https://sandbox-api2.okanjo.com',\n\n /**\n * API routes\n */\n routes: {\n ads: '/content',\n metrics: '/metrics/:object_type/:event_type',\n metrics_batch: '/metrics'\n },\n\n /**\n * Compiles a route and parameters into a final URL\n * @param {string} route - Route constant\n * @param {*} [params] - Key value hash\n * @param {*} [env] - Optional environment to use instead of live\n * @return {string} - Route\n */\n getRoute: function getRoute(route, params, env) {\n if (params) {\n Object.keys(params).forEach(function (key) {\n route = route.replace(':' + key, params[key] + \"\");\n });\n }\n env = env || okanjo.env || 'live';\n return (env === 'sandbox' ? okanjo.net.sandboxEndpoint : okanjo.net.endpoint) + route;\n },\n\n // placeholder, xhr request extension\n request: NOOP\n };\n\n //endregion\n\n // region Utilities\n\n //noinspection JSClosureCompilerSyntax,JSValidateJSDoc\n /**\n * Utility functions and helpers\n * @type {{isEmpty: ((p1?:*)=>boolean), isMobile: (()), getPageArguments: ((p1:boolean))}}\n */\n okanjo.util = {\n\n /**\n * Checks whether a value is _really_ empty (trims)\n * @param val\n * @return {boolean}\n */\n isEmpty: function isEmpty(val) {\n return val === null || val === undefined || typeof val === \"string\" && val.trim().length === 0;\n },\n\n /**\n * Checks if the current user agent identifies as a mobile device\n * @returns {boolean}\n */\n isMobile: function isMobile() {\n // KludgyAF™, but let's go with it\n return MOBILE_PATTERN.test(AGENT);\n },\n\n /**\n * Returns an object hashmap of query and hash parameters\n * @param {boolean} includeHashArguments - Whether to include the hash arguments, if any\n * @return {*}\n */\n getPageArguments: function getPageArguments(includeHashArguments) {\n\n var split = function split(query) {\n query = query || \"\";\n var params = {};\n var parts = query.split('&');\n parts.forEach(function (part) {\n var eqIndex = part.indexOf('=');\n var key = void 0,\n value = void 0;\n if (eqIndex < 0) {\n key = decodeURIComponent(part);\n value = null;\n } else {\n key = decodeURIComponent(part.substring(0, eqIndex));\n value = decodeURIComponent(part.substring(eqIndex + 1));\n }\n if (key) params[key] = value;\n });\n return params;\n };\n\n var queryArgs = split(window.location.search.substring(window.location.search.indexOf('?') + 1));\n var hashArgs = includeHashArguments ? split(window.location.hash.substring(Math.max(window.location.hash.indexOf('#') + 1, window.location.hash.indexOf('#!') + 2))) : {};\n Object.keys(hashArgs).forEach(function (key) {\n return queryArgs[key] = hashArgs[key];\n });\n\n return queryArgs;\n }\n\n };\n\n /**\n * Deep clones an object by breaking references, unlike Object.assign\n * @param mixed – Source to clone (object, array, value)\n * @param [out] - Existing output, if any\n * @return {*}\n */\n okanjo.util.deepClone = function (mixed, out) {\n if (Array.isArray(mixed)) {\n // Array reference\n out = out || [];\n out = out.concat(mixed.map(function (val) {\n return okanjo.util.deepClone(val);\n }));\n } else if ((typeof mixed === 'undefined' ? 'undefined' : _typeof(mixed)) === \"object\" && mixed !== null) {\n // Object reference\n out = out || {};\n Object.keys(mixed).forEach(function (key) {\n out[key] = okanjo.util.deepClone(mixed[key]);\n });\n } else {\n // Value\n out = mixed;\n }\n\n return out;\n };\n\n /**\n * Flattens a multi-dimensional object into a single object\n * @param input\n * @param [options]\n * @return {{}}\n */\n okanjo.util.flatten = function (input) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n var output = {};\n\n if (input !== undefined && input !== null) {\n Object.keys(input).forEach(function (key) {\n // Convert object ids to hex strings\n if (input[key] instanceof Date) {\n if (options.dateToIso) {\n output[key] = input[key].toISOString(); // convert to iso\n } else {\n output[key] = input[key]; // as-is\n }\n } else if (_typeof(input[key]) === 'object' && input[key] !== null) {\n // Allow ignoring arrays if desired\n if (Array.isArray(input[key]) && options.ignoreArrays === true) {\n output[key] = input[key];\n } else if (Array.isArray(input[key]) && options.arrayToCsv === true) {\n output[key] = input[key].join(',');\n } else {\n // Make child objects flat too (always returns object so Object.keys is safe)\n var childObject = okanjo.util.flatten(input[key], options);\n Object.keys(childObject).forEach(function (childKey) {\n output[key + '_' + childKey] = childObject[childKey];\n });\n }\n } else {\n // Copy value references\n output[key] = input[key];\n }\n });\n }\n\n return output;\n };\n\n /*! based on shortid https://github.com/dylang/shortid */\n okanjo.util.shortid = function (clusterWorkerId) {\n\n var shuffled = 'ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC',\n crypto = window.crypto || window.msCrypto || typeof require === \"function\" && require('crypto'),\n randomByte = function randomByte() {\n /* istanbul ignore next: platform diffs out of scope */\n if (crypto && crypto.randomBytes) {\n return crypto.randomBytes(1)[0] & 0x30;\n } else if (!crypto || !crypto.getRandomValues) {\n return Math.floor(Math.random() * 256) & 0x30;\n }\n /* istanbul ignore next: platform diffs out of scope */\n var dest = new Uint8Array(1);\n /* istanbul ignore next: platform diffs out of scope */\n crypto.getRandomValues(dest);\n /* istanbul ignore next: platform diffs out of scope */\n return dest[0] & 0x30;\n },\n encode = function encode(number) {\n var loopCounter = 0,\n done = void 0,\n str = '';\n\n while (!done) {\n str = str + shuffled[number >> 4 * loopCounter & 0x0f | randomByte()];\n done = number < Math.pow(16, loopCounter + 1);\n loopCounter++;\n }\n return str;\n },\n\n\n // Ignore all milliseconds before a certain time to reduce the size of the date entropy without sacrificing uniqueness.\n // This number should be updated every year or so to keep the generated id short.\n // To regenerate `new Date() - 0` and bump the version. Always bump the version!\n\n REDUCE_TIME = 1490384907498,\n version = 7;\n\n var counter = void 0,\n previousSeconds = void 0;\n\n clusterWorkerId = clusterWorkerId || 0;\n\n return function () {\n var str = '',\n seconds = Math.floor((new Date().getTime() - REDUCE_TIME) * 0.001);\n\n if (seconds === previousSeconds) {\n counter++;\n } else {\n counter = 0;\n previousSeconds = seconds;\n }\n\n str = str + encode(version) + encode(clusterWorkerId);\n if (counter > 0) {\n str = str + encode(counter);\n }\n str = str + encode(seconds);\n\n return str;\n };\n }();\n\n /**\n * Gets the best URL for where we are operating\n * @returns {string|*}\n */\n okanjo.util.getLocation = function () {\n return window.location !== window.parent.location ? /* istanbul ignore next: oos */document.referrer : document.location.href;\n };\n\n //endregion\n\n //region User Interface\n\n okanjo.ui = {\n\n /**\n * Gets the current page scroll position\n * @returns {{x: Number, y: Number}}\n */\n getScrollPosition: function getScrollPosition() {\n return {\n x: SUPPORTS_PAGE_OFFSET ? window.pageXOffset : /* istanbul ignore next: old browsers */CSS1_COMPATIBLE ? document.documentElement.scrollLeft : document.body.scrollLeft,\n y: SUPPORTS_PAGE_OFFSET ? window.pageYOffset : /* istanbul ignore next: old browsers */CSS1_COMPATIBLE ? document.documentElement.scrollTop : document.body.scrollTop\n };\n },\n\n /**\n * Gets the height and width of the given element\n * @param {HTMLElement|Node} element – The DOM element to get the size of\n * @param {boolean} [includeMargin] – Whether to include the margins of the element in the size\n * @returns {{height: number, width: number}}\n */\n getElementSize: function getElementSize(element, includeMargin) {\n var size = {\n height: element.offsetHeight,\n width: element.offsetWidth\n };\n var style = element.currentStyle || window.getComputedStyle(element);\n\n if (includeMargin) {\n size.height += parseInt(style.marginTop) + parseInt(style.marginBottom);\n size.width += parseInt(style.marginLeft) + parseInt(style.marginRight);\n }\n\n return size;\n },\n\n /**\n * Gets the current page size\n * @return {{w: number, h: number}}\n */\n getPageSize: function getPageSize() {\n var body = document.querySelector('body');\n var html = document.documentElement;\n\n return {\n w: Math.max(body.scrollWidth, body.offsetWidth, html.clientWidth, html.scrollWidth, html.offsetWidth),\n\n h: Math.max(body.scrollHeight, body.offsetHeight, html.clientHeight, html.scrollHeight, html.offsetHeight)\n };\n },\n\n /**\n * Gets the current viewport size\n * @return {{vw: number, vh: number}}\n */\n getViewportSize: function getViewportSize() {\n var element = CSS1_COMPATIBLE ? document.documentElement /* istanbul ignore next: browser diffs */ : document.body;\n var width = element.clientWidth;\n var height = element.clientHeight;\n var inWidth = window.innerWidth /* istanbul ignore next: browser diffs */ || 0;\n var inHeight = window.innerHeight /* istanbul ignore next: browser diffs */ || 0;\n var isMobileZoom = inWidth && width > inWidth || inHeight && height > inHeight;\n\n return {\n vw: isMobileZoom /* istanbul ignore next: browser diffs */ ? inWidth : width,\n vh: isMobileZoom /* istanbul ignore next: browser diffs */ ? inHeight : height\n };\n },\n\n /**\n * Gets the x, y location of the event relative to the page\n * @param event – Mouse/Touch Event\n * @return {{ex: number, ey: number}}\n */\n getEventPosition: function getEventPosition(event) {\n var ex = event.pageX;\n var ey = event.pageY;\n var body = document.body;\n var el = document.documentElement;\n var scrollLeft = 'scrollLeft';\n var scrollTop = 'scrollTop';\n var type = event.__proto__.constructor.name;\n\n return {\n et: type, // mouse? touch? keyboard? robot?\n ex: ex === undefined /* istanbul ignore next: browser diffs */ ? event.clientX + body[scrollLeft] + el[scrollLeft] : ex,\n ey: ey === undefined /* istanbul ignore next: browser diffs */ ? event.clientY + body[scrollTop] + el[scrollTop] : ey\n };\n },\n\n /**\n * Gets the element's rectangle coordinates on the page\n * @param element\n * @return {{x1: number, y1: number, x2: number, y2: number}}\n */\n getElementPosition: function getElementPosition(element) {\n\n // Wrapped in try-catch because IE is super strict about the\n // element being on the DOM before you call this. Other browsers\n // let it slide, but oh well.\n\n var err = 'Could not get position of element. Did you attach the element to the DOM before initializing?';\n try {\n var rect = element.getBoundingClientRect();\n var body = document.body.getBoundingClientRect();\n // let pos = okanjo.ui.getScrollPosition();\n\n /* istanbul ignore else: jsdom doesn't mock this */\n if (!document.body.contains(element)) {\n okanjo.report(err, element);\n }\n return {\n // x1: rect.left + pos.x,\n // y1: rect.top + pos.y,\n // x2: rect.right + pos.x,\n // y2: rect.bottom + pos.y\n\n // This might fix\n x1: rect.left - body.left,\n y1: rect.top - body.top,\n x2: rect.right - body.left,\n y2: rect.bottom - body.top\n\n };\n } catch (e) {\n okanjo.report(err, { exception: e, element: element });\n return {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: 0,\n err: 1\n };\n }\n },\n\n /**\n * Gets the intersection information given the element, viewport and scroll positions\n * @param e – Element position\n * @param s - Scroll position\n * @param v - Viewport size\n * @return {{intersectionArea: number, elementArea: number}}\n * @private\n */\n _getIntersection: function _getIntersection(e, s, v) {\n var iLeft = Math.max(e.x1, s.x),\n iRight = Math.min(e.x2, s.x + v.vw),\n iTop = Math.max(e.y1, s.y),\n iBottom = Math.min(e.y2, s.y + v.vh),\n intersectionArea = Math.max(0, iRight - iLeft) * Math.max(0, iBottom - iTop),\n elementArea = (e.x2 - e.x1) * (e.y2 - e.y1);\n\n return {\n intersectionArea: intersectionArea,\n elementArea: elementArea\n };\n },\n\n /**\n * Checks whether the element is actually displayed on the DOM\n * @param element\n * @return {boolean}\n */\n isElementVisible: function isElementVisible(element) {\n /* istanbul ignore next: jsdom won't trigger this */\n return element.offsetWidth > 0 && element.offsetHeight > 0;\n },\n\n /**\n * Gets the percentage of the element pixels currently within the viewport\n * @param {HTMLElement|Node} element\n * @return {number}\n */\n getPercentageInViewport: function getPercentageInViewport(element) {\n var e = okanjo.ui.getElementPosition(element),\n s = okanjo.ui.getScrollPosition(),\n v = okanjo.ui.getViewportSize();\n\n // If there was a problem getting the element position, fail fast\n if (e.err) return 0;\n\n // Get intersection rectangle\n\n var _okanjo$ui$_getInters = okanjo.ui._getIntersection(e, s, v),\n intersectionArea = _okanjo$ui$_getInters.intersectionArea,\n elementArea = _okanjo$ui$_getInters.elementArea;\n\n // Don't let it return NaN\n /* istanbul ignore else: jsdom no love positional data */\n\n\n if (elementArea <= 0) return 0;\n\n /* istanbul ignore next: jsdom no love positional data, area tested with helper fn tho */\n return intersectionArea / elementArea;\n }\n };\n\n /**\n * Splits the text in the element to fit within the visible height of its container, and separates with an ellipses\n * @param {HTMLElement|Node} element – The DOM element containing the text to fit\n * @param {HTMLElement} [container] – Optional container to compute fit on. Defaults to the element's parent\n */\n okanjo.ui.ellipsify = function (element, container) {\n\n // It's a sad day when you have to resort to JS because CSS kludges are too hacky to work down to IE8, programmatically\n\n //noinspection JSValidateTypes\n var parent = container || element.parentNode,\n targetHeight = okanjo.ui.getElementSize(parent).height,\n useTextContent = element.textContent !== undefined;\n\n var text = useTextContent ? element.textContent /* istanbul ignore next: browser diffs */ : element.innerText,\n replacedText = \"\",\n safety = 5000,\n // Safety switch to bust out of the loop in the event something goes terribly wrong\n replacer = function replacer(match) {\n /* istanbul ignore next: n/a to jsdom */\n replacedText = match.substr(0, match.length - 3) + replacedText;\n /* istanbul ignore next: n/a to jsdom */\n return '...';\n };\n\n // Trim off characters until we can fit the text and ellipses\n // If the text already fits, this loop is ignored\n /* istanbul ignore next: jsdom doesn't do element size computing stuff */\n while (okanjo.ui.getElementSize(element).height > targetHeight && text.length > 0 && safety-- > 0) {\n text = useTextContent ? element.textContent : element.innerText;\n\n text = text.replace(ELLIPSIFY_PATTERN, replacer);\n\n if (useTextContent) {\n element.textContent = text;\n } else {\n element.innerText = text;\n }\n }\n\n // If there is work to do, split the content into two span tags\n // Like so: [content]...[hidden content]\n /* istanbul ignore if: n/a to jsdom */\n if (replacedText.length > 0) {\n\n var content = document.createElement('span'),\n span = document.createElement('span');\n\n content.setAttribute('class', 'okanjo-ellipses');\n span.setAttribute('class', 'okanjo-visually-hidden');\n\n if (useTextContent) {\n content.textContent = text.substr(0, text.length - 3);\n span.textContent = replacedText;\n } else {\n content.innerText = text.substr(0, text.length - 3);\n span.innerText = replacedText;\n }\n\n element.innerHTML = '';\n element.appendChild(content);\n element.appendChild(span);\n }\n };\n\n /**\n * Locates images with the class okanjo-fit and ensures that they get filled.\n * This is basically a object-fit hacky workaround\n * @param element\n */\n okanjo.ui.fitImages = function (element) {\n // Detect objectFit support\n /* istanbul ignore else: n/a to jsdom */\n if ('objectFit' in document.documentElement.style === false) {\n // Find images to fit\n element.querySelectorAll('img.okanjo-fit').forEach(function (img) {\n\n // Hide the image\n img.style.display = 'none';\n\n // Update the parent w/ the background\n var parent = img.parentNode;\n parent.style.backgroundSize = 'cover';\n parent.style.backgroundImage = 'url(' + img.src + ')';\n parent.style.backgroundposition = 'center center';\n });\n }\n };\n\n //endregion\n\n // Export the root namespace\n return window.okanjo = okanjo;\n}(window, document);\n\"use strict\";\n\n(function (window) {\n\n var JSON_TEST = /^application\\/json/;\n var okanjo = window.okanjo;\n\n /**\n * Performs a reliable XHR request\n * @param {string} method - Request method\n * @param {string} url - URL\n * @param [payload] optional payload\n * @param callback Fired on when completed (err, res), normalized to standard response format\n */\n okanjo.net.request = function (method, url, payload, callback) {\n\n // payload is not required\n if (typeof payload === \"function\") {\n callback = payload;\n payload = undefined;\n }\n\n // Create a new instance\n var req = new (window.XMLHttpRequest /* istanbul ignore next: old ie */ || window.ActiveXObject)('MSXML2.XMLHTTP.3.0');\n\n // Flag to prevent duplicate callbacks / races\n var calledBack = false;\n\n // Normalized done handler\n var done = function done(err, res) {\n /* istanbul ignore else: out of scope */\n if (!calledBack) {\n calledBack = true;\n callback(err, res);\n }\n };\n\n // Apply timeout if configured globally\n if (okanjo.net.request.timeout) {\n req.timeout = okanjo.net.request.timeout;\n }\n\n // Catch timeout errors\n req.ontimeout = function (e) {\n /* istanbul ignore next: idk if jsdom can mock this, also readystatechange may fire before this anyway */\n done({\n statusCode: 504,\n error: \"Request timed out\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n };\n\n // Handle the response\n req.onreadystatechange = function (e) {\n // 4 = completed / failed\n if (req.readyState === 4) {\n // Do we have a response?\n if (req.status > 0) {\n var res = void 0;\n\n // Check if we got JSON and parse it right away\n if (JSON_TEST.test(req.getResponseHeader('Content-Type'))) {\n res = JSON.parse(req.responseText);\n } else {\n // Not JSON, normalize it instead\n res = {\n statusCode: req.status,\n data: req.responseText\n };\n }\n\n // Put the response in the proper slot (err for non success responses)\n if (req.status >= 200 && req.status < 300) {\n done(null, res);\n } else {\n done(res);\n }\n } else {\n // Request failed - e.g. CORS or network issues\n done({\n statusCode: 503,\n error: \"Request failed\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n }\n }\n };\n\n // Open the request\n req.open(method.toUpperCase(), url);\n\n // Include credentials\n req.withCredentials = true;\n\n // Handle post payloads\n if (['POST', 'PUT', 'PATCH'].includes(method.toUpperCase())) {\n req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n if (payload !== undefined) {\n payload = JSON.stringify(payload);\n }\n }\n\n // Ship it\n req.send(payload || undefined);\n };\n\n // Bind helpers to make things easy as pie\n okanjo.net.request.get = okanjo.net.request.bind(this, 'GET');\n okanjo.net.request.post = okanjo.net.request.bind(this, 'POST');\n okanjo.net.request.put = okanjo.net.request.bind(this, 'PUT');\n okanjo.net.request.delete = okanjo.net.request.bind(this, 'DELETE');\n\n /**\n * Helper to aid in minificiation+querystringify and redundant encodeURIComponent stuff\n * @param val\n * @return {*}\n */\n var encode = function encode(val) {\n if (val === null || val === undefined) return '';\n return encodeURIComponent('' + val);\n };\n\n /**\n * Helper to aid in getting a query string key using a prefix and keyname\n * @param key\n * @param keyPrefix\n * @return {*}\n */\n var getKey = function getKey(key, keyPrefix) {\n if (keyPrefix) {\n return keyPrefix + '[' + encode(key) + ']';\n } else {\n return encode(key);\n }\n };\n\n /**\n * Super basic querystringify helper. It handles deep objects, but not for array values\n * @param obj\n * @param [keyPrefix]\n * @return {string}\n */\n okanjo.net.request.stringify = function (obj, keyPrefix) {\n var pairs = [];\n keyPrefix = keyPrefix || \"\";\n Object.keys(obj).forEach(function (key) {\n var value = obj[key];\n if (Array.isArray(value)) {\n value.forEach(function (v) {\n return pairs.push(getKey(key, keyPrefix) + '=' + encode(v));\n }); // Does not do that PHP garbage with key[]=val\n } else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === \"object\" && value !== null) {\n // Recurse\n var res = okanjo.net.request.stringify(value, getKey(key, keyPrefix));\n if (res) pairs.push(res);\n } else if (value !== undefined) {\n pairs.push(getKey(key, keyPrefix) + '=' + encode(value));\n }\n });\n return pairs.join('&');\n };\n})(window);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function (window, document) {\n\n /**\n * Okanjo cookie utility helpers\n */\n window.okanjo.util.cookie = {\n\n /**\n * Sets a cookie\n * @param cookieName\n * @param value\n * @param expireDays\n */\n set: function set(cookieName, value, expireDays) {\n var expireDate = new Date();\n expireDate.setDate(expireDate.getDate() + expireDays);\n var expires = expireDays ? \" Expires=\" + expireDate.toUTCString() + \";\" : \"\";\n var path = \" Path=/\";\n var secure = window.location.protocol === 'https:' ? ' Secure;' : '';\n // const secure = ' Secure;';\n var cookieValue = encodeURI(value) + ';' + expires + secure + ' SameSite=None;' + path;\n // console.log('setting cookie', cookieName, cookieValue)\n document.cookie = cookieName + \"=\" + cookieValue;\n },\n\n /**\n * Gets a cookie\n * @param cookieName\n * @return {*}\n */\n get: function get(cookieName) {\n var output = null;\n document.cookie.split(\";\").find(function (cookie) {\n var nameTest = cookie.substr(0, cookie.indexOf(\"=\")).trim();\n var value = cookie.substr(cookie.indexOf(\"=\") + 1);\n if (nameTest === cookieName) {\n output = decodeURI(value);\n return true;\n } else {\n return false;\n }\n });\n return output;\n }\n };\n})(window, document);\n\"use strict\";\n\n//noinspection JSUnusedLocalSymbols,ThisExpressionReferencesGlobalObjectJS\n(function (window, document) {\n\n var okanjo = window.okanjo;\n\n /**\n * UI Rendering Engine\n */\n\n var TemplateEngine = function () {\n function TemplateEngine() {\n _classCallCheck(this, TemplateEngine);\n\n // Load initial templates from options\n this._templates = {};\n this._css = {};\n\n // Hook point for adding custom styles to ui elements\n this.classDetects = '';\n }\n\n /**\n * Registers a template for use\n * @param name\n * @param template\n * @param beforeRender\n * @param options\n */\n\n\n _createClass(TemplateEngine, [{\n key: 'registerTemplate',\n value: function registerTemplate(name, template, beforeRender, options) {\n\n if ((typeof template === 'undefined' ? 'undefined' : _typeof(template)) === \"object\") {\n //noinspection JSValidateTypes\n if (template.nodeType === undefined) {\n throw new Error('Parameter template must be a string or a DOM element');\n } else {\n template = template.innerHTML;\n okanjo.lib.Mustache.parse(template);\n }\n } else if (typeof template !== \"string\") {\n throw new Error('Parameter template must be a string or a DOM element');\n }\n\n // Shift options if only have 3 params\n if (arguments.length === 3 && (typeof beforeRender === 'undefined' ? 'undefined' : _typeof(beforeRender)) === \"object\") {\n options = beforeRender;\n beforeRender = null;\n } else {\n options = options || {};\n }\n\n if (beforeRender && typeof beforeRender !== \"function\") {\n throw new Error('Parameter beforeRender must be a function');\n }\n\n // Assign the template\n this._templates[name] = {\n markup: template,\n options: options,\n beforeRender: beforeRender\n };\n }\n\n /**\n * Registers a CSS payload for use\n * @param name\n * @param css\n * @param options\n */\n\n }, {\n key: 'registerCss',\n value: function registerCss(name, css, options) {\n options = options || {};\n\n if ((typeof css === 'undefined' ? 'undefined' : _typeof(css)) === \"object\") {\n //noinspection JSValidateTypes\n if (css.nodeType === undefined) {\n throw new Error('Parameter css must be a string or a DOM element');\n }\n } else if (typeof css !== \"string\") {\n throw new Error('Parameter css must be a string or a DOM element');\n }\n\n this._css[name] = {\n markup: css,\n options: options\n };\n }\n\n /**\n * Checks whether a template is registered\n * @param name\n * @return {boolean}\n */\n\n }, {\n key: 'isTemplateRegistered',\n value: function isTemplateRegistered(name) {\n return !!this._templates[name];\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Checks whether a CSS payload is registered\n * @param name\n * @return {boolean}\n */\n\n }, {\n key: 'isCssRegistered',\n value: function isCssRegistered(name) {\n return !!this._css[name];\n }\n\n /**\n * Ensures that a CSS payload has been added to the DOM\n * @param name\n */\n\n }, {\n key: 'ensureCss',\n value: function ensureCss(name) {\n if (this._css[name]) {\n //noinspection JSValidateTypes\n var css = this._css[name],\n id = css.markup.nodeType === undefined ? css.options.id || \"okanjo-css-\" + name : null; // If it's a DOM element, just forget it cuz it's already on the page\n\n // Check for css element on page, if we have an ID to look for\n if (id) {\n var element = document.querySelector('#' + id.replace(/\\./g, '\\\\.'));\n if (!element) {\n var head = document.head,\n style = document.createElement('style');\n\n style.id = id;\n style.setAttribute('type', 'text/css');\n\n /* istanbul ignore else: old ie */\n if (style.hasOwnProperty) {\n // old ie\n style.innerHTML = css.markup;\n } else {\n style.styleSheet.cssText = css.markup;\n }\n\n if (head) {\n head.appendChild(style);\n } else {\n // NO HEAD, just prepend to body then\n var body = document.body;\n if (body) {\n body.appendChild(style);\n } else {\n // And if this doesn't work, just give up\n okanjo.report('Cannot add CSS template to document. Does it not have a body or head?');\n }\n }\n }\n }\n } else {\n okanjo.report('Attempted to add CSS template \"' + name + '\" to the DOM, however it does not appear to be registered?');\n }\n }\n\n /**\n * Renders a template and returns the markup\n * @param templateName\n * @param context\n * @param model\n * @return {string}\n */\n\n }, {\n key: 'render',\n value: function render(templateName, context, model) {\n var _this = this;\n\n model = model || {};\n var template = this._templates[templateName];\n\n // If there's a data controller closure set, and if so, run the data through there\n if (template.beforeRender) {\n model = template.beforeRender.call(context, model);\n }\n\n // Attach globals\n model.okanjo = okanjo;\n model.okanjoMetricUrl = okanjo.net.endpoint.replace(/^https?:\\/\\//, ''); // Url w/o scheme to prevent mixed-content warnings\n model.now = function () {\n return new Date().getTime();\n };\n model.classDetects = this.classDetects;\n\n //noinspection JSUnresolvedVariable\n if (model.blockClasses && Array.isArray(model.blockClasses)) {\n model.classDetects += \" \" + model.blockClasses.join(' ');\n delete model.blockClasses;\n }\n\n // Add CSS unless we are told not to\n if (model.css !== false && template.options.css && template.options.css.length > 0) {\n template.options.css.forEach(function (css) {\n return _this.ensureCss(css);\n });\n delete model.css;\n }\n\n // Render the template and return the result\n return okanjo.lib.Mustache.render(template.markup, model);\n }\n }]);\n\n return TemplateEngine;\n }();\n\n /**\n * Formats a number into a currency string (rounded, decimal points, thousands separators)\n * See: http://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-money-in-javascript\n *\n * @param value – the number to format\n * @param [decimals] - The number of decimals to show\n * @param [decimalSeparator] – The decimals separator, default: .\n * @param [thousandsSeparator] – The thousands separator, default: ,\n * @returns {string} – Formatted currency string\n */\n\n\n TemplateEngine.formatCurrency = function (value) {\n var decimals = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 2;\n var decimalSeparator = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : '.';\n var thousandsSeparator = arguments.length > 3 && arguments[3] !== undefined ? arguments[3] : ',';\n\n var s = value < 0 ? \"-\" : \"\",\n i = parseInt(value = Math.abs(+value || 0).toFixed(decimals)) + \"\";\n var j = i.length;\n j = j > 3 ? j % 3 : 0;\n return s + (j ? i.substr(0, j) + thousandsSeparator : \"\") + i.substr(j).replace(/(\\d{3})(?=\\d)/g, \"$1\" + thousandsSeparator) + (decimals ? decimalSeparator + Math.abs(value - i).toFixed(decimals).slice(2) : \"\");\n };\n\n // Export\n okanjo.ui.engine = new TemplateEngine();\n})(window, document);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window, document) {\n\n /*\n div .modal-container .fade-out .hidden\n | div .modal-window .clearfix\n | |\n | | div .modal-window-skin\n | | | div .modal-window-outer\n | | | | div .modal-window-inner\n | | | | | iframe .okanjo-inline-buy-frame\n | | | | /div\n | | | /div\n | | /div\n | |\n | | div .close-button\n | | | ×\n | | /div\n | |\n | /div\n /div\n */\n\n var okanjo = window.okanjo;\n var IS_MOBILE = okanjo.util.isMobile();\n\n var initialized = false,\n\n // scrollY = null,\n\n // Selectors\n $html = void 0,\n $body = void 0,\n $modalContainer = void 0,\n $modalWindow = void 0,\n $modalSkin = void 0,\n $modalOuter = void 0,\n $modalInner = void 0,\n $modalClose = void 0,\n $modalFrame = void 0,\n createElements = function createElements() {\n\n // Page elements\n //noinspection JSUnresolvedFunction\n $html = document.documentElement /* istanbul ignore next: old browsers */ || document.querySelector('html');\n //noinspection JSUnresolvedFunction\n $body = document.body /* istanbul ignore next: old browsers */ || document.querySelector('body');\n\n // Modal elements\n $modalContainer = document.createElement('div');\n $modalWindow = document.createElement('div');\n $modalSkin = document.createElement('div');\n $modalOuter = document.createElement('div');\n $modalInner = document.createElement('div');\n $modalClose = document.createElement('div');\n $modalFrame = document.createElement('iframe');\n\n $modalContainer.setAttribute('class', 'okanjo-modal-container okanjo-modal-hidden ' /*+ okanjo.util.detectClasses().join(' ')*/);\n $modalWindow.setAttribute('class', 'okanjo-modal-window');\n $modalSkin.setAttribute('class', 'okanjo-modal-window-skin');\n $modalOuter.setAttribute('class', 'okanjo-modal-window-outer');\n $modalInner.setAttribute('class', 'okanjo-modal-window-inner');\n $modalClose.setAttribute('class', 'okanjo-modal-close-button');\n\n $modalFrame.setAttribute('class', 'okanjo-inline-buy-frame');\n $modalFrame.setAttribute('frameborder', '0');\n $modalFrame.setAttribute('vspace', '0');\n $modalFrame.setAttribute('hspace', '0');\n $modalFrame.setAttribute('webkitallowfullscreen', '');\n $modalFrame.setAttribute('mozallowfullscreen', '');\n $modalFrame.setAttribute('allowfullscreen', '');\n $modalFrame.setAttribute('scrolling', 'auto');\n\n $modalClose.innerHTML = '×';\n\n // Create the modal element tree\n $modalInner.appendChild($modalFrame);\n $modalOuter.appendChild($modalInner);\n $modalSkin.appendChild($modalOuter);\n $modalWindow.appendChild($modalSkin);\n $modalWindow.appendChild($modalClose);\n $modalContainer.appendChild($modalWindow);\n\n // Add the modal stuff to the body\n $body.appendChild($modalContainer);\n },\n addListener = function addListener(el, event, handler) {\n /* istanbul ignore else: old browsers */\n if (el.addEventListener) {\n el.addEventListener(event, handler, false);\n } else {\n el.attachEvent(\"on\" + event, handler);\n }\n },\n getWindowHeight = function getWindowHeight() {\n return window.innerHeight /* istanbul ignore next: old browsers */ || document.documentElement.clientHeight;\n },\n handleReposition = function handleReposition() {\n // scrollY = okanjo.ui.getScrollPosition().y;\n //$modalWindow.style.marginTop = scrollY + 40 + \"px\";\n $modalWindow.style.height = getWindowHeight() - 80 + \"px\";\n },\n bindEvents = function bindEvents() {\n\n // If the device orientation changes, adjust the modal view port\n addListener(window, 'orientationchange', function () {\n for (var t = 0; t < 2; t++) {\n setTimeout(handleReposition, 1000 * t + 10);\n }\n });\n\n // If the window changes size, also adjust the modal view port\n addListener(window, 'resize', function () {\n setTimeout(handleReposition, 100);\n });\n\n // Click the overlay to close the modal\n addListener($modalContainer, 'click', closeModal);\n\n // If you click in the modal, don't close it!\n addListener($modalWindow, 'click', function (e) {\n e.preventDefault();\n e.stopPropagation();\n });\n\n // Click the close button to close it\n addListener($modalClose, 'click', function (e) {\n\n // Don't close it twice\n e.preventDefault();\n e.stopPropagation();\n\n closeModal();\n });\n },\n\n\n //removeListener = function(el, event, handler) {\n // if (el.removeEventListener) {\n // el.removeEventListener(event, handler);\n // } else {\n // el.detachEvent(\"on\" + event, handler);\n // }\n //},\n\n addClass = function addClass(el, name) {\n el.className += \" \" + name;\n },\n removeClass = function removeClass(el, name) {\n el.className = el.className.replace(new RegExp(' *?' + name), '');\n },\n openModal = function openModal() {\n\n // scrollY = document.body.scrollTop;\n\n removeClass($modalContainer, 'okanjo-modal-hidden');\n addClass($modalContainer, 'okanjo-modal-fade-out');\n\n handleReposition();\n\n addClass($html, \"okanjo-modal-active\");\n\n if (!IS_MOBILE) {\n addClass($html, \"okanjo-modal-margin-fix\");\n }\n\n setTimeout(function () {\n removeClass($modalContainer, 'okanjo-modal-fade-out');\n }, 10);\n\n // Click the overlay to close the modal\n //addListener($body, 'click', closeModal);\n },\n closeModal = function closeModal() {\n addClass($modalContainer, 'okanjo-modal-fade-out');\n\n setTimeout(function () {\n removeClass($modalContainer, 'okanjo-modal-fade-out');\n addClass($modalContainer, \"okanjo-modal-hidden\");\n\n removeClass($html, \"okanjo-modal-active\");\n if (!IS_MOBILE) {\n removeClass($html, \"okanjo-modal-margin-fix\");\n }\n }, 210);\n\n // Click the overlay to close the modal\n //removeListener($body, 'click', closeModal);\n },\n\n\n /**\n * Insert an element or markup into the modal\n * @param content\n */\n setContent = function setContent(content) {\n\n // Remove existing content\n $modalInner.innerHTML = \"\";\n\n // Insert new content\n if (typeof content === \"string\") {\n $modalInner.innerHTML = content;\n } else {\n $modalInner.appendChild(content);\n }\n };\n\n // Expose the modal functions\n okanjo.ui.modal = {\n\n show: function show(content) {\n\n if (!initialized) {\n initialized = true;\n createElements();\n bindEvents();\n }\n\n setContent(content);\n openModal();\n },\n\n hide: function hide() {\n closeModal();\n }\n\n };\n\n return okanjo.ui.modal;\n})(window, document);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window, document) {\n\n var okanjo = window.okanjo;\n\n /**\n * Event tracking class\n * @type {Metrics}\n */\n\n var Metrics = function () {\n\n //noinspection JSUnusedGlobalSymbols\n function Metrics() {\n _classCallCheck(this, Metrics);\n\n /**\n * Events queued here before submission\n * @type {Array}\n * @private\n */\n this._queue = this._getStoredQueue();\n this._processTimeout = null; // queue event loop timeout pointer\n\n /**\n * Unique page grouping event identifier\n */\n this.pageId = okanjo.util.shortid();\n this.defaultChannel = Metrics.Channel.external;\n\n this.sid = null;\n this.sourceCh = null;\n this.sourceCx = null;\n\n // Extract referral data, if set\n this._checkUrlForReferral();\n\n // TODO - look into iframe session correlation system\n }\n\n //noinspection JSMethodCanBeStatic\n /**\n * Gets the storage backed metric queue, in case we did not send everything last time\n * @return {Array}\n * @private\n */\n\n\n _createClass(Metrics, [{\n key: '_getStoredQueue',\n value: function _getStoredQueue() {\n if (window.localStorage[Metrics.Params.queue]) {\n try {\n var queue = JSON.parse(window.localStorage[Metrics.Params.queue]);\n if (Array.isArray(queue)) {\n return queue;\n } else {\n okanjo.report('Stored queue is not a queue', { queue: queue });\n return [];\n }\n } catch (e) {\n okanjo.report('Failed to load metric queue from storage', { err: e });\n return [];\n }\n } else {\n // not stored\n return [];\n }\n }\n\n /**\n * Updates the queue stored in storage, in the event we can't complete our submissions\n * @param delay - Whether to delay updating the queue for a bit, to let other metrics pile in\n * @private\n */\n\n }, {\n key: '_saveQueue',\n value: function _saveQueue(delay) {\n var _this2 = this;\n\n if (delay) {\n if (this._saveQueueTimeout) clearTimeout(this._saveQueueTimeout);\n this._saveQueueTimeout = setTimeout(function () {\n _this2._saveQueue(false);\n _this2._saveQueueTimeout = null;\n }, 100);\n } else {\n window.localStorage[Metrics.Params.queue] = JSON.stringify(this._queue);\n }\n }\n\n /**\n * Extract contextual pass-through data from the URL, if present\n * @private\n */\n\n }, {\n key: '_checkUrlForReferral',\n value: function _checkUrlForReferral() {\n var pageArgs = okanjo.util.getPageArguments(true),\n urlSid = pageArgs[Metrics.Params.name],\n localSid = window.localStorage[Metrics.Params.name] || okanjo.util.cookie.get(Metrics.Params.name),\n // pull from storage or cookie\n sourceContext = pageArgs[Metrics.Params.context],\n sourceChannel = pageArgs[Metrics.Params.channel];\n\n // If for some reason, both are set, record the incident as a possible correlation\n if (urlSid && localSid && urlSid !== localSid) {\n this.trackEvent({\n object_type: Metrics.Object.metric_session,\n event_type: Metrics.Event.correlation,\n id: urlSid + \"_\" + localSid,\n ch: this.defaultChannel,\n _noProcess: true\n });\n }\n\n // Update local values\n this.sid = localSid || urlSid || null; // prefer local over remote (changed in 1.0)\n this.sourceCh = sourceChannel || null;\n this.sourceCx = sourceContext || null;\n }\n\n /**\n * Submits an individual event metric\n * @param event\n * @param callback\n */\n\n }, {\n key: 'trackEvent',\n value: function trackEvent(event, callback) {\n // Ensure the event contains the required fields\n if (!event.object_type || !event.event_type) {\n okanjo.report('Invalid metric to track (missing object_type or event_type)', { event: event });\n return;\n }\n\n // Queue the event for publishing\n this._push(event, callback);\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Submits a page view metric\n * @param event\n * @param callback\n */\n\n }, {\n key: 'trackPageView',\n value: function trackPageView(event, callback) {\n event = event || {};\n event.object_type = Metrics.Object.page;\n event.event_type = Metrics.Event.view;\n event.id = event.id || okanjo.util.getLocation();\n event.ch = event.ch || this.defaultChannel;\n\n // Queue the event for publishing\n this.trackEvent(event, callback);\n }\n\n /**\n * Adds an event to the queue\n * @param event\n * @param callback\n * @private\n */\n\n }, {\n key: '_push',\n value: function _push(event, callback) {\n this._queue.push({ event: event, callback: callback });\n\n // Save the queue\n this._saveQueue(true);\n\n // Start burning down the queue, unless the event says not to\n if (event._noProcess) {\n delete event._noProcess;\n } else {\n this._processQueue();\n }\n }\n\n /**\n * Burn down the queue\n * @private\n */\n\n }, {\n key: '_processQueue',\n value: function _processQueue() {\n var _this3 = this;\n\n // If the queue is not already being processed, and there's stuff to process, continue sending them\n if (!this._processTimeout && this._queue.length > 0) {\n this._processTimeout = setTimeout(function () {\n\n // Pull the items we're going to batch out of the queue\n var items = _this3._queue.splice(0, 255);\n _this3._saveQueue(false);\n\n // Track the item\n _this3._batchSend(items, function (err, res) {\n // TODO: If there was an error, consider splicing the batch back into the queue\n\n // Update / Set the metric sid on the publisher\n /* istanbul ignore else: server barks */\n if (res && res.data && res.data.sid) _this3._updateSid(res.data.sid);\n\n // When this batch is done being tracked, iterate to the next metric then fire it's callback if set\n _this3._processTimeout = null;\n _this3._processQueue();\n\n // Fire the event callbacks if there are any\n items.forEach(function (item) {\n item.callback && item.callback(err, res);\n });\n });\n }, 0); // break event loop, maybe\n }\n }\n\n /**\n * Sends a bunch of queued metric events\n * @param items\n * @param callback\n * @private\n */\n\n }, {\n key: '_batchSend',\n value: function _batchSend(items, callback) {\n var _this4 = this;\n\n // Normalize event data\n var events = items.map(function (item) {\n _this4._normalizeEvent(item.event);\n\n // Strip duplicated data from event batch\n delete item.event.sid;\n delete item.event.win;\n\n return item.event;\n });\n\n var payload = {\n events: events,\n win: okanjo.util.getLocation()\n };\n\n var route = okanjo.net.getRoute(okanjo.net.routes.metrics_batch);\n\n // Set sid if present\n if (this.sid) {\n payload.sid = this.sid;\n }\n\n // Send it\n okanjo.net.request.post(route, payload, function (err, res) {\n /* istanbul ignore if: out of scope */\n if (err) {\n okanjo.report('Failed to send metrics batch', { err: err, res: res, items: items, route: route });\n }\n callback && callback(err, res);\n });\n }\n\n /**\n * Normaizes events so that they contain consistent data values\n * @param event\n * @private\n */\n\n }, {\n key: '_normalizeEvent',\n value: function _normalizeEvent(event) {\n\n // Ensure meta is ready to receive values\n event.m = event.m || {};\n\n // Set key\n event.key = event.key || event.m.key || okanjo.key || undefined;\n\n // Set session\n if (this.sid) event.sid = this.sid;\n\n // Clone the metadata, since it might be a direct reference to a widget property\n // Deleting properties on the meta object could be very destructive\n event.m = Object.assign({}, event.m); // event.m should be flat\n\n // Strip meta keys that should be excluded\n Object.keys(Metrics.Meta.exclude).forEach(function (key) {\n return delete event.m[key];\n });\n\n // Set referral channel / context\n if (this.sourceCh) {\n event.m.ref_ch = this.sourceCh;\n }\n if (this.sourceCx) {\n event.m.ref_cx = this.sourceCx;\n }\n\n // Set page group id\n event.m.pgid = this.pageId;\n\n // Set okanjo version\n event.m.ok_ver = okanjo.version;\n\n // Finalize metadata\n event.m = okanjo.util.flatten(event.m, { arrayToCsv: true });\n\n // Ensure metadata strings won't exceed the imposed limit\n Object.keys(event.m).forEach(function (key) {\n if (typeof event.m[key] === \"string\") {\n event.m[key] = event.m[key].substr(0, 255);\n }\n });\n\n // Set page source reference\n if (document.referrer) {\n event.ref = document.referrer;\n }\n\n // Set the window location\n event.win = okanjo.util.getLocation();\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n\n }, {\n key: '_updateSid',\n value: function _updateSid(sid) {\n // Not set or changed?\n if (sid && (!this.sid || this.sid !== sid)) {\n this.sid = sid;\n window.localStorage[Metrics.Params.name] = sid;\n okanjo.util.cookie.set(Metrics.Params.name, sid, Metrics.Params.ttl);\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'create',\n\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Helper to create a new fluent event structure\n * @param args\n * @return {*}\n */\n value: function create() {\n for (var _len3 = arguments.length, args = Array(_len3), _key3 = 0; _key3 < _len3; _key3++) {\n args[_key3] = arguments[_key3];\n }\n\n return Metrics.create.apply(null, args);\n }\n }], [{\n key: 'addElementInfo',\n value: function addElementInfo(element, event) {\n var page = okanjo.ui.getPageSize(),\n size = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n event.m.pw = page.w;\n event.m.ph = page.h;\n event.m.x1 = size.x1;\n event.m.y1 = size.y1;\n event.m.x2 = size.x2;\n event.m.y2 = size.y2;\n\n return event;\n }\n }, {\n key: 'addWidgetInfo',\n value: function addWidgetInfo(element, event) {\n var containerSize = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n\n // placement div size\n event.m.wox1 = containerSize.x1;\n event.m.woy1 = containerSize.y1;\n event.m.wox2 = containerSize.x2;\n event.m.woy2 = containerSize.y2;\n\n // Inner size is the min/max of the child elements since they may be floating and have no official height/width\n var resources = okanjo.qwery('.okanjo-resource, .okanjo-adx-container', element);\n var size = void 0,\n wix1 = void 0,\n wiy1 = void 0,\n wix2 = void 0,\n wiy2 = void 0,\n boxes = [];\n var getMin = function getMin(val, current) {\n return typeof current === \"undefined\" || val < current ? val : current;\n };\n var getMax = function getMax(val, current) {\n return typeof current === \"undefined\" || val > current ? val : current;\n };\n var fallback = function fallback(val, _fallback) {\n return typeof val === \"undefined\" ? _fallback : val;\n };\n\n resources.forEach(function (e) {\n size = okanjo.ui.getElementPosition(e);\n wix1 = getMin(size.x1, wix1);\n wiy1 = getMin(size.y1, wiy1);\n wix2 = getMax(size.x2, wix2);\n wiy2 = getMax(size.y2, wiy2);\n boxes.push(size.x1, size.y1, size.x2, size.y2);\n });\n\n // inner size (might be centered or something)\n // noinspection JSUnusedAssignment\n event.m.wix1 = fallback(wix1, containerSize.x1); // noinspection JSUnusedAssignment\n event.m.wiy1 = fallback(wiy1, containerSize.y1); // noinspection JSUnusedAssignment\n event.m.wix2 = fallback(wix2, containerSize.x2); // noinspection JSUnusedAssignment\n event.m.wiy2 = fallback(wiy2, containerSize.y2);\n event.m.wrps = boxes.map(function (v) {\n return Math.floor(v);\n }).join(','); // all resource positions x1,y1,x2,y2,...\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds viewport dimensions / positional data to the event\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'addViewportInfo',\n value: function addViewportInfo(event) {\n var vp = okanjo.ui.getViewportSize(),\n pos = okanjo.ui.getScrollPosition();\n\n event = event || {};\n event.m = event.m || {};\n event.m.vx1 = pos.x;\n event.m.vy1 = pos.y;\n event.m.vx2 = pos.x + vp.vw;\n event.m.vy2 = pos.y + vp.vh;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @param event\n * @return {*|{}}\n */\n\n }, {\n key: 'addEventInfo',\n value: function addEventInfo(jsEvent, event) {\n var pos = okanjo.ui.getEventPosition(jsEvent);\n\n event = event || {};\n event.m = event.m || {};\n event.m.et = pos.et;\n event.m.ex = pos.ex;\n event.m.ey = pos.ey;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param event\n * @param args\n * @return {*|{}}\n */\n\n }, {\n key: 'addEventMeta',\n value: function addEventMeta(event) {\n event = event || {};\n event.m = event.m || {};\n\n for (var _len4 = arguments.length, args = Array(_len4 > 1 ? _len4 - 1 : 0), _key4 = 1; _key4 < _len4; _key4++) {\n args[_key4 - 1] = arguments[_key4];\n }\n\n event.m = Object.assign.apply(Object, [event.m].concat(args));\n\n return event;\n }\n\n /**\n * Helper to create a new fluent event structure\n * @param data\n * @param args\n * @return {MetricEvent}\n */\n\n }, {\n key: 'create',\n value: function create(data) {\n for (var _len5 = arguments.length, args = Array(_len5 > 1 ? _len5 - 1 : 0), _key5 = 1; _key5 < _len5; _key5++) {\n args[_key5 - 1] = arguments[_key5];\n }\n\n // return okanjo.util.deepClone(Object.assign.apply(Object, [{}].concat(args)));\n return new MetricEvent(data, args);\n }\n }]);\n\n return Metrics;\n }();\n\n /**\n * The storage/cookie/url param names\n * @type {{queue: string, name: string, channel: string, context: string, ttl: number}}\n */\n\n\n Metrics.Params = {\n queue: '_ok_q',\n name: 'ok_msid',\n channel: 'ok_ch',\n context: 'ok_cx',\n ttl: 1460 // 4 years\n };\n\n /**\n * Event Metadata configuration\n * @type {{exclude: [*]}}\n */\n Metrics.Meta = {\n exclude: ['key', 'callback', 'metrics_channel_context', 'metrics_context', 'mode']\n };\n\n /**\n * Event Types\n * @type {{view: string, impression: string, interaction: string, correlation: string}}\n */\n Metrics.Event = {\n view: 'vw',\n impression: 'imp',\n interaction: 'int',\n correlation: 'cor'\n };\n\n /**\n * Event Action Types\n * @type {{click: string, inline_click: string}}\n */\n Metrics.Action = {\n click: \"click\",\n inline_click: \"inline_click\"\n };\n\n /**\n * Event Object Types\n * @type {{article: string, thirdparty_ad: string, cart: string, page: string, widget: string, product: string, store: string, cause: string, marketplace: string, order: string, order_item: string, user: string, metric_session: string}}\n */\n Metrics.Object = {\n article: 'am',\n thirdparty_ad: 'ta',\n cart: 'ct',\n page: 'pg',\n widget: 'wg',\n product: 'pr',\n store: 'st',\n cause: 'ca',\n marketplace: 'mp',\n order: 'or',\n order_item: 'oi',\n user: 'ur',\n metric_session: 'mt'\n };\n\n /**\n * Event Channels\n * @type {{product_widget: string, ad_widget: string, store_widget: string, marketplace: string, external: string}}\n */\n Metrics.Channel = {\n placement: 'pw',\n marketplace: 'mp',\n external: 'ex',\n\n // Deprecated:\n product_widget: 'pw',\n ad_widget: 'aw',\n store_widget: 'sw'\n };\n\n /**\n * Event Environments\n * @type {{live: string, testing: string}}\n */\n Metrics.Environment = {\n live: \"live\",\n testing: \"testing\"\n };\n\n /**\n * Fluent wrapper around making events simple\n */\n\n var MetricEvent = function () {\n function MetricEvent(data, others) {\n var _this5 = this;\n\n _classCallCheck(this, MetricEvent);\n\n // Merge the data and other data sets into this object\n data = data || {};\n this.data(data);\n /* istanbul ignore else: metrics.create is the only way to create this right now */\n if (Array.isArray(others)) {\n others.forEach(function (data) {\n _this5.data(data);\n });\n }\n }\n\n /**\n * Sets event parameter key-values\n * @param data\n */\n\n\n _createClass(MetricEvent, [{\n key: 'data',\n value: function data(_data) {\n Object.assign(this, okanjo.util.deepClone(_data));\n return this;\n }\n\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @return {MetricEvent}\n */\n\n }, {\n key: 'event',\n value: function event(jsEvent) {\n Metrics.addEventInfo(jsEvent, this);\n return this;\n }\n\n /**\n * Adds viewport dimensions / positional data to the event\n * @return {MetricEvent}\n */\n\n }, {\n key: 'viewport',\n value: function viewport() {\n Metrics.addViewportInfo(this);\n return this;\n }\n\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @return {MetricEvent}\n */\n\n }, {\n key: 'element',\n value: function element(_element) {\n Metrics.addElementInfo(_element, this);\n return this;\n }\n\n /**\n * Adds widget DOM element dimensions / positional data to the event\n * @param element\n * @returns {MetricEvent}\n */\n\n }, {\n key: 'widget',\n value: function widget(element) {\n Metrics.addWidgetInfo(element, this);\n return this;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param args\n * @return {MetricEvent}\n */\n\n }, {\n key: 'meta',\n value: function meta() {\n for (var _len6 = arguments.length, args = Array(_len6), _key6 = 0; _key6 < _len6; _key6++) {\n args[_key6] = arguments[_key6];\n }\n\n Metrics.addEventMeta.apply(null, [this].concat(args));\n return this;\n }\n\n /**\n * Sets the object and event type on the event w/o having to use .data\n * @param object_type\n * @param event_type\n * @return {MetricEvent}\n */\n\n }, {\n key: 'type',\n value: function type(object_type, event_type) {\n this.object_type = object_type;\n this.event_type = event_type;\n return this;\n }\n\n /**\n * Finalizes and sends the event\n * @param callback\n */\n\n }, {\n key: 'send',\n value: function send(callback) {\n okanjo.metrics.trackEvent(this, callback);\n // DONT RETURN - BREAK THE CHAIN HERE\n }\n\n /**\n * Gets the single-metric tracking url for this event\n * @return {string}\n */\n\n }, {\n key: 'toUrl',\n value: function toUrl() {\n // Copy data w/o modifying it\n var event = Object.assign({}, this);\n\n // Extract params\n var object_type = event.object_type,\n event_type = event.event_type;\n\n delete event.object_type;\n delete event.event_type;\n\n // Normalize event data\n okanjo.metrics._normalizeEvent(event);\n\n // Get the URL\n return okanjo.net.getRoute(okanjo.net.routes.metrics, { object_type: object_type, event_type: event_type }) + '?' + okanjo.net.request.stringify(event);\n }\n }]);\n\n return MetricEvent;\n }();\n\n // Export / initialize\n\n\n okanjo.metrics = new Metrics();\n})(window, document);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function (window) {\n\n var okanjo = window.okanjo;\n\n // Track the page view, but don't send it right away.\n // Send it in one full second unless something else pushes an event\n // This way, we have a chance that a placement key will be set globally\n okanjo.metrics.trackPageView({ _noProcess: true });\n setTimeout(function () {\n okanjo.metrics._processQueue();\n }, 1000);\n})(window);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/** Based on https://gist.github.com/mudge/5830382 **/\n(function (window) {\n\n /**\n * Simplified EventEmitter base class\n */\n var EventEmitter = function () {\n function EventEmitter() {\n _classCallCheck(this, EventEmitter);\n\n this._events = {};\n }\n\n /**\n * Registers an event handler to fire on any occurrence of an event\n * @param event\n * @param listener\n */\n\n\n _createClass(EventEmitter, [{\n key: 'on',\n value: function on(event, listener) {\n if (!this._events[event]) {\n this._events[event] = [];\n }\n\n this._events[event].push(listener);\n }\n\n /**\n * Removes an event handler for an event\n * @param event\n * @param listener\n */\n\n }, {\n key: 'removeListener',\n value: function removeListener(event, listener) {\n\n if (this._events[event]) {\n var idx = this._events[event].indexOf(listener);\n if (idx >= 0) {\n this._events[event].splice(idx, 1);\n }\n }\n }\n\n /**\n * Emits an event\n * @param event\n */\n\n }, {\n key: 'emit',\n value: function emit(event) {\n var i = void 0,\n listeners = void 0,\n length = void 0,\n args = [].slice.call(arguments, 1);\n\n if (this._events[event]) {\n listeners = this._events[event].slice();\n length = listeners.length;\n\n for (i = 0; i < length; i++) {\n listeners[i].apply(this, args);\n }\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Registers an event handler to fire only once on an event\n * @param event\n * @param listener\n */\n\n }, {\n key: 'once',\n value: function once(event, listener) {\n var _arguments = arguments,\n _this6 = this;\n\n var callback = function callback() {\n var args = [].slice.call(_arguments, 1);\n _this6.removeListener(event, callback);\n listener.apply(_this6, args);\n };\n\n this.on(event, callback);\n }\n }]);\n\n return EventEmitter;\n }();\n\n window.okanjo._EventEmitter = EventEmitter;\n return EventEmitter;\n})(window);\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window) {\n\n var okanjo = window.okanjo;\n var DATA_ATTRIBUTE_PATTERN = /^data-(.+)$/;\n var DATA_REPLACE_PATTERN = /-/g;\n\n /**\n * Base widget class\n */\n\n var Widget = function (_okanjo$_EventEmitter) {\n _inherits(Widget, _okanjo$_EventEmitter);\n\n function Widget(element, options) {\n _classCallCheck(this, Widget);\n\n // Verify element was given (we can't load unless we have one)\n var _this7 = _possibleConstructorReturn(this, (Widget.__proto__ || Object.getPrototypeOf(Widget)).call(this));\n\n if (!element || element === null || element.nodeType === undefined) {\n okanjo.report('Invalid or missing element on widget construction', { widget: _this7, element: element, options: options });\n throw new Error('Okanjo: Invalid element - make sure to pass a valid DOM element when constructing Okanjo Widgets.');\n }\n\n // Verify configuration is OK\n if (options && (typeof options === 'undefined' ? 'undefined' : _typeof(options)) !== \"object\") {\n // Warn and fix it\n okanjo.report('Invalid widget options. Expected object, got: ' + (typeof options === 'undefined' ? 'undefined' : _typeof(options)), { widget: _this7, element: element, options: options });\n options = {};\n } else {\n options = options || {};\n }\n\n // Store basics\n _this7.name = 'Widget';\n _this7.element = element;\n _this7.instanceId = okanjo.util.shortid();\n\n // Clone initial config, breaking the top-level reference\n _this7.config = Object.assign({}, options);\n return _this7;\n }\n\n /**\n * Base widget initialization procedures\n */\n\n\n _createClass(Widget, [{\n key: 'init',\n value: function init() {\n // process config attributes\n this._applyConfiguration();\n\n this._setCompatibilityOptions();\n\n // ensure placement key\n if (!this._ensurePlacementKey()) return;\n\n // Tell the widget to load\n this.load();\n }\n\n /**\n * This is for extended widgets, so they may modify the configuration before loading\n */\n\n }, {\n key: '_setCompatibilityOptions',\n value: function _setCompatibilityOptions() {}\n // By default, this does nothing. Must be overridden to be useful\n\n\n //noinspection JSMethodCanBeStatic\n /**\n * Widget configuration definitions\n * @return {{}}\n */\n\n }, {\n key: 'getSettings',\n value: function getSettings() {\n // Override this\n return {};\n }\n\n /**\n * Main widget load function.\n */\n\n }, {\n key: 'load',\n value: function load() {}\n // Override this in the widget implementation\n\n\n /**\n * Applies data attribute settings and defaults to the widget configuration\n * @private\n */\n\n }, {\n key: '_applyConfiguration',\n value: function _applyConfiguration() {\n var _this8 = this;\n\n // this.config was set to the options provided in the constructor\n // so layer data attributes on top\n\n var data = this.getDataAttributes();\n var settings = this.getSettings();\n Object.keys(data).forEach(function (key) {\n var normalizedKey = key.replace(DATA_REPLACE_PATTERN, '_');\n\n var val = data[key];\n\n // Attempt to convert the value if there's a setting for it\n if (settings[normalizedKey]) val = settings[normalizedKey].value(val, false);\n\n if (!okanjo.util.isEmpty(val)) {\n _this8.config[normalizedKey] = val;\n }\n });\n\n // Apply defaults from the widget settings\n Object.keys(settings).forEach(function (key) {\n if (_this8.config[key] === undefined && settings[key]._default !== undefined) {\n _this8.config[key] = settings[key].value(undefined, false);\n }\n });\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets a copy of the configuration, suitable for transmission\n * @return {{}}\n */\n\n }, {\n key: 'getConfig',\n value: function getConfig() {\n var _this9 = this;\n\n var settings = this.getSettings();\n var out = {};\n\n Object.keys(this.config).forEach(function (origKey) {\n var val = _this9.config[origKey];\n var key = origKey;\n var group = null;\n\n // Check if this is a known property\n if (settings[key]) {\n val = settings[key].value(val);\n group = settings[key].getGroup();\n }\n\n // Init the target/group if not already setup\n var target = out;\n if (group) {\n target[group] = target[group] || {};\n target = target[group];\n }\n\n // Set the value on the target if set\n if (val === null) {\n target[key] = ''; // format null values as empty strings for transmission\n } else if (val !== undefined) {\n target[key] = val;\n }\n });\n\n return out;\n }\n\n /**\n * Before loading, ensure that a placement key is present or abort\n * @return {boolean}\n * @private\n */\n\n }, {\n key: '_ensurePlacementKey',\n value: function _ensurePlacementKey() {\n\n // Check if set on widget or globally\n if (this.config.key) {\n return true;\n } else if (okanjo.key) {\n // Copy key from global scope,\n this.config.key = okanjo.key;\n return true;\n }\n\n // No key set, can't load.\n okanjo.report('No key provided on widget', { widget: this });\n this.showError('Error: Missing placement key.');\n return false;\n }\n\n /**\n * Displays an error in the widget element\n * @param message\n */\n\n }, {\n key: 'showError',\n value: function showError(message) {\n this.setMarkup(okanjo.ui.engine.render('okanjo.error', this, { message: message }));\n }\n\n /**\n * Sets the markup of the widget's element\n * @param markup\n */\n\n }, {\n key: 'setMarkup',\n value: function setMarkup(markup) {\n this.element.innerHTML = markup;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets the current page URL, sans query string and fragment.\n * @returns {string} - URL\n */\n\n }, {\n key: 'getDataAttributes',\n\n\n /**\n * Instead of using HTML5 dataset, just rip through attributes and return data attributes\n * @returns {*}\n */\n value: function getDataAttributes() {\n var data = {};\n Array.from(this.element.attributes).forEach(function (attr) {\n var match = DATA_ATTRIBUTE_PATTERN.exec(attr.name);\n if (match) {\n data[match[1]] = attr.value;\n }\n });\n return data;\n }\n }], [{\n key: 'getCurrentPageUrl',\n value: function getCurrentPageUrl() {\n return window.location.href.replace(/([?#].*)$/, '');\n }\n }]);\n\n return Widget;\n }(okanjo._EventEmitter);\n\n /**\n * Fluent configuration helper for organizing and formatting ad-hoc configuration values\n * @type {Field}\n */\n\n\n Widget.Field = function () {\n\n //noinspection JSUnusedGlobalSymbols\n function Field() {\n _classCallCheck(this, Field);\n\n this._convert = null;\n this._strip = false;\n this._default = undefined;\n this._group = null;\n }\n\n /**\n * Formats the value as an array of strings\n * @param converter\n * @return {Field}\n */\n\n\n _createClass(Field, [{\n key: 'array',\n value: function array(converter) {\n this._convert = function (val) {\n if (Array.isArray(val)) {\n if (converter) {\n return val.map(function (v) {\n return converter(v);\n });\n } else {\n return val;\n }\n }\n val = val.replace(/\\\\,/g, '\\0');\n return val.split(',').map(function (v) {\n var res = v.trim().replace('\\0', ',');\n if (converter) res = converter(res);\n return res;\n });\n };\n return this;\n }\n //noinspection JSUnusedGlobalSymbols\n\n }, {\n key: 'string',\n\n\n /**\n * Formats the value as a string\n * @return {Field}\n */\n value: function string() {\n this._convert = function (val) {\n if (val === null || val === undefined) return val;else return \"\" + val;\n };\n return this;\n }\n }, {\n key: 'bool',\n\n\n /**\n * Formats the value as a boolean (takes 1, 0, true, false)\n * @return {Field}\n */\n value: function bool() {\n this._convert = function (val) {\n if (typeof val === \"string\") {\n return val === \"1\" || val.toLowerCase() === \"true\";\n } else {\n return !!val;\n }\n };\n return this;\n }\n //noinspection JSUnusedGlobalSymbols\n\n }, {\n key: 'strip',\n\n\n /**\n * Indicates the field should not be passed on for transmission\n * @return {Field}\n */\n value: function strip() {\n this._strip = true;return this;\n }\n }, {\n key: 'int',\n\n\n /**\n * Formats the value as a integer (whole) number\n * @return {Field}\n */\n value: function int() {\n this._convert = function (val) {\n return parseInt(val);\n };return this;\n }\n //noinspection JSUnusedGlobalSymbols\n\n }, {\n key: 'float',\n\n\n /**\n * Formats the value as a floating point number\n * @return {Field}\n */\n value: function float() {\n this._convert = function (val) {\n return parseFloat(val);\n };return this;\n }\n //noinspection JSUnusedGlobalSymbols\n\n }, {\n key: 'default',\n\n\n //noinspection ReservedWordAsName\n /**\n * Sets the default value to use if not set\n * @param val\n * @return {Field}\n */\n value: function _default(val) {\n this._default = val;\n return this;\n }\n\n /**\n * Assigns the property to a bucket for hierarchy\n * @param name\n * @return {Field}\n */\n\n }, {\n key: 'group',\n value: function group(name) {\n this._group = name;\n return this;\n }\n\n /**\n * Gets the group the field belongs to\n * @return {*|null}\n */\n\n }, {\n key: 'getGroup',\n value: function getGroup() {\n return this._group;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets the formatted value of the field\n * @param val\n * @param strip\n * @return {*}\n */\n\n }, {\n key: 'value',\n value: function value(val) {\n var strip = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : true;\n\n if (this._strip && strip) return undefined;\n if (val !== undefined && this._convert) {\n val = this._convert(val);\n }\n return val !== undefined ? val : this._default;\n }\n }], [{\n key: 'array',\n value: function array(converter) {\n return new Field().array(converter);\n }\n }, {\n key: 'string',\n value: function string() {\n return new Field().string();\n }\n }, {\n key: 'bool',\n value: function bool() {\n return new Field().bool();\n }\n }, {\n key: 'strip',\n value: function strip() {\n return new Field().strip();\n }\n }, {\n key: 'int',\n value: function int() {\n return new Field().int();\n }\n }, {\n key: 'float',\n value: function float() {\n return new Field().float();\n }\n }]);\n\n return Field;\n }();\n\n // Export\n return okanjo._Widget = Widget;\n})(window);\n\n\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window) {\n\n //region Imports and Constants\n\n var okanjo = window.okanjo;\n var _okanjo$_Widget$Field = okanjo._Widget.Field,\n string = _okanjo$_Widget$Field.string,\n array = _okanjo$_Widget$Field.array,\n float = _okanjo$_Widget$Field.float,\n int = _okanjo$_Widget$Field.int,\n bool = _okanjo$_Widget$Field.bool;\n\n var Metrics = okanjo.metrics.constructor;\n var TemplateEngine = okanjo.ui.engine.constructor;\n\n var FILTERS = 'filters';\n var DISPLAY = 'display';\n var ARTICLE_META = 'article_meta';\n\n var MINIMUM_VIEW_PX = 0.5; // 50% of pixels must be in viewport\n var MINIMUM_VIEW_TIME = 1000; // for 1 full second\n var MINIMUM_VIEW_FREQ = 2; // time / freq = interval\n\n //endregion\n\n /**\n * Placement widget\n */\n\n var Placement = function (_okanjo$_Widget) {\n _inherits(Placement, _okanjo$_Widget);\n\n //region Configuration & Overrides\n\n /**\n * Initializes a new placement\n * @param element\n * @param options\n */\n function Placement(element) {\n var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};\n\n _classCallCheck(this, Placement);\n\n // Flatten the options before passing on\n options = okanjo.util.flatten(options, { ignoreArrays: true });\n\n var _this10 = _possibleConstructorReturn(this, (Placement.__proto__ || Object.getPrototypeOf(Placement)).call(this, element, options));\n\n _this10.name = 'Placement';\n _this10._metricBase = {}; // placeholder for metrics\n _this10._response = null;\n\n // Aggregate view watchers into a single interval fn\n _this10._viewWatcherIv = null;\n _this10._viewedWatchers = [];\n\n // Start loading content\n if (!options.no_init) _this10.init();\n return _this10;\n }\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Gets the widget settings configuration\n * @return {{type: *, ids: *, q: *, url: *, url_referrer: *, url_selectors: *, organization_id: *, property_id: *, store_id: *, organization_name: *, property_name: *, store_name: *, external_id: *, sku: *, external_store_id: *, condition: *, manufacturer: *, upc: *, isbn: *, tags: *, category: *, pools: *, min_price: *, max_price: *, min_donation_percent: *, max_donation_percent: *, donation_to: *, sort_by: *, sort_direction: *, skip: *, take: *, placement_tests_only: *, size: *, template_name: *, template_layout: *, template_theme: *, template_cta_style: *, template_cta_text: *, template_cta_color: *, adx_unit_path: *, url_category: *, url_keywords: *, no_init: *, proxy_url: *, expandable, disable_inline_buy, disable_popup, backwards: *}}\n */\n\n\n _createClass(Placement, [{\n key: 'getSettings',\n value: function getSettings() {\n return {\n\n // What type of response do you want\n type: string().group(FILTERS),\n\n // What specific products do you want\n ids: array().group(FILTERS),\n\n // Filter by generic query string\n q: string().group(FILTERS),\n\n // Filter by relation to content\n url: string().group(FILTERS),\n url_referrer: string().group(FILTERS).strip(),\n url_selectors: string().group(FILTERS),\n url_paths: array().group(FILTERS),\n not_url_paths: array().group(FILTERS),\n\n // Filter by hierarchy\n organization_id: string().group(FILTERS),\n property_id: string().group(FILTERS),\n store_id: string().group(FILTERS),\n\n // Filter by hierarchy names (use *_id where possible, this might not work as you might expect)\n organization_name: string().group(FILTERS),\n property_name: string().group(FILTERS),\n store_name: string().group(FILTERS),\n\n // Filter by integrations\n external_id: string().group(FILTERS),\n sku: string().group(FILTERS),\n external_store_id: string().group(FILTERS),\n\n // Filter by product attributes\n condition: string().group(FILTERS),\n manufacturer: string().group(FILTERS),\n upc: string().group(FILTERS),\n isbn: string().group(FILTERS),\n\n // Filter by categorization / distribution\n tags: array().group(FILTERS),\n category: array().group(FILTERS),\n pools: array().group(FILTERS),\n\n // Filter by price range\n min_price: float().group(FILTERS),\n max_price: float().group(FILTERS),\n\n // Filter by donation ranges\n min_donation_percent: float().group(FILTERS),\n max_donation_percent: float().group(FILTERS),\n\n // Filter by donation recipient\n donation_to: string().group(FILTERS),\n\n // Sorting\n sort_by: string().group(FILTERS),\n sort_direction: string().group(FILTERS),\n\n // Pagination\n skip: int().group(FILTERS),\n take: int().group(FILTERS),\n\n // Placement Testing\n placement_tests_only: bool(),\n\n // Display settings\n size: string().group(DISPLAY),\n template_name: string().group(DISPLAY),\n template_layout: string().group(DISPLAY),\n template_theme: string().group(DISPLAY),\n template_variant: string().group(DISPLAY),\n template_cta_style: string().group(DISPLAY),\n template_cta_text: string().group(DISPLAY),\n template_cta_color: string().group(DISPLAY),\n adx_unit_path: string().group(DISPLAY), // Custom DFP ad unit path\n\n // Article metadata\n url_category: array().group(ARTICLE_META),\n url_keywords: array().group(ARTICLE_META),\n\n // Functional settings\n key: string().strip(), // don't need to resend key on all our requests\n no_init: bool().strip(), // don't automatically load the placement, do it manually (e.g. (new Placement({no_init:true})).init()\n no_css: bool().strip(), // don't automatically include stylesheets\n proxy_url: string().strip(),\n expandable: bool().strip().default(true),\n disable_inline_buy: bool().strip().default(false), // stops inline buy functionality\n disable_popup: bool().strip().default(false), // stops new window on mobile for inline buy functionality\n backwards: string().strip(), // internal flag indicating port from a deprecated widget\n testing: bool().strip() // metrics flag to indicate testing\n };\n }\n\n /**\n * Gets the widget configuration formatted using settings, suitable for transmission\n * @return {{filters: {}, display: {}, backfill: {}, shortfill: {}, article_meta: {}}}\n */\n\n }, {\n key: 'getConfig',\n value: function getConfig() {\n var _this11 = this;\n\n var settings = this.getSettings();\n var out = { filters: {}, display: {}, backfill: {}, shortfill: {}, article_meta: {} };\n var backfillPattern = /^backfill_(.+)$/; // backfill_property\n var shortfillPattern = /^shortfill_(.+)$/; // shortfill_property\n\n Object.keys(this.config).forEach(function (origKey) {\n var val = _this11.config[origKey];\n var key = origKey;\n var isBackfill = false;\n var isShortfill = false;\n var group = null;\n\n // Get the property name if it was prefixed with backfill\n var matches = backfillPattern.exec(origKey);\n if (matches) {\n key = matches[1];\n isBackfill = true;\n } else {\n // Get the property name if it was prefixed with shortfill\n matches = shortfillPattern.exec(origKey);\n if (matches) {\n key = matches[1];\n isShortfill = true;\n }\n }\n\n // Check if this is a known property\n if (settings[key]) {\n val = settings[key].value(val);\n group = settings[key].getGroup();\n }\n\n // Init the target/group if not already setup\n var target = out;\n if (isBackfill) {\n target = out.backfill;\n } else if (isShortfill) {\n target = out.shortfill;\n }\n\n // Set the target to the bucket in the settings container\n // except shortfill - can only apply settings directly to the bucket\n // e.g. backfill_url -> { backfill: { filters: { url: xxx } } }\n // e.g. shortfill_url-> { shortfill: { url: xxx } }\n if (!isShortfill && group) {\n target[group] = target[group] || {};\n target = target[group];\n }\n\n // Set the value on the target if set\n if (val === null) {\n target[key] = ''; // format null values as empty strings for transmission\n } else if (val !== undefined) {\n target[key] = val;\n }\n });\n\n return out;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Core load process\n */\n\n }, {\n key: 'load',\n value: function load() {\n var _this12 = this;\n\n // Set metric base data (stub for all future events emitted by the widget)\n this._setMetricBase();\n\n // Find out what we should display here\n this._fetchContent(function (err) {\n if (err) {\n // Report the widget load as declined\n _this12._reportWidgetLoad(\"fetch failed: \" + err.statusCode /* istanbul ignore next: out of scope */ || err.toString());\n } else {\n // Merge display settings from response\n _this12._mergeResponseSettings();\n\n // Merge the referential data from the response\n _this12._updateBaseMetaFromResponse();\n\n // Handle rendering based on output type\n _this12._showContent();\n }\n });\n }\n\n //endregion\n\n //region Internal Helpers\n\n /**\n * Initializes the common metric data for events emitted by the placement\n * @private\n */\n\n }, {\n key: '_setMetricBase',\n value: function _setMetricBase() {\n var base = this._metricBase;\n base.ch = Metrics.Channel.placement;\n base.cx = this.config.backwards || 'auto';\n base.key = this.config.key;\n base.m = base.m || {};\n base.m.wgid = this.instanceId;\n\n if (this.config.testing) base.env = Metrics.Environment.testing;\n }\n\n /**\n * Emits the widget impression event\n * @param declined\n * @private\n */\n\n }, {\n key: '_reportWidgetLoad',\n value: function _reportWidgetLoad(declined) {\n var _this13 = this;\n\n var res = this._response || {};\n var data = res.data || { results: [] };\n\n // If this is declined, mark future events as declined too\n this._metricBase.m.decl = declined || '0';\n\n // Attach other main response attributes to all future events\n this._metricBase.m.res_bf = data.backfilled ? 1 : 0; // whether the response used the back fill flow\n this._metricBase.m.res_sf = data.shortfilled ? 1 : 0; // whether the response used the short fill flow\n this._metricBase.m.res_spltfl = data.splitfilled ? 1 : 0; // whether the response used the short fill flow\n this._metricBase.m.res_total = data.total || 0; // how many total candidate results were available given filters\n this._metricBase.m.res_type = data.type; // what the given resource type was\n this._metricBase.m.res_length = data.results.length; // number of resources delivered\n\n // Track impression\n okanjo.metrics.create(this._metricBase).type(Metrics.Object.widget, Metrics.Event.impression).meta(this.getConfig()).element(this.element) // this might not be all that useful cuz the content hasn't been rendered yet\n .viewport().widget(this.element).send();\n\n // Start watching for a viewable impression\n this._addOnceViewedHandler(this.element, function () {\n okanjo.metrics.create(_this13._metricBase).type(Metrics.Object.widget, Metrics.Event.view).meta(_this13.getConfig()).element(_this13.element).viewport().widget(_this13.element).send();\n });\n }\n\n /**\n * Executes the request for content to fill the placement\n * @param callback\n * @private\n */\n\n }, {\n key: '_fetchContent',\n value: function _fetchContent(callback) {\n var _this14 = this;\n\n // Build request to api, starting with this placement config params\n var query = this.getConfig();\n\n // Extract the key\n var key = this.config.key;\n\n // Attach sid and referrer\n if (okanjo.metrics.sid) query.sid = okanjo.metrics.sid;\n query.filters.url_referrer = this.config.url_referrer || window.location.href;\n query.wgid = this.instanceId;\n query.pgid = okanjo.metrics.pageId;\n\n // Send it\n okanjo.net.request.post(okanjo.net.getRoute(okanjo.net.routes.ads, null, this.config.sandbox ? 'sandbox' : 'live') + '?key=' + encodeURIComponent(key), query, function (err, res) {\n if (err) {\n okanjo.report('Failed to retrieve placement content', err, { placement: _this14 });\n _this14.setMarkup(''); // Don't show anything\n _this14.emit('error', err);\n callback && callback(err);\n } else {\n\n // Store the raw response\n _this14._response = res;\n\n // Hook point for response handling\n _this14.emit('data');\n\n // Return\n callback && callback();\n }\n });\n }\n\n /**\n * Applies response filters and display settings into the widget configuration\n * @private\n */\n\n }, {\n key: '_mergeResponseSettings',\n value: function _mergeResponseSettings() {\n var _this15 = this;\n\n var res = this._response;\n var data = res.data || {};\n var settings = data.settings || {};\n\n if (settings.filters) {\n Object.keys(settings.filters).forEach(function (key) {\n _this15.config[key] = settings.filters[key];\n });\n }\n\n if (settings.display) {\n Object.keys(settings.display).forEach(function (key) {\n _this15.config[key] = settings.display[key];\n });\n }\n }\n\n /**\n * Applies response data to future metric events\n * @private\n */\n\n }, {\n key: '_updateBaseMetaFromResponse',\n value: function _updateBaseMetaFromResponse() {\n // Update the base metric data with info from the response\n var data = (this._response || {}).data || {};\n this._metricBase.m = this._metricBase.m || {};\n var meta = this._metricBase.m;\n\n // Article\n if (data.article) meta.aid = data.article.id;\n\n if (data.test && data.test.enabled) {\n meta.pten = 1;\n meta.ptid = data.test.id;\n meta.ptseed = data.test.seed;\n } else {\n meta.pten = 0;\n }\n }\n\n /**\n * Beings the render process based on the response content\n * @private\n */\n\n }, {\n key: '_showContent',\n value: function _showContent() {\n var data = (this._response || {}).data || {};\n\n // Known content types we can display\n if (data.type === Placement.ContentTypes.products) {\n this._showProducts();\n } else if (data.type === Placement.ContentTypes.articles) {\n this._showArticles();\n } else if (data.type === Placement.ContentTypes.adx) {\n this._showADX();\n } else {\n // Unknown response type!\n\n // Report the widget load as declined\n var msg = 'Unknown response content type: ' + data.type;\n okanjo.report(msg, { placement: this });\n this.setMarkup(''); // Don't show anything\n this.emit('error', msg);\n this._reportWidgetLoad(msg);\n }\n }\n\n /**\n * Generates the click url using the event, proxy_url, and additional params\n * @param event\n * @param url\n * @param additionalUrlParams\n * @return {*}\n * @private\n */\n\n }, {\n key: '_getClickThroughURL',\n value: function _getClickThroughURL(event, url, additionalUrlParams) {\n var joiner = url.indexOf('?') >= 0 ? '&' : '?';\n\n // Tack on transfer params\n additionalUrlParams = additionalUrlParams /* istanbul ignore next: paranoia */ || {};\n additionalUrlParams.ok_msid = okanjo.metrics.sid || 'unknown';\n additionalUrlParams.ok_ch = this._metricBase.ch;\n additionalUrlParams.ok_cx = this._metricBase.cx;\n additionalUrlParams._okjr = window.location.href.split(/[?#]/)[0];\n additionalUrlParams.utm_source = 'okanjo';\n additionalUrlParams.utm_campaign = 'smartserve';\n // additionalUrlParams.utm_source = window.location.hostname;\n additionalUrlParams.utm_medium = 'smartserve';\n // additionalUrlParams.utm_campaign = 'smartserve';\n\n\n url += joiner + Object.keys(additionalUrlParams).map(function (key) {\n return encodeURIComponent(key) + '=' + encodeURIComponent(additionalUrlParams[key]);\n }).join('&');\n\n // Wrap the url if we're proxying\n if (this.config.proxy_url) {\n url = this.config.proxy_url + encodeURIComponent(url);\n }\n\n // Set the url on the event\n event.data({\n u: url\n });\n\n return event.toUrl();\n }\n\n /**\n * Converts a resource's link into one suitable for tracking, making middle-click safe\n * @param type\n * @param resource\n * @param e\n * @private\n */\n\n }, {\n key: '_handleResourceMouseDown',\n value: function _handleResourceMouseDown(type, resource, e) {\n // Generate a new click id for this event\n // const clickId = okanjo.util.shortid();\n var clickId = resource._cid;\n\n // Start building the event\n var event = okanjo.metrics.create(this._metricBase, {\n id: resource.id\n }).type(type, Metrics.Event.interaction).meta(this.getConfig()).meta({ cid: clickId }).meta({\n bf: resource.backfill ? 1 : 0,\n sf: resource.shortfill ? 1 : 0,\n spltfl_seg: resource.splitfill_segment || null\n }).event(e).element(e.currentTarget).viewport().widget(this.element);\n\n // Pull the proper params out of the resource depending on it's type\n var trackParam = 'url_track_param';\n var urlParam = 'url';\n\n if (type === Metrics.Object.product) {\n trackParam = 'buy_url_track_param';\n urlParam = 'buy_url';\n }\n\n // Attach the campaign tracking identifier\n var additionalParams = {\n ok_cid: clickId\n };\n if (resource[trackParam]) additionalParams[resource[trackParam]] = clickId;\n\n // Update the link with the event data\n event.data({ ea: Metrics.Action.click });\n e.currentTarget.href = this._getClickThroughURL(event, resource[urlParam], additionalParams);\n\n // Cache this on the product\n resource._clickId = clickId;\n resource._event = event;\n resource._additionalParams = additionalParams;\n }\n\n /**\n * Gets the template to use, accounting for configured preference if available\n * @param contentType\n * @param defaultName\n * @return {string}\n * @private\n */\n\n }, {\n key: '_getTemplate',\n value: function _getTemplate(contentType, defaultName) {\n var templateName = this.config.template_name;\n if (!templateName || !okanjo.ui.engine.isTemplateRegistered(contentType + '.' + templateName)) {\n templateName = defaultName;\n }\n return contentType + '.' + templateName;\n }\n\n /**\n * Enforces size/layout/cta restrictions\n * @private\n */\n\n }, {\n key: '_enforceLayoutOptions',\n value: function _enforceLayoutOptions() {\n // Enforce format restrictions\n if (this.config.size === \"leaderboard\" || this.config.size === \"large_mobile_banner\") {\n this.config.template_layout = \"list\";\n this.config.template_cta_style = \"link\";\n } else if (this.config.size === \"half_page\" || this.config.size === \"auto\") {\n this.config.template_layout = \"list\";\n }\n }\n\n /**\n * Enforces\n * @private\n */\n\n }, {\n key: '_enforceSlabLayoutOptions',\n value: function _enforceSlabLayoutOptions() {\n if (this.config.size === \"medium_rectangle\" || this.config.size === \"billboard\") {\n // no list view\n this.config.template_layout = \"grid\";\n\n // no buttons\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n } else if (this.config.size === \"half_page\") {\n this.config.template_layout = \"grid\";\n } else if (this.config.size === \"leaderboard\" || this.config.size === \"large_mobile_banner\") {\n this.config.template_layout = \"list\";\n\n // no button\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n } else if (this.config.size === \"auto\") {\n this.config.template_layout = \"list\";\n } else if (this.config.size === \"responsive\") {\n // no button in responsive mode\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n }\n }\n\n /**\n * Register a custom\n * @private\n */\n\n }, {\n key: '_registerCustomBranding',\n value: function _registerCustomBranding() /*prefix, buttonClass*/{\n var brandColor = this.config.template_cta_color;\n if (brandColor) {\n var brandCSS = void 0,\n brandCSSId = \"okanjo-wgid-\" + this.instanceId;\n\n brandCSS = '\\n .okanjo-block2.' + brandCSSId + ' .okanjo-resource-cta-button, .okanjo-block2.' + brandCSSId + ' .okanjo-resource-buy-button { color: ' + brandColor + ' !important; } \\n .okanjo-block2.' + brandCSSId + '.okanjo-cta-style-button .okanjo-resource-cta-button, .okanjo-block2.' + brandCSSId + '.okanjo-cta-style-button .okanjo-resource-buy-button { border-color: ' + brandColor + ' !important; } \\n .okanjo-block2.' + brandCSSId + '.okanjo-cta-style-button .okanjo-resource-cta-button:hover, .okanjo-block2.' + brandCSSId + '.okanjo-cta-style-button .okanjo-resource-buy-button:hover { background: ' + brandColor + ' !important; color: #fff !important; } \\n ';\n\n okanjo.ui.engine.registerCss(brandCSSId, brandCSS, { id: brandCSSId });\n okanjo.ui.engine.ensureCss(brandCSSId);\n }\n }\n\n /**\n * When element is in view per viewability constants (50% for 1s) trigger handler once\n * @param element\n * @param handler\n * @private\n */\n\n }, {\n key: '_addOnceViewedHandler',\n value: function _addOnceViewedHandler(element, handler) {\n var controller = {\n element: element,\n successfulCount: 0,\n handler: handler\n };\n\n // Add our element to the watch list and turn on the watcher if not already on\n this._viewedWatchers.push(controller);\n this._toggleViewWatcher(true);\n }\n\n /**\n * Interval function to check viewability of registered elements\n * @private\n */\n\n }, {\n key: '_checkViewWatchers',\n value: function _checkViewWatchers() {\n\n // Check each registered watcher\n for (var i = 0, controller; i < this._viewedWatchers.length; i++) {\n controller = this._viewedWatchers[i];\n\n // Check if watcher is complete, then remove it from the list\n /* istanbul ignore next: jsdom won't trigger this */\n if (okanjo.ui.isElementVisible(controller.element) && okanjo.ui.getPercentageInViewport(controller.element) >= MINIMUM_VIEW_PX) {\n controller.successfulCount++;\n }\n\n // While this could more optimally be contained within the former condition, unit-testing blocks on this\n if (controller.successfulCount >= MINIMUM_VIEW_FREQ) {\n controller.handler();\n this._viewedWatchers.splice(i, 1);\n i--;\n }\n }\n\n // Turn off if nobody is watching\n if (this._viewedWatchers.length === 0) {\n this._toggleViewWatcher(false);\n }\n }\n\n /**\n * Turns the viewability watcher on and off\n * @param enabled\n * @private\n */\n\n }, {\n key: '_toggleViewWatcher',\n value: function _toggleViewWatcher(enabled) {\n if (enabled) {\n if (this._viewWatcherIv === null) {\n this._viewWatcherIv = setInterval(this._checkViewWatchers.bind(this), MINIMUM_VIEW_TIME / MINIMUM_VIEW_FREQ);\n }\n } else {\n clearInterval(this._viewWatcherIv);\n this._viewWatcherIv = null;\n }\n }\n\n //endregion\n\n //region Product Handling\n\n /**\n * Renders a product response\n * @private\n */\n\n }, {\n key: '_showProducts',\n value: function _showProducts() {\n var _this16 = this;\n\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n\n // Determine template to render, using custom template name if it exists\n var templateName = this._getTemplate(Placement.ContentTypes.products, Placement.DefaultTemplates.products);\n\n // - render\n\n // Format products\n data.results.forEach(function (offer, index) {\n // Disable inline buy if configured to do so\n if (_this16.config.disable_inline_buy) offer.inline_buy_url = null;\n if (offer.inline_buy_url) offer._escaped_inline_buy_url = encodeURIComponent(offer.inline_buy_url);\n\n // Set primary image\n offer._image_url = offer.image_urls ? offer.image_urls[0] : '';\n\n // Escape buy url (fixme: does not include proxy_url!)\n offer._escaped_buy_url = encodeURIComponent(offer.buy_url);\n\n // Make price tag pretty\n offer._price_formatted = TemplateEngine.formatCurrency(offer.price);\n offer._index = index;\n });\n\n var model = {\n css: !this.config.no_css\n };\n\n // Render and display the results\n this.setMarkup(okanjo.ui.engine.render(templateName, this, model));\n\n // Track widget impression\n if (data.results.length === 0) {\n // Hook point for no results found\n this.emit('empty');\n this._reportWidgetLoad('empty'); // decline the impression\n } else {\n this._reportWidgetLoad();\n }\n\n // Bind interaction handlers and track impressions\n this.element.querySelectorAll('a').forEach(function (a) {\n\n var id = a.getAttribute('data-id'),\n index = a.getAttribute('data-index');\n\n // Don't bind links that are not tile links\n /* istanbul ignore else: custom templates could break it */\n if (id && index >= 0) {\n var product = _this16._response.data.results[index];\n /* istanbul ignore else: custom templates could break it */\n if (product) {\n\n // Bind interaction listener\n a.addEventListener('mousedown', _this16._handleResourceMouseDown.bind(_this16, Metrics.Object.product, product));\n a.addEventListener('click', _this16._handleProductClick.bind(_this16, product));\n\n // Track impression\n okanjo.metrics.create(_this16._metricBase, { id: product.id }).type(Metrics.Object.product, Metrics.Event.impression).meta(_this16.getConfig()).meta({\n bf: product.backfill ? 1 : 0,\n sf: product.shortfill ? 1 : 0,\n spltfl_seg: product.splitfill_segment || null\n }).element(a).viewport().widget(_this16.element).send();\n\n // Start watching for a viewable impression\n _this16._addOnceViewedHandler(a, function () {\n okanjo.metrics.create(_this16._metricBase, { id: product.id }).type(Metrics.Object.product, Metrics.Event.view).meta(_this16.getConfig()).meta({\n bf: product.backfill ? 1 : 0,\n sf: product.shortfill ? 1 : 0,\n spltfl_seg: product.splitfill_segment || null\n }).element(a).viewport().widget(_this16.element).send();\n });\n }\n }\n });\n\n // Truncate product name to fit the space\n this.element.querySelectorAll('.okanjo-resource-title').forEach(function (element) {\n okanjo.ui.ellipsify(element);\n });\n\n // Fit images\n okanjo.ui.fitImages(this.element);\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n /**\n * Handles the product click process\n * @param product\n * @param e\n * @private\n */\n\n }, {\n key: '_handleProductClick',\n value: function _handleProductClick(product, e) {\n\n // Update the event\n if (!product._event || !product._additionalParams || !product._clickId) {\n this._handleResourceMouseDown(Metrics.Object.product, product, e);\n }\n\n // Extract the already generated event and params list\n var event = product._event,\n additionalParams = product._additionalParams;\n\n // Update the event to the current one\n\n event.event(e);\n\n // Determine what we're doing - native ux or redirect\n var showNativeBuyUx = !!product.inline_buy_url,\n showPopupNativeBuyUx = !this.config.disable_popup && showNativeBuyUx && okanjo.util.isMobile();\n\n // Show the inline buy experience or redirect\n if (showPopupNativeBuyUx) {\n // Mobile native buy ux\n\n // Don't follow the link\n e.preventDefault();\n\n //\n // Mobile devices (especially iOS) have real janky UX when interacting with iframes.\n // So, we'll choose to popup a window with the native buy experience, so we can ensure\n // a positive user experience. Nobody likes bouncy form fields and really weird zooming.\n //\n\n // Update the event\n event.data({ ea: Metrics.Action.inline_click }).meta({ popup: 'true' });\n\n // Get the frame url\n var url = this._getClickThroughURL(event, product.inline_buy_url, additionalParams);\n\n // Open the window or redirect if that failed\n this._popupFrame = window.open(url, \"okanjo-inline-buy-frame\", \"width=400,height=400,location=yes,resizable=yes,scrollbars=yes\");\n /* istanbul ignore else: jsdom doesn't support window.open or setting window.location.href */\n if (!this._popupFrame) {\n // Fallback to just replacing the window with the target, since popups don't work :(\n okanjo.report('Popup blocker stopped buy experience from showing', { placement: this });\n window.location.href = url;\n }\n } else if (showNativeBuyUx) {\n // Regular native buy ux\n\n // Don't follow the link\n e.preventDefault();\n\n var frame = document.createElement('iframe');\n var attributes = {\n 'class': 'okanjo-inline-buy-frame',\n frameborder: 0,\n vspace: 0,\n hspace: 0,\n webkitallowfullscreen: '',\n mozallowfullscreen: '',\n allowfullscreen: '',\n scrolling: 'auto'\n };\n\n // Apply attributes\n Object.keys(attributes).forEach(function (key) {\n return frame.setAttribute(key, attributes[key]);\n });\n\n // Check whether we're allowed to expand past the bounds of the placement\n additionalParams.expandable = this.config.expandable ? 1 : 0;\n if (!this.config.expandable) {\n var parent = this.element.querySelector('.okanjo-expansion-root');\n /* istanbul ignore else: custom templates could break this */\n if (parent) {\n frame.className += ' okanjo-ad-in-unit';\n frame.setAttribute('height', \"100%\");\n frame.setAttribute('width', \"100%\");\n\n parent.appendChild(frame);\n\n var size = okanjo.ui.getElementSize(parent);\n additionalParams.frame_height = size.height;\n additionalParams.frame_width = size.width;\n /* istanbul ignore next: i'm not writing a whole test for this one config param */\n if (this.config.size) additionalParams.ad_size = this.config.size;\n }\n }\n\n // Update the event\n event.data({ ea: Metrics.Action.inline_click }).meta({ expandable: this.config.expandable ? 'true' : 'false' });\n\n // Set the frame url\n frame.src = this._getClickThroughURL(event, product.inline_buy_url, additionalParams);\n\n // Show the modal if it was not internally expanded\n if (!frame.parentNode) {\n okanjo.ui.modal.show(frame);\n }\n } else {\n // Update the link a second time, just in case the data changed\n e.currentTarget.href = this._getClickThroughURL(event, product.buy_url, additionalParams);\n }\n }\n\n //endregion\n\n //region Article Handling\n\n /**\n * Renders an article response\n * @private\n */\n\n }, {\n key: '_showArticles',\n value: function _showArticles() {\n var _this17 = this;\n\n var data = (this._response || { data: { results: [] } }).data || { results: [] };\n\n // Determine template to render, using custom template name if it exists\n var templateName = this._getTemplate(Placement.ContentTypes.articles, Placement.DefaultTemplates.articles);\n\n // - render\n\n // Format articles\n data.results.forEach(function (article, index) {\n // Escape url (fixme: does not include proxy_url!)\n article._escaped_url = encodeURIComponent(article.url);\n article._index = index;\n });\n\n var model = {\n css: !this.config.no_css\n };\n\n // Render and display the results\n this.setMarkup(okanjo.ui.engine.render(templateName, this, model));\n\n // Track widget impression\n if (data.results.length === 0) {\n // Hook point for no results found\n this.emit('empty');\n this._reportWidgetLoad('empty'); // decline the impression\n } else {\n this._reportWidgetLoad();\n }\n\n // Bind interaction handlers and track impressions\n this.element.querySelectorAll('a').forEach(function (a) {\n\n var id = a.getAttribute('data-id'),\n index = a.getAttribute('data-index');\n\n // Don't bind links that are not tile links\n /* istanbul ignore else: custom templates could break this */\n if (id && index >= 0) {\n var article = _this17._response.data.results[index];\n /* istanbul ignore else: custom templates could break this */\n if (article) {\n\n // Bind interaction listener\n a.addEventListener('mousedown', _this17._handleResourceMouseDown.bind(_this17, Metrics.Object.article, article));\n a.addEventListener('click', _this17._handleArticleClick.bind(_this17, article));\n\n // Track impression\n okanjo.metrics.create(_this17._metricBase, { id: article.id }).type(Metrics.Object.article, Metrics.Event.impression).meta(_this17.getConfig()).meta({\n bf: article.backfill ? 1 : 0,\n sf: article.shortfill ? 1 : 0,\n spltfl_seg: article.splitfill_segment || null\n }).element(a).viewport().widget(_this17.element).send();\n\n // Start watching for a viewable impression\n _this17._addOnceViewedHandler(a, function () {\n okanjo.metrics.create(_this17._metricBase, { id: article.id }).type(Metrics.Object.article, Metrics.Event.view).meta(_this17.getConfig()).meta({\n bf: article.backfill ? 1 : 0,\n sf: article.shortfill ? 1 : 0,\n spltfl_seg: article.splitfill_segment || null\n }).element(a).viewport().widget(_this17.element).send();\n });\n }\n }\n });\n\n // Truncate product name to fit the space\n this.element.querySelectorAll('.okanjo-resource-title').forEach(function (element) {\n okanjo.ui.ellipsify(element);\n });\n\n // Fit images\n okanjo.ui.fitImages(this.element);\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n /**\n * Handles the article click process\n * @param article\n * @param e\n * @private\n */\n\n }, {\n key: '_handleArticleClick',\n value: function _handleArticleClick(article, e) {\n // Update the event\n if (!article._event || !article._additionalParams || !article._clickId) {\n this._handleResourceMouseDown(Metrics.Object.article, article, e);\n }\n\n // Extract the already generated event and params list\n var event = article._event,\n additionalParams = article._additionalParams;\n\n // Update the event to the current one\n\n event.event(e);\n\n // Update the link a second time, just in case the data changed\n e.currentTarget.href = this._getClickThroughURL(event, article.url, additionalParams);\n }\n\n //endregion\n\n //region ADX Handling\n\n /**\n * Renders a Google DFP/ADX response\n * @private\n */\n\n }, {\n key: '_showADX',\n value: function _showADX() {\n var _this18 = this;\n\n var data = (this._response || { data: { settings: {} } }).data || { settings: {} };\n\n // Get the template we should use to render the google ad\n var templateName = this._getTemplate(Placement.ContentTypes.adx, Placement.DefaultTemplates.adx);\n\n // Determine what size ad we can place here\n var size = null;\n if (this.config.size) {\n if (Placement.Sizes[this.config.size]) {\n // Defined size, use these known dimensions\n size = Placement.Sizes[this.config.size];\n } else {\n var match = /^([0-9]+)x([0-9]+)$/i.exec(this.config.size);\n if (match) {\n size = { width: match[1], height: match[2] };\n }\n }\n }\n\n // No given size, we need to guess\n if (!size) size = Placement.Sizes.default;\n\n // If we're using okanjo's ad slot, then track the impression\n // otherwise decline it because we're just passing through to the publishers account\n var adUnitPath = '/90447967/okanjo:';\n var declineReason = void 0;\n if (data.settings.display && data.settings.display.adx_unit_path) {\n adUnitPath = data.settings.display.adx_unit_path;\n declineReason = 'custom_ad_unit';\n }\n\n // Pass along what the template needs to know to display the ad\n var renderContext = {\n css: !this.config.no_css,\n size: size,\n adUnitPath: adUnitPath\n };\n\n // Render the container\n this.setMarkup(okanjo.ui.engine.render(templateName, this, renderContext));\n\n // Report the impression\n this._reportWidgetLoad(declineReason);\n\n // Insert the actual ad into the container\n var container = this.element.querySelector('.okanjo-adx-container');\n /* istanbul ignore else: custom templates could break this */\n if (container) {\n\n // Make the frame element\n var frame = document.createElement('iframe');\n var attributes = {\n 'class': 'okanjo-adx-frame',\n frameborder: 0,\n vspace: 0,\n hspace: 0,\n webkitallowfullscreen: '',\n mozallowfullscreen: '',\n allowfullscreen: '',\n scrolling: 'auto',\n width: size.width,\n height: size.height\n };\n\n // Apply attributes\n Object.keys(attributes).forEach(function (key) {\n return frame.setAttribute(key, attributes[key]);\n });\n\n // Attach to dOM\n container.appendChild(frame);\n\n // Build a click-through tracking url so we know when an ad is clicked too\n var clickUrl = okanjo.metrics.create(this._metricBase).type(Metrics.Object.thirdparty_ad, Metrics.Event.interaction).meta(this.getConfig()).meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n }).element(frame).viewport().widget(this.element).toUrl();\n\n // Transfer references to the frame window\n // frame.contentWindow.okanjo = okanjo;\n // frame.contentWindow.placement = this;\n frame.contentWindow.trackImpression = function () {\n okanjo.metrics.create(_this18._metricBase).type(Metrics.Object.thirdparty_ad, Metrics.Event.impression).meta(_this18.getConfig()).meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n }).element(frame).viewport().widget(_this18.element).send();\n\n // Start watching for a viewable impression\n _this18._addOnceViewedHandler(frame, function () {\n okanjo.metrics.create(_this18._metricBase).type(Metrics.Object.thirdparty_ad, Metrics.Event.view).meta(_this18.getConfig()).meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n }).element(frame).viewport().widget(_this18.element).send();\n });\n };\n\n // Load Google ad!\n frame.contentWindow.document.open();\n frame.contentWindow.document.write('\\n<' + ('script type=\"text/javascript\" src=\"https://www.googletagservices.com/tag/js/gpt.js\">\\n googletag.pubads().addEventListener(\\'slotRenderEnded\\', function(e) { \\n trackImpression(e);\\n });\\n googletag.pubads()\\n .definePassback(\"' + adUnitPath.replace(/\"/g, '\\\\\"') + '\", [[' + size.width + ', ' + size.height + ']])\\n .setClickUrl(\"' + clickUrl + '&u=\")\\n .display();\\n<') + '/script>\\n');\n frame.contentWindow.document.close();\n\n // TODO future event hooks\n // googletag.pubads().addEventListener('impressionViewable', function(e) { future )});\n // googletag.pubads().addEventListener('slotOnload', function(e) { future });\n // googletag.pubads().addEventListener('slotVisibilityChangedEvent', function(e) { future );\n\n // Impression tracking is done from within the iframe. Crazy, right?\n }\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n //endregion\n\n }]);\n\n return Placement;\n }(okanjo._Widget);\n\n //region Enumerations\n\n /**\n * Standard ad sizes\n * @type {{billboard: {width: number, height: number}, button_2: {width: number, height: number}, half_page: {width: number, height: number}, leaderboard: {width: number, height: number}, medium_rectangle: {width: number, height: number}, micro_bar: {width: number, height: number}, portrait: {width: number, height: number}, rectangle: {width: number, height: number}, super_leaderboard: {width: number, height: number}, wide_skyscraper: {width: number, height: number}, large_mobile_banner: {width: number, height: number}, mobile_leaderboard: {width: number, height: number}, small_square: {width: number, height: number}, button_1: {width: number, height: number}, full_banner: {width: number, height: number}, half_banner: {width: number, height: number}, large_rectangle: {width: number, height: number}, pop_under: {width: number, height: number}, three_to_one_rectangle: {width: number, height: number}, skyscraper: {width: number, height: number}, square: {width: number, height: number}, square_button: {width: number, height: number}, vertical_banner: {width: number, height: number}, vertical_rectangle: {width: number, height: number}}}\n */\n\n\n Placement.Sizes = {\n\n // Supported\n medium_rectangle: { width: 300, height: 250 }, // aka: sidekick\n leaderboard: { width: 728, height: 90 },\n large_mobile_banner: { width: 320, height: 100 },\n half_page: { width: 300, height: 600 }, // aka: filmstrip, sidekick\n billboard: { width: 970, height: 250 }, // aka: sidekick\n\n // IAB / Others\n button_2: { width: 120, height: 60 },\n micro_bar: { width: 88, height: 31 },\n portrait: { width: 300, height: 1050 },\n rectangle: { width: 180, height: 150 },\n super_leaderboard: { width: 970, height: 90 }, // aka: pushdown, slider, large_leaderboard\n wide_skyscraper: { width: 160, height: 600 },\n\n // Google\n mobile_leaderboard: { width: 320, height: 50 },\n small_square: { width: 200, height: 200 },\n\n // Retired / Deprecated\n button_1: { width: 120, height: 90 },\n full_banner: { width: 468, height: 60 },\n half_banner: { width: 234, height: 60 },\n large_rectangle: { width: 336, height: 280 },\n pop_under: { width: 720, height: 300 },\n three_to_one_rectangle: { width: 300, height: 100 },\n skyscraper: { width: 120, height: 600 },\n square: { width: 250, height: 250 },\n square_button: { width: 125, height: 125 },\n vertical_banner: { width: 120, height: 240 },\n vertical_rectangle: { width: 240, height: 400 }\n };\n\n // When we should show an ad but nobody told us what size\n Placement.Sizes.default = Placement.Sizes.medium_rectangle;\n\n /**\n * Placement content types\n * @type {{products: string, articles: string, adx: string}}\n */\n Placement.ContentTypes = {\n products: 'products',\n articles: 'articles',\n adx: 'adx'\n };\n\n /**\n * Default templates for each content type\n * @type {{products: string, articles: string, adx: string}}\n */\n Placement.DefaultTemplates = {\n products: 'block2',\n articles: 'block2',\n adx: 'block2'\n };\n\n //endregion\n\n return okanjo.Placement = Placement;\n})(window);\n\"use strict\";\n\n// **********\n// DEPRECATED - USE okanjo.Placement instead!\n// **********\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window) {\n\n var okanjo = window.okanjo;\n\n /**\n * Backwards compatible interface, turning a Product widget into a placement widget\n * @deprecated\n */\n\n var Product = function (_okanjo$Placement) {\n _inherits(Product, _okanjo$Placement);\n\n function Product(element, options) {\n _classCallCheck(this, Product);\n\n // Initialize placement w/o loading (we need to jack the config)\n options = options || {};\n var no_init = options.no_init; // hold original no_init flag, if set\n options.no_init = true;\n\n var _this19 = _possibleConstructorReturn(this, (Product.__proto__ || Object.getPrototypeOf(Product)).call(this, element, options));\n\n okanjo.warn('Product widget has been deprecated. Use Placement instead (may require configuration changes)', { widget: _this19 });\n\n // Start loading content\n if (!no_init) {\n delete _this19.config.no_init;\n _this19.init();\n }\n return _this19;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Converts the old product widget configuration into a usable placement configuration\n */\n\n\n _createClass(Product, [{\n key: '_setCompatibilityOptions',\n value: function _setCompatibilityOptions() {\n // Convert the product config to a placement configuration\n this.config.backwards = 'Product';\n this.config.type = okanjo.Placement.ContentTypes.products;\n\n // Set filters based on old \"mode\"\n if (this.config.mode === 'sense') {\n // sense\n this.config.url = this.config.url || 'referrer';\n this.config.take = this.config.take || 5;\n } else if (this.config.mode === 'single') {\n // single\n this.config.url = null;\n if (this.config.id) this.config.ids = [this.config.id];\n this.config.take = 1;\n delete this.config.id;\n } else {\n // browse\n this.config.url = null;\n this.config.take = this.config.take || 25;\n }\n delete this.config.mode;\n\n // Sold by changed to store name\n if (this.config.sold_by) {\n this.config.store_name = this.config.sold_by;\n delete this.config.sold_by;\n }\n\n // Selectors is now url_selectors\n if (this.config.selectors) {\n this.config.url_selectors = this.config.selectors;\n delete this.config.selectors;\n }\n\n // Marketplace_id is no longer a thing, closest analog are properties.\n if (this.config.marketplace_id) {\n this.config.property_id = this.config.marketplace_id;\n delete this.config.marketplace_id;\n }\n\n // Marketplace status is no longer a thing, instead, use the sandbox environment for testing\n if (this.config.marketplace_status === 'testing') {\n this.config.sandbox = true;\n }\n delete this.config.marketplace_status;\n\n // Deprecated\n delete this.config.suboptimal;\n delete this.config.text;\n }\n }]);\n\n return Product;\n }(okanjo.Placement);\n\n return okanjo.Product = Product;\n})(window);\n\"use strict\";\n\n// **********\n// DEPRECATED - USE okanjo.Placement instead!\n// **********\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function (window) {\n\n var okanjo = window.okanjo;\n\n /**\n * Backwards compatible interface, turning an Ad widget into a placement widget\n * @deprecated\n */\n\n var Ad = function (_okanjo$Placement2) {\n _inherits(Ad, _okanjo$Placement2);\n\n function Ad(element, options) {\n _classCallCheck(this, Ad);\n\n // Initialize placement w/o loading (we need to jack the config)\n options = options || {};\n var no_init = options.no_init; // hold original no_init flag, if set\n options.no_init = true;\n\n var _this20 = _possibleConstructorReturn(this, (Ad.__proto__ || Object.getPrototypeOf(Ad)).call(this, element, options));\n\n okanjo.warn('Ad widget has been deprecated. Use Placement instead (may require configuration changes)', { widget: _this20 });\n\n // Start loading content\n if (!no_init) {\n delete _this20.config.no_init;\n _this20.init();\n }\n return _this20;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Converts the old product widget configuration into a usable placement configuration\n */\n\n\n _createClass(Ad, [{\n key: '_setCompatibilityOptions',\n value: function _setCompatibilityOptions() {\n // Convert the product config to a placement configuration\n this.config.backwards = 'Ad';\n this.config.type = okanjo.Placement.ContentTypes.products;\n\n // Id / single mode is now ids\n this.config.url = null;\n if (this.config.id) {\n this.config.ids = [this.config.id];\n } else {\n okanjo.warn('Ad widget should have parameter `id` set.');\n }\n this.config.take = 1;\n delete this.config.id;\n\n // Content is automatically determined whether the placement element contains children\n delete this.config.content;\n }\n }]);\n\n return Ad;\n }(okanjo.Placement);\n\n return okanjo.Ad = Ad;\n})(window);\n/* jshint ignore:start */\n\n(function () {\n\n /*!\n * mustache.js - Logic-less {{mustache}} templates with JavaScript\n * http://github.com/janl/mustache.js\n */\n\n /*global define: false Mustache: true*/\n\n (function defineMustache(global, factory) {\n if ((typeof exports === 'undefined' ? 'undefined' : _typeof(exports)) === 'object' && exports && typeof exports.nodeName !== 'string') {\n factory(exports); // CommonJS\n } else if (typeof define === 'function' && define.amd) {\n define(['exports'], factory); // AMD\n } else {\n global.Mustache = {};\n factory(global.Mustache); // script, wsh, asp\n }\n })(this, function mustacheFactory(mustache) {\n\n var objectToString = Object.prototype.toString;\n var isArray = Array.isArray || function isArrayPolyfill(object) {\n return objectToString.call(object) === '[object Array]';\n };\n\n function isFunction(object) {\n return typeof object === 'function';\n }\n\n /**\n * More correct typeof string handling array\n * which normally returns typeof 'object'\n */\n function typeStr(obj) {\n return isArray(obj) ? 'array' : typeof obj === 'undefined' ? 'undefined' : _typeof(obj);\n }\n\n function escapeRegExp(string) {\n return string.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, '\\\\$&');\n }\n\n /**\n * Null safe way of checking whether or not an object,\n * including its prototype, has a given property\n */\n function hasProperty(obj, propName) {\n return obj != null && (typeof obj === 'undefined' ? 'undefined' : _typeof(obj)) === 'object' && propName in obj;\n }\n\n // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577\n // See https://github.com/janl/mustache.js/issues/189\n var regExpTest = RegExp.prototype.test;\n function testRegExp(re, string) {\n return regExpTest.call(re, string);\n }\n\n var nonSpaceRe = /\\S/;\n function isWhitespace(string) {\n return !testRegExp(nonSpaceRe, string);\n }\n\n var entityMap = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n '/': '/',\n '`': '`',\n '=': '='\n };\n\n function escapeHtml(string) {\n return String(string).replace(/[&<>\"'`=\\/]/g, function fromEntityMap(s) {\n return entityMap[s];\n });\n }\n\n var whiteRe = /\\s*/;\n var spaceRe = /\\s+/;\n var equalsRe = /\\s*=/;\n var curlyRe = /\\s*\\}/;\n var tagRe = /#|\\^|\\/|>|\\{|&|=|!/;\n\n /**\n * Breaks up the given `template` string into a tree of tokens. If the `tags`\n * argument is given here it must be an array with two string values: the\n * opening and closing tags used in the template (e.g. [ \"<%\", \"%>\" ]). Of\n * course, the default is to use mustaches (i.e. mustache.tags).\n *\n * A token is an array with at least 4 elements. The first element is the\n * mustache symbol that was used inside the tag, e.g. \"#\" or \"&\". If the tag\n * did not contain a symbol (i.e. {{myValue}}) this element is \"name\". For\n * all text that appears outside a symbol this element is \"text\".\n *\n * The second element of a token is its \"value\". For mustache tags this is\n * whatever else was inside the tag besides the opening symbol. For text tokens\n * this is the text itself.\n *\n * The third and fourth elements of the token are the start and end indices,\n * respectively, of the token in the original template.\n *\n * Tokens that are the root node of a subtree contain two more elements: 1) an\n * array of tokens in the subtree and 2) the index in the original template at\n * which the closing tag for that section begins.\n */\n function parseTemplate(template, tags) {\n if (!template) return [];\n\n var sections = []; // Stack to hold section tokens\n var tokens = []; // Buffer to hold the tokens\n var spaces = []; // Indices of whitespace tokens on the current line\n var hasTag = false; // Is there a {{tag}} on the current line?\n var nonSpace = false; // Is there a non-space char on the current line?\n\n // Strips all whitespace tokens array for the current line\n // if there was a {{#tag}} on it and otherwise only space.\n function stripSpace() {\n if (hasTag && !nonSpace) {\n while (spaces.length) {\n delete tokens[spaces.pop()];\n }\n } else {\n spaces = [];\n }\n\n hasTag = false;\n nonSpace = false;\n }\n\n var openingTagRe, closingTagRe, closingCurlyRe;\n function compileTags(tagsToCompile) {\n if (typeof tagsToCompile === 'string') tagsToCompile = tagsToCompile.split(spaceRe, 2);\n\n if (!isArray(tagsToCompile) || tagsToCompile.length !== 2) throw new Error('Invalid tags: ' + tagsToCompile);\n\n openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\\\s*');\n closingTagRe = new RegExp('\\\\s*' + escapeRegExp(tagsToCompile[1]));\n closingCurlyRe = new RegExp('\\\\s*' + escapeRegExp('}' + tagsToCompile[1]));\n }\n\n compileTags(tags || mustache.tags);\n\n var scanner = new Scanner(template);\n\n var start, type, value, chr, token, openSection;\n while (!scanner.eos()) {\n start = scanner.pos;\n\n // Match any text between tags.\n value = scanner.scanUntil(openingTagRe);\n\n if (value) {\n for (var i = 0, valueLength = value.length; i < valueLength; ++i) {\n chr = value.charAt(i);\n\n if (isWhitespace(chr)) {\n spaces.push(tokens.length);\n } else {\n nonSpace = true;\n }\n\n tokens.push(['text', chr, start, start + 1]);\n start += 1;\n\n // Check for whitespace on the current line.\n if (chr === '\\n') stripSpace();\n }\n }\n\n // Match the opening tag.\n if (!scanner.scan(openingTagRe)) break;\n\n hasTag = true;\n\n // Get the tag type.\n type = scanner.scan(tagRe) || 'name';\n scanner.scan(whiteRe);\n\n // Get the tag value.\n if (type === '=') {\n value = scanner.scanUntil(equalsRe);\n scanner.scan(equalsRe);\n scanner.scanUntil(closingTagRe);\n } else if (type === '{') {\n value = scanner.scanUntil(closingCurlyRe);\n scanner.scan(curlyRe);\n scanner.scanUntil(closingTagRe);\n type = '&';\n } else {\n value = scanner.scanUntil(closingTagRe);\n }\n\n // Match the closing tag.\n if (!scanner.scan(closingTagRe)) throw new Error('Unclosed tag at ' + scanner.pos);\n\n token = [type, value, start, scanner.pos];\n tokens.push(token);\n\n if (type === '#' || type === '^') {\n sections.push(token);\n } else if (type === '/') {\n // Check section nesting.\n openSection = sections.pop();\n\n if (!openSection) throw new Error('Unopened section \"' + value + '\" at ' + start);\n\n if (openSection[1] !== value) throw new Error('Unclosed section \"' + openSection[1] + '\" at ' + start);\n } else if (type === 'name' || type === '{' || type === '&') {\n nonSpace = true;\n } else if (type === '=') {\n // Set the tags for the next time around.\n compileTags(value);\n }\n }\n\n // Make sure there are no open sections when we're done.\n openSection = sections.pop();\n\n if (openSection) throw new Error('Unclosed section \"' + openSection[1] + '\" at ' + scanner.pos);\n\n return nestTokens(squashTokens(tokens));\n }\n\n /**\n * Combines the values of consecutive text tokens in the given `tokens` array\n * to a single token.\n */\n function squashTokens(tokens) {\n var squashedTokens = [];\n\n var token, lastToken;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n token = tokens[i];\n\n if (token) {\n if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {\n lastToken[1] += token[1];\n lastToken[3] = token[3];\n } else {\n squashedTokens.push(token);\n lastToken = token;\n }\n }\n }\n\n return squashedTokens;\n }\n\n /**\n * Forms the given array of `tokens` into a nested tree structure where\n * tokens that represent a section have two additional items: 1) an array of\n * all tokens that appear in that section and 2) the index in the original\n * template that represents the end of that section.\n */\n function nestTokens(tokens) {\n var nestedTokens = [];\n var collector = nestedTokens;\n var sections = [];\n\n var token, section;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n token = tokens[i];\n\n switch (token[0]) {\n case '#':\n case '^':\n collector.push(token);\n sections.push(token);\n collector = token[4] = [];\n break;\n case '/':\n section = sections.pop();\n section[5] = token[2];\n collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;\n break;\n default:\n collector.push(token);\n }\n }\n\n return nestedTokens;\n }\n\n /**\n * A simple string scanner that is used by the template parser to find\n * tokens in template strings.\n */\n function Scanner(string) {\n this.string = string;\n this.tail = string;\n this.pos = 0;\n }\n\n /**\n * Returns `true` if the tail is empty (end of string).\n */\n Scanner.prototype.eos = function eos() {\n return this.tail === '';\n };\n\n /**\n * Tries to match the given regular expression at the current position.\n * Returns the matched text if it can match, the empty string otherwise.\n */\n Scanner.prototype.scan = function scan(re) {\n var match = this.tail.match(re);\n\n if (!match || match.index !== 0) return '';\n\n var string = match[0];\n\n this.tail = this.tail.substring(string.length);\n this.pos += string.length;\n\n return string;\n };\n\n /**\n * Skips all text until the given regular expression can be matched. Returns\n * the skipped string, which is the entire tail if no match can be made.\n */\n Scanner.prototype.scanUntil = function scanUntil(re) {\n var index = this.tail.search(re),\n match;\n\n switch (index) {\n case -1:\n match = this.tail;\n this.tail = '';\n break;\n case 0:\n match = '';\n break;\n default:\n match = this.tail.substring(0, index);\n this.tail = this.tail.substring(index);\n }\n\n this.pos += match.length;\n\n return match;\n };\n\n /**\n * Represents a rendering context by wrapping a view object and\n * maintaining a reference to the parent context.\n */\n function Context(view, parentContext) {\n this.view = view;\n this.cache = { '.': this.view };\n this.parent = parentContext;\n }\n\n /**\n * Creates a new context using the given view with this context\n * as the parent.\n */\n Context.prototype.push = function push(view) {\n return new Context(view, this);\n };\n\n /**\n * Returns the value of the given name in this context, traversing\n * up the context hierarchy if the value is absent in this context's view.\n */\n Context.prototype.lookup = function lookup(name) {\n var cache = this.cache;\n\n var value;\n if (cache.hasOwnProperty(name)) {\n value = cache[name];\n } else {\n var context = this,\n names,\n index,\n lookupHit = false;\n\n while (context) {\n if (name.indexOf('.') > 0) {\n value = context.view;\n names = name.split('.');\n index = 0;\n\n /**\n * Using the dot notion path in `name`, we descend through the\n * nested objects.\n *\n * To be certain that the lookup has been successful, we have to\n * check if the last object in the path actually has the property\n * we are looking for. We store the result in `lookupHit`.\n *\n * This is specially necessary for when the value has been set to\n * `undefined` and we want to avoid looking up parent contexts.\n **/\n while (value != null && index < names.length) {\n if (index === names.length - 1) lookupHit = hasProperty(value, names[index]);\n\n value = value[names[index++]];\n }\n } else {\n value = context.view[name];\n lookupHit = hasProperty(context.view, name);\n }\n\n if (lookupHit) break;\n\n context = context.parent;\n }\n\n cache[name] = value;\n }\n\n if (isFunction(value)) value = value.call(this.view);\n\n return value;\n };\n\n /**\n * A Writer knows how to take a stream of tokens and render them to a\n * string, given a context. It also maintains a cache of templates to\n * avoid the need to parse the same template twice.\n */\n function Writer() {\n this.cache = {};\n }\n\n /**\n * Clears all cached templates in this writer.\n */\n Writer.prototype.clearCache = function clearCache() {\n this.cache = {};\n };\n\n /**\n * Parses and caches the given `template` and returns the array of tokens\n * that is generated from the parse.\n */\n Writer.prototype.parse = function parse(template, tags) {\n var cache = this.cache;\n var tokens = cache[template];\n\n if (tokens == null) tokens = cache[template] = parseTemplate(template, tags);\n\n return tokens;\n };\n\n /**\n * High-level method that is used to render the given `template` with\n * the given `view`.\n *\n * The optional `partials` argument may be an object that contains the\n * names and templates of partials that are used in the template. It may\n * also be a function that is used to load partial templates on the fly\n * that takes a single argument: the name of the partial.\n */\n Writer.prototype.render = function render(template, view, partials) {\n var tokens = this.parse(template);\n var context = view instanceof Context ? view : new Context(view);\n return this.renderTokens(tokens, context, partials, template);\n };\n\n /**\n * Low-level method that renders the given array of `tokens` using\n * the given `context` and `partials`.\n *\n * Note: The `originalTemplate` is only ever used to extract the portion\n * of the original template that was contained in a higher-order section.\n * If the template doesn't use higher-order sections, this argument may\n * be omitted.\n */\n Writer.prototype.renderTokens = function renderTokens(tokens, context, partials, originalTemplate) {\n var buffer = '';\n\n var token, symbol, value;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n value = undefined;\n token = tokens[i];\n symbol = token[0];\n\n if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);else if (symbol === '&') value = this.unescapedValue(token, context);else if (symbol === 'name') value = this.escapedValue(token, context);else if (symbol === 'text') value = this.rawValue(token);\n\n if (value !== undefined) buffer += value;\n }\n\n return buffer;\n };\n\n Writer.prototype.renderSection = function renderSection(token, context, partials, originalTemplate) {\n var self = this;\n var buffer = '';\n var value = context.lookup(token[1]);\n\n // This function is used to render an arbitrary template\n // in the current context by higher-order sections.\n function subRender(template) {\n return self.render(template, context, partials);\n }\n\n if (!value) return;\n\n if (isArray(value)) {\n for (var j = 0, valueLength = value.length; j < valueLength; ++j) {\n buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);\n }\n } else if ((typeof value === 'undefined' ? 'undefined' : _typeof(value)) === 'object' || typeof value === 'string' || typeof value === 'number') {\n buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);\n } else if (isFunction(value)) {\n if (typeof originalTemplate !== 'string') throw new Error('Cannot use higher-order sections without the original template');\n\n // Extract the portion of the original template that the section contains.\n value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);\n\n if (value != null) buffer += value;\n } else {\n buffer += this.renderTokens(token[4], context, partials, originalTemplate);\n }\n return buffer;\n };\n\n Writer.prototype.renderInverted = function renderInverted(token, context, partials, originalTemplate) {\n var value = context.lookup(token[1]);\n\n // Use JavaScript's definition of falsy. Include empty arrays.\n // See https://github.com/janl/mustache.js/issues/186\n if (!value || isArray(value) && value.length === 0) return this.renderTokens(token[4], context, partials, originalTemplate);\n };\n\n Writer.prototype.renderPartial = function renderPartial(token, context, partials) {\n if (!partials) return;\n\n var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];\n if (value != null) return this.renderTokens(this.parse(value), context, partials, value);\n };\n\n Writer.prototype.unescapedValue = function unescapedValue(token, context) {\n var value = context.lookup(token[1]);\n if (value != null) return value;\n };\n\n Writer.prototype.escapedValue = function escapedValue(token, context) {\n var value = context.lookup(token[1]);\n if (value != null) return mustache.escape(value);\n };\n\n Writer.prototype.rawValue = function rawValue(token) {\n return token[1];\n };\n\n mustache.name = 'mustache.js';\n mustache.version = '2.3.2';\n mustache.tags = ['{{', '}}'];\n\n // All high-level mustache.* functions use this writer.\n var defaultWriter = new Writer();\n\n /**\n * Clears all cached templates in the default writer.\n */\n mustache.clearCache = function clearCache() {\n return defaultWriter.clearCache();\n };\n\n /**\n * Parses and caches the given template in the default writer and returns the\n * array of tokens it contains. Doing this ahead of time avoids the need to\n * parse templates on the fly as they are rendered.\n */\n mustache.parse = function parse(template, tags) {\n return defaultWriter.parse(template, tags);\n };\n\n /**\n * Renders the `template` with the given `view` and `partials` using the\n * default writer.\n */\n mustache.render = function render(template, view, partials) {\n if (typeof template !== 'string') {\n throw new TypeError('Invalid template! Template should be a \"string\" ' + 'but \"' + typeStr(template) + '\" was given as the first ' + 'argument for mustache#render(template, view, partials)');\n }\n\n return defaultWriter.render(template, view, partials);\n };\n\n // This is here for backwards compatibility with 0.4.x.,\n /*eslint-disable */ // eslint wants camel cased function name\n mustache.to_html = function to_html(template, view, partials, send) {\n /*eslint-enable*/\n\n var result = mustache.render(template, view, partials);\n\n if (isFunction(send)) {\n send(result);\n } else {\n return result;\n }\n };\n\n // Export the escaping function so that the user may override it.\n // See https://github.com/janl/mustache.js/issues/244\n mustache.escape = escapeHtml;\n\n // Export these mainly for testing, but also for advanced usage.\n mustache.Scanner = Scanner;\n mustache.Context = Context;\n mustache.Writer = Writer;\n\n return mustache;\n });\n}).apply(okanjo.lib);\n\n/* jshint ignore:end */\nreturn okanjo;\n}));\n","// Production steps of ECMA-262, Edition 6, 22.1.2.1\nif (!Array.from) {\n Array.from = (function () {\n var toStr = Object.prototype.toString;\n var isCallable = function (fn) {\n return typeof fn === 'function' || toStr.call(fn) === '[object Function]';\n };\n var toInteger = function (value) {\n var number = Number(value);\n if (isNaN(number)) { return 0; }\n if (number === 0 || !isFinite(number)) { return number; }\n return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number));\n };\n var maxSafeInteger = Math.pow(2, 53) - 1;\n var toLength = function (value) {\n var len = toInteger(value);\n return Math.min(Math.max(len, 0), maxSafeInteger);\n };\n\n // The length property of the from method is 1.\n return function from(arrayLike/*, mapFn, thisArg */) {\n // 1. Let C be the this value.\n var C = this;\n\n // 2. Let items be ToObject(arrayLike).\n var items = Object(arrayLike);\n\n // 3. ReturnIfAbrupt(items).\n if (arrayLike == null) {\n throw new TypeError('Array.from requires an array-like object - not null or undefined');\n }\n\n // 4. If mapfn is undefined, then let mapping be false.\n var mapFn = arguments.length > 1 ? arguments[1] : void undefined;\n var T;\n if (typeof mapFn !== 'undefined') {\n // 5. else\n // 5. a If IsCallable(mapfn) is false, throw a TypeError exception.\n if (!isCallable(mapFn)) {\n throw new TypeError('Array.from: when provided, the second argument must be a function');\n }\n\n // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined.\n if (arguments.length > 2) {\n T = arguments[2];\n }\n }\n\n // 10. Let lenValue be Get(items, \"length\").\n // 11. Let len be ToLength(lenValue).\n var len = toLength(items.length);\n\n // 13. If IsConstructor(C) is true, then\n // 13. a. Let A be the result of calling the [[Construct]] internal method\n // of C with an argument list containing the single item len.\n // 14. a. Else, Let A be ArrayCreate(len).\n var A = isCallable(C) ? Object(new C(len)) : new Array(len);\n\n // 16. Let k be 0.\n var k = 0;\n // 17. Repeat, while k < len… (also steps a - h)\n var kValue;\n while (k < len) {\n kValue = items[k];\n if (mapFn) {\n A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k);\n } else {\n A[k] = kValue;\n }\n k += 1;\n }\n // 18. Let putStatus be Put(A, \"length\", len, true).\n A.length = len;\n // 20. Return A.\n return A;\n };\n }());\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.find\nif (!Array.prototype.find) {\n Object.defineProperty(Array.prototype, 'find', {\n value: function(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return kValue.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return kValue;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return undefined.\n return undefined;\n }\n });\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.findIndex\nif (!Array.prototype.findIndex) {\n Object.defineProperty(Array.prototype, 'findIndex', {\n value: function(predicate) {\n // 1. Let O be ? ToObject(this value).\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If IsCallable(predicate) is false, throw a TypeError exception.\n if (typeof predicate !== 'function') {\n throw new TypeError('predicate must be a function');\n }\n\n // 4. If thisArg was supplied, let T be thisArg; else let T be undefined.\n var thisArg = arguments[1];\n\n // 5. Let k be 0.\n var k = 0;\n\n // 6. Repeat, while k < len\n while (k < len) {\n // a. Let Pk be ! ToString(k).\n // b. Let kValue be ? Get(O, Pk).\n // c. Let testResult be ToBoolean(? Call(predicate, T, « kValue, k, O »)).\n // d. If testResult is true, return k.\n var kValue = o[k];\n if (predicate.call(thisArg, kValue, k, o)) {\n return k;\n }\n // e. Increase k by 1.\n k++;\n }\n\n // 7. Return -1.\n return -1;\n }\n });\n}","// https://tc39.github.io/ecma262/#sec-array.prototype.includes\nif (!Array.prototype.includes) {\n Object.defineProperty(Array.prototype, 'includes', {\n value: function(searchElement, fromIndex) {\n\n if (this == null) {\n throw new TypeError('\"this\" is null or not defined');\n }\n\n // 1. Let O be ? ToObject(this value).\n var o = Object(this);\n\n // 2. Let len be ? ToLength(? Get(O, \"length\")).\n var len = o.length >>> 0;\n\n // 3. If len is 0, return false.\n if (len === 0) {\n return false;\n }\n\n // 4. Let n be ? ToInteger(fromIndex).\n // (If fromIndex is undefined, this step produces the value 0.)\n var n = fromIndex | 0;\n\n // 5. If n ≥ 0, then\n // a. Let k be n.\n // 6. Else n < 0,\n // a. Let k be len + n.\n // b. If k < 0, let k be 0.\n var k = Math.max(n >= 0 ? n : len - Math.abs(n), 0);\n\n function sameValueZero(x, y) {\n return x === y || (typeof x === 'number' && typeof y === 'number' && isNaN(x) && isNaN(y));\n }\n\n // 7. Repeat, while k < len\n while (k < len) {\n // a. Let elementK be the result of ? Get(O, ! ToString(k)).\n // b. If SameValueZero(searchElement, elementK) is true, return true.\n if (sameValueZero(o[k], searchElement)) {\n return true;\n }\n // c. Increase k by 1.\n k++;\n }\n\n // 8. Return false\n return false;\n }\n });\n}","// https://developer.mozilla.org/en-US/docs/Web/API/NodeList/forEach\nif (window.NodeList && !NodeList.prototype.forEach) {\n NodeList.prototype.forEach = function (callback, thisArg) {\n thisArg = thisArg || window;\n for (var i = 0; i < this.length; i++) {\n callback.call(thisArg, this[i], i, this);\n }\n };\n}","// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Object/assign\nif (typeof Object.assign != 'function') {\n // Must be writable: true, enumerable: false, configurable: true\n Object.defineProperty(Object, \"assign\", {\n value: function assign(target, varArgs) { // .length of function is 2\n 'use strict';\n if (target == null) { // TypeError if undefined or null\n throw new TypeError('Cannot convert undefined or null to object');\n }\n\n var to = Object(target);\n\n for (var index = 1; index < arguments.length; index++) {\n var nextSource = arguments[index];\n\n if (nextSource != null) { // Skip over if undefined or null\n for (var nextKey in nextSource) {\n // Avoid bugs when hasOwnProperty is shadowed\n if (Object.prototype.hasOwnProperty.call(nextSource, nextKey)) {\n to[nextKey] = nextSource[nextKey];\n }\n }\n }\n }\n return to;\n },\n writable: true,\n configurable: true\n });\n}","\"use strict\";\n\n/* exported okanjo */\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/**\n * Okanjo widget framework namespace\n * @global okanjo\n */\nconst okanjo = (function(window, document) {\n\n //region Constants\n\n // Environment Vars\n const SUPPORTS_PAGE_OFFSET = window.pageXOffset !== undefined;\n const CSS1_COMPATIBLE = (document.compatMode /* istanbul ignore next: out of scope */ || \"\") === \"CSS1Compat\";\n const AGENT = window.navigator.userAgent;\n const ELLIPSIFY_PATTERN = /[\\s\\S](?:\\.\\.\\.)?$/;\n const MOBILE_PATTERN = /(iPhone|iPad|iPod|Android|blackberry)/i;\n const NOOP = () => {};\n const Console = window.console;\n\n // Place to pull defaults, if already set\n const settings = window.okanjo || {};\n\n //endregion\n\n //region Okanjo Core\n\n\n //noinspection JSValidateJSDoc,JSClosureCompilerSyntax - idk phpStorm generated it so why would it be wrong? :P\n /**\n * Okanjo namespace\n * @global\n * @type {{version: string, metrics: null, key: null, report: ((...p1?:*[])), warn: ((p1?:*, ...p2?:*[])), qwery: ((p1?:*, p2?:*))}}\n */\n const okanjo = {\n\n /**\n * Okanjo version\n */\n version: \"%%OKANJO_VERSION\",\n\n /**\n * Placeholder\n */\n metrics: null,\n\n /**\n * Global/default placement key\n */\n key: settings.key || null,\n\n /**\n * Reports an error to the console and possibly Raven in the future\n * @param args\n */\n report: (...args) => {\n let err = args.find((arg) => arg instanceof Error);\n if (!err) {\n let messageIndex = args.findIndex((arg) => typeof arg === \"string\");\n err = new Error(args[messageIndex] || \"Okanjo Error\");\n if (messageIndex >= 0) args.splice(messageIndex, 1);\n } else {\n // Grow our own stack so we can figure out what async thing did it\n let stack = (new Error()).stack.split('\\n');\n stack.shift();\n stack.shift();\n args.push({ reportStack: stack.join('\\n') });\n args = args.filter((a) => a !== err);\n }\n\n Console.error(`[Okanjo v${okanjo.version}]: ${err.stack}`);\n args.length && Console.error.apply(Console, ['Additional information:'].concat(args));\n\n // TODO - integrate with Raven\n },\n\n /**\n * Warn developers of their misdeeds\n * @param message\n * @param args\n */\n warn: (message, ...args) => {\n const err = new Error(message);\n\n Console.warn(`[Okanjo v${okanjo.version}]: ${err.stack}`);\n args.length && Console.warn.apply(Console, ['Additional information:'].concat(args));\n },\n\n // Backwards compatibility when we shipped with qwery, cuz querySelector[All] wasn't mainstream enough\n qwery: (selector, parent) => {\n\n // If parent is a selector, select the parent first!\n if (typeof parent === \"string\") {\n parent = document.querySelector(parent);\n\n // If parent is not found, there are obviously no results\n if (!parent) return [];\n }\n\n if (!parent) parent = document;\n\n return parent.querySelectorAll(selector);\n }\n };\n\n //endregion\n\n //region Vendor Libs\n\n /**\n * Placeholder for where vendor libraries get no-conflict loaded\n * @type {{}}\n */\n okanjo.lib = {};\n\n //endregion\n\n //region Networking\n\n /**\n * Networking methods\n * @type {{getRoute: *, exec: *}}\n */\n okanjo.net = {\n\n /**\n * API Endpoints\n */\n endpoint: 'https://api2.okanjo.com',\n sandboxEndpoint: 'https://sandbox-api2.okanjo.com',\n\n /**\n * API routes\n */\n routes: {\n ads: '/content',\n metrics: '/metrics/:object_type/:event_type',\n metrics_batch: '/metrics'\n },\n\n /**\n * Compiles a route and parameters into a final URL\n * @param {string} route - Route constant\n * @param {*} [params] - Key value hash\n * @param {*} [env] - Optional environment to use instead of live\n * @return {string} - Route\n */\n getRoute: (route, params, env) => {\n if (params) {\n Object.keys(params).forEach((key) => {\n route = route.replace(`:${key}`, params[key]+\"\");\n });\n }\n env = env || okanjo.env || 'live';\n return (env === 'sandbox' ? okanjo.net.sandboxEndpoint : okanjo.net.endpoint) + route;\n },\n\n // placeholder, xhr request extension\n request: NOOP\n };\n\n //endregion\n\n // region Utilities\n\n //noinspection JSClosureCompilerSyntax,JSValidateJSDoc\n /**\n * Utility functions and helpers\n * @type {{isEmpty: ((p1?:*)=>boolean), isMobile: (()), getPageArguments: ((p1:boolean))}}\n */\n okanjo.util = {\n\n /**\n * Checks whether a value is _really_ empty (trims)\n * @param val\n * @return {boolean}\n */\n isEmpty: (val) => val === null || val === undefined || (typeof val === \"string\" && val.trim().length === 0),\n\n /**\n * Checks if the current user agent identifies as a mobile device\n * @returns {boolean}\n */\n isMobile: () => {\n // KludgyAF™, but let's go with it\n return MOBILE_PATTERN.test(AGENT);\n },\n\n /**\n * Returns an object hashmap of query and hash parameters\n * @param {boolean} includeHashArguments - Whether to include the hash arguments, if any\n * @return {*}\n */\n getPageArguments: (includeHashArguments) => {\n\n const split = (query) => {\n query = query || \"\";\n const params = {};\n const parts = query.split('&');\n parts.forEach((part) => {\n const eqIndex = part.indexOf('=');\n let key, value;\n if (eqIndex < 0) {\n key = decodeURIComponent(part);\n value = null;\n } else {\n key = decodeURIComponent(part.substring(0, eqIndex));\n value = decodeURIComponent(part.substring(eqIndex + 1));\n }\n if (key) params[key] = value;\n });\n return params;\n };\n\n const queryArgs = split(window.location.search.substring(window.location.search.indexOf('?') + 1));\n const hashArgs = includeHashArguments ? split(window.location.hash.substring(Math.max(window.location.hash.indexOf('#') + 1, window.location.hash.indexOf('#!') + 2))) : {};\n Object.keys(hashArgs).forEach((key) => queryArgs[key] = hashArgs[key]);\n\n return queryArgs;\n }\n\n };\n\n /**\n * Deep clones an object by breaking references, unlike Object.assign\n * @param mixed – Source to clone (object, array, value)\n * @param [out] - Existing output, if any\n * @return {*}\n */\n okanjo.util.deepClone = (mixed, out) => {\n if (Array.isArray(mixed)) {\n // Array reference\n out = out || [];\n out = out.concat(mixed.map((val) => okanjo.util.deepClone(val)));\n } else if (typeof mixed === \"object\" && mixed !== null) {\n // Object reference\n out = out || {};\n Object.keys(mixed).forEach((key) => {\n out[key] = okanjo.util.deepClone(mixed[key]);\n });\n } else {\n // Value\n out = mixed;\n }\n\n return out;\n };\n\n /**\n * Flattens a multi-dimensional object into a single object\n * @param input\n * @param [options]\n * @return {{}}\n */\n okanjo.util.flatten = (input, options = {}) => {\n const output = {};\n\n if (input !== undefined && input !== null) {\n Object\n .keys(input)\n .forEach((key) => {\n // Convert object ids to hex strings\n if (input[key] instanceof Date) {\n if (options.dateToIso) {\n output[key] = input[key].toISOString(); // convert to iso\n } else {\n output[key] = input[key]; // as-is\n }\n } else if (typeof input[key] === 'object' && input[key] !== null) {\n // Allow ignoring arrays if desired\n if (Array.isArray(input[key]) && options.ignoreArrays === true) {\n output[key] = input[key];\n } else if (Array.isArray(input[key]) && options.arrayToCsv === true) {\n output[key] = input[key].join(',');\n } else {\n // Make child objects flat too (always returns object so Object.keys is safe)\n const childObject = okanjo.util.flatten(input[key], options);\n Object\n .keys(childObject)\n .forEach((childKey) => {\n output[key + '_' + childKey] = childObject[childKey];\n })\n ;\n }\n } else {\n // Copy value references\n output[key] = input[key];\n }\n })\n ;\n }\n\n return output;\n };\n\n /*! based on shortid https://github.com/dylang/shortid */\n okanjo.util.shortid = (function(clusterWorkerId) {\n\n const shuffled = 'ylZM7VHLvOFcohp01x-fXNr8P_tqin6RkgWGm4SIDdK5s2TAJebzQEBUwuY9j3aC',\n\n crypto = window.crypto || window.msCrypto || (typeof require === \"function\" && require('crypto')),\n\n randomByte = () => {\n /* istanbul ignore next: platform diffs out of scope */\n if (crypto && crypto.randomBytes) {\n return crypto.randomBytes(1)[0] & 0x30;\n } else if (!crypto || !crypto.getRandomValues) {\n return Math.floor(Math.random() * 256) & 0x30;\n }\n /* istanbul ignore next: platform diffs out of scope */\n const dest = new Uint8Array(1);\n /* istanbul ignore next: platform diffs out of scope */\n crypto.getRandomValues(dest);\n /* istanbul ignore next: platform diffs out of scope */\n return dest[0] & 0x30;\n },\n\n encode = (number) => {\n let loopCounter = 0,\n done,\n str = '';\n\n while (!done) {\n str = str + shuffled[ ( (number >> (4 * loopCounter)) & 0x0f ) | randomByte() ];\n done = number < (Math.pow(16, loopCounter + 1 ) );\n loopCounter++;\n }\n return str;\n },\n\n // Ignore all milliseconds before a certain time to reduce the size of the date entropy without sacrificing uniqueness.\n // This number should be updated every year or so to keep the generated id short.\n // To regenerate `new Date() - 0` and bump the version. Always bump the version!\n\n REDUCE_TIME = 1490384907498,\n version = 7;\n\n let counter,\n previousSeconds;\n\n clusterWorkerId = clusterWorkerId || 0;\n\n return function() {\n let str = '',\n seconds = Math.floor(((new Date()).getTime() - REDUCE_TIME) * 0.001);\n\n if (seconds === previousSeconds) {\n counter++;\n } else {\n counter = 0;\n previousSeconds = seconds;\n }\n\n str = str + encode(version) + encode(clusterWorkerId);\n if (counter > 0) {\n str = str + encode(counter);\n }\n str = str + encode(seconds);\n\n return str;\n };\n })();\n\n /**\n * Gets the best URL for where we are operating\n * @returns {string|*}\n */\n okanjo.util.getLocation = () => window.location !== window.parent.location ? /* istanbul ignore next: oos */ document.referrer : document.location.href;\n\n //endregion\n\n //region User Interface\n\n okanjo.ui = {\n\n /**\n * Gets the current page scroll position\n * @returns {{x: Number, y: Number}}\n */\n getScrollPosition: () => {\n return {\n x: SUPPORTS_PAGE_OFFSET ? window.pageXOffset : /* istanbul ignore next: old browsers */ CSS1_COMPATIBLE ? document.documentElement.scrollLeft : document.body.scrollLeft,\n y: SUPPORTS_PAGE_OFFSET ? window.pageYOffset : /* istanbul ignore next: old browsers */ CSS1_COMPATIBLE ? document.documentElement.scrollTop : document.body.scrollTop\n };\n },\n\n /**\n * Gets the height and width of the given element\n * @param {HTMLElement|Node} element – The DOM element to get the size of\n * @param {boolean} [includeMargin] – Whether to include the margins of the element in the size\n * @returns {{height: number, width: number}}\n */\n getElementSize: (element, includeMargin) => {\n const size = {\n height: element.offsetHeight,\n width : element.offsetWidth\n };\n const style = element.currentStyle || window.getComputedStyle(element);\n\n if (includeMargin) {\n size.height += parseInt(style.marginTop) + parseInt(style.marginBottom);\n size.width += parseInt(style.marginLeft) + parseInt(style.marginRight);\n }\n\n return size;\n },\n\n /**\n * Gets the current page size\n * @return {{w: number, h: number}}\n */\n getPageSize: () => {\n const body = document.querySelector('body');\n const html = document.documentElement;\n\n return {\n w: Math.max(\n body.scrollWidth,\n body.offsetWidth,\n html.clientWidth,\n html.scrollWidth,\n html.offsetWidth\n ),\n\n h: Math.max(\n body.scrollHeight,\n body.offsetHeight,\n html.clientHeight,\n html.scrollHeight,\n html.offsetHeight\n )\n };\n },\n\n /**\n * Gets the current viewport size\n * @return {{vw: number, vh: number}}\n */\n getViewportSize: () => {\n const element = CSS1_COMPATIBLE ? document.documentElement /* istanbul ignore next: browser diffs */: document.body;\n const width = element.clientWidth;\n const height = element.clientHeight;\n const inWidth = window.innerWidth /* istanbul ignore next: browser diffs */ || 0;\n const inHeight = window.innerHeight /* istanbul ignore next: browser diffs */ || 0;\n const isMobileZoom = (inWidth && width > inWidth) || (inHeight && height > inHeight);\n\n return {\n vw: isMobileZoom /* istanbul ignore next: browser diffs */ ? inWidth : width,\n vh: isMobileZoom /* istanbul ignore next: browser diffs */ ? inHeight : height\n };\n },\n\n /**\n * Gets the x, y location of the event relative to the page\n * @param event – Mouse/Touch Event\n * @return {{ex: number, ey: number}}\n */\n getEventPosition: (event) => {\n const ex = event.pageX;\n const ey = event.pageY;\n const body = document.body;\n const el = document.documentElement;\n const scrollLeft = 'scrollLeft';\n const scrollTop = 'scrollTop';\n const type = event.__proto__.constructor.name;\n\n return {\n et: type, // mouse? touch? keyboard? robot?\n ex: ex === undefined /* istanbul ignore next: browser diffs */ ? event.clientX + body[scrollLeft] + el[scrollLeft] : ex,\n ey: ey === undefined /* istanbul ignore next: browser diffs */ ? event.clientY + body[scrollTop] + el[scrollTop] : ey\n };\n },\n\n /**\n * Gets the element's rectangle coordinates on the page\n * @param element\n * @return {{x1: number, y1: number, x2: number, y2: number}}\n */\n getElementPosition: (element) => {\n\n // Wrapped in try-catch because IE is super strict about the\n // element being on the DOM before you call this. Other browsers\n // let it slide, but oh well.\n\n const err = 'Could not get position of element. Did you attach the element to the DOM before initializing?';\n try {\n let rect = element.getBoundingClientRect();\n let body = document.body.getBoundingClientRect();\n // let pos = okanjo.ui.getScrollPosition();\n\n /* istanbul ignore else: jsdom doesn't mock this */\n if (!document.body.contains(element)) {\n okanjo.report(err, element);\n }\n return {\n // x1: rect.left + pos.x,\n // y1: rect.top + pos.y,\n // x2: rect.right + pos.x,\n // y2: rect.bottom + pos.y\n\n // This might fix\n x1: rect.left - body.left,\n y1: rect.top - body.top,\n x2: rect.right - body.left,\n y2: rect.bottom - body.top,\n\n };\n } catch (e) {\n okanjo.report(err, { exception: e, element });\n return {\n x1: 0,\n y1: 0,\n x2: 0,\n y2: 0,\n err: 1\n };\n }\n },\n\n /**\n * Gets the intersection information given the element, viewport and scroll positions\n * @param e – Element position\n * @param s - Scroll position\n * @param v - Viewport size\n * @return {{intersectionArea: number, elementArea: number}}\n * @private\n */\n _getIntersection: (e, s, v) => {\n let iLeft = Math.max(e.x1, s.x),\n iRight = Math.min(e.x2, s.x+v.vw),\n iTop = Math.max(e.y1, s.y),\n iBottom = Math.min(e.y2, s.y+v.vh),\n\n intersectionArea = Math.max(0, iRight - iLeft) * Math.max(0, iBottom - iTop),\n elementArea = (e.x2 - e.x1) * (e.y2 - e.y1);\n\n return {\n intersectionArea,\n elementArea\n };\n },\n\n /**\n * Checks whether the element is actually displayed on the DOM\n * @param element\n * @return {boolean}\n */\n isElementVisible: (element) => {\n /* istanbul ignore next: jsdom won't trigger this */\n return element.offsetWidth > 0 && element.offsetHeight > 0;\n },\n\n /**\n * Gets the percentage of the element pixels currently within the viewport\n * @param {HTMLElement|Node} element\n * @return {number}\n */\n getPercentageInViewport: (element) => {\n let e = okanjo.ui.getElementPosition(element),\n s = okanjo.ui.getScrollPosition(),\n v = okanjo.ui.getViewportSize();\n\n // If there was a problem getting the element position, fail fast\n if (e.err) return 0;\n\n // Get intersection rectangle\n let { intersectionArea, elementArea } = okanjo.ui._getIntersection(e,s,v);\n\n // Don't let it return NaN\n /* istanbul ignore else: jsdom no love positional data */\n if (elementArea <= 0) return 0;\n\n /* istanbul ignore next: jsdom no love positional data, area tested with helper fn tho */\n return intersectionArea / elementArea;\n }\n };\n\n /**\n * Splits the text in the element to fit within the visible height of its container, and separates with an ellipses\n * @param {HTMLElement|Node} element – The DOM element containing the text to fit\n * @param {HTMLElement} [container] – Optional container to compute fit on. Defaults to the element's parent\n */\n okanjo.ui.ellipsify = function(element, container) {\n\n // It's a sad day when you have to resort to JS because CSS kludges are too hacky to work down to IE8, programmatically\n\n //noinspection JSValidateTypes\n const parent = container || element.parentNode,\n targetHeight = okanjo.ui.getElementSize(parent).height,\n useTextContent = element.textContent !== undefined;\n\n let text = useTextContent ? element.textContent /* istanbul ignore next: browser diffs */ : element.innerText,\n replacedText = \"\",\n safety = 5000, // Safety switch to bust out of the loop in the event something goes terribly wrong\n replacer = (match) => {\n /* istanbul ignore next: n/a to jsdom */\n replacedText = match.substr(0, match.length-3) + replacedText;\n /* istanbul ignore next: n/a to jsdom */\n return '...';\n };\n\n // Trim off characters until we can fit the text and ellipses\n // If the text already fits, this loop is ignored\n /* istanbul ignore next: jsdom doesn't do element size computing stuff */\n while (okanjo.ui.getElementSize(element).height > targetHeight && text.length > 0 && (safety-- > 0)) {\n text = useTextContent ? element.textContent : element.innerText;\n\n text = text.replace(ELLIPSIFY_PATTERN, replacer);\n\n if (useTextContent) {\n element.textContent = text;\n } else {\n element.innerText = text;\n }\n }\n\n // If there is work to do, split the content into two span tags\n // Like so: [content]...[hidden content]\n /* istanbul ignore if: n/a to jsdom */\n if (replacedText.length > 0) {\n\n let content = document.createElement('span'),\n span = document.createElement('span');\n\n content.setAttribute('class','okanjo-ellipses');\n span.setAttribute('class','okanjo-visually-hidden');\n\n if (useTextContent) {\n content.textContent = text.substr(0, text.length-3);\n span.textContent = replacedText;\n } else {\n content.innerText = text.substr(0, text.length-3);\n span.innerText = replacedText;\n }\n\n element.innerHTML = '';\n element.appendChild(content);\n element.appendChild(span);\n }\n\n };\n\n /**\n * Locates images with the class okanjo-fit and ensures that they get filled.\n * This is basically a object-fit hacky workaround\n * @param element\n */\n okanjo.ui.fitImages = function(element) {\n // Detect objectFit support\n /* istanbul ignore else: n/a to jsdom */\n if ('objectFit' in document.documentElement.style === false) {\n // Find images to fit\n element.querySelectorAll('img.okanjo-fit').forEach((img) => {\n\n // Hide the image\n img.style.display = 'none';\n\n // Update the parent w/ the background\n let parent = img.parentNode;\n parent.style.backgroundSize = 'cover';\n parent.style.backgroundImage = 'url('+img.src+')';\n parent.style.backgroundposition = 'center center';\n });\n }\n };\n\n //endregion\n\n // Export the root namespace\n return window.okanjo = okanjo;\n\n})(window, document);","\"use strict\";\n\n(function(window) {\n\n const JSON_TEST = /^application\\/json/;\n const okanjo = window.okanjo;\n\n /**\n * Performs a reliable XHR request\n * @param {string} method - Request method\n * @param {string} url - URL\n * @param [payload] optional payload\n * @param callback Fired on when completed (err, res), normalized to standard response format\n */\n okanjo.net.request = function (method, url, payload, callback) {\n\n // payload is not required\n if (typeof payload === \"function\") {\n callback = payload;\n payload = undefined;\n }\n\n // Create a new instance\n const req = new (window.XMLHttpRequest /* istanbul ignore next: old ie */ || window.ActiveXObject)('MSXML2.XMLHTTP.3.0');\n\n // Flag to prevent duplicate callbacks / races\n let calledBack = false;\n\n // Normalized done handler\n const done = function(err, res) {\n /* istanbul ignore else: out of scope */\n if (!calledBack) {\n calledBack = true;\n callback(err, res);\n }\n };\n\n // Apply timeout if configured globally\n if (okanjo.net.request.timeout) {\n req.timeout = okanjo.net.request.timeout;\n }\n\n // Catch timeout errors\n req.ontimeout = function(e) {\n /* istanbul ignore next: idk if jsdom can mock this, also readystatechange may fire before this anyway */\n done({\n statusCode: 504,\n error: \"Request timed out\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n };\n\n // Handle the response\n req.onreadystatechange = function(e) {\n // 4 = completed / failed\n if (req.readyState === 4) {\n // Do we have a response?\n if (req.status > 0) {\n let res;\n\n // Check if we got JSON and parse it right away\n if (JSON_TEST.test(req.getResponseHeader('Content-Type'))) {\n res = JSON.parse(req.responseText);\n } else {\n // Not JSON, normalize it instead\n res = {\n statusCode: req.status,\n data: req.responseText\n };\n }\n\n // Put the response in the proper slot (err for non success responses)\n if (req.status >= 200 && req.status < 300) {\n done(null, res);\n } else {\n done(res);\n }\n } else {\n // Request failed - e.g. CORS or network issues\n done({\n statusCode: 503,\n error: \"Request failed\",\n message: 'Something went wrong',\n attributes: {\n event: e,\n xhr: req\n }\n });\n }\n }\n };\n\n // Open the request\n req.open(method.toUpperCase(), url);\n\n // Include credentials\n req.withCredentials = true;\n\n // Handle post payloads\n if (['POST','PUT','PATCH'].includes(method.toUpperCase())) {\n req.setRequestHeader('Content-Type', 'application/json; charset=utf-8');\n if (payload !== undefined) {\n payload = JSON.stringify(payload);\n }\n }\n\n // Ship it\n req.send(payload || undefined);\n };\n\n // Bind helpers to make things easy as pie\n okanjo.net.request.get = okanjo.net.request.bind(this, 'GET');\n okanjo.net.request.post = okanjo.net.request.bind(this, 'POST');\n okanjo.net.request.put = okanjo.net.request.bind(this, 'PUT');\n okanjo.net.request.delete = okanjo.net.request.bind(this, 'DELETE');\n\n /**\n * Helper to aid in minificiation+querystringify and redundant encodeURIComponent stuff\n * @param val\n * @return {*}\n */\n const encode = (val) => {\n if (val === null || val === undefined) return '';\n return encodeURIComponent(''+val);\n };\n\n /**\n * Helper to aid in getting a query string key using a prefix and keyname\n * @param key\n * @param keyPrefix\n * @return {*}\n */\n const getKey = (key, keyPrefix) => {\n if (keyPrefix) {\n return `${keyPrefix}[${encode(key)}]`;\n } else {\n return encode(key)\n }\n };\n\n /**\n * Super basic querystringify helper. It handles deep objects, but not for array values\n * @param obj\n * @param [keyPrefix]\n * @return {string}\n */\n okanjo.net.request.stringify = (obj, keyPrefix) => {\n let pairs = [];\n keyPrefix = keyPrefix || \"\";\n Object.keys(obj).forEach((key) => {\n let value = obj[key];\n if (Array.isArray(value)) {\n value.forEach((v) => pairs.push(getKey(key, keyPrefix) + '=' + encode(v))); // Does not do that PHP garbage with key[]=val\n } else if (typeof value === \"object\" && value !== null) {\n // Recurse\n let res = okanjo.net.request.stringify(value, getKey(key, keyPrefix));\n if (res) pairs.push(res);\n } else if (value !== undefined) {\n pairs.push(getKey(key, keyPrefix) + '=' + encode(value));\n }\n });\n return pairs.join('&');\n };\n\n})(window);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function(window, document) {\n\n /**\n * Okanjo cookie utility helpers\n */\n window.okanjo.util.cookie = {\n\n /**\n * Sets a cookie\n * @param cookieName\n * @param value\n * @param expireDays\n */\n set: (cookieName, value, expireDays) => {\n const expireDate = new Date();\n expireDate.setDate(expireDate.getDate() + expireDays);\n const expires = expireDays ? \" Expires=\" + expireDate.toUTCString() + \";\" : \"\";\n const path = \" Path=/\";\n const secure = window.location.protocol === 'https:' ? ' Secure;' : '';\n // const secure = ' Secure;';\n const cookieValue = `${encodeURI(value)};${expires}${secure} SameSite=None;${path}`;\n // console.log('setting cookie', cookieName, cookieValue)\n document.cookie = cookieName + \"=\" + cookieValue;\n },\n\n /**\n * Gets a cookie\n * @param cookieName\n * @return {*}\n */\n get: (cookieName) => {\n let output = null;\n document.cookie\n .split(\";\")\n .find((cookie) => {\n let nameTest = cookie.substr(0, cookie.indexOf(\"=\")).trim();\n let value = cookie.substr(cookie.indexOf(\"=\") + 1);\n if (nameTest === cookieName) {\n output = decodeURI(value);\n return true;\n } else {\n return false;\n }\n })\n ;\n return output;\n }\n };\n\n})(window, document);","\"use strict\";\n\n//noinspection JSUnusedLocalSymbols,ThisExpressionReferencesGlobalObjectJS\n(function(window, document) {\n\n const okanjo = window.okanjo;\n\n /**\n * UI Rendering Engine\n */\n class TemplateEngine {\n\n constructor() {\n\n // Load initial templates from options\n this._templates = {};\n this._css = {};\n\n // Hook point for adding custom styles to ui elements\n this.classDetects = '';\n }\n\n /**\n * Registers a template for use\n * @param name\n * @param template\n * @param beforeRender\n * @param options\n */\n registerTemplate(name, template, beforeRender, options) {\n\n if (typeof template === \"object\") {\n //noinspection JSValidateTypes\n if (template.nodeType === undefined) {\n throw new Error('Parameter template must be a string or a DOM element');\n } else {\n template = template.innerHTML;\n okanjo.lib.Mustache.parse(template);\n }\n } else if (typeof template !== \"string\") {\n throw new Error('Parameter template must be a string or a DOM element');\n }\n\n // Shift options if only have 3 params\n if (arguments.length === 3 && typeof beforeRender === \"object\") {\n options = beforeRender;\n beforeRender = null;\n } else {\n options = options || {};\n }\n\n if (beforeRender && typeof beforeRender !== \"function\") {\n throw new Error('Parameter beforeRender must be a function');\n }\n\n // Assign the template\n this._templates[name] = {\n markup: template,\n options,\n beforeRender\n };\n }\n\n /**\n * Registers a CSS payload for use\n * @param name\n * @param css\n * @param options\n */\n registerCss(name, css, options) {\n options = options || {};\n\n if (typeof css === \"object\") {\n //noinspection JSValidateTypes\n if (css.nodeType === undefined) {\n throw new Error('Parameter css must be a string or a DOM element');\n }\n } else if (typeof css !== \"string\") {\n throw new Error('Parameter css must be a string or a DOM element');\n }\n\n this._css[name] = {\n markup: css,\n options: options\n };\n }\n\n /**\n * Checks whether a template is registered\n * @param name\n * @return {boolean}\n */\n isTemplateRegistered(name) {\n return !!this._templates[name];\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Checks whether a CSS payload is registered\n * @param name\n * @return {boolean}\n */\n isCssRegistered(name) {\n return !!this._css[name];\n }\n\n /**\n * Ensures that a CSS payload has been added to the DOM\n * @param name\n */\n ensureCss(name) {\n if (this._css[name]) {\n //noinspection JSValidateTypes\n const css = this._css[name],\n id = css.markup.nodeType === undefined ? css.options.id || \"okanjo-css-\" + name : null; // If it's a DOM element, just forget it cuz it's already on the page\n\n // Check for css element on page, if we have an ID to look for\n if (id) {\n const element = document.querySelector('#' + id.replace(/\\./g, '\\\\.'));\n if (!element) {\n const head = document.head,\n style = document.createElement('style');\n\n style.id = id;\n style.setAttribute('type', 'text/css');\n\n /* istanbul ignore else: old ie */\n if (style.hasOwnProperty) { // old ie\n style.innerHTML = css.markup;\n } else {\n style.styleSheet.cssText = css.markup;\n }\n\n if (head) {\n head.appendChild(style);\n } else {\n // NO HEAD, just prepend to body then\n const body = document.body;\n if (body) {\n body.appendChild(style);\n } else {\n // And if this doesn't work, just give up\n okanjo.report('Cannot add CSS template to document. Does it not have a body or head?');\n }\n }\n }\n }\n } else {\n okanjo.report('Attempted to add CSS template \"'+name+'\" to the DOM, however it does not appear to be registered?');\n }\n }\n\n /**\n * Renders a template and returns the markup\n * @param templateName\n * @param context\n * @param model\n * @return {string}\n */\n render(templateName, context, model) {\n\n model = model || {};\n const template = this._templates[templateName];\n\n // If there's a data controller closure set, and if so, run the data through there\n if (template.beforeRender) {\n model = template.beforeRender.call(context, model);\n }\n\n // Attach globals\n model.okanjo = okanjo;\n model.okanjoMetricUrl = okanjo.net.endpoint.replace(/^https?:\\/\\//,''); // Url w/o scheme to prevent mixed-content warnings\n model.now = function() { return (new Date()).getTime(); };\n model.classDetects = this.classDetects;\n\n //noinspection JSUnresolvedVariable\n if (model.blockClasses && Array.isArray(model.blockClasses)) {\n model.classDetects += \" \" + model.blockClasses.join(' ');\n delete model.blockClasses;\n }\n\n // Add CSS unless we are told not to\n if (model.css !== false && template.options.css && template.options.css.length > 0) {\n template.options.css.forEach((css) => this.ensureCss(css));\n delete model.css;\n }\n\n // Render the template and return the result\n return okanjo.lib.Mustache.render(template.markup, model);\n }\n\n }\n\n /**\n * Formats a number into a currency string (rounded, decimal points, thousands separators)\n * See: http://stackoverflow.com/questions/149055/how-can-i-format-numbers-as-money-in-javascript\n *\n * @param value – the number to format\n * @param [decimals] - The number of decimals to show\n * @param [decimalSeparator] – The decimals separator, default: .\n * @param [thousandsSeparator] – The thousands separator, default: ,\n * @returns {string} – Formatted currency string\n */\n TemplateEngine.formatCurrency = (value, decimals=2, decimalSeparator='.', thousandsSeparator=',') => {\n const s = value < 0 ? \"-\" : \"\",\n i = parseInt(value = Math.abs(+value || 0).toFixed(decimals)) + \"\";\n let j = i.length;\n j = (j) > 3 ? j % 3 : 0;\n return s + (j ? i.substr(0, j) + thousandsSeparator : \"\") + i.substr(j).replace(/(\\d{3})(?=\\d)/g, \"$1\" + thousandsSeparator) + (decimals ? decimalSeparator + Math.abs(value - i).toFixed(decimals).slice(2) : \"\");\n };\n\n // Export\n okanjo.ui.engine = new TemplateEngine();\n\n})(window, document);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window, document) {\n\n /*\n\n div .modal-container .fade-out .hidden\n | div .modal-window .clearfix\n | |\n | | div .modal-window-skin\n | | | div .modal-window-outer\n | | | | div .modal-window-inner\n | | | | | iframe .okanjo-inline-buy-frame\n | | | | /div\n | | | /div\n | | /div\n | |\n | | div .close-button\n | | | ×\n | | /div\n | |\n | /div\n /div\n\n */\n\n const okanjo = window.okanjo;\n const IS_MOBILE = okanjo.util.isMobile();\n\n let initialized = false,\n // scrollY = null,\n\n // Selectors\n $html, $body, $modalContainer, $modalWindow, $modalSkin, $modalOuter, $modalInner, $modalClose, $modalFrame,\n\n createElements = function() {\n\n // Page elements\n //noinspection JSUnresolvedFunction\n $html = document.documentElement /* istanbul ignore next: old browsers */ || document.querySelector('html');\n //noinspection JSUnresolvedFunction\n $body = document.body /* istanbul ignore next: old browsers */ || document.querySelector('body');\n\n // Modal elements\n $modalContainer = document.createElement('div');\n $modalWindow = document.createElement('div');\n $modalSkin = document.createElement('div');\n $modalOuter = document.createElement('div');\n $modalInner = document.createElement('div');\n $modalClose = document.createElement('div');\n $modalFrame = document.createElement('iframe');\n\n $modalContainer.setAttribute('class', 'okanjo-modal-container okanjo-modal-hidden ' /*+ okanjo.util.detectClasses().join(' ')*/);\n $modalWindow.setAttribute('class', 'okanjo-modal-window');\n $modalSkin.setAttribute('class', 'okanjo-modal-window-skin');\n $modalOuter.setAttribute('class', 'okanjo-modal-window-outer');\n $modalInner.setAttribute('class', 'okanjo-modal-window-inner');\n $modalClose.setAttribute('class', 'okanjo-modal-close-button');\n\n $modalFrame.setAttribute('class', 'okanjo-inline-buy-frame');\n $modalFrame.setAttribute('frameborder', '0');\n $modalFrame.setAttribute('vspace', '0');\n $modalFrame.setAttribute('hspace', '0');\n $modalFrame.setAttribute('webkitallowfullscreen', '');\n $modalFrame.setAttribute('mozallowfullscreen', '');\n $modalFrame.setAttribute('allowfullscreen', '');\n $modalFrame.setAttribute('scrolling', 'auto');\n\n $modalClose.innerHTML = '×';\n\n // Create the modal element tree\n $modalInner.appendChild($modalFrame);\n $modalOuter.appendChild($modalInner);\n $modalSkin.appendChild($modalOuter);\n $modalWindow.appendChild($modalSkin);\n $modalWindow.appendChild($modalClose);\n $modalContainer.appendChild($modalWindow);\n\n // Add the modal stuff to the body\n $body.appendChild($modalContainer);\n },\n\n addListener = function(el, event, handler) {\n /* istanbul ignore else: old browsers */\n if (el.addEventListener) {\n el.addEventListener(event, handler, false);\n } else {\n el.attachEvent(\"on\" + event, handler);\n }\n },\n\n getWindowHeight = function() {\n return window.innerHeight /* istanbul ignore next: old browsers */ || document.documentElement.clientHeight;\n },\n\n handleReposition = function() {\n // scrollY = okanjo.ui.getScrollPosition().y;\n //$modalWindow.style.marginTop = scrollY + 40 + \"px\";\n $modalWindow.style.height = (getWindowHeight() - 80) + \"px\";\n },\n\n bindEvents = function() {\n\n // If the device orientation changes, adjust the modal view port\n addListener(window, 'orientationchange', function() {\n for (let t = 0; t < 2; t++) {\n setTimeout(handleReposition, 1000 * t + 10);\n }\n });\n\n // If the window changes size, also adjust the modal view port\n addListener(window, 'resize', function() {\n setTimeout(handleReposition, 100);\n });\n\n // Click the overlay to close the modal\n addListener($modalContainer, 'click', closeModal);\n\n // If you click in the modal, don't close it!\n addListener($modalWindow, 'click', function(e) {\n e.preventDefault();\n e.stopPropagation();\n });\n\n // Click the close button to close it\n addListener($modalClose, 'click', function(e) {\n\n // Don't close it twice\n e.preventDefault();\n e.stopPropagation();\n\n closeModal();\n });\n\n },\n\n //removeListener = function(el, event, handler) {\n // if (el.removeEventListener) {\n // el.removeEventListener(event, handler);\n // } else {\n // el.detachEvent(\"on\" + event, handler);\n // }\n //},\n\n addClass = function(el, name) {\n el.className += \" \" + name;\n },\n\n removeClass = function(el, name) {\n el.className = el.className.replace(new RegExp(' *?'+name), '');\n },\n\n openModal = function() {\n\n // scrollY = document.body.scrollTop;\n\n removeClass($modalContainer, 'okanjo-modal-hidden');\n addClass($modalContainer, 'okanjo-modal-fade-out');\n\n handleReposition();\n\n addClass($html, \"okanjo-modal-active\");\n\n if (!IS_MOBILE) {\n addClass($html, \"okanjo-modal-margin-fix\");\n }\n\n setTimeout(function() {\n removeClass($modalContainer, 'okanjo-modal-fade-out');\n }, 10);\n\n // Click the overlay to close the modal\n //addListener($body, 'click', closeModal);\n\n },\n\n closeModal = function() {\n addClass($modalContainer, 'okanjo-modal-fade-out');\n\n setTimeout(function() {\n removeClass($modalContainer, 'okanjo-modal-fade-out');\n addClass($modalContainer, \"okanjo-modal-hidden\");\n\n removeClass($html, \"okanjo-modal-active\");\n if (!IS_MOBILE) {\n removeClass($html, \"okanjo-modal-margin-fix\");\n }\n }, 210);\n\n // Click the overlay to close the modal\n //removeListener($body, 'click', closeModal);\n },\n\n /**\n * Insert an element or markup into the modal\n * @param content\n */\n setContent = function(content) {\n\n // Remove existing content\n $modalInner.innerHTML = \"\";\n\n // Insert new content\n if (typeof content === \"string\") {\n $modalInner.innerHTML = content;\n } else {\n $modalInner.appendChild(content);\n }\n };\n\n\n // Expose the modal functions\n okanjo.ui.modal = {\n\n show: function(content) {\n\n if (!initialized) {\n initialized = true;\n createElements();\n bindEvents();\n }\n\n setContent(content);\n openModal();\n },\n\n hide: function() {\n closeModal();\n }\n\n };\n\n return okanjo.ui.modal;\n\n})(window, document);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window, document) {\n\n const okanjo = window.okanjo;\n\n /**\n * Event tracking class\n * @type {Metrics}\n */\n class Metrics {\n\n //noinspection JSUnusedGlobalSymbols\n constructor() {\n\n /**\n * Events queued here before submission\n * @type {Array}\n * @private\n */\n this._queue = this._getStoredQueue();\n this._processTimeout = null; // queue event loop timeout pointer\n\n /**\n * Unique page grouping event identifier\n */\n this.pageId = okanjo.util.shortid();\n this.defaultChannel = Metrics.Channel.external;\n\n this.sid = null;\n this.sourceCh = null;\n this.sourceCx = null;\n\n // Extract referral data, if set\n this._checkUrlForReferral();\n\n // TODO - look into iframe session correlation system\n }\n\n //noinspection JSMethodCanBeStatic\n /**\n * Gets the storage backed metric queue, in case we did not send everything last time\n * @return {Array}\n * @private\n */\n _getStoredQueue() {\n if (window.localStorage[Metrics.Params.queue]) {\n try {\n let queue = JSON.parse(window.localStorage[Metrics.Params.queue]);\n if (Array.isArray(queue)) {\n return queue;\n } else {\n okanjo.report('Stored queue is not a queue', {queue});\n return [];\n }\n } catch (e) {\n okanjo.report('Failed to load metric queue from storage', {err: e});\n return [];\n }\n } else {\n // not stored\n return [];\n }\n }\n\n /**\n * Updates the queue stored in storage, in the event we can't complete our submissions\n * @param delay - Whether to delay updating the queue for a bit, to let other metrics pile in\n * @private\n */\n _saveQueue(delay) {\n if (delay) {\n if (this._saveQueueTimeout) clearTimeout(this._saveQueueTimeout);\n this._saveQueueTimeout = setTimeout(() => {\n this._saveQueue(false);\n this._saveQueueTimeout = null;\n }, 100);\n } else {\n window.localStorage[Metrics.Params.queue] = JSON.stringify(this._queue);\n }\n }\n\n /**\n * Extract contextual pass-through data from the URL, if present\n * @private\n */\n _checkUrlForReferral() {\n const pageArgs = okanjo.util.getPageArguments(true),\n urlSid = pageArgs[Metrics.Params.name],\n localSid = window.localStorage[Metrics.Params.name] || okanjo.util.cookie.get(Metrics.Params.name), // pull from storage or cookie\n sourceContext = pageArgs[Metrics.Params.context],\n sourceChannel = pageArgs[Metrics.Params.channel];\n\n // If for some reason, both are set, record the incident as a possible correlation\n if (urlSid && localSid && urlSid !== localSid) {\n this.trackEvent({\n object_type: Metrics.Object.metric_session,\n event_type: Metrics.Event.correlation,\n id: urlSid+\"_\"+localSid,\n ch: this.defaultChannel,\n _noProcess: true\n });\n }\n\n // Update local values\n this.sid = localSid || urlSid || null; // prefer local over remote (changed in 1.0)\n this.sourceCh = sourceChannel || null;\n this.sourceCx = sourceContext || null;\n }\n\n /**\n * Submits an individual event metric\n * @param event\n * @param callback\n */\n trackEvent(event, callback) {\n // Ensure the event contains the required fields\n if (!event.object_type || !event.event_type) {\n okanjo.report('Invalid metric to track (missing object_type or event_type)', {event});\n return;\n }\n\n // Queue the event for publishing\n this._push(event, callback);\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Submits a page view metric\n * @param event\n * @param callback\n */\n trackPageView(event, callback) {\n event = event || {};\n event.object_type = Metrics.Object.page;\n event.event_type = Metrics.Event.view;\n event.id = event.id || okanjo.util.getLocation();\n event.ch = event.ch || this.defaultChannel;\n\n // Queue the event for publishing\n this.trackEvent(event, callback);\n }\n\n /**\n * Adds an event to the queue\n * @param event\n * @param callback\n * @private\n */\n _push(event, callback) {\n this._queue.push({ event, callback });\n\n // Save the queue\n this._saveQueue(true);\n\n // Start burning down the queue, unless the event says not to\n if (event._noProcess) {\n delete event._noProcess;\n } else {\n this._processQueue();\n }\n }\n\n /**\n * Burn down the queue\n * @private\n */\n _processQueue() {\n // If the queue is not already being processed, and there's stuff to process, continue sending them\n if (!this._processTimeout && this._queue.length > 0) {\n this._processTimeout = setTimeout(() => {\n\n // Pull the items we're going to batch out of the queue\n const items = this._queue.splice(0, 255);\n this._saveQueue(false);\n\n // Track the item\n this._batchSend(items, (err, res) => {\n // TODO: If there was an error, consider splicing the batch back into the queue\n\n // Update / Set the metric sid on the publisher\n /* istanbul ignore else: server barks */\n if (res && res.data && res.data.sid) this._updateSid(res.data.sid);\n\n // When this batch is done being tracked, iterate to the next metric then fire it's callback if set\n this._processTimeout = null;\n this._processQueue();\n\n // Fire the event callbacks if there are any\n items.forEach((item) => {\n item.callback && item.callback(err, res);\n });\n });\n\n }, 0); // break event loop, maybe\n }\n }\n\n /**\n * Sends a bunch of queued metric events\n * @param items\n * @param callback\n * @private\n */\n _batchSend(items, callback) {\n\n // Normalize event data\n const events = items.map((item) => {\n this._normalizeEvent(item.event);\n\n // Strip duplicated data from event batch\n delete item.event.sid;\n delete item.event.win;\n\n return item.event;\n });\n\n const payload = {\n events,\n win: okanjo.util.getLocation()\n };\n\n const route = okanjo.net.getRoute(okanjo.net.routes.metrics_batch);\n\n // Set sid if present\n if (this.sid) {\n payload.sid = this.sid;\n }\n\n // Send it\n okanjo.net.request.post(\n route,\n payload,\n (err, res) => {\n /* istanbul ignore if: out of scope */\n if (err) {\n okanjo.report('Failed to send metrics batch', { err, res, items, route });\n }\n callback && callback(err, res);\n }\n );\n }\n\n /**\n * Normaizes events so that they contain consistent data values\n * @param event\n * @private\n */\n _normalizeEvent(event) {\n\n // Ensure meta is ready to receive values\n event.m = event.m || {};\n\n // Set key\n event.key = event.key || event.m.key || okanjo.key || undefined;\n\n // Set session\n if (this.sid) event.sid = this.sid;\n\n // Clone the metadata, since it might be a direct reference to a widget property\n // Deleting properties on the meta object could be very destructive\n event.m = Object.assign({}, event.m); // event.m should be flat\n\n // Strip meta keys that should be excluded\n Object.keys(Metrics.Meta.exclude).forEach((key) => delete event.m[key]);\n\n // Set referral channel / context\n if (this.sourceCh) { event.m.ref_ch = this.sourceCh; }\n if (this.sourceCx) { event.m.ref_cx = this.sourceCx; }\n\n // Set page group id\n event.m.pgid = this.pageId;\n\n // Set okanjo version\n event.m.ok_ver = okanjo.version;\n\n // Finalize metadata\n event.m = okanjo.util.flatten(event.m, { arrayToCsv: true });\n\n // Ensure metadata strings won't exceed the imposed limit\n Object.keys(event.m).forEach((key) => {\n if (typeof event.m[key] === \"string\") {\n event.m[key] = event.m[key].substr(0, 255);\n }\n });\n\n // Set page source reference\n if (document.referrer) {\n event.ref = document.referrer;\n }\n\n // Set the window location\n event.win = okanjo.util.getLocation();\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n _updateSid(sid) {\n // Not set or changed?\n if (sid && (!this.sid || this.sid !== sid) ) {\n this.sid = sid;\n window.localStorage[Metrics.Params.name] = sid;\n okanjo.util.cookie.set(Metrics.Params.name, sid, Metrics.Params.ttl);\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @param event\n * @return {*|{}}\n */\n static addElementInfo(element, event) {\n const page = okanjo.ui.getPageSize(),\n size = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n event.m.pw = page.w;\n event.m.ph = page.h;\n event.m.x1 = size.x1;\n event.m.y1 = size.y1;\n event.m.x2 = size.x2;\n event.m.y2 = size.y2;\n\n return event;\n }\n\n static addWidgetInfo(element, event) {\n const containerSize = okanjo.ui.getElementPosition(element);\n\n event = event || {};\n event.m = event.m || {};\n\n // placement div size\n event.m.wox1 = containerSize.x1;\n event.m.woy1 = containerSize.y1;\n event.m.wox2 = containerSize.x2;\n event.m.woy2 = containerSize.y2;\n\n // Inner size is the min/max of the child elements since they may be floating and have no official height/width\n const resources = okanjo.qwery('.okanjo-resource, .okanjo-adx-container', element);\n let size, wix1, wiy1, wix2, wiy2, boxes = [];\n const getMin = (val, current) => typeof current === \"undefined\" || val < current ? val : current;\n const getMax = (val, current) => typeof current === \"undefined\" || val > current ? val : current;\n const fallback = (val, fallback) => typeof val === \"undefined\" ? fallback : val;\n\n resources.forEach(e => {\n size = okanjo.ui.getElementPosition(e);\n wix1 = getMin(size.x1, wix1);\n wiy1 = getMin(size.y1, wiy1);\n wix2 = getMax(size.x2, wix2);\n wiy2 = getMax(size.y2, wiy2);\n boxes.push(size.x1, size.y1, size.x2, size.y2);\n });\n\n // inner size (might be centered or something)\n // noinspection JSUnusedAssignment\n event.m.wix1 = fallback(wix1, containerSize.x1); // noinspection JSUnusedAssignment\n event.m.wiy1 = fallback(wiy1, containerSize.y1); // noinspection JSUnusedAssignment\n event.m.wix2 = fallback(wix2, containerSize.x2); // noinspection JSUnusedAssignment\n event.m.wiy2 = fallback(wiy2, containerSize.y2);\n event.m.wrps = boxes.map(v => Math.floor(v)).join(','); // all resource positions x1,y1,x2,y2,...\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds viewport dimensions / positional data to the event\n * @param event\n * @return {*|{}}\n */\n static addViewportInfo(event) {\n const vp = okanjo.ui.getViewportSize(),\n pos = okanjo.ui.getScrollPosition();\n\n event = event || {};\n event.m = event.m || {};\n event.m.vx1 = pos.x;\n event.m.vy1 = pos.y;\n event.m.vx2 = pos.x+vp.vw;\n event.m.vy2 = pos.y+vp.vh;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @param event\n * @return {*|{}}\n */\n static addEventInfo(jsEvent, event) {\n const pos = okanjo.ui.getEventPosition(jsEvent);\n\n event = event || {};\n event.m = event.m || {};\n event.m.et = pos.et;\n event.m.ex = pos.ex;\n event.m.ey = pos.ey;\n\n return event;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param event\n * @param args\n * @return {*|{}}\n */\n static addEventMeta(event, ...args) {\n event = event || {};\n event.m = event.m || {};\n event.m = Object.assign.apply(Object, [event.m].concat(args));\n \n return event;\n }\n\n /**\n * Helper to create a new fluent event structure\n * @param data\n * @param args\n * @return {MetricEvent}\n */\n static create(data, ...args) {\n // return okanjo.util.deepClone(Object.assign.apply(Object, [{}].concat(args)));\n return new MetricEvent(data, args);\n }\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Helper to create a new fluent event structure\n * @param args\n * @return {*}\n */\n create(...args) {\n return Metrics.create.apply(null, args);\n }\n\n }\n\n /**\n * The storage/cookie/url param names\n * @type {{queue: string, name: string, channel: string, context: string, ttl: number}}\n */\n Metrics.Params = {\n queue: '_ok_q',\n name: 'ok_msid',\n channel: 'ok_ch',\n context: 'ok_cx',\n ttl: 1460 // 4 years\n };\n\n /**\n * Event Metadata configuration\n * @type {{exclude: [*]}}\n */\n Metrics.Meta = {\n exclude: ['key','callback','metrics_channel_context','metrics_context','mode']\n };\n\n /**\n * Event Types\n * @type {{view: string, impression: string, interaction: string, correlation: string}}\n */\n Metrics.Event = {\n view: 'vw',\n impression: 'imp',\n interaction: 'int',\n correlation: 'cor'\n };\n\n /**\n * Event Action Types\n * @type {{click: string, inline_click: string}}\n */\n Metrics.Action = {\n click: \"click\",\n inline_click: \"inline_click\"\n };\n\n /**\n * Event Object Types\n * @type {{article: string, thirdparty_ad: string, cart: string, page: string, widget: string, product: string, store: string, cause: string, marketplace: string, order: string, order_item: string, user: string, metric_session: string}}\n */\n Metrics.Object = {\n article: 'am',\n thirdparty_ad: 'ta',\n cart: 'ct',\n page: 'pg',\n widget: 'wg',\n product: 'pr',\n store: 'st',\n cause: 'ca',\n marketplace: 'mp',\n order: 'or',\n order_item: 'oi',\n user: 'ur',\n metric_session: 'mt'\n };\n\n /**\n * Event Channels\n * @type {{product_widget: string, ad_widget: string, store_widget: string, marketplace: string, external: string}}\n */\n Metrics.Channel = {\n placement: 'pw',\n marketplace: 'mp',\n external: 'ex',\n\n // Deprecated:\n product_widget: 'pw',\n ad_widget: 'aw',\n store_widget: 'sw'\n };\n\n /**\n * Event Environments\n * @type {{live: string, testing: string}}\n */\n Metrics.Environment = {\n live: \"live\",\n testing: \"testing\"\n };\n\n /**\n * Fluent wrapper around making events simple\n */\n class MetricEvent {\n constructor(data, others) {\n // Merge the data and other data sets into this object\n data = data || {};\n this.data(data);\n /* istanbul ignore else: metrics.create is the only way to create this right now */\n if (Array.isArray(others)) {\n others.forEach((data) => {\n this.data(data);\n });\n }\n }\n\n /**\n * Sets event parameter key-values\n * @param data\n */\n data(data) {\n Object.assign(this, okanjo.util.deepClone(data));\n return this;\n }\n\n /**\n * Adds DOM event positional data to the event\n * @param jsEvent\n * @return {MetricEvent}\n */\n event(jsEvent) {\n Metrics.addEventInfo(jsEvent, this);\n return this;\n }\n\n /**\n * Adds viewport dimensions / positional data to the event\n * @return {MetricEvent}\n */\n viewport() {\n Metrics.addViewportInfo(this);\n return this;\n }\n\n /**\n * Adds DOM element dimensions / positional data to the event\n * @param element\n * @return {MetricEvent}\n */\n element(element) {\n Metrics.addElementInfo(element, this);\n return this;\n }\n\n /**\n * Adds widget DOM element dimensions / positional data to the event\n * @param element\n * @returns {MetricEvent}\n */\n widget(element) {\n Metrics.addWidgetInfo(element, this);\n return this;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Adds meta data values to the event\n * @param args\n * @return {MetricEvent}\n */\n meta(...args) {\n Metrics.addEventMeta.apply(null, [this].concat(args));\n return this;\n }\n\n /**\n * Sets the object and event type on the event w/o having to use .data\n * @param object_type\n * @param event_type\n * @return {MetricEvent}\n */\n type(object_type, event_type) {\n this.object_type = object_type;\n this.event_type = event_type;\n return this;\n }\n\n /**\n * Finalizes and sends the event\n * @param callback\n */\n send(callback) {\n okanjo.metrics.trackEvent(this, callback);\n // DONT RETURN - BREAK THE CHAIN HERE\n }\n\n /**\n * Gets the single-metric tracking url for this event\n * @return {string}\n */\n toUrl() {\n // Copy data w/o modifying it\n const event = Object.assign({}, this);\n\n // Extract params\n const {\n object_type,\n event_type\n } = event;\n delete event.object_type;\n delete event.event_type;\n\n // Normalize event data\n okanjo.metrics._normalizeEvent(event);\n\n // Get the URL\n return okanjo.net.getRoute(okanjo.net.routes.metrics, { object_type, event_type }) + '?' +\n okanjo.net.request.stringify(event);\n }\n }\n\n // Export / initialize\n okanjo.metrics = new Metrics();\n\n})(window, document);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS\n(function(window) {\n\n const okanjo = window.okanjo;\n\n // Track the page view, but don't send it right away.\n // Send it in one full second unless something else pushes an event\n // This way, we have a chance that a placement key will be set globally\n okanjo.metrics.trackPageView({_noProcess:true});\n setTimeout(() => {\n okanjo.metrics._processQueue();\n }, 1000);\n\n})(window);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n/** Based on https://gist.github.com/mudge/5830382 **/\n(function(window) {\n\n /**\n * Simplified EventEmitter base class\n */\n class EventEmitter {\n\n constructor() {\n this._events = {};\n }\n\n /**\n * Registers an event handler to fire on any occurrence of an event\n * @param event\n * @param listener\n */\n on(event, listener) {\n if (!this._events[event]) {\n this._events[event] = [];\n }\n\n this._events[event].push(listener);\n }\n\n /**\n * Removes an event handler for an event\n * @param event\n * @param listener\n */\n removeListener(event, listener) {\n\n if (this._events[event]) {\n let idx = this._events[event].indexOf(listener);\n if (idx >= 0) {\n this._events[event].splice(idx, 1);\n }\n }\n }\n\n /**\n * Emits an event\n * @param event\n */\n emit(event) {\n let i, listeners, length, args = [].slice.call(arguments, 1);\n\n if (this._events[event]) {\n listeners = this._events[event].slice();\n length = listeners.length;\n\n for (i = 0; i < length; i++) {\n listeners[i].apply(this, args);\n }\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Registers an event handler to fire only once on an event\n * @param event\n * @param listener\n */\n once(event, listener) {\n\n const callback = () => {\n let args = [].slice.call(arguments, 1);\n this.removeListener(event, callback);\n listener.apply(this, args);\n };\n\n this.on(event, callback);\n }\n\n }\n\n window.okanjo._EventEmitter = EventEmitter;\n return EventEmitter;\n\n})(window);","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window) {\n\n const okanjo = window.okanjo;\n const DATA_ATTRIBUTE_PATTERN = /^data-(.+)$/;\n const DATA_REPLACE_PATTERN = /-/g;\n\n /**\n * Base widget class\n */\n class Widget extends okanjo._EventEmitter {\n\n constructor(element, options) {\n super();\n\n // Verify element was given (we can't load unless we have one)\n if (!element || element === null || element.nodeType === undefined) {\n okanjo.report('Invalid or missing element on widget construction', { widget: this, element, options });\n throw new Error('Okanjo: Invalid element - make sure to pass a valid DOM element when constructing Okanjo Widgets.');\n }\n\n // Verify configuration is OK\n if (options && typeof options !== \"object\") {\n // Warn and fix it\n okanjo.report('Invalid widget options. Expected object, got: ' + typeof options, { widget: this, element, options });\n options = {};\n } else {\n options = options || {};\n }\n\n // Store basics\n this.name = 'Widget';\n this.element = element;\n this.instanceId = okanjo.util.shortid();\n\n // Clone initial config, breaking the top-level reference\n this.config = Object.assign({}, options);\n }\n\n /**\n * Base widget initialization procedures\n */\n init() {\n // process config attributes\n this._applyConfiguration();\n\n this._setCompatibilityOptions();\n\n // ensure placement key\n if (!this._ensurePlacementKey()) return;\n\n // Tell the widget to load\n this.load();\n }\n\n /**\n * This is for extended widgets, so they may modify the configuration before loading\n */\n _setCompatibilityOptions() {\n // By default, this does nothing. Must be overridden to be useful\n }\n\n //noinspection JSMethodCanBeStatic\n /**\n * Widget configuration definitions\n * @return {{}}\n */\n getSettings() {\n // Override this\n return {};\n }\n\n /**\n * Main widget load function.\n */\n load() {\n // Override this in the widget implementation\n }\n\n /**\n * Applies data attribute settings and defaults to the widget configuration\n * @private\n */\n _applyConfiguration() {\n\n // this.config was set to the options provided in the constructor\n // so layer data attributes on top\n\n const data = this.getDataAttributes();\n const settings = this.getSettings();\n Object\n .keys(data)\n .forEach((key) => {\n let normalizedKey = key.replace(DATA_REPLACE_PATTERN, '_');\n\n let val = data[key];\n\n // Attempt to convert the value if there's a setting for it\n if (settings[normalizedKey]) val = settings[normalizedKey].value(val, false);\n\n if (!okanjo.util.isEmpty(val)) {\n this.config[normalizedKey] = val;\n }\n })\n ;\n\n // Apply defaults from the widget settings\n Object.keys(settings).forEach((key) => {\n if (this.config[key] === undefined && settings[key]._default !== undefined) {\n this.config[key] = settings[key].value(undefined, false);\n }\n });\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets a copy of the configuration, suitable for transmission\n * @return {{}}\n */\n getConfig() {\n const settings = this.getSettings();\n const out = {};\n\n Object.keys(this.config).forEach((origKey) => {\n let val = this.config[origKey];\n let key = origKey;\n let group = null;\n\n // Check if this is a known property\n if (settings[key]) {\n val = settings[key].value(val);\n group = settings[key].getGroup();\n }\n\n // Init the target/group if not already setup\n let target = out;\n if (group) {\n target[group] = target[group] || {};\n target = target[group];\n }\n\n // Set the value on the target if set\n if (val === null) {\n target[key] = ''; // format null values as empty strings for transmission\n } else if (val !== undefined) {\n target[key] = val;\n }\n });\n\n return out;\n }\n\n /**\n * Before loading, ensure that a placement key is present or abort\n * @return {boolean}\n * @private\n */\n _ensurePlacementKey() {\n\n // Check if set on widget or globally\n if (this.config.key) {\n return true;\n } else if (okanjo.key) {\n // Copy key from global scope,\n this.config.key = okanjo.key;\n return true;\n }\n\n // No key set, can't load.\n okanjo.report('No key provided on widget', { widget: this });\n this.showError('Error: Missing placement key.');\n return false;\n }\n\n /**\n * Displays an error in the widget element\n * @param message\n */\n showError(message) {\n this.setMarkup(okanjo.ui.engine.render(\n 'okanjo.error',\n this,\n { message }\n ));\n }\n\n /**\n * Sets the markup of the widget's element\n * @param markup\n */\n setMarkup(markup) {\n this.element.innerHTML = markup;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets the current page URL, sans query string and fragment.\n * @returns {string} - URL\n */\n static getCurrentPageUrl() {\n return window.location.href.replace(/([?#].*)$/, '');\n }\n\n /**\n * Instead of using HTML5 dataset, just rip through attributes and return data attributes\n * @returns {*}\n */\n getDataAttributes() {\n const data = {};\n Array\n .from(this.element.attributes)\n .forEach((attr) => {\n const match = DATA_ATTRIBUTE_PATTERN.exec(attr.name);\n if (match) {\n data[match[1]] = attr.value;\n }\n });\n return data;\n }\n\n }\n\n /**\n * Fluent configuration helper for organizing and formatting ad-hoc configuration values\n * @type {Field}\n */\n Widget.Field = class Field {\n\n //noinspection JSUnusedGlobalSymbols\n constructor() {\n this._convert = null;\n this._strip = false;\n this._default = undefined;\n this._group = null;\n }\n\n /**\n * Formats the value as an array of strings\n * @param converter\n * @return {Field}\n */\n array(converter) {\n this._convert = (val) => {\n if (Array.isArray(val)) {\n if (converter) {\n return val.map((v) => converter(v))\n } else {\n return val;\n }\n }\n val = val.replace(/\\\\,/g, '\\0');\n return val.split(',').map((v) => {\n let res = v.trim().replace('\\0', ',');\n if (converter) res = converter(res);\n return res;\n });\n };\n return this;\n }\n //noinspection JSUnusedGlobalSymbols\n static array(converter) { return (new Field()).array(converter); }\n\n /**\n * Formats the value as a string\n * @return {Field}\n */\n string() {\n this._convert = (val) => {\n if (val === null || val === undefined) return val;\n else return \"\"+val;\n };\n return this;\n }\n static string() { return (new Field()).string(); }\n\n /**\n * Formats the value as a boolean (takes 1, 0, true, false)\n * @return {Field}\n */\n bool() {\n this._convert = (val) => {\n if (typeof val === \"string\") {\n return (val === \"1\" || val.toLowerCase() === \"true\");\n } else {\n return !!val;\n }\n };\n return this;\n }\n //noinspection JSUnusedGlobalSymbols\n static bool() { return (new Field()).bool(); }\n\n /**\n * Indicates the field should not be passed on for transmission\n * @return {Field}\n */\n strip() { this._strip = true; return this; }\n static strip() { return (new Field()).strip(); }\n\n /**\n * Formats the value as a integer (whole) number\n * @return {Field}\n */\n int() { this._convert = (val) => parseInt(val); return this; }\n //noinspection JSUnusedGlobalSymbols\n static int() { return (new Field()).int(); }\n\n /**\n * Formats the value as a floating point number\n * @return {Field}\n */\n float() { this._convert = (val) => parseFloat(val); return this; }\n //noinspection JSUnusedGlobalSymbols\n static float() { return (new Field()).float(); }\n\n //noinspection ReservedWordAsName\n /**\n * Sets the default value to use if not set\n * @param val\n * @return {Field}\n */\n default(val) {\n this._default = val;\n return this;\n }\n\n /**\n * Assigns the property to a bucket for hierarchy\n * @param name\n * @return {Field}\n */\n group(name) {\n this._group = name;\n return this;\n }\n\n /**\n * Gets the group the field belongs to\n * @return {*|null}\n */\n getGroup() {\n return this._group;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Gets the formatted value of the field\n * @param val\n * @param strip\n * @return {*}\n */\n value(val, strip=true) {\n if (this._strip && strip) return undefined;\n if (val !== undefined && this._convert) {\n val = this._convert(val);\n }\n return val !== undefined ? val : this._default;\n }\n\n };\n\n // Export\n return okanjo._Widget = Widget;\n\n})(window);\n\n\n\n","\"use strict\";\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window) {\n\n //region Imports and Constants\n\n const okanjo = window.okanjo;\n const { string, array, float, int, bool } = okanjo._Widget.Field;\n const Metrics = okanjo.metrics.constructor;\n const TemplateEngine = okanjo.ui.engine.constructor;\n\n const FILTERS = 'filters';\n const DISPLAY = 'display';\n const ARTICLE_META = 'article_meta';\n\n const MINIMUM_VIEW_PX = 0.5; // 50% of pixels must be in viewport\n const MINIMUM_VIEW_TIME = 1000; // for 1 full second\n const MINIMUM_VIEW_FREQ = 2; // time / freq = interval\n\n //endregion\n\n /**\n * Placement widget\n */\n class Placement extends okanjo._Widget {\n\n //region Configuration & Overrides\n\n /**\n * Initializes a new placement\n * @param element\n * @param options\n */\n constructor(element, options = {}) {\n\n // Flatten the options before passing on\n options = okanjo.util.flatten(options, { ignoreArrays: true });\n super(element, options);\n\n this.name = 'Placement';\n this._metricBase = {}; // placeholder for metrics\n this._response = null;\n\n // Aggregate view watchers into a single interval fn\n this._viewWatcherIv = null;\n this._viewedWatchers = [];\n\n // Start loading content\n if (!options.no_init) this.init();\n }\n\n //noinspection JSMethodCanBeStatic,JSUnusedGlobalSymbols\n /**\n * Gets the widget settings configuration\n * @return {{type: *, ids: *, q: *, url: *, url_referrer: *, url_selectors: *, organization_id: *, property_id: *, store_id: *, organization_name: *, property_name: *, store_name: *, external_id: *, sku: *, external_store_id: *, condition: *, manufacturer: *, upc: *, isbn: *, tags: *, category: *, pools: *, min_price: *, max_price: *, min_donation_percent: *, max_donation_percent: *, donation_to: *, sort_by: *, sort_direction: *, skip: *, take: *, placement_tests_only: *, size: *, template_name: *, template_layout: *, template_theme: *, template_cta_style: *, template_cta_text: *, template_cta_color: *, adx_unit_path: *, url_category: *, url_keywords: *, no_init: *, proxy_url: *, expandable, disable_inline_buy, disable_popup, backwards: *}}\n */\n getSettings() {\n return {\n\n // What type of response do you want\n type: string().group(FILTERS),\n\n // What specific products do you want\n ids: array().group(FILTERS),\n\n // Filter by generic query string\n q: string().group(FILTERS),\n\n // Filter by relation to content\n url: string().group(FILTERS),\n url_referrer: string().group(FILTERS).strip(),\n url_selectors: string().group(FILTERS),\n url_paths: array().group(FILTERS),\n not_url_paths: array().group(FILTERS),\n\n // Filter by hierarchy\n organization_id: string().group(FILTERS),\n property_id: string().group(FILTERS),\n store_id: string().group(FILTERS),\n\n // Filter by hierarchy names (use *_id where possible, this might not work as you might expect)\n organization_name: string().group(FILTERS),\n property_name: string().group(FILTERS),\n store_name: string().group(FILTERS),\n\n // Filter by integrations\n external_id: string().group(FILTERS),\n sku: string().group(FILTERS),\n external_store_id: string().group(FILTERS),\n\n // Filter by product attributes\n condition: string().group(FILTERS),\n manufacturer: string().group(FILTERS),\n upc: string().group(FILTERS),\n isbn: string().group(FILTERS),\n\n // Filter by categorization / distribution\n tags: array().group(FILTERS),\n category: array().group(FILTERS),\n pools: array().group(FILTERS),\n\n // Filter by price range\n min_price: float().group(FILTERS),\n max_price: float().group(FILTERS),\n\n // Filter by donation ranges\n min_donation_percent: float().group(FILTERS),\n max_donation_percent: float().group(FILTERS),\n\n // Filter by donation recipient\n donation_to: string().group(FILTERS),\n\n // Sorting\n sort_by: string().group(FILTERS),\n sort_direction: string().group(FILTERS),\n\n // Pagination\n skip: int().group(FILTERS),\n take: int().group(FILTERS),\n\n // Placement Testing\n placement_tests_only: bool(),\n\n // Display settings\n size: string().group(DISPLAY),\n template_name: string().group(DISPLAY),\n template_layout: string().group(DISPLAY),\n template_theme: string().group(DISPLAY),\n template_variant: string().group(DISPLAY),\n template_cta_style: string().group(DISPLAY),\n template_cta_text: string().group(DISPLAY),\n template_cta_color: string().group(DISPLAY),\n adx_unit_path: string().group(DISPLAY), // Custom DFP ad unit path\n\n // Article metadata\n url_category: array().group(ARTICLE_META),\n url_keywords: array().group(ARTICLE_META),\n\n // Functional settings\n key: string().strip(), // don't need to resend key on all our requests\n no_init: bool().strip(), // don't automatically load the placement, do it manually (e.g. (new Placement({no_init:true})).init()\n no_css: bool().strip(), // don't automatically include stylesheets\n proxy_url: string().strip(),\n expandable: bool().strip().default(true),\n disable_inline_buy: bool().strip().default(false), // stops inline buy functionality\n disable_popup: bool().strip().default(false), // stops new window on mobile for inline buy functionality\n backwards: string().strip(), // internal flag indicating port from a deprecated widget\n testing: bool().strip() // metrics flag to indicate testing\n };\n }\n\n /**\n * Gets the widget configuration formatted using settings, suitable for transmission\n * @return {{filters: {}, display: {}, backfill: {}, shortfill: {}, article_meta: {}}}\n */\n getConfig() {\n const settings = this.getSettings();\n const out = { filters: {}, display: {}, backfill: {}, shortfill: {}, article_meta: {} };\n const backfillPattern = /^backfill_(.+)$/; // backfill_property\n const shortfillPattern = /^shortfill_(.+)$/; // shortfill_property\n\n Object.keys(this.config).forEach((origKey) => {\n let val = this.config[origKey];\n let key = origKey;\n let isBackfill = false;\n let isShortfill = false;\n let group = null;\n\n // Get the property name if it was prefixed with backfill\n let matches = backfillPattern.exec(origKey);\n if (matches) {\n key = matches[1];\n isBackfill = true;\n } else {\n // Get the property name if it was prefixed with shortfill\n matches = shortfillPattern.exec(origKey);\n if (matches) {\n key = matches[1];\n isShortfill = true;\n }\n }\n\n // Check if this is a known property\n if (settings[key]) {\n val = settings[key].value(val);\n group = settings[key].getGroup();\n }\n\n // Init the target/group if not already setup\n let target = out;\n if (isBackfill) {\n target = out.backfill;\n } else if (isShortfill) {\n target = out.shortfill;\n }\n\n // Set the target to the bucket in the settings container\n // except shortfill - can only apply settings directly to the bucket\n // e.g. backfill_url -> { backfill: { filters: { url: xxx } } }\n // e.g. shortfill_url-> { shortfill: { url: xxx } }\n if (!isShortfill && group) {\n target[group] = target[group] || {};\n target = target[group];\n }\n\n // Set the value on the target if set\n if (val === null) {\n target[key] = ''; // format null values as empty strings for transmission\n } else if (val !== undefined) {\n target[key] = val;\n }\n });\n\n return out;\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Core load process\n */\n load() {\n // Set metric base data (stub for all future events emitted by the widget)\n this._setMetricBase();\n\n // Find out what we should display here\n this._fetchContent((err) => {\n if (err) {\n // Report the widget load as declined\n this._reportWidgetLoad(\"fetch failed: \" + err.statusCode /* istanbul ignore next: out of scope */ || err.toString());\n } else {\n // Merge display settings from response\n this._mergeResponseSettings();\n\n // Merge the referential data from the response\n this._updateBaseMetaFromResponse();\n\n // Handle rendering based on output type\n this._showContent();\n }\n });\n }\n\n //endregion\n\n //region Internal Helpers\n\n /**\n * Initializes the common metric data for events emitted by the placement\n * @private\n */\n _setMetricBase() {\n const base = this._metricBase;\n base.ch = Metrics.Channel.placement;\n base.cx = this.config.backwards || 'auto';\n base.key = this.config.key;\n base.m = base.m || {};\n base.m.wgid = this.instanceId;\n\n if (this.config.testing) base.env = Metrics.Environment.testing;\n }\n\n /**\n * Emits the widget impression event\n * @param declined\n * @private\n */\n _reportWidgetLoad(declined) {\n\n const res = this._response || {};\n const data = res.data || { results: [] };\n\n // If this is declined, mark future events as declined too\n this._metricBase.m.decl = declined || '0';\n\n // Attach other main response attributes to all future events\n this._metricBase.m.res_bf = data.backfilled ? 1 : 0; // whether the response used the back fill flow\n this._metricBase.m.res_sf = data.shortfilled ? 1 : 0; // whether the response used the short fill flow\n this._metricBase.m.res_spltfl = data.splitfilled ? 1 : 0; // whether the response used the short fill flow\n this._metricBase.m.res_total = data.total || 0; // how many total candidate results were available given filters\n this._metricBase.m.res_type = data.type; // what the given resource type was\n this._metricBase.m.res_length = data.results.length; // number of resources delivered\n\n // Track impression\n okanjo.metrics.create(this._metricBase)\n .type(Metrics.Object.widget, Metrics.Event.impression)\n .meta(this.getConfig())\n .element(this.element) // this might not be all that useful cuz the content hasn't been rendered yet\n .viewport()\n .widget(this.element)\n .send();\n\n // Start watching for a viewable impression\n this._addOnceViewedHandler(this.element, () => {\n okanjo.metrics.create(this._metricBase)\n .type(Metrics.Object.widget, Metrics.Event.view)\n .meta(this.getConfig())\n .element(this.element)\n .viewport()\n .widget(this.element)\n .send();\n });\n }\n\n /**\n * Executes the request for content to fill the placement\n * @param callback\n * @private\n */\n _fetchContent(callback) {\n // Build request to api, starting with this placement config params\n const query = this.getConfig();\n\n // Extract the key\n const key = this.config.key;\n\n // Attach sid and referrer\n if (okanjo.metrics.sid) query.sid = okanjo.metrics.sid;\n query.filters.url_referrer = this.config.url_referrer || window.location.href;\n query.wgid = this.instanceId;\n query.pgid = okanjo.metrics.pageId;\n\n // Send it\n okanjo.net.request.post(\n `${okanjo.net.getRoute(okanjo.net.routes.ads, null, this.config.sandbox ? 'sandbox' : 'live')}?key=${encodeURIComponent(key)}`,\n query,\n (err, res) => {\n if (err) {\n okanjo.report('Failed to retrieve placement content', err, { placement: this });\n this.setMarkup(''); // Don't show anything\n this.emit('error', err);\n callback && callback(err);\n } else {\n\n // Store the raw response\n this._response = res;\n\n // Hook point for response handling\n this.emit('data');\n\n // Return\n callback && callback();\n }\n }\n );\n }\n\n /**\n * Applies response filters and display settings into the widget configuration\n * @private\n */\n _mergeResponseSettings() {\n const res = this._response;\n const data = res.data || {};\n const settings = data.settings || {};\n\n if (settings.filters) {\n Object.keys(settings.filters).forEach((key) => {\n this.config[key] = settings.filters[key];\n });\n }\n\n if (settings.display) {\n Object.keys(settings.display).forEach((key) => {\n this.config[key] = settings.display[key];\n });\n }\n }\n\n /**\n * Applies response data to future metric events\n * @private\n */\n _updateBaseMetaFromResponse() {\n // Update the base metric data with info from the response\n const data = (this._response|| {}).data || {};\n this._metricBase.m = this._metricBase.m || {};\n const meta = this._metricBase.m;\n\n // Article\n if (data.article) meta.aid = data.article.id;\n\n if (data.test && data.test.enabled) {\n meta.pten = 1;\n meta.ptid = data.test.id;\n meta.ptseed = data.test.seed;\n } else {\n meta.pten = 0;\n }\n }\n\n /**\n * Beings the render process based on the response content\n * @private\n */\n _showContent() {\n const data = (this._response|| {}).data || {};\n\n // Known content types we can display\n if (data.type === Placement.ContentTypes.products) {\n this._showProducts();\n } else if (data.type === Placement.ContentTypes.articles) {\n this._showArticles();\n } else if (data.type === Placement.ContentTypes.adx) {\n this._showADX();\n } else {\n // Unknown response type!\n\n // Report the widget load as declined\n const msg = 'Unknown response content type: ' + data.type;\n okanjo.report(msg, { placement: this });\n this.setMarkup(''); // Don't show anything\n this.emit('error', msg);\n this._reportWidgetLoad(msg);\n }\n }\n\n /**\n * Generates the click url using the event, proxy_url, and additional params\n * @param event\n * @param url\n * @param additionalUrlParams\n * @return {*}\n * @private\n */\n _getClickThroughURL(event, url, additionalUrlParams) {\n const joiner = url.indexOf('?') >= 0 ? '&' : '?';\n\n // Tack on transfer params\n additionalUrlParams = additionalUrlParams /* istanbul ignore next: paranoia */ || {};\n additionalUrlParams.ok_msid = okanjo.metrics.sid || 'unknown';\n additionalUrlParams.ok_ch = this._metricBase.ch;\n additionalUrlParams.ok_cx = this._metricBase.cx;\n additionalUrlParams._okjr = window.location.href.split(/[?#]/)[0];\n additionalUrlParams.utm_source = 'okanjo';\n additionalUrlParams.utm_campaign = 'smartserve';\n // additionalUrlParams.utm_source = window.location.hostname;\n additionalUrlParams.utm_medium = 'smartserve';\n // additionalUrlParams.utm_campaign = 'smartserve';\n\n\n url += joiner + Object.keys(additionalUrlParams)\n .map((key) => encodeURIComponent(key)+'='+encodeURIComponent(additionalUrlParams[key]))\n .join('&');\n\n // Wrap the url if we're proxying\n if (this.config.proxy_url) {\n url = this.config.proxy_url + encodeURIComponent(url);\n }\n\n // Set the url on the event\n event.data({\n u: url\n });\n\n return event.toUrl();\n }\n\n /**\n * Converts a resource's link into one suitable for tracking, making middle-click safe\n * @param type\n * @param resource\n * @param e\n * @private\n */\n _handleResourceMouseDown(type, resource, e) {\n // Generate a new click id for this event\n // const clickId = okanjo.util.shortid();\n const clickId = resource._cid;\n\n // Start building the event\n const event = okanjo.metrics.create(this._metricBase, {\n id: resource.id\n })\n .type(type, Metrics.Event.interaction)\n .meta(this.getConfig())\n .meta({ cid: clickId })\n .meta({\n bf: resource.backfill ? 1 : 0,\n sf: resource.shortfill ? 1 : 0,\n spltfl_seg: resource.splitfill_segment || null\n })\n .event(e)\n .element(e.currentTarget)\n .viewport()\n .widget(this.element);\n\n // Pull the proper params out of the resource depending on it's type\n let trackParam = 'url_track_param';\n let urlParam = 'url';\n\n if (type === Metrics.Object.product) {\n trackParam = 'buy_url_track_param';\n urlParam = 'buy_url';\n }\n\n // Attach the campaign tracking identifier\n const additionalParams = {\n ok_cid: clickId\n };\n if (resource[trackParam]) additionalParams[resource[trackParam]] = clickId;\n\n // Update the link with the event data\n event.data({ ea: Metrics.Action.click });\n e.currentTarget.href = this._getClickThroughURL(event, resource[urlParam], additionalParams);\n\n // Cache this on the product\n resource._clickId = clickId;\n resource._event = event;\n resource._additionalParams = additionalParams;\n }\n\n /**\n * Gets the template to use, accounting for configured preference if available\n * @param contentType\n * @param defaultName\n * @return {string}\n * @private\n */\n _getTemplate(contentType, defaultName) {\n let templateName = this.config.template_name;\n if (!templateName ||\n !okanjo.ui.engine.isTemplateRegistered(`${contentType}.${templateName}`)) {\n templateName = defaultName;\n }\n return `${contentType}.${templateName}`;\n }\n\n /**\n * Enforces size/layout/cta restrictions\n * @private\n */\n _enforceLayoutOptions() {\n // Enforce format restrictions\n if (this.config.size === \"leaderboard\" || this.config.size === \"large_mobile_banner\") {\n this.config.template_layout = \"list\";\n this.config.template_cta_style = \"link\";\n } else if (this.config.size === \"half_page\" || this.config.size === \"auto\") {\n this.config.template_layout = \"list\";\n }\n }\n\n /**\n * Enforces\n * @private\n */\n _enforceSlabLayoutOptions() {\n if (this.config.size === \"medium_rectangle\" || this.config.size === \"billboard\") {\n // no list view\n this.config.template_layout = \"grid\";\n\n // no buttons\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n } else if (this.config.size === \"half_page\") {\n this.config.template_layout = \"grid\";\n } else if (this.config.size === \"leaderboard\" || this.config.size === \"large_mobile_banner\") {\n this.config.template_layout = \"list\";\n\n // no button\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n } else if (this.config.size === \"auto\") {\n this.config.template_layout = \"list\";\n } else if (this.config.size === \"responsive\") {\n // no button in responsive mode\n if (this.config.template_cta_style === \"button\") {\n this.config.template_cta_style = \"link\";\n }\n }\n }\n\n /**\n * Register a custom\n * @private\n */\n _registerCustomBranding(/*prefix, buttonClass*/) {\n const brandColor = this.config.template_cta_color;\n if (brandColor) {\n let brandCSS,\n brandCSSId = \"okanjo-wgid-\" + this.instanceId;\n\n brandCSS = `\n .okanjo-block2.${brandCSSId} .okanjo-resource-cta-button, .okanjo-block2.${brandCSSId} .okanjo-resource-buy-button { color: ${brandColor} !important; } \n .okanjo-block2.${brandCSSId}.okanjo-cta-style-button .okanjo-resource-cta-button, .okanjo-block2.${brandCSSId}.okanjo-cta-style-button .okanjo-resource-buy-button { border-color: ${brandColor} !important; } \n .okanjo-block2.${brandCSSId}.okanjo-cta-style-button .okanjo-resource-cta-button:hover, .okanjo-block2.${brandCSSId}.okanjo-cta-style-button .okanjo-resource-buy-button:hover { background: ${brandColor} !important; color: #fff !important; } \n `;\n\n okanjo.ui.engine.registerCss(brandCSSId, brandCSS, { id: brandCSSId });\n okanjo.ui.engine.ensureCss(brandCSSId);\n }\n }\n\n /**\n * When element is in view per viewability constants (50% for 1s) trigger handler once\n * @param element\n * @param handler\n * @private\n */\n _addOnceViewedHandler(element, handler) {\n let controller = {\n element,\n successfulCount: 0,\n handler\n };\n\n // Add our element to the watch list and turn on the watcher if not already on\n this._viewedWatchers.push(controller);\n this._toggleViewWatcher(true);\n }\n\n /**\n * Interval function to check viewability of registered elements\n * @private\n */\n _checkViewWatchers() {\n\n // Check each registered watcher\n for (let i = 0, controller; i < this._viewedWatchers.length; i++) {\n controller = this._viewedWatchers[i];\n\n // Check if watcher is complete, then remove it from the list\n /* istanbul ignore next: jsdom won't trigger this */\n if (okanjo.ui.isElementVisible(controller.element) &&\n okanjo.ui.getPercentageInViewport(controller.element) >= MINIMUM_VIEW_PX) {\n controller.successfulCount++;\n }\n\n // While this could more optimally be contained within the former condition, unit-testing blocks on this\n if (controller.successfulCount >= MINIMUM_VIEW_FREQ) {\n controller.handler();\n this._viewedWatchers.splice(i, 1);\n i--;\n }\n }\n\n // Turn off if nobody is watching\n if (this._viewedWatchers.length === 0) {\n this._toggleViewWatcher(false);\n }\n }\n\n /**\n * Turns the viewability watcher on and off\n * @param enabled\n * @private\n */\n _toggleViewWatcher(enabled) {\n if (enabled) {\n if (this._viewWatcherIv === null) {\n this._viewWatcherIv = setInterval(this._checkViewWatchers.bind(this), MINIMUM_VIEW_TIME / MINIMUM_VIEW_FREQ);\n }\n } else {\n clearInterval(this._viewWatcherIv);\n this._viewWatcherIv = null;\n }\n }\n\n //endregion\n\n //region Product Handling\n\n /**\n * Renders a product response\n * @private\n */\n _showProducts() {\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n\n // Determine template to render, using custom template name if it exists\n const templateName = this._getTemplate(Placement.ContentTypes.products, Placement.DefaultTemplates.products);\n\n // - render\n\n // Format products\n data.results.forEach((offer, index) => {\n // Disable inline buy if configured to do so\n if (this.config.disable_inline_buy) offer.inline_buy_url = null;\n if (offer.inline_buy_url) offer._escaped_inline_buy_url = encodeURIComponent(offer.inline_buy_url);\n\n // Set primary image\n offer._image_url = offer.image_urls ? offer.image_urls[0] : '' ;\n\n // Escape buy url (fixme: does not include proxy_url!)\n offer._escaped_buy_url = encodeURIComponent(offer.buy_url);\n\n // Make price tag pretty\n offer._price_formatted = TemplateEngine.formatCurrency(offer.price);\n offer._index = index;\n });\n\n const model = {\n css: !this.config.no_css\n };\n\n // Render and display the results\n this.setMarkup(okanjo.ui.engine.render(templateName, this, model));\n\n // Track widget impression\n if (data.results.length === 0) {\n // Hook point for no results found\n this.emit('empty');\n this._reportWidgetLoad('empty'); // decline the impression\n } else {\n this._reportWidgetLoad();\n }\n\n // Bind interaction handlers and track impressions\n this.element.querySelectorAll('a').forEach((a) => {\n\n const id = a.getAttribute('data-id'),\n index = a.getAttribute('data-index');\n\n // Don't bind links that are not tile links\n /* istanbul ignore else: custom templates could break it */\n if (id && index >= 0) {\n const product = this._response.data.results[index];\n /* istanbul ignore else: custom templates could break it */\n if (product) {\n\n // Bind interaction listener\n a.addEventListener('mousedown', this._handleResourceMouseDown.bind(this, Metrics.Object.product, product));\n a.addEventListener('click', this._handleProductClick.bind(this, product));\n\n // Track impression\n okanjo.metrics.create(this._metricBase, { id: product.id })\n .type(Metrics.Object.product, Metrics.Event.impression)\n .meta(this.getConfig())\n .meta({\n bf: product.backfill ? 1 : 0,\n sf: product.shortfill ? 1 : 0,\n spltfl_seg: product.splitfill_segment || null\n })\n .element(a)\n .viewport()\n .widget(this.element)\n .send();\n\n // Start watching for a viewable impression\n this._addOnceViewedHandler(a, () => {\n okanjo.metrics.create(this._metricBase, { id: product.id })\n .type(Metrics.Object.product, Metrics.Event.view)\n .meta(this.getConfig())\n .meta({\n bf: product.backfill ? 1 : 0,\n sf: product.shortfill ? 1 : 0,\n spltfl_seg: product.splitfill_segment || null\n })\n .element(a)\n .viewport()\n .widget(this.element)\n .send();\n });\n }\n }\n });\n\n // Truncate product name to fit the space\n this.element.querySelectorAll('.okanjo-resource-title').forEach((element) => {\n okanjo.ui.ellipsify(element);\n });\n\n // Fit images\n okanjo.ui.fitImages(this.element);\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n /**\n * Handles the product click process\n * @param product\n * @param e\n * @private\n */\n _handleProductClick(product, e) {\n\n // Update the event\n if (!product._event || !product._additionalParams || !product._clickId) {\n this._handleResourceMouseDown(Metrics.Object.product, product, e);\n }\n\n // Extract the already generated event and params list\n const {\n _event: event,\n _additionalParams: additionalParams\n } = product;\n\n // Update the event to the current one\n event.event(e);\n\n // Determine what we're doing - native ux or redirect\n const showNativeBuyUx = !!product.inline_buy_url,\n showPopupNativeBuyUx = !this.config.disable_popup && showNativeBuyUx && okanjo.util.isMobile()\n ;\n\n // Show the inline buy experience or redirect\n if (showPopupNativeBuyUx) {\n // Mobile native buy ux\n\n // Don't follow the link\n e.preventDefault();\n\n //\n // Mobile devices (especially iOS) have real janky UX when interacting with iframes.\n // So, we'll choose to popup a window with the native buy experience, so we can ensure\n // a positive user experience. Nobody likes bouncy form fields and really weird zooming.\n //\n\n // Update the event\n event\n .data({ ea: Metrics.Action.inline_click })\n .meta({ popup: 'true' });\n\n // Get the frame url\n let url = this._getClickThroughURL(event, product.inline_buy_url, additionalParams);\n\n // Open the window or redirect if that failed\n this._popupFrame = window.open(url, \"okanjo-inline-buy-frame\", \"width=400,height=400,location=yes,resizable=yes,scrollbars=yes\");\n /* istanbul ignore else: jsdom doesn't support window.open or setting window.location.href */\n if (!this._popupFrame) {\n // Fallback to just replacing the window with the target, since popups don't work :(\n okanjo.report('Popup blocker stopped buy experience from showing', { placement: this });\n window.location.href = url;\n }\n\n } else if (showNativeBuyUx) {\n // Regular native buy ux\n\n // Don't follow the link\n e.preventDefault();\n\n const frame = document.createElement('iframe');\n const attributes = {\n 'class': 'okanjo-inline-buy-frame',\n frameborder: 0,\n vspace: 0,\n hspace: 0,\n webkitallowfullscreen: '',\n mozallowfullscreen: '',\n allowfullscreen: '',\n scrolling: 'auto'\n };\n\n // Apply attributes\n Object.keys(attributes).forEach((key) => frame.setAttribute(key, attributes[key]));\n\n // Check whether we're allowed to expand past the bounds of the placement\n additionalParams.expandable = this.config.expandable ? 1: 0;\n if (!this.config.expandable) {\n const parent = this.element.querySelector('.okanjo-expansion-root');\n /* istanbul ignore else: custom templates could break this */\n if (parent) {\n frame.className += ' okanjo-ad-in-unit';\n frame.setAttribute('height', \"100%\");\n frame.setAttribute('width', \"100%\");\n\n parent.appendChild(frame);\n\n const size = okanjo.ui.getElementSize(parent);\n additionalParams.frame_height = size.height;\n additionalParams.frame_width = size.width;\n /* istanbul ignore next: i'm not writing a whole test for this one config param */\n if (this.config.size) additionalParams.ad_size = this.config.size;\n }\n }\n\n // Update the event\n event\n .data({ ea: Metrics.Action.inline_click })\n .meta({ expandable: this.config.expandable ? 'true' : 'false' });\n\n // Set the frame url\n frame.src = this._getClickThroughURL(event, product.inline_buy_url, additionalParams);\n\n // Show the modal if it was not internally expanded\n if (!frame.parentNode) {\n okanjo.ui.modal.show(frame);\n }\n\n } else {\n // Update the link a second time, just in case the data changed\n e.currentTarget.href = this._getClickThroughURL(event, product.buy_url, additionalParams);\n }\n }\n\n //endregion\n\n //region Article Handling\n\n /**\n * Renders an article response\n * @private\n */\n _showArticles() {\n const data = (this._response || { data: { results: [] } }).data || { results: [] };\n\n // Determine template to render, using custom template name if it exists\n const templateName = this._getTemplate(Placement.ContentTypes.articles, Placement.DefaultTemplates.articles);\n\n // - render\n\n // Format articles\n data.results.forEach((article, index) => {\n // Escape url (fixme: does not include proxy_url!)\n article._escaped_url = encodeURIComponent(article.url);\n article._index = index;\n });\n\n const model = {\n css: !this.config.no_css\n };\n\n // Render and display the results\n this.setMarkup(okanjo.ui.engine.render(templateName, this, model));\n\n // Track widget impression\n if (data.results.length === 0) {\n // Hook point for no results found\n this.emit('empty');\n this._reportWidgetLoad('empty'); // decline the impression\n } else {\n this._reportWidgetLoad();\n }\n\n // Bind interaction handlers and track impressions\n this.element.querySelectorAll('a').forEach((a) => {\n\n const id = a.getAttribute('data-id'),\n index = a.getAttribute('data-index');\n\n // Don't bind links that are not tile links\n /* istanbul ignore else: custom templates could break this */\n if (id && index >= 0) {\n const article = this._response.data.results[index];\n /* istanbul ignore else: custom templates could break this */\n if (article) {\n\n // Bind interaction listener\n a.addEventListener('mousedown', this._handleResourceMouseDown.bind(this, Metrics.Object.article, article));\n a.addEventListener('click', this._handleArticleClick.bind(this, article));\n\n // Track impression\n okanjo.metrics.create(this._metricBase, { id: article.id })\n .type(Metrics.Object.article, Metrics.Event.impression)\n .meta(this.getConfig())\n .meta({\n bf: article.backfill ? 1 : 0,\n sf: article.shortfill ? 1 : 0,\n spltfl_seg: article.splitfill_segment || null\n })\n .element(a)\n .viewport()\n .widget(this.element)\n .send();\n\n // Start watching for a viewable impression\n this._addOnceViewedHandler(a, () => {\n okanjo.metrics.create(this._metricBase, { id: article.id })\n .type(Metrics.Object.article, Metrics.Event.view)\n .meta(this.getConfig())\n .meta({\n bf: article.backfill ? 1 : 0,\n sf: article.shortfill ? 1 : 0,\n spltfl_seg: article.splitfill_segment || null\n })\n .element(a)\n .viewport()\n .widget(this.element)\n .send();\n });\n\n }\n }\n });\n\n // Truncate product name to fit the space\n this.element.querySelectorAll('.okanjo-resource-title').forEach((element) => {\n okanjo.ui.ellipsify(element);\n });\n\n // Fit images\n okanjo.ui.fitImages(this.element);\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n /**\n * Handles the article click process\n * @param article\n * @param e\n * @private\n */\n _handleArticleClick(article, e) {\n // Update the event\n if (!article._event || !article._additionalParams || !article._clickId) {\n this._handleResourceMouseDown(Metrics.Object.article, article, e);\n }\n\n // Extract the already generated event and params list\n const {\n _event: event,\n _additionalParams: additionalParams\n } = article;\n\n // Update the event to the current one\n event.event(e);\n\n // Update the link a second time, just in case the data changed\n e.currentTarget.href = this._getClickThroughURL(event, article.url, additionalParams);\n }\n\n //endregion\n\n //region ADX Handling\n\n /**\n * Renders a Google DFP/ADX response\n * @private\n */\n _showADX() {\n const data = (this._response || { data: { settings: {} } }).data || { settings: {} };\n\n // Get the template we should use to render the google ad\n const templateName = this._getTemplate(Placement.ContentTypes.adx, Placement.DefaultTemplates.adx);\n\n // Determine what size ad we can place here\n let size = null;\n if (this.config.size) {\n if (Placement.Sizes[this.config.size]) {\n // Defined size, use these known dimensions\n size = Placement.Sizes[this.config.size];\n } else {\n let match = (/^([0-9]+)x([0-9]+)$/i).exec(this.config.size);\n if (match) {\n size = { width: match[1], height: match[2] }\n }\n }\n }\n\n // No given size, we need to guess\n if (!size) size = Placement.Sizes.default;\n\n // If we're using okanjo's ad slot, then track the impression\n // otherwise decline it because we're just passing through to the publishers account\n let adUnitPath = '/90447967/okanjo:';\n let declineReason;\n if (data.settings.display && data.settings.display.adx_unit_path) {\n adUnitPath = data.settings.display.adx_unit_path;\n declineReason = 'custom_ad_unit';\n }\n\n // Pass along what the template needs to know to display the ad\n const renderContext = {\n css: !this.config.no_css,\n size,\n adUnitPath\n };\n\n // Render the container\n this.setMarkup(okanjo.ui.engine.render(templateName, this, renderContext));\n\n // Report the impression\n this._reportWidgetLoad(declineReason);\n\n // Insert the actual ad into the container\n const container = this.element.querySelector('.okanjo-adx-container');\n /* istanbul ignore else: custom templates could break this */\n if (container) {\n\n // Make the frame element\n const frame = document.createElement('iframe');\n const attributes = {\n 'class': 'okanjo-adx-frame',\n frameborder: 0,\n vspace: 0,\n hspace: 0,\n webkitallowfullscreen: '',\n mozallowfullscreen: '',\n allowfullscreen: '',\n scrolling: 'auto',\n width: size.width,\n height: size.height\n };\n\n // Apply attributes\n Object.keys(attributes).forEach((key) => frame.setAttribute(key, attributes[key]));\n\n // Attach to dOM\n container.appendChild(frame);\n\n // Build a click-through tracking url so we know when an ad is clicked too\n let clickUrl = okanjo.metrics.create(this._metricBase)\n .type(Metrics.Object.thirdparty_ad, Metrics.Event.interaction)\n .meta(this.getConfig())\n .meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n })\n .element(frame)\n .viewport()\n .widget(this.element)\n .toUrl();\n\n // Transfer references to the frame window\n // frame.contentWindow.okanjo = okanjo;\n // frame.contentWindow.placement = this;\n frame.contentWindow.trackImpression = () => {\n okanjo.metrics.create(this._metricBase)\n .type(Metrics.Object.thirdparty_ad, Metrics.Event.impression)\n .meta(this.getConfig())\n .meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n })\n .element(frame)\n .viewport()\n .widget(this.element)\n .send()\n ;\n\n // Start watching for a viewable impression\n this._addOnceViewedHandler(frame, () => {\n okanjo.metrics.create(this._metricBase)\n .type(Metrics.Object.thirdparty_ad, Metrics.Event.view)\n .meta(this.getConfig())\n .meta({\n ta_s: adUnitPath,\n ta_w: size.width,\n ta_h: size.height\n })\n .element(frame)\n .viewport()\n .widget(this.element)\n .send()\n ;\n });\n };\n\n // Load Google ad!\n frame.contentWindow.document.open();\n frame.contentWindow.document.write(\n`\n<`+`script type=\"text/javascript\" src=\"https://www.googletagservices.com/tag/js/gpt.js\">\n googletag.pubads().addEventListener('slotRenderEnded', function(e) { \n trackImpression(e);\n });\n googletag.pubads()\n .definePassback(\"${adUnitPath.replace(/\"/g, '\\\\\"')}\", [[${size.width}, ${size.height}]])\n .setClickUrl(\"${clickUrl}&u=\")\n .display();\n<`+`/script>\n`);\n frame.contentWindow.document.close();\n\n // TODO future event hooks\n // googletag.pubads().addEventListener('impressionViewable', function(e) { future )});\n // googletag.pubads().addEventListener('slotOnload', function(e) { future });\n // googletag.pubads().addEventListener('slotVisibilityChangedEvent', function(e) { future );\n\n // Impression tracking is done from within the iframe. Crazy, right?\n }\n\n // Hook point that the widget is done loading\n this.emit('load');\n }\n\n //endregion\n }\n\n //region Enumerations\n\n /**\n * Standard ad sizes\n * @type {{billboard: {width: number, height: number}, button_2: {width: number, height: number}, half_page: {width: number, height: number}, leaderboard: {width: number, height: number}, medium_rectangle: {width: number, height: number}, micro_bar: {width: number, height: number}, portrait: {width: number, height: number}, rectangle: {width: number, height: number}, super_leaderboard: {width: number, height: number}, wide_skyscraper: {width: number, height: number}, large_mobile_banner: {width: number, height: number}, mobile_leaderboard: {width: number, height: number}, small_square: {width: number, height: number}, button_1: {width: number, height: number}, full_banner: {width: number, height: number}, half_banner: {width: number, height: number}, large_rectangle: {width: number, height: number}, pop_under: {width: number, height: number}, three_to_one_rectangle: {width: number, height: number}, skyscraper: {width: number, height: number}, square: {width: number, height: number}, square_button: {width: number, height: number}, vertical_banner: {width: number, height: number}, vertical_rectangle: {width: number, height: number}}}\n */\n Placement.Sizes = {\n\n // Supported\n medium_rectangle: { width: 300, height: 250 }, // aka: sidekick\n leaderboard: { width: 728, height: 90 },\n large_mobile_banner: { width: 320, height: 100 },\n half_page: { width: 300, height: 600 }, // aka: filmstrip, sidekick\n billboard: { width: 970, height: 250 }, // aka: sidekick\n\n // IAB / Others\n button_2: { width: 120, height: 60 },\n micro_bar: { width: 88, height: 31 },\n portrait: { width: 300, height:1050 },\n rectangle: { width: 180, height: 150 },\n super_leaderboard: { width: 970, height: 90 }, // aka: pushdown, slider, large_leaderboard\n wide_skyscraper: { width: 160, height: 600 },\n\n // Google\n mobile_leaderboard: { width: 320, height: 50 },\n small_square: { width: 200, height: 200 },\n\n // Retired / Deprecated\n button_1: { width: 120, height: 90 },\n full_banner: { width: 468, height: 60 },\n half_banner: { width: 234, height: 60 },\n large_rectangle: { width: 336, height: 280 },\n pop_under: { width: 720, height: 300 },\n three_to_one_rectangle: { width: 300, height: 100 },\n skyscraper: { width: 120, height: 600 },\n square: { width: 250, height: 250 },\n square_button: { width: 125, height: 125 },\n vertical_banner: { width: 120, height: 240 },\n vertical_rectangle: { width: 240, height: 400 }\n };\n\n // When we should show an ad but nobody told us what size\n Placement.Sizes.default = Placement.Sizes.medium_rectangle;\n\n /**\n * Placement content types\n * @type {{products: string, articles: string, adx: string}}\n */\n Placement.ContentTypes = {\n products: 'products',\n articles: 'articles',\n adx: 'adx'\n };\n\n /**\n * Default templates for each content type\n * @type {{products: string, articles: string, adx: string}}\n */\n Placement.DefaultTemplates = {\n products: 'block2',\n articles: 'block2',\n adx: 'block2'\n };\n\n //endregion\n\n return okanjo.Placement = Placement;\n\n})(window);","\"use strict\";\n\n// **********\n// DEPRECATED - USE okanjo.Placement instead!\n// **********\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window) {\n\n const okanjo = window.okanjo;\n\n /**\n * Backwards compatible interface, turning a Product widget into a placement widget\n * @deprecated\n */\n class Product extends okanjo.Placement {\n\n constructor(element, options) {\n // Initialize placement w/o loading (we need to jack the config)\n options = options || {};\n const no_init = options.no_init; // hold original no_init flag, if set\n options.no_init = true;\n super(element, options);\n\n okanjo.warn('Product widget has been deprecated. Use Placement instead (may require configuration changes)', { widget: this });\n\n // Start loading content\n if (!no_init) {\n delete this.config.no_init;\n this.init();\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Converts the old product widget configuration into a usable placement configuration\n */\n _setCompatibilityOptions() {\n // Convert the product config to a placement configuration\n this.config.backwards = 'Product';\n this.config.type = okanjo.Placement.ContentTypes.products;\n\n // Set filters based on old \"mode\"\n if (this.config.mode === 'sense') {\n // sense\n this.config.url = this.config.url || 'referrer';\n this.config.take = this.config.take || 5;\n } else if (this.config.mode === 'single') {\n // single\n this.config.url = null;\n if (this.config.id) this.config.ids = [this.config.id];\n this.config.take = 1;\n delete this.config.id;\n } else {\n // browse\n this.config.url = null;\n this.config.take = this.config.take || 25;\n }\n delete this.config.mode;\n\n // Sold by changed to store name\n if (this.config.sold_by) {\n this.config.store_name = this.config.sold_by;\n delete this.config.sold_by;\n }\n\n // Selectors is now url_selectors\n if (this.config.selectors) {\n this.config.url_selectors = this.config.selectors;\n delete this.config.selectors;\n }\n\n // Marketplace_id is no longer a thing, closest analog are properties.\n if (this.config.marketplace_id) {\n this.config.property_id = this.config.marketplace_id;\n delete this.config.marketplace_id\n }\n\n // Marketplace status is no longer a thing, instead, use the sandbox environment for testing\n if (this.config.marketplace_status === 'testing') {\n this.config.sandbox = true;\n }\n delete this.config.marketplace_status;\n\n // Deprecated\n delete this.config.suboptimal;\n delete this.config.text;\n }\n\n }\n\n return okanjo.Product = Product;\n\n})(window);","\"use strict\";\n\n// **********\n// DEPRECATED - USE okanjo.Placement instead!\n// **********\n\n//noinspection ThisExpressionReferencesGlobalObjectJS,JSUnusedLocalSymbols\n(function(window) {\n\n const okanjo = window.okanjo;\n\n /**\n * Backwards compatible interface, turning an Ad widget into a placement widget\n * @deprecated\n */\n class Ad extends okanjo.Placement {\n\n constructor(element, options) {\n // Initialize placement w/o loading (we need to jack the config)\n options = options || {};\n const no_init = options.no_init; // hold original no_init flag, if set\n options.no_init = true;\n super(element, options);\n\n okanjo.warn('Ad widget has been deprecated. Use Placement instead (may require configuration changes)', { widget: this });\n\n // Start loading content\n if (!no_init) {\n delete this.config.no_init;\n this.init();\n }\n }\n\n //noinspection JSUnusedGlobalSymbols\n /**\n * Converts the old product widget configuration into a usable placement configuration\n */\n _setCompatibilityOptions() {\n // Convert the product config to a placement configuration\n this.config.backwards = 'Ad';\n this.config.type = okanjo.Placement.ContentTypes.products;\n\n // Id / single mode is now ids\n this.config.url = null;\n if (this.config.id) {\n this.config.ids = [this.config.id];\n } else {\n okanjo.warn('Ad widget should have parameter `id` set.');\n }\n this.config.take = 1;\n delete this.config.id;\n\n // Content is automatically determined whether the placement element contains children\n delete this.config.content;\n }\n\n }\n\n return okanjo.Ad = Ad;\n\n})(window);","/* jshint ignore:start */\n\n(function() {\n\n/*!\n * mustache.js - Logic-less {{mustache}} templates with JavaScript\n * http://github.com/janl/mustache.js\n */\n\n/*global define: false Mustache: true*/\n\n(function defineMustache (global, factory) {\n if (typeof exports === 'object' && exports && typeof exports.nodeName !== 'string') {\n factory(exports); // CommonJS\n } else if (typeof define === 'function' && define.amd) {\n define(['exports'], factory); // AMD\n } else {\n global.Mustache = {};\n factory(global.Mustache); // script, wsh, asp\n }\n}(this, function mustacheFactory (mustache) {\n\n var objectToString = Object.prototype.toString;\n var isArray = Array.isArray || function isArrayPolyfill (object) {\n return objectToString.call(object) === '[object Array]';\n };\n\n function isFunction (object) {\n return typeof object === 'function';\n }\n\n /**\n * More correct typeof string handling array\n * which normally returns typeof 'object'\n */\n function typeStr (obj) {\n return isArray(obj) ? 'array' : typeof obj;\n }\n\n function escapeRegExp (string) {\n return string.replace(/[\\-\\[\\]{}()*+?.,\\\\\\^$|#\\s]/g, '\\\\$&');\n }\n\n /**\n * Null safe way of checking whether or not an object,\n * including its prototype, has a given property\n */\n function hasProperty (obj, propName) {\n return obj != null && typeof obj === 'object' && (propName in obj);\n }\n\n // Workaround for https://issues.apache.org/jira/browse/COUCHDB-577\n // See https://github.com/janl/mustache.js/issues/189\n var regExpTest = RegExp.prototype.test;\n function testRegExp (re, string) {\n return regExpTest.call(re, string);\n }\n\n var nonSpaceRe = /\\S/;\n function isWhitespace (string) {\n return !testRegExp(nonSpaceRe, string);\n }\n\n var entityMap = {\n '&': '&',\n '<': '<',\n '>': '>',\n '\"': '"',\n \"'\": ''',\n '/': '/',\n '`': '`',\n '=': '='\n };\n\n function escapeHtml (string) {\n return String(string).replace(/[&<>\"'`=\\/]/g, function fromEntityMap (s) {\n return entityMap[s];\n });\n }\n\n var whiteRe = /\\s*/;\n var spaceRe = /\\s+/;\n var equalsRe = /\\s*=/;\n var curlyRe = /\\s*\\}/;\n var tagRe = /#|\\^|\\/|>|\\{|&|=|!/;\n\n /**\n * Breaks up the given `template` string into a tree of tokens. If the `tags`\n * argument is given here it must be an array with two string values: the\n * opening and closing tags used in the template (e.g. [ \"<%\", \"%>\" ]). Of\n * course, the default is to use mustaches (i.e. mustache.tags).\n *\n * A token is an array with at least 4 elements. The first element is the\n * mustache symbol that was used inside the tag, e.g. \"#\" or \"&\". If the tag\n * did not contain a symbol (i.e. {{myValue}}) this element is \"name\". For\n * all text that appears outside a symbol this element is \"text\".\n *\n * The second element of a token is its \"value\". For mustache tags this is\n * whatever else was inside the tag besides the opening symbol. For text tokens\n * this is the text itself.\n *\n * The third and fourth elements of the token are the start and end indices,\n * respectively, of the token in the original template.\n *\n * Tokens that are the root node of a subtree contain two more elements: 1) an\n * array of tokens in the subtree and 2) the index in the original template at\n * which the closing tag for that section begins.\n */\n function parseTemplate (template, tags) {\n if (!template)\n return [];\n\n var sections = []; // Stack to hold section tokens\n var tokens = []; // Buffer to hold the tokens\n var spaces = []; // Indices of whitespace tokens on the current line\n var hasTag = false; // Is there a {{tag}} on the current line?\n var nonSpace = false; // Is there a non-space char on the current line?\n\n // Strips all whitespace tokens array for the current line\n // if there was a {{#tag}} on it and otherwise only space.\n function stripSpace () {\n if (hasTag && !nonSpace) {\n while (spaces.length)\n delete tokens[spaces.pop()];\n } else {\n spaces = [];\n }\n\n hasTag = false;\n nonSpace = false;\n }\n\n var openingTagRe, closingTagRe, closingCurlyRe;\n function compileTags (tagsToCompile) {\n if (typeof tagsToCompile === 'string')\n tagsToCompile = tagsToCompile.split(spaceRe, 2);\n\n if (!isArray(tagsToCompile) || tagsToCompile.length !== 2)\n throw new Error('Invalid tags: ' + tagsToCompile);\n\n openingTagRe = new RegExp(escapeRegExp(tagsToCompile[0]) + '\\\\s*');\n closingTagRe = new RegExp('\\\\s*' + escapeRegExp(tagsToCompile[1]));\n closingCurlyRe = new RegExp('\\\\s*' + escapeRegExp('}' + tagsToCompile[1]));\n }\n\n compileTags(tags || mustache.tags);\n\n var scanner = new Scanner(template);\n\n var start, type, value, chr, token, openSection;\n while (!scanner.eos()) {\n start = scanner.pos;\n\n // Match any text between tags.\n value = scanner.scanUntil(openingTagRe);\n\n if (value) {\n for (var i = 0, valueLength = value.length; i < valueLength; ++i) {\n chr = value.charAt(i);\n\n if (isWhitespace(chr)) {\n spaces.push(tokens.length);\n } else {\n nonSpace = true;\n }\n\n tokens.push([ 'text', chr, start, start + 1 ]);\n start += 1;\n\n // Check for whitespace on the current line.\n if (chr === '\\n')\n stripSpace();\n }\n }\n\n // Match the opening tag.\n if (!scanner.scan(openingTagRe))\n break;\n\n hasTag = true;\n\n // Get the tag type.\n type = scanner.scan(tagRe) || 'name';\n scanner.scan(whiteRe);\n\n // Get the tag value.\n if (type === '=') {\n value = scanner.scanUntil(equalsRe);\n scanner.scan(equalsRe);\n scanner.scanUntil(closingTagRe);\n } else if (type === '{') {\n value = scanner.scanUntil(closingCurlyRe);\n scanner.scan(curlyRe);\n scanner.scanUntil(closingTagRe);\n type = '&';\n } else {\n value = scanner.scanUntil(closingTagRe);\n }\n\n // Match the closing tag.\n if (!scanner.scan(closingTagRe))\n throw new Error('Unclosed tag at ' + scanner.pos);\n\n token = [ type, value, start, scanner.pos ];\n tokens.push(token);\n\n if (type === '#' || type === '^') {\n sections.push(token);\n } else if (type === '/') {\n // Check section nesting.\n openSection = sections.pop();\n\n if (!openSection)\n throw new Error('Unopened section \"' + value + '\" at ' + start);\n\n if (openSection[1] !== value)\n throw new Error('Unclosed section \"' + openSection[1] + '\" at ' + start);\n } else if (type === 'name' || type === '{' || type === '&') {\n nonSpace = true;\n } else if (type === '=') {\n // Set the tags for the next time around.\n compileTags(value);\n }\n }\n\n // Make sure there are no open sections when we're done.\n openSection = sections.pop();\n\n if (openSection)\n throw new Error('Unclosed section \"' + openSection[1] + '\" at ' + scanner.pos);\n\n return nestTokens(squashTokens(tokens));\n }\n\n /**\n * Combines the values of consecutive text tokens in the given `tokens` array\n * to a single token.\n */\n function squashTokens (tokens) {\n var squashedTokens = [];\n\n var token, lastToken;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n token = tokens[i];\n\n if (token) {\n if (token[0] === 'text' && lastToken && lastToken[0] === 'text') {\n lastToken[1] += token[1];\n lastToken[3] = token[3];\n } else {\n squashedTokens.push(token);\n lastToken = token;\n }\n }\n }\n\n return squashedTokens;\n }\n\n /**\n * Forms the given array of `tokens` into a nested tree structure where\n * tokens that represent a section have two additional items: 1) an array of\n * all tokens that appear in that section and 2) the index in the original\n * template that represents the end of that section.\n */\n function nestTokens (tokens) {\n var nestedTokens = [];\n var collector = nestedTokens;\n var sections = [];\n\n var token, section;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n token = tokens[i];\n\n switch (token[0]) {\n case '#':\n case '^':\n collector.push(token);\n sections.push(token);\n collector = token[4] = [];\n break;\n case '/':\n section = sections.pop();\n section[5] = token[2];\n collector = sections.length > 0 ? sections[sections.length - 1][4] : nestedTokens;\n break;\n default:\n collector.push(token);\n }\n }\n\n return nestedTokens;\n }\n\n /**\n * A simple string scanner that is used by the template parser to find\n * tokens in template strings.\n */\n function Scanner (string) {\n this.string = string;\n this.tail = string;\n this.pos = 0;\n }\n\n /**\n * Returns `true` if the tail is empty (end of string).\n */\n Scanner.prototype.eos = function eos () {\n return this.tail === '';\n };\n\n /**\n * Tries to match the given regular expression at the current position.\n * Returns the matched text if it can match, the empty string otherwise.\n */\n Scanner.prototype.scan = function scan (re) {\n var match = this.tail.match(re);\n\n if (!match || match.index !== 0)\n return '';\n\n var string = match[0];\n\n this.tail = this.tail.substring(string.length);\n this.pos += string.length;\n\n return string;\n };\n\n /**\n * Skips all text until the given regular expression can be matched. Returns\n * the skipped string, which is the entire tail if no match can be made.\n */\n Scanner.prototype.scanUntil = function scanUntil (re) {\n var index = this.tail.search(re), match;\n\n switch (index) {\n case -1:\n match = this.tail;\n this.tail = '';\n break;\n case 0:\n match = '';\n break;\n default:\n match = this.tail.substring(0, index);\n this.tail = this.tail.substring(index);\n }\n\n this.pos += match.length;\n\n return match;\n };\n\n /**\n * Represents a rendering context by wrapping a view object and\n * maintaining a reference to the parent context.\n */\n function Context (view, parentContext) {\n this.view = view;\n this.cache = { '.': this.view };\n this.parent = parentContext;\n }\n\n /**\n * Creates a new context using the given view with this context\n * as the parent.\n */\n Context.prototype.push = function push (view) {\n return new Context(view, this);\n };\n\n /**\n * Returns the value of the given name in this context, traversing\n * up the context hierarchy if the value is absent in this context's view.\n */\n Context.prototype.lookup = function lookup (name) {\n var cache = this.cache;\n\n var value;\n if (cache.hasOwnProperty(name)) {\n value = cache[name];\n } else {\n var context = this, names, index, lookupHit = false;\n\n while (context) {\n if (name.indexOf('.') > 0) {\n value = context.view;\n names = name.split('.');\n index = 0;\n\n /**\n * Using the dot notion path in `name`, we descend through the\n * nested objects.\n *\n * To be certain that the lookup has been successful, we have to\n * check if the last object in the path actually has the property\n * we are looking for. We store the result in `lookupHit`.\n *\n * This is specially necessary for when the value has been set to\n * `undefined` and we want to avoid looking up parent contexts.\n **/\n while (value != null && index < names.length) {\n if (index === names.length - 1)\n lookupHit = hasProperty(value, names[index]);\n\n value = value[names[index++]];\n }\n } else {\n value = context.view[name];\n lookupHit = hasProperty(context.view, name);\n }\n\n if (lookupHit)\n break;\n\n context = context.parent;\n }\n\n cache[name] = value;\n }\n\n if (isFunction(value))\n value = value.call(this.view);\n\n return value;\n };\n\n /**\n * A Writer knows how to take a stream of tokens and render them to a\n * string, given a context. It also maintains a cache of templates to\n * avoid the need to parse the same template twice.\n */\n function Writer () {\n this.cache = {};\n }\n\n /**\n * Clears all cached templates in this writer.\n */\n Writer.prototype.clearCache = function clearCache () {\n this.cache = {};\n };\n\n /**\n * Parses and caches the given `template` and returns the array of tokens\n * that is generated from the parse.\n */\n Writer.prototype.parse = function parse (template, tags) {\n var cache = this.cache;\n var tokens = cache[template];\n\n if (tokens == null)\n tokens = cache[template] = parseTemplate(template, tags);\n\n return tokens;\n };\n\n /**\n * High-level method that is used to render the given `template` with\n * the given `view`.\n *\n * The optional `partials` argument may be an object that contains the\n * names and templates of partials that are used in the template. It may\n * also be a function that is used to load partial templates on the fly\n * that takes a single argument: the name of the partial.\n */\n Writer.prototype.render = function render (template, view, partials) {\n var tokens = this.parse(template);\n var context = (view instanceof Context) ? view : new Context(view);\n return this.renderTokens(tokens, context, partials, template);\n };\n\n /**\n * Low-level method that renders the given array of `tokens` using\n * the given `context` and `partials`.\n *\n * Note: The `originalTemplate` is only ever used to extract the portion\n * of the original template that was contained in a higher-order section.\n * If the template doesn't use higher-order sections, this argument may\n * be omitted.\n */\n Writer.prototype.renderTokens = function renderTokens (tokens, context, partials, originalTemplate) {\n var buffer = '';\n\n var token, symbol, value;\n for (var i = 0, numTokens = tokens.length; i < numTokens; ++i) {\n value = undefined;\n token = tokens[i];\n symbol = token[0];\n\n if (symbol === '#') value = this.renderSection(token, context, partials, originalTemplate);\n else if (symbol === '^') value = this.renderInverted(token, context, partials, originalTemplate);\n else if (symbol === '>') value = this.renderPartial(token, context, partials, originalTemplate);\n else if (symbol === '&') value = this.unescapedValue(token, context);\n else if (symbol === 'name') value = this.escapedValue(token, context);\n else if (symbol === 'text') value = this.rawValue(token);\n\n if (value !== undefined)\n buffer += value;\n }\n\n return buffer;\n };\n\n Writer.prototype.renderSection = function renderSection (token, context, partials, originalTemplate) {\n var self = this;\n var buffer = '';\n var value = context.lookup(token[1]);\n\n // This function is used to render an arbitrary template\n // in the current context by higher-order sections.\n function subRender (template) {\n return self.render(template, context, partials);\n }\n\n if (!value) return;\n\n if (isArray(value)) {\n for (var j = 0, valueLength = value.length; j < valueLength; ++j) {\n buffer += this.renderTokens(token[4], context.push(value[j]), partials, originalTemplate);\n }\n } else if (typeof value === 'object' || typeof value === 'string' || typeof value === 'number') {\n buffer += this.renderTokens(token[4], context.push(value), partials, originalTemplate);\n } else if (isFunction(value)) {\n if (typeof originalTemplate !== 'string')\n throw new Error('Cannot use higher-order sections without the original template');\n\n // Extract the portion of the original template that the section contains.\n value = value.call(context.view, originalTemplate.slice(token[3], token[5]), subRender);\n\n if (value != null)\n buffer += value;\n } else {\n buffer += this.renderTokens(token[4], context, partials, originalTemplate);\n }\n return buffer;\n };\n\n Writer.prototype.renderInverted = function renderInverted (token, context, partials, originalTemplate) {\n var value = context.lookup(token[1]);\n\n // Use JavaScript's definition of falsy. Include empty arrays.\n // See https://github.com/janl/mustache.js/issues/186\n if (!value || (isArray(value) && value.length === 0))\n return this.renderTokens(token[4], context, partials, originalTemplate);\n };\n\n Writer.prototype.renderPartial = function renderPartial (token, context, partials) {\n if (!partials) return;\n\n var value = isFunction(partials) ? partials(token[1]) : partials[token[1]];\n if (value != null)\n return this.renderTokens(this.parse(value), context, partials, value);\n };\n\n Writer.prototype.unescapedValue = function unescapedValue (token, context) {\n var value = context.lookup(token[1]);\n if (value != null)\n return value;\n };\n\n Writer.prototype.escapedValue = function escapedValue (token, context) {\n var value = context.lookup(token[1]);\n if (value != null)\n return mustache.escape(value);\n };\n\n Writer.prototype.rawValue = function rawValue (token) {\n return token[1];\n };\n\n mustache.name = 'mustache.js';\n mustache.version = '2.3.2';\n mustache.tags = [ '{{', '}}' ];\n\n // All high-level mustache.* functions use this writer.\n var defaultWriter = new Writer();\n\n /**\n * Clears all cached templates in the default writer.\n */\n mustache.clearCache = function clearCache () {\n return defaultWriter.clearCache();\n };\n\n /**\n * Parses and caches the given template in the default writer and returns the\n * array of tokens it contains. Doing this ahead of time avoids the need to\n * parse templates on the fly as they are rendered.\n */\n mustache.parse = function parse (template, tags) {\n return defaultWriter.parse(template, tags);\n };\n\n /**\n * Renders the `template` with the given `view` and `partials` using the\n * default writer.\n */\n mustache.render = function render (template, view, partials) {\n if (typeof template !== 'string') {\n throw new TypeError('Invalid template! Template should be a \"string\" ' +\n 'but \"' + typeStr(template) + '\" was given as the first ' +\n 'argument for mustache#render(template, view, partials)');\n }\n\n return defaultWriter.render(template, view, partials);\n };\n\n // This is here for backwards compatibility with 0.4.x.,\n /*eslint-disable */ // eslint wants camel cased function name\n mustache.to_html = function to_html (template, view, partials, send) {\n /*eslint-enable*/\n\n var result = mustache.render(template, view, partials);\n\n if (isFunction(send)) {\n send(result);\n } else {\n return result;\n }\n };\n\n // Export the escaping function so that the user may override it.\n // See https://github.com/janl/mustache.js/issues/244\n mustache.escape = escapeHtml;\n\n // Export these mainly for testing, but also for advanced usage.\n mustache.Scanner = Scanner;\n mustache.Context = Context;\n mustache.Writer = Writer;\n\n return mustache;\n}));\n\n\n}).apply(okanjo.lib);\n\n/* jshint ignore:end */"],"sourceRoot":"./"} \ No newline at end of file diff --git a/examples/dfp.html b/examples/dfp.html index 2d2bc0f..56583e0 100644 --- a/examples/dfp.html +++ b/examples/dfp.html @@ -8,7 +8,7 @@ outside of the iframe (when able to do so) to enable expandable functionality. -->