Toggle Zoom

Extend image zoom modes with scale-to-width and scale-to-height of window

  1. // ==UserScript==
  2. // @name Toggle Zoom
  3. // @namespace Nickel
  4. // @description Extend image zoom modes with scale-to-width and scale-to-height of window
  5. // @version 0.5
  6. // @license GNU General Public License v3
  7. // @copyright 2022, Nickel
  8. // @author Nickel
  9. // @grant none
  10. // @run-at document-start
  11. // @noframes
  12. // @include *
  13. // ==/UserScript==
  14.  
  15.  
  16. (function(){
  17.  
  18. function unscaled() {
  19. img.removeAttribute( "width" );
  20. img.removeAttribute( "height" );
  21. mode = "unscaled";
  22. document.title = titleBase;
  23. }
  24. function scaleToWidth() {
  25. img.removeAttribute( "height" );
  26. img.width = document.documentElement.clientWidth;
  27. // do it again due to scrollbars that may have (dis)appeared
  28. img.width = document.documentElement.clientWidth;
  29. mode = "scaleToWidth";
  30. document.title = titleBase + " — " + mode + " (" + (100*img.width/img.naturalWidth).toFixed(0) + "%)";
  31. }
  32. function scaleToHeight() {
  33. img.removeAttribute( "width" );
  34. img.height = document.documentElement.clientHeight;
  35. // do it again due to scrollbars that may have (dis)appeared
  36. img.height = document.documentElement.clientHeight;
  37. mode = "scaleToHeight";
  38. document.title = titleBase + " — " + mode + " (" + (100*img.width/img.naturalWidth).toFixed(0) + "%)";
  39. }
  40.  
  41. function toggle() {
  42. if( (img.naturalWidth / img.naturalHeight) > (document.documentElement.clientWidth / document.documentElement.clientHeight) ) {
  43. if( mode == "unscaled" ) {
  44. scaleToHeight();
  45. // next is scaleToWidth
  46. img.style.cursor = "zoom-out";
  47. }
  48. else if( mode == "scaleToHeight" || mode == "doScaleToFit" ) {
  49. scaleToWidth();
  50. // next is unscaled
  51. if( img.naturalWidth > document.documentElement.clientWidth ) img.style.cursor = "zoom-in";
  52. else img.style.cursor = "zoom-out";
  53. }
  54. else {
  55. unscaled();
  56. // next is scaleToHeight
  57. img.style.cursor = "zoom-in";
  58. }
  59. }
  60. else {
  61. if( mode == "unscaled" ) {
  62. scaleToWidth();
  63. // next is scaleToHeight
  64. img.style.cursor = "zoom-out";
  65. }
  66. else if( mode == "scaleToWidth" || mode == "doScaleToFit" ) {
  67. scaleToHeight();
  68.  
  69. // next is unscaled
  70. if( img.naturalHeight > document.documentElement.clientHeight ) img.style.cursor = "zoom-in";
  71. else img.style.cursor = "zoom-out";
  72. }
  73. else {
  74. unscaled();
  75. // next is scaleToWidth
  76. img.style.cursor = "zoom-in";
  77. }
  78. }
  79. }
  80.  
  81. function initialize() {
  82. if( initialized == true ) return;
  83. initialized = true;
  84.  
  85. // Firefox does some weird shit
  86. img.style.marginTop = "0";
  87.  
  88. titleBase = document.title.replace( / — Scaled.*$/, "" );
  89.  
  90. // set initial mode by setting do* and toggling
  91. if( (img.naturalWidth > document.documentElement.clientWidth) || (img.naturalHeight > document.documentElement.clientHeight) ) mode = "doScaleToFit";
  92. else mode = "doUnscaled";
  93. toggle();
  94.  
  95. // add new left mouse button event listener
  96. // NOTE: would prefer to put listener on `img` instead of `document` to not react to clicks on blank space
  97. document.addEventListener( "click", function(e) {
  98. if( e.button === 0 ) {
  99. e.stopPropagation();
  100. toggle();
  101. }
  102. }, true );
  103. }
  104.  
  105. var initialized = false;
  106. var img = document.images[0];
  107. if( typeof img === 'undefined' ) return;
  108. if( img.src != window.location.href ) return;
  109.  
  110. // get image metadata as early as possible
  111. wait = setInterval( function() {
  112. if( img.naturalWidth !== 0 && img.naturalHeight !== 0 && document.title !== "" ) {
  113. clearInterval(wait);
  114. initialize();
  115. }
  116. }, 10 );
  117. // also try initializing when image finishes loading
  118. img.onload = initialize;
  119.  
  120. })();