WL.Objects = {};
WL.Objects.Event = WL.Class( Object,
function( base, type )
{
	var current = null;
	var stack	= [];
	
	type.cancel = function() { current.cancel(); }
	
	this.constructor = function()
	{
		this.invocationList = [];
	}	

	this.add = function( ctx, func, afterRemove )
	{
		this.invocationList.push( { context: ctx, method: func, remove: afterRemove } );
	}
	
	this.remove = function( func )
	{
		this.invocationList.removeIf( function(it) { return it.method == func; } );
	}
	
	this.clear = function()
	{
		this.invocationList.clear();
	}
	
	this.doAfterRemove = function()
	{
		this.invocationList.removeIf( function(it) { return it.remove; } );
	}
	
	this.isEmpty = function() { return this.invocationList.length == 0; }
	
	this.cancel = function() { this._iscancel = true; }
		
	this.invoke = function( sender, e )
	{		
		this._iscancel = false;
		
		if( this.invocationList.length != 0 )
		{
			stack.push( current );
						current = this;	
			
			for( var i = 0; i < this.invocationList.length; ++i )
				this.invocationList[i].method.call( this.invocationList[i].context, sender, e || {} );
				
			this.doAfterRemove();
		
			current = stack.pop();
		}
		
		this.timer = 0;
		
		return !this._iscancel;
	}
	
	this.raise = function( sender, e, timeout )
	{
		if( timeout == null ) timeout = 0;
		
   		var copy = this.clone();
   		var method = (function() 
   			{
   				this.doAfterRemove();
   				copy.invoke( sender, e );
   			}).bind( this );
   		
		if( this.timer ) window.clearTimeout( this.timer );
			this.timer = window.setTimeout( method, timeout );
	}
	
	this.clone = function()
	{
		var clone = new WL.Objects.Event();		
		for( var i = 0; i < this.invocationList.length; ++i )
			clone.invocationList[i] = this.invocationList[i];			
		return clone;
	}
} );

WL.Objects.Guid = WL.Class( Object,
function( base, type )
{
	this.constructor = function( str )
	{
		if( !str ){this.a=this.b=this.c=this.d=this.e=0;return;}	
		WL.Objects.Guid.regexp.lastIndex = 0;
		var items = WL.Objects.Guid.regexp.exec( str );
		this.a = parseInt( items[1], 16 );
		this.b = parseInt( items[2], 16 );
		this.c = parseInt( items[3], 16 );
		this.d = parseInt( items[4], 16 );
		this.e = parseInt( items[5], 16 );
	}
	this.constructor.Null = new this.constructor(null);
	this.constructor.regexp = /\b([0-9|a-f]{8})\-([0-9|a-f]{4})\-([0-9|a-f]{4})\-([0-9|a-f]{4})\-([0-9|a-f]{12})\b/ig;
	this.constructor.newGuid = function()
	{
		var guid = new WL.Objects.Guid();
		guid.a = Math.floor(Math.random() * 0xFFFFFFFF);
		guid.b = Math.floor(Math.random() * 0xFFFF);
		guid.c = Math.floor(Math.random() * 0xFFFF);
		guid.d = Math.floor(Math.random() * 0xFFFF);
		guid.e = Math.floor(Math.random() * 0xFFFFFFFFFFFF);
		return guid;
	}

	this.equals = function( guid )
	{
		return	this.a == guid.a && 
				this.b == guid.b && 
				this.c == guid.c &&
				this.d == guid.d &&
				this.e == guid.e;
	}

	this.toString = function() 
	{
		var guid = [];
		guid.push( this.a.toHexString( 8 ) );
		guid.push( this.b.toHexString( 4 ) );
		guid.push( this.c.toHexString( 4 ) );
		guid.push( this.d.toHexString( 4 ) );
		guid.push( this.e.toHexString( 12 ) );
		return "{" + guid.join( '-' ) + "}";
	}

	this.isNull = function()
	{
		return this.a == 0 && this.b == 0 && this.c == 0 && this.d == 0;
	}
	
	this.write = function( writer ) { writer.write( this.toString() ) }
} );

