/*
 * AC Fry - JavaScript Framework v1.0
 * (c)2006 Petr Krontorad, April-Child.com
 * Portions of code based on WHOA Bender Framework, (c)2002-2005 Petr Krontorad, WHOA Group.
 * http://www.april-child.com. All rights reserved.
 * See the license/license.txt for additional details regarding the license.
 * Special thanks to Matt Groening and David X. Cohen for all the robots.
 */


// String prototype enhancements
String.prototype.camelize = function()
{
	return this.replace( /(-.)/g, function(){ return arguments[0].substr(1).toUpperCase();} );
}

String.prototype.decamelize = function()
{
	return this.replace( /([A-Z])/g, function(){ return '-'+arguments[0].toLowerCase();} );
}

String.prototype.trim = function()
{
    return this.replace(/(^\s*)|(\s*$)/g, '' );
}

String.prototype.stripLines = function()
{
	return this.replace( /\n/g, '' );
}

String.prototype.stripMarkup = function()
{
	return this.replace( /<(.|\n)+?>/g, '' );
}

String.prototype.replaceMarkup = function( charRep )
{
	return this.replace( /(<(.|\n)+?>)/g, function()
	{
		var t = '';
		for ( var i=0; i<arguments[0].length; i++ )
		{
			t += charRep;
		}
		return t;
	} );
}

String.prototype.encodeMarkup = function()
{
	return this.replace( /&/g, '&amp;' ).replace( />/g, '&gt;' ).replace( /</g, '&lt;' );
}

String.prototype.decodeMarkup = function()
{
	return this.replace( /&lt;/g, '<' ).replace( /&gt;/g, '>' ).replace( /&amp;/g, '&' );
}

String.prototype.surround = function(t, side)
{
	side = side || 3;
	return (1==1&side?t:'')+this+(2==2&side?t:'');
}

String.prototype.surroundTag = function(t)
{
	return '<'+t+'>'+this+'</'+t+'>';
}

// example of use: var pattern = '? is ?; alert(pattern.embed('Decin', 'sunny')); pattern = '@city is @weather'; alert(pattern.embed({weather:'cloudy', city:'Decin'}))
String.prototype.embed = function()
{
	var t = this;
	if ( 1 == arguments.length && 'object' == typeof arguments[0] )
	{
		// named placeholders
		for ( var i in arguments[0] )
		{
			eval('var re=/@'+i+'/g;');
			t = t.replace(re, arguments[0][i]);
		}
	}
	else
	{
		// anonymous placeholders `?`
		for ( var i=0; i<arguments.length; i++ )
		{
			var ix = t.indexOf('?');
			if ( -1 != ix )
			{
				t = t.substr(0,ix)+arguments[i]+t.substr(ix+1);
				continue;
			}
			break;
		}
	}
	return t;
}

