1/* 2 * N-JOY ads â GPT lifecycle that survives pjax navigation. 3 * 4 * Full load : define + display every ad slot whose container is on the page. 5 * pjax nav : in-content slots get their <div> swapped, so we destroy + redefine 6 * + display them; the global slots (outside #njp-pjax-root) keep their 7 * <div>, so we just refresh() them for a fresh ad on the new page. 8 * 9 * Slot ids / paths / sizes come verbatim from the client's GPT codes. 10 * ES5 only (this app's browser code is jQuery ES5). 11 */ 12(function () { 13 var SLOTS = { 14 "div-gpt-ad-1781870884903-0": { path: "/120344282/njoy_top", sizes: [1, 1] }, 15 "div-gpt-ad-1781870821819-0": { path: "/120344282/njoy_wallpaper", sizes: [1, 1] }, 16 "div-gpt-ad-1781870127457-0": { path: "/120344282/njoy_megaboard", sizes: [[980, 300], [980, 600], [728, 90], [320, 100], [980, 200], [980, 100], [970, 250], [970, 90], [300, 250]] }, 17 "div-gpt-ad-1781870621512-0": { path: "/120344282/njoy_megaboard_second", sizes: [[320, 100], [980, 200], [980, 300], [980, 600], [970, 90], [970, 250], [728, 90], [980, 100], [300, 250]] }, 18 "div-gpt-ad-1781869801787-0": { path: "/120344282/njoy_medium_rectangle_300x250_first", sizes: [[300, 600], [300, 250], [300, 100], [300, 75], [300, 50]] }, 19 "div-gpt-ad-1781869898977-0": { path: "/120344282/njoy_medium_rectangle_300x250_first", sizes: [[300, 250], [300, 100], [300, 75], [300, 50]] }, 20 "div-gpt-ad-1781870007844-0": { path: "/120344282/njoy_medium_rectangle_300x250_second", sizes: [[300, 600], [300, 250], [300, 100], [300, 75], [300, 50]] }, 21 "div-gpt-ad-1781870039284-0": { path: "/120344282/njoy_medium_rectangle_300x250_second", sizes: [[300, 250], [300, 100], [300, 75], [300, 50]] }, 22 "div-gpt-ad-1781870672189-0": { path: "/120344282/njoy_carousel", sizes: [1, 1] } 23 }; 24 25 // Megaboards carry sizes up to 980px wide. Without a size map, GPT could serve 26 // a 980px creative on a phone and blow out the layout. Restrict by viewport so 27 // mobile only ever gets mobile-width sizes. 28 var MEGABOARDS = { 29 "div-gpt-ad-1781870127457-0": 1, 30 "div-gpt-ad-1781870621512-0": 1 31 }; 32 // Transition interstitial â show once per full load, skip on pjax (don't re-fire per click). 33 var TOP_SLOT = "div-gpt-ad-1781870884903-0"; 34 var megaMap = null; 35 function megaboardMap() { 36 if (megaMap) { return megaMap; } 37 megaMap = googletag.sizeMapping() 38 .addSize([1024, 0], [[980, 600], [980, 300], [980, 200], [980, 100], [970, 250], [970, 90], [728, 90]]) 39 .addSize([728, 0], [[728, 90], [320, 100]]) 40 .addSize([0, 0], [[300, 250], [320, 100], [320, 50]]) 41 .build(); 42 return megaMap; 43 } 44 45 window.googletag = window.googletag || { cmd: [] }; 46 var servicesEnabled = false; 47 48 function present(id) { return !!document.getElementById(id); } 49 50 function presentIds() { 51 var out = [], id; 52 for (id in SLOTS) { 53 if (SLOTS.hasOwnProperty(id) && present(id)) { out.push(id); } 54 } 55 return out; 56 } 57 58 function definedById() { 59 var map = {}; 60 try { 61 var slots = googletag.pubads().getSlots(); 62 for (var i = 0; i < slots.length; i++) { 63 map[slots[i].getSlotElementId()] = slots[i]; 64 } 65 } catch (e) {} 66 return map; 67 } 68 69 function targeting() { 70 var root = document.getElementById("njp-pjax-root"); 71 var aid = (root && root.getAttribute("data-njoy-article")) || "0"; 72 var sid = (root && root.getAttribute("data-njoy-section")) || "160792091"; 73 return { article_id: aid, section_id: sid }; 74 } 75 76 function applyTargeting() { 77 try { 78 var t = targeting(); 79 var template = "unknown"; 80 if (location.pathname === "/") { template = "homepage"; } 81 else if (t.article_id && t.article_id !== "0") { template = "article"; } 82 else if (t.section_id && t.section_id !== "0") { template = "section"; } 83 googletag.pubads().setTargeting("template", template); 84 googletag.pubads().setTargeting("article_id", t.article_id || "0"); 85 googletag.pubads().setTargeting("section_id", t.section_id || ""); 86 } catch (e) {} 87 } 88 89 // Inner pages: the first megaboard belongs INSIDE the white content, right after the 90 // page title â never in the orange hero seam. The homepage places it in its template 91 // (after the live panel), so this only inserts when the div isn't already on the page. 92 function ensureMegaboardPlacement() { 93 var id = "div-gpt-ad-1781870127457-0"; 94 if (document.getElementById(id)) { return; } 95 var title = document.querySelector("#njp-pjax-root .big-section-title"); 96 if (!title || !title.parentNode) { return; } 97 var wrap = document.createElement("div"); 98 wrap.className = "njoy-ad njoy-ad--megaboard-first";
99 wrap.innerHTML = "<!-- SMART START: njoy_megaboard - inner page, between breadcrumb and title -->" 100 + "<div id='" + id + "' style='min-width:320px;min-height:90px;'></div>" 101 + "<!-- SMART END: njoy_megaboard -->"; 102 title.parentNode.insertBefore(wrap, title); 103 } 104 105 function defineIfNeeded(id, defined) { 106 if (defined[id]) { return true; } 107 var cfg = SLOTS[id]; 108 var slot = googletag.defineSlot(cfg.path, cfg.sizes, id); 109 if (!slot) { return false; } 110 if (MEGABOARDS[id]) { slot.defineSizeMapping(megaboardMap()); } 111 slot.addService(googletag.pubads()); 112 return true; 113 } 114 115 // Debug aid (visible only with ads ON, i.e. to the team): flag empty slots so every 116 // position is visible. A dashed placeholder = the slot IS placed/displayed and the blank 117 // is GAM returning no ad for that unit, NOT a code problem. 118 function onSlotRender(event) { 119 var el = document.getElementById(event.slot.getSlotElementId()); 120 var wrap = el && el.parentNode ? el.parentNode : null; 121 if (!wrap || wrap.nodeType !== 1) { return; } 122 if (event.isEmpty) { 123 wrap.setAttribute("data-njoy-empty", event.slot.getAdUnitPath().split("/").pop()); 124 } else { 125 wrap.removeAttribute("data-njoy-empty"); 126 } 127 } 128 129 function initialLoad() { 130 googletag.cmd.push(function () { 131 ensureMegaboardPlacement(); 132 var defined = definedById(); 133 var ids = presentIds(), i; 134 for (i = 0; i < ids.length; i++) { defineIfNeeded(ids[i], defined); } 135 136 applyTargeting(); 137 if (!servicesEnabled) { 138 googletag.pubads().enableSingleRequest(); 139 googletag.pubads().collapseEmptyDivs(); 140 googletag.pubads().addEventListener("slotRenderEnded", onSlotRender); 141 googletag.enableServices(); 142 servicesEnabled = true; 143 } 144 145 for (i = 0; i < ids.length; i++) { googletag.display(ids[i]); } 146 }); 147 } 148 149 function onPjax() { 150 googletag.cmd.push(function () { 151 applyTargeting(); 152 ensureMegaboardPlacement(); 153 154 // Destroy every defined slot except the interstitial, then redefine + display 155 // every slot present on the new page. Uniform handling also covers slots that are 156 // global on most pages but in-content on the homepage (the first megaboard). 157 var defined = definedById(), id, destroy = []; 158 for (id in defined) { 159 if (defined.hasOwnProperty(id) && id !== TOP_SLOT) { destroy.push(defined[id]); } 160 } 161 if (destroy.length) { googletag.destroySlots(destroy); } 162 163 var ids = presentIds(), i, show = []; 164 for (i = 0; i < ids.length; i++) { 165 if (ids[i] === TOP_SLOT) { continue; } 166 if (defineIfNeeded(ids[i], {})) { show.push(ids[i]); } 167 } 168 for (i = 0; i < show.length; i++) { googletag.display(show[i]); } 169 }); 170 } 171 172 if (window.jQuery) { 173 jQuery(document).on("njp:pjax:loaded", onPjax); 174 } 175 176 if (document.readyState === "loading") { 177 document.addEventListener("DOMContentLoaded", initialLoad); 178 } else { 179 initialLoad(); 180 } 181})();
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.