1(function () { 2 /** 3 * @typedef {Object} AdUnit 4 * @property {string} type 5 * @property {string|undefined} unitId 6 * @property {string} insert 7 * @property {string} autoSelector 8 * @property {string} selector 9 * @property {Object} settings 10 * @property {Element|undefined} element 11 */ 12 var LOADING_TIMEOUT_MS = 10000 13 var EVENT_ERROR_LOADING_SCRIPT = 'error_loading_script' 14 var verbose = /[\?\&]verbose([\?|\&|\#]|$)/.test(window.location.search) 15 var checkTimeout = true 16 var logger = { 17 log: function () { 18 console.log.apply(null, arguments) 19 }, 20 debug: function () { 21 if (verbose) { 22 console.log.apply(null, arguments) 23 } 24 }, 25 warn: function () { 26 console.warn.apply(null, arguments) 27 }, 28 error: function () { 29 console.error.apply(null, arguments) 30 } 31 } 32 33 /** 34 * @param {Element} el 35 * @return {number} 36 */ 37 function calcOffsetTop(el) { 38 return (el.getBoundingClientRect().top + window.pageYOffset) 39 } 40 41 function contentIntegration() { 42 if (window.NRentContentIntegrated === true) { 43 return false 44 } 45 46 var contentBlock = Array.from(window.document.querySelectorAll('.nativerent-content-integration')).pop() 47 if (contentBlock == null) { 48 return false 49 } 50 51 window.NRentContentIntegrated = true 52 var article = contentBlock.parentNode 53 var articleWidth = article.clientWidth 54 var minDistance = (articleWidth < 500 ? 150 : 100) 55 var minDistanceNTGB = 500; 56 var paragraphs = article.querySelectorAll('p') 57 var titles = article.querySelectorAll('h2') 58 var insertedUnits = {} 59 var unitsToCheckDistance = { 60 regular: {}, 61 ntgb: {} 62 } 63 var ntgbUnitsCount = 0; 64 65 for (var i = 0; i < window.NRentAdUnits.length; i++) { 66 try { 67 /** @type {AdUnit} **/ 68 var adUnit = window.NRentAdUnits[i] 69 var anchor = undefined 70 var dataPlacementAttr = true 71 72 switch (adUnit.autoSelector) { 73 case 'firstParagraph': { 74 anchor = paragraphs[0] 75 break 76 } 77 case 'middleParagraph': { 78 anchor = paragraphs[Math.floor(paragraphs.length / 2)] 79 break 80 } 81 case 'lastParagraph': { 82 anchor = paragraphs[paragraphs.length - 1] 83 break 84 } 85 case 'firstTitle': { 86 anchor = titles[0] 87 break 88 } 89 case 'middleTitle': { 90 anchor = titles[Math.floor(titles.length / 2)] 91 break 92 } 93 case 'lastTitle': { 94 anchor = titles[titles.length - 1] 95 break 96 } 97 case 'body': { 98 anchor = window.document.body 99 dataPlacementAttr = false 100 break 101 } 102 default: { 103 try { 104 dataPlacementAttr = false 105 var customSelector = decodeURIComponent(adUnit.selector) 106 if (!/^body[^a-z0-9]/i.test(customSelector)) { 107 anchor = article.querySelector(customSelector) 108 } else { 109 anchor = window.document.querySelector(customSelector) 110 } 111 } catch (error) { 112 logger.error(error) 113 logger.warn( 114 'NRentPlugin: Anchor for adUnit \'' + adUnit.type + '\' was not found by selector \'' + 115 adUnit.selector + '\'', 116 ) 117 continue 118 } 119 break 120 } 121 } 122 logger.debug("NRentPlugin: placement info", adUnit, anchor) 123 124 if (anchor == null || typeof anchor !== 'object') { 125 logger.warn( 126 'NRentPlugin: Anchor for adUnit \'' + adUnit.type + 127 '\' was not found by selector \'' + adUnit.selector + '\'', 128 ) 129 continue 130 } 131 132 adUnit.element = document.createElement('div') 133 adUnit.element.id = 'NRent-' + 134 (window.NRentCounter.options || window.NRentCounter || {id: 'undefined'}).id + '-' + i 135 136 if (dataPlacementAttr) { 137 adUnit.element.setAttribute( 138 'data-placement', 139 (typeof adUnit.insert === 'string' && adUnit.insert !== '' ? adUnit.insert : 'after') 140 ) 141 } 142 143 switch (adUnit.insert) { 144 case 'after': { 145 if (anchor.nextSibling == null) { 146 anchor.parentNode.appendChild(document.createElement('meta')) 147 } 148 anchor = anchor.nextSibling 149 anchor.parentNode.insertBefore(adUnit.element, anchor) 150 break 151 } 152 case 'inside': { 153 anchor.appendChild(adUnit.element) 154 break 155 } 156 case 'before': 157 default: {
158 anchor.parentNode.insertBefore(adUnit.element, anchor) 159 break 160 } 161 } 162 163 insertedUnits[adUnit.element.id] = adUnit 164 if (adUnit.type === 'ntgb') { 165 ++ntgbUnitsCount 166 if (adUnit.unitId === undefined) { 167 adUnit.unitId = ntgbUnitsCount.toString() 168 } 169 adUnit.element.setAttribute('data-nrent-ntgb-id', adUnit.unitId) 170 unitsToCheckDistance.ntgb[adUnit.element.id] = adUnit 171 } else if (i < 3) { 172 unitsToCheckDistance.regular[adUnit.element.id] = adUnit 173 } 174 175 } catch (error) { 176 logger.error(error) 177 } 178 } 179 180 try { 181 logger.debug('NRentPlugin: Units to check distance', unitsToCheckDistance) 182 checkDistanceOfGroupUnits(unitsToCheckDistance.regular, insertedUnits, minDistance) 183 checkDistanceOfGroupUnits(unitsToCheckDistance.ntgb, insertedUnits, minDistanceNTGB) 184 logger.debug('NRentPlugin: Units with valid distance', unitsToCheckDistance) 185 } catch (error) { 186 logger.error(error) 187 } 188 189 logger.debug('NRentPlugin: Init inserted ad-units', insertedUnits) 190 initInsertedAdUnits(insertedUnits) 191 } 192 193 /** 194 * @param {Object<string, AdUnit>} insertedUnits 195 */ 196 function initInsertedAdUnits(insertedUnits) { 197 for (var id in insertedUnits) { 198 var adUnit = insertedUnits[id] 199 if ('ntgb' === adUnit.type) { 200 (window.NtgbManager = window.NtgbManager || []).push({ 201 renderTo: adUnit.element.id, 202 position: 'ntgb', 203 place: 'place-' + adUnit.unitId 204 }) 205 } else { 206 (window.NRentManager = window.NRentManager || []).push({ 207 renderTo: adUnit.element.id, 208 position: adUnit.type, 209 settings: adUnit.settings 210 }) 211 } 212 } 213 } 214 215 /** 216 * @param {Object<string, AdUnit>} unitsMap 217 * @param {Object<string, AdUnit>} insertedUnits 218 * @param {number} minDistance 219 */ 220 function checkDistanceOfGroupUnits(unitsMap, insertedUnits, minDistance) { 221 var ids = Object.keys(unitsMap) 222 if (ids.length < 2) { 223 return 224 } 225 var selector = ids 226 .map(function (id) { 227 return '#' + id 228 }) 229 .join(', ') 230 var foundElems = document.querySelectorAll(selector) 231 logger.debug('NRentPlugin: Found elements to check distance by selector `' + selector + '`', foundElems) 232 for (var i = 0; i < foundElems.length; i++) { 233 if (i === 0) { 234 continue 235 } 236 if (!checkDistance(foundElems[i], foundElems[i - 1], minDistance)) { 237 if (insertedUnits.hasOwnProperty(foundElems[i].id)) { 238 delete insertedUnits[foundElems[i].id] 239 } 240 delete unitsMap[foundElems[i].id] 241 checkDistanceOfGroupUnits(unitsMap, insertedUnits, minDistance) 242 } 243 } 244 } 245 246 /** 247 * @param {Element} element 248 * @param {Element} prevElement 249 * @param {number} minDistance 250 * 251 * @return {Boolean} 252 */ 253 function checkDistance(element, prevElement, minDistance) { 254 if (prevElement === undefined) { 255 logger.error('NRentPlugin: Failed to calculate distance between elements', element, prevElement) 256 return false; 257 } 258 var distance = (calcOffsetTop(element) - calcOffsetTop(prevElement)) 259 if (window.document.body.clientHeight > minDistance && distance < minDistance) { 260 logger.warn( 261 'NRentPlugin: AdUnit element `#' + element.id + '` is too close ' + 262 'to adUnit element `#' + prevElement.id + '` (distance = ' + distance + ')', 263 element, prevElement 264 ) 265 return false; 266 } 267 268 return true; 269 } 270 271 function cloneScriptElement(script) { 272 var scriptClone = window.document.createElement('script') 273 if (script.innerHTML) { 274 scriptClone.insertAdjacentText('afterbegin', script.innerHTML) 275 } 276 if (script.onload) { 277 scriptClone.onload = script.onload 278 } 279 if (script.hasAttributes()) { 280 var attrs = script.attributes 281 for (var i = 0; i < attrs.length; i++) { 282 var attr = attrs[i] 283 if (attr !== undefined) { 284 scriptClone.setAttribute(attr.name, attr.value) 285 } 286 } 287 } 288 return scriptClone 289 } 290 291 function unblockElements() { 292 var blocked = window.document.querySelectorAll('meta[property="nativerent-block"]') 293 logger.debug('NRentPlugin: Found blocked elements', blocked) 294 295 for (var i = 0; i < blocked.length; i++) { 296 var blockedElement = blocked[i] 297 try { 298 if (blockedElement.content.length) { 299 var tpl = window.document.createElement('div') 300 tpl.insertAdjacentHTML('afterbegin', atob(blockedElement.content)) 301 for (var ci = 0; ci < tpl.childNodes.length; ci++) { 302 var newNode = tpl.childNodes[ci] 303 if (newNode.nodeName === 'SCRIPT') { 304 if ("NRentPluginUnblockHandler" in window) { 305 window.NRentPluginUnblockHandler(newNode); 306 } 307 newNode = cloneScriptElement(newNode) 308 } 309 var inserted = blockedElement.insertAdjacentElement('afterend', newNode) 310 if (inserted) { 311 logger.debug('NRentPlugin: Unblocked element', inserted) 312 blockedElement.remove() 313 } else { 314 logger.warn('NRentPlugin: Failed to unblock element', blockedElement) 315 } 316 } 317 } 318 } catch (e) { 319 logger.error(e) 320 logger.error('NRentPlugin: Failed to unblock element', blockedElement) 321 } 322 } 323 } 324 325 function errorLoadingScriptHandler() { 326 logger.warn('NRentPlugin: Error loading nativerent script. Unblock blocked elements...') 327 unblockElements() 328 checkTimeout = false 329 } 330 331 function NRentPlugin(queued) { 332 queued = (queued || []) 333 for (var i = 0; i < queued.length; i++) { 334 this.push(queued[i]) 335 } 336 } 337 338 NRentPlugin.prototype.push = function (event) { 339 if (typeof event === 'string') { 340 this.handleEvent(event) 341 return 342 } 343 344 if (typeof event === 'object' && event.hasOwnProperty('name')) { 345 this.handleEvent(event.name, event.hasOwnProperty('payload') ? event.payload : null) 346 } 347 } 348 349 NRentPlugin.prototype.handleEvent = function (eventName, payload) { 350 switch (eventName) { 351 case EVENT_ERROR_LOADING_SCRIPT: 352 errorLoadingScriptHandler() 353 break 354 } 355 } 356 357 NRentPlugin.prototype.getOptions = function () { 358 return {
359 verbose: verbose, 360 loadingTimeout: LOADING_TIMEOUT_MS, 361 checkTimeout: checkTimeout 362 } 363 } 364 365 try { 366 if (/complete|interactive|loaded/.test(window.document.readyState)) { 367 contentIntegration() 368 } else { 369 window.document.addEventListener('DOMContentLoaded', contentIntegration) 370 } 371 } finally { 372 window.NRentPlugin = new NRentPlugin(window.NRentPlugin || []) 373 setTimeout(function () { 374 logger.debug('NRentPlugin: Check timeout...') 375 if (checkTimeout && !('NRentBlocker' in window)) { 376 logger.warn('NRentPlugin: Timeout script loading. Sending a script loading error event...') 377 window.NRentPlugin = (window.NRentPlugin || []).push(EVENT_ERROR_LOADING_SCRIPT) 378 } 379 }, LOADING_TIMEOUT_MS) 380 } 381})()
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.