﻿// Prototypes
Array.prototype.append = function(collection) { for (var c = 0; c < collection.length; c++) this.push(collection[c]); };
String.prototype.clean = function() { return this.replace(/\s*([^\w\]\.]|\,)\s*/g, "$1"); };

// qUI Object Query Methods
var $get = function(object) {
    var base = (typeof object === "object" ? object : (
    typeof object === "function" ? new object() : (
    typeof object === "string" ? 
        document.getElementById(object) ? document.getElementById(object) : $query(object) : null)));
    if (base !== null) {
        base.css = function(style, value) {
            style = ($properties[style] !== undefined ? $properties[style] : style);
            if (base instanceof Array) for (var i = 0; i < base.length; i++) base[i].style[style] = value;
            else base.style[style] = value;
        };
        base.fadeIn = function(settings) {
            var base = this;
            settings = (settings !== undefined ? settings : {});
            if (settings.timeout) window.clearTimeout(settings.timeout);
            if (base.opacity < 100) {
                base.setOpacity(base.opacity + (settings.increment ? settings.increment : 1));
                settings.timeout = window.setTimeout(function() { base.fadeIn(settings); }, (settings.speed || 100));
            } else {
                base.setOpacity(100)
                if (settings.callback && typeof settings.callback === "function") settings.callback();
            };
        };
        base.fadeOut = function(settings) {
            var base = this;
            settings = (settings !== undefined ? settings : {});
            if (settings.timeout) window.clearTimeout(settings.timeout);
            if (base.opacity > 0) {
                base.setOpacity(base.opacity - (settings.increment ? settings.increment : 1));
                settings.timeout = window.setTimeout(function() { base.fadeOut(settings); }, (settings.speed || 100));
            } else {
                base.setOpacity(0)
                if (settings.callback && typeof settings.callback === "function") settings.callback();
            };
        };
        base.fadeTo = function(settings) {
            var base = this;
            settings = (settings !== undefined ? settings : {});
            if (settings.timeout) window.clearTimeout(settings.timeout);
            if (base.opacity !== settings.opacity || base.opacity > 100 || base.opacity < 0) {
                if (base.opacity > settings.opacity) {
                    base.setOpacity(base.opacity - (settings.increment ? settings.increment : 1));
                } else {
                    base.setOpacity(base.opacity + (settings.increment ? settings.increment : 1));
                };
                settings.timeout = window.setTimeout(function() { base.fadeTo(settings); }, (settings.speed || 100));
            } else {
                base.setOpacity(settings.opacity)
                if (settings.callback && typeof settings.callback === "function") settings.callback();
            };
        };
        base.first = function() {
            var f = this.firstChild; while (f && (f.nodeType === 8 || f.nodeType === 3)) f = f.nextSibling; return $get(f);
        };
        base.hide = function() {
            base.style["display"] = "none";
        };
        base.last = function() {
            var l = this.lastChild; while (l && (l.nodeType === 8 || l.nodeType === 3)) l = l.previousSibling; return $get(l);
        };
        base.opacity = (base.opacity ? base.opacity : 100);
        base.setOpacity = function(opacity) {
            base.opacity = opacity;
            base.css((window.ActiveXObject ? "filter" : "opacity"), (window.ActiveXObject ? "alpha(opacity=" + opacity + ")" : (opacity / 100)));
        };
        base.show = function(display) {
            base.style["display"] = (display !== null ? display : "");
        };
        if (base instanceof Array) for (var i = 0; i < base.length; i++) base[i] = $get(base[i]);
    };
    return base;
};

