/*
 * JavaScript dom framework: js
 * Version 0.2.0a
 * Dmitrij Sosnovsenko
 * biodiscus@gmail.com
 *
 * last update: 2011-12-13
 */

/**
 * Methods for DOM
 *
 * required: js_core.js
 * required: js_css.js
 */

//Quirks or Standards mode
//js.body= (document.compatMode == 'CSS1Compat' && /*!js.browser.opera*/ !document.body) ? document.documentElement : document.body;

/*
js.body= function(){
	if(document.compatMode == 'CSS1Compat' && !js.browser.opera && !js.browser.chrome){
		return document.documentElement;
	}else{
		return document.body;
	}
}
*/

;js.iframeDoc= function(elm){
	var doc= null;
	if(elm.contentDocument){doc= elm.contentDocument;}
	else if(elm.contentWindow){doc= elm.contentWindow.document;}
	else if(elm.document){doc= elm.document;}
	return doc;
}

//Get element & value from functions arguments. Used by function with GET || SET methode
js.getArgs= function(arg){
	var args= {'elm':undefined,'val':undefined}
	for(var i=0;i<arg.length&&i<2;i++){
		if(typeof arg[i] == 'object'){args.elm= arg[i];}else
		if(typeof arg[i] == 'string' || typeof arg[i] == 'number'){args.val= arg[i];}
	}
	return args;
}

js.isBody= function(elm){
	var elm= elm.tagName.toLowerCase();
	return (elm == 'body' || elm == 'html');
}

js.getWindowWidth= function(){
	//return js.body.clientWidth;
}

js.getWindowHeight= function(){
	//return js.body.clientHeight;
}

js.getDocumentWidth= function(){
	//return js.body.clientWidtht + js.body.o;
}

js.getDocumentHeight= function(){
	//return js.body.clientHeight + js.body.o;
}

/*js.getDocumentSize= function(){
	return {w:js.getDocumentWidth(),h:js.getDocumentHeight()}
}*/

// http://www.softcomplex.com/docs/get_window_size_and_scrollbar_position.html
// on site reload in IE scroll ist immer 0!
js.getScroll= function(elm){
	var x,y= 0;
	if(!elm || js.isBody(elm)){
		if(!document.body){return{x:0, y:0}}
		x= Math.max(document.documentElement.scrollLeft, document.body.scrollLeft);
		y= Math.max(document.documentElement.scrollTop, document.body.scrollTop);
	}else{
		x= elm.scrollLeft;
		y= elm.scrollTop;
	}
	return{x:x, y:y}
}

js.height= function(){// #
	var args= js.getArgs(arguments);
	return js.element.size((args.elm || this.elm),'height','',args.val);
}
js.innerHeight= function(){
	var args= js.getArgs(arguments);
	return js.element.size((args.elm || this.elm),'height','inner',args.val);
}
js.outerHeight= function(){
	var args= js.getArgs(arguments);
	return js.element.size((args.elm || this.elm),'height','outer',args.val);
}
js.width= function(){// #
	var args= js.getArgs(arguments);
	return js.element.size((args.elm || this.elm),'width','',args.val);
}
js.innerWidth= function(){
	var args= js.getArgs(arguments);
	return js.element.size((args.elm || this.elm),'width','inner',args.val);
}
js.outerWidth= function(){
	var args= js.getArgs(arguments);
	return js.element.size((args.elm || this.elm),'width','outer',args.val);
}