// Tuning helpers - dealing with user-agent differences
var $__tune = 
{
	__prop:{},
	isIE:('function' == typeof window.ActiveXObject),
	isSafari:-1!=navigator.appVersion.indexOf('afari'),
	isGecko:false,
	node:
	{
		getOpacity:function(node)
		{
			if ( $__tune.isIE )
			{
				var f = node.style.filter;
				if ( !f || -1 == f.indexOf('alpha') )
				{
					return 1.0;
				}
				return 1.0;
			}
			return parseFloat(node.style[$__tune.isGecko?'MozOpacity':'opacity'] || 1.0);
		},
		setOpacity:function(node, opacity)
		{
			if ( $__tune.isIE )
			{
				node.style.filter = 'alpha(opacity='+(100*opacity)+')';
			}
			else
			{
				node.style.opacity = opacity;
				node.style.MozOpacity = opacity;
			}
		},
		getPageScrollPosition:function()
		{
			var d = document.documentElement;
			if ( d && d.scrollTop) 
			{
				return [d.scrollLeft, d.scrollTop];
			} 
			else if (document.body) 
			{
				return [document.body.scrollLeft, document.body.scrollTop];
			}
			else
			{
				return [0, 0];
			}
		}
	},
	event:
	{
		get:function(evt, type)
		{
			if ( $notset(evt.target) )
			{
				evt.target = evt.srcElement;
				evt.stopPropagation = function()
				{
					window.event.cancelBubble = true;
				};
			}
			evt.stop = function()
			{
				evt.stopPropagation();
				evt.stopped = true;
			}
			evt.$ = $(evt.target);
			if ( $notset(evt.pageX) )
			{
				evt.pageX = evt.clientX + document.body.scrollLeft;
				evt.pageY = evt.clientY + document.body.scrollTop;
			}
			evt.getOffsetX = function()
			{
				if ( $notset(evt.offsetX) )
				{
					var pos = evt.$.abspos();
					evt.offsetX = evt.pageX - pos.x;
					evt.offsetY = evt.pageY - pos.y;
				}
				return evt.offsetX;
			}
			evt.getOffsetY = function()
			{
				if ( $notset(evt.offsetY) )
				{
					var pos = evt.$.abspos();
					evt.offsetX = evt.pageX - pos.x;
					evt.offsetY = evt.pageY - pos.y;
				}
				return evt.offsetY;				
			}
			evt.isAnyControlKeyPressed = function()
			{
				return evt.metaKey||evt.controlKey||evt.altKey||evt.shiftKey;
			}
			evt.KEY_ESCAPE = 27;
			evt.KEY_ENTER = 13;
			evt.KEY_ARR_RIGHT = 39;
			evt.KEY_ARR_LEFT = 37;
			evt.KEY_ARR_UP = 38;
			evt.KEY_ARR_DOWN = 40;
			return evt;
		},
		addListener:function(node, type, listener)
		{
			if ( $__tune.isIE )
			{
                node.attachEvent('on'+type, listener);
			}
			else
			{
				node.addEventListener(type, listener, false);
			}
		},
		removeListener:function(node, type, listener)
		{
			if ( $__tune.isIE )
			{
                node.detachEvent('on'+type, listener);
			}
			else
			{
					node.removeEventListener(type, listener, false);
			}				
		}		
	},
	behavior:
	{
		disablePageScroll:function()
		{
			if ( $notset($__tune.__prop.page_scroll) )
			{
				$__tune.__prop.page_scroll = [$().s().overflow, $().ga('scroll')];
			}
			$().s('overflow:hidden').sa('scroll', 'no');
		},
		enablePageScroll:function()
		{
			$().s('overflow:auto').sa('scroll', 'yes');
		},
		disableCombos:function()
		{
			$().g('select', function(node)
			{
				node.sa('__dis_combo', node.s().visibility);
				$(node).v(false);
			});
		},
		enableCombos:function()
		{
			$().g('select', function(node)
			{
				node.s({visibility:node.ga('__dis_combo') || 'visible'});
			});
		},
		clearSelection:function()
		{
			try
			{
				if ( window.getSelection )
				{
					if ( $__tune.isSafari )
					{
						window.getSelection().collapse();
					}
					else
					{
						window.getSelection().removeAllRanges();
					}
				}
				else
				{
					if ( document.selection )
					{
						if ( document.selection.empty )
						{
							document.selection.empty();
						}
						else
						{
							if ( document.selection.clear )
							{
								document.selection.clear();
							}
						}
					}
				}
			}
			catch (e) {}
		},
		makeBodyUnscrollable:function()
		{
			$().s('position:fixed').w(fry.ui.info.page.width);
		}
	},
	ui:
	{
		scrollbarWidth:-1!=navigator.appVersion.indexOf('intosh')?15:17
	}
}
// some browsers masks its presence having Gecko string somewhere inside its userAgent field...
$__tune.isGecko = !$__tune.isSafari&&!$__tune.isIE&&-1!=navigator.userAgent.indexOf('ecko');

// Node manipulations

