Google Translator Tooltip Expanded Fork

Translates the selected text into a tooltip automatically. Fork from https://greasyfork.org/scripts/5727/

当前为 2017-05-25 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Google Translator Tooltip Expanded Fork
  3. // @description Translates the selected text into a tooltip automatically. Fork from https://greasyfork.org/scripts/5727/
  4. // @namespace https://greasyfork.org/scripts/16204/
  5. // @homepage https://greasyfork.org/scripts/16204/
  6. // @version 1.23
  7. // @icon http://translate.google.com/favicon.ico
  8. // @include http*
  9. // @include https*
  10. // @include chrome*
  11. // @grant GM_getValue
  12. // @grant GM_xmlhttpRequest
  13. // @grant GM_log
  14. // @grant GM_deleteValue
  15. // @grant GM_addStyle
  16. // @grant GM_openInTab
  17. // @grant GM_registerMenuCommand
  18. // @grant GM_setValue
  19. // ==/UserScript==
  20.  
  21. /**
  22. * ColorPicker - pure JavaScript color picker without using images, external CSS or 1px divs.
  23. * Copyright © 2011 David Durman, All rights reserved.
  24. * http://www.daviddurman.com/flexi-color-picker/#
  25. */
  26. (function (window, document, undefined) {
  27. var type = (window.SVGAngle || document.implementation.hasFeature("http://www.w3.org/TR/SVG11/feature#BasicStructure", "1.1") ? "SVG" : "VML"),
  28. picker,
  29. slide,
  30. hueOffset = 15,
  31. svgNS = 'http://www.w3.org/2000/svg';
  32. // This HTML snippet is inserted into the innerHTML property of the passed color picker element
  33. // when the no-hassle call to ColorPicker() is used, i.e. ColorPicker(function(hex, hsv, rgb) { ... });
  34. var colorpickerHTMLSnippet = [
  35. '<div class="picker-wrapper">',
  36. '<div class="picker"></div>',
  37. '<div class="picker-indicator"></div>',
  38. '</div>',
  39. '<div class="slide-wrapper">',
  40. '<div class="slide"></div>',
  41. '<div class="slide-indicator"></div>',
  42. '</div>'
  43. ].join('');
  44. /**
  45. * Return mouse position relative to the element el.
  46. */
  47. function mousePosition(evt) {
  48. // IE:
  49. if (window.event && window.event.contentOverflow !== undefined) {
  50. return {
  51. x : window.event.offsetX,
  52. y : window.event.offsetY
  53. };
  54. }
  55. // Webkit:
  56. if (evt.offsetX !== undefined && evt.offsetY !== undefined) {
  57. return {
  58. x : evt.offsetX,
  59. y : evt.offsetY
  60. };
  61. }
  62. // Firefox:
  63. var wrapper = evt.target.parentNode.parentNode;
  64. return {
  65. x : evt.layerX - wrapper.offsetLeft,
  66. y : evt.layerY - wrapper.offsetTop
  67. };
  68. }
  69. /**
  70. * Create SVG element.
  71. */
  72. function $(el, attrs, children) {
  73. el = document.createElementNS(svgNS, el);
  74. for (var key in attrs)
  75. el.setAttribute(key, attrs[key]);
  76. if (Object.prototype.toString.call(children) != '[object Array]')
  77. children = [children];
  78. var i = 0,
  79. len = (children[0] && children.length) || 0;
  80. for (; i < len; i++)
  81. el.appendChild(children[i]);
  82. return el;
  83. }
  84. /**
  85. * Create slide and picker markup depending on the supported technology.
  86. */
  87. if (type == 'SVG') {
  88. slide = $('svg', {
  89. xmlns : 'http://www.w3.org/2000/svg',
  90. version : '1.1',
  91. width : '100%',
  92. height : '100%'
  93. },
  94. [
  95. $('defs', {},
  96. $('linearGradient', {
  97. id : 'gradient-hsv',
  98. x1 : '0%',
  99. y1 : '100%',
  100. x2 : '0%',
  101. y2 : '0%'
  102. },
  103. [
  104. $('stop', {
  105. offset : '0%',
  106. 'stop-color' : '#FF0000',
  107. 'stop-opacity' : '1'
  108. }),
  109. $('stop', {
  110. offset : '13%',
  111. 'stop-color' : '#FF00FF',
  112. 'stop-opacity' : '1'
  113. }),
  114. $('stop', {
  115. offset : '25%',
  116. 'stop-color' : '#8000FF',
  117. 'stop-opacity' : '1'
  118. }),
  119. $('stop', {
  120. offset : '38%',
  121. 'stop-color' : '#0040FF',
  122. 'stop-opacity' : '1'
  123. }),
  124. $('stop', {
  125. offset : '50%',
  126. 'stop-color' : '#00FFFF',
  127. 'stop-opacity' : '1'
  128. }),
  129. $('stop', {
  130. offset : '63%',
  131. 'stop-color' : '#00FF40',
  132. 'stop-opacity' : '1'
  133. }),
  134. $('stop', {
  135. offset : '75%',
  136. 'stop-color' : '#0BED00',
  137. 'stop-opacity' : '1'
  138. }),
  139. $('stop', {
  140. offset : '88%',
  141. 'stop-color' : '#FFFF00',
  142. 'stop-opacity' : '1'
  143. }),
  144. $('stop', {
  145. offset : '100%',
  146. 'stop-color' : '#FF0000',
  147. 'stop-opacity' : '1'
  148. })
  149. ])),
  150. $('rect', {
  151. x : '0',
  152. y : '0',
  153. width : '100%',
  154. height : '100%',
  155. fill : 'url(#gradient-hsv)'
  156. })
  157. ]);
  158. picker = $('svg', {
  159. xmlns : 'http://www.w3.org/2000/svg',
  160. version : '1.1',
  161. width : '100%',
  162. height : '100%'
  163. },
  164. [
  165. $('defs', {},
  166. [
  167. $('linearGradient', {
  168. id : 'gradient-black',
  169. x1 : '0%',
  170. y1 : '100%',
  171. x2 : '0%',
  172. y2 : '0%'
  173. },
  174. [
  175. $('stop', {
  176. offset : '0%',
  177. 'stop-color' : '#000000',
  178. 'stop-opacity' : '1'
  179. }),
  180. $('stop', {
  181. offset : '100%',
  182. 'stop-color' : '#CC9A81',
  183. 'stop-opacity' : '0'
  184. })
  185. ]),
  186. $('linearGradient', {
  187. id : 'gradient-white',
  188. x1 : '0%',
  189. y1 : '100%',
  190. x2 : '100%',
  191. y2 : '100%'
  192. },
  193. [
  194. $('stop', {
  195. offset : '0%',
  196. 'stop-color' : '#FFFFFF',
  197. 'stop-opacity' : '1'
  198. }),
  199. $('stop', {
  200. offset : '100%',
  201. 'stop-color' : '#CC9A81',
  202. 'stop-opacity' : '0'
  203. })
  204. ])
  205. ]),
  206. $('rect', {
  207. x : '0',
  208. y : '0',
  209. width : '100%',
  210. height : '100%',
  211. fill : 'url(#gradient-white)'
  212. }),
  213. $('rect', {
  214. x : '0',
  215. y : '0',
  216. width : '100%',
  217. height : '100%',
  218. fill : 'url(#gradient-black)'
  219. })
  220. ]);
  221. } else if (type == 'VML') {
  222. slide = [
  223. '<DIV style="position: relative; width: 100%; height: 100%">',
  224. '<v:rect style="position: absolute; top: 0; left: 0; width: 100%; height: 100%" stroked="f" filled="t">',
  225. '<v:fill type="gradient" method="none" angle="0" color="red" color2="red" colors="8519f fuchsia;.25 #8000ff;24903f #0040ff;.5 aqua;41287f #00ff40;.75 #0bed00;57671f yellow"></v:fill>',
  226. '</v:rect>',
  227. '</DIV>'
  228. ].join('');
  229. picker = [
  230. '<DIV style="position: relative; width: 100%; height: 100%">',
  231. '<v:rect style="position: absolute; left: -1px; top: -1px; width: 101%; height: 101%" stroked="f" filled="t">',
  232. '<v:fill type="gradient" method="none" angle="270" color="#FFFFFF" opacity="100%" color2="#CC9A81" o:opacity2="0%"></v:fill>',
  233. '</v:rect>',
  234. '<v:rect style="position: absolute; left: 0px; top: 0px; width: 100%; height: 101%" stroked="f" filled="t">',
  235. '<v:fill type="gradient" method="none" angle="0" color="#000000" opacity="100%" color2="#CC9A81" o:opacity2="0%"></v:fill>',
  236. '</v:rect>',
  237. '</DIV>'
  238. ].join('');
  239. if (!document.namespaces['v'])
  240. document.namespaces.add('v', 'urn:schemas-microsoft-com:vml', '#default#VML');
  241. }
  242. /**
  243. * Convert HSV representation to RGB HEX string.
  244. * Credits to http://www.raphaeljs.com
  245. */
  246. function hsv2rgb(hsv) {
  247. var R,
  248. G,
  249. B,
  250. X,
  251. C;
  252. var h = (hsv.h % 360) / 60;
  253. C = hsv.v * hsv.s;
  254. X = C * (1 - Math.abs(h % 2 - 1));
  255. R = G = B = hsv.v - C;
  256. h = ~~h;
  257. R += [C, X, 0, 0, X, C][h];
  258. G += [X, C, C, X, 0, 0][h];
  259. B += [0, 0, X, C, C, X][h];
  260. var r = Math.floor(R * 255);
  261. var g = Math.floor(G * 255);
  262. var b = Math.floor(B * 255);
  263. return {
  264. r : r,
  265. g : g,
  266. b : b,
  267. hex : "#" + (16777216 | b | (g << 8) | (r << 16)).toString(16).slice(1)
  268. };
  269. }
  270. /**
  271. * Convert RGB representation to HSV.
  272. * r, g, b can be either in <0,1> range or <0,255> range.
  273. * Credits to http://www.raphaeljs.com
  274. */
  275. function rgb2hsv(rgb) {
  276. var r = rgb.r;
  277. var g = rgb.g;
  278. var b = rgb.b;
  279. if (rgb.r > 1 || rgb.g > 1 || rgb.b > 1) {
  280. r /= 255;
  281. g /= 255;
  282. b /= 255;
  283. }
  284. var H,
  285. S,
  286. V,
  287. C;
  288. V = Math.max(r, g, b);
  289. C = V - Math.min(r, g, b);
  290. H = (C == 0 ? null :
  291. V == r ? (g - b) / C + (g < b ? 6 : 0) :
  292. V == g ? (b - r) / C + 2 :
  293. (r - g) / C + 4);
  294. H = (H % 6) * 60;
  295. S = C == 0 ? 0 : C / V;
  296. return {
  297. h : H,
  298. s : S,
  299. v : V
  300. };
  301. }
  302. /**
  303. * Return click event handler for the slider.
  304. * Sets picker background color and calls ctx.callback if provided.
  305. */
  306. function slideListener(ctx, slideElement, pickerElement) {
  307. return function (evt) {
  308. evt = evt || window.event;
  309. var mouse = mousePosition(evt);
  310. ctx.h = mouse.y / slideElement.offsetHeight * 360 + hueOffset;
  311. var pickerColor = hsv2rgb({
  312. h : ctx.h,
  313. s : 1,
  314. v : 1
  315. });
  316. var c = hsv2rgb({
  317. h : ctx.h,
  318. s : ctx.s,
  319. v : ctx.v
  320. });
  321. pickerElement.style.backgroundColor = pickerColor.hex;
  322. ctx.callback && ctx.callback(c.hex, {
  323. h : ctx.h - hueOffset,
  324. s : ctx.s,
  325. v : ctx.v
  326. }, {
  327. r : c.r,
  328. g : c.g,
  329. b : c.b
  330. }, undefined, mouse);
  331. }
  332. };
  333. /**
  334. * Return click event handler for the picker.
  335. * Calls ctx.callback if provided.
  336. */
  337. function pickerListener(ctx, pickerElement) {
  338. return function (evt) {
  339. evt = evt || window.event;
  340. var mouse = mousePosition(evt),
  341. width = pickerElement.offsetWidth,
  342. height = pickerElement.offsetHeight;
  343. ctx.s = mouse.x / width;
  344. ctx.v = (height - mouse.y) / height;
  345. var c = hsv2rgb(ctx);
  346. ctx.callback && ctx.callback(c.hex, {
  347. h : ctx.h - hueOffset,
  348. s : ctx.s,
  349. v : ctx.v
  350. }, {
  351. r : c.r,
  352. g : c.g,
  353. b : c.b
  354. }, mouse);
  355. }
  356. };
  357. var uniqID = 0;
  358. /**
  359. * ColorPicker.
  360. * @param {DOMElement} slideElement HSV slide element.
  361. * @param {DOMElement} pickerElement HSV picker element.
  362. * @param {Function} callback Called whenever the color is changed provided chosen color in RGB HEX format as the only argument.
  363. */
  364. function ColorPicker(slideElement, pickerElement, callback) {
  365. if (!(this instanceof ColorPicker))
  366. return new ColorPicker(slideElement, pickerElement, callback);
  367. this.h = 0;
  368. this.s = 1;
  369. this.v = 1;
  370. if (!callback) {
  371. // call of the form ColorPicker(element, funtion(hex, hsv, rgb) { ... }), i.e. the no-hassle call.
  372. var element = slideElement;
  373. element.innerHTML = colorpickerHTMLSnippet;
  374. this.slideElement = element.getElementsByClassName('slide')[0];
  375. this.pickerElement = element.getElementsByClassName('picker')[0];
  376. var slideIndicator = element.getElementsByClassName('slide-indicator')[0];
  377. var pickerIndicator = element.getElementsByClassName('picker-indicator')[0];
  378. ColorPicker.fixIndicators(slideIndicator, pickerIndicator);
  379. this.callback = function (hex, hsv, rgb, pickerCoordinate, slideCoordinate) {
  380. ColorPicker.positionIndicators(slideIndicator, pickerIndicator, slideCoordinate, pickerCoordinate);
  381. pickerElement(hex, hsv, rgb);
  382. };
  383. } else {
  384. this.callback = callback;
  385. this.pickerElement = pickerElement;
  386. this.slideElement = slideElement;
  387. }
  388. if (type == 'SVG') {
  389. // Generate uniq IDs for linearGradients so that we don't have the same IDs within one document.
  390. // Then reference those gradients in the associated rectangles.
  391. var slideClone = slide.cloneNode(true);
  392. var pickerClone = picker.cloneNode(true);
  393. var hsvGradient = slideClone.getElementById('gradient-hsv');
  394. var hsvRect = slideClone.getElementsByTagName('rect')[0];
  395. hsvGradient.id = 'gradient-hsv-' + uniqID;
  396. hsvRect.setAttribute('fill', 'url(#' + hsvGradient.id + ')');
  397. var blackAndWhiteGradients = [pickerClone.getElementById('gradient-black'), pickerClone.getElementById('gradient-white')];
  398. var whiteAndBlackRects = pickerClone.getElementsByTagName('rect');
  399. blackAndWhiteGradients[0].id = 'gradient-black-' + uniqID;
  400. blackAndWhiteGradients[1].id = 'gradient-white-' + uniqID;
  401. whiteAndBlackRects[0].setAttribute('fill', 'url(#' + blackAndWhiteGradients[1].id + ')');
  402. whiteAndBlackRects[1].setAttribute('fill', 'url(#' + blackAndWhiteGradients[0].id + ')');
  403. this.slideElement.appendChild(slideClone);
  404. this.pickerElement.appendChild(pickerClone);
  405. uniqID++;
  406. } else {
  407. this.slideElement.innerHTML = slide;
  408. this.pickerElement.innerHTML = picker;
  409. }
  410. addEventListener(this.slideElement, 'click', slideListener(this, this.slideElement, this.pickerElement));
  411. addEventListener(this.pickerElement, 'click', pickerListener(this, this.pickerElement));
  412. enableDragging(this, this.slideElement, slideListener(this, this.slideElement, this.pickerElement));
  413. enableDragging(this, this.pickerElement, pickerListener(this, this.pickerElement));
  414. };
  415. function addEventListener(element, event, listener) {
  416. if (element.attachEvent) {
  417. element.attachEvent('on' + event, listener);
  418. } else if (element.addEventListener) {
  419. element.addEventListener(event, listener, false);
  420. }
  421. }
  422. /**
  423. * Enable drag&drop color selection.
  424. * @param {object} ctx ColorPicker instance.
  425. * @param {DOMElement} element HSV slide element or HSV picker element.
  426. * @param {Function} listener Function that will be called whenever mouse is dragged over the element with event object as argument.
  427. */
  428. function enableDragging(ctx, element, listener) {
  429. var mousedown = false;
  430. addEventListener(element, 'mousedown', function (evt) {
  431. mousedown = true;
  432. });
  433. addEventListener(element, 'mouseup', function (evt) {
  434. mousedown = false;
  435. });
  436. addEventListener(element, 'mouseout', function (evt) {
  437. mousedown = false;
  438. });
  439. addEventListener(element, 'mousemove', function (evt) {
  440. if (mousedown) {
  441. listener(evt);
  442. }
  443. });
  444. }
  445. ColorPicker.hsv2rgb = function (hsv) {
  446. var rgbHex = hsv2rgb(hsv);
  447. delete rgbHex.hex;
  448. return rgbHex;
  449. };
  450. ColorPicker.hsv2hex = function (hsv) {
  451. return hsv2rgb(hsv).hex;
  452. };
  453. ColorPicker.rgb2hsv = rgb2hsv;
  454. ColorPicker.rgb2hex = function (rgb) {
  455. return hsv2rgb(rgb2hsv(rgb)).hex;
  456. };
  457. ColorPicker.hex2hsv = function (hex) {
  458. return rgb2hsv(ColorPicker.hex2rgb(hex));
  459. };
  460. ColorPicker.hex2rgb = function (hex) {
  461. return {
  462. r : parseInt(hex.substr(1, 2), 16),
  463. g : parseInt(hex.substr(3, 2), 16),
  464. b : parseInt(hex.substr(5, 2), 16)
  465. };
  466. };
  467. /**
  468. * Sets color of the picker in hsv/rgb/hex format.
  469. * @param {object} ctx ColorPicker instance.
  470. * @param {object} hsv Object of the form: { h: <hue>, s: <saturation>, v: <value> }.
  471. * @param {object} rgb Object of the form: { r: <red>, g: <green>, b: <blue> }.
  472. * @param {string} hex String of the form: #RRGGBB.
  473. */
  474. function setColor(ctx, hsv, rgb, hex) {
  475. ctx.h = hsv.h % 360;
  476. ctx.s = hsv.s;
  477. ctx.v = hsv.v;
  478. var c = hsv2rgb(ctx);
  479. var mouseSlide = {
  480. y : (ctx.h * ctx.slideElement.offsetHeight) / 360,
  481. x : 0 // not important
  482. };
  483. var pickerHeight = ctx.pickerElement.offsetHeight;
  484. var mousePicker = {
  485. x : ctx.s * ctx.pickerElement.offsetWidth,
  486. y : pickerHeight - ctx.v * pickerHeight
  487. };
  488. ctx.pickerElement.style.backgroundColor = hsv2rgb({
  489. h : ctx.h,
  490. s : 1,
  491. v : 1
  492. }).hex;
  493. ctx.callback && ctx.callback(hex || c.hex, {
  494. h : ctx.h,
  495. s : ctx.s,
  496. v : ctx.v
  497. }, rgb || {
  498. r : c.r,
  499. g : c.g,
  500. b : c.b
  501. }, mousePicker, mouseSlide);
  502. return ctx;
  503. };
  504. /**
  505. * Sets color of the picker in hsv format.
  506. * @param {object} hsv Object of the form: { h: <hue>, s: <saturation>, v: <value> }.
  507. */
  508. ColorPicker.prototype.setHsv = function (hsv) {
  509. return setColor(this, hsv);
  510. };
  511. /**
  512. * Sets color of the picker in rgb format.
  513. * @param {object} rgb Object of the form: { r: <red>, g: <green>, b: <blue> }.
  514. */
  515. ColorPicker.prototype.setRgb = function (rgb) {
  516. return setColor(this, rgb2hsv(rgb), rgb);
  517. };
  518. /**
  519. * Sets color of the picker in hex format.
  520. * @param {string} hex Hex color format #RRGGBB.
  521. */
  522. ColorPicker.prototype.setHex = function (hex) {
  523. return setColor(this, ColorPicker.hex2hsv(hex), undefined, hex);
  524. };
  525. /**
  526. * Helper to position indicators.
  527. * @param {HTMLElement} slideIndicator DOM element representing the indicator of the slide area.
  528. * @param {HTMLElement} pickerIndicator DOM element representing the indicator of the picker area.
  529. * @param {object} mouseSlide Coordinates of the mouse cursor in the slide area.
  530. * @param {object} mousePicker Coordinates of the mouse cursor in the picker area.
  531. */
  532. ColorPicker.positionIndicators = function (slideIndicator, pickerIndicator, mouseSlide, mousePicker) {
  533. if (mouseSlide) {
  534. slideIndicator.style.top = (mouseSlide.y - slideIndicator.offsetHeight / 2) + 'px';
  535. }
  536. if (mousePicker) {
  537. pickerIndicator.style.top = (mousePicker.y - pickerIndicator.offsetHeight / 2) + 'px';
  538. pickerIndicator.style.left = (mousePicker.x - pickerIndicator.offsetWidth / 2) + 'px';
  539. }
  540. };
  541. /**
  542. * Helper to fix indicators - this is recommended (and needed) for dragable color selection (see enabledDragging()).
  543. */
  544. ColorPicker.fixIndicators = function (slideIndicator, pickerIndicator) {
  545. pickerIndicator.style.pointerEvents = 'none';
  546. slideIndicator.style.pointerEvents = 'none';
  547. };
  548. window.ColorPicker = ColorPicker;
  549. })(window, window.document);
  550.  
  551. var UA = navigator.userAgent;
  552. var googleDomain = "translate.google.com";
  553. var dictURL= "https://" + googleDomain + "/translate_a/single?client=t";
  554. var ttsURL= "http://" + googleDomain + "/translate_tts?client=t";
  555.  
  556. const HREF_NO = 'javascript:void(0)';
  557. initCrossBrowserSupportForGmFunctions();
  558. var languagesGoogle = '<option value="auto">Detect language</option><option value="af">Afrikaans</option><option value="sq">Albanian</option><option value="ar">Arabic</option><option value="hy">Armenian</option><option value="az">Aerbaijani</option><option value="eu">Basque</option><option value="be">Belarusian</option><option value="bn">Bengali</option><option value="bg">Bulgarian</option><option value="ca">Catalan</option><option value="zh-CN">Chinese (simplified)</option><option value="zh-TW">Chinese (traditional)</option><option value="hr">Croatian</option><option value="cs">Czech</option><option value="da">Danish</option><option value="nl">Dutch</option><option value="en">English</option><option value="et">Estonian</option><option value="tl">Filipino</option><option value="fi">Finnish</option><option value="fr">French</option><option value="gl">Galician</option><option value="ka">Georgian</option><option value="de">German</option><option value="el">Greek</option><option value="ht">Haitian Creole</option><option value="iw">Hebrew</option><option value="hi">Hindi</option><option value="hu">Hungarian</option><option value="is">Icelandic</option><option value="id">Indonesian</option><option value="ga">Irish</option><option value="it">Italian</option><option value="ja">Japanese</option><option value="ko">Korean</option><option value="lv">Latvian</option><option value="lt">Lithuanian</option><option value="mk">Macedonian</option><option value="ms">Malay</option><option value="mt">Maltese</option><option value="no">Norwegian</option><option value="fa">Persian</option><option value="pl">Polish</option><option value="pt">Portuguese</option><option value="ro">Romanian</option><option value="ru">Russian</option><option value="sr">Serbian</option><option value="sk">Slovak</option><option value="sl">Slovenian</option><option value="es">Spanish</option><option value="sw">Swahili</option><option value="sv">Swedish</option><option value="th">Thai</option><option value="tr">Turkish</option><option value="uk">Ukrainian</option><option value="ur">Urdu</option><option value="vi">Vietnamese</option><option value="cy">Welsh</option><option value="yi">Yiddish</option>';
  559. var body = getTag('body')[0];
  560. var imgLookup;
  561. var txtSel = encodeURIComponent(txtSel); // text selected
  562. var translation2Element = document.createElement('span');
  563. var translation3Element = document.createElement('span');
  564. var currentURL;
  565. var context;
  566. var initialized = false;
  567. images();
  568. css();
  569. document.addEventListener('mouseup', showLookupIcon, false);
  570. document.addEventListener('mousedown', mousedownCleaning, false);
  571. function mousedownCleaning(evt) {
  572. var divDic = getId('divDic');
  573. var divLookup = getId('divLookup');
  574. if (divDic) {
  575. if (!clickedInsideID(evt.target, 'divDic'))
  576. divDic.parentNode.removeChild(divDic);
  577. }
  578. if (divLookup)
  579. divLookup.parentNode.removeChild(divLookup);
  580. }
  581. function showLookupIcon(evt) {
  582. if (evt.ctrlKey && evt.altKey && (!GM_getValue('ctrl') || !GM_getValue('alt')))
  583. return;
  584. // XOR http://www.howtocreate.co.uk/xor.html
  585. if (evt.ctrlKey ? !GM_getValue('ctrl') : GM_getValue('ctrl'))
  586. return;
  587. if (evt.altKey ? !GM_getValue('alt') : GM_getValue('alt'))
  588. return;
  589. if (!initialized) {
  590. images();
  591. css();
  592. initialized = true;
  593. }
  594. var divDic = getId('divDic');
  595. var divLookup = getId('divLookup');
  596. txtSel = getSelection();
  597. // Exit if no text is selected
  598. if (!txtSel || txtSel == "") {
  599. if (divDic) {
  600. if (!clickedInsideID(evt.target, 'divDic'))
  601. divDic.parentNode.removeChild(divDic);
  602. }
  603. if (divLookup)
  604. divLookup.parentNode.removeChild(divLookup);
  605. return;
  606. }
  607. // Possible cleanup
  608. if (divDic) {
  609. if (!clickedInsideID(evt.target, 'divDic'))
  610. divDic.parentNode.removeChild(divDic);
  611. return;
  612. }
  613. // Remove div if exists
  614. if (divLookup) {
  615. divLookup.parentNode.removeChild(divLookup);
  616. }
  617. if(context!=null){
  618. context.close();
  619. context = null;
  620. }
  621. if(GM_getValue('tts', false) == true)context = new AudioContext();
  622. // Div container
  623. divLookup = createElement('div', {
  624. id : 'divLookup',
  625. style : 'background-color:transparent; color:#000000; position:absolute; top:' + (evt.clientY + window.pageYOffset + 10) + 'px; left:' + (evt.clientX + window.pageXOffset + 10) + 'px; padding:0px; z-index:10000; border-radius:2px;'
  626. });
  627. divLookup.appendChild(imgLookup.cloneNode(false));
  628. divLookup.addEventListener('mouseover', function(evt){setTimeout(lookup,parseInt(GM_getValue('delay')))}, false);
  629. body.appendChild(divLookup);
  630. }
  631. // Create the tooltip and launch the Google Translate request to get the translation
  632. function lookup(evt) {
  633. var divResult = null;
  634. var divDic = getId('divDic');
  635. var divLookup = getId('divLookup');
  636. var top = divLookup.style.top;
  637. var left = divLookup.style.left;
  638. // No text selected
  639. if (!txtSel || txtSel == "") {
  640. if (divDic = getId('divDic'))
  641. divDic.parentNode.removeChild(divDic);
  642. return;
  643. }
  644. // Cleanup divs
  645. if (divDic = getId('divDic')) {
  646. divDic.parentNode.removeChild(divDic);
  647. }
  648. divLookup.parentNode.removeChild(divLookup);
  649. // Div container
  650. divDic = createElement('div', {
  651. id : 'divDic',
  652. style : 'opacity: 1; font-family: "Open Sans", Arial, Helvetica, sans-serif !important; font-size: ' + GM_getValue('fontsize', 'small') + '; background-color: ' + GM_getValue('backgroundColor', '#EDF4FC') + '; color: ' + GM_getValue('textcolor', 'Gray') + '; position:absolute; top:' + top + '; left:' + left + '; min-width:250px; min-height:50px; max-width:50%; padding:5px; text-align:left; z-index:10000; border-radius:4px; box-shadow: -2px 0px 9px 5px #898D91'
  653. });
  654. divDic.addEventListener('mousedown', dragHandler, false);
  655. body.appendChild(divDic);
  656. // Div result
  657. // This awfull wall of text is the "+" image
  658. divResult = createElement('div', {
  659. id : 'divResult',
  660. style : 'overflow:auto; padding:3px;'
  661. }, null, '<img src="data:image/gif;base64,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' +
  662. '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' +
  663. 'SX8jiuicMMBFd2OmKwQFs2tjXpDfnPE1j30V3c7iRHlrzBD2HONzODyZtsQJMI4r0AUNaE3XNHQw95c9GC001MpIxDacFQ+ulTNTZlU3O1eWVHa6vb/pnQUUrgHHSBKIuwG+bCPyEqbAg25gMVV1iOB/IGh5YOKLKIQ6xBAcUHmzjIcIqgajZ+Ro42DcvXl7j0U4WOUd+2IGu7DWjI1pt4DYq8BPm0entuGSQY/4tBi9Ss0HqfwngBQtHbCH88MQXb/zxyFfRRRHMN+/889BHL/301Fdv/fXYZ39CCAAh+QQJCgAAACwAAAAA3AATAAAF/yAgjmRpnmiqrmzrvnAsz3Rt33iu73zv/8CgcEgECAaEpHLJbDqf0Kh0Sq1ar9isdjoQtAQFh2fAKXsKm7R6Q+Y43vABep0mGwwOPH7w2CT+gHZ3d3lyagl+CQNvg4yGh36LcHoGfHR/ZYOElQ9/a4ocmoRygIiRk5p8pYmZjXePaYBujHoOqp5qZHBlHAUFXitddg8PBg8KGsgayxvGkAkFDwgICtPTzX2mftHW3QnOpojG3dbYkNjk1waxsdDS1N7ga9zw1t/aifTk35fu6Qj3numL14fOuHTNECHqU4DDgQEsCCwidiHBAwYQMmpcUOCAhI8gJVzUuLGThAQnP/9abEAyI4MCIVOKZNnyJUqUJxNcGNlywYOQgHZirGkSJ8gHNEky+AkS58qWEJYC/bMzacmbQHkqNdlUJ1KoSz2i9COhmQYCEXtVrCBgwYS3cCf8qTcNQ9u4cFFOq2bPLV65Cf7dxZthbjW+CgbjnWtNgWPFcAsHdoxgWWK/iyV045sAc2S96SDn1exYw17REwpLQEYt2eW/qtPZRQAB7QoC61RW+GsBwYZ/CXb/XRCYLsAKFizEtUAc+G7lcZsjroscOvTmsoUvx15PwccJ0N8yL17N9PG/E7jv9S4hOV7pdIPDdZ+ePDzv2qMXn2b5+wTbKuAWnF3oZbABZY' +
  664. '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' +
  665. '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"/><br/>Loading...');
  666. divDic.appendChild(divResult);
  667. // Options link
  668. var optionLink = createElement('a', {
  669. id : 'optionsLink',
  670. href : HREF_NO,
  671. style : 'opacity:0.2; position:absolute; bottom:3px; right:13px; font-size:18px; text-decoration:none!important;background:#528DDF;padding:1px;color:#fff;border-radius:6px 6px 6px 6px;border:2px solid #EEEEEE;font-weight:bold;width:20px;text-align:center;display:block;'
  672. }, 'click openCloseOptions false', '+');
  673. divDic.appendChild(optionLink);
  674. optionLink.addEventListener('mouseover', function (e) {
  675. e.target.style.opacity = 1.0
  676. });
  677. optionLink.addEventListener('mouseout', function (e) {
  678. e.target.style.opacity = 0.2
  679. });
  680. // Send the Google Translate request
  681. if ((txtSel + " ").search(/^\s*https?:\/\//) > -1) {
  682. divResult.innerHTML = '<a href="' + txtSel + '" target="_blank" >' + txtSel + '</a>';
  683. } else if ((txtSel + " ").search(/^\s*\S+(\.\S+)+/) > -1) // site.dom
  684. {
  685. divResult.innerHTML = '<a style="color:#888;" href="http://' + txtSel + '" target="_blank" >' + txtSel + '</a>';
  686. } else {
  687. var sl, tl;
  688. sl = GM_getValue('from') ? GM_getValue('from') : "auto";
  689. tl = GM_getValue('to') ? GM_getValue('to') : "auto";
  690. Request(txtSel, sl, tl, extractResult);
  691.  
  692. if (GM_getValue('to2', 'Disabled') != 'Disabled') {
  693. sl = GM_getValue('from') ? GM_getValue('from') : "auto";
  694. tl = GM_getValue('to2') ? GM_getValue('to2') : "auto";
  695. Request(txtSel, sl, tl, extractResult2);
  696. } else {
  697. translation2Element.innerHTML = '';
  698. }
  699.  
  700. if (GM_getValue('to3', 'Disabled') != 'Disabled') {
  701. sl = GM_getValue('from') ? GM_getValue('from') : "auto";
  702. tl = GM_getValue('to3') ? GM_getValue('to3') : "auto";
  703. Request(txtSel, sl, tl, extractResult3);
  704. } else {
  705. translation3Element.innerHTML = '';
  706. }
  707. }
  708. }
  709. // Lanched when we select an other language in the setup menu
  710. function quickLookup() {
  711. getId('divDic').style.fontSize = getId('optFontSize').value;
  712. getId('divDic').style.color = getId('optTextColor').value;
  713. getId('divResult').innerHTML = 'Loading...';
  714. if((context == null) && (GM_getValue('tts', false) == true) ) context = new AudioContext();
  715. var sl,tl;
  716. sl = getId('optSelLangFrom').value;
  717. tl = getId('optSelLangTo').value;
  718. Request(txtSel, sl, tl, extractResult);
  719.  
  720. if (getId('optSelLangTo2').value != 'Disabled') {
  721. var sl,tl;
  722. sl = getId('optSelLangFrom').value;
  723. tl = getId('optSelLangTo2').value;
  724. Request(txtSel, sl, tl, extractResult2);
  725. } else {
  726. translation2Element.innerHTML = '';
  727. }
  728.  
  729. if (getId('optSelLangTo3').value != 'Disabled') {
  730. var sl,tl;
  731. sl = getId('optSelLangFrom').value;
  732. tl = getId('optSelLangTo3').value;
  733. Request(txtSel, sl, tl, extractResult3);
  734. } else {
  735. translation3Element.innerHTML = '';
  736. }
  737. }
  738.  
  739. function init_google_value_tk() {
  740. var url = "https://" + googleDomain;
  741. var timeout = setTimeout( function(){ this.abort(); }, 2000);
  742. GM_xmlhttpRequest({
  743. method: "GET",
  744. url: url,
  745. onreadystatechange: function(resp) {
  746. if (resp.readyState == 4) {
  747. clearTimeout(timeout);
  748. if (resp.status == 200) {
  749. init_google_value_tk_parse(resp.responseText);
  750. }
  751. }
  752. }
  753. });
  754. }
  755.  
  756. function init_google_value_tk_parse(responseText) {
  757. // TKK=eval('((function(){var a\x3d4264492758;var b\x3d-1857761911;return 406375+\x27.\x27+(a+b)})())');
  758. var res = /;TKK=(.*?\'\));/i.exec(responseText);
  759. if (res != null) {
  760. var res2 = /var a=(.*?);.*?var b=(.*?);.*?return (\d+)/i.exec(res[1].replace(/\\x3d/g, '='));
  761. if (res2 != null) {
  762. var tkk = Number(res2[3]) + '.' + (Number(res2[1]) + Number(res2[2]));
  763. GM_setValue('google_value_tk', tkk);
  764. }
  765. };
  766. }
  767.  
  768. // return token for the new API
  769. function googleTK(text) {
  770. // view-source:https://translate.google.com/translate/releases/twsfe_w_20151214_RC03/r/js/desktop_module_main.js && TKK from HTML
  771. var uM = GM_getValue('google_value_tk');
  772. if (uM == 'undefined' || uM == null) {
  773. init_google_value_tk();
  774. uM = GM_getValue('google_value_tk');
  775. };
  776. var cb="&";
  777. var k="";
  778. var Gf="=";
  779. var Vb="+-a^+6";
  780. var t="a";
  781. var Yb="+";
  782. var Zb="+-3^+b+-f";
  783. var jd=".";
  784. var sM=function(a){return function(){return a}}
  785. var tM=function(a,b){for(var c=0;c<b.length-2;c+=3){var d=b.charAt(c+2),d=d>=t?d.charCodeAt(0)-87:Number(d),d=b.charAt(c+1)==Yb?a>>>d:a<<d;a=b.charAt(c)==Yb?a+d&4294967295:a^d}return a};
  786. var vM=function(a){
  787. var b;
  788. if(null!==uM) {
  789. b=uM;
  790. }else{
  791. b=sM(String.fromCharCode(84));var c=sM(String.fromCharCode(75));b=[b(),b()];
  792. b[1]=c();
  793. b=(uM=window[b.join(c())]||k)||k
  794. }
  795. var d=sM(String.fromCharCode(116)),c=sM(String.fromCharCode(107)),d=[d(),d()];
  796. d[1]=c();
  797. c=cb+d.join(k)+Gf;
  798. d=b.split(jd);
  799. b=Number(d[0])||0;
  800.  
  801. for(var e=[],f=0,g=0;g<a.length;g++){
  802. var m=a.charCodeAt(g);
  803. 128>m?e[f++]=m:(2048>m?e[f++]=m>>6|192:(55296==(m&64512)&&g+1<a.length&&56320==(a.charCodeAt(g+1)&64512)?(m=65536+((m&1023)<<10)+(a.charCodeAt(++g)&1023),e[f++]=m>>18|240,e[f++]=m>>12&63|128):e[f++]=m>>12|224,e[f++]=m>>6&63|128),e[f++]=m&63|128)
  804. }
  805. a=b||0;
  806. for(f=0;f<e.length;f++) { a+=e[f],a=tM(a,Vb)};
  807. a=tM(a,Zb);
  808. a^=Number(d[1])||0;
  809. 0>a&&(a=(a&2147483647)+2147483648);
  810. a%=1E6;
  811. return a.toString()+jd+(a^b);
  812. };
  813. return vM(text);
  814. }
  815.  
  816. // Google Translate Request
  817. function Request(txt, sl, tl, parse) {
  818. var tk=googleTK(txt);
  819. var Url = dictURL +
  820. "&hl=auto" +
  821. "&sl=" + sl + "&tl=" + tl +
  822. "&dt=bd&dt=ex&dt=ld&dt=md&dt=qca&dt=rw&dt=rm&dt=ss&dt=t&dt=at&ie=UTF-8&oe=UTF-8&otf=2&trs=1&inputm=1&ssel=0&tsel=0&source=btn&kc=3"+
  823. "&tk=" + tk +
  824. "&q="+ encodeURI(txt);
  825. var method='POST';
  826. var Data='';
  827. var Hdr= {
  828. "User-Agent": UA,
  829. "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  830. "Accept-Encoding": "gzip, deflate"
  831. }
  832. var Q=Url.split('&q=');
  833. Url=Q[0];
  834. Data='&q='+Q[1];
  835. Hdr["Content-Length"]=Data.length+'';
  836. Hdr["Content-Type"]="application/x-www-form-urlencoded; charset=UTF-8";
  837. GM_xmlhttpRequest({
  838. method: method,
  839. url: Url,
  840. data: Data,
  841. headers: Hdr,
  842. onload: function(resp) {
  843. try{
  844. parse(resp.responseText)
  845. }catch(e){
  846. GM_log(e);
  847. }
  848. }
  849. });
  850. }
  851.  
  852. function extractResult(gTradStringArray) {
  853. var arr = eval(gTradStringArray); // eval is used to transform the string to an array. I alse made a custom parsing function, but it doesn't handle antislashed characters, so I prefer using eval()
  854. /*
  855. Content of the gTrad array :
  856. 0 / 0:Translation 1:Source text
  857. 1 / i:Grammar / 0:Types (word, verb, ...) 1: Other translations
  858. 5 / Array of other translations
  859. */
  860. var translation = '';
  861. // 0 - Full translation
  862. translation += '<small><a style="color:#1a0dab;" href="https://' + googleDomain + '/#' + GM_getValue('from', 'auto') + '/' + GM_getValue('to', 'auto') + '/' + txtSel + '">[' + arr[2] + '] ';
  863. for (var i = 0; i < arr[0].length; i++) { if (typeof arr[0][i][1] != 'undefined' && arr[0][i][1] != null) translation += arr[0][i][1]; }
  864. translation += '</a> <span id="texttospeechbuttonfrom"></span></small><br/>';
  865. translation += '[' + GM_getValue('to', 'auto') + '] ';
  866. for (var i = 0; i < arr[0].length; i++) { if (typeof arr[0][i][0] != 'undefined' && arr[0][i][0] != null) translation += arr[0][i][0]; }
  867. translation += ' <span id="texttospeechbuttonto"></span><br/>';
  868. translation += '<span id="translation2Element"></span>';
  869. translation += '<span id="translation3Element"></span>';
  870. translation += '<a id="toggleShowDetails" style="color:#000;' + (!GM_getValue('details', 'false') ? 'display:none;"' : '"') + '>Show details</a>';
  871. translation += '<span id="divDetails" ' + (GM_getValue('details', 'false') ? 'style="display:none;"' : '') + '><a style="color:#000;" id="toggleHideDetails">Hide details</a><br/>';
  872.  
  873. // 1 - Grammar
  874. if (typeof arr[1] != 'undefined' && arr[1] != null ||
  875. typeof arr[5] != 'undefined' && arr[5] != null ||
  876. typeof arr[14] != 'undefined' && arr[14] != null) {
  877. translation += '<strong>Translations</strong><br/>';
  878. }
  879.  
  880. if (typeof arr[1] != 'undefined' && arr[1] != null) {
  881. for (var i = 0; i < arr[1].length; i++) {
  882. translation += arr[1][i][0] + ': ';
  883. translation += arr[1][i][1].join(', ');
  884. translation += '<br/>';
  885. }
  886. }
  887.  
  888. // 5 - Alternatives
  889. if (GM_getValue('alternatives', 'true')) {
  890. if (typeof arr[5] != 'undefined' && arr[5] != null) {
  891. for (var i = 0; i < arr[5].length; i++) {
  892. if (typeof arr[5][i][2] != 'undefined' && arr[5][i][2] != null) { // 5/i/2 array of alternatives, 5/i/0 the part of the text we are studying
  893. translation += '<i>alternatives: </i>';
  894. for (var j = 0; j < arr[5][i][2].length; j++) {
  895. translation += '<i>' + ((j == 0) ? '' : ', ') + arr[5][i][2][j][0] + '</i>';
  896. }
  897. translation += '<br/>';
  898. }
  899. }
  900. }
  901. }
  902.  
  903. // 14 - See also
  904. if (typeof arr[14] != 'undefined' && arr[14] != null) {
  905. // for (var i = 0; i < arr[14].length; i++) {
  906. translation += '<i>See also: </i>';
  907. translation += '<i>' + arr[14][0].join(', ') + '</i>';
  908. translation += '<br/>';
  909. // }
  910. }
  911.  
  912. // if ((typeof arr[1] != 'undefined' && arr[1] != null ||
  913. // typeof arr[5] != 'undefined' && arr[5] != null ||
  914. // typeof arr[14] != 'undefined' && arr[14] != null) &&
  915. // (typeof arr[12] != 'undefined' && arr[12] != null)) {
  916. // translation += '<br/>';
  917. // }
  918.  
  919. // 12 and 11 - Definitions and Synonyms
  920. if (typeof arr[12] != 'undefined' && arr[12] != null) {
  921. translation += '<strong>Definitions</strong><br/>';
  922. for (var i = 0; i < arr[12].length; i++) {
  923. if (typeof arr[12][i][1] != 'undefined' && arr[12][i][1] != null) { // 11/i/1 array of alternatives, 11/i/0 the part of the text we are studying
  924. for (var j = 0; j < arr[12][i][1].length; j++) {
  925. translation += '' + arr[12][i][0] + ': ';
  926. translation += arr[12][i][1][j][0];
  927. translation += '<br/>';
  928. if (GM_getValue('synonyms', 'true')) {
  929. if (typeof arr[11] != 'undefined' && arr[11] != null) {
  930. if (typeof arr[11][i] != 'undefined' && [11][i] != null) {
  931. for (var k = 0; k < arr[11][i][1].length; k++) {
  932. if (arr[12][i][1][j][1] == arr[11][i][1][k][1]) {
  933. translation += '<i>synonyms:</i> ';
  934. translation += '<i>' + arr[11][i][1][k][0].join(', ') + '</i>';
  935. translation += '<br/>';
  936. break;
  937. }
  938. }
  939. }
  940. }
  941. }
  942. }
  943. }
  944. }
  945. }
  946.  
  947. translation += '</span>'; // Detail end
  948.  
  949. getId('divResult').innerHTML = '<p style="margin:0px;padding:0px;line-height:150%;text-align:left;">' + translation + '</p>';
  950. getId('translation2Element').appendChild(translation2Element); // Optional second translation
  951. getId('translation3Element').appendChild(translation3Element); // Optional third translation
  952. getId('toggleShowDetails').addEventListener('click', function () {
  953. getId('toggleShowDetails').style.display = 'none';
  954. getId('divDetails').style.display = 'block';
  955. }, false);
  956. getId('toggleHideDetails').addEventListener('click', function () {
  957. getId('toggleShowDetails').style.display = 'inline';
  958. getId('divDetails').style.display = 'none';
  959. }, false);
  960. // Create the Text to speech
  961. var fromText = '';
  962. var toText = '';
  963. for (var i = 0; i < arr[0].length; i++) { if (typeof arr[0][i][1] != 'undefined' && arr[0][i][1] != null) fromText += arr[0][i][1]; }
  964. for (var i = 0; i < arr[0].length; i++) { if (typeof arr[0][i][0] != 'undefined' && arr[0][i][0] != null) toText += arr[0][i][0]; }
  965. addTextTospeechLink(getId('texttospeechbuttonfrom'), arr[2], fromText); // arr[2] contains the detected input language
  966. addTextTospeechLink(getId('texttospeechbuttonto'), GM_getValue('to', 'auto') == 'auto' ? 'en' : GM_getValue('to', 'auto'), toText); // I cannot find a way to get the detected destination language, so if the requested destination is 'auto', I use the english Text to speech language
  967. }
  968. function extractResult2(gTradStringArray) {
  969. var arr = eval(gTradStringArray);
  970. var translation = '';
  971. translation += '#[' + GM_getValue('to2', 'auto') + '] ';
  972. for (var i = 0; i < arr[0].length; i++) { if (typeof arr[0][i][0] != 'undefined' && arr[0][i][0] != null) translation += arr[0][i][0]; }
  973. translation += ' <span id="texttospeechbuttonto2"></span><br/>';
  974. translation2Element.innerHTML = translation;
  975. var toText2 = '';
  976. for (var i = 0; i < arr[0].length; i++) { if (typeof arr[0][i][0] != 'undefined' && arr[0][i][0] != null) toText2 += arr[0][i][0]; }
  977. addTextTospeechLink(getId('texttospeechbuttonto2'), GM_getValue('to2', 'auto') == 'auto' ? 'en' : GM_getValue('to2', 'auto'), toText2);
  978. }
  979. function extractResult3(gTradStringArray) {
  980. var arr = eval(gTradStringArray);
  981. var translation = '';
  982. translation += '#[' + GM_getValue('to3', 'auto') + '] ';
  983. for (var i = 0; i < arr[0].length; i++) { if (typeof arr[0][i][0] != 'undefined' && arr[0][i][0] != null) translation += arr[0][i][0]; }
  984. translation += ' <span id="texttospeechbuttonto3"></span><br/>';
  985. translation3Element.innerHTML = translation;
  986. var toText3 = '';
  987. for (var i = 0; i < arr[0].length; i++) { if (typeof arr[0][i][0] != 'undefined' && arr[0][i][0] != null) toText3 += arr[0][i][0]; }
  988. addTextTospeechLink(getId('texttospeechbuttonto3'), GM_getValue('to3', 'auto') == 'auto' ? 'en' : GM_getValue('to3', 'auto'), toText3);
  989. }
  990. function addTextTospeechLink(element, lang, text) {
  991. if (GM_getValue('tts', false) == false) return;
  992.  
  993. var img = document.createElement('img');
  994. img.setAttribute('src', "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAABmJLR0QA/wD/AP+gvaeTAAAACXBIWXMAAAsTAAALEwEAmpwYAAAAB3RJTUUH3QEQDhUFQkzk7wAAAIpJREFUOMtj/P//PwNFgAQD3jMwMDRg6MVjwHw0/n4GBob/DAwM5xkYGAQIGTAfqhgdFEDF1+MzAKYZl9P6oXIO2AxA1owsAXc2lH7PwMCwHtmA/zgwPLygYYBi0f///xmYSIgwByT2QxiDiYFCQIoBB5DY8rgSEtmBSLVopEpCokpSJjozMVKanQFy4nkNOfntnwAAAABJRU5ErkJggg==");
  995. img.setAttribute('width', '16');
  996. img.setAttribute('height', '16');
  997. img.setAttribute('align', "top");
  998. element.appendChild(img);
  999.  
  1000. // var context = new AudioContext();
  1001. element.addEventListener('click', function() { playTTS(lang, text, context) }, false);
  1002. }
  1003.  
  1004. function playTTS(lang, text, context) {
  1005. text = text.replace(/[«»'"]/g, ' ');
  1006. tk = googleTK(text);
  1007. Url = ttsURL + "&ie=UTF-8&total=1&idx=0" +
  1008. "&tl=" + lang +
  1009. "&q=" + text +
  1010. "&textlen=" + text.length +
  1011. "&tk=" + tk;
  1012. window.AudioContext = window.AudioContext || window.webkitAudioContext;
  1013. //var context = new AudioContext();
  1014. var source = context.createBufferSource();
  1015.  
  1016. var soundRequest = GM_xmlhttpRequest({
  1017. method: "GET",
  1018. url: Url,
  1019. responseType: 'arraybuffer',
  1020. onload: function(response) {
  1021. try {
  1022. context.decodeAudioData(response.response, function(buffer) {
  1023. source.buffer = buffer;
  1024. source.connect(context.destination);
  1025. source.start(0);
  1026. });
  1027. } catch(e) {
  1028. GM_log(e);
  1029. }
  1030. }
  1031. });
  1032. }
  1033.  
  1034. function getSelection() {
  1035. var text = null;
  1036. //get selected text
  1037. if (window.getSelection && !window.opera) // window.getSelection() bugs with Opera 12.16 and ViolentMonkey
  1038. {
  1039. if (document.activeElement &&
  1040. (document.activeElement.tagName.toLowerCase() == "textarea" ||
  1041. document.activeElement.tagName.toLowerCase() == "input")) {
  1042. text = document.activeElement.value;
  1043. text = text.substring (document.activeElement.selectionStart, document.activeElement.selectionEnd);
  1044. } else {
  1045. text = window.getSelection().toString();
  1046. }
  1047. } else if (document.getSelection) {
  1048. text = document.getSelection().toString();
  1049. } else if (document.selection) {
  1050. text = document.selection.createRange().text;
  1051. }
  1052. // text = text.replace(/[«»'"]/g, ' ');
  1053. text = text.replace(/&/g,'\u00E6').replace(/</g,'\u227A').replace(/\+/g,'\u2795');
  1054. return text;
  1055. }
  1056. function openCloseOptions(evt) {
  1057. var divOptions = getId('divOpt');
  1058. if (!divOptions) //Show options
  1059. {
  1060. divOptions = createElement('div', {
  1061. id : 'divOpt',
  1062. style : 'border-top:2px solid #5A91D8;position:relative; padding:5px;'
  1063. });
  1064. getId('divDic').appendChild(divOptions);
  1065. getId('optionsLink').style.visibility = 'hidden';
  1066. // color picker, the library doesn't work on Opera
  1067. // try {
  1068. // if (!window.divColorPicker) {
  1069. // window.divColorPicker = createElement('div', {
  1070. // id : 'optPicker',
  1071. // class : 'cp-small'
  1072. // });
  1073. // window.colorPicker = ColorPicker(
  1074. // window.divColorPicker,
  1075. // function (hex, hsv, rgb) {
  1076. // getId('divDic').style.backgroundColor = hex;
  1077. // });
  1078. // }
  1079. // window.colorPicker.setHex(GM_getValue('backgroundColor', '#EDF4FC'));
  1080. // divOptions.appendChild(window.divColorPicker);
  1081. // } catch (err) {
  1082. // divOptions.innerHTML += '<p>Error : Cannot load color picker (Known issue on Opera)</p>';
  1083. // }
  1084. //fields container
  1085. divOptionsFields = createElement('p', {style: "margin:0px;padding:0px;line-height:160%;"});
  1086. divOptions.appendChild(divOptionsFields);
  1087. //from
  1088. divOptionsFields.appendChild(createElement('span', null, null, 'From: '));
  1089. divOptionsFields.appendChild(createElement('select', {
  1090. id : 'optSelLangFrom'
  1091. }, null, languagesGoogle));
  1092. getId('optSelLangFrom').value = GM_getValue('from') ? GM_getValue('from') : 'auto';
  1093. getId('optSelLangFrom').addEventListener('change', quickLookup, false);
  1094. //to
  1095. divOptionsFields.appendChild(createElement('br'));
  1096. divOptionsFields.appendChild(createElement('span', null, null, 'To: &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;'));
  1097. divOptionsFields.appendChild(createElement('select', {
  1098. id : 'optSelLangTo'
  1099. }, null, languagesGoogle));
  1100. getId('optSelLangTo').value = GM_getValue('to') ? GM_getValue('to') : 'auto';
  1101. getId('optSelLangTo').addEventListener('change', quickLookup, false);
  1102. //to2
  1103. divOptionsFields.appendChild(createElement('br'));
  1104. divOptionsFields.appendChild(createElement('span', null, null, 'To 2: &nbsp;&nbsp;'));
  1105. divOptionsFields.appendChild(createElement('select', {
  1106. id : 'optSelLangTo2'
  1107. }, null, '<option value="Disabled">Disabled</option>' + languagesGoogle));
  1108. getId('optSelLangTo2').value = GM_getValue('to2') ? GM_getValue('to2') : 'Disabled';
  1109. getId('optSelLangTo2').addEventListener('change', quickLookup, false);
  1110. //to3
  1111. divOptionsFields.appendChild(createElement('br'));
  1112. divOptionsFields.appendChild(createElement('span', null, null, 'To 3: &nbsp;&nbsp;'));
  1113. divOptionsFields.appendChild(createElement('select', {
  1114. id : 'optSelLangTo3'
  1115. }, null, '<option value="Disabled">Disabled</option>' + languagesGoogle));
  1116. getId('optSelLangTo3').value = GM_getValue('to3') ? GM_getValue('to3') : 'Disabled';
  1117. getId('optSelLangTo3').addEventListener('change', quickLookup, false);
  1118. //use text to speech
  1119. divOptionsFields.appendChild(createElement('br'));
  1120. divOptionsFields.appendChild(createElement('input', {
  1121. id : 'checkTTS',
  1122. type : 'checkbox',
  1123. style: "margin-left:0px;"
  1124. }));
  1125. divOptionsFields.appendChild(createElement('span', null, null, '<span title="The feature has many issues. You often have to refresh the page to launch the .mp3 file. If you use the langage auto-detection, you have to change the langage in the url of the new tab."> Display Text To speech</span>'));
  1126. getId('checkTTS').checked = GM_getValue('tts');
  1127. //hide details
  1128. divOptionsFields.appendChild(createElement('br'));
  1129. divOptionsFields.appendChild(createElement('input', {
  1130. id : 'checkDetails',
  1131. type : 'checkbox',
  1132. style: "margin-left:0px;"
  1133. }));
  1134. divOptionsFields.appendChild(createElement('span', null, null, ' Hide details by default'));
  1135. getId('checkDetails').checked = GM_getValue('details');
  1136.  
  1137. //show alternatives in details
  1138. divOptionsFields.appendChild(createElement('br'));
  1139. divOptionsFields.appendChild(createElement('input', {
  1140. id: 'checkAlternatives',
  1141. type: 'checkbox',
  1142. style: "margin-left:0px;"
  1143. }));
  1144. divOptionsFields.appendChild(createElement('span', null, null, ' Show alternatives in details'));
  1145. getId('checkAlternatives').checked = GM_getValue('alternatives');
  1146.  
  1147. //show synonyms in definitions
  1148. divOptionsFields.appendChild(createElement('br'));
  1149. divOptionsFields.appendChild(createElement('input', {
  1150. id: 'checkSynonyms',
  1151. type: 'checkbox',
  1152. style: "margin-left:0px;"
  1153. }));
  1154. divOptionsFields.appendChild(createElement('span', null, null, ' Show synonyms in definitions'));
  1155. getId('checkSynonyms').checked = GM_getValue('synonyms');
  1156.  
  1157. //font size
  1158. divOptionsFields.appendChild(createElement('br'));
  1159. divOptionsFields.appendChild(createElement('span', null, null, 'Font size: &nbsp;&nbsp;'));
  1160. divOptionsFields.appendChild(createElement('select', {
  1161. id : 'optFontSize',
  1162. style: 'width:141px'
  1163. }, null, '<option value="x-small">Extra small</option><option value="small">Small (default)</option><option value="medium">Medium</option><option value="large">Large</option>'));
  1164. getId('optFontSize').value = GM_getValue('fontsize') ? GM_getValue('fontsize') : 'small';
  1165. getId('optFontSize').addEventListener('change', quickLookup, false);
  1166. //text color
  1167. divOptionsFields.appendChild(createElement('br'));
  1168. divOptionsFields.appendChild(createElement('span', null, null, 'Text color: '));
  1169. divOptionsFields.appendChild(createElement('select', {
  1170. id : 'optTextColor',
  1171. style: 'width:141px'
  1172. }, null, '<option value="Gray">Gray (default)</option><option value="Black">Black</option><option value="White">White</option><option value="CadetBlue">CadetBlue</option><option value="ForestGreen">ForestGreen</option><option value="FireBrick">FireBrick</option>'));
  1173. getId('optTextColor').value = GM_getValue('textcolor') ? GM_getValue('textcolor') : 'Gray';
  1174. getId('optTextColor').addEventListener('change', quickLookup, false);
  1175. //use ctrl
  1176. divOptionsFields.appendChild(createElement('br'));
  1177. divOptionsFields.appendChild(createElement('input', {
  1178. id : 'checkCtrl',
  1179. type : 'checkbox',
  1180. style: "margin-left:0px;"
  1181. }));
  1182. divOptionsFields.appendChild(createElement('span', null, null, ' Use Ctrl key'));
  1183. getId('checkCtrl').checked = GM_getValue('ctrl');
  1184. //use alt
  1185. divOptionsFields.appendChild(createElement('br'));
  1186. divOptionsFields.appendChild(createElement('input', {
  1187. id : 'checkAlt',
  1188. type : 'checkbox',
  1189. style: "margin-left:0px;"
  1190. }));
  1191. divOptionsFields.appendChild(createElement('span', null, null, ' Use Alt key'));
  1192. getId('checkAlt').checked = GM_getValue('alt');
  1193. //delay display
  1194. divOptionsFields.appendChild(createElement('br'));
  1195. divOptionsFields.appendChild(createElement('span', null, null, 'Delay '));
  1196. divOptionsFields.appendChild(createElement('input', {
  1197. id: 'delayDisplay',
  1198. type: 'text',
  1199. style: "height:20px;width:50px;padding:0px;text-align:center;",
  1200. }));
  1201. divOptionsFields.appendChild(createElement('span', null, null, ' ms'));
  1202. getId('delayDisplay').value = GM_getValue('delay') ? GM_getValue('delay') : '0';
  1203. //save
  1204. divOptionsFields.appendChild(createElement('br'));
  1205. divOptionsFields.appendChild(createElement('a', {
  1206. href : HREF_NO,
  1207. class : "gootranslink"
  1208. }, 'click saveOptions false', 'Save'));
  1209. //reset
  1210. divOptionsFields.appendChild(createElement('span', null, null, ' - '));
  1211. divOptionsFields.appendChild(createElement('a', {
  1212. href : HREF_NO,
  1213. class : "gootranslink"
  1214. }, 'click resetOptions false', 'Reset'));
  1215. //cancel
  1216. divOptionsFields.appendChild(createElement('span', null, null, ' - '));
  1217. divOptionsFields.appendChild(createElement('a', {
  1218. href : HREF_NO,
  1219. class : "gootranslink"
  1220. }, 'click openCloseOptions false', 'Cancel'));
  1221. } else // Hide options
  1222. {
  1223. divOptions.parentNode.removeChild(divOptions);
  1224. getId('optionsLink').style.visibility = 'visible';
  1225. }
  1226. }
  1227.  
  1228. function saveOptions(evt) {
  1229.  
  1230. var backgroundColor = getId('divDic').style.backgroundColor;
  1231. var from = getId('optSelLangFrom').value;
  1232. var to = getId('optSelLangTo').value;
  1233. var to2 = getId('optSelLangTo2').value;
  1234. var to3 = getId('optSelLangTo3').value;
  1235. var tts = getId('checkTTS').checked;
  1236. var details = getId('checkDetails').checked;
  1237. var alternatives = getId('checkAlternatives').checked;
  1238. var synonyms = getId('checkSynonyms').checked;
  1239. var fontsize = getId('optFontSize').value;
  1240. var textcolor = getId('optTextColor').value;
  1241. var ctrl = getId('checkCtrl').checked;
  1242. var alt = getId('checkAlt').checked;
  1243. var delay = getId('delayDisplay').value;
  1244.  
  1245. GM_setValue('backgroundColor', backgroundColor);
  1246. GM_setValue('from', from);
  1247. GM_setValue('to', to);
  1248. GM_setValue('to2', to2);
  1249. GM_setValue('to3', to3);
  1250. GM_setValue('tts', tts);
  1251. GM_setValue('details', details);
  1252. GM_setValue('alternatives', alternatives);
  1253. GM_setValue('synonyms', synonyms);
  1254. GM_setValue('fontsize', fontsize);
  1255. GM_setValue('textcolor', textcolor);
  1256. GM_setValue('ctrl', ctrl);
  1257. GM_setValue('alt', alt);
  1258. GM_setValue('delay', delay);
  1259.  
  1260. quickLookup();
  1261. getId('divDic').removeChild(getId('divOpt'));
  1262. getId('optionsLink').style.visibility = 'visible';
  1263. }
  1264.  
  1265. function resetOptions(evt) {
  1266.  
  1267. GM_deleteValue('backgroundColor');
  1268. GM_deleteValue('from');
  1269. GM_deleteValue('to');
  1270. GM_deleteValue('to2');
  1271. GM_deleteValue('to3');
  1272. GM_deleteValue('tts');
  1273. GM_deleteValue('details');
  1274. GM_deleteValue('alternatives');
  1275. GM_deleteValue('synonyms');
  1276. GM_deleteValue('fontsize');
  1277. GM_deleteValue('textcolor');
  1278. GM_deleteValue('ctrl');
  1279. GM_deleteValue('alt');
  1280. GM_deleteValue('delay');
  1281.  
  1282. getId('divDic').parentNode.removeChild(getId('divDic'));
  1283. }
  1284.  
  1285. function css() {
  1286. var style = createElement('style', {
  1287. type : "text/css"
  1288. }, null, "" +
  1289. 'a.gootranslink:link {color: #0000FF !important; text-decoration: underline !important;}' +
  1290. 'a.gootranslink:visited {color: #0000FF !important; text-decoration: underline !important;}' +
  1291. 'a.gootranslink:hover {color: #0000FF !important; text-decoration: underline !important;}' +
  1292. 'a.gootranslink:active {color: #0000FF !important; text-decoration: underline !important;}' +
  1293. '.picker-wrapper,.slide-wrapper{position:relative;float:left}.picker-indicator,.slide-indicator{position:absolute;left:0;top:0;pointer-events:none}.picker,.slide{cursor:crosshair;float:left}.cp-default{background-color:gray;padding:12px;box-shadow:0 0 40px #000;border-radius:15px;float:left}.cp-default .picker{width:200px;height:200px}.cp-default .slide{width:30px;height:200px}.cp-default .slide-wrapper{margin-left:10px}.cp-default .picker-indicator{width:5px;height:5px;border:2px solid darkblue;-moz-border-radius:4px;-o-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;opacity:.5;-ms-filter:"alpha(opacity=50)";filter:alpha(opacity=50);filter:alpha(opacity=50);background-color:white}.cp-default .slide-indicator{width:100%;height:10px;left:-4px;opacity:.6;-ms-filter:"alpha(opacity=60)";filter:alpha(opacity=60);filter:alpha(opacity=60);border:4px solid lightblue;-moz-border-radius:4px;-o-border-radius:4px;-webkit-border-radius:4px;border-radius:4px;background-color:white}.cp-small{padding:5px;background-color:white;float:left;border-radius:5px}.cp-small .picker{width:100px;height:100px}.cp-small .slide{width:15px;height:100px}.cp-small .slide-wrapper{margin-left:5px}.cp-small .picker-indicator{width:1px;height:1px;border:1px solid black;background-color:white}.cp-small .slide-indicator{width:100%;height:2px;left:0;background-color:black}.cp-fancy{padding:10px;background:-webkit-linear-gradient(top,#aaa 0,#222 100%);float:left;border:1px solid #999;box-shadow:inset 0 0 10px white}.cp-fancy .picker{width:200px;height:200px}.cp-fancy .slide{width:30px;height:200px}.cp-fancy .slide-wrapper{margin-left:10px}.cp-fancy .picker-indicator{width:24px;height:24px;background-image:url(http://cdn1.iconfinder.com/data/icons/fugue/bonus/icons-24/target.png)}.cp-fancy .slide-indicator{width:30px;height:31px;left:30px;background-image:url(http://cdn1.iconfinder.com/data/icons/bluecoral/Left.png)}.cp-normal{padding:10px;background-color:white;float:left;border:4px solid #d6d6d6;box-shadow:inset 0 0 10px white}.cp-normal .picker{width:200px;height:200px}.cp-normal .slide{width:30px;height:200px}.cp-normal .slide-wrapper{margin-left:10px}.cp-normal .picker-indicator{width:5px;height:5px;border:1px solid gray;opacity:.5;-ms-filter:"alpha(opacity=50)";filter:alpha(opacity=50);filter:alpha(opacity=50);background-color:white;pointer-events:none}.cp-normal .slide-indicator{width:100%;height:10px;left:-4px;opacity:.6;-ms-filter:"alpha(opacity=60)";filter:alpha(opacity=60);filter:alpha(opacity=60);border:4px solid gray;background-color:white;pointer-events:none}');
  1294. getTag('head')[0].appendChild(style);
  1295. }
  1296. /*
  1297. * Short functions to replace the document.createElement document.getElementById and document.getElementsByTagName
  1298. */
  1299. function createElement(type, attrArray, evtListener, html) {
  1300. var node = document.createElement(type);
  1301. for (var attr in attrArray)
  1302. if (attrArray.hasOwnProperty(attr)) {
  1303. node.setAttribute(attr, attrArray[attr]);
  1304. }
  1305. if (evtListener) {
  1306. var a = evtListener.split(' ');
  1307. node.addEventListener(a[0], eval(a[1]), eval(a[2]));
  1308. }
  1309. if (html)
  1310. node.innerHTML = html;
  1311. return node;
  1312. }
  1313. function getId(id, parent) {
  1314. if (!parent)
  1315. return document.getElementById(id);
  1316. return parent.getElementById(id);
  1317. }
  1318. function getTag(name, parent) {
  1319. if (!parent)
  1320. return document.getElementsByTagName(name);
  1321. return parent.getElementsByTagName(name);
  1322. }
  1323. /*
  1324. * Drag and drop support adapted from http://www.hunlock.com/blogs/Javascript_Drag_and_Drop
  1325. */
  1326. var savedTarget = null; // The target layer (effectively vidPane)
  1327. var orgCursor = null; // The original mouse style so we can restore it
  1328. var dragOK = false; // True if we're allowed to move the element under mouse
  1329. var dragXoffset = 0; // How much we've moved the element on the horozontal
  1330. var dragYoffset = 0; // How much we've moved the element on the verticle
  1331. var didDrag = false; // Set to true when we do a drag
  1332. function moveHandler(e) {
  1333. if (e == null)
  1334. return; // { e = window.event }
  1335. if (e.button <= 1 && dragOK) {
  1336. savedTarget.style.left = e.clientX - dragXoffset + 'px';
  1337. savedTarget.style.top = e.clientY - dragYoffset + 'px';
  1338. return false;
  1339. }
  1340. }
  1341. function dragCleanup(e) {
  1342. document.removeEventListener('mousemove', moveHandler, false);
  1343. document.removeEventListener('mouseup', dragCleanup, false);
  1344. savedTarget.style.cursor = orgCursor;
  1345. dragOK = false; // Its been dragged now
  1346. didDrag = true;
  1347. }
  1348. function dragHandler(e) {
  1349. var htype = '-moz-grabbing';
  1350. if (e == null)
  1351. return; // { e = window.event;} // htype='move';}
  1352. var target = e.target; // != null ? e.target : e.srcElement;
  1353. orgCursor = target.style.cursor;
  1354. if (target.nodeName != 'DIV' && target.nodeName != 'P')
  1355. return;
  1356. if (target = clickedInsideID(target, 'divDic')) {
  1357. savedTarget = target;
  1358. target.style.cursor = htype;
  1359. dragOK = true;
  1360. dragXoffset = e.clientX - target.offsetLeft;
  1361. dragYoffset = e.clientY - target.offsetTop;
  1362. // Set the left before removing the right
  1363. target.style.left = e.clientX - dragXoffset + 'px';
  1364. target.style.right = null;
  1365. document.addEventListener('mousemove', moveHandler, false);
  1366. document.addEventListener('mouseup', dragCleanup, false);
  1367. return false;
  1368. }
  1369. }
  1370. function clickedInsideID(target, id) {
  1371. if (target.getAttribute('id') == id)
  1372. return getId(id);
  1373. if (target.parentNode) {
  1374. while (target = target.parentNode) {
  1375. try {
  1376. if (target.getAttribute('id') == id)
  1377. return getId(id);
  1378. } catch (e) {}
  1379. }
  1380. }
  1381. return null;
  1382. }
  1383. // End drag code
  1384. /*
  1385. * Images
  1386. */
  1387. function images() {
  1388. imgLookup = createElement('img', {
  1389. border : 0
  1390. });
  1391. imgLookup.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABs0lEQVQ4jY2SP4viQBiHX0UQWz/AXb+VX8Iu/YqFhdhcd5BKEOTKC9jJFYrFgo3FIjYiCRauhTCQDMp4bJFklzCuLJLOWNj8rpDMJt7u7Q08xQzze953/hAR0el4QJLw8KR4fXkE/Wtch01zjP6gmxLsd9uPJafjAf1BF82WjmZLR61eRa1eVfNmS4cMxP8JksGk6FPB6XjAii1Qq1fBBYMMBL79+InvDIrbB0CzIpSmQHF0RnF0vkiTFxZX7A+6MOzwU0FxdEZKYJpj1fp1eO5KzF0JzYreF/iekzr77QMUhh2q1zDsUIULPQl6fXkEFww53cWKLWCaY3DBVMuaFWHuSsT7fM/5W5DTXYUMBGQgUJoCpelFst9tcc84DDuE7znQrAiFnrwIkuGY/W6rBIYdQgYC7RmHZkXwPQf3jL8JiCglISLKVCaqzfhZfc9RcMFwc/eMfGd9EWQbS+R0F9nGEtnGEpnKBJnKJFWxPNygPNygPePggqE942nBdTjG9xyUhxvVcqEnsWILrNjiTfCRJN9ZI99Zp8LxWsy73ztTmYCI6ObuGV/7Tym+/PqtICL6A7F/dNYyWabFAAAAAElFTkSuQmCC';
  1392. }
  1393. if (typeof GM_deleteValue == 'undefined') {
  1394. GM_addStyle = function (css) {
  1395. var style = document.createElement('style');
  1396. style.textContent = css;
  1397. document.getElementsByTagName('head')[0].appendChild(style);
  1398. }
  1399. GM_deleteValue = function (name) {
  1400. localStorage.removeItem(name);
  1401. }
  1402. GM_getValue = function (name, defaultValue) {
  1403. var value = localStorage.getItem(name);
  1404. if (!value)
  1405. return defaultValue;
  1406. var type = value[0];
  1407. value = value.substring(1);
  1408. switch (type) {
  1409. case 'b':
  1410. return value == 'true';
  1411. case 'n':
  1412. return Number(value);
  1413. default:
  1414. return value;
  1415. }
  1416. }
  1417. GM_log = function (message) {
  1418. console.log(message);
  1419. }
  1420. GM_openInTab = function (url) {
  1421. return window.open(url, "_blank");
  1422. }
  1423. GM_registerMenuCommand = function (name, funk) {
  1424. //todo
  1425. }
  1426. GM_setValue = function (name, value) {
  1427. value = (typeof value)[0] + value;
  1428. localStorage.setItem(name, value);
  1429. }
  1430. }
  1431. /*
  1432. * Cross browser support for GM functions
  1433. * http://userscripts.org/topics/41177
  1434. */
  1435. function initCrossBrowserSupportForGmFunctions() {
  1436. if (typeof GM_deleteValue == 'undefined') {
  1437. GM_addStyle = function (css) {
  1438. var style = document.createElement('style');
  1439. style.textContent = css;
  1440. document.getElementsByTagName('head')[0].appendChild(style);
  1441. }
  1442. GM_deleteValue = function (name) {
  1443. localStorage.removeItem(name);
  1444. }
  1445. GM_getValue = function (name, defaultValue) {
  1446. var value = localStorage.getItem(name);
  1447. if (!value)
  1448. return defaultValue;
  1449. var type = value[0];
  1450. value = value.substring(1);
  1451. switch (type) {
  1452. case 'b':
  1453. return value == 'true';
  1454. case 'n':
  1455. return Number(value);
  1456. default:
  1457. return value;
  1458. }
  1459. }
  1460. GM_log = function (message) {
  1461. console.log(message);
  1462. }
  1463. GM_openInTab = function (url) {
  1464. return window.open(url, "_blank");
  1465. }
  1466. GM_registerMenuCommand = function (name, funk) {
  1467. //todo
  1468. }
  1469. GM_setValue = function (name, value) {
  1470. value = (typeof value)[0] + value;
  1471. localStorage.setItem(name, value);
  1472. }
  1473. }
  1474. }