/*

Persistant HTML Forms


This script provides client-side persistance to html forms.
It relies on cookies. If cookies are disabled, this script
does nothing.

Each form stores its state in a separate cookie. 
The cookie lifetime is configured to be browser session.
Cookies names are prefixed by an application identifier.

This script requires that:
- Every page that uses this script has a unique file name
- PFORMS.init() is called on page load
- Every form and form control on the page has a unique name
- Only text and checkbox form controls are used
- PFORMS.store(this) is called on controls' change events
- Reset buttons call PFORMS.reset(this.form) on reset

*/


//
// Declare namespace 
//
var PFORMS = {};

//
// Application identifier used for cookie name prefix
//
PFORMS.cookiePrefix = "__pforms__";

//
// Messages that may popup on the UI. (Localize!)
//
PFORMS.phrases = ["Really reset?", "Reset done!", "Warning: The data store for this form is full!"];

//
// Persistance duration for cookie storage
//
PFORMS.persistDays = 0; // survive the browser session only

// 
// Associative array (2-dim) to go from control name to index.
//
// Control values are stored ordered, and looked up by index 
// rather than by name to save cookie storage space.
//
PFORMS.forms = {};

//
// The page "nick name" is used to prefix cookie names
//
PFORMS.pageNick = escape(window.location.href.match(/[^\/\\]+$/));

//
// Get cookie name for form
//
PFORMS.getCookieNameForForm = function(frm) {
  return PFORMS.cookiePrefix + PFORMS.pageNick + frm.name;
};

//
// Initialization of persistant forms
//
PFORMS.init = function() {

  //
  // Iterate over all form fields and 
  // initialize with value stored in cookie (if any).
  // 
  var forms = document.forms;

  for(var i=0;i<forms.length;i++) {
    var form = forms[i];
    PFORMS.forms[form.name] = {};
    PFORMS.setupCookieForForm(form);
    var elms = form.elements;
    for(var j=0;j<elms.length;j++) {
      var elm = elms[j];
      PFORMS.forms[form.name][elm.name] = j;
      PFORMS.restore(elm);
    }
  }

};

PFORMS.setupCookieForForm = function(frm) {

  if (!Cookies.available())
    return;

  var cn = PFORMS.getCookieNameForForm(frm);
  if (Cookies.get(cn) == null) {
    var a = new Array(frm.elements.length);
    Cookies.set(cn, a.join("&"))
  }
};


//
// form.onreset event handler
//
// Deletes the cookie associated with a form
//
PFORMS.reset = function(frm) {

  if(confirm(PFORMS.phrases[0])) {
    if (Cookies.available())
      Cookies.erase(PFORMS.getCookieNameForForm(frm));
    return true;
  }
  else {
    return false;
  } 
};


//
// Store value for control
//
PFORMS.store = function(ctl) {

  if (!Cookies.available())
    return;

  var c = Cookies.get(PFORMS.getCookieNameForForm(ctl.form));
  if (c == null) 
    var values = [];
  else 
    var values = c.split("&");
  switch(ctl.type) {
    case "text":
      var val = ctl.value;
      break;
    case "checkbox":
      var val = (ctl.checked ? "1" : "0");
      break;
  }
  var i = PFORMS.forms[ctl.form.name][ctl.name];
  values[i] = typeof(encodeURIComponent) == "undefined" ? escape(val) : encodeURIComponent(val);
  str = values.join("&");
  if(str.length > 4000) { // Cookie max size 4096
    alert(PFORMS.phrases[2]);
    return;
  }
  Cookies.set(PFORMS.getCookieNameForForm(ctl.form), str, PFORMS.persistDays);
};


//
// Restore value for control
//
PFORMS.restore = function(ctl) {

  if (!Cookies.available())
    return;

  var c = Cookies.get(PFORMS.getCookieNameForForm(ctl.form));
  if (c == null) c = "";
  var values = c.split("&");
  var i = PFORMS.forms[ctl.form.name][ctl.name];
  var val = values[i];
  if (val != null)
    var v = typeof(decodeURIComponent) == "undefined" ? unescape(val) : decodeURIComponent(val);
  else
    var v = "";
  switch(ctl.type) {
    case "text":
      ctl.value = v;
      break;
    case "checkbox":
      ctl.checked = (v == "" || v == "0") ? false : true;
      break;
  }
};


//
// Cookies read/write convenience functions
//

var Cookies = {};

Cookies.available = function() {
  if(typeof(navigator.cookieEnabled) != "undefined") {
    return navigator.cookieEnabled;
  }
  else {
    var cn = "__COOKIE_AVAILABILITY_TEST";
    var cv = "ok";
    Cookies.set(cn, "ok");
    return Cookies.get(cn) == cv;
  }
};

Cookies.set = function(name, value, days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime() + (days*24*60*60*1000));
    var expires = "; expires=" + date.toGMTString();
  }
  else
    var expires = "";
  document.cookie = name + "=" + value + expires + "; path=/";
};

Cookies.get = function(name) {
  var nameEQ = name + "=";
  var ca = document.cookie.split(';');
  for (var i=0; i < ca.length; i++) {
    var c = ca[i];
    while(c.charAt(0)==' ') c = c.substring(1,c.length);
    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
  }
  return null;
};

Cookies.erase = function(name) {
  Cookies.set(name, "", -1);
};

Cookies.eraseAll = function() {
  var ca = document.cookie.split(';');
  for (var i=0; i < ca.length; i++) {
    var c = ca[i];
    while(c.charAt(0)==' ') c = c.substring(1,c.length);
    cn = c.split('=')[0];
    Cookies.erase(cn);
  }
};