function ACNode(node)
{
	this.$ = node;
	if ( node )
	{
		node.setAttribute('fryis', '1');		
	}
}
// `$$` creates new node
ACNode.prototype.$$ = function(tagName)
{
	return $$(tagName);
}
// *is* - tells whether node is a part of the active DOM tree (that is displayed on page). Node may exist only in memory before appending or after removing when references, in which case node.is() will return false.
ACNode.prototype.is = function()
{
	return this.$ && null != this.$.parentNode;
}
// *i*d
ACNode.prototype.i = function(id)
{
	if ( 'undefined' == typeof id )
	{
		return this.$.id||'';
	}
	this.$.id = id;
	return this;
}
// class *n*ame
ACNode.prototype.n = function(n)
{
	if ( 'undefined' == typeof n)
	{
		return this.$.className||'';
	}
	this.$.className = n;
	return this;
}
// *e*vent listener, if called with one argument only, previously registered listeners are removed
ACNode.prototype.e = function(t, c, oneUseOnly)
{
	var ser_type_id = 'fryse-'+t;
	if ( !c )
	{
		if ( null != this.$.getAttribute(ser_type_id) )
		{
			var ser_listeners = this.$.getAttribute(ser_type_id).split(',');
	//		console.log('*E* removing listeners for %s, listeners: %s', t, ser_listeners);
			for ( var i=0; i<ser_listeners.length; i++ )
			{
				$__tune.event.removeListener(this.$, t, self[ser_listeners[i]]);
				self[ser_listeners[i]] = null;
			}
			this.$['on'+t] = null;
			this.$.removeAttribute(ser_type_id);
		}
		return this;
	}
	var hash = t+(''+Math.random()).substr(2);
	var ser_listeners = null != this.$.getAttribute(ser_type_id) ? this.$.getAttribute(ser_type_id).split(',') : [];
	ser_listeners.push(hash);
	this.$.setAttribute(ser_type_id, ser_listeners.join(','));
//	console.log('*E* add listener self.%s for %s', hash, t);
	self[hash] = function(evt)
	{
		evt.removeListener = function()
		{
			$__tune.event.removeListener(evt.$.$, t, self[hash]);
//			console.log('*E* remove listener self.%s for %s', hash, t);
			c = null;
			evt = null;
			self[hash] = null;
		}
		evt = evt || self.event;
		if ( null != c )
		{
			c($__tune.event.get(evt));			
		}
		if ( null != evt )
		{
			if ( oneUseOnly )
			{
				evt.removeListener();
				return;
			}
			else if ( evt.stopped )
			{
//				console.log('*E* stop self.%s for %s', hash, t);
				evt = null;				
			}
		}
	};
	this.$.setAttribute('fryhe', 1);
	$__tune.event.addListener(this.$, t, self[hash]);
	return this;
}
// *x* coordinate
ACNode.prototype.x = function(x)
{
	if ( 'undefined' == typeof x )
	{
		return parseInt(this.$.style.left||0);
	}
	this.$.style.left = x+'px';
	return this;
}
// *y* coordinate
ACNode.prototype.y = function(y)
{
	if ( 'undefined' == typeof y )
	{
		return parseInt(this.$.style.top||0);
	}
	this.$.style.top = y+'px';
	return this;
}
// *abs*olute page *pos*ition coordinates (you can optionally specify node to which the position is calculated), returns {x:, y:} coordinates
ACNode.prototype.abspos = function(n)
{
	if ( document.getBoxObjectFor )
	{
		var p = document.getBoxObjectFor(this.$);
		return {x:p.x, y:p.y};
	}
	if ( this.$.getBoundingClientRect )
	{
		var p = this.$.getBoundingClientRect();
		return {x:p.left+(document.documentElement.scrollLeft || document.body.scrollLeft), y:p.top+(document.documentElement.scrollTop || document.body.scrollTop)};
	}
	var p = {x:0, y:0};
	var n2 = this.$;
	while ( document.body != n2 && document != n2 && n != n2 )
	{
		p.x += n2.offsetLeft - n2.scrollLeft;
		p.y += n2.offsetTop - n2.scrollTop;
		if ( n2.offsetParent )
		{
			n2 = n2.offsetParent;
		}
		else
		{
			n2 = n2.parentNode;
		}
	}
	return p;
}
// *pos*ition, if true - absolute, false - relative
ACNode.prototype.pos = function(p)
{
	if ( 'undefined' == typeof p )
	{
		return 'absolute' == this.$.style.position;
	}
	this.$.style.position = p ? 'absolute' : 'relative';
	return this;
}
// *z*-index coordinate
ACNode.prototype.z = function(z)
{
	if ( 'undefined' == typeof z )
	{
		return parseInt(this.$.style.zIndex||0);
	}
	this.$.style.zIndex = z;
	return this;
}
// *w*idth
ACNode.prototype.w = function(w)
{
	if ( 'undefined' == typeof w )
	{
		return parseInt(this.$.style.width||this.$.offsetWidth);
	}
	this.$.style.width = w+'px';
	return this;
}
// *h*eight
ACNode.prototype.h = function(h)
{
	if ( 'undefined' == typeof h )
	{
		return parseInt(this.$.style.height||this.$.offsetHeight);
	}
	this.$.style.height = h+'px';
	if ( $__tune.isIE && 8 > h )
	{
		this.$.style.fontSize = '1px';
	}
	return this;
}
// *s*tyle information - argument can be either "{color:'red', backgroundColor:'blue'}" or "'color:red;background-color:blue'"
ACNode.prototype.s = function(s)
{
	if ( 'undefined' == typeof s )
	{
		return this.$.style;
	}
	if ( 'object' == typeof s )
	{
		for ( var n in s )
		{
			this.$.style[n] = s[n];
		}
	}
	else if ( 'string' == typeof s )
	{
		if ( '' != s )
		{
			var styles = s.split(';');
			for ( var i=0; i<styles.length; i++ )
			{
				var style = styles[i].split(':');
				if ( 2 == style.length )
				{
					this.$.style[style[0].trim().camelize()] = style[1].trim();
				}
			}
		}
	}
	return this;
}
// *o*pacity
ACNode.prototype.o = function(o)
{
	if ( 'undefined' == typeof o )
	{
		return $__tune.node.getOpacity(this.$);
	}
	$__tune.node.setOpacity(this.$, o);
	return this;
}
// *d*isplay
ACNode.prototype.d = function(d)
{
	if ( 'undefined' == typeof d )
	{
		return 'none' != this.$.style.display;
	}
	this.$.style.display = d ? 'block' : 'none';
	return this;						
}
// *v*isibility
ACNode.prototype.v = function(v)
{
	if ( 'undefined' == typeof v )
	{
		return 'hidden' != this.$.style.visibility;
	}
	this.$.style.visibility = v ? 'visible' : 'hidden';
	return this;			
}
// H*T*ML source (equivalent to infamous innerHTML, remember innerHTML is not considered *evil* here - see the KISS principle, plus it's actually faster than DOM)
ACNode.prototype.t = function(t)
{
	if ( 'undefined' == typeof t )
	{
		return this.$.innerHTML;
	}
	this.rc();
	this.$.innerHTML = t;
	return this;
}
// *p*arent node
ACNode.prototype.p = function(p)
{
	if ( 'undefined' == typeof p )
	{
		return $(this.$.parentNode);
	}
	return $(p).a(this);
}
// *g*et child node(s), the format of a query might be either `[['table',0],['tr',2],['td',4]]`, `['table',['tr',2],['td',4]]`, 'table:0/tr:2/td:4' or 'table/tr:2/td:4'. you can use `*` in path for any node
ACNode.prototype.g = function(q)
{
	var lst = [];
	if ( 'string' == typeof q )
	{
		var qt = q.split('/');
		q = [];
		for ( var i=0; i<qt.length; i++ )
		{
			var qtt = qt[i].split(':');
			q[q.length] = qtt;
		}
	}
	var lookup = function(node, qIndex)
	{
		if ( !node )
		{
			return;
		}
		var qq = q[qIndex];
		var is_final_index = q.length-1 == qIndex;
		var ls = node.getElementsByTagName(qq[0]);
		var num = ls.length;
		if ( 2 == qq.length )
		{
			// specific node required
			if ( is_final_index )
			{
				// store results
				lst.push($(ls.item(parseInt(qq[1]))));
			}
			else
			{
				lookup(ls.item(parseInt(qq[1])), qIndex+1);
			}
		}
		else
		{
			// all nodes required
			for ( var i=0; i<num; i++ )
			{
				if ( is_final_index )
				{
					lst.push($(ls.item(i)));
				}
				else
				{
					lookup(ls.item(i), qIndex+1);
				}
			}
		}
		ls = null;
	}
	lookup(this.$, 0);
	lookup = null;
	var num = lst.length;
	if ( 1 == num )
	{
		return lst[0];
	}
	else if ( 0 == num )
	{
		lst = null;
	}
	return lst;
}
// *g*et *p*arent node at some path - allows for returning grand-grand-grand...parent node. imagine node tree: `div>div>table>tbody>tr>td>` and node at `td`
// to return second div you would call `gp('tr/tbody/table/div')` or `tr/table/div:1`, first div could be acquired using `table/div:2` etc. you can use `*` for any node.
ACNode.prototype.gp = function(q)
{
	if ( 'string' == typeof q )
	{
		q = q.split('/');
	}
	var fq = [];
	for ( var i=0; i<q.length; i++ )
	{
		if ( -1 != q[i].indexOf(':') )
		{
			q[i] = q[i].split(':');
			for ( var ii=0; ii<q[i][1]; ii++ )
			{
				fq.push(q[i][0]);
			}
		}
		else
		{
			fq.push(q[i]);
		}
	}
	var c = 0;
	var p = this.$;
	while ( p && c < fq.length)
	{
		p = p.parentNode;
		if ( '*' == fq[c] || fq[c] == p.tagName.toLowerCase() )
		{
			c++;
		}
	}
	return $(p);
}
// *a*ppends child node
ACNode.prototype.a = function(n)
{
	if ( 'undefined' != typeof n['$'] )
	{
		n = n.$;
	}
	return $(this.$.appendChild(n));
}
// *a*ppend H*T*ML code - adds innerHTML to existing node code
ACNode.prototype.at = function(t)
{
	var ht = this.$.innerHTML;
	this.$.innerHTML = ht + t;
	return this;
}
// *r*emoves child node
ACNode.prototype.r = function(n)
{
	if ( 'undefined' != typeof n['$'] )
	{
		n = n.$;
	}
	return $(this.$.removeChild(n));
}
// *r*emove *c*hildren
ACNode.prototype.rc = function()
{
	if ( !this.$ )
	{
		return this;
	}
	if ( -1 != this.$.innerHTML.indexOf('fryse') )
	{
//		__fry_gcnode_fast(this.$);		
		__fry_gcnode(this.$, true);
	}
	this.$.innerHTML = '';
	return this;
}

