/* For discussion and comments, see: http://remysharp.com/2009/01/07/html5-enabling-script/ */
(function(){if(!/*@cc_on!@*/0)return;var e = "abbr,article,aside,audio,canvas,datalist,details,eventsource,figure,footer,header,hgroup,mark,menu,meter,nav,output,progress,section,time,video".split(','),i=e.length;while(i--){document.createElement(e[i])}})()


/**********************************************************
Author:
Adam Barry
eBOUND
www.ebound.dk

Date: December 8 2008

© 2007 Adam Barry, all rights reserved

Inspiration: http://simonwillison.net/2004/May/26/addLoadEvent/
-----------------------------------------------------------

Name:
windowOnLoad script

-----------------------------------------------------------
Description:
Function that enables loading of multiple functions during
window.onload

-----------------------------------------------------------
Usage:
Simply place a link to the this script in the top of the
<head>-section of the XHTML page - before including
additional JavaScript files. The script will then
automatically execute on page load.

Include the addLoadEvent code in the scripts that you wish to have
loaded at the time of page-load according to the example below.

<script type="text/javascript" src="windowOnLoad.js"></script>

-----------------------------------------------------------
Example:
<script type="text/javascript" src="windowOnLoad.js"></script>

function functionToLoad() {
  alert("Execute me on page-load, please");
}

addLoadEvent(function(){functionToLoad();});

-----------------------------------------------------------
Dependencies:
None

**********************************************************/
var onLoadScripts = new Array();

function addLoadEvent(func) {
    var oldonload = window.onload;
    if (typeof window.onload != 'function') {
        window.onload = func;
    } else {
        window.onload = function() {
            if (oldonload) {
                oldonload();
            }
            func();
            onLoadScripts.push(func);
        }
    }
}


/*********************************************************
Name:
reloadOnLoadScripts script

-----------------------------------------------------------
Description:
Function that enables reloading of the functions loaded
onpageload for AJAX environments

-----------------------------------------------------------
Usage:
Execute reloadOnLoadScripts() after a part of the website
that is dependent on the windowOnLoad-scripts has been
refreshed.

reloadOnLoadScripts()

-----------------------------------------------------------
Dependencies:
This script depends on the windowOnLoad-script to execute

**********************************************************/

function reloadOnLoadScripts () {

  for (var i = 0; i < onLoadScripts.length; i++) {
    onLoadScripts[i]();
  }
}


/**********************************************************
Author:
Adam Barry
Klestrup partners
www.klestrup-partners.dk

Date: August 9 2009

© 2009 Adam Barry, all rights reserved
-----------------------------------------------------------

Name:
keyHandler script

-----------------------------------------------------------
Description:
Functions that enables various actions to keyboard events
to various elements, thus making it possible to have
various actions to key events depending on which element
is currently active.

-----------------------------------------------------------
Usage:
Identify the element which you wish to assign a function to.
Create the function that is to be executed.
Assign the function to a specific key.

<script type="text/javascript" src="keyHandler.js"></script>

-----------------------------------------------------------
Example:
<script type="text/javascript" src="keyHandler.js"></script>

Initialize:
  if(typeof addKeyAction == 'function') {  
    addKeyAction(elementToHaveKeyHandlerAttached,function(){functionToLoad();},27);
  }
  
  if(typeof setActiveElement == 'function') {
    setActiveElement(elementToHaveKeyHandlerAttached);
  }

  if(typeof removeActiveElement == 'function') {
    removeActiveElement();
  }
  

Quick key-code reference:
13: Enter/return key
27: Escape key
32: Space bar key

-----------------------------------------------------------
Dependencies:
None

**********************************************************/

var keyActions = new Array();  /* Array holding all elements and associated key-actions */
function keyAction(element,func,keycode) {
  this.element = element;    /* The element invoking a key event */
  this.func = func;      /* The function that is to be executed */
  this.keycode = keycode;    /* The keycode that will initiate the function */
}

var currentActiveKeyElement = "";

var activeKeyElements = new Array();  /* Array-stack holding the active element in last position */
function activeKeyElement(element) {
  this.element = element;
}


function addKeyAction(element,func,keycode) {
  
  keyActions.push(new keyAction(element,func,keycode));
}


function setActiveElement(element) {
  activeKeyElements.push(new activeKeyElement(element));
  currentActiveKeyElement = element;
  
  
  /* identify the keyactions for the current active element */
  for (var i = 0; i < keyActions.length; i++) {
    if (keyActions[i].element == element) {
      var me = keyActions[i];
    }
  }
}


function removeActiveElement() {
  activeKeyElements.pop();
  
  /* If more elements are currently in the stack, activate the next element */
  var length = activeKeyElements.length;
  if (length > 0) {
    setActiveElement(activeKeyElements[length-1].element);  
  }
  else {
    currentActiveKeyElement = "";  
  }
}


function keyListener(event) {
  
  var evt = event || window.event;

  if (evt) {
  
    /* document.getElementById("notify").innerHTML = evt.keyCode; */
    
    for (var i = 0; i < keyActions.length; i++) {
      if (keyActions[i].element == currentActiveKeyElement && keyActions[i].keycode == evt.keyCode) {
        keyActions[i].func();
      }
    }
  }
} document.onkeydown = keyListener;


/**********************************************************
Author:
Adam Barry
eBOUND
www.ebound.dk

Date: June 12 2007

© 2007 Adam Barry, all rights reserved
-----------------------------------------------------------

Name:
dropDownNav script

-----------------------------------------------------------
Description:
Function that enables drop-down navigation functionality by
the use of a standard compliant list-based navigation
structure with drop-down functionality in IE, Firefox,
Opera, Safari etc.

-----------------------------------------------------------
Usage:
Simply place a link to the this script in the head-section
of the XHTML page. The script will then automatically
execute on page load.

<script type="text/javascript" src="dropDownNav.js"></script>

Make sure that your list structure has "navigation" as
classname, according to the example below.

-----------------------------------------------------------
Example:
<script type="text/javascript" src="dropDownNav.js"></script>

<ul class="navigation">
  <li class='first'><a class='selected' href='default.htm'>Home</a></li>
  <li><a href='default.htm'>Page 2</a>
    <ul>
      <li><a class='first' href='default.htm'>Subpage 2.1</a></li>
      <li><a href='default.htm'>Subpage 2.2</a></li>
    </ul>
  </li>
  <li><a href='default.htm'>Page 3</a>
    <ul>
      <li><a class='first' href='default.htm'>Subpage 3.1</a></li>
      <li><a href='default.htm'>Subpage 3.2</a></li>
    </ul>
  </li>
</ul>

-----------------------------------------------------------
Dependencies:
windowOnLoad.js

**********************************************************/

