com.saltcollective.Phocus.DOM=function(){};
$pr=com.saltcollective.Phocus.DOM.prototype;
$or=com.saltcollective.Phocus.DOM;

// DOM properties
$pr.d=$or.d=document;
$pr.context=$or.context=document;
$pr.nodeint=$or.nodeint=0;
$pr.nodeid=$or.nodeid='__phocusnode';
$pr.nodecache=$or.nodecache={};

// methods
// getNode - tests for a string and returns a node
$pr.getnodes=$or.getnodes=function(query,c) // : Array
{
	var q=this.getquerycontext()+query;
	var currentContext = new Array(document);
		
	if(!c)
		var c=this.context;
	try
	{
		if(typeof query == 'string')
		{ 				
			// Attempt to fail gracefully in lesser browsers
			if (!document.getElementsByTagName)
			{
				return new com.saltcollective.Phocus.DOM_nodeset();
			}
			// Split selector in to tokens
			var ts = q.split(' ');
			for (var i = 0; i < ts.length; i++)
			{
				t = ts[i].replace(/^\s+/,'').replace(/\s+$/,'');;
				if (t.indexOf('#') > -1)
				{
					// Token is an ID selector
					var bits = t.split('#');
					var tagName = bits[0];
					var id = bits[1];
					var element = document.getElementById(id);
					if (tagName && element.nodeName.toLowerCase() != tagName)
					{
						// tag with that ID not found, return false
						currentContext = new Array();
						break;
					}
					// Set currentContext to contain just this element
					currentContext = new Array(element);
					continue; // Skip to next token
				}
				if (t.indexOf('.') > -1)
				{
					// Token contains a class selector
					var bits = t.split('.');
					var tagName = bits[0];
					var className = bits[1];
					if (!tagName)
					{
						tagName = '*';
					}
					// Get elements matching tag, filter them for class selector
					var found = new Array;
					var foundCount = 0;
					for (var h = 0; h < currentContext.length; h++)
					{
						var elements;
						if (tagName == '*')
						{
							elements = this.getAllChildren(currentContext[h]);
						} else
						{
							elements = currentContext[h].getElementsByTagName(tagName);
						}
						for (var j = 0; j < elements.length; j++)
						{
							found[foundCount++] = elements[j];
						}
					}
					currentContext = new Array;
					var currentContextIndex = 0;
					var regexp=new RegExp('(\\s|^)'+className+'(\\s|$)');
					for (var k = 0; k < found.length; k++)
					{
// patch 1*							if (found[k].className && found[k].className.match(new RegExp('\\b'+className+'\\b')))
						if (found[k].className && found[k].className.match(regexp))
						{
							currentContext[currentContextIndex++] = found[k];
						}
					}
					continue; // Skip to next token
				}
				// Code to deal with attribute selectors
				if (t.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) //"
				{
					var tagName = RegExp.$1;
					var attrName = RegExp.$2;
					var attrOperator = RegExp.$3;
					var attrValue = RegExp.$4;
					if (!tagName)
					{
						tagName = '*';
					}
					// Grab all of the tagName elements within current context
					var found = new Array;
					var foundCount = 0;
					for (var h = 0; h < currentContext.length; h++)
					{
						var elements;
						if (tagName == '*')
						{
							elements = getAllChildren(currentContext[h]);
						} else
						{
							elements = currentContext[h].getElementsByTagName(tagName);
						}
						for (var j = 0; j < elements.length; j++)
						{
							found[foundCount++] = elements[j];
						}
					}
					currentContext = new Array;
					var currentContextIndex = 0;
					var checkFunction; // This function will be used to filter the elements
					switch (attrOperator)
					{
						case '=': // Equality
							checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue); };
							break;
						case '~': // Match one of space seperated words 
// patch 1*								checkFunction = function(e) { return (e.getAttribute(attrName) ? e.getAttribute(attrName).match(new RegExp('\\b'+attrValue+'\\b')) : false); };
							checkFunction = function(e) { return (e.getAttribute(attrName) ? e.getAttribute(attrName).match(new RegExp('(\\s|^)'+attrValue+'(\\s|$)')) : false); };
							break;
						case '|': // Match start with value followed by optional hyphen
							checkFunction = function(e) { return (e.getAttribute(attrName) ? e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?')) : false); };
							break;
						case '^': // Match starts with value
							checkFunction = function(e) { return (e.getAttribute(attrName) ? e.getAttribute(attrName).indexOf(attrValue) == 0 : false); };
							break;
						case '$': // Match ends with value - fails with "Warning" in Opera 7
							checkFunction = function(e) { return (e.getAttribute(attrName) ? e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length : false); };
							break;
						case '*': // Match ends with value
							checkFunction = function(e) { return (e.getAttribute(attrName) ? e.getAttribute(attrName).indexOf(attrValue) > -1 : false); };
							break;
						default :
							// Just test for existence of attribute
							checkFunction = function(e) { return e.getAttribute(attrName); };
					}
					currentContext = new Array;
					var currentContextIndex = 0;
					for (var k = 0; k < found.length; k++)
					{
						if (checkFunction(found[k]))
						{
							currentContext[currentContextIndex++] = found[k];
						}
					}
					// alert('Attribute Selector: '+tagName+' '+attrName+' '+attrOperator+' '+attrValue);
					continue; // Skip to next token
				}
				// If we get here, token is JUST an element (not a class or ID selector)
				tagName = t;
				var found = new Array;
				var foundCount = 0;
				for (var h = 0; h < currentContext.length; h++)
				{
					var elements = currentContext[h].getElementsByTagName(tagName);
					for (var j = 0; j < elements.length; j++)
					{
						found[foundCount++] = elements[j];
					}
				}
				currentContext = found;
			}
		}
		else if (query.length) // if this is an array
			currentContext = query;
		else if(typeof query == 'object')
			return phocus.DOM.getNode(query);
		else
		{
			// error
			this.error='Wrong parameter passed as a node reference.';
			throw(this.error);
		}
	} catch(err)
	{
		return err;
//			this.Catcher.log(err);
	}
	
	var rtn=new com.saltcollective.Phocus.DOM_nodeset();
	rtn.parsearray(currentContext);
// removed because I don't want to have to error check this each time. Maybe error check length in DOM_nodes on any action
//	if(rtn.length == 0)
//		return null;
	return rtn;
}
// the basic query context
$pr.getquerycontext=$or.getquerycontext=function(){return '';}

