source for sakino.kelbie.scot
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

143 lines
4.5 KiB

7 months ago
  1. /* Smooth scrolling
  2. Changes links that link to other parts of this page to scroll
  3. smoothly to those links rather than jump to them directly, which
  4. can be a little disorienting.
  5. sil, http://www.kryogenix.org/
  6. v1.0 2003-11-11
  7. v1.1 2005-06-16 wrap it up in an object
  8. */
  9. var ss = {
  10. fixAllLinks: function() {
  11. // Get a list of all links in the page
  12. var allLinks = document.getElementsByTagName('a');
  13. // Walk through the list
  14. for (var i=0;i<allLinks.length;i++) {
  15. var lnk = allLinks[i];
  16. if ((lnk.href && lnk.href.indexOf('#') != -1) &&
  17. ( (lnk.pathname == location.pathname) ||
  18. ('/'+lnk.pathname == location.pathname) ) &&
  19. (lnk.search == location.search)) {
  20. // If the link is internal to the page (begins in #)
  21. // then attach the smoothScroll function as an onclick
  22. // event handler
  23. ss.addEvent(lnk,'click',ss.smoothScroll);
  24. }
  25. }
  26. },
  27. smoothScroll: function(e) {
  28. // This is an event handler; get the clicked on element,
  29. // in a cross-browser fashion
  30. if (window.event) {
  31. target = window.event.srcElement;
  32. } else if (e) {
  33. target = e.target;
  34. } else return;
  35. // Make sure that the target is an element, not a text node
  36. // within an element
  37. if (target.nodeName.toLowerCase() != 'a') {
  38. target = target.parentNode;
  39. }
  40. // Paranoia; check this is an A tag
  41. if (target.nodeName.toLowerCase() != 'a') return;
  42. // Find the <a name> tag corresponding to this href
  43. // First strip off the hash (first character)
  44. anchor = target.hash.substr(1);
  45. // Now loop all A tags until we find one with that name
  46. var allLinks = document.getElementsByTagName('a');
  47. var destinationLink = null;
  48. for (var i=0;i<allLinks.length;i++) {
  49. var lnk = allLinks[i];
  50. if (lnk.name && (lnk.name == anchor)) {
  51. destinationLink = lnk;
  52. break;
  53. }
  54. }
  55. // If we didn't find a destination, give up and let the browser do
  56. // its thing
  57. if (!destinationLink) return true;
  58. // Find the destination's position
  59. var destx = destinationLink.offsetLeft;
  60. var desty = destinationLink.offsetTop;
  61. var thisNode = destinationLink;
  62. while (thisNode.offsetParent &&
  63. (thisNode.offsetParent != document.body)) {
  64. thisNode = thisNode.offsetParent;
  65. destx += thisNode.offsetLeft;
  66. desty += thisNode.offsetTop;
  67. }
  68. // Stop any current scrolling
  69. clearInterval(ss.INTERVAL);
  70. cypos = ss.getCurrentYPos();
  71. ss_stepsize = parseInt((desty-cypos)/ss.STEPS);
  72. ss.INTERVAL =
  73. setInterval('ss.scrollWindow('+ss_stepsize+','+desty+',"'+anchor+'")',10);
  74. // And stop the actual click happening
  75. if (window.event) {
  76. window.event.cancelBubble = true;
  77. window.event.returnValue = false;
  78. }
  79. if (e && e.preventDefault && e.stopPropagation) {
  80. e.preventDefault();
  81. e.stopPropagation();
  82. }
  83. },
  84. scrollWindow: function(scramount,dest,anchor) {
  85. wascypos = ss.getCurrentYPos();
  86. isAbove = (wascypos < dest);
  87. window.scrollTo(0,wascypos + scramount);
  88. iscypos = ss.getCurrentYPos();
  89. isAboveNow = (iscypos < dest);
  90. if ((isAbove != isAboveNow) || (wascypos == iscypos)) {
  91. // if we've just scrolled past the destination, or
  92. // we haven't moved from the last scroll (i.e., we're at the
  93. // bottom of the page) then scroll exactly to the link
  94. window.scrollTo(0,dest);
  95. // cancel the repeating timer
  96. clearInterval(ss.INTERVAL);
  97. // and jump to the link directly so the URL's right
  98. location.hash = anchor;
  99. }
  100. },
  101. getCurrentYPos: function() {
  102. if (document.body && document.body.scrollTop)
  103. return document.body.scrollTop;
  104. if (document.documentElement && document.documentElement.scrollTop)
  105. return document.documentElement.scrollTop;
  106. if (window.pageYOffset)
  107. return window.pageYOffset;
  108. return 0;
  109. },
  110. addEvent: function(elm, evType, fn, useCapture) {
  111. // addEvent and removeEvent
  112. // cross-browser event handling for IE5+, NS6 and Mozilla
  113. // By Scott Andrew
  114. if (elm.addEventListener){
  115. elm.addEventListener(evType, fn, useCapture);
  116. return true;
  117. } else if (elm.attachEvent){
  118. var r = elm.attachEvent("on"+evType, fn);
  119. return r;
  120. } else {
  121. alert("Handler could not be removed");
  122. }
  123. }
  124. }
  125. ss.STEPS = 25;
  126. ss.addEvent(window,"load",ss.fixAllLinks);