/////////////////////////////
WL.Objects.Unit = function( str )
{
	WL.Objects.Unit.regexp.lastIndex = 0;
	var items = WL.Objects.Unit.regexp.exec( str );
	
	this.value	= items[1] == "-" ? -parseInt( items[2] ) : parseInt( items[2] );
	this.unit	= items[3];
}
WL.Objects.Unit.regexp = /([+|-]*)(\d+)(\D+)/ig;

WL.Objects.Cookie = WL.Class( Object, function()
{
	this.constructor = function( key, expires )
	{
		this.key = key || "";
		this.expires = expires || "";
	}

	this.set = function( name, value )
	{
		document.cookie = String.format( "{0}{1}={2}; expires={3}", this.key, name, escape( value ), this.expires );
	}

	this.get = function( name )
	{
		var name = this.key + name;
		
		var cookies = document.cookie.split( "; " );
		for( var i = 0; i < cookies.length; ++i )
		{
			var crumb = cookies[i].split( "=" );
			if( name == crumb[0] )
				return crumb.length>1 ? unescape( crumb[1] ) : "";
		}

		return null;
	}

	this.remove = function( name )
	{
		document.cookie = String.format( "{0}{1}=; expires=Fri, 31 Dec 1999 23:59:59 GMT;", this.key, name );
	}
} );

//////////////////////////////
WL.Objects.XmlWriter = WL.Class( Object, function()
{
	this.constructor = function()
	{
		this.body = new Array();
		this.tagStack = new Array();
		this.state = 0;
	}

	var LT = "<";
	var GT = ">";
	var EQ = "=";
	var CL = "</";
	var SP = " ";
	var QU = '"';
	
	this.writeStartElement = function( tagName )
	{
		if( this.state == 1 )
			this.body.push( GT );
		
		this.body.push( LT );
		this.body.push( tagName );
		this.tagStack.push( tagName );
		this.state = 1;
	}
	this.writeAttributeString = function( name, value )
	{
		if( this.state == 0 )
		{	
			throw( "tag not open can't add attributes" );
			return;
		}
		
		this.body.push( SP );
		this.body.push( name );
		this.body.push( EQ );
		this.body.push( QU );
		this.body.push( value );
		this.body.push( QU );
	}
	this.writeElementString = function( tagName, value )
	{
		this.writeStartElement( tagName );
		this.write( value==null?"":value.toString().escapeXML() );
		this.writeEndElement();
	}	
	this.write = function( value )
	{
		if( this.state == 1 )
		{
			this.body.push( GT ); 
			this.state = 0;
		}
		
		this.body.push( value );
	}
	this.writeEndElement = function()
	{
		if( this.state == 1 )
		{
			this.body.push( GT ); // at future selfclosingtag
			this.state = 0;
		}
		
		this.body.push( CL );
		this.body.push( this.tagStack.pop() );
		this.body.push( GT );
	}
	this.writeObject = function( tagName, object )
	{
		this.writeStartElement( tagName );
		object.write( this );
		this.writeEndElement( tagName );
	}
	this.writeArray = function( tagName, subTagName, array )
	{
		if( tagName ) this.writeStartElement( tagName );
		for( var i = 0; i < array.length; ++i )
			this.writeElementString( subTagName, array[i] );
		if( tagName ) this.writeEndElement( tagName );
	}
	this.writeObjectArray = function( tagName, subTagName, array )
	{
		if( tagName ) this.writeStartElement( tagName );
		for( var i = 0; i < array.length; ++i )
			this.writeObject( subTagName, array[i] );
		if( tagName ) this.writeEndElement( tagName );
	}
	this.writeBinHex = function( tagName, binhex, itemSize )
	{
		var is = (itemSize || 1) * 2;
		var data = new Array( binhex.length );
		for( var i = 0; i < binhex.length; ++i )
			data[i] = binhex[i].toHexString( is );	
		
		this.writeElementString( tagName, data.join( '' ) );
	}	
	this.writeBoolean = function( tagname, value )
	{
		this.writeElementString( tagname, value ? "true" : "false" );
	}	
	this.writeDate = function( tagname, value )
	{
		this.writeElementString( tagname, value.valueOf() );
	}
	this.writeTime = function( tagname, value )
	{
		this.writeElementString( tagname, value.time );
	}
	this.toString = function()
	{
		return this.body.join("");
	}
} );

