/*
:: phyp.project :::::::::::::::::::
:: core.phyp.js.boot ::::::::::: :|
:: 20100119 ::::::::::::::::: @greg
*/

/** Shortcuts **/
var p = { };
var d = document;
var w = window;
var ie = !!d.all;

/// Popup
function pop(e) {
    e.blur();
    w.open(e.href);
    return false;
}

/// Now
function now() {
    var t = new Date();
    return t.getTime();
}

/// Array
Array.prototype.indexOf = function(v) {
    var i;
    for (i = 0; i < this.length; i++)
	if (this[i] == v)
	    return i;
    return -1;
};
Array.prototype.inArray = function(v) {
    return this.indexOf(v) != -1;
};
Array.prototype.except = function(v) {
    if (!this.inArray(v))
	return this;
    var i, vs = [ ];
    for (i = 0; i < this.length; i++)
	if (this[i] != v)
	    vs.push(this[i]);
    return vs;
};

/// String
String.prototype.sub = function(a, b) {
    if (a < 0) a += this.length;
    if (b == null) return this.substring(a);
    if (b < 0) b += this.length;
    return this.substring(a, b);
};
String.prototype.ucFirst = function() {
    if (!this) return '';
    return this.charAt(0).toUpperCase() + this.sub(1);
};
String.prototype.lcFirst = function() {
    if (!this) return '';
    return this.charAt(0).toLowerCase() + this.sub(1);
};
String.prototype.firstUp = function(offset) {
    var i;
    if (!this) return -1;
    if (!offset) offset = 0;
    for (i = offset; i < this.length; i++)
	if (this.charAt(i).toUpperCase() == this.charAt(i))
	    return i;
    return -1;
};
String.prototype.firstChar = function() {
    return this.charAt(0);
};
String.prototype.lastChar = function() {
    return this.charAt(this.length - 1);
};
String.prototype.toCss = function() {
    if (this == 'float')
	return ie? 'styleFloat': 'cssFloat';
    if (this.indexOf('-') == -1)
	return this;
    var t;
    var ss = this.split('-');
    t = ss.shift();
    while (ss.length)
	t += ss.shift().ucFirst();
    return t;
};

/// DOM constructor
function dom(tag, atts, nodes) {
    return new Node(tag, atts, nodes);
}

/// Class
function Node(tag, atts, nodes) {
    // Element
    if (tpo(tag)) {
	this.e = tag;
	return;
    }
    var i, s, e;
    // Switch
    if (!tpo(atts)) {
	s = atts;
	atts = (tpo(nodes))? nodes: { };
	nodes = s;
    }
    if (!tps(tag)) {
	return false;
    }
    // Classname
    if (tag.indexOf('.') != -1) {
	s = tag.split('.');
	tag = s[0];
	atts['class'] = s[1];
    }
    // Element
    e = d.createElement(tag);
    for (i in atts) {
	if (tpf(atts[i]))
	    continue;
	try {
	    if (i == 'class')
		e.className = atts[i];
	    else e.setAttribute(i, atts[i]);
	} catch(err) { alert(err + '\n' + tag + ', ' + i + ', ' + atts[i]); }
    }
    // Nodes
    if (nodes) {
	if (!tpo(nodes) || nodes.e)
	    nodes = { 'node': nodes };
	for (i in nodes) {
	    if (tpf(nodes[i]))
		continue;
	    if (tps(nodes[i]) || tpn(nodes[i]))
		e.appendChild(d.createTextNode(nodes[i]));
	    else {
		try {
		    e.appendChild(nodes[i].e);
		} catch(err) {
		    alert(err + ': ' + nodes[i]);
		}
	    }
	}
    }
    this.e = e;
}

/// Attributes
Node.prototype.getAtts = function() { return this.e.attributes; };
Node.prototype.getAtt = function(att) { return this.e.getAttribute(att); };
Node.prototype.setAtt = function(att, v) { this.e.setAttribute(att, v); return this; };
Node.prototype.rmAtt = function(att) { this.e.removeAttribute(att); return this; };
Node.prototype.rmAtts = function(atts) {
    var i;
    for (i = 0; i < atts.length; i++)
	this.rmAtt(atts[i]);
    return this;
};
Node.prototype.setAtts = function(atts) {
    var att;
    for (att in atts)
	if (nf(atts[att]))
	    this.setAtt(att, atts[att]);
    return this;
};