$pr.getAllChildren=$or.getAllChildren=function(e)
{
	// Returns all children of element. Workaround required for IE5/Windows. Ugh.
	return e.all ? e.all : e.getElementsByTagName('*');
}

$pr.getETarget=$or.getETarget=function(e)
{
	var te=null; // target element
	if(typeof e.target != 'undefined')
		te=e.target;
	else
		te=e.srcElement;
	while(te.nodeType==3 && te.parentNode!= null)
		te=te.parentNode;
	return te;
}
$pr.stopEvent=$or.stopEvent=function(e)
{
	if(typeof e.stopPropagation != 'undefined')
		e.stopPropagation();
	else
		e.cancelBubble = true;
		
	// 20080102
	// This following block was commented out for some reason, if for 
	// some reason this function fails to work as expected in future, 
	// you have a good idea of why
	e.returnValue=false;
	if(typeof e.preventDefault != 'undefined')
		e.preventDefault();
}
$pr.getmousepos=$or.getmousepos=function(e,el)
{
	var rtn=[];
	var screenx=e.clientX;
	var screeny=e.clientY;
	var offset=this.getScroll();
	rtn[0]=screenx+offset[0];
	rtn[1]=screeny+offset[1];
	if(typeof el != 'undefined')
	{
		var elpos=this.getPosition(el)[0];
		rtn[0]=rtn[0]-elpos[0];
		rtn[1]=rtn[1]-elpos[1];
	}
	return rtn;
}
$pr.getNode=$or.getNode=function(node)
{
	var nid='';
	if(node.id)
		nid=node.id;
	else
		nid=com.saltcollective.Phocus.DOM.nodeid+(com.saltcollective.Phocus.DOM.nodeint++);
	
	var comopt=com.saltcollective.Phocus.DOM.nodecache
	
	if(comopt[nid] && comopt[nid].context && comopt[nid].context.nodeType == 1)
		return com.saltcollective.Phocus.DOM.nodecache[nid];
	
	var phocusnode=new com.saltcollective.Phocus.DOM_node(node);
	phocusnode.set('id',nid);
	com.saltcollective.Phocus.DOM.nodecache[nid]=phocusnode;
	
	return phocusnode;
	
	/*
	if(typeof node.phocusNode != 'undefined')
		return node.phocusNode;
	else
		return new com.saltcollective.Phocus.DOM_node(node);
	*/
}
$pr.deleteNode=$or.deleteNode=function(node)
{
	var nid='';
	if(node.id)
		nid=node.id;
	else
		return false;
	
	if(com.saltcollective.Phocus.DOM.nodecache[nid])
	{
		com.saltcollective.Phocus.DOM.nodecache[nid]=null;
		delete com.saltcollective.Phocus.DOM.nodecache[nid];
		return true;
	}
	return false;
}
$pr.cleanupcache=function()
{
	var cache=com.saltcollective.Phocus.DOM.nodecache;
	for(var i in cache)
	{
		if(cache[i].get('id') != i)
		{
			cache[i]=null;
			delete cache[i];
		}
	}
}
$pr.flush=$or.flush=function()
{
//		com.saltcollective.Phocus.DOM.nodeint=0;
//
//		removed this because we want IDs to be unique.
//		If we wanted to be REALLY good at this point
//		we would loop through and remove any IDs that
//		we could match as a phocus_NODE ID.
	for(var i in com.saltcollective.Phocus.DOM.nodecache)
	{
		var op=com.saltcollective.Phocus.DOM.nodecache[i];
		if(op.get('id').indexOf(this.nodeid)==0)
			op.set('id','');
		op=null;
	}

	com.saltcollective.Phocus.DOM.nodecache={};
}
com.saltcollective.Phocus.register(com.saltcollective.Phocus.DOM,'DOM');