// http://paularmstrongdesigns.com/projects/basejs/docs/
js.element= {

	/**
	* js.element.create('div',{id:'d1',style:{width:'200px',opacity:50,color:'#FF0000'}},'<span>content</span>')
	* js.element.create('div',{id:'iframe1',name:'iframe1',src:'javascript:false;',style:{width:'10px',height:'10px',position:'absolute',top:0,left:0;}},'')
	*/
	create: function(tag,attrs,content){
		var elm;
		if(tag == 'iframe'){elm= js.dom.create('<iframe name="'+attrs.name+'"></iframe>')} // IE bugfix: don't create attr 'name' if so it do -  elm['name']= 'name123';
		//if(tag == 'iframe'){elm= js.dom.create('<iframe></iframe>')}
		else{elm= document.createElement(tag)}
		var attr;
		for(attr in attrs){
			if(attr == 'style'){
				js.elm= elm; // anonyme for JS
				js.css(attrs[attr]);
				continue;
			}else{
				js.element._attr(elm, attr, attrs[attr]);
			}
		}
		if(content){try{elm.innerHTML= content}catch(e){}}
		return elm;
	},

	/**
	* parce style string to css object
	* opacity:20; width:30px => {opacity:20,width:30px}
	*/
	/*parseStyle: function(style){
		style= style.replace(';',',');
		var css;
		eval('css=({'+style+'})');
		return css;
	},
	parseStyle1: function(style){
		style= style.split(';');
		var len= style.length;
		var css;
		var s;
		for(var i=0;i>len;i++){
			s= style[i].split(':');
			css[s[0]]=s[1];
		}
		return css;
	},*/

	position: function(elm){
		var rect= elm.getBoundingClientRect();
		var body = document.body;
		var docElm = document.documentElement;
		var scroll= {x:0,y:0};
		js.support.getBoxModel(elm);
		if(js.getStyle(elm,'position') != 'fixed' /*&& js.support.borderBox*/){
			scroll= js.getScroll();
		}

		var clientX = docElm.clientLeft || body.clientLeft || 0;
		var clientY = docElm.clientTop || body.clientTop || 0;

		var x= rect.left + scroll.x - clientX;
		var y= rect.top  + scroll.y - clientY;
		return {x: x,y: y}
	},

	// GET - if val is undefined
	// SET - if is val
	// elm - object of element
	// param - width | height
	// opt - outer | inner
	// val - for SET, value in unit (px,em,..)
	size: function(elm,param,opt,val){
		var o,v;
		if(elm == document){elm= document.getElementsByTagName("body")[0];}
		if(param == 'width'){
			o= ['left','right'];
			//if(elm == document){elm= js.body}
			v= elm.offsetWidth;
		}else
		if(param == 'height'){
			o= ['top','bottom'];
			v= elm.offsetHeight;
		}else{return false;}
		// GET
		if(val == undefined){
			v= parseFloat(v);
			if(opt == 'outer'){
				v+= js.toInt(js.getStyle(elm,'margin-'+o[0])) + js.toInt(js.getStyle(elm,'margin-'+o[1]));
			}else
			if(opt == 'inner'){
				v-= js.toInt(js.getStyle(elm,'padding-'+o[0])) + js.toInt(js.getStyle(elm,'padding-'+o[1])) + js.toInt(js.getStyle(elm,'border-'+o[0]+'-width')) + js.toInt(js.getStyle(elm,'border-'+o[1]+'-width'));
			}
			return v;
		}
		// SET
		var unit= js.formatOf(val);
		if(opt == 'outer'){
			if(unit[3] == 'px'){
				val= (unit[2] - js.toInt(js.getStyle(elm,'padding-'+o[0])) - js.toInt(js.getStyle(elm,'padding-'+o[1])) - js.toInt(js.getStyle(elm,'border-'+o[0]+'-width')) - js.toInt(js.getStyle(elm,'border-'+o[1]+'-width')) - js.toInt(js.getStyle(elm,'margin-'+o[0])) - js.toInt(js.getStyle(elm,'margin-'+o[1])) ) + 'px';
			}
		}else
		if(opt == 'inner'){
			val= unit[2]+unit[3]; // h + unit (px,..)
		}else{
			if(unit[3] == 'px'){
				val= (unit[2] - js.toInt(js.getStyle(elm,'padding-'+o[0])) - js.toInt(js.getStyle(elm,'padding-'+o[1])) - js.toInt(js.getStyle(elm,'border-'+o[0]+'-width')) - js.toInt(js.getStyle(elm,'border-'+o[1]+'-width')) ) + 'px';
			}
		}
		return elm.style[param]= val;
	}

}// element