function dropDownNav () {
  if (!document.getElementsByTagName) return;

  var navs = new Array();
  var lists = document.getElementsByTagName("ul");

  for (var i = 0; i < lists.length; i++) {
    if (lists[i].className.indexOf('navigation') == 0) {
      navs.push(lists[i]);
    }
  }

  for (var t = 0; t < navs.length; t++) {

    var togglers = navs[t].getElementsByTagName("LI");
    for (var i=0; i < togglers.length; i++) {
      togglers[i].onmouseover=function() {
        this.className += " stretch";
      }
      togglers[i].onmouseout = function() {
        this.className = this.className.replace(new RegExp("stretch\\b"), "");
      }
      togglers[i].onclick = function() {
        this.className = this.className.replace(new RegExp("stretch\\b"), "");
      }
    }
  }
} addLoadEvent(function(){dropDownNav();});


/**********************************************************
Author:
Adam Barry
Klestrup partners
www.klestrup-partners.dk

Date: March 9 2009

© 2009 Adam Barry, all rights reserved

-----------------------------------------------------------

Name:
textFieldHandler script

-----------------------------------------------------------
Description:
Functions that enables dynamic style-switching when input
fields are filled.

-----------------------------------------------------------
Usage:
Simply place a link to the this script in the head-section
of the XHTML page. The script will then automatically
execute on page load.

<script type="text/javascript" src="textFieldHandler.js"></script>

<fieldset>
  <input type="text" class="text" />
</fieldset>

-----------------------------------------------------------
Dependencies:
windowOnLoad.js

-----------------------------------------------------------
Revision history:

2009-05-18: Maxlength-functionality for input and password
fields added

**********************************************************/

function controlInputFields() {
  if (!document.getElementsByTagName) return;

  var inputs = document.getElementsByTagName('input');

  if (!inputs) return;

  for (var i = 0; i < inputs.length; i++) {
    if (inputs[i].type == "text" || inputs[i].type == "password" || inputs[i].type == "email"|| inputs[i].type == "number") {
      var me = inputs[i];
      me.onkeydown = function(event) {
        var evt = event || window.event;

        toggleInputClass(this);

        if (this.getAttribute("maxlength")) {
          var maxlength = this.getAttribute("maxlength");

          if (evt.keyCode >= 48 && this.value.length >= maxlength) {
            focusOnNextElement(this);
          }
        }
      }

      me.onblur = function() {
        toggleInputClass(this);
      }

      /* If the page is refreshed, make sure that filled fields have a correponding classname */
      if (me.value !="") {
        me.className += " filled";
      }
    }
  }

} addLoadEvent(function(){controlInputFields();});


function toggleInputClass(element) {

  if (element.value.length > 0) {

    /* If the element contains text, but does not yet have its classname set to 'filled' */
    if (element.className.indexOf("filled") < 0) {
      element.className += " filled";
    }

    /* If an error class is set on the current element then remove it when typing occurs */
    if (element.className.indexOf("error") > -1) {
      element.className = element.className.replace(new RegExp("error\\b"), "");
    }
  }

  /* If the element does not contain any text then remove the 'filled' class */
  else {
    element.className = element.className.replace(new RegExp("filled\\b"), "");
  }

  if (element.className.indexOf("error") > -1) {
    element.className = element.className.replace(new RegExp("error\\b"), "");
  }
}


function focusOnNextElement(element) {

  if (!element.form) return;

  var elements = element.form.elements;

  if (!elements) return;

  for (var i = 0; i < elements.length; i++) {
    if (elements[i] == element && elements[i+1]) {
      elements[i+1].focus();
    }
  }
}


/**********************************************************
Author:
Adam Barry
Klestrup partners
www.klestrup-partners.dk

Date: April 30 2009

© 2009 Adam Barry, all rights reserved

Based on script from http://homepage.ntlworld.com/bobosola
-----------------------------------------------------------

Name:
pngfix script

-----------------------------------------------------------
Description:
Function that enables PNG-transparency in IE 5.5 & 6

-----------------------------------------------------------
Usage:
Simply place a link to the this script in the head-section
of the XHTML page. The script will then automatically
execute on page load.

<script type="text/javascript" src="pngfix.js"></script>

-----------------------------------------------------------
Dependencies:
windowOnLoad.js

**********************************************************/

function fixSpecificPNG() {

  var arVersion = navigator.appVersion.split("MSIE")
  var version = parseFloat(arVersion[1])

  if ((version < 7) && (version >= 5.5) && (document.body.filters)) {

    /* Specify specific global elements  that should be handled */

    /* Search */
    var elements = document.getElementsByTagName('div');
    for (var i = 0; i < elements.length; i++) {
      if (elements[i].className.indexOf('search') > -1) {
        fixPngImage(elements[i],'/graphics/searchVignette.png','crop');
      }
    }

    var elements = document.getElementsByTagName('span');
    for (var i = 0; i < elements.length; i++) {
      if (elements[i].className.indexOf('myBimco') > -1) {
        fixPngImage(elements[i],'/graphics/myBimcoSignedIn.png','scale');
      }
    }

    fixPNGimages();
  }
}
addLoadEvent(function(){fixSpecificPNG();});


function fixPngImage(element,backgroundImage,sizingMethod) {
  /* sizingMethod options: scale, crop, image */
  element.style.backgroundImage = "none";
  element.style.filter  = "progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+ backgroundImage +"', sizingMethod='"+sizingMethod+"')";
}