//////////////////////
WL.Objects.XmlReader = WL.Class( Object, function()
{
	this.constructor = function( xmlNode )
	{
		WL.Utils.assert( xmlNode == null, "xml node is null in XmlReader ctor" );
		this.xmlNode = xmlNode;
	}

	this.getXmlNode = function( tagName )
	{
		return !tagName ? this.xmlNode : this.selectSingleNode( tagName );
	}
	
	var getNodeValue;
	
if( WL.browser.ie )
{
	getNodeValue = function(n,dv) { return (n&&n.firstChild) ? n.firstChild.nodeValue : dv; } 
	
	this.selectSingleNode = function( tagName )
	{
		return this.xmlNode.selectSingleNode( tagName ); 
	}
	
	this.selectNodes = function( tagName )
	{
		return this.xmlNode.selectNodes( tagName ); 
	}
}
else
{
	getNodeValue = function(n,dv) { return n ? n.textContent : dv; } 
	
	this.selectSingleNode = function( tagName )
	{
		var nodes = this.xmlNode.childNodes;
		for( var i = 0; i < nodes.length; ++i )
			if( nodes[i].tagName == tagName ) return nodes[i];
		return null;
	}
	
	this.selectNodes = function( tagName )
	{
		var nodes = [];
		selectInnerNodes( this.xmlNode, tagName.split('/'), nodes, 0 );
		nodes.__innerIndex = 0;
		nodes.nextNode = function() { return this[this.__innerIndex++]; }
		return nodes;
	}
	
	var selectInnerNodes = function( node, tags, list, index )
	{
		var nodes = node.childNodes;
		for( var i = 0; i < nodes.length; ++i )
			if( nodes[i].tagName == tags[index] )
			{
				if( index == tags.length-1 ) list.push( nodes[i] );
				else
					selectInnerNodes( nodes[i], tags, list, index+1 );
			}		
	}
}	
	this.select = function( tagName )
	{
		var node = this.selectSingleNode( tagName );
		return node ? new WL.Objects.XmlReader( node ) : null;
	}
	
	this.readNodeValue = function( defaultValue ) { return getNodeValue( this.xmlNode, defaultValue ); }

	this.readString = function( tagName, defaultValue )
	{
		var node = this.selectSingleNode( tagName );
		return getNodeValue( node, defaultValue || "" );
	}

	this.readInt = function( tagName, defaultValue )
	{
		var node = this.selectSingleNode( tagName );
		return parseInt( getNodeValue(node, defaultValue||0) );
	}
	
	this.readFloat = function( tagName, defaultValue )
	{
		var node = this.selectSingleNode( tagName );
		return parseFloat( getNodeValue(node, defaultValue||0) );
	}
	
	this.readBoolean = function( tagName, defaultValue )
	{
		var node = this.selectSingleNode( tagName );
		var str = getNodeValue( node, null );
		return str ? (str.toLowerCase() == "true" ? true : false) : (defaultValue||false);
	}

	this.readGuid = function( tagName, defaultValue )
	{
		var node = this.selectSingleNode( tagName );
		var str = getNodeValue( node, null );
		return str ? new WL.Objects.Guid( str ) : (defaultValue||WL.Objects.Guid.Null);
	}
	
	this.readDate = function( tagName, defaultValue )
	{
		var node = this.selectSingleNode( tagName );
		var str = getNodeValue( node, null );
		if( !str ) return defaultValue||new Date(1970,0,1,0,0,0);
		return new Date( parseInt(str) );
	//	var d = new Date( parseInt(str) );
	//	return new Date( d.getUTCFullYear(), d.getUTCMonth(), d.getUTCDate(), d.getUTCHours(), d.getUTCMinutes(), d.getUTCSeconds(), d.getUTCMilliseconds() );
	}
	
	this.readTime = function( tagName, defaultValue )
	{
		var node = this.selectSingleNode( tagName );
		return new WL.Objects.Time( parseInt(getNodeValue( node, 0 )).NaN0() );
	}
	
	this.readObject = function( tagName, obj )
	{
		var node = this.selectSingleNode( tagName );
		if( node ) obj.read( new WL.Objects.XmlReader( node ) );
	}

	this.readObject2 = function( tagName, obj_type )
	{
		var obj = new obj_type();
		this.readObject( tagName, obj );
		return obj;
	}
	
	this.readJson = function( tagName, obj_type )
	{
		var json = this.readString(tagName);
		return json ? String.parseJson(json,obj_type) : null;
	}
	
	this.readStringArray = function( tagName )
	{
		var xmlNodes = this.selectNodes( tagName );
		var collection = [];
		while( (xmlNode = xmlNodes.nextNode()) != null )
			collection.push( getNodeValue(xmlNode,"") );			
		return collection;
	}

	this.readIntArray = function( tagName )
	{		
		var xmlNodes = this.selectNodes( tagName );
		var collection = [];
		while( (xmlNode = xmlNodes.nextNode()) != null )
			collection.push( parseInt( getNodeValue(xmlNode,0) ) );			
		return collection;
	}
	
	this.readFloatArray = function( tagName )
	{		
		var xmlNodes = this.selectNodes( tagName );
		var collection = [];
		while( (xmlNode = xmlNodes.nextNode()) != null )
			collection.push( parseFloat( getNodeValue(xmlNode,0) ) );			
		return collection;
	}

	this.readGuidArray = function( tagName )
	{
		var xmlNodes = this.selectNodes( tagName );
		var collection = [];
		while( (xmlNode = xmlNodes.nextNode()) != null )
			collection.push( new WL.Objects.Guid( getNodeValue(xmlNode,"") ) );			
		return collection;
	}

	this.readObjectArray = function( tagName, objClass )
	{
		var xmlNodes = this.selectNodes( tagName );
		var collection = [];
		while( (xmlNode = xmlNodes.nextNode()) != null )
		{
			var obj = new objClass();
			obj.read( new WL.Objects.XmlReader( xmlNode ) );
			collection.push( obj );
		}
		return collection;
	}

	this.readObjectArray2 = function( tagName, objCreator )
	{
		var xmlNodes = this.selectNodes( tagName );
		var collection = [];
		while( (xmlNode = xmlNodes.nextNode()) != null )
		{
			var obj = objCreator.createObject();
			obj.read( new WL.Objects.XmlReader( xmlNode ) );
			collection.push( obj );
		}
		return collection;
	}

	this.readAttributeString = function( attrName, defaultValue ) 
	{ 
		return this.xmlNode.getAttribute( attrName ) || ( defaultValue || "" ); 
	}
	
	this.readAttributeInt = function( attrName, defaultValue ) 
	{ 
		var attribute = this.xmlNode.getAttribute( attrName );
		return attribute ? parseInt( attribute ) : (defaultValue||0);
	}

	this.readAttributeGuid = function( attrName, defaultValue )
	{
		var attribute = this.xmlNode.getAttribute( attrName );
		return attribute ? new WL.Objects.Guid( attribute ) : ( defaultValue || WL.Objects.Guid.Null ); 
	}
/*
	this.readClassObject = function()
	{
		var guid = this.readAttributeGuid( "clsid" );
		var obj = new WL.ClassFactory[ guid ]();
		obj.read( this );
		return obj;
	}

	this.readClassObjectArray = function( tagName )
	{
		var xmlNodes = this.selectNodes( tagName );
		var collection = [];
		while( (xmlNode = xmlNodes.nextNode()) != null )
		{
			var obj = ( new WL.Objects.XmlReader( xmlNode ) ).readClassObject();
			collection.push( obj );
		}
		return collection;
	}

	this.readBinHex = function( tagName, itemSize )
	{
		var is = (itemSize || 1)*2;
		var string = this.readString( tagName );	
		var count = Math.floor( string.length / is );	
		
		var ret = new Array( count );
		for( var i = 0; i < count; ++i )
			ret[i] = parseInt( string.substr( i * is, is ), 16 );

		return ret;
	}*/
} );