/// Insert, move & remove
Node.prototype.append = function(m) {
    var i;
    if (!m.e)
	for (i = 0; i < m.length; i++)
	    this.e.appendChild(m[i].e);
    else this.e.appendChild(m.e);
    return this;
};
Node.prototype.insert = function(m, n) {
    var i;
    if (!m.e)
	for (i = 0; i < m.length; i++)
	    this.e.insertBefore(m[i].e, n.e);
    else this.e.insertBefore(m.e, n.e);
    return this;
};
Node.prototype.after = function(m) { m.parent().insert(this, m.next()); return this; };
Node.prototype.before = function(m) { m.parent().insert(this, m); return this; };
Node.prototype.remove = function(m) { this.e.removeChild(m.e); return this; };
Node.prototype.shift = function() { var e = this.first(); this.remove(e); return e; };
Node.prototype.unshift = function(m) { this.first().before(m); return this; };
Node.prototype.pop = function() { var e = this.last(); this.remove(e); return e; };
Node.prototype.detach = function() { this.parent().remove(this); return this; };
Node.prototype.moveEnd = function() { var f = this.parent(); f.remove(this); f.append(this); return this; };
Node.prototype.moveAfter = function(m) { return this.detach().after(m); };
Node.prototype.moveBefore = function(m) { return this.detach().before(m); };

/// Childnodes
Node.prototype.length = function() { return this.e.childNodes.length; };
Node.prototype.node = function(i) { return dom(this.e.childNodes[parseInt(i)]); };
Node.prototype.index = function() {
    var i, f = this.parent();
    for (i = 0; i < f.length(); i++)
	if (f.node(i).e == this.e)
	    return i;
    return -1;
};
Node.prototype.first = function() { return dom(this.e.firstChild); };
Node.prototype.last = function() { return dom(this.e.childNodes[this.e.childNodes.length - 1]); };
Node.prototype.gfirst = function() { return this.first().first(); };
Node.prototype.clear = function(n) { n |= 0; while (this.length() > n) this.shift(); return this; };
Node.prototype.truncate = function(n) { n |= 0; while (this.length() > n) this.pop(); return this; };

/// Siblings
Node.prototype.previous = function(txt) {
    if (!this.e.previousSibling)
	return false;
    var m = dom(this.e.previousSibling);
    return (!m.name() && !txt)? m.previous(): m;
};
Node.prototype.next = function(txt) {
    if (!this.e.nextSibling)
	return false;
    var m = dom(this.e.nextSibling);
    return (!m.name() && !txt)? m.next(): m;
};

/// Parents
Node.prototype.parent = function() { return dom(this.e.parentNode); };
Node.prototype.gparent = function() { return this.parent().parent(); };

/// Elements
Node.prototype.id = function(id) { return dom(this.e.getElementById(id)); };
Node.prototype.tags = function(tag) {
    var i;
    var ms = [ ];
    var es = this.e.getElementsByTagName(tag);
    for (i = 0; i < es.length; i++)
	ms.push(dom(es[i]));
    return ms;
};
Node.prototype.tag = function(tag) { return this.tags(tag)[0]; }
Node.prototype.classNodes = function(c) {
    var i;
    var ms = [ ];
    var es = this.e.all || this.e.getElementsByTagName('*');
    for (i = 0; i < es.length; i++)
	if (es[i].className && es[i].className.split(' ').inArray(c))
	    ms.push(dom(es[i]));
    return ms;
};
Node.prototype.classNode = function(c) { return this.classNodes(c)[0]; };
Node.prototype.attNodes = function(att) {
    var i;
    var ms = [ ];
    var es = this.e.all || this.e.getElementsByTagName('*');
    for (i = 0; i < es.length; i++)
	if (es[i].attributes && es[i].getAttribute(att) != null)
	    ms.push(dom(es[i]));
    return ms;
};
Node.prototype.attNode = function(att) { return this.attNodes(att)[0]; };

