try{var _tl;function tl_init(){function parseUri(str){var o=parseUri.options,m=o.parser[o.strictMode?"strict":"loose"].exec(str),uri={},i=14;while(i--)uri[o.key[i]]=m[i]||"";uri[o.q.name]={};uri[o.key[12]].replace(o.q.parser,function($0,$1,$2){if($1)uri[o.q.name][$1]=$2;});return uri;};parseUri.options={strictMode:false,key:["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],q:{name:"queryKey",parser:/(?:^|&)([^&=]*)=?([^&]*)/g},parser:{strict:/^(?:([^:\/?#]+):)?(?:\/\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?))?((((?:[^?#\/]*\/)*)([^?#]*))(?:\?([^#]*))?(?:#(.*))?)/,loose:/^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/}};var fireError=function(msg){var i=document.createElement('IMG');i.style.display="none";i.src="//eb.3lift.com/sce?block=header&inv_code=psmag_article_big&e="+encodeURIComponent(msg);document.body.appendChild(i);};_tl={};_tl.fe=fireError;_tl.parseUri=parseUri;try{if(isNaN(top.tlsn)){top.tlsn=0;}
_tl.updateTlSN=function(){try{top.tlsn++;}
catch(e){return false;}};_tl.getTlSN=function(){try{return top.tlsn;}
catch(e){return false;}};}
catch(e){_tl.getTlSN=function(){};_tl.updateTlSN=function(){};}
try{(function determineTlDebug(window,isTop){var winIsTop=(window===top);if((winIsTop&&isTop)||!window){_tl.debug=false;_tl.tlTest=false;return;}
var document=window.document;if(!document){_tl.debug=false;_tl.tlTest=false;return;}
if((document.URL.search("tripleliftTest=true")>0)||(document.referrer.search("tripleliftTest=true")>0)){var url=document.URL.search("tripleliftTest=true")>0?document.URL:document.referrer;var parsedUrl=_tl.parseUri(url);var queryKey=parsedUrl.queryKey;try{_tl.tlTest=true;var c=console;_tl.debug=true;}catch(e){_tl.debug=false;}
if(queryKey["third_party"]==="true"){_tl.third_party=true;}
else{_tl.third_party=false;}
if(queryKey["tl_image_id"]){_tl.tl_image_id=queryKey["tl_image_id"];}
if(queryKey["tlsr"]){_tl.tlsr=queryKey["tlsr"];}
if(queryKey["tlBidParams"]){_tl.tlBidParams=decodeURIComponent(queryKey["tlBidParams"]);}
return;}
determineTlDebug(window.parent,winIsTop);})(window);}catch(e){_tl.tlTest=false;_tl.debug=false;}
_tl.debugMessage=function(m){if(this.debug){var d=new Date().toString();console.log(d+': '+m);}};_tl.isTopLevel=function(w){var f;try{if(w&&(w==top)){f=true;}
else{f=false;}}
catch(e){f=false;}
return f;};_tl.fireEBPix=function(name,parameters,cb){var base="//eb.3lift.com/"+name+"?"+parameters;var first=true;var i,ii;var pix=document.createElement('IMG');pix.src=base;pix.width=0;pix.height=0;pix.style.display='none';if(cb){pix.onload=cb;}
document.body.appendChild(pix);this.fireEB2Pix(name,parameters,cb);};_tl.fireEB2Pix=function(name,parameters,cb){var base="//eb2.3lift.com/"+name+"?"+parameters;var first=true;var i,ii;var pix=document.createElement('IMG');pix.src=base;pix.width=0;pix.height=0;pix.style.display='none';if(cb){pix.onload=cb;}
document.body.appendChild(pix);};_tl.offset=function(el){var offset={};offset.top=0;offset.left=0;while(el){if(el.offsetTop){offset.top+=el.offsetTop;}
if(el.offsetLeft){offset.left+=el.offsetLeft;}
el=el.offsetParent;}
return offset;};_tl.couldBeViewed=function(elem,jquery,useTopWindow){var win;if(useTopWindow){win=top;}
else{win=window;}
if(!jquery){try{var $=jQuery;}
catch(e){return couldBeViewedSansJQuery(elem,win);}}
else{$=jquery;}
var docViewTop=$(win).scrollTop();var docViewBottom=docViewTop+$(win).height();var elemTop=$(elem).offset().top;var elemBottom=elemTop+$(elem).height();return checkForViewability(elemTop,elemBottom,docViewTop,docViewBottom);};var couldBeViewedSansJQuery=function(elem,win){var docViewTop=win.pageYOffset;var docViewBottom=docViewTop+_tl.getWindowHeight(win);var offset=_tl.offset(elem);var elemTop=offset.top;var elemBottom=elemTop+elem.offsetHeight;return checkForViewability(elemTop,elemBottom,docViewTop,docViewBottom);};var checkForViewability=function(elemTop,elemBottom,docViewTop,docViewBottom){var inView;if((elemTop<docViewTop)&&(elemBottom>docViewBottom)){_tl.fe('the ad is bigger than the viewable area');inView=true;}
else if((elemBottom<=docViewBottom)&&(elemBottom>docViewTop)){inView=true;}
else if((elemTop<=docViewBottom)&&(elemTop>docViewTop)){inView=true;}
else{inView=false;}
var buffer=50;var closeToView=elemTop<=(docViewBottom+buffer);return{inView:inView,closeToView:closeToView};};_tl.getWindowHeight=function(win){if(win.innerHeight===undefined){return win.document.documentElement.clientHeight;}
return win.innerHeight;};_tl.getTlScript=function(inv_code){var scripts=document.getElementsByTagName('SCRIPT');var script;var s,i,ii;for(i=0,ii=scripts.length;i<ii;i++){s=scripts[i];if((s.src&&s.src.match("ib.3lift.com/ttj"))||(s.getAttribute('data-src')&&s.getAttribute('data-src').match("ib.3lift.com/ttj"))){if(!((s.src&&s.src.match(inv_code))||(s.getAttribute('data-src')&&s.getAttribute('data-src').match(inv_code)))){continue;}
if(!s.getAttribute('tl_id')){script=s;break;}}}
script.setAttribute('tl_id',Math.round(Math.random()*100000));this.updateTlSN();return script;};_tl.needHTML5=(function(){var div=document.createElement('DIV');div.innerHTML="<article></article>";var flag=div.childNodes.length!==1?true:false;return flag;})();_tl.buildDOMElement=function(str,ct){if(this.debug){console.log('TL MESSAGE');console.log('in buildDOMElement');console.log('got string');console.log(str);console.log('Need html5 element support? '+this.needHTML5);}
var div=document.createElement('DIV');if(this.needHTML5){var html5Frag=document.createDocumentFragment();var html5='abbr article aside audio canvas datalist details figcaption figure footer header hgroup mark meter nav output progress section summary time video'.split(' ');var i=0,ii=html5.length;for(i;i<ii;i++){html5Frag.createElement(html5[i]);}
html5Frag.appendChild(div);}
div.innerHTML=str;if(this.debug){console.log('TL MESSAGE');console.log('FINISHING BUILDDOMELEMENT firstchild INNERHTML');console.log(div.firstChild.innerHTML);}
return div;};_tl.checkHook=function(html,hook){var jq,thook;try{jq=jQuery;}
catch(e){jq=false;}
if(html.match("tl-escape-type")){var type=html.match(/tl-escape-type=".+"/)[0].split("=")[1].split('"')[1];var value=html.match(/tl-escape-value=".+"/)[0].split("=")[1].split('"')[1];if(type==="selector"){var selector=value;if(jq){thook=jq(hook).closest(selector)[0];if(!thook&&this.debug){console.log('**** TL MESSAGE **** jQuery.before returned null on tl-escape');console.log('selector was: '+selector);console.log('starting point was:');console.log(hook);}}
if(!thook){this._hook=hook;thook=this.closest(hook,new this.Selector(selector),1);}
if(!thook){var p=document.createElement('IMG');p.src="http://eb.3lift.com/sce?block=master&inv_code=psmag_article_big&e="+encodeURIComponent("Failed to find selector: "+selector);document.body.appendChild(p);}
hook=thook;}}
return hook;};_tl.Selector=function(selectorString){var tnString=selectorString.match(/^[A-Za-z0-9]+/);var idString=selectorString.match(/#([A-Za-z0-9]|\-|_)+/);var cnString=selectorString.match(/\.([A-Za-z0-9]|\-|_)+/g);if(tnString){this.tagName=tnString[0];}
if(idString){this.id=idString[0].split('#')[1];}
if(cnString){this.classNames=[];var that=this;cnString.forEach(function(cn){that.classNames.push(cn.split('.')[1]);});}};_tl.closest=function(start,selector,direction){var RIGHT=0;var LEFT=1;if(!start){if(this.debug){console.log('**** TL MESSAGE **** TL-SELECTOR Could Not Be Found');console.log('selector was: ')
console.log(selector);console.log('starting point was:');console.log(this._hook);}
return false;}
var flag=true;if(selector.tagName){if(start.tagName!==selector.tagName){flag=false;}}
if(selector.id){if(start.id!==selector.id){flag=false;}}
if(selector.classNames){if(!start.className){flag=false;}
else{var classes_array=start.className.split(' ');var classes={};classes_array.forEach(function(c){classes[c]=c;});selector.classNames.forEach(function(cn){if(!(cn in classes)){flag=false;}});}}
if(flag){return start;}
else{if(direction===LEFT){if(start.previousSibling){return this.closest(start.previousSibling,selector,LEFT);}
return this.closest(start.nextSibling,selector,RIGHT);}
else{if(start.nextSibling){return this.closest(start.nextSibling,selector,RIGHT);}
return this.closest(start.parentNode,selector,LEFT);}}};_tl.render_inline=function(hook,html,analyticsTag,analyticsText,adID,adDID,serveDefaultID,adImageScripts){var jq,masonryContainer,ad,adUnit;var hookDocument=(function(h){var findDoc=function(start){if(!start){return false;}
if(start.getElementById&&!start.tagName){return start;}
return findDoc(start.parentNode);};return findDoc(h);})(hook);hook=this.checkHook(html,hook);if(!hook){return;}
html='<div style="display:inline">'+html+'</div>';var fragFirstChild=this.buildDOMElement(html).firstChild;var scriptList=fragFirstChild.getElementsByTagName('SCRIPT');var ii=scriptList.length;var i=0;var to_be_evaled=[];var Script=function(node){this.src=node.src;this.text=node.text;this.id="tles"+Math.round(Math.random()*100000);};var p,scriptInfo;if(true){if(this.debug){console.log('TL MESSAGE: SCRIPTS ENABLED');}
for(;i<ii;i++){p=document.createElement('P');scriptInfo=new Script(scriptList[0]);p.id=scriptInfo.id;scriptList[0].parentNode.insertBefore(p,scriptList[0]);to_be_evaled.push(scriptInfo);scriptList[0].parentNode.removeChild(scriptList[0]);}}
else{if(this.debug){console.log('TL MESSAGE: SCRIPTS DISABLED');}
for(;i<ii;i++){scriptList[0].parentNode.removeChild(scriptList[0]);}}
try{jq=jQuery;}
catch(e){jq=false;}
if(this.debug){console.log('TL MESSAGE');console.log('ABOUT TO APPEND AD (SCRIPTS WILL POSSIBLY BE ADDED LATER)');console.log('INNER HTML');console.log(fragFirstChild.innerHTML);}
if(!jq){adUnit=this.appendContent(hook,fragFirstChild);}
else{adUnit=jQuery(hook).before(fragFirstChild).prev()[0];}
var adImages=adUnit.getElementsByTagName('IMG');var mainAdImage;var l=0,ll=adImages.length;for(;l<ll;l++){if(adImages[l].src&&adImages[l].src.match("img.3lift.com")){mainAdImage=adImages[l];break;}}
if(mainAdImage){var layout=this.layOut;var getLp=function(){var f;var addToParent;try{if(updateLogoZones){f=true;}
else{f=false;}}
catch(e){if(parent&&parent.updateLogoZones){f=true;addToParent=true;}
else{f=false;}}
if(f){var s=document.createElement('SCRIPT');s.src="//img.3lift.com/lp?"+mainAdImage.src.split("?")[1];if(addToParent){parent.document.body.appendChild(s);}
else{document.body.appendChild(s);}}
else{setTimeout(getLp,50);}};var madload=function(n){var jquery;try{if(window!==window.top){jquery=window.top.jQuery;if(!jquery){throw new Error();}}
else{jquery=jQuery;}}
catch(e){if(n>5){fireError('no jQuery when mainAdImage loaded');return}
setTimeout(function(){madload(n+1);},200);return;}
var $mainAdImage=jquery(mainAdImage);if(adImageScripts&&adImageScripts.length){if(!$mainAdImage.hoverIntent){fireError('mainAdImage does not have hoverIntent');}
var firePix=(function(){var fired=false;return function(e){if(fired){return;}
else{fired=true;}
var i,ii;for(i=0,ii=adImageScripts.length;i<ii;i++){(function(){var scriptSrc=adImageScripts[i];var s;s=document.createElement('SCRIPT');s.src=scriptSrc;mainAdImage.parentNode.appendChild(s);})();}};})();var hoverConfig={};hoverConfig.over=firePix;hoverConfig.sensitivity=5;hoverConfig.out=function(){};$mainAdImage.hoverIntent(hoverConfig);}
getLp();layout(jquery,hook);}
mainAdImage.onload=function(){madload(0);};}
else{if(jq){this.layOut(jq,hook);}
if(this.debug){console.log('TL MESSAGE');console.log('NO MAIN AD IMAGE');console.log(mainAdImage);}}
if(serveDefaultID){this[serveDefaultID].ad();}
if(this.scriptAttributePresent(adUnit)&&true){if(this.debug){console.log('TL MESSAGE: SCRIPT ATTRIBUTE PRESENT');}
this.evalScriptAttribute(adUnit);}
if(to_be_evaled.length&&hookDocument){to_be_evaled.forEach(function(script){if(this.debug){console.log('TL MESSAGE');console.log('ADDING SCRIPT');console.log('SRC');console.log(script.src);console.log('TEXT');console.log(script.text);}
var s=document.createElement('SCRIPT');var stub;stub=hookDocument.getElementById(script.id);stub.parentNode.insertBefore(s,stub);stub.parentNode.removeChild(stub);if(script.text){s.text=script.text;}
if(script.src){s.src=script.src;}});}
if(analyticsTag){this.addAnalytics(adUnit,analyticsTag,analyticsText,adID,adDID);}};_tl.layOut=function(jQuery,hook){var that=_tl;masonryContainer=jQuery(".masonry");if(!masonryContainer.length){masonryContainer=null;}
if(masonryContainer&&masonryContainer.length>1){masonryContainer=jQuery(masonryContainer[0]);}
if(!masonryContainer){jQuery.each(jQuery.find("*"),function(index,elem){if(jQuery.data(elem,"masonry")){masonryContainer=jQuery(elem);}});}
if(masonryContainer&&masonryContainer.data("masonry")){if(that.debug){console.log('********* TL RELOADING MASONRY *****************');console.log('masonry container is');console.log(masonryContainer);console.log('masonry data is');console.log(masonryContainer.data("masonry"));console.log('********** /TL MESSAGE *******');}
masonryContainer.masonry("reloadItems");masonryContainer.masonry();}
var isoPresent=jQuery.fn.isotope;if(isoPresent){var $isoContainer=jQuery(".isotope");if($isoContainer.length!==1){var currentEl=hook;while(true){if(!currentEl.parentNode){break;}
if(!jQuery.data(jQuery(currentEl.parentNode),"isotope")){currentEl=currentEl.parentNode;continue;}
$isoContainer=jQuery(currentEl.parentNode);break;}}
if(!$isoContainer.data("isotope")){$isoContainer=false;}
$isoContainer&&$isoContainer.isotope('reloadItems').isotope({sortBy:'original-order'});}};_tl.addAnalytics=function(adUnit,analytics,analyticsText,adID,adDID){if(adID){adUnit.setAttribute('id',adID);}
if(adDID){adUnit.setAttribute('data-id',adDID);}
adUnit.appendChild(analytics);analytics.text=analyticsText;};_tl.scriptAttributePresent=function(DOMelement){if(DOMelement.getAttribute('tl-eval')){return true;}
var candidates=DOMelement.getElementsByTagName('*');var i=0,ii=candidates.length;for(;i<ii;i++){if(candidates[i].getAttribute("tl-eval")){return true;}}};_tl.evalScriptAttribute=function(adUnit){var tlEvalTags=(function(DOMelement){var evalTags=[];if(DOMelement.getAttribute('tl-eval')){evalTags.push(DOMelement);}
var candidates=DOMelement.getElementsByTagName('*');var i=0,ii=candidates.length;for(;i<ii;i++){if(candidates[i].getAttribute("tl-eval")){evalTags.push(candidates[i]);}}
return evalTags;})(adUnit);for(i=0,ii=tlEvalTags.length;i<ii;i++){script=document.createElement('SCRIPT');tlEvalTags[i].appendChild(script);script.text=tlEvalTags[i].getAttribute('tl-eval');}};_tl.appendContent=function(hook,content){return hook.parentNode.insertBefore(content,hook);};_tl.cc=0;_tl.count=function(){return++this.cc;};_tl.init=true;};if(!_tl||!_tl.init){tl_init();}
(function(){var tl_script=_tl.getTlScript("psmag_article_big");if(false&&!_tl.isTopLevel(window)){var a=document;var iframe=a.createElement('iframe');var hostname=a.referrer;var parsedHostname=_tl.parseUri(hostname);hostname=parsedHostname.host;var docsrc=encodeURIComponent(document.URL);iframe.src="http://"+hostname+"/doubleclick/TLIframe.html?docsrc="+docsrc+"&script_src="+encodeURIComponent(tl_script.src);iframe.width=0;iframe.height=0;iframe.frameborder=0;if(a.body==null){var body=document.createElement('body');a.firstElementChild.appendChild(body);}
a.body.appendChild(iframe);return;}
var scriptNumber=_tl.getTlSN();if(!Array.prototype.forEach){Array.prototype.forEach=function(fn){for(var i=0,ii=this.length;i<ii;i++){fn(this[i]);}};}
var serveDefaultController=(function(){var default_served=false;var abort_default=function(){default_served=true;};var get_default_status=function(){return default_served;};var sd=function(type,an_auction_id,an_user_id){if(default_served){return;}
else{default_served=true;}
if(_tl.debug){console.log('*** TL MESSAGE ***');console.log('*** SERVING DEFAULT OF TYPE : '+type+' ***');}
var writeDefTemplate=function(){var def_template='';if(def_template.match('###TL_IF_ID###')){def_template=def_template.replace('###TL_IF_ID###',tl_if_id);}
if(def_template.length){try{if(window.frameElement&&window.frameElement.id&&window.frameElement.id.match&&window.frameElement.id.match('tl_iframe_wrap')){_tl.render_inline(parent.document.getElementById(window.frameElement.id),def_template);}
else if(top!==self){document.open();document.write(def_template);document.close();}
else{_tl.render_inline(tl_script,def_template);}}
catch(e){if(top!==self){document.open();document.write(def_template);document.close();}
else{_tl.render_inline(tl_script,def_template);}}}};(function(){if(Math.ceil(Math.random()*10)===1){var pix=new Image();var base="//eb.3lift.com/sci?";var ref=encodeURIComponent(document.URL);var query="inv_code=psmag_article_big&sr=10&ref="+ref+"&default=true&type="+type+"&aid="+an_auction_id+"&uid="+an_user_id+"&cb="+Math.floor(89999999*Math.random()+10000000);var src=base+query;pix.src=src;pix.width=0;pix.height=0;pix.onload=function(){writeDefTemplate();};document.body.appendChild(pix);_tl.fireEB2Pix('sci',query);}
else{writeDefTemplate();}})();};return{sd:sd,ad:abort_default,gd:get_default_status};})();var tl_if_id
var serveSponsoredAd=function(scu_id,type){if((!scu_id)&&(document.URL.search('tl_scu_id')>=0)){scu_id=document.URL.substring(document.URL.search("tl_scu_id=")+10,document.URL.search("tl_scu_id=")+10+6);}
else if((!scu_id)&&(document.referrer.search('tl_scu_id')>=0)){scu_id=document.referrer.substring(document.referrer.search("tl_scu_id=")+10,document.referrer.search("tl_scu_id=")+10+6);}
if(!type){type="tl";}
var ttj_ct='';var ttj_params=_tl.parseUri(tl_script.src).queryKey;if(ttj_params.ct){ttj_ct=ttj_params.ct;}
tl_if_id="tlif_"+Math.round(Math.random()*100000);var tl_if=document.createElement('IFRAME');var tl_if_body='try {\n     // IE <= 7 need a json parser\n    /*! JSON v3.3.1 | http://bestiejs.github.io/json3 | Copyright 2012-2014, Kit Cambridge | http://kit.mit-license.org */\n (function(){function N(p,r){function q(a){if(q[a]!==w)return q[a];var c;if("bug-string-char-index"==a)c="a"!="a"[0];else if("json"==a)c=q("json-stringify")&&q("json-parse");else{var e;if("json-stringify"==a){c=r.stringify;var b="function"==typeof c&&s;if(b){(e=function(){return 1}).toJSON=e;try{b="0"===c(0)&&"0"===c(new t)&&\'""\'==c(new A)&&c(u)===w&&c(w)===w&&c()===w&&"1"===c(e)&&"[1]"==c([e])&&"[null]"==c([w])&&"null"==c(null)&&"[null,null,null]"==c([w,u,null])&&\'{"a":[1,true,false,null,"\\\\u0000\\\\b\\\\n\\\\f\\\\r\\\\t"]}\'==\n c({a:[e,!0,!1,null,"\\x00\\b\\n\\f\\r\\t"]})&&"1"===c(null,e)&&"[\\n 1,\\n 2\\n]"==c([1,2],null,1)&&\'"-271821-04-20T00:00:00.000Z"\'==c(new C(-864E13))&&\'"+275760-09-13T00:00:00.000Z"\'==c(new C(864E13))&&\'"-000001-01-01T00:00:00.000Z"\'==c(new C(-621987552E5))&&\'"1969-12-31T23:59:59.999Z"\'==c(new C(-1))}catch(f){b=!1}}c=b}if("json-parse"==a){c=r.parse;if("function"==typeof c)try{if(0===c("0")&&!c(!1)){e=c(\'{"a":[1,true,false,null,"\\\\u0000\\\\b\\\\n\\\\f\\\\r\\\\t"]}\');var n=5==e.a.length&&1===e.a[0];if(n){try{n=!c(\'"\\t"\')}catch(d){}if(n)try{n=\n 1!==c("01")}catch(g){}if(n)try{n=1!==c("1.")}catch(m){}}}}catch(X){n=!1}c=n}}return q[a]=!!c}p||(p=k.Object());r||(r=k.Object());var t=p.Number||k.Number,A=p.String||k.String,H=p.Object||k.Object,C=p.Date||k.Date,G=p.SyntaxError||k.SyntaxError,K=p.TypeError||k.TypeError,L=p.Math||k.Math,I=p.JSON||k.JSON;"object"==typeof I&&I&&(r.stringify=I.stringify,r.parse=I.parse);var H=H.prototype,u=H.toString,v,B,w,s=new C(-0xc782b5b800cec);try{s=-109252==s.getUTCFullYear()&&0===s.getUTCMonth()&&1===s.getUTCDate()&&\n 10==s.getUTCHours()&&37==s.getUTCMinutes()&&6==s.getUTCSeconds()&&708==s.getUTCMilliseconds()}catch(Q){}if(!q("json")){var D=q("bug-string-char-index");if(!s)var x=L.floor,M=[0,31,59,90,120,151,181,212,243,273,304,334],E=function(a,c){return M[c]+365*(a-1970)+x((a-1969+(c=+(1<c)))/4)-x((a-1901+c)/100)+x((a-1601+c)/400)};(v=H.hasOwnProperty)||(v=function(a){var c={},e;(c.__proto__=null,c.__proto__={toString:1},c).toString!=u?v=function(a){var c=this.__proto__;a=a in(this.__proto__=null,this);this.__proto__=\n c;return a}:(e=c.constructor,v=function(a){var c=(this.constructor||e).prototype;return a in this&&!(a in c&&this[a]===c[a])});c=null;return v.call(this,a)});B=function(a,c){var e=0,b,f,n;(b=function(){this.valueOf=0}).prototype.valueOf=0;f=new b;for(n in f)v.call(f,n)&&e++;b=f=null;e?B=2==e?function(a,c){var e={},b="[object Function]"==u.call(a),f;for(f in a)b&&"prototype"==f||v.call(e,f)||(e[f]=1,!v.call(a,f))||c(f)}:function(a,c){var e="[object Function]"==u.call(a),b,f;for(b in a)e&&"prototype"==\n b||!v.call(a,b)||(f="constructor"===b)||c(b);(f||v.call(a,b="constructor"))&&c(b)}:(f="valueOf toString toLocaleString propertyIsEnumerable isPrototypeOf hasOwnProperty constructor".split(" "),B=function(a,c){var e="[object Function]"==u.call(a),b,h=!e&&"function"!=typeof a.constructor&&F[typeof a.hasOwnProperty]&&a.hasOwnProperty||v;for(b in a)e&&"prototype"==b||!h.call(a,b)||c(b);for(e=f.length;b=f[--e];h.call(a,b)&&c(b));});return B(a,c)};if(!q("json-stringify")){var U={92:"\\\\\\\\",34:\'\\\\"\',8:"\\\\b",\n 12:"\\\\f",10:"\\\\n",13:"\\\\r",9:"\\\\t"},y=function(a,c){return("000000"+(c||0)).slice(-a)},R=function(a){for(var c=\'"\',b=0,h=a.length,f=!D||10<h,n=f&&(D?a.split(""):a);b<h;b++){var d=a.charCodeAt(b);switch(d){case 8:case 9:case 10:case 12:case 13:case 34:case 92:c+=U[d];break;default:if(32>d){c+="\\\\u00"+y(2,d.toString(16));break}c+=f?n[b]:a.charAt(b)}}return c+\'"\'},O=function(a,c,b,h,f,n,d){var g,m,k,l,p,r,s,t,q;try{g=c[a]}catch(z){}if("object"==typeof g&&g)if(m=u.call(g),"[object Date]"!=m||v.call(g,\n "toJSON"))"function"==typeof g.toJSON&&("[object Number]"!=m&&"[object String]"!=m&&"[object Array]"!=m||v.call(g,"toJSON"))&&(g=g.toJSON(a));else if(g>-1/0&&g<1/0){if(E){l=x(g/864E5);for(m=x(l/365.2425)+1970-1;E(m+1,0)<=l;m++);for(k=x((l-E(m,0))/30.42);E(m,k+1)<=l;k++);l=1+l-E(m,k);p=(g%864E5+864E5)%864E5;r=x(p/36E5)%24;s=x(p/6E4)%60;t=x(p/1E3)%60;p%=1E3}else m=g.getUTCFullYear(),k=g.getUTCMonth(),l=g.getUTCDate(),r=g.getUTCHours(),s=g.getUTCMinutes(),t=g.getUTCSeconds(),p=g.getUTCMilliseconds();\n g=(0>=m||1E4<=m?(0>m?"-":"+")+y(6,0>m?-m:m):y(4,m))+"-"+y(2,k+1)+"-"+y(2,l)+"T"+y(2,r)+":"+y(2,s)+":"+y(2,t)+"."+y(3,p)+"Z"}else g=null;b&&(g=b.call(c,a,g));if(null===g)return"null";m=u.call(g);if("[object Boolean]"==m)return""+g;if("[object Number]"==m)return g>-1/0&&g<1/0?""+g:"null";if("[object String]"==m)return R(""+g);if("object"==typeof g){for(a=d.length;a--;)if(d[a]===g)throw K();d.push(g);q=[];c=n;n+=f;if("[object Array]"==m){k=0;for(a=g.length;k<a;k++)m=O(k,g,b,h,f,n,d),q.push(m===w?"null":\n m);a=q.length?f?"[\\n"+n+q.join(",\\n"+n)+"\\n"+c+"]":"["+q.join(",")+"]":"[]"}else B(h||g,function(a){var c=O(a,g,b,h,f,n,d);c!==w&&q.push(R(a)+":"+(f?" ":"")+c)}),a=q.length?f?"{\\n"+n+q.join(",\\n"+n)+"\\n"+c+"}":"{"+q.join(",")+"}":"{}";d.pop();return a}};r.stringify=function(a,c,b){var h,f,n,d;if(F[typeof c]&&c)if("[object Function]"==(d=u.call(c)))f=c;else if("[object Array]"==d){n={};for(var g=0,k=c.length,l;g<k;l=c[g++],(d=u.call(l),"[object String]"==d||"[object Number]"==d)&&(n[l]=1));}if(b)if("[object Number]"==\n (d=u.call(b))){if(0<(b-=b%1))for(h="",10<b&&(b=10);h.length<b;h+=" ");}else"[object String]"==d&&(h=10>=b.length?b:b.slice(0,10));return O("",(l={},l[""]=a,l),f,n,h,"",[])}}if(!q("json-parse")){var V=A.fromCharCode,W={92:"\\\\",34:\'"\',47:"/",98:"\\b",116:"\\t",110:"\\n",102:"\\f",114:"\\r"},b,J,l=function(){b=J=null;throw G();},z=function(){for(var a=J,c=a.length,e,h,f,k,d;b<c;)switch(d=a.charCodeAt(b),d){case 9:case 10:case 13:case 32:b++;break;case 123:case 125:case 91:case 93:case 58:case 44:return e=\n D?a.charAt(b):a[b],b++,e;case 34:e="@";for(b++;b<c;)if(d=a.charCodeAt(b),32>d)l();else if(92==d)switch(d=a.charCodeAt(++b),d){case 92:case 34:case 47:case 98:case 116:case 110:case 102:case 114:e+=W[d];b++;break;case 117:h=++b;for(f=b+4;b<f;b++)d=a.charCodeAt(b),48<=d&&57>=d||97<=d&&102>=d||65<=d&&70>=d||l();e+=V("0x"+a.slice(h,b));break;default:l()}else{if(34==d)break;d=a.charCodeAt(b);for(h=b;32<=d&&92!=d&&34!=d;)d=a.charCodeAt(++b);e+=a.slice(h,b)}if(34==a.charCodeAt(b))return b++,e;l();default:h=\n b;45==d&&(k=!0,d=a.charCodeAt(++b));if(48<=d&&57>=d){for(48==d&&(d=a.charCodeAt(b+1),48<=d&&57>=d)&&l();b<c&&(d=a.charCodeAt(b),48<=d&&57>=d);b++);if(46==a.charCodeAt(b)){for(f=++b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}d=a.charCodeAt(b);if(101==d||69==d){d=a.charCodeAt(++b);43!=d&&45!=d||b++;for(f=b;f<c&&(d=a.charCodeAt(f),48<=d&&57>=d);f++);f==b&&l();b=f}return+a.slice(h,b)}k&&l();if("true"==a.slice(b,b+4))return b+=4,!0;if("false"==a.slice(b,b+5))return b+=5,!1;if("null"==a.slice(b,\n b+4))return b+=4,null;l()}return"$"},P=function(a){var c,b;"$"==a&&l();if("string"==typeof a){if("@"==(D?a.charAt(0):a[0]))return a.slice(1);if("["==a){for(c=[];;b||(b=!0)){a=z();if("]"==a)break;b&&(","==a?(a=z(),"]"==a&&l()):l());","==a&&l();c.push(P(a))}return c}if("{"==a){for(c={};;b||(b=!0)){a=z();if("}"==a)break;b&&(","==a?(a=z(),"}"==a&&l()):l());","!=a&&"string"==typeof a&&"@"==(D?a.charAt(0):a[0])&&":"==z()||l();c[a.slice(1)]=P(z())}return c}l()}return a},T=function(a,b,e){e=S(a,b,e);e===\n w?delete a[b]:a[b]=e},S=function(a,b,e){var h=a[b],f;if("object"==typeof h&&h)if("[object Array]"==u.call(h))for(f=h.length;f--;)T(h,f,e);else B(h,function(a){T(h,a,e)});return e.call(a,b,h)};r.parse=function(a,c){var e,h;b=0;J=""+a;e=P(z());"$"!=z()&&l();b=J=null;return c&&"[object Function]"==u.call(c)?S((h={},h[""]=e,h),"",c):e}}}r.runInContext=N;return r}var K=typeof define==="function"&&define.amd,F={"function":!0,object:!0},G=F[typeof exports]&&exports&&!exports.nodeType&&exports,k=F[typeof window]&&\n window||this,t=G&&F[typeof module]&&module&&!module.nodeType&&"object"==typeof global&&global;!t||t.global!==t&&t.window!==t&&t.self!==t||(k=t);if(G&&!K)N(k,G);else{var L=k.JSON,Q=k.JSON3,M=!1,A=N(k,k.JSON3={noConflict:function(){M||(M=!0,k.JSON=L,k.JSON3=Q,L=Q=null);return A}});k.JSON={parse:A.parse,stringify:A.stringify}}K&&define(function(){return A})}).call(this);\n  \n     // the url parser\n     // (c) Steven Levithan\n     // MIT Lisence\n     function parseUri (str) {\n         var o   = parseUri.options,\n             m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),\n             uri = {},\n             i   = 14;\n \n         while (i--) uri[o.key[i]] = m[i] || "";\n \n         uri[o.q.name] = {};\n         uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {\n             if ($1) uri[o.q.name][$1] = $2;\n         });\n \n         return uri;\n     };\n \n     // options for the uri parser\n     parseUri.options = {\n         strictMode: false,\n         key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],\n         q:   {\n             name:   "queryKey",\n             parser: /(?:^|&)([^&=]*)=?([^&]*)/g\n         },\n         parser: {\n             strict: /^(?:([^:\\/?#]+):)?(?:\\/\\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?))?((((?:[^?#\\/]*\\/)*)([^?#]*))(?:\\?([^#]*))?(?:#(.*))?)/,\n             loose:  /^(?:(?![^:@]+:[^:@\\/]*@)([^:\\/?#.]+):)?(?:\\/\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\/?#]*)(?::(\\d*))?)(((\\/(?:[^?#](?![^?#\\/]*\\.[^?#\\/.]+(?:[?#]|$)))*\\/?)?([^?#\\/]*))(?:\\?([^#]*))?(?:#(.*))?)/\n         }\n     };\n // IE STUFF\n  if (!Array.prototype.forEach) {\n   Array.prototype.forEach = function (fn) {\n    for (var i = 0,ii=this.length;i<ii;i++) {\n     fn(this[i],i);\n    }\n   };\n  }\n //Serve Default\n  var serveDefault = function (type,auction_id,user_id) {\n         user_id = user_id || 0;\n         auction_id = auction_id || 0;\n         if (ADNXSstart && !type && false) {\n    var ADNXSend = new Date().getTime();\n    var diff = ADNXSend-ADNXSstart;\n    (function () {\n     var  p = document.createElement(\'IMG\');\n     p.src = "//eb.3lift.com/adnxsTime?inv_code=psmag_article_big&time="+diff;\n     document.body.appendChild(p);\n    })();\n   } \n   var s = document.createElement(\'SCRIPT\');\n   var st = "setTimeout(function () { _tl.###TL_SD_ID###.sd(\'"+type+"\',\'"+auction_id+"\',\'"+user_id+"\') },100);";\n   parent.document.body.appendChild(s);\n   s.text = st;\n  };\n \n  // we implement a variable ms timeout for both adnxs and dynamic.3lift\n  var Dytimeout = true;\n  var ADNXSTimeout = true;\n  var has_been_timed_out = false;\n  var ADNXSstart;\n     var adnxs_auction_id,\n         adnxs_user_id\n     ;\n \n  var unitData;\n     var thirdPartyMacros = {};\n //Request TripleLift Sponsored Content Unit\n  var  generic_get_unit = function (data,pixel,addr,auction_id,user_id,third_party_macros) {\n         if (third_party_macros) {\n             thirdPartyMacros = third_party_macros;\n         }\n         adnxs_auction_id = auction_id;\n         adnxs_user_id = user_id;\n   if (ADNXSstart && false) {\n    var ADNXSend = new Date().getTime();\n    var diff = ADNXSend-ADNXSstart;\n    (function () {\n     var  p = document.createElement(\'IMG\');\n     p.src = "//eb.3lift.com/adnxsTime?inv_code=psmag_article_big&time="+diff;\n     document.body.appendChild(p);\n    })();\n   } \n   if (has_been_timed_out) { return; }\n   // set the timeout flag to false\n   ADNXSTimeout = false;\n   // call dyanmic.3lift to fetch the advertiser json\n   // optionally pass a click tracker to be handled during render_ad()\n   // MACROS:\n   // SERVER SIDE:\n   // SCU_VERSION -> a cache buster for dynamic.3lift\n   // TL_DYNAMIC_ADDR -> the address where the scu are cached\n   unitData = data;\n   var tlParent = parent.document.getElementById(window.frameElement.id);\n   var version = \'?rsv=169-S834-37\';\n   var a = document.createElement(\'script\');\n   if (!pixel) { pixel = false; }\n   a.setAttribute(\'id\', "tldynamic");\n   a.setAttribute(\'adnxsCt\', pixel);\n   a.setAttribute(\'src\', addr  + data+version); \n   document.body.appendChild(a);\n   setTimeout(function () {\n    if (Dytimeout) {\n     has_been_timed_out = true;\n     serveDefault("dynamic timeout");\n    }\n   }, 10000);\n  };\n \n     var get_unit = function (data,pixel,tag_code,auction_id,user_id,thirdPartyMacros) {\n         user_id = user_id || 0;\n         auction_id = auction_id || 0;\n         var addr = \'//dynamic.3lift.com/sc/advertiser/jsonp/\';\n         generic_get_unit(data,pixel,addr,auction_id,user_id,{});\n     };\n \n     var get_3p_unit = function (data,pixel,tag_code,auction_id,user_id,thirdPartyMacros) {\n   user_id = user_id || 0;\n         auction_id = auction_id || 0;\n         var addr =  \'//dynamic.3lift.com/sc/bidder/jsonp/\';\n         generic_get_unit(data,pixel,addr,auction_id,user_id,thirdPartyMacros);\n     };\n         \n     var expandThirdPartyMacros = function (url) {\n         url = url.replace("${CACHEBUSTER}",Math.floor(10000000000 * Math.random())); // choose a random 10-digit number\n         url = url.replace("[timestamp]",Math.floor(10000000000 * Math.random())); // choose a random 10-digit number\n         url = url.replace("[CACHEBUSTER]",Math.floor(10000000000 * Math.random())); // choose a random 10-digit number\n         url = url.replace("[PLACEMENT_ID]", "2087");\n         var tpmacro, tpmacroValue;\n         for (tpmacro in thirdPartyMacros) {\n             if (!tpmacro.match(\'%\')) {\n                 continue;\n             }\n             tpmacroValue = thirdPartyMacros[tpmacro];\n             tpmacro = \'$\'+tpmacro.slice(1);\n             url = url.replace(tpmacro,tpmacroValue);\n         }\n         return url;\n     };\n         \n  var send3rdPartyPix = function(url) {\n   // fire a pixel for the given url\n   var p = document.createElement(\'IMG\');\n      p.setAttribute(\'width\', \'0\');\n   p.setAttribute(\'height\', \'0\');\n   p.src = expandThirdPartyMacros(url);\n   document.body.appendChild(p);\n  };\n \n  var send3rdPartyJS = function(url) {\n   // fire a pixel for the given url\n         var p = document.createElement(\'SCRIPT\');\n         p.setAttribute(\'type\',\'text/javascript\');\n         p.src = expandThirdPartyMacros(url);\n   var tl_iframe = window.frameElement;\n   var tl_iframe_parent = tl_iframe.parentNode;\n         if (tl_iframe.nextSibling) {\n          tl_iframe_parent.insertBefore(p, tl_iframe.nextSibling);\n         }\n         else {\n             tl_iframe_parent.insertBefore(p, tl_iframe);\n         }\n  }\n // tl_advertiser_json\n  var tl_advertiser_json =  function (data) {\n   // check to see if we\'ve been timed out\n   if (has_been_timed_out) { return; }\n   // set the timeout flag to false\n   Dytimeout = false;\n   // we define some functions in scope, and then call\n   //  setImageUrl(trending_item);\n   //  setClickTracker(trending_item);\n   //  setShares(trending_item);\n   //  trending_item.advertiser_name = data.tl_advertiser_data.settings.advertiser_name;\n   //  create_script(trending_item);\n        \n   var getTrendingItem = function () {\n    if (data.tl_advertiser_data.images.length === 0) {\n     serveDefault("no images");\n    }\n    var trending_item_index = Math.floor(Math.random() * data.tl_advertiser_data.images.length);\n    var trending_item = data.tl_advertiser_data.images[trending_item_index];\n    if(parent._tl.tl_image_id){\n     for (i=0; i < data.tl_advertiser_data.images.length; i++){\n      if(parent._tl.tl_image_id == data.tl_advertiser_data.images[i].image_id){\n       trending_item = data.tl_advertiser_data.images[i];\n      }\n     }\n    }\n             // add the adnxs user and auction id\'s to the trending_item\n             trending_item.adnxs_auction_id = adnxs_auction_id;\n             trending_item.adnxs_user_id    = adnxs_user_id;\n             // add the logo_url\n             trending_item.logo_image_url = settings.logo_image_url;\n    return trending_item;\n   };\n   \n   var setClickTracker = function () {\n    if(!settings.impression_discrepancy_rate)\n     settings.impression_discrepancy_rate = 1;\n    if (settings.impression_pixels || (settings.impression_pixel_url && settings.impression_pixel_url.length)) {\n        if(!settings.impression_sampling_rate || Math.random() < settings.impression_sampling_rate * settings.impression_discrepancy_rate || parent._tl.third_party) {\n            if(settings.impression_pixels) {\n                pixels = settings.impression_pixels;\n                if(pixels.length && pixels.length > 0) {\n                    for(var i = 0; i < pixels.length; i++) {\n                        send3rdPartyPix(pixels[i]);\n                    }\n                }\n            } else if(settings.impression_pixel_url) {\n             send3rdPartyPix(settings.impression_pixel_url);\n            }\n        }\n    }\n             trending_item.comScoreArr = [];\n       if(!settings.impression_sampling_rate || Math.random() < settings.impression_sampling_rate * settings.impression_discrepancy_rate || parent._tl.third_party) {\n                 if(settings.js_pixels) {\n            pixels = settings.js_pixels;\n            if(pixels.length && pixels.length > 0) {\n                for(var i = 0; i < pixels.length; i++) {\n                             send3rdPartyJS(pixels[i]);\n                }\n            }\n           }\n       }\n             // add the original clickthrough url, in case we mutate it below\n             trending_item.original_clickthrough_url = trending_item.clickthrough_url;\n    if (settings.click_tracker_url && settings.click_tracker_url.length) {\n     var el;\n     var ct = trending_item.clickthrough_url;\n     var ctracker = expandThirdPartyMacros(settings.click_tracker_url);\n     if (isNaN(parseInt(settings.click_tracker_encoding_level))) {\n      el = 1;\n     }\n     else {\n      el = parseInt(settings.click_tracker_encoding_level);\n     }\n     while (el--) {\n      ct = encodeURIComponent(ct);\n     }\n     trending_item.clickthrough_url = ctracker+ct;\n    }\n    if (\'###TTJ_CT_URL###\'.length) {\n     var ct = decodeURIComponent(\'###TTJ_CT_URL###\');\n     var tct = encodeURIComponent(trending_item.clickthrough_url);\n     trending_item.clickthrough_url = ct+tct;\n    }\n    // set up the adnxs click tracker\n    var dynamicTag = document.getElementById(\'tldynamic\');\n             var adnxsPix;\n             // in dynamicCreative units, adnxsPix is not set, nor is the dynamicTag\n             if (dynamicTag) {\n                 adnxsPix = dynamicTag.getAttribute(\'adnxsCt\');\n             }\n             else {\n                 adnxsPix  = "false";\n             }\n    if (adnxsPix !== "false") {\n     trending_item.adnxsPix = adnxsPix;\n    }\n             else {\n                 trending_item.adnxsPix = "";\n             }\n             // check if the pixel should be tied to an arbitrary event\n             // defaults to click\n             if (settings.adnxs_pixel_event) {\n                 trending_item.adnxs_pix_event;\n             }\n             else {\n                 trending_item.adnxs_pix_event = "click";\n             }\n   };\n   \n         var setImageUrl = function () {\n    // MACROS:\n    // SERVER SIDE\n    // TL_IMG_ADDR -> the image-server address\n    // IMAGE_WIDTH/IMAGE_HEIGHT -> the image dimensions obtained from the placement data\n    // first create a width 600 image for pinterest\n             trending_item.w600_url = \'//img.3lift.com/?inv_code=psmag_article_big&width=600&alt=max&url=\' + encodeURIComponent(trending_item.image_url);\n             // create the image url that will render in the ad\n             trending_item.image_url = \'//img.3lift.com/?inv_code=psmag_article_big&width=680&height=350&alt=tl&url=\' + encodeURIComponent(trending_item.image_url);\n    \n    // since the logo exclude zones are set on a publisher basis, and are needed when setting the share buttons, we add logo_exclude zones whether or not there is a logo set\n    var exclude_zones = \'NW\';\n    if(exclude_zones == \'N,NE,E,SE,S,SW,W,NW,C\'){\n     settings.include_logo = 0;\n     trending_item.img_server_params = trending_item.img_server_params.replace(/logo.*\\&/g,\'\'); //consider moving this to the image server\n    }\n    else{\n     trending_item.image_url += "&logo_exclude="+exclude_zones;\n    }\n    if (trending_item.img_server_params) {\n        trending_item.image_url += \'&\'+trending_item.img_server_params;\n    } else {\n                 if (!settings.image_version) {\n                  settings.image_version = \'0\';\n                 }\n                 trending_item.image_url += \'&v=\'+settings.image_version;\n                 \n                 if (settings.include_logo == 1) {\n                  var logoUrl = encodeURIComponent(settings.logo_image_url);\n                  if (settings.logo_offset_x) {\n                   var xlogo = settings.logo_offset_x; \n                  }\n                  else {\n                   xlogo = 0;\n                  }\n                  if (settings.logo_offset_y) {\n                   var ylogo = settings.logo_offset_y;\n                  }\n                  else {\n                   ylogo = 0;\n                  }\n                  trending_item.image_url += "&logo="+logoUrl+"&lox="+xlogo+"&loy="+ylogo;\n                 }\n                 \n                 if(settings.logo_placement) {\n                  trending_item.image_url += \'&lp=\' + settings.logo_placement;\n                 }\n                 // cv ha and ir\n                 if (trending_item.cv_version) {\n                  trending_item.image_url += \'&cv_version=\' + trending_item.cv_version;\n                 }\n                 if (trending_item.ha_version) {\n                  trending_item.image_url += \'&ha_version=\' + trending_item.ha_version;\n                 }\n                 if (trending_item.ir_version) {\n                  trending_item.image_url += \'&ir_version=\' + trending_item.ir_version;\n                 }\n    }\n   };\n  \n   var setShares = function () {\n    if (settings.share_types) {\n     settings.share_types = settings.share_types.split(",");\n     trending_item.share_types = [];\n     settings.share_types.forEach(function (st) {\n      trending_item.share_types.push(st);\n     });\n    }\n             // video needs a copy of this array so a macro may be populated later\n             trending_item.video_share_types = trending_item.share_types || [];\n   };\n    \n   var settings = data.tl_advertiser_data.settings;\n   if(settings.tl_scu_id) { //overwrite unitData with tl_scu_id in json if it exists so that we always pass first party IDs along to the EB\n    unitData = parseInt(settings.tl_scu_id);\n         }\n   var trending_item = getTrendingItem();\n   setImageUrl(trending_item);\n   setClickTracker(trending_item);\n   setShares(trending_item);\n   trending_item.advertiser_name = data.tl_advertiser_data.settings.advertiser_name;\n   create_script(trending_item,settings);\n  };\n     // dynamicCreativeRender is exactly similar to tl_advertiser_json, except that the object must first be wrapped in a tl_advertiser_data object\n     var dynamicCreativeRender = function (data) {\n         data = {tl_advertiser_data:data};\n         tl_advertiser_json(data);\n     };\n \n  var create_script = function (trending_item,settings) {\n   var scriptText;\n   var tl_rd = \'tl_rd_\'+Math.round(Math.random()*100000);\n   var script = document.createElement(\'SCRIPT\');\n   script.setAttribute(\'id\',tl_rd);\n   var appendScript = function () {\n    //var hook = parent.document.getElementById(window.frameElement.id);\n    //hook.parentNode.insertBefore(script,hook);\n    parent.document.body.appendChild(script);\n             script.text = scriptText;\n   };\n   var createShareTypesFromPhpJson = function (shareJson) { // an array of objects\n    var st = {};\n    shareJson.forEach(function (s) {\n     st[s.name] = {code:s.code,button:s.button_src};\n    });\n    return st;\n   };\n   var addSharing = function (templateCode) {\n             var trending_url = trending_item.image_url;\n             // get the possible share types\n    // {object} ex. FACEBOOK:// code snippet\n    var share_types = createShareTypesFromPhpJson([{\"id\":\"1\",\"name\":\"PINTEREST\",\"code\":\"window.open(\\\'http:\\/\\/pinterest.com\\/pin\\/create\\/button\\/?url=\\\' + encodeURIComponent(\\\'%%%ORIGINAL_CLICKTHROUGH_URL%%%\\\') + \\\'&media=\\\'+encodeURIComponent(\\\'%%%IMAGE_URL%%%\\\') + \\\'&description=\\\'+encodeURIComponent(\\\'%%%SINGLE_ESCAPED_CAPTION%%%\\\'),\\\'popup\\\',\\\'width=650,height=316\\\');\",\"button_src\":\"http:\\/\\/images.3lift.com\\/2917936.png\"},{\"id\":\"2\",\"name\":\"TWITTER\",\"code\":\"window.open(\\\'http:\\/\\/twitter.com\\/home?status=\\\'+encodeURIComponent(\\\'%%%SINGLE_ESCAPED_CAPTION%%%\\\'),\\\'popup\\\',\\\'width=650,height=316\\\');\",\"button_src\":\"http:\\/\\/images.3lift.com\\/2917933.png\"},{\"id\":\"3\",\"name\":\"FACEBOOK\",\"code\":\"window.open(\\\'http:\\/\\/www.facebook.com\\/sharer.php?u=\\\'+encodeURIComponent(\\\'%%%CLICKTHROUGH_URL%%%\\\'),\\\'popup\\\',\\\'width=626,height=436\\\');\",\"button_src\":\"http:\\/\\/images.3lift.com\\/2917935.png\"},{\"id\":\"4\",\"name\":\"PINTEREST_TEST\",\"code\":\"window.open(\\\'http:\\/\\/pinterest.com\\/pin\\/create\\/button\\/?url=\\\' + encodeURIComponent(\\\'%%%CLICKTHROUGH_URL%%%\\\') + \\\'&media=\\\'+encodeURIComponent(\\\'http:%%%IMAGE_URL%%%\\\') + \\\'&description=\\\'+encodeURIComponent(\\\'%%%SINGLE_ESCAPED_CAPTION%%%\\\'),\\\'popup\\\',\\\'width=650,height=316\\\');\",\"button_src\":null},{\"id\":\"5\",\"name\":\"PIN\",\"code\":\"window.open(\\\'http:\\/\\/pinterest.com\\/pin\\/create\\/button\\/?url=\\\' + encodeURIComponent(\\\'%%%CLICKTHROUGH_URL%%%\\\') + \\\'&media=\\\'+encodeURIComponent(\\\'http:%%%IMAGE_URL%%%\\\') + \\\'&description=\\\'+encodeURIComponent(\\\'%%%SINGLE_ESCAPED_CAPTION%%%\\\'),\\\'popup\\\',\\\'width=650,height=316\\\');\",\"button_src\":null},{\"id\":\"6\",\"name\":\"TUMBLR\",\"code\":\"window.open(\\\'https:\\/\\/tumblr.com\\/share\\/photo?source=\\\'+encodeURIComponent(\\\'http:%%%IMAGE_URL%%%\\\')+\\\'&caption=\\\'+encodeURIComponent(\\\'%%%SINGLE_ESCAPED_CAPTION%%%\\\'), \\\'popup\\\', \\\'width=650,height=316\\\');\",\"button_src\":\"http:\\/\\/images.3lift.com\\/2917934.png\"}]);\n    // get already included {array}\n    //var include_share_types = [];\n    //var publisherBlackListShareTypes = [];\n    // check if the unit has any share buttons\n    var scu_st = trending_item.share_types;\n    if (scu_st) {\n     scu_st.forEach(function (st) {\n      // check black list and included\n      st = st.toUpperCase();\n      //if ((include_share_types.indexOf(st) < 0) && (publisherBlackListShareTypes.indexOf(st) < 0)) {\n       // concatenate the share type\n       templateCode += "<div style=\\"display:none\\" class=\\"tl_share\\" onclick=\\"tlobj[\'```ANALYTICS_ID```\'](\'"+st+"\'); "+share_types[st][\'code\'] +"\\" data-button=\\""+(share_types[st][\'button\'].replace(/\\//g,"\\\\/"))+"\\"></div>";\n     // }\n     });\n    }\n    return templateCode;\n   };\n         // addOptionalVideo checks if the scu is a video unit, and from the video settings object adds various settings to the trending_item object, so that those settings can later be used to populate macros elsewhere\n         var addOptionalVideo = function (templateCode) {\n             var vid;\n             // list the options that need to be pulled out the video data\n             var videoOptions = ["hover_action","alt_see_more","expose_controls","reset_video","always_show_buttons"];\n             if (settings.type === "youtube") {\n                 if (settings.video_data) {\n                     vid = settings.video_data.video_id;\n                     templateCode += \'<div style="display:none" class="tl-vid" tl-vid-type="yt" tl-vid-id="\'+vid+\'"></div>\';\n                     videoOptions.forEach(function (videoOption) {\n                         if (settings.video_data[videoOption]) {\n                             trending_item[videoOption] = settings.video_data[videoOption];\n                         }\n                         else { //  the default value for hover_action is \'none\'\n                             trending_item[videoOption] = \'0\'; // TODO make not set\n                         }\n                     });\n                 }\n             }\n             return templateCode;\n         };\n         \n         var addThirdPartyMacros = function (trending_item) {\n             if (!thirdPartyMacros) {\n                 return;\n             }\n             var propt, tpmacro, tpmacrovalue;\n             for (propt in trending_item) {\n                 if (!trending_item[propt] || !trending_item[propt].replace) {\n                     continue;\n                 }\n                 for (tpmacro in  thirdPartyMacros) {\n                     tpmacrovalue = thirdPartyMacros[tpmacro];\n                     tpmacro = \'$\'+tpmacro.slice(1);\n                     trending_item[propt] = trending_item[propt].replace(tpmacro,tpmacrovalue);\n                 }\n             }\n         };\n \n   var addEscapedMacros = function (trending_item) {\n    // create \'%%%SINGLE_ESCAPED, %%%DOUBLE_ESCAPED, and %%%ALL_ESCAPED versions of the macros\n    var propt, \n     esc_types = ["SINGLE_ESCAPED_","DOUBLE_ESCAPED_","ALL_ESCAPED_"], \n     additional_macros = {}\n    ;\n    for (propt in trending_item) {\n     if ((typeof trending_item[propt]).toLowerCase() === "string") {\n      esc_types.forEach(function (et,index) {\n       var ept = et+propt;\n       additional_macros[ept] = (function () {\n        if (et === \'SINGLE_ESCAPED_\') {\n         return trending_item[propt].replace(/\'/g,"\\\\\'").replace(/\\n/g,"\\\\n");\n        }\n        if (et === \'DOUBLE_ESCAPED_\') {\n         return trending_item[propt].replace(/"/g,\'\\\\"\').replace(/\\n/g,"\\\\n");\n        }\n        else {\n         return trending_item[propt].replace(/\'/g,"\\\\\'").replace(/"/g,\'\\\\"\').replace(/\\n/g,"\\\\n");\n        }\n       })();\n      });\n     }\n    }\n    // IE <9 FIX\n    for (propt in additional_macros) {\n     trending_item[propt] = additional_macros[propt];\n    }\n   };\n  \n   var createTemplate = function (html) {\n    // MACROS:\n    //  SERVER SIDE:\n    //  TEMPLATE_CODE : the template code provided by the placement with which the native ad is rendered\n    // set up advertiser sharing\n    if (true) {\n     html = addSharing(html);\n    }\n             html = addOptionalVideo(html);\n    for (propt in trending_item) {\n     var re = new RegExp(\'%%%\'+propt+\'%%%\', "gi");\n     html   = html.replace(re,trending_item[propt]);\n    }\n             // escape new lines\n             html = html.replace(/\\\\n/g, "\\\\\\\\n");\n             html = html.replace(/\\n/g," \\\\n");\n    // the first replace is too aggresive, and will escape the first escape marker, breaking single quotes\n    // we correct for that by replacing all the instances where there are two slashes followed by a single quote, replacing them with a double escaped single quote\n             return html.replace(/\'/g,"\\\\\'").replace(/\\\\\\\\\'/g,"\\\\\\\\\\\\\'");\n   };\n   \n         var createAnalyticsTemplate = function (html) {\n    // we have to call add optional video to get a desired side effect\n             // namely, get the EXPOSE_CONTROLS macro in the trending item\n             addOptionalVideo(html);\n             // set up the trending item with escaped macros\n    addEscapedMacros(trending_item);\n                        addThirdPartyMacros(trending_item);\n    // MACROS:\n    //  SERVER SIDE:\n    //  TEMPLATE_CODE : the template code provided by the placement with which the native ad is rendered\n    // set up the trending item with escaped macros\n          //   addEscapedMacros(trending_item);\n    for (propt in trending_item){\n     var re = new RegExp(\'%%%\'+propt+\'%%%\', "gi");\n     html = html.replace(re,trending_item[propt]);\n    }\n             // since there are two levels, we have to double escape everything\n             // a single esacpe character therefore becomes 3, since \\? must become \\\\\\?->\\?->?, and unescaped control characters must be escaped once\n             html = html.replace(/\\\\/g, "\\\\\\\\\\\\");\n             html = html.replace(/\\\\n/g, "\\\\\\\\n");\n             html = html.replace(/\\n/g," \\\\n");\n             // the first replace is too aggresive, and will escape the first escape marker, breaking single quotes\n    // we correct for that by replacing all the instances where there are two slashes followed by a single quote, replacing them with a double escaped single quote\n             html = html.replace(/([^\\\\])(\')(\')/g, "$1\\\\$2\\\\$3");\n             html = html.replace(/([^\\\\])(\')/g,"$1\\\\$2");\n             return html;\n   };\n   \n   var writeScriptText = function () {\n    // create the text of the script which will be appended\n    // outside the current iframe\n    //\n    // MACROS:\n    // SERVER SIDE:\n    // RENDER_SCRIPT -> the body of the script that will render the add\n    //\n    // CLIENT SIDE:\n    // PLACEMENT_HTML -> the template, with the trending_item data in place of the template macro\n    // TL_RD_ID -> the id of the script tag that will render the add\n    // IMAGEID -> the image id of the trending item\n    // ADNXS_CLICK_PIX -> a boolean: true if a click tracker is present in the trending_item, false otherwise\n    // ADNXS_CLICK_PIX_URL -> the url of the adnxs click tracker\n    // CLICKTHROUGH_URL -> the CLICKTHROUGH_URL, as given in the trending_item\n    // CAPTION -> the CAPTION, as given in the trending item\n    // UNIT_SHARE_ENABLED -> the trending_item has specified supported share types\n    // UNIT_ID -> the sponsored content unit id\n    var scriptBody = \'try {\\n (function () {\\n  var tl_iframe = document.getElementById(\\\'###TL_IF_ID###\\\');\\n \\n  var render_ad = function () {\\n   // create a div and write the contents of the add in it,\\n   // adding the sharing and the analytics tag\\n   // \\n   // MACROS:\\n   // SERVER SIDE\\n   // SPONSORED_TAG_BODY -> the body of the analytics tag\\n   // INV_CODE -> the inventory code set in the ttj tag\\n   //\\n   // CLIENT SIDE:\\n   // ANALYTICS_ID -> the id of the analytics script\\n   // ID -> the id of the div that the advertisement is written in.\\n   // get the placement html\\n   var adID = "tl_"+Math.round(Math.random() * 100000);\\n   var adDID = "@@@IMAGEID@@@";\\n   var sdID = "###TL_SD_ID###";\\n         // check that we haven\\\'t already served a default between writing this tag that and its evaluation\\n         if (_tl[sdID] && _tl[sdID].gd && _tl[sdID].gd()) {\\n             return;\\n         }\\n         var cturl = \\\'@@@CLICKTHROUGH_URL@@@\\\';\\n   // create the analytics tag \\n   var analyticsTagID = "tlat_"+Math.round(Math.random() * 100000);\\n   var analyticsTag = document.createElement(\\\'script\\\');\\n   analyticsTag.setAttribute(\\\'type\\\',\\\'text/javascript\\\');\\n   analyticsTag.setAttribute(\\\'charset\\\',\\\'UTF-8\\\');\\n   analyticsTag.setAttribute(\\\'id\\\', analyticsTagID);\\n   var analyticsText = \\\'@@@SPONSORED_TAG_BODY@@@\\\'.replace(new RegExp(\\\'```ANALYTICS_ID```\\\',"gi"),analyticsTagID).replace(new RegExp(\\\'```CLICKTHROUGH_URL```\\\',\\\'gi\\\'),cturl);\\n \\n         // get any script srcs, like the comscore tag, that must be appended to the image\\n             // for right now, we know there\\\'s only one\\n         var comscoreArr = @@@COMSCORESRC@@@;\\n   // create the html string\\n   var html = \\\'@@@PLACEMENT_HTML@@@\\\'.replace(new RegExp(\\\'```ANALYTICS_ID```\\\',"gi"),analyticsTagID);\\n    _tl.render_inline(tl_iframe,html,analyticsTag,analyticsText,adID,adDID,sdID,comscoreArr);\\n \\n  };\\n  render_ad();\\n })();\\n } catch (e) {\\n  if (_tl.debug) {\\n   console.log(\\\'*** TL MESSAGE ***\\\');\\n   console.log(\\\'CAUGHT ERROR\\\');\\n   console.log(e.stack);\\n  }\\n  var p = document.createElement(\\\'IMG\\\');\\n  p.src= "//eb.3lift.com/sce?block=render&inv_code=psmag_article_big&e="+encodeURIComponent(e);\\n  p.width = 0;\\n  p.height = 0;\\n  document.body.appendChild(p);\\n }\\n \'.replace(\'@@@SPONSORED_TAG_BODY@@@\',createAnalyticsTemplate(\'try {\\n // init some video stuff\\n var glYTAPI;\\n function onYouTubePlayerAPIReady () {\\n     glYTAPI = true;\\n };\\n \\n var isMobile = function () {\\n  return (navigator && navigator.userAgent && navigator.userAgent.match(/iphone|ipad|android/i));\\n };\\n \\n var safeSetZindex = function (index,el,$el,info) {\\n     if (el) {\\n         try {\\n             el.style.zIndex = index;\\n         }\\n         catch (e) {\\n             el.style.zIndex = index+\\\'\\\';\\n         }\\n     }\\n     else {\\n         try {\\n             $el.style(\\\'z-index\\\',index,info);\\n         }\\n         catch (e) {\\n             $el.style(\\\'z-index\\\',index+\\\'\\\',info);\\n         }\\n     }\\n };\\n var tlobj;\\n // sometimes we need to specify specific style attributes with !important so they don\\\'t get clobbered\\n // by publishers\\\' css\\n \\n var gaurd = function ($el) {\\n     $el.style("min-width","0","important");\\n     $el.style("min-height","0","important");\\n     return $el;\\n };\\n \\n var createImportantPlugin = function($) {    \\n   if ($.fn.style) {\\n     return;\\n   }\\n   try {\\n       // Escape regex chars with \\\\\\n       var escape = function(text) {\\n         return text.replace(/[-[\\\\]{}()*+?.,\\\\\\\\^$|#\\\\s]/g, "\\\\\\\\$&");\\n       };\\n \\n       // For those who need them (< IE 9), add support for CSS functions\\n       var isStyleFuncSupported = !!CSSStyleDeclaration.prototype.getPropertyValue;\\n       if (!isStyleFuncSupported) {\\n         CSSStyleDeclaration.prototype.getPropertyValue = function(a) {\\n           return this.getAttribute(a);\\n         };\\n         CSSStyleDeclaration.prototype.setProperty = function(styleName, value, priority) {\\n           this.setAttribute(styleName, value);\\n           var priority = typeof priority != \\\'undefined\\\' ? priority : \\\'\\\';\\n           if (priority != \\\'\\\') {\\n             // Add priority manually\\n             var rule = new RegExp(escape(styleName) + \\\'\\\\\\\\s*:\\\\\\\\s*\\\' + escape(value) +\\n                 \\\'(\\\\\\\\s*;)?\\\', \\\'gmi\\\');\\n             this.cssText =\\n                 this.cssText.replace(rule, styleName + \\\': \\\' + value + \\\' !\\\' + priority + \\\';\\\');\\n           }\\n         };\\n         CSSStyleDeclaration.prototype.removeProperty = function(a) {\\n           return this.removeAttribute(a);\\n         };\\n         CSSStyleDeclaration.prototype.getPropertyPriority = function(styleName) {\\n           var rule = new RegExp(escape(styleName) + \\\'\\\\\\\\s*:\\\\\\\\s*[^\\\\\\\\s]*\\\\\\\\s*!important(\\\\\\\\s*;)?\\\',\\n               \\\'gmi\\\');\\n           return rule.test(this.cssText) ? \\\'important\\\' : \\\'\\\';\\n         }\\n       }\\n \\n       // The style function\\n       $.fn.style = function(styleName, value, priority) {\\n         // DOM node\\n         var node = this.get(0);\\n         // Ensure we have a DOM node\\n         if (typeof node == \\\'undefined\\\') {\\n           return;\\n         }\\n         // CSSStyleDeclaration\\n         var style = this.get(0).style;\\n         // Getter/Setter\\n         if (typeof styleName != \\\'undefined\\\') {\\n           if (typeof value != \\\'undefined\\\') {\\n             // Set style property\\n             priority = typeof priority != \\\'undefined\\\' ? priority : \\\'\\\';\\n             style.setProperty(styleName, value, priority);\\n           } else {\\n             // Get style property\\n             return style.getPropertyValue(styleName);\\n           }\\n         } else {\\n           // Get CSSStyleDeclaration\\n           return style;\\n         }\\n       };\\n     }\\n     catch (e) {\\n         // for IE 7\\n         // this won\\\'t work for all our use cases\\n         // the share buttons won\\\'t show in ie 7 for example\\n         // but it allows other analytics data to be collected\\n         // until a more comprehensive solution can be found\\n         $.fn.style = function(styleName, value, priority) {\\n             if (!styleName) {\\n                 return this.get(0).style;\\n             }\\n             if (!value) {\\n                 return this.get(0).style && this.get(0).style[styleName];\\n             }\\n             var style = this.get(0).style;\\n             style[styleName] = value;\\n         };\\n     }\\n };\\n if (!tlobj) {\\n  tlobj = {};\\n }\\n tlobj["```ANALYTICS_ID```"] = (function tlprivate () {\\n  var ts;\\n     var tljQuery;\\n     var oldjQuery;\\n \\n     var swapCorrectJquery = function () {\\n         tljQuery = jQuery;\\n         if (oldjQuery) {\\n             jQuery = oldjQuery;\\n             // don\\\'t let jQuery clobber the global $\\n             if ($.noConflict) {\\n                 $.noConflict();\\n             }\\n         }\\n     };\\n \\n  // start_analytics starts analytics if jQuery is present\\n  var start_analytics = function () { \\n         // set tljQuery to be jQuery, and if we have a stashed version, make sure that jQuery ultimately refers to that\\n   swapCorrectJquery();\\n         if (tljQuery) {\\n             createImportantPlugin(tljQuery);\\n    analytics(tljQuery);\\n   }\\n  };\\n     \\n     var correctjQueryVersion = function () {\\n         if (!jQuery) {\\n             return false;\\n         }\\n         // parse the jquery version\\n         var version_string = jQuery.fn.jquery;\\n         var parsed_vs = version_string.split(".");\\n         var jq_version = {};\\n         jq_version.major = parseInt(parsed_vs[0]);\\n         jq_version.minor = parseInt(parsed_vs[1]);\\n         jq_version.point = parseInt(parsed_vs[2]);\\n         var minMajor = 1;\\n         var minMinor = 9;\\n         var minPoint = 1;\\n         if (jq_version.major < minMajor) {\\n             return false;\\n         }\\n         if (jq_version.minor < minMinor) {\\n             return false;\\n         }\\n         if (jq_version.minPoint < minPoint) {\\n             return false;\\n         }\\n         return true;\\n     };\\n \\n  var check_jq = function () {\\n   // check for jquery\\n   // if it\\\'s not present load it\\n   if ((typeof jQuery != \\\'undefined\\\') && correctjQueryVersion()) {\\n    start_analytics();\\n   }\\n   else {\\n             // if jQuery exists, its an out of date version\\n             // so we stash it in oldjQuery\\n             // enclose this in a try to prevent jQuery not defined errors\\n             try {\\n                 if (jQuery) {\\n                     oldjQuery = jQuery;\\n                 }\\n             }\\n             catch (e) {\\n             }\\n    var jq = document.createElement(\\\'SCRIPT\\\');\\n    jq.src = "//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js";\\n    if (jq.onload || document.addEventListener) {\\n     jq.onload = start_analytics;\\n    }\\n    else {\\n     setTimeout((function () {\\n      var looper = function (n) {\\n       if (n>100 || jq.readyState === \\\'complete\\\' || jq.readyState === \\\'loaded\\\') {\\n        start_analytics();\\n       }\\n       else {\\n        setTimeout(function () { looper(n+1); }, 50);\\n       }\\n      };\\n      return function () {\\n       looper(0);\\n      }\\n     })(), 100);\\n    }\\n    document.body.appendChild(jq);\\n   }\\n  };\\n  // check for jquery and start analytics\\n  var analytics = function (tljQuery) {\\n   // set the protocol we\\\'ll be using on our calls\\n   var protocol = window.location.protocol + \\\'//\\\';\\n   // indexOf for IE //\\n   if (!Array.prototype.indexOf) {\\n    Array.prototype.indexOf = function (searchElement /*, fromIndex */ ) {\\n     //"use strict";\\n     if (this == null) {\\n      throw new TypeError();\\n     }\\n     var t = Object(this);\\n     var len = t.length >>> 0;\\n     if (len === 0) {\\n      return -1;\\n     }\\n     var n = 0;\\n     if (arguments.length > 0) {\\n      n = Number(arguments[1]);\\n      if (n != n) { // shortcut for verifying if it\\\'s NaN\\n       n = 0;\\n      } else if (n != 0 && n != Infinity && n != -Infinity) {\\n       n = (n > 0 || -1) * Math.floor(Math.abs(n));\\n      }\\n     }\\n     if (n >= len) {\\n      return -1;\\n     }\\n     var k = n >= 0 ? n : Math.max(len - Math.abs(n), 0);\\n     for (; k < len; k++) {\\n      if (k in t && t[k] === searchElement) {\\n       return k;\\n      }\\n     }\\n     return -1;\\n    }\\n   }\\n   \\n   // IEs below 9 don\\\'t have Object.keys\\n   // NOTE: Do not appy this to DOM Objects,\\n   // they don\\\'t have a hasOwnProperty method\\n   Object.keys = Object.keys || function(o) {\\n    var result = [];\\n    for(var name in o) {\\n     if (o.hasOwnProperty(name))\\n     result.push(name);\\n    }\\n    return result;\\n   };\\n   \\n   // the url parser\\n   // (c) Steven Levithan\\n   // MIT Lisence\\n   function parseUri (str) {\\n    var o   = parseUri.options,\\n     m   = o.parser[o.strictMode ? "strict" : "loose"].exec(str),\\n     uri = {},\\n     i   = 14;\\n \\n    while (i--) uri[o.key[i]] = m[i] || "";\\n \\n    uri[o.q.name] = {};\\n    uri[o.key[12]].replace(o.q.parser, function ($0, $1, $2) {\\n     if ($1) uri[o.q.name][$1] = $2;\\n    });\\n \\n    return uri;\\n   };\\n \\n   // options for the uri parser\\n   parseUri.options = {\\n    strictMode: false,\\n    key: ["source","protocol","authority","userInfo","user","password","host","port","relative","path","directory","file","query","anchor"],\\n    q:   {\\n     name:   "queryKey",\\n     parser: /(?:^|&)([^&=]*)=?([^&]*)/g\\n    },\\n    parser: {\\n     strict: /^(?:([^:\\\\/?#]+):)?(?:\\\\/\\\\/((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\\\/?#]*)(?::(\\\\d*))?))?((((?:[^?#\\\\/]*\\\\/)*)([^?#]*))(?:\\\\?([^#]*))?(?:#(.*))?)/,\\n     loose:  /^(?:(?![^:@]+:[^:@\\\\/]*@)([^:\\\\/?#.]+):)?(?:\\\\/\\\\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\\\\/?#]*)(?::(\\\\d*))?)(((\\\\/(?:[^?#](?![^?#\\\\/]*\\\\.[^?#\\\\/.]+(?:[?#]|$)))*\\\\/?)?([^?#\\\\/]*))(?:\\\\?([^#]*))?(?:#(.*))?)/\\n    }\\n   };\\n   // create a url\\n   // takes a string, and an object that represents a query string\\n   // returns a string\\n   function createUrl (str, options) {\\n    if (!str.match(/^http/))\\n     str = \\\'//\\\' + str;\\n    var keys = Object.keys(options);\\n    if (!keys.length)\\n     return str;\\n    if (str.indexOf(\\\'?\\\') === str.length-1) {\\n     str = str.slice(0, str.length-1);\\n    }\\n    var qs = "?";\\n    var n, nn;\\n    for (n=0, nn=keys.length; n<nn; n++) {\\n     if (n === (nn-1)) { // we are at the final parameter\\n      qs += keys[n] + \\\'=\\\' + options[keys[n]];\\n     }\\n     else {\\n      qs += keys[n] + \\\'=\\\' + options[keys[n]] + \\\'&\\\';\\n     }\\n    }\\n    return str + qs;\\n   }\\n         var isPin = function (b) {\\n             return (b.src && b.src.match("2917936"));\\n         };\\n         var isFb = function (b) {\\n             return (b.src && b.src.match("2917935"));\\n         };\\n  // parse the jquery version\\n  var version_string = tljQuery.fn.jquery;\\n  var parsed_vs = version_string.split(".");\\n  var jq_version = {};\\n  jq_version.major = parseInt(parsed_vs[0]);\\n  jq_version.minor = parseInt(parsed_vs[1]);\\n  jq_version.point = parseInt(parsed_vs[2]);\\n  if (jq_version.major >= 1 && jq_version.minor >= 9 && jq_version.point >= 1) {\\n   /*! \\n    * hoverIntent r7 // 2013.03.11 // tljQuery 1.9.1+\\n    * //cherne.net/brian/resources/jquery.hoverIntent.html\\n    *\\n    * You may use hoverIntent under the terms of the MIT license.\\n    * Copyright 2007, 2013 Brian Cherne\\n    */\\n   (function(e){e.fn.hoverIntent=function(t,n,r){var i={interval:100,sensitivity:7,timeout:0};if(typeof t==="object"){i=e.extend(i,t)}else if(e.isFunction(n)){i=e.extend(i,{over:t,out:n,selector:r})}else{i=e.extend(i,{over:t,out:t,selector:n})}var s,o,u,a;var f=function(e){s=e.pageX;o=e.pageY};var l=function(t,n){n.hoverIntent_t=clearTimeout(n.hoverIntent_t);if(Math.abs(u-s)+Math.abs(a-o)<i.sensitivity){e(n).off("mousemove.hoverIntent",f);n.hoverIntent_s=1;return i.over.apply(n,[t])}else{u=s;a=o;n.hoverIntent_t=setTimeout(function(){l(t,n)},i.interval)}};var c=function(e,t){t.hoverIntent_t=clearTimeout(t.hoverIntent_t);t.hoverIntent_s=0;return i.out.apply(t,[e])};var h=function(t){var n=tljQuery.extend({},t);var r=this;if(r.hoverIntent_t){r.hoverIntent_t=clearTimeout(r.hoverIntent_t)}if(t.type=="mouseenter"){u=n.pageX;a=n.pageY;e(r).on("mousemove.hoverIntent",f);if(r.hoverIntent_s!=1){r.hoverIntent_t=setTimeout(function(){l(n,r)},i.interval)}}else{e(r).off("mousemove.hoverIntent",f);if(r.hoverIntent_s==1){r.hoverIntent_t=setTimeout(function(){c(n,r)},i.timeout)}}};return this.on({"mouseenter.hoverIntent":h,"mouseleave.hoverIntent":h},i.selector)}})(tljQuery)\\n  }\\n  else if (jq_version.major >= 1 && jq_version.minor >= 5 && jq_version.point >= 1) {\\n   (function(e){e.fn.hoverIntent=function(t,n){var r={sensitivity:7,interval:100,timeout:0};r=e.extend(r,n?{over:t,out:n}:t);var i,s,o,u;var a=function(e){i=e.pageX;s=e.pageY};var f=function(t,n){n.hoverIntent_t=clearTimeout(n.hoverIntent_t);if(Math.abs(o-i)+Math.abs(u-s)<r.sensitivity){e(n).unbind("mousemove",a);n.hoverIntent_s=1;return r.over.apply(n,[t])}else{o=i;u=s;n.hoverIntent_t=setTimeout(function(){f(t,n)},r.interval)}};var l=function(e,t){t.hoverIntent_t=clearTimeout(t.hoverIntent_t);t.hoverIntent_s=0;return r.out.apply(t,[e])};var c=function(t){var n=tljQuery.extend({},t);var i=this;if(i.hoverIntent_t){i.hoverIntent_t=clearTimeout(i.hoverIntent_t)}if(t.type=="mouseenter"){o=n.pageX;u=n.pageY;e(i).bind("mousemove",a);if(i.hoverIntent_s!=1){i.hoverIntent_t=setTimeout(function(){f(n,i)},r.interval)}}else{e(i).unbind("mousemove",a);if(i.hoverIntent_s==1){i.hoverIntent_t=setTimeout(function(){l(n,i)},r.timeout)}}};return this.bind("mouseenter",c).bind("mouseleave",c)}})(tljQuery)\\n  }\\n  else { // assume at least 1.1.2\\n   (function(e){e.fn.hoverIntent=function(t,n){var r={sensitivity:7,interval:100,timeout:0};r=e.extend(r,n?{over:t,out:n}:t);var i,s,o,u;var a=function(e){i=e.pageX;s=e.pageY};var f=function(t,n){n.hoverIntent_t=clearTimeout(n.hoverIntent_t);if(Math.abs(o-i)+Math.abs(u-s)<r.sensitivity){e(n).unbind("mousemove",a);n.hoverIntent_s=1;return r.over.apply(n,[t])}else{o=i;u=s;n.hoverIntent_t=setTimeout(function(){f(t,n)},r.interval)}};var l=function(e,t){t.hoverIntent_t=clearTimeout(t.hoverIntent_t);t.hoverIntent_s=0;return r.out.apply(t,[e])};var c=function(t){var n=(t.type=="mouseover"?t.fromElement:t.toElement)||t.relatedTarget;while(n&&n!=this){try{n=n.parentNode}catch(t){n=this}}if(n==this){return false}var i=tljQuery.extend({},t);var s=this;if(s.hoverIntent_t){s.hoverIntent_t=clearTimeout(s.hoverIntent_t)}if(t.type=="mouseover"){o=i.pageX;u=i.pageY;e(s).bind("mousemove",a);if(s.hoverIntent_s!=1){s.hoverIntent_t=setTimeout(function(){f(i,s)},r.interval)}}else{e(s).unbind("mousemove",a);if(s.hoverIntent_s==1){s.hoverIntent_t=setTimeout(function(){l(i,s)},r.timeout)}}};return this.mouseover(c).mouseout(c)}})(tljQuery)\\n  }  \\n  \\n   // BEGIN TAG CONTENT\\n   // find the current tag\\n         var parsePlacementOptionsJSON = function () {\\n             var options = \\\'\\\'; /* keep CUSTOM_OPTIONS single quoted to avoid JSON escape issues */\\n             var parsedOptions;\\n             try {\\n                 parsedOptions = JSON.parse(options);\\n             }\\n             catch (e) {\\n                 parsedOptions = {};\\n             }\\n             return parsedOptions;\\n         };\\n         var placementOptions = parsePlacementOptionsJSON();\\n   var currentTag = document.getElementById(\\\'```ANALYTICS_ID```\\\');\\n   // the unit container is the script\\\'s parent\\n         var unit;\\n         if (placementOptions.unwrappedUnit) {\\n             // unwrapped units are units where the inline div is taken off the DOM\\n             // in these cases, the first child is considered to be the unit\\n             unit = tljQuery(currentTag).parent().children()[0];\\n         }\\n         else {\\n             unit = tljQuery(currentTag).parent().get(0);\\n         }\\n         var unitNumber = parseInt(\\\'```SCRIPT_NUMBER```\\\');\\n   // given the script and the unit, we can find the sponsored_content_tag_id,\\n   // and sponsored_content_image_id, respectively, as well as the referrer\\n   var tag_id = @@@UNIT_ID@@@;\\n   var image_id = @@@IMAGEID@@@;\\n   var third_party_sampling_rate = @@@THIRD_PARTY_SAMPLING_RATE@@@;\\n   var third_party_discrepancy_rate = @@@THIRD_PARTY_DISCREPANCY_RATE@@@;\\n   var inv_code = \\\'psmag_article_big\\\';\\n   // find the referrer and domain\\n   var ref = document.URL;\\n   var domain = parseUri(ref).host;\\n   // remove pixel after it has finished loading\\n   var removePixel = function(pixel, i) {\\n       i = i || 0;\\n       if(pixel.complete || i == 1000) {\\n           // remove the pixel\\n           document.body.removeChild(pixel);\\n       } else {\\n           setTimeout(function() {\\n               removePixel(pixel, i+1);\\n           }, 100); // wait a bit and try to remove the pixel again\\n       }\\n   };\\n         // set the analytics for the given unit\\n         // this shadows $unit, but is conceptually easier to understand than letting it hang out so far in scope\\n      var AnalyticsController = function ($unit) {\\n             var adnxs_auction_id = "%%%ADNXS_AUCTION_ID%%%";\\n             var adnxs_user_id = "%%%ADNXS_USER_ID%%%";\\n             // fireClick, fire a click event on the unit\\n             var fireClick = this.fireClick = function (e) {\\n                 var pix        = document.createElement(\\\'IMG\\\');\\n                 var query      = {};\\n                 query.cid      = 0;\\n                 query.id       = tag_id;\\n                 query.ii       = image_id;\\n                 query.inv_code = inv_code;\\n                 query.ref      = encodeURIComponent(ref);\\n                 query.domain   = encodeURIComponent(domain);\\n                 query.cb       = Math.floor(89999999*Math.random()+10000000);\\n                 query.aid      = adnxs_auction_id;\\n                 query.uid      = adnxs_user_id;\\n                 var src        = createUrl(protocol+"eb.3lift.com/scc", query);\\n                 pix.src        = src;\\n                 pix.width      = 0;\\n                 pix.height     = 0;\\n                 document.body.appendChild(pix);\\n                 removePixel(pix);\\n                 return src.split("eb.3lift.com");\\n             };\\n             //fireDuration, send the current amount of time the video has played\\n             var fireDuration = this.fireDuration = function (t) {\\n                 var pix        = document.createElement(\\\'IMG\\\');\\n                 var query      = {};\\n                 query.cid      = 0;\\n                 query.id       = tag_id;\\n                 query.ii       = image_id;\\n                 query.inv_code = inv_code;\\n                 query.ref      = encodeURIComponent(ref);\\n                 query.domain   = encodeURIComponent(domain);\\n                 query.cb       = Math.floor(89999999*Math.random()+10000000);\\n                 query.aid      = adnxs_auction_id;\\n                 query.uid      = adnxs_user_id;\\n                 query.duration = t;\\n                 var src        = createUrl(protocol+"eb.3lift.com/scvd", query);\\n                 pix.src        = src;\\n                 pix.width      = 0;\\n                 pix.height     = 0;\\n                 document.body.appendChild(pix);\\n                 removePixel(pix);\\n                 return src.split("eb.3lift.com");\\n             };\\n             // firePlay, fire a click event on the unit\\n             var firePlay= this.firePlay = function (e) {\\n                 var pix = document.createElement(\\\'IMG\\\');\\n                 var query = {};\\n                 query.cid = 0;\\n                 query.id = tag_id;\\n                 query.ii = image_id;\\n                 query.inv_code = inv_code;\\n                 query.ref = encodeURIComponent(ref);\\n                 query.domain = encodeURIComponent(domain);\\n                 query.cb = Math.floor(89999999*Math.random()+10000000);\\n                 query.aid = adnxs_auction_id;\\n                 query.uid = adnxs_user_id;\\n                 var src = createUrl(protocol+"eb.3lift.com/scvs", query);\\n                 pix.src = src;\\n                 pix.width = 0;\\n                 pix.height = 0;\\n                 document.body.appendChild(pix);\\n                 removePixel(pix);\\n                 return src.split("eb.3lift.com");\\n             };\\n             //fireCompletion, indicate a video has been completed\\n             var fireCompletion= this.fireCompletion = function (e) {\\n                 var pix        = document.createElement(\\\'IMG\\\');\\n                 var query      = {};\\n                 query.cid      = 0;\\n                 query.id       = tag_id;\\n                 query.ii       = image_id;\\n                 query.inv_code = inv_code;\\n                 query.ref      = encodeURIComponent(ref);\\n                 query.domain   = encodeURIComponent(domain);\\n                 query.cb       = Math.floor(89999999*Math.random()+10000000);\\n                 query.aid      = adnxs_auction_id;\\n                 query.uid      = adnxs_user_id;\\n                 var src        = createUrl(protocol+"eb.3lift.com/scvc", query);\\n                 pix.src        = src;\\n                 pix.width      = 0;\\n                 pix.height     = 0;\\n                 document.body.appendChild(pix);\\n                 removePixel(pix);\\n                 return src.split("eb.3lift.com");\\n             }\\n             var fireShare = this.fireShare = function (share_type) {\\n                 if (this.event && this.event.stopPropagation) {\\n                     this.event.stopPropagation(); // TODO: CHECK THAT THIS IS BROWSER SAFE: 5/16/2014: It is for IE >= 9, but this is coded defensively enough to not break 8 and 7\\n                 } \\n                 var pix        = document.createElement(\\\'IMG\\\');\\n                 var query      = {};\\n                 query.cid      = 0;\\n                 query.id       = tag_id;\\n                 query.ii       = image_id;\\n                 query.inv_code = inv_code;\\n                 query.ref      = encodeURIComponent(ref);\\n                 query.domain   = encodeURIComponent(domain);\\n                 query.st       = share_type;\\n                 query.cb       = Math.floor(89999999*Math.random()+10000000);\\n                 query.aid      = adnxs_auction_id;\\n                 query.uid      = adnxs_user_id;\\n                 var src        = createUrl(protocol+"eb.3lift.com/scs", query);\\n                 pix.src        = src;\\n                 pix.width      = 0;\\n                 pix.height     = 0;\\n                 document.body.appendChild(pix);\\n                 removePixel(pix);\\n                 return src.split("eb.3lift.com");\\n             };\\n             // we publish a reference to fireShare, so that its available to the share buttons to use later on click events\\n             // we don\\\'t have to worry about wrapping ts in a function that checks for analytics off, because the buttons won\\\'t appear when that is the case\\n             ts = fireShare;\\n             var fireHover = this.fireHover = function (e) {\\n                 var pix        = document.createElement(\\\'IMG\\\');\\n                 var query      = {};\\n                 query.cid      = 0; //campaign_id\\n                 query.id       = tag_id;\\n                 query.ii       = image_id;\\n                 query.inv_code = inv_code;\\n                 query.ref      = encodeURIComponent(ref);\\n                 query.domain   = encodeURIComponent(domain);\\n                 query.cb       = Math.floor(89999999*Math.random()+10000000);\\n                 query.aid      = adnxs_auction_id;\\n                 query.uid      = adnxs_user_id;\\n                 var src        = createUrl(protocol+"eb.3lift.com/scm", query);\\n                 pix.src        = src;\\n                 pix.width      = 0;\\n                 pix.height     = 0;\\n                 document.body.appendChild(pix);\\n                 removePixel(pix);\\n                 toggleShareButton(\\\'on\\\');\\n                 return src.split("eb.3lift.com");\\n             };\\n             this.imp = function (sr) {\\n                 var pix        = document.createElement(\\\'IMG\\\');\\n                 var query      = {};\\n                 query.cid      = 0;\\n                 query.id       = tag_id;\\n                 query.ii       = image_id;\\n                 query.sr       = sr;\\n                 query.tpsr     = third_party_sampling_rate;\\n                 query.tpdr     = third_party_discrepancy_rate;\\n                 query.inv_code = inv_code;\\n                 query.ref      = encodeURIComponent(ref);\\n                 query.domain   = encodeURIComponent(domain);\\n                 query.cb       = Math.floor(89999999*Math.random()+10000000);\\n                 query.aid      = adnxs_auction_id;\\n                 query.uid      = adnxs_user_id;\\n                 var src        = createUrl(protocol+"eb.3lift.com/sci", query);\\n                 pix.src        = src;\\n                 pix.width      = 0;\\n                 pix.height     = 0;\\n                 document.body.appendChild(pix);\\n                 removePixel(pix);\\n                 return src.split("eb.3lift.com");\\n             };\\n             this.click = function (e) {\\n                 if (!this.analyticsOff) {\\n                     if (e.target && e.target.tagName && (e.target.tagName.toLowerCase() != \\\'a\\\')) {\\n                         window.open(\\\'%%%CLICKTHROUGH_URL%%%\\\',\\\'_blank\\\');\\n                         // ensure that under no circumstance two windows open\\n                         e.stopPropagation();\\n                         e.preventDefault();\\n                     }\\n                     this.fireClick(e);\\n                 }\\n             };\\n             this.share = function (share_type) {\\n                 if (!this.analyticsOff) {\\n                     this.fireShare(share_type);\\n                 }\\n             };\\n             this.hover = function (e) {\\n                 if (!this.analyticsOff) {\\n                     this.fireHover(e);\\n                 }\\n             };\\n             this.analyticsOff = false;\\n             // set click handler\\n             var that = this;\\n             $unit.click(function(e) { that.click(e);});\\n         };\\n \\n         AnalyticsController.prototype.setAdnxsPix = function () {\\n             var adnxsPix = "%%%ADNXSPIX%%%";\\n             var pixEvent = "%%%ADNXS_PIX_EVENT%%%";\\n             var that     = this;\\n             \\n             var fireAdnxsPix = function () {\\n                 var adnxsPixel = document.createElement(\\\'IMG\\\');\\n                 adnxsPixel.style.display = "none";\\n                 adnxsPixel.width = 0;\\n                 adnxsPixel.height = 0;\\n                 adnxsPixel.src = adnxsPix;\\n                 document.body.appendChild(adnxsPixel);\\n             };\\n \\n             var clobber = function (methodName) {\\n                 var oldEvent = that[methodName];\\n                 that[methodName] = function (e) {\\n                     fireAdnxsPix();\\n                     oldEvent.call(this,e);\\n                 };\\n             };\\n \\n             if (adnxsPix.length) {\\n                 if (pixEvent === "click") {\\n                     clobber("fireClick");\\n                 }\\n                 else if (pixEvent === "video_start") {\\n                     clobber("firePlay");\\n                 }\\n                 else if (pixEvent === "video_completion") {\\n                     clobber("fireCompletion");\\n                 }\\n                 this.adnxsPixData = { adnxsPix:adnxsPix, pixEvent: pixEvent };\\n             }\\n         };\\n \\n         // until we switch over to eb2, we mirror eb traffic by wrapping the click,\\n         // mouseover, impression, share, video start, video n seconds, and video completion\\n         // calls in a function that also calls eb2\\n         AnalyticsController.prototype.getEndPointList = function () {\\n             return ["fireClick","fireShare","firePlay","firePlay","fireCompletion","fireHover","imp"];\\n         };\\n         AnalyticsController.prototype.setUpEB2Calls = function () {\\n             var endPointList  = this.getEndPointList();\\n             var that          = this;\\n             var clobberForEB2 = function (callName) {\\n                 var call = that[callName];\\n                 var newCall = function (e) {\\n                     var pathAndQS = call(e)[1];\\n                     var i         = document.createElement(\\\'IMG\\\');\\n                     i.src         = "//eb2.3lift.com"+pathAndQS;\\n                     i.display     = "none";\\n                     i.width       = 0;\\n                     i.height      = 0;\\n                     document.body.appendChild(i);\\n                     removePixel(i);\\n                 };\\n                 that[callName] = newCall;\\n             };\\n                 \\n             endPointList.forEach(function (callName) {\\n                 clobberForEB2(callName);\\n             });\\n         };\\n \\n         var analyticsController = new AnalyticsController(tljQuery(unit));\\n         // setUPEB2Calls Must Be Called First, before the original EB1 calls are clobbered\\n         analyticsController.setUpEB2Calls();\\n         analyticsController.setAdnxsPix();\\n   \\n   // share logic\\n         var toggleCreator = function (shareButtons) {\\n             var disabled = false;\\n             return function  (el) {\\n                 if (el === \\\'disable\\\') {\\n                     disabled = true;\\n                     return;\\n                 }\\n                 else if (disabled) {\\n                     return;\\n                 }\\n     else if (el == \\\'off\\\' && (navigator.userAgent.match("MSIE 7.0") || (tljQuery(".tl_share_button:hover").length == 0))) { //waxoff\\n                     shareButtons.off();\\n     }\\n     else {\\n      shareButtons.on();\\n     }\\n    };\\n   };\\n \\n   var ShareButtons = function ($unit,analyticsController) {\\n             var parseUrl = function (sUrl) {\\n                 try {\\n                     var url = sUrl.split(\\\'(\\\')[1].split(\\\')\\\')[0];\\n                     if (url.match(\\\'"\\\')) {\\n                         url = url.split(\\\'"\\\')[1];\\n                     }\\n                     return url;\\n                 }\\n                 catch (e) {\\n                     return false;\\n                 }\\n             };\\n             var getSafeBackgroundImage = function (el) {\\n                 var cs = window.getComputedStyle(el);\\n                 if (cs[\\\'background-image\\\']) {\\n                     return cs[\\\'background-image\\\'];\\n                 }\\n                 if (cs.backgroundImage) {\\n                     return cs.backgroundImage;\\n                 }\\n                 return false;\\n             };\\n             var createLoadListener = function (el) {\\n                 return function (cb) {\\n                     var i = document.createElement(\\\'IMG\\\');\\n                     i.width = 0;\\n                     i.height = 0;\\n                     i.style.display = "none";\\n                     i.src = parseUrl(getSafeBackgroundImage(el));\\n                     var $i = tljQuery(i);\\n                     var that = this;\\n                     $i.load(function () {\\n                         cb();\\n                     });\\n                     document.body.appendChild(i);\\n                 };\\n             };\\n             this.analyticsController = analyticsController;\\n             var that = this;\\n    this.$referenceImage = (function () {\\n     var $ri;\\n     $unit.find(\\\'img\\\').each(function (index,child) {\\n      if (child.src.match("img.3lift.com") && !child.className.match("tl_secondary")) {\\n       $ri = tljQuery(child);\\n      }\\n     });\\n                 // sometimes the image is not in a tag, but is a css attribute\\n                 if (!$ri) {\\n                     $unit.find(\\\'*\\\').each(function () {\\n                         if (getSafeBackgroundImage(this) && getSafeBackgroundImage(this).match("img.3lift.com")) {\\n                             that.listenForLoad = createLoadListener(this); \\n                             $ri = tljQuery(this);\\n                             $ri.isDiv = true;\\n                         }\\n                     });\\n                 }\\n     return $ri;\\n    })();\\n    this.share_buttons = [];\\n             this.set_share_dimensions = function () {\\n     // since we control the buttons, we can make some assumptions about them\\n     var buttonAssumptions = {width:100, height:48,ar:100/48};\\n     var shareButtonCount = tljQuery(unit).find(".tl_share").length;\\n     if (shareButtonCount < 3) {\\n      shareButtonCount = 3;\\n     }\\n     this.shareButtonCount = shareButtonCount;\\n     var w,h;\\n                 this.adUrl = parseUri(this.$referenceImage[0].src);\\n                 var adQs = this.adUrl.queryKey;\\n                 this.adQs = adQs;\\n                 //intuitively, we want to check if $referenceImage.width and height return something greater than 0\\n                 // however, both ff and ie will return a non zero value lower than the actual image dimensions, while the image is loading\\n                 // so we have to check against a value higher than 0--we use 50, which is somewhat arbitary, smaller than all our placements, but higher than what ff and ie return when they give incorrect values\\n                 if (this.$referenceImage.width() > 50 && this.$referenceImage.height() > 50) {\\n                     w = this.w = this.$referenceImage.width();\\n                     h = this.h = this.$referenceImage.height();\\n                 }\\n                 else {\\n                     w = adQs.width;\\n                     h = adQs.height;\\n                     this.w = parseInt(w);\\n                     this.h = parseInt(h);\\n                 }\\n     var shareButtonDimensions = (function () {\\n      // vertical alignment\\n                     var MaxButtonWidth = 70;\\n                     var MaxButtonHeight = 34;\\n      var verticalShareHeight = Math.round((h/2)/shareButtonCount);\\n      if (verticalShareHeight > MaxButtonHeight) {\\n       verticalShareHeight = MaxButtonHeight;\\n      }\\n      var verticalShareWidth = Math.round(verticalShareHeight * buttonAssumptions.ar);\\n      var verticalArea = verticalShareWidth * verticalShareWidth;\\n      // horizontal alignment\\n      var horizontalShareWidth = Math.round((w/2)/shareButtonCount);\\n      if (horizontalShareWidth > MaxButtonWidth) {\\n       horizontalShareWidth = MaxButtonWidth;\\n      }\\n      var horizontalShareHeight = Math.round((1/buttonAssumptions.ar)*horizontalShareWidth);\\n      var horizontalArea = horizontalShareWidth * horizontalShareHeight;\\n      if (horizontalArea <= verticalArea) {\\n       return {\\n        width:horizontalShareWidth,\\n        height:horizontalShareHeight,\\n        alignment: 0\\n       };\\n      }\\n      else {\\n       return {\\n        width:verticalShareWidth,\\n        height:verticalShareHeight,\\n        alignment:1\\n       };\\n      }\\n     })();\\n     if (shareButtonDimensions.alignment === 0) {\\n      this.horizontalAligment = true;\\n      this.shareWidth  = shareButtonDimensions.width;\\n     }\\n     else {\\n      this.verticalAlignment = true;\\n      this.shareHeight = shareButtonDimensions.height;\\n     }\\n     this.sbh = shareButtonDimensions.height;\\n     this.sbw = shareButtonDimensions.width;     \\n             };\\n    // if there is no referenceImage -- ie we cannot find the ad, don\\\'t append sharebuttons\\n             // we also don\\\'t append the share buttons if we are on a mobile device\\n             // this is so that users click through correctly on the first attempt\\n             // rather than seeing share buttons\\n             if (this.$referenceImage && !isMobile()) {\\n     this.set_share_dimensions();\\n                 this.initShareButtons();\\n    }\\n   };\\n \\n         ShareButtons.prototype.alignPinBeforeFacebook = function () {\\n             var that = this;\\n    this.share_buttons.sort(function (a,b) {\\n     if (that.verticalAlignment) {\\n      if (that.sharingZone.match("S")) {\\n       if (isFb(a) && isPin(b)) {\\n        return 1;\\n       }\\n       if (isPin(a) && isFb(b)) {\\n        return 0;\\n       }\\n       if (isFb(a) || isPin(a)) {\\n        return 1;\\n       }\\n       return 0;\\n      }\\n      else {\\n       if (isPin(a) && isFb(b)) {\\n        return 1;\\n       }\\n       if (isFb(a) && isPin(b)) {\\n        return 0;\\n       }\\n       if (isFb(a) || isPin(a)) {\\n        return -1;\\n       }\\n       return 0;\\n      }\\n     }\\n     else {\\n      if (that.sharingZone.match("E")) {\\n       if (isFb(a) && isPin(b)) {\\n        return 1;\\n       }\\n       if (isPin(a) && isFb(b)) {\\n        return 0;\\n       }\\n       if (isFb(a) || isPin(a)) {\\n        return 1;\\n       }\\n       return 0;\\n      }\\n      else {\\n       if (isPin(a) && isFb(b)) {\\n        return 1;\\n       }\\n       if (isFb(a) && isPin(b)) {\\n        return 0;\\n       }\\n       if (isFb(a) || isPin(a)) {\\n        return -1;\\n       }\\n       return 0;\\n      }\\n     }\\n    });\\n         };\\n         ShareButtons.prototype.getShareZone = function () {\\n             /****************************************************************************************\\n              *  getShareZone returns the appropiate place to render the share buttons\\n              *  the default, which is returned if no optimal position is found, is NE,\\n              *  when reading the code, it might not be immediately clear why the first element\\n              *  of sharingZones (an array of acceptable corners to render the share buttons)\\n              *  isn\\\'t simply returned.  This is because we don\\\'t want to return a zone that is adjacent to \\n              *  an excluded zone, if we can help it.  Since there are only 4 corners to a given image, we can \\n              *  check manually if a given candidate corner is adjacent to an excluded corner, and try to filter it.\\n              *  This is not always sucessfully, if there is no better corner (ie one not adjacent to an exclude zone)\\n              *  then it might be the case that the sub-optimal corner is returned.\\n              *  ******************************************************************************************************/\\n             if (this.lpSet) {\\n                 return this.sharingZone;\\n             }\\n             var logoBlackList = this.adQs.logo_exclude || \\\'\\\';\\n \\n             var sharingZones = [];\\n             var excludeZones = [];\\n             if (this.$referenceImage.attr(\\\'lp\\\')) {\\n                 logoBlackList += this.$referenceImage.attr(\\\'lp\\\');\\n                 this.lpSet = true;\\n             }\\n             var corners = ["NW","NE","SW","SE"];\\n             var sharingZone;\\n             corners.forEach(function (corner) {\\n                 if (!logoBlackList || (logoBlackList.indexOf(corner) < 0)) {\\n                     sharingZones.push(corner);\\n                 }\\n                 else { \\n                     excludeZones.push(corner);\\n                 }\\n             });\\n             if (sharingZones.length) {\\n                 var en = function (k) { \\n                     if (sharingZones.indexOf(k) >= 0) { \\n                         return true;\\n                     }\\n                     return false;\\n                 };\\n                 var that = this;\\n                 var setSZ = function (op1,op2,op3) {\\n                     if (en(op1)) {\\n                         sharingZone = op1;\\n                     }\\n                     else if (en(op2)) {\\n                         sharingZone = op2;\\n                     }\\n                     else if (en(op3)) {\\n                         sharingZone = op3;\\n                     }\\n                 };\\n                 sharingZone = sharingZones[0]; // default\\n                 excludeZones.forEach(function(ez) {\\n                     switch (ez) {\\n                         case "NW":\\n                             setSZ("SE","SW","NE");\\n                             break;\\n                         case "NE":\\n                             setSZ("SW","SE","NW");\\n                             break;\\n                         case "SW":\\n                             setSZ("NE","NW","SE");\\n                             break;\\n                         case "SE":\\n                             setSZ("NW","NE","SW");\\n                             break;\\n                     }\\n                 });\\n             }\\n             else { // default\\n                 sharingZone = \\\'NE\\\';\\n             }\\n             return sharingZone;\\n         };\\n \\n   ShareButtons.prototype.initShareButtons = function () {\\n             // IMPORTANT: This Should only be called once per instance of ShareButtons\\n             // otherwise the click listeners will be registered more than once\\n             this.sharingZone = this.getShareZone();\\n             var that = this;\\n    tljQuery(unit).find(\\\'.tl_share\\\').each(function (index, $child) {\\n     var share_button = document.createElement(\\\'IMG\\\');\\n                 var $share_button = tljQuery(share_button);\\n     share_button.className = "tl_share_button";\\n     $share_button.style("display","none");\\n     $share_button.style("position","absolute");\\n     $share_button.style("cursor","pointer");\\n     $share_button.style("outline","none");\\n     var zi;\\n     var rzi = that.$referenceImage.css(\\\'zIndex\\\');\\n     if (rzi && rzi !== \\\'auto\\\' && parseInt(rzi)) {\\n      zi = rzi;\\n     }\\n     else {\\n      zi = 9999;\\n     }\\n                 safeSetZindex(zi,null,$share_button,\\\'\\\');\\n     share_button.setAttribute(\\\'onclick\\\', $child.getAttribute(\\\'onclick\\\'));\\n     if ($child.getAttribute(\\\'data-button\\\')) {\\n      share_button.src = "//img.3lift.com/?url="+encodeURIComponent($child.getAttribute(\\\'data-button\\\'))+"&alt=box&color=none&width="+that.shareWidth+"&height="+that.shareHeight;\\n     }\\n     // preserve this for backwards compatability\\n     else if(share_button.getAttribute(\\\'onclick\\\').match(\\\'facebook\\\')) {\\n      share_button.src = "//images.adpinr.com/shareit.png";\\n     }\\n     else {\\n      share_button.src = "//images.adpinr.com/reserved/pinit.png";   \\n     }\\n     that.$referenceImage.offsetParent().append(share_button);\\n     that.share_buttons.push(share_button);\\n    });\\n             this.alignPinBeforeFacebook();\\n   };\\n         var filterForShareButtons = function (jqChildren) {\\n             var sb = [];\\n             jqChildren.each(function (i,e) {\\n                 if (tljQuery(e).hasClass("tl_share_button")) {\\n                     sb.push(e);\\n                 }\\n             });\\n             return sb;\\n         };\\n \\n   ShareButtons.prototype.on = function () {\\n             if (this.analyticsController.analyticsOff) {\\n                 return;\\n             }\\n             this.set_share_dimensions();\\n             this.sharingZone = this.getShareZone();\\n             this.alignPinBeforeFacebook();\\n    var that = this;\\n             var testShareButton = tljQuery(this.share_buttons[0]);\\n    var refPos = this.$referenceImage.position();\\n    this.w = this.$referenceImage.width();\\n             this.h = this.$referenceImage.height();\\n             this.xoff = refPos.left;\\n    this.yoff = refPos.top; \\n    var xoff = this.xoff;\\n    var yoff = this.yoff\\n    // pad ensures there is enough room to comfortably fit all the share buttons\\n    var pad = this.shareButtonCount-1;\\n    var sbc = this.shareButtonCount;\\n    if (this.sharingZone === \\\'NW\\\') {\\n     xoff += 10;\\n     yoff += 10;\\n    }\\n    else if (this.sharingZone === "NE") {\\n     xoff += this.w;\\n     yoff += 10;\\n    }\\n    else if (this.sharingZone === \\\'SE\\\') {\\n     xoff += this.w-10;\\n     yoff += this.h-10;\\n    }\\n    else if (this.sharingZone === \\\'SW\\\') {\\n     xoff += 10;\\n     yoff += this.h;\\n    }\\n    this.share_buttons.forEach(function (share_button) {\\n                 var $share_button = tljQuery(share_button);\\n                 $share_button.style("width",that.sbw+"px","important");\\n                 $share_button.style("height",that.sbh+"px","important");\\n                 $share_button.style("min-width","0","important");\\n                 $share_button.style("min-height","0","important");\\n                 if (that.verticalAlignment) {\\n      if ((that.sharingZone === \\\'SW\\\') || (that.sharingZone === \\\'SE\\\')) {\\n       yoff -= (that.sbh+10);\\n       //share_button.style.top = yoff + "px";\\n          $share_button.style("top",yoff+"px","important"); \\n                         yoff -= 10;\\n      }\\n      else {\\n                         $share_button.style("top",yoff+"px","important");\\n       //share_button.style.top = yoff + "px";\\n       yoff += that.sbh + 10;\\n      }\\n      if ((that.sharingZone === \\\'NE\\\') || (that.sharingZone === \\\'SE\\\')) {\\n                         $share_button.style("left",(xoff-that.sbw) + "px","important");\\n      }\\n      else {\\n       $share_button.style("left",(xoff)+"px","important");\\n      }\\n     }\\n     else {\\n      if ((that.sharingZone === \\\'NE\\\') || (that.sharingZone === \\\'SE\\\')) {\\n       xoff -= that.sbw;\\n       $share_button.style("left",xoff + "px","important");\\n       xoff -= 10;\\n      }\\n      else {\\n       $share_button.style("left",xoff + "px","important");\\n       xoff += that.sbw+10;\\n      }\\n      if ((that.sharingZone === \\\'SE\\\') || (that.sharingZone == \\\'SW\\\')) {\\n       $share_button.style("top",(yoff-that.sbh)+"px","important");\\n      }\\n      else {\\n       $share_button.style("top",yoff+"px","important");\\n      }\\n     }\\n     $share_button.style("display","block","important");\\n    });\\n   };\\n \\n   ShareButtons.prototype.off = function () {\\n    this.share_buttons.forEach(function (share_button) {\\n     tljQuery(share_button).style("display","none","important");\\n    });\\n   };\\n \\n   ShareButtons.prototype.getBox = function () {\\n    // get the approximate box defined by the ad unit\\n    var $ad = tljQuery(tljQuery(unit).children()[0]);\\n    var pos = $ad.offset();\\n    return {\\n     x1: pos.left,\\n     y1: pos.top,\\n     x2: pos.left + $ad.width(),\\n     y2: pos.top + $ad.height()\\n    };\\n   };\\n \\n         var shareButtons;\\n   shareButtons = new ShareButtons(tljQuery(unit),analyticsController);\\n         // for mobile users, we create an empty toggler\\n         // this is part of fix for their click through issues\\n         var toggleShareButton,\\n             decorateOffChecker,\\n             offChecker\\n         ;\\n         if (!isMobile()) {\\n             toggleShareButton = toggleCreator(shareButtons);\\n             \\n             decorateOffChecker = function  (shareButtons,toggler,video) {\\n                 return function (e) {\\n                     var box;\\n \\n                     if (shareButtons) {\\n                         box = shareButtons.getBox();\\n                     }\\n                     else {\\n                         box = video.getBox();\\n                     }\\n                     if (((e.pageX) < box.x1) || ((e.pageX) > box.x2) || ((e.pageY) < box.y1) || ((e.pageY) > box.y2)) {\\n                         toggler(\\\'off\\\');\\n                         return true;\\n                     }\\n                     return false;\\n                 };\\n             };\\n \\n             offChecker = decorateOffChecker(shareButtons,toggleShareButton);\\n         }\\n         else {\\n             toggleShareButton = function () {};\\n             offChecker = function () {};\\n         }\\n         // VIDEO\\n         var VideoFetcher = function ($unit, analyticsController, shareToggler, configuration) {\\n             this.getAnalyticsController = function () { return analyticsController; };\\n             this.getUnit = function () { return $unit; };\\n             this.getShareToggler = function () { return shareToggler; };\\n             this.getConfiguration = function () { return configuration; };\\n             this.disableAnalyticsAndSharing();\\n             this.getTlImg = function () {\\n                 return configuration.$referenceImage[0];\\n             };\\n             this.isInit = false;\\n             this.clickRegistered = false;\\n             this.clicked = false;\\n             this.inPlay = false;\\n             this.playState = false;\\n             this.cursor = {notSet:true};\\n         };\\n \\n         // VideoFetcher.lazyLoadPlayerHookData\\n         // loads in data about the player hook; its size, its position on the DOM, etc\\n         VideoFetcher.prototype.lazyLoadPlayerHookData = function () {\\n             // the player hook is an iframe of the correct dimensions, positioned in the correct place\\n             var playerHookData = this.findPlayerHook();\\n             var playerWidth = playerHookData.width;\\n             var playerHeight = playerHookData.height;\\n             var playerHook = playerHookData.hook;\\n             var outterParent = playerHookData.outterParent;\\n             this.getPlayerHookData = function () { return playerHookData; };\\n         };\\n \\n         // VideoFetcher.prototype.lazyLoadWrappedPlayer\\n         // creates a div inside of which the player will be loaded\\n         // expects this.lazyLoadPlayerHookData to already have been called\\n         VideoFetcher.prototype.lazyLoadWrappedPlayer = function () {\\n             var playerHookData = this.getPlayerHookData();\\n             var wrappedPlayerInfo = this.createWrappedPlayer(playerHookData.width,playerHookData.height);\\n             this.getWrappedPlayerInfo = function () { return wrappedPlayerInfo; };\\n         };\\n         \\n         // make sure there\\\'s enough space to accomodate the button bar\\n         VideoFetcher.prototype.adjustDimensions = function (w,h) {\\n             var configuration = this.getConfiguration();\\n             if (configuration && (configuration.playerSettings.buttonBar || configuration.playerSettings.buttonBarMobile)) {\\n                 this.determineButtonBarDimensions();\\n                 h = h-this.buttonBarDimensions.height;\\n             }\\n             return {h:h,w:w};\\n         };\\n \\n         // VideoFetcher.lazyLoad\\n         // VideoFetcher.lazyLoadVideoInfo\\n         // to keep the constructor more static, we only load in information about the video \\n         // when we need it\\n         VideoFetcher.prototype.lazyLoadVideoInfo = function () {\\n             var $videoSpec = this.getVideoSpec();\\n             var type = $videoSpec.attr(\\\'tl-vid-type\\\');\\n             var id = $videoSpec.attr(\\\'tl-vid-id\\\');\\n             this.videoID = id;\\n             this.getPlayerType = function () { return type; };\\n             this.getVideoId = function () { return id; };\\n         };\\n \\n         VideoFetcher.prototype.disableAnalyticsAndSharing = function () { \\n             var analyticsController = this.getAnalyticsController();\\n             var shareToggler = this.getShareToggler();\\n             analyticsController.analyticsOff = true; // the videoFetcher controls its own analytics pixels\\n             shareToggler(\\\'disable\\\'); //turn off permanently\\n         };\\n         // GetVideoSpec:\\n         // finds a div on the unit that contains information related to video\\n         // in particular, this div specifies the player type and video id\\n         // if the div is not present, this function throws an error, which will be caught and sent as an eb pixel\\n         // otherwise it returns the div as a jquery object\\n         VideoFetcher.prototype.getVideoSpec = function () {\\n             var $unit = this.getUnit();\\n             var videoSpec = $unit.find(\\\'.tl-vid\\\');\\n             var $videoSpec;\\n             if (videoSpec) {\\n                 $videoSpec = tljQuery(videoSpec);\\n             }\\n             else {\\n                 throw new Error(\\\'could not find video info\\\');\\n             }\\n             return $videoSpec;\\n         };\\n \\n \\n \\n         VideoFetcher.prototype.setClassProperties = function () {\\n             if (!this.styleSet) {\\n                 var x = document.createElement(\\\'STYLE\\\');\\n                 x.textContent = \\\'.triplelift_progress_element::-webkit-progress-value { background: white; }\\\';\\n                 x.textContent += \\\'.triplelift_progress_element::-moz-progress-bar { background: white; }\\\';\\n                 // IE\\n                 x.textContent += \\\'.triplelift_progress_div { width:100%; height:100%; position: relative; background-color:whiteSmoke; }\\\';\\n                 x.textContent += \\\'.triplelift_progress_div > span { text-indent: -9999px; background-color:blue; display:block; border-radius:2px;}\\\';\\n                 document.body.appendChild(x);\\n                 this.styleSet = true;\\n             }\\n         };\\n \\n         VideoFetcher.prototype.styleProgressBar = function (pb) {\\n             this.setClassProperties();\\n             var tlImg = this.getTlImg();\\n             var $tlImg = tljQuery(tlImg);\\n             var pos = $tlImg.position();\\n             pb.className = "triplelift_progress_element";\\n             pb.style.position = "absolute";\\n             pb.style.top = pos.top;\\n             pb.style.left = pos.left;\\n             pb.style.opacity = 0.6;\\n             safeSetZindex(this.ZI_LEVEL_0,pb);\\n             pb.style.width = Math.round($tlImg.width()) + "px";\\n             pb.style.height = "10px";\\n             pb.style[\\\'-webkit-appearance\\\'] = \\\'none\\\';\\n         };\\n \\n         // only IE10+ supports the PROGRESS element\\n         // a common way to emulate is to append a div containing a span insided the progresss element\\n         // and manipulate the span as the progress of the bar\\n         // mondern browsers will ignore whatever is contained in a progress element\\n         // so this is safe\\n         VideoFetcher.prototype.createIESafeProgress = function (pb) {\\n             var d = document.createElement(\\\'DIV\\\');\\n             d.className = "triplelift_progress_div";\\n             var s = document.createElement(\\\'SPAN\\\');\\n             s.className = "triplelift_progress_span";\\n             d.appendChild(s);\\n             s.style.width = "0%";\\n             s.textContent = "1000000";\\n             pb.appendChild(d);\\n         };\\n \\n         VideoFetcher.prototype.setProgressBar = function (cb) {\\n             var pb = document.createElement(\\\'PROGRESS\\\');\\n             this.createIESafeProgress(pb);\\n             this.styleProgressBar(pb);\\n             tlImg.parentNode.insertBefore(pb,tlImg);\\n             this.monitorProgress(pb,cb);\\n         };\\n \\n         VideoFetcher.prototype.monitorProgress = function (pb,cb) {\\n             //  increment the progress bar for as long as the mouse is hovered over the unit\\n             //  otherwise remove the bar from the unit\\n             //  if the progress bar completes call the cb\\n \\n             this.progressBar = new ProgressBar(this,pb,cb);\\n             this.progressBar.startMonitor();\\n \\n         };\\n \\n         VideoFetcher.prototype.setCursor = function (e) {\\n             this.cursor.pageX = e.pageX;\\n             this.cursor.pageY = e.pageY;\\n             this.cursor.notSet = false;\\n         };\\n \\n         VideoFetcher.prototype.getBox = function () {\\n             var wrappedPlayerInfo = this.getWrappedPlayerInfo();\\n             var wrappedPlayer = wrappedPlayerInfo.wrappedPlayer;\\n             var $wrappedPlayer = tljQuery(wrappedPlayer);\\n             var wrappedPlayerBox = {};\\n             var wpo = $wrappedPlayer.offset();\\n             wrappedPlayerBox.x1 = wpo.left;\\n             wrappedPlayerBox.y1 = wpo.top;\\n             wrappedPlayerBox.x2 = wpo.left+$wrappedPlayer.width();\\n             wrappedPlayerBox.y2 = wpo.top+$wrappedPlayer.height();\\n             return wrappedPlayerBox;\\n         };\\n \\n         // we inline a little logic here\\n         // to determine what the seemore button should look like\\n         var altSeeMore = \\\'%%%ALT_SEE_MORE%%%\\\';\\n         if (altSeeMore === \\\'0\\\') {\\n             altSeeMore = false;\\n         };\\n \\n         VideoFetcher.prototype.assets = {\\n             clickthrough:\\n             "http://images.3lift.com/3127258.png",\\n             close: "http://images.3lift.com/3127259.png",\\n             facebook: "http://images.3lift.com/3127260.png",\\n             pinterest: "http://images.3lift.com/3127261.png",\\n             play: "http://images.3lift.com/3127262.png",\\n             share: "http://images.3lift.com/3127263.png",\\n             tumblr: "http://images.3lift.com/3127264.png",\\n             twitter: "http://images.3lift.com/3127265.png",\\n             safeGradient: "http://img.3lift.com/?width=200&height=100&url=http%3A%2F%2Fimages.3lift.com%2F3129001.png",\\n             gradient: "http://images.3lift.com/3129001.png",\\n             xbutton: "http://images.3lift.com/3129012.png",\\n             seemore: altSeeMore || "http://images.3lift.com/3129101.png",\\n             whiteplaybutton: "http://images.3lift.com/3129104.png"\\n         };\\n         // style the main play button\\n         VideoFetcher.prototype.stylePlayButton = function ($pb, playButtonInfo) {\\n             safeSetZindex(this.ZI_LEVEL_0,null,$pb,\\\'\\\');\\n             $pb.style("display","none","important");\\n             $pb.style("position","absolute","important");\\n             $pb.style("width",playButtonInfo.width+"px","important");\\n             $pb.style("height",playButtonInfo.height+"px","important");\\n             $pb.style("left",playButtonInfo.x+"px","important");\\n             $pb.style("top",playButtonInfo.y+"px","important");\\n             $pb.style("border","none","important");\\n             $pb.style("background","none","important");\\n         };\\n \\n         VideoFetcher.prototype.setPrePlay = function () {\\n             var config = this.getConfiguration();\\n             var playerHookData = this.getPlayerHookData();\\n             var hook = playerHookData.hook;\\n             var $hook = tljQuery(hook);\\n             var size = this.getImageSize();\\n             var playButton = document.createElement(\\\'IMG\\\');\\n             playButton.src = this.assets.whiteplaybutton;\\n             var playButtonInfo = this.getPlayButtonInfo(size,$hook);\\n             var $pb = this.pb = tljQuery(playButton);\\n             gaurd($pb);\\n             this.stylePlayButton($pb,playButtonInfo);\\n             hook.appendChild(playButton);\\n             var toggler = function (msg) {\\n                 if (msg === "on") {\\n                     //$hook.style("opacity",0.3,"important");\\n                     $pb.style("display","","important");\\n                 }\\n                 else if (msg == "off") {\\n                    // $hook.style("opacity",1,"important");\\n                     $pb.style("display","none","important");\\n                 }\\n                 else {\\n                     throw new Error("setPrePlay Toggler Called with unkown message");\\n                 }\\n             };\\n \\n             var offchecker; \\n             var that = this;\\n             if (config.playButtonSettings.showOnHover) {\\n                 offchecker = decorateOffChecker(null,toggler,this);\\n                 $hook.on(\\\'mouseover\\\',function () { \\n                     if (!that.inPlay && !that.playState) {\\n                         toggler("on"); \\n                     }\\n                 });\\n                 $hook.on(\\\'mouseout\\\', function (e) { offchecker(e); });\\n             }\\n             else {\\n                 toggler(\\\'on\\\');\\n             }\\n             //turns off the play button on click\\n             this.preHoverOff = function ()  { toggler("off"); };\\n             //turns on the play button on click\\n             this.resetPlayButton = function () { \\n                 if (this.videoToggler && this.videoToggler.getToggleState() === this.videoToggler.PLAYING) {\\n                     return;\\n                 }\\n                 toggler("on"); };\\n         };\\n \\n         VideoFetcher.prototype.getPlayButtonInfo = function (size,$hook) {\\n             var info = {};\\n             var config = this.getConfiguration();\\n             var maxWidth = 115;\\n             var maxHeight = 83;\\n             var oar = maxWidth/maxHeight;\\n             var w = $hook.width();\\n             var h = $hook.height();\\n             var wpct = config.playButtonSettings.width;\\n \\n             info.width = Math.round(wpct*w);\\n             if (info.width > maxWidth) {\\n                 info.width = maxWidth;\\n             }\\n             info.height = Math.round((1/oar)*info.width);\\n             info.x = (Math.round(w/2)-Math.round(info.width/2));\\n             info.y = (Math.round(h/2)-Math.round(info.height/2));\\n             return info;\\n         };\\n \\n         VideoFetcher.prototype.registerClick = function () {\\n             var type = this.getPlayerType();\\n             if (this.clickRegistered) {\\n                 return;\\n             }\\n             if (type === \\\'yt\\\') {\\n                 this.clickRegistered = true;\\n                 this.registerYTClick();\\n             }\\n         };\\n \\n         // VideoFetcher.prototype.determineRenderStrategy\\n         // determines what strategy should be used to display the player and initiate plays\\n         // takes whatever is set in the configuration object, unless the browser is mobile\\n         // in which case the strategy is always click.\\n         VideoFetcher.prototype.determineRenderStrategy = function () {\\n             var config = this.getConfiguration();\\n             this.CLICK_STRATEGY = 0;\\n             this.PLAY_STRATEGY  = 1;\\n             this.PROGRESS_STRATEGY = 2;\\n             this.NONE_STRATEGY = 3;\\n             this.MOBILE_CLICK_ONCE_STRATEGY = 4;\\n             if (isMobile()) {\\n                 return this.MOBILE_CLICK_ONCE_STRATEGY\\n             } \\n             var strats = {};\\n             strats.click = 0;\\n             strats.play = 1;\\n             strats.progress = 2;\\n             strats.none = 3;\\n             return strats[config.render_strategy];\\n         };\\n \\n         // VideoFetcher.prototype.registerVideoAd\\n         // decides on a rendering strategy based on the browser type and configuration setting\\n         // the options are as follows:\\n         // "click" clicking the image initiates a play\\n         // "play" hovering initiates\\\' the play\\n         // "progress" for the progress bar \\n         // "none" expose the youtube controls on hover\\n         // this will also mutate the config object, setting various player settings\\n         VideoFetcher.prototype.registerVideoAd = function () {\\n             // to prevent incorrect clickthrough behavior\\n             // we will alter the unit to take out any hrefs that match CLICKTHROUGH_URL\\n             this.alterUnit();\\n             this.checkForCTConsistency();\\n             var videoConfig = this.getConfiguration();\\n             var strategy = this.determineRenderStrategy();\\n             if (strategy === this.CLICK_STRATEGY) {\\n                 videoConfig.playerSettings.autoPlay = true;\\n                 this.registerClick();\\n             }\\n             else if (strategy === this.PLAY_STRATEGY) {\\n                 videoConfig.playerSettings.autoPlay = true;\\n                 this.registerHover();\\n             }\\n             else if (strategy === this.PROGRESS_STRATEGY) {\\n                 videoConfig.playerSettings.autoPlay = true;\\n                 videoConfig.playerSettings.hoverProgressBar = true;\\n                 videoConfig.progressLimit = 2000;\\n                 this.registerClick();\\n                 this.registerHover();\\n             }\\n             else if (strategy === this.MOBILE_CLICK_ONCE_STRATEGY) {\\n                 videoConfig.playerSettings.autoPlay = false;\\n                 videoConfig.transparentClickThroughDiv = false;\\n                 this.registerClick();\\n             }\\n             else {\\n                 this.registerHover();\\n             }\\n         };\\n         // transparentClickThroughDiv cannot be true when autoplay is false\\n         VideoFetcher.prototype.checkForCTConsistency = function () {\\n             var config = this.getConfiguration();\\n             if (config.transparentClickThroughDiv && false) {\\n                 if (!config.playerSettings.autoPlay) {\\n                     config.transparentClickThroughDiv = false;\\n                 }\\n             }\\n         };\\n \\n         VideoFetcher.prototype.registerHover = function () {\\n             var type = this.getPlayerType();\\n             if (this.hoverRegistered) {\\n                 return;\\n             }\\n             if (type === \\\'yt\\\') {\\n                 this.hoverRegistered = true;\\n                 this.registerYTHover();\\n             }\\n         };\\n \\n         VideoFetcher.prototype.registerYTHover = function () {\\n             // we also register a click handler to prevent default behavior--ie an unwanted\\n             // clickthrough\\n             var config = this.getConfiguration();\\n             var analyticsController = this.getAnalyticsController();\\n             if (!this.clickRegistered) {\\n                 this.clicked = true;\\n                 this.registerYTClick();\\n             }\\n             var $unit = this.getUnit();\\n             var that = this;\\n             var onHover = function (e) {\\n                 if (that.hovered) {\\n                     e.preventDefault();\\n                     e.stopPropagation();\\n                     return;\\n                 }\\n                 that.inPlay  = true;\\n                 that.hovered = true;\\n                 that.clicked = true;\\n                 if (that.preHoverOff) {\\n                     that.preHoverOff();\\n                 }\\n                 e.preventDefault();\\n                 e.stopPropagation();\\n                 var playerHookData    = that.getPlayerHookData();\\n                 var playerHook        = playerHookData.hook;\\n                 var w                 = playerHookData.width;\\n                 var h                 = playerHookData.height;\\n                 var wrappedPlayerInfo = that.getWrappedPlayerInfo();\\n                 var wrappedPlayer     = wrappedPlayerInfo.wrappedPlayer\\n                 playerHook.appendChild(wrappedPlayer);\\n                 that.positionWrappedPlayer(wrappedPlayer);\\n                 that.wrappedPlayer = wrappedPlayer;\\n                 that.initYTPlayer(wrappedPlayerInfo,w,h);\\n             };\\n             var stashedHover;\\n             if (config.playerSettings.hoverProgressBar) {                 \\n                 stashedHover = onHover;\\n                 onHover = function (e) {\\n                     if (!that.progressSet) {\\n                         that.setProgressBar(function () {\\n                             stashedHover(e);\\n                         });\\n                     }\\n                 };\\n             }\\n \\n             var hoverWithAnalytics = function (e) {\\n                 analyticsController.fireHover(e);\\n                 onHover(e);\\n             };\\n                     \\n             var hoverConfig = {over: hoverWithAnalytics, out: function () {}, sensitivy:8 };\\n             // sometimes, when there are multiple ads on page, hover intent wont\\\' bind past the the 3rd or 4th ad,\\n             // this function ensures that, even in those cases, the video player is shown\\n             if (unitNumber && (unitNumber < 3)) {\\n                 $unit.hoverIntent(hoverConfig);\\n             }\\n             else {\\n                 $unit.bind(\\\'mouseover\\\',onHover);\\n             }\\n         };\\n \\n         VideoFetcher.prototype.getVideoControls = function () {\\n                 return {width:0,height:0}; \\n         };\\n         // VideoFetcher.prototype.alterUnit\\n         // find A element where the href is %%%CLICKTHROUGH_URL%%%\\n         // and which also contain the main ad image\\n         // and set the href to "" to prevent incorrect clickthrough behavior\\n         VideoFetcher.prototype.alterUnit = function () { \\n             var tlImg = this.getTlImg();\\n             var horizontalRecursiveCheck = function (el) {\\n                 if (el.tagName === \\\'A\\\' && el.href === \\\'%%%CLICKTHROUGH_URL%%%\\\') {\\n                     el.href = \\\'\\\';\\n                     var $el = tljQuery(el);\\n                     // stop clicks from taking the user off the page\\n                     $el.click(function (e) {  e.preventDefault();  });\\n                     return true;\\n                 }\\n                 if (el.nextSibling) {\\n                     return horizontalRecursiveCheck(el.nextSibling);\\n                 }\\n                 return false;\\n             };\\n \\n             var verticalRecursiveCheck = function (el) {\\n                 if (!el) {\\n                     return;\\n                 }\\n                 // set element for horizontalRecursiveCheck by finding the first sibling\\n                 while (el.previousSibling) {\\n                     el = el.previousSibling;\\n                 }\\n                 if (horizontalRecursiveCheck(el)) {\\n                     return;\\n                 }\\n                 return verticalRecursiveCheck(el.parentNode);\\n             };\\n             verticalRecursiveCheck(tlImg);\\n         };\\n \\n         VideoFetcher.prototype.registerYTClick = function () {\\n             var $unit = this.getUnit();\\n             var that = this;\\n             $unit.click(function (e) {\\n                 if (that.clicked) {\\n                     return;\\n                 }\\n                 that.inPlay = true;\\n                 if (that.preHoverOff) {\\n                     that.preHoverOff();\\n                 }\\n                 that.clicked = true;\\n                 that.hovered = true;\\n                 if (that.progressBar) {\\n                     that.progressSet = true;\\n                     that.progressBar.removeProgressBar();\\n                 }\\n                 e.preventDefault();\\n                 e.stopPropagation();\\n                 var playerHookData = that.getPlayerHookData();\\n                 var playerHook = playerHookData.hook;\\n                 var w = playerHookData.width;\\n                 var h = playerHookData.height;\\n                 var wrappedPlayerInfo = that.getWrappedPlayerInfo();\\n                 var wrappedPlayer = wrappedPlayerInfo.wrappedPlayer\\n                 playerHook.appendChild(wrappedPlayer);\\n \\n                 that.positionWrappedPlayer(wrappedPlayer);\\n                 that.wrappedPlayer = wrappedPlayer;\\n                 that.initYTPlayer(wrappedPlayerInfo,w,h);\\n             });\\n         };\\n \\n         VideoFetcher.prototype.initYTPlayer = function (wrappedPlayerInfo,w,h) {\\n             var config = this.getConfiguration();\\n             var c = config.playerSettings.showControls ? 1:0;\\n             var r = 0;\\n             var id = this.getVideoId();\\n             var that = this;\\n             this.player = new YT.Player(wrappedPlayerInfo.playerID, {\\n               height: h,\\n               width: w,\\n               videoId: id,\\n               playerVars : {\\n                 controls:c,\\n                 showinfo:0,\\n                 modestbranding:1,\\n                 rel:r\\n               },\\n               events: {\\n                 \\\'onReady\\\':function () { that.onPlayerReady(); },\\n                 \\\'onStateChange\\\': function (e) {  that.onPlayerStateChange(e); },\\n                 \\\'onError\\\' : function (e) {  } // do nothing for now\\n                 }\\n             });\\n         };\\n         \\n         VideoFetcher.prototype.createWrappedPlayer = function (w,h) {\\n             var type = this.getPlayerType();\\n             if (type == \\\'yt\\\') {\\n                 var playerDiv = document.createElement("DIV");\\n                 playerDiv.id = "pd_"+Math.round(Math.random() * 10000);\\n                 var wrappedDiv = document.createElement("DIV");\\n                 wrappedDiv.id = "wpd_"+playerDiv.id;\\n                 wrappedDiv.appendChild(playerDiv);\\n                 wrappedDiv.style.width = w+"px";\\n                 wrappedDiv.style.height = h+"px";\\n                 wrappedDiv.style.position = "absolute";\\n                 safeSetZindex(0,wrappedDiv);\\n                 var playerID = playerDiv.id;\\n                 var wrappedDivID = wrappedDiv.id;\\n                 return {wrappedPlayer: wrappedDiv, playerID:playerDiv.id, wrappedDivID:wrappedDiv.id };\\n             }\\n         };\\n \\n         VideoFetcher.prototype.positionWrappedPlayer = function (wrappedPlayer) {\\n             var type = this.getPlayerType();\\n             var $tlImg = tljQuery(this.getTlImg());\\n             if (type == \\\'yt\\\') {\\n                 var hookTop = $tlImg.position().top;\\n                 var hookLeft = $tlImg.position().left;\\n                 wrappedPlayer.style.left = hookLeft+"px";\\n                 wrappedPlayer.style.top = (hookTop-tljQuery(wrappedPlayer).height())+"px";\\n                 safeSetZindex(this.ZI_LEVEL_1,wrappedPlayer);\\n             }\\n         };\\n \\n         VideoFetcher.prototype.pauseVideo = function () {\\n             var type = this.getPlayerType();\\n             if (type === "yt") {\\n                 this.player.pauseVideo();\\n             }\\n         };\\n \\n         VideoFetcher.prototype.playVideo = function () {\\n             var type = this.getPlayerType();\\n             if (type === "yt") {\\n                 this.player.playVideo();\\n             }\\n         };\\n \\n         VideoFetcher.prototype.isFireFox = function () {\\n             if (navigator && navigator.userAgent) {\\n                 return navigator.userAgent.toLowerCase().indexOf(\\\'firefox\\\') > -1;\\n             }\\n             return false;\\n         };\\n \\n         VideoFetcher.prototype.forceHTML5 = function () {\\n             var player = document.getElementById(this.getWrappedPlayerInfo().playerID);\\n             player.src += \\\'&html5=1\\\';\\n         };\\n \\n         // There\\\'s a bug in firefox affecting fansided:\\n         // the stopgap solution is to force the iframn to load an html5 player\\n         // this only impacts fansided_main_largefeature\\n         VideoFetcher.prototype.checkForFireFoxBug = function () { \\n             if (this.isFireFox() && !this.HTML5FORCED && inv_code.match(\\\'fansided_main_largefeature\\\')) { \\n                 this.checkedForFireFoxBug = true;\\n                 return true;\\n             }\\n             return false;\\n         };\\n \\n         VideoFetcher.prototype.checkAndSetHTML5 = function () {\\n             if (!this.forcedHTML5) {\\n                 if (this.checkForFireFoxBug()) {\\n                     this.HTML5FORCED = true;\\n                     this.forceHTML5();\\n                     return true;\\n                 }\\n                 if (this.IEHTML5 && !this.HTML5FORCED) {\\n                     this.HTML5FORCED = true;\\n                     this.forceHTML5();\\n                     return true;\\n                 }\\n             }\\n             return false;\\n         };\\n \\n         VideoFetcher.prototype.onPlayerReady = function () {\\n             if (this.checkAndSetHTML5()) {\\n                 return;\\n             }\\n             var $tlImg = tljQuery(this.getTlImg());\\n             var type = this.getPlayerType();\\n             var configuration = this.getConfiguration();\\n             if (type == \\\'yt\\\') {\\n                 var hookTop = $tlImg.position().top;\\n                 var hookLeft = $tlImg.position().left;\\n                 var wrappedPlayerInfo = this.getWrappedPlayerInfo();\\n                 var wrappedPlayer = wrappedPlayerInfo.wrappedPlayer;\\n                 // we have to do this here, so that the button isn\\\'t visible until the player is ready\\n                 var playerHookData = this.getPlayerHookData();\\n                 var playerEl = document.getElementById(wrappedPlayerInfo.playerID);\\n                 if (configuration && configuration.playerSettings) {\\n                     if (configuration.playerSettings.buttonBar) {\\n                         this.appendButtonBar(wrappedPlayer,playerEl);\\n                     }\\n                     else if (configuration.playerSettings.buttonBarMobile) {\\n                         this.appendButtonBarMobile(wrappedPlayer,playerEl);\\n                     }\\n                 }\\n                 this.show();\\n             }\\n         };\\n         \\n         //VideoFetcher.prototype.resetVideo\\n         // toggle in the main image\\n         // and see the video back to 0\\n         VideoFetcher.prototype.resetVideo = function () {\\n             var that = this;\\n             // onPlay pauses the video\\n             // and then checks shortly after to make sure the video is paused\\n             var onPlay = function ()  { \\n                 that.player.pauseVideo(); \\n                 // sometimes the youtube api does not pause the video\\n                 // even when pause is called and the player state is PLAYING\\n                 // so we have to check to make sure that the player is actually paused\\n                 var testDuration = 250; // ms\\n                 setTimeout(function () {\\n                     if (that.player.getPlayerState() !== YT.PlayerState.PAUSED) {\\n                         onPlay();\\n                     }\\n                 },testDuration);\\n             };\\n             this.videoToggler.toggle();\\n             this.player.seekTo(0);\\n             // becasue the player state will stopped immediately after calling seek to\\n             // we wait until the player state changes to playing to immediately pause the video\\n             this.registerOneTimePlayEvent(onPlay);\\n         };\\n \\n         // register a one time playe event\\n         // if an even has already been registered throw an error\\n         // this is so that resetVideo can pause the video properly\\n         VideoFetcher.prototype.registerOneTimePlayEvent = function (cb) {\\n             if (this.oneTimePlayEvent) {\\n                 throw new Error(\\\'event already registered\\\');\\n             }\\n             this.oneTimePlayEvent = cb;\\n         };\\n \\n         VideoFetcher.prototype.YTPlayerStateChange = function (e) {\\n             var ac = this.getAnalyticsController();\\n             if (e.data == YT.PlayerState.PLAYING) {\\n                 this.playState = "playing";\\n                 this.inPlay = true;\\n                 if (!this.initPlay) {\\n                     this.initPlay = true;\\n                     ac.firePlay();\\n                     // start measuring player progress\\n                     this.initPlayMonitor();\\n                 }\\n                 else {\\n                     this.playMonitor.setStart(new Date().getTime());\\n                 }\\n                 // if a one time event has been registered, fire it\\n                 if (this.oneTimePlayEvent) {\\n                     this.oneTimePlayEvent();\\n                     this.oneTimePlayEvent = false;\\n                 }\\n             }\\n             else if (e.data == YT.PlayerState.PAUSED) {\\n                 this.playState = "paused";\\n                 this.inPlay = false;\\n                 if (this.playMonitor) {\\n                     this.playMonitor.setStop(new Date().getTime());\\n                     this.playMonitor.setStop(new Date().getTime());\\n                 }\\n             }\\n             else if (e.data === YT.PlayerState.ENDED) {\\n                 var config = this.getConfiguration();\\n                 if (!this.videoEnded) {\\n                     ac.fireCompletion();\\n                     this.videoEnded = true;\\n                 }\\n                 this.playMonitor.setStop(new Date().getTime());\\n                 if (config.playerSettings.resetVideo) {\\n                     this.resetVideo();\\n                 }\\n                 // we also set autoplay for any subsequent plays\\n                 if (!config.playerSettings.autoPlay) {\\n                     config.playerSettings.autoPlay = true;\\n                 }\\n             }\\n         };\\n \\n         var PlayMonitor = function (ac,upperLimit) {\\n             var playing  = false;\\n             var totalTime = 0;\\n             var start;\\n             var stop;\\n             this.setStart = function (d)  { \\n                 start = d;\\n                 stop = undefined;\\n                 playing = true;\\n             };\\n             this.setStop = function (d) {\\n                 if (!playing) {\\n                     return;\\n                 }\\n                 stop = d;\\n                 playing = false;\\n                 totalTime += (stop-start);\\n             };\\n             this.getPlayDuration = function () {\\n                 var t;\\n                 if (playing) {\\n                     t = totalTime+(new Date().getTime()-start);\\n                 }\\n                 else {\\n                     t = totalTime;\\n                 }\\n                 // duration cannot exceed the duration of the video\\n                 // as represented by the upper limit\\n                 if (t > upperLimit) {\\n                     t = upperLimit;\\n                 }\\n                 return t;\\n             };\\n             this.expDecayMonitor = function(n) {\\n                 var d = this.getPlayDuration();\\n                 ac.fireDuration(d);\\n                 var that = this;\\n                 setTimeout(function () {\\n                     that.expDecayMonitor(n*1.5);\\n                 },n);\\n             };\\n         };\\n \\n         VideoFetcher.prototype.initPlayMonitor = function () {\\n             this.playMonitor = new PlayMonitor(this.getAnalyticsController(), this.getVideoLengthMS());\\n             this.playMonitor.setStart(new Date().getTime());\\n             var that = this;\\n             setTimeout(function () {\\n                 that.playMonitor.expDecayMonitor(1000);\\n             },1000);\\n         };\\n \\n         VideoFetcher.prototype.onPlayerStateChange = function (e) {\\n             var $tlImg = tljQuery(this.getTlImg());\\n             var type = this.getPlayerType();\\n             if (type == \\\'yt\\\') {\\n                 this.YTPlayerStateChange(e);\\n             }\\n         };\\n \\n         VideoFetcher.prototype.getYTVideoLength = function () {\\n             // if the ytapi video metadata has not yet been loaded\\n             // 0 will be returned, but since 0 is falsey that works\\n             return this.player.getDuration();\\n         };\\n \\n         VideoFetcher.prototype.getVideoLengthMS = function () {\\n             var type = this.getPlayerType();\\n             if (type == \\\'yt\\\') {\\n                 return this.getYTVideoLength() * 1000;\\n             }\\n         };\\n \\n         VideoFetcher.prototype.getCanvass = function () {\\n             var size = this.getImageSize();\\n             var canvass = {};\\n             if (size === "small") {\\n                 canvass.shareButtons = {width:0.60, alignment:\\\'bottom right\\\'};\\n                 canvass.xButton = {width:0.04,alignment:\\\'top right\\\'};\\n                 canvass.seeMoreButton = {width:0.20, alignment:\\\'above\\\'};\\n             }\\n             else if (size === "large") {\\n                 canvass.shareButtons = {width:0.33, alignment:\\\'bottom right\\\'};\\n                 canvass.xButton = {width:0.04,alignment:\\\'top right\\\'};\\n                 canvass.seeMoreButton = {width:0.20, alignment:\\\'left\\\'};\\n             }\\n             else { \\n                 throw new Error(\\\'no valid image size\\\');\\n             }\\n             return canvass;\\n         };\\n \\n         VideoFetcher.prototype.positionButton = function (button,$hook) { \\n             // due to a bug in driving plays via the youtube api\\n             // the x button is not included in mobile impressions\\n             var config = this.getConfiguration();\\n             var elType;\\n             if (config.isMobile && (button.type === \\\'xbutton\\\')) {\\n                 return;\\n             }\\n             elType = button.elementType || "IMG";\\n             var i  = document.createElement(elType);\\n             if (elType == "IMG") {\\n                 i.src = button.src;\\n             }\\n             var $i = tljQuery(i);\\n             gaurd($i);\\n             $i.style("display","none","important");\\n             $hook[0].appendChild(i);\\n             $i.style("position","absolute","important");\\n             $i.style("width",button.width+"px","important");\\n             $i.style("height",button.height+"px","important");\\n             $i.style("left",button.x+"px","important");\\n             $i.style("top",button.y+"px","important");\\n             $i.staticTop = button.y;\\n             safeSetZindex(button.zIndex,null,$i,\\\'\\\');\\n             this.addClick(button,$i);\\n             if (button.type == "ctdiv") {\\n                 this.addCTDiv($i);\\n             }\\n             return $i;\\n         };\\n \\n         VideoFetcher.prototype.addCTDiv = function ($div) {\\n             this.transparentClickThroughDiv  = $div[0];\\n             this.$transparentClickThroughDiv = $div;\\n         };\\n \\n         VideoFetcher.prototype.addClick = function (buttonInfo,$buttonImg) { /* in the case of the transparent clickthrough div, $buttonImg is a div, but in all other cases it\\\'s an image */\\n             \\n             if (buttonInfo.type === "xButton")        {\\n                 this.addXButtonClick($buttonImg[0]);\\n                 $buttonImg.type = \\\'xButton\\\';\\n             }\\n             else if (buttonInfo.type === \\\'pinterest\\\') {\\n                 this.addPinButtonClick($buttonImg);\\n             }\\n             else if (buttonInfo.type === \\\'tumblr\\\')    {\\n                 this.addTumblrButtonClick($buttonImg);\\n             }\\n             else if (buttonInfo.type === \\\'twitter\\\')   {\\n                 this.addTwitterButtonClick($buttonImg);\\n             }\\n             else if (buttonInfo.type === \\\'facebook\\\')  {\\n                 this.addFacebookButtonClick($buttonImg);\\n             }\\n             else if (buttonInfo.type === \\\'seemore\\\')   {\\n                 this.addSeeMoreButtonClick($buttonImg);\\n             }\\n             else if (buttonInfo.type === \\\'ctdiv\\\')     {\\n                 this.addCTDivClick($buttonImg);\\n             }\\n         };\\n \\n         VideoFetcher.prototype.addSeeMoreButtonClick = function ($button) {\\n             var ac = this.getAnalyticsController();\\n             $button.click(function () {\\n                 window.open(\\\'%%%CLICKTHROUGH_URL%%%\\\',\\\'_blank\\\');\\n                 ac.fireClick();\\n             });\\n         };\\n         \\n         VideoFetcher.prototype.addCTDivClick = function ($button) {\\n             var ac   = this.getAnalyticsController();\\n             var that = this;\\n             $button.click(function () {\\n                 if (!that.isPlayerShowing()) {\\n                     that.show();\\n                 }\\n                 else if ((that.player.getPlayerState() == YT.PlayerState.PAUSED) || (that.player.getPlayerState() == YT.PlayerState.CUED)) {\\n                     that.player.playVideo();\\n                 }\\n                 else {\\n                     that.pauseVideo();\\n                     window.open(\\\'%%%CLICKTHROUGH_URL%%%\\\',\\\'_blank\\\');\\n                     ac.fireClick();\\n                 }\\n             });\\n         };\\n \\n         VideoFetcher.prototype.addXButtonClick = function (button) {\\n             this.videoToggler =  new VideoToggler(button,this);\\n             // add a click event for the play button so the video will be toggled back in\\n             this.addPlayButtonClick();\\n         };\\n \\n         VideoFetcher.prototype.createYTURL = function () {\\n             var id = this.videoID;\\n             var url = "http://youtube.com/watch?v="+id;\\n             return url;\\n         };\\n \\n         VideoFetcher.prototype.addFacebookButtonClick = function ($button) {\\n             // in the future we might want to use the share dialog api, but below is easier and closer to what we do for native images\\n             //var shareUrl = "http://facebook.com/dialog/feed?app_id=269157343104443&display=popup&ref=share&picture="+encodeURIComponent(\\\'http:%%%IMAGE_URL%%%\\\')+"&link="+encodeURIComponent(\\\'%%%CLICKTHROUGH_URL%%%\\\')+\\\'&name=\\\'+encodeURIComponent(\\\'%%%SINGLE_ESCAPED_HEADING%%%\\\')+\\\'&caption=\\\'+encodeURIComponent(\\\'%%%SINGLE_ESCAPED_CAPTION%%%\\\')+\\\'&source=\\\'+encodeURIComponent(this.createYTURL())+\\\'&redirect_uri=\\\'+encodeURIComponent(\\\'https://triplelift.com\\\')+\\\'&show_error=true\\\';\\n             var shareUrl = "http://facebook.com/sharer/sharer.php?u="+encodeURIComponent(this.createYTURL());\\n             var ac = this.getAnalyticsController();\\n             $button.click(function () {\\n                 ac.fireShare("facebook");\\n                 window.open(shareUrl,\\\'popup\\\',\\\'width=650,height=316\\\');\\n             });\\n         };\\n \\n         VideoFetcher.prototype.addPinButtonClick = function ($button) {\\n            var shareUrl = \\\'http://pinterest.com/pin/create/button/?is_video=true&url=\\\'+encodeURIComponent(this.createYTURL())+\\\'&media=\\\'+encodeURIComponent(\\\'%%%IMAGE_URL%%%\\\') + \\\'&description=\\\'+encodeURIComponent(\\\'%%%SINGLE_ESCAPED_CAPTION%%%\\\');\\n            var ac       = this.getAnalyticsController();\\n           $button.click(function () {\\n                ac.fireShare("pinterest");\\n                window.open(shareUrl,\\\'popup\\\',\\\'width=650,height=316\\\');\\n           });\\n         };\\n \\n         VideoFetcher.prototype.addTwitterButtonClick = function ($button) {\\n             var shareUrl = \\\'http://twitter.com/intent/tweet?text=\\\'+encodeURIComponent(\\\'%%%SINGLE_ESCAPED_CAPTION%%%\\\')+\\\'&url=\\\'+encodeURIComponent(this.createYTURL());\\n             var ac = this.getAnalyticsController();\\n             $button.click(function () {\\n                 ac.fireShare("twitter");\\n                 window.open(shareUrl,\\\'popup\\\',\\\'width=650,height=316\\\');\\n             });\\n         };\\n \\n         VideoFetcher.prototype.createEmbed = function (src) {\\n             return \\\'<iframe src="\\\'+src+\\\'">\\\';\\n         };\\n \\n         VideoFetcher.prototype.addTumblrButtonClick = function ($button) {\\n             // NOTE: This Only Works With youtube Videos\\n             var wrappedPlayerInfo = this.getWrappedPlayerInfo(); \\n             var wrappedPlayer     = wrappedPlayerInfo.wrappedPlayer;\\n             var i                 = wrappedPlayer.getElementsByTagName(\\\'IFRAME\\\')[0];\\n             var shareUrl          = \\\'http://www.tumblr.com/share/video?embed=\\\'+encodeURIComponent(this.createEmbed(i.src))+\\\'&caption=\\\'+encodeURIComponent(\\\'%%%SINGLE_ESCAPED_CAPTION%%%\\\');\\n             var ac                = this.getAnalyticsController();\\n             $button.click(function () {\\n                ac.fireShare("tumblr");\\n                window.open(shareUrl,\\\'popup\\\',\\\'width=650,height=316\\\');\\n           });\\n         };\\n         // returns the commands to layout the particular mouse buttons specified in the config object\\n         VideoFetcher.prototype.constructMouseButtonLayoutCommands = function () {\\n             var config   = this.getConfiguration();\\n             var commands = ["getShareButtonsLayout","getXButtonLayout","getBottomTransBar"];\\n             if (!config.transparentClickThroughDiv) {\\n                 commands.push("getSeeMoreButtonLayout");\\n             }\\n             else {\\n                 commands.push("getTransparentClickThroughDiv");\\n             }\\n             return commands;\\n         };\\n \\n         VideoFetcher.prototype.getLayout = function ($hook) {\\n             var canvass       = this.getCanvass();\\n             canvass.available = {x1:0,y1:0,x2:$hook.width(),y2:$hook.height()};\\n             var info          = [];\\n             canvass.info      = info;\\n \\n             var commands      = this.constructMouseButtonLayoutCommands();\\n             var that          = this;\\n \\n             commands.forEach(function (cmd) {\\n                 that[cmd]($hook,canvass);\\n             });\\n \\n             return info;\\n         };\\n \\n         VideoFetcher.prototype.getBottomTransBar = function ($hook,canvass) {\\n             var config = this.getConfiguration();\\n             var info = {};\\n             // Safari doesn\\\'t like to render the 1x1000 png of the gradient background, but handles a 200x100 image much better\\n             // however, the 1x1000 png looks better, so if we can we use that\\n             if (navigator && navigator.userAgent && navigator.userAgent.match("Safari") && !navigator.userAgent.match("Chrome")) {\\n                 info.src = this.getAsset(\\\'safeGradient\\\');\\n             }\\n             else {\\n                 info.src = this.getAsset(\\\'gradient\\\');\\n             }\\n             info.width = $hook.width();\\n             var size = this.getImageSize();\\n             if (size === "small") {\\n                 info.height = Math.round(canvass.info[0].height*3.5)+10;\\n             }\\n             else {\\n                 info.height = Math.round(canvass.info[0].height*1.5)+10;\\n             }\\n             // the first div is the wrapped player div\\n             info.x = $hook.find("div").position().left;\\n             info.y = $hook.height()-info.height;\\n             if (config.playerSettings.showControls) {\\n                 info.y -= 37;\\n             }\\n             info.zIndex = this.ZI_LEVEL_3; // so the transparent div won\\\'t catch these clicks\\n             canvass.info.push(info);\\n         };\\n \\n         VideoFetcher.prototype.seeMoreButtonOriginalWidth = 183;\\n         VideoFetcher.prototype.seeMoreButtonOriginalHeight = 23;\\n \\n         // the see more button is laid out relative to the share buttons\\n         VideoFetcher.prototype.getSeeMoreButtonLayout = function ($hook,canvass) {\\n             var sminfo = canvass.seeMoreButton;\\n             var oar = this.seeMoreButtonOriginalWidth/this.seeMoreButtonOriginalHeight;\\n             var w,h,x,y;\\n             var info = {};\\n             info.type = "seemore";\\n             if (canvass.shareButtons.alignment === \\\'bottom right\\\') {\\n                 if (sminfo.alignment === \\\'left\\\') {\\n                     h = Math.round(this.shareButton.height/4)*3; \\n                     w = oar*h;\\n                     if (h > this.seeMoreButtonOriginalHeight) {\\n                         h = this.seeMoreButtonOriginalHeight;\\n                         w = this.seeMoreButtonOriginalWidth;\\n                     }\\n                     y = canvass.available.y2 + Math.round(this.shareButton.height/2) - Math.round(h/2);\\n                     x = canvass.available.x2 = canvass.available.x2-w-10;\\n                     info.type = "seemore";\\n                     info.x =x;\\n                     info.y = y;\\n                     info.width = w;\\n                     info.height = h;\\n                     info.src = this.getAsset("seemore");\\n                     info.zIndex = this.ZI_LEVEL_4;\\n                     canvass.info.push(info);\\n                 }\\n                 else if (sminfo.alignment === \\\'above\\\') {\\n                     // if we are placing the see more button above\\n                     // the width of the see more button is 3/4 that of the available width\\n                     // so the seemore button fits within the combined width of the share buttons\\n                     w = Math.round(($hook.width()-canvass.available.x2)/4)*3; \\n                     h = Math.round((1/oar)*w); \\n                     if (h > this.originalSeeMoreButtonHeight) {\\n                         h = this.originalSeeMoreButtonHeight;\\n                         w = this.originalSeeMoreButtonWidth;\\n                     }\\n                     // there is a 15px gap between the share buttons and the seemore button\\n                     // and a 10px gap between the see more button and the edge of the player\\n                     y = canvass.available.y2 - h - 15;\\n                     x = $hook.width() - (w + Math.round(w/10));\\n                     info.x = x;\\n                     info.y = y;\\n                     info.width = w;\\n                     info.height = h;\\n                     info.src = this.getAsset("seemore");\\n                     info.zIndex = this.ZI_LEVEL_4;\\n                     canvass.info.push(info);\\n                 }\\n                 else {\\n                     throw new Error(\\\'getSeeMoreButtonLayout: no valid alignment found\\\');\\n                 }\\n             }\\n             else {\\n                 throw new Error(\\\'getSeeMoreButtonLayout: no valid alignment found\\\');\\n             }\\n         };\\n \\n         VideoFetcher.prototype.getTransparentClickThroughDiv = function ($hook,canvass) {\\n             var config       = this.getConfiguration();\\n             var info         = {};\\n             var w            = $hook.width();\\n             var h            = $hook.height();\\n             info.type        = "ctdiv";\\n             info.elementType = "DIV";\\n             info.x           = 0;\\n             info.y           = 0;\\n             if (config.playerSettings.showControls) {\\n                 info.height  = h- this.playerControlHeight;\\n             }\\n             else {\\n                 info.height  = h;\\n             }\\n             info.width       = w;\\n             info.zIndex      = this.ZI_LEVEL_2;\\n             canvass.info.push(info);\\n         };\\n \\n         VideoFetcher.prototype.getXButtonLayout = function ($hook,canvass) {\\n             var xinfo = canvass.xButton;\\n             var $wrappedPlayer = tljQuery(this.getWrappedPlayerInfo().wrappedPlayer);\\n             var ow = 85;\\n             var oh = 85;\\n             var oar = ow/oh;\\n             var w,h,x,y;\\n             var w = xinfo.width*$hook.width();\\n             h = Math.round((1/oar)*w);\\n             if (h > oh) {\\n                 h = oh;\\n                 w = ow;\\n             }\\n             if (xinfo.alignment === \\\'top right\\\') {\\n                 y = canvass.available.y1 + $wrappedPlayer.position().top;\\n                 x = $hook.width()-w; // TODO: there is a logic error in determining where the available offset is\\n                 var info = {};\\n                 info.type = "xButton";\\n                 info.x =x;\\n                 info.y = y;\\n                 info.width = w;\\n                 info.height = h;\\n                 info.src = this.getAsset("xbutton");\\n                 info.zIndex = this.ZI_LEVEL_4;\\n                 canvass.info.push(info);\\n             }\\n             else {\\n                 throw new Error(\\\'getXButtonLayout: no valid alignment found\\\');\\n             }\\n         };\\n         \\n         VideoFetcher.prototype.shareTypes = (function () { \\n             var st = "%%%VIDEO_SHARE_TYPES%%%";\\n             if (st === "") {\\n                 return [];\\n             }\\n             return st.split(",");\\n         })();\\n \\n \\n         VideoFetcher.prototype.shareButtonOriginalWidth = 80;\\n         VideoFetcher.prototype.shareButtonOriginalHeight = 60;\\n         VideoFetcher.prototype.shareButtonOriginalRatio = 80/60;\\n         VideoFetcher.prototype.shareButtonOriginalInverseRatio = 60/80;\\n         VideoFetcher.prototype.shareButtonHeightPct = 0.11;\\n \\n         VideoFetcher.prototype.aspectRatioGT16 = function () {\\n             var $tlImg = tljQuery(this.getTlImg());\\n             var width = $tlImg.width();\\n             var height = $tlImg.height();\\n             var ar = width/height;\\n             var lowerBound = 1.72;\\n             var upperBound = 1.83;\\n             if ((lowerBound <= ar) && (ar <= upperBound)) {\\n                 return true;\\n             }\\n             return false;\\n         };\\n         \\n         VideoFetcher.prototype.playerControlDimensions = {width:35, height:27}; // these are constant no matter the player size\\n \\n         //VideoFetcher.prototype.getAvailablePlayerHeight\\n         // takes the $hook object, and checks if expose_controls is true\\n         // and returns either the height() of the hook, or the height of the hook minus an appropiate offset\\n         VideoFetcher.prototype.getAvailablePlayerHeight = function ($hook) {\\n             var config = this.getConfiguration();\\n             if (config.playerSettings.showControls) {\\n                 return $hook.height()-this.playerControlDimensions.height;\\n             }\\n             return $hook.height();\\n         };\\n \\n         // checkShareButtonSizeGT checks if the share buttons are greater than their original width\\n         // or if they are greater than a certain proportion of the image height\\n         // and corrects their dimensions as necessary\\n         VideoFetcher.prototype.checkShareButtonSizeGT = function($hook,canvass) {\\n             var w,h\\n             var oar = this.shareButtonOriginalWidth/this.shareButtonOriginalHeight;\\n             w = this.shareButton.width;\\n             h = this.shareButton.height;\\n             if (w > this.shareButtonOriginalWidth) {\\n                 w = this.shareButtonOriginalWidth;\\n                 h = this.shareButtonOriginalHeight;\\n             }\\n             if (h > Math.round(this.shareButtonHeightPct * this.getAvailablePlayerHeight($hook))) {\\n                 h = Math.round(this.shareButtonHeightPct * this.getAvailablePlayerHeight($hook));\\n                 w = Math.round(oar*h);\\n             }\\n             this.shareButton.width = w;\\n             this.shareButton.height = h;\\n         };\\n \\n         VideoFetcher.prototype.calcShareButtonDimensions = function ($hook,canvass) {\\n             var sbinfo = canvass.shareButtons;\\n             var x,y;\\n             var w,h;\\n             var oar = this.shareButtonOriginalWidth/this.shareButtonOriginalHeight;\\n             w = Math.round((this.getAvailablePlayerHeight($hook) * sbinfo.width)/this.shareTypes.length);\\n             h = Math.round(w*(1/oar));\\n             this.shareButton = {height:h,width:w};\\n             this.checkShareButtonSizeGT($hook,canvass);\\n         };\\n \\n         VideoFetcher.prototype.getShareButtonsLayout = function($hook,canvass) {\\n             var config = this.getConfiguration();\\n             var sbinfo = canvass.shareButtons;\\n             var that = this;\\n             var x,y,w,h;\\n             this.calcShareButtonDimensions($hook,canvass);\\n             w = this.shareButton.width;\\n             h = this.shareButton.height;\\n             if (sbinfo.alignment === \\\'bottom right\\\') {\\n                 y =  canvass.available.y2-h-10;\\n                 if (config.playerSettings.showControls) {\\n                     y -= 37;\\n                 }\\n                 canvass.available.y2 = y;\\n                 this.shareTypes.forEach(function (st) {\\n                     var src = that.getAsset(st);\\n                     x = canvass.available.x2-w;\\n                     canvass.info.push({src:src, width:w, height:h, x:x, y:y, zIndex:that.ZI_LEVEL_4, type:st});\\n                     canvass.available.x2 -= (w+10);\\n                 });\\n             }\\n             else {\\n                 throw new Error(\\\'getShareButtonsLayout: no valid alignment found\\\');\\n             }\\n         };\\n \\n         VideoFetcher.prototype.layoutButtons = function (buttons,$hook) {\\n             var layout = this.getLayout($hook);\\n             var that = this;\\n             layout.forEach(function (button) {\\n                 var $button = that.positionButton(button,$hook);\\n                 // remove float, padding, etc\\n                 // if positionButton returns undefined, it opted to not position that button\\n                 // due to some logic driven by the configuration object\\n                 if ($button) {\\n                     that.removeImageStyling($button);\\n                     buttons.push($button);\\n                 }\\n             });\\n         };\\n         \\n         var buttonToggleEvents = {};\\n         buttonToggleEvents.MOUSEOVER  = 1;\\n         buttonToggleEvents.MOUSEOUT   = 2;\\n         buttonToggleEvents.PLAY       = 3;\\n         buttonToggleEvents.PAUSE      = 4;\\n         buttonToggleEvents.STOP       = 5;\\n         buttonToggleEvents.TOGGLEOFF  = 6;\\n         buttonToggleEvents.TOGGLEON   = 7;\\n         buttonToggleEvents.SHOWPLAYER = 8;\\n \\n         VideoFetcher.prototype.buttonToggleEvents = buttonToggleEvents;\\n \\n         var basez                         = VideoFetcher.prototype.BASE_ZINDEX = 99999;\\n         VideoFetcher.prototype.ZI_LEVEL_0 = basez;     // the player itself\\n         VideoFetcher.prototype.ZI_LEVEL_1 = basez + 1; // the wrapped player\\n         VideoFetcher.prototype.ZI_LEVEL_2 = basez + 2; // transparent click through div\\n         VideoFetcher.prototype.ZI_LEVEL_3 = basez + 3; // the dark button bar\\n         VideoFetcher.prototype.ZI_LEVEL_4 = basez + 4; // the share buttons and see more button\\n \\n         VideoFetcher.prototype.addMouseButtons = function (wrappedPlayer) {\\n             var config = this.getConfiguration();\\n             var $wrappedPlayer = tljQuery(wrappedPlayer);\\n             var that = this;\\n             var buttons = [];\\n             var $hook = tljQuery(this.getPlayerHookData().hook);\\n             this.layoutButtons(buttons,$hook);\\n             var buttonController = (function () {\\n                 var controller = {};\\n                 controller.display = function () {\\n                     buttons.forEach(function ($button) {\\n                         $button.style("display","","important");\\n                     });\\n                 };\\n                 \\n                 controller.hide = function () {\\n                     buttons.forEach(function ($button) {\\n                         if ($button.type === \\\'xButton\\\') {\\n                             return;\\n                         }\\n                         $button.style("display","none","important");\\n                     });\\n                 };\\n \\n                 controller.adjustDown = function () {\\n                     buttons.forEach(function ($button) {\\n                         if ($button.type === \\\'xButton\\\') {\\n                             return;\\n                         }\\n                         $button.style("top",($button.staticTop+37)+"px","important");\\n                     });\\n                 };\\n \\n                 controller.adjustUp = function () {\\n                     buttons.forEach(function ($button) {\\n                         if ($button.type === \\\'xButton\\\') {\\n                             return;\\n                         }\\n                         $button.style("top",($button.staticTop)+"px","important");\\n                     });\\n                 };\\n \\n                 return controller;\\n             })();\\n \\n             var ButtonStateDispatcher = function (buttonController,video) {\\n                 var OFFSTATE        = 1,\\n                     ONSTATE         = 2,\\n                     ADJUSTUPSTATE   = 3,\\n                     ADJUSTDOWNSTATE = 4,\\n                     FROZENSTATE     = 5,\\n                     ERRORSTATE      = 6\\n                 ;\\n                 var buttonToggleEvents = video.buttonToggleEvents;\\n                 var enabled = true;\\n                 this.enable = function () {\\n                     enabled = true;\\n                 };\\n                 this.disable = function () {\\n                     enabled = false;\\n                 };\\n                 var getPlayerShowingBool = function () {\\n                     return video.isPlayerShowing();\\n                 };\\n \\n                 var getExposeControlsBool = function () {\\n                     var config = video.getConfiguration();\\n                     return config.playerSettings.showControls;\\n                 };\\n \\n                 var getAlwaysShowButtonsBool = function () {\\n                     var config = video.getConfiguration();\\n                     return config.playerSettings.alwaysShowButtons;\\n                 };\\n \\n                 var getButtonState = function (event) {\\n                     var playerShowing     = getPlayerShowingBool();\\n                     var alwaysShowButtons = getAlwaysShowButtonsBool();\\n                     var exposeControls    = getExposeControlsBool();  \\n                     var state;\\n                     if (!enabled) {\\n                         return FROZENSTATE;\\n                     }\\n                     if (event === buttonToggleEvents.MOUSEOVER) {\\n                         if (playerShowing && alwaysShowButtons && exposeControls) {\\n                             state = ADJUSTUPSTATE;\\n                         }\\n                         else {\\n                             state = ONSTATE;\\n                         }\\n                     }\\n                     else if (event === buttonToggleEvents.MOUSEOUT) {\\n                         if (alwaysShowButtons) {\\n                             if (playerShowing && exposeControls) {\\n                                 state = ADJUSTDOWNSTATE;\\n                             }\\n                             else  {\\n                                 state = FROZENSTATE;\\n                             }\\n                         }\\n                         else {\\n                             state = OFFSTATE;\\n                         }\\n                     }\\n                     else if (event === buttonToggleEvents.TOGGLEOFF) {\\n                         if (exposeControls) {\\n                             state = ADJUSTDOWNSTATE;\\n                         }\\n                     }\\n                     else if (event === buttonToggleEvents.TOGGLEON) {\\n                         if (exposeControls) {\\n                             state = ADJUSTUPSTATE;\\n                         }\\n                     }\\n                     else if (event === buttonToggleEvents.SHOWPLAYER) {\\n                         state = ONSTATE;\\n                     }\\n                     else {\\n                         state = ERRORSTATE;\\n                     }\\n                     return state;\\n                 };\\n \\n                 this.adjustButtonState = function (event) {\\n                     var state = getButtonState(event);\\n                     if (state === ADJUSTUPSTATE) {\\n                         buttonController.adjustUp();\\n                     }\\n                     else if (state === ADJUSTDOWNSTATE) {\\n                         buttonController.adjustDown();\\n                     }\\n                     else if (state === ONSTATE) {\\n                         buttonController.display();\\n                     }\\n                     else if (state === OFFSTATE) {\\n                         buttonController.hide();\\n                     }\\n                     else if (state === FROZENSTATE) {\\n                         // FROZEN\\n                     }\\n                     else {\\n                         throw new Error("ButtonStateDispatcher in ERRORSTATE: " + event);\\n                     }\\n                 };\\n             };\\n \\n             var buttonToggler = new ButtonStateDispatcher(buttonController,this); \\n             var dummyOffChecker = function () {};\\n             var tlImg = this.getTlImg();\\n             var $tlImg = this.fansided_largefeature_check();\\n             \\n             var playerOffchecker = decorateOffChecker(null,dummyOffChecker,this);\\n             var imageOffChecker  = decorateOffChecker(null,\\n                                                     dummyOffChecker,\\n                                                     {getBox:function () {\\n                                                         var box = {};\\n                                                         var pos = $tlImg.offset();\\n                                                         box.x1 = pos.left;\\n                                                         box.x2 = pos.left+$tlImg.width();\\n                                                         box.y1 = pos.top;\\n                                                         box.y2 = pos.top+$tlImg.height();\\n                                                         return box;\\n                                                     }});\\n \\n             var $transparentClickThroughDiv = config.transparentClickThroughDiv ? this.$transparentClickThroughDiv : false;\\n             \\n             var onMouseOver = function () {\\n                     buttonToggler.adjustButtonState(that.buttonToggleEvents.MOUSEOVER);\\n                     var boundEvent = function (e) {\\n                         that.setCursor(e);\\n                     };\\n                     tljQuery(document).bind(\\\'mousemove\\\',boundEvent);\\n                     var recursiveCheck = function () {\\n                         var cursor = that.cursor;\\n                         if (!cursor.notSet && playerOffchecker(cursor)) {\\n                             buttonToggler.adjustButtonState(that.buttonToggleEvents.MOUSEOUT);\\n                             tljQuery(document).unbind(\\\'mousemove\\\',boundEvent);\\n                             cursor.notSet = true;\\n                         }\\n                         else {\\n                             setTimeout(recursiveCheck,100);\\n                         }\\n                     };\\n                     recursiveCheck();\\n             };\\n             \\n             $wrappedPlayer.on(\\\'mouseover\\\',onMouseOver );\\n             // because the transparentClickThroughDiv will have a higher zindex than the wrappedplayer when its present, we also add the mouseover listener here when it\\\'s present\\n             if ($transparentClickThroughDiv) {\\n                 $transparentClickThroughDiv.on(\\\'mouseover\\\', function (e) { \\n                     if (that.isPlayerShowing()) { onMouseOver(e) }\\n                 });\\n             }\\n             // add toggle events to the image itself, for when the video is toggle up\\n             $tlImg.on(\\\'mouseover\\\', function () {\\n                 buttonToggler.adjustButtonState(that.buttonToggleEvents.MOUSEOVER);\\n                 \\n                 var boundEvent = function (e) {\\n                     that.setCursor(e);\\n                 };\\n                 tljQuery(document).bind(\\\'mousemove\\\',boundEvent);\\n                 var recursiveCheck = function () {\\n                     var cursor = that.cursor;\\n                     if (!cursor.notSet && imageOffChecker(cursor)) {\\n                         buttonToggler.adjustButtonState(that.buttonToggleEvents.MOUSEOUT);\\n                         tljQuery(document).unbind(\\\'mousemove\\\',boundEvent);\\n                         cursor.notSet = true;\\n                     }\\n                     else {\\n                         setTimeout(recursiveCheck,100);\\n                     }\\n                 };\\n                 recursiveCheck();\\n             });\\n \\n             return buttonToggler;\\n         };\\n \\n         VideoFetcher.prototype.getImageSize = function () { \\n             var $hook = tljQuery(this.getTlImg());\\n             var w = $hook.width();\\n             var h = this.getAvailablePlayerHeight($hook);\\n             var wlimit = 300;\\n             var hlimit = 200;\\n             var alimit = wlimit*hlimit;\\n             var area = w*h;\\n \\n             var r;\\n             if (area >= alimit) {\\n                 r ="large";\\n             }\\n             else {\\n                 r = "small";\\n             }\\n             return r;\\n         };\\n \\n         VideoFetcher.prototype.setPlayerShow = function (bool) {\\n             this.playerVisible = bool;\\n         };\\n \\n         VideoFetcher.prototype.isPlayerShowing = function () {\\n             return this.playerVisible;\\n         };\\n \\n         VideoFetcher.prototype.afterShow = function (wrappedPlayer) { \\n             var config = this.getConfiguration();\\n             this.setPlayerShow(true);\\n             if (!this.mouseButtonToggler && !config.playerSettings.buttonBar) {\\n                 this.mouseButtonToggler = this.addMouseButtons(wrappedPlayer);\\n             }\\n             if (this.mouseButtonToggler) { \\n                 this.mouseButtonToggler.enable();\\n                 this.mouseButtonToggler.adjustButtonState(this.buttonToggleEvents.SHOWPLAYER);\\n             }\\n             if (!this.extraTextHidden) {\\n                 this.hideExtraText(); \\n             }\\n         };\\n \\n         VideoFetcher.prototype.show = function (playFlag) {\\n             var type = this.getPlayerType();\\n             var config = this.getConfiguration();\\n             if (type == \\\'yt\\\') {\\n                 var wrappedPlayerInfo = this.getWrappedPlayerInfo();\\n                 var wrappedPlayer = wrappedPlayerInfo.wrappedPlayer;\\n                 var playerEl = document.getElementById(wrappedPlayerInfo.playerID);\\n                 var $tlImg = tljQuery(this.getTlImg());\\n                 var hookTop = $tlImg.position().top;\\n                 var that = this;\\n                 var $wrappedPlayer = tljQuery(wrappedPlayer);\\n                 if (config.playerSettings.fadeIn) {\\n                     $wrappedPlayer.style("display","none");\\n                     $wrappedPlayer.style("top",hookTop+"px","important");\\n                     $wrappedPlayer.fadeIn(1000,function () { that.afterShow(wrappedPlayer); });\\n                 }\\n                 else {\\n                     $wrappedPlayer.animate({"top":hookTop},800, function () { that.afterShow(wrappedPlayer);  });\\n                 }\\n                 if (config.playerSettings.autoPlay) {\\n                     this.player.playVideo();\\n                 }\\n             }\\n         };\\n \\n         VideoFetcher.prototype.supportsHTML5Video = (function () {\\n             // borrowed from http://youtube.com/html5\\n             var videoElement = document.createElement(\\\'video\\\');\\n             var videoCompatible = videoElement && videoElement.canPlayType;\\n             return videoCompatible;\\n         })();\\n \\n         VideoFetcher.prototype.hideExtraText = function () {\\n             this.extraTextHidden = true;\\n             var $unit = tljQuery(this.getUnit());\\n             tljQuery($unit[0].getElementsByClassName(\\\'tl-extra\\\')).style(\\\'display\\\',\\\'none\\\',\\\'important\\\');\\n         };\\n         // VideoFetcher.prototype.hide\\n         // hide the player using a jquery animation, and then, if a call back has been passed in, invoke that callback\\n         VideoFetcher.prototype.hide = function (cb) {\\n             // if no callback has been passed, we create a dummy one so tljQuery doesn\\\'t throw an exception\\n             if (!cb) {\\n                 cb = function () {};\\n             }\\n             var type = this.getPlayerType();\\n             var config = this.getConfiguration();\\n             if (type == \\\'yt\\\') {\\n                 var $tlImg = tljQuery(this.getTlImg());\\n                 var wrappedPlayerInfo = this.getWrappedPlayerInfo();\\n                 var wrappedPlayer = wrappedPlayerInfo.wrappedPlayer\\n                 var $wrappedPlayer = tljQuery(wrappedPlayer);\\n                 this.pauseVideo();\\n                 // take into account the button bar if it is present\\n                 var buttonBarExtra = this.buttonBarDimensions ? this.buttonBarDimensions.height : 0;\\n                 var hookTop = $tlImg.position().top - ($wrappedPlayer.height() + buttonBarExtra);\\n                 if (config.playerSettings.fadeIn) {\\n                     $wrappedPlayer.fadeOut(1000,cb);\\n                 }\\n                 else {\\n                     $wrappedPlayer.animate({"top":hookTop},1500,cb);\\n                 }\\n             }\\n         };\\n \\n         VideoFetcher.prototype.styleAttributes = ["float","padding","border","margin"];\\n \\n         VideoFetcher.prototype.generateSafeStyle = function (cs) {\\n             var importantStyleAttributes = this.styleAttributes;\\n             var safeStyle = [];\\n             importantStyleAttributes.forEach(function (sa) {\\n                 var ss = {};\\n                 ss.name = sa;\\n                 if (sa === "float") {\\n                     ss.val = this.getSafeFloat(cs);\\n                 }\\n                 else if (sa === "padding") { \\n                     ss.val = this.getSafePadding(cs);\\n                 }\\n                 else if (sa === "border") {\\n                     ss.val = this.getSafeBorder(cs);\\n                 }\\n                 else if (sa === "margin") {\\n                     ss.val = this.getSafeMargin(cs);\\n                 }\\n                 else {\\n                     ss.val = cs[sa];\\n                 }\\n                 safeStyle.push(ss);\\n             }.bind(this));\\n             return safeStyle;\\n         };\\n \\n         VideoFetcher.prototype.getSafeFloat = function (cs) { \\n             var test1,test2;\\n             test1 = cs.float;\\n             test2 = cs.cssFloat;\\n             if (test1 && test1.length) {\\n                 return test1;\\n             }\\n             return test2;\\n         };\\n         \\n         VideoFetcher.prototype.getSafeMargin = function (cs) { \\n             var test1,test2;\\n             test1 = cs.margin;\\n             test2 = cs.marginTop+\\\' \\\'+cs.marginRight+\\\' \\\'+cs.marginBottom+\\\' \\\'+cs.marginLeft;\\n             if (test1 && test1.length) {\\n                 return test1;\\n             }\\n             return test2;\\n         };\\n         \\n         VideoFetcher.prototype.getSafePadding = function (cs) { \\n             var test1,test2;\\n             test1 = cs.padding;\\n             test2 = cs.paddingTop+\\\' \\\'+cs.paddingRight+\\\' \\\'+cs.paddingBottom+\\\' \\\'+cs.paddingLeft;\\n             if (test1 && test1.length) {\\n                 return test1;\\n             }\\n             return test2;\\n         };\\n         \\n         VideoFetcher.prototype.getSafeBorder = function (cs) { \\n             var test1,test2;\\n             test1 = cs.border;\\n             test2 = cs.borderTop+\\\' \\\'+cs.borderRight+\\\' \\\'+cs.borderBottom+\\\' \\\'+cs.borderLeft;\\n             if (test1 && test1.length) {\\n                 return test1;\\n             }\\n             return test2;\\n         };\\n \\n         VideoFetcher.prototype.setStyleAttributes = function ($wppp) { \\n             var $tlImg = tljQuery(this.getTlImg());\\n             var cs = window.getComputedStyle($tlImg[0]);\\n             var safeStyle = this.generateSafeStyle(cs); \\n             safeStyle.forEach(function (s) {\\n                 $wppp.style(s.name,s.val);\\n             });\\n             \\n         };\\n \\n         VideoFetcher.prototype.removeImageStyling = function ($img) {\\n             $img.style("float","none");\\n             $img.style("padding","0px 0px 0px 0px");\\n             $img.style("border","0px");\\n             $img.style("margin","0px");\\n             if (!inv_code.match("fansided_main_largefeature")) {\\n                 $img.style("background","none");\\n             }\\n         };\\n \\n         VideoFetcher.prototype.findPlayerHook = function () {\\n             var $tlImg = tljQuery(this.getTlImg());\\n             var $unit = this.getUnit();\\n             var $tlImg = tljQuery(this.getTlImg());\\n             var tlImg = $tlImg[0];\\n             var w = $tlImg.width();\\n             var h = $tlImg.height();\\n \\n             var d = document.createElement(\\\'div\\\');\\n             var $wppp = tljQuery(d);\\n             this.setStyleAttributes($wppp);\\n             this.removeImageStyling($tlImg); \\n             // if the tlImg is absolutely positioned, then we also absolutely position this div\\n             // otherwise we position it relatively, since we don\\\'t want to otherwise change the document layout\\n             var cs = window.getComputedStyle(this.getTlImg());\\n             var absoluteFlag = false;\\n             if (cs.position === \\\'absolute\\\') {\\n                 absoluteFlag = true;\\n                 d.style.position = "absolute";\\n             }\\n             else {\\n                 d.style.position = "relative";\\n             }\\n             d.style.overflow = "hidden";\\n             var imageParent = $tlImg[0].parentNode;\\n             var $outterParent = tljQuery(imageParent);\\n             while (($outterParent.width() < (w-10)) || ($outterParent.height() < (h-10))) {\\n                 $outterParent = tljQuery($outterParent[0].parentNode);\\n                 if (!$outterParent[0]) {\\n                     throw new Error(\\\'could not find player hook\\\');\\n                 }\\n             }\\n             var opw = $outterParent.width();\\n             var oph = $outterParent.height();\\n             // if the outter container is smaller than the image, we have to set the hook dimensions\\n             // to be those of the outer parent\\n             if (opw < w) {\\n                 w = opw;\\n             }\\n             if (oph < h) {\\n                 h = oph;\\n             }\\n             d.style.width = w+"px"\\n             d.style.height = h+"px";\\n             imageParent.insertBefore(d,tlImg);\\n             if (absoluteFlag) {\\n                 d.style.top = cs[\\\'top\\\'];\\n                 d.style.left = cs[\\\'left\\\'];\\n             }\\n             d.appendChild(tlImg);\\n             var adjustedDimensions = ad = this.adjustDimensions(w,h);\\n             return { width:ad.w, height:ad.h, hook:d, outterParent:$outterParent[0] };\\n         };\\n \\n         VideoFetcher.prototype.xButtonHeight       = 36;\\n         VideoFetcher.prototype.xButtonWidth        = 36;\\n         VideoFetcher.prototype.playerControlHeight = 36;\\n         VideoFetcher.prototype.xButtonGap          = 20;\\n \\n         VideoFetcher.prototype.initAPI = function () {\\n             // load the api\\n             var tag = document.createElement(\\\'script\\\');\\n             tag.src = "https://www.youtube.com/player_api";\\n             var firstScriptTag = document.getElementsByTagName(\\\'script\\\')[0];\\n             firstScriptTag.parentNode.insertBefore(tag, firstScriptTag);\\n         };\\n \\n         VideoFetcher.prototype.determineButtonBarDimensions = function () {\\n             var configuration = this.getConfiguration();\\n             var size = this.getImageSize();\\n             var width = tljQuery(this.getTlImg()).width();\\n             var height = this.xButtonHeight;\\n             var ar = width/height;\\n             var inverse_ar = height/ar;\\n             if (size === "small") {\\n                 height = Math.round(height/2);\\n                 this.xButtonWidth = Math.round(this.xButtonWidth/2);\\n                 this.xButtonHeight = Math.round(this.xButtonHeight/2);\\n                 this.xButtonGap = 10;\\n             }\\n             // if we show the player controls, the buttons should be the same size\\n             else if (configuration.showControls) {\\n                 height = 27;\\n             }\\n             this.buttonBarDimensions = {width:width,height:height};\\n         };\\n \\n \\n         VideoFetcher.prototype.appendButtonBar = function (wrappedPlayer,playerEl) {\\n             var iwidth = this.buttonBarDimensions.width;\\n             var iheight = this.buttonBarDimensions.height;\\n             var d = document.createElement(\\\'DIV\\\');\\n             var $d = tljQuery(d);\\n             var i = document.createElement(\\\'IMG\\\');\\n             i.src = this.getAsset(\\\'xbutton\\\');\\n             $i = tljQuery(i);\\n             //  remove padding, float, margin\\n             this.removeImageStyling($i);\\n             $i.style("min-width","0","important");\\n             $i.style("min-height","0","important");\\n             $i.style("position","absolute","important");\\n             $i.style("width",this.xButtonWidth+"px","important");\\n             $i.style("height",this.xButtonHeight+"px","important");\\n             $i.style("top","0px","important");\\n             $i.style("left","0px","important");\\n             d.style[\\\'background-color\\\'] = \\\'black\\\';\\n             $d.style("position","absolute","important");\\n             $d.style("width",tljQuery(wrappedPlayer).width()+"px","important");\\n             $d.style("height",this.buttonBarDimensions.height+"px","important");\\n             $d.style("top",tljQuery(playerEl).height()+"px");\\n             var xoff = this.addSeeMore(d,$d);\\n             this.addShareTypes(d,$d,xoff);\\n             this.videoToggler = new VideoToggler(i,this);\\n             this.addPlayButtonClick();\\n             d.appendChild(i);\\n             wrappedPlayer.appendChild(d);\\n         };\\n         \\n         // appendButtonBarMobile is just like appendButtonBar, except that no x button is given\\n         // since mobile units cannot drive play events programatically\\n         VideoFetcher.prototype.appendButtonBarMobile = function (wrappedPlayer,playerEl) {\\n             var iwidth = this.buttonBarDimensions.width;\\n             var iheight = this.buttonBarDimensions.height;\\n             var d = document.createElement(\\\'DIV\\\');\\n             var $d = tljQuery(d);\\n             d.style[\\\'background-color\\\'] = \\\'black\\\';\\n             $d.style("position","absolute","important");\\n             $d.style("width",tljQuery(wrappedPlayer).width()+"px","important");\\n             $d.style("height",this.buttonBarDimensions.height+"px","important");\\n             $d.style("top",tljQuery(playerEl).height()+"px");\\n             var xoff = this.addSeeMore(d,$d,10);\\n             this.addShareTypes(d,$d,xoff);\\n             this.addPlayButtonClick();\\n             wrappedPlayer.appendChild(d);\\n         };\\n \\n         // VideoFetcher.prototype.addPlayButtonClick\\n         // once the video has been toggled off, when the play button is clicked it should toggle the video back in\\n         VideoFetcher.prototype.addPlayButtonClick = function () {\\n             var that = this;\\n             this.pb.click(function () { that.videoToggler.toggle() });\\n         };\\n \\n         // style the social sharing buttons for the button bar\\n         VideoFetcher.prototype.styleBarShareButton = function ($i,w,h,x,y) {\\n             $i.style("min-width","0","important");\\n             $i.style("min-height","0","important");\\n             $i.style("width",w+"px","important");\\n             $i.style("height",h+"px","important");\\n             $i.style("position","absolute","important");\\n             $i.style("top",y+"px","important");\\n             $i.style("left",x+"px","important");\\n         };\\n \\n         // determineBarShareButtonXoff determine where to beging to lay the button bars\\n         // if there is a seemore button, lay them after that button\\n         // otherwise +20px after the xbutton\\n         VideoFetcher.prototype.determineBarShareButtonXoff = function (xoff,pos) {\\n             var x;\\n             if (xoff) {\\n                 x = xoff;\\n             }\\n             else {\\n                 x = pos.left+(this.xButtonWidth+this.xButtonGap); // take into account the x button\\n             }\\n             return x;\\n         };\\n \\n         // addBarHorizontalShareButtons: layout the share buttons in a horizontal row\\n         VideoFetcher.prototype.addBarHorizontalShareButtons = function (div,$div,xoff) {\\n             var w = $div.width();\\n             var h = 34;\\n             var pos = $div.position();\\n             var x = this.determineBarShareButtonXoff(xoff,pos);\\n             var y = pos.top;\\n             var that = this;\\n             var sbw = 45;\\n             var sbh = h;\\n             var size = this.getImageSize();\\n             if (size ==="small") {\\n                 sbw = Math.round(sbw/2);\\n                 sbh = Math.round(sbh/2);\\n                 y = (pos.top+$div.height())-sbh;\\n             }\\n             this.shareTypes.forEach(function (st) {\\n                 if ((x+sbw) > w) {\\n                     return;\\n                 }\\n                 var i = document.createElement(\\\'IMG\\\');\\n                 var $i = tljQuery(i);\\n                 // remove float, padding, etc\\n                 that.removeImageStyling($i);\\n                 i.src = that.getAsset(st);\\n                 that.styleBarShareButton($i,sbw,sbh,x,y);\\n                 that.addClick({type:st},$i);\\n                 div.appendChild(i);\\n                 x += (sbw+10);\\n             });\\n             return x;\\n         };\\n \\n         VideoFetcher.prototype.determineBarButtonSquare = function (x,y,w,h) {\\n             var square = {};\\n             square.x1 = x;\\n             square.y1 = y;\\n             square.x2 = w;\\n             square.y2 = h;\\n             square.midX = Math.round((square.x2-square.x1)/2)+square.x1;\\n             square.midY = Math.round((square.y2-square.y1)/2)+square.y1;\\n             return square;\\n         };\\n \\n         VideoFetcher.prototype.findQuadrantsInSquare = function (square) {\\n             var quadrants = [];\\n             // top left\\n             quadrants.push({x1:square.x1,y1:square.y1});\\n             // top right\\n             quadrants.push({x1:square.midX,y1:square.y1});\\n             // bottom left\\n             quadrants.push({x1:square.x1,y1:square.midY});\\n             // bottom right\\n             quadrants.push({x1:square.midX,y1:square.midY});\\n             return quadrants;\\n         };\\n \\n         // addBarSquareShareButtons add the sharebuttons in the button bar as square grid\\n         // this assumes there won\\\'t be more than 4 share buttons\\n         VideoFetcher.prototype.addBarSquareShareButtons = function (div,$div,xoff) {\\n             var w = this.buttonBarDimensions.width;\\n             var h = this.buttonBarDimensions.height;\\n             var pos = $div.position();\\n             var x = this.determineBarShareButtonXoff(xoff,pos);\\n             var y = pos.top;\\n             var that = this;\\n             var square = this.determineBarButtonSquare(x,y,w,h);\\n             var quadrants = this.findQuadrantsInSquare(square);\\n             // the button dimensions are 3/4 of each quadrant of the square\\n             var sbh = Math.round((((square.y2-square.y1)/2)/4)*3);\\n             var sbw = Math.round(this.shareButtonOriginalRatio * sbh);\\n             this.shareTypes.forEach(function (st,index) {\\n                 var i = document.createElement(\\\'IMG\\\');\\n                 var $i = tljQuery(i);\\n                 // remove float, padding, etc\\n                 that.removeImageStyling($i);\\n                 i.src = that.getAsset(st);\\n                 var quadrant = quadrants[index];\\n                 that.styleBarShareButton($i,sbw,sbh,quadrant.x1,quadrant.y1);\\n                 that.addClick({type:st},$i);\\n                 div.appendChild(i);\\n             });\\n             return true;\\n         };\\n \\n         VideoFetcher.prototype.addShareTypes = function (div,$div,xoff) {\\n             // laying out the buttons in a square pattern does not look good\\n             // so avoid doing so for now\\n             if (true || (this.shareTypes.length <= 2) || this.getImageSize() === "small") {\\n                 return this.addBarHorizontalShareButtons(div,$div,xoff);\\n             }\\n             else {\\n                 this.addBarSquareShareButtons(div,$div,xoff);\\n             }\\n         };\\n \\n         VideoFetcher.prototype.addSeeMore = function (div,$div,xoff) {\\n             var pos = $div.position();\\n             var y = pos.top;\\n             var x;\\n             if (!isNaN(xoff)) {\\n                 x = xoff;\\n             }\\n             else {\\n                 x = pos.left+(this.xButtonWidth+20); // take into account the x button\\n             }\\n             var h = 23;\\n             var ar = 183/23;\\n             var w = Math.round(h*ar);\\n             var size = this.getImageSize();\\n             if (size === "small") {\\n                 w = Math.round(w/2);\\n                 h = Math.round(h/2);\\n             }\\n             y = (pos.top+$div.height())-(h+Math.round(h/3));\\n             var i = document.createElement(\\\'IMG\\\');\\n             var $i = tljQuery(i);\\n             this.removeImageStyling($i);\\n             i.src = this.getAsset("seemore");\\n             $i.style("min-width","0","important");\\n             $i.style("min-height","0","important");\\n             $i.style("width",w+"px","important");\\n             $i.style("height",h+"px","important");\\n             $i.style("position","absolute","important");\\n             $i.style("top",y+"px","important");\\n             $i.style("left",x+"px","important");\\n             this.addClick({type:"seemore"},$i);\\n             div.appendChild(i);\\n             return x+w+10;\\n         };\\n \\n         VideoFetcher.prototype.getAsset = function (st) {\\n             return this.assets[st];\\n         };\\n \\n         VideoFetcher.prototype.beginWait = function (action) {\\n             if (glYTAPI) {\\n                 action.call(this);\\n             }\\n             else {\\n                 var that = this;\\n                 setTimeout(function () {\\n                     that.beginWait(action); },500);\\n             }\\n         };\\n \\n         var VideoToggler = function (button,video) {\\n             var toggleState = 0;\\n             // state 0: playing \\n             // state 1: not playing\\n             var $button = tljQuery(button);\\n             var toggle = function () {\\n                 if (toggleState === 0) {\\n                     video.setPlayerShow(false);\\n                     toggleState = 1;\\n                     button.src = video.getAsset("whiteplaybutton");\\n                     video.mouseButtonToggler && video.mouseButtonToggler.adjustButtonState(video.buttonToggleEvents.TOGGLEOFF);\\n                     video.hide(function () {video.resetPlayButton();});\\n                 }\\n                 else {\\n                     video.setPlayerShow(true);\\n                     video.mouseButtonToggler && video.mouseButtonToggler.adjustButtonState(video.buttonToggleEvents.TOGGLEON);\\n                     toggleState = 0;\\n                     button.src = video.getAsset(\\\'xbutton\\\');\\n                     video.preHoverOff();\\n                     video.show();\\n                 }\\n             };\\n             tljQuery(button).click(toggle);\\n             var $tlImg = video.fansided_largefeature_check();\\n             $tlImg.click(function (e) {\\n                 toggle();\\n             });\\n             this.toggle = toggle;\\n             this.getToggleState = function () { return toggleState; };\\n             this.PLAYING = 0;\\n             this.NOT_PLAYING = 1;\\n         };\\n         \\n         // on fansided_main_largefeature, a css rule sets an A element sibling of the main image to have a pseudo-before element, the effect of which is to make the A element behave as though it were the parent of the image\\n         // this function returns that A element as a jQuery object\\n         // otherwise it returns the main ad image\\n         VideoFetcher.prototype.fansided_largefeature_check = function () {\\n             if (inv_code.match("fansided_main_largefeature")) {\\n                 var $a = tljQuery(this.getUnit()[0].getElementsByTagName(\\\'A\\\')[0]);\\n                 // because the A element actually has no height, the padding is used to determine the height\\n                 var aheight = $a.height;\\n                 $a.height = function () {\\n                     var cs = window.getComputedStyle($a[0]);\\n                     return aheight.call($a)+parseInt(cs.paddingBottom);\\n                 };\\n                 return $a;\\n             }\\n             return tljQuery(this.getTlImg());\\n         };\\n         \\n         // VideoFetcher.prototype.init\\n         // after the constructor is called, there are still actions that must be taken\\n         // to get the videoFetcher into a state where it can show videos:\\n         //  the api must be loaded\\n         //  the video type and id must be found\\n         //  the playerHook must be found\\n         //  and the wrappedPlayer div must be instantiated and appended to the DOM\\n         //  init does all these things\\n         VideoFetcher.prototype.init = function  () {\\n             this.isInit = true;\\n             this.lazyLoadVideoInfo(); \\n             this.initAPI();\\n             this.lazyLoadPlayerHookData();\\n             this.lazyLoadWrappedPlayer();\\n             this.beginWait(function () { this.setPrePlay(); this.registerVideoAd(); });\\n         };\\n         \\n         optionalStartVideo = function () {\\n             var videoConfig = {};\\n             videoConfig.render_strategy = \\\'%%%HOVER_ACTION%%%\\\';\\n             // this makes things a little clearer when dispatching on the render strategy object above\\n             // since a "false" strategy makes little sense\\n             if (videoConfig.render_strategy === \\\'0\\\') {\\n                 videoConfig.render_strategy = \\\'none\\\';\\n             }\\n             // should click the video take the user to the clickthrough?\\n             videoConfig.transparentClickThroughDiv = true; /* default until we can pass this through the scu */\\n             // settings of the play button image that is appended pre-play\\n             videoConfig.playButtonSettings = {};\\n             videoConfig.playButtonSettings.width = 0.3;\\n             videoConfig.playButtonSettings.alignment = \\\'center\\\';\\n             videoConfig.playButtonSettings.showOnHover = false;\\n             // player settings\\n             videoConfig.playerSettings = {};\\n             videoConfig.playerSettings.showControls = \\\'%%%EXPOSE_CONTROLS%%%\\\';\\n             // if show controls is "false", make it a real boolean\\n             if (videoConfig.playerSettings.showControls === \\\'0\\\') {//TODO make true by default\\n                 videoConfig.playerSettings.showControls = false;\\n             }\\n             else {\\n                 videoConfig.playerSettings.showControls = true;\\n             }\\n             videoConfig.playerSettings.resetVideo = \\\'%%%RESET_VIDEO%%%\\\';\\n             if (videoConfig.playerSettings.resetVideo === \\\'0\\\') {\\n                 videoConfig.playerSettings.resetVideo = false;\\n             }\\n             else {\\n                 videoConfig.playerSettings.resetVideo = true;\\n             }\\n             // ALWAYS_SHOW_BUTTONS determines if the share buttons should dissapear when the user hovers off\\n             videoConfig.playerSettings.alwaysShowButtons = \\\'%%%ALWAYS_SHOW_BUTTONS%%%\\\';\\n             if (videoConfig.playerSettings.alwaysShowButtons === \\\'0\\\') {\\n                 videoConfig.playerSettings.alwaysShowButtons = false;\\n             }\\n             else {\\n                 videoConfig.playerSettings.alwaysShowButtons = true;\\n             }\\n             videoConfig.playerSettings.showOnHover = true;\\n             // either fade the video in or, if false, slide the player in\\n             // NOTE: for IE we must slide the player in\\n             videoConfig.playerSettings.fadeIn = true;\\n             // navigator is unreliable, but most of our users won\\\'t lie, and this doesn\\\'t break anything--it only determines how the share buttons will be laid out on the video\\n             if (navigator && navigator.userAgent && (navigator.userAgent.match("MSIE")||navigator.userAgent.match(/trident/i))) { \\n                 // in IE, to prevent the flash element from convering the share buttons, we use the html5 player\\n                 // where possible, otherwise we use the buttonBar -- ie we put the buttons beneath the player\\n                 if (VideoFetcher.prototype.supportsHTML5Video) {\\n                     VideoFetcher.prototype.IEHTML5 = true;\\n                     videoConfig.playerSettings.buttonBar = false;\\n                 }\\n                 else {\\n                     videoConfig.playerSettings.buttonBar = true;\\n                     videoConfig.playerSettings.fadeIn    = false;\\n                 }\\n             }\\n             else if (isMobile()) {\\n                 videoConfig.playerSettings.buttonBarMobile = true;\\n                 videoConfig.isMobile = true;\\n             }\\n             else {\\n                 videoConfig.playerSettings.buttonBar = false;\\n             }\\n             videoConfig.$referenceImage = shareButtons.$referenceImage;\\n             // IE 8 fix -- but IE 8 is not currently supported\\n             if (unit.getElementsByClassName) {\\n                 if (unit.getElementsByClassName(\\\'tl-vid\\\').length) {\\n                     var vf = new VideoFetcher(tljQuery(unit),analyticsController,toggleShareButton,videoConfig);\\n                     vf.init();\\n                 }\\n             }\\n             else {\\n                 if (unit.querySelectorAll && unit.querySelectorAll(\\\'.tl-vid\\\').length) {\\n                     var vf = new VideoFetcher(tljQuery(unit),analyticsController,toggleShareButton,videoConfig);\\n                     vf.init();\\n                 }\\n             }\\n         };\\n \\n         var ProgressBar = function (videoFetcher,pb,cb) {\\n             // instantiate a progress bar controller\\n             // these should only be instantiated when the user is already engaged\\n             // with whatever needs a progress bar\\n             // ie the hovered property of these objects is initalized to true\\n             var config = videoFetcher.getConfiguration();\\n             var maxVal = pb.max = config.progressLimit;\\n             var currentVal = pb.value = 0;\\n             // for IE <= 9 we set the width of the internal span\\n             var IESpan = pb.getElementsByTagName(\\\'SPAN\\\')[0];\\n             var setIESpanWidth = function (val,max) {\\n                 IESpan.style.width = Math.round(100*(val/max))+"%";\\n             };\\n             var removed = false;\\n             var removeProgressBar = this.removeProgressBar = function () {\\n                 if (!removed) { // if the ad is clicked before the progress bar completes, it will already have been removed\\n                     removed = true;\\n                     pb.parentNode.removeChild(pb);\\n                 }\\n             };\\n             var interval = 50; // ms\\n             var hovered = true;\\n             var toggler = function (msg) {\\n                 if (msg === \\\'off\\\') {\\n                     hovered = false;\\n                 }\\n             };\\n             // return a box representing the unit\\n             this.getBox = function () {\\n                 var $unit = videoFetcher.getUnit();\\n                 $unit = this.checkUnit($unit);\\n                 var offset = $unit.offset();\\n                 var box = {};\\n                 box.x1 = offset.left;\\n                 box.x2 = offset.left+$unit.width();\\n                 box.y1 = offset.top;\\n                 box.y2 = offset.top+$unit.height();\\n                 return box;\\n             };\\n             // check if the jQuery object is large enough to be the unit\\n             // since the vast majority of our units are structured as a div displayed inline\\n             // with a single child, the unit itself often has a width and height of 0, and it\\\'s the child we are interested in\\n             // but some units have a leading <br> or <hr> so we check all the children until we find the best candidate\\n             this.checkUnit = function ($unit) {\\n                 var check = function ($unit) {\\n                     var w = $unit.width();\\n                     var h = $unit.height();\\n                     var $tlImg = tljQuery(videoFetcher.getTlImg());\\n                     var tlw = $tlImg.width();\\n                     var tlh = $tlImg.height();\\n                     var buffer = 10;\\n                     if ((w < (tlw-buffer)) || (h < (tlh - buffer))) {\\n                         return false;\\n                     }\\n                     return true;\\n                 };\\n                 var $base = $unit;\\n                 var $children = $unit.children();\\n                 var i = 0;\\n                 var ii = $children.length\\n                 while ((!check($unit)) && (i<ii)) {\\n                     $unit = tljQuery($children[i]);\\n                     i++;\\n                 }\\n                 return $unit;\\n             };\\n \\n             var offchecker = decorateOffChecker(null,toggler,this);\\n             var recursiveMonitor = function () {\\n                 if (!hovered) {\\n                     stopMonitor();\\n                     removeProgressBar();\\n                 }\\n                 else {\\n                     currentVal += interval;\\n                     pb.value = currentVal;\\n                     setIESpanWidth(currentVal,maxVal);\\n                     if (currentVal >= maxVal) {\\n                         stopMonitor();\\n                         removeProgressBar();\\n                         videoFetcher.progressSet = true;\\n                         cb();\\n                     }\\n                     else {\\n                         setTimeout(recursiveMonitor,interval);\\n                     }\\n                 }\\n             };\\n             var monitor = function (e) {\\n                 offchecker(e);\\n             };\\n \\n             this.startMonitor = function () {\\n                 tljQuery(document).bind(\\\'mousemove\\\',monitor);\\n                 recursiveMonitor();\\n             };\\n \\n             var stopMonitor = function () { \\n                 tljQuery(document).unbind(\\\'mousemove\\\',monitor);\\n             };\\n         };\\n \\n         // TODO: in the future, the VideoFetcher and ShareButtons objects will use this\\n         // to position their share and play buttons\\n         var Positioner = function (area) { };\\n \\n         var tlImg = shareButtons.$referenceImage[0];\\n         var $tlImg = shareButtons.$referenceImage;\\n         // div\\\'s don\\\'t complete, so we explicitly check here\\n         if (tlImg.complete) {\\n            optionalStartVideo();\\n         }\\n         else if ($tlImg.isDiv) {\\n             shareButtons.listenForLoad(optionalStartVideo);\\n         }\\n         else {\\n             tljQuery(tlImg).on(\\\'load\\\',optionalStartVideo);\\n         }\\n         \\n     \\n   // set hover handler\\n   var hoverConfig = {over : function () {analyticsController.hover()}, sensitivity: 5, out : offChecker};\\n   tljQuery(unit).hoverIntent(hoverConfig);\\n   tljQuery(unit).mouseleave(offChecker);\\n   // run an imp trial\\n   (function imptrial () {\\n    // MDN recommends the following formula to get an even distribution across a given range of integers, a and b, where a<b and the range is a inclusive and b exclusive\\n    // randomInt = Math.floor(Math.random * ((b-a+1)+a)\\n    // this works to:  randomInt = Math.floor(Math.random() * (n+1))\\n     // what we want though is a random int between 0-n, such that 0 is exlusive and n inclusive\\n     // this is because is the sample rate is eaqual to one, we want to fire an impression each time\\n     // we can use Math.ceild to accomplish this\\n     // randomInt = Math.ceil(Math.random() * n)\\n             var tlExplicitSampleRate = parseInt(\\\'```TL_EXPLICIT_SR```\\\',10);\\n             var sr;\\n             if (!isNaN(tlExplicitSampleRate)) {\\n                 sr = tlExplicitSampleRate;\\n             }\\n             else {\\n                 sr = 10;\\n             }\\n             var t = Math.ceil(Math.random() * sr); \\n    if (t === 1) {\\n     analyticsController.imp(sr);\\n    }\\n   })();\\n     };\\n  check_jq();\\n  \\n  return function (st) { ts(st); };\\n })();\\n \\n var updateLogoZones = function (json) {\\n     var qs = json.qs;\\n     var lp = json.lp;\\n     var images = document.getElementsByTagName(\\\'IMG\\\');\\n     var image, $image;\\n     var i = 0;\\n     var ii = images.length;\\n     for (;i<ii;i++) {\\n         image = images[i];\\n         if (image.src && image.src.match(qs)) {\\n             $image = jQuery(image);\\n             break;\\n         }\\n     }\\n     $image.attr("lp",lp);\\n };\\n \\n }\\n catch (e) {\\n     var p = document.createElement(\\\'IMG\\\');\\n  p.src= "//eb.3lift.com/sce?block=analytics&inv_code=psmag_article_big&e="+encodeURIComponent(e);\\n  p.width = 0;\\n  p.height = 0;\\n  document.body.appendChild(p);\\n }\\n \')).replace(\'@@@PLACEMENT_HTML@@@\',createTemplate(\'<div class=\"inPostVideo\" style=\"display:block;\"><div class=\"catPageHatch\"></div><h3 class=\"videoSectionHeader\" style=\"margin-bottom: 0px;\">A Message from <a class=\"tvLink\" target=\"_blank\" href=\"%%%CLICKTHROUGH_URL%%%\" target=\"_blank\" style=\"color: #23AAEB;\">%%%ADVERTISER_NAME%%%</a></h3><a href=\"%%%CLICKTHROUGH_URL%%%\" target=\"_blank\"><img src=\"%%%IMAGE_URL%%%\" ></a><h5 style=\"margin-bottom: 5px; font-size: 20px;\"><a href=\"%%%CLICKTHROUGH_URL%%%\" target=\"_blank\">%%%HEADING%%%</a></h5><div class=\"entry-content\"><span class=\"caption\"><p>%%%CAPTION%%%</p></span></div></div><hr>\')).replace(\'@@@TL_RD_ID@@@\',tl_rd).replace(\'@@@IMAGEID@@@\',trending_item.image_id);\n    scriptBody = scriptBody.replace(\'@@@UNIT_DATA@@@\',unitData);\n    scriptBody = scriptBody.replace(\'@@@CAPTION@@@\',trending_item.caption);\n    scriptBody = scriptBody.replace(\'@@@UNIT_ID@@@\',unitData);\n    scriptBody = scriptBody.replace(\'@@@IMAGEID@@@\',trending_item.image_id);\n    scriptBody = scriptBody.replace(\'@@@THIRD_PARTY_SAMPLING_RATE@@@\',settings.impression_sampling_rate);\n    scriptBody = scriptBody.replace(\'@@@THIRD_PARTY_DISCREPANCY_RATE@@@\',settings.impression_discrepancy_rate);\n             scriptBody = scriptBody.replace(\'@@@COMSCORESRC@@@\',JSON.stringify(trending_item.comScoreArr));\n             if (trending_item.share_types) {\n     scriptBody = scriptBody.replace(\'@@@UNIT_SHARE_ENABLED@@@\', \'true\');\n    }\n    else {\n     scriptBody = scriptBody.replace(\'@@@UNIT_SHARE_ENABLED@@@\', \'false\');\n    }\n    return scriptBody;\n   };\n   // if the caption is too long\n   // truncate it\n   var captionLimit = parseInt(0);\n   if ((trending_item.caption.length > captionLimit) && (captionLimit > 0)) {\n    trending_item.caption = trending_item.caption.substr(0,captionLimit-3) + "...";\n   }\n   scriptText = writeScriptText();\n   appendScript();\n  };\n  ###TL_IFRAME_FOOTER###\n } catch (e) { \n  var p = document.createElement(\'IMG\');\n  p.src= "//eb.3lift.com/sce?block=tl_iframe&inv_code=psmag_article_big&e="+encodeURIComponent(e);\n  p.width = 0;\n  p.height = 0;\n  document.body.appendChild(p);\n }\n '.replace(/###TL_SD_ID###/g,'tl_sd'+_tl.cc);tl_if_body=tl_if_body.replace('###TL_IF_ID###',tl_if_id);tl_if_body=tl_if_body.replace(/###TTJ_CT_URL###/g,ttj_ct);var call_adnxs='//Request TripleLift Sponsored Content Unit ID (AppNexus Creative Code)\n // According to a given sample rate\n var tlt = ###TRIPLELIFT_TEST###;\n var explicitBidParams = "###TRIPLELIFT_BID_PARAMS###";\n var isMobile = function () {\n  return (navigator && navigator.userAgent && navigator.userAgent.match(/iphone|android/i));\n };\n if (Math.ceil(Math.random() * 1) === 1) {\n     /*\n      * SET UP IFRAME CREATIVE LOGIC\n      */\n     // stash document.write in case we get an iframe creative back from adnxs\n     var oldWriter = document.write;\n \n     // stub out document.write with a function that appends content to the DOM\n     document.write = function (str) {\n         var d = document.createElement("div");\n         d.style.display = "none";\n         document.body.appendChild(d);\n         d.innerHTML = str;\n     };\n     // add an event listener in case an iframe creative is served\n     window.addEventListener("message", function (event) {\n         // only respond to messages we know are from an iframe creative\n         if (event.data.match("get_3p")) {\n             var scriptBody = event.data;\n             var s = document.createElement(\'SCRIPT\');\n             s.textContent = scriptBody;\n             document.body.appendChild(s);\n             document.write = oldWriter;\n         }\n     });\n \n     /*\n      * END IFRAME CREATIVE LOGIC \n      */\n \n \n  var a = document.createElement(\'script\');\n     var adnxsURI;\n     if (tlt && explicitBidParams !== "undefined") {\n         adnxsURI = \'//mob.adnxs.com/mob\'+explicitBidParams;\n     }\n     else {\n         adnxsURI = \'//mob.adnxs.com/mob?inv_code=psmag_article_big&member=1314&st=\' + (isMobile() ? \'mobile_web\' : \'web\')+ \'&cb=\' + Math.floor(89999999*Math.random()+10000000);\n     }\n     if (tlt || false) {\n         adnxsURI += "&test=true";\n     }\n  a.setAttribute(\'src\',adnxsURI); \n  ADNXSstart = new Date().getTime();\n  document.body.appendChild(a);\n  // give adnxs variable amount of ms to get back\n  setTimeout(function () {\n   if (ADNXSTimeout) {\n    has_been_timed_out = true;\n    serveDefault("adnxs timeout");\n   }\n  }, 10000);\n }\n else {\n  serveDefault("an_sample");\n }\n ';var tlt=_tl.tlTest;if(tlt){call_adnxs=call_adnxs.replace('###TRIPLELIFT_TEST###','true');}
else{call_adnxs=call_adnxs.replace('###TRIPLELIFT_TEST###','false');}
call_adnxs=call_adnxs.replace("###TRIPLELIFT_BID_PARAMS###",_tl.tlBidParams);tl_if_body=tl_if_body.replace('```SCRIPT_NUMBER```',scriptNumber);tl_if_body=tl_if_body.replace('```TL_EXPLICIT_SR```',_tl.tlsr);var get_unit='(function () {\n     if ("###SCU_UNIT_TYPE###" === "tl") {\n         get_unit(###SCU_ID###);\n     }\n     else {\n         get_3p_unit(###SCU_ID###);\n     }\n })();\n ';var tl_iframe_header='<html><head></head><body>';tl_if.setAttribute('src','about:blank');tl_if.setAttribute('id',tl_if_id);tl_if.style.display="none";tl_if.width=0;tl_if.height=0;tl_script.parentNode.insertBefore(tl_if,tl_script);tl_if.contentWindow.document.open();if(!scu_id){var sc=tl_iframe_header+'<scr'+'ipt>'+tl_if_body.replace('###TL_IFRAME_FOOTER###',call_adnxs)+' </scr'+'ipt></body></html>';tl_if.contentWindow.document.write(sc);}
else{tl_if_body=tl_if_body.replace('###TL_IFRAME_FOOTER###',get_unit);tl_if.contentWindow.document.write((tl_iframe_header+'<scr'+'ipt>'+tl_if_body+'</scr'+'ipt></body></html>').replace(/###SCU_ID###/g,scu_id).replace(/###SCU_UNIT_TYPE###/g,type));}
tl_if.contentWindow.document.close();setTimeout(function(){serveDefaultController.sd('global timeout');},10000+Math.round(10000/3));};var checkForMetaTag=function(){var metaTags=document.getElementsByTagName('META');var i=0,ii=metaTags.length;var mt;for(;i<ii;i++){mt=metaTags[i];if(mt.hasAttribute&&mt.getAttribute){if(mt.hasAttribute('name')&&(mt.getAttribute('name')==='triplelift-brand-safe')){if(mt.hasAttribute('content')&&(mt.getAttribute('content')==='no')){return true;}}}
else{if(mt['name']&&(mt['name']==='triplelift-brand-safe')){if(mt['content']&&(mt['content']==='no')){return true;}}}}
return false;};_tl['tl_sd'+_tl.count()]=serveDefaultController;if(checkForMetaTag()){return serveDefaultController.sd('publisher default');}
var AdLoader=function(){var loadAd=function(){serveSponsoredAd();};var loaded=false;this.load=function(){if(!loaded){loadAd();loaded=true;}}};var adLoader=new AdLoader();var findClosestPositionedElement=function(el){if(!el){return false;}
var baseEl=el;var horizontalLeftCheck=function(el){var o;if(!el){return false;}
o=_tl.offset(el);if((o.top>0)){return el;}
return horizontalLeftCheck(el.previousSibling);};var horizontalRightCheck=function(el){var o;if(!el){return false;}
o=_tl.offset(el);if((o.top>0)){return el;}
return horizontalLeftCheck(el.nextSibling);};if(el=horizontalLeftCheck(el)){return el;}
if(el=horizontalRightCheck(el)){return el;}
return findClosestPositionedElement(baseEl.parentNode);};var parsePlacementOptionsJSON=function(){var options='';var parsedOptions;try{parsedOptions=JSON.parse(options);}
catch(e){parsedOptions={};}
return parsedOptions;};var getTLStartElement=function(){if(_tl.isTopLevel(window)){return tl_script;}
try{var p,fe;p=parent;if(parent!==top){while(p&&(p!==top)){p&&(fe=p.frameElement);p=p.parent;}
if(!p){throw new Error("could not find top level window");}
if(!fe){throw new Error("could not find top level frame");}
return fe;}
else{return window.frameElement;}}
catch(e){return false;}};var tlStartElement=getTLStartElement();var viewabilityElement=findClosestPositionedElement(tlStartElement);var placementOptions=parsePlacementOptionsJSON();var recursiveViewabilityCheck=function(){var viewabilityElement=findClosestPositionedElement(tlStartElement);var interval=300;var viewData=_tl.couldBeViewed(viewabilityElement,null,true);if(viewData.closeToView&&!viewabilityController.viewabilityLoadFired){viewabilityController.viewabilityLoadFired=true;viewabilityController.fireViewabilityPix("vbr");_tl.debugMessage("viewability view load: only if viewability based adserving is enabled");adLoader.load();}
else if(viewData.inView&&!viewabilityController.viewabilityViewFired){viewabilityController.viewabilityViewFired=true;viewabilityController.fireViewabilityPix("vbv");_tl.debugMessage("viewability view view");return;}
setTimeout(function(){recursiveViewabilityCheck(viewabilityElement);},interval);};var ViewabilityController=function(){var sr=_tl.tlsr?_tl.tlsr:10;if(Math.ceil(Math.random()*sr)===1){this.enabled=true;}};ViewabilityController.prototype.fireViewabilityPix=function(endpoint){if(this.enabled){var sampleRate=1;var base="//eb2.3lift.com/"+endpoint+"?inv_code=psmag_article_big&ref="+encodeURIComponent(document.URL);var pix=document.createElement('IMG');pix.style.display='none';pix.width=0;pix.height=0;pix.src=base;document.body.appendChild(pix);}};var viewabilityController=new ViewabilityController();if(!placementOptions.viewabilityEnabled){adLoader.load();_tl.debugMessage("viewability adloading disabled");}
else{_tl.debugMessage("viewability adloading enabled");}
if(!viewabilityElement){_tl.fe('could not find positioned element near tl_script');_tl.debugMessage('could not find positioned element near tl_script');adLoader.load();}
else{viewabilityController.fireViewabilityPix("vbs");_tl.debugMessage("viewability view init");recursiveViewabilityCheck();}
var UserSync=function(){var nusp=parseInt('0',10)||0;var start_sync=this.start_sync=function(){_tl.fireEB2Pix('cset','key=tlcookieable&value=true',function(){var iframe=document.createElement('iframe');iframe.src='//ib.3lift.com/user_sync?nusp='+nusp+'?debug='+_tl.debug;iframe.width=0;iframe.height=0;iframe.frameborder=0;iframe.style.display="none";document.body.appendChild(iframe);});}};var userSync=new UserSync();userSync.start_sync();})();}catch(e){if(_tl.debug){console.log('*** TL MESSAGE ***');console.log('CAUGHT ERROR');if(e.stack){console.log(e.stack);}
else{console.log(e);}}
var p=document.createElement('IMG');p.src="//eb.3lift.com/sce?block=master&inv_code=psmag_article_big&e="+encodeURIComponent(e);p.width=0;p.height=0;document.body.appendChild(p);}