WL.Objects.Size = WL.Class( Object, function()
{
	this.constructor = function( cx, cy )
	{
		this.cx = cx || 0;
		this.cy = cy || 0;
	}
	this.isNull		= function() { return this.cx == 0 || this.cy == 0; }
	this.setNull	= function() { this.cx = 0; this.cy = 0; }
	this.clone		= function() { return new WL.Objects.Size( this.cx, this.cy ); }
} );

WL.Objects.Point = WL.Class( Object, function()
{
	this.constructor = function( x, y )
	{
		this.x = x || 0;
		this.y = y || 0;
	}
} );

WL.Objects.Range = WL.Class( Object, function()
{
	this.constructor = function( from, to )
	{
		this.from = from || 0;
		this.to = to != null ? to : this.from;
	}

	this.isInclude = function( value ) { return this.from <= value && value <= this.to; }
	
	this.write = function( writer )
	{
		writer.writeElementString( "f", this.from );
		writer.writeElementString( "t", this.to );
	}
	
	this.read = function( reader )
	{
		this.from = reader.readInt( "f" );
		this.to = reader.readInt( "t" );
	}
} );

WL.Objects.RangeArray = WL.Class( Object, function(base,type)
{
	type.maximum = 4294967295;
	
	this.constructor = function( ranges )
	{
		this.ranges = ranges || [];
	}

	this.add = function( range )
	{
		var index = this.binarySearch( range );
		
		if( index != -1 && range.from <= this.ranges[index].to + 1 )
		{
			range.from = this.ranges[index].from;
			if( range.to < this.ranges[index].to )
				range.to = this.ranges[index].to;
				
			this.ranges.removeAt(index--);
		}
	
		for( var i = index+1; i < this.ranges.length; ++i )
			if( range.to + 1 >= this.ranges[i].from )
			{
				var r = this.ranges[i];
				this.ranges.removeAt(i--);
				
				if( range.to < r.to )
				{
					range.to = r.to;
					break;
				}
			}
			else break;

		this.ranges.insert( index+1, range );
	}
	
	this.remove = function( range )
	{
		var index = this.binarySearch( range );
		
		if( index != -1 && range.from <= this.ranges[index].to )
		{
			if( this.ranges[index].from >= range.from )
			{
				if( range.to < this.ranges[index].to )
					this.ranges[index].from = range.to+1;
				else
					this.ranges.removeAt(index--);
			}
			else
			{
				if( range.to < this.ranges[index].to )
					this.ranges.insert( index+1, new WL.Objects.Range( range.to+1, this.ranges[index].to ) );

				this.ranges[index].to = range.from-1;
			}
		}
	
		for( var i = index+1; i < this.ranges.length; ++i )
			if( range.to >= this.ranges[i].from )
			{
				if( range.to < this.ranges[i].to )
				{
					this.ranges[i].from = range.to+1;
					break;					
				}
				else
					this.ranges.removeAt(i--);
			}
			else break;
	}
	
	this.addValue	 = function( v ) { this.add( new WL.Objects.Range(v,v) ); }
	this.removeValue = function( v ) { this.remove( new WL.Objects.Range(v,v) ); }
	
	this.binarySearch = function( range )
	{
		var count = this.ranges.length;
		var l = 0, r = count-1, m;
		var res;
		while( l <= r )
		{
			m = ( l + r ) >> 1;
			if( m + 1 < count )
			{
				if( range.from >= this.ranges[m].from )
				{
					if( range.from < this.ranges[m+1].from ) res = 0;
					else res = -1;
				}
				else res = 1;
			}
			else
			{
				if( range.from >= this.ranges[m].from ) res = 0;
				else res = -1;
			}
					
			if( res == 0 ) return m;
			if( res < 0 ) l = m + 1;
			else r = m - 1;
		}
		return -1;
	}
	
	this.clear = function() { this.ranges.clear(); }
	
	this.isInclude = function( range )
	{
		var index = this.binarySearch( range );
		if( index != -1 )
			if( this.ranges[index].to >= range.from ) return true;
		
		if( index + 1 < this.ranges.length )
			if( this.ranges[index+1].from <= range.to ) return true;
			
		return false;
	}
	
	this.binaryValueSearch = function( value )
	{
		var l = 0, r = this.ranges.length-1, m;
		
		while( l <= r )
		{
			m = ( l + r ) >> 1;
			if( this.ranges[m].isInclude( value ) ) return m;
			if( this.ranges[m].to < value ) l = m + 1;
			else r = m - 1;
		}
		
		return ~l;
	}
	
	this.isValueInclude = function( value )
	{
		return this.binaryValueSearch( value ) >= 0;
	}
	
	this.isStrictInclude = function( range )
	{
		var index = this.binarySearch( range );
		return index != -1 && this.ranges[index].from <= range.from && this.ranges[index].to >= range.to;
	}
	
	this.trim = function( range )
	{
		if( range.from > 0 ) this.remove( new WL.Objects.Range( 0, range.from-1 ) );
		if( range.to < WL.Objects.RangeArray.maximum )	this.remove( new WL.Objects.Range( range.to+1, WL.Objects.RangeArray.maximum ) );
	} 
	
	this.toIndexes = function()
	{
		var indexes = [];
		var r;
		for( var i = 0; i < this.ranges.length; ++i )
		{
			r = this.ranges[i];
			for( var j = r.from; j <= r.to; ++j ) indexes.push(j);
		}
		return indexes;
	}
	
	this.getCount = function()
	{
		var count = 0;
		var r;
		for( var i = 0; i < this.ranges.length; ++i )
		{
			r = this.ranges[i];
			count += r.to - r.from + 1;
		}
		return count;
	}
	
	this.write = function( writer )
	{
		writer.writeObjectArray( "Ranges", "r", this.ranges );
	}
	
	this.read = function( reader )
	{
		this.ranges = reader.readObjectArray( "Ranges/r", WL.Objects.Range );
	}
} );

