/**============================================================================
 * 
 * XERO JAVASCRIPT LIBRARY
 *
 * http://www.xero.com/
 *
 * About: 
 * This JavaScript library is used in the Xero Accounting web application. It
 * is designed by be used in conjunction with the Prototype library.
 *
 *============================================================================/
 
/* Register the XERO namespace if not already done */
if (typeof XERO == "undefined") {
    var XERO = {};
};

/**
 * NB: A direct rip off of the YUI library .namespace method
 *
 * Returns the namespace specified and creates it if it doesn't exist
 * <pre>
 * XERO.namespace("XERO.property.package");
 * XERO.namespace("property.package");
 * </pre>
 *
 * Be careful when naming packages. Reserved words may work in some browsers
 * and not others. For instance, the following will fail in Safari:
 * <pre>
 * XERO.namespace("really.long.nested.namespace");
 * </pre>
 * This fails because "long" is a future reserved word in ECMAScript
 *
 * @method namespace
 * @static
 * @param  {String*} arguments 1-n namespaces to create 
 * @return {Object}  A reference to the last namespace object created
 */
XERO.namespace = function() {
    var a=arguments, o=null, i, j, d;
    for (i=0; i<a.length; i++) {
        d=a[i].split(".");
        o=XERO;
        for (j=0; j<d.length; j++) {
            o[d[j]]=o[d[j]] || {};
            o=o[d[j]];
        }
    }
    return o;
};

/**
 * declare(className)
 * 
 * Creates a new Prototype Class for the passed class name ID string.
 * For example: 
 * <pre>
 * XERO.declare("XERO.util.math") 
 * </pre> 
 * would create and return the new class instance XERO.util.math
 *
 * Be careful when naming packages. Reserved words may work in some browsers
 * and not others. For instance, the following will fail in Safari:
 * <pre>
 * XERO.namespace("really.long.nested.namespace");
 * </pre>
 * This fails because "long" is a future reserved word in ECMAScript
 *
 * @method 
 * @static
 * @param {String} Name of the class to create
 */
XERO.declare = function(className) {
    var a=arguments, o=null, i, j, d, classPath;
    d=className.split(".");
    o=XERO;
    classPath = "";
    for (j=0; j<d.length; j++) {
        classPath = classPath + d[j];
        if(j < d.length - 1) classPath += ".";
        if(typeof o[d[j]] == "undefined"){
            if((j < d.length - 1)){
                XERO.namespace(classPath);
            } else {
                eval(classPath + "=Class.create()");
            }
        }          
    } 
    var newClass = eval(classPath);
    newClass.prototype.className = classPath;    
    return newClass;
};

/**
 * inherit(subClass, baseClass)
 * 
 * Provides an easy method of inheriting from a base class.
 * When inheriting note that there is a base() method created to access the
 * base class.
 */
XERO.inherit = function(subClass, baseClass, baseFuncName) { 
    if(!baseClass) return;
    var inheritance = Class.create();
    inheritance.prototype = baseClass.prototype;
    Object.extend(subClass.prototype, new inheritance());
    subClass.prototype.constructor = subClass;
    subClass.prototype.initializeBase = function(baseClass){
        baseClass.prototype.initialize.apply(this, $A(arguments).splice(1));
    };
    if(!subClass.prototype.base) subClass.prototype.base = {};
    subClass.prototype.base[baseClass.className] = baseClass.prototype.initialize;
}

/**
 * Include .inherits on the Object prototype as a shortcut to XERO.inherit.
 * This will allow for easy chaining, such as XERO.declare("B").inherits("A")
 */
//TODO: Something is really iffy with this: prototype? Object? double quotes around "string"
Object.prototype.inherits = function(baseClass, baseFuncName){
    if(typeof baseClass == 'string'){
        XERO.namespace(baseClass);
        baseClass = eval(baseClass);
    }
    XERO.inherit(this, baseClass, baseFuncName);
    return this;
};

/**
 * getElementsByAttribute
 *
 * Provides functionality to get a list of elements by their attributes.
 * The attributes can be standard or custom.
 *
 * <pre>
 * <div id="container">
 *    <p custom="a"></p>
 *    <p custom="b"></p>
 * </div>
 * 
 * //each exmaple alerts "a" and "b"
 * document.getElementsByAttribute('custom').each(function(element){
 *     alert(element.getAttribute('custom'));
 * });
 * $('container').getElementsByAttribute('custom').each(function(element){
 *     alert(element.getAttribute('custom'));
 * });
 * </pre>
 */
document.getElementsByAttribute = function(attribute,parent) {
	return $A(($(parent) || document.body).getElementsByTagName('*')).inject([],function(elements,child){
		if(Element.readAttribute(child,attribute))
			elements.push(Element.extend(child));
		return elements;
	});
}

document.getElementsByAttributeValue = function(attribute,value,parent) {
	return $A(($(parent) || document.body).getElementsByTagName('*')).inject([],function(elements,child){
		if(Element.readAttribute(child,attribute) == value)
			elements.push(Element.extend(child));
		return elements;
	});
}

Element.addMethods({
	getElementsByAttribute: function(element,attribute){
		return document.getElementsByAttribute(attribute,element);
	},
	getElementsByAttributeValue: function(element,attribute,value){
		return document.getElementsByAttributeValue(attribute,value,element);
	}
});

/**

 * init()
 *
 * Sets up the XERO library, creates required namespaces and registers variables
 * as needed.
 */
XERO.init = function() {
    // Setup namespaces
    this.namespace("util","widget","ui");
};

/* Start the library */
XERO.init();