//IE bugfix: don't create attr 'name', 'enctype', etc
js.element._attr= js.browser.ie ?
	function(elm,attr,val){elm.setAttribute(attr,val)} :
	function(elm,attr,val){elm[attr]= val};

// return {x,y}
js.position= function(){
	return js.element.position(this.elm);
}

//
js.show= function(fn){
	if(!this.elm){return false;}
	this.elm.style.display= 'block';
	this.elm.style.visibility= 'visible';
}
js.hide= function(fn){
	if(!this.elm){return false;}
	this.elm.style.display= 'none';
}


/**
 * DOM - init
 */
js.dom= {}

/**
 * Creates and returns element from html string
 * Uses innerHTML to create an element
 */
js.dom.create= function(html){
	var elm= document.createElement('div');
	elm.innerHTML= html;
	return elm.firstChild;
}

// add the elm as first into js(sel)
js.addFirst= function(elm){this.elm= js.dom.addFirst(elm,this.elm);return this;}
// add js(sel) into elm as first
js.addFirstTo= function(elm){this.elm= js.dom.addFirst(this.elm,elm);return this;}
// add the elm as last into js(sel)
js.addLast= function(elm){this.elm= js.dom.addLast(elm,this.elm);return this;}
// add js(sel) into elm as last
js.addLastTo= function(elm){this.elm= js.dom.addLast(this.elm,elm);return this;}
// add the elm befor js(sel)
js.addBefor= function(elm){this.elm= js.dom.addBefor(elm,this.elm);return this;}
// add js(sel) befor elm
js.addBeforBy= function(elm){this.elm= js.dom.addBefor(this.elm,elm);return this;}
// add the elm after js(sel)
js.addAfter= function(elm){this.elm= js.dom.addAfter(elm,this.elm);return this;}
//add js(sel) after elm
js.addAfterBy= function(elm){this.elm= js.dom.addAfter(this.elm,elm);return this;}
//add js(sel) into outer elm; return js(sel)
js.addOuter= function(elm){elm= js.dom.addBefor(elm,this.elm);js.dom.addLast(this.elm,elm);return this;}
//add elm into outer js(sel); return outer js(sel)
js.addOuterBy= function(elm){js.dom.addBefor(this.elm,elm);js.dom.addLast(elm,this.elm);return this;}

js.next= js.nextElement= function(){this.elm= js.dom.next(this.elm);return this;}
js.prev= js.prevElement= function(){this.elm= js.dom.prev(this.elm);return this;}
js.remove= js.removeElement= function(){
	js.dom.walk(this.elm, function(){
		js.$.remove(this.id); // remove all sub-elements from collection
		return false;
	})
	this.elm= js.dom.remove(this.elm); // remove element from dom
	return this;
}
js.replace= js.replaceElement= function(elm){return js.dom.replace(elm,this.elm);}

/**
 * add newElm als first chils to elm1
 * js.dom.addFirst(newElm) - add newElm as first child to BODY
 * js.dom.addFirst(newElm,toElm) - add newElm as first child to toElm
 */
js.dom.addFirst= function(newElm,toElm){
	if(typeof newElm == 'string'){newElm= js.dom.create(newElm)}
	if(!toElm){
		toElm= js('body').elm;
	}
	return toElm.firstChild ?
		toElm.insertBefore(newElm,toElm.firstChild) :
		toElm.appendChild(newElm);
}

/**
 * add newElm als last child to toElm
 * js.dom.addLast(newElm) - add newElm as last child to BODY
 * js.dom.addLast(newElm,toElm) - add newElm as last child to toElm
 */
