Reverse TinEye Image Search

Dragging any image allows you to do a TinEye image search.

  1. // ==UserScript==
  2. // @name Reverse TinEye Image Search
  3. // @namespace AmineKudo
  4. // @description Dragging any image allows you to do a TinEye image search.
  5. // @include *
  6. // @exclude *www.google.*/imghp*
  7. // @exclude *www.google.*/search?*site=imghp&*
  8. // @exclude *www.google.*/search?tbs=sbi:*
  9. // @grant none
  10. // @version 1.00
  11. // ==/UserScript==
  12.  
  13. if (!document || !document.body || top !== self) return;
  14.  
  15. /*=============*\
  16. |* CONSTANTS *|
  17. \*=============*/
  18. var CONSTANT = {
  19. incorrectTimeout: 2000, //Milliseconds
  20. };
  21.  
  22. var EL = {
  23. body: document.body,
  24. head: document.getElementsByTagName('head')[0],
  25. zone: null, //Set later
  26. form: null, //Set later
  27. message: null, //Set later
  28. };
  29.  
  30. var VAR = {
  31. dragImgSrc: null, //String
  32. dontHide: false, //Bool
  33. draggedOver: false, //Bool
  34. };
  35.  
  36. var MESSAGE = {
  37. drop: "Drop image here!",
  38. incorrect: "This is not a valid image.",
  39. oldBrowser: "You browser is too old and cannot use FileReader HTML5 API, please uninstall this userscript",
  40. };
  41.  
  42. var URL = {
  43. imageSearch: "https://www.tineye.com/search?url=",
  44. formSearch: "https://www.tineye.com/search",
  45. };
  46.  
  47. /*=============*\
  48. |* CHECKS *|
  49. \*=============*/
  50. if(!window.FileReader) {
  51. alert(MESSAGE.oldBrowser);
  52. return;
  53. }
  54.  
  55. /*=============*\
  56. |* FUNCTIONS *|
  57. \*=============*/
  58. function getId(id) {
  59. return document.getElementById(id);
  60. }
  61.  
  62. function createEl(elementName, id /*optional*/, attrArr /*optional*/) {
  63. var el = document.createElement(elementName);
  64. if (id) {
  65. el.id = id;
  66. }
  67. if (attrArr) {
  68. try{
  69. for (var attr in attrArr) {
  70. el.setAttribute(attr, attrArr[attr]);
  71. }
  72. }catch(e){alert("Attributes are set wrong: "+e);}
  73. }
  74. return el;
  75. }
  76.  
  77. function fileNameFromFileUrl (url) {
  78. var index = url.lastIndexOf("/");
  79. if (index == -1) {return url;}
  80. return url.substr(index + 1);
  81. }
  82.  
  83. function fixDataUrl(dataURL) {
  84. return dataURL.substr(dataURL.indexOf(",") + 1)
  85. .replace(/\//gm, "_").replace(/\+/gm, "-");
  86. }
  87.  
  88.  
  89. /*=============*\
  90. |* HTML *|
  91. \*=============*/
  92. function addDropZone() {
  93. EL.zone = createEl("div", "userscripts-dropzone");
  94. EL.body.appendChild(EL.zone);
  95. EL.message = createEl("div", "userscripts-dropzone-message");
  96. EL.zone.appendChild(EL.message);
  97. attachDragEvents(false);
  98. }
  99.  
  100. /*=============*\
  101. |* CSS *|
  102. \*=============*/
  103. (function(){
  104. var CSS = {
  105. "#userscripts-dropzone" : {
  106. "margin" : "0",
  107. "height" : "50px",
  108. "width" : "100%",
  109. "-webkit-user-select" : "none",
  110. "-moz-user-select" : "none",
  111. "user-select" : "none",
  112. "position" : "fixed",
  113. "top" : "-140px",
  114. "left" : "0px",
  115. "background" : "#f0f0f0",
  116. "box-shadow" : "0 0px 10px rgba(0,0,0,0.8)",
  117. "box-sizing" : "border-box",
  118. "-webkit-box-sizing" : "border-box",
  119. "-moz-box-sizing" : "border-box",
  120. "z-index" : "10000000",
  121. "-moz-transition-property" : "top",
  122. "-moz-transition-duration" : "0.2s",
  123. "-moz-transition-timing-function" : "ease-out",
  124. "-webkit-transition-property" : "top",
  125. "-webkit-transition-duration" : "0.2s",
  126. "-webkit-transition-timing-function" : "ease-out",
  127. "transition-property" : "top",
  128. "transition-duration" : "0.2s",
  129. "transition-timing-function" : "ease-out",
  130. },
  131. "#userscripts-dropzone.show" : {
  132. "top" : "0px",
  133. },
  134. "#userscripts-dropzone-message": {
  135. "text-align" : "center",
  136. "font-size" : "18px !important",
  137. "font-weight" : "bold !important",
  138. "font-family" : "Arial, san-serif !important",
  139. "color" : "black !important",
  140. "padding" : "15px",
  141. },
  142. },
  143. cssString = "",
  144. propString = "",
  145. eachSelector = "",
  146. style = createEl("style");
  147. for(var selector in CSS) {
  148. eachSelector = CSS[selector];
  149. propString = "";
  150. for(var property in eachSelector) {
  151. propString += property + ":" + eachSelector[property] + ";";
  152. }
  153. cssString += selector + "{" + propString + "}";
  154. }
  155. style.appendChild(document.createTextNode(cssString));
  156. EL.head.appendChild(style);
  157. })();
  158.  
  159. /*=============*\
  160. |* FUNCTIONS *|
  161. \*=============*/
  162.  
  163. function openSearchUrl(url) {
  164. var fileName = fileNameFromFileUrl(url);
  165. // Check if real file
  166. if (fileName.indexOf(".") === -1) {
  167. displayIncorrectFile();
  168. return;
  169. }
  170. var tehUrl = URL.imageSearch + escape(url);
  171. window.open(tehUrl, "_blank");
  172. hide();
  173. }
  174.  
  175. function displayIncorrectFile() {
  176. VAR.dontHide = true;
  177. EL.message.innerHTML = MESSAGE.incorrect;
  178. setTimeout(function(){
  179. VAR.dontHide = false;
  180. hide();
  181. }, CONSTANT.incorrectTimeout);
  182. }
  183.  
  184. function processDrop(event) {
  185. try{
  186. var dt = event.dataTransfer,
  187. link = dt.getData("Text"),
  188. imgUrl = VAR.dragImgSrc,
  189. files = dt.files,
  190. file = null,
  191. i = 0;
  192. if (imgUrl != null) {
  193. clearImageSource();
  194. openSearchUrl(imgUrl);
  195. } else if (link != "") {
  196. console.log(link)
  197. openSearchUrl(link);
  198. } else if (files.length > 0) {
  199. for (; i < files.length; i++) {
  200. file = files[i];
  201. var reader = new FileReader();
  202. reader.file = file;
  203. reader.addEventListener("loadend", processFile, false);
  204. try {
  205. reader.readAsDataURL(file);
  206. }catch(error) {
  207. displayIncorrectFile();
  208. if (console && console.log) {
  209. console.log(error);
  210. }
  211. }
  212. }
  213. } else {
  214. displayIncorrectFile();
  215. if (console && console.log) {
  216. console.log("Not an image",event);
  217. }
  218. }
  219. stopBrowser(event);
  220. }catch(e){alert(e)}
  221. }
  222.  
  223. function processFile(event) {
  224. event.currentTarget.removeEventListener('loadend', processFile, false);
  225. if (this.result == "") {
  226. displayIncorrectFile();
  227. return;
  228. }
  229. var dataUrl = fixDataUrl(this.result),
  230. fileName = this.file.name;
  231. setImageForm(dataUrl, fileName);
  232. EL.form.submit();
  233. hide();
  234. this.file = null;
  235. setImageForm("", "");
  236. // Fixes Chrome's form searching
  237. var counter = parseInt(EL.form.getAttribute('counter')) + 1;
  238. EL.form.setAttribute('counter', counter);
  239. EL.form.action = EL.form.getAttribute('origAction') + counter;
  240. }
  241.  
  242. function setImageForm(dataUrl, fileName) {
  243. if (EL.form) {
  244. getId('userscripts-form-data-url').setAttribute('value', dataUrl);
  245. getId('userscripts-form-filename').setAttribute('value', fileName);
  246. return;
  247. }
  248. EL.form = createEl("form", "userscripts-form-image-search", {
  249. enctype: 'multipart/form-data',
  250. method: 'POST',
  251. target: '_blank',
  252. action: (URL.formSearch + '?d=0'),
  253. origAction: (URL.formSearch + '?d'),
  254. counter: 0,
  255. });
  256. var field1 = createEl("input", 'userscripts-form-data-url', {
  257. type: 'hidden',
  258. name: 'image',
  259. value: dataUrl
  260. }),
  261. field2 = createEl("input", null, {
  262. type: 'hidden',
  263. name: 'btnG',
  264. value: 'Search'
  265. }),
  266. field3 = createEl("input", 'userscripts-form-filename', {
  267. type: 'hidden',
  268. name: 'filename',
  269. value: fileName
  270. }),
  271. field4 = createEl("input", null, {
  272. type: 'hidden',
  273. name: 'hl',
  274. value: 'en'
  275. });
  276. EL.form.appendChild(field1);
  277. EL.form.appendChild(field2);
  278. EL.form.appendChild(field3);
  279. EL.form.appendChild(field4);
  280. EL.zone.appendChild(EL.form);
  281. }
  282.  
  283. /*=============*\
  284. |* EVENTS *|
  285. \*=============*/
  286.  
  287. function detachDragEvents() {
  288. document.removeEventListener("dragstart", processDragStart, false);
  289. document.removeEventListener("dragenter", processDragEnter, false);
  290. document.addEventListener("dragend", clearImageSource, false);
  291. document.addEventListener("mouseover", mouseMove, false);
  292. EL.zone.addEventListener("dragover", dragOverZone, false);
  293. EL.zone.addEventListener("dragleave", dragOutZone, false);
  294. EL.zone.addEventListener("drop", processDrop, false);
  295. }
  296.  
  297. function attachDragEvents(shouldRemoveEvents) {
  298. document.addEventListener("dragenter", processDragEnter, false);
  299. document.addEventListener("dragstart", processDragStart, false);
  300. if (!shouldRemoveEvents) {
  301. document.removeEventListener("dragend", clearImageSource, false);
  302. document.removeEventListener("mouseover", mouseMove, false);
  303. EL.zone.removeEventListener("dragover", dragOverZone, false);
  304. EL.zone.removeEventListener("dragleave", dragOutZone, false);
  305. EL.zone.removeEventListener("drop", processDrop, false);
  306. }
  307. }
  308. function stopBrowser(evt) {
  309. evt.stopPropagation();
  310. evt.preventDefault();
  311. }
  312.  
  313. function dragOverZone(event){
  314. VAR.draggedOver = true;
  315. stopBrowser(event);
  316. }
  317.  
  318. function dragOutZone(event){
  319. VAR.draggedOver = false;
  320. stopBrowser(event);
  321. }
  322.  
  323. function mouseMove(e) {
  324. if (VAR.draggedOver) {
  325. return;
  326. }
  327. if (EL.zone.className === "show") {
  328. hide();
  329. } else {
  330. attachDragEvents();
  331. }
  332. }
  333.  
  334. function processDragStart(event) {
  335. var el = event.target;
  336. if (el.tagName === "IMG") {
  337. VAR.dragImgSrc = el.src;
  338. } else {
  339. var imgs = el.getElementsByTagName('img');
  340. if (imgs.length > 0) {
  341. VAR.dragImgSrc = imgs[0].src;
  342. } else {
  343. if (el.tagName !== "A" || el.getAttribute("href") == "") {
  344. detachDragEvents();
  345. return;
  346. }
  347. }
  348. }
  349. show();
  350. }
  351.  
  352. function processDragEnter(event) {
  353. if (VAR.dragImgSrc != null || event.dataTransfer.getData('Text') == "") {
  354. show();
  355. } else {
  356. detachDragEvents();
  357. }
  358. }
  359.  
  360. /*=============*\
  361. |* MISC *|
  362. \*=============*/
  363. function clearImageSource(event) {
  364. VAR.dragImgSrc = null;
  365. hide();
  366. }
  367.  
  368. function show() {
  369. if (EL.zone.className === "show") {
  370. return;
  371. }
  372. EL.message.innerHTML = MESSAGE.drop;
  373. detachDragEvents();
  374. EL.zone.className = "show";
  375. }
  376.  
  377. function hide() {
  378. if (EL.zone.className === "") {
  379. return;
  380. }
  381. attachDragEvents();
  382. if (VAR.dontHide) {
  383. return;
  384. }
  385. VAR.draggedOver = false;
  386. EL.zone.className = "";
  387. }
  388.  
  389. /*=============*\
  390. |* START *|
  391. \*=============*/
  392. addDropZone();