

    /*
    |-------------|
    |   Globals   |
    |-------------|
    */






    /*
    |----------------------------------------------------|
    |   Language / core objects manipulation functions   |
    |----------------------------------------------------|
    */


function moveArrayItemsBackwards(array, from_index) {

    if (array[from_index]) {
        for (var i = array.length - 1; i >= from_index; i--) {
            array[i + 1] = array[i];
        }
    }
    return array;
}



function is(value) {
    if (typeof(value) != 'undefined') {
        return true;
    } else {
        return false;
    }
}



    /*
    |---------------------------------------|
    |   Create / fetch elements functions   |
    |---------------------------------------|
    */



function $E(event) {
    if (!event) {
        event = window.event;
    }
    return event.target || event.srcElement;
}



// alias to Simon Willison's getElementsBySelector function
var $CSS = function (rule) { return document.getElementsBySelector(rule); };



// copyright -> Simon Willison (http://simon.incutio.com/archive/2003/06/15/javascriptWithXML)
function createElement(element) {
  if (typeof document.createElementNS != 'undefined') {
    return document.createElementNS('http://www.w3.org/1999/xhtml', element);
  }
  if (typeof document.createElement != 'undefined') {
    return document.createElement(element);
  }
  return false;
}



    /*
    |-----------------------------|
    |   Event-related functions   |
    |   (also see $E above)       |
    |-----------------------------|
    */



function bindEvent(object, type, func) {
    var capture = (arguments.length > 3) ? arguments[3] : true;
    if (ie) {
        object.attachEvent('on' + type, func);
    } else {
        object.addEventListener(type, func, capture);
    }
}


function cancelEvent(event) {
    if (ie) {
        window.event.cancelBubble = true;
    } else {
        event.stopPropagation();
    }
}



    /*
    |----------------------------------|
    |   Style manipulation functions   |
    |----------------------------------|
    */



// this returns a style object from a stylesheet rule selector
// manipulating the returned style object will impact all
// elements to which this rule applies
function getStyleFromCssSelector(selector) {

    var style = null;

    if (ie) {
        for (var i in document.styleSheets) {
            for (var j in document.styleSheets[i].rules) {
                if (document.styleSheets[i].rules[j].selectorText == selector) {
                    style = document.styleSheets[i].rules[j].style;
                    break;
                }
            }
        }
    } else {
        for (var i in document.styleSheets) {
            for (var j in document.styleSheets[i].cssRules) {
                if (document.styleSheets[i].cssRules[j].selectorText == selector) {
                    style = document.styleSheets[i].cssRules[j].style;
                    break;
                }
            }
        }
    }

    return style;
}



    /*
    |----------------------------|
    |   DOM releated functions   |
    |----------------------------|
    */



function DOM_removeAllChildren(element) {
    while (element.hasChildNodes()) {
        element.removeChild(element.childNodes[element.childNodes.length - 1]);
    }
}



function DOM_WalkUpToTagName(obj, tag) {
    var original = obj;
    while (obj != null && typeof(obj) != 'undefined' && obj.tagName && (obj.tagName.toLowerCase() != tag || obj == original) && obj.parentNode) {
        obj = obj.parentNode;
    }
    return obj;
}



function DOM_WalkBackwardsToTagName(obj, tag) {
    var original = obj;
    while ( ((typeof obj.tagName == 'undefined') || (obj.tagName.toLowerCase() != tag || obj == original)) && obj.previousSibling) {
        obj = obj.previousSibling;
    }
    return obj;
}



function DOM_WalkForwardsToTagName(obj, tag) {
    var original = obj;
    while ( ((typeof obj.tagName == 'undefined') || (obj.tagName.toLowerCase() != tag || obj == original)) && obj.nextSibling) {
        obj = obj.nextSibling;
    }
    return obj;
}



// insert something after
function DOM_insertAfter(parent, node, referenceNode) {

    if (referenceNode.nextSibling) {
        parent.insertBefore(node, referenceNode.nextSibling);
    } else {
        parent.appendChild(node);
    }
}



function DOM_getSiblingsWithTagName(node, tag, direction) {
    var siblings = [ ];
    tag = tag.toLowerCase();
    if (direction != 'after') {
        sibling = node.previousSibling;
        while (sibling) {
            if (sibling.tagName.toLowerCase() == tag) {
                siblings.push(sibling);
            }
            sibling = sibling.previousSibling;
        }
    }
    if (direction != 'before') {
        sibling = node.nextSibling;
        while (sibling) {
            if (sibling.tagName.toLowerCase() == tag) {
                siblings.push(sibling);
            }
            sibling = sibling.nextSibling;
        }
    }
    return siblings;
}



function DOM_insertAtPosition(parent, node, pos) {

    if (!parent.firstChild || (pos >= parent.childNodes.length)) {
        parent.appendChild(node);
        return;
    }

    var child = parent.firstChild;
    var i = 0;
    while (child) {
        if (pos == i) {
            parent.insertBefore(node, child);
            break;
        }
        i ++;
        child = child.nextSibling;
    }
}