js.dom.addLast= function(newElm,toElm){
	if(typeof newElm == 'string'){newElm= js.dom.create(newElm)}
	if(toElm){
		return toElm.appendChild(newElm)
	}
	return js('body').elm.appendChild(newElm);
}

js.dom.addBefor= function(newElm,beforElm){
	if(typeof newElm == 'string'){newElm= js.dom.create(newElm)}
	return beforElm.parentNode.insertBefore(newElm,beforElm);
}

js.dom.addAfter= function(newElm,afterElm){
	if(typeof newElm == 'string'){newElm= js.dom.create(newElm)}
	var nextElm= js.dom.next(afterElm);
	if(nextElm){
		return js.dom.addBefor(newElm,nextElm);
	}
	return afterElm.parentNode.appendChild(newElm);
}

js.dom.remove= function(eml){
	return eml.parentNode.removeChild(eml);
}

js.dom.replace= function(newElm,oldElm){
	if(typeof newElm == 'string'){newElm= js.dom.create(newElm)}
	return oldElm.parentNode.replaceChild(newElm,oldElm);
}

/**
 * IE fix - check if the next sibling node is an element node
 */
js.dom.next= function(elm){
	do{elm= elm.nextSibling;}while(elm && elm.nodeType != 1);
	return elm;
}//

/**
 * IE fix - check if the previous sibling node is an element node
 */
js.dom.prev= function(elm){
	do{elm= elm.previousSibling;}while(elm && elm.nodeType != 1);
	return elm;
}//

js.dom.getParentByTagName= function(node,tagName){
	for(;node && node.nodeName.toLowerCase() != tagName; node=node.parentNode);
	return node ? node : null;
}

js.dom.walk= function(node,fn){
	var response;
	try{
		if(response=fn.call(node)){return response;}
	}catch(e){}
	node= node.firstChild;
	while(node){
		if(response=js.dom.walk(node,fn)){return response;}
		node= js.dom.next(node);
	}
}//

js.getChildByParentId= function(parentId,childId){
	var elm= document.getElementById(parentId);
	if(!elm){return null}

	var compare= function(){
		if(this.id && this.id == childId){return this;}
		return false;
	}

	return js.dom.walk(elm,compare);
}


//TODO:
/*
function getDocumentSize(){
	var w1= 0;
	var h1= 0;
	if(window.innerHeight){
		w1= js.toInt(window.innerWidth);
		h1= js.toInt(window.innerHeight);
	}

	var w2= 0;
	var h2= 0;
	if(document.body){
		w2= js.toInt(document.body.clientWidth);
		h2= js.toInt(document.body.clientHeight);
	}

	var w3= 0;
	var h3= 0;
	if(document.documentElement){
		w3= js.toInt(document.documentElement.clientWidth);
		h3= js.toInt(document.documentElement.clientHeight);
	}

	return{
		w: Math.max(Math.max(w1,w2),w3),
		h: Math.max(Math.max(h1,h2),h3)
	}
}//

function getBrowserWidth(){
	var clientWidth;
	if (window.innerWidth){
		clientWidth = (window.__safari ? window.innerWidth : Math.min(window.innerWidth, document.documentElement.clientWidth));
	}else if (document.documentElement && document.documentElement.clientWidth){
		clientWidth = document.documentElement.clientWidth;
	}else if (document.body){
		clientWidth = document.body.clientWidth;
	}else {
		clientWidth = document.documentElement.clientWidth;
	}
	return parseInt(clientWidth,10);
}//#

function getBrowserHeight(){
	var clientHeight;
	if (window.innerHeight) {
		clientHeight = (window.__safari ? window.innerHeight : Math.min(window.innerHeight, document.documentElement.clientHeight));
	}else if (document.documentElement && document.documentElement.clientHeight){
		clientHeight = document.documentElement.clientHeight;
	}else if (document.body){
		clientHeight = document.body.clientHeight;
	}else {
		clientHeight = document.documentElement.clientHeight;
	}
	return parseInt(clientHeight,10);
}//
*/