com.saltcollective.Phocus.DOM_node=function(node)
{
	this.context=node;
//	this.context.phocusNode=this;
	this.style=node.style;
}
com.saltcollective.Phocus.DOM_node.prototype=com.saltcollective.Phocus.extend(com.saltcollective.Phocus.DOM);
$pr=com.saltcollective.Phocus.DOM_node.prototype;
$pr.d=document;
$pr.issub=true;

// query context - for extending subqueries.
$pr.getquerycontext=function()
{
	return this.get('className').toLowerCase()+'#'+this.get('id')+' ';
}
/* properties take the following form:

	alias : map [, unit [, rounding]]
	if map is p:X, that refers to a parent property (where X is the property name to which it refers)
	if map is an empty string: '' then the name of the property is also the name of the style property
	if map is b:X, that refers to a base property
*/
$pr.properties=
{
	width:				['','px', 1],
	height:				['','px', 1],
	top:				['','px', 1],
	right:				['','px', 1],
	bottom:				['','px', 1],
	left:				['','px', 1],
	margin:				['','px', 1],
	marginTop:			['','px', 1],
	marginRight:		['','px', 1],
	marginBottom:		['','px', 1],
	marginLeft:			['','px', 1],
	padding:			['','px', 1],
	paddingTop:			['','px', 1],
	paddingRight:		['','px', 1],
	paddingBottom:		['','px', 1],
	paddingLeft:		['','px', 1],
	borderWidth:		['','px', 1],
	borderTopWidth:		['','px', 1],
	borderRightWidth:	['','px', 1],
	borderBottomWidth:	['','px', 1],
	borderLeftWidth:	['','px', 1],
	fontSize:			['','px', 1],
	w:					['p:width'],
	h:					['p:height'],
	t:					['p:top'],
	r:					['p:right'],
	b:					['p:bottom'],
	l:					['p:left'],
	z:					['p:zIndex'],
	x:					['p:left'],
	y:					['p:top'],
	bg:					['background'],
	color:				['f:colour'],
	colour:				['f:colour'],
	backgroundColor:	['f:bgColour'],
	bgColour:			['f:bgColour'],
	bgColor:			['f:bgColour'],
// Ive removed these because the rounding was fucking up the colour properties when passing a string hex value.
// can't quite remember why I was rounding the values. If anything goes wrong with colour, look here first.
//	color:				['f:colour',0,1],
//	backgroundColor:	['f:bgColour',0,1],
//	bgColour:			['f:bgColour',0,1],
//	bgColor:			['f:bgColour',0,1],
	id:					['b:id'],
	className:			['b:className'],
	title:				['b:title'],
	name:				['b:name'],
	value:				['b:value'],
	type:				['b:type'],
	src:				['b:src'],
	target:				['b:target'],
	nodeName:			['b:nodeName'],
//	class:				['p:className'], // class is a reserved word - LE
	href:				['b:href'],
	src:				['b:src'],
	opacity:			['f:alpha'],
	alpha:				['f:alpha'],
	dims:				['f:dims'],
	pos:				['f:position']
};
// to String
$pr.toString=function(){ return 'DOM '+this.context.nodeName+(this.context.id ? ': '+this.context.id : '')};
// set a style property
$pr.set=function(prop,value,override)
{
//	alert(prop+': '+value);

	// style is the default context as it contains the most properties that one would want changed
	var context='style';

	var p=this.properties[prop];
	
	var p=this.getprop(prop);
	var u=p[1] && p[1][1] ? p[1][1] : '';
	var v=p[1] && p[1][2] ? Math.round(value) : value;
	var prop=p[1] && p[1][0] ? p[1][0] : p && p[0] ? p[0] : prop;
		
	var propsp=prop.split(':');
	if(propsp.length > 1)
	{
		prop=propsp[1];
		context=propsp[0];
	}
	
	var opt=(typeof v == 'string' && v=='') ? '' : (!u || typeof u == 'undefined') ? v : v+u;
	
	if(context == 'style' || override=='style')
		this.style[prop]=opt;
	else if(context == 'b' || override=='attribute')
		this.context[prop]=opt;
	else if(context == 'f')
		this['set'+prop](opt);
}
// get a style property
$pr.get=function(prop)
{
	// style is the default context as it contains the most properties that one would want changed
	var context='style';

	var p=this.properties[prop];
	
	var p=this.getprop(prop);
	var u=p[1] && p[1][1] ? p[1][1] : '';
	var prop=p[1] && p[1][0] ? p[1][0] : p && p[0] ? p[0] : prop;
	
	var propsp=prop.split(':');
	if(propsp[1])
	{
		prop=propsp[1];
		context=propsp[0];
	}
		
	var rtn;
//	alert(this.context == window);
	if(context == 'style')
		rtn = this.style[prop];
	else if(context == 'b')
		rtn = this.context[prop];
	else if(context == 'f')
		rtn = this['get'+prop]();
		
	if(u!='')
		rtn=rtn.split(u).join('').split(' ')[0];
	
	return rtn;
}
// private 
// getprop recursively loops through and gets the final property
$pr.getprop=function(prop)
{
	var p=this.properties[prop];
	var propsp,rtn;
	
	if(!p)
		return [prop,null,true];
	else if(p && !isNaN(p.length))
		propsp=p[0].split('p:');
		
	// update 20080207-01
	if(propsp[1])
		rtn=this.getprop(propsp[1]);
	
	if(rtn && rtn[2]==true)
		return rtn;
	else if(!rtn || !rtn[1])
		rtn=[prop,p];
	
	return rtn;
}
// add node. Multi purpose node addition.
// e:string[, m:string[, a:array[, t:text[, c:node[, n:number]]]]]
// e - the element to add
// m - mode. This determines where the node[s] are attached. legal values: BEFORE, AFTER, REPLACE, REPLACECHILDREN, BEGINNING, END (default: END)
// a - attributes : array of objects - [{p:property;v:variable},{p:property;v:variable}]
// EDIT: changed above to {property1:value1, property2:value2 ... propertyN:valueN}
// t - text
// n - number. Will add the node 'n' number of times
$pr.addnode=function(e,m,a,t,n)
{
	var cn=this.context;
	var rtn=new com.saltcollective.Phocus.DOM_nodeset();

	// verifying method properties
	if(!m || m==undefined)
		var m='END';
	if(!n || n==undefined)
		var n=1;
	if(!a || a==undefined)
		var a=[];
	if(!t || t==undefined)
		var t='';
		
	for(var j=0;j<n;j++)
	{
		if(typeof e == 'string')
			var _n=this.d.createElement(e);
		else
		{
			var _n=e.cloneNode(true);
			
			// cleaning out any potential duplicate IDs
			var rid=function(n)
			{
				for(var i in n.childNodes)
					rid(n.childNodes[i]);
				n.id='';
			}
			rid(_n);
		}
		
		switch(m)
		{
			case 'BEFORE':
				_n=cn.parentNode.insertBefore(_n,cn)
				break
			case 'AFTER':
				_n=cn.parentNode.insertBefore(_n,cn.nextSibling)
				break
			case 'REPLACE':
				cn.parentNode.replaceChild(_n,cn)
				break
			case 'BEGINNING':
				_n=cn.insertBefore(_n,cn.firstChild)
				break
			case 'REPLACECHILDREN':
				this.clear()
			default:
				_n=cn.appendChild(_n)
		}
		_n=com.saltcollective.Phocus.DOM.getNode(_n);
		_n.createdby='DOM_nodeset';
		for(var k in a)
			_n.set(k,a[k]);
//			_n.set(a[k].p,a[k].v);
		if(t!='')
			_n.context.appendChild(this.d.createTextNode(t));
		rtn.addelement(_n.context);
	}
	return rtn;
}
$pr.deletenode=function()
{
	var cn=this.context;
	cn.parentNode.removeChild(cn);
	phocus.DOM.deleteNode(cn);
	this.context=null;
}

