1/** 2 * @file 3 * JS View implementation for 'adition_default' ads view plugin. 4 */ 5var adition = adition || {}; 6adition.srq = adition.srq || []; 7 8// Initialize adition library. 9(function (Drupal, drupalSettings) { 10 const sourceUrl = (document.location.protocol === "https:" ? "https:" : "http:") + "//imagesrv.adition.com/js/srp.js"; 11 12 var srpRequested = false; 13 14 // Fetch and run srp.js (the Adition SDK). Guarded so it only ever runs once. 15 function loadAdition() { 16 if (srpRequested) return; 17 srpRequested = true; 18 var request = new XMLHttpRequest(); 19 request.open('GET', sourceUrl, true); 20 request.onreadystatechange = function () { 21 if (request.readyState !== 4) return; 22 if (request.status === 200) { 23 var script = document.createElement("script"); 24 script.type = "text/javascript"; 25 script.text = request.responseText; 26 document.body.appendChild(script); 27 } else if (request.status === 0) { 28 window.dispatchEvent(new Event('adition_na')); 29 } 30 }; 31 request.send(); 32 } 33 34 function getDidomiListenerMethod() { 35 if (!window.Didomi) return null; 36 if (typeof window.Didomi.on === 'function') return 'on'; 37 if (typeof window.Didomi.addEventListener === 'function') return 'addEventListener'; 38 return null; 39 } 40 41 // Gate the actual ad loading on Didomi vendor consent. The view handler 42 // itself is NOT consent-gated anymore (so ad_entity initialises the 43 // placeholders normally, with no race / layout shift); only the network 44 // request for ads waits here. With no vendor configured we load directly. 45 function loadWhenConsented() { 46 var vendorId = drupalSettings.ad_entity_adition && drupalSettings.ad_entity_adition.didomi_vend
46or_id; 47 if (!vendorId) { 48 loadAdition(); 49 return; 50 } 51 52 function attempt() { 53 if (window.Didomi && 54 typeof window.Didomi.getUserConsentStatusForVendor === 'function' && 55 window.Didomi.getUserConsentStatusForVendor(vendorId) === true) { 56 loadAdition(); 57 return true; 58 } 59 return false; 60 } 61 62 // Didomi exposes a stub before the real SDK is ready (ContentPass), so 63 // use its ready queue and then poll for the real API before binding. 64 window.didomiOnReady = window.didomiOnReady || []; 65 window.didomiOnReady.push(function () { 66 if (attempt()) return; 67 var method = getDidomiListenerMethod(); 68 if (method) { 69 window.Didomi[method]('consent.changed', attempt); 70 } 71 }); 72 } 73 74 // cp('authenticate', cb) is asynchronous â the queue-pushing stub returns 75 // undefined, so a synchronous check would bail out before anything ran. 76 // Decide inside the callback: only paying ContentPass subscribers skip ads. 77 // In environments where ContentPass isn't fully set up (ddev, broken 78 // staging) the callback may never fire, so fall back after a short timeout. 79 var decided = false; 80 function decide() { 81 if (decided) return; 82 decided = true; 83 loadWhenConsented(); 84 } 85 86 try { 87 cp('authenticate', function (err, user) { 88 if (!err && user && typeof user.isLoggedIn === 'function' && 89 user.isLoggedIn() && 90 typeof user.hasValidSubscription === 'function' && 91 user.hasValidSubscription()) { 92 decided = true; // paying ContentPass user â never load ads 93 return; 94 } 95 decide(); 96 }); 97 setTimeout(decide, 2500); 98 } 99 catch (error) { 100 console.info('Failed to load due: ' + sourceUrl, error); 101 decide(); 102 } 103})(Drupal, drupalSettings); 104 105(function (Drupal, drupalSettings, window) { 106 if (typeof adition === undefined) { 107 return; 108 } 109 110 Drupal.ad_entity = Drupal.ad_entity || window.adEntity || {}; 111 Drupal.ad_entity.viewHandlers = Drupal.ad_entity.viewHandlers || {}; 112 var handler = new drupalSettings.ad_entity_adition.Adition(); 113 114 Drupal.ad_entity.viewHandlers.adition_default = { 115 initialize: function (containers, context, settings) { 116 var self = this;
117 if (containers) { 118 adition.srq.push(function(api) { 119 self.initAdServer(api); 120 self.renderAds(api, containers); 121 }); 122 } 123 }, 124 125 /** 126 * Inits ad server configuration. 127 * 128 * @param api 129 */ 130 initAdServer: function(api) { 131 // Set up the adfarm. 132 api.registerAdfarm(handler.getAdFarm()); 133 134 // Set adition params. 135 var aditionParams = handler.getAditionParams(); 136 for (var aditionParam in aditionParams){ 137 if (aditionParams.hasOwnProperty(aditionParam)) { 138 api.setProfile(aditionParam, aditionParams[aditionParam]); 139 } 140 } 141 142 // Set keyword 143 let terms = ''; 144 if (typeof drupalSettings.terms !== 'undefined') { 145 terms = drupalSettings.terms.toString(); 146 } 147 148 let mobileContainerClass = document.getElementsByClassName("mobile--mirror--container")[0]; 149 let isMobileVisible = (mobileContainerClass && mobileContainerClass.style.opacity !== '0' && mobileContainerClass.style.visibility !== 'hidden' && window.getComputedStyle(mobileContainerClass).getPropertyValue('display') !== 'none'); 150 if (isMobileVisible) { 151 terms = terms + ',mobile'; 152 } else { 153 terms = terms + ',desktop'; 154 } 155 156 terms = terms.replace(/^(,)+/, ''); 157 api.setProfile("keyword", terms); 158 }, 159 160 /** 161 * Renders ads. 162 * 163 * @param api 164 * @param containers 165 */ 166 renderAds: function (api, containers) { 167 var self = this; 168 // Render ad positions. 169 Object.values(containers).forEach(function(container, i) { 170 var adPosition = container.el.querySelector('.ad-entity-adition'); 171 if (adPosition) { 172 self.renderAd(adPosition, api); 173 } 174 }); 175 176 api.load().completeRendering(); 177 178 // Register ads pre-render. 179 api.events.onPreRender(function(adPosition, bannerDescriptionApi, renderControlApi) { 180 self.preRenderAd(adPosition, api, bannerDescriptionApi, renderControlApi); 181 }); 182 183 // Register ads post-render. 184 api.events.onPostRender(function(adPosition, bannerDescriptionApi, renderControlApi) { 185 self.postRenderAd(adPosition, api, bannerDescriptionApi, renderControlApi); 186 187 }); 188 189 // Register ads no-banner. 190 api.events.onNoBanner(function(adPosition, bannerDescriptionApi, renderControlApi) { 191 self.NoBanner(adPosition, api, bannerDescriptionApi, renderControlApi); 192 }); 193 }, 194 195 /** 196 * Renders ad position. 197 * 198 * @param adPosition 199 * @param api 200 */ 201 renderAd: function(adPosition, api) { 202 var name = adPosition.dataset.adPositionName; 203 var id = parseInt(adPosition.dataset.adPositionId); 204 if (id) { 205 api.configureRenderSlot(name).setContentunitId(id); 206 api.renderSlot(name); 207 } 208 }, 209 210 /** 211 * Pre-renders ads. 212 * 213 * @param adPosition 214 * @param api 215 * @param bannerDescriptionApi 216 * @param renderControlApi 217 */ 218 preRenderAd: function(adPosition, api, bannerDescriptionApi, renderControlApi) { 219 var container = adPosition.closest('.ad-entity-container'); 220 if (container) { 221 // Do not display banner empty banners (option "blocker" is "1"). 222 223 if (bannerDescriptionApi.getOptions().blocker === '1') { 224 renderControlApi.disable(); 225 container.style.display = 'none'; 226 if (container.closest('.tile__wrapper')) { 227 container.closest('.tile__wrapper').remove(); 228 } 229 } 230 else { 231 container.display = 'block'; 232 container.classList.remove('not-initialized'); 233 container.classList.add('initialized'); 234 } 235 } 236 }, 237 238 /** 239 * Post-renders ads. 240 * 241 * @param adPosition 242 * @param api 243 * @param bannerDescriptionApi 244 * @param renderControlApi 245 */ 246 postRenderAd: function(adPosition, api, bannerDescriptionApi, renderControlApi) { 247 var container = adPosition.closest('.ad-entity-container'); 248 var iFrame = adPosition.getElementsByTagName('iframe')[0]; 249 250 // Hide empty ads. 251 if (!iFrame.contentDocument || bannerDescriptionApi.getOptions().noAd === '1') { 252 adPosition.classList.add('no-ad'); 253 container.style.display = 'none'; 254 } 255 var aditionId = parseInt(adPosition.dataset.adPositionId); 256 setTimeout(() => {
257 onFinishLoadingAditionTile(adPosition.id, aditionId, bannerDescriptionApi.getBannerCode(), window.jQuery); 258 }, 100); 259 }, 260 261 /** 262 * NoBanner. 263 * 264 * @param adPosition 265 * @param api 266 * @param bannerDescriptionApi 267 * @param renderControlApi 268 */ 269 NoBanner: function(adPosition, api, bannerDescriptionApi, renderControlApi) { 270 var container = adPosition.closest('.ad-entity-container'); 271 if (container) { 272 container.classList.add('d-none'); 273 if (container.closest('.tile__wrapper')) { 274 container.closest('.tile__wrapper').remove(); 275 } 276 } 277 }, 278 279 detach: function (containers, context, settings) {}, 280 }; 281 282}(Drupal, drupalSettings, window));
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.