function fixPNGimages() {
  var pngImages = new Array();
  var images = document.getElementsByTagName('img');

  if (!images.length > 0) return;

  for (var i = 0; i < images.length; i++) {

    if (images[i].src.indexOf('.png') > -1) {

      pngImages.push(images[i]);
    }
  }

  if (pngImages.length < 1) return;

  for (var i = 0; i < pngImages.length; i++) {
    if (pngImages[i].parentNode.className.indexOf('imageGallery') <= -1) {

      var width = pngImages[i].width;
      var height = pngImages[i].height;
      var fileName = pngImages[i].src;


      var newHTML = "<span style=\"width:"+width+"px;height:"+height+"px;float:left;display:block;position:relative;filter:progid:DXImageTransform.Microsoft.AlphaImageLoader(src='"+fileName+"', sizingMethod='scale')\"></span>";

      if (pngImages[i].parentNode) {
        pngImages[i].parentNode.innerHTML = newHTML;
      }
    }
  }
}


/**********************************************************
Author:
Adam Barry
Klestrup partners
www.klestrup-partners.dk

Date: December 8 2008

© 2008 Adam Barry, all rights reserved
-----------------------------------------------------------

Name:
formValidation script (Microsoft .NET compatible)

-----------------------------------------------------------
Description:
Function that enable runs validation on userinputs on
various forms conforming to Microsoft.Net built pages.

-----------------------------------------------------------
Usage:
Simply place a link to the this script in the head-section
of the XHTML page. The script will then automatically
execute on page load.

<script type="text/javascript" src="formValidators.js"></script>
<script type="text/javascript" src="formValidation.Net.js"></script>

<form method="get" action="">


<div class="form">
<fieldset>
<legend>Form framework</legend>
<ul>
<li><label for="name">Name</label><input name="name" id="name" class="text required" type="text" /></li>
<li><label for="address">Address</label><input name="address" id="address" class="text" type="text" /></li>
<li><label for="email">E-mail</label><input name="email" id="email" class="text email" type="text" /></li>
<li><label for="number">Number</label><input name="number" id="number" class="text number required" type="text" /></li>
</ul>
<button type="button" class="submit"><span><span><span>Submit</span></span></span></button>
<button type="reset"><span><span><span>Reset</span></span></span></button>
</fieldset>
</div>

<div class="form">
<fieldset>
<legend>Form framework</legend>
<ul>
<li><label for="name">Name</label><input name="name" id="name" class="text required" type="text" /></li>
<li><label for="address">Address</label><input name="address" id="address" class="text" type="text" /></li>
<li><label for="email">E-mail</label><input name="email" id="email" class="text email" type="text" /></li>
</ul>
<button type="button" class="submit"><span><span><span>Submit</span></span></span></button>
<button type="reset"><span><span><span>Reset</span></span></span></button>
</fieldset>
</div>


</form>

Please note that the class attribute "required" and "email"
determins whether the specific form element is required.

-----------------------------------------------------------
Dependencies:
windowOnLoad.js

-----------------------------------------------------------
Revision history:

2009-05-15: Submit-on-enter functionality added

2009-05-18: Script refactored with emphasis on submit-on-
enter functionality

2009-06-27: Added additional check to test whether buttons onchange property has already been set
This allows script to be run multiple times on page

2010-03-24: Validators moved to separate JavaScript-file

2010-10-18 - Joakim: Re-merged with validator scripts, replaced the "onchange" function storage
trick with a Dictionary, ensuring cross-browser functionality (onchange didn't work in Chrome)

**********************************************************/
var buttonFunctions;

function initSubmitButtons() {

  if (!document.getElementsByTagName) return false;

  var buttons = document.getElementsByTagName("button");
  if (buttonFunctions == null) buttonFunctions = new Dictionary();

  for (var i = 0; i < buttons.length; i++) {
    var button = buttons[i];
    if (buttonFunctions[i] == null) {
      if (button.onclick != null) {
        buttonFunctions.Add(button.id, button.onclick);
      } else {
        buttonFunctions.Add(button, "");
      }
    }
    if (button.className.indexOf("submit") > -1) {
      if (button.onclick != null) {
        changeOnclick(button, buttonFunctions.Lookup(button.id));
      }
    }
  }
} addLoadEvent(function () { initSubmitButtons(); });

function changeOnclick(button, oldOnclick) {
  var me = button;
  me.onclick = function () {
    if (findDivForm(me) == true) {
      oldOnclick();
    }
    else {
      return false;
    }
  }
}

function initInputs() {

  /* Overcome stupid Firefox-error */
  var browser = navigator.userAgent;

  if (browser.indexOf('Firefox') > -1) {

    if (!document.getElementsByTagName) return false;

    var elements = document.getElementsByTagName("input");
    for (var i = 0; i < elements.length; i++) {
      elements[i].setAttribute("autocomplete", "off");
    }
  }
} addLoadEvent(function () { initInputs(); });


function findDivForm(button) {
  var formDivClassName = "form";
  var formDiv = button.parentNode;

  /* Loop throug the parentNodes of the clícked button until a div.form is found */
  while (formDiv.className.indexOf("form") == -1) {
    formDiv = formDiv.parentNode;
  }

  /* Validate the field elements in div.form */
  return validateForm(formDiv);
}

function submitButtonExecute(vThisform) {
  if (!vThisform) { return false; }

  buttons = vThisform.getElementsByTagName('button');
  if (!buttons) { return false; }

  for (var i = 0; i < buttons.length; i++) {
    if (buttons[i].className.indexOf('submit') > -1 && buttons[i].onclick != null) {
      buttons[i].onclick();
    }
  }
}

function submitPseudoForm(vThisform) {
  submitButtonExecute(vThisform);
  return false;
}


function validateCustomForm(button) {

  var formDivClassName = "form";
  var formDiv = button.parentNode;

  /* Loop throug the parentNodes of the clícked button until a div.form is found */
  while (formDiv.className.indexOf("form") == -1) {
    formDiv = formDiv.parentNode;
  }

  /*Validate the field elements in div.form */
  submitPseudoForm(formDiv);
}


/**********************************************************
Form validation
**********************************************************/