// clone

// previous sibling
$pr.previous=function()
{
	var n = this.context;
	do n = n.previousSibling;
	while (n && n.nodeType != 1);
	
	if(!n) return null;
	return new phocus.DOM_node(n);
}
$pr.moveup=function()
{
	var p=this.previous();
	if(!p) return;
	
	var c=this.context.cloneNode(true);
	this.deletenode();
	
	p.addnode(c,'BEFORE');
}

// next sibling
$pr.next=function()
{
	var n = this.context;
	do n = n.nextSibling;
	while (n && n.nodeType != 1);
	
	if(!n) return null;
	return new phocus.DOM_node(n);
}
$pr.movedown=function()
{
	var p=this.next();
	if(!p) return;
	
	var c=this.context.cloneNode(true);
	this.deletenode();
	
	p.addnode(c,'AFTER');
}


// add event
// e:string, m:method[, cap:node=false]
// e    - the event to add
// m    - The method to add
// cap  - Whether the event is applied during capture or bubble
$pr.setevent=function(e,m,cap)
{
	var cn=this.context;

	if(!cap)
		var cap=false;
	ae='attachEvent'; // ie
	ael='addEventListener'; // everything else
	if(typeof cn[ael] != 'undefined')
		cn[ael](e,m,cap);
	else if(typeof cn[ae] != 'undefined')
	{
		var fs=e+m;
		cn['e'+fs]=m;
		cn[fs]=function(e)
		{
			if(typeof e == "undefined")
			{
				e=window.event;
			}
			cn['e'+fs](e);
		}
		
		cn[ae]('on'+e,cn[fs]);
	}
	else
	{
		// memory leak city (fortunately only in older browsers)
    	var et='on'+e; // event type
    	var te=cn[et];// target event
    	if(typeof te == 'function')
    	{
    		var ol=te; // old listener
    		te=function()
    		{
    			ol();
    			return m();
    		}
    	} else
    	{
			te=m;
    	}
    }
    
	return [e,m,cap];
}
$pr.unsetevent=function(e,m,cap)
{
	var cn=this.context;
	
	// error checking a parsed array and making an assumption of it's validity based on a number of arbitrary tests.
	if(typeof e == 'object' && e.length==3 && typeof e[0] == 'string' && typeof e[1] == 'function' && typeof e[2]=='boolean'){var cap=e[2];var m=e[1];var e=e[0];}
		
	if(!cap)
		var cap=false;
	de='detachEvent'; // ie
	rel='removeEventListener'; // everything else
	if(typeof cn[rel] != 'undefined')
		cn[rel](e,m,cap);
	else if(typeof cn[de] != 'undefined')
		cn[de]('on'+e,m);
	else
		cn["on"+e]=null;
}
// position getter
$pr.getposition=function()
{
	var cn=this.context;
	
	var rtn=new phocus.Point(0,0);
	while(cn!=null)
	{
		var add=new phocus.Point(cn.offsetLeft,cn.offsetTop);
		rtn.add(add);
		cn=cn.offsetParent;
	}
	
	return rtn;
}
$pr.setposition=function(obj)
{
	this.set('position','absolute');
	this.set('x',obj.x);
	this.set('y',obj.y);
}
// show / hide
$pr.hide=function()
{
	this.set('display','none');
}
$pr.show=function()
{
	this.set('display','');
}
// dimensions getter
$pr.getdims=function()
{
	var cn=this.context;
	
	var rtn=new phocus.Point(cn.offsetWidth,cn.offsetHeight);
	
	return rtn;
}
$pr.setdims=function(obj)
{
	this.set('w',obj.x);
	this.set('h',obj.y);
}
// opacity setter
$pr.setalpha=function(a)
{
	if(phocus.Util.isIE())
	{
		if(typeof this.context.filters!='object' || typeof this.context.filters.alpha!='object' )
			this.style.filter = 'alpha(opacity='+Math.round(a)+')';
		else
			this.context.filters.alpha.opacity=Math.round(a);
	} else
	{
		this.style.opacity = Math.round(a*100)/10000;
	}
}
$pr.getalpha=function()
{
	var a=100;
	if(phocus.Util.isIE() && typeof this.context.filters=='object')
	{
		a=this.context.filters.alpha.opacity;
	} else
	{
		a=this.style.opacity*100;
	}
	return a;
}
// coloe setter
$pr.setcolour=function(c)
{
	this.style.color=this.colourParcel(c).toString();
}
$pr.setbgColour=function(c)
{
	this.style.backgroundColor=this.colourParcel(c).toString();
}
$pr.getcolour=function()
{
	return this.colourParcel(this.style.color);
}
$pr.getbgColour=function()
{
	return this.colourParcel(this.style.backgroundColor);
}
$pr.colourParcel=function(c)
{
	var colour=new phocus.Colour();
	if(typeof c == 'string')
	{
		var regexp=/(rgb)\(([0-9]+)[^0-9]*([0-9]+)[^0-9]*([0-9]+)\)|[a-fA-F0-9]{6}|[a-fA-F0-9]{3}|[a-fA-F0-9]{2}/; 
//		var regexp=/[a-fA-F0-9]{6}|[a-fA-F0-9]{3}|[a-fA-F0-9]{2}/;
		var col=c.match(regexp);
		// if we didn't match anything
		if(col == null)
			col=['000000'];
		// if we matched an RGB value
		else if(col[1] == 'rgb')
		{
			colour.setRGB(col[2],col[3],col[4]);
			return colour;
		}
		colour.setHEX(col[0]);
	} else if(!isNaN(c))
		colour.setDEC(c);
	else
		colour.setDEC(0);
	return colour;
}
// clear
$pr.clear=function()
{
	var n=this.context;
	if(n.hasChildNodes)
		for(var j in n.childNodes)
			n.removeChild(n.childNodes[j]);
}
com.saltcollective.Phocus.register(com.saltcollective.Phocus.DOM_node,'DOM_node');