function __fry_gcnode_fast(inode)
{
	var ht = inode.innerHTML;
	var ht2 = ht.replace(/fryse\-[^=]*="([^"]*)"/g, function()
	{
//		console.log('%o', arguments);
		var ser_listeners = arguments[1].split(',');
		for ( var i=0; i<ser_listeners.length; i++ )
		{
//			console.log(ser_listeners[i]);
			self[ser_listeners[i]] = null;
		}
		return '';
	});
//	console.log(ht2);
//	alert(ht2);
	
}

function __fry_gcnode_inner(inode)
{
	if ( null != inode.getAttribute('frydrag') )
	{
		$(inode).removeDrag();
	}
	if ( null != inode.getAttribute('frydnd') )
	{
		$(inode).removeDnD();
	}
	if ( null == inode.getAttribute('fryis') || null == inode.getAttribute('fryhe') )
	{
		inode = null;
		return;
	}
	inode.removeAttribute('fryhe');
	var lst = inode.attributes;
	var num = lst.length;
	for ( var i=0; i<num; i++ )
	{
		var attr_name = lst.item(i).name;
		if ( attr_name && 'fryse' == attr_name.substr(0,5) )
		{
			var type = attr_name.substr(6);
			var listeners = lst.item(i).value.split(',');
			for ( var ii=0; ii<listeners.length; ii++ )
			{
				$__tune.event.removeListener(inode, type, self[listeners[ii]]);
				self[listeners[ii]] = null;
			}
		}
		attr = null;
	}
	lst = null;
	for ( var i in inode )
	{
		if ( 'on' == i.substr(0,2) && 'function' == typeof inode[i] )
		{
			inode[i] = null;
		}
	}
	inode = null;
}
function __fry_gcnode(node, skipSelf)
{
	var lst = node.getElementsByTagName('*');
	var num = lst.length;
	for ( var i=0; i<num; i++ )
	{
		__fry_gcnode_inner(lst.item(i));
	}
	if ( !skipSelf )
	{
		__fry_gcnode_inner(node);		
	}
	lst = null;
	node = null;
}
// *r*emoves *s*elf node
ACNode.prototype.rs = function()
{
	if ( !this.$ )
	{
		return;
	}
	__fry_gcnode(this.$);	
	this.$.parentNode.removeChild(this.$);
	this.$ = null;
}
// *g*et *a*ttribute
ACNode.prototype.ga = function(n)
{
	return this.$.getAttribute(n);
}
// *s*et *a*ttribute
ACNode.prototype.sa = function(n, v)
{
	this.$.setAttribute(n, v);
	return this;
}
// *r*emove *a*ttribute
ACNode.prototype.ra = function(n)
{
	this.$.removeAttribute(n);
	return this;
}

