﻿window.fast = new function() {

    var self = this;
    function FastObject(e) {
        var id = e;
        this.length = 1;
        if (e == "") {
            id = null;
            this.e = new Object();
            this.e.style = new Object();
        } else {
            this.e = (typeof e == "string" ? document.getElementById(e) : e);
        }
        this.create = function() { return this; };
        if (!this.e) {
            this.length = 0;

            if (typeof id == "string") {
                this.id = id;
                this.create = function(el, parent) {
                    var obj = document.createElement(el);
                    obj.id = id;
                    parent = parent || document.body;
                    parent = (parent.constructor == FastObject) ? parent : $(parent);
                    parent.e.appendChild(obj, false);
                    return new FastObject(obj);
                };
            };
        };
        return this;
    };

    var FastArray = function() {
        var x = [], a = arguments;
        for (var i = 0; i < a.length; i++) { x.push(a[i]) };
        for (var i in this) { x[i] = this[i] };
        return x;
    };
    FastArray.prototype = [];

    var pl = new Array();

    this.register = function(n, func) {
        pl.push({ n: n, func: func });
        FastObject.prototype[n] = func;
        FastArray.prototype[n] = function() {
            for (var i = 0, l = this.length; i < l; i++) {
                this[i][n].apply(this[i], arguments);
            };
            return this;
        };
    };

    //    this.extend = function(o) {
    //        for (var i = 0; i < pl.length; i++) {
    //            o[pl[i].n] = pl[i].func;
    //        }
    //        return o;
    //    }

    this.extend = function(name, func) {
        if (!self.extensions) {
            self.extensions = new Object();
        };
        self.extensions[name] = func;
    };

    var $ = function() {
        var o = null;
        var ao = null;

        var args = new Array();
        for (var i = 0; i < arguments.length; i++) {

            if (arguments[i].constructor == FastObject) {
                args.push(arguments[i].e);
            } else if (typeof arguments[i] != "string" && arguments[i].length && !arguments[i].tagName) {

                for (var j = 0; j < arguments[i].length; j++) {
                    args.push(arguments[i][j]);
                }

            } else if (typeof arguments[i] == "string") {
                var ids = arguments[i].split(",");
                for (var j = 0; j < ids.length; j++) {
                    if (ids[j].trim() != "") {
                        args.push(ids[j].trim());
                    };
                }

            } else {
                args.push(arguments[i]);
            }
        }

        var i = args.length;
        do {
            o = new FastObject(args[i - 1]);

            if (args.length == 1) {
                ao = o;
            } else {
                ao = ao ? ao : new FastArray();
                if (o.length) {
                    ao.push(o);
                }
            };

        } while ((--i) > 0);
        return ao;
    };
    window.$ = $;
    this.$ = $;

    //Get DOM elements based on the given CSS Selector - V 1.00.A Beta
    //http://www.openjs.com/scripts/dom/css_selector/
    function getElementsBySelector() {
        var args = new Array();
        for (var i = 0; i < arguments.length; i++) {
            args.push(arguments[i]);
        }

        var all_selectors = args.join(",");
        var selected = new Array();
        if (!document.getElementsByTagName) return selected;
        all_selectors = all_selectors.replace(/\s*([^\w])\s*/g, "$1"); //Remove the 'beutification' spaces
        var selectors = all_selectors.split(",");
        // Grab all of the tagName elements within current context	
        var getElements = function(context, tag) {
            if (!tag) tag = '*';
            // Get elements matching tag, filter them for class selector
            var found = new Array;
            for (var a = 0, len = context.length; con = context[a], a < len; a++) {
                var eles;
                if (tag == '*') eles = con.all ? con.all : con.getElementsByTagName("*");
                else eles = con.getElementsByTagName(tag);

                for (var b = 0, leng = eles.length; b < leng; b++) found.push(eles[b]);
            };
            return found;
        };

        COMMA:
        for (var i = 0, len1 = selectors.length; selector = selectors[i], i < len1; i++) {
            var context = new Array(document);
            var inheriters = selector.split(" ");

            SPACE:
            for (var j = 0, len2 = inheriters.length; element = inheriters[j], j < len2; j++) {
                //This part is to make sure that it is not part of a CSS3 Selector
                var left_bracket = element.indexOf("[");
                var right_bracket = element.indexOf("]");
                var pos = element.indexOf("#"); //ID
                if (pos + 1 && !(pos > left_bracket && pos < right_bracket)) {
                    var parts = element.split("#");
                    var tag = parts[0];
                    var id = parts[1];
                    var ele = document.getElementById(id);
                    if (!ele || (tag && ele.nodeName.toLowerCase() != tag)) { //Specified element not found
                        continue COMMA;
                    };
                    context = new Array(ele);
                    continue SPACE;
                };

                pos = element.indexOf("."); //Class
                if (pos + 1 && !(pos > left_bracket && pos < right_bracket)) {
                    var parts = element.split('.');
                    var tag = parts[0];
                    var class_name = parts[1];

                    var found = getElements(context, tag);
                    context = new Array;
                    for (var l = 0, len = found.length; fnd = found[l], l < len; l++) {
                        if (fnd.className && fnd.className.match(new RegExp('(^|\s)' + class_name + '(\s|$)'))) context.push(fnd);
                    }
                    continue SPACE;
                }

                if (element.indexOf('[') + 1) {//If the char '[' appears, that means it needs CSS 3 parsing
                    // Code to deal with attribute selectors
                    if (element.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?['"]?([^\]'"]*)['"]?\]$/)) {
                        var tag = RegExp.$1;
                        var attr = RegExp.$2;
                        var operator = RegExp.$3;
                        var value = RegExp.$4;
                    }
                    var found = getElements(context, tag);
                    context = new Array;
                    for (var l = 0, len = found.length; fnd = found[l], l < len; l++) {
                        if (operator == '=' && fnd.getAttribute(attr) != value) continue;
                        if (operator == '~' && !fnd.getAttribute(attr).match(new RegExp('(^|\\s)' + value + '(\\s|$)'))) continue;
                        if (operator == '|' && !fnd.getAttribute(attr).match(new RegExp('^' + value + '-?'))) continue;
                        if (operator == '^' && fnd.getAttribute(attr).indexOf(value) != 0) continue;
                        if (operator == '$' && fnd.getAttribute(attr).lastIndexOf(value) != (fnd.getAttribute(attr).length - value.length)) continue;
                        if (operator == '*' && !(fnd.getAttribute(attr).indexOf(value) + 1)) continue;
                        else if (!fnd.getAttribute(attr)) continue;
                        context.push(fnd);
                    }

                    continue SPACE;
                }

                //Tag selectors - no class or id specified.
                var found = getElements(context, element);
                context = found;
            }
            for (var o = 0, len = context.length; o < len; o++) selected.push(context[o]);
        }

        return selected;
    }

    window.$$ = function() {
        return $(getElementsBySelector.apply(document, arguments));
    };
    this.$$ = window.$$;

    this.register("style", function(prop, value) {
        if (typeof value == "undefined") {
            if (this.e.currentStyle) {

                var ar = prop.match(/\w[^-]*/g);
                var s = ar[0];

                for (var i = 1; i < ar.length; ++i) {
                    s += ar[i].replace(/\w/, ar[i].charAt(0).toUpperCase());
                }

                return this.e.currentStyle[s];
            } else if (document.defaultView.getComputedStyle) {
                return document.defaultView.getComputedStyle(this.e, null).getPropertyValue(prop);
            }
        } else {
            this.e.style[prop] = value;
            return this;
        };
    });

    this.register("hide", function() {
        this.e.style.display = "none";
        return this;
    });

    this.register("show", function() {
        this.e.style.display = "block";
        return this;
    });

    this.register("setClass", function(cn) {
        this.e.className = cn;
        return this;
    });

    this.register("removeClass", function(cn) {
        var l = new String(this.e.className).split(" ");
        if (l.indexOf(cn) > -1) {
            l.splice(l.indexOf(cn), 1);
        };
        this.e.className = l.join(" ");
        return this;
    });

    this.register("addClass", function(cn) {
        var l = new String(this.e.className).split(" ");
        if (l.indexOf(cn) == -1) {
            l.push(cn);
        };
        this.e.className = l.join(" ");
        return this;
    });

    this.register("setContent", function(data) {
        this.innerHTML = data;
        return this;
    });

    this.register("paste", function(data) {
        this.e.innerHTML = data;
        return this;
    });

    this.register("opacity", function(alpha) {
        if (typeof alpha == "undefined") {
            var c = this.style("opacity");
            c = (typeof c == "undefined" ? 1 : c);
            return parseInt(parseFloat(c) * 100);
        } else {
            this.e.style.opacity = alpha > 0 ? alpha / 100 : 0;
            this.e.style.filter = "alpha(opacity=" + alpha + ")";
            return this;
        };
    });

    this.register("pos", function() {
        var pos = { x: 0, y: 0 };
        var obj = this.e;
        if (obj.offsetParent) {
            do {
                pos.x += (obj.offsetLeft - obj.scrollLeft);
                pos.y += (obj.offsetTop - obj.scrollTop);
            } while (obj = obj.offsetParent);
        };
        pos.left = pos.x;
        pos.top = pos.y;
        return pos;
    });

    this.register("left", function(left) {
        var self = this;
        if (typeof left == "undefined") {
            return self.pos().left;
        } else {
            if (typeof left == "string") {
                self.e.style.left = left;
            } else {
                self.e.style.left = left + "px";
            }
            return this;
        };
    });

    this.register("top", function(top) {
        var self = this;
        if (typeof top == "undefined") {
            return self.pos().top;
        } else {
            if (typeof top == "string") {
                self.e.style.top = top;
            } else {
                self.e.style.top = top + "px";
            }
            return this;
        };
    });

    this.register("width", function(width) {
        var self = this;
        if (typeof width == "undefined") {
            var w = 0;
            with (this) {
                var op = style("padding");
                var od = style("display");
                style("display", "block").style("padding", "0");
                w = e.clientWidth;
                style("display", od).style("padding", op);
            };
            return w;
        } else {
            if (typeof width == "string") {
                self.e.style.width = width;
            } else {
                self.e.style.width = width + "px";
            }
            return this;
        };
    });

    this.register("height", function(height) {
        var self = this;
        if (typeof height == "undefined") {
            var h = 0;
            with (this) {
                var op = style("padding");
                var od = style("display");
                style("display", "block").style("padding", "0");
                h = e.clientHeight;
                style("display", od).style("padding", op);
            };
            return h;
        } else {
            if (typeof height == "string") {
                self.e.style.height = height;
            } else {
                self.e.style.height = height + "px";
            }
            return this;
        };
    });
};