WL.Objects.Time = WL.Class( Object, function()
{
	this.constructor = function( t )
	{
		this.time = t || 0;
	}

	this.reset = function( d, h, m, s )
	{
		d = d || 0;
		h = h || 0;
		m = m || 0;
		s = s || 0;
		this.time = d*86400+h*3600+m*60+s;
	}
	
	this.valueOf = function() { return this.time; }
	this.clearDays = function() { this.time = this.time%86400; }
		
	this.getTotalDays = function() { return Math.floor( this.time / 86400 ); }
	this.getTotalHours = function() { return Math.floor( this.time / 3600 ); }
	this.getTotalMinutes = function() { return Math.floor( this.time / 60 ); }
	this.getTotalSeconds = function() { return this.time; }
	
	this.getHour = function() { return Math.floor( ( this.time % 86400 ) / 3600 ); }
	this.getMin = function() { return Math.floor( ( this.time % 3600 ) / 60 ); }
	this.getSec = function() { return this.time % 60; }
	
	this.addSec = function(s) { this.time += s; }
	this.addMin = function(m) { this.time += m*60; }
	this.addHour = function(h) { this.time += h*3600; }
	
	this.toString = function( format )
	{
		if( !format ) format = "H:mm:ss";
		return format.replace(/dd?|DD?|hh?|HH?|mm?|MM?|ss?/g, formatter.bind(this) );
	}
	
	var p = function(s) { return (s.toString().length == 1) ? "0" + s : s; }
	var formatter = function( format )
	{
		switch( format )
		{
			case "hh":	return p(this.getHour());
			case "h":	return this.getHour();
			case "HH":	return p(this.getTotalHours());
			case "H":	return this.getTotalHours();
			case "mm":	return p(this.getMin());
			case "m":	return this.getMin();
			case "MM":	return p(this.getTotalMinutes());
			case "M":	return this.getTotalMinutes();
			case "ss":	return p(this.getSec());
			case "s":	return this.getSec();
			case "DD": case "dd":	return p(this.getTotalDays());
			case "D": case "d":		return this.getTotalDays();
		}
	}
} );