// `$_` converts any value into string - useful for numeric values before calling for String enhanced methods.
var $_ = function(t)
{
	return ''+t;
}

// `$$` creates new node with specified tag name, returns $-ed node
var $$ = function(n)
{
	return $(document.createElement(n||'div'));
}

// returns $-ed node for existing node, argument can be either ID string or node itself (standard or $-ed). If argument is omitted, returns the body node
var $ = function(id)
{
	if ( 'undefined' == typeof id )
	{
		return $(document.body || document.getElementsByTagName('body').item(0));
	}
	if ( 'undefined' == id || null == id )
	{
		return null;
	}
	if ( 'object' != typeof id )
	{
		return new ACNode(document.getElementById(id));
	}
	else
	{
		if ( id instanceof ACNode )
		{
			return id;
		}
		if ( 1 != id.nodeType )
		{
			return null;
		}
		return new ACNode(id);
	}
}

// Language constructs

var $runafter = function(t, c)
{
	setTimeout(c, t);
}
var $runinterval = function(from, to, interval, c)
{
	var i = from;
	var control = 
	{
		from:from,
		to:to,
		stopped:false,
		stop:function()
		{
			this.stopped = true;
		}
	}
	var t = self.setInterval(function()
	{
		if ( i > to && to>=from )
		{
			self.clearInterval(t);
		}
		else
		{
			c(i, control);
			if ( control.stopped )
			{
				self.clearInterval(t);
			}
		}
		i++;
	}, interval);
}
var $dotimes = function(n, c)
{
	for ( var i=0; i<n; i++ )
	{
		c(i);
	}
}
var $foreach = function(o, c)
{
	if ( !o )
	{
		c = null;
		return;
	}
	if ( 'undefined' == typeof o.length && 'function' != typeof o.__length )
	{
		c = null;
		return;
	}
	var n = 'function' == typeof o.__length ? o.__length() : o.length;
	var control = 
	{
		stopped:false,
		stop:function()
		{
			this.stopped = true;
		},
		skipped:false,
		skip:function()
		{
			this.skipped = true;
		},
		removed:false,
		remove:function(stopAfterwards)
		{
			this.removed = true;
			this.stopped = true == stopAfterwards;
		}
	}
	// cannot just extend Array.prototype for `item()` method due bug in IE6 iteration mechanism. Some day (>2010 :) this might get fixed and will become obsolete
	for ( var i=0; i<n; i++ )
	{
		var item = null;
		if ( 'function' == typeof o.item )
		{
			item = o.item(i);
		}
		else if ( 'function' == typeof o.__item )
		{
			item = o.__item(i);
		}
		else
		{
			if ( 'undefined' == typeof o[i] )
			{
				continue;
			}
			item = o[i];
		}
		c(item, 'function' == typeof o.__key ? o.__key(i) : i, control);
		if ( control.removed )
		{
			control.removed = false;
			if ( 'undefined' != typeof o[i] )
			{
				delete o[i];
			}
			else
			{
				if ( 'function' == typeof o.removeItem )
				{
					o.removeItem(i);
				}
				else if ( 'function' == typeof o.__remove )
				{
					o.remove(i);
				}
			}
		}
		if ( control.stopped )
		{
			break;
		}
		if ( control.skipped )
		{
			control.skipped = false;
			continue;
		}
	}
	control = null;
	c = null;	
}

var $notset = function(value)
{
	return ( 'undefined' == typeof value || 'undefined' == value || null == value );
}
var $isset = function(value)
{
	return ( 'undefined' != typeof value && 'undefined' != value && null != value );
}
var $getdef = function(value, defaultValue)
{
	if ( 'undefined' == typeof value || 'undefined' == value || null == value )
	{
		return defaultValue;
	}
	return value;
}

/* Reserving global `fry` object */
var fry = 
{
	version:1.0
};


/* Generic exception object */
function FryException(code, message)
{
	this.code = code;
	this.message = message;
}
FryException.prototype.toString = function()
{
	return 'Fry Exception: code[?] message[?]'.embed(this.code, this.message);
}


$__tune.event.addListener(self, 'unload', function(evt)
{
	$().rs();
});

