Next Image/Previous Image [adopted]

Quick scroll to next/previous image on a page with n/p buttons

  1. // ==UserScript==
  2. // @name Next Image/Previous Image [adopted]
  3. // @author arty <me@arty.name>
  4. // @namespace http://arty.name/
  5. // @version 2.1.1
  6. // @description Quick scroll to next/previous image on a page with n/p buttons
  7. // @include *
  8. // ==/UserScript==
  9.  
  10. // This is a minor adaptation of arty's original, by joeytwiddle
  11.  
  12. // 2012/10 - Now sorting positions so out-of-order images do not break the sequence.
  13.  
  14. (function(){
  15. // var forwardButton = 102; // F
  16. // var backwardButton = 114; // R
  17. var forwardButton = 110; // N
  18. var backwardButton = 112; // P
  19. var leeway = 2; // This is needed if you have zoomed out the page. (We might try to set scrollTop to 100, but it will only move to 99.)
  20.  
  21. var positions = [];
  22.  
  23. document.addEventListener('keypress', function(event){
  24. if (event.ctrlKey || event.shiftKey || event.altKey) return;
  25. var code = event.keyCode || event.which;
  26. if (code != backwardButton && code != forwardButton) return;
  27. if (event.target.tagName && event.target.tagName.match(/input|select|textarea/i) || event.target.getAttribute('contenteditable')==="true") return;
  28.  
  29. // We force a rescan of the page's images every time, for dynamic pages.
  30. positions = [];
  31. if (positions.length === 0) {
  32. var selector = 'img' + (document.location.hostname === 'www.dwitter.net' ? ', iframe' : '');
  33. var elements = document.querySelectorAll(selector);
  34. for (var index = 0; index < elements.length; index++) {
  35. var image = elements[index];
  36. if (image.clientWidth * image.clientHeight < 200*200) continue;
  37. var ytop = getYOffset(image);
  38. // Vertically centralise smaller images.
  39. if (image.clientHeight && image.clientHeight < window.innerHeight) {
  40. ytop -= (window.innerHeight - image.clientHeight)/2 | 0;
  41. }
  42. positions.push([index, ytop]);
  43. }
  44. }
  45. positions.sort(function(a,b) {
  46. return a[1] - b[1];
  47. });
  48.  
  49. var scroll = Math.max(document.documentElement.scrollTop, document.body.scrollTop);
  50.  
  51. if (code === forwardButton) {
  52. for (index = 0; index < positions.length; index++) {
  53. if (positions[index][1] <= scroll + leeway) continue;
  54. // Hard to detect which one our browser is using when we are at the top of the document.
  55. // Because Chrome presents documentElement.scrollTop = 0 all the time!
  56. // Likewise Firefox presents document.body.scrollTop = 0 all the time!
  57. // Solution? Just set both of them!
  58. document.body.scrollTop = positions[index][1];
  59. document.documentElement.scrollTop = positions[index][1];
  60. return;
  61. }
  62. } else if (code === backwardButton) {
  63. for (index = positions.length - 1; index >= 0; index--) {
  64. if (positions[index][1] >= scroll - leeway) continue;
  65. document.body.scrollTop = positions[index][1];
  66. document.documentElement.scrollTop = positions[index][1];
  67. return;
  68. }
  69. }
  70.  
  71. }, false);
  72.  
  73. function getYOffset(node) {
  74. for (var offset = 0; node; offset += node.offsetTop, node = node.offsetParent);
  75. return offset;
  76. }
  77. })();