/*
Element.extras.js
An extended library to handle DOM Elements
Works with Element 3+

Documentation at http://barney.wallst.com/wsodwiki/index.php/Element.2.js_:Dev

Element.isInsideOf 
Element.isInsideOfNS 
Element.isInsideOfEW 
Element.debug
Element.setOpacity 
Element.setDisabled

ElementObject (dom style syntax element commands)

*/




Element_class.prototype.getParentBySelector = function(el, selector, includeSelf) {

	el = this.get(el);
	var pNode = includeSelf ? el : el.parentNode; 

	selector = selector.replace(/\s+/," ").split(" ");
	var levels = selector.length;
	var level = 0;
	var selectorType, isMatch, isTag, isClass;

	function getSelectorType() {
		var sel = selector[level];
		
		selectorType = {tag:sel}; // assume tag selection if nothing below passes

		// id
		if (sel.match(/(\D*)\#(\D*)/)) { selectorType.tag = RegExp.$1; selectorType.id= RegExp.$2; }

		// css attribute
		else if(sel.match(/(.*)\[([^^$*]*?)((\*=|\$=|\^=|=)+["'](.*)["'])?]/)) {
			selectorType.tag = RegExp.$1; selectorType.attribute = RegExp.$2; selectorType.operator = RegExp.$4; selectorType.value = RegExp.$5;
		}

		// class
		else if (sel.match(/(\D*)\.(\D*)/)) { selectorType.tag = RegExp.$1; selectorType.className = RegExp.$2; }

	}

	getSelectorType();
	// loop through parent nodes checking for selector
	while (pNode && !pNode.tagName.match(/^BODY$/i)) {

		isMatch = false;
		isTag = pNode.tagName.match(new RegExp("^"+selectorType.tag.replace(/([*])/,"\\$1")+"$","i")) || selectorType.tag == "*" || selectorType.tag == "";
		isClass = selectorType.className && this.hasClass(pNode,selectorType.className);

		if (isTag && selectorType.attribute) {
			var att = pNode.getAttribute(selectorType.attribute);
			if (!selectorType.operator) {
				if (att) isMatch = true;
			}
			else { 
				switch(selectorType.operator){
					case '*=': ;if (att.match(selectorType.value)) isMatch = true; break;
					case '=': if (att == selectorType.value) isMatch = true; break;
					case '^=': if (att.match('^'+selectorType.value)) isMatch = true; break;
					case '$=': if (att.match(selectorType.value+'$')) isMatch = true;
				}	
			}
		}
		else if (isTag) {
			if (isClass) { isMatch = true; }
			else if (selectorType.tag && !selectorType.className) { isMatch = true; }
			else if (selectorType.id && pNode.getAttribute("id") == selectorType.id) { isMatch = true; }

		}
		else if (isTag  && isClass) { isMatch = true; }

		if (isMatch) {
			if (level == levels-1) {
				return pNode;
			}
			level++;
			getSelectorType();
		}

		pNode = pNode.parentNode || null;

	}

	return null; // no match

}



Element_class.prototype.isOnScreen = function(el,considerPosition) {

	el = Element.get(el); if (!el) { return false; }
	var pNode = el;
	while(pNode && pNode.tagName.toUpperCase() != "HTML") {
		//alert(pNode.style.display + " " + pNode.tagName + (pNode.id?("#"+pNode.id):"") + " + " + Element.getStyle(pNode,"display"))
		var curStyle = Element.getStyle(pNode,"display");
		if (curStyle == "none" || curStyle == null || Element.getStyle(pNode,"visibility") == "hidden") {
			return false;
		}
		pNode = pNode.parentNode;
	}

	if (considerPosition) {
		var elPos = Element.getXY(el);
		if (elPos.x < 0 || elPos.y < 0) {
			return false;
		}
	}

	return true;
}



Element_class.prototype.isInsideOf = function(pos, x, y, width, height) {
	if (this.isInsideOfEW(pos, width, x) && this.isInsideOfNS(pos, height, y)) {
		return true;
	}
	return false;
};

Element_class.prototype.isInsideOfEW = function(pos, width, x) {
	if (x > pos.x && x < pos.x + width) {
		return true;
	}
	return false;
};

Element_class.prototype.isInsideOfNS = function(pos, height, y) {
	if (y > pos.y && y < pos.y + height) {
		return true;
	}
	return false;
};


Element_class.prototype.setOpacity = function(el, opacity) {

	el = this.get(el); 	if (!el) return;


	if (!this.isArray(el)) {
		el = [el]
	}

	for (var i=0; i<el.length; i++) {	


		//try{
			//opacity = (opacity == 100) ? 99.999 : opacity;
			// IE/Win
			el[i].style.filter = "alpha(opacity:"+opacity+")";
	
			// Safari<1.2, Konqueror
			el[i].style.KHTMLOpacity = opacity/100;
	
			// Older Mozilla and Firefox
			el[i].style.MozOpacity = opacity/100;
	
			// Safari 1.2, newer Firefox and Mozilla, CSS3
			el[i].style.opacity = opacity/100;
		//}catch(e){
			//dbg("error setting opacity");
		//}

	}
};


Element_class.prototype.setProperty = function(el,prop,val) {

	el = this.get(el);

	if (!this.isArray(el)) {
		el = [el]
	}
	for (var i=0; i<el.length; i++) {
		el[i][prop] = val;
	}

};

Element_class.prototype.setAttribute = function(el,prop,val) {

	el = this.get(el);

	if (!this.isArray(el)) {
		el = [el]
	}
	for (var i=0; i<el.length; i++) {
		el[i].setAttribute(prop,val);
	}

};

Element_class.prototype.setDisabled = function(el, bool) {
	this.setProperty(el,"disabled",!!bool); // absolute boolean
};


Element_class.prototype.debug = function(el,ElementObjectInstance) {


	var output = [];
	output.push("---------------------------");
	if (ElementObjectInstance) { output.push("Selector: " + ElementObjectInstance.selector); }

	var els = (el instanceof Array) ? el : [el];
	var pos, size;

	for (var i=0; i<els.length;i++) {
		if (els.length > 1) { output.push(i + ": " + (els[i].tagName || "")); }

		pos = this.getXY(els[i]);

		size= this.getSize(els[i]);
		output.push("  x: " + pos.x + " y: " + pos.y + " / w: " + size.width + " h: " + size.height);

		//output.push("  Style: " + this.getStyle(els[i]));
		if (els[i].className) { output.push("  Class: " + (els[i].className)) };
		if (els[i].id) { output.push("  Id: " + (els[i].id )); }
		output.push("");
	}

	return output.join("\n")+"\n";
}




Element = new Element_class();




/*
	var eObj = new ElementObject("h2");
	eObj.setStyle("color:red");
*/
function ElementObject(el) {

	this.selector = (typeof el == "string") ? el : "element";
	this.elementInstance = new Element_class();

	this.el = this.elementInstance.isArray(el) ? el :this.elementInstance.get(el);

	if (!this.el) {
		this.el = this.elementInstance.parseSelector(arguments[0],arguments[1]||null,arguments[2]||null); // allow parseSelector parent/which to come through
	}

	var noChangeMethodsRE = new RegExp(/_getClassnameRegEx|isArray|isInsideOf/);
	var mName;
	for (var i in this.elementInstance) {
		mName = i;
		if (noChangeMethodsRE.test(i)) { // these don't take the element as an argument
			this[mName] = hitch(this.elementInstance,mName,false);	
		}
		else if (/parseSelector/.test(i)) { // these take parent as last param
			this[mName] = hitchAppend(this.elementInstance,mName,false,this.el);	
		}
		else if (/create|debug/.test(i)) {
			this[mName] = hitchAppend(this.elementInstance,mName,false,this.el,this)
		}
		else {
			this[mName] = hitchAppend(this.elementInstance,mName,true,this.el)
		}
	}

	//dwO(this.elementInstance.parseSelector)

	function hitch(obj, methodName) {
		return function() { 
			return obj[methodName].apply(obj, arguments);
		};
	}
	
	// appends or preappends additional arguments to method
	function hitchAppend(obj, methodName, bAppend) {
		//dwO(methodName + " - " +  bAppend)
		var args = [];
		for (var i = 3; i < arguments.length; i++) {
			args.push(arguments[i]);
		}
	
		return function() { 
			var args2 = [];
			for (var i = 0; i < arguments.length; i++) {
				args2.push(arguments[i]);
			}
			return obj[methodName].apply(obj, bAppend?args.concat(args2):args2.concat(args));
		};
	}
}

ElementObject.prototype.toString = function() {


	return this.debug();


}