function DOM_getRecursiveTextDataFromElement(element) {

    // little shonk for simple browse
    if (element.getAttribute('text_data')) {
        return element.getAttribute('text_data');
    }

    var element_text = '';
    // go through element nodes
    var text_node_type = document.createTextNode('dummy').nodeType;
    var element_node = element.firstChild;
    while (element_node) {
        if (element_node.nodeType == text_node_type) {
            element_text += element_node.nodeValue;
        } else {
            element_text += this.DOM_getRecursiveTextDataFromElement(element_node);
        }
        element_node = element_node.nextSibling;
    }

    return element_text;
}



function DOM_removeEmptyTextNodes(parent) {
    var child = parent.firstChild;
    while (child) {
        child = child.nextSibling;
        if (child && child.previousSibling.tagName == undefined) {
            parent.removeChild(child.previousSibling);
        }
    }
}



// normally 3 but may differ across browsers so wrapped in a function ...
function DOM_getTextNodeType() {
    var text_node = document.createTextNode('');
    var node_type = text_node.nodeType;
    text_node = null;
    return node_type;
}



function insertElementAtPosition(element, parent, pos) {
    var n = 0;
    for (var child = parent.firstChild; child; child = child.nextSibling) {
        if (n == pos) {
            parent.insertBefore(element, child);
        }
    }
    parent.appendChild(element);
}



    /*
    |----------------------------|
    |   Positionning functions   |
    |----------------------------|
    */



// position an element above another one with the specified zIndex
function setAsOverlay(element, target, zindex) {
    element.style.position = 'absolute';
    element.style.zIndex = zindex;
    element.style.left = findPosX(target);
    element.style.top = findPosY(target);
    element.style.width = target.offsetWidth;
    element.style.height = target.offsetHeight;
}



// element: dom node (div)
// centers using top & left margins computed from parent's width/height
function centerElement(element, horizontal, vertical) {
    if (horizontal) {
        element.style.marginLeft = (element.parentNode.offsetWidth / 2)  - (element.offsetWidth / 2);
    }
    if (vertical) {
        element.style.marginTop  = (element.parentNode.offsetHeight / 2) - (element.offsetHeight / 2);
    }
}



    /*
    |-----------------------------------|
    |   Cookie manipulation functions   |
    |-----------------------------------|
    */



    function createCookie(name, value) {

        // cookie path
        var path = arguments[2] || '/';

        // cookie expiry date
    	if (arguments[3]) {
    		var date = new Date();
    		date.setTime(date.getTime() + (arguments[3] * 24 * 60 * 60 * 1000));
    		var expires = '; expires=' + date.toGMTString();
    	} else {
    	    var expires = '; expires=Sun 01-Jan-2070 00:00:00 UTC';
    	}

    	document.cookie = name + '=' + value + expires + '; path=' + path;
    }



    function readCookie(name) {

    	var name_eq = 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(name_eq) == 0) {
    		    return c.substring(name_eq.length, c.length);
    		}
    	}

    	return null;
    }



    function eraseCookie(name) {
    	createCookie(name, '', null, -1);
    }



    /*
    |-----------------------------|
    |   Miscellaneous functions   |
    |-----------------------------|
    */



function printfire()
{
    if (document.createEvent)
    {
        printfire.args = arguments;
        var ev = document.createEvent("Events");
        ev.initEvent("printfire", false, true);
        dispatchEvent(ev);
    }
}



function appendUrlParameters(url, parameters) {
    url += url.indexOf('?') > -1 ? '&' : '?';
    url += parameters;
    return url;
}



// copyright Joel T. Anderson: http://www.sonofsofaman.com/hobbies/code/js/formatcurrency.asp
function formatCurrency(strValue)
{
	strValue = strValue.toString().replace(/\$|\,/g,'');
	dblValue = parseFloat(strValue);

	blnSign = (dblValue == (dblValue = Math.abs(dblValue)));
	dblValue = Math.floor(dblValue*100+0.50000000001);
	intCents = dblValue%100;
	strCents = intCents.toString();
	dblValue = Math.floor(dblValue/100).toString();
	if(intCents<10)
		strCents = "0" + strCents;
	for (var i = 0; i < Math.floor((dblValue.length-(1+i))/3); i++)
		dblValue = dblValue.substring(0,dblValue.length-(4*i+3))+','+
		dblValue.substring(dblValue.length-(4*i+3));
	return (((blnSign)?'':'-') + '$' + dblValue + '.' + strCents);
}



// also defined in Prototype (with the same check, so they'll never overwrite each other)
if (!window.Element) {
  var Element = new Object();
}


Element.hasAttribute = function(element, attribute) {
    var result =    Try.these(
                        function() {
                            if (element.getAttribute && (element.getAttribute(attribute) && (element.getAttribute(attribute) !== 'false'))) {
                                return true;
                            }
                        }.bind(this),
                        function() {
                            if (element.getAttribute && (element.getAttributeNode(attribute).value && (element.getAttribute(attribute).value !== 'false'))) {
                                return true;
                            }
                        }.bind(this),
                        function() { return false; }
                    );

    return result;
}


Element.getAttribute = function(element, attribute) {
    var result =    Try.these(
                        function() {
                            if (element.getAttribute) {
                                return element.getAttribute(attribute);
                            }
                        }.bind(this),
                        function() {
                            if (element.getAttributeNode) {
                                return element.getAttributeNode(attribute).value;
                            }
                        }.bind(this),
                        function() { return false; }
                    );

    return result;
}