function validateForm(vThisform) {

  if (!vThisform) { return false; }

  var thisform = vThisform.getElementsByTagName("*");

  /*  Loop through all form elements of 'thisform' and determine
  which of them have 'required' or 'email' classes and are not children of a
  noValidation fieldset */

  for (var i = 0; i < thisform.length; i++) {
    var me = thisform[i];

    /* Loop through the form's required fields */
    if (me.className.indexOf("required") > -1 && me.parentNode.parentNode.parentNode.className.indexOf("noValidation") == -1) {

      if (me.tagName.toLowerCase() == "input" || me.tagName.toLowerCase == "password") {

        if (validate_required(me) == false) {
          return false;
        }
      }

      if (me.tagName.toLowerCase() == "select") {

        if (validate_select(me) == false) {
          return false;
        }
      }

      if (me.tagName.toLowerCase() == "textarea") {

        if (validate_textarea(me) == false) {
          return false;
        }
      }
    }

    /* Loop through the form's fields that have been filled out, although they are not required */
    if (me.className.indexOf('email') > -1 && me.value.length > 0) {

      if (validate_email(me) == false) {
        return false;
      }
    }

    if (me.className.indexOf('number') > -1 && me.value.length > 0) {

      if (validate_number(me) == false) {
        return false;
      }
    }
  }

  return true; /* Form is valid */
}

function validate_required(field) {

  with (field) {

    if (type == "checkbox") {
      if (checked == "") {
        field.className += " error";
        field.focus();
        return false;
      }
    }

    if (value == null || value.length <= 0 || value == " ") {
      field.className += " error";
      field.focus();
      return false;
    }

    else {
      field.className = field.className.replace(new RegExp("error\\b"), "");
      return true;
    }
  }
}


function validate_email(field) {

  with (field) {

    if (field.value.indexOf(".") > 0 && field.value.indexOf("@") > 0) {
      field.className = field.className.replace(new RegExp("error\\b"), "");
      return true;
    }
    else {
      field.className += " error";
      field.focus();
      return false;
    }
  }
}


function validate_number(field) {

  with (field) {

    if (field.value.match(/^\d+$/)) {
      field.className = field.className.replace(new RegExp("error\\b"), "");
      return true;
    }
    else {
      field.className += " error";
      field.focus();
      return false;
    }
  }
}

function validate_decimal(field) {

  with (field) {

    if (field.value.match(/^[0-9]+([,\.][0-9]{1,2})?$/)) {
      field.className = field.className.replace(new RegExp("error\\b"), "");
      return true;
    }
    else {
      field.className += " error";
      field.focus();
      return false;
    }
  }
}

function validate_select(element) {

  if (element.selectedIndex == 0) {
    element.focus();
    element.className += " error";
    return false;
  }
}


function validate_textarea(field) {

  if (field.value.length <= 0) {
    field.focus();
    field.className += " error";
    return false;
  }
}


/**********************************************************
No validation pseudo-forms
**********************************************************/

function noValidationCheckboxes() {
  if (!document.getElementsByTagName) return false;

  var inputs = document.getElementsByTagName("input");

  for (var i = 0; i < inputs.length; i++) {

    if (inputs[i].className.indexOf("noValidation") > -1) {
      var me = inputs[i];

      me.onclick = function () {

        /* if the page is reloaded and the checkbox is unchecked */
        if (me.checked == true && me.parentNode.className.indexOf('noValidation') > -1) {
          me.parentNode.className = me.parentNode.className.replace(new RegExp("noValidation\\b"), "");
        }

        if (me.checked == false) {
          me.parentNode.className = me.parentNode.className.replace(new RegExp("noValidation\\b"), "");
        }
        else {
          me.parentNode.className += " noValidation";
        }
      }
    }
  }

} addLoadEvent(function () { noValidationCheckboxes(); });


/**********************************************************
Eventhandlers
**********************************************************/

function checkFormsOnEnter() {
  if (!document.getElementsByTagName) return false;

  var forms = new Array();
  var elements = document.getElementsByTagName("div");

  for (var i = 0; i < elements.length; i++) {
    if (elements[i].className.indexOf("form") > -1) {
      forms.push(elements[i]);
    }
  }

  for (var i = 0; i < forms.length; i++) {
    forms[i].onkeydown = function (event) {

      var evt = event || window.event;

      if (evt) {
        var target = evt.target || evt.srcElement;

        switch (evt.keyCode) {
          case 13: /* Enter/return key */
            if (target.tagName.toLowerCase() == "textarea") {
              return true;
            }

            else {
              if (validateForm(this) == true) {
                submitPseudoForm(this);
              }
              return false;
              break;
            }
        }
      }
    }
  }
} addLoadEvent(function () { checkFormsOnEnter(); });

/**********************************************************
Dictionary object
**********************************************************/
function Lookup(key) {
  return (this[key]);
}

function Delete() {
  for (c = 0; c < Delete.arguments.length; c++) {
    this[Delete.arguments[c]] = null;
  }
  // Adjust the keys (not terribly efficient)
  var keys = new Array()
  for (var i = 0; i < this.Keys.length; i++) {
    if (this[this.Keys[i]] != null)
      keys[keys.length] = this.Keys[i];
  }
  this.Keys = keys;
}

function Add() {
  for (c = 0; c < Add.arguments.length; c += 2) {
    // Add the property
    this[Add.arguments[c]] = Add.arguments[c + 1];
    // And add it to the keys array
    this.Keys[this.Keys.length] = Add.arguments[c];
  }
}

function Dictionary() {
  this.Add = Add;
  this.Lookup = Lookup;
  this.Delete = Delete;
  this.Keys = new Array();
}