/// Frames
Node.prototype.body = function() { return this.doc()? dom(this.doc().e.body): false; };
Node.prototype.doc = function() {
    var doc;
    if (this.e.contentDocument) doc = this.e.contentDocument; // NS6
    else if (this.e.contentWindow) doc = this.e.contentWindow.document; // IE5.5, IE6
    else if (this.e.document) doc = this.e.document; // IE5
    else {
	return false;
    }
    return dom(doc);
};

/// Contents
Node.prototype.clone = function(a) { return new node(this.e.cloneNode(a)); }
Node.prototype.html = function(h) {
    if (h == null)
	return this.e.innerHTML;
    this.e.innerHTML = h;
    return this;
};
Node.prototype.text = function(t) {
    if (ie) return (t == null)? this.e.innerText: this.e.innerText = t;
    if (t == null)
	return this.e.textContent;
    this.e.textContent = t;
    return this;
};
Node.prototype.name = function() {
    if (!this.e.nodeName) return false;
    var n = this.e.nodeName.toLowerCase();
    return (n.firstChar() == '#')? '': n;
};
Node.prototype.submit = function() { this.e.submit(); return this; };
Node.prototype.focus = function() { this.e.focus(); return this; };
Node.prototype.blur = function() { this.e.blur(); return this; };
Node.prototype.select = function() { this.e.select(); return this; };
Node.prototype.enable = function() { this.e.disabled = false; return this; };
Node.prototype.disable = function() { this.e.disabled = true; return this; };

/// CSS
Node.prototype.css = function(c, on) {
    var cs = this.e.className.split(' ');
    if (c == null)
	return cs;
    if (on == null) {
	this.e.className = c;
    } else {
	if (on && !cs.inArray(c)) cs.push(c);
	if (!on) cs = cs.except(c);
	this.e.className = cs.join(' ');
    }
    if (!this.e.className)
	this.rmAtt('class');
    return this;
};
Node.prototype.toggle = function(a, b) {
    if (this.css().inArray(a)) {
	this.css(a, false);
	this.css(b, true);
    } else {
	this.css(b, false);
	this.css(a, true);
    }
    return this;
};

/// Style
Node.prototype.getStyle = function(s) { return this.e.style[s.toCss()]; };
Node.prototype.setStyle = function(s, v) { return this.e.style[s.toCss()] = v; };
Node.prototype.setStyles = function(ss, r) {
    var s;
    if (!r) r = '';
    for (s in ss) {
	if (tpf(ss[s]) || ss[s] == null)
	    continue;
	if (tpo(ss[s]))
	    this.setStyles(ss[s], r + s + '-');
	else this.setStyle(r + s, ss[s]);
    }
};
Node.prototype.getAlpha = function() {
    var a, m;
    if (ie) {
	a = this.getStyle('filter');
	if (a.match(/opacity=([0-9]+),/, m))
	    return m[1] / 100;
	return 1;
    }
    return this.getStyle('opacity');
};
Node.prototype.setAlpha = function(a) {
    if (ie) {
	if (a == null) this.setStyle('filter', '');
	else this.setStyle('filter', 'Alpha(Opacity=' + round(a * 100) + ')');
    } else {
	if (a == null) this.setStyle('opacity', '');
	else this.setStyle('opacity', a);
    }
    return this;
};

/// Types
function type(i) { return (typeof i); };
function tpo(i) { return type(i) == 'object'; };
function tpf(i) { return type(i) == 'function'; };
function tps(i) { return type(i) == 'string'; };
function tpb(i) { return type(i) == 'boolean'; };
function tpn(i) { return type(i) == 'number'; };
function tpu(i) { return type(i) == 'undefined'; };
function nf(i) { return !tpf(i); };

/// Math
function abs(f) { return tpn(f)? Math.abs(f): 0; }
function round(f) { return tpn(f)? Math.round(f): 0; }
function floor(f) { return tpn(f)? Math.floor(f): 0; }
function ceil(f) { return tpn(f)? Math.ceil(f): 0; }
function sqrt(f) { return tpn(f)? Math.sqrt(f): 0; }
function pow(f, a) { return tpn(f)? Math.pow(f, a): 0; }
function max(a, b) { return Math.max(a, b); }
function min(a, b) { return Math.min(a, b); }
function between(a, b, c) { return min(c, max(a, b)); }

/// HTML
var h = dom(d);