var $query = function(value) {
    var selectors = value.clean().match(/((\w*)(\.|\#|\s|\w)[^\,\s]*)+/g),
    xpaths = value.clean().match(/(\w*\s*)\[[^\,]*\][^\,]*/g),
    results = [];
    var filter = function(filter) {
        switch (filter.value) {
            case ":first-child": var f = $get(filter.object).first(); return f;
            case ":last-child": var l = $get(filter.object).last(); return l;
            default: return filter.object; break;
        };
    };
    var process = function(query) {
        var queries = query.value.split(" "), context = document;
        for (var q = 0; q < queries.length; q++) {
            if (query.method === "selector") {
                var filters = queries[q].match(/(\.|\#|\:|^)[^\.\#\:]+/g);
                if (filters[0].indexOf("#") !== -1 || (filters[1] && filters[1].indexOf("#") !== -1)) {
                    if (filters[0].indexOf("#") === -1) filters.shift();
                    context = document.getElementById(filters.shift().replace("#", ""));
                    if (filters.length > 0) context = filter({ object: context, value: filters[0] });
                } else if (filters[0].indexOf(".") !== -1 || (filters[1] && filters[1].indexOf(".") !== -1)) {
                    element = (filters[0].indexOf(".") === -1 ? filters.shift() : "*");
                    context = retrieve({ object: (context instanceof Array ? context : [context]), element: element, filters: filters });
                } else {
                    context = retrieve({ object: (context instanceof Array ? context : [context]), element: filters.shift(), filters: filters });
                };
            };
        };
        return context;
    };

    var retrieve = function(query) {
        var results = [], elements = [];
        for (var o = 0; o < query.object.length; o++) { elements.append(query.object[o].getElementsByTagName(query.element)); };
        for (var e = 0; e < elements.length; e++) {
            if (query.filters[0] && query.filters[0].indexOf(".") !== -1) {
                if (elements[e].className === query.filters[0].replace(".", "")) results.push(filter({ object: elements[e], value: query.filters[1] }));
            } else {
                results.push(filter({ object: elements[e], value: query.filters[0] }));
            };
        };
        return results;
    };
    for (var s = 0; s < selectors.length; s++) {
        var r = process({ method: "selector", value: selectors[s] });
        if (r instanceof Array) { results.append(r); } else { results.push(r); };
    };
    return (results.length === 1 ? results[0] : results);
};

// CSS Properties to JavaScript Properties List
var $properties = {
    "background-attachment": "backgroundAttachment", "background-color": "backgroundColor", "background-image": "backgroundImage",
    "background-position": "backgroundPosition", "background-repeat": "backgroundRepeat", "border-bottom": "borderBottom",
    "border-bottom-color": "borderBottomColor", "border-bottom-style": "borderBottomStyle", "border-bottom-width": "borderBottomWidth",
    "border-color": "borderColor", "border-left": "borderLeft", "border-left-color": "borderLeftColor", "border-left-style": "borderLeftStyle",
    "border-left-width": "borderLeftWidth", "border-right": "borderRight", "border-right-color": "borderRightColor",
    "border-right-style": "borderRightStyle", "border-right-width": "borderRightWidth", "border-style": "borderStyle", "border-top": "borderTop",
    "border-top-color": "borderTopColor", "border-top-style": "borderTopStyle", "border-top-width": "borderTopWidth", "border-width": "borderWidth",
    "float": "styleFloat", "font-family": "fontFamily", "font-size": "fontSize", "font-variant": "fontVariant", "font-weight": "fontWeight",
    "letter-spacing": "letterSpacing", "line-height": "lineHeight", "list-style": "listStyle", "list-style-image": "listStyleImage",
    "list-style-position": "listStylePosition", "list-style-type": "listStyleType", "margin-bottom": "marginBottom", "margin-left": "marginLeft",
    "margin-right": "marginRight", "margin-top": "marginTop", "padding-bottom": "paddingBottom", "padding-left": "paddingLeft",
    "padding-right": "paddingRight", "padding-top": "paddingTop", "page-break-after": "pageBreakAfter", "page-break-before": "pageBreakBefore",
    "text-align": "textAlign", "text-decoration": "textDecoration", "text-decoration: blink": "textDecorationBlink",
    "text-decoration: line-through": "textDecorationLineThrough", "text-decoration: none": "textDecorationNone",
    "text-decoration: overline": "textDecorationOverline", "text-decoration: underline": "textDecorationUnderline", "text-indent": "textIndent",
    "text-transform": "textTransform", "vertical-align": "verticalAlign", "z-index": "zIndex"
};
