1function OpenAdViewability() { 2 3 /* 4 This implementation is according to MRC Viewability guidelines - 5 http://mediaratingcouncil.org/081815%20Viewable%20Ad%20Impression%20Guideline_v2.0_Final.pdf 6 */ 7 8 var geometryViewabilityCalculator = new OAVGeometryViewabilityCalculator(); 9 10 var check = { 11 percentObscured: 0, 12 percentViewable: 0, 13 acceptedViewablePercentage: 50, 14 viewabiltyStatus: false, 15 duration: 0 16 }; 17 18 this.DEBUG_MODE = false; 19 20 this.checkViewability = function(ad, statusCallback){ 21 var count = 0; 22 var that = this; 23 var timer = setInterval(function() { 24 if (checkViewable(ad)) { 25 count++; 26 } else { 27 count = 0; 28 } 29 check.duration = count*100; 30 if (count >= 9) { 31 check.viewabiltyStatus = true; 32 if(!that.DEBUG_MODE) 33 clearInterval(timer); 34 } 35 check.ad_id = ad.id; 36 statusCallback(check); 37 }, 100); 38 } 39 40 var checkViewable = function(ad) { 41 var adRect = ad.getBoundingClientRect(); 42 var totalArea = adRect.width * adRect.height; 43 // According to MRC standards, larget ad unit size have only 30% viewable requirements 44 if(totalArea >= 242500) 45 check.acceptedViewablePercentage = 30; 46 47 if (checkCssInvisibility(ad) === true){ 48 if(ad.id == 'metv_top'){ 49 console.log("invisible"); 50 } 51 return false; 52 } 53 54 if (checkDomObscuring(ad) === true){ 55 if(ad.id == 'metv_top'){ 56 console.log("obscure"); 57 } 58 59 return false; 60 } 61 62 checkGeometry(ad); 63 64 if(check.percentViewable && check.percentViewable < check.acceptedViewablePercentage){ 65 if(ad.id == 'metv_top'){ 66 //console.log("obscured view"); 67 } 68 69 return false; 70 } 71 72 if(!check.percentViewable) 73 return false; 74 75 return true; 76 }; 77 78 /** 79 * Performs the geometry technique to determine viewability. First gathers 80 * information on the viewport and on the ad. Then compares the two to 81 * determine what percentage, if any, of the ad is within the bounds 82 * of the viewport. 83 * @param {Element} ad The HTML Element to measure 84 */ 85 var checkGeometry = function (ad) { 86 check.percentObscured = check.percentObscured || 0; 87 var viewabilityResult = geometryViewabilityCalculator.getViewabilityState(ad, window); 88 if (!viewabilityResult.error) { 89 check.percentViewable = viewabilityResult.percentViewable - check.percentObscured; 90 } 91 return viewabilityResult; 92 }; 93 94 /** 95 * Checks if the ad is made invisible by css attribute 'visibility:hidden' 96 * or 'display:none'. 97 * Is so, viewability at the time of this check is 'not viewable' and no further check 98 * is required. 99 * These properties are inherited, so no need to parse up the DOM hierarchy. 100 * If the ad is in an iframe inheritance is restricted to elements within 101 * the DOM of the iframe document 102 * @param {Element} ad The HTML Element to measure 103 */ 104 var checkCssInvisibility = function (ad) { 105 var style = window.getComputedStyle(ad, null); 106 var visibility = style.getPropertyValue('visibility'); 107 var display = style.getPropertyValue('display'); 108 if ( visibility == 'hidden' || display == 'none' ){ 109 return true; 110 } 111 return false; 112 }; 113 114 /** 115 * Checks if the ad is more then 50% obscured by another dom element. 116 * Is so, viewability at the time of this check is 'not viewable' and no further check 117 * is required. 118 * If the ad is in an iframe this check is restricted to elements within 119 * the DOM of the iframe document 120 * @param {Element} ad The HTML Element to measure 121 */ 122 var checkDomObscuring = function(ad){ 123 var adRect = ad.getBoundingClientRect(), 124 offset = 12, 125 xLeft = adRect.left+offset, 126 xRight = adRect.right-offset, 127 yTop = adRect.top+offset, 128 yBottom = adRect.bottom-offset, 129 xCenter = Math.floor(adRect.left+adRect.width/2), 130 yCenter = Math.floor(adRect.top+adRect.height/2), 131 testPoints = [ 132 { x:xLeft, y:yTop }, 133 { x:xCenter, y:yTop }, 134 { x:xRight, y:yTop }, 135 { x:xLeft, y:yCenter }, 136 { x:xCenter, y:yCenter }, 137 { x:xRight, y:yCenter }, 138 { x:xLeft, y:yBottom }, 139 { x:xCenter, y:yBottom }, 140 { x:xRight, y:yBottom } 141 ]; 142 143 for (var p in testPoints) { 144 if (testPoints[p] && testPoints[p].x >= 0 && testPoints[p].y >= 0) { 145 elem = document.elementFromPoint(testPoints[p].x, testPoints[p].y); 146 147 if (elem != null && elem != ad && !ad.contains(elem)) { 148 overlappingArea = overlapping(adRect, elem.getBoundingClientRect()); 149 if (overlappingArea > 0) { 150 check.percentObscured = 100 * overlapping(adRect, elem.getBoundingClientRect()); 151 if (check.percentObscured > check.acceptedViewablePercentage) { 152 check.percentViewable = 100 - check.percentObscured; 153 return true; 154 } 155 } 156 } 157 } 158 } 159 return false;
160 } 161 162 var overlapping = function(adRect, elem ){ 163 var adArea = adRect.width * adRect.height; 164 var x_overlap = Math.max(0, Math.min(adRect.right, elem.right) - Math.max(adRect.left, elem.left)); 165 var y_overlap = Math.max(0, Math.min(adRect.bottom, elem.bottom) - Math.max(adRect.top, elem.top)); 166 return (x_overlap * y_overlap) / adArea; 167 } 168 169} 170 171 172function OAVGeometryViewabilityCalculator() { 173 174 this.getViewabilityState = function (element, contextWindow) { 175 var minViewPortSize = getMinViewPortSize(), 176 viewablePercentage; 177 if (minViewPortSize.area == Infinity) { 178 return { error: 'Failed to determine viewport'}; 179 } 180 var assetRect = element.getBoundingClientRect(); 181 var adArea = assetRect.width * assetRect.height; 182 if ((minViewPortSize.area / adArea) < 0.5) { 183 // no position testing required if viewport is less than half the area of the ad 184 viewablePercentage = Math.floor(100 * minViewPortSize.area / adArea); 185 }else{ 186 var viewPortSize = getViewPortSize(window.top), 187 visibleAssetSize = getAssetVisibleDimension(element, contextWindow); 188 //var viewablePercentage = getAssetViewablePercentage(assetSize, viewPortSize); 189 //Height within viewport: 190 if ( visibleAssetSize.bottom > viewPortSize.height ) { 191 //Partially below the bottom 192 visibleAssetSize.height -= (visibleAssetSize.bottom - viewPortSize.height); 193 } 194 if ( visibleAssetSize.top < 0 ) { 195 //Partially above the top 196 visibleAssetSize.height += visibleAssetSize.top; 197 } 198 if ( visibleAssetSize.left < 0 ) { 199 visibleAssetSize.width += visibleAssetSize.left; 200 } 201 if ( visibleAssetSize.right > viewPortSize.width ) { 202 visibleAssetSize.width -= ( visibleAssetSize.right - viewPortSize.width ); 203 } 204 // Viewable percentage is the portion of the ad that's visible divided by the size of the ad 205 viewablePercentage = Math.floor( 100 * ( visibleAssetSize.width * visibleAssetSize.height ) / adArea ); 206 } 207 /* 208 //Get ad dimensions: 209 var assetRect = element.getBoundingClientRect(); 210 */ 211 return { 212 clientWidth: viewPortSize.width, 213 clientHeight: viewPortSize.height, 214 objTop: assetRect.top, 215 objBottom: assetRect.bottom, 216 objLeft: assetRect.left, 217 objRight: assetRect.right, 218 percentViewable: viewablePercentage 219 }; 220 }; 221 222 /////////////////////////////////////////////////////////////////////////// 223 // PRIVATE FUNCTIONS 224 /////////////////////////////////////////////////////////////////////////// 225 226 // Check nested iframes 227 var getMinViewPortSize = function (){ 228 var minViewPortSize = getViewPortSize(window), 229 minViewPortArea = minViewPortSize.area, 230 currentWindow = window; 231 232 while (currentWindow != window.top){ 233 currentWindow = currentWindow.parent; 234 viewPortSize = getViewPortSize(currentWindow); 235 if (viewPortSize.area < minViewPortArea){ 236 minViewPortArea = viewPortSize.area; 237 minViewPortSize = viewPortSize; 238 } 239 } 240 return minViewPortSize; 241 } 242 243 244 /** 245 * Get the viewport size by taking the smallest dimensions 246 */ 247 var getViewPortSize = function (contextWindow) { 248 var viewPortSize = { 249 width: Infinity, 250 height: Infinity, 251 area:Infinity 252 }; 253 254 //document.body - Handling case where viewport is represented by documentBody 255 //.width 256 if (!isNaN(contextWindow.document.body.clientWidth) && contextWindow.document.body.clientWidth > 0) { 257 viewPortSize.width = contextWindow.document.body.clientWidth; 258 } 259 //.height 260 if (!isNaN(contextWindow.document.body.clientHeight) && contextWindow.document.body.clientHeight > 0) { 261 viewPortSize.height = contextWindow.document.body.clientHeight; 262 } 263 //document.documentElement - Handling case where viewport is represented by documentElement 264 //.width 265 if (!!contextWindow.document.documentElement && !!contextWindow.document.documentElement.clientWidth && !isNaN(contextWindow.document.documentElement.clientWidth)) { 266 viewPortSize.width = contextWindow.document.documentElement.clientWidth; 267 } 268 //.height 269 if (!!contextWindow.document.documentElement && !!contextWindow.document.documentElement.clientHeight && !isNaN(contextWindow.document.documentElement.clientHeight)) { 270 viewPortSize.height = contextWindow.document.documentElement.clientHeight; 271 } 272 //window.innerWidth/Height - Handling case where viewport is represented by window.innerH/W 273 //.innerWidth 274 if (!!contextWindow.innerWidth && !isNaN(contextWindow.innerWidth)) { 275 viewPortSize.width = Math.min(viewPortSize.width, contextWindow.innerWidth); 276 } 277 //.innerHeight 278 if (!!contextWindow.innerHeight && !isNaN(contextWindow.innerHeight)) { 279 viewPortSize.height = Math.min(viewPortSize.height, contextWindow.innerHeight); 280 } 281 viewPortSize.area = viewPortSize.height * viewPortSize.width; 282 return viewPortSize; 283 }; 284 285 /** 286 * Recursive function that return the asset (element) visible dimension 287 * @param {element} The element to get his visible dimension 288 * @param {contextWindow} The relative window 289 */ 290 291 var getAssetVisibleDimension = function (element, contextWindow) {
292 var currWindow = contextWindow; 293 //Set parent window for recursive call 294 var parentWindow = contextWindow.parent; 295 var resultDimension = { width: 0, height: 0, left: 0, right: 0, top: 0, bottom: 0 }; 296 297 if (element) { 298 var elementRect = getPositionRelativeToViewPort(element, contextWindow); 299 elementRect.width = elementRect.right - elementRect.left; 300 elementRect.height = elementRect.bottom - elementRect.top; 301 resultDimension = elementRect; 302 //Calculate the relative element dimension if we clime to a parent window 303 if (currWindow != parentWindow) { 304 //Recursive call to get the relative element dimension from the parent window 305 var parentDimension = getAssetVisibleDimension(currWindow.frameElement, parentWindow); 306 //The asset is partially below the parent window (asset bottom is below the visible window) 307 if (parentDimension.bottom < resultDimension.bottom) { 308 if (parentDimension.bottom < resultDimension.top) { 309 //The entire asset is below the parent window 310 resultDimension.top = parentDimension.bottom; 311 } 312 //Set the asset bottom to be the visible part 313 resultDimension.bottom = parentDimension.bottom; 314 } 315 //The asset is partially right to the parent window 316 if (parentDimension.right < resultDimension.right) { 317 if (parentDimension.right < resultDimension.left) { 318 //The entire asset is to the right of the parent window 319 resultDimension.left = parentDimension.right; 320 } 321 //Set the asset right to be the visible 322 resultDimension.right = parentDimension.right; 323 } 324 325 resultDimension.width = resultDimension.right - resultDimension.left; 326 resultDimension.height = resultDimension.bottom - resultDimension.top; 327 } 328 } 329 return resultDimension; 330 }; 331 332 var getPositionRelativeToViewPort = function (element, contextWindow) { 333 var currWindow = contextWindow; 334 var parentWindow = contextWindow.parent; 335 var resultPosition = { left: 0, right: 0, top: 0, bottom: 0 }; 336 337 if (element) { 338 var elementRect = element.getBoundingClientRect(); 339 if (currWindow != parentWindow) { 340 resultPosition = getPositionRelativeToViewPort(currWindow.frameElement, parentWindow); 341 } 342 resultPosition = { 343 left: elementRect.left + resultPosition.left, 344 right: elementRect.right + resultPosition.left, 345 top: elementRect.top + resultPosition.top, 346 bottom: elementRect.bottom + resultPosition.top 347 }; 348 } 349 return resultPosition; 350 }; 351 /** 352 * Calculate asset viewable percentage given the asset size and the viewport 353 * @param {effectiveAssetRect} the asset viewable rect; effectiveAssetRect = {left :, top :,bottom:,right:,} 354 * @param {viewPortSize} the browser viewport size; 355 */ 356 var getAssetViewablePercentage = function (effectiveAssetRect, viewPortSize) { 357 // holds the asset viewable surface 358 var assetVisibleHeight = 0, assetVisibleWidth = 0; 359 var asset = { 360 width: effectiveAssetRect.right - effectiveAssetRect.left, 361 height: effectiveAssetRect.bottom - effectiveAssetRect.top 362 }; 363 364 // Ad is 100% out off-view 365 if (effectiveAssetRect.bottom < 0 // the entire asset is above the viewport 366 || effectiveAssetRect.right < 0 // the entire asset is left to the viewport 367 || effectiveAssetRect.top > viewPortSize.height // the entire asset bellow the viewport 368 || effectiveAssetRect.left > viewPortSize.width // the entire asset is right to the viewport 369 || asset.width <= 0 // the asset width is zero 370 || asset.height <= 0) // the asset height is zero 371 { 372 return 0; 373 } 374 // ---- Handle asset visible height ---- 375 // the asset is partially above the viewport 376 if (effectiveAssetRect.top < 0) { 377 // take the visible part 378 assetVisibleHeight = asset.height + effectiveAssetRect.top; 379 //if the asset height is larger then the viewport height, set the asset height to be the viewport height 380 if (assetVisibleHeight > viewPortSize.height) { 381 assetVisibleHeight = viewPortSize.height; 382 } 383 } 384 // the asset is partially below the viewport 385 else if (effectiveAssetRect.top + asset.height > viewPortSize.height) { 386 // take the visible part 387 assetVisibleHeight = viewPortSize.height - effectiveAssetRect.top; 388 } 389 // the asset is in the viewport 390 else { 391 assetVisibleHeight = asset.height; 392 } 393 // ---- Handle asset visible width ---- 394 // the asset is partially left to the viewport 395 if (effectiveAssetRect.left < 0) { 396 // take the visible part 397 assetVisibleWidth = asset.width + effectiveAssetRect.left; 398 //if the asset width is larger then the viewport width, set the asset width to be the viewport width 399 if (assetVisibleWidth > viewPortSize.width) { 400 assetVisibleWidth = viewPortSize.width; 401 } 402 } 403 // the asset is partially right to the viewport 404 else if (effectiveAssetRect.left + asset.width > viewPortSize.width) { 405 // take the visible part 406 assetVisibleWidth = viewPortSize.width - effectiveAssetRect.left; 407 } 408 // the asset is in the viewport 409 else { 410 assetVisibleWidth = asset.width; 411 } 412 // Divied the visible asset area by the full asset area to the the visible percentage 413 return Math.round((((assetVisibleWidth * assetVisibleHeight)) / (asset.width * asset.height)) * 100); 414 }; 415}
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.