Alternative search engines 2

Adds search on other sites for google, bing, yandex, duckduckgo

目前為 2015-10-18 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Alternative search engines 2
  3. // @description Adds search on other sites for google, bing, yandex, duckduckgo
  4. // @namespace 2k1dmg@userscript
  5. // @license GPL version 3 or any later version; http://www.gnu.org/licenses/gpl.html
  6. // @version 0.2.0
  7. // @grant none
  8. // @noframes
  9. // @include /^https?://yandex\.(ru|ua|by|kz|com|com\.tr)/.*$/
  10. // @include /^https?://www\.google\.(am|az|by|co\.uz|com|com\.tr|com\.ua|de|ee|fi|ge|kg|kz|lt|lv|md|ru|tm)/.*$/
  11. // @include https://encrypted.google.com/*
  12. // @include /^https?://www\.bing\.com/.*$/
  13. // @include /^https?://duckduckgo\.com/.*$/
  14. // ==/UserScript==
  15.  
  16. // 2015-05-25
  17.  
  18. var SEARCH_ON = '• ';
  19. var SEARCH_ON_END = ' •';
  20. var LINK_BOX_ID = 'oeid-box';
  21. var ENGINES_SEPARATOR = ' - ';
  22. var POSITION = 'left';
  23.  
  24. var ENGINES = {
  25. Yandex: 'https://yandex.ru/yandsearch?text=',
  26. Google: 'https://www.google.com/search?q=',
  27. Bing: 'https://www.bing.com/search?q=',
  28. DuckDuckGo: 'https://duckduckgo.com/?q='
  29. };
  30.  
  31. var PLACEHOLDER_SELECTORS = [
  32. '.content__left', // yandex
  33. '#resultStats', // google
  34. '.sb_count', // bing
  35. '#links_wrapper' // duckduckgo
  36. ].join(',');
  37.  
  38. var INPUT_FIELD_SELECTORS = [
  39. '.input__control', // yandex
  40. '#lst-ib', // google
  41. '#sb_form_q', // bing
  42. '#search_form_input' // duckduckgo
  43. ].join(',');
  44.  
  45. function onClick(event) {
  46. var link = event.target;
  47. if(link.nodeName.toLowerCase() !== 'a')
  48. return;
  49. var engineSource = ENGINES[link.engineName];
  50. var engineURL;
  51. var engineParam = '';
  52. if(Array.isArray(engineSource)) {
  53. engineParam = engineSource[1];
  54. engineURL = engineSource[0];
  55. }
  56. else if(typeof engineSource === 'string') {
  57. engineURL = engineSource;
  58. }
  59. else {
  60. return;
  61. }
  62. var searchText = document.querySelector(INPUT_FIELD_SELECTORS);
  63. if(engineURL && searchText && searchText.value.length > 0) {
  64. var url = engineURL + encodeURIComponent(searchText.value) + engineParam;
  65. window.open(url, '_blank');
  66. }
  67. }
  68.  
  69. function addCSSStyle() {
  70. var cssStyle = document.createElement('style');
  71. cssStyle.type = 'text/css';
  72. cssStyle.textContent = [
  73. '#' + LINK_BOX_ID + ' {',
  74. ' display: inline-block;',
  75. ' padding-right: 10px;',
  76. ' padding-bottom: 3px;',
  77. ' color: rgb(115, 115, 115);' ,
  78. ' font-family: Verdana,sans-serif;',
  79. ' font-size: 11px;',
  80. ' text-align: ' + POSITION + ';',
  81. ' z-index: 10000;',
  82. '}'
  83. ].join('\n');
  84. document.head.appendChild(cssStyle);
  85. }
  86.  
  87. var createFragment = (function() {
  88. var setCommon = function(node, sAttr, reason) {
  89. var aAttr = sAttr.split(',');
  90. aAttr.forEach(function(attr) {
  91. var attrSource = /:=/.test(attr) ? attr.split(':=') : [attr, ''];
  92. var attrName = attrSource[0].trim();
  93. var attrValue = attrSource[1].trim().replace(/^(['"])([^\1]*)\1$/, '$2');
  94. if(reason === 'a') {
  95. node.setAttribute(attrName, attrValue);
  96. }
  97. else {
  98. node[attrName] = attrValue;
  99. }
  100. });
  101. return node;
  102. };
  103. var setAttr = function(node, sAttr) {
  104. return setCommon(node, sAttr, 'a');
  105. };
  106. var setProp = function(node, sAttr) {
  107. return setCommon(node, sAttr, 'p');
  108. };
  109. var createFragmentInner = function(data, fragment) {
  110. if(data.n) {
  111. var node = document.createElement(data.n);
  112. if(data.a)
  113. node = setAttr(node, data.a);
  114. if(data.p)
  115. node = setProp(node, data.p);
  116. if(data.s)
  117. node.style.cssText = data.s;
  118. fragment.appendChild(node);
  119. }
  120. if(data.c) {
  121. data.c.forEach(function(cn) {
  122. createFragmentInner(cn, node || fragment);
  123. });
  124. }
  125. if(data.t && node) {
  126. node.appendChild(document.createTextNode(data.t));
  127. }
  128. if(data.tc) {
  129. fragment.appendChild(document.createTextNode(data.tc));
  130. }
  131. if(data.dn) {
  132. fragment.appendChild(data.dn);
  133. }
  134. return fragment;
  135. };
  136. return function(data) {
  137. var fragment = document.createDocumentFragment();
  138. return createFragmentInner({c:data}, fragment);
  139. };
  140. })();
  141.  
  142. function createLinkBox() {
  143. return createFragment([
  144. {n:'div',a:'id:="'+LINK_BOX_ID+'"',c:(function() {
  145. var domain = document.domain;
  146. var aLinks = [{tc:SEARCH_ON}];
  147. for(var engine in ENGINES) {
  148. if(domain.indexOf(engine.toLowerCase()) !== -1)
  149. continue;
  150. aLinks.push(
  151. {n:'a',a:'href:="javascript:void(0)"',p:'engineName:="'+engine+'"',t:engine},
  152. {tc:ENGINES_SEPARATOR}
  153. );
  154. }
  155. aLinks[aLinks.length-1] = {tc:SEARCH_ON_END};
  156. return aLinks;
  157. })()}
  158. ]);
  159. }
  160.  
  161. function onDOMLoad() {
  162. var results = document.querySelector(PLACEHOLDER_SELECTORS);
  163. if(!results)
  164. return;
  165. if(document.getElementById(LINK_BOX_ID))
  166. return;
  167. addCSSStyle();
  168. var fragment = createLinkBox();
  169. var linkBox = fragment.querySelector('#'+LINK_BOX_ID);
  170. linkBox.onclick = onClick;
  171. results.insertBefore(fragment, results.firstChild);
  172. }
  173.  
  174. function addObserver(target, config, callback) {
  175. var observer = new MutationObserver(function(mutations) {
  176. mutations.forEach(function(mutation) {
  177. callback.call(this, mutation);
  178. });
  179. });
  180. observer.observe(target, config);
  181. return observer;
  182. }
  183.  
  184. function removeObserver(observer) {
  185. observer.disconnect();
  186. }
  187.  
  188. function getNodes() {
  189. var _slice = Array.slice || Function.prototype.call.bind(Array.prototype.slice);
  190. var trg = document.body;
  191. var params = { childList: true, subtree: true };
  192. var getNode = function(mut) {
  193. var addedNodes = mut.addedNodes;
  194. var nodes = _slice(addedNodes);
  195. nodes.forEach(function(node) {
  196. if(node.querySelector &&
  197. node.querySelector(PLACEHOLDER_SELECTORS)) {
  198. onDOMLoad();
  199. }
  200. });
  201. };
  202. var observer = addObserver(trg, params, getNode);
  203. window.addEventListener('unload', function(event) {
  204. removeObserver(observer);
  205. }, false);
  206. }
  207.  
  208. onDOMLoad();
  209. getNodes();