/**********************************************************
Author:
Adam Barry
Klestrup partners
www.klestrup-partners.dk

Date: December 8 2008

© 2008 Adam Barry, all rights reserved
-----------------------------------------------------------

Name:
formValidation script (Microsoft .NET compatible)

-----------------------------------------------------------
Description:
Function that enable runs validation on userinputs on
various forms conforming to Microsoft.Net built pages.

-----------------------------------------------------------
Usage:
Simply place a link to the this script in the head-section
of the XHTML page. The script will then automatically
execute on page load.

<script type="text/javascript" src="formValidators.js"></script>
<script type="text/javascript" src="formValidation.Net.js"></script>

<form method="get" action="">


  <div class="form">
    <fieldset>
      <legend>Form framework</legend>
      <ul>
        <li><label for="name">Name</label><input name="name" id="name" class="text required" type="text" /></li>
        <li><label for="address">Address</label><input name="address" id="address" class="text" type="text" /></li>
        <li><label for="email">E-mail</label><input name="email" id="email" class="text email" type="text" /></li>
        <li><label for="number">Number</label><input name="number" id="number" class="text number required" type="text" /></li>
      </ul>
      <button type="button" class="submit"><span><span><span>Submit</span></span></span></button>
      <button type="reset"><span><span><span>Reset</span></span></span></button>
    </fieldset>
  </div>

  <div class="form">
    <fieldset>
      <legend>Form framework</legend>
      <ul>
        <li><label for="name">Name</label><input name="name" id="name" class="text required" type="text" /></li>
        <li><label for="address">Address</label><input name="address" id="address" class="text" type="text" /></li>
        <li><label for="email">E-mail</label><input name="email" id="email" class="text email" type="text" /></li>
      </ul>
      <button type="button" class="submit"><span><span><span>Submit</span></span></span></button>
      <button type="reset"><span><span><span>Reset</span></span></span></button>
    </fieldset>
  </div>


</form>

Please note that the class attribute "required" and "email"
determins whether the specific form element is required.

-----------------------------------------------------------
Dependencies:
windowOnLoad.js
formValidators.js

-----------------------------------------------------------
Revision history:

2009-05-15: Submit-on-enter functionality added

2009-05-18: Script refactored with emphasis on submit-on-
enter functionality

2009-06-27: Added additional check to test whether buttons onchange property has already been set
This allows script to be run multiple times on page

2010-03-24: Validators moved to separate JavaScript-file

**********************************************************/

function initSubmitButtons () {
  if (!document.getElementsByTagName) return false;

  var buttons = document.getElementsByTagName("button");
  for (var i = 0; i < buttons.length; i++) {
    if (buttons[i].className.indexOf("submit") > -1) {

      var button = buttons[i];

      if (button.onclick != null && button.onchange == null) {

        /* store the onclick command in onchange attribute */
        button.onchange = button.onclick;

        button.onclick = function() {

          var me = this;

          if (findDivForm(me) == true) {
            me.onchange();
          }

          else {
            return false;
          }
        }

      }
    }
  }
}addLoadEvent(function(){initSubmitButtons();});


function initInputs () {

  /* Overcome stupid Firefox-error */
  var browser = navigator.userAgent;

  if (browser.indexOf('Firefox') > -1) {

    if (!document.getElementsByTagName) return false;

    var elements = document.getElementsByTagName("input");
    for (var i = 0; i < elements.length; i++) {
      elements[i].setAttribute("autocomplete","off");
    }
  }
}addLoadEvent(function(){initInputs();});


function findDivForm (button) {

  var formDivClassName = "form";
  var formDiv = button.parentNode;

  /* Loop throug the parentNodes of the clícked button until a div.form is found */
  while (formDiv.className.indexOf("form") == -1) {
    formDiv = formDiv.parentNode;
  }

  /* Validate the field elements in div.form */
  return validateForm(formDiv);
}


function submitButtonExecute (vThisform) {
  if (!vThisform) {return false;}

  buttons = vThisform.getElementsByTagName('button');
  if (!buttons) {return false;}

  for (var i = 0; i < buttons.length; i++) {
    if (buttons[i].className.indexOf('submit') > -1 &&   buttons[i].onchange != null) {
      buttons[i].onchange();
    }
  }
}


function submitPseudoForm(vThisform) {
  submitButtonExecute(vThisform);
  return false;
}


function validateCustomForm (button) {

    var formDivClassName = "form";
  var formDiv = button.parentNode;

  /* Loop throug the parentNodes of the clícked button until a div.form is found */
  while (formDiv.className.indexOf("form") == -1) {
    formDiv = formDiv.parentNode;
  }

  /*Validate the field elements in div.form */
  submitPseudoForm(formDiv);
}


/**********************************************************
Form validation
**********************************************************/

function validateForm(vThisform) {

  if (!vThisform) {return false;}

  var thisform = vThisform.getElementsByTagName("*");

   /*  Loop through all form elements of 'thisform' and determine
    which of them have 'required' or 'email' classes and are not children of a
    noValidation fieldset */

  for (var i = 0; i < thisform.length; i++) {
    var me = thisform[i];

    /* Loop through the form's required fields */
    if (me.className.indexOf('required') > -1 && me.parentNode.parentNode.parentNode.className.indexOf('noValidation') == -1) {

      if (me.tagName.toLowerCase() == "input" || me.tagName.toLowerCase == "password") {

        if (validate_required(me) == false) {
          return false;
        }
      }

      if (me.tagName.toLowerCase() == "select") {

        if (validate_select(me) == false) {
          return false;
        }
      }

      if (me.tagName.toLowerCase() == "textarea") {

        if (validate_textarea(me) == false) {
          return false;
        }
      }
    }

    /* Loop through the form's fields that have been filled out, although they are not required */
    if (me.className.indexOf('email') > -1 && me.value.length > 0) {

      if (validate_email(me) == false) {
        return false;
      }
    }

    if (me.className.indexOf('number') > -1 && me.value.length > 0) {

      if (validate_number(me) == false) {
        return false;
      }
    }
  }

  return true; /* Form is valid */
}


/**********************************************************
Eventhandlers
**********************************************************/

function checkFormsOnEnter() {
  if (!document.getElementsByTagName) return false;

  var forms = new Array();
  var elements = document.getElementsByTagName("div");

  for (var i = 0; i < elements.length; i++) {
    if (elements[i].className.indexOf("form") > -1) {
      forms.push(elements[i]);
    }
  }

  for (var i = 0; i < forms.length; i++) {
    forms[i].onkeydown = function(event) {

      var evt = event || window.event;

      if (evt) {
        var target = evt.target || evt.srcElement;

        switch (evt.keyCode) {
          case 13:  /* Enter/return key */
            if (target.tagName.toLowerCase() == "textarea") {
              return true;
            }

            else {
              if (validateForm(this) == true) {
                submitPseudoForm(this);
              }
              return false;
              break;
            }
        }
      }
    }
  }
} addLoadEvent(function(){checkFormsOnEnter();});