if (!Array.prototype.indexOf){
	Array.prototype.indexOf = function(elt /*, from*/) {
		var len = this.length;
		var from = Number(arguments[1]) || 0;
		from = (from < 0)	
			? Math.ceil(from)
			: Math.floor(from);
		if (from < 0) {
			from += len;
		};
		for (; from < len; from++) {
			if (from in this && this[from] === elt)
				return from;
		};
		return -1;
	};
};

if( !String.prototype.trim ) {
	String.prototype.trim = function() {
		return this.replace(/^\s*/,'').replace(/\s*$/,'');
	};
};

window.fast.window = (new function() {

    this.width = function() {
        var myWidth = 0;
        if( typeof( window.innerWidth ) == 'number' ) {
            //Non-IE
            myWidth = window.innerWidth;
        } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
            //IE 6+ in 'standards compliant mode'
            myWidth = document.documentElement.clientWidth;
        } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
            //IE 4 compatible
            myWidth = document.body.clientWidth;
        }
        return myWidth; 
    };

    this.height = function() {
        var myHeight = 0;
        if( typeof( window.innerWidth ) == 'number' ) {
            //Non-IE
            myHeight = window.innerHeight;
        } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
            //IE 6+ in 'standards compliant mode'
            myHeight = document.documentElement.clientHeight;
        } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
            //IE 4 compatible
            myHeight = document.body.clientHeight;
        }
        return myHeight; 
    };

    this.scrollLeft = function() {
        var scrOfX = 0;
        if( typeof( window.pageYOffset ) == 'number' ) {
            //Netscape compliant
            scrOfX = window.pageXOffset;
        } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
            //DOM compliant
            scrOfX = document.body.scrollLeft;
        } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
            //IE6 standards compliant mode
            scrOfX = document.documentElement.scrollLeft;
        }
       return scrOfX; 
    }; 

    this.scrollTop = function() {
        var scrOfY = 0;
        if( typeof( window.pageYOffset ) == 'number' ) {
            //Netscape compliant
            scrOfY = window.pageYOffset;
        } else if( document.body && ( document.body.scrollLeft || document.body.scrollTop ) ) {
            //DOM compliant
            scrOfY = document.body.scrollTop;
        } else if( document.documentElement && ( document.documentElement.scrollLeft || document.documentElement.scrollTop ) ) {
            //IE6 standards compliant mode
            scrOfY = document.documentElement.scrollTop;
        }
       return scrOfY; 
    };

});
