The Tiny Scrolling(s)

hash.jpgFirst published on March 25, 2006 and March 31, 2006
Start with an example is the better way to begin a javascript technique post: click one of the links above to see straight away - in two meanings - what i’m going to talk about.

What is Tiny Scrolling?

Tiny Scrolling is a small script dedicated to support the navigation between the internal links and their destinations.
It replace that annoying and confusing jump from various part of a page with a smooth scroll of the page itself. The user will never say: “Ehi, but where am I now?” but “Oh, thanks for accompany me there!”

Top

How can I use it?

An internal link is an anchor that refers to a fragment identifier, so to a part of the document inserted in an element with a particular “id” attribute.
For example, every title of this post is inserted in an heading with attribute “id” and has one (o more) anchors that links to it: the anchor <a href="#what">What is...</a> refers to the element <h3 id="#what">...</> The <h3> could be replaced by a <div>, a <p>, a <span> or one of the other elements.
To add the smooth scrolling effect you don’t need to modify any of the tag below: following the unobtruvise js first rule the only thing that you could do is to insert in the head of your HTML document a line like this:
<script type="text/javascript" src="tinyscrolling.js"></script>
The places for ideal use of this script are long documents subdivided in titled paragraphes (like this page already linked), or simply the footers containing links that “back to top” of the site.

Top

How does it works?

The functioning is simple: using three principal function it searches the links inside the page with an “#” inside, look at the destination calculating its position, and “scrollTo” it.
(Here start the annoying section: go forward until you are in time!)
The first function searches all the links in the page, selects those with the hash “#” inside, controls for the pathname and the querystring, and attaches an onclick event handler:

init: function() {
  var lnks = document.getElementsByTagName('a');
  for(var i = 0, lnk; lnk = lnks[i]; i++) {
   if ((lnk.href && lnk.href.indexOf('#') != -1) &&  ( (lnk.pathname == location.pathname) ||
     ('/'+lnk.pathname == location.pathname) ) && (lnk.search == location.search)) {
   lnk.onclick = tinyScrolling.initScroll;
 }
 }
 },

This is the second function, that: 1)prepares to read informations about the event; 2)extract the string after the “#”; 3) set a variable related to the element that has as “id” the string itself; 4)searches the relative position of that element in the document.

initScroll: function(e){
  var targ;
  if (!e) var e = window.event;
  if (e.target) targ = e.target;
  else if (e.srcElement) targ = e.srcElement;
  tinyScrolling.hash = targ.href.substr(targ.href.indexOf('#')+1,targ.href.length);
  tinyScrolling.currentBlock = document.getElementById(tinyScrolling.hash);
  if(!tinyScrolling.currentBlock) return;
  tinyScrolling.requestedY = tinyScrolling.getElementYpos(tinyScrolling.currentBlock);
  tinyScrolling.scroll();
  return false;
  },

The third and last principal function is more complicated. First sets a variable (”top”) with the position of scroll bar from the top of the window, then control If the relative position of the searched element (”requestedY”) is greater than this variable value: if yes, it means that the page must to scroll down.
The “offset” is the distance that the scroll bar must to cover, and is calculated using two important variables: “endDistance” and “maxStep”. The first is obtained using the document and the window height; this is interesting for the anchors that refers to a part of the document at the bottom of the page, where sometimes the height of this part is less than the height of the window so the scroll bar can’t positioning the top of this part at the top of the window, as happens with the other parts of a document.
The second “endDistance”, instead, refers to a simply distance from the position of scroll bar to the requested element. The variable “maxStep” is used from long pages: for a certain distance the scroll bar has a uniform motion, and slow down when is arriving to the destination, while brakeK is an abitrary “coefficient of slowing down”.
If “requestedY” is less than the top, the page must to scroll up: there isn’t the problem with the height of page so the offset is calculated in one step. The shift will be execute by the function “scrollTo”, and the last lines stop this motion if the distance has been covered. If that’s not, there’s a recursive call to the same function that starts from the begin.


scroll: function(){
  var top  = tinyScrolling.getScrollTop();
  tinyScrolling.lastY = top;
  if(tinyScrolling.requestedY > top) {
  var endDistance = Math.round((tinyScrolling.getDocumentHeight() - (top + tinyScrolling.getWindowHeight())) / tinyScrolling.brakeK);
  endDistance = Math.min(Math.round((tinyScrolling.requestedY-top)/ tinyScrolling.brakeK), endDistance);
  var offset = Math.max(2, Math.min(endDistance, tinyScrolling.maxStep));
  } else { var offset = - Math.min(Math.abs(Math.round((tinyScrolling.requestedY-top)/ tinyScrolling.brakeK)), tinyScrolling.maxStep);
  } window.scrollTo(0, top + offset);
  if(Math.abs(top-tinyScrolling.requestedY) < = 1 || tinyScrolling.getScrollTop() == top) {
  tinyScrolling.lastY = -1;
  window.scrollTo(0, tinyScrolling.requestedY);
  if(!document.all) location.hash = tinyScrolling.hash;
  tinyScrolling.hash = null;
  } else 	setTimeout(tinyScrolling.scroll,tinyScrolling.speed);
  }	

Top

Where I can download it?

Here. You can download the standalone javascript or a .zip with a example html page inside.

Another online example is located here.

Top

Someone to thanks?

Tiny Scrolling is an optimization of two previous “smooth scrolling” techniques played by Travis Beckham and Brian McAllister.
A very big thanks to my magister Skid X for the fix of two relevant bugs.
Thanks also toTakeshi Takatsudo for a jQuery version of the script.
You can find other interesting “smooth scrolling” solutions in the scripts by Stuart Landgridge, Dave Lindquist and Valerio Proietti.

Top

The Horizontal Tiny Scrolling

Some time ago, in a italian post called “Who is afraid of the horizontal scrolling?“, I started to be interesting in an unusual layout that “force” to scroll a page from left to right (a bit magazine-like) instead of from top to bottom as in the classic mode.
To avoid to move the bottom scrollbar with mouse every time, I thinked to modify the Tiny Scrolling to help this particular motion using equally internal links.
I called this version “Horizontal Tiny Scrolling”, a name decided after six hours of dramatic brainstorming.
I will not bore you as in the previous post, only because the working of the ’smooth scrolling’ is pretty the same: the script searches for an internal link (with a ‘#’ inside), control the position of the respective element and make a scroll to this at a variable speed, replacing the usual confusing direct jump.
This time naturally the motion will be from left to right, and back.
As you can see in the online example, building a “standard” horizontal layout I placed the paragraphs side by side, applying the float property; at the click of one of the internal link, the scroll will stop the requested paragraph at the left extremity of the page.
(it can be add the temporary lighting of the interested element through the Fade Anithing Technique) .
After the different working of the “scrollTo” the functions don’t refers any more to relative Y position and the height of the document or the window, but naturally to X position e widths. (see here)

Update: Thanks to Michael Ionita-Ganea (mizi) for two bug fixes and all the “community” below that tested the scripts :-)

152 comments:

Leave a Reply


Here' s the tag cloud, with the topics of this site:

ajax4 api2 blog2 colours1 css1 google1 graphics1 javascript7 marketing1 php4 svg1 technorati2 web2.01