/**********************************************************
Author:
Adam Barry
Klestrup partners
www.klestrup-partners.dk

Date: August 8 2009

© 2009 Adam Barry, all rights reserved
-----------------------------------------------------------

Name:
popupWindow script

-----------------------------------------------------------
Description:
Functions that enable an integrated popup-window which
sits in front of the normal page content.

-----------------------------------------------------------
Usage:
Simply place a link to the this script in the head-section
of the XHTML page. The script will then automatically
execute on page load.

<script type="text/javascript" src="popupWindow.js"></script>

-----------------------------------------------------------
Example:
<script type="text/javascript" src="popupWindow.js"></script>


<a href="javascript:popup(false,false,false)">Open popup window</a>
<a href="javascript:popup('<h2>New HTML</h2><p>This text has been injected into the popup-window.</p>',false,2500)">Open time-limited popup window</a>


<div class="popupWindow">
  <div class="popupContainer">

    <div class="popup">
      <a class="close"><span>Close</span></a>

      <div class="popupContent">
        <h2>User notification</h2>
      </div>

    </div>

  </div>
</div>  

-----------------------------------------------------------
Dependencies:
windowOnLoad.js

Optional:
keyHandler.js

**********************************************************/

var popupWindow;
var popupContent;

function initPopup() {
  if (!document.getElementsByTagName) return;

  var divs = document.getElementsByTagName("div");

  for (var i = 0; i < divs.length; i++) {
    if (divs[i].className.indexOf('popupWindow') > -1) {
      var me = divs[i];
      popupWindow = me;
      if(typeof addKeyAction == 'function') {  
        addKeyAction(me,function(){hidePopup();},13);
        addKeyAction(me,function(){hidePopup();},27);
        addKeyAction(me,function(){hidePopup();},32);
      }
      break;
    }
  }


  if (!popupWindow) addPopupWindow();

  var anchors = popupWindow.getElementsByTagName("a");

  for (var i = 0; i < anchors.length; i++) {

    if (anchors[i].className.indexOf('close') > -1) {
      var me = anchors[i];
      me.onclick = function() {
        hidePopup();
      }
        break;
    }
  }

  var divs = popupWindow.getElementsByTagName("div");

  for (var i = 0; i < divs.length; i++) {
    if (divs[i].className.indexOf('popupContent') > -1) {
      popupContent = divs[i];
      break;
    }
  }

}addLoadEvent(function(){initPopup();});


function addPopupWindow() {
  popupStructure = document.createElement('div');

  popupStructure.innerHTML = "<div class=\"popupContainer\"><div class=\"popup\"><a class=\"close\"><span>Close</span></a><div class=\"popupContent\"><h2>User notification</h2></div></div></div>";

  document.body.appendChild(popupStructure);
  popupStructure.className = "popupWindow";

  popupWindow = popupStructure;
}



function hidePopup() {
  popupWindow.className = popupWindow.className.replace(new RegExp("active\\b"), "");

  if(typeof removeActiveElement == 'function') {
    removeActiveElement();
  }
}


function popupTimer(time) {
  window.setTimeout(hidePopup,time);
}


function popup(message,classInformation,keepVisibleTime) {
  if (!popupWindow) return;
  if (!popupContent) return;

  if (message) {
    popupContent.innerHTML = message;
  }
  else {
    popupContent.innerHTML = "";
  }

  if (classInformation) {
    popupWindow.className += classInformation;
  }

  popupWindow.className += " active";

  if (keepVisibleTime) {
    popupTimer(keepVisibleTime);
  }

  if(typeof setActiveElement == 'function') {
    setActiveElement(popupWindow);
  }
}


/**********************************************************
Author:
Adam Barry
Klestrup partners
www.klestrup-partners.dk

Date: February 20 2008

© 2008 Adam Barry, all rights reserved
-----------------------------------------------------------

Name:
Google Analytics track links script

-----------------------------------------------------------
Inspiration
http://www.terenzani.it/54/urchintrack-utility-tracciare-link-esterni-e-download-con-google-analytics
GA urchin.trackLinks 0.2

-----------------------------------------------------------
Description:
Function that enables Google Analytics tracking of
downloaded files - when placed in an <a> structure.

NB. This version is not compatible with the old Google
Analytics/Urchin tracking code.

-----------------------------------------------------------
Usage:
Simply place a link to the this script in the head-section
of the XHTML page. The script will then automatically
execute on page load.

<script type="text/javascript" src="GA.trackLinks.js"></script>

-----------------------------------------------------------
Example:
<script type="text/javascript" src="GA.trackLinks.js"></script>

<a href="filename.pdf">Download tracked PDF file</a>

-----------------------------------------------------------
Dependencies:
windowOnLoad.js

**********************************************************/