WL.Objects.ElementsPool = WL.Class( Object, function()
{
	this.constructor = function()
	{
		var pool = WL.$e("div");
		pool.style.display="none";
		pool.style.width = pool.style.height = "1px";
	//	document.forms[0].appendChild(pool);
	//	document.forms[0].insertBefore(pool,document.forms[0].firstChild);
		document.body.insertBefore(pool,document.body.firstChild);
		this.p_id = WL.uniqueID(pool);
	}
	this.put = function( el ) { if( el.parentNode ) el.parentNode.removeChild( el ); WL.$(this.p_id).appendChild( el ); }
	this.get = function( elID ) { var el = WL.$(elID); el.parentNode.removeChild(el); return el; }
	this.putChildren = function( parent ) { while( parent.firstChild ) this.put( parent.firstChild ); }
} );

WL.queryElementsPool = function()
{
	if( window.elementsPool == null )
		window.elementsPool = new WL.Objects.ElementsPool();
	return window.elementsPool;
}

WL.ResizeManager = WL.Class( Object, function()
{
	this.constructor = function()
	{
		this.list = [];
	}
	this.attachListener = function( el, opt, handler )
	{
		if( this.list.some( function(o) { return o.el == el && o.c == handler; } ) ) return;
		if( !opt ) opt = {};
		if( !opt.check ) opt.check = "both";
		this.list.push( {el:el,w:el.offsetWidth,h:el.offsetHeight,p:opt||{},c:handler} );
		if( this.list.length == 1 )
		{
			WL.attachListener( window, "resize", this.check.raise( this ) );
			check_timeout.call( this );
		}
	}
	this.check = function()
	{
		var handlers = [];
		this.list.each( function(o)
		{
			var h = false;
			if( ["both","width"].indexOf(o.p.check) !=-1 && o.w != o.el.offsetWidth ) { o.w = o.el.offsetWidth; h = true; }
			if( ["both","height"].indexOf(o.p.check)!=-1 && o.h != o.el.offsetHeight) { o.h = o.el.offsetHeight; h = true; }			
			if( h && handlers.indexOf(o.c) == -1 ) handlers.push(o.c);			
		} );
		for( var i = 0; i < handlers.length; ++i ) handlers[i]();
	}
	var check_timeout = function() { this._cc = window.setTimeout( check_timeout.bind(this), 1000 ); this.check(); }
	
	this.listenElements = function( els, opt )
	{
		if( !opt ) opt = {};
		if( !opt.check ) opt.check = "both";
		var check = function()
		{
			if( ["both","height"].indexOf(opt.check)!=-1 )
			{
				var mh = 0;
				els.each( function(el) { if( mh < el.firstChild.offsetHeight ) mh = el.firstChild.offsetHeight; } );
				els.each( function(el) { el.style.height = mh+"px"; } );
			}
			if( ["both","width"].indexOf(opt.check)!=-1 )
			{
				var mx = 0;
				els.each( function(el) { if( mx < el.firstChild.offsetWidth ) mx = el.firstChild.offsetWidth; } );				
				els.each( function(el) { el.style.width = mx+"px"; } );
			}
		};
		check();
		els.each( function(el) { window.resizeManager.attachListener(el.firstChild,opt,check); } );
	}
} );
window.resizeManager = new WL.ResizeManager();