1/** 2 * jQuery DFP v1.1.5 3 * http://github.com/coop182/jquery.dfp.js 4 * 5 * Copyright 2014 Matt Cooper 6 * Released under the MIT license 7 */ 8(function ($, window, undefined) { 9 10 'use strict'; 11 12 var 13 14 // Save Scope 15 dfpScript = this, 16 17 // DFP account ID 18 dfpID = '', 19 20 // Init counters 21 count = 0, 22 uid = 0, 23 rendered = 0, 24 25 // Default DFP selector 26 dfpSelector = '.adunit', 27 28 // DFP options object 29 dfpOptions = {}, 30 31 // Keep track of if we've already tried to load gpt.js before 32 dfpIsLoaded = false, 33 34 // Collection of ads 35 $adCollection, 36 37 // Store adunit on div as: 38 storeAs = 'googleAdUnit', 39 40 /** 41 * Init function sets required params and loads Google's DFP script 42 * @param String id The DFP account ID 43 * @param String selector The adunit selector 44 * @param Object options Custom options to apply 45 */ 46 init = function (id, selector, options) { 47 48 // Reset counters on each call 49 count = 0; 50 rendered = 0; 51 52 dfpID = id; 53 $adCollection = $(selector); 54 55 dfpLoader(); 56 setOptions(options); 57 58 $(function () { 59 createAds(); 60 displayAds(); 61 }); 62 63 }, 64 65 /** 66 * Set the options for DFP 67 * @param Object options Custom options to apply 68 */ 69 setOptions = function (options) { 70 71 // Set default options 72 dfpOptions = { 73 setTargeting: {}, 74 setCategoryExclusion: '', 75 setLocation: '', 76 enableSingleRequest: true, 77 collapseEmptyDivs: 'original', 78 refreshExisting: true, 79 disablePublisherConsole: false, 80 disableInitialLoad: false, 81 noFetch: false, 82 namespace: undefined, 83 sizeMapping: {} 84 }; 85 86 if (typeof options.setUrlTargeting === 'undefined' || options.setUrlTargeting) 87 { 88 // Get URL Targeting 89 var urlTargeting = getUrlTargeting(); 90 $.extend(true, dfpOptions.setTargeting, { inURL: urlTargeting.inURL, URLIs: urlTargeting.URLIs, Query: urlTargeting.Query, Domain: window.location.host }); 91 } 92 93 // Merge options objects 94 $.extend(true, dfpOptions, options); 95 96 // If a custom googletag is specified, use it. 97 if (dfpOptions.googletag) { 98 window.googletag.cmd.push(function () { 99 $.extend(true, window.googletag, dfpOptions.googletag); 100 }); 101 } 102 }, 103 104 /** 105 * Find and create all Ads 106 * @return Array an array of ad units that have been created. 107 */ 108 createAds = function () { 109 110 // Loops through on page Ad units and gets ads for them. 111 $adCollection.each(function () { 112 113 var $adUnit = $(this); 114 115 count++; 116 117 // adUnit name 118 var adUnitName = getName($adUnit); 119 120 // adUnit id - this will use an existing id or an auto generated one. 121 var adUnitID = getID($adUnit, adUnitName); 122 123 // get dimensions of the adUnit 124 var dimensions = getDimensions($adUnit); 125 126 // set existing content 127 $adUnit.data('existingContent', $adUnit.html()); 128 129 // wipe html clean ready for ad and set the default display class. 130 $adUnit.html('').addClass('display-none'); 131 132 // Push commands to DFP to create ads 133 window.googletag.cmd.push(function () { 134 135 var googleAdUnit, 136 $adUnitData = $adUnit.data(storeAs); 137 138 if ($adUnitData) { 139 140 // Get existing ad unit 141 googleAdUnit = $adUnitData; 142 143 } else { 144 145 // Create the ad - out of page or normal 146 if ($adUnit.data('outofpage')) { 147 googleAdUnit = window.googletag.defineOutOfPageSlot('/' + dfpID + '/' + adUnitName, adUnitID).addService(window.googletag.pubads()); 148 } else { 149 if ($adUnit.data('companion')) { 150 googleAdUnit = window.googletag.defineSlot('/' + dfpID + '/' + adUnitName, dimensions, adUnitID) 151 .addService(window.googletag.companionAds()).addService(window.googletag.pubads()); 152 } else { 153 googleAdUnit = window.googletag.defineSlot('/' + dfpID + '/' + adUnitName, dimensions, adUnitID) 154 .addService(window.googletag.pubads()); 155 } 156 } 157 158 } 159 160 // Sets custom targeting for just THIS ad unit if it has been specified 161 var targeting = $adUnit.data('targeting'); 162 if (targeting) { 163 $.each(targeting, function (k, v) { 164 googleAdUnit.setTargeting(k, v); 165 }); 166 } 167 168 // Sets custom exclusions for just THIS ad unit if it has been specified 169 var exclusions = $adUnit.data('exclusions'); 170 if (exclusions) { 171 var exclusionsGroup = exclusions.split(','); 172 var valueTrimmed; 173 $.each(exclusionsGroup, function (k, v) { 174 valueTrimmed = $.trim(v); 175 if (valueTrimmed.length > 0) { 176 googleAdUnit.setCategoryExclusion(valueTrimmed); 177 } 178 }); 179 } 180 181 // Sets responsive size mapping for just THIS ad unit if it has been specified 182 var mapping = $adUnit.data('size-mapping'); 183 if (mapping && dfpOptions.sizeMapping[mapping]) { 184 // Convert verbose to DFP format 185 var map = window.googletag.sizeMapping(); 186 $.each(dfpOptions.sizeMapping[mapping], function(k, v) { 187 map.addSize(v.browser, v.ad_sizes); 188 }); 189 googleAdUnit.defineSizeMapping(map.build()); 190 } 191 192 // Store googleAdUnit reference 193 $adUnit.data(storeAs, googleAdUnit); 194 195 // Allow altering of the ad slot before ad load 196 if (typeof dfpOptions.beforeEachAdLoaded === 'function') { 197 dfpOptions.beforeEachAdLoaded.call(this, $adUnit); 198 } 199 }); 200 201 }); 202 203 // Push DFP config options 204 window.googletag.cmd.push(function () { 205 206 if (dfpOptions.enableSingleRequest) { 207 window.googletag.pubads().enableSingleRequest(); 208 } 209 $.each(dfpOptions.setTargeting, function (k, v) { 210 window.googletag.pubads().setTargeting(k, v); 211 }); 212 213 if (typeof dfpOptions.setLocation === 'object') { 214 if (typeof dfpOptions.setLocation.latitude === 'number' && typeof dfpOptions.setLocation.longitude === 'number' && typeof dfpOptions.setLocation.precision === 'number') { 215 window.googletag.pubads().setLocation(dfpOptions.setLocation.latitude, dfpOptions.setLocation.longitude, dfpOptions.setLocation.precision); 216 } else if (typeof dfpOptions.setLocation.latitude === 'number' && typeof dfpOptions.setLocation.longitude === 'number') { 217 window.googletag.pubads().setLocation(dfpOptions.setLocation.latitude, dfpOptions.setLocation.longitude); 218 } 219 } 220 221 if (dfpOptions.setCategoryExclusion.length > 0) { 222 var exclusionsGroup = dfpOptions.setCategoryExclusion.split(','); 223 var valueTrimmed; 224 $.each(exclusionsGroup, function (k, v) { 225 valueTrimmed = $.trim(v); 226 if (valueTrimmed.length > 0) { 227 window.googletag.pubads().setCategoryExclusion(valueTrimmed); 228 } 229 }); 230 } 231 if (dfpOptions.collapseEmptyDivs) { 232 window.googletag.pubads().collapseEmptyDivs(); 233 } 234 235 if (dfpOptions.disablePublisherConsole) { 236 window.googletag.pubads().disablePublisherConsole(); 237 } 238 if (dfpOptions.companionAds) { 239 window.googletag.companionAds().setRefreshUnfilledSlots(true); 240 241 if (!dfpOptions.disableInitialLoad) { 242 window.googletag.pubads().enableVideoAds(); 243 } 244 } 245 if (dfpOptions.disableInitialLoad) { 246 window.googletag.pubads().disableInitialLoad(); 247 } 248 249 if (dfpOptions.noFetch) { 250 window.googletag.pubads().noFetch(); 251 } 252 253 // Setup event listener to listen for renderEnded event and fire callbacks. 254 window.googletag.pubads().addEventListener('slotRenderEnded', function(event) { 255 256 rendered++; 257 258 var $adUnit = $('#' + event.slot.getSlotId().getDomId()); 259 260 var display = event.isEmpty ? 'none' : 'block'; 261 262 // if the div has been collapsed but there was existing content expand the 263 // div and reinsert the existing content. 264 var $existingContent = $adUnit.data('existingContent'); 265 if (display === 'none' && $.trim($existingContent).length > 0 && dfpOptions.collapseEmptyDivs === 'original') { 266 $adUnit.show().html($existingContent); 267 display = 'block display-original'; 268 } 269 270 $adUnit.removeClass('display-none').addClass('display-' + display); 271 272 // Excute afterEachAdLoaded callback if provided
273 if (typeof dfpOptions.afterEachAdLoaded === 'function') { 274 dfpOptions.afterEachAdLoaded.call(this, $adUnit, event); 275 } 276 277 // Excute afterAllAdsLoaded callback if provided 278 if (typeof dfpOptions.afterAllAdsLoaded === 'function' && rendered === count) { 279 dfpOptions.afterAllAdsLoaded.call(this, $adCollection); 280 } 281 282 }); 283 284 window.googletag.enableServices(); 285 286 }); 287 288 }, 289 290 /** 291 * Display all created Ads 292 */ 293 displayAds = function () { 294 295 // Display each ad 296 $adCollection.each(function () { 297 298 var $adUnit = $(this), 299 $adUnitData = $adUnit.data(storeAs); 300 301 if (dfpOptions.refreshExisting && $adUnitData && $adUnit.hasClass('display-block')) { 302 303 window.googletag.cmd.push(function () { window.googletag.pubads().refresh([$adUnitData]); }); 304 305 } else { 306 307 window.googletag.cmd.push(function () { window.googletag.display($adUnit.attr('id')); }); 308 309 } 310 311 }); 312 313 }, 314 315 /** 316 * Create an array of paths so that we can target DFP ads to Page URI's 317 * @return Array an array of URL parts that can be targeted. 318 */ 319 getUrlTargeting = function () { 320 321 // Get the paths for targeting against 322 var paths = window.location.pathname.replace(/\/$/, ''), 323 patt = new RegExp('\/([^\/]*)', 'ig'), 324 pathsMatches = paths.match(patt), 325 targetPaths = ['/'], 326 longestpath = ''; 327 328 if (pathsMatches && paths !== '/') { 329 var target = '', 330 size = pathsMatches.length; 331 if (size > 0) { 332 for (var i = 0; i < size; i++) { 333 target = pathsMatches[i]; 334 targetPaths.push(target); 335 for (var j = i + 1; j < size; j++) { 336 target += pathsMatches[j]; 337 targetPaths.push(target); 338 } 339 if (i === 0) { 340 targetPaths.splice(-1, 1); 341 longestpath = target; 342 } 343 } 344 } 345 targetPaths.push(longestpath); 346 } 347 348 targetPaths = targetPaths.reverse(); 349 350 // Get the query params for targeting against 351 var url = window.location.toString().replace(/\=/ig, ':').match(/\?(.+)$/), 352 params = RegExp.$1.split('&'); 353 354 return { 355 inURL: targetPaths, 356 URLIs: targetPaths[0], 357 Query: params 358 }; 359 360 }, 361 362 /** 363 * Get the id of the adUnit div or generate a unique one. 364 * @param Object $adUnit The adunit to work with 365 * @param String adUnitName The name of the adunit 366 * @return String The ID of the adunit or a unique autogenerated ID 367 */ 368 getID = function ($adUnit, adUnitName) { 369 370 uid++; 371 return $adUnit.attr('id') || $adUnit.attr('id', adUnitName.replace(/[^A-z0-9]/g, '_') + '-auto-gen-id-' + uid).attr('id'); 372 373 }, 374 375 /** 376 * Get the name of the Ad unit, either use the div id or 377 * check for the optional attribute data-adunit 378 * @param Object $adUnit The adunit to work with 379 * @return String The name of the adunit, will be the same as inside DFP 380 */ 381 getName = function ($adUnit) { 382 383 var adUnitName = $adUnit.data('adunit') || dfpOptions.namespace || $adUnit.attr('id') || ''; 384 if (typeof dfpOptions.alterAdUnitName === 'function') { 385 adUnitName = dfpOptions.alterAdUnitName.call(this, adUnitName, $adUnit); 386 } 387 return adUnitName; 388 389 }, 390 391 /** 392 * Get the dimensions of the ad unit using the container div dimensions or 393 * check for the optional attribute data-dimensions 394 * @param Object $adUnit The adunit to work with 395 * @return Array The dimensions of the adunit (width, height) 396 */ 397 getDimensions = function ($adUnit) { 398 399 var dimensions = [], 400 dimensionsData = $adUnit.data('dimensions'); 401 402 // Check if data-dimensions are specified. If they aren't, use the dimensions of the ad unit div. 403 if (dimensionsData) { 404 405 var dimensionGroups = dimensionsData.split(','); 406 407 $.each(dimensionGroups, function (k, v) { 408 409 var dimensionSet = v.split('x'); 410 dimensions.push([parseInt(dimensionSet[0], 10), parseInt(dimensionSet[1], 10)]); 411 412 }); 413 414 } else { 415 416 dimensions.push([$adUnit.width(), $adUnit.height()]); 417 418 } 419 420 return dimensions; 421 422 }, 423 424 /** 425 * Call the google DFP script - there is a little bit of error detection in here to detect 426 * if the dfp script has failed to load either through an error or it being blocked by an ad 427 * blocker... if it does not load we execute a dummy script to replace the real DFP. 428 */ 429 dfpLoader = function () { 430 431 // make sure we don't load gpt.js multiple times 432 dfpIsLoaded = dfpIsLoaded || $('script[src*="googletagservices.com/tag/js/gpt.js"]').length; 433 if (dfpIsLoaded) { 434 return; 435 } 436 437 window.googletag = window.googletag || {}; 438 window.googletag.cmd = window.googletag.cmd || []; 439 440 var gads = document.createElement('script'); 441 gads.async = true; 442 gads.type = 'text/javascript'; 443 444 // Adblock blocks the load of Ad scripts... so we check for that 445 gads.onerror = function () { 446 dfpBlocked(); 447 }; 448 449 var useSSL = 'https:' === document.location.protocol; 450 gads.src = (useSSL ? 'https:' : 'http:') + 451 '//www.googletagservices.com/tag/js/gpt.js'; 452 var node = document.getElementsByTagName('script')[0]; 453 node.parentNode.insertBefore(gads, node); 454 455 // Adblock plus seems to hide blocked scripts... so we check for that 456 if (gads.style.display === 'none') { 457 dfpBlocked(); 458 } 459 460 }, 461 462 /**
463 * This function gets called if DFP has been blocked by an adblocker 464 * it implements a dummy version of the dfp object and allows the script to excute its callbacks 465 * regardless of whether DFP is actually loaded or not... it is basically only useful for situations 466 * where you are laying DFP over existing content and need to init things like slide shows after the loading 467 * is completed. 468 */ 469 dfpBlocked = function () { 470 471 // Get the stored dfp commands 472 var commands = window.googletag.cmd; 473 474 // SetTimeout is a bit dirty but the script does not execute in the correct order without it 475 setTimeout(function () { 476 477 var _defineSlot = function (name, dimensions, id, oop) { 478 window.googletag.ads.push(id); 479 window.googletag.ads[id] = { 480 renderEnded: function () { }, 481 addService: function () { return this; } 482 }; 483 return window.googletag.ads[id]; 484 }; 485 486 // overwrite the dfp object - replacing the command array with a function and defining missing functions 487 window.googletag = { 488 cmd: { 489 push: function (callback) { 490 callback.call(dfpScript); 491 } 492 }, 493 ads: [], 494 pubads: function () { return this; }, 495 noFetch:function () { return this; }, 496 disableInitialLoad: function () { return this; }, 497 disablePublisherConsole: function () { return this; }, 498 enableSingleRequest: function () { return this; }, 499 setTargeting: function () { return this; }, 500 collapseEmptyDivs: function () { return this; }, 501 enableServices: function () { return this; }, 502 defineSlot: function (name, dimensions, id) { 503 return _defineSlot(name, dimensions, id, false); 504 }, 505 defineOutOfPageSlot: function (name, id) { 506 return _defineSlot(name, [], id, true); 507 }, 508 display: function (id) { 509 window.googletag.ads[id].renderEnded.call(dfpScript); 510 return this; 511 } 512 513 }; 514 515 // Execute any stored commands 516 $.each(commands, function (k, v) { 517 window.googletag.cmd.push(v); 518 }); 519 520 }, 50); 521 522 }; 523 524 /** 525 * Add function to the jQuery / Zepto / tire namespace 526 * @param String id (Optional) The DFP account ID 527 * @param Object options (Optional) Custom options to apply 528 */ 529 $.dfp = $.fn.dfp = function (id, options) { 530 531 options = options || {}; 532 533 if (id === undefined) { 534 id = dfpID; 535 } 536 537 if (typeof id === 'object') { 538 options = id; 539 id = options.dfpID || dfpID; 540 } 541 542 var selector = this; 543 544 if (typeof this === 'function') { 545 selector = dfpSelector; 546 } 547 548 init(id, selector, options); 549 550 return this; 551 552 }; 553 554})(window.jQuery || window.Zepto || window.tire, 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.