﻿// 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" ? $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"
};
