- // ==UserScript==
- // @name Alternative search engines 2
- // @description Adds search on other sites for google, bing, yandex, duckduckgo
- // @namespace 2k1dmg@userscript
- // @license GPL version 3 or any later version; http://www.gnu.org/licenses/gpl.html
- // @version 0.2.7
- // @grant none
- // @noframes
- // @include https://yandex.tld/*
- // @include https://ya.ru/*
- // @include https://www.google.tld/*
- // @include https://www.bing.com/*
- // @include https://duckduckgo.com/*
- // @exclude /^https://(yandex|www\.google)\.(net|org)/.*$/
- // ==/UserScript==
-
- // 2024-02-14
-
- var SEARCH_ON = '• ';
- var SEARCH_ON_END = ' •';
- var LINK_BOX_ID = 'oeid-box';
- var ENGINES_SEPARATOR = ' - ';
- var POSITION = 'left';
-
- var ENGINES = {
- Yandex: 'https://yandex.ru/yandsearch?text=',
- Ya: 'https://ya.ru/yandsearch?text=',
- Google: 'https://www.google.com/search?q=',
- Bing: 'https://www.bing.com/search?q=',
- DuckDuckGo: 'https://duckduckgo.com/?q='
- };
-
- var PLACEHOLDER_SELECTORS = [
- '.content__left', // yandex
- '.content__left', // ya
- '#result-stats', // google
- '.sb_count', // bing
- '.results--main' // duckduckgo
- ].join(',');
-
- var INPUT_FIELD_SELECTORS = [
- '.HeaderDesktopForm-Input', // yandex
- '.HeaderDesktopForm-Input', // ya
- 'textarea.gLFyf', // google
- '#sb_form_q', // bing
- '#search_form_input' // duckduckgo
- ].join(',');
-
- function onClick(event) {
- var link = event.target;
- if(link.nodeName.toLowerCase() !== 'a')
- return;
- var engineSource = ENGINES[link.engineName];
- var engineURL;
- var engineParam = '';
- if(Array.isArray(engineSource)) {
- engineParam = engineSource[1];
- engineURL = engineSource[0];
- }
- else if(typeof engineSource === 'string') {
- engineURL = engineSource;
- }
- else {
- return;
- }
- var searchText = document.querySelector(INPUT_FIELD_SELECTORS);
- if(engineURL && searchText && searchText.value.length > 0) {
- var url = engineURL + encodeURIComponent(searchText.value) + engineParam;
- window.open(url, '_blank');
- }
- }
-
- function addCSSStyle() {
- var cssStyle = document.createElement('style');
- cssStyle.type = 'text/css';
- cssStyle.textContent = [
- '#' + LINK_BOX_ID + ' {',
- ' display: inline-block;',
- ' padding-right: 10px;',
- ' padding-bottom: 10px;',
- ' color: rgb(115, 115, 115);' ,
- ' font-family: Verdana,sans-serif;',
- ' font-size: 9pt;',
- ' text-align: ' + POSITION + ';',
- ' z-index: 10000;',
- '}',
- '#' + LINK_BOX_ID + ' > a {',
- ' text-decoration: none;',
- '}'
- ].join('\n');
- document.head.appendChild(cssStyle);
- }
-
- var createFragment = (function() {
- var setCommon = function(node, sAttr, reason) {
- var aAttr = sAttr.split(',');
- aAttr.forEach(function(attr) {
- var attrSource = /:=/.test(attr) ? attr.split(':=') : [attr, ''];
- var attrName = attrSource[0].trim();
- var attrValue = attrSource[1].trim().replace(/^(['"])([^\1]*)\1$/, '$2');
- if(reason === 'a') {
- node.setAttribute(attrName, attrValue);
- }
- else {
- node[attrName] = attrValue;
- }
- });
- return node;
- };
- var setAttr = function(node, sAttr) {
- return setCommon(node, sAttr, 'a');
- };
- var setProp = function(node, sAttr) {
- return setCommon(node, sAttr, 'p');
- };
- var createFragmentInner = function(data, fragment) {
- if(data.n) {
- var node = document.createElement(data.n);
- if(data.a)
- node = setAttr(node, data.a);
- if(data.p)
- node = setProp(node, data.p);
- if(data.s)
- node.style.cssText = data.s;
- fragment.appendChild(node);
- }
- if(data.c) {
- data.c.forEach(function(cn) {
- createFragmentInner(cn, node || fragment);
- });
- }
- if(data.t && node) {
- node.appendChild(document.createTextNode(data.t));
- }
- if(data.tc) {
- fragment.appendChild(document.createTextNode(data.tc));
- }
- if(data.dn) {
- fragment.appendChild(data.dn);
- }
- return fragment;
- };
- return function(data) {
- var fragment = document.createDocumentFragment();
- return createFragmentInner({c:data}, fragment);
- };
- })();
-
- function createLinkBox() {
- return createFragment([
- {n:'div',a:'id:="'+LINK_BOX_ID+'"',c:(function() {
- var domain = document.domain.split('.').splice(-2, 2)[0];
- var aLinks = [{tc:SEARCH_ON}];
- for(var engine in ENGINES) {
- if(domain == engine.toLowerCase())
- continue;
- aLinks.push(
- {n:'a',a:'href:="javascript:void(0)"',p:'engineName:="'+engine+'"',t:engine},
- {tc:ENGINES_SEPARATOR}
- );
- }
- aLinks[aLinks.length-1] = {tc:SEARCH_ON_END};
- return aLinks;
- })()}
- ]);
- }
-
- function onDOMLoad() {
- var results = document.querySelector(PLACEHOLDER_SELECTORS);
- if(!results)
- return;
- if(document.getElementById(LINK_BOX_ID))
- return;
- addCSSStyle();
- var fragment = createLinkBox();
- var linkBox = fragment.querySelector('#'+LINK_BOX_ID);
- linkBox.onclick = onClick;
- results.insertBefore(fragment, results.firstChild);
- }
-
- function addObserver(target, config, callback) {
- var observer = new MutationObserver(function(mutations) {
- mutations.forEach(function(mutation) {
- callback.call(this, mutation);
- });
- });
- observer.observe(target, config);
- return observer;
- }
-
- function removeObserver(observer) {
- observer.disconnect();
- }
-
- function getNodes() {
- var _slice = Array.slice || Function.prototype.call.bind(Array.prototype.slice);
- var trg = document.body;
- var params = { childList: true, subtree: true };
- var getNode = function(mut) {
- var addedNodes = mut.addedNodes;
- var nodes = _slice(addedNodes);
- nodes.forEach(function(node) {
- if(node.querySelector &&
- node.querySelector(PLACEHOLDER_SELECTORS)) {
- onDOMLoad();
- }
- });
- };
- var observer = addObserver(trg, params, getNode);
- window.addEventListener('unload', function(event) {
- removeObserver(observer);
- }, false);
- }
-
- onDOMLoad();
- getNodes();