Drag to Resize Image

Click and Drag to resize images. Ctrl+Click to disable resizing. Right Click to restore image to original size. Based on code in Reddit Enhancement Suite.

  1. // ==UserScript==
  2. // @name Drag to Resize Image
  3. // @namespace
  4. // @description Click and Drag to resize images. Ctrl+Click to disable resizing. Right Click to restore image to original size. Based on code in Reddit Enhancement Suite.
  5. // @author Kabaka, MajorVictory87
  6. // @require https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js
  7. // @include *
  8. // @version 1.3
  9. // ==/UserScript==
  10.  
  11. /*
  12. * Drag to Resize - Drag images to resize them no matter where you are.
  13. *
  14. * The image resizing code was extracted from honestbleeps's
  15. * (steve@honestbleeps.com) Reddit Enhancement Suite, a GPL
  16. * Greasemonkey script. The idea was, as far as I know, all his. What
  17. * I've done is duplicated that feature in this script and started
  18. * adding on things to make it useful in different contexts.
  19. *
  20. * Because it now runs everywhere, it will likely break some web
  21. * sites. And it definitely opens up doors for some silliness such as
  22. * making images hilariously gigantic. If this script causes you to
  23. * lose data, money, or time, don't hold me responsible!
  24. *
  25. *
  26. * Instructions:
  27. *
  28. * To resize an image, hold the left mouse button and drag. Down and to the
  29. * right will expand. Up and to the left will shrink. Images aligned to the
  30. * right will expand in an unusual way. Sorry.
  31. *
  32. * To reset an image to original size, right-click it.
  33. *
  34. * To drag an image without resizing (as if the script were not installed),
  35. * hold control (or command on Mac) and drag.
  36. *
  37. *
  38. *
  39. * This program is free software: you can redistribute it and/or modify
  40. * it under the terms of the GNU General Public License as published by
  41. * the Free Software Foundation, either version 3 of the License, or
  42. * (at your option) any later version.
  43. *
  44. * This program is distributed in the hope that it will be useful,
  45. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  46. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  47. * GNU General Public License for more details.
  48. *
  49. * You should have received a copy of the GNU General Public License
  50. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  51. */
  52.  
  53. var imageData = Array();
  54.  
  55. /*
  56. * Find all img elements on the page and feed them to makeImageZoomable().
  57. * Also, record the image's original width in imageData[] in case the user
  58. * wants to restore size later.
  59. */
  60. function findAllImages()
  61. {
  62. var imgs = document.getElementsByTagName('img');
  63.  
  64. for (i=0; i<imgs.length; i++)
  65. {
  66.  
  67. // We will populate this as the user interacts with the image, if they
  68. // do at all.
  69. imageData[imgs[i]] = {
  70. zindex: imgs[i].style.zIndex,
  71. width: imgs[i].style.width,
  72. height: imgs[i].style.height,
  73. position: imgs[i].style.position,
  74. resized: 0,
  75. resizable: true
  76. };
  77.  
  78. makeImageZoomable(imgs[i]);
  79. }
  80.  
  81. }
  82.  
  83. /*
  84. * Calculate the drag size for the event. This is taken directly from
  85. * honestbleeps's Reddit Enhancement Suite.
  86. *
  87. * @param e mousedown or mousemove event.
  88. * @return Size for image resizing.
  89. */
  90. function getDragSize(e)
  91. {
  92. return (p = Math.pow)(p(e.clientX - (rc = e.target.getBoundingClientRect()).left, 2) + p(e.clientY - rc.top, 2), .5);
  93. }
  94.  
  95. /*
  96. * Get the viewport's vertical size. This should work in most browsers. We'll
  97. * use this when making images fit the screen by height.
  98. *
  99. * @return Viewport size.
  100. */
  101. function getHeight() {
  102. return window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight;
  103. }
  104.  
  105. /*
  106. * Set up events for the given img element to make it zoomable via
  107. * drag to zoom. Most of this is taken directly from honestbleeps's
  108. * Reddit Enhancement Suite. Event functions are currently written
  109. * inline. For readability, I may move them. But the code is small
  110. * enough that I don't yet care.
  111. *
  112. * @param imgTag Image element.
  113. */
  114. function makeImageZoomable(imgTag)
  115. {
  116. DragData = {};
  117.  
  118. imgTag.addEventListener('mousedown', function(e)
  119. {
  120. if(e.ctrlKey != 0)
  121. return true;
  122.  
  123. /*
  124. * This is so we can support the command key on Mac. The combination of OS
  125. * and browser changes how the key is passed to JavaScript. So we're just
  126. * going to catch all of them. This means we'll also be catching meta keys
  127. * for other systems. Oh well! Patches are welcome.
  128. */
  129. if(e.metaKey != null) // Can be on some platforms
  130. if(e.metaKey != 0)
  131. return true;
  132.  
  133.  
  134. if(e.button == 0) {
  135. DragData.width = e.target.width;
  136. DragData.delta = getDragSize(e);
  137. DragData.dragging = true;
  138.  
  139. e.preventDefault();
  140. }
  141.  
  142. }, true);
  143.  
  144. imgTag.addEventListener('contextmenu', function(e){
  145. if(imageData[e.target].resized != 0) {
  146. imageData[e.target].resized = 0;
  147. e.target.style.zIndex = imageData[e.target].zIndex;
  148. e.target.style.maxWidth = e.target.style.width = imageData[e.target].width;
  149. e.target.style.maxHeight = e.target.style.height = imageData[e.target].height;
  150. e.target.style.position = imageData[e.target].position;
  151.  
  152. // Prevent the context menu from actually appearing.
  153. e.preventDefault();
  154. e.returnValue = false;
  155. e.stopPropagation();
  156. return false;
  157. }
  158. return true;
  159.  
  160. }, true);
  161. imgTag.addEventListener('mousemove', function(e)
  162. {
  163.  
  164.  
  165. if (DragData.dragging){
  166.  
  167. clingdelta = Math.abs(DragData.delta - getDragSize(e));
  168.  
  169. console.log("Cling [mousemove]: "+clingdelta);
  170.  
  171. if (clingdelta > 5) {
  172.  
  173. var prevwidth = parseInt(e.target.style.width.replace('px', ''));
  174.  
  175. e.target.style.maxWidth = e.target.style.width = Math.floor(((getDragSize(e)) * DragData.width / DragData.delta)) + "px";
  176. e.target.style.maxHeight = '';
  177. e.target.style.height = 'auto';
  178. e.target.style.zIndex = 1000; // Make sure the image is on top.
  179.  
  180. if(e.target.style.position == '') {
  181. e.target.style.position = 'relative';
  182. }
  183.  
  184. imageData[e.target].resized = (prevwidth - parseInt(e.target.style.width.replace('px', '')));
  185. }
  186. }
  187. }, false);
  188.  
  189. imgTag.addEventListener('mouseout', function(e) {
  190.  
  191. if (DragData.dragging) {
  192. DragData.dragging = false;
  193. e.preventDefault();
  194. return false;
  195. }
  196.  
  197. return true;
  198.  
  199. }, true);
  200.  
  201. imgTag.addEventListener('mouseup', function(e) {
  202.  
  203. if (DragData.dragging) {
  204. DragData.dragging = false;
  205. e.preventDefault();
  206. return false;
  207. }
  208.  
  209. return true;
  210.  
  211. }, true);
  212.  
  213. imgTag.addEventListener('click', function(e)
  214. {
  215. if(e.ctrlKey != 0)
  216. return true;
  217.  
  218. if(e.metaKey != null && e.metaKey != 0) // Can be on some platforms
  219. return true;
  220.  
  221. console.log("Click [click]: "+e.button);
  222. console.log("Resize [click]: "+imageData[e.target].resized);
  223.  
  224. if (!isNaN(imageData[e.target].resized) && imageData[e.target].resized != 0) {
  225. e.preventDefault();
  226. return false;
  227. }
  228.  
  229. return true;
  230. }, true);
  231.  
  232. }
  233.  
  234. findAllImages();
  235. document.addEventListener('dragstart', function() {return false}, false);