function urchin() {
 /* It contains the download extension separated by a "|" */
  this.trackDownload = '';

   this.trackLinks = function() {
      var a = document.getElementsByTagName('a');

   /* Extract the domain from the location (the domain is in domain[2]) */
    var domain = /^(http|https):\/\/([a-z-.0-9]+)[\/]{0,1}/i.exec(window.location);
     if (!domain) return;

   /* Expression that checks for internal links */
    var internalLink = new RegExp("^(http|https):\/\/"+domain[2], "i");

   /* Expression that checks for downloads */
    var isDownload = new RegExp("("+this.trackDownload+")$", "i");

    /* For each anchor */
    for(var i = 0; i < a.length; i++) {
    /* If href points to an internal resource */
      if(internalLink.test(a[i].href)) {
    /* ... and if the file extension is in this.trackDownload ... */
        if(this.trackDownload && isDownload.test(a[i].href))
        a[i].onclick = function() {
      /* Clean and track the URL */
        pageTracker._trackPageview('/download/'+this.href.replace(/^(http|https):\/\/([a-z-.0-9]+)\//i, '').split('/').join('--'));
        }
      }

      else
        /* is external */
        a[i].onclick = function() {
        /* Clean and track the URL */
        pageTracker._trackPageview('/outgoing/'+this.href.replace(/^http:\/\/|https:\/\//i, '').split('/').join('--'));
      }
    }
   }
}

function initDownloadTracker () {
    urchin = new urchin();
    urchin.trackDownload = "zip|rar|pdf|exe|gz|dmg|avi|jpg|gif|png|doc|dot|ashx";
    urchin.trackLinks();
} addLoadEvent(function(){initDownloadTracker();});


/**********************************************************
Author:
Adam Barry
Klestrup partners
www.klestrup-partners.dk

Date: November 11 2007

© 2007 Adam Barry, all rights reserved
-----------------------------------------------------------

Name:
thumbnails script

-----------------------------------------------------------
Description:
A script that enables thumbnail/preview functionality to
multiple thumbnail structures. The construction of the
thumbnail list means that browsers that do not support
document.getElementsByTagName will still be able to view
the standard-images, although in new windows.

-----------------------------------------------------------
Usage:
Simply place a link to the this script in the head-section
of the XHTML page. The script will then automatically
execute on page load.

<script type="text/javascript" src="thumbnails.js"></script>

Make sure that your list structure has (1) an image element
where the class-name is "previewImage" and (2) a unordered
list with "thumbnails" as class-name according to the
example below.

-----------------------------------------------------------
Example:
<script type="text/javascript" src="thumbnails.js"></script>

<img class="previewImage" src="books/bookname/standard/image1.png" alt=""/>

<ul class="thumbnails">
  <li>
    <a href="components/imagegallery/standard/image1.png" class="selected">
      <img src="components/imagegallery/thumbs/image1.png" alt=""/>
      <span>1</span>
    </a>
  </li>
  <li>
    <a href="components/imagegallery/standard/image2.png">
      <img src="components/imagegallery/thumbs/image2.png" alt=""/>
      <span>2</span>
    </a>
  </li>
  <li>
</ul>

-----------------------------------------------------------
Dependencies:
windowOnLoad.js

Optional:
keyHandler.js

**********************************************************/

var imageGalleries = new Array();
function imageGallery (element,previewImage,thumbnails,currentPosition) {
  this.element = element;
  this.previewImage = previewImage;
  this.thumbnails = new Array();
  this.currentPosition = currentPosition;
}


function initImageGalleries () {
  if (!document.getElementsByTagName) return;

  var elements = document.getElementsByTagName("div");

  /* When an element with the classname 'imageGallery' is found
     create a new entry in the imageGalleries array */
  for (var i = 0; i < elements.length; i++) {
    if (elements[i].className.indexOf('imageGallery') > -1) {
      imageGalleries.push(new imageGallery(elements[i],'','',''))
    }
  }

  /* If the imageGalleries array is empty do not proceed  */
  if (!imageGalleries[0]) return;

  /* Run through each imageGallery in the imageGalleries array */
  for (var x = 0; x < imageGalleries.length; x++) {
    /* alert("Debug: Now processing imageGallery No. #"+x); */
    var gallery = imageGalleries[x].element;

    /* Identify the previewImage of the current imageGallery
       and store it in the imageGalleries array */
    var images = gallery.getElementsByTagName("img");

    for (var i = 0; i < images.length; i++) {
      if (images[i].className.indexOf('previewImage') == 0) {
        imageGalleries[x].previewImage = images[i];
      }
    }

    if (!imageGalleries[x].previewImage) return;
    var previewImage = imageGalleries[x].previewImage;

    /* Now that we have identified the previewImage let's
       identify the thumbnail images and add them the the
       imageGalleries array */
    var thumbnailList;
    var lists = gallery.getElementsByTagName("ul");

    for (var i = 0; i < lists.length; i++) {
      if (lists[i].className == 'thumbnails') {
        thumbnailList = lists[i];
      }
    }

    /* Identify the child items of the thumbnailList */
    var thumbnails = thumbnailList.getElementsByTagName("a");

    /* When a thumbnail element is found add it to thumbnails array in
       the current imageGallery object */
    for (var i = 0; i < thumbnails.length; i++) {
      imageGalleries[x].thumbnails.push(thumbnails[i]);
    }

    /* Quit the function if no thumbnails have been found */
    if (!imageGalleries[x].thumbnails[0]) return;

    /* To keep track of which thumbnail is currently selected
       find it an store it in the current imageGallery object */
    for (var i = 0; i < thumbnails.length; i++) {
      if (thumbnails[i].className == 'selected') {
        imageGalleries[x].currentPosition = i;
      }
    }

    /* The thumbnails have now been stored in the imageGallery object
       so now add some functionality to them */
    for (var i = 0; i < thumbnails.length; i++) {
      thumbnails[i].onclick = function() {
        var parentNode = this.parentNode.parentNode.parentNode.parentNode;

        thumbnailHandler(parentNode,this);
        return false;  /* make sure the link is not actually followed */
      }
    }

    /* Make it possible to proceed to the next image by clicking the previewImage */
    previewImage.onclick = function() {
      var currentImageGallery;

      /* identify the image currently shown */
      for (var i = 0; i < imageGalleries.length; i++) {
        if (imageGalleries[i].previewImage == this) {
          currentImageGallery = imageGalleries[i].element;
        }
      }
      showNextImage(currentImageGallery);
    }

    /* Make it possible to navigate through the images by mouse scroll */
    initMouseScroll(previewImage);


    /* Make it possible to navigate through the images by using the arrow-keys */
    previewImage.onmouseover = function() {
      var currentImageGallery;

      /* identify the image currently shown */
      for (var i = 0; i < imageGalleries.length; i++) {
        if (imageGalleries[i].previewImage == this) {
          currentImageGallery = imageGalleries[i].element;
        }
      }

      if (typeof addKeyAction == 'function') {
        addKeyAction(currentImageGallery, function() { showPreviousImage(currentImageGallery); }, 37);
        addKeyAction(currentImageGallery, function() { showNextImage(currentImageGallery); }, 39);
      }

      if (typeof setActiveElement == 'function') {
        setActiveElement(currentImageGallery);
      }
    }

    previewImage.onmouseout = function() {
      if (typeof removeActiveElement == 'function') {
        removeActiveElement();
      }
    }
  }

  /* Preload the images to make viewing faster */
  for (var i = 0; i < imageGalleries.length; i++) {
    preloadImages(imageGalleries[i].element);
  }
}
addLoadEvent(function(){initImageGalleries();});


function identifyImageGallery(imageGallery) {
  var currentImageGallery;

  /* Identify the position of the current imageGallery
     in the imageGalleries array */
  for (var i = 0; i < imageGalleries.length; i++) {

    if (imageGalleries[i].element == imageGallery) {
      currentImageGallery = imageGalleries[i];
    }
  }

  return currentImageGallery;
}

function thumbnailHandler (imageGallery,thumbnail) {
  clearThumbnails(imageGallery);
  thumbnail.className+="selected";
  thumbnail.blur();
  showImage(imageGallery,thumbnail);
  setDisplayedThumbnail(imageGallery,thumbnail);
}

function clearThumbnails (imageGallery) {
  var currentImageGallery = identifyImageGallery(imageGallery);

  /* Loop through the thumbnails and make sure none of them
     are selected */
  for (var i = 0; i < currentImageGallery.thumbnails.length; i++) {
    currentImageGallery.thumbnails[i].className = "";
  }
}

function showImage (imageGallery,thumbnail) {
  var currentImageGallery = identifyImageGallery(imageGallery);
  var path = thumbnail.href;

  currentImageGallery.previewImage.src = path;
}

function setDisplayedThumbnail(imageGallery,thumbnail) {
  var currentImageGallery = identifyImageGallery(imageGallery);

  for (var i = 0; i < currentImageGallery.thumbnails.length; i++) {
    if (currentImageGallery.thumbnails[i] == thumbnail) {
      currentImageGallery.currentPosition = i;
    }
  }
}

function showNextImage (imageGallery) {
  var currentImageGallery = identifyImageGallery(imageGallery);
  var noOfThumbnails = currentImageGallery.thumbnails.length-1;
  var nextImage;

  if (currentImageGallery.currentPosition < noOfThumbnails) {
    nextPosition = currentImageGallery.currentPosition + 1;
    nextImage = currentImageGallery.thumbnails[nextPosition];
  }
  else {
    nextImage = currentImageGallery.thumbnails[0];
  }

  thumbnailHandler(imageGallery,nextImage);
}

function showPreviousImage (imageGallery) {
  var currentImageGallery = identifyImageGallery(imageGallery);
  var noOfThumbnails = currentImageGallery.thumbnails.length-1;
  var previousImage;

  if (currentImageGallery.currentPosition > 0) {
    previousPosition = currentImageGallery.currentPosition - 1;
    previousImage = currentImageGallery.thumbnails[previousPosition];
  }
  else {
    previousImage = currentImageGallery.thumbnails[noOfThumbnails];
  }

  thumbnailHandler(imageGallery,previousImage);
}

function setDisplayedThumbnail(imageGallery,thumbnail) {
  var currentImageGallery = identifyImageGallery(imageGallery);

  for (var i = 0; i < currentImageGallery.thumbnails.length; i++) {
    if (currentImageGallery.thumbnails[i] == thumbnail) {
      currentImageGallery.currentPosition = i;
    }
  }
}


/*: Mouse scroll navigation
Functions relevant
----------------------------------------------------------*/

function initMouseScroll (previewImage) {
  if (previewImage.addEventListener) {
    previewImage.addEventListener ("DOMMouseScroll",wheelGallery,false); /* Firefox */
    previewImage.addEventListener ("mousewheel",wheelGallery,false); /* Safari  & Opera */
  } else if (previewImage.attachEvent) {
    previewImage.attachEvent ("onmousewheel",wheelGallery); /* Internet Explorer */
  } else {
    previewImage.DOMMouseScroll = wheelGallery;
  }
}

function eventTrigger (e) {
    if (! e) {
        e = event;
  }

    return e.target || e.srcElement;
}

function handleWheelGallery (delta,event) {

  /* Identify which object triggered the mouse scroll event */
  var obj = eventTrigger (event);
  var currentImageGallery;

  for (var i = 0; i < imageGalleries.length; i++) {
    if (imageGalleries[i].previewImage == obj) {
      currentImageGallery = imageGalleries[i].element;
    }
  }

  /* Mouse scroll down */
  if (delta < 0) {
    showNextImage(currentImageGallery);
  }
  /* Mouse scroll up */
  else {
    showPreviousImage(currentImageGallery);
  }
}

function wheelGallery (event) {
  var delta = 0;

  if (!event) { /* For IE. */
    event = window.event;
  }

  if (event.wheelDelta) { /* IE/Opera. */
    delta = event.wheelDelta/120;
    if (window.opera) {
      delta = -delta;
    }
  }

  else if (event.detail) { /** Mozilla case. */
      delta = -event.detail/3;
  }

  if (delta) {
    handleWheelGallery(delta,event);
  }

  if (event.preventDefault) {
    event.preventDefault();
  }

  event.returnValue = false;
}


/*: Pre-load thumbnail images
Functions relevant
----------------------------------------------------------*/

String.prototype.reverse = function () {
  var s = "";
  var i = this.length;

  while (i>0) {
    s += this.substring(i-1,i);
    i--;
  }
    return s;
}

function getFileName (string) {
  var reversePath = string.reverse();
  var splitPath = reversePath.split("/");
  var fileName = splitPath[0].reverse();
  return fileName;
}

function preloadImages (imageGallery) {
  var currentImageGallery;

  /* Identify the position of the current imageGallery
     in the imageGalleries array */
  for (var i = 0; i < imageGalleries.length; i++) {

    if (imageGalleries[i].element == imageGallery) {
      currentImageGallery = imageGalleries[i];
    }
  }

  for (var i = 0; i < currentImageGallery.thumbnails.length; i++) {
    var path = currentImageGallery.thumbnails[i].href;
    var fileName = getFileName(path);

    fileName = new Image();
    fileName.src = path;
  }
}


function siteSearch() {
  var queryString = document.getElementById('query').value;

  location = "/search?search="+queryString;
}