com.saltcollective.Phocus.DOM_nodeset=function()
{
	this.nodeset=[];
	this.length=0;
}
$pr=com.saltcollective.Phocus.DOM_nodeset.prototype;
$pr.name='DOM_nodeset';
// to String
$pr.toString=function(){ var rtn='['; for(var i=0;i<this.nodeset.length;i++){ rtn+='['+i+']'+this.nodeset[i].toString()+(i<this.nodeset.length-1 ? ', ' : '') }; return rtn+']'; };
// parse an array of nodes into the nodeset
// *** NOTE: Should addd shecking for nodes and node type in here
$pr.parsearray=function(nodeset /* :Array */)
{
	for(var i=0;i<nodeset.length;i++)
		this.addelement(nodeset[i]);
}
// join
// joins 2 DOM_nodesets together
// should add some type checking here
$pr.join=function(joiningnodeset)
{
	this.parsearray(joiningnodeset.nodeset);
	joiningnodeset.empty();
}
// empty
// deletes all node references contained in the nodeset
$pr.empty=function()
{
	this.nodeset.length=0;
}
// addelement
// adds a node to the DOM_nodeset object
$pr.addelement=function(node)
{
	// if we're a type 1 node then we need to make a new DOM_node Object
	// we should also add a check here for a DOM_node objct
	// if neither, return null
	if(typeof node != 'undefined' && node !=null && node.nodeType == 1)
		var node=com.saltcollective.Phocus.DOM.getNode(node);
	this.nodeset.push(node);
	
//	this[this.length]=node;
	this.length=this.nodeset.length;
	this.firstnode=this.nodeset[0];
	this.lastnode=node;
}
// convenient nodeset wrapper
$pr.node=function(i)
{
	return this.nodeset[i];
}
// implementing parent setters
$pr.set=function(prop,value,override)
{
	// a property is a template if it's an array and it has the same number of children as the nodeset
	var template=typeof value == 'object' && value.length == this.nodeset.length;
	for(var i=this.nodeset.length-1;i>=0;i--)
		this.nodeset[i].set(prop,template ? value[i] : value,override);
}
// implementing get
$pr.get=function(prop)
{
	var rtn=[];
	for(var i=this.nodeset.length-1;i>=0;i--)
		rtn.push(this.nodeset[i].get(prop));
	return rtn;
}
// implementing getElementById
$pr.getElementById=function(id)
{
	for(var i=this.nodeset.length-1;i>=0;i--)
		this.nodeset[i].set(prop,value);
}
// implementing add node. Multi purpose node addition.
// e:string[, m:string[, a:array[, t:text[, c:node[, n:number]]]]]
// e - the element to add
// m - mode. This determines where the node[s] are attached. legal values: BEFORE, AFTER, REPLACE, REPLACECHILDREN, BEGINNING, END (default: END)
// a - attributes : array of objects - [{p:property;v:variable},{p:property;v:variable}]
// t - text
// c - nodal context. will default to document if undefined. Allows you to add to, for example, all nodes under a specific node
// n - number. Will add the node 'n' number of times
$pr.addnode=function(e,m,a,t,c,n)
{
	var rtn=new com.saltcollective.Phocus.DOM_nodeset();
	for(var i=this.nodeset.length-1;i>=0;i--)
	{
		var rt=this.nodeset[i].addnode(e,m,a,t,c,n);
		rtn.join(rt);
	}
	return rtn;
}
// implementing add event
// e:string, m:method[, cap:node=false]
// e    - the event to add
// m    - The method to add
// cap  - Whether the event is applied during capture or bubble
$pr.setevent=function(e,m,cap)
{
	for(var i=this.nodeset.length-1;i>=0;i--)
		this.nodeset[i].setevent(e,m,cap);
}
$pr.unsetevent=function(e,m,cap)
{
	for(var i=this.nodeset.length-1;i>=0;i--)
		this.nodeset[i].unsetevent(e,m,cap);
}
// show / hide
$pr.deletenode=function()
{
	for(var i=this.nodeset.length-1;i>=0;i--)
		this.nodeset[i].deletenode();
}
// show / hide
$pr.hide=function()
{
	for(var i=this.nodeset.length-1;i>=0;i--)
		this.nodeset[i].hide();
}
$pr.show=function()
{
	for(var i=this.nodeset.length-1;i>=0;i--)
		this.nodeset[i].show();
}

// implementing getnodes
$pr.getnodes=function(query)
{
	var rtn=new com.saltcollective.Phocus.DOM_nodeset();
	for(var i=this.nodeset.length-1;i>=0;i--)
		rtn.join(this.nodeset[i].getnodes(query));
	return rtn;
}

com.saltcollective.Phocus.register(com.saltcollective.Phocus.DOM_nodeset,'DOM_nodeset');


// cleanup
$pr=null;