├── .gitignore ├── Gruntfile.js ├── README.md ├── dist ├── index.js └── index.min.js ├── package.json └── src └── index.js /.gitignore: -------------------------------------------------------------------------------- 1 | /node_modules/ 2 | *.log -------------------------------------------------------------------------------- /Gruntfile.js: -------------------------------------------------------------------------------- 1 | module.exports = function (grunt) { 2 | 3 | grunt.initConfig({ 4 | pkg: grunt.file.readJSON('package.json'), 5 | jshint: { 6 | all: { 7 | options: { 8 | node: true, 9 | undef: true, 10 | curly: true, 11 | eqeqeq: true, 12 | eqnull: true, 13 | browser: true 14 | }, 15 | files: { 16 | src: ['Gruntfile.js', 'src/*.js'] 17 | } 18 | } 19 | }, 20 | uglify: { 21 | options: { 22 | banner: '/*!\n * <%= pkg.name %> \n * <%= grunt.template.today() %>\n * <%= pkg.homepage %>\n */\n', 23 | footer: ';' 24 | }, 25 | build: { 26 | src: 'src/index.js', 27 | dest: 'dist/index.min.js' 28 | } 29 | }, 30 | copy: { 31 | all: { 32 | expand: true, 33 | src: 'index.js', 34 | cwd: 'src/', 35 | dest: 'dist/' 36 | } 37 | } 38 | }); 39 | 40 | // Load the plugin that provides the "uglify" task. 41 | grunt.loadNpmTasks('grunt-contrib-uglify'); 42 | grunt.loadNpmTasks('grunt-contrib-jshint'); 43 | grunt.loadNpmTasks('grunt-contrib-copy'); 44 | 45 | grunt.registerTask('default', ['jshint', 'uglify', 'copy']); 46 | 47 | }; -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Отключение Яндекс-Советника. 2 | 3 | Этот скрипт поможет заблокировать и полностью отключить Яндекс-Советник на вашем сайте. 4 |

5 | 6 | 7 | ## Установка 8 | Воспользуйте любым из приведенных ниже способов, что установить скрипт блокировки Яндекс-Советника: 9 | 10 | ### 1. Скачать и скопировать скрипт. 11 | Скачайте и скопируйте в папку со своими скриптами следующий скрипт (или добавьте в общий файл с вашими скриптами): 12 | ``` 13 | https://serjopepper.github.io/kick_sovetnik/dist/index.min.js 14 | ``` 15 | Затем вставьте этот скрипт на ваш сайт (в начало ``), этот скрипт должен грузится синхронно, до полной загрузки DOM. 16 | 17 | ### 2. Через npm и browserify 18 | Установите: 19 | ``` 20 | npm install --save kick_sovetnik 21 | ``` 22 | 23 | Подключите в ваших скриптах (скрипт исполняется автоматически); 24 | ``` 25 | require('kick_sovetnik'); 26 | ``` 27 | 28 | Если у вас перестал работать скрипт или скрипт ломает ваш сайт, создайте тикет: 29 | https://github.com/SerjoPepper/kick_sovetnik/issues 30 | 31 | -------------------------------------------------------------------------------- /dist/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Блокирует Яндекс-Советник на страницах вашего интернет-магазина 3 | * https://github.com/SerjoPepper/kick_sovetnik 4 | * Если скрипт по каким то причинам перестал работать или что-то ломает на вашем сайте, пожалуйста, создайте тикет: 5 | * https://github.com/SerjoPepper/kick_sovetnik/issues 6 | */ 7 | 8 | (function () { 9 | 10 | function patchOnMessage() { 11 | window.addEventListener('message', function (e) { 12 | var data; 13 | if (typeof e.data === 'string') { 14 | try { 15 | data = JSON.parse(e.data); 16 | } 17 | catch (e) { 18 | return; 19 | } 20 | } else { 21 | data = e.data; 22 | } 23 | if (data && data.type === 'MBR_ENVIRONMENT') { 24 | e.stopImmediatePropagation(); 25 | e.stopPropagation(); 26 | e.data = {}; 27 | } 28 | }, true); 29 | } 30 | 31 | var observer; 32 | 33 | function init () { 34 | try { 35 | observer = new MutationObserver(function (records) { 36 | check(records); 37 | }); 38 | } catch (e) { 39 | 40 | } 41 | if (document.body) { 42 | checkNodes(document.body.children); 43 | } 44 | } 45 | 46 | function startObserve () { 47 | if (!document.body) { 48 | setTimeout(startObserve, 200); 49 | return; 50 | } 51 | if (observer) { 52 | observer.observe(document.body, {childList: true}); 53 | } 54 | } 55 | 56 | function stopObserve () { 57 | if (observer) { 58 | observer.disconnect(); 59 | observer = null; 60 | } 61 | } 62 | 63 | // Проверки 64 | function check (records) { 65 | records.forEach(function (record) { 66 | var addedNodes = record.addedNodes; 67 | if (addedNodes && addedNodes.length) { 68 | checkNodes(addedNodes); 69 | } 70 | }); 71 | } 72 | 73 | function checkNodes (nodes) { 74 | Array.prototype.slice.call(nodes).forEach(function (node) { 75 | if (isDiv(node) && (hasSovetnikImage(node))) { 76 | remove(node); 77 | } 78 | }); 79 | } 80 | 81 | function createStyleNode(selector, styles) { 82 | var styleNode = document.createElement('style'); 83 | var css = ''; 84 | for (var k in styles) { 85 | if (styles.hasOwnProperty(k)) { 86 | css += k + ':' + styles[k] + ' !important;\n'; 87 | } 88 | } 89 | styleNode.type = 'text/css'; 90 | styleNode.appendChild(document.createTextNode(selector + ', ' + selector + ':hover{' + css + '}')); 91 | return styleNode; 92 | } 93 | 94 | function addStyleNode(selector, styles) { 95 | var styleNode = createStyleNode(selector, styles); 96 | document.body.appendChild(styleNode); 97 | } 98 | 99 | function propName(s) { 100 | return s.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); }); 101 | } 102 | 103 | // Скрываем яндекс-советник со страницы, возвращаем прежний margin-top для body 104 | function remove (node) { 105 | var rootStyles = { 106 | background: 'transparent', 107 | transition: 'none', 108 | 'box-shadow': 'none', 109 | 'border-color': 'transparent' 110 | }; 111 | 112 | setTimeout(function () { 113 | var onMouseEnter = function () { 114 | addStyleNode('#' + node.id, { 115 | 'pointer-events': 'none' 116 | }); 117 | node.removeEventListener('mouseover', onMouseEnter, true); 118 | node.removeEventListener('mouseenter', onMouseEnter, true); 119 | }; 120 | node.addEventListener('mouseover', onMouseEnter, true); 121 | node.addEventListener('mouseenter', onMouseEnter, true); 122 | }, 3e3); 123 | 124 | addStyleNode('#' + node.id, rootStyles); 125 | addStyleNode('#' + node.id + ' *', { 126 | opacity: '0', 127 | 'pointer-events': 'none' 128 | }); 129 | 130 | // следим в течении 3 сек за изменением marginTop у html 131 | var marginObserver = new MutationObserver(function () { 132 | var marginTop = document.documentElement.style.marginTop; 133 | if (marginTop && parseInt(marginTop, 10) !== 0) { 134 | document.documentElement.style.marginTop = ''; 135 | } 136 | }); 137 | setTimeout(function () { 138 | marginObserver.disconnect(); 139 | marginObserver = null; 140 | }, 5e3); 141 | marginObserver.observe(document.documentElement, {attributes: true, attributeFilter: ['style']}); 142 | document.documentElement.style.marginTop = ''; 143 | } 144 | 145 | function isDiv (node) { 146 | return node.tagName === 'DIV'; 147 | } 148 | 149 | function hasSovetnikLink (node) { 150 | return !!node.querySelector('[href*="sovetnik.market.yandex.ru"]'); 151 | } 152 | 153 | // найти по картинке 154 | function hasSovetnikImage (node) { 155 | if(node.nodeName === '#text'){ 156 | return false; 157 | } 158 | return !!node.querySelector('[src*="data:image/png;base64,iVBORw0KGgoAAAA"]'); 159 | } 160 | 161 | function getStyle (node, prop) { 162 | return window.getComputedStyle(node).getPropertyValue(prop); 163 | } 164 | 165 | // function removeAttrs (attr, selector) { 166 | // var elements = document.querySelectorAll(selector); 167 | // for (var i = 0; i < elements.length; i++) { 168 | // elements[i].removeAttribute(attr); 169 | // } 170 | // } 171 | 172 | // function removeElements(selector) { 173 | // var elements = document.querySelectorAll(selector); 174 | // for (var i = 0; i < elements.length; i++) { 175 | // elements[i].parentNode.removeChild(elements[i]) 176 | // } 177 | // } 178 | 179 | try { 180 | /* 181 | removeElements('meta'); 182 | removeAttrs('itemscope', '[itemscope]'); 183 | removeAttrs( 184 | 'property', 185 | '[property="gr:mpn"],[property="gr:hasEAN_UCC-13"]' 186 | ); 187 | removeAttrs( 188 | 'itemprop', 189 | '[itemprop="name"],[property="gr:name"],[itemprop="brand"],[itemprop="productID"],[itemprop="isbn"],[itemprop="mpn"]' + 190 | ',[itemprop="hasMPN"],[itemprop="model"],[itemprop="model"],[itemprop=name],[itemprop^="gtin"],[itemprop$="category"]' + 191 | ',[itemprop="price"],[itemprop="offers"],[itemprop="offer"]' 192 | ); 193 | removeAttrs( 194 | 'itemtype', 195 | '[itemtype*="schema.org/Product"],[itemtype*="data-vocabulary.org/Product"],[itemtype*="schema.org/Offer"]' 196 | ); 197 | */ 198 | 199 | init(); 200 | startObserve(); 201 | patchOnMessage(); 202 | } catch (e) { 203 | if (typeof console !== 'undefined') { 204 | console.error('error while kick sovetnik', e); 205 | } 206 | } 207 | 208 | })(); 209 | 210 | -------------------------------------------------------------------------------- /dist/index.min.js: -------------------------------------------------------------------------------- 1 | /*! 2 | * kick_sovetnik 3 | * Tue Jun 06 2017 09:55:35 4 | * https://github.com/SerjoPepper/kick_sovetnik#readme 5 | */ 6 | !function(){function a(){window.addEventListener("message",function(a){var b;if("string"==typeof a.data)try{b=JSON.parse(a.data)}catch(a){return}else b=a.data;b&&"MBR_ENVIRONMENT"===b.type&&(a.stopImmediatePropagation(),a.stopPropagation(),a.data={})},!0)}function b(){try{k=new MutationObserver(function(a){d(a)})}catch(a){}document.body&&e(document.body.children)}function c(){return document.body?void(k&&k.observe(document.body,{childList:!0})):void setTimeout(c,200)}function d(a){a.forEach(function(a){var b=a.addedNodes;b&&b.length&&e(b)})}function e(a){Array.prototype.slice.call(a).forEach(function(a){i(a)&&j(a)&&h(a)})}function f(a,b){var c=document.createElement("style"),d="";for(var e in b)b.hasOwnProperty(e)&&(d+=e+":"+b[e]+" !important;\n");return c.type="text/css",c.appendChild(document.createTextNode(a+", "+a+":hover{"+d+"}")),c}function g(a,b){var c=f(a,b);document.body.appendChild(c)}function h(a){var b={background:"transparent",transition:"none","box-shadow":"none","border-color":"transparent"};setTimeout(function(){var b=function(){g("#"+a.id,{"pointer-events":"none"}),a.removeEventListener("mouseover",b,!0),a.removeEventListener("mouseenter",b,!0)};a.addEventListener("mouseover",b,!0),a.addEventListener("mouseenter",b,!0)},3e3),g("#"+a.id,b),g("#"+a.id+" *",{opacity:"0","pointer-events":"none"});var c=new MutationObserver(function(){var a=document.documentElement.style.marginTop;a&&0!==parseInt(a,10)&&(document.documentElement.style.marginTop="")});setTimeout(function(){c.disconnect(),c=null},5e3),c.observe(document.documentElement,{attributes:!0,attributeFilter:["style"]}),document.documentElement.style.marginTop=""}function i(a){return"DIV"===a.tagName}function j(a){return"#text"!==a.nodeName&&!!a.querySelector('[src*="data:image/png;base64,iVBORw0KGgoAAAA"]')}var k;try{b(),c(),a()}catch(l){"undefined"!=typeof console&&console.error("error while kick sovetnik",l)}}();; -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "kick_sovetnik", 3 | "version": "0.0.24", 4 | "description": "KickSovetnik поможем вам заблокировать и отключить Яндекс-Советник на страницах товаров вашего интернет-магазина", 5 | "main": "dist/index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "repository": { 10 | "type": "git", 11 | "url": "git+https://github.com/SerjoPepper/kick_sovetnik.git" 12 | }, 13 | "keywords": [ 14 | "yandex", 15 | "yandex-sovetnik" 16 | ], 17 | "author": "serjopepper@gmail.com", 18 | "license": "ISC", 19 | "bugs": { 20 | "url": "https://github.com/SerjoPepper/kick_sovetnik/issues" 21 | }, 22 | "homepage": "https://github.com/SerjoPepper/kick_sovetnik#readme", 23 | "devDependencies": { 24 | "grunt": "^0.4.5", 25 | "grunt-contrib-copy": "^0.8.2", 26 | "grunt-contrib-jshint": "^0.11.3", 27 | "grunt-contrib-uglify": "^0.11.0" 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Блокирует Яндекс-Советник на страницах вашего интернет-магазина 3 | * https://github.com/SerjoPepper/kick_sovetnik 4 | * Если скрипт по каким то причинам перестал работать или что-то ломает на вашем сайте, пожалуйста, создайте тикет: 5 | * https://github.com/SerjoPepper/kick_sovetnik/issues 6 | */ 7 | 8 | (function () { 9 | 10 | function patchOnMessage() { 11 | window.addEventListener('message', function (e) { 12 | var data; 13 | if (typeof e.data === 'string') { 14 | try { 15 | data = JSON.parse(e.data); 16 | } 17 | catch (e) { 18 | return; 19 | } 20 | } else { 21 | data = e.data; 22 | } 23 | if (data && data.type === 'MBR_ENVIRONMENT') { 24 | e.stopImmediatePropagation(); 25 | e.stopPropagation(); 26 | e.data = {}; 27 | } 28 | }, true); 29 | } 30 | 31 | var observer; 32 | 33 | function init () { 34 | try { 35 | observer = new MutationObserver(function (records) { 36 | check(records); 37 | }); 38 | } catch (e) { 39 | 40 | } 41 | if (document.body) { 42 | checkNodes(document.body.children); 43 | } 44 | } 45 | 46 | function startObserve () { 47 | if (!document.body) { 48 | setTimeout(startObserve, 200); 49 | return; 50 | } 51 | if (observer) { 52 | observer.observe(document.body, {childList: true}); 53 | } 54 | } 55 | 56 | function stopObserve () { 57 | if (observer) { 58 | observer.disconnect(); 59 | observer = null; 60 | } 61 | } 62 | 63 | // Проверки 64 | function check (records) { 65 | records.forEach(function (record) { 66 | var addedNodes = record.addedNodes; 67 | if (addedNodes && addedNodes.length) { 68 | checkNodes(addedNodes); 69 | } 70 | }); 71 | } 72 | 73 | function checkNodes (nodes) { 74 | Array.prototype.slice.call(nodes).forEach(function (node) { 75 | if (isDiv(node) && (hasSovetnikImage(node))) { 76 | remove(node); 77 | } 78 | }); 79 | } 80 | 81 | function createStyleNode(selector, styles) { 82 | var styleNode = document.createElement('style'); 83 | var css = ''; 84 | for (var k in styles) { 85 | if (styles.hasOwnProperty(k)) { 86 | css += k + ':' + styles[k] + ' !important;\n'; 87 | } 88 | } 89 | styleNode.type = 'text/css'; 90 | styleNode.appendChild(document.createTextNode(selector + ', ' + selector + ':hover{' + css + '}')); 91 | return styleNode; 92 | } 93 | 94 | function addStyleNode(selector, styles) { 95 | var styleNode = createStyleNode(selector, styles); 96 | document.body.appendChild(styleNode); 97 | } 98 | 99 | function propName(s) { 100 | return s.replace(/-([a-z])/g, function (g) { return g[1].toUpperCase(); }); 101 | } 102 | 103 | // Скрываем яндекс-советник со страницы, возвращаем прежний margin-top для body 104 | function remove (node) { 105 | var rootStyles = { 106 | background: 'transparent', 107 | transition: 'none', 108 | 'box-shadow': 'none', 109 | 'border-color': 'transparent' 110 | }; 111 | 112 | setTimeout(function () { 113 | var onMouseEnter = function () { 114 | addStyleNode('#' + node.id, { 115 | 'pointer-events': 'none' 116 | }); 117 | node.removeEventListener('mouseover', onMouseEnter, true); 118 | node.removeEventListener('mouseenter', onMouseEnter, true); 119 | }; 120 | node.addEventListener('mouseover', onMouseEnter, true); 121 | node.addEventListener('mouseenter', onMouseEnter, true); 122 | }, 3e3); 123 | 124 | addStyleNode('#' + node.id, rootStyles); 125 | addStyleNode('#' + node.id + ' *', { 126 | opacity: '0', 127 | 'pointer-events': 'none' 128 | }); 129 | 130 | // следим в течении 3 сек за изменением marginTop у html 131 | var marginObserver = new MutationObserver(function () { 132 | var marginTop = document.documentElement.style.marginTop; 133 | if (marginTop && parseInt(marginTop, 10) !== 0) { 134 | document.documentElement.style.marginTop = ''; 135 | } 136 | }); 137 | setTimeout(function () { 138 | marginObserver.disconnect(); 139 | marginObserver = null; 140 | }, 5e3); 141 | marginObserver.observe(document.documentElement, {attributes: true, attributeFilter: ['style']}); 142 | document.documentElement.style.marginTop = ''; 143 | } 144 | 145 | function isDiv (node) { 146 | return node.tagName === 'DIV'; 147 | } 148 | 149 | function hasSovetnikLink (node) { 150 | return !!node.querySelector('[href*="sovetnik.market.yandex.ru"]'); 151 | } 152 | 153 | // найти по картинке 154 | function hasSovetnikImage (node) { 155 | if(node.nodeName === '#text'){ 156 | return false; 157 | } 158 | return !!node.querySelector('[src*="data:image/png;base64,iVBORw0KGgoAAAA"]'); 159 | } 160 | 161 | function getStyle (node, prop) { 162 | return window.getComputedStyle(node).getPropertyValue(prop); 163 | } 164 | 165 | // function removeAttrs (attr, selector) { 166 | // var elements = document.querySelectorAll(selector); 167 | // for (var i = 0; i < elements.length; i++) { 168 | // elements[i].removeAttribute(attr); 169 | // } 170 | // } 171 | 172 | // function removeElements(selector) { 173 | // var elements = document.querySelectorAll(selector); 174 | // for (var i = 0; i < elements.length; i++) { 175 | // elements[i].parentNode.removeChild(elements[i]) 176 | // } 177 | // } 178 | 179 | try { 180 | /* 181 | removeElements('meta'); 182 | removeAttrs('itemscope', '[itemscope]'); 183 | removeAttrs( 184 | 'property', 185 | '[property="gr:mpn"],[property="gr:hasEAN_UCC-13"]' 186 | ); 187 | removeAttrs( 188 | 'itemprop', 189 | '[itemprop="name"],[property="gr:name"],[itemprop="brand"],[itemprop="productID"],[itemprop="isbn"],[itemprop="mpn"]' + 190 | ',[itemprop="hasMPN"],[itemprop="model"],[itemprop="model"],[itemprop=name],[itemprop^="gtin"],[itemprop$="category"]' + 191 | ',[itemprop="price"],[itemprop="offers"],[itemprop="offer"]' 192 | ); 193 | removeAttrs( 194 | 'itemtype', 195 | '[itemtype*="schema.org/Product"],[itemtype*="data-vocabulary.org/Product"],[itemtype*="schema.org/Offer"]' 196 | ); 197 | */ 198 | 199 | init(); 200 | startObserve(); 201 | patchOnMessage(); 202 | } catch (e) { 203 | if (typeof console !== 'undefined') { 204 | console.error('error while kick sovetnik', e); 205 | } 206 | } 207 | 208 | })(); 209 | 210 | --------------------------------------------------------------------------------