/*******************\
  GSSI DOM devices
  Requires: Base
\*******************/

if (! GSSI) { alert("gssi.dom.js: gssi.base.js not loaded") };
GSSI.DOM = {};

GSSI.Base.Extend( GSSI.ElementPrototype,  {
	prependChild: function ( node ) {
		if ( this.hasChildNodes ) {
			this.insertBefore( node, this.childNodes[0] );
		} else {
			this.appendChild( node );
		}
		return this;
	},
	
	trueOffset: function () {
		var element = this;
		var T = 0, L = 0;
		do {
			T += element.offsetTop  || 0;
			L += element.offsetLeft || 0;
			element = element.offsetParent;
		} while (element);
		return {left:L, top:T};
	},
	
	trueSize: function() {
		var H = this.offsetHeight || this.style.pixelHeight || 0;
		var W = this.offsetWidth || this.style.pixelWidth || 0;
		return {height:H, width:W};
	},
	
	trueShape: function() {
		return GSSI.Base.Extend(this.trueOffset(), this.trueSize());
	},
	
	trueLeft: function () {
		return this.trueOffset().left;
	},

	trueTop: function () {
		return this.trueOffset().top;
	},
	
	moveTo: function( fix, position, options ) {
		options = GSSI.Base.Extend({ offsetTop:0, offsetLeft:0 }, options);
		var pfn;
		fix = GSSI.$(fix);
		this.style.margin = 0;
		
		var fixobj = fix.trueShape();

		var thisobj =  this.trueShape();

		if(position) {
			if (typeof(position)=='string') { position = position.split(' '); };
			for( var i=0; i<position.length; i++ ) {
				pfn = GSSI.DOM.Positions[position[i]];
				if(pfn) {
					pfn( thisobj, fixobj );
				}
			}
		} 
		
		thisobj.left += options.offsetLeft;
		thisobj.top +=  options.offsetTop;
		this.style.top = thisobj.top + 'px';
		this.style.left = thisobj.left + 'px';
		return this;
	}, 
	
	sizeTo: function( src, widthdelta, heightdelta, options ) {
		options = options || {};
		widthdelta = widthdelta || 0;
		heightdelta = heightdelta || 0;
		if(!options.skipHeight) { this.style.height = ((src.style.pixelHeight || src.offsetHeight) + heightdelta) + "px"; };
		if(!options.skipWidth) { this.style.width = ((src.style.pixelWidth || src.offsetWidth) + widthdelta) + "px"; };
		return this;
	},
	
	selectable: function( ok ) {
		var n;
		if (arguments.length < 1) { var ok = true; }
		if (ok) {
			if ( this.unselectable == 'on' ) {
				this.unselectable = null;
				this.style.MozUserSelect = 'inherit';
				for( var i = 0; i< this.childNodes.length; i++ ) {
					n = this.childNodes[i];
					if (n.nodeType != 3) { GSSI.$(n).selectable(true); };
				}
			}
		} else {
			if ( this.unselectable != 'on' ) {
				this.unselectable = 'on';
				this.style.MozUserSelect = 'none';
				for( var i = 0; i< this.childNodes.length; i++ ) {
					n = this.childNodes[i];
					if (n.nodeType != 3) { GSSI.$(n).selectable(false); };
				}
			}
		}
		return this;
	},
	
	getElementsByClassName: function(classname, tagname) {
		if (! classname) { return []; }
		tagname = tagname || "*";
		result = [];
	
		var cre = new RegExp('(^|\\s)'+ classname.replace(/\-/g, '\\-') +'(\\s|$)');
		var elems = this.getElementsByTagName(tagname);
		var e;
		for(var i=0; i< elems.length; i++ ) {
			e = elems[i];
			if ( cre.test(e.className) ) { result.push(e); };
		}
		
		return result;
	},
	
	hasClass: function( classname ) {
		return ( (" " + this.className + " ").indexOf(" " + classname + " ") ) != -1;
	},
	
	addClass: function( classname ) {
		if (this.hasClass(classname)) { return; }
		if (this.className == "") {
			this.className = classname;
		} else {
			this.className += " " + classname;
		}
	},
	
	removeClass: function( classname ) {
		var thisclassname = " " + this.className + " ";
		var removeclassname = " " + classname + " ";
		var removelength = removeclassname.length - 1;
		var at;
		
		while ( (at = thisclassname.indexOf(removeclassname)) > -1 ) {
			thisclassname = thisclassname.substr(0, at) + thisclassname.substr(at+removelength);
		}
		this.className = thisclassname.substr(1, thisclassname.length-2);
	}
	
});

GSSI.DOM.getElementsByClassName = function(classname, tagname) {
	return GSSI.DOM.GetBody().getElementsByClassName(classname, tagname);
};

GSSI.DOM.GetBody = function() {
	return GSSI.Base.WrapElement(document.body);
};

GSSI.DOM.createElement = function ( tagname, attribs, styles, text, children ) {
	if (! tagname) { return null; }
	tagname = tagname.toString();
	attribs = GSSI.Base.Clone( attribs );
	
	var cssclass = null;
	if(GSSI.Base.HasProperty( attribs, "class" )) {
		cssclass = attribs["class"];
		attribs["class"]=null;
	}
	attribs["style"]=null;  // Can't support this crossbrowserly yet.
	
	e = document.createElement(tagname);
	if (!e ) { return null; }
	
	var a;
	for( p in attribs ) {
		a = attribs[p];
		if( (a === null) || (a === undefined) ) { continue; }
		if(GSSI.Base.HasProperty( e, p )) {
			e[p] = a;
		} else {
			e.setAttribute( p, a );
		}
	}

	for( p in styles ) {
		a = styles[p];
		if( (a === null) || (a === undefined) ) { continue; }
		e.style[p] = a;
	}
	e = GSSI.Base.WrapElement(e);
	if( cssclass ) { e.className = cssclass; };
	
	if (text) {
		e.appendChild(GSSI.DOM.createTextNode(text));
	};
	
	if (children) {
		for(var i=0; i<children.length; i++) {
			e.appendChild(children[i]);
		}
	}
	
	return e;
}

GSSI.DOM.createTextNode = function ( content ) {
	return document.createTextNode( content );
}

GSSI.DOM.UID = function() {
	var id;
	do {
		id = GSSI.Base.UID();
	} while( GSSI.$(id) )
	return id;
}

GSSI.DOM.Positions = {
	above:  function( targ, fix ) { targ.top = ( fix.top - targ.height ); },
	top:    function( targ, fix ) { targ.top = ( fix.top ); },
	middle: function( targ, fix ) { targ.top = ( fix.top + (fix.height/2) - (targ.height/2) ); },
	bottom: function( targ, fix ) { targ.top = ( fix.top + fix.height - targ.height ); },
	below:  function( targ, fix ) { targ.top = ( fix.top + fix.height ); },
	before: function( targ, fix ) { targ.left = ( fix.left - targ.width ); },
	left:   function( targ, fix ) { targ.left = ( fix.left ); },
	center: function( targ, fix ) { targ.left = ( fix.left + (fix.width/2) - (targ.width/2) ); },
	right:  function( targ, fix ) { targ.left = ( fix.left + fix.width - targ.width ); },
	after:  function( targ, fix ) { targ.left = ( fix.left + fix.width ); }
};


GSSI.DOM._positionstyles = { left:true, top:true, right:true, bottom:true };

GSSI.DOM.isPositionStyle = function( s ) { return !!GSSI.DOM._positionstyles[s]; }