/* 
 * ScrollSaver.js
 *
 * Allows the user to submit a page and return to the same scroll position
 * as before. Saves scroll position of document and scrollable areas, which 
 * have registered themselves to be saved.
 *
 * Elements register in the following way:
 *   scrollSaveElementIds.push("elementId");
 * 
 * To restore the coordinates, call
 *   restoreScrollCoordinates();
 * 
 * Set a page name with
 *   scrollPageName = "myScrollPage";
 * to allow the cookie identify the page.
 * 
 * @author Karri-Pekka Laakso, karri@reaktor.fi
 */

var scrollCookieName = "scrollCookie"; 
var scrollPageName = "scrolledPage";
var scrollSaveElementIds = new Array();
var timeoutId;

// Save the scroll coordinates in a cookie 
function saveScrollCoordinates() {
  if (timeoutId != undefined) {
    window.clearTimeout(timeoutId);
  }
  
  var docXY = getDocumentScroll();
  var cookie = new ScrollCookie(scrollCookieName, scrollPageName, docXY[0], docXY[1]);
    
  for (var i=0; i<scrollSaveElementIds.length; i++) {
    saveElementScroll(scrollSaveElementIds[i], cookie);
  }

  // Save the thing
  cookie.write();
  
  timeoutId = window.setTimeout("saveScrollCoordinates()", 100);
}


function restoreScrollCoordinates() {
  if (timeoutId != undefined) {
    window.clearTimeout(timeoutId);
  }
  
  var cookie = new ScrollCookie(scrollCookieName);
  cookie.read();

  if (cookie.page.id != scrollPageName) {
    deleteCookie(scrollCookieName);
  }
  else {
    setDocumentScroll(cookie.page.x, cookie.page.y);
    
    for (var i=0; i<cookie.savedElements.length; i++) {
      var settings = cookie.savedElements[i];
      restoreElementScroll(settings.id, settings.x, settings.y);
    }
  }
  
  timeoutId = window.setTimeout("saveScrollCoordinates()", 100);
}


function getDocumentScroll() {
  var x, y;
  
  if (self.pageYOffset) {
    // all except Explorer
  	x = self.pageXOffset;
  	y = self.pageYOffset;
  }
  else if (document.documentElement && document.documentElement.scrollTop) {
  	// Explorer 6 Strict
  	x = document.documentElement.scrollLeft;
  	y = document.documentElement.scrollTop;
  }
  else if (document.body) {
    // all other Explorers
  	x = document.body.scrollLeft;
  	y = document.body.scrollTop;
  }  

  // alert("Doc: x=" + x + ", y=" + y);
  return new Array(x,y);
}     


function setDocumentScroll(x, y) {
  window.scrollTo(x, y);
}


function saveElementScroll(elemId, cookie) {
  var element = document.getElementById(elemId); 
  if (element == null) {
    return; 
  }
  
  var x = element.scrollLeft;
  var	y = element.scrollTop;

  cookie.addElement(elemId, x, y);
  // alert((new SavedElement(elemId, x, y)).toString());
}


function restoreElementScroll(elemId, x, y) {
  var element = document.getElementById(elemId); 
  if (element == null) {
    return; 
  }
  
  element.scrollLeft = x;
  element.scrollTop = y;
}


//
// Class ScrollCookie
//
function ScrollCookie(name, page, x, y) {
  this.name = name;
  this.page = new SavedElement(page, x, y);
  this.savedElements = new Array();
}

ScrollCookie.prototype.addElement = function(id, x, y) {
  this.savedElements.push(new SavedElement(id, x, y));
}

ScrollCookie.prototype.write = function() {
  var cookieText = this.page.toString();
  
  for (var i=0; i<this.savedElements.length; i++) {
    cookieText += ";" + this.savedElements[i].toString();  
  }
  
  setCookie(this.name, cookieText);
  return cookieText;
}

ScrollCookie.prototype.read = function() {
  var cookieText = getCookie(this.name);
  if (cookieText == null) {
    return;
  }
  
  var elems = cookieText.split(";");
  this.page.fromString(elems.shift());
  
  for (var i=0; i<elems.length; i++) {
    var element = new SavedElement();
    element.fromString(elems[i]);
    this.savedElements.push(element);
  }
}

//
// Class SavedElement
//
function SavedElement(newId, newX, newY) {
  this.id = newId;
  this.x = newX;
  this.y = newY;
}

SavedElement.prototype.toString = function () {
  return this.id + "(" + this.x + "," + this.y + ")";
}

SavedElement.prototype.fromString = function(str) {
  // Ensure that we have some kind of a string
  if (arguments.length != 1 || str == null || str == undefined) {
    return;
  }
  str = ""+str;

  var res = str.match(/^([^(]+)\((\d+),(\d+)\)$/);
  if (res == null) {
    this.id = this.x = this.y = undefined;
  } else {
    this.id = RegExp.$1;
    this.x = parseInt(RegExp.$2);
    this.y = parseInt(RegExp.$3);
  }
}



// ----- Borrowed -----


/**
 * Sets a Cookie with the given name and value.
 *
 * name       Name of the cookie
 * value      Value of the cookie
 * [expires]  Expiration date of the cookie (default: end of current session)
 * [path]     Path where the cookie is valid (default: path of calling document)
 * [domain]   Domain where the cookie is valid
 *              (default: domain of calling document)
 * [secure]   Boolean value indicating if the cookie transmission requires a
 *              secure transmission
 */
function setCookie(name, value, expires, path, domain, secure)
{
    /* This is a hack to get scrollsaver work on Uutiset page */
    path = "/";  

    document.cookie= name + "=" + escape(value) +
        ((expires) ? "; expires=" + expires.toGMTString() : "") +
        ((path) ? "; path=" + path : "") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");
}

/**
 * Gets the value of the specified cookie.
 *
 * name  Name of the desired cookie.
 *
 * Returns a string containing value of specified cookie,
 *   or null if cookie does not exist.
 */
function getCookie(name)
{
    var dc = document.cookie;
    var prefix = name + "=";
    var begin = dc.indexOf("; " + prefix);
    if (begin == -1)
    {
        begin = dc.indexOf(prefix);
        if (begin != 0) return null;
    }
    else
    {
        begin += 2;
    }
    var end = document.cookie.indexOf(";", begin);
    if (end == -1)
    {
        end = dc.length;
    }
    return unescape(dc.substring(begin + prefix.length, end));
}

/**
 * Deletes the specified cookie.
 *
 * name      name of the cookie
 * [path]    path of the cookie (must be same as path used to create cookie)
 * [domain]  domain of the cookie (must be same as domain used to create cookie)
 */
function deleteCookie(name, path, domain)
{
    if (getCookie(name))
    {
        /* This is a hack to get scrollsaver work on Uutiset page */
        path = "/";

	document.cookie = name + "=" + 
            ((path) ? "; path=" + path : "") +
            ((domain) ? "; domain=" + domain : "") +
            "; expires=Thu, 01-Jan-70 00:00:01 GMT";
    }
}
