From b54d1f4d79125ceac71c49e5eba5194dcc0177ac Mon Sep 17 00:00:00 2001 From: Kevin Fitzgerald Date: Mon, 6 Apr 2020 13:35:08 -0500 Subject: [PATCH] Use server generated cids - Placement.js: use resource defined cid instead of generating one client side - _test_responses.js: Updated to include cids - gulpfile.js: Added task option to skip version bump - package.json: Bumped minor to 1.14.0 --- dist/okanjo-bundle.js | 9 +++++---- 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 | 7 ++++--- dist/okanjo.min.js | 8 ++++---- dist/okanjo.min.js.map | 2 +- gulpfile.js | 11 +++++++++-- package-lock.json | 2 +- package.json | 2 +- src/Placement.js | 3 ++- test/_test_responses.js | 33 +++++++++++++++++++++----------- 17 files changed, 65 insertions(+), 44 deletions(-) diff --git a/dist/okanjo-bundle.js b/dist/okanjo-bundle.js index 6e20f1a..4ef3454 100644 --- a/dist/okanjo-bundle.js +++ b/dist/okanjo-bundle.js @@ -1,4 +1,4 @@ -/*! okanjo-js v1.13.2 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.14.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.13.2", + version: "1.14.0", /** * Placeholder @@ -3476,7 +3476,8 @@ var okanjo = function (window, document) { key: '_handleResourceMouseDown', value: function _handleResourceMouseDown(type, resource, e) { // Generate a new click id for this event - var clickId = okanjo.util.shortid(); + // const clickId = okanjo.util.shortid(); + var clickId = resource._cid; // Start building the event var event = okanjo.metrics.create(this._metricBase, { @@ -5002,7 +5003,7 @@ var okanjo = function (window, document) { return okanjo; })); -/*! okanjo-js v1.13.2 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.14.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 f550b03..3f91493 100644 --- a/dist/okanjo-bundle.min.js +++ b/dist/okanjo-bundle.min.js @@ -1,11 +1,11 @@ -/*! okanjo-js v1.13.2 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ -/*! okanjo-js v1.13.2 | (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.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(e,o,n){var i=new Date;i.setDate(i.getDate()+n);var a=n?" Expires="+i.toUTCString()+";":"",r=" Path=/",s=encodeURI(o)+";"+a+r;t.cookie=e+"="+s},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(t,o){t=t||{},t.object_type=a.Object.page,t.event_type=a.Event.view,t.id=t.id||e.location.href,t.ch=t.ch||this.defaultChannel,this.trackEvent(t,o)}},{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(t,o){var n=this,a=t.map(function(e){return n._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),r={events:a,win:e.location.href},s=i.net.getRoute(i.net.routes.metrics_batch);this.sid&&(r.sid=this.sid),i.net.request.post(s,r,function(e,n){e&&i.report("Failed to send metrics batch",{err:e,res:n,items:t,route:s}),o&&o(e,n)})}},{key:"_normalizeEvent",value:function(o){o.m=o.m||{},o.key=o.key||o.m.key||i.key||void 0,this.sid&&(o.sid=this.sid),o.m=Object.assign({},o.m),Object.keys(a.Meta.exclude).forEach(function(e){return delete o.m[e]}),this.sourceCh&&(o.m.ref_ch=this.sourceCh),this.sourceCx&&(o.m.ref_cx=this.sourceCx),o.m.pgid=this.pageId,o.m.ok_ver=i.version,o.m=i.util.flatten(o.m,{arrayToCsv:!0}),Object.keys(o.m).forEach(function(e){"string"==typeof o.m[e]&&(o.m[e]=o.m[e].substr(0,255))}),t.referrer&&(o.ref=t.referrer),o.win=e.location.href}},{key:"_updateSid",value:function(t){!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;o1?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().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().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.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=a.util.shortid(),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(),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]]=(a.metrics.sid||"unknown")+":"+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().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().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().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().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().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().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().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.14.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.14.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.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(e,o,n){var i=new Date;i.setDate(i.getDate()+n);var a=n?" Expires="+i.toUTCString()+";":"",r=" Path=/",s=encodeURI(o)+";"+a+r;t.cookie=e+"="+s},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(t,o){t=t||{},t.object_type=a.Object.page,t.event_type=a.Event.view,t.id=t.id||e.location.href,t.ch=t.ch||this.defaultChannel,this.trackEvent(t,o)}},{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(t,o){var n=this,a=t.map(function(e){return n._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),r={events:a,win:e.location.href},s=i.net.getRoute(i.net.routes.metrics_batch);this.sid&&(r.sid=this.sid),i.net.request.post(s,r,function(e,n){e&&i.report("Failed to send metrics batch",{err:e,res:n,items:t,route:s}),o&&o(e,n)})}},{key:"_normalizeEvent",value:function(o){o.m=o.m||{},o.key=o.key||o.m.key||i.key||void 0,this.sid&&(o.sid=this.sid),o.m=Object.assign({},o.m),Object.keys(a.Meta.exclude).forEach(function(e){return delete o.m[e]}),this.sourceCh&&(o.m.ref_ch=this.sourceCh),this.sourceCx&&(o.m.ref_cx=this.sourceCx),o.m.pgid=this.pageId,o.m.ok_ver=i.version,o.m=i.util.flatten(o.m,{arrayToCsv:!0}),Object.keys(o.m).forEach(function(e){"string"==typeof o.m[e]&&(o.m[e]=o.m[e].substr(0,255))}),t.referrer&&(o.ref=t.referrer),o.win=e.location.href}},{key:"_updateSid",value:function(t){!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;o1?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().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().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.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(),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]]=(a.metrics.sid||"unknown")+":"+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().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().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().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().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().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().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().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 44d7647..59addb6 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.13.2 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */\n/*! okanjo-js v1.13.2 | (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.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(e,o,n){var i=new Date;i.setDate(i.getDate()+n);var a=n?\" Expires=\"+i.toUTCString()+\";\":\"\",r=\" Path=/\",s=encodeURI(o)+\";\"+a+r;t.cookie=e+\"=\"+s},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(t,o){t=t||{},t.object_type=a.Object.page,t.event_type=a.Event.view,t.id=t.id||e.location.href,t.ch=t.ch||this.defaultChannel,this.trackEvent(t,o)}},{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(t,o){var n=this,a=t.map(function(e){return n._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),r={events:a,win:e.location.href},s=i.net.getRoute(i.net.routes.metrics_batch);this.sid&&(r.sid=this.sid),i.net.request.post(s,r,function(e,n){e&&i.report(\"Failed to send metrics batch\",{err:e,res:n,items:t,route:s}),o&&o(e,n)})}},{key:\"_normalizeEvent\",value:function(o){o.m=o.m||{},o.key=o.key||o.m.key||i.key||void 0,this.sid&&(o.sid=this.sid),o.m=Object.assign({},o.m),Object.keys(a.Meta.exclude).forEach(function(e){return delete o.m[e]}),this.sourceCh&&(o.m.ref_ch=this.sourceCh),this.sourceCx&&(o.m.ref_cx=this.sourceCx),o.m.pgid=this.pageId,o.m.ok_ver=i.version,o.m=i.util.flatten(o.m,{arrayToCsv:!0}),Object.keys(o.m).forEach(function(e){\"string\"==typeof o.m[e]&&(o.m[e]=o.m[e].substr(0,255))}),t.referrer&&(o.ref=t.referrer),o.win=e.location.href}},{key:\"_updateSid\",value:function(t){!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;o1?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().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().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.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=a.util.shortid(),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(),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]]=(a.metrics.sid||\"unknown\")+\":\"+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||{\ndata:{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().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().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().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().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().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().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().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.14.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */\n/*! okanjo-js v1.14.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.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(e,o,n){var i=new Date;i.setDate(i.getDate()+n);var a=n?\" Expires=\"+i.toUTCString()+\";\":\"\",r=\" Path=/\",s=encodeURI(o)+\";\"+a+r;t.cookie=e+\"=\"+s},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(t,o){t=t||{},t.object_type=a.Object.page,t.event_type=a.Event.view,t.id=t.id||e.location.href,t.ch=t.ch||this.defaultChannel,this.trackEvent(t,o)}},{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(t,o){var n=this,a=t.map(function(e){return n._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),r={events:a,win:e.location.href},s=i.net.getRoute(i.net.routes.metrics_batch);this.sid&&(r.sid=this.sid),i.net.request.post(s,r,function(e,n){e&&i.report(\"Failed to send metrics batch\",{err:e,res:n,items:t,route:s}),o&&o(e,n)})}},{key:\"_normalizeEvent\",value:function(o){o.m=o.m||{},o.key=o.key||o.m.key||i.key||void 0,this.sid&&(o.sid=this.sid),o.m=Object.assign({},o.m),Object.keys(a.Meta.exclude).forEach(function(e){return delete o.m[e]}),this.sourceCh&&(o.m.ref_ch=this.sourceCh),this.sourceCx&&(o.m.ref_cx=this.sourceCx),o.m.pgid=this.pageId,o.m.ok_ver=i.version,o.m=i.util.flatten(o.m,{arrayToCsv:!0}),Object.keys(o.m).forEach(function(e){\"string\"==typeof o.m[e]&&(o.m[e]=o.m[e].substr(0,255))}),t.referrer&&(o.ref=t.referrer),o.win=e.location.href}},{key:\"_updateSid\",value:function(t){!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;o1?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().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().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.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(),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]]=(a.metrics.sid||\"unknown\")+\":\"+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:{\nresults:[]}}).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().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().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().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().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().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().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().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 4ab5919..c6a20f3 100644 --- a/dist/okanjo-metrics.js +++ b/dist/okanjo-metrics.js @@ -1,4 +1,4 @@ -/*! okanjo-metrics.js v1.13.2 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-metrics.js v1.14.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.13.2", + version: "1.14.0", /** * Placeholder diff --git a/dist/okanjo-metrics.min.js b/dist/okanjo-metrics.min.js index 5af7c5d..4298e5e 100644 --- a/dist/okanjo-metrics.min.js +++ b/dist/okanjo-metrics.min.js @@ -1,4 +1,4 @@ -/*! okanjo-metrics.js v1.13.2 | (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.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(e,n,r){var o=new Date;o.setDate(o.getDate()+r);var i=r?" Expires="+o.toUTCString()+";":"",a=" Path=/",u=encodeURI(n)+";"+i+a;t.cookie=e+"="+u},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||n.location.href,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 r=this,i=e.map(function(e){return r._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),a={events:i,win:n.location.href},u=o.net.getRoute(o.net.routes.metrics_batch);this.sid&&(a.sid=this.sid),o.net.request.post(u,a,function(n,r){n&&o.report("Failed to send metrics batch",{err:n,res:r,items:e,route:u}),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=n.location.href}},{key:"_updateSid",value:function(e){!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;n1?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.13.2\",\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 //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 cookieValue = encodeURI(value) + ';' + expires + path;\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 || window.location.href;\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: window.location.href\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 = window.location.href;\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 if (!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 //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 //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 //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 cookieValue = `${encodeURI(value)};${expires}${path}`;\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 || window.location.href;\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: window.location.href\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 = window.location.href;\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n _updateSid(sid) {\n if (!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 //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 //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","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","encodeURI","cookie","cookieValue","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","href","_processQueue","_this2","_processTimeout","_batchSend","_updateSid","item","_this3","events","win","metrics_batch","m","exclude","Meta","ok_ver","pgid","referrer","ref","ttl","_len3","_key3","pw","w","ph","h","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","_len6","_key6","addEventMeta","_normalizeEvent"],"mappings":"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","file":"okanjo-metrics.min.js","sourcesContent":["/*! okanjo-metrics.js v1.14.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.14.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 //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 cookieValue = encodeURI(value) + ';' + expires + path;\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 || window.location.href;\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: window.location.href\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 = window.location.href;\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 if (!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 //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 //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 //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 cookieValue = `${encodeURI(value)};${expires}${path}`;\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 || window.location.href;\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: window.location.href\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 = window.location.href;\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n _updateSid(sid) {\n if (!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 //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 //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 6aa8c06..f8b3d13 100644 --- a/dist/okanjo-templates.js +++ b/dist/okanjo-templates.js @@ -1,4 +1,4 @@ -/*! okanjo-js v1.13.2 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.14.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 07b2bdb..8da1568 100644 --- a/dist/okanjo-templates.min.js +++ b/dist/okanjo-templates.min.js @@ -1,4 +1,4 @@ -/*! okanjo-js v1.13.2 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ -/*! okanjo-js v1.13.2 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.14.0 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.14.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 ddc4d2d..29c8cd0 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":";CACA,SAAUA,IAAS,SAAWC,GCE9BD,GAAAA,GAAAE,EAAAC,MDCIH,GAAOI,GAAGF,OAAOC,YAAY,aAAc,6lBAAimBE,GAAI,sBAEhpBL,EAAOI,GAAGF,OAAOI,iBAAiB,aAAc,gQAAuQ,SAAUC,GCOrU,MAJAA,GAAAC,OAAAA,KAAAC,OACAF,EAAAG,WAAAC,KAAAX,WDCQO,EAAMG,aAAeV,EAAOY,IAAIC,QAAQC,UAAUH,KAAKI,aCE/DR,IARAS,KAAA,aAAA,oBCLAf,QFkBA,SAAWA,GEfXD,GAAAA,GAAAE,EAAAC,MFkBIH,GAAOI,GAAGF,OAAOC,YAAY,kBAAmB,wSAA0SE,GAAI,0BAE9VL,EAAOI,GAAGa,iBAAmB,qtHEfjCjB,EAAAI,GAAAc,OAAAZ,iBAAA,kBAAAN,EAAAI,GAAAc,iBAAA,SAAAX,GACAA,GAAAA,IAAAY,KAAAD,YAAAA,MAAAE,cAAAF,OAAAE,WAcA,OAbAb,GAAAE,SAAAS,EAAAT,QACAF,EAAAC,OAAAA,KAAAC,OACAF,EAAAc,WAAAV,KAAAH,WACAD,EAAAe,cAAAX,KAAAI,YAAAQ,GACAhB,EAAAG,cAAAV,KAAAA,YAAAuB,GFkBQhB,EAAMG,aAAeV,EAAOY,IAAIC,QAAQC,UAAUH,KAAKI,aAGvDJ,KAAKa,wBAGLb,KAAKc,wBAAwB,kBAAmB,UEfxDlB,IAhBAS,KAAA,kBAAA,oBCPAf,QH6CA,SAAWA,GG1CXD,GAAAA,GAAAE,EAAAC,MH6CIH,GAAOI,GAAGF,OAAOC,YAAY,gBAAiB,IAAME,GAAI,wBGzC5DL,EAAAI,GAAAc,OAAAZ,iBAAA,gBAAAc,EAAAhB,GAAAc,iBAAAE,SAAAb,GACAA,GAAAA,IAAAmB,KAAAA,YAAAR,MAAAE,cAAAF,OAAAE,WAiBA,OAhBAb,GAAAY,cAAAC,eACAb,EAAAE,SAAAS,EAAAT,QACAF,EAAAC,OAAAA,KAAAC,OACAF,EAAAc,WAAAV,KAAAH,WACAD,EAAAe,cAAAX,KAAAI,YAAAQ,GACAhB,EAAAG,cAAAV,KAAAA,YAAAuB,GACAhB,EAAAoB,aAAA3B,EAAAY,IAAAC,QAAAC,UAAAH,KAAAI,aH6CQR,EAAMoB,SAAW,aAIjBhB,KAAKiB,4BAGLjB,KAAKc,wBAAwB,kBAAmB,UG1CxDlB,IAnBAS,KAAA,gBAAA,cAAA,oBCNAf,QACA,SAAAD,GACAA,GAAAA,GAAAE,EAAAC,MACAF,GAHAG,GAAAF,OAAAC,YAAA,gBAAA,m7PAAAE,GAAA,mBCAAJ,QACA,SAAAD,GACAA,GAAAA,GAAAE,EAAAC,MACAH,GAAAI,GAAAF,OAAAC,YAAA,cAAA,IAAAE,GAAA,gBL8EIL,EAAOI,GAAGF,OAAOC,YAAY,eAAgB,u5EAA25EE,GAAI,iBK3Eh9EJ,EANAG,GAAAF,OAAAI,iBAAA,eAAA,iLAAAU,KAAA,kBCAAf,QACA,SAAAD,GACAA,GAAAA,GAAAE,EAAAC,MACAF,GAHAG,GAAAF,OAAAC,YAAA,cAAA,shKAAAE,GAAA,iBCAAJ,QPyFA,SAAWA,GOtFXD,GAAAA,GAAAE,EAAAC,MPyFIH,GAAOI,GAAGF,OAAOC,YAAY,kBAAmB,IAAME,GAAI,0BAE1DL,EAAOI,GAAGyB,iBAAmB,ugFAE7B7B,EAAOI,GAAGF,OAAOI,iBAAiB,kBAAmBN,EAAOI,GAAGyB,iBAAkB,SAAUtB,GOrF/FA,GAAAA,IAAAuB,KAAAZ,YAAAA,MAAAE,cAAAF,OAAAE,WAcA,OAbAb,GAAAE,SAAAS,EAAAT,QACAF,EAAAC,OAAAA,KAAAC,OACAF,EAAAc,WAAAV,KAAAH,WACAD,EAAAe,cAAAX,KAAAI,YAAAQ,GACAhB,EAAAG,cAAAV,KAAAA,YAAAuB,GPyFQhB,EAAMG,aAAeV,EAAOY,IAAIC,QAAQC,UAAUH,KAAKI,aAGvDJ,KAAKa,wBAGLb,KAAKc,wBAAwB,kBAAmB,cOtFxDlB,IAlBAS,KAAA,kBAAA,gBAAA,mBCPAf,QRsHA,SAAWA,GQnHXD,GAAAA,GAAAE,EAAAC,MRsHIH,GAAOI,GAAGF,OAAOC,YAAY,gBAAiB,6oIAA+oIE,GAAI,wBQlHrsIL,EAAAI,GAAAc,OAAAZ,iBAAA,gBAAAc,EAAAhB,GAAAc,iBAAAE,SAAAb,GACAA,GAAAA,IAAAmB,KAAAA,YAAAR,MAAAE,cAAAF,OAAAE,WAiBA,OAhBAb,GAAAuB,cAAAV,eACAb,EAAAE,SAAAS,EAAAT,QACAF,EAAAC,OAAAA,KAAAC,OACAF,EAAAc,WAAAV,KAAAH,WACAD,EAAAe,cAAAX,KAAAI,YAAAQ,GACAhB,EAAAG,cAAAV,KAAAA,YAAAuB,GACAhB,EAAAoB,aAAA3B,EAAAY,IAAAC,QAAAC,UAAAH,KAAAI,aRsHQR,EAAMoB,SAAW,aAIjBhB,KAAKiB,4BAGLjB,KAAKc,wBAAwB,kBAAmB,UQnHxDlB,IAnBAS,KAAA,gBAAA,cAAA,oBR4IGf,SAAWD","file":"okanjo-templates.min.js","sourcesContent":["/*! okanjo-js v1.13.2 | (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":";CACA,SAAUA,IAAS,SAAWC,GCE9BD,GAAAA,GAAAE,EAAAC,MDCIH,GAAOI,GAAGF,OAAOC,YAAY,aAAc,6lBAAimBE,GAAI,sBAEhpBL,EAAOI,GAAGF,OAAOI,iBAAiB,aAAc,gQAAuQ,SAAUC,GCOrU,MAJAA,GAAAC,OAAAA,KAAAC,OACAF,EAAAG,WAAAC,KAAAX,WDCQO,EAAMG,aAAeV,EAAOY,IAAIC,QAAQC,UAAUH,KAAKI,aCE/DR,IARAS,KAAA,aAAA,oBCLAf,QFkBA,SAAWA,GEfXD,GAAAA,GAAAE,EAAAC,MFkBIH,GAAOI,GAAGF,OAAOC,YAAY,kBAAmB,wSAA0SE,GAAI,0BAE9VL,EAAOI,GAAGa,iBAAmB,qtHEfjCjB,EAAAI,GAAAc,OAAAZ,iBAAA,kBAAAN,EAAAI,GAAAc,iBAAA,SAAAX,GACAA,GAAAA,IAAAY,KAAAD,YAAAA,MAAAE,cAAAF,OAAAE,WAcA,OAbAb,GAAAE,SAAAS,EAAAT,QACAF,EAAAC,OAAAA,KAAAC,OACAF,EAAAc,WAAAV,KAAAH,WACAD,EAAAe,cAAAX,KAAAI,YAAAQ,GACAhB,EAAAG,cAAAV,KAAAA,YAAAuB,GFkBQhB,EAAMG,aAAeV,EAAOY,IAAIC,QAAQC,UAAUH,KAAKI,aAGvDJ,KAAKa,wBAGLb,KAAKc,wBAAwB,kBAAmB,UEfxDlB,IAhBAS,KAAA,kBAAA,oBCPAf,QH6CA,SAAWA,GG1CXD,GAAAA,GAAAE,EAAAC,MH6CIH,GAAOI,GAAGF,OAAOC,YAAY,gBAAiB,IAAME,GAAI,wBGzC5DL,EAAAI,GAAAc,OAAAZ,iBAAA,gBAAAc,EAAAhB,GAAAc,iBAAAE,SAAAb,GACAA,GAAAA,IAAAmB,KAAAA,YAAAR,MAAAE,cAAAF,OAAAE,WAiBA,OAhBAb,GAAAY,cAAAC,eACAb,EAAAE,SAAAS,EAAAT,QACAF,EAAAC,OAAAA,KAAAC,OACAF,EAAAc,WAAAV,KAAAH,WACAD,EAAAe,cAAAX,KAAAI,YAAAQ,GACAhB,EAAAG,cAAAV,KAAAA,YAAAuB,GACAhB,EAAAoB,aAAA3B,EAAAY,IAAAC,QAAAC,UAAAH,KAAAI,aH6CQR,EAAMoB,SAAW,aAIjBhB,KAAKiB,4BAGLjB,KAAKc,wBAAwB,kBAAmB,UG1CxDlB,IAnBAS,KAAA,gBAAA,cAAA,oBCNAf,QACA,SAAAD,GACAA,GAAAA,GAAAE,EAAAC,MACAF,GAHAG,GAAAF,OAAAC,YAAA,gBAAA,m7PAAAE,GAAA,mBCAAJ,QACA,SAAAD,GACAA,GAAAA,GAAAE,EAAAC,MACAH,GAAAI,GAAAF,OAAAC,YAAA,cAAA,IAAAE,GAAA,gBL8EIL,EAAOI,GAAGF,OAAOC,YAAY,eAAgB,u5EAA25EE,GAAI,iBK3Eh9EJ,EANAG,GAAAF,OAAAI,iBAAA,eAAA,iLAAAU,KAAA,kBCAAf,QACA,SAAAD,GACAA,GAAAA,GAAAE,EAAAC,MACAF,GAHAG,GAAAF,OAAAC,YAAA,cAAA,shKAAAE,GAAA,iBCAAJ,QPyFA,SAAWA,GOtFXD,GAAAA,GAAAE,EAAAC,MPyFIH,GAAOI,GAAGF,OAAOC,YAAY,kBAAmB,IAAME,GAAI,0BAE1DL,EAAOI,GAAGyB,iBAAmB,ugFAE7B7B,EAAOI,GAAGF,OAAOI,iBAAiB,kBAAmBN,EAAOI,GAAGyB,iBAAkB,SAAUtB,GOrF/FA,GAAAA,IAAAuB,KAAAZ,YAAAA,MAAAE,cAAAF,OAAAE,WAcA,OAbAb,GAAAE,SAAAS,EAAAT,QACAF,EAAAC,OAAAA,KAAAC,OACAF,EAAAc,WAAAV,KAAAH,WACAD,EAAAe,cAAAX,KAAAI,YAAAQ,GACAhB,EAAAG,cAAAV,KAAAA,YAAAuB,GPyFQhB,EAAMG,aAAeV,EAAOY,IAAIC,QAAQC,UAAUH,KAAKI,aAGvDJ,KAAKa,wBAGLb,KAAKc,wBAAwB,kBAAmB,cOtFxDlB,IAlBAS,KAAA,kBAAA,gBAAA,mBCPAf,QRsHA,SAAWA,GQnHXD,GAAAA,GAAAE,EAAAC,MRsHIH,GAAOI,GAAGF,OAAOC,YAAY,gBAAiB,6oIAA+oIE,GAAI,wBQlHrsIL,EAAAI,GAAAc,OAAAZ,iBAAA,gBAAAc,EAAAhB,GAAAc,iBAAAE,SAAAb,GACAA,GAAAA,IAAAmB,KAAAA,YAAAR,MAAAE,cAAAF,OAAAE,WAiBA,OAhBAb,GAAAuB,cAAAV,eACAb,EAAAE,SAAAS,EAAAT,QACAF,EAAAC,OAAAA,KAAAC,OACAF,EAAAc,WAAAV,KAAAH,WACAD,EAAAe,cAAAX,KAAAI,YAAAQ,GACAhB,EAAAG,cAAAV,KAAAA,YAAAuB,GACAhB,EAAAoB,aAAA3B,EAAAY,IAAAC,QAAAC,UAAAH,KAAAI,aRsHQR,EAAMoB,SAAW,aAIjBhB,KAAKiB,4BAGLjB,KAAKc,wBAAwB,kBAAmB,UQnHxDlB,IAnBAS,KAAA,gBAAA,cAAA,oBR4IGf,SAAWD","file":"okanjo-templates.min.js","sourcesContent":["/*! okanjo-js v1.14.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 b2627f7..715f06c 100644 --- a/dist/okanjo.js +++ b/dist/okanjo.js @@ -1,4 +1,4 @@ -/*! okanjo-js v1.13.2 | (c) 2013 Okanjo Partners Inc | https://okanjo.com/ */ +/*! okanjo-js v1.14.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.13.2", + version: "1.14.0", /** * Placeholder @@ -3476,7 +3476,8 @@ var okanjo = function (window, document) { key: '_handleResourceMouseDown', value: function _handleResourceMouseDown(type, resource, e) { // Generate a new click id for this event - var clickId = okanjo.util.shortid(); + // const clickId = okanjo.util.shortid(); + var clickId = resource._cid; // Start building the event var event = okanjo.metrics.create(this._metricBase, { diff --git a/dist/okanjo.min.js b/dist/okanjo.min.js index a729ecd..db50ccd 100644 --- a/dist/okanjo.min.js +++ b/dist/okanjo.min.js @@ -1,7 +1,7 @@ -/*! okanjo-js v1.13.2 | (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.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(e,n,i){var r=new Date;r.setDate(r.getDate()+i);var o=i?" Expires="+r.toUTCString()+";":"",a=" Path=/",s=encodeURI(n)+";"+o+a;t.cookie=e+"="+s},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(t,n){t=t||{},t.object_type=o.Object.page,t.event_type=o.Event.view,t.id=t.id||e.location.href,t.ch=t.ch||this.defaultChannel,this.trackEvent(t,n)}},{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(t,n){var i=this,o=t.map(function(e){return i._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),a={events:o,win:e.location.href},s=r.net.getRoute(r.net.routes.metrics_batch);this.sid&&(a.sid=this.sid),r.net.request.post(s,a,function(e,i){e&&r.report("Failed to send metrics batch",{err:e,res:i,items:t,route:s}),n&&n(e,i)})}},{key:"_normalizeEvent",value:function(n){n.m=n.m||{},n.key=n.key||n.m.key||r.key||void 0,this.sid&&(n.sid=this.sid),n.m=Object.assign({},n.m),Object.keys(o.Meta.exclude).forEach(function(e){return delete n.m[e]}),this.sourceCh&&(n.m.ref_ch=this.sourceCh),this.sourceCx&&(n.m.ref_cx=this.sourceCx),n.m.pgid=this.pageId,n.m.ok_ver=r.version,n.m=r.util.flatten(n.m,{arrayToCsv:!0}),Object.keys(n.m).forEach(function(e){"string"==typeof n.m[e]&&(n.m[e]=n.m[e].substr(0,255))}),t.referrer&&(n.ref=t.referrer),n.win=e.location.href}},{key:"_updateSid",value:function(t){!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;n1?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().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().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.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=o.util.shortid(),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(),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]]=(o.metrics.sid||"unknown")+":"+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().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().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().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().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().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().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().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.14.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.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(e,n,i){var r=new Date;r.setDate(r.getDate()+i);var o=i?" Expires="+r.toUTCString()+";":"",a=" Path=/",s=encodeURI(n)+";"+o+a;t.cookie=e+"="+s},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(t,n){t=t||{},t.object_type=o.Object.page,t.event_type=o.Event.view,t.id=t.id||e.location.href,t.ch=t.ch||this.defaultChannel,this.trackEvent(t,n)}},{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(t,n){var i=this,o=t.map(function(e){return i._normalizeEvent(e.event),delete e.event.sid,delete e.event.win,e.event}),a={events:o,win:e.location.href},s=r.net.getRoute(r.net.routes.metrics_batch);this.sid&&(a.sid=this.sid),r.net.request.post(s,a,function(e,i){e&&r.report("Failed to send metrics batch",{err:e,res:i,items:t,route:s}),n&&n(e,i)})}},{key:"_normalizeEvent",value:function(n){n.m=n.m||{},n.key=n.key||n.m.key||r.key||void 0,this.sid&&(n.sid=this.sid),n.m=Object.assign({},n.m),Object.keys(o.Meta.exclude).forEach(function(e){return delete n.m[e]}),this.sourceCh&&(n.m.ref_ch=this.sourceCh),this.sourceCx&&(n.m.ref_cx=this.sourceCx),n.m.pgid=this.pageId,n.m.ok_ver=r.version,n.m=r.util.flatten(n.m,{arrayToCsv:!0}),Object.keys(n.m).forEach(function(e){"string"==typeof n.m[e]&&(n.m[e]=n.m[e].substr(0,255))}),t.referrer&&(n.ref=t.referrer),n.win=e.location.href}},{key:"_updateSid",value:function(t){!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;n1?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().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().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.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(),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]]=(o.metrics.sid||"unknown")+":"+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().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().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().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().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().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().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().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 a36e92a..fb6898a 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","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","encodeURI","cookie","cookieValue","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","href","_processQueue","_this3","_processTimeout","_batchSend","_updateSid","item","_this4","events","win","metrics_batch","m","exclude","Meta","ok_ver","pgid","referrer","ref","ttl","_len3","_key3","pw","w","ph","h","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","_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","utm_medium","ok_cx","utm_source","utm_campaign","u","toUrl","sf","spltfl_seg","splitfill_segment","resource","clickId","urlParam","cid","trackParam","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","bf","_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.13.2 | (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.13.2\",\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 //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 cookieValue = encodeURI(value) + ';' + expires + path;\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 || window.location.href;\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: window.location.href\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 = window.location.href;\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 if (!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 //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 //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().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().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.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 var clickId = okanjo.util.shortid();\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();\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]] = (okanjo.metrics.sid || 'unknown') + ':' + 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().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().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().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().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().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().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().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 //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 cookieValue = `${encodeURI(value)};${expires}${path}`;\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 || window.location.href;\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: window.location.href\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 = window.location.href;\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n _updateSid(sid) {\n if (!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 //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 //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 .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 .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.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\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\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]] = (okanjo.metrics.sid || 'unknown') + ':' + 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 .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 .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 .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 .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 .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 .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 .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","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","encodeURI","cookie","cookieValue","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","href","_processQueue","_this3","_processTimeout","_batchSend","_updateSid","item","_this4","events","win","metrics_batch","m","exclude","Meta","ok_ver","pgid","referrer","ref","ttl","_len3","_key3","pw","w","ph","h","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","_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","utm_medium","ok_cx","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.14.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.14.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 //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 cookieValue = encodeURI(value) + ';' + expires + path;\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 || window.location.href;\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: window.location.href\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 = window.location.href;\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 if (!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 //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 //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().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().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.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();\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]] = (okanjo.metrics.sid || 'unknown') + ':' + 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().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().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().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().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().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().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().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 //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 cookieValue = `${encodeURI(value)};${expires}${path}`;\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 || window.location.href;\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: window.location.href\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 = window.location.href;\n }\n\n /**\n * Updates the stored session identifier\n * @param sid\n * @private\n */\n _updateSid(sid) {\n if (!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 //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 //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 .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 .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.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\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]] = (okanjo.metrics.sid || 'unknown') + ':' + 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 .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 .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 .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 .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 .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 .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 .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/gulpfile.js b/gulpfile.js index 73bca01..687e98d 100644 --- a/gulpfile.js +++ b/gulpfile.js @@ -416,8 +416,7 @@ Gulp.task('pre-deploy-bump', function() { }); -Gulp.task('pre-deploy-release', ['pre-deploy-bump', 'full-build'], function() { - +function CommitTagPush() { const Stream = require('stream'); //function cb(obj) { // var stream = new Stream.Transform({objectMode: true}); @@ -450,6 +449,14 @@ Gulp.task('pre-deploy-release', ['pre-deploy-bump', 'full-build'], function() { cb(); }); })); +} + +Gulp.task('pre-deploy-release', ['pre-deploy-bump', 'full-build'], function() { + return CommitTagPush(); +}); + +Gulp.task('pre-deploy-release-no-bump', ['full-build'], function() { + return CommitTagPush(); }); Gulp.task('deploy-s3-latest', function() { diff --git a/package-lock.json b/package-lock.json index 9903951..78201ec 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "okanjo-js", - "version": "1.13.0", + "version": "1.13.2", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 11aa6fd..f9a92e2 100644 --- a/package.json +++ b/package.json @@ -1,7 +1,7 @@ { "name": "okanjo-js", "homepage": "https://okanjo.com/", - "version": "1.13.2", + "version": "1.14.0", "description": "Okanjo JavaScript Widget Framework", "main": "index.js", "repository": { diff --git a/src/Placement.js b/src/Placement.js index 4bbf5c7..a9b8cdf 100644 --- a/src/Placement.js +++ b/src/Placement.js @@ -461,7 +461,8 @@ */ _handleResourceMouseDown(type, resource, e) { // Generate a new click id for this event - const clickId = okanjo.util.shortid(); + // const clickId = okanjo.util.shortid(); + const clickId = resource._cid; // Start building the event const event = okanjo.metrics.create(this._metricBase, { diff --git a/test/_test_responses.js b/test/_test_responses.js index 7055787..cfe45eb 100644 --- a/test/_test_responses.js +++ b/test/_test_responses.js @@ -50,7 +50,8 @@ module.exports.getExampleArticlesResponse = () => { "created": "2017-05-12T14:05:44.567Z", "updated": "2017-05-12T14:05:45.460Z", "backfill": false, - "shortfill": false + "shortfill": false, + "_cid": "SSCLK2EiyYZ5Y4EriWsEaC0Ech1" }, { "id": "article_test_2gWFnrrPHhoJPDQoA", @@ -84,7 +85,8 @@ module.exports.getExampleArticlesResponse = () => { "created": "2017-05-12T14:05:44.554Z", "updated": "2017-05-12T14:05:44.561Z", "backfill": false, - "shortfill": false + "shortfill": false, + "_cid": "SSCLK2EiyYZ5Y4EriWsEaC0Ech2" }, { "id": "article_test_2gWFnrrPHhoJPDQoA", @@ -118,7 +120,8 @@ module.exports.getExampleArticlesResponse = () => { "created": "2017-05-12T14:05:44.554Z", "updated": "2017-05-12T14:05:44.561Z", "backfill": false, - "shortfill": false + "shortfill": false, + "_cid": "SSCLK2EiyYZ5Y4EriWsEaC0Ech3" }, { "id": "article_test_2gWFnrrPHhoJPDQoA", @@ -152,7 +155,8 @@ module.exports.getExampleArticlesResponse = () => { "created": "2017-05-12T14:05:44.554Z", "updated": "2017-05-12T14:05:44.561Z", "backfill": false, - "shortfill": false + "shortfill": false, + "_cid": "SSCLK2EiyYZ5Y4EriWsEaC0Ech4" }, { "id": "article_test_2gWFnrrPHhoJPDQoA", @@ -186,7 +190,8 @@ module.exports.getExampleArticlesResponse = () => { "created": "2017-05-12T14:05:44.554Z", "updated": "2017-05-12T14:05:44.561Z", "backfill": false, - "shortfill": false + "shortfill": false, + "_cid": "SSCLK2EiyYZ5Y4EriWsEaC0Ech5" } ], total: 2, @@ -245,7 +250,8 @@ module.exports.getExampleProductResponse = () => { "created": "2017-05-02T19:00:05.519Z", "updated": null, "backfill": false, - "shortfill": false + "shortfill": false, + "_cid": "SSCLK2EiyYZ5Y4EriWsEaC0Ech26" }, { "id": "product_test_2gT3kBcwVQZ1kpEmb", "store_id": "store_2gT3kBcwVQZ1kpEmc", @@ -278,7 +284,8 @@ module.exports.getExampleProductResponse = () => { "created": "2017-04-30T19:00:14.114Z", "updated": "2017-05-02T19:00:18.048Z", "backfill": false, - "shortfill": false + "shortfill": false, + "_cid": "SSCLK2EiyYZ5Y4EriWsEaC0Ech7" } ], total: 2, @@ -335,7 +342,8 @@ module.exports.getExampleSplitfillProductResponse = () => { "updated": null, "backfill": false, "shortfill": false, - "splitfill_segment": "test split segment" + "splitfill_segment": "test split segment", + "_cid": "SSCLK2EiyYZ5Y4EriWsEaC0Ech8" }, { "id": "product_test_2gT3kBcwVQZ1kpEmb", "store_id": "store_2gT3kBcwVQZ1kpEmc", @@ -369,7 +377,8 @@ module.exports.getExampleSplitfillProductResponse = () => { "updated": "2017-05-02T19:00:18.048Z", "backfill": false, "shortfill": false, - "splitfill_segment": null + "splitfill_segment": null, + "_cid": "SSCLK2EiyYZ5Y4EriWsEaC0Ech9" } ], total: 2, @@ -414,7 +423,8 @@ module.exports.getExampleSplitfillArticlesResponse = () => { "updated": "2017-05-12T14:05:45.460Z", "backfill": false, "shortfill": false, - "splitfill_segment": "test split segment" + "splitfill_segment": "test split segment", + "_cid": "SSCLK2EiyYZ5Y4EriWsEaC0Ec10" }, { "id": "article_test_2gWFnrrPHhoJPDQoA", @@ -449,7 +459,8 @@ module.exports.getExampleSplitfillArticlesResponse = () => { "updated": "2017-05-12T14:05:44.561Z", "backfill": false, "shortfill": false, - "splitfill_segment": null + "splitfill_segment": null, + "_cid": "SSCLK2EiyYZ5Y4EriWsEaC0Ec11" } ], total: 2,