Всім дякую за реально корисні поради !!
![:az:](http://vaz2101.com/public/style_emoticons/default/az.gif)
<script async="" type="text/javascript">/** @preserve version !region_version! */ /** @define {boolean} */ var ENABLE_CONSOLE = true; /** @define {boolean} */ var ENABLE_ERROR_HANDLING = false; (function (window, document, undefined) { "use strict"; /** @const */ var CONFIG = { juke_host: 'juke.mmi.bemobile.ua/bug/pic.gif', host: "pagestat.mmi.bemobile.ua", sslhost: "sslpagestat.mmi.bemobile.ua", source : "source.mmi.bemobile.ua", err_host: "er.mmi.bemobile.ua", timer: { frequency: 5, // seconds pings: [5, 15, 30, 60, 120], stop_after: 5, // minutes check_location_timer: 1 }, ads: { scan_frequency: 5, // seconds // minimal size width: 50, height: 40 } }; extend(CONFIG, window.addonCMeter && addonCMeter.config); /** * Prepare CONFIG array for use. Apply local params for the specific domain. Add parameter for be able to work in iframe (by default is true). * **/ if (CONFIG.custom_url && location.host === CONFIG.custom_url.href) { CONFIG.ads.scan_frequency = CONFIG.custom_url.banner_scan_frequency; CONFIG.work_in_frame = CONFIG.custom_url.work_in_frame; } else { CONFIG.work_in_frame = true; } // this part is already in helpers.js /** * Extend destination object with the items from the source object. * If 3d argument is true, functions from the source are bound and then copied. * Function returns nothing, first argument is modified instead * * @param {Object} dest destination, where to copy items from the source * @param {Object} src source object from where items are taken * @param {Boolean} [bindFuncs] if true - functions in the source will be bound and returned rather then original functions */ function extend(dest, src, bindFuncs) { var k, item; for (k in src) { if (src.hasOwnProperty(k)) { item = src[k]; dest[k] = bindFuncs && "function" === typeof item ? bind(item, dest) : item; } } } var head = { js: function (src, cb) { var s = document.createElement("script"), head = document.head || document.getElementsByTagName('head')[0]; function done (err) { s.onload = s.onerror = s.onreadystatechange = null; if (cb && typeof cb == "function") { cb(err); } } extend(s, { "async": true, "type": "text/javascript", "onload": function () { done(null); }, "onerror": done, "onreadystatechange": function () { if ("loaded" === s.readyState || "complete" === s.readyState) { done(null); } } }); // put src assigning after extend() to make sure it // is being set later than other attributes s.src = src; head.insertBefore(s, head.lastChild); }, onready: function (cb) { function done() { each(head.onready.funcs, function (cb) { cb(); }); delete head.onready.funcs; } function onreadystatechanged() { if ("loading" !== document.readyState) { done(); document.detachEvent("onreadystatechange", onreadystatechanged); } } if ("loading" !== document.readyState) { cb(); return; } if (head.onready.funcs) { head.onready.funcs.push(cb); } else { head.onready.funcs = [cb]; if (document.addEventListener) { document.addEventListener("DOMContentLoaded", done, false); return; } if (document.attachEvent) { document.attachEvent("onreadystatechange", onreadystatechanged); } } }, ready: function (cb) { head.onready(cb); } } window["idCoreOnReady"] = function(id){ IDCore["onFlashReady"](id); }; window["tnsOnStatResult"] = function(e){ console.log("result:" + e.result + " pid:" + e.pid + " e.id: " + e.id); if(e.result != "success") { } }; // generate random value // unused in extension function random(){ var d = new Date().valueOf().toString(); return parseInt(d.substr(d.length - 8, d.length)) + Math.round(Math.random() * Math.pow(10, 9)); }; // resolve url by site protocol, host and path // unused in extension function getUrl(host, sslhost, path){ return location.protocol + "//" + (location.protocol == "https:" ? sslhost : host) + path; }; // bind function to another scope // bind function implementation // unused in extension function delegate(fn, scope){ return function(){ return fn.apply((scope || window), Array.prototype.slice .call(arguments)); }; }; // return now in unixtime function time(){ return new Date().getTime(); }; // send requests by cors function createCors(errorHandler){ var cors; try { if(window.XDomainRequest) { cors = new window.XDomainRequest(); if(errorHandler){ cors.onerror = function(){ errorHandler.call(null, cors); }; } } else { cors = new XMLHttpRequest(); if(errorHandler){ cors.onreadystatechange = function (e) { if (cors.readyState == 4) { if(cors.status == 200){ }else{ errorHandler.call(null, cors); } } }; } } } catch(e) { console.error("cors:" + e); } return cors; }; // check is mobile by regex from useragent // double var isMobile = (function(){ return /Mobi|Mini|Symbian|SAMSUNG|Nokia|BlackBerry|Series|Bada|SymbOS|PLAYSTATION/g .test(navigator.userAgent.toString()); }()); // add param to url function addParam(url, param, value){ var newurl = url; var delimiter = "&"; if(newurl.indexOf("?") == -1) { delimiter = "?"; } newurl += delimiter + param + "=" + value; return newurl; }; /* create UUID * */ function createUUID(){ var s = []; var hexDigits = "0123456789ABCDEF"; for( var i = 0; i < 32; i++) { s[i] = hexDigits.substr(Math.floor(Math.random() * 0x10), 1); } s[12] = "4"; s[16] = hexDigits.substr((s[16] & 0x3) | 0x8, 1); return s.join(""); }; function setCookie(name, value, expires, path, domain, secure){ document.cookie = name + "=" + escape(value) + ((expires) ? "; expires=" + expires : "") + ((path) ? "; path=" + path : "") + ((domain) ? "; domain=" + domain : "") + ((secure) ? "; secure" : ""); }; function getCookie(name){ var cookie = " " + document.cookie; var search = " " + name + "="; var setStr = null; var offset = 0; var end = 0; if(cookie.length > 0) { offset = cookie.indexOf(search); if(offset != -1) { offset += search.length; end = cookie.indexOf(";", offset) if(end == -1) { end = cookie.length; } setStr = unescape(cookie.substring(offset, end)); } } return (setStr); }; function deleteCookie(name){ document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;'; }; var hasLocalStorage = (function(){ try { return "localStorage" in window && window["localStorage"] !== null; } catch(e) { return false; } }()); var hasFlash = (function(){ if(typeof navigator.plugins == "undefined" || navigator.plugins.length == 0) { try { return !!(new ActiveXObject("ShockwaveFlash.ShockwaveFlash")); } catch(er) { return false; } } else { return navigator.plugins["Shockwave Flash"]; } }()); var isIE = (function(){ return /MSIE/.test(navigator.userAgent); }()); var isIE7 = (function(){ return /MSIE\ 7/.test(navigator.userAgent); }()); function getBody(){ var body; try { body = document.getElementsByTagName("body")[0]; } catch(e) { } if(typeof body == "undefined" || body == null) { if(typeof document.body != "undefined") { body = document.body; if(!body) { // console.warn("body is not availible"); } } } return body; }; var isCookieEnabled = (function(){ var cookieEnabled = (navigator.cookieEnabled) ? true : false; if(typeof navigator.cookieEnabled == "undefined" && !cookieEnabled) { document.cookie = "testcookie"; cookieEnabled = (document.cookie.indexOf("testcookie") != -1) ? true : false; deleteCookie("testcookie"); } return (cookieEnabled); }()); function isNotEmpty(str){ return undefined !== str && null != str && str.replace(/\s/g, "") != ""; }; function getPath(str, root){ var path = str; if(path.toLowerCase().indexOf("/") == 0) { if(root) { path = root + path; } else { var location = window.location.protocol.toString() + "//" + window.location.hostname.toString() + window.location.port.toString(); if(location != "") { path = location + path; } } } return encodeURIComponent(path); }; function round(n){ return Math.floor(n * 100) / 100; }; function makeArray(items){ try { return Array.prototype.slice.call(items); } catch(ex) { var i = 0, len = items.length, result = Array(len); while(i < len) { result[i] = items[i]; i++; } return result; } }; var idScope = (function(){ var scope = "l"; if(hasFlash){ scope = "b"; }else if(window.postMessage && (hasLocalStorage || isCookieEnabled)){ scope = "d"; }else if(hasLocalStorage == false && isCookieEnabled == false){ scope = "g"; } try { if(window.chrome){ for(var i in navigator.plugins){ if(/PepperFlashPlayer/gi.test(navigator.plugins[i].filename)){ scope = "c"; break; } } } }catch(e){ console.warn("chrome : PepperFlashPlayer - has some error"); } return scope; }()); var IDCore = (function(){ var isReady = false; var host = window.addonCMeter && addonCMeter.hostAddon; var version = "1.73-r52607"; var short_version = version.replace(/-r\d+$/, ""); var juke_host = CONFIG.juke_host || 'juke.mmi.bemobile.ua/bug/pic.gif'; var hostForFlash = "https://" + CONFIG.source; var cookie = {}; cookie["id"] = "vplayer_user_id"; cookie["wasInitialized"] = "tns_was_initialized"; cookie["wasMigrated"] = "tns_was_migrated"; cookie["flag"] = "flag"; var wasInitialized = false; var holder = "div_holder"; var buffer = new Array(); var uid = ""; var refs = new Array(); function cds(){ function initCds() { try { var remoteStorage = new CrossDomainStorage(hostForFlash, "/id-core/" + version + "/id.html"); remoteStorage["requestValue"](cookie["id"], function(key, id){ onLocalReady(id); }); } catch(e) { console.error("cds.js:" + e); uid = createUUID(); onLocalReady(uid); } } if (typeof CrossDomainStorage === "undefined") { head.js(host + "/id-core/" + version + "/cds.js", initCds); } else { initCds(); } } function setMigrate(){ var expirationDate = new Date(); expirationDate.setFullYear(expirationDate.getFullYear() + 1); // toGMTString() is deprecated setCookie(cookie["wasMigrated"], true, expirationDate.toUTCString(), "/", ""); // when everything is okay onLocalReady(uid); } function migrate(){ if(getCookie(cookie["wasMigrated"])) { return false; } if(isCookieEnabled) { var initialized = getCookie(cookie["wasInitialized"]); if(initialized) { uid = getCookie(cookie["id"]); if(hasLocalStorage) { head.js(host + "/id-core/cds.js", function(){ try { var remoteStorage = new CrossDomainStorage( hostForFlash, "id.html"); remoteStorage["requestValue"](cookie["id"] + ":" + uid, function(key, id){ if(id != uid) { console.error("id: " + id + " != " + uid); } else { setMigrate(); } }); } catch(e) { console.error("migrate:" + e); } }); deleteCookie(cookie["id"]); deleteCookie(cookie["wasInitialized"]); } else if(hasFlash) { window["tns_uid"] = uid; head.js(host + "/id-core/" + version + "/flash.js", function(){ setMigrate(); // delete window["tns_uid"]; }); } return true; } } return false; } function init(){ wasInitialized = true; if(migrate()) { return; } if(hasLocalStorage) { uid = localStorage.getItem(cookie["id"]); if(uid) { onLocalReady(uid); } else { if(window.postMessage && !window.JSON && window.localStorage) { head.js(host + "/json2.min.js", function(){ if(getBody()) { cds(); } else { head.ready(function(){ cds(); }); } }); } else if(window.postMessage && window.JSON && window.localStorage) { if(getBody()) { cds(); } else { head.ready(function(){ cds(); }); } } else { onLocalReady(createUUID()); } } } else { if(hasFlash) { if(getBody()) { head.js(host + "/id-core/" + version + "/flash.js"); } else { head.ready(function(){ head.js(host + "/id-core/" + version + "/flash.js"); }); } } else { uid = getCookie(cookie["id"]); if(!uid) { uid = createUUID(); } onLocalReady(uid); } } } function flushOnReady(){ var i; for(i in buffer) { if(buffer.hasOwnProperty(i)) { var url = buffer[i]["url"]; var params = buffer[i]["params"]; var time = buffer[i]["time"]; var type = buffer[i]["type"]; var onError = buffer[i]["onError"]; if(/^POST$/ig.test(type)) { sendPost(url, params, time, onError); } else { sendGet(url, params, time, type, onError); } } } buffer = Array(); var ref; for(ref in refs) { if(refs.hasOwnProperty(ref)) { refs[ref].call(this, uid); } } refs = new Array(); } function onLocalReady(id){ saveId(id); isReady = true; flushOnReady(); if(hasLocalStorage){ if(!localStorage.getItem(cookie["flag"])) { (new Image).src = location.protocol + "//" + juke_host + "?uid=" + id + "&time=" + new Date().valueOf(); localStorage.setItem(cookie["flag"], "true"); } } else if(isCookieEnabled) { if(!getCookie(cookie["flag"])){ var expirationDate = new Date(); expirationDate.setFullYear(expirationDate.getFullYear() + 1); setCookie(cookie["flag"], "true", expirationDate.toGMTString(), "/", ""); (new Image).src = location.protocol + "//" + juke_host + "?uid=" + id + "&time=" + new Date().valueOf(); } } } function saveId(id){ uid = id; if(hasLocalStorage) { localStorage.setItem(cookie["id"], id); } else if(isCookieEnabled) { var expirationDate = new Date(); expirationDate.setFullYear(expirationDate.getFullYear() + 1); setCookie(cookie["id"], id, expirationDate.toGMTString(), "/", ""); setCookie(cookie["wasInitialized"], true, expirationDate .toGMTString(), "/", ""); } } function addParams(url, params){ var i, key; if(params instanceof Array) { for(i in params) { url = addParam(url, params[i]["key"], params[i]["value"]); } } else { for(key in params) { url = addParam(url, key, params[key]); } } return url; } function onFlashReady(id){ try { var div = document.getElementById(holder); div.parentNode.removeChild(div); } catch(e) { } swfobjectlite = null; onLocalReady(id); } function getVersion(){ return short_version; } function sendPost(url, params, time, onError){ try { var cors = createCors(onError); cors.open("POST", url, true); if(!params) { params = {}; } if(params instanceof Array) { params.push({ "key" : "cookie", "value" : uid }); params.push({ "key" : "time", "value" : time ? time : new Date().valueOf() }); } else { params["cookie"] = uid; params["time"] = time ? time : new Date().valueOf(); } if(isIE) { cors.contentType = "text/plain"; } else { cors.setRequestHeader("Content-type", "application/x-www-form-urlencoded;charset=UTF-8"); } var postParams = addParams("?", params).replace(/^\?/, ""); cors.send(postParams); }catch(e){ console.error(e); } } function sendGet(url, params, time, type, onError){ if(!params) { params = {}; } url = addParam(url, "cookie", uid); url = addParam(url, "time", time ? time : new Date().valueOf()); url = addParams(url, params); // TODO: If this version will be in production -- return send JSONP capability try { // Opera supports CORS only since v12 // For other Operas there is no obvious way to call external API // except injecting script into page if((type && type == "JSONP") || (window.opera && !("withCredentials" in new XMLHttpRequest))) { var script = document.createElement("script"); script.setAttribute("src", url); document.getElementsByTagName("head")[0].appendChild(script); } else if(type && type == "GET") { var cors = createCors(onError); cors.open("GET", url, true); if(isIE == false) { cors.setRequestHeader("Accept", "application/json"); } cors.send(); } } catch(e) { console.log(e); } } return { "init" : function(){ if(wasInitialized == false) { if(isCookieEnabled && !getCookie(cookie["wasMigrated"])){ if(getBody()){ init(); }else{ head.ready(function(){ init(); }); } }else{ init(); } } else if(isReady) { flushOnReady(); } }, "send" : function(url, params, type, onError){ if(!params){ params = {}; } params["vt"] = idScope; var now = new Date().valueOf(); if(isReady) { if(/^POST$/ig.test(type)) { sendPost(url, params, now, onError); } else { sendGet(url, params, now, type, onError); } } else { buffer.push({ "url" : url, "params" : params, "type" : type, "time" : now, "onError": onError }); } }, "onFlashReady" : function(id){ onFlashReady(id); }, "addOnReadyListener" : function(ref){ refs.push(ref); }, "isReady" : function(){ return isReady; }, "getId" : function(){ return uid; }, "version" : function(){ return getVersion(); } }; })(); IDCore["init"](); /*jslint browser:true,devel:true,plusplus:true,regexp:true*/ /*global TUtility,IDCore,addonCMeter,ENABLE_CONSOLE*/ /** @const */ var VERSION = "3.3.291_ua"; var v = VERSION + "/" + IDCore.version(), perf = window.performance, perf_t = perf ? perf.timing : null, started = perf_t ? new Date(perf_t.navigationStart || perf_t.connectStart) : new Date(), ua = navigator.userAgent, mobile = /android|mobi|mini|blackberry|samsung|bada|nokia|series|symb(ian|os)|playstation/i.test(ua), vendors = ["", "moz", "ms", "webkit"], isFrame = top !== self, id = IDCore.getId(), templates = {}, excludeElements = [], // array for keeping exclude elements from video tags subscribers = {}, previousLocation = location.href.replace(location.hash,""); // Utils /** * Just empty function. Intended for some cases as callback where no actions should be performed */ function nop() {} function random() { var d = new Date().valueOf().toString(); return parseInt(d.substr(d.length - 8, d.length)) + Math.round(Math.random() * Math.pow(10, 9)); }; var hasFlash = (function(){ if(typeof navigator.plugins == "undefined" || navigator.plugins.length == 0) { try { return !!(new ActiveXObject("ShockwaveFlash.ShockwaveFlash")); } catch(er) { return false; } } else { return navigator.plugins["Shockwave Flash"]; } }()); /** * Strip initial & trailing whitespaces. * * @param str * @returns {String} */ function trim(str) { if (String.prototype.trim !== undefined) { return String.prototype.trim.call(str); } return str.replace(/^\s+|\s+$/g, ''); } /** * Apply callback to each element of the sequence (arr item / sting symbol) * * @param {Array|String|NodeList} arr array to process * @param {Function} cb callback to apply to each array item */ function each(arr, cb) { var i, l; if (!arr) { return; } l = arr.length; if (!l) { return; } for (i = 0; i < l; i += 1) { try { cb(arr[i], i, arr); } catch (ignore) {} } } /** * We need such function since IE < 9 doesn't support it natively for arrays -
http://stackoverflow.com/a/9768663 * * @param {Array} arr * @param item * @return {Number} index >= 0 if found, -1 otherwise */ function indexOf(arr, item) { var i = 0, l = arr.length; while (i < l) { if (arr[i++] === item) { return i - 1; } } return -1; } function bind(fn, obj) { return function () { return fn.apply(obj, arguments); }; } /** * asynchronous version of each function - apply callback to each element of array and call in async way and finally call custom callback * * @param {Array} arr array to walk * @param {Function} cbEach callback to apply to each element of the array * @param {Function} [cbEnd] function to be called on the end of * @returns {Boolean|undefined|Number} setInterval ID, false or nothing */ function iterateAsync(arr, cbEach, cbEnd) { var interval, l; cbEnd = cbEnd || nop; if (!arr) { return false; } l = arr.length; if (0 === l) { cbEnd(); } if (!l) { return undefined; } interval = setInterval(function () { var i = 10; // every time use next 10 items from arr do { l -= 1; if (-1 === l) { clearInterval(interval); cbEnd(); return; } cbEach(arr[l], l, arr); } while (--i); }, 4); return interval; } /** * Extend destination object with the items from the source object. * If 3d argument is true, functions from the source are bound and then copied. * Function returns nothing, first argument is modified instead * * @param {Object} dest destination, where to copy items from the source * @param {Object} src source object from where items are taken * @param {Boolean} [bindFuncs] if true - functions in the source will be bound and returned rather then original functions */ function extend(dest, src, bindFuncs) { var k, item; for (k in src) { if (src.hasOwnProperty(k)) { item = src[k]; dest[k] = bindFuncs && "function" === typeof item ? bind(item, dest) : item; } } } function on(node, event, cb) { if (window.addEventListener) { node.addEventListener(event, cb, false); } else if (window.attachEvent) { node.attachEvent("on" + event, cb); } } /** * Schedule callback to be run when DOM is ready. * Callback will be fired immediately if DOM has already been parsed. * * @param {Function} cb callback to execute */ function onready(cb) { function done() { each(onready.funcs, function (cb) { cb(); }); delete onready.funcs; } function onreadystatechanged() { if ("loading" !== document.readyState) { done(); document.detachEvent("onreadystatechange", onreadystatechanged); } } if ("loading" !== document.readyState) { cb(); return; } if (onready.funcs) { onready.funcs.push(cb); } else { onready.funcs = [cb]; if (document.addEventListener) { document.addEventListener("DOMContentLoaded", done, false); return; } if (document.attachEvent) { document.attachEvent("onreadystatechange", onreadystatechanged); } } } /** * Schedule callback to be run on window load. * Callback will be fired immediately if window is * already neither loading nor parsing DOM. * The only argument passed against callback is time when * load state had been reached. * * @param {Function} cb callback function to be run */ function load(cb) { var q; function done() { var e = "loadEventStart"; load.time = perf_t && perf_t[e] > 0 ? new Date(perf_t[e]) : new Date(); while (q.length) { q.shift()(load.time); } } if (load.time) { cb(load.time); return; } if (!load.queue) { load.queue = []; on(window, "load", done); } q = load.queue; q.push(cb); if ("complete" === document.readyState) { done(); } } function onViewportChange(cb) { on(window, "scroll", cb); on(window, "resize", cb); cb(); } // TODO: Investigate if it is better to pass object w/ methods // instead of two separate callbacks. // Will it need to implement @interface to compile properly? function onVisibilityChange(cbVis, cbInv) { var i, field; cbInv = cbInv || nop; function trigger() { var state = document[field] || "visible"; switch (state) { case "hidden": cbInv(state); break; default: cbVis(state); break; } } for (i = 0; i < vendors.length; i++) { field = vendors[i] + "VisibilityState"; field = field.charAt(0).toLowerCase() + field.substring(1); if (document[field]) { // we create and register new trigger() on // every call to function onVisibilityChange on(document, vendors[i] + "visibilitychange", trigger); if ("hidden" !== document[field]) { trigger(); } return; } } trigger(); } /** * Split string to Key-value object. * @param {String} source string for parse * @returns {Object} Key-value Object */ function parseParams(source) { var params = {}; if (source) { each(source.split("&"), function (param) { var p = param.split("="); params[decodeURIComponent(p[0].toLowerCase())] = decodeURIComponent(p[1]); }); } return params; } /** Function tries identify path to ads destination. * * @param {Element} node for inspection. * @returns {String|Boolean} path to ads source or false. */ function getDestinationPath(node) { var tagName = node.nodeName, cl, param_str, params_list = node.childNodes, parent = node.parentNode, node_attr = '', params = {}; function findParam(params) { var result = false; each(['link1', 'clicktag', 'alink1', 'url'], function (attr_value) { if (params.hasOwnProperty(attr_value)) { result = params[attr_value]; } }); return result; } switch (tagName) { case "IMG": while (parent) { if ("A" === parent.nodeName) { cl = parent.href; break; } parent = parent.parentNode; } break; case "OBJECT": each(params_list, function (param) { if ("PARAM" === param.nodeName && "flashvars" === param.getAttribute("name").toLowerCase()) { param_str = param.getAttribute("value"); params = parseParams(param_str.replace(/&/g, "&")); cl = findParam(params); } }); break; case "EMBED": node_attr = node.getAttribute("flashvars"); if (node_attr) { params = parseParams(node_attr.replace(/&/g, "&")); cl = findParam(params); } break; } try { if ("string" === typeof cl) cl = decodeURIComponent(cl); } catch (ignore) {} return cl; } function getDocumentHeight() { var b = document.body, d = document.documentElement, h = b ? Math.max(b.scrollHeight, b.offsetHeight, b.clientHeight) : 0; return Math.max(h, d.scrollHeight, d.offsetHeight, d.clientHeight); } function isVisible(node) { var retVal = false, r, rects = node.getClientRects(), h = getDocumentHeight(), i = rects.length; while (i--) { r = rects[i]; if (0 === r.width || 0 === r.height) { continue; } if (r.top > 0) { return r.top <= h; } if (r.bottom > 0) { return r.bottom <= h; } retVal = true; } return retVal; } /** * Get specific style's value of the DOM element * * @param {Element} element DOM element to explore * @param {String} name style name * @returns {String|null} Text style value **/ function getStyle(element, name) { var s; if (document.defaultView && document.defaultView.getComputedStyle) { // W3C name = name.replace(/([A-Z])/g, "-$1").toLowerCase(); s = document.defaultView.getComputedStyle(element, null); return s && s.getPropertyValue(name); } if (element.currentStyle) { // IE? return element.currentStyle[name]; } if (element.style && element.style[name]) { return element.style[name]; } return null; } /** * Calculate offset of the element, taking into account all his parents. * If on any step there is NaN (seems no offsetTop / offsetLeft property) - undefined is returned instead * Falsie argument returns (0; 0) coordinates * * @param {Object} e DOM element object * @returns {Object} {left: X, top: Y} */ function getOffset(e) { if (!e) { return { top: 0, left: 0 }; } var offset = { top: e.offsetTop, left: e.offsetLeft }, parent = getOffset(e.offsetParent); offset.top += parent.top; offset.left += parent.left; if (isNaN(offset.top)) { offset.top = undefined; } if (isNaN(offset.left)) { offset.left = undefined; } return offset; } // WARNING: it will return zero as height for document.body if there is // only one element on page and it has been positioned absolutely function getSize(node) { var props = { w: ["paddingLeft", "paddingRight", "borderLeftWidth", "borderRightWidth"], h: ["paddingTop", "paddingBottom", "borderTopWidth", "borderBottomWidth"] }, s = { w: node.offsetWidth, h: node.offsetHeight }, type, i, style; for (type in s) { if (s.hasOwnProperty(type)) { if (s[type] > 0) { i = props[type].length; while (i--) { s[type] -= parseInt(getStyle(node, props[type][i]), 10) || 0; } } style = s[type] || getStyle(node, "w" === type ? "width" : "height"); if (/%/.test(style)) { continue; } s[type] = parseInt(style, 10); } } return s; } function getDoc(node) { // second is for IE<
http://stackoverflow.com/a/6582370) return node.contentDocument || (node.contentWindow && node.contentWindow.document) || node.document || null; } // this must be tested on different browsers, code looks like obsolete function getWindowTop() { var b = document.body, d = document.documentElement; if ("number" === typeof window.pageYOffset) { return window.pageYOffset; // Netscape compliant } if (d && d.scrollTop) { return d.scrollTop; // IE6 standards compliant mode } if (b && b.scrollTop) { return b.scrollTop; // DOM compliant } return 0; } /** * Iterate through node children (including node itself) applying callback * to each of them. * Useful for searching something inside document. * * @param node {DOMElement} * @param {Function} cb callback to apply to each node * @returns {*} */ function domIterate(node, cb) { var nodes = node.childNodes, i = nodes.length, ret; while (i--) { ret = domIterate(nodes[i], cb); if (ret) { return ret; } } return cb(node); } function iframeAccessible(frame) { try { var src = frame.getAttribute("src") || "", index = src.indexOf("//" + location.host), document; if ((0 !== src.indexOf("http") && 0 !== src.indexOf("//")) || (index > -1 && index < 8)) { document = getDoc(frame); if (document && document.getElementById) { return true; } } } catch (ignore) {} return false; } function getNodeSrc(node) { var src, i, params, param; function checkExcludes(element) { if (-1 === indexOf(excludeElements, element)) { excludeElements.push(element); } } if (!node.tagName) { return false; } if ("OBJECT" === node.tagName) { src = node.getAttribute("data"); if (!src) { // [fix23828] as of msdn.microsoft.com/library/ms536439#5 /* params = node.getElementsByTagName("param"); i = params.length; while (i--) { if ("movie" === params[i].getAttribute("name")) { return params[i].getAttribute("value"); } } */ params = node.childNodes; i = params.length; while (i--) { param = params[i]; if ("PARAM" === param.nodeName && "movie" === param.getAttribute("name").toLowerCase()) { return param.getAttribute("value"); } } } return src; } if ("VIDEO" === node.tagName) { var sources = node.childNodes, length = sources.length, sourceElement, src ,type; if (!node.canPlayType){ return false; } for (var i = 0; i < length; i++) { sourceElement = sources[i]; if ("SOURCE" === sourceElement.nodeName) { type = sourceElement.getAttribute("type"); if (node.canPlayType(type)) { src = sourceElement.getAttribute("src") || false; each(node.getElementsByTagName("embed"), checkExcludes); each(node.getElementsByTagName("object"), checkExcludes); return src; } } } src = node.getAttribute("src"); return src; } else { src = node.getAttribute("src"); if (src != null && src.substring(0, 10) !== 'data:image') { src = node.getAttribute("src"); } else { if (src && src.substring(0, 10) == 'data:image') { return CONFIG.juke_host || null; } else { return null } } } return src; } function emit (event, data) { each(subscribers[event], function (func) { if (ENABLE_CONSOLE) { console.log("fire callback"); } data = func.call(this, data); }); return data; } // Classes /** * A message. * @constructor */ function CM_Message(type, obj) { var that = this; function addonReady(e) { if ("AddonCMeterReady" !== e.data) { return; } that.initialize(); window.removeEventListener("message", addonReady, false); } on(window, 'beforeunload', function(e) { that.doNotSendError = true; }); if (arguments.length >= 2) { extend(this, obj, true); } /** * `params` must be an array, but may have additional own properties. * They will be sent along w/ ordinary array items. * * For instance, consider the following: * var params = ["~param1~", 2]; * params.customKey = "customVal"; * * This will send following message: * param1: "~param1~" * param2: 2 * customKey: "customVal" */ this.params = this.params || []; this.params[0] = "~cm_" + type + "~"; if (this.initialize) { // XXX: Google Chrome extension workaround. if (window.localStorage && "initializing" === localStorage.getItem("AddonCMeter")) { window.addEventListener("message", addonReady, false); } else { this.initialize(); } } } extend(CM_Message.prototype, { httpMethod: "GET", origin: location.protocol + "//" + ("https:" === location.protocol ? CONFIG.sslhost : CONFIG.host), sid: random(), /** * Compile and return common properties of client, such as location, referrer, screen properties and others * * @this {CM_Message} * @return {Object} Keys: location, referrer, is_flash, session_id, version, sw, sh, scd [, spd, tnscm_plid, tnscm_cat, tnscm_adn] * */ getCommonParams: function () { var p = { "location": encodeURIComponent(window.location.href), "referrer": encodeURIComponent(this.referrer || document.referrer), "is_flash": hasFlash ? "1" : "0", "session_id": this.sid, "version": v, "sw": screen.width, "sh": screen.height, "scd": screen.colorDepth }; if (screen.pixelDepth) { /** @expose */ p.spd = screen.pixelDepth; } if (window.addonCMeter && addonCMeter.PLID) { /** @expose */ p.tnscm_plid = addonCMeter.PLID; } if (window.tnscm_cat) { /** @expose */ p.tnscm_cat = tnscm_cat; } if (window.tnscm_adn) { /** @expose */ p.tnscm_adn = window.tnscm_adn; } if (window.tnscm_pak) { /** @expose */ p.tnscm_pak = tnscm_pak; } return p; }, /** * Send message. Run either commit or onBeforeCommit handler if exists * * @this {CM_Message} **/ send: function () { if (this.onBeforeCommit) { this.onBeforeCommit(); } else { this.commit(); } }, /** * Actually send message (with id.js) * * @protected * @this {CM_Message} **/ commit: function () { var that = this, i = 0, item, params = {}, cloned = []; extend(params, that.getCommonParams()); extend(cloned, that.params); while (cloned.length) { i += 1; item = cloned.shift(); if (item || 0 === item) { params["param" + i] = item; } } extend(params, cloned); if (!ENABLE_ERROR_HANDLING) { IDCore.send(that.url, emit("send", params), that.httpMethod); } else { IDCore.send(that.url, emit("send", params), that.httpMethod, function (xhr) { if (that.doNotSendError) { return; }; // setup error handler (see #36588) var params, resp = xhr.responseText || ""; params = { "http_code": encodeURIComponent(xhr.status), "http_status": encodeURIComponent(xhr.statusText), "http_body": encodeURIComponent(resp.substr(0, 400)), "message_type": that.params[0] }; extend(params, that.getCommonParams()); if (ENABLE_CONSOLE) { console.log(params, "error reported"); } IDCore.send(location.protocol + "//" + CONFIG.err_host + "/e", params, "GET"); }); } if (ENABLE_CONSOLE) { console.log(that.params[0], "sent"); console.log(params); } } }); extend(CM_Message.prototype, { url: CM_Message.prototype.origin + "/pagestat/PageStatEntry" }); /** * An advertisement template. * @constructor */ function CM_Template(params) { var that = this, num = ["w", "h"], rexp = ["src"]; // default values // XXX: it is not exposed anywhere, but current implementation of // this constructor is tied to names. Consider rewriting into code, // better optimized for compiling by Google Closure Compiler in future /** @expose */ this.w = null; /** @expose */ this.h = null; each(params, function (param) { var k, v = parseInt(param, 10); if (!isNaN(v)) { k = num.shift(); } else if (param instanceof RegExp) { k = rexp.shift(); v = param; } if (k) { that[k] = v; } }); // empty template should not catch anything if (!this.src && (this.w || this.h)) { // see comment about Closure Compiler above /** @expose */ this.src = /./; } } extend(CM_Template, { /** * Create list of signatures (objects) based on incoming array of templates. Synchronous method * * @param {Array} arr list of signature templates * @returns {Object} array of signatures */ build: function (arr) { var use = true, isCurrent = false, retVal = {common: [], current: []}; each(arr, function (t) { if (t instanceof RegExp) { use = isCurrent = t.test(window.location.host); } else if (use && !isCurrent) { retVal.common.push(new CM_Template(t)); } else if (use && isCurrent) { retVal.current.push(new CM_Template(t)); } }); return retVal; }, embeds: function (doc) { var embeds = [], objects = []; doc = doc || document; each(doc.getElementsByTagName("embed"), function (embed) { var parent = embed.parentNode; while (parent) { if ("OBJECT" === parent.nodeName) { objects.push(parent); break; } parent = parent.parentNode; } if ( -1 === indexOf(excludeElements, embed)) { embeds.push(embed); } }); each(doc.getElementsByTagName("object"), function (node) { // skip <object>s, that contain nested <embed> if (-1 === indexOf(objects, node) && -1 === indexOf(excludeElements, node)) { embeds.push(node); } }); return embeds; }, // passing real DOM Nodes every time was considered too expensive scan: function (nodesData) { var ads = [], isAd, typeTemplate; function checkNodes(type, node) { each(templates.yes[type], function (t) { if (t.check(node[0], node[1], node[2])) { isAd = true; if (ENABLE_CONSOLE) { console.log('include ' + ' ' + node[0] + ' [' + node[1] + ', ' + node[2] + '] by signature - ' + t.src + '[' + t.w + ', ' + t.h + '] (' + type + ')'); } } }); if (isAd) { // take out from inside templates.yes loop because it didn't execute if templates.yes.current is empty each(templates.no[type], function (t) { if (t.check(node[0], node[1], node[2])) { if (ENABLE_CONSOLE) { console.log('exclude ' + node[0] + ' [' + node[1] + ', ' + node[2] + '] by signature - ' + t.src + '[' + t.w + ', ' + t.h + '] (' + type + ')'); } isAd = false; } }); } } // TODO: use filter() here instead of each() each(nodesData, function (node, index) { isAd = false; for (typeTemplate in templates.yes) { if (templates.yes.hasOwnProperty(typeTemplate)) { checkNodes(typeTemplate, node); } } if (isAd) { ads.push(index); } }); return ads; } }); extend(CM_Template.prototype, { /** @this {CM_Template} */ check: function (src, w, h) { if (this.src && !this.src.test(src)) { return false; } if (this.w && this.w !== w) { return false; } if (this.h && this.h !== h) { return false; } return true; } }); // Run only once if (!window["__cm"]) { var cm = window["__cm"] = []; extend(cm, { "on": function (event, callback) { if (!subscribers[event]) { subscribers[event] = []; } subscribers[event].push(callback); } }); } // TODO: !region-id is better to be defined as @const and // then replaced during Closure Compiler compilation // as well as VERSION variable if (indexOf(window['__cm'], "ua") == -1) { window.tnscm_adn = window.tnscm_adn || []; if (indexOf(window.tnscm_adn, "inline_cm") < 0) { var cmInlined = domIterate(document, function (node) { if (8 === node.nodeType && "MMI CMeter" === trim(node.nodeValue)) { return true; } }); if (cmInlined) { tnscm_adn.push("inline_cm"); } } templates.yes = CM_Template.build([ [/\.adocean\.pl\//i], [/\.googlesyndication\.com\//i], [/static\..*\.kcdn\.kz\//i], [/base\.kiwi\.kz\//i], [/rate\.ru\/banner/i], [/b\.c8\.net\.ua\//i], [/post\.rmbn\.net\//i], [/sensismediasmart\.com\.ua/i], [/dotua\.org\//i], [/advideo\.com\.ua\//i], [/admixer\.net/i], [234, 200], [205, 333], [205, 280], [205, 60], [203, 70], [950, 90], [760, 90], [730, 60], [730, 90], [728, 90], [640, 90], [500, 100], [468, 120], [468, 60], [320, 76], [320, 60], [300, 600], [300, 250], [300, 240], [285, 130], [250, 250], [240, 400], [240, 350], [240, 200], [240, 90], [234, 60], [230, 90], [230, 60], [180, 150], [160, 600], [160, 60], [150, 60], [120, 600], [120, 240], [120, 60], [/bigbn\.com\.ua/i], [/adriver\.ru/i], [/banner\.km\.ua/i], [/bannerka\.ua/i], [/\/.*\/adfox\/.*\/.*\.swf/i], [/rle\.ru/i], [/reclama\./i], [/adcenter\.net/i], [/bbn\.img\.com\.ua/i], [/images\.rambler\.ru\/upl\//i], [/\/images\/.*\/.*\/.*\/.*300x250\./i], [/ab\.adpro\.com\.ua\/.*\/.*\/.*\./i], [/images\/.*\/.*300x150.*\./i], [/baner\./i], [/www\.ukr\.net\/img\/autos\/auto.*\.jpg$/i], [/\/data\/enquetes\/images\/banner_.*\./i], [/www\.ukr\.net\/_temp\/.*\/..\/..\/.*\.jpg$/i], [/ad.*\.bigmir\.net/i], [/meta\.ua\/img\/.*\/.*_200_300_.*href=/i], [/\/css\/partner-swf\/.*\./i], [/\/banners_files\/.*\./i], [/b\.ex\.ua\/.*\/.*\.swf/i], [/adbrite\.com/i], [/\/openx\/www\/images\/.*\./i], [/\/bnr\//i], [/ban\./i], [/\/adban\/.*\/.*\/.*\./i], [/informers\.sinoptik\.ua/i], [/adnet\.com\.ua\/banners\/.*\/.*\/.*\/.*\./i], [/rose\.ixbt\.com/i], [/\/adv\//i], [/\/pagead\/imgad.id=/i], [/\/adimage\.php/i], [/i\.holder\.com\.ua\/.*\/.*\/.*\/.*\./i], [/img\.gad\.org\.ua\/.*\/.*\./i], [/\/images\/.*\/.*\/.*\/.*\.swf$/i], /\.ge/, [/\/www\/images\//i], [/baner/i], [/banner/i], [640, 100], /\.md/, [/\/banner/i], /\.kz/, [/\/banners/i], /mail\.ru/, [/r\.mradx\.net\//i, 300, 300], [/r.*\.mail\.ru\/b.*\.gif$/i], [/r.*\.mail\.ru\/b.*\.png$/i], [/r.*\.mail\.ru\/b.*\.jpg$/i], [/r.*\.mail\.ru\/b.*\.swf$/i], [/promoblocks\.ru/i], /podrobnosti\.ua/, [/media\.adrcdn\.com\/ads\//i], /football\.ua/, [/spadsmedia\.com\/www\/delivery\/afr\.php\//i], [/sportingbet\.host\.bannerflow\.com\//i], /total\.kz/, [1000, 115], [/\/gb\.php..*=/i], /namba\.net/, [468, 90], [1000, 90], [200, 350], /besplatka\.ua/, [300, 300], [660, 90], /nur\.kz/, [/\/advert\//i], /magnolia-tv\.com/, [668, 60], [300, 100], [/\/files\/ban\//i], [100, 100], /blogas\.lt/, [/static-system\.adtarget\.me\//i], [/banners\.adnet.*\.lt\//i], [980, 200], [750, 200], [980, 180], /companion\.ua\//, [960, 90], /172\.16\.0\./, [/\.gif/i], [/\.png/i], [/\.swf/i], [/\.jpeg/i], [/\.jpg/i], /ex\.ua/, [/ad_click/i], /^cm\.mmi\.macc\.com\.ua$/, [100, 100], /aviso\.ua/, [/banner\.ool\.ua\//i] ]); templates.no = CM_Template.build([ [/ticket\.net\//i], [/hoptopboy\.com\//i], [/porn\..*com\//i], [/kvihit\.com\//i], [/imagevenue\.com\//i], [/obrona\.org\//i], [/null$/i], [/interakt\.md\/content/i], [/gwallet\.com\//i], [/predictormedia\.com\//i], [/img\.ubr\.ua\/banners\/.*adsense\./i], [/dotomi\.com\//i], [/mobileadhost\.com\//i], [/adsoptimizer\.net\//i], [/ad-sys\.com\//i], [/drivesection\.net\//i], [/tooldiv\.net\//i], [/livexjs\.net\//i], [/fellabooks\.net.*\/$/i], [/chocolatemx\.net\//i], [/aspire-guitar\.com\//i], [/golinkon\.info\//i], [/perfectnavigator\.com\//i], [/aceadsys\.net\/show_banner\//i], [/googleads/i], [/\.host\.bannerflow\.com\//i], [/serving.*\.com\//i], [/tracking\.m6r\.eu\//i], [/upload.*\/articles\//i], [/zedo\.com\//i], [/gogorithm\.com\//i], [/pdmayt\.com\//i], [/metrigo\.com\//i], [/vdaqyqwsrd\.ru\//i], [/qrdeom\.com\//i], [/tatami-solutions\.com\//i], [/cloudfront\.net\//i], [/mrlmedia\.net\//i], [/mothernist\.hiro\.tv\//i], [/\.wlboon\.com\//i], [/admetaserver\.com\//i], [/\.ru\/show_banner\//i], [/tags\.qservz\.com\//i], [/neomion\.com\//i], [/^http:\/\/54\./i], [/x\.abk954\.com/i], [/creative\.xtendmedia\.com\//i], [/statisticsreporting\.com\//i], [/imhonet\.ru\/element\//i], [/mailsmania\.ru\//i], [/romilit\.com\//i], [/proligtb\.com\//i], [/brucelead\.com\//i], [/exebid\.ru\//i], [/koluty\.com\//i], [/\.retark\.com\//i], [/com\.adv\.vz\.ru\//i], [/adserver/i], [/webmoney\.ua\/tools\//i], [/weropiy\.com\//i], [/\/games\/img\//i], [/flashgames.*\..*\//i], [/games\.info\//i], [/maikaru\.ru\/picture\//i], [/zvek\.com\.ua\/images\//i], [/get_qrapi/i], [/grandcapital\.ru\/static\/img/i], [/creativecdn\.com\//i], [/\.rontar\.com\//i], [/greefl\.com\//i], [/\.jutulep\.com\//i], [/baseflash\.com\//i], [/media\.tumblr\.com\//i], [/gstatic\.com\//i], [/ssp\.adriver\.ru\/cgi-bin\/sync\.cgi/i], [/tractionize\.com\//i], [/secure\.demand-go\.com\//i], [/rbc\.ua\/static\/adsense/i], [/tvi\.ua\/adsense/i], [/yourbucks\.org\//i], [/datamind\.ru\//i], [/fresh-cup\.org\//i], [/ad\.starlightmedia\.ua\//i], [/financecontext\.ru\//i], [/attiveri\.com\/.* $/i], [/youtube\.com\//i], [/meta\.ua\/cell\.php/i], [/paramedjo\.com\//i], [/intencysrv\.com\//i], [/kilopog\.com\//i], [/gravyseals\.com\//i], [/media6degrees\.com\//i], [/lokomusic\.com\//i], [/tisa.ama\.com\/banner\.php/i], [/ministerial5\.com\//i], [/admailtiser\.com\//i], [/adgorithms\.com\//i], [/\/media\/gallery\//i], [/\.dotua\.org\/.*\/cover\/.*\.jpg$/i], [/wp-content\/upload/i], [/netdna-cdn\.com\//i], [/\/logo/i], [/adsmile\.biz\//i], [/medads\.ru\//i], [/gittigidiyor\.com\//i], [/oneund\.com\//i], [/xmasdom\.com\//i], [/rainoftraffic\.info\//i], [/1xbet\.com\//i], [/clkrev\.com\//i], [/pub-fit\.com\//i], [/clicksor\.com\//i], [/sendspace\.com\//i], [/pgssl\.com\//i], [/rutarget\.ru\//i], [/datropy\.com\//i], [/dolka\.ru\//i], [/batanga\.net\//i], [/adorika\.net\//i], [/rfihub\.com\//i], [/loponop\.com\//i], [/palgames\.info\//i], [/play882\.info\//i], [/medialand\.ru\//i], [/funnygamezer\.info\//i], [/cloudgamezer\.com\//i], [/utrehter\.com\//i], [/hopto\.me\//i], [/intag\.co\/.* $/i], [/adk2\.com\//i], [/img\.admaster\.net\//i], [/openx\.net\//i], [/firstadvplug\.com\//i], [/pirrit\.com\//i], [/metka\.ru\//i], [/tomobol\.com\//i], [/adzoook\.com\//i], [/adservingfree\.info\//i], [/drgo\.ru\//i], [/slopty\.ru\//i], [/tradedoubler\.com\//i], [/fastloca\.com\//i], [/hide4you\.com\//i], [/proxy\.net\//i], [/bannerhost\.ru\//i], [/bannercity\.ru\//i], [/m2pub\.com\//i], [/theseaapp\.com\//i], [/holisticmedicalwellness\.com\//i], [/qonenoj\.ru\//i], [/amazonaws\.com\//i], [/ipicture\.ru\/uploads\//i], [/reacten\.com\//i], [/thinglink\.me\//i], [/ad\.mail\.ru\/adi\//i], [/k8media\.com\//i], [/notificatoin\.com\//i], [/co-co-co\.co\//i], [/\.dd34\.ru\//i], [/screenshot/i], [/yidop\.com\//i], [/phncdn\.com\//i], [/pokitom\.com\//i], [/perfectmoney\.is\//i], [/20dollars2surf\.com\//i], [/bet-at-home\.com\//i], [/\.derploime\.com\//i], [/\.nekki\.ru\/banner\.php/i], [/tlvmedia\.com\//i], [/yoz5\.info\//i], [/game.*\.info\//i], [/jumbaexchange\.com\//i], [/media-servers\.net\//i], [/gnezdo\.ru\//i], [/quelliclub\.ru\/slider\//i], [/all\.biz\/img\/.*\/catalog\/.*\.png/i], [/azd3\.info\//i], [/26sec\.com\//i], [/magicplayer\.torrentstream\.org\//i], [/refban\.com\//i], [/microads\.ru\//i], [/scanmedios\.com\//i], [/trkclk\.net\//i], [/game.*\.com\//i], [/062\.ua\/delivery\/afr\.php/i], [/ro2\.biz\/ad\.php/i], [/gmodules\.com\//i], [/bremdy\.ru\//i], [/biglu\.ru\//i], [/pricora\.com\//i], [/twitbridge\.com\//i], [/resultsaccelerator\.net\//i], [/gayua\.com\//i], [/okitspace\.com\//i], [/yottos\.com\//i], [/teaserjs\.info\//i], [/wambacdn\.net\//i], [/adultadworld\.com\//i], [/adnetworkme\.com\//i], [/seethisinaction\.com\//i], [/cameleo\.ru\//i], [/exoclick\.com\//i], [/\.rubiconproject\.com\//i], [/\.adnetwork.*\.net\//i], [/mediads\.info\//i], [/\.zanox\.com\//i], [/\.abnad\.net/i], [/reachjunction\.com\//i], [/\.e-viral\.com\//i], [/\.traffichaus\.com\//i], [/\.cmle\.ru\//i], [/datam\.com\//i], [/improvemedianetwork\.com\//i], [/adxplosions\.com\//i], [/mediaplex\.com\//i], [/redintelligence\.net\/request_content\.php/i], [/baserve\.net\/serve\.php/i], [/ktbt\.ru\/b\.php/i], [/sociomantic\.com\//i], [/yangot\.com\//i], [/static.*\.rutracker\.org\/iframe/i], [/partners\.otpusk\.com\/media\.php/i], [/image\.tsn\.ua\/media\/images/i], [/nepalon\.com\//i], [/\.56.*\.net\/.*2\.php/i], [/\/vast\.php/i], [/ad.*\.adkserve\.com\//i], [/r\.c8\.net\.ua\/getiframe\.php/i], [/s\.holder\.com\.ua\/s/i], [/\.avazu\.net\//i], [/media\.glispa\.com\//i], [/squirrelsigdrs\.in\//i], [/overridingnichts\.in\//i], [/tecontx\.com\//i], [/ad-srvr\.com\//i], [/pswec\.com\//i], [/hubrus\.com\//i], [/beatwaretranscribing\.in\//i], [/ads\.people-group\.net/i], [/holyclick\.ru/i], [/\.bidsystem\.com/i], [/zpk200\.com\/serve/i], [/imgads\..*\.net\/afr\.php/i], [/\.btricl3\.ru\/js\/rot\.php/i], [/\.tizerbank\.com\//i], [/\.plomihy\.com/i], [/static\.adv.*\.ru\/banners\//i], [/meta\.ua\/f_new\.asp/i], [/bdv\.bidvertiser\.com\/bidvertiser\.dbm/i], [/squirrelsigdrs\.in\/banners\/show\.php/i], [/code\.gif/i], [/calend\.ru\/img\/calendar\//i], [/hochu\.ua\/images\/articles\//i], [/tagcloud\.swf/i], [/myinfotopia\.com\//i], [/swfhttprequest\.swf/i], [/cityads\.ru\//i], [/\/www\/delivery\//i], [/z5x\.net\//i], [/adotube\.com\//i], [/lux-bn\.com\.ua\//i], [/criteo\.com\//i], [/autocompleteplus\.com\//i], [/akamaihd\.net\//i], [/etgdta\.com/i], [/soundmanager.*\.swf/i], [/player\.swf/i], [/img\.traffim\.com\//i], [/sharedaddomain\.com\//i], [/avalala\.com\//i], [/meta\.ua\/img\/b\/roll_flv2\.swf/i], [/flowplayer/i], [/manifest\.f4m/i], [/radikal\.ru\//i], [/jsonlock\.net\//i], [/medbrowse\.com\.ua\/oops/i], [/\.yandex\./i], [/proxy\.com/i], [/ternopilmarket\.net\/modules\/goods\/images\//i], [/proxy.*\.media\.online\.ua\//i], [/\/picture.*_user\//i], [/img.*\.begun\.ru\//i], [/topdownloads\.ru\//i], [/gloker\.org\/upload/i], [/e-parfum\.in\.ua\/products_image\//i], [/mycdn\.me\//i], [/gallery\.ru\//i], [/adxpansion\.com\//i], [/creoads\.com\//i], [/bm\.img\.com\.ua\//i], [/adserver\.juicyads\.com\//i], [/a\.s3\.ua\//i], [/servedbyadbutler\.com/i], [/kidstaff\.net/i], [/counter\.png/i], [100, 100], [/\.rjainc\.com\/images\/uploads\//i], [/\/widget.*\//i], [/lh.*\.ggpht\.com\//i], [/cdn\.adnxs\.com/i], [/mathtag\.com/i], [/kavanga\.ru/i], [/anonymizer\.com\.ua/i], [/\.adnxs\.com/i], [/\.yadro\.ru/i], [/\/img.*\/photo.*\//i], [/\/foto\//i], [/odnoklassniki\./i], [/static\/images/i], [/\.vk\.me\//i], [/rollingstone\.com\//i], [/\/interview.*\//i], [/\/post.*\//i], [/ads.*\.contentabc\.com\//i], [/ads.*\.msn\.com\//i], [/ads\.webmasters\.ru\//i], [/ads\.vsisumy\.com\//i], [/ads\.trk4\.com\//i], [/ads\.trafficjunky\.net\//i], [/files\/images/i], [/ads\.porn.*\//i], [/4baby\.ua\/pictures/i], [/\.de\//i], [/\/thumb.*\//i], [/ad\.drugasmuga\.com\/ban\.php/i], [/\/public\/images\/gallery\//i], [/w.*\.am15\.net\//i], [/imgn\.dt00\.net\//i], [/lcads\.ru\//i], [/gazzete\.mk\.ua\/wp-content\/uploads\//i], [/techniks\.mk\.ua\/wp-content\/uploads\//i], [/img\.terrikon\.info\//i], [/img\.ria\.ua\/photos\/adv\//i], [/optimizedby\.brealtime\.com\//i], [/\/uploads\/posts/i], [/source\.mmi\.bemobile\.ua\/video\//i], [/avatar/i], [/\.pcads\.ru\//i], [78, 78], [/uploads\.ru\//i], [88, 40], [/fliphotos\.com\//i], [/rand_img\.php/i], [/\/images_slandocomua\//i], [/chrome-extension:/i], [/about:blank/i], [/data:/i], [/hotline\.ua\/img\/tx\//i], [/gazeta\.ua\/img\/preview\//i], [/www\.ex\.ua\/show\//i], [/4baby\.ua\/productpicture\//i], [/img\.gad\.org\.ua/i], [/1x1\.gif/i], [/vk\.jpg/i], [/c\.bigmir\.net/i], [/adlesse\.com/i], [/turzona\.com\.ua/i], [/kartinka\.com\.ua/i], [/totoro\.com\.ua/i], [/tas-ua\.toboads\.com/i], [/vk\.com/i], [/infrm\.weather\.ua\/image\//i], [/vk_banner/i], [/\.doubleclick\.net/i], [/twitter\.com/i], [/facebook\.com/i], [/captcha/i], [/images\.mob\.ua\//i], [/gorgeoushandbag\.com\//i], [/imgg\.dt0.*\.net\//i], [/banner\.ua\/cgi-bin\/core\.fcgi/i], [/adverserve\.net/i], [/yield.*\.com\//i], [/tbn\.ru/i], [/adv\.fraza\.ua\//i], [/sinoptik\.ua\/_uploaded_files\/..\/..\/uft_................................\.jpg$/i], [/liga\.net\/www\/images\/.*\./i], [/x\.magnet\.kiev\.ua\/www\/images\/.*\./i], [/ads.*\.com\//i], /\.kz/, [/\/i\/0.*\.gif/i], /krisha\.kz/, [/\/i\/pro\//i], [70, 50], [120, 90], [60, 50], /kolesa\.kz/, [60, 50], [/\/idrive\//i], [/\/uploads\/content\//i], /magnolia-tv\.com/, [/pictures\/avatar\//i], /infohome\.com\.ua/, [250, 250], /auto\.mail\.ru/, [/r.*\.mail\.ru\/b.*\.jpg$/i], /sport\.ua/, [/sport\.ua\/images\//i], /autocentre\.ua/, [/autocentre\.ua\/images\//i], /terrikon\.com/, [/\/fans\//i], /kievskaya\.com\.ua/, [/image\.tsn\.ua\//i], /mbox2\.i\.ua/, [/fsimg\.ru\//i], /uaua\.info/, [/\/pictures\//i], /telekritika\.ua/, [/telekritika\.ua.*\/imgs\//i], [/telekritika\.ua.*\/images\//i], /meteo\.ua/, [/meteo\.ua\/var\/banners\/favorites_ua\.jpg/i], /smartphone\.ua/, [/smartphone\.ua\/img\//i], [240, 400], /ria\.ua/, [/img\.ria\.ua\/photos\/auto/i], /itc\.ua/, [/itc\.ua\/files\/pic/i], [/wp-content/i], /lissod\.com\.ua/, [/\/st_img\/flash\//i], /onlinetb\.com\.ua/, [200, 200], /delo\.ua/, [/inf\.korrespondent\.net/i], [/informers\.ukr\.net/i], /sport-express\.ua/, [/sport-express\.ua\/img\//i], /calend\.ru/, [/promo\.1000zakazov\.ru\//i], [/shkolazhizni\.ru\/img\/adv\//i], /bestdroid\.ru/, [/upload/i], /hnb\.com\.ua/, [/artimage/i], /biathlon\.com\.ua/, [/img\/ministerstvo\.gif/i], /hotline\.ua/, [120, 60], /gazeta\.ua/, [300, 240], /mamaclub\.ua/, [300, 250], /myradio\.ua/, [300, 250], /oceni\.ua/, [250, 250], /ava\.ua/, [240, 400], /games\.bigmir\.net/, [/ads\..*\./i], /connect\.ua/, [300, 240], /bilshe\.com/, [/banner/i], /realty\.mail\.ru/, [/img\.pre\.realty\.mail\.ru\/.*\.jpg$/i], /pogoda\.mail\.ru/, [/r.*\.mail\.ru\/b.*\.jpg$/i], /cards\.mail\.ru/, [/r.*\.mail\.ru\/b.*\.png$/i], /hi-tech\.mail\.ru/, [/r.*\.mail\.ru\/b.*\.png$/i], [/r.*\.mail\.ru\/b.*\.jpg$/i], /otvet\.mail\.ru/, [/r.*\.mail\.ru\/b.*\.gif$/i], /health\.mail\.ru/, [/r.*\.mail\.ru\/b.*\.gif$/i], [/r.*\.mail\.ru\/b.*\.jpg$/i], /deti\.mail\.ru/, [/r.*\.mail\.ru\/b.*\.jpg$/i], /mail\.ru/, [/ban\./i], [/\/adv\//i], /^cm\.mmi\.macc\.com\.ua$/, [/\.png$/i] ]); var banners = new CM_Message("banners", { invisible: [], sentCount: 0, initCounter: 1, /** @this {CM_Message} */ initialize: function () { var ie = /MSIE/.test(ua), iphone3 = /iPhone OS 3/.test(ua); if (isFrame && !CONFIG.work_in_frame) { return; } this.httpMethod = window.opera || ie || iphone3 ? "GET" : "POST"; setInterval(function () { banners.scan(banners.onAdsDone); }, CONFIG.ads.scan_frequency * 1000); // Set `sr` by default to inactive tab value. // It will be removed immediately by the call of // onTabActive(), if tab has been opened active. /** @expose */ this.params.sr = 1; // XXX: should not need timeout setTimeout(function () { banners.scan(banners.onAdsDone); }, 4); // scan(this.onAdsDone); onVisibilityChange(this.onTabActive, this.onTabInactive); }, restart: function () { this.referrer = previousLocation; this.sentCount = 0; this.invisible = []; this.initCounter++; }, /** @this {CM_Message} */ onTabActive: function () { if (isFrame) { this.params.sr = 2; } else { delete this.params.sr; } }, /** @this {CM_Message} */ onTabInactive: function () { this.params.sr = 1; }, /** * Scan document for ads based on pre-configured positive & negative templates. * Passes found ads as Array to callback function from 1st param. * * @param {Function} cb callback where to pass found list of ads */ scan: function (cb) { var ads = [], callbacks = banners.scan.callbacks = banners.scan.callbacks || [], nodes = [], nodesData = [], SEARCH_DEPTH = 4; // same callback must not be called twice w/ same ads if (-1 === indexOf(callbacks, cb)) { callbacks.push(cb); } function searchBg(node, depth) { var items = node.childNodes || [], l = items.length, nodes = searchBg.nodes = searchBg.nodes || [], excludeTags = ['head', 'script', 'style']; if (depth <= 0 ) { return; } function getBg(node) { var style = node.currentStyle || window.getComputedStyle(node, null) || {}, bg = style.backgroundImage || false, MIN_WIDTH = 300, MIN_HEIGHT = 300; if (node.offsetWidth >= MIN_WIDTH && node.offsetHeight >= MIN_HEIGHT && bg !== 'none') { nodes.push({"node": node, "bg": bg.slice(4, -1).split('"').join('')}); } } while (l--) { if (items[l].nodeType == 1 && indexOf(excludeTags, items[l].tagName.toLowerCase()) < 0) { getBg(items[l]); searchBg(items[l], depth - 1); } } return nodes; } // prepare cache of DOM to improve overall performance function prepare(doc) { function append(node) { var src = getNodeSrc(node), size = getSize(node); if (size.w <= CONFIG.ads.width || size.h <= CONFIG.ads.height) { return; } nodes.push(node); nodesData.push([src, size.w, size.h]); } each(doc.images || doc.getElementsByTagName("img"), append); each(doc.getElementsByTagName("video"), append); each(CM_Template.embeds(doc), append); each(doc.getElementsByTagName("iframe"), function (frame) { var frameWindow, insideCounter = false; if (iframeAccessible(frame)) { frameWindow = frame.contentWindow || frame.contentDocument.parent; if (!frameWindow['__cm'] || (indexOf(frameWindow['__cm'], 'ua') == -1)) { // TODO: refactor into containsCMeter() function and // reuse it in addon/cmeter_an.js/etc each(frameWindow.document.getElementsByTagName('script'), function (script) { var src = getNodeSrc(script), mask = /source\.mmi\.bemobile\.ua\/cm\/(cmeter_an|cm)\.js/; if (mask.test(src)) { insideCounter = true; } }); if (!insideCounter) { if (ENABLE_CONSOLE) { console.log('start scanning iframe!'); } prepare(getDoc(frame)); } } } else { append(frame); } }); } prepare(document); each(CM_Template.scan(nodesData), function (idx) { ads.push(nodes[idx]); }); while (callbacks.length) { callbacks.shift()(ads, searchBg(document, SEARCH_DEPTH)); } }, /** * Callback that is passed to **scan** function. * It receives array of found banners, and for each banner that has not been sent yet calculates its normalized URL, obtains visibility and position, * manually converts list of [{link: "", pos: {left: X, top: Y}}] to JSON string and then sends by portions with 50 banners * * @param {Array} ads array of banners * @this {CM_Message} **/ onAdsDone: function (ads, backgrounds) { var that = this, r = [], CMeterAttr = "data-cmeter", CMeterAttrValue = 'sent' + that.initCounter; function send() { that.params.result = encodeURIComponent("[" + r.join(",") + "]"); if (ENABLE_CONSOLE) { console.log("found new ads:", r.length); } if (r.length) { that.send(); } } function append(src, pos, cl, btype) { var item = ""; item = '{"link":"' + src + '", "pos":"' + pos; if (cl) { item += '", "cl":"' + cl; } if (btype != undefined) { item += '", "bt":"' + btype; } return item + '"}'; } function setSentAttr(node) { node.setAttribute(CMeterAttr, CMeterAttrValue); banners.sentCount++; } function getSentAttr(node) { var l = node.attributes.length, value; if (value = node.getAttribute(CMeterAttr)) { return value; } else { while (l--) if (node.attributes[l].nodeName == CMeterAttr) return node.attributes[i].nodeValue } } each(backgrounds, function(background) { if (getSentAttr(background['node']) !== CMeterAttrValue) { setSentAttr(background["node"]); r.push(append(background["bg"], 0, null, 2)); if (r.length >= 50) { send(); r = []; } } }); each(ads, function (ad) { if (getSentAttr(ad) !== CMeterAttrValue) { var pos, src = getNodeSrc(ad), cl = getDestinationPath(ad); if (isVisible(ad)) { pos = getOffset(ad).top + getSize(ad).h; } else { // Ad may be considered invisible due to it is still // being loaded. Delay itâs sending âtill next scan. // See bug #29960 if (-1 === indexOf(that.invisible, ad)) { that.invisible.push(ad); return; } pos = -1; } setSentAttr(ad); r.push(append(src, pos, cl)); // Note: if there are 50 ads, then it will try to send() // twice (but second time should not make HTTP request) if (r.length >= 50) { send(); r = []; } } }); send(); } }); var timer = new CM_Message("timer", { /** @this {CM_Message} */ initialize: function () { // null can later be safely compared w/ numbers this.maxScrollHeight = null; if (isFrame && (!CONFIG.work_in_frame || CONFIG.addon_disable_frame_timers)) { return; } this.pings = []; extend(this.pings, CONFIG.timer.pings); load(this.onWindowLoad); onViewportChange(this.onViewportChange); // since cm.js is executed exactly before // <script src="cm.js"> onload callback fires, // this delay gives scripts some time to subscribe // for very first __cm.on("send", â¦); to modify it setTimeout(function () { onVisibilityChange(timer.onTabActive, timer.onTabInactive); }, 20); }, /** @this {CM_Message} */ onBeforeCommit: function () { var now = new Date(), activated = this.activated || started, total = now - started, active = (this.inactived || now) - activated; this.params[1] = Math.round(active / 1000); this.params[2] = this.maxScrollHeight; this.params[4] = Math.round(total / 1000); this.commit(); this.commit.time = now; }, /** @this {CM_Message} */ tick: function () { var now = new Date(), commited = this.commit.time || 0, active = now - this.activated, param2 = Math.round(active / 1000), canCommit = Math.round((now - commited) / 1000) >= CONFIG.timer.frequency; if (!this.activated) { return; } if (!canCommit) { return; } if (param2 >= CONFIG.timer.stop_after * 60) { clearInterval(this.interval); if (ENABLE_CONSOLE) { console.log("timer stopped:", param2); } } // TODO: May param2 be lower than lastPing? if (param2 >= CONFIG.timer.pings[0]) { this.send(); if (1 === CONFIG.timer.pings.length) { this.pingsFrequency = CONFIG.timer.pings[0] - this.lastPing; if (ENABLE_CONSOLE) { console.log("last ping interval:", this.pingsFrequency); } } this.lastPing = CONFIG.timer.pings.shift(); } else if (param2 % this.pingsFrequency == 0) { this.send(); this.lastPing = param2; } else if (this.params[2] !== this.maxScrollHeight) { if (ENABLE_CONSOLE) { console.log("scrolled to point", this.maxScrollHeight); } this.send(); } }, /** @this {CM_Message} */ onWindowLoad: function (date) { this.params[3] = date - started; this.onViewportChange(); }, /** @this {CM_Message} */ onTabActive: function () { var now = new Date(); // it can be inactivated only after it was activated // and cm.js should count only first activation if (!this.inactived) { this.activated = now; if (ENABLE_CONSOLE) { console.log("timer activated", +now); } if (mobile) { var that = this; setTimeout(function () { if (!(banners.sentCount + banners.invisible.length)) { that.tick(); } }, CONFIG.ads.scan_frequency * 1000 + 1000); } else { this.interval = setInterval(this.tick , 1000); // and send on 0th second this.send(); } } }, /** @this {CM_Message} */ onTabInactive: function () { var now = new Date(); if (!this.inactived) { this.inactived = now; if (!mobile) this.send(); if (ENABLE_CONSOLE) { console.log("timer deactivated", +now); } clearInterval(this.interval); } }, /** @this {CM_Message} */ onViewportChange: function () { var b = document.body, d = document.documentElement, t = getWindowTop(), h = "clientHeight" in d ? d.clientHeight : 0; if (b) { h = document.compatMode === "CSS1Compat" ? d.clientHeight : b.clientHeight; } if (t + h >= this.maxScrollHeight) { this.maxScrollHeight = t + h; } }, restart: function () { if (ENABLE_CONSOLE) { console.log('start new timers'); } this.maxScrollHeight = null; this.inactived = undefined; this.referrer = previousLocation; started = new Date(); clearInterval(this.interval); if (isFrame && (!CONFIG.work_in_frame || CONFIG.addon_disable_frame_timers)) { return; } load(this.onWindowLoad); this.params[3] = 0; CONFIG.timer.pings = []; extend(CONFIG.timer.pings, this.pings); this.onTabActive(); } }); setInterval(function () { var currentLocation = location.href.replace(location.hash,""); if (previousLocation !== currentLocation) { banners.restart(); timer.restart(); previousLocation = currentLocation; } }, CONFIG.timer.check_location_timer * 1000 || 1000); window['__cm'].push("ua"); } }(window, document)); </script>