if (typeof Translation == 'undefined') {
	var Translation = {};
}

Array.prototype.indexOf = function(str) {
    for(var i = 0; i < this.length; i++) {
        if(this[i] == str) {
            return i;
        }
    }
    return -1;
}

String.prototype.translate = function (params) {
    var str = this;
	if (typeof Translation != 'undefined' && typeof Translation[this] != 'undefined') {
        var re;
		str = Translation[this];
	}
    if (params) {
        for (param in params) {
            re = new RegExp('%' + param + '%', 'g');
            str = str.replace(re, params[param]);
        }
    }
    return str;
};

String.prototype.trunc = function(len) {
        if (this.length > len) {
                var cut = Math.floor((len - 3) / 2);
                var re = new RegExp('^(.{' + cut + '}).+(.{' + cut + '})$');
                return  this.replace(re, '$1...$2');
        }

        return this;
};


(function(){
/*
 * jQuery 1.2.3 - New Wave Javascript
 *
 * Copyright (c) 2008 John Resig (jquery.com)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * $Date: 2008-02-06 00:21:25 -0500 (Wed, 06 Feb 2008) $
 * $Rev: 4663 $
 */

// Map over jQuery in case of overwrite
if ( window.jQuery )
	var _jQuery = window.jQuery;

var jQuery = window.jQuery = function( selector, context ) {
	// The jQuery object is actually just the init constructor 'enhanced'
	return new jQuery.prototype.init( selector, context );
};

// Map over the $ in case of overwrite
if ( window.$ )
	var _$ = window.$;
	
// Map the jQuery namespace to the '$' one
window.$ = jQuery;

// A simple way to check for HTML strings or ID strings
// (both of which we optimize for)
var quickExpr = /^[^<]*(<(.|\s)+>)[^>]*$|^#(\w+)$/;

// Is it a simple selector
var isSimple = /^.[^:#\[\.]*$/;

jQuery.fn = jQuery.prototype = {
	init: function( selector, context ) {
		// Make sure that a selection was provided
		selector = selector || document;

		// Handle $(DOMElement)
		if ( selector.nodeType ) {
			this[0] = selector;
			this.length = 1;
			return this;

		// Handle HTML strings
		} else if ( typeof selector == "string" ) {
			// Are we dealing with HTML string or an ID?
			var match = quickExpr.exec( selector );

			// Verify a match, and that no context was specified for #id
			if ( match && (match[1] || !context) ) {

				// HANDLE: $(html) -> $(array)
				if ( match[1] )
					selector = jQuery.clean( [ match[1] ], context );

				// HANDLE: $("#id")
				else {
					var elem = document.getElementById( match[3] );

					// Make sure an element was located
					if ( elem )
						// Handle the case where IE and Opera return items
						// by name instead of ID
						if ( elem.id != match[3] )
							return jQuery().find( selector );

						// Otherwise, we inject the element directly into the jQuery object
						else {
							this[0] = elem;
							this.length = 1;
							return this;
						}

					else
						selector = [];
				}

			// HANDLE: $(expr, [context])
			// (which is just equivalent to: $(content).find(expr)
			} else
				return new jQuery( context ).find( selector );

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) )
			return new jQuery( document )[ jQuery.fn.ready ? "ready" : "load" ]( selector );

		return this.setArray(
			// HANDLE: $(array)
			selector.constructor == Array && selector ||

			// HANDLE: $(arraylike)
			// Watch for when an array-like object, contains DOM nodes, is passed in as the selector
			(selector.jquery || selector.length && selector != window && !selector.nodeType && selector[0] != undefined && selector[0].nodeType) && jQuery.makeArray( selector ) ||

			// HANDLE: $(*)
			[ selector ] );
	},
	
	// The current version of jQuery being used
	jquery: "1.2.3",

	// The number of elements contained in the matched element set
	size: function() {
		return this.length;
	},
	
	// The number of elements contained in the matched element set
	length: 0,

	// Get the Nth element in the matched element set OR
	// Get the whole matched element set as a clean array
	get: function( num ) {
		return num == undefined ?

			// Return a 'clean' array
			jQuery.makeArray( this ) :

			// Return just the object
			this[ num ];
	},
	
	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems ) {
		// Build a new jQuery matched element set
		var ret = jQuery( elems );

		// Add the old object onto the stack (as a reference)
		ret.prevObject = this;

		// Return the newly-formed element set
		return ret;
	},
	
	// Force the current matched set of elements to become
	// the specified array of elements (destroying the stack in the process)
	// You should use pushStack() in order to do this, but maintain the stack
	setArray: function( elems ) {
		// Resetting the length to 0, then using the native Array push
		// is a super-fast way to populate an object with array-like properties
		this.length = 0;
		Array.prototype.push.apply( this, elems );
		
		return this;
	},

	// Execute a callback for every element in the matched set.
	// (You can seed the arguments with an array of args, but this is
	// only used internally.)
	each: function( callback, args ) {
		return jQuery.each( this, callback, args );
	},

	// Determine the position of an element within 
	// the matched set of elements
	index: function( elem ) {
		var ret = -1;

		// Locate the position of the desired element
		this.each(function(i){
			if ( this == elem )
				ret = i;
		});

		return ret;
	},

	attr: function( name, value, type ) {
		var options = name;
		
		// Look for the case where we're accessing a style value
		if ( name.constructor == String )
			if ( value == undefined )
				return this.length && jQuery[ type || "attr" ]( this[0], name ) || undefined;

			else {
				options = {};
				options[ name ] = value;
			}
		
		// Check to see if we're setting style values
		return this.each(function(i){
			// Set all the styles
			for ( name in options )
				jQuery.attr(
					type ?
						this.style :
						this,
					name, jQuery.prop( this, options[ name ], type, i, name )
				);
		});
	},

	css: function( key, value ) {
		// ignore negative width and height values
		if ( (key == 'width' || key == 'height') && parseFloat(value) < 0 )
			value = undefined;
		return this.attr( key, value, "curCSS" );
	},

	text: function( text ) {
		if ( typeof text != "object" && text != null )
			return this.empty().append( (this[0] && this[0].ownerDocument || document).createTextNode( text ) );

		var ret = "";

		jQuery.each( text || this, function(){
			jQuery.each( this.childNodes, function(){
				if ( this.nodeType != 8 )
					ret += this.nodeType != 1 ?
						this.nodeValue :
						jQuery.fn.text( [ this ] );
			});
		});

		return ret;
	},

	wrapAll: function( html ) {
		if ( this[0] )
			// The elements to wrap the target around
			jQuery( html, this[0].ownerDocument )
				.clone()
				.insertBefore( this[0] )
				.map(function(){
					var elem = this;

					while ( elem.firstChild )
						elem = elem.firstChild;

					return elem;
				})
				.append(this);

		return this;
	},

	wrapInner: function( html ) {
		return this.each(function(){
			jQuery( this ).contents().wrapAll( html );
		});
	},

	wrap: function( html ) {
		return this.each(function(){
			jQuery( this ).wrapAll( html );
		});
	},

	append: function() {
		return this.domManip(arguments, true, false, function(elem){
			if (this.nodeType == 1)
				this.appendChild( elem );
		});
	},

	prepend: function() {
		return this.domManip(arguments, true, true, function(elem){
			if (this.nodeType == 1)
				this.insertBefore( elem, this.firstChild );
		});
	},
	
	before: function() {
		return this.domManip(arguments, false, false, function(elem){
			this.parentNode.insertBefore( elem, this );
		});
	},

	after: function() {
		return this.domManip(arguments, false, true, function(elem){
			this.parentNode.insertBefore( elem, this.nextSibling );
		});
	},

	end: function() {
		return this.prevObject || jQuery( [] );
	},

	find: function( selector ) {
		var elems = jQuery.map(this, function(elem){
			return jQuery.find( selector, elem );
		});

		return this.pushStack( /[^+>] [^+>]/.test( selector ) || selector.indexOf("..") > -1 ?
			jQuery.unique( elems ) :
			elems );
	},

	clone: function( events ) {
		// Do the clone
		var ret = this.map(function(){
			if ( jQuery.browser.msie && !jQuery.isXMLDoc(this) ) {
				// IE copies events bound via attachEvent when
				// using cloneNode. Calling detachEvent on the
				// clone will also remove the events from the orignal
				// In order to get around this, we use innerHTML.
				// Unfortunately, this means some modifications to 
				// attributes in IE that are actually only stored 
				// as properties will not be copied (such as the
				// the name attribute on an input).
				var clone = this.cloneNode(true),
					container = document.createElement("div");
				container.appendChild(clone);
				return jQuery.clean([container.innerHTML])[0];
			} else
				return this.cloneNode(true);
		});

		// Need to set the expando to null on the cloned set if it exists
		// removeData doesn't work here, IE removes it from the original as well
		// this is primarily for IE but the data expando shouldn't be copied over in any browser
		var clone = ret.find("*").andSelf().each(function(){
			if ( this[ expando ] != undefined )
				this[ expando ] = null;
		});
		
		// Copy the events from the original to the clone
		if ( events === true )
			this.find("*").andSelf().each(function(i){
				if (this.nodeType == 3)
					return;
				var events = jQuery.data( this, "events" );

				for ( var type in events )
					for ( var handler in events[ type ] )
						jQuery.event.add( clone[ i ], type, events[ type ][ handler ], events[ type ][ handler ].data );
			});

		// Return the cloned set
		return ret;
	},

	filter: function( selector ) {
		return this.pushStack(
			jQuery.isFunction( selector ) &&
			jQuery.grep(this, function(elem, i){
				return selector.call( elem, i );
			}) ||

			jQuery.multiFilter( selector, this ) );
	},

	not: function( selector ) {
		if ( selector.constructor == String )
			// test special case where just one selector is passed in
			if ( isSimple.test( selector ) )
				return this.pushStack( jQuery.multiFilter( selector, this, true ) );
			else
				selector = jQuery.multiFilter( selector, this );

		var isArrayLike = selector.length && selector[selector.length - 1] !== undefined && !selector.nodeType;
		return this.filter(function() {
			return isArrayLike ? jQuery.inArray( this, selector ) < 0 : this != selector;
		});
	},

	add: function( selector ) {
		return !selector ? this : this.pushStack( jQuery.merge( 
			this.get(),
			selector.constructor == String ? 
				jQuery( selector ).get() :
				selector.length != undefined && (!selector.nodeName || jQuery.nodeName(selector, "form")) ?
					selector : [selector] ) );
	},

	is: function( selector ) {
		return selector ?
			jQuery.multiFilter( selector, this ).length > 0 :
			false;
	},

	hasClass: function( selector ) {
		return this.is( "." + selector );
	},
	
	val: function( value ) {
		if ( value == undefined ) {

			if ( this.length ) {
				var elem = this[0];

				// We need to handle select boxes special
				if ( jQuery.nodeName( elem, "select" ) ) {
					var index = elem.selectedIndex,
						values = [],
						options = elem.options,
						one = elem.type == "select-one";
					
					// Nothing was selected
					if ( index < 0 )
						return null;

					// Loop through all the selected options
					for ( var i = one ? index : 0, max = one ? index + 1 : options.length; i < max; i++ ) {
						var option = options[ i ];

						if ( option.selected ) {
							// Get the specifc value for the option
							value = jQuery.browser.msie && !option.attributes.value.specified ? option.text : option.value;
							
							// We don't need an array for one selects
							if ( one )
								return value;
							
							// Multi-Selects return an array
							values.push( value );
						}
					}
					
					return values;
					
				// Everything else, we just grab the value
				} else
					return (this[0].value || "").replace(/\r/g, "");

			}

			return undefined;
		}

		return this.each(function(){
			if ( this.nodeType != 1 )
				return;

			if ( value.constructor == Array && /radio|checkbox/.test( this.type ) )
				this.checked = (jQuery.inArray(this.value, value) >= 0 ||
					jQuery.inArray(this.name, value) >= 0);

			else if ( jQuery.nodeName( this, "select" ) ) {
				var values = value.constructor == Array ?
					value :
					[ value ];

				jQuery( "option", this ).each(function(){
					this.selected = (jQuery.inArray( this.value, values ) >= 0 ||
						jQuery.inArray( this.text, values ) >= 0);
				});

				if ( !values.length )
					this.selectedIndex = -1;

			} else
				this.value = value;
		});
	},
	
	html: function( value ) {
		return value == undefined ?
			(this.length ?
				this[0].innerHTML :
				null) :
			this.empty().append( value );
	},

	replaceWith: function( value ) {
		return this.after( value ).remove();
	},

	eq: function( i ) {
		return this.slice( i, i + 1 );
	},

	slice: function() {
		return this.pushStack( Array.prototype.slice.apply( this, arguments ) );
	},

	map: function( callback ) {
		return this.pushStack( jQuery.map(this, function(elem, i){
			return callback.call( elem, i, elem );
		}));
	},

	andSelf: function() {
		return this.add( this.prevObject );
	},

	data: function( key, value ){
		var parts = key.split(".");
		parts[1] = parts[1] ? "." + parts[1] : "";

		if ( value == null ) {
			var data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);
			
			if ( data == undefined && this.length )
				data = jQuery.data( this[0], key );

			return data == null && parts[1] ?
				this.data( parts[0] ) :
				data;
		} else
			return this.trigger("setData" + parts[1] + "!", [parts[0], value]).each(function(){
				jQuery.data( this, key, value );
			});
	},

	removeData: function( key ){
		return this.each(function(){
			jQuery.removeData( this, key );
		});
	},
	
	domManip: function( args, table, reverse, callback ) {
		var clone = this.length > 1, elems; 

		return this.each(function(){
			if ( !elems ) {
				elems = jQuery.clean( args, this.ownerDocument );

				if ( reverse )
					elems.reverse();
			}

			var obj = this;

			if ( table && jQuery.nodeName( this, "table" ) && jQuery.nodeName( elems[0], "tr" ) )
				obj = this.getElementsByTagName("tbody")[0] || this.appendChild( this.ownerDocument.createElement("tbody") );

			var scripts = jQuery( [] );

			jQuery.each(elems, function(){
				var elem = clone ?
					jQuery( this ).clone( true )[0] :
					this;

				// execute all scripts after the elements have been injected
				if ( jQuery.nodeName( elem, "script" ) ) {
					scripts = scripts.add( elem );
				} else {
					// Remove any inner scripts for later evaluation
					if ( elem.nodeType == 1 )
						scripts = scripts.add( jQuery( "script", elem ).remove() );

					// Inject the elements into the document
					callback.call( obj, elem );
				}
			});

			scripts.each( evalScript );
		});
	}
};

// Give the init function the jQuery prototype for later instantiation
jQuery.prototype.init.prototype = jQuery.prototype;

function evalScript( i, elem ) {
	if ( elem.src )
		jQuery.ajax({
			url: elem.src,
			async: false,
			dataType: "script"
		});

	else
		jQuery.globalEval( elem.text || elem.textContent || elem.innerHTML || "" );

	if ( elem.parentNode )
		elem.parentNode.removeChild( elem );
}

jQuery.extend = jQuery.fn.extend = function() {
	// copy reference to target object
	var target = arguments[0] || {}, i = 1, length = arguments.length, deep = false, options;

	// Handle a deep copy situation
	if ( target.constructor == Boolean ) {
		deep = target;
		target = arguments[1] || {};
		// skip the boolean and the target
		i = 2;
	}

	// Handle case when target is a string or something (possible in deep copy)
	if ( typeof target != "object" && typeof target != "function" )
		target = {};

	// extend jQuery itself if only one argument is passed
	if ( length == 1 ) {
		target = this;
		i = 0;
	}

	for ( ; i < length; i++ )
		// Only deal with non-null/undefined values
		if ( (options = arguments[ i ]) != null )
			// Extend the base object
			for ( var name in options ) {
				// Prevent never-ending loop
				if ( target === options[ name ] )
					continue;

				// Recurse if we're merging object values
				if ( deep && options[ name ] && typeof options[ name ] == "object" && target[ name ] && !options[ name ].nodeType )
					target[ name ] = jQuery.extend( target[ name ], options[ name ] );

				// Don't bring in undefined values
				else if ( options[ name ] != undefined )
					target[ name ] = options[ name ];

			}

	// Return the modified object
	return target;
};

var expando = "jQuery" + (new Date()).getTime(), uuid = 0, windowData = {};

// exclude the following css properties to add px
var exclude = /z-?index|font-?weight|opacity|zoom|line-?height/i;

jQuery.extend({
	noConflict: function( deep ) {
		window.$ = _$;

		if ( deep )
			window.jQuery = _jQuery;

		return jQuery;
	},

	// See test/unit/core.js for details concerning this function.
	isFunction: function( fn ) {
		return !!fn && typeof fn != "string" && !fn.nodeName && 
			fn.constructor != Array && /function/i.test( fn + "" );
	},
	
	// check if an element is in a (or is an) XML document
	isXMLDoc: function( elem ) {
		return elem.documentElement && !elem.body ||
			elem.tagName && elem.ownerDocument && !elem.ownerDocument.body;
	},

	// Evalulates a script in a global context
	globalEval: function( data ) {
		data = jQuery.trim( data );

		if ( data ) {
			// Inspired by code by Andrea Giammarchi
			// http://webreflection.blogspot.com/2007/08/global-scope-evaluation-and-dom.html
			var head = document.getElementsByTagName("head")[0] || document.documentElement,
				script = document.createElement("script");

			script.type = "text/javascript";
			if ( jQuery.browser.msie )
				script.text = data;
			else
				script.appendChild( document.createTextNode( data ) );

			head.appendChild( script );
			head.removeChild( script );
		}
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toUpperCase() == name.toUpperCase();
	},
	
	cache: {},
	
	data: function( elem, name, data ) {
		elem = elem == window ?
			windowData :
			elem;

		var id = elem[ expando ];

		// Compute a unique ID for the element
		if ( !id ) 
			id = elem[ expando ] = ++uuid;

		// Only generate the data cache if we're
		// trying to access or manipulate it
		if ( name && !jQuery.cache[ id ] )
			jQuery.cache[ id ] = {};
		
		// Prevent overriding the named cache with undefined values
		if ( data != undefined )
			jQuery.cache[ id ][ name ] = data;
		
		// Return the named cache data, or the ID for the element	
		return name ?
			jQuery.cache[ id ][ name ] :
			id;
	},
	
	removeData: function( elem, name ) {
		elem = elem == window ?
			windowData :
			elem;

		var id = elem[ expando ];

		// If we want to remove a specific section of the element's data
		if ( name ) {
			if ( jQuery.cache[ id ] ) {
				// Remove the section of cache data
				delete jQuery.cache[ id ][ name ];

				// If we've removed all the data, remove the element's cache
				name = "";

				for ( name in jQuery.cache[ id ] )
					break;

				if ( !name )
					jQuery.removeData( elem );
			}

		// Otherwise, we want to remove all of the element's data
		} else {
			// Clean up the element expando
			try {
				delete elem[ expando ];
			} catch(e){
				// IE has trouble directly removing the expando
				// but it's ok with using removeAttribute
				if ( elem.removeAttribute )
					elem.removeAttribute( expando );
			}

			// Completely remove the data cache
			delete jQuery.cache[ id ];
		}
	},

	// args is for internal usage only
	each: function( object, callback, args ) {
		if ( args ) {
			if ( object.length == undefined ) {
				for ( var name in object )
					if ( callback.apply( object[ name ], args ) === false )
						break;
			} else
				for ( var i = 0, length = object.length; i < length; i++ )
					if ( callback.apply( object[ i ], args ) === false )
						break;

		// A special, fast, case for the most common use of each
		} else {
			if ( object.length == undefined ) {
				for ( var name in object )
					if ( callback.call( object[ name ], name, object[ name ] ) === false )
						break;
			} else
				for ( var i = 0, length = object.length, value = object[0]; 
					i < length && callback.call( value, i, value ) !== false; value = object[++i] ){}
		}

		return object;
	},
	
	prop: function( elem, value, type, i, name ) {
			// Handle executable functions
			if ( jQuery.isFunction( value ) )
				value = value.call( elem, i );
				
			// Handle passing in a number to a CSS property
			return value && value.constructor == Number && type == "curCSS" && !exclude.test( name ) ?
				value + "px" :
				value;
	},

	className: {
		// internal only, use addClass("class")
		add: function( elem, classNames ) {
			jQuery.each((classNames || "").split(/\s+/), function(i, className){
				if ( elem.nodeType == 1 && !jQuery.className.has( elem.className, className ) )
					elem.className += (elem.className ? " " : "") + className;
			});
		},

		// internal only, use removeClass("class")
		remove: function( elem, classNames ) {
			if (elem.nodeType == 1)
				elem.className = classNames != undefined ?
					jQuery.grep(elem.className.split(/\s+/), function(className){
						return !jQuery.className.has( classNames, className );	
					}).join(" ") :
					"";
		},

		// internal only, use is(".class")
		has: function( elem, className ) {
			return jQuery.inArray( className, (elem.className || elem).toString().split(/\s+/) ) > -1;
		}
	},

	// A method for quickly swapping in/out CSS properties to get correct calculations
	swap: function( elem, options, callback ) {
		var old = {};
		// Remember the old values, and insert the new ones
		for ( var name in options ) {
			old[ name ] = elem.style[ name ];
			elem.style[ name ] = options[ name ];
		}

		callback.call( elem );

		// Revert the old values
		for ( var name in options )
			elem.style[ name ] = old[ name ];
	},

	css: function( elem, name, force ) {
		if ( name == "width" || name == "height" ) {
			var val, props = { position: "absolute", visibility: "hidden", display:"block" }, which = name == "width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ];
		
			function getWH() {
				val = name == "width" ? elem.offsetWidth : elem.offsetHeight;
				var padding = 0, border = 0;
				jQuery.each( which, function() {
					padding += parseFloat(jQuery.curCSS( elem, "padding" + this, true)) || 0;
					border += parseFloat(jQuery.curCSS( elem, "border" + this + "Width", true)) || 0;
				});
				val -= Math.round(padding + border);
			}
		
			if ( jQuery(elem).is(":visible") )
				getWH();
			else
				jQuery.swap( elem, props, getWH );
			
			return Math.max(0, val);
		}
		
		return jQuery.curCSS( elem, name, force );
	},

	curCSS: function( elem, name, force ) {
		var ret;

		// A helper method for determining if an element's values are broken
		function color( elem ) {
			if ( !jQuery.browser.safari )
				return false;

			var ret = document.defaultView.getComputedStyle( elem, null );
			return !ret || ret.getPropertyValue("color") == "";
		}

		// We need to handle opacity special in IE
		if ( name == "opacity" && jQuery.browser.msie ) {
			ret = jQuery.attr( elem.style, "opacity" );

			return ret == "" ?
				"1" :
				ret;
		}
		// Opera sometimes will give the wrong display answer, this fixes it, see #2037
		if ( jQuery.browser.opera && name == "display" ) {
			var save = elem.style.outline;
			elem.style.outline = "0 solid black";
			elem.style.outline = save;
		}
		
		// Make sure we're using the right name for getting the float value
		if ( name.match( /float/i ) )
			name = styleFloat;

		if ( !force && elem.style && elem.style[ name ] )
			ret = elem.style[ name ];

		else if ( document.defaultView && document.defaultView.getComputedStyle ) {

			// Only "float" is needed here
			if ( name.match( /float/i ) )
				name = "float";

			name = name.replace( /([A-Z])/g, "-$1" ).toLowerCase();

			var getComputedStyle = document.defaultView.getComputedStyle( elem, null );

			if ( getComputedStyle && !color( elem ) )
				ret = getComputedStyle.getPropertyValue( name );

			// If the element isn't reporting its values properly in Safari
			// then some display: none elements are involved
			else {
				var swap = [], stack = [];

				// Locate all of the parent display: none elements
				for ( var a = elem; a && color(a); a = a.parentNode )
					stack.unshift(a);

				// Go through and make them visible, but in reverse
				// (It would be better if we knew the exact display type that they had)
				for ( var i = 0; i < stack.length; i++ )
					if ( color( stack[ i ] ) ) {
						swap[ i ] = stack[ i ].style.display;
						stack[ i ].style.display = "block";
					}

				// Since we flip the display style, we have to handle that
				// one special, otherwise get the value
				ret = name == "display" && swap[ stack.length - 1 ] != null ?
					"none" :
					( getComputedStyle && getComputedStyle.getPropertyValue( name ) ) || "";

				// Finally, revert the display styles back
				for ( var i = 0; i < swap.length; i++ )
					if ( swap[ i ] != null )
						stack[ i ].style.display = swap[ i ];
			}

			// We should always get a number back from opacity
			if ( name == "opacity" && ret == "" )
				ret = "1";

		} else if ( elem.currentStyle ) {
			var camelCase = name.replace(/\-(\w)/g, function(all, letter){
				return letter.toUpperCase();
			});

			ret = elem.currentStyle[ name ] || elem.currentStyle[ camelCase ];

			// From the awesome hack by Dean Edwards
			// http://erik.eae.net/archives/2007/07/27/18.54.15/#comment-102291

			// If we're not dealing with a regular pixel number
			// but a number that has a weird ending, we need to convert it to pixels
			if ( !/^\d+(px)?$/i.test( ret ) && /^\d/.test( ret ) ) {
				// Remember the original values
				var style = elem.style.left, runtimeStyle = elem.runtimeStyle.left;

				// Put in the new values to get a computed value out
				elem.runtimeStyle.left = elem.currentStyle.left;
				elem.style.left = ret || 0;
				ret = elem.style.pixelLeft + "px";

				// Revert the changed values
				elem.style.left = style;
				elem.runtimeStyle.left = runtimeStyle;
			}
		}

		return ret;
	},
	
	clean: function( elems, context ) {
		var ret = [];
		context = context || document;
		// !context.createElement fails in IE with an error but returns typeof 'object'
		if (typeof context.createElement == 'undefined') 
			context = context.ownerDocument || context[0] && context[0].ownerDocument || document;

		jQuery.each(elems, function(i, elem){
			if ( !elem )
				return;

			if ( elem.constructor == Number )
				elem = elem.toString();
			
			// Convert html string into DOM nodes
			if ( typeof elem == "string" ) {
				// Fix "XHTML"-style tags in all browsers
				elem = elem.replace(/(<(\w+)[^>]*?)\/>/g, function(all, front, tag){
					return tag.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i) ?
						all :
						front + "></" + tag + ">";
				});

				// Trim whitespace, otherwise indexOf won't work as expected
				var tags = jQuery.trim( elem ).toLowerCase(), div = context.createElement("div");

				var wrap =
					// option or optgroup
					!tags.indexOf("<opt") &&
					[ 1, "<select multiple='multiple'>", "</select>" ] ||
					
					!tags.indexOf("<leg") &&
					[ 1, "<fieldset>", "</fieldset>" ] ||
					
					tags.match(/^<(thead|tbody|tfoot|colg|cap)/) &&
					[ 1, "<table>", "</table>" ] ||
					
					!tags.indexOf("<tr") &&
					[ 2, "<table><tbody>", "</tbody></table>" ] ||
					
				 	// <thead> matched above
					(!tags.indexOf("<td") || !tags.indexOf("<th")) &&
					[ 3, "<table><tbody><tr>", "</tr></tbody></table>" ] ||
					
					!tags.indexOf("<col") &&
					[ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ] ||

					// IE can't serialize <link> and <script> tags normally
					jQuery.browser.msie &&
					[ 1, "div<div>", "</div>" ] ||
					
					[ 0, "", "" ];

				// Go to html and back, then peel off extra wrappers
				div.innerHTML = wrap[1] + elem + wrap[2];
				
				// Move to the right depth
				while ( wrap[0]-- )
					div = div.lastChild;
				
				// Remove IE's autoinserted <tbody> from table fragments
				if ( jQuery.browser.msie ) {
					
					// String was a <table>, *may* have spurious <tbody>
					var tbody = !tags.indexOf("<table") && tags.indexOf("<tbody") < 0 ?
						div.firstChild && div.firstChild.childNodes :
						
						// String was a bare <thead> or <tfoot>
						wrap[1] == "<table>" && tags.indexOf("<tbody") < 0 ?
							div.childNodes :
							[];
				
					for ( var j = tbody.length - 1; j >= 0 ; --j )
						if ( jQuery.nodeName( tbody[ j ], "tbody" ) && !tbody[ j ].childNodes.length )
							tbody[ j ].parentNode.removeChild( tbody[ j ] );
					
					// IE completely kills leading whitespace when innerHTML is used	
					if ( /^\s/.test( elem ) )	
						div.insertBefore( context.createTextNode( elem.match(/^\s*/)[0] ), div.firstChild );
				
				}
				
				elem = jQuery.makeArray( div.childNodes );
			}

			if ( elem.length === 0 && (!jQuery.nodeName( elem, "form" ) && !jQuery.nodeName( elem, "select" )) )
				return;

			if ( elem[0] == undefined || jQuery.nodeName( elem, "form" ) || elem.options )
				ret.push( elem );

			else
				ret = jQuery.merge( ret, elem );

		});

		return ret;
	},
	
	attr: function( elem, name, value ) {
		// don't set attributes on text and comment nodes
		if (!elem || elem.nodeType == 3 || elem.nodeType == 8)
			return undefined;

		var fix = jQuery.isXMLDoc( elem ) ?
			{} :
			jQuery.props;

		// Safari mis-reports the default selected property of a hidden option
		// Accessing the parent's selectedIndex property fixes it
		if ( name == "selected" && jQuery.browser.safari )
			elem.parentNode.selectedIndex;
		
		// Certain attributes only work when accessed via the old DOM 0 way
		if ( fix[ name ] ) {
			if ( value != undefined )
				elem[ fix[ name ] ] = value;

			return elem[ fix[ name ] ];

		} else if ( jQuery.browser.msie && name == "style" )
			return jQuery.attr( elem.style, "cssText", value );

		else if ( value == undefined && jQuery.browser.msie && jQuery.nodeName( elem, "form" ) && (name == "action" || name == "method") )
			return elem.getAttributeNode( name ).nodeValue;

		// IE elem.getAttribute passes even for style
		else if ( elem.tagName ) {

			if ( value != undefined ) {
				// We can't allow the type property to be changed (since it causes problems in IE)
				if ( name == "type" && jQuery.nodeName( elem, "input" ) && elem.parentNode )
					throw "type property can't be changed";

				// convert the value to a string (all browsers do this but IE) see #1070
				elem.setAttribute( name, "" + value );
			}

			if ( jQuery.browser.msie && /href|src/.test( name ) && !jQuery.isXMLDoc( elem ) ) 
				return elem.getAttribute( name, 2 );

			return elem.getAttribute( name );

		// elem is actually elem.style ... set the style
		} else {
			// IE actually uses filters for opacity
			if ( name == "opacity" && jQuery.browser.msie ) {
				if ( value != undefined ) {
					// IE has trouble with opacity if it does not have layout
					// Force it by setting the zoom level
					elem.zoom = 1; 
	
					// Set the alpha filter to set the opacity
					elem.filter = (elem.filter || "").replace( /alpha\([^)]*\)/, "" ) +
						(parseFloat( value ).toString() == "NaN" ? "" : "alpha(opacity=" + value * 100 + ")");
				}
	
				return elem.filter && elem.filter.indexOf("opacity=") >= 0 ?
					(parseFloat( elem.filter.match(/opacity=([^)]*)/)[1] ) / 100).toString() :
					"";
			}

			name = name.replace(/-([a-z])/ig, function(all, letter){
				return letter.toUpperCase();
			});

			if ( value != undefined )
				elem[ name ] = value;

			return elem[ name ];
		}
	},
	
	trim: function( text ) {
		return (text || "").replace( /^\s+|\s+$/g, "" );
	},

	makeArray: function( array ) {
		var ret = [];

		// Need to use typeof to fight Safari childNodes crashes
		if ( typeof array != "array" )
			for ( var i = 0, length = array.length; i < length; i++ )
				ret.push( array[ i ] );
		else
			ret = array.slice( 0 );

		return ret;
	},

	inArray: function( elem, array ) {
		for ( var i = 0, length = array.length; i < length; i++ )
			if ( array[ i ] == elem )
				return i;

		return -1;
	},

	merge: function( first, second ) {
		// We have to loop this way because IE & Opera overwrite the length
		// expando of getElementsByTagName

		// Also, we need to make sure that the correct elements are being returned
		// (IE returns comment nodes in a '*' query)
		if ( jQuery.browser.msie ) {
			for ( var i = 0; second[ i ]; i++ )
				if ( second[ i ].nodeType != 8 )
					first.push( second[ i ] );

		} else
			for ( var i = 0; second[ i ]; i++ )
				first.push( second[ i ] );

		return first;
	},

	unique: function( array ) {
		var ret = [], done = {};

		try {

			for ( var i = 0, length = array.length; i < length; i++ ) {
				var id = jQuery.data( array[ i ] );

				if ( !done[ id ] ) {
					done[ id ] = true;
					ret.push( array[ i ] );
				}
			}

		} catch( e ) {
			ret = array;
		}

		return ret;
	},

	grep: function( elems, callback, inv ) {
		var ret = [];

		// Go through the array, only saving the items
		// that pass the validator function
		for ( var i = 0, length = elems.length; i < length; i++ )
			if ( !inv && callback( elems[ i ], i ) || inv && !callback( elems[ i ], i ) )
				ret.push( elems[ i ] );

		return ret;
	},

	map: function( elems, callback ) {
		var ret = [];

		// Go through the array, translating each of the items to their
		// new value (or values).
		for ( var i = 0, length = elems.length; i < length; i++ ) {
			var value = callback( elems[ i ], i );

			if ( value !== null && value != undefined ) {
				if ( value.constructor != Array )
					value = [ value ];

				ret = ret.concat( value );
			}
		}

		return ret;
	}
});

var userAgent = navigator.userAgent.toLowerCase();

// Figure out what browser is being used
jQuery.browser = {
	version: (userAgent.match( /.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/ ) || [])[1],
	safari: /webkit/.test( userAgent ),
	opera: /opera/.test( userAgent ),
	msie: /msie/.test( userAgent ) && !/opera/.test( userAgent ),
	mozilla: /mozilla/.test( userAgent ) && !/(compatible|webkit)/.test( userAgent )
};

var styleFloat = jQuery.browser.msie ?
	"styleFloat" :
	"cssFloat";
	
jQuery.extend({
	// Check to see if the W3C box model is being used
	boxModel: !jQuery.browser.msie || document.compatMode == "CSS1Compat",
	
	props: {
		"for": "htmlFor",
		"class": "className",
		"float": styleFloat,
		cssFloat: styleFloat,
		styleFloat: styleFloat,
		innerHTML: "innerHTML",
		className: "className",
		value: "value",
		disabled: "disabled",
		checked: "checked",
		readonly: "readOnly",
		selected: "selected",
		maxlength: "maxLength",
		selectedIndex: "selectedIndex",
		defaultValue: "defaultValue",
		tagName: "tagName",
		nodeName: "nodeName"
	}
});

jQuery.each({
	parent: function(elem){return elem.parentNode;},
	parents: function(elem){return jQuery.dir(elem,"parentNode");},
	next: function(elem){return jQuery.nth(elem,2,"nextSibling");},
	prev: function(elem){return jQuery.nth(elem,2,"previousSibling");},
	nextAll: function(elem){return jQuery.dir(elem,"nextSibling");},
	prevAll: function(elem){return jQuery.dir(elem,"previousSibling");},
	siblings: function(elem){return jQuery.sibling(elem.parentNode.firstChild,elem);},
	children: function(elem){return jQuery.sibling(elem.firstChild);},
	contents: function(elem){return jQuery.nodeName(elem,"iframe")?elem.contentDocument||elem.contentWindow.document:jQuery.makeArray(elem.childNodes);}
}, function(name, fn){
	jQuery.fn[ name ] = function( selector ) {
		var ret = jQuery.map( this, fn );

		if ( selector && typeof selector == "string" )
			ret = jQuery.multiFilter( selector, ret );

		return this.pushStack( jQuery.unique( ret ) );
	};
});

jQuery.each({
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function(name, original){
	jQuery.fn[ name ] = function() {
		var args = arguments;

		return this.each(function(){
			for ( var i = 0, length = args.length; i < length; i++ )
				jQuery( args[ i ] )[ original ]( this );
		});
	};
});

jQuery.each({
	removeAttr: function( name ) {
		jQuery.attr( this, name, "" );
		if (this.nodeType == 1) 
			this.removeAttribute( name );
	},

	addClass: function( classNames ) {
		jQuery.className.add( this, classNames );
	},

	removeClass: function( classNames ) {
		jQuery.className.remove( this, classNames );
	},

	toggleClass: function( classNames ) {
		jQuery.className[ jQuery.className.has( this, classNames ) ? "remove" : "add" ]( this, classNames );
	},

	remove: function( selector ) {
		if ( !selector || jQuery.filter( selector, [ this ] ).r.length ) {
			// Prevent memory leaks
			jQuery( "*", this ).add(this).each(function(){
				jQuery.event.remove(this);
				jQuery.removeData(this);
			});
			if (this.parentNode)
				this.parentNode.removeChild( this );
		}
	},

	empty: function() {
		// Remove element nodes and prevent memory leaks
		jQuery( ">*", this ).remove();
		
		// Remove any remaining nodes
		while ( this.firstChild )
			this.removeChild( this.firstChild );
	}
}, function(name, fn){
	jQuery.fn[ name ] = function(){
		return this.each( fn, arguments );
	};
});

jQuery.each([ "Height", "Width" ], function(i, name){
	var type = name.toLowerCase();
	
	jQuery.fn[ type ] = function( size ) {
		// Get window width or height
		return this[0] == window ?
			// Opera reports document.body.client[Width/Height] properly in both quirks and standards
			jQuery.browser.opera && document.body[ "client" + name ] || 
			
			// Safari reports inner[Width/Height] just fine (Mozilla and Opera include scroll bar widths)
			jQuery.browser.safari && window[ "inner" + name ] ||
			
			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
			document.compatMode == "CSS1Compat" && document.documentElement[ "client" + name ] || document.body[ "client" + name ] :
		
			// Get document width or height
			this[0] == document ?
				// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
				Math.max( 
					Math.max(document.body["scroll" + name], document.documentElement["scroll" + name]), 
					Math.max(document.body["offset" + name], document.documentElement["offset" + name]) 
				) :

				// Get or set width or height on the element
				size == undefined ?
					// Get width or height on the element
					(this.length ? jQuery.css( this[0], type ) : null) :

					// Set the width or height on the element (default to pixels if value is unitless)
					this.css( type, size.constructor == String ? size : size + "px" );
	};
});

var chars = jQuery.browser.safari && parseInt(jQuery.browser.version) < 417 ?
		"(?:[\\w*_-]|\\\\.)" :
		"(?:[\\w\u0128-\uFFFF*_-]|\\\\.)",
	quickChild = new RegExp("^>\\s*(" + chars + "+)"),
	quickID = new RegExp("^(" + chars + "+)(#)(" + chars + "+)"),
	quickClass = new RegExp("^([#.]?)(" + chars + "*)");

jQuery.extend({
	expr: {
		"": function(a,i,m){return m[2]=="*"||jQuery.nodeName(a,m[2]);},
		"#": function(a,i,m){return a.getAttribute("id")==m[2];},
		":": {
			// Position Checks
			lt: function(a,i,m){return i<m[3]-0;},
			gt: function(a,i,m){return i>m[3]-0;},
			nth: function(a,i,m){return m[3]-0==i;},
			eq: function(a,i,m){return m[3]-0==i;},
			first: function(a,i){return i==0;},
			last: function(a,i,m,r){return i==r.length-1;},
			even: function(a,i){return i%2==0;},
			odd: function(a,i){return i%2;},

			// Child Checks
			"first-child": function(a){return a.parentNode.getElementsByTagName("*")[0]==a;},
			"last-child": function(a){return jQuery.nth(a.parentNode.lastChild,1,"previousSibling")==a;},
			"only-child": function(a){return !jQuery.nth(a.parentNode.lastChild,2,"previousSibling");},

			// Parent Checks
			parent: function(a){return a.firstChild;},
			empty: function(a){return !a.firstChild;},

			// Text Check
			contains: function(a,i,m){return (a.textContent||a.innerText||jQuery(a).text()||"").indexOf(m[3])>=0;},

			// Visibility
			visible: function(a){return "hidden"!=a.type&&jQuery.css(a,"display")!="none"&&jQuery.css(a,"visibility")!="hidden";},
			hidden: function(a){return "hidden"==a.type||jQuery.css(a,"display")=="none"||jQuery.css(a,"visibility")=="hidden";},

			// Form attributes
			enabled: function(a){return !a.disabled;},
			disabled: function(a){return a.disabled;},
			checked: function(a){return a.checked;},
			selected: function(a){return a.selected||jQuery.attr(a,"selected");},

			// Form elements
			text: function(a){return "text"==a.type;},
			radio: function(a){return "radio"==a.type;},
			checkbox: function(a){return "checkbox"==a.type;},
			file: function(a){return "file"==a.type;},
			password: function(a){return "password"==a.type;},
			submit: function(a){return "submit"==a.type;},
			image: function(a){return "image"==a.type;},
			reset: function(a){return "reset"==a.type;},
			button: function(a){return "button"==a.type||jQuery.nodeName(a,"button");},
			input: function(a){return /input|select|textarea|button/i.test(a.nodeName);},

			// :has()
			has: function(a,i,m){return jQuery.find(m[3],a).length;},

			// :header
			header: function(a){return /h\d/i.test(a.nodeName);},

			// :animated
			animated: function(a){return jQuery.grep(jQuery.timers,function(fn){return a==fn.elem;}).length;}
		}
	},
	
	// The regular expressions that power the parsing engine
	parse: [
		// Match: [@value='test'], [@foo]
		/^(\[) *@?([\w-]+) *([!*$^~=]*) *('?"?)(.*?)\4 *\]/,

		// Match: :contains('foo')
		/^(:)([\w-]+)\("?'?(.*?(\(.*?\))?[^(]*?)"?'?\)/,

		// Match: :even, :last-chlid, #id, .class
		new RegExp("^([:.#]*)(" + chars + "+)")
	],

	multiFilter: function( expr, elems, not ) {
		var old, cur = [];

		while ( expr && expr != old ) {
			old = expr;
			var f = jQuery.filter( expr, elems, not );
			expr = f.t.replace(/^\s*,\s*/, "" );
			cur = not ? elems = f.r : jQuery.merge( cur, f.r );
		}

		return cur;
	},

	find: function( t, context ) {
		// Quickly handle non-string expressions
		if ( typeof t != "string" )
			return [ t ];

		// check to make sure context is a DOM element or a document
		if ( context && context.nodeType != 1 && context.nodeType != 9)
			return [ ];

		// Set the correct context (if none is provided)
		context = context || document;

		// Initialize the search
		var ret = [context], done = [], last, nodeName;

		// Continue while a selector expression exists, and while
		// we're no longer looping upon ourselves
		while ( t && last != t ) {
			var r = [];
			last = t;

			t = jQuery.trim(t);

			var foundToken = false;

			// An attempt at speeding up child selectors that
			// point to a specific element tag
			var re = quickChild;
			var m = re.exec(t);

			if ( m ) {
				nodeName = m[1].toUpperCase();

				// Perform our own iteration and filter
				for ( var i = 0; ret[i]; i++ )
					for ( var c = ret[i].firstChild; c; c = c.nextSibling )
						if ( c.nodeType == 1 && (nodeName == "*" || c.nodeName.toUpperCase() == nodeName) )
							r.push( c );

				ret = r;
				t = t.replace( re, "" );
				if ( t.indexOf(" ") == 0 ) continue;
				foundToken = true;
			} else {
				re = /^([>+~])\s*(\w*)/i;

				if ( (m = re.exec(t)) != null ) {
					r = [];

					var merge = {};
					nodeName = m[2].toUpperCase();
					m = m[1];

					for ( var j = 0, rl = ret.length; j < rl; j++ ) {
						var n = m == "~" || m == "+" ? ret[j].nextSibling : ret[j].firstChild;
						for ( ; n; n = n.nextSibling )
							if ( n.nodeType == 1 ) {
								var id = jQuery.data(n);

								if ( m == "~" && merge[id] ) break;
								
								if (!nodeName || n.nodeName.toUpperCase() == nodeName ) {
									if ( m == "~" ) merge[id] = true;
									r.push( n );
								}
								
								if ( m == "+" ) break;
							}
					}

					ret = r;

					// And remove the token
					t = jQuery.trim( t.replace( re, "" ) );
					foundToken = true;
				}
			}

			// See if there's still an expression, and that we haven't already
			// matched a token
			if ( t && !foundToken ) {
				// Handle multiple expressions
				if ( !t.indexOf(",") ) {
					// Clean the result set
					if ( context == ret[0] ) ret.shift();

					// Merge the result sets
					done = jQuery.merge( done, ret );

					// Reset the context
					r = ret = [context];

					// Touch up the selector string
					t = " " + t.substr(1,t.length);

				} else {
					// Optimize for the case nodeName#idName
					var re2 = quickID;
					var m = re2.exec(t);
					
					// Re-organize the results, so that they're consistent
					if ( m ) {
						m = [ 0, m[2], m[3], m[1] ];

					} else {
						// Otherwise, do a traditional filter check for
						// ID, class, and element selectors
						re2 = quickClass;
						m = re2.exec(t);
					}

					m[2] = m[2].replace(/\\/g, "");

					var elem = ret[ret.length-1];

					// Try to do a global search by ID, where we can
					if ( m[1] == "#" && elem && elem.getElementById && !jQuery.isXMLDoc(elem) ) {
						// Optimization for HTML document case
						var oid = elem.getElementById(m[2]);
						
						// Do a quick check for the existence of the actual ID attribute
						// to avoid selecting by the name attribute in IE
						// also check to insure id is a string to avoid selecting an element with the name of 'id' inside a form
						if ( (jQuery.browser.msie||jQuery.browser.opera) && oid && typeof oid.id == "string" && oid.id != m[2] )
							oid = jQuery('[@id="'+m[2]+'"]', elem)[0];

						// Do a quick check for node name (where applicable) so
						// that div#foo searches will be really fast
						ret = r = oid && (!m[3] || jQuery.nodeName(oid, m[3])) ? [oid] : [];
					} else {
						// We need to find all descendant elements
						for ( var i = 0; ret[i]; i++ ) {
							// Grab the tag name being searched for
							var tag = m[1] == "#" && m[3] ? m[3] : m[1] != "" || m[0] == "" ? "*" : m[2];

							// Handle IE7 being really dumb about <object>s
							if ( tag == "*" && ret[i].nodeName.toLowerCase() == "object" )
								tag = "param";

							r = jQuery.merge( r, ret[i].getElementsByTagName( tag ));
						}

						// It's faster to filter by class and be done with it
						if ( m[1] == "." )
							r = jQuery.classFilter( r, m[2] );

						// Same with ID filtering
						if ( m[1] == "#" ) {
							var tmp = [];

							// Try to find the element with the ID
							for ( var i = 0; r[i]; i++ )
								if ( r[i].getAttribute("id") == m[2] ) {
									tmp = [ r[i] ];
									break;
								}

							r = tmp;
						}

						ret = r;
					}

					t = t.replace( re2, "" );
				}

			}

			// If a selector string still exists
			if ( t ) {
				// Attempt to filter it
				var val = jQuery.filter(t,r);
				ret = r = val.r;
				t = jQuery.trim(val.t);
			}
		}

		// An error occurred with the selector;
		// just return an empty set instead
		if ( t )
			ret = [];

		// Remove the root context
		if ( ret && context == ret[0] )
			ret.shift();

		// And combine the results
		done = jQuery.merge( done, ret );

		return done;
	},

	classFilter: function(r,m,not){
		m = " " + m + " ";
		var tmp = [];
		for ( var i = 0; r[i]; i++ ) {
			var pass = (" " + r[i].className + " ").indexOf( m ) >= 0;
			if ( !not && pass || not && !pass )
				tmp.push( r[i] );
		}
		return tmp;
	},

	filter: function(t,r,not) {
		var last;

		// Look for common filter expressions
		while ( t && t != last ) {
			last = t;

			var p = jQuery.parse, m;

			for ( var i = 0; p[i]; i++ ) {
				m = p[i].exec( t );

				if ( m ) {
					// Remove what we just matched
					t = t.substring( m[0].length );

					m[2] = m[2].replace(/\\/g, "");
					break;
				}
			}

			if ( !m )
				break;

			// :not() is a special case that can be optimized by
			// keeping it out of the expression list
			if ( m[1] == ":" && m[2] == "not" )
				// optimize if only one selector found (most common case)
				r = isSimple.test( m[3] ) ?
					jQuery.filter(m[3], r, true).r :
					jQuery( r ).not( m[3] );

			// We can get a big speed boost by filtering by class here
			else if ( m[1] == "." )
				r = jQuery.classFilter(r, m[2], not);

			else if ( m[1] == "[" ) {
				var tmp = [], type = m[3];
				
				for ( var i = 0, rl = r.length; i < rl; i++ ) {
					var a = r[i], z = a[ jQuery.props[m[2]] || m[2] ];
					
					if ( z == null || /href|src|selected/.test(m[2]) )
						z = jQuery.attr(a,m[2]) || '';

					if ( (type == "" && !!z ||
						 type == "=" && z == m[5] ||
						 type == "!=" && z != m[5] ||
						 type == "^=" && z && !z.indexOf(m[5]) ||
						 type == "$=" && z.substr(z.length - m[5].length) == m[5] ||
						 (type == "*=" || type == "~=") && z.indexOf(m[5]) >= 0) ^ not )
							tmp.push( a );
				}
				
				r = tmp;

			// We can get a speed boost by handling nth-child here
			} else if ( m[1] == ":" && m[2] == "nth-child" ) {
				var merge = {}, tmp = [],
					// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
					test = /(-?)(\d*)n((?:\+|-)?\d*)/.exec(
						m[3] == "even" && "2n" || m[3] == "odd" && "2n+1" ||
						!/\D/.test(m[3]) && "0n+" + m[3] || m[3]),
					// calculate the numbers (first)n+(last) including if they are negative
					first = (test[1] + (test[2] || 1)) - 0, last = test[3] - 0;
 
				// loop through all the elements left in the jQuery object
				for ( var i = 0, rl = r.length; i < rl; i++ ) {
					var node = r[i], parentNode = node.parentNode, id = jQuery.data(parentNode);

					if ( !merge[id] ) {
						var c = 1;

						for ( var n = parentNode.firstChild; n; n = n.nextSibling )
							if ( n.nodeType == 1 )
								n.nodeIndex = c++;

						merge[id] = true;
					}

					var add = false;

					if ( first == 0 ) {
						if ( node.nodeIndex == last )
							add = true;
					} else if ( (node.nodeIndex - last) % first == 0 && (node.nodeIndex - last) / first >= 0 )
						add = true;

					if ( add ^ not )
						tmp.push( node );
				}

				r = tmp;

			// Otherwise, find the expression to execute
			} else {
				var fn = jQuery.expr[ m[1] ];
				if ( typeof fn == "object" )
					fn = fn[ m[2] ];

				if ( typeof fn == "string" )
					fn = eval("false||function(a,i){return " + fn + ";}");

				// Execute it against the current filter
				r = jQuery.grep( r, function(elem, i){
					return fn(elem, i, m, r);
				}, not );
			}
		}

		// Return an array of filtered elements (r)
		// and the modified expression string (t)
		return { r: r, t: t };
	},

	dir: function( elem, dir ){
		var matched = [];
		var cur = elem[dir];
		while ( cur && cur != document ) {
			if ( cur.nodeType == 1 )
				matched.push( cur );
			cur = cur[dir];
		}
		return matched;
	},
	
	nth: function(cur,result,dir,elem){
		result = result || 1;
		var num = 0;

		for ( ; cur; cur = cur[dir] )
			if ( cur.nodeType == 1 && ++num == result )
				break;

		return cur;
	},
	
	sibling: function( n, elem ) {
		var r = [];

		for ( ; n; n = n.nextSibling ) {
			if ( n.nodeType == 1 && (!elem || n != elem) )
				r.push( n );
		}

		return r;
	}
});

/*
 * A number of helper functions used for managing events.
 * Many of the ideas behind this code orignated from 
 * Dean Edwards' addEvent library.
 */
jQuery.event = {

	// Bind an event to an element
	// Original by Dean Edwards
	add: function(elem, types, handler, data) {
		if ( elem.nodeType == 3 || elem.nodeType == 8 )
			return;

		// For whatever reason, IE has trouble passing the window object
		// around, causing it to be cloned in the process
		if ( jQuery.browser.msie && elem.setInterval != undefined )
			elem = window;

		// Make sure that the function being executed has a unique ID
		if ( !handler.guid )
			handler.guid = this.guid++;
			
		// if data is passed, bind to handler 
		if( data != undefined ) { 
			// Create temporary function pointer to original handler 
			var fn = handler; 

			// Create unique handler function, wrapped around original handler 
			handler = function() { 
				// Pass arguments and context to original handler 
				return fn.apply(this, arguments); 
			};

			// Store data in unique handler 
			handler.data = data;

			// Set the guid of unique handler to the same of original handler, so it can be removed 
			handler.guid = fn.guid;
		}

		// Init the element's event structure
		var events = jQuery.data(elem, "events") || jQuery.data(elem, "events", {}),
			handle = jQuery.data(elem, "handle") || jQuery.data(elem, "handle", function(){
				// returned undefined or false
				var val;

				// Handle the second event of a trigger and when
				// an event is called after a page has unloaded
				if ( typeof jQuery == "undefined" || jQuery.event.triggered )
					return val;
		
				val = jQuery.event.handle.apply(arguments.callee.elem, arguments);
		
				return val;
			});
		// Add elem as a property of the handle function
		// This is to prevent a memory leak with non-native
		// event in IE.
		handle.elem = elem;
			
			// Handle multiple events seperated by a space
			// jQuery(...).bind("mouseover mouseout", fn);
			jQuery.each(types.split(/\s+/), function(index, type) {
				// Namespaced event handlers
				var parts = type.split(".");
				type = parts[0];
				handler.type = parts[1];

				// Get the current list of functions bound to this event
				var handlers = events[type];

				// Init the event handler queue
				if (!handlers) {
					handlers = events[type] = {};
		
					// Check for a special event handler
					// Only use addEventListener/attachEvent if the special
					// events handler returns false
					if ( !jQuery.event.special[type] || jQuery.event.special[type].setup.call(elem) === false ) {
						// Bind the global event handler to the element
						if (elem.addEventListener)
							elem.addEventListener(type, handle, false);
						else if (elem.attachEvent)
							elem.attachEvent("on" + type, handle);
					}
				}

				// Add the function to the element's handler list
				handlers[handler.guid] = handler;

				// Keep track of which events have been used, for global triggering
				jQuery.event.global[type] = true;
			});
		
		// Nullify elem to prevent memory leaks in IE
		elem = null;
	},

	guid: 1,
	global: {},

	// Detach an event or set of events from an element
	remove: function(elem, types, handler) {
		// don't do events on text and comment nodes
		if ( elem.nodeType == 3 || elem.nodeType == 8 )
			return;

		var events = jQuery.data(elem, "events"), ret, index;

		if ( events ) {
			// Unbind all events for the element
			if ( types == undefined || (typeof types == "string" && types.charAt(0) == ".") )
				for ( var type in events )
					this.remove( elem, type + (types || "") );
			else {
				// types is actually an event object here
				if ( types.type ) {
					handler = types.handler;
					types = types.type;
				}
				
				// Handle multiple events seperated by a space
				// jQuery(...).unbind("mouseover mouseout", fn);
				jQuery.each(types.split(/\s+/), function(index, type){
					// Namespaced event handlers
					var parts = type.split(".");
					type = parts[0];
					
					if ( events[type] ) {
						// remove the given handler for the given type
						if ( handler )
							delete events[type][handler.guid];
			
						// remove all handlers for the given type
						else
							for ( handler in events[type] )
								// Handle the removal of namespaced events
								if ( !parts[1] || events[type][handler].type == parts[1] )
									delete events[type][handler];

						// remove generic event handler if no more handlers exist
						for ( ret in events[type] ) break;
						if ( !ret ) {
							if ( !jQuery.event.special[type] || jQuery.event.special[type].teardown.call(elem) === false ) {
								if (elem.removeEventListener)
									elem.removeEventListener(type, jQuery.data(elem, "handle"), false);
								else if (elem.detachEvent)
									elem.detachEvent("on" + type, jQuery.data(elem, "handle"));
							}
							ret = null;
							delete events[type];
						}
					}
				});
			}

			// Remove the expando if it's no longer used
			for ( ret in events ) break;
			if ( !ret ) {
				var handle = jQuery.data( elem, "handle" );
				if ( handle ) handle.elem = null;
				jQuery.removeData( elem, "events" );
				jQuery.removeData( elem, "handle" );
			}
		}
	},

	trigger: function(type, data, elem, donative, extra) {
		// Clone the incoming data, if any
		data = jQuery.makeArray(data || []);

		if ( type.indexOf("!") >= 0 ) {
			type = type.slice(0, -1);
			var exclusive = true;
		}

		// Handle a global trigger
		if ( !elem ) {
			// Only trigger if we've ever bound an event for it
			if ( this.global[type] )
				jQuery("*").add([window, document]).trigger(type, data);

		// Handle triggering a single element
		} else {
			// don't do events on text and comment nodes
			if ( elem.nodeType == 3 || elem.nodeType == 8 )
				return undefined;

			var val, ret, fn = jQuery.isFunction( elem[ type ] || null ),
				// Check to see if we need to provide a fake event, or not
				event = !data[0] || !data[0].preventDefault;
			
			// Pass along a fake event
			if ( event )
				data.unshift( this.fix({ type: type, target: elem }) );

			// Enforce the right trigger type
			data[0].type = type;
			if ( exclusive )
				data[0].exclusive = true;

			// Trigger the event
			if ( jQuery.isFunction( jQuery.data(elem, "handle") ) )
				val = jQuery.data(elem, "handle").apply( elem, data );

			// Handle triggering native .onfoo handlers
			if ( !fn && elem["on"+type] && elem["on"+type].apply( elem, data ) === false )
				val = false;

			// Extra functions don't get the custom event object
			if ( event )
				data.shift();

			// Handle triggering of extra function
			if ( extra && jQuery.isFunction( extra ) ) {
				// call the extra function and tack the current return value on the end for possible inspection
				ret = extra.apply( elem, val == null ? data : data.concat( val ) );
				// if anything is returned, give it precedence and have it overwrite the previous value
				if (ret !== undefined)
					val = ret;
			}

			// Trigger the native events (except for clicks on links)
			if ( fn && donative !== false && val !== false && !(jQuery.nodeName(elem, 'a') && type == "click") ) {
				this.triggered = true;
				try {
					elem[ type ]();
				// prevent IE from throwing an error for some hidden elements
				} catch (e) {}
			}

			this.triggered = false;
		}

		return val;
	},

	handle: function(event) {
		// returned undefined or false
		var val;

		// Empty object is for triggered events with no data
		event = jQuery.event.fix( event || window.event || {} ); 

		// Namespaced event handlers
		var parts = event.type.split(".");
		event.type = parts[0];

		var handlers = jQuery.data(this, "events") && jQuery.data(this, "events")[event.type], args = Array.prototype.slice.call( arguments, 1 );
		args.unshift( event );

		for ( var j in handlers ) {
			var handler = handlers[j];
			// Pass in a reference to the handler function itself
			// So that we can later remove it
			args[0].handler = handler;
			args[0].data = handler.data;

			// Filter the functions by class
			if ( !parts[1] && !event.exclusive || handler.type == parts[1] ) {
				var ret = handler.apply( this, args );

				if ( val !== false )
					val = ret;

				if ( ret === false ) {
					event.preventDefault();
					event.stopPropagation();
				}
			}
		}

		// Clean up added properties in IE to prevent memory leak
		if (jQuery.browser.msie)
			event.target = event.preventDefault = event.stopPropagation =
				event.handler = event.data = null;

		return val;
	},

	fix: function(event) {
		// store a copy of the original event object 
		// and clone to set read-only properties
		var originalEvent = event;
		event = jQuery.extend({}, originalEvent);
		
		// add preventDefault and stopPropagation since 
		// they will not work on the clone
		event.preventDefault = function() {
			// if preventDefault exists run it on the original event
			if (originalEvent.preventDefault)
				originalEvent.preventDefault();
			// otherwise set the returnValue property of the original event to false (IE)
			originalEvent.returnValue = false;
		};
		event.stopPropagation = function() {
			// if stopPropagation exists run it on the original event
			if (originalEvent.stopPropagation)
				originalEvent.stopPropagation();
			// otherwise set the cancelBubble property of the original event to true (IE)
			originalEvent.cancelBubble = true;
		};
		
		// Fix target property, if necessary
		if ( !event.target )
			event.target = event.srcElement || document; // Fixes #1925 where srcElement might not be defined either
				
		// check if target is a textnode (safari)
		if ( event.target.nodeType == 3 )
			event.target = originalEvent.target.parentNode;

		// Add relatedTarget, if necessary
		if ( !event.relatedTarget && event.fromElement )
			event.relatedTarget = event.fromElement == event.target ? event.toElement : event.fromElement;

		// Calculate pageX/Y if missing and clientX/Y available
		if ( event.pageX == null && event.clientX != null ) {
			var doc = document.documentElement, body = document.body;
			event.pageX = event.clientX + (doc && doc.scrollLeft || body && body.scrollLeft || 0) - (doc.clientLeft || 0);
			event.pageY = event.clientY + (doc && doc.scrollTop || body && body.scrollTop || 0) - (doc.clientTop || 0);
		}
			
		// Add which for key events
		if ( !event.which && ((event.charCode || event.charCode === 0) ? event.charCode : event.keyCode) )
			event.which = event.charCode || event.keyCode;
		
		// Add metaKey to non-Mac browsers (use ctrl for PC's and Meta for Macs)
		if ( !event.metaKey && event.ctrlKey )
			event.metaKey = event.ctrlKey;

		// Add which for click: 1 == left; 2 == middle; 3 == right
		// Note: button is not normalized, so don't use it
		if ( !event.which && event.button )
			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
			
		return event;
	},
	
	special: {
		ready: {
			setup: function() {
				// Make sure the ready event is setup
				bindReady();
				return;
			},
			
			teardown: function() { return; }
		},
		
		mouseenter: {
			setup: function() {
				if ( jQuery.browser.msie ) return false;
				jQuery(this).bind("mouseover", jQuery.event.special.mouseenter.handler);
				return true;
			},
		
			teardown: function() {
				if ( jQuery.browser.msie ) return false;
				jQuery(this).unbind("mouseover", jQuery.event.special.mouseenter.handler);
				return true;
			},
			
			handler: function(event) {
				// If we actually just moused on to a sub-element, ignore it
				if ( withinElement(event, this) ) return true;
				// Execute the right handlers by setting the event type to mouseenter
				arguments[0].type = "mouseenter";
				return jQuery.event.handle.apply(this, arguments);
			}
		},
	
		mouseleave: {
			setup: function() {
				if ( jQuery.browser.msie ) return false;
				jQuery(this).bind("mouseout", jQuery.event.special.mouseleave.handler);
				return true;
			},
		
			teardown: function() {
				if ( jQuery.browser.msie ) return false;
				jQuery(this).unbind("mouseout", jQuery.event.special.mouseleave.handler);
				return true;
			},
			
			handler: function(event) {
				// If we actually just moused on to a sub-element, ignore it
				if ( withinElement(event, this) ) return true;
				// Execute the right handlers by setting the event type to mouseleave
				arguments[0].type = "mouseleave";
				return jQuery.event.handle.apply(this, arguments);
			}
		}
	}
};

jQuery.fn.extend({
	bind: function( type, data, fn ) {
		return type == "unload" ? this.one(type, data, fn) : this.each(function(){
			jQuery.event.add( this, type, fn || data, fn && data );
		});
	},
	
	one: function( type, data, fn ) {
		return this.each(function(){
			jQuery.event.add( this, type, function(event) {
				jQuery(this).unbind(event);
				return (fn || data).apply( this, arguments);
			}, fn && data);
		});
	},

	unbind: function( type, fn ) {
		return this.each(function(){
			jQuery.event.remove( this, type, fn );
		});
	},

	trigger: function( type, data, fn ) {
		return this.each(function(){
			jQuery.event.trigger( type, data, this, true, fn );
		});
	},

	triggerHandler: function( type, data, fn ) {
		if ( this[0] )
			return jQuery.event.trigger( type, data, this[0], false, fn );
		return undefined;
	},

	toggle: function() {
		// Save reference to arguments for access in closure
		var args = arguments;

		return this.click(function(event) {
			// Figure out which function to execute
			this.lastToggle = 0 == this.lastToggle ? 1 : 0;
			
			// Make sure that clicks stop
			event.preventDefault();
			
			// and execute the function
			return args[this.lastToggle].apply( this, arguments ) || false;
		});
	},

	hover: function(fnOver, fnOut) {
		return this.bind('mouseenter', fnOver).bind('mouseleave', fnOut);
	},
	
	ready: function(fn) {
		// Attach the listeners
		bindReady();

		// If the DOM is already ready
		if ( jQuery.isReady )
			// Execute the function immediately
			fn.call( document, jQuery );
			
		// Otherwise, remember the function for later
		else
			// Add the function to the wait list
			jQuery.readyList.push( function() { return fn.call(this, jQuery); } );
	
		return this;
	}
});

jQuery.extend({
	isReady: false,
	readyList: [],
	// Handle when the DOM is ready
	ready: function() {
		// Make sure that the DOM is not already loaded
		if ( !jQuery.isReady ) {
			// Remember that the DOM is ready
			jQuery.isReady = true;
			
			// If there are functions bound, to execute
			if ( jQuery.readyList ) {
				// Execute all of them
				jQuery.each( jQuery.readyList, function(){
					this.apply( document );
				});
				
				// Reset the list of functions
				jQuery.readyList = null;
			}
		
			// Trigger any bound ready events
			jQuery(document).triggerHandler("ready");
		}
	}
});

var readyBound = false;

function bindReady(){
	if ( readyBound ) return;
	readyBound = true;

	// Mozilla, Opera (see further below for it) and webkit nightlies currently support this event
	if ( document.addEventListener && !jQuery.browser.opera)
		// Use the handy event callback
		document.addEventListener( "DOMContentLoaded", jQuery.ready, false );
	
	// If IE is used and is not in a frame
	// Continually check to see if the document is ready
	if ( jQuery.browser.msie && window == top ) (function(){
		if (jQuery.isReady) return;
		try {
			// If IE is used, use the trick by Diego Perini
			// http://javascript.nwbox.com/IEContentLoaded/
			document.documentElement.doScroll("left");
		} catch( error ) {
			setTimeout( arguments.callee, 0 );
			return;
		}
		// and execute any waiting functions
		jQuery.ready();
	})();

	if ( jQuery.browser.opera )
		document.addEventListener( "DOMContentLoaded", function () {
			if (jQuery.isReady) return;
			for (var i = 0; i < document.styleSheets.length; i++)
				if (document.styleSheets[i].disabled) {
					setTimeout( arguments.callee, 0 );
					return;
				}
			// and execute any waiting functions
			jQuery.ready();
		}, false);

	if ( jQuery.browser.safari ) {
		var numStyles;
		(function(){
			if (jQuery.isReady) return;
			if ( document.readyState != "loaded" && document.readyState != "complete" ) {
				setTimeout( arguments.callee, 0 );
				return;
			}
			if ( numStyles === undefined )
				numStyles = jQuery("style, link[rel=stylesheet]").length;
			if ( document.styleSheets.length != numStyles ) {
				setTimeout( arguments.callee, 0 );
				return;
			}
			// and execute any waiting functions
			jQuery.ready();
		})();
	}

	// A fallback to window.onload, that will always work
	jQuery.event.add( window, "load", jQuery.ready );
}

jQuery.each( ("blur,focus,load,resize,scroll,unload,click,dblclick," +
	"mousedown,mouseup,mousemove,mouseover,mouseout,change,select," + 
	"submit,keydown,keypress,keyup,error").split(","), function(i, name){
	
	// Handle event binding
	jQuery.fn[name] = function(fn){
		return fn ? this.bind(name, fn) : this.trigger(name);
	};
});

// Checks if an event happened on an element within another element
// Used in jQuery.event.special.mouseenter and mouseleave handlers
var withinElement = function(event, elem) {
	// Check if mouse(over|out) are still within the same parent element
	var parent = event.relatedTarget;
	// Traverse up the tree
	while ( parent && parent != elem ) try { parent = parent.parentNode; } catch(error) { parent = elem; }
	// Return true if we actually just moused on to a sub-element
	return parent == elem;
};

// Prevent memory leaks in IE
// And prevent errors on refresh with events like mouseover in other browsers
// Window isn't included so as not to unbind existing unload events
jQuery(window).bind("unload", function() {
	jQuery("*").add(document).unbind();
});
jQuery.fn.extend({
	load: function( url, params, callback ) {
		if ( jQuery.isFunction( url ) )
			return this.bind("load", url);

		var off = url.indexOf(" ");
		if ( off >= 0 ) {
			var selector = url.slice(off, url.length);
			url = url.slice(0, off);
		}

		callback = callback || function(){};

		// Default to a GET request
		var type = "GET";

		// If the second parameter was provided
		if ( params )
			// If it's a function
			if ( jQuery.isFunction( params ) ) {
				// We assume that it's the callback
				callback = params;
				params = null;

			// Otherwise, build a param string
			} else {
				params = jQuery.param( params );
				type = "POST";
			}

		var self = this;

		// Request the remote document
		jQuery.ajax({
			url: url,
			type: type,
			dataType: "html",
			data: params,
			complete: function(res, status){
				// If successful, inject the HTML into all the matched elements
				if ( status == "success" || status == "notmodified" )
					// See if a selector was specified
					self.html( selector ?
						// Create a dummy div to hold the results
						jQuery("<div/>")
							// inject the contents of the document in, removing the scripts
							// to avoid any 'Permission Denied' errors in IE
							.append(res.responseText.replace(/<script(.|\s)*?\/script>/g, ""))

							// Locate the specified elements
							.find(selector) :

						// If not, just inject the full result
						res.responseText );

				self.each( callback, [res.responseText, status, res] );
			}
		});
		return this;
	},

	serialize: function() {
		return jQuery.param(this.serializeArray());
	},
	serializeArray: function() {
		return this.map(function(){
			return jQuery.nodeName(this, "form") ?
				jQuery.makeArray(this.elements) : this;
		})
		.filter(function(){
			return this.name && !this.disabled && 
				(this.checked || /select|textarea/i.test(this.nodeName) || 
					/text|hidden|password/i.test(this.type));
		})
		.map(function(i, elem){
			var val = jQuery(this).val();
			return val == null ? null :
				val.constructor == Array ?
					jQuery.map( val, function(val, i){
						return {name: elem.name, value: val};
					}) :
					{name: elem.name, value: val};
		}).get();
	}
});

// Attach a bunch of functions for handling common AJAX events
jQuery.each( "ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","), function(i,o){
	jQuery.fn[o] = function(f){
		return this.bind(o, f);
	};
});

var jsc = (new Date).getTime();

jQuery.extend({
	get: function( url, data, callback, type ) {
		// shift arguments if data argument was ommited
		if ( jQuery.isFunction( data ) ) {
			callback = data;
			data = null;
		}
		
		return jQuery.ajax({
			type: "GET",
			url: url,
			data: data,
			success: callback,
			dataType: type
		});
	},

	getScript: function( url, callback ) {
		return jQuery.get(url, null, callback, "script");
	},

	getJSON: function( url, data, callback ) {
		return jQuery.get(url, data, callback, "json");
	},

	post: function( url, data, callback, type ) {
		if ( jQuery.isFunction( data ) ) {
			callback = data;
			data = {};
		}

		return jQuery.ajax({
			type: "POST",
			url: url,
			data: data,
			success: callback,
			dataType: type
		});
	},

	ajaxSetup: function( settings ) {
		jQuery.extend( jQuery.ajaxSettings, settings );
	},

	ajaxSettings: {
		global: true,
		type: "GET",
		timeout: 0,
		contentType: "application/x-www-form-urlencoded",
		processData: true,
		async: true,
		data: null,
		username: null,
		password: null,
		accepts: {
			xml: "application/xml, text/xml",
			html: "text/html",
			script: "text/javascript, application/javascript",
			json: "application/json, text/javascript",
			text: "text/plain",
			_default: "*/*"
		}
	},
	
	// Last-Modified header cache for next request
	lastModified: {},

	ajax: function( s ) {
		var jsonp, jsre = /=\?(&|$)/g, status, data;

		// Extend the settings, but re-extend 's' so that it can be
		// checked again later (in the test suite, specifically)
		s = jQuery.extend(true, s, jQuery.extend(true, {}, jQuery.ajaxSettings, s));

		// convert data if not already a string
		if ( s.data && s.processData && typeof s.data != "string" )
			s.data = jQuery.param(s.data);

		// Handle JSONP Parameter Callbacks
		if ( s.dataType == "jsonp" ) {
			if ( s.type.toLowerCase() == "get" ) {
				if ( !s.url.match(jsre) )
					s.url += (s.url.match(/\?/) ? "&" : "?") + (s.jsonp || "callback") + "=?";
			} else if ( !s.data || !s.data.match(jsre) )
				s.data = (s.data ? s.data + "&" : "") + (s.jsonp || "callback") + "=?";
			s.dataType = "json";
		}

		// Build temporary JSONP function
		if ( s.dataType == "json" && (s.data && s.data.match(jsre) || s.url.match(jsre)) ) {
			jsonp = "jsonp" + jsc++;

			// Replace the =? sequence both in the query string and the data
			if ( s.data )
				s.data = (s.data + "").replace(jsre, "=" + jsonp + "$1");
			s.url = s.url.replace(jsre, "=" + jsonp + "$1");

			// We need to make sure
			// that a JSONP style response is executed properly
			s.dataType = "script";

			// Handle JSONP-style loading
			window[ jsonp ] = function(tmp){
				data = tmp;
				success();
				complete();
				// Garbage collect
				window[ jsonp ] = undefined;
				try{ delete window[ jsonp ]; } catch(e){}
				if ( head )
					head.removeChild( script );
			};
		}

		if ( s.dataType == "script" && s.cache == null )
			s.cache = false;

		if ( s.cache === false && s.type.toLowerCase() == "get" ) {
			var ts = (new Date()).getTime();
			// try replacing _= if it is there
			var ret = s.url.replace(/(\?|&)_=.*?(&|$)/, "$1_=" + ts + "$2");
			// if nothing was replaced, add timestamp to the end
			s.url = ret + ((ret == s.url) ? (s.url.match(/\?/) ? "&" : "?") + "_=" + ts : "");
		}

		// If data is available, append data to url for get requests
		if ( s.data && s.type.toLowerCase() == "get" ) {
			s.url += (s.url.match(/\?/) ? "&" : "?") + s.data;

			// IE likes to send both get and post data, prevent this
			s.data = null;
		}

		// Watch for a new set of requests
		if ( s.global && ! jQuery.active++ )
			jQuery.event.trigger( "ajaxStart" );

		// If we're requesting a remote document
		// and trying to load JSON or Script with a GET
		if ( (!s.url.indexOf("http") || !s.url.indexOf("//")) && s.dataType == "script" && s.type.toLowerCase() == "get" ) {
			var head = document.getElementsByTagName("head")[0];
			var script = document.createElement("script");
			script.src = s.url;
			if (s.scriptCharset)
				script.charset = s.scriptCharset;

			// Handle Script loading
			if ( !jsonp ) {
				var done = false;

				// Attach handlers for all browsers
				script.onload = script.onreadystatechange = function(){
					if ( !done && (!this.readyState || 
							this.readyState == "loaded" || this.readyState == "complete") ) {
						done = true;
						success();
						complete();
						head.removeChild( script );
					}
				};
			}

			head.appendChild(script);

			// We handle everything using the script element injection
			return undefined;
		}

		var requestDone = false;

		// Create the request object; Microsoft failed to properly
		// implement the XMLHttpRequest in IE7, so we use the ActiveXObject when it is available
		var xml = window.ActiveXObject ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();

		// Open the socket
		xml.open(s.type, s.url, s.async, s.username, s.password);

		// Need an extra try/catch for cross domain requests in Firefox 3
		try {
			// Set the correct header, if data is being sent
			if ( s.data )
				xml.setRequestHeader("Content-Type", s.contentType);

			// Set the If-Modified-Since header, if ifModified mode.
			if ( s.ifModified )
				xml.setRequestHeader("If-Modified-Since",
					jQuery.lastModified[s.url] || "Thu, 01 Jan 1970 00:00:00 GMT" );

			// Set header so the called script knows that it's an XMLHttpRequest
			xml.setRequestHeader("X-Requested-With", "XMLHttpRequest");

			// Set the Accepts header for the server, depending on the dataType
			xml.setRequestHeader("Accept", s.dataType && s.accepts[ s.dataType ] ?
				s.accepts[ s.dataType ] + ", */*" :
				s.accepts._default );
		} catch(e){}

		// Allow custom headers/mimetypes
		if ( s.beforeSend )
			s.beforeSend(xml);
			
		if ( s.global )
			jQuery.event.trigger("ajaxSend", [xml, s]);

		// Wait for a response to come back
		var onreadystatechange = function(isTimeout){
			// The transfer is complete and the data is available, or the request timed out
			if ( !requestDone && xml && (xml.readyState == 4 || isTimeout == "timeout") ) {
				requestDone = true;
				
				// clear poll interval
				if (ival) {
					clearInterval(ival);
					ival = null;
				}
				
				status = isTimeout == "timeout" && "timeout" ||
					!jQuery.httpSuccess( xml ) && "error" ||
					s.ifModified && jQuery.httpNotModified( xml, s.url ) && "notmodified" ||
					"success";

				if ( status == "success" ) {
					// Watch for, and catch, XML document parse errors
					try {
						// process the data (runs the xml through httpData regardless of callback)
						data = jQuery.httpData( xml, s.dataType );
					} catch(e) {
						status = "parsererror";
					}
				}

				// Make sure that the request was successful or notmodified
				if ( status == "success" ) {
					// Cache Last-Modified header, if ifModified mode.
					var modRes;
					try {
						modRes = xml.getResponseHeader("Last-Modified");
					} catch(e) {} // swallow exception thrown by FF if header is not available
	
					if ( s.ifModified && modRes )
						jQuery.lastModified[s.url] = modRes;

					// JSONP handles its own success callback
					if ( !jsonp )
						success();	
				} else
					jQuery.handleError(s, xml, status);

				// Fire the complete handlers
				complete();

				// Stop memory leaks
				if ( s.async )
					xml = null;
			}
		};
		
		if ( s.async ) {
			// don't attach the handler to the request, just poll it instead
			var ival = setInterval(onreadystatechange, 13); 

			// Timeout checker
			if ( s.timeout > 0 )
				setTimeout(function(){
					// Check to see if the request is still happening
					if ( xml ) {
						// Cancel the request
						xml.abort();
	
						if( !requestDone )
							onreadystatechange( "timeout" );
					}
				}, s.timeout);
		}
			
		// Send the data
		try {
			xml.send(s.data);
		} catch(e) {
			jQuery.handleError(s, xml, null, e);
		}
		
		// firefox 1.5 doesn't fire statechange for sync requests
		if ( !s.async )
			onreadystatechange();

		function success(){
			// If a local callback was specified, fire it and pass it the data
			if ( s.success )
				s.success( data, status );

			// Fire the global callback
			if ( s.global )
				jQuery.event.trigger( "ajaxSuccess", [xml, s] );
		}

		function complete(){
			// Process result
			if ( s.complete )
				s.complete(xml, status);

			// The request was completed
			if ( s.global )
				jQuery.event.trigger( "ajaxComplete", [xml, s] );

			// Handle the global AJAX counter
			if ( s.global && ! --jQuery.active )
				jQuery.event.trigger( "ajaxStop" );
		}
		
		// return XMLHttpRequest to allow aborting the request etc.
		return xml;
	},

	handleError: function( s, xml, status, e ) {
		// If a local callback was specified, fire it
		if ( s.error ) s.error( xml, status, e );

		// Fire the global callback
		if ( s.global )
			jQuery.event.trigger( "ajaxError", [xml, s, e] );
	},

	// Counter for holding the number of active queries
	active: 0,

	// Determines if an XMLHttpRequest was successful or not
	httpSuccess: function( r ) {
		try {
			// IE error sometimes returns 1223 when it should be 204 so treat it as success, see #1450
			return !r.status && location.protocol == "file:" ||
				( r.status >= 200 && r.status < 300 ) || r.status == 304 || r.status == 1223 ||
				jQuery.browser.safari && r.status == undefined;
		} catch(e){}
		return false;
	},

	// Determines if an XMLHttpRequest returns NotModified
	httpNotModified: function( xml, url ) {
		try {
			var xmlRes = xml.getResponseHeader("Last-Modified");

			// Firefox always returns 200. check Last-Modified date
			return xml.status == 304 || xmlRes == jQuery.lastModified[url] ||
				jQuery.browser.safari && xml.status == undefined;
		} catch(e){}
		return false;
	},

	httpData: function( r, type ) {
		var ct = r.getResponseHeader("content-type");
		var xml = type == "xml" || !type && ct && ct.indexOf("xml") >= 0;
		var data = xml ? r.responseXML : r.responseText;

		if ( xml && data.documentElement.tagName == "parsererror" )
			throw "parsererror";

		// If the type is "script", eval it in global context
		if ( type == "script" )
			jQuery.globalEval( data );

		// Get the JavaScript object, if JSON is used.
		if ( type == "json" )
			data = eval("(" + data + ")");

		return data;
	},

	// Serialize an array of form elements or a set of
	// key/values into a query string
	param: function( a ) {
		var s = [];

		// If an array was passed in, assume that it is an array
		// of form elements
		if ( a.constructor == Array || a.jquery )
			// Serialize the form elements
			jQuery.each( a, function(){
				s.push( encodeURIComponent(this.name) + "=" + encodeURIComponent( this.value ) );
			});

		// Otherwise, assume that it's an object of key/value pairs
		else
			// Serialize the key/values
			for ( var j in a )
				// If the value is an array then the key names need to be repeated
				if ( a[j] && a[j].constructor == Array )
					jQuery.each( a[j], function(){
						s.push( encodeURIComponent(j) + "=" + encodeURIComponent( this ) );
					});
				else
					s.push( encodeURIComponent(j) + "=" + encodeURIComponent( a[j] ) );

		// Return the resulting serialization
		return s.join("&").replace(/%20/g, "+");
	}

});
jQuery.fn.extend({
	show: function(speed,callback){
		return speed ?
			this.animate({
				height: "show", width: "show", opacity: "show"
			}, speed, callback) :
			
			this.filter(":hidden").each(function(){
				this.style.display = this.oldblock || "";
				if ( jQuery.css(this,"display") == "none" ) {
					var elem = jQuery("<" + this.tagName + " />").appendTo("body");
					this.style.display = elem.css("display");
					// handle an edge condition where css is - div { display:none; } or similar
					if (this.style.display == "none")
						this.style.display = "block";
					elem.remove();
				}
			}).end();
	},
	
	hide: function(speed,callback){
		return speed ?
			this.animate({
				height: "hide", width: "hide", opacity: "hide"
			}, speed, callback) :
			
			this.filter(":visible").each(function(){
				this.oldblock = this.oldblock || jQuery.css(this,"display");
				this.style.display = "none";
			}).end();
	},

	// Save the old toggle function
	_toggle: jQuery.fn.toggle,
	
	toggle: function( fn, fn2 ){
		return jQuery.isFunction(fn) && jQuery.isFunction(fn2) ?
			this._toggle( fn, fn2 ) :
			fn ?
				this.animate({
					height: "toggle", width: "toggle", opacity: "toggle"
				}, fn, fn2) :
				this.each(function(){
					jQuery(this)[ jQuery(this).is(":hidden") ? "show" : "hide" ]();
				});
	},
	
	slideDown: function(speed,callback){
		return this.animate({height: "show"}, speed, callback);
	},
	
	slideUp: function(speed,callback){
		return this.animate({height: "hide"}, speed, callback);
	},

	slideToggle: function(speed, callback){
		return this.animate({height: "toggle"}, speed, callback);
	},
	
	fadeIn: function(speed, callback){
		return this.animate({opacity: "show"}, speed, callback);
	},
	
	fadeOut: function(speed, callback){
		return this.animate({opacity: "hide"}, speed, callback);
	},
	
	fadeTo: function(speed,to,callback){
		return this.animate({opacity: to}, speed, callback);
	},
	
	animate: function( prop, speed, easing, callback ) {
		var optall = jQuery.speed(speed, easing, callback);

		return this[ optall.queue === false ? "each" : "queue" ](function(){
			if ( this.nodeType != 1)
				return false;

			var opt = jQuery.extend({}, optall);
			var hidden = jQuery(this).is(":hidden"), self = this;
			
			for ( var p in prop ) {
				if ( prop[p] == "hide" && hidden || prop[p] == "show" && !hidden )
					return jQuery.isFunction(opt.complete) && opt.complete.apply(this);

				if ( p == "height" || p == "width" ) {
					// Store display property
					opt.display = jQuery.css(this, "display");

					// Make sure that nothing sneaks out
					opt.overflow = this.style.overflow;
				}
			}

			if ( opt.overflow != null )
				this.style.overflow = "hidden";

			opt.curAnim = jQuery.extend({}, prop);
			
			jQuery.each( prop, function(name, val){
				var e = new jQuery.fx( self, opt, name );

				if ( /toggle|show|hide/.test(val) )
					e[ val == "toggle" ? hidden ? "show" : "hide" : val ]( prop );
				else {
					var parts = val.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),
						start = e.cur(true) || 0;

					if ( parts ) {
						var end = parseFloat(parts[2]),
							unit = parts[3] || "px";

						// We need to compute starting value
						if ( unit != "px" ) {
							self.style[ name ] = (end || 1) + unit;
							start = ((end || 1) / e.cur(true)) * start;
							self.style[ name ] = start + unit;
						}

						// If a +=/-= token was provided, we're doing a relative animation
						if ( parts[1] )
							end = ((parts[1] == "-=" ? -1 : 1) * end) + start;

						e.custom( start, end, unit );
					} else
						e.custom( start, val, "" );
				}
			});

			// For JS strict compliance
			return true;
		});
	},
	
	queue: function(type, fn){
		if ( jQuery.isFunction(type) || ( type && type.constructor == Array )) {
			fn = type;
			type = "fx";
		}

		if ( !type || (typeof type == "string" && !fn) )
			return queue( this[0], type );

		return this.each(function(){
			if ( fn.constructor == Array )
				queue(this, type, fn);
			else {
				queue(this, type).push( fn );
			
				if ( queue(this, type).length == 1 )
					fn.apply(this);
			}
		});
	},

	stop: function(clearQueue, gotoEnd){
		var timers = jQuery.timers;

		if (clearQueue)
			this.queue([]);

		this.each(function(){
			// go in reverse order so anything added to the queue during the loop is ignored
			for ( var i = timers.length - 1; i >= 0; i-- )
				if ( timers[i].elem == this ) {
					if (gotoEnd)
						// force the next step to be the last
						timers[i](true);
					timers.splice(i, 1);
				}
		});

		// start the next in the queue if the last step wasn't forced
		if (!gotoEnd)
			this.dequeue();

		return this;
	}

});

var queue = function( elem, type, array ) {
	if ( !elem )
		return undefined;

	type = type || "fx";

	var q = jQuery.data( elem, type + "queue" );

	if ( !q || array )
		q = jQuery.data( elem, type + "queue", 
			array ? jQuery.makeArray(array) : [] );

	return q;
};

jQuery.fn.dequeue = function(type){
	type = type || "fx";

	return this.each(function(){
		var q = queue(this, type);

		q.shift();

		if ( q.length )
			q[0].apply( this );
	});
};

jQuery.extend({
	
	speed: function(speed, easing, fn) {
		var opt = speed && speed.constructor == Object ? speed : {
			complete: fn || !fn && easing || 
				jQuery.isFunction( speed ) && speed,
			duration: speed,
			easing: fn && easing || easing && easing.constructor != Function && easing
		};

		opt.duration = (opt.duration && opt.duration.constructor == Number ? 
			opt.duration : 
			{ slow: 600, fast: 200 }[opt.duration]) || 400;
	
		// Queueing
		opt.old = opt.complete;
		opt.complete = function(){
			if ( opt.queue !== false )
				jQuery(this).dequeue();
			if ( jQuery.isFunction( opt.old ) )
				opt.old.apply( this );
		};
	
		return opt;
	},
	
	easing: {
		linear: function( p, n, firstNum, diff ) {
			return firstNum + diff * p;
		},
		swing: function( p, n, firstNum, diff ) {
			return ((-Math.cos(p*Math.PI)/2) + 0.5) * diff + firstNum;
		}
	},
	
	timers: [],
	timerId: null,

	fx: function( elem, options, prop ){
		this.options = options;
		this.elem = elem;
		this.prop = prop;

		if ( !options.orig )
			options.orig = {};
	}

});

jQuery.fx.prototype = {

	// Simple function for setting a style value
	update: function(){
		if ( this.options.step )
			this.options.step.apply( this.elem, [ this.now, this ] );

		(jQuery.fx.step[this.prop] || jQuery.fx.step._default)( this );

		// Set display property to block for height/width animations
		if ( this.prop == "height" || this.prop == "width" )
			this.elem.style.display = "block";
	},

	// Get the current size
	cur: function(force){
		if ( this.elem[this.prop] != null && this.elem.style[this.prop] == null )
			return this.elem[ this.prop ];

		var r = parseFloat(jQuery.css(this.elem, this.prop, force));
		return r && r > -10000 ? r : parseFloat(jQuery.curCSS(this.elem, this.prop)) || 0;
	},

	// Start an animation from one number to another
	custom: function(from, to, unit){
		this.startTime = (new Date()).getTime();
		this.start = from;
		this.end = to;
		this.unit = unit || this.unit || "px";
		this.now = this.start;
		this.pos = this.state = 0;
		this.update();

		var self = this;
		function t(gotoEnd){
			return self.step(gotoEnd);
		}

		t.elem = this.elem;

		jQuery.timers.push(t);

		if ( jQuery.timerId == null ) {
			jQuery.timerId = setInterval(function(){
				var timers = jQuery.timers;
				
				for ( var i = 0; i < timers.length; i++ )
					if ( !timers[i]() )
						timers.splice(i--, 1);

				if ( !timers.length ) {
					clearInterval( jQuery.timerId );
					jQuery.timerId = null;
				}
			}, 13);
		}
	},

	// Simple 'show' function
	show: function(){
		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
		this.options.show = true;

		// Begin the animation
		this.custom(0, this.cur());

		// Make sure that we start at a small width/height to avoid any
		// flash of content
		if ( this.prop == "width" || this.prop == "height" )
			this.elem.style[this.prop] = "1px";
		
		// Start by showing the element
		jQuery(this.elem).show();
	},

	// Simple 'hide' function
	hide: function(){
		// Remember where we started, so that we can go back to it later
		this.options.orig[this.prop] = jQuery.attr( this.elem.style, this.prop );
		this.options.hide = true;

		// Begin the animation
		this.custom(this.cur(), 0);
	},

	// Each step of an animation
	step: function(gotoEnd){
		var t = (new Date()).getTime();

		if ( gotoEnd || t > this.options.duration + this.startTime ) {
			this.now = this.end;
			this.pos = this.state = 1;
			this.update();

			this.options.curAnim[ this.prop ] = true;

			var done = true;
			for ( var i in this.options.curAnim )
				if ( this.options.curAnim[i] !== true )
					done = false;

			if ( done ) {
				if ( this.options.display != null ) {
					// Reset the overflow
					this.elem.style.overflow = this.options.overflow;
				
					// Reset the display
					this.elem.style.display = this.options.display;
					if ( jQuery.css(this.elem, "display") == "none" )
						this.elem.style.display = "block";
				}

				// Hide the element if the "hide" operation was done
				if ( this.options.hide )
					this.elem.style.display = "none";

				// Reset the properties, if the item has been hidden or shown
				if ( this.options.hide || this.options.show )
					for ( var p in this.options.curAnim )
						jQuery.attr(this.elem.style, p, this.options.orig[p]);
			}

			// If a callback was provided, execute it
			if ( done && jQuery.isFunction( this.options.complete ) )
				// Execute the complete function
				this.options.complete.apply( this.elem );

			return false;
		} else {
			var n = t - this.startTime;
			this.state = n / this.options.duration;

			// Perform the easing function, defaults to swing
			this.pos = jQuery.easing[this.options.easing || (jQuery.easing.swing ? "swing" : "linear")](this.state, n, 0, 1, this.options.duration);
			this.now = this.start + ((this.end - this.start) * this.pos);

			// Perform the next step of the animation
			this.update();
		}

		return true;
	}

};

jQuery.fx.step = {
	scrollLeft: function(fx){
		fx.elem.scrollLeft = fx.now;
	},

	scrollTop: function(fx){
		fx.elem.scrollTop = fx.now;
	},

	opacity: function(fx){
		jQuery.attr(fx.elem.style, "opacity", fx.now);
	},

	_default: function(fx){
		fx.elem.style[ fx.prop ] = fx.now + fx.unit;
	}
};
// The Offset Method
// Originally By Brandon Aaron, part of the Dimension Plugin
// http://jquery.com/plugins/project/dimensions
jQuery.fn.offset = function() {
	var left = 0, top = 0, elem = this[0], results;
	
	if ( elem ) with ( jQuery.browser ) {
		var parent       = elem.parentNode, 
		    offsetChild  = elem,
		    offsetParent = elem.offsetParent, 
		    doc          = elem.ownerDocument,
		    safari2      = safari && parseInt(version) < 522 && !/adobeair/i.test(userAgent),
		    fixed        = jQuery.css(elem, "position") == "fixed";
	
		// Use getBoundingClientRect if available
		if ( elem.getBoundingClientRect ) {
			var box = elem.getBoundingClientRect();
		
			// Add the document scroll offsets
			add(box.left + Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
				box.top  + Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
		
			// IE adds the HTML element's border, by default it is medium which is 2px
			// IE 6 and 7 quirks mode the border width is overwritable by the following css html { border: 0; }
			// IE 7 standards mode, the border is always 2px
			// This border/offset is typically represented by the clientLeft and clientTop properties
			// However, in IE6 and 7 quirks mode the clientLeft and clientTop properties are not updated when overwriting it via CSS
			// Therefore this method will be off by 2px in IE while in quirksmode
			add( -doc.documentElement.clientLeft, -doc.documentElement.clientTop );
	
		// Otherwise loop through the offsetParents and parentNodes
		} else {
		
			// Initial element offsets
			add( elem.offsetLeft, elem.offsetTop );
			
			// Get parent offsets
			while ( offsetParent ) {
				// Add offsetParent offsets
				add( offsetParent.offsetLeft, offsetParent.offsetTop );
			
				// Mozilla and Safari > 2 does not include the border on offset parents
				// However Mozilla adds the border for table or table cells
				if ( mozilla && !/^t(able|d|h)$/i.test(offsetParent.tagName) || safari && !safari2 )
					border( offsetParent );
					
				// Add the document scroll offsets if position is fixed on any offsetParent
				if ( !fixed && jQuery.css(offsetParent, "position") == "fixed" )
					fixed = true;
			
				// Set offsetChild to previous offsetParent unless it is the body element
				offsetChild  = /^body$/i.test(offsetParent.tagName) ? offsetChild : offsetParent;
				// Get next offsetParent
				offsetParent = offsetParent.offsetParent;
			}
		
			// Get parent scroll offsets
			while ( parent && parent.tagName && !/^body|html$/i.test(parent.tagName) ) {
				// Remove parent scroll UNLESS that parent is inline or a table to work around Opera inline/table scrollLeft/Top bug
				if ( !/^inline|table.*$/i.test(jQuery.css(parent, "display")) )
					// Subtract parent scroll offsets
					add( -parent.scrollLeft, -parent.scrollTop );
			
				// Mozilla does not add the border for a parent that has overflow != visible
				if ( mozilla && jQuery.css(parent, "overflow") != "visible" )
					border( parent );
			
				// Get next parent
				parent = parent.parentNode;
			}
		
			// Safari <= 2 doubles body offsets with a fixed position element/offsetParent or absolutely positioned offsetChild
			// Mozilla doubles body offsets with a non-absolutely positioned offsetChild
			if ( (safari2 && (fixed || jQuery.css(offsetChild, "position") == "absolute")) || 
				(mozilla && jQuery.css(offsetChild, "position") != "absolute") )
					add( -doc.body.offsetLeft, -doc.body.offsetTop );
			
			// Add the document scroll offsets if position is fixed
			if ( fixed )
				add(Math.max(doc.documentElement.scrollLeft, doc.body.scrollLeft),
					Math.max(doc.documentElement.scrollTop,  doc.body.scrollTop));
		}

		// Return an object with top and left properties
		results = { top: top, left: left };
	}

	function border(elem) {
		add( jQuery.curCSS(elem, "borderLeftWidth", true), jQuery.curCSS(elem, "borderTopWidth", true) );
	}

	function add(l, t) {
		left += parseInt(l) || 0;
		top += parseInt(t) || 0;
	}

	return results;
};
})();


/*
 * Date prototype extensions. Doesn't depend on any
 * other code. Doens't overwrite existing methods.
 *
 * Adds dayNames, abbrDayNames, monthNames and abbrMonthNames static properties and isLeapYear,
 * isWeekend, isWeekDay, getDaysInMonth, getDayName, getMonthName, getDayOfYear, getWeekOfYear,
 * setDayOfYear, addYears, addMonths, addDays, addHours, addMinutes, addSeconds methods
 *
 * Copyright (c) 2006 J��rn Zaefferer and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 *
 * Additional methods and properties added by Kelvin Luck: firstDayOfWeek, dateFormat, zeroTime, asString, fromString -
 * I've added my name to these methods so you know who to blame if they are broken!
 * 
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * An Array of day names starting with Sunday.
 * 
 * @example dayNames[0]
 * @result 'Sunday'
 *
 * @name dayNames
 * @type Array
 * @cat Plugins/Methods/Date
 */
Date.dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];

/**
 * An Array of abbreviated day names starting with Sun.
 * 
 * @example abbrDayNames[0]
 * @result 'Sun'
 *
 * @name abbrDayNames
 * @type Array
 * @cat Plugins/Methods/Date
 */
Date.abbrDayNames = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat'];

/**
 * An Array of month names starting with Janurary.
 * 
 * @example monthNames[0]
 * @result 'January'
 *
 * @name monthNames
 * @type Array
 * @cat Plugins/Methods/Date
 */
Date.monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];

/**
 * An Array of abbreviated month names starting with Jan.
 * 
 * @example abbrMonthNames[0]
 * @result 'Jan'
 *
 * @name monthNames
 * @type Array
 * @cat Plugins/Methods/Date
 */
Date.abbrMonthNames = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'];

/**
 * The first day of the week for this locale.
 *
 * @name firstDayOfWeek
 * @type Number
 * @cat Plugins/Methods/Date
 * @author Kelvin Luck
 */
Date.firstDayOfWeek = 1;

/**
 * The format that string dates should be represented as (e.g. 'dd/mm/yyyy' for UK, 'mm/dd/yyyy' for US, 'yyyy-mm-dd' for Unicode etc).
 *
 * @name format
 * @type String
 * @cat Plugins/Methods/Date
 * @author Kelvin Luck
 */
Date.format = 'dd/mm/yyyy';
//Date.format = 'mm/dd/yyyy';
//Date.format = 'yyyy-mm-dd';
//Date.format = 'dd mmm yy';

(function() {

	/**
	 * Adds a given method under the given name 
	 * to the Date prototype if it doesn't
	 * currently exist.
	 *
	 * @private
	 */
	function add(name, method) {
		if( !Date.prototype[name] ) {
			Date.prototype[name] = method;
		}
	};
	
	/**
	 * Checks if the year is a leap year.
	 *
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.isLeapYear();
	 * @result true
	 *
	 * @name isLeapYear
	 * @type Boolean
	 * @cat Plugins/Methods/Date
	 */
	add("isLeapYear", function() {
		var y = this.getFullYear();
		return (y%4==0 && y%100!=0) || y%400==0;
	});
	
	/**
	 * Checks if the day is a weekend day (Sat or Sun).
	 *
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.isWeekend();
	 * @result false
	 *
	 * @name isWeekend
	 * @type Boolean
	 * @cat Plugins/Methods/Date
	 */
	add("isWeekend", function() {
		return this.getDay()==0 || this.getDay()==6;
	});
	
	/**
	 * Check if the day is a day of the week (Mon-Fri)
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.isWeekDay();
	 * @result false
	 * 
	 * @name isWeekDay
	 * @type Boolean
	 * @cat Plugins/Methods/Date
	 */
	add("isWeekDay", function() {
		return !this.isWeekend();
	});
	
	/**
	 * Gets the number of days in the month.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getDaysInMonth();
	 * @result 31
	 * 
	 * @name getDaysInMonth
	 * @type Number
	 * @cat Plugins/Methods/Date
	 */
	add("getDaysInMonth", function() {
		return [31,(this.isLeapYear() ? 29:28),31,30,31,30,31,31,30,31,30,31][this.getMonth()];
	});
	
	/**
	 * Gets the name of the day.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getDayName();
	 * @result 'Saturday'
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getDayName(true);
	 * @result 'Sat'
	 * 
	 * @param abbreviated Boolean When set to true the name will be abbreviated.
	 * @name getDayName
	 * @type String
	 * @cat Plugins/Methods/Date
	 */
	add("getDayName", function(abbreviated) {
		return abbreviated ? Date.abbrDayNames[this.getDay()] : Date.dayNames[this.getDay()];
	});

	/**
	 * Gets the name of the month.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getMonthName();
	 * @result 'Janurary'
	 *
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getMonthName(true);
	 * @result 'Jan'
	 * 
	 * @param abbreviated Boolean When set to true the name will be abbreviated.
	 * @name getDayName
	 * @type String
	 * @cat Plugins/Methods/Date
	 */
	add("getMonthName", function(abbreviated) {
		return abbreviated ? Date.abbrMonthNames[this.getMonth()] : Date.monthNames[this.getMonth()];
	});

	/**
	 * Get the number of the day of the year.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getDayOfYear();
	 * @result 11
	 * 
	 * @name getDayOfYear
	 * @type Number
	 * @cat Plugins/Methods/Date
	 */
	add("getDayOfYear", function() {
		var tmpdtm = new Date("1/1/" + this.getFullYear());
		return Math.floor((this.getTime() - tmpdtm.getTime()) / 86400000);
	});
	
	/**
	 * Get the number of the week of the year.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.getWeekOfYear();
	 * @result 2
	 * 
	 * @name getWeekOfYear
	 * @type Number
	 * @cat Plugins/Methods/Date
	 */
	add("getWeekOfYear", function() {
		return Math.ceil(this.getDayOfYear() / 7);
	});

	/**
	 * Set the day of the year.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.setDayOfYear(1);
	 * dtm.toString();
	 * @result 'Tue Jan 01 2008 00:00:00'
	 * 
	 * @name setDayOfYear
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("setDayOfYear", function(day) {
		this.setMonth(0);
		this.setDate(day);
		return this;
	});
	
	/**
	 * Add a number of years to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addYears(1);
	 * dtm.toString();
	 * @result 'Mon Jan 12 2009 00:00:00'
	 * 
	 * @name addYears
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addYears", function(num) {
		this.setFullYear(this.getFullYear() + num);
		return this;
	});
	
	/**
	 * Add a number of months to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addMonths(1);
	 * dtm.toString();
	 * @result 'Tue Feb 12 2008 00:00:00'
	 * 
	 * @name addMonths
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addMonths", function(num) {
		var tmpdtm = this.getDate();
		
		this.setMonth(this.getMonth() + num);
		
		if (tmpdtm > this.getDate())
			this.addDays(-this.getDate());
		
		return this;
	});
	
	/**
	 * Add a number of days to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addDays(1);
	 * dtm.toString();
	 * @result 'Sun Jan 13 2008 00:00:00'
	 * 
	 * @name addDays
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addDays", function(num) {
		this.setDate(this.getDate() + num);
		return this;
	});
	
	/**
	 * Add a number of hours to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addHours(24);
	 * dtm.toString();
	 * @result 'Sun Jan 13 2008 00:00:00'
	 * 
	 * @name addHours
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addHours", function(num) {
		this.setHours(this.getHours() + num);
		return this;
	});

	/**
	 * Add a number of minutes to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addMinutes(60);
	 * dtm.toString();
	 * @result 'Sat Jan 12 2008 01:00:00'
	 * 
	 * @name addMinutes
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addMinutes", function(num) {
		this.setMinutes(this.getMinutes() + num);
		return this;
	});
	
	/**
	 * Add a number of seconds to the date object.
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.addSeconds(60);
	 * dtm.toString();
	 * @result 'Sat Jan 12 2008 00:01:00'
	 * 
	 * @name addSeconds
	 * @type Date
	 * @cat Plugins/Methods/Date
	 */
	add("addSeconds", function(num) {
		this.setSeconds(this.getSeconds() + num);
		return this;
	});
	
	/**
	 * Sets the time component of this Date to zero for cleaner, easier comparison of dates where time is not relevant.
	 * 
	 * @example var dtm = new Date();
	 * dtm.zeroTime();
	 * dtm.toString();
	 * @result 'Sat Jan 12 2008 00:01:00'
	 * 
	 * @name zeroTime
	 * @type Date
	 * @cat Plugins/Methods/Date
	 * @author Kelvin Luck
	 */
	add("zeroTime", function() {
		this.setMilliseconds(0);
		this.setSeconds(0);
		this.setMinutes(0);
		this.setHours(0);
		return this;
	});
	
	/**
	 * Returns a string representation of the date object according to Date.format.
	 * (Date.toString may be used in other places so I purposefully didn't overwrite it)
	 * 
	 * @example var dtm = new Date("01/12/2008");
	 * dtm.asString();
	 * @result '12/01/2008' // (where Date.format == 'dd/mm/yyyy'
	 * 
	 * @name asString
	 * @type Date
	 * @cat Plugins/Methods/Date
	 * @author Kelvin Luck
	 */
	add("asString", function() {
		var r = Date.format;
		return r
			.split('yyyy').join(this.getFullYear())
			.split('yy').join(this.getYear())
			.split('mmm').join(this.getMonthName(true))
			.split('mm').join(_zeroPad(this.getMonth()+1))
			.split('dd').join(_zeroPad(this.getDate()));
	});
	
	/**
	 * Returns a new date object created from the passed String according to Date.format or false if the attempt to do this results in an invalid date object
	 * (We can't simple use Date.parse as it's not aware of locale and I chose not to overwrite it incase it's functionality is being relied on elsewhere)
	 *
	 * @example var dtm = Date.fromString("12/01/2008");
	 * dtm.toString();
	 * @result 'Sat Jan 12 2008 00:00:00' // (where Date.format == 'dd/mm/yyyy'
	 * 
	 * @name fromString
	 * @type Date
	 * @cat Plugins/Methods/Date
	 * @author Kelvin Luck
	 */
	Date.fromString = function(s)
	{
		var f = Date.format;
        if(f.length != s.length)
        {
            return false;
        }
		var d = new Date('01/01/1977');
		var iY = f.indexOf('yyyy');
		if (iY > -1) {
			d.setFullYear(Number(s.substr(iY, 4)));
		} else {
			// TODO - this doesn't work very well - are there any rules for what is meant by a two digit year?
			d.setYear(Number(s.substr(f.indexOf('yy'), 2)));
		}
		var iM = f.indexOf('mmm');
		if (iM > -1) {
			var mStr = s.substr(iM, 3);
			for (var i=0; i<Date.abbrMonthNames.length; i++) {
				if (Date.abbrMonthNames[i] == mStr) break;
			}
			d.setMonth(i);
		} else {
			d.setMonth(Number(s.substr(f.indexOf('mm'), 2)) - 1);
		}
		d.setDate(Number(s.substr(f.indexOf('dd'), 2)));
		if (isNaN(d.getTime())) {
			return false;
		}
		return d;
	};
	
	// utility method
	var _zeroPad = function(num) {
		var s = '0'+num;
		return s.substring(s.length-2)
		//return ('0'+num).substring(-2); // doesn't work on IE :(
	};
	
})();

/**
 * jQBrowser v0.2 - Extend jQuery's browser detection capabilities
 *   * http://davecardwell.co.uk/javascript/jquery/plugins/jquery-browserdetect/0.2/
 *
 * Dave Cardwell <http://davecardwell.co.uk/>
 *
 * Built on the shoulders of giants:
 *   * John Resig <http://jquery.com/>
 *   * Peter-Paul Koch <http://www.quirksmode.org/?/js/detect.html>
 *
 *
 * Copyright (c) 2006 Dave Cardwell, dual licensed under the MIT and GPL
 * licenses:
 *   * http://www.opensource.org/licenses/mit-license.php
 *   * http://www.gnu.org/licenses/gpl.txt
 */


/**
 * For the latest version of this plugin, and a discussion of its usage and
 * implementation, visit:
 *   * http://davecardwell.co.uk/javascript/jquery/plugins/jquery-browserdetect/
 */

(
 	function()
 	{
		/**
		 * The following functions and attributes form the internal methods and
		 * state of the jQBrowser plugin.  See the relevant function definition
		 * later in the source for further information.
		 *
		 * Private.browser
		 * Private.version
		 * Private.OS
		 *
		 * Private.aol
		 * Private.camino
		 * Private.firefox
		 * Private.flock
		 * Private.icab
		 * Private.konqueror
		 * Private.mozilla
		 * Private.msie
		 * Private.netscape
		 * Private.opera
		 * Private.safari
		 *
		 * Private.linux
		 * Private.mac
		 * Private.win
		 */
		var Private = 
		{
			// Initially set to 'Unknown', if detected each of these properties will
			// be updated.
			  'browser': 'Unknown',
			  'version': 
			  {
				  'number': undefined,
				  'string': 'Unknown'
			  },
				   'OS': 'Unknown',
	
			// Initially set to false, if detected one of the following browsers
			// will be updated.
				  'aol': false,
			   'camino': false,
			  'firefox': false,
				'flock': false,
				 'icab': false,
			'konqueror': false,
			  'mozilla': false,
				 'msie': false,
			 'netscape': false,
				'opera': false,
			   'safari': false,
	
			// Initially set to false, if detected one of the following operating
			// systems will be updated.
				'linux': false,
				  'mac': false,
				  'win': false
		};
	
	
	
		/**
		 * Loop over the items in 'data' trying to find a browser match with the
		 * test in data[i].browser().  Once found, attempt to determine the
		 * browser version.
		 *
		 *       'name': A string containing the full name of the browser.
		 * 'identifier': By default this is a lowercase version of 'name', but
		 *               this can be overwritten by explicitly defining an
		 *               'identifier'.
		 *    'browser': A function that returns a boolean value indicating
		 *               whether or not the given browser is detected.
		 *    'version': An optional function that overwrites the default version
		 *               testing.  Must return the result of a .match().
		 *
		 * Please note that the order of the data array is important, as some
		 * browsers contain details of others in their navigator.userAgent string.
		 * For example, Flock's contains 'Firefox' so much come before Firefox's
		 * test to avoid false positives.
		 */
		for( var  i = 0,                    // counter
				 ua = navigator.userAgent,  // the navigator's user agent string
				 ve = navigator.vendor,     // the navigator's vendor string
			   data = [                     // browser tests and data
					{ // Safari <http://www.apple.com/safari/>
							  'name': 'Safari',
						   'browser': function() { return /Apple/.test(ve) }
					},
					{ // Opera <http://www.opera.com/>
							  'name': 'Opera',
						   'browser': function() {
										  return window.opera != undefined
									  }
					},
					{ // iCab <http://www.icab.de/>
							  'name': 'iCab',
						   'browser': function() { return /iCab/.test(ve) }
					},
					{ // Konqueror <http://www.konqueror.org/>
							  'name': 'Konqueror',
						   'browser': function() { return /KDE/.test(ve) }
					},
					{ // AOL Explorer <http://downloads.channel.aol.com/browser>
						'identifier': 'aol',
							  'name': 'AOL Explorer',
						   'browser': function() {
										  return /America Online Browser/.test(ua)
									  },
						   'version': function() {
										  return ua.match(/rev(\d+(?:\.\d+)+)/)
									  }
					},
					{ // Flock <http://www.flock.com/>
							  'name': 'Flock',
						   'browser': function() { return /Flock/.test(ua) }
					},
					{ // Camino <http://www.caminobrowser.org/>
							  'name': 'Camino',
						   'browser': function() { return /Camino/.test(ve) }
					},
					{ // Firefox <http://www.mozilla.com/firefox/>
							  'name': 'Firefox',
						   'browser': function() { return /Firefox/.test(ua) }
					},
					{ // Netscape <http://browser.netscape.com/>
							  'name': 'Netscape',
						   'browser': function() { return /Netscape/.test(ua) }
					},
					{ // Internet Explorer <http://www.microsoft.com/windows/ie/>
					  //                   <http://www.microsoft.com/mac/ie/>
						'identifier': 'msie',
							  'name': 'Internet Explorer',
						   'browser': function() { return /MSIE/.test(ua) },
						   'version': function() {
										  return ua.match(
											  /MSIE (\d+(?:\.\d+)+(?:b\d*)?)/
										  )
									  }
					},
					{ // Mozilla <http://www.mozilla.org/products/mozilla1.x/>
							  'name': 'Mozilla',
						   'browser': function() {
										  return /Gecko|Mozilla/.test(ua)
									  },
						   'version': function() {
										  return ua.match(/rv:(\d+(?:\.\d+)+)/)
									  }
					 }
				 ];
			 i < data.length;
			 i++
		) 
		{
			if( data[i].browser() ) 
			{ // we have a match
				// If the identifier is not explicitly set, use a lowercase
				// version of the given name.
				var identifier = data[i].identifier ? data[i].identifier : data[i].name.toLowerCase();
	
				// Make a note that this browser was detected.
				Private[ identifier ] = true;
	
				// $.browser.browser() will now return the correct browser.
				Private.browser = data[i].name;
	
				var result;
				if( data[i].version != undefined && (result = data[i].version()) ) 
				{
					// Use the explicitly set test for browser version.
					Private.version.string = result[1];
					Private.version.number = parseFloat( result[1] );
				} 
				else 
				{
					// Otherwise use the default test which searches for the
					// version number after the browser name in the user agent
					// string.
					var re = new RegExp(
						data[i].name + '(?:\\s|\\/)(\\d+(?:\\.\\d+)+(?:(?:a|b)\\d*)?)'
					);
	
					result = ua.match(re);
					if( result != undefined ) 
					{
						Private.version.string = result[1];
						Private.version.number = parseFloat( result[1] );
					}
				}
	
				// Once we've detected the browser there is no need to check the
				// others.
				break;
			}
		};
	
	
	
		/**
		 * Loop over the items in 'data' trying to find a operating system match
		 * with the test in data[i].os().
		 *
		 *       'name': A string containing the full name of the operating
		 *               system.
		 * 'identifier': By default this is a lowercase version of 'name', but
		 *               this can be overwritten by explicitly defining an
		 *               'identifier'.
		 *         'OS': A function that returns a boolean value indicating
		 *               whether or not the given operating system is detected.
		 */
		for( var  i = 0,                  // counter
				 pl = navigator.platform, // the navigator's platform string
			   data = [                   // OS data and tests
					{ // Microsoft Windows <http://www.microsoft.com/windows/>
						'identifier': 'win',
							  'name': 'Windows',
								'OS': function() { return /Win/.test(pl) }
					},
					{ // Apple Mac OS <http://www.apple.com/macos/>
							  'name': 'Mac',
								'OS': function() { return /Mac/.test(pl) }
					},
					{ // Linux <http://www.linux.org/>
							  'name': 'Linux',
								'OS': function() { return /Linux/.test(pl) }
					}
			   ];
		   i < data.length;
		   i++
		) 
		{
			if( data[i].OS() ) 
			{ // we have a match
				// If the identifier is not explicitly set, use a lowercase
				// version of the given name.
				var identifier = data[i].identifier ? data[i].identifier : data[i].name.toLowerCase();
	
				// Make a note that the OS was detected.
				Private[ identifier ] = true;
	
				// $.browser.OS() will now return the correct OS.
				Private.OS = data[i].name;
	
				// Once we've detected the browser there is no need to check the
				// others.
				break;
			}
		};
		
		/**
		 * The following functions and attributes form the Public interface of the
		 * jQBrowser plugin, accessed externally through the $.browser object.
		 * See the relevant function definition later in the source for further
		 * information.
		 *
		 * $.browser.browser()
		 * $.browser.version.number()
		 * $.browser.version.string()
		 * $.browser.OS()
		 *
		 * $.browser.aol()
		 * $.browser.camino()
		 * $.browser.firefox()
		 * $.browser.flock()
		 * $.browser.icab()
		 * $.browser.konqueror()
		 * $.browser.mozilla()
		 * $.browser.msie()
		 * $.browser.netscape()
		 * $.browser.opera()
		 * $.browser.safari()
		 *
		 * $.browser.linux()
		 * $.browser.mac()
		 * $.browser.win()
		 */
		var Public = 
		{
			// The current browser, its version as a number or a string, and the
			// operating system its running on.
			  'browser': Private.browser,
			  'version': 
			  {
				  'number': Private.version.number,
				  'string': Private.version.string
			  },
				   'OS': Private.OS,
	
			// A boolean value indicating whether or not the given browser was
			// detected.
				  'aol': Private.aol,
			   'camino': Private.camino,
			  'firefox': Private.firefox,
				'flock': Private.flock,
				 'icab': Private.icab,
			'konqueror': Private.konqueror,
			  'mozilla': Private.firefox || Private.flock || Private.camino ? true : Private.mozilla,
				 'msie': Private.msie,
			 'netscape': Private.netscape,
				'opera': Private.opera,
			   'safari': Private.safari,
	
			// A boolean value indicating whether or not the given OS was
			// detected.
				'linux': Private.linux,
				  'mac': Private.mac,
				  'win': Private.win
		};
	
		// Allow external access to the 'Public' interface through the $.browser
		// object.
		
		$.browser = Public;
	}
)();

/*
 * Metadata - jQuery plugin for parsing metadata from elements
 *
 * Copyright (c) 2006 John Resig, Yehuda Katz, J�örn Zaefferer, Paul McLanahan
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.metadata.js 4187 2007-12-16 17:15:27Z joern.zaefferer $
 *
 */

/**
 * Sets the type of metadata to use. Metadata is encoded in JSON, and each property
 * in the JSON will become a property of the element itself.
 *
 * There are three supported types of metadata storage:
 *
 *   attr:  Inside an attribute. The name parameter indicates *which* attribute.
 *          
 *   class: Inside the class attribute, wrapped in curly braces: { }
 *   
 *   elem:  Inside a child element (e.g. a script tag). The
 *          name parameter indicates *which* element.
 *          
 * The metadata for an element is loaded the first time the element is accessed via jQuery.
 *
 * As a result, you can define the metadata type, use $(expr) to load the metadata into the elements
 * matched by expr, then redefine the metadata type and run another $(expr) for other elements.
 * 
 * @name $.metadata.setType
 *
 * @example <p id="one" class="some_class {item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("class")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from the class attribute
 * 
 * @example <p id="one" class="some_class" data="{item_id: 1, item_label: 'Label'}">This is a p</p>
 * @before $.metadata.setType("attr", "data")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a "data" attribute
 * 
 * @example <p id="one" class="some_class"><script>{item_id: 1, item_label: 'Label'}</script>This is a p</p>
 * @before $.metadata.setType("elem", "script")
 * @after $("#one").metadata().item_id == 1; $("#one").metadata().item_label == "Label"
 * @desc Reads metadata from a nested script element
 * 
 * @param String type The encoding type
 * @param String name The name of the attribute to be used to get metadata (optional)
 * @cat Plugins/Metadata
 * @descr Sets the type of encoding to be used when loading metadata for the first time
 * @type undefined
 * @see metadata()
 */

(function($) {

$.extend({
	metadata : {
		defaults : {
			type: 'class',
			name: 'metadata',
			cre: /({.*})/,
			single: 'metadata'
		},
		setType: function( type, name ){
			this.defaults.type = type;
			this.defaults.name = name;
		},
		get: function( elem, opts ){
			var settings = $.extend({},this.defaults,opts);
			// check for empty string in single property
			if ( !settings.single.length ) settings.single = 'metadata';
			
			var data = $.data(elem, settings.single);
			// returned cached data if it already exists
			if ( data ) return data;
			
			data = "{}";
			
			if ( settings.type == "class" ) {
				var m = settings.cre.exec( elem.className );
				if ( m ) {
					data = m[1];
					elem.className = elem.className.replace(data, ''); 
				}
			} else if ( settings.type == "elem" ) {
				if( !elem.getElementsByTagName )
					return undefined;
				var e = elem.getElementsByTagName(settings.name);
				if ( e.length )
					data = $.trim(e[0].innerHTML);
			} else if ( elem.getAttribute != undefined ) {
				var attr = elem.getAttribute( settings.name );
				if ( attr )
					data = attr;
			}
			
			if ( data.indexOf( '{' ) <0 )
			data = "{" + data + "}";
			
			data = eval("(" + data + ")");
			
			$.data( elem, settings.single, data );
			return data;
		}
	}
});

/**
 * Returns the metadata object for the first member of the jQuery object.
 *
 * @name metadata
 * @descr Returns element's metadata object
 * @param Object opts An object contianing settings to override the defaults
 * @type jQuery
 * @cat Plugins/Metadata
 */
$.fn.metadata = function( opts ){
	return $.metadata.get( this[0], opts );
};

})(jQuery);

/* Copyright (c) 2007 Paul Bakaus (paul.bakaus@googlemail.com) and Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-12-20 16:43:48 +0200 (Чт, 20 дек 2007) $
 * $Rev: 4257 $
 *
 * Version: @VERSION
 *
 * Requires: jQuery 1.2+
 */

(function($){
	
$.dimensions = {
	version: '@VERSION'
};

// Create innerHeight, innerWidth, outerHeight and outerWidth methods
$.each( [ 'Height', 'Width' ], function(i, name){
	
	// innerHeight and innerWidth
	$.fn[ 'inner' + name ] = function() {
		if (!this[0]) return;
		
		var torl = name == 'Height' ? 'Top'    : 'Left',  // top or left
		    borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right
		
		return this.is(':visible') ? this[0]['client' + name] : num( this, name.toLowerCase() ) + num(this, 'padding' + torl) + num(this, 'padding' + borr);
	};
	
	// outerHeight and outerWidth
	$.fn[ 'outer' + name ] = function(options) {
		if (!this[0]) return;
		
		var torl = name == 'Height' ? 'Top'    : 'Left',  // top or left
		    borr = name == 'Height' ? 'Bottom' : 'Right'; // bottom or right
		
		options = $.extend({ margin: false }, options || {});
		
		var val = this.is(':visible') ? 
				this[0]['offset' + name] : 
				num( this, name.toLowerCase() )
					+ num(this, 'border' + torl + 'Width') + num(this, 'border' + borr + 'Width')
					+ num(this, 'padding' + torl) + num(this, 'padding' + borr);
		
		return val + (options.margin ? (num(this, 'margin' + torl) + num(this, 'margin' + borr)) : 0);
	};
});

// Create scrollLeft and scrollTop methods
$.each( ['Left', 'Top'], function(i, name) {
	$.fn[ 'scroll' + name ] = function(val) {
		if (!this[0]) return;
		
		return val != undefined ?
		
			// Set the scroll offset
			this.each(function() {
				this == window || this == document ?
					window.scrollTo( 
						name == 'Left' ? val : $(window)[ 'scrollLeft' ](),
						name == 'Top'  ? val : $(window)[ 'scrollTop'  ]()
					) :
					this[ 'scroll' + name ] = val;
			}) :
			
			// Return the scroll offset
			this[0] == window || this[0] == document ?
				self[ (name == 'Left' ? 'pageXOffset' : 'pageYOffset') ] ||
					$.boxModel && document.documentElement[ 'scroll' + name ] ||
					document.body[ 'scroll' + name ] :
				this[0][ 'scroll' + name ];
	};
});

$.fn.extend({
	position: function() {
		var left = 0, top = 0, elem = this[0], offset, parentOffset, offsetParent, results;
		
		if (elem) {
			// Get *real* offsetParent
			offsetParent = this.offsetParent();
			
			// Get correct offsets
			offset       = this.offset();
			parentOffset = offsetParent.offset();
			
			// Subtract element margins
			offset.top  -= num(elem, 'marginTop');
			offset.left -= num(elem, 'marginLeft');
			
			// Add offsetParent borders
			parentOffset.top  += num(offsetParent, 'borderTopWidth');
			parentOffset.left += num(offsetParent, 'borderLeftWidth');
			
			// Subtract the two offsets
			results = {
				top:  offset.top  - parentOffset.top,
				left: offset.left - parentOffset.left
			};
		}
		
		return results;
	},
	
	offsetParent: function() {
		var offsetParent = this[0].offsetParent;
		while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') )
			offsetParent = offsetParent.offsetParent;
		return $(offsetParent);
	}
});

function num(el, prop) {
	return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0;
};

})(jQuery);

/*
 * jQuery JSON Plugin
 * version: 1.0 (2008-04-17)
 *
 * This document is licensed as free software under the terms of the
 * MIT License: http://www.opensource.org/licenses/mit-license.php
 *
 * Brantley Harris technically wrote this plugin, but it is based somewhat
 * on the JSON.org website's http://www.json.org/json2.js, which proclaims:
 * "NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.", a sentiment that
 * I uphold.  I really just cleaned it up.
 *
 * It is also based heavily on MochiKit's serializeJSON, which is 
 * copywrited 2005 by Bob Ippolito.
 */
 
(function($) {   
    function toIntegersAtLease(n) 
    // Format integers to have at least two digits.
    {    
        return n < 10 ? '0' + n : n;
    }

    Date.prototype.toJSON = function(date)
    // Yes, it polutes the Date namespace, but we'll allow it here, as
    // it's damned usefull.
    {
        return date.getUTCFullYear()   + '-' +
             toIntegersAtLease(date.getUTCMonth() + 1) + '-' +
             toIntegersAtLease(date.getUTCDate());
    };

    var escapeable = /["\\\x00-\x1f\x7f-\x9f]/g;
    var meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        }
        
    $.quoteString = function(string)
    // Places quotes around a string, inteligently.
    // If the string contains no control characters, no quote characters, and no
    // backslash characters, then we can safely slap some quotes around it.
    // Otherwise we must also replace the offending characters with safe escape
    // sequences.
    {
        if (escapeable.test(string))
        {
            return '"' + string.replace(escapeable, function (a) 
            {
                var c = meta[a];
                if (typeof c === 'string') {
                    return c;
                }
                c = a.charCodeAt();
                return '\\u00' + Math.floor(c / 16).toString(16) + (c % 16).toString(16);
            }) + '"'
        }
        return '"' + string + '"';
    }
    
    $.toJSON = function(o)
    {
        var type = typeof(o);
        
        if (type == "undefined")
            return "undefined";
        else if (type == "number" || type == "boolean")
            return o + "";
        else if (o === null)
            return "null";
        
        // Is it a string?
        if (type == "string") 
        {
            return $.quoteString(o);
        }
        
        // Does it have a .toJSON function?
        if (type == "object" && typeof o.toJSON == "function") 
            return o.toJSON();
        
        // Is it an array?
        if (type != "function" && typeof(o.length) == "number") 
        {
            var ret = [];
            for (var i = 0; i < o.length; i++) {
                ret.push( $.toJSON(o[i]) );
            }
            return "[" + ret.join(", ") + "]";
        }
        
        // If it's a function, we have to warn somebody!
        if (type == "function") {
            throw new TypeError("Unable to convert object of type 'function' to json.");
        }
        
        // It's probably an object, then.
        ret = [];
        for (var k in o) {
            var name;
            var type = typeof(k);
            
            if (type == "number")
                name = '"' + k + '"';
            else if (type == "string")
                name = $.quoteString(k);
            else
                continue;  //skip non-string or number keys
            
            val = $.toJSON(o[k]);
            if (typeof(val) != "string") {
                // skip non-serializable values
                continue;
            }
            
            ret.push(name + ": " + val);
        }
        return "{" + ret.join(", ") + "}";
    }
    
    $.evalJSON = function(src)
    // Evals JSON that we know to be safe.
    {
        return eval("(" + src + ")");
    }
    
    $.secureEvalJSON = function(src)
    // Evals JSON in a way that is *more* secure.
    {
        var filtered = src;
        filtered = filtered.replace(/\\["\\\/bfnrtu]/g, '@');
        filtered = filtered.replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']');
        filtered = filtered.replace(/(?:^|:|,)(?:\s*\[)+/g, '');
        
        if (/^[\],:{}\s]*$/.test(filtered))
            return eval("(" + src + ")");
        else
            throw new SyntaxError("Error parsing JSON, source is not valid.");
    }
})(jQuery);

/// Tests ///
/*

// 'console' comes from FireBug
function testJSON(o, expected) {
    try { 
        out = $.toJSON(o);
    } catch (e) { 
        if (e.name === expected.name) return;
        return console.error(e, o); }
    if (out != expected) console.error("%s != %s", out, expected);
}

testJSON('hi', "\"hi\"");
testJSON({apple: 2}, "{\"apple\": 2}");
testJSON({apple: {apple: 2}}, "{\"apple\": {\"apple\": 2}}");
testJSON(2.5, "2.5");
testJSON(25, "25");
testJSON([2, 5], "[2, 5]");
testJSON(function() {}, TypeError);
//*/


/* Copyright (c) 2006 Brandon Aaron (http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $LastChangedDate: 2007-07-22 02:44:59 +0300 (Вс, 22 июл 2007) $
 * $Rev: 2446 $
 *
 * Version 2.1.1
 */

(function($){

/**
 * The bgiframe is chainable and applies the iframe hack to get 
 * around zIndex issues in IE6. It will only apply itself in IE6 
 * and adds a class to the iframe called 'bgiframe'. The iframe
 * is appeneded as the first child of the matched element(s) 
 * with a tabIndex and zIndex of -1.
 * 
 * By default the plugin will take borders, sized with pixel units,
 * into account. If a different unit is used for the border's width,
 * then you will need to use the top and left settings as explained below.
 *
 * NOTICE: This plugin has been reported to cause perfromance problems
 * when used on elements that change properties (like width, height and
 * opacity) a lot in IE6. Most of these problems have been caused by 
 * the expressions used to calculate the elements width, height and 
 * borders. Some have reported it is due to the opacity filter. All 
 * these settings can be changed if needed as explained below.
 *
 * @example $('div').bgiframe();
 * @before <div><p>Paragraph</p></div>
 * @result <div><iframe class="bgiframe".../><p>Paragraph</p></div>
 *
 * @param Map settings Optional settings to configure the iframe.
 * @option String|Number top The iframe must be offset to the top
 * 		by the width of the top border. This should be a negative 
 *      number representing the border-top-width. If a number is 
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used. 
 * 		By default the value is "auto" which will use an expression 
 * 		to get the border-top-width if it is in pixels.
 * @option String|Number left The iframe must be offset to the left
 * 		by the width of the left border. This should be a negative 
 *      number representing the border-left-width. If a number is 
 * 		is used here, pixels will be assumed. Otherwise, be sure
 *		to specify a unit. An expression could also be used. 
 * 		By default the value is "auto" which will use an expression 
 * 		to get the border-left-width if it is in pixels.
 * @option String|Number width This is the width of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetWidth.
 * @option String|Number height This is the height of the iframe. If
 *		a number is used here, pixels will be assume. Otherwise, be sure
 * 		to specify a unit. An experssion could also be used.
 *		By default the value is "auto" which will use an experssion
 * 		to get the offsetHeight.
 * @option Boolean opacity This is a boolean representing whether or not
 * 		to use opacity. If set to true, the opacity of 0 is applied. If
 *		set to false, the opacity filter is not applied. Default: true.
 * @option String src This setting is provided so that one could change 
 *		the src of the iframe to whatever they need.
 *		Default: "javascript:false;"
 *
 * @name bgiframe
 * @type jQuery
 * @cat Plugins/bgiframe
 * @author Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 */
$.fn.bgIframe = $.fn.bgiframe = function(s) {
	// This is only for IE6
	if ( $.browser.msie && /6.0/.test(navigator.userAgent) ) {
		s = $.extend({
			top     : 'auto', // auto == .currentStyle.borderTopWidth
			left    : 'auto', // auto == .currentStyle.borderLeftWidth
			width   : 'auto', // auto == offsetWidth
			height  : 'auto', // auto == offsetHeight
			opacity : true,
			src     : 'javascript:false;'
		}, s || {});
		var prop = function(n){return n&&n.constructor==Number?n+'px':n;},
		    html = '<iframe class="bgiframe"frameborder="0"tabindex="-1"src="'+s.src+'"'+
		               'style="display:block;position:absolute;z-index:-1;'+
			               (s.opacity !== false?'filter:Alpha(Opacity=\'0\');':'')+
					       'top:'+(s.top=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderTopWidth)||0)*-1)+\'px\')':prop(s.top))+';'+
					       'left:'+(s.left=='auto'?'expression(((parseInt(this.parentNode.currentStyle.borderLeftWidth)||0)*-1)+\'px\')':prop(s.left))+';'+
					       'width:'+(s.width=='auto'?'expression(this.parentNode.offsetWidth+\'px\')':prop(s.width))+';'+
					       'height:'+(s.height=='auto'?'expression(this.parentNode.offsetHeight+\'px\')':prop(s.height))+';'+
					'"/>';
		return this.each(function() {
			if ( $('> iframe.bgiframe', this).length == 0 )
				this.insertBefore( document.createElement(html), this.firstChild );
		});
	}
	return this;
};

})(jQuery);

/**
 * Ajax Queue Plugin
 * 
 * Homepage: http://jquery.com/plugins/project/ajaxqueue
 * Documentation: http://docs.jquery.com/AjaxQueue
 */

/**

<script>
$(function(){
	jQuery.ajaxQueue({
		url: "test.php",
		success: function(html){ jQuery("ul").append(html); }
	});
	jQuery.ajaxQueue({
		url: "test.php",
		success: function(html){ jQuery("ul").append(html); }
	});
	jQuery.ajaxSync({
		url: "test.php",
		success: function(html){ jQuery("ul").append("<b>"+html+"</b>"); }
	});
	jQuery.ajaxSync({
		url: "test.php",
		success: function(html){ jQuery("ul").append("<b>"+html+"</b>"); }
	});
});
</script>
<ul style="position: absolute; top: 5px; right: 5px;"></ul>

 */
/*
 * Queued Ajax requests.
 * A new Ajax request won't be started until the previous queued 
 * request has finished.
 */

/*
 * Synced Ajax requests.
 * The Ajax request will happen as soon as you call this method, but
 * the callbacks (success/error/complete) won't fire until all previous
 * synced requests have been completed.
 */


(function($) {
	
	var ajax = $.ajax;
	
	var pendingRequests = {};
	
	var synced = [];
	var syncedData = [];
	
	$.ajax = function(settings) {
		// create settings for compatibility with ajaxSetup
		settings = jQuery.extend(settings, jQuery.extend({}, jQuery.ajaxSettings, settings));
		
		var port = settings.port;
		
		switch(settings.mode) {
		case "abort": 
			if ( pendingRequests[port] ) {
				pendingRequests[port].abort();
			}
			return pendingRequests[port] = ajax.apply(this, arguments);
		case "queue": 
			var _old = settings.complete;
			settings.complete = function(){
				if ( _old )
					_old.apply( this, arguments );
				jQuery([ajax]).dequeue("ajax" + port );;
			};
		
			jQuery([ ajax ]).queue("ajax" + port, function(){
				ajax( settings );
			});
			return;
		case "sync":
			var pos = synced.length;
	
			synced[ pos ] = {
				error: settings.error,
				success: settings.success,
				complete: settings.complete,
				done: false
			};
		
			syncedData[ pos ] = {
				error: [],
				success: [],
				complete: []
			};
		
			settings.error = function(){ syncedData[ pos ].error = arguments; };
			settings.success = function(){ syncedData[ pos ].success = arguments; };
			settings.complete = function(){
				syncedData[ pos ].complete = arguments;
				synced[ pos ].done = true;
		
				if ( pos == 0 || !synced[ pos-1 ] )
					for ( var i = pos; i < synced.length && synced[i].done; i++ ) {
						if ( synced[i].error ) synced[i].error.apply( jQuery, syncedData[i].error );
						if ( synced[i].success ) synced[i].success.apply( jQuery, syncedData[i].success );
						if ( synced[i].complete ) synced[i].complete.apply( jQuery, syncedData[i].complete );
		
						synced[i] = null;
						syncedData[i] = null;
					}
			};
		}
		return ajax.apply(this, arguments);
	};
	
})(jQuery);

/*
 * jQuery mrAjax plugin 0.1
 *
 * Copyright (c) 2007 Denis Kuznetsov
 *
 */

/**
 * Custom ajax wrapper which understand our internal request/response format
 *
 * Optionally depends on metadata plugin
 *
 */

(function($){
	// main plugin method
	$.fn.mrAjax = function(options) {
		var options = typeof options == 'undefined' ? $.mrAjax.defaultOptions : $.mrAjax.getOptions(options);
		return this.each(function(){
			var eOpts = $.extend({}, options);
			if ($.metadata && $(this).metadata()) {
				if (typeof $(this).metadata().data != 'undefined') {
					eOpts = $.extend(eOpts, $(this).metadata());
				}
				else {
					eOpts.data = $.extend(eOpts.data, $(this).metadata());
				}
			}						
			if (typeof eOpts.data != 'undefined' && typeof eOpts.data[$.mrAjax.constHandler] != 'undefined' && typeof eOpts.data[$.mrAjax.constCallHandler] != 'undefined') {				
				if (eOpts.bind == 'none') {					
					$.ajax(eOpts);					
				}
				else {
					$(this).bind(eOpts.bind, {
						o: eOpts
					}, function(event){
						event.preventDefault();
						$.ajax(event.data.o);
					});
				}
			}
		});
	};

	// static call
	$.mrAjax = function(options) {
		options = typeof options == 'undefined' ? $.mrAjax.defaultOptions : $.mrAjax.getOptions(options);
		return $.ajax(options);
	};

	// default options
	$.mrAjax.defaultOptions = {
		bind: 'none',
		url: '/ajax.php',
		type: 'post',
		async: true,
		cache: false,
		timeout: 30000,
		dataType: 'json'
	};

	// extending default options
	$.mrAjax.getOptions = function(options) {
		return $.extend(
			{
				error:   $.mrAjax.error,
				success: $.mrAjax.success
			},			
			$.mrAjax.defaultOptions,
			options
		);
	};

	// ajax success handler
	$.mrAjax.success = function(data, stat) {
		if(parseInt(data.Error.Code, 10) > 0) {            
			// if we have error we just show error message and next do nothing
			$.mrAjax.error(this, data.Error.Message);
		} else {
			// looking all ClientMessages and process it
			if(typeof data.ClientMessages != 'undefined')
			{
				for(idx in data.ClientMessages) {
					if(typeof data.ClientMessages[idx].InsertionAreaID != 'undefined' && data.ClientMessages[idx].InsertionAreaID.length > 0) {
						var e = $('#' + data.ClientMessages[idx].InsertionAreaID);
						if(e.length > 0){
							switch(data.ClientMessages[idx].MessageTextType) {
								case 'PLAIN_TEXT':
									e.text(data.ClientMessages[idx].MessageBody);
									break;
								case 'HTML_TEXT':
									e.html(data.ClientMessages[idx].MessageBody);
									break;
							}
						}
					}
				}
			}
			// looking all ClientCommands and process it
			if(typeof data.ClientCommands != 'undefined')
			{
				$(data.ClientCommands).each(function(){
					switch(this.Command) {
						// perform INSERTION action
						case 'INSERTION':
							if(typeof this.InsertionAreaID != 'undefined' && this.InsertionAreaID.length > 0 && typeof this.CommandBody != 'undefined') {
								var e = $('#' + this.InsertionAreaID);
								if(e.length > 0) {
									e.html(this.CommandBody);
									$.mrAjax.autoBind($(e));
								}
							}
							break;
						// perform APPEND action
						case 'APPEND':
							if(typeof this.InsertionAreaID != 'undefined' && this.InsertionAreaID.length > 0 && typeof this.CommandBody != 'undefined') {
								var e = $('#' + this.InsertionAreaID);
								if(e.length > 0) {
									e.append($(this.CommandBody));
									$.mrAjax.autoBind(e.children(':last-child'));
								}
							}
							break;
						// perform CALLBACK action
						case 'CALLBACK':
							if(typeof this.InsertionAreaID != 'undefined' && this.InsertionAreaID.length > 0) {
								eval('var f = ' + this.InsertionAreaID);
								if(typeof f != 'undefined') {
									f(this.CommandBody);
								}
							}
							break;
						// perform REDIRECT action
						case 'REDIRECT':
							if(typeof this.CommandBody != 'undefined' && this.CommandBody.length > 0) {
								window.location.href = this.CommandBody;
							}
							break;
					}
				});
			}
		}
		if(typeof this.callback != 'undefined') {
			try {
				this.callback(stat, data);
			}
			catch (e) {
				$.mrAjax.error(this, e);
			}
		}
	};
    
    // auto binding util
    $.mrAjax.autoBind = function(root) {
        $($.mrAjax.autoBindSelector, root).bind('click', function(e){
            try {
                /**
    			 * TODO work better with mrAjax options
    			 */
                $.mrAjax({data: $(this).metadata()});                
            }   
            catch (e) {
                /**
    			 * Catches erroneous metadata
    			 * 
    			 * TODO Put somewhere exception's message
    			 */
                if(window.console) {
                    window.console.log('Exception:');
                    window.console.log(e);
                } 
                else {
                    //window.alert(e);
                }
            }                                 
        });     
    };

	// ajax request error handler
	$.mrAjax.error = function(req, err) {
		var errMsg = 'Error: ' + err;
		if(window.console && window.console.log) {
			window.console.log(errMsg);
		} else {
			//window.alert(errMsg);
		}
	};

	// constants used to identify handler and call handler
	$.mrAjax.constHandler = 'handler';
	$.mrAjax.constCallHandler = '__callHandler';
    
    // auto binding class name
    $.mrAjax.autoBindSelector = '.ajaxLink';
    
    // auto binding init
    $(function(e){
        $.mrAjax.autoBind(document);                                        
    });
})(jQuery);

/*
 * jQuery imagePosition plugin 0.1
 *
 * Copyright (c) 2007 Sergey Konyshev
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id$
 *
 */

/**
 * Repositioning image inside divs with negative margins
 *
 *
 *
 * @name imagePosition
 * @type jQuery
 * @cat Plugins/imagePosition
 * @author Sergey Konyshev
 */
(function($){
	jQuery.fn.imagePosition = function(s) {

		// return this;

		var x = 0, y = 0, capture = false, minx = 0, miny = 0;
		s = $.extend({timeout:3000}, s);

		function mousedown(ev) {
			var e = ev.data.e;
			capture = !capture;
			x = ev.clientX;
			y = ev.clientY;
			$(document).one('mouseup', {e:ev.data.e}, mouseup);
			$(document).one('mousemove', {e:ev.data.e}, mousemove);
			return false;
		}

		function mouseup(ev) {
			var e = ev.data.e;
			capture = false;
			$(document).unbind('mousemove');
			window.clearTimeout(e.get(0).timer);
			e.get(0).timer = window.setTimeout(function() { e.trigger('Drop'); }, s.timeout);
			return false;
		}

		function mousemove(ev) {
			if(!capture) return;

			var e = ev.data.e;
			e.trigger('Drag');

			dx = ev.clientX - x - parseInt(e.css('margin-left').replace(/[^0-9]+/, ''));
			x = ev.clientX;
			if(dx > 0) dx = 0;
			if(dx < minx) dx = minx;
			e.css('margin-left', dx);

			dy = ev.clientY - y - parseInt(e.css('margin-top').replace(/[^0-9]+/, ''));
			y = ev.clientY;
			if(dy > 0) dy = 0;
			if(dy < miny) dy = miny;
			e.css('margin-top', dy);

			$(document).one('mousemove', {e:e}, mousemove);
			return false;
		}

		return this.each(
			function() {
				var e = $(this);
				$(['Drag', 'Drop']).each(function(){
					if(s['on' + this]) {
						e.bind(this, s, s['on' + this]);
					}
				});
				e.css('cursor', 'move');
				e.parent().css('cursor', 'move');
				e.bind('mousedown', {e:e}, mousedown);
				minx = e.parent().width() - $('img', e).width();
				miny = e.parent().height() - $('img', e).height();
			}
		);
	};
})(jQuery);

/* initialization */
function imgMove() {
	$(function (event){
		var i = $('#photo-sidebar-user-logged img');
		if (i) {
			if ((i.width() > 204 || i.height() > 300)) {
				if ($('#photo-sidebar-user-logged a')) {
					$('#photo-sidebar-user-logged a').click(function(event) { event.preventDefault(); });
					i.mousedown(function(event) {
						$(this).css('cursor', 'move');
						$(this).parents('.s-user').next('.sidebar-user-image-hint').each(function(){
							$(this).fadeOut('fast', function() {
								$(this).remove();
							});
						});
					}).mouseup(function(event) {
						$(this).css('cursor', 'pointer');
					});
					$('#photo-sidebar-user-logged').imagePosition({
						onDrop: function(e) {
							var elm = $(e.target);
							var $this = $(this);
	
							$this.mrAjax({
								bind: 'none',
								data: {
									handler:       'AJAX_JSON_UserProfileManager',
									__callHandler: 'saveProfileImagePosition',
									marginTop:  $(this).css('margin-top'),
									marginLeft: $(this).css('margin-left')
								},
								callback: function (req, data){
								}
							});
						}
					});
				}
			}
			else {
				$('#photo-sidebar-user-logged').css({
					'margin-left': ((204 - i.width())/2) + 'px',
					'margin-top': ((300 - i.height())/2) + 'px'
				});
			}
		}
	});
};

(function($){
	imgMove();
})(jQuery);

function imgMoveDelayed() {
	setTimeout('imgMove()', 500);
}

/*
 * jQuery inplaceEdit plugin 0.1
 *
 * Copyright (c) 2007 Sergey Konyshev
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id$
 *
 */

/**
 * Can be used to toggle something (showing some elements and 
 * hiding some elements at same time by click).
 *
 * Requires metadata plugin. 
 *
 * @name moreLess
 * @type jQuery
 * @cat Plugins/inplaceEdit
 * @author Sergey Konyshev
 */
(function($){
    jQuery.fn.inplaceEdit = function(s) {
		//setting default params
		s = $.extend({debug: true}, s);
		
		//action
		function toggle(ev) {
			ev.preventDefault();
			e = $(ev.target);

			if (e.metadata().id) {
				//loading from container
				insert(ev, $('#'+e.metadata().id));
			}
			else if (e.metadata().url) {
				//loading from url
				$.ajax({
					url: e.metadata().url,
					success: function(data, status){
						insert(ev, $(data));
					},
					error: function(req, status, error){
						if (s.debug) {
							if (window.console) {
								window.console.log('Status: ' + status + '\r\nError: ' + error);
							}
							else {
								window.alert('Status: ' + status + '\r\nError: ' + error);
							}
						}
					}
				});
			}
		}
		
		function insert(ev, form) {
			// trying to create our custom events and attach callbacks if it present
            $(['Ready', 'Submit', 'Cancel']).each(function(){
                if(ev.data['on' + this]) {
                    form.bind(
						('ip' + this), 
						{e:$(ev.target),o:ev.data},
						ev.data['on' + this]
					);                                               
                }                   
            });
			
			//triggering default form handlers
			$(['submit', 'cancel']).each(function(i,val){
				$(['input','button','a']).each(function(i1,val1){
					$((val1 + '.' + val), form).bind('click', form, function(event){
						$(event.data).trigger('ip' + val.substring(0,1).toUpperCase() + val.substring(1));
					});					
				});
			});
			
			//inserting form
			if(ev.data.target) {
				$('#'+ev.data.target).append(form);
			}
			else {
				$(ev.target).after(form);
			}
			$(ev.target).trigger('ipReady');
			
			e.moreLess({bind:'none'});
		}
		
		//iterating through objects
        return this.each(function () {
            var e = $(this);
			
			// extending global settings with settings from metadata plugin if it present
			var opts = $.metadata ? $.extend(s, e.metadata()) : s;
			
			//bindig to event
			e.bind('click', opts, toggle);
        });
    };
})(jQuery);

/*
 * jQuery moreLess plugin 0.1
 *
 * Copyright (c) 2007 Denis Kuznetsov
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id$
 *
 */

/**
 * Can be used to toggle something (showing some elements and 
 * hiding some elements at same time by click).
 *
 * Requires metadata plugin. 
 *
 * @example $('a.some-class').moreLess();
 * @desc Attach to all "a" elements click handler which will look
 * into metadata and search properties with name "h" and "s" 
 * ("h" means "hide" and "s" means "show") which can be array or 
 * string with ids of some elements, something like this:
 * <a href="javascript:void(0)" class="ml-lnk {s:['usr-profile-info-more','usr-profile-info-less-lnk'],h:'usr-profile-info-more-lnk'}">More info</a>
 *
 * @name moreLess
 * @type jQuery
 * @cat Plugins/moreLess
 * @author Denis Kuznetsov (http://q-zma.com/)
 */
(function($){
    jQuery.fn.moreLess = function(s) {
		//setting default params
		var s = $.extend({bind:'none'}, s);
		
		//action handler
		function action(ev){
			toggle($(ev.target));
		};
		
		//action
		function toggle(e){
			e = $(e);
			if(!e.metadata || !(e.metadata().s || e.metadata().h)) return;
			var o = [];
			e.metadata().s instanceof Array ? o = o.concat(e.metadata().s) : (typeof e.metadata().s != 'undefined' ? o.push(e.metadata().s) : void(0));
			e.metadata().h instanceof Array ? o = o.concat(e.metadata().h) : (typeof e.metadata().h != 'undefined' ? o.push(e.metadata().h) : void(0));
			$('#' + o.join(',#')).toggle();                                                
		};
		
		//iterating through objects
        return this.each(
            function() {
                var e = $(this);
				s.bind != 'none' ? (e[s.bind])(action) : toggle(this);
            }
        );
    };
})(jQuery);

/*
 * jQuery submitOnce plugin 0.1
 *
 * Copyright (c) 2007 Sergey Konyshev
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id$
 *
 */

/**
 * Can be used to prevent repetative click on any button and hiding some controls after pressing the button
 *
 * @example $('input.some-class').ajaxSubmit();
 * @desc Attach to all submit buttons click handler
 * and disables it with loader image displaying at the right of the button.
 *
 * @name ajaxSubmit
 * @type jQuery
 * @cat Plugins/submitOnce
 * @author Sergey Konyshev
 */

(function($){
    jQuery.fn.submitOnce = function(s) {
		s = $.extend({
			image:''
		}, s);
		
		function submit(ev) {
			var e = $(ev.target);
			var elm = ev.data.e;
			elm.attr('disabled', true);
			try {
				elm.moreLess({bind:'none'});
			} 
			catch(e){
				if(window.console) {
					window.console.log('jQuery moreLess plugin required!');
				}
				else {
					window.alert('jQuery moreLess plugin required!');
				}
			}
			if(s.image.length) {
				var ldr = $('<span>&nbsp<img src="' + s.image + '" alt="Please wait&hellip;" /></span>');
				ldr.css('display', 'inline').children('img').css('vertical-align', 'middle');
				elm.after(ldr);
			}
            e.parents('form').get(0).submit();
		}
		
        return this.each(
            function() {
                var e = $(this);
				e.parents('form').bind('submit', {e:e}, submit);
				e.bind(
                    'click', 
                    {e:e},
                    function(event) {
                        event.preventDefault();
                        submit(event);                        
                    }
                );
            }
        );
    };    
})(jQuery);

/*
 * Autocomplete - jQuery plugin 1.0 Alpha
 *
 * Copyright (c) 2007 Dylan Verheul, Dan G. Switzer, Anjesh Tuladhar, Jörn Zaefferer
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id: jquery.autocomplete.js 3261 2007-09-12 12:27:28Z joern.zaefferer $
 *
 */

/**
 * Provide autocomplete for text-inputs or textareas.
 *
 * Depends on dimensions plugin's offset method for correct positioning of the select box and bgiframe plugin
 * to fix IE's problem with selects.
 *
 * @example $("#input_box").autocomplete("my_autocomplete_backend.php");
 * @before <input id="input_box" />
 * @desc Autocomplete a text-input with remote data. For small to giant datasets.
 *
 * When the user starts typing, a request is send to the specified backend ("my_autocomplete_backend.php"),
 * with a GET parameter named q that contains the current value of the input box and a paremeter "limit" with
 * the value specified for the max option.
 *
 * A value of "foo" would result in this request url: my_autocomplete_backend.php?q=foo&limit=10
 *
 * The result must return with one value on each line. The result is presented in the order
 * the backend sends it.
 *
 * @example $("#input_box").autocomplete(["Cologne", "Berlin", "Munich"]);
 * @before <input id="input_box" />
 * @desc Autcomplete a text-input with local data. For small datasets.
 *
 * @example $.getJSON("my_backend.php", function(data) {
 *   $("#input_box").autocomplete(data);
 * });
 * @before <input id="input_box" />
 * @desc Autcomplete a text-input with data received via AJAX. For small to medium sized datasets.
 *
 * @example $("#mytextarea").autocomplete(["Cologne", "Berlin", "Munich"], {
 *  multiple: true
 * });
 * @before <textarea id="mytextarea" />
 * @desc Autcomplete a textarea with local data (for small datasets). Once the user chooses one
 * value, a separator is appended (by default a comma, see multipleSeparator option) and more values
 * are autocompleted.
 *
 * @name autocomplete
 * @cat Plugins/Autocomplete
 * @type jQuery
 * @param String|Array urlOrData Pass either an URL for remote-autocompletion or an array of data for local auto-completion
 * @param Map options Optional settings
 * @option String inputClass This class will be added to the input box. Default: "ac_input"
 * @option String resultsClass The class for the UL that will contain the result items (result items are LI elements). Default: "ac_results"
 * @option String loadingClass The class for the input box while results are being fetched from the server. Default: "ac_loading"
 * @option Number minChars The minimum number of characters a user has to type before the autocompleter activates. Default: 1
 * @option Number delay The delay in milliseconds the autocompleter waits after a keystroke to activate itself. Default: 400 for remote, 10 for local
 * @option Number cacheLength The number of backend query results to store in cache. If set to 1 (the current result), no caching will happen. Do not set below 1. Default: 10
 * @option Boolean matchSubset Whether or not the autocompleter can use a cache for more specific queries. This means that all matches of "foot" are a subset of all matches for "foo". Usually this is true, and using this options decreases server load and increases performance. Only useful with cacheLength settings bigger than one, like 10. Default: true
 * @option Boolean matchCase Whether or not the comparison is case sensitive. Only important only if you use caching. Default: false
 * @option Boolean matchContains Whether or not the comparison looks inside (i.e. does "ba" match "foo bar") the search results. Only important if you use caching. Don't mix with autofill. Default: false
 * @option Booolean mustMatch If set to true, the autocompleter will only allow results that are presented by the backend. Note that illegal values result in an empty input box. Default: false
 * @option Object extraParams Extra parameters for the backend. If you were to specify { bar:4 }, the autocompleter would call my_autocomplete_backend.php?q=foo&bar=4 (assuming the input box contains "foo"). The param can be a function that is called to calculate the param before each request. Default: none
 * @option Boolean selectFirst If this is set to true, the first autocomplete value will be automatically selected on tab/return, even if it has not been handpicked by keyboard or mouse action. If there is a handpicked (highlighted) result, that result will take precedence. Default: true
 * @option Function|Boolean formatItem Provides advanced markup for an item. For each row of results, this function will be called. If false is returned, the row is skipped. Otherwise the returned value will be displayed inside an LI element in the results list. Autocompleter will provide 3 parameters: the results row, the position of the row in the list of results (starting at 1), and the number of items in the list of results. Default: none, assumes that a single row contains a single value.
 * @option Function formatResult Similar to formatResult, but provides the formatting for the value to be put into the input field. Again three arguments: Data, position (starting with one) and total number of data. Default: none, assumes either plain data to use as result or uses the same value as provided by formatItem.
 * @option Boolean multiple Whether to allow more than one autocomplted-value to enter. Default: false
 * @option String multipleSeparator Seperator to put between values when using multiple option. Default: ", "
 * @option Number width Specify a custom width for the select box. Default: width of the input element
 * @option Boolean autoFill Fill the textinput while still selecting a value, replacing the value if more is type or something else is selected. Default: false
 * @option Number max Limit the number of items in the select box. Is also send as a "limit" parameter with a remote request. Default: 10
 * @option Boolean|Function highlight Whether and how to highlight matches in the select box. Set to false to disable. Set to a function to customize. The function gets the value as the first argument and the search term as the second and must return the formatted value. Default: Wraps the search term in a <strong> element 
 * @option Boolean|String moreItems Whether or not to show the "more items" text if there are more items than are currently be displayed. Set to false to disable. Set to a string to customize the html. Default: Displays "more", surrounded with three arrows.
 * @option Boolean scroll Whether or not use experimental scroll feature
 * @option Number scrollHeight height of scrolled autocomplete control in pixels
 */

/**
 * Handle the result of a search event. Is executed when the user selects a value or a
 * programmatic search event is triggered (see search()).
 *
 * You can add and remove (using unbind("result")) this event at any time.
 *
 * @example jQuery('input#suggest').result(function(event, data, formatted) {
 *   jQuery("#result").html( !data ? "No match!" : "Selected: " + formatted);
 * });
 * @desc Bind a handler to the result event to display the selected value in a #result element.
 *    The first argument is a generic event object, in this case with type "result".
 *    The second argument refers to the selected data, which can be a plain string value or an array or object.
 *    The third argument is the formatted value that is inserted into the input field.
 *
 * @param Function handler The event handler, gets a default event object as first and
 * 		the selected list item as second argument.
 * @name result
 * @cat Plugins/Autocomplete
 * @type jQuery
 */

/**
 * Trigger a search event. See result(Function) for binding to that event.
 *
 * A search event mimics the same behaviour as when the user selects a value from
 * the list of autocomplete items. You can use it to execute anything that does something
 * with the selected value, beyond simply putting the value into the input and submitting it.
 *
 * @example jQuery('input#suggest').search();
 * @desc Triggers a search event.
 *
 * @name search
 * @cat Plugins/Autocomplete
 * @type jQuery
 */
 
/**
 * Flush (empty) the cache of matched input's autocompleters.
 *
 * @example jQuery('input#suggest').flushCache();
 *
 * @name flushCache
 * @cat Plugins/Autocomplete
 * @type jQuery
 */

/**
 * Updates the options for the current autocomplete field. This allows 
 * you to change things like the URL, max items to display, etc. If you're
 * changing the URL, be sure to remember to call the flushCache() method.
 *
 * @example jQuery('input#suggest').setOptions({
 *  max: 15
 * });
 * @desc Changes the maximum number of items to display to 15.
 *
 * @name setOptions
 * @cat Plugins/Autocomplete
 * @type jQuery
 */
 
jQuery.fn.extend({
	autocomplete: function(urlOrData, options) {
		var isUrl = typeof urlOrData == "string";
		options = jQuery.extend({}, jQuery.Autocompleter.defaults, {
			url: isUrl ? urlOrData : null,
			data: isUrl ? null : urlOrData,
			delay: isUrl ? jQuery.Autocompleter.defaults.delay : 10
		}, options);
		// if highlight is set to false, replace it with a do-nothing function
		options.highlight = options.highlight || function(value) { return value; };
		// if moreItems is false, replace it w/empty string
		options.moreItems = options.moreItems || "";
		
		return this.each(function() {
			new jQuery.Autocompleter(this, options);
		});
	},
	result: function(handler) {
		return this.bind("result", handler);
	},
	search: function(handler) {
		return this.trigger("search", [handler]);
	},
	flushCache: function() {
		return this.trigger("flushCache");
	},
	setOptions: function(options){
		return this.trigger("setOptions", [options]);
	}
});

jQuery.Autocompleter = function(input, options) {

	var KEY = {
		UP: 38,
		DOWN: 40,
		DEL: 46,
		TAB: 9,
		RETURN: 13,
		ESC: 27,
		COMMA: 188
	};

	// Create jQuery object for input element
	var $input = jQuery(input).attr("autocomplete", "off").addClass(options.inputClass);

	var timeout;
	var previousValue = "";
	var cache = jQuery.Autocompleter.Cache(options);
	var hasFocus = input.hasFocus != null && typeof input.hasFocus != 'undefined' ? input.hasFocus : 0;
	var lastKeyPressCode;
	var config = {
		mouseDownOnSelect: false
	};
	var select = jQuery.Autocompleter.Select(options, input, selectCurrent, config);
	
	$input.keydown(function(event) {        
		// track last key pressed
		lastKeyPressCode = event.keyCode;
		switch(event.keyCode) {
		
			case KEY.UP:
				event.preventDefault();
				if ( select.visible() ) {
					select.prev();
				} else {
					onChange(0, true);
				}
				break;
				
			case KEY.DOWN:
				event.preventDefault();
				if ( select.visible() ) {
					select.next();
				} else {
					onChange(0, true);
				}
				break;
			
			// matches also semicolon
			case options.multiple && jQuery.trim(options.multipleSeparator) == "," && KEY.COMMA:
			case KEY.TAB:
			case KEY.RETURN:
				if( selectCurrent() ){
					// make sure to blur off the current field
					if( !options.multiple )
						$input.blur();
					event.preventDefault();
				}
				break;
				
			case KEY.ESC:
				select.hide();
				break;
				
			default:
				clearTimeout(timeout);
				timeout = setTimeout(onChange, options.delay);
				break;
		}
	}).keypress(function() {
		// having fun with opera - remove this binding and Opera submits the form when we select an entry via return
	}).focus(function(){
		// track whether the field has focus, we shouldn't process any
		// results if the field no longer has focus
		hasFocus++;
	}).blur(function() {
		hasFocus = 0;
		if (!config.mouseDownOnSelect) {
			hideResults();
		}
	}).click(function() {
		// show select when clicking in a focused field
		if ( hasFocus++ > 1 && !select.visible() ) {
			onChange(0, true);
		}
	}).bind("search", function() {
		var fn = (arguments.length > 1) ? arguments[1] : null;
		function findValueCallback(q, data) {
			var result;
			if( data && data.length ) {
				for (var i=0; i < data.length; i++) {
					if( data[i].result.toLowerCase() == q.toLowerCase() ) {
						result = data[i];
						break;
					}
				}
			}
			if( typeof fn == "function" ) fn(result);
			else $input.trigger("result", result && [result.data, result.value]);
		}
		jQuery.each(trimWords($input.val()), function(i, value) {
			request(value, findValueCallback, findValueCallback);
		});
	}).bind("flushCache", function() {
		cache.flush();
	}).bind("setOptions", function() {
		jQuery.extend(options, arguments[1]);
		// if we've updated the data, repopulate
		if ( "data" in arguments[1] )
			cache.populate();
	});
	
	hideResultsNow();
	
	function selectCurrent() {
		var selected = select.selected();
		if( !selected )
			return false;
		
		var v = selected.result;
		previousValue = v;
		
		if ( options.multiple ) {
			var words = trimWords($input.val());
			if ( words.length > 1 ) {
				v = words.slice(0, words.length - 1).join( options.multipleSeparator ) + options.multipleSeparator + v;
			}
			v += options.multipleSeparator;
		}
		
		$input.val(v);
		hideResultsNow();
		$input.trigger("result", [selected.data, selected.value]);
        $input.focus();
		return true;
	}
	
	function onChange(crap, skipPrevCheck) {
		if( lastKeyPressCode == KEY.DEL ) {
			select.hide();
			return;
		}
		
		var currentValue = $input.val();
		
		if ( !skipPrevCheck && currentValue == previousValue )
			return;
		
		previousValue = currentValue;
		
		currentValue = lastWord(currentValue);
		if ( currentValue.length >= options.minChars) {
			$input.addClass(options.loadingClass);
			if (!options.matchCase)
				currentValue = currentValue.toLowerCase();
			request(currentValue, receiveData, hideResultsNow);
		} else {
			stopLoading();
			select.hide();
		}
	};
	
	function trimWords(value) {
		if ( !value ) {
			return [""];
		}
		var words = value.split( jQuery.trim( options.multipleSeparator ) );
		var result = [];
		jQuery.each(words, function(i, value) {
			if ( jQuery.trim(value) )
				result[i] = jQuery.trim(value);
		});
		return result;
	}
	
	function lastWord(value) {
		if ( !options.multiple )
			return value;
		var words = trimWords(value);
		return words[words.length - 1];
	}
	
	// fills in the input box w/the first match (assumed to be the best match)
	function autoFill(q, sValue){
		// autofill in the complete box w/the first match as long as the user hasn't entered in more data
		// if the last user key pressed was backspace, don't autofill
		if( options.autoFill && (lastWord($input.val()).toLowerCase() == q.toLowerCase()) && lastKeyPressCode != 8 ) {
			// fill in the value (keep the case the user has typed)
			$input.val($input.val() + sValue.substring(lastWord(previousValue).length));
			// select the portion of the value not typed by the user (so the next character will erase)
			jQuery.Autocompleter.Selection(input, previousValue.length, previousValue.length + sValue.length);
		}
	};

	function hideResults() {
		clearTimeout(timeout);
		timeout = setTimeout(hideResultsNow, 200);
	};

	function hideResultsNow() {
		select.hide();
		clearTimeout(timeout);
		stopLoading();
		if (options.mustMatch) {
			// call search and run callback
			$input.search(
				function (result){
					// if no value found, clear the input box
					if( !result ) $input.val("");
				}
			);
		}
	};

	function receiveData(q, data) {
		if ( data && data.length && hasFocus ) {
			stopLoading();
			select.display(data, q);
			autoFill(q, data[0].value);
			select.show();
		} else {
			hideResultsNow();
		}
	};

	function request(term, success, failure) {
		if (!options.matchCase)
			term = term.toLowerCase();
		var data = cache.load(term);
		// recieve the cached data
		if (data && data.length) {
			success(term, data);
		// if an AJAX url has been supplied, try loading the data now
		} else if( (typeof options.url == "string") && (options.url.length > 0) ){
			
			var extraParams = {};
			jQuery.each(options.extraParams, function(key, param) {
				extraParams[key] = typeof param == "function" ? param() : param;
			});
			
			jQuery.ajax({
				// try to leverage ajaxQueue plugin to abort previous requests
				mode: "abort",
				// limit abortion to this input
				port: "autocomplete" + input.name,
				url: options.url,
				data: jQuery.extend({
					q: lastWord(term),
					limit: options.max
				}, extraParams),
				success: function(data) {
					var parsed = options.parse && options.parse(data) || parse(data);
					cache.add(term, parsed);
					success(term, parsed);
				}
			});
		} else {
			failure(term);
		}
	};
	
	function parse(data) {
		var parsed = [];
		var rows = data.split("\n");
		for (var i=0; i < rows.length; i++) {
			var row = jQuery.trim(rows[i]);
			if (row) {
				row = row.split("|");
				parsed[parsed.length] = {
					data: row,
					value: row[0],
					result: options.formatResult && options.formatResult(row, row[0]) || row[0]
				};
			}
		}
		return parsed;
	};

	function stopLoading() {
		$input.removeClass(options.loadingClass);
	};

};

jQuery.Autocompleter.defaults = {
	inputClass: "ac_input",
	resultsClass: "ac_results",
	loadingClass: "ac_loading",
	minChars: 1,
	delay: 400,
	matchCase: false,
	matchSubset: true,
	matchContains: false,
	cacheLength: 10,
	mustMatch: false,
	extraParams: {},
	selectFirst: true,
	max: 10,
	moreItems: "&#x25be;&#x25be;&#x25be; more &#x25be;&#x25be;&#x25be;",
	//size: 10,
	autoFill: false,
	width: 0,
	multiple: false,
	multipleSeparator: ", ",
	highlight: function(value, term) {
		return value.replace(new RegExp("(?!<[^<>]*)(" + term + ")(?![^<>]*>)", "gi"), "<strong>$1</strong>");
	},
    scroll: false,
    scrollHeight: 100
};

jQuery.Autocompleter.Cache = function(options) {

	var data = {};
	var length = 0;
	
	function matchSubset(s, sub) {
		if (!options.matchCase) 
			s = s.toLowerCase();
		var i = s.indexOf(sub);
		if (i == -1) return false;
		return i == 0 || options.matchContains;
	};
	
	function add(q, value) {
		if (length > options.cacheLength){
			flush();
		}
		if (!data[q]){ 
			length++;
		}
		data[q] = value;
	}
	
	function populate(){
		if( !options.data ) return false;
		// track the matches
		var stMatchSets = {},
			nullData = 0;

		// no url was specified, we need to adjust the cache length to make sure it fits the local data store
		if( !options.url ) options.cacheLength = 1;
		
		// track all options for minChars = 0
		stMatchSets[""] = [];
		
		// loop through the array and create a lookup structure
		jQuery.each(options.data, function(i, rawValue) {
			// if row is a string, make an array otherwise just reference the array
			
			var value = options.formatItem
				? options.formatItem(rawValue, i+1, options.data.length)
				: rawValue;
			if ( value === false )
				return;
				
			var firstChar = value.charAt(0).toLowerCase();
			// if no lookup array for this character exists, look it up now
			if( !stMatchSets[firstChar] ) 
				stMatchSets[firstChar] = [];

			// if the match is a string
			var row = {
				value: value,
				data: rawValue,
				result: options.formatResult && options.formatResult(rawValue) || value
			};
			
			// push the current match into the set list
			stMatchSets[firstChar].push(row);

			// keep track of minChars zero items
			if ( nullData++ < options.max ) {
				stMatchSets[""].push(row);
			}
		});

		// add the data items to the cache
		jQuery.each(stMatchSets, function(i, value) {
			// increase the cache size
			options.cacheLength++;
			// add to the cache
			add(i, value);
		});
	}
	
	// populate any existing data
	populate();
	
	function flush(){
		data = {};
		length = 0;
	}
	
	return {
		flush: flush,
		add: add,
		populate: populate,
		load: function(q) {
			if (!options.cacheLength || !length)
				return null;
			/* 
			 * if dealing w/local data and matchContains than we must make sure
			 * to loop through all the data collections looking for matches
			 */
			if( !options.url && options.matchContains ){
				// track all matches
				var csub = [];
				// loop through all the data grids for matches
				for( var k in data ){
					// don't search through the stMatchSets[""] (minChars: 0) cache
					// this prevents duplicates
					if( k.length > 0 ){
						var c = data[k];
						jQuery.each(c, function(i, x) {
							// if we've got a match, add it to the array
							if (matchSubset(x.value, q)) {
								csub.push(x);
							}
						});
					}
				}				
				return csub;
			} else 
			// if the exact item exists, use it
			if (data[q]){
				return data[q];
			} else
			if (options.matchSubset) {
				for (var i = q.length - 1; i >= options.minChars; i--) {
					var c = data[q.substr(0, i)];
					if (c) {
						var csub = [];
						jQuery.each(c, function(i, x) {
							if (matchSubset(x.value, q)) {
								csub[csub.length] = x;
							}
						});
						return csub;
					}
				}
			}
			return null;
		}
	};
};

jQuery.Autocompleter.Select = function (options, input, select, config) {
	var CLASSES = {
		ACTIVE: "ac_over"
	};
	
	// Create results
	var element = jQuery("<div>")
		.hide()
		.addClass(options.resultsClass)
		.css("position", "absolute")
		.appendTo("body");
	
	var list = jQuery("<ul>").appendTo(element).mouseover( function(event) {
        if(target(event).nodeName && target(event).nodeName.toUpperCase() == 'LI')
        {
            active = jQuery("li", list).removeClass().index(target(event));
		    jQuery(target(event)).addClass(CLASSES.ACTIVE);            
        }
	}).mouseout( function(event) {
        // why we must to do that? is it really needed ?
        /*jQuery(target(event)).removeClass();*/
        return;
	}).click(function(event) {
		jQuery(target(event)).addClass(CLASSES.ACTIVE);
		select();
		input.focus();
		return false;
	}).mousedown(function() {
		config.mouseDownOnSelect = true;
	}).mouseup(function() {
		config.mouseDownOnSelect = false;
	});
	var listItems,
		active = -1,
		data,
		term = "";
		
	if( options.moreItems.length > 0 ) 
		var moreItems = jQuery("<div>")
			.addClass("ac_moreItems")
			.css("display", "none")
			.html(options.moreItems)
			.appendTo(element);
		
	if( options.width > 0 )
		element.css("width", options.width);
		
	function target(event) {
		var element = event.target;
		while(element && element.tagName != "LI")
			element = element.parentNode;
		// more fun with IE, sometimes event.target is empty, just ignore it then
		if(!element)
			return [];
		return element;
	}

	function moveSelect(step) {
        var paItem = listItems.slice(active, active + 1);
        paItem.removeClass();
		active += step;
		wrapSelection();
        var aItem = listItems.slice(active, active + 1);
        aItem.addClass(CLASSES.ACTIVE);
        if(options.scroll) {
            // looks like that variant is more simple, but it works more slow in IE :(
            /* var aItemOffset = aItem.offset().top - list.offset().top + list.scrollTop(); */
            var aItemOffset = 0;
            listItems.slice(0, active).each(
                function() {
                    aItemOffset += this.offsetHeight;
                }
            );
            if((aItemOffset + aItem[0].offsetHeight - list.scrollTop()) > list[0].clientHeight) {
                list.scrollTop(aItemOffset + aItem[0].offsetHeight - list.innerHeight());
            }
            else if(aItemOffset < list.scrollTop()) {
                list.scrollTop(aItemOffset);
            }
        }
	};
	
	function wrapSelection() {
		if (active < 0) {
			active = listItems.size() - 1;
		} else if (active >= listItems.size()) {
			active = 0;
		}
	}
	
	function limitNumberOfItems(available) {
		return (options.max > 0) && (options.max < available) && !options.scroll
			? options.max
			: available;
        return available;
	}
	
	function fillList() {
		list.empty();
		var num = limitNumberOfItems(data.length);
		for (var i=0; i < num; i++) {
			if (!data[i])
				continue;
			
			var formatted = options.formatItem ? options.formatItem(data[i].data, i+1, num, data[i].value) : data[i].value;
			if ( formatted === false )
				continue;
			
			jQuery("<li>").html( options.highlight(formatted, term) ).appendTo(list)[0].index = i;
		}
		listItems = list.find("li");
		if ( options.selectFirst ) {
			listItems.slice(0, 1).addClass(CLASSES.ACTIVE);
			active = 0;
		}
		if( options.moreItems.length > 0 && !options.scroll) moreItems.css("display", (data.length > num)? "block" : "none");
		list.bgiframe();
	}
	
	return {
		display: function(d, q) {
			data = d;
			term = q;
			fillList();
		},
		next: function() {
			moveSelect(1);
		},
		prev: function() {
			moveSelect(-1);
		},
		hide: function() {
			element.hide();
			active = -1;
		},
		visible : function() {
			return element.is(":visible");
		},
		current: function() {
			return this.visible() && (listItems.filter("." + CLASSES.ACTIVE)[0] || options.selectFirst && listItems[0]);
		},
		show: function() {
			var offset = jQuery(input).offset();
			element.css
            (
                {
    				width: typeof options.width == "string" || options.width > 0 ? options.width : jQuery(input).width(),
    				top: offset.top + input.offsetHeight,
    				left: offset.left
			    }
            ).show();
            if(options.scroll) {
                list.scrollTop(0);
                list.css( { 'max-height': (options.scrollHeight + 'px'), 'overflow':   'auto' } );
                if(jQuery.browser.msie && typeof document.body.style.maxHeight === "undefined" && list.height() > options.scrollHeight)
                {
                    list.css('height', (options.scrollHeight + 'px'));                    
                }
            }
		},
		selected: function() {
            if(listItems)
            {
                var filteredItems = listItems.filter("." + CLASSES.ACTIVE);
                if(filteredItems.length > 0)
                {
                    return data && data[ filteredItems[0].index ];                
                }
    			else
                {
                    return false;
                }                
            }
            else
            {
                return false;
            }
		}
	};
};

jQuery.Autocompleter.Selection = function(field, start, end) {
	if( field.createTextRange ){
		var selRange = field.createTextRange();
		selRange.collapse(true);
		selRange.moveStart("character", start);
		selRange.moveEnd("character", end);
		selRange.select();
	} else if( field.setSelectionRange ){
		field.setSelectionRange(start, end);
	} else {
		if( field.selectionStart ){
			field.selectionStart = start;
			field.selectionEnd = end;
		}
	}
	field.focus();
};

/**
 * Copyright (c) 2007 Kelvin Luck (http://www.kelvinluck.com/)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php) 
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 *
 * $Id: jquery.datePicker.js 2036 2007-06-05 22:55:15Z kelvin.luck $
 **/

(function($){
    
	$.fn.extend({
/**
 * Render a calendar table into any matched elements.
 * 
 * @param Object s (optional) Customize your calendars.
 * @option Number month The month to render (NOTE that months are zero based). Default is today's month.
 * @option Number year The year to render. Default is today's year.
 * @option Function renderCallback A reference to a function that is called as each cell is rendered and which can add classes and event listeners to the created nodes. Default is no callback.
 * @option Number showHeader Whether or not to show the header row, possible values are: $.dpConst.SHOW_HEADER_NONE (no header), $.dpConst.SHOW_HEADER_SHORT (first letter of each day) and $.dpConst.SHOW_HEADER_LONG (full name of each day). Default is $.dpConst.SHOW_HEADER_SHORT.
 * @option String hoverClass The class to attach to each cell when you hover over it (to allow you to use hover effects in IE6 which doesn't support the :hover pseudo-class on elements other than links). Default is dp-hover. Pass false if you don't want a hover class.
 * @type jQuery
 * @name renderCalendar
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('#calendar-me').renderCalendar({month:0, year:2007});
 * @desc Renders a calendar displaying January 2007 into the element with an id of calendar-me.
 *
 * @example
 * var testCallback = function($td, thisDate, month, year)
 * {
 * if ($td.is('.current-month') && thisDate.getDay() == 4) {
 *		var d = thisDate.getDate();
 *		$td.bind(
 *			'click',
 *			function()
 *			{
 *				alert('You clicked on ' + d + '/' + (Number(month)+1) + '/' + year);
 *			}
 *		).addClass('thursday');
 *	} else if (thisDate.getDay() == 5) {
 *		$td.html('Friday the ' + $td.html() + 'th');
 *	}
 * }
 * $('#calendar-me').renderCalendar({month:0, year:2007, renderCallback:testCallback});
 * 
 * @desc Renders a calendar displaying January 2007 into the element with an id of calendar-me. Every Thursday in the current month has a class of "thursday" applied to it, is clickable and shows an alert when clicked. Every Friday on the calendar has the number inside replaced with text.
 **/
		renderCalendar  :   function(s)
		{
			var dc = function(a)
			{
				return document.createElement(a);
			};
			
			s = $.extend(
				{
					month			: null,
					year			: null,
					renderCallback	: null,
					showHeader		: $.dpConst.SHOW_HEADER_SHORT,
					dpController	: null,
					hoverClass		: 'dp-hover'
				}
				, s
			);
			
			if (s.showHeader != $.dpConst.SHOW_HEADER_NONE) {
				var headRow = $(dc('tr'));
				for (var i=Date.firstDayOfWeek; i<Date.firstDayOfWeek+7; i++) {
					var weekday = i%7;
					var day = Date.dayNames[weekday];
					headRow.append(
						jQuery(dc('th')).attr({'scope':'col', 'abbr':day, 'title':day, 'class':(weekday == 0 || weekday == 6 ? 'weekend' : 'weekday')}).html(s.showHeader == $.dpConst.SHOW_HEADER_SHORT ? day.substr(0, 1) : day)
					);
				}
			};
			
			var calendarTable = $(dc('table'))
									.attr(
										{
											'cellspacing':2,
											'className':'jCalendar'
										}
									)
									.append(
										(s.showHeader != $.dpConst.SHOW_HEADER_NONE ? 
											$(dc('thead'))
												.append(headRow)
											:
											dc('thead')
										)
									);
			var tbody = $(dc('tbody'));
			
			var today = (new Date()).zeroTime();
			
			var month = s.month == undefined ? today.getMonth() : s.month;
			var year = s.year || today.getFullYear();
			
			var currentDate = new Date(year, month, 1);
			
			
			var firstDayOffset = Date.firstDayOfWeek - currentDate.getDay() + 1;
			if (firstDayOffset > 1) firstDayOffset -= 7;
			currentDate.addDays(firstDayOffset-1);
			
			var doHover = function()
			{
				if (s.hoverClass) {
					$(this).addClass(s.hoverClass);
				}
			};
			var unHover = function()
			{
				if (s.hoverClass) {
					$(this).removeClass(s.hoverClass);
				}
			};
			
			var w = 0;
			while (w++<6) {
				var r = jQuery(dc('tr'));
				for (var i=0; i<7; i++) {
					var thisMonth = currentDate.getMonth() == month;
					var d = $(dc('td'))
								.text(currentDate.getDate() + '')
								.attr('className', (thisMonth ? 'current-month ' : 'other-month ') +
													(currentDate.isWeekend() ? 'weekend ' : 'weekday ') +
													(thisMonth && currentDate.getTime() == today.getTime() ? 'today ' : '')
								)
								.hover(doHover, unHover)
							;
					if (s.renderCallback) {
						s.renderCallback(d, currentDate, month, year);
					}
					r.append(d);
					currentDate.addDays(1);
				}
				tbody.append(r);
			}
			calendarTable.append(tbody);
			
			return this.each(
				function()
				{
					$(this).empty().append(calendarTable);
				}
			);
		},
/**
 * Create a datePicker associated with each of the matched elements.
 *
 * The matched element will receive a few custom events with the following signatures:
 *
 * dateSelected(event, date, $td, status)
 * Triggered when a date is selected. event is a reference to the event, date is the Date selected, $td is a jquery object wrapped around the TD that was clicked on and status is whether the date was selected (true) or deselected (false)
 * 
 * dpClosed(event, selected)
 * Triggered when the date picker is closed. event is a reference to the event and selected is an Array containing Date objects.
 *
 * dpMonthChanged(event, displayedMonth, displayedYear)
 * Triggered when the month of the popped up calendar is changed. event is a reference to the event, displayedMonth is the number of the month now displayed (zero based) and displayedYear is the year of the month.
 *
 * dpDisplayed(event, $datePickerDiv)
 * Triggered when the date picker is created. $datePickerDiv is the div containing the date picker. Use this event to add custom content/ listeners to the popped up date picker.
 *
 * @param Object s (optional) Customize your date pickers.
 * @option Number month The month to render when the date picker is opened (NOTE that months are zero based). Default is today's month.
 * @option Number year The year to render when the date picker is opened. Default is today's year.
 * @option Date startDate The first date date can be selected.
 * @option Date endDate The last date that can be selected.
 * @option Boolean createButton Whether to create a .dp-choose-date anchor directly after the matched element which when clicked will trigger the showing of the date picker. Default is true.
 * @option Boolean showYearNavigation Whether to display buttons which allow the user to navigate through the months a year at a time. Default is true.
 * @option Boolean closeOnSelect Whether to close the date picker when a date is selected. Default is true.
 * @option Boolean displayClose Whether to create a "Close" button within the date picker popup. Default is false.
 * @option Boolean selectMultiple Whether a user should be able to select multiple dates with this date picker. Default is false.
 * @option Boolean clickInput If the matched element is an input type="text" and this option is true then clicking on the input will cause the date picker to appear.
 * @option Number verticalPosition The vertical alignment of the popped up date picker to the matched element. One of $.dpConst.POS_TOP and $.dpConst.POS_BOTTOM. Default is $.dpConst.POS_TOP.
 * @option Number horizontalPosition The horizontal alignment of the popped up date picker to the matched element. One of $.dpConst.POS_LEFT and $.dpConst.POS_RIGHT.
 * @option Number verticalOffset The number of pixels offset from the defined verticalPosition of this date picker that it should pop up in. Default in 0.
 * @option Number horizontalOffset The number of pixels offset from the defined horizontalPosition of this date picker that it should pop up in. Default in 0.
 * @option (Function|Array) renderCallback A reference to a function (or an array of seperate functions) that is called as each cell is rendered and which can add classes and event listeners to the created nodes. Each callback function will receive four arguments; a jquery object wrapping the created TD, a Date object containing the date this TD represents, a number giving the currently rendered month and a number giving the currently rendered year. Default is no callback.
 * @option String hoverClass The class to attach to each cell when you hover over it (to allow you to use hover effects in IE6 which doesn't support the :hover pseudo-class on elements other than links). Default is dp-hover. Pass false if you don't want a hover class.
 * @type jQuery
 * @name datePicker
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('input.date-picker').datePicker();
 * @desc Creates a date picker button next to all matched input elements. When the button is clicked on the value of the selected date will be placed in the corresponding input (formatted according to Date.format).
 *
 * @example demo/index.html
 * @desc See the projects homepage for many more complex examples...
 **/
		datePicker : function(s)
		{			
			if (!$.event._dpCache) $.event._dpCache = [];
			
			// initialise the date picker controller with the relevant settings...
			s = $.extend(
				{
					month				: undefined,
					year				: undefined,
					startDate			: undefined,
					endDate				: undefined,
					renderCallback		: [],
					createButton		: true,
					showYearNavigation	: true,
					closeOnSelect		: true,
					displayClose		: false,
					selectMultiple		: false,
					clickInput			: false,
					verticalPosition	: $.dpConst.POS_TOP,
					horizontalPosition	: $.dpConst.POS_LEFT,
					verticalOffset		: 0,
					horizontalOffset	: 0,
					hoverClass			: 'dp-hover'
				}
				, s
			);
			
			return this.each(
				function()
				{
					var $this = $(this);
					
					if (!this._dpId) {
						this._dpId = $.event.guid++;
						$.event._dpCache[this._dpId] = new DatePicker(this);
					}
					
					var controller = $.event._dpCache[this._dpId];
					
					controller.init(s);
					
					if (s.createButton) {
						// create it!
						//controller.button = $('<a href="#" class="dp-choose-date" title="' + $.dpText.TEXT_CHOOSE_DATE + '">' + $.dpText.TEXT_CHOOSE_DATE + '</a>')
                        controller.button = $('<a href="#" class="dp-choose-date" title="' + $.dpText.TEXT_CHOOSE_DATE + '"><img src="/i/b.gif" width="16" height="16" alt="' + $.dpText.TEXT_CHOOSE_DATE + '" /></a>')
								.bind(
									'click',
									function()
									{
										$this.dpDisplay(this);
										this.blur();
										return false;
									}
								);
						$this.after(controller.button);
					}
					
					if ($this.is(':text')) {
						$this
							.bind(
								'dateSelected',
								function(e, selectedDate, $td)
								{
									this.value = selectedDate.asString();
								}
							).bind(
								'change',
								function()
								{
									var d = Date.fromString(this.value);
									if (d) {
										controller.setSelected(d, true, true);
									}
								}
							);
						if (s.clickInput) {
							$this.bind(
								'click',
								function()
								{
									$this.dpDisplay();
								}
							);
						}
					}
					
					$this.addClass('dp-applied');
					
				}
			)
		},
/**
 * Disables or enables this date picker
 *
 * @param Boolean s Whether to disable (true) or enable (false) this datePicker
 * @type jQuery
 * @name dpSetDisabled
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('.date-picker').datePicker();
 * $('.date-picker').dpSetDisabled(true);
 * @desc Prevents this date picker from displaying and adds a class of dp-disabled to it (and it's associated button if it has one) for styling purposes. If the matched element is an input field then it will also set the disabled attribute to stop people directly editing the field.
 **/
		dpSetDisabled : function(s)
		{
			return _w.call(this, 'setDisabled', s);
		},
/**
 * Updates the first selectable date for any date pickers on any matched elements.
 *
 * @param String d A string representing the first selectable date (formatted according to Date.format).
 * @type jQuery
 * @name dpSetStartDate
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('.date-picker').datePicker();
 * $('.date-picker').dpSetStartDate('01/01/2000');
 * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the first selectable date for each of these to the first day of the millenium.
 **/
		dpSetStartDate : function(d)
		{
			return _w.call(this, 'setStartDate', d);
		},
/**
 * Updates the last selectable date for any date pickers on any matched elements.
 *
 * @param String d A string representing the last selectable date (formatted according to Date.format).
 * @type jQuery
 * @name dpSetEndDate
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('.date-picker').datePicker();
 * $('.date-picker').dpSetEndDate('01/01/2010');
 * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the last selectable date for each of these to the first Janurary 2010.
 **/
		dpSetEndDate : function(d)
		{
			return _w.call(this, 'setEndDate', d);
		},
/**
 * Gets a list of Dates currently selected by this datePicker. This will be an empty array if no dates are currently selected or NULL if there is no datePicker associated with the matched element.
 *
 * @type Array
 * @name dpGetSelected
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('.date-picker').datePicker();
 * alert($('.date-picker').dpGetSelected());
 * @desc Will alert an empty array (as nothing is selected yet)
 **/
		dpGetSelected : function()
		{
			var c = _getController(this[0]);
			if (c) {
				return c.getSelected();
			}
			return null;
		},
/**
 * Selects or deselects a date on any matched element's date pickers. Deselcting is only useful on date pickers where selectMultiple==true. Selecting will only work if the passed date is within the startDate and endDate boundries for a given date picker.
 *
 * @param String d A string representing the date you want to select (formatted according to Date.format).
 * @param Boolean v Whether you want to select (true) or deselect (false) this date. Optional - default = true.
 * @param Boolean m Whether you want the date picker to open up on the month of this date when it is next opened. Optional - default = true.
 * @type jQuery
 * @name dpSetSelected
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('.date-picker').datePicker();
 * $('.date-picker').dpSetSelected('01/01/2010');
 * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the selected date on these date pickers to the first Janurary 2010. When the date picker is next opened it will display Janurary 2010.
 **/
		dpSetSelected : function(d, v, m)
		{
			if (v == undefined) v=true;
			if (m == undefined) m=true;
			return _w.call(this, 'setSelected', Date.fromString(d), v, m);
		},
/**
 * Sets the month that will be displayed when the date picker is next opened. If the passed month is before startDate then the month containing startDate will be displayed instead. If the passed month is after endDate then the month containing the endDate will be displayed instead.
 *
 * @param Number m The month you want the date picker to display. Optional - defaults to the currently displayed month.
 * @param Number y The year you want the date picker to display. Optional - defaults to the currently displayed year.
 * @type jQuery
 * @name dpSetDisplayedMonth
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('.date-picker').datePicker();
 * $('.date-picker').dpSetDisplayedMonth(10, 2008);
 * @desc Creates a date picker associated with all elements with a class of "date-picker" then sets the selected date on these date pickers to the first Janurary 2010. When the date picker is next opened it will display Janurary 2010.
 **/
		dpSetDisplayedMonth : function(m, y)
		{
			return _w.call(this, 'setDisplayedMonth', Number(m), Number(y));
		},
/**
 * Displays the date picker associated with the matched elements. Since only one date picker can be displayed at once then the date picker associated with the last matched element will be the one that is displayed.
 *
 * @param HTMLElement e An element that you want the date picker to pop up relative in position to. Optional - default behaviour is to pop up next to the element associated with this date picker.
 * @type jQuery
 * @name dpDisplay
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('#date-picker').datePicker();
 * $('#date-picker').dpDisplay();
 * @desc Creates a date picker associated with the element with an id of date-picker and then causes it to pop up.
 **/
		dpDisplay : function(e)
		{
			return _w.call(this, 'display', e);
		},
/**
 * Sets a function or array of functions that is called when each TD of the date picker popup is rendered to the page
 *
 * @param (Function|Array) a A function or an array of functions that are called when each td is rendered. Each function will receive four arguments; a jquery object wrapping the created TD, a Date object containing the date this TD represents, a number giving the currently rendered month and a number giving the currently rendered year.
 * @type jQuery
 * @name dpSetRenderCallback
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('#date-picker').datePicker();
 * $('#date-picker').dpSetRenderCallback(function($td, thisDate, month, year)
 * {
 * 	// do stuff as each td is rendered dependant on the date in the td and the displayed month and year
 * });
 * @desc Creates a date picker associated with the element with an id of date-picker and then creates a function which is called as each td is rendered when this date picker is displayed.
 **/
		dpSetRenderCallback : function(a)
		{
			return _w.call(this, 'setRenderCallback', a);
		},
/**
 * Sets the position that the datePicker will pop up (relative to it's associated element)
 *
 * @param Number v The vertical alignment of the created date picker to it's associated element. Possible values are $.dpConst.POS_TOP and $.dpConst.POS_BOTTOM
 * @param Number h The horizontal alignment of the created date picker to it's associated element. Possible values are $.dpConst.POS_LEFT and $.dpConst.POS_RIGHT
 * @type jQuery
 * @name dpSetPosition
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('#date-picker').datePicker();
 * $('#date-picker').dpSetPosition($.dpConst.POS_BOTTOM, $.dpConst.POS_RIGHT);
 * @desc Creates a date picker associated with the element with an id of date-picker and makes it so that when this date picker pops up it will be bottom and right aligned to the #date-picker element.
 **/
		dpSetPosition : function(v, h)
		{
			return _w.call(this, 'setPosition', v, h);
		},
/**
 * Sets the offset that the popped up date picker will have from it's default position relative to it's associated element (as set by dpSetPosition)
 *
 * @param Number v The vertical offset of the created date picker.
 * @param Number h The horizontal offset of the created date picker.
 * @type jQuery
 * @name dpSetOffset
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('#date-picker').datePicker();
 * $('#date-picker').dpSetOffset(-20, 200);
 * @desc Creates a date picker associated with the element with an id of date-picker and makes it so that when this date picker pops up it will be 20 pixels above and 200 pixels to the right of it's default position.
 **/
		dpSetOffset : function(v, h)
		{
			return _w.call(this, 'setOffset', v, h);
		},
		// private function called on unload to clean up any expandos etc and prevent memory links...
		_dpDestroy : function()
		{
			// TODO - implement this?
		}
	});
	
	// private internal function to cut down on the amount of code needed where we forward
	// dp* methods on the jQuery object on to the relevant DatePicker controllers...
	var _w = function(f, a1, a2, a3)
	{
		return this.each(
			function()
			{
				var c = _getController(this);
				if (c) {
					c[f](a1, a2, a3);
				}
			}
		);
	};
	
	function DatePicker(ele)
	{
		this.ele = ele;
		
		// initial values...
		this.displayedMonth		=	null;
		this.displayedYear		=	null;
		this.startDate			=	null;
		this.endDate			=	null;
		this.showYearNavigation	=	null;
		this.closeOnSelect		=	null;
		this.displayClose		=	null;
		this.selectMultiple		=	null;
		this.verticalPosition	=	null;
		this.horizontalPosition	=	null;
		this.verticalOffset		=	null;
		this.horizontalOffset	=	null;
		this.button				=	null;
		this.renderCallback		=	[];
		this.selectedDates		=	{};
	};
	$.extend(
		DatePicker.prototype,
		{	
			init : function(s)
			{
				this.setStartDate(s.startDate);
				this.setEndDate(s.endDate);
				this.setDisplayedMonth(Number(s.month), Number(s.year));
				this.setRenderCallback(s.renderCallback);
				this.showYearNavigation = s.showYearNavigation;
				this.closeOnSelect = s.closeOnSelect;
				this.displayClose = s.displayClose;
				this.selectMultiple = s.selectMultiple;
				this.verticalPosition = s.verticalPosition;
				this.horizontalPosition = s.horizontalPosition;
				this.hoverClass = s.hoverClass;
				this.setOffset(s.verticalOffset, s.horizontalOffset);
			},
			setStartDate : function(d)
			{
				if (d) {
					this.startDate = Date.fromString(d);
				}
				if (!this.startDate) {
					this.startDate = (new Date()).zeroTime();
				}
				this.setDisplayedMonth(this.displayedMonth, this.displayedYear);
			},
			setEndDate : function(d)
			{
				if (d) {
					this.endDate = Date.fromString(d);
				}
				if (!this.endDate) {
					this.endDate = (new Date('12/31/2999')); // using the JS Date.parse function which expects mm/dd/yyyy
				}
				if (this.endDate.getTime() < this.startDate.getTime()) {
					this.endDate = this.startDate;
				}
				this.setDisplayedMonth(this.displayedMonth, this.displayedYear);
			},
			setPosition : function(v, h)
			{
				this.verticalPosition = v;
				this.horizontalPosition = h;
			},
			setOffset : function(v, h)
			{
				this.verticalOffset = parseInt(v) || 0;
				this.horizontalOffset = parseInt(h) || 0;
			},
			setDisabled : function(s)
			{
				$e = $(this.ele);
				$e[s ? 'addClass' : 'removeClass']('dp-disabled');
				if (this.button) {
					$but = $(this.button);
					$but[s ? 'addClass' : 'removeClass']('dp-disabled');
					$but.attr('title', s ? '' : $.dpText.TEXT_CHOOSE_DATE);
				}
				if ($e.is(':text')) {
					$e.attr('disabled', s ? 'disabled' : '');
				}
			},
			setDisplayedMonth : function(m, y)
			{
				if (this.startDate == undefined || this.endDate == undefined) {
					return;
				}
				var s = new Date(this.startDate.getTime());
				s.setDate(1);
				var e = new Date(this.endDate.getTime());
				e.setDate(1);
				
				var t;
				
				if (isNaN(m) && isNaN(y)) {
					// no month or year passed - default to current month
					t = new Date().zeroTime();
					t.setDate(1);
				} else if (isNaN(m)) {
					// just year passed in - presume we want the displayedMonth
					t = new Date(y, this.displayedMonth, 1);
				} else if (isNaN(y)) {
					// just month passed in - presume we want the displayedYear
					t = new Date(this.displayedYear, m, 1);
				} else {
					// year and month passed in - that's the date we want!
					t = new Date(y, m, 1)
				}
				
				// check if the desired date is within the range of our defined startDate and endDate
				if (t.getTime() < s.getTime()) {
					t = s;
				} else if (t.getTime() > e.getTime()) {
					t = e;
				}
				this.displayedMonth = t.getMonth();
				this.displayedYear = t.getFullYear();
			},
			setSelected : function(d, v, moveToMonth)
			{
				if (this.selectMultiple == false) {
					this.selectedDates = {};
				}
				if (moveToMonth) {
					this.setDisplayedMonth(d.getMonth(), d.getFullYear());
				}
				this.selectedDates[d.getTime()] = v;
			},
			isSelected : function(t)
			{
				return this.selectedDates[t];
			},
			getSelected : function()
			{
				var r = [];
				for(t in this.selectedDates) {
					if (this.selectedDates[t] == true) {
						r.push(new Date(Number(t)));
					}
				}
				return r;
			},
			display : function(eleAlignTo)
			{
				if ($(this.ele).is('.dp-disabled')) return;
				
				eleAlignTo = eleAlignTo || this.ele;
				var c = this;
				var $ele = $(eleAlignTo);
				var eleOffset = $ele.offset();
				
				
				var _checkMouse = function(e)
				{
					var el = e.target;
					var cal = $('#dp-popup')[0];
					while (true){
						if (el == cal) {
							return true;
						} else if (el == document) {
							c._closeCalendar();
							return false;
						} else {
							el = $(el).parent()[0];
						}
					}
				};
				this._checkMouse = _checkMouse;
				
				this._closeCalendar(true);
				
				$('body')
					.append(
						$('<div></div>')
							.attr('id', 'dp-popup')
							.css(
								{
									'top'	:	eleOffset.top + c.verticalOffset,
									'left'	:	eleOffset.left + c.horizontalOffset
								}
							)
							.append(
								$('<h2></h2>'),
								$('<div id="dp-nav-prev"></div>')
									.append(
										$('<a id="dp-nav-prev-year" href="#" title="' + $.dpText.TEXT_PREV_YEAR + '">&lt;&lt;</a>')
											.bind(
												'click',
												function()
												{
													return c._displayNewMonth.call(c, this, 0, -1);
												}
											),
										$('<a id="dp-nav-prev-month" href="#" title="' + $.dpText.TEXT_PREV_MONTH + '">&lt;</a>')
											.bind(
												'click',
												function()
												{
													return c._displayNewMonth.call(c, this, -1, 0);
												}
											)
									),
								$('<div id="dp-nav-next"></div>')
									.append(
										$('<a id="dp-nav-next-year" href="#" title="' + $.dpText.TEXT_NEXT_YEAR + '">&gt;&gt;</a>')
											.bind(
												'click',
												function()
												{
													return c._displayNewMonth.call(c, this, 0, 1);
												}
											),
										$('<a id="dp-nav-next-month" href="#" title="' + $.dpText.TEXT_NEXT_MONTH + '">&gt;</a>')
											.bind(
												'click',
												function()
												{
													return c._displayNewMonth.call(c, this, 1, 0);
												}
											)
									),
								$('<div></div>')
									.attr('id', 'dp-calendar')
							)
							.bgIframe()
						);
					
				var $pop = $('#dp-popup');
				
				if (this.showYearNavigation == false) {
					$('#dp-nav-prev-year, #dp-nav-next-year').css('display', 'none');
				}
				if (this.displayClose) {
					$pop.append(
						$('<a href="#" id="dp-close">' + $.dpText.TEXT_CLOSE + '</a>')
							.bind(
								'click',
								function()
								{
									c._closeCalendar();
									return false;
								}
							)
					);
				}
				c._renderCalendar();
				
				if (this.verticalPosition == $.dpConst.POS_BOTTOM) {
					$pop.css('top', eleOffset.top + $ele.height() - $pop.height() + c.verticalOffset);
				}
				if (this.horizontalPosition == $.dpConst.POS_RIGHT) {
					$pop.css('left', eleOffset.left + $ele.width() - $pop.width() + c.horizontalOffset);
				}
				
				$(this.ele).trigger('dpDisplayed', $pop);
				
				$(document).bind('mousedown', this._checkMouse);
			},
			setRenderCallback : function(a)
			{
				if (a && typeof(a) == 'function') {
					a = [a];
				}
				this.renderCallback = this.renderCallback.concat(a);
			},
			cellRender : function ($td, thisDate, month, year) {
				var c = this.dpController;
				var d = new Date(thisDate.getTime());
				
				// add our click handlers to deal with it when the days are clicked...
				
				$td.bind(
					'click',
					function()
					{
						var $this = $(this);
						if (!$this.is('.disabled')) {
							c.setSelected(d, !$this.is('.selected') || !c.selectMultiple);
							var s = c.isSelected(d.getTime());
							$(c.ele).trigger('dateSelected', [d, $td, s]);
							if (c.closeOnSelect) {
								c._closeCalendar();
							} else {
								$this[s ? 'addClass' : 'removeClass']('selected');
							}
						}
					}
				);
				
				if (c.isSelected(d.getTime())) {
					$td.addClass('selected');
				}
				
				// call any extra renderCallbacks that were passed in
				for (var i=0; i<c.renderCallback.length; i++) {
					c.renderCallback[i].apply(this, arguments);
				}
				
				
			},
			// ele is the clicked button - only proceed if it doesn't have the class disabled...
			// m and y are -1, 0 or 1 depending which direction we want to go in...
			_displayNewMonth : function(ele, m, y) 
			{
				if (!$(ele).is('.disabled')) {
					this.setDisplayedMonth(this.displayedMonth + m, this.displayedYear + y);
					this._clearCalendar();
					this._renderCalendar();
					$(this.ele).trigger('dpMonthChanged', [this.displayedMonth, this.displayedYear]);
				}
				ele.blur();
				return false;
			},
			_renderCalendar : function()
			{
				// set the title...
				$('#dp-popup h2').html(Date.monthNames[this.displayedMonth] + ' ' + this.displayedYear);
				
				// render the calendar...
				$('#dp-calendar').renderCalendar(
					{
						month			: this.displayedMonth,
						year			: this.displayedYear,
						renderCallback	: this.cellRender,
						dpController	: this,
						hoverClass		: this.hoverClass
					}
				);
				
				// update the status of the control buttons and disable dates before startDate or after endDate...
				// TODO: When should the year buttons be disabled? When you can't go forward a whole year from where you are or is that annoying?
				if (this.displayedYear == this.startDate.getFullYear() && this.displayedMonth == this.startDate.getMonth()) {
					$('#dp-nav-prev-year').addClass('disabled');
					$('#dp-nav-prev-month').addClass('disabled');
					$('#dp-calendar td.other-month').each(
						function()
						{
							var $this = $(this);
							if (Number($this.text()) > 20) {
								$this.addClass('disabled');
							}
						}
					);
					var d = this.startDate.getDate();
					$('#dp-calendar td.current-month').each(
						function()
						{
							var $this = $(this);
							if (Number($this.text()) < d) {
								$this.addClass('disabled');
							}
						}
					);
				} else {
					$('#dp-nav-prev-year').removeClass('disabled');
					$('#dp-nav-prev-month').removeClass('disabled');
					var d = this.startDate.getDate();
					if (d > 20) {
						// check if the startDate is last month as we might need to add some disabled classes...
						var sd = new Date(this.startDate.getTime());
						sd.addMonths(1);
						if (this.displayedYear == sd.getFullYear() && this.displayedMonth == sd.getMonth()) {
							$('#dp-calendar td.other-month').each(
								function()
								{
									var $this = $(this);
									if (Number($this.text()) < d) {
										$this.addClass('disabled');
									}
								}
							);
						}
					}
				}
				if (this.displayedYear == this.endDate.getFullYear() && this.displayedMonth == this.endDate.getMonth()) {
					$('#dp-nav-next-year').addClass('disabled');
					$('#dp-nav-next-month').addClass('disabled');
					$('#dp-calendar td.other-month').each(
						function()
						{
							var $this = $(this);
							if (Number($this.text()) < 14) {
								$this.addClass('disabled');
							}
						}
					);
					var d = this.endDate.getDate();
					$('#dp-calendar td.current-month').each(
						function()
						{
							var $this = $(this);
							if (Number($this.text()) > d) {
								$this.addClass('disabled');
							}
						}
					);
				} else {
					$('#dp-nav-next-year').removeClass('disabled');
					$('#dp-nav-next-month').removeClass('disabled');
					var d = this.endDate.getDate();
					if (d < 13) {
						// check if the endDate is next month as we might need to add some disabled classes...
						var ed = new Date(this.endDate.getTime());
						ed.addMonths(-1);
						if (this.displayedYear == ed.getFullYear() && this.displayedMonth == ed.getMonth()) {
							$('#dp-calendar td.other-month').each(
								function()
								{
									var $this = $(this);
									if (Number($this.text()) > d) {
										$this.addClass('disabled');
									}
								}
							);
						}
					}
				}
			},
			_closeCalendar : function(programatic)
			{
				$(document).unbind('mousedown', this._checkMouse);
				this._clearCalendar();
				$('#dp-popup a').unbind();
				$('#dp-popup').empty().remove();
				if (!programatic) {
					$(this.ele).trigger('dpClosed', [this.getSelected()]);
				}
			},
			// empties the current dp-calendar div and makes sure that all events are unbound
			// and expandos removed to avoid memory leaks...
			_clearCalendar : function()
			{
				// TODO.
				$('#dp-calendar td').unbind();
				$('#dp-calendar').empty();
			}
		}
	);
	
	// static constants
	$.dpConst = {
		SHOW_HEADER_NONE	:	0,
		SHOW_HEADER_SHORT	:	1,
		SHOW_HEADER_LONG	:	2,
		POS_TOP				:	0,
		POS_BOTTOM			:	1,
		POS_LEFT			:	0,
		POS_RIGHT			:	1
	};
	// localisable text
	$.dpText = {
		TEXT_PREV_YEAR		:	'Previous year',
		TEXT_PREV_MONTH		:	'Previous month',
		TEXT_NEXT_YEAR		:	'Next year',
		TEXT_NEXT_MONTH		:	'Next month',
		TEXT_CLOSE			:	'Close',
		TEXT_CHOOSE_DATE	:	'Choose date'
	};
	// version
	$.dpVersion = '$Id: jquery.datePicker.js 2036 2007-06-05 22:55:15Z kelvin.luck $';

	function _getController(ele)
	{
		if (ele._dpId) return $.event._dpCache[ele._dpId];
		return false;
	};
	
	// make it so that no error is thrown if bgIframe plugin isn't included (allows you to use conditional
	// comments to only include bgIframe where it is needed in IE without breaking this plugin).
	if ($.fn.bgIframe == undefined) {
		$.fn.bgIframe = function() {return this; };
	};


	// clean-up
	$(window)
		.bind('unload', function() {
			var els = $.event._dpCache || [];
			for (var i in els) {
				$(els[i].ele)._dpDestroy();
			}
		});
		
	
})(jQuery);

/*
 * jQuery defInput plugin 0.1
 *
 * Copyright (c) 2007 Dmitry Pavlov
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id$
 *
 */

/**
 * Can be used to put default text to form inputs, which won't be sent to server
 *
 * Requires metadata plugin. 
 *
 * @example <input class="def-val {text: 'Please input something...'}">
 *
 * @name definput
 * @type jQuery
 * @cat Plugins/definput
 * @author Dmitry Pavlov (dmitry@dev.mrise.ru)
 */

var definp = {
	init: function () {
		jQuery('.def-val').each(function () { 
			var e = jQuery(this);
			var text = e.metadata().text;
			if (e.val() === '') {
				e.addClass('def-val-color');
				e.val(text);
			} else {
				e.removeClass('def-val-color');
			}
		}).focus(function () {
			var e = jQuery(this);
			var text = e.metadata().text;
			if (e.val() == text) {
				e.val(''); 
				e.removeClass('def-val-color');
			}			
		}).blur(function (a) {
			var e = jQuery(this);
			var text = e.metadata().text;
			if (e.val() === '') {
				e.addClass('def-val-color');
				e.val(text);
			} else {
				e.removeClass('def-val-color');
			}
		});		
		jQuery('form:has(.def-val)').submit(function () {
			jQuery('.def-val', this).each(function () {
				var e = jQuery(this);
				var text = e.metadata().text;
				if (e.val() == text) {
					e.val(''); 
				}
			});
		});
	}
};

$(document).ready(function(){
	definp.init();
});

/*
 * SYL image lister jQuery extension 0.1
 *
 * Copyright (c) 2007 Denis Kuznetsov
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 */
(function($){
    
    // main function
	$.sylImageLister = function(options) {
		options = typeof options == 'undefined' ? $.sylImageLister.defaultOptions : $.sylImageLister.getOptions(options);
		$('#' + options.tapeOptions.id).each(function () {             
			var eOpts = $.extend({callback: $.sylImageLister.success},options);
			if ($.metadata && $(this).metadata()) { eOpts = $.extend(eOpts, $(this).metadata()); }
            this.options = eOpts;
            $.mrAjax(eOpts);
        });
    };
    
    // success handler
    $.sylImageLister.success = function(stat, data) {        
        var $e = $('#' + this.tapeOptions.id);        
        var e = $e.get(0);        
        var o = e.options;        
        o.res = data.Response;
		var res = o.res;
        var prevLnk = $('a.tape-prevPhoto', e);
        var nextLnk = $('a.tape-nextPhoto', e);
        var tape = [];

        /*get current id in array*/
        var currentPictureId = 0;
        for(i = 0; i < res.length; i++) {
        	if (res[i].id == o.data.currentPictureId) {
        		currentPictureId = i;
        		break; 
        	}
        }
        
        if (res.length <= o.tapeOptions.length) {
            var sId = 0;
            var eId = res.length - 1;
        }
        else {
			var afterOffset, beforeOffset;
            if (o.tapeOptions.length % 2 > 0) {
                afterOffset = Math.floor(o.tapeOptions.length / 2);
				beforeOffset = afterOffset;  
            } else {
                beforeOffset = o.tapeOptions.length / 2 - 1;
                afterOffset = o.tapeOptions.length / 2;
            }
            if(currentPictureId >= (res.length - afterOffset)) {
                sId = res.length - o.tapeOptions.length;
                eId = res.length - 1;
            } 
            else if(currentPictureId < beforeOffset) {
                sId = 0;
                eId = o.tapeOptions.length - 1;
            }
            else {
                sId = currentPictureId - beforeOffset;
                eId = currentPictureId + afterOffset;
            }
        }
        
 		for(i = sId; i <= eId; i++) {
            tape[tape.length] = $('<a href="' + res[i].moveUrl + '" id="' + this.tapeOptions.id + '_' + i + '" class="tape-item img-loading"></a>');
            var tmpImg = $('<img src="' + res[i].url + '" width="' + res[i].width + '" height="' + res[i].height + '" alt="' + res[i].alt + '" title="'+ res[i].alt +'" />');
            if(i == currentPictureId) {
                tape[tape.length-1].addClass('tape-item-current').click(function(event) { event.preventDefault(); });
            }
            tape[tape.length-1].append(tmpImg);
            tmpImg.css('visibility', 'hidden').load($.sylImageLister.imageLoaded);
        }        
        $('img.loader', e).remove();                            
        $(tape).each(function(){                
            this.insertBefore(nextLnk);            
        });
        if(res.length > o.tapeOptions.length) {
            if(currentPictureId >= beforeOffset) {
                prevLnk.removeClass('tape-prevPhoto-disabled').one('click', $.sylImageLister.moveTape);
            } else {
                prevLnk.addClass('tape-prevPhoto-disabled').click(function(event) { 
					event.preventDefault(); 
				});
            }        
            if(currentPictureId < (res.length - 1 - afterOffset)) {
                nextLnk.removeClass('tape-nextPhoto-disabled').one('click', $.sylImageLister.moveTape);
            } else {
                nextLnk.addClass('tape-nextPhoto-disabled').click(function(event) { 
					event.preventDefault(); 
				});
            }                        
        } else {
           prevLnk.addClass('tape-prevPhoto-disabled').click(function(event) { event.preventDefault(); } );
           nextLnk.addClass('tape-nextPhoto-disabled').click(function(event) { event.preventDefault(); } );
        }
        return;
    };
    
    // move tape click
    $.sylImageLister.moveTape = function(event) {
        event.preventDefault();        
        var e = $(event.target);
        var tape = e.parent().get(0);
        var $tape = $(tape);
        var o = tape.options; 
        var thumbs = $('a[id^="user-gallery-tape_"]', tape);
        var firstThumb = $(thumbs.get(0));
        var lastThumb = $(thumbs.get(thumbs.length - 1));
        var prevLnk = $('a.tape-prevPhoto', tape);
        var nextLnk = $('a.tape-nextPhoto', tape); 
        var res = e.parent().get(0).res;
        var step = e.is('.tape-prevPhoto') ? 'prev' : (e.is('.tape-nextPhoto') ? 'next' : 'unknown');
		var id, firstId, lastId;
        if(step == 'next') {
            id = parseInt(lastThumb.attr('id').replace('user-gallery-tape_', ''), 10);
            firstId = parseInt(firstThumb.attr('id').replace('user-gallery-tape_', ''), 10);
            if(id < o.res.length - 1) {
                $([prevLnk, nextLnk]).each(function(){
                   this.unbind(); 
                });
                firstThumb.unbind();
                firstThumb.fadeOut('fast', function() {
                    $(this).remove();
                    var newPicLnk = $('<a href="' + o.res[id+1].moveUrl + '" id="' + $tape.attr('id') + '_' + (id + 1) + '" class="tape-item img-loading"></a>');
                    lastThumb.after(newPicLnk);
                    var newPic = $('<img src="' + o.res[id+1].url + '" width="' + o.res[id+1].width + '" height="' + o.res[id+1].height + '" alt="' + o.res[id+1].alt + '" title="' + o.res[id+1].alt + '" />');
                    if((o.res[id + 1].id) == o.data.currentPictureId) {
                        newPicLnk.addClass('tape-item-current').click(function(event) { event.preventDefault(); });
                    }
                    newPicLnk.append(newPic);
                    newPic.css('visibility', 'hidden').load($.sylImageLister.imageLoaded);
                    if ((id + 1) < (o.res.length - 1)) {                        
                        nextLnk.removeClass('tape-nextPhoto-disabled').one('click', $.sylImageLister.moveTape);
                    } else {                        
                        nextLnk.addClass('tape-nextPhoto-disabled').click(function(event) { event.preventDefault(); });
                    }
                    if((firstId + 1) > 0) {
                        prevLnk.removeClass('tape-prevPhoto-disabled').one('click', $.sylImageLister.moveTape);
                    } else {
                        prevLnk.addClass('tape-prevPhoto-disabled').click(function(event) { event.preventDefault(); });
                    }                                                                                              
                });
            }
        } else if (step == 'prev') {
            id = parseInt(firstThumb.attr('id').replace('user-gallery-tape_', ''), 10);
            lastId = parseInt(lastThumb.attr('id').replace('user-gallery-tape_', ''), 10);
            if(id > 0) {
                $([prevLnk, nextLnk]).each(function(){
                   this.unbind(); 
                });
                lastThumb.unbind();
                lastThumb.fadeOut('fast', function() {
                    $(this).remove();
                    var newPicLnk = $('<a href="' + o.res[id - 1].moveUrl + '" id="' + $tape.attr('id') + '_' + (id - 1) + '" class="tape-item img-loading"></a>');
                    firstThumb.before(newPicLnk);
                    var newPic = $('<img src="' + o.res[id - 1].url + '" width="' + o.res[id - 1].width + '" height="' + o.res[id - 1].height + '" alt="' + o.res[id - 1].alt + '" title="' + o.res[id - 1].alt + '" />');
                    if((o.res[id - 1].id) == o.data.currentPictureId) {
                        newPicLnk.addClass('tape-item-current').click(function(event) { event.preventDefault(); });
                    }
                    newPicLnk.append(newPic);
                    newPic.css('visibility', 'hidden').load($.sylImageLister.imageLoaded);
                    if ((id - 1) === 0) {                        
                        prevLnk.addClass('tape-prevPhoto-disabled').click(function(event) { event.preventDefault(); });
                    } else {                        
                        prevLnk.removeClass('tape-prevPhoto-disabled').one('click', $.sylImageLister.moveTape);
                    }
                    if ((id - 1) < (o.res.length - 1)) {
                        nextLnk.removeClass('tape-nextPhoto-disabled').one('click', $.sylImageLister.moveTape);
                    } else {
                        nextLnk.addClass('tape-nextPhoto-disabled').click(function(event) { event.preventDefault(); });
                    }                                                      
                });
            }
        } else {
            return;
        }
    };
    
    // image loaded
    $.sylImageLister.imageLoaded = function(event) {
        $(this).parent().removeClass('img-loading');
        $(this).css('visibility', 'visible').css('opacity', 1);
        $(this).fadeTo('fast', 1);
    };
    
    // default options
    $.sylImageLister.defaultOptions = {
        tapeOptions: {
            id: 'user-gallery-tape',
            dynamicLength: false,
            length: 5
        }
    };
    
    // extending options
    $.sylImageLister.getOptions = function(options) {
        return $.extend(
            $.sylImageLister.defaultOptions, 
            options
        );
    };
    
    $(function(){
        jQuery.sylImageLister();
    });
    
})(jQuery);

(function($){
	$(function (event) {
		var $sn = $('#signed-nav');
		if ($sn.length > 0) {			
			var sn = $sn.get(0);
			$sn.find('ul>li').each(function () {
				var cn = $(this).attr('class');
				if (typeof cn != 'undefined') {
					this.prevClassName = cn;	
				}				
			});
			$('.usertab')
				.bind('mouseover', sn, function (event) {
					event.preventDefault();												
					var t = this, $t = $(t), sn = event.data, $i = $t.parents('li'), i = $i.get(0), $m = $t.next('.submenu-wrap'), m = $m.get(0);
					if (typeof m.timer != 'undefined') {
						window.clearTimeout(m.timer);
					}
					if (typeof this.timer != 'undefined') {
						window.clearTimeout(this.timer);
					}				
					if ($m.is(':hidden')) {
						$i.addClass('active');
						$m.show();
						$m.unbind()
							.bind('mouseout', function (event) {
								var that = $(this);
								this.timer = window.setTimeout(function () {
									var l = that.prev('.usertab').parents('li');
									if (typeof l.get(0).prevClassName == 'undefined') {
										l.removeAttr('class');
									}
									else {
										l.attr('class', l.get(0).prevClassName);	
									}
									that.hide();
								}, 100);
							})
							.bind('mouseover', function (event) {
						  		window.clearTimeout(this.timer);
							});
					}
				})
				.bind('mouseout', function (event) {
					var that = $(this).next('.submenu-wrap');  
					that.get(0).timer = window.setTimeout(function () {
						var l = that.prev('.usertab').parents('li');
						if (typeof l.get(0).prevClassName == 'undefined') {
							l.removeAttr('class');
						}
						else {
							l.attr('class', l.get(0).prevClassName);	
						}
						that.hide();
					}, 100);
				});
		}
	});
})(jQuery);

/*
 * SYL form hints jQuery extension
 *
 * Copyright (c) 2007 Sergey Nepyivoda
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Revision: $Id$
 *
 */

(function($){
	$(function(event){
		var $uL = $('#usersList');
		var $uLgrp = $('#usersListGrp');
		if($uL.length > 0 || $uLgrp.lenght > 0) {
			var uL = $uL.get(0);
			var uLgrp = $uLgrp.get(0);
			var uArr = Array (uL, uLgrp);
			$('div.git-lnk a.drop-down', uArr).bind('click', uArr, function(event){
				event.preventDefault();
				event.stopPropagation();
				var l = this;
				var $l = $(this);
				var uL = event.data;
				var $uL = $(uL); 
				$('div.git', uL).each(function(){
					var vm = $('div.git-block:visible', this);
					if(vm.length > 0) {
						$(document).trigger('click');
					}
				});
				var $gb = $l.parent().nextAll('div.git-block');
				$l.blur();
				$gb.show();


				// for ie
				if($.browser.msie) {
					var gbw = $gb.width();
					$gb.find('div.bot-t').width(gbw-1);
					$gb.find('div.bot-m').width(gbw-1);
					$gb.find('div.bot-b').width(gbw-4);
				}

				$(document).one('click', $gb, function(event) {
					var $gb = event.data;
					$gb.hide();
				});
			});
		}
	});
	$(function(event){
		var $uL = $('#lang');
		if($uL.length > 0) {
			var uL = $uL.get(0);
			$('div.git-lnk a.drop-down', uL).bind('click', uL, function(event){
				event.preventDefault();
				event.stopPropagation();
				var l = this;
				var $l = $(this);
				var uL = event.data;
				var $uL = $(uL); 
				$('div.git', uL).each(function(){
					var vm = $('div.git-block:visible', this);
					if(vm.length > 0) {
						$(document).trigger('click');
					}
				});
				var $gb = $l.parent().nextAll('div.git-block');
				$l.blur();
				$gb.show();

				$(document).one('click', $gb, function(event) {
					var $gb = event.data;
					$gb.hide();
				});
			});
		}
	});
})(jQuery);

/*
 * jQuery UI @VERSION
 *
 * Copyright (c) 2008 Paul Bakaus (ui.jquery.com)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI
 *
 * $Date: 2008-04-01 16:23:47 +0300 (Вт, 01 апр 2008) $
 * $Rev: 5174 $
 */
;(function($) {

	//If the UI scope is not available, add it
	$.ui = $.ui || {};
	
	//Add methods that are vital for all mouse interaction stuff (plugin registering)
	$.extend($.ui, {
		plugin: {
			add: function(module, option, set) {
				var proto = $.ui[module].prototype;
				for(var i in set) {
					proto.plugins[i] = proto.plugins[i] || [];
					proto.plugins[i].push([option, set[i]]);
				}
			},
			call: function(instance, name, arguments) {
				var set = instance.plugins[name]; if(!set) return;
				for (var i = 0; i < set.length; i++) {
					if (instance.options[set[i][0]]) set[i][1].apply(instance.element, arguments);
				}
			}	
		},
		cssCache: {},
		css: function(name) {
			if ($.ui.cssCache[name]) return $.ui.cssCache[name];
			var tmp = $('<div class="ui-resizable-gen">').addClass(name).css({position:'absolute', top:'-5000px', left:'-5000px', display:'block'}).appendTo('body');
			
			//if (!$.browser.safari)
				//tmp.appendTo('body'); 
			
			//Opera and Safari set width and height to 0px instead of auto
			//Safari returns rgba(0,0,0,0) when bgcolor is not set
			$.ui.cssCache[name] = !!(
				(!/auto|default/.test(tmp.css('cursor')) || (/^[1-9]/).test(tmp.css('height')) || (/^[1-9]/).test(tmp.css('width')) || 
				!(/none/).test(tmp.css('backgroundImage')) || !(/transparent|rgba\(0, 0, 0, 0\)/).test(tmp.css('backgroundColor')))
			);
			try { $('body').get(0).removeChild(tmp.get(0));	} catch(e){}
			return $.ui.cssCache[name];
		},
		disableSelection: function(e) {
			e.unselectable = "on";
			e.onselectstart = function() {	return false; };
			if (e.style) e.style.MozUserSelect = "none";
		},
		enableSelection: function(e) {
			e.unselectable = "off";
			e.onselectstart = function() { return true; };
			if (e.style) e.style.MozUserSelect = "";
		},
		hasScroll: function(e, a) {
      		var scroll = /top/.test(a||"top") ? 'scrollTop' : 'scrollLeft', has = false;
      		if (e[scroll] > 0) return true; e[scroll] = 1;
      		has = e[scroll] > 0 ? true : false; e[scroll] = 0;
      		return has; 
    	}
	});

	/******* fn scope modifications ********/

	$.each( ['Left', 'Top'], function(i, name) {
		if(!$.fn['scroll'+name]) $.fn['scroll'+name] = function(v) {
			return v != undefined ?
				this.each(function() { this == window || this == document ? window.scrollTo(name == 'Left' ? v : $(window)['scrollLeft'](), name == 'Top'  ? v : $(window)['scrollTop']()) : this['scroll'+name] = v; }) :
				this[0] == window || this[0] == document ? self[(name == 'Left' ? 'pageXOffset' : 'pageYOffset')] || $.boxModel && document.documentElement['scroll'+name] || document.body['scroll'+name] : this[0][ 'scroll' + name ];
		};
	});

	var _remove = $.fn.remove;
	$.fn.extend({
		position: function() {
			var offset       = this.offset();
			var offsetParent = this.offsetParent();
			var parentOffset = offsetParent.offset();

			return {
				top:  offset.top - num(this[0], 'marginTop')  - parentOffset.top - num(offsetParent, 'borderTopWidth'),
				left: offset.left - num(this[0], 'marginLeft')  - parentOffset.left - num(offsetParent, 'borderLeftWidth')
			};
		},
		offsetParent: function() {
			var offsetParent = this[0].offsetParent;
			while ( offsetParent && (!/^body|html$/i.test(offsetParent.tagName) && $.css(offsetParent, 'position') == 'static') )
				offsetParent = offsetParent.offsetParent;
			return $(offsetParent);
		},
		mouseInteraction: function(o) {
			return this.each(function() {
				new $.ui.mouseInteraction(this, o);
			});
		},
		removeMouseInteraction: function(o) {
			return this.each(function() {
				if($.data(this, "ui-mouse"))
					$.data(this, "ui-mouse").destroy();
			});
		},
		remove: function() {
			jQuery("*", this).add(this).trigger("remove");
			return _remove.apply(this, arguments );
		}
	});
	
	function num(el, prop) {
		return parseInt($.curCSS(el.jquery?el[0]:el,prop,true))||0;
	};
	
	
	/********** Mouse Interaction Plugin *********/
	
	$.ui.mouseInteraction = function(element, options) {
	
		var self = this;
		this.element = element;

		$.data(this.element, "ui-mouse", this);
		this.options = $.extend({}, options);
		
		$(element).bind('mousedown.draggable', function() { return self.click.apply(self, arguments); });
		if($.browser.msie) $(element).attr('unselectable', 'on'); //Prevent text selection in IE
		
		// prevent draggable-options-delay bug #2553
		$(element).mouseup(function() {
			if(self.timer) clearInterval(self.timer);
		});
	};
	
	$.extend($.ui.mouseInteraction.prototype, {
		
		destroy: function() { $(this.element).unbind('mousedown.draggable'); },
		trigger: function() { return this.click.apply(this, arguments); },
		click: function(e) {
			
			if(
				   e.which != 1 //only left click starts dragging
				|| $.inArray(e.target.nodeName.toLowerCase(), this.options.dragPrevention || []) != -1 // Prevent execution on defined elements
				|| (this.options.condition && !this.options.condition.apply(this.options.executor || this, [e, this.element])) //Prevent execution on condition
			) return true;
				
			var self = this;
			var initialize = function() {
				self._MP = { left: e.pageX, top: e.pageY }; // Store the click mouse position
				$(document).bind('mouseup.draggable', function() { return self.stop.apply(self, arguments); });
				$(document).bind('mousemove.draggable', function() { return self.drag.apply(self, arguments); });
				
				if(!self.initalized && Math.abs(self._MP.left-e.pageX) >= self.options.distance || Math.abs(self._MP.top-e.pageY) >= self.options.distance) {				
					if(self.options.start) self.options.start.call(self.options.executor || self, e, self.element);
					if(self.options.drag) self.options.drag.call(self.options.executor || self, e, this.element); //This is actually not correct, but expected
					self.initialized = true;
				}
			};

			if(this.options.delay) {
				if(this.timer) clearInterval(this.timer);
				this.timer = setTimeout(initialize, this.options.delay);
			} else {
				initialize();
			}
				
			return false;
			
		},
		stop: function(e) {			
			
			var o = this.options;
			if(!this.initialized) return $(document).unbind('mouseup.draggable').unbind('mousemove.draggable');

			if(this.options.stop) this.options.stop.call(this.options.executor || this, e, this.element);
			$(document).unbind('mouseup.draggable').unbind('mousemove.draggable');
			this.initialized = false;
			return false;
			
		},
		drag: function(e) {

			var o = this.options;
			if ($.browser.msie && !e.button) return this.stop.apply(this, [e]); // IE mouseup check
			
			if(!this.initialized && (Math.abs(this._MP.left-e.pageX) >= o.distance || Math.abs(this._MP.top-e.pageY) >= o.distance)) {				
				if(this.options.start) this.options.start.call(this.options.executor || this, e, this.element);
				this.initialized = true;
			} else {
				if(!this.initialized) return false;
			}

			if(o.drag) o.drag.call(this.options.executor || this, e, this.element);
			return false;
			
		}
	});
	
})(jQuery);
 

/*
 * jQuery UI Resizable
 *
 * Copyright (c) 2008 Paul Bakaus
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 * 
 * http://docs.jquery.com/UI/Resizables
 *
 * Depends:
 *   ui.base.js
 *
 * Revision: $Id: ui.resizable.js 5187 2008-04-03 16:58:37Z braeker $
 */
;(function($) {
	
	$.fn.extend({
		resizable: function(options, data) {
			var args = Array.prototype.slice.call(arguments, 1);
			
			return this.each(function() {
				if (typeof options == "string") {
					var resize = $.data(this, "resizable");
					if (resize) resize[options].apply(resize, args);
	
				} else if(!$(this).is(".ui-resizable"))
					new $.ui.resizable(this, options);
			});
		}
	});

	$.ui.resizable = function(element, options) {
		//Initialize needed constants
		var self = this;
		
		this.element = $(element);
		
		$.data(element, "resizable", this);
		
		// simulate .ui-resizable { position: relative; }
		var elpos = this.element.css('position');
		this.element.addClass("ui-resizable").css({ position: /static/.test(elpos) ? 'relative' : elpos });
		
		//Prepare the passed options
		this.options = $.extend({
			preventDefault: true,
			transparent: false,
			minWidth: 10,
			minHeight: 10,
			aspectRatio: false,
			disableSelection: true,
			preserveCursor: true,
			autohide: false,
			knobHandles: false
		}, options);
		
		this.options._aspectRatio = !!(this.options.aspectRatio);
		
		// force proxy if helper is enabled
		this.options.proxy = this.options.proxy || this.options.ghost ? 'proxy' : null; 
		
		// force proxy if animation is enabled
		this.options.proxy = this.options.proxy || this.options.animate ? 'proxy' : null; 
		
		// if knobHandles equals true set to ui-resizable-knob-handle
		this.options.knobHandles = this.options.knobHandles === true ? 'ui-resizable-knob-handle' : this.options.knobHandles;
		
		$(element).bind("setData.resizable", function(event, key, value){
			self.options[key] = value;
		}).bind("getData.resizable", function(event, key){
			return self.options[key];
		});
	
		var o = this.options;
	
		//Default Theme
		var aBorder = '1px solid #DEDEDE';
	
		o.defaultTheme = {
			'ui-resizable': { display: 'block' },
			'ui-resizable-handle': { position: 'absolute', background: '#F2F2F2', fontSize: '0.1px' },
			'ui-resizable-n': { cursor: 'n-resize', height: '4px', left: '0px', right: '0px', borderTop: aBorder },
			'ui-resizable-s': { cursor: 's-resize', height: '4px', left: '0px', right: '0px', borderBottom: aBorder },
			'ui-resizable-e': { cursor: 'e-resize', width: '4px', top: '0px', bottom: '0px', borderRight: aBorder },
			'ui-resizable-w': { cursor: 'w-resize', width: '4px', top: '0px', bottom: '0px', borderLeft: aBorder },
			'ui-resizable-se': { cursor: 'se-resize', width: '4px', height: '4px', borderRight: aBorder, borderBottom: aBorder },
			'ui-resizable-sw': { cursor: 'sw-resize', width: '4px', height: '4px', borderBottom: aBorder, borderLeft: aBorder },
			'ui-resizable-ne': { cursor: 'ne-resize', width: '4px', height: '4px', borderRight: aBorder, borderTop: aBorder },
			'ui-resizable-nw': { cursor: 'nw-resize', width: '4px', height: '4px', borderLeft: aBorder, borderTop: aBorder }
		};
		
		o.knobTheme = {
			'ui-resizable-handle': { background: '#F2F2F2', border: '1px solid #808080', height: '8px', width: '8px' },
			'ui-resizable-n': { cursor: 'n-resize', top: '-4px', left: '45%' },
			'ui-resizable-s': { cursor: 's-resize', bottom: '-4px', left: '45%' },
			'ui-resizable-e': { cursor: 'e-resize', right: '-4px', top: '45%' },
			'ui-resizable-w': { cursor: 'w-resize', left: '-4px', top: '45%' },
			'ui-resizable-se': { cursor: 'se-resize', right: '-4px', bottom: '-4px' },
			'ui-resizable-sw': { cursor: 'sw-resize', left: '-4px', bottom: '-4px' },
			'ui-resizable-nw': { cursor: 'nw-resize', left: '-4px', top: '-4px' },
			'ui-resizable-ne': { cursor: 'ne-resize', right: '-4px', top: '-4px' }
		};
	
		//Position the node
		if(!o.proxy && (this.element.css('position') == 'static' || this.element.css('position') === ''))
			this.element.css('position', 'relative');
	
		o._nodeName = element.nodeName;
	
		//Wrap the element if it cannot hold child nodes
		if(o._nodeName.match(/textarea|input|select|button|img/i)) {
			var el = this.element;
			
			//Opera fixing relative position
			if (/relative/.test(el.css('position')) && $.browser.opera)
				el.css({ position: 'relative', top: 'auto', left: 'auto' });
			
			//Create a wrapper element and set the wrapper to the new current internal element
			el.wrap(
				$('<div class="ui-wrapper"	style="overflow: hidden;"></div>').css( {
					position: el.css('position'),
					width: el.outerWidth(),
					height: el.outerHeight(),
					top: el.css('top'),
					left: el.css('left')
				})
			);
			
			var oel = this.element; element = element.parentNode; this.element = $(element);
	
			//Move margins to the wrapper
			this.element.css({ marginLeft: oel.css("marginLeft"), marginTop: oel.css("marginTop"),
				marginRight: oel.css("marginRight"), marginBottom: oel.css("marginBottom")
			});
	
			oel.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
	
			//Prevent Safari textarea resize
			if ($.browser.safari && o.preventDefault) oel.css('resize', 'none');
	
			o.proportionallyResize = oel.css({ position: 'static', zoom: 1, display: 'block' });
			
			// avoid IE jump
			this.element.css({ margin: oel.css('margin') });
			
			// fix handlers offset
			this._proportionallyResize();
		}
	
		if(!o.handles) o.handles = !$('.ui-resizable-handle', element).length ? "e,s,se" : { n: '.ui-resizable-n', e: '.ui-resizable-e', s: '.ui-resizable-s', w: '.ui-resizable-w', se: '.ui-resizable-se', sw: '.ui-resizable-sw', ne: '.ui-resizable-ne', nw: '.ui-resizable-nw' };
		if(o.handles.constructor == String) {
	
			if(o.handles == 'all') o.handles = 'n,e,s,w,se,sw,ne,nw';
	
			var n = o.handles.split(","); o.handles = {};
	
			o.zIndex = o.zIndex || 1000;
			
			// insertions are applied when don't have theme loaded
			var insertionsDefault = {
				handle: 'position: absolute; display: none; overflow:hidden;',
				n: 'top: 0pt; width:100%;',
				e: 'right: 0pt; height:100%;',
				s: 'bottom: 0pt; width:100%;',
				w: 'left: 0pt; height:100%;',
				se: 'bottom: 0pt; right: 0px;',
				sw: 'bottom: 0pt; left: 0px;',
				ne: 'top: 0pt; right: 0px;',
				nw: 'top: 0pt; left: 0px;'
			};
	
			for(var i = 0; i < n.length; i++) {
				var handle = jQuery.trim(n[i]), dt = o.defaultTheme, hname = 'ui-resizable-'+handle, loadDefault = !$.ui.css(hname) && !o.knobHandles, userKnobClass = $.ui.css('ui-resizable-knob-handle'), 
							allDefTheme = $.extend(dt[hname], dt['ui-resizable-handle']), allKnobTheme = $.extend(o.knobTheme[hname], !userKnobClass ? o.knobTheme['ui-resizable-handle'] : {});
				
				// increase zIndex of sw, se, ne, nw axis
				var applyZIndex = /sw|se|ne|nw/.test(handle) ? { zIndex: ++o.zIndex } : {};
				
				var defCss = (loadDefault ? insertionsDefault[handle] : ''), 
					axis = $(['<div class="ui-resizable-handle ', hname, '" style="', defCss, insertionsDefault.handle, '"></div>'].join('')).css( applyZIndex );
				o.handles[handle] = '.ui-resizable-'+handle;
				
				this.element.append(
					//Theme detection, if not loaded, load o.defaultTheme
					axis.css( loadDefault ? allDefTheme : {} )
						// Load the knobHandle css, fix width, height, top, left...
						.css( o.knobHandles ? allKnobTheme : {} ).addClass(o.knobHandles ? 'ui-resizable-knob-handle' : '').addClass(o.knobHandles)
				);
			}
			
			if (o.knobHandles) this.element.addClass('ui-resizable-knob').css( !$.ui.css('ui-resizable-knob') ? { /*border: '1px #fff dashed'*/ } : {} );
		}
	
		this._renderAxis = function(target) {
			target = target || this.element;
	
			for(var i in o.handles) {
				if(o.handles[i].constructor == String) 
					o.handles[i] = $(o.handles[i], element).show();
	
				if (o.transparent)
					o.handles[i].css({opacity:0});
	
				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
				if (this.element.is('.ui-wrapper') && 
					o._nodeName.match(/textarea|input|select|button/i)) {
	
					var axis = $(o.handles[i], element), padWrapper = 0;
	
					//Checking the correct pad and border
					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
	
					//The padding type i have to apply...
					var padPos = [ 'padding', 
						/ne|nw|n/.test(i) ? 'Top' :
						/se|sw|s/.test(i) ? 'Bottom' : 
						/^e$/.test(i) ? 'Right' : 'Left' ].join(""); 
	
					if (!o.transparent)
						target.css(padPos, padWrapper);
	
					this._proportionallyResize();
				}
				if(!$(o.handles[i]).length) continue;
			}
		};
			
		this._renderAxis(this.element);
		o._handles = $('.ui-resizable-handle', self.element);
		
		if (o.disableSelection)
			o._handles.each(function(i, e) { $.ui.disableSelection(e); });
		
		//Matching axis name
		o._handles.mouseover(function() {
			if (!o.resizing) {
				if (this.className) 
					var axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
				//Axis, default = se
				self.axis = o.axis = axis && axis[1] ? axis[1] : 'se';
			}
		});
				
		//If we want to auto hide the elements
		if (o.autohide) {
			o._handles.hide();
			$(self.element).addClass("ui-resizable-autohide").hover(function() {
				$(this).removeClass("ui-resizable-autohide");
				o._handles.show();
			},
			function(){
				if (!o.resizing) {
					$(this).addClass("ui-resizable-autohide");
					o._handles.hide();
				}
			});
		}
	
		//Initialize mouse events for interaction
		this.element.mouseInteraction({
			executor: this,
			delay: 0,
			distance: 0,
			dragPrevention: ['input','textarea','button','select','option'],
			start: this.start,
			stop: this.stop,
			drag: this.drag,
			condition: function(e) {
				if(this.disabled) return false;
				for(var i in this.options.handles) {
					if($(this.options.handles[i])[0] == e.target) return true;
				}
				return false;
			}
		});
	};

	$.extend($.ui.resizable.prototype, {
		plugins: {},
		ui: function() {
			return {
				instance: this,
				axis: this.options.axis,
				options: this.options
			};
		},
		_renderProxy: function() {
			var el = this.element, o = this.options;
			this.elementOffset = el.offset();
	
			if(o.proxy) {
				this.helper = this.helper || $('<div style="overflow:hidden;"></div>');
	
				// fix ie6 offset
				var ie6 = $.browser.msie && $.browser.version  < 7, ie6offset = (ie6 ? 1 : 0),
				pxyoffset = ( ie6 ? 2 : -1 );
	
				this.helper.addClass(o.proxy).css({
					width: el.outerWidth() + pxyoffset,
					height: el.outerHeight() + pxyoffset,
					position: 'absolute',
					left: this.elementOffset.left - ie6offset +'px',
					top: this.elementOffset.top - ie6offset +'px',
					zIndex: ++o.zIndex
				});
				
				this.helper.appendTo("body");
	
				if (o.disableSelection)
					$.ui.disableSelection(this.helper.get(0));
	
			} else {
				this.helper = el; 
			}
		},
		propagate: function(n,e) {
			$.ui.plugin.call(this, n, [e, this.ui()]);
			this.element.triggerHandler(n == "resize" ? n : ["resize", n].join(""), [e, this.ui()], this.options[n]);
		},
		destroy: function() {
			var el = this.element, wrapped = el.children(".ui-resizable").get(0),
			
			_destroy = function(exp) {
				$(exp).removeClass("ui-resizable ui-resizable-disabled")
					.removeMouseInteraction().removeData("resizable").unbind(".resizable");
			};
			
			_destroy(el);
			
			if (el.is('.ui-wrapper') && wrapped) {
		  	el.parent().append(
					$(wrapped).css({
			  		position: el.css('position'),
			  		width: el.outerWidth(),
			  		height: el.outerHeight(),
			  		top: el.css('top'),
			  		left: el.css('left')
		  		})
				).end().remove();
				
				_destroy(wrapped);
	  	}
		},
		enable: function() {
			this.element.removeClass("ui-resizable-disabled");
			this.disabled = false;
		},
		disable: function() {
			this.element.addClass("ui-resizable-disabled");
			this.disabled = true;
		},
		start: function(e) {
			var o = this.options, iniPos = this.element.position(), el = this.element, 
				num = function(v) { return parseInt(v, 10) || 0; }, ie6 = $.browser.msie && $.browser.version < 7;
			o.resizing = true;
			o.documentScroll = { top: $(document).scrollTop(), left: $(document).scrollLeft() };
	
			// bugfix #1749
			if (el.is('.ui-draggable') || (/absolute/).test(el.css('position'))) {
				
				// sOffset decides if document scrollOffset will be added to the top/left of the resizable element
				var sOffset = $.browser.msie && !o.containment && (/absolute/).test(el.css('position')) && !(/relative/).test(el.parent().css('position'));
				var dscrollt = sOffset ? o.documentScroll.top : 0, dscrolll = sOffset ? o.documentScroll.left : 0;
				
				el.css({ position: 'absolute', top: (iniPos.top + dscrollt), left: (iniPos.left + dscrolll) });
			}
			
			//Opera fixing relative position
			if (/relative/.test(el.css('position')) && $.browser.opera)
				el.css({ position: 'relative', top: 'auto', left: 'auto' });
	
			this._renderProxy();
	
			var curleft = num(this.helper.css('left')), curtop = num(this.helper.css('top'));
			
			//Store needed variables
			this.offset = this.helper.offset();
			this.position = { left: curleft, top: curtop };
			this.size = o.proxy || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
			this.originalSize = o.proxy || ie6 ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
			this.originalPosition = { left: curleft, top: curtop };
			this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
			this.originalMousePosition = { left: e.pageX, top: e.pageY };
			
			//Aspect Ratio
			o.aspectRatio = (typeof o.aspectRatio == 'number') ? o.aspectRatio : ((this.originalSize.height / this.originalSize.width)||1);
	
			if (o.preserveCursor)
				$('body').css('cursor', this.axis + '-resize');
				
			this.propagate("start", e); 	
			return false;
		},
		stop: function(e) {
			this.options.resizing = false;
			var o = this.options, num = function(v) { return parseInt(v, 10) || 0; }, self = this;
	
			if(o.proxy) {
				var pr = o.proportionallyResize, ista = pr && /textarea/i.test(pr.get(0).nodeName), 
							soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
								soffsetw = ista ? 0 : self.sizeDiff.width;
			
				var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
						left = parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left), 
							top = parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top);
				
				if (!o.animate)
					this.element.css($.extend(style, { top: top, left: left }));
				
				if (o.proxy && !o.animate) this._proportionallyResize();
				this.helper.remove();
			}

			if (o.preserveCursor)
			$('body').css('cursor', 'auto');
	
			this.propagate("stop", e);	
			return false;
		},
		drag: function(e) {
			//Increase performance, avoid regex
			var el = this.helper, o = this.options, props = {},
				self = this, smp = this.originalMousePosition, a = this.axis;

			var dx = (e.pageX-smp.left)||0, dy = (e.pageY-smp.top)||0;
			var trigger = this.change[a];
			if (!trigger) return false;
		 
			// Calculate the attrs that will be change
			var data = trigger.apply(this, [e, dx, dy]), ie6 = $.browser.msie && $.browser.version < 7, csdif = this.sizeDiff;
		 
			if (o._aspectRatio || e.shiftKey)
				data = this._updateRatio(data, e);
			
			data = this._respectSize(data, e);
			
			this.propagate("resize", e);
			
			el.css({
				top: this.position.top + "px", left: this.position.left + "px", 
				width: this.size.width + "px", height: this.size.height + "px"
			});
			
			if (!o.proxy && o.proportionallyResize)
				this._proportionallyResize();
			
			this._updateCache(data);
			
			return false;
		},
		
		_updateCache: function(data) {
			var o = this.options;
			this.offset = this.helper.offset();
			if (data.left) this.position.left = data.left;
			if (data.top) this.position.top = data.top;
			if (data.height) this.size.height = data.height;
			if (data.width) this.size.width = data.width;
		},
		
		_updateRatio: function(data, e) {
			var o = this.options, cpos = this.position, csize = this.size, a = this.axis;
			
			if (data.height) data.width = Math.round(csize.height / o.aspectRatio);
			else if (data.width) data.height = Math.round(csize.width * o.aspectRatio);
			
			if (a == 'sw') {
				data.left = cpos.left + (csize.width - data.width);
				data.top = null;
			}
			if (a == 'nw') { 
				data.top = cpos.top + (csize.height - data.height);
				data.left = cpos.left + (csize.width - data.width);
			}
			
			return data;
		},
		
		_respectSize: function(data, e) {
			
			var el = this.helper, o = this.options, pRatio = o._aspectRatio || e.shiftKey,  a = this.axis, 
					ismaxw = data.width && o.maxWidth && o.maxWidth < data.width, ismaxh = data.height && o.maxHeight && o.maxHeight < data.height,
						isminw = data.width && o.minWidth && o.minWidth > data.width, isminh = data.height && o.minHeight && o.minHeight > data.height;
			
			if (isminw) data.width = o.minWidth;
			if (isminh) data.height = o.minHeight;
			if (ismaxw) data.width = o.maxWidth;
			if (ismaxh) data.height = o.maxHeight;
			
			var dw = this.originalPosition.left + this.originalSize.width, dh = this.position.top + this.size.height;
			var cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
			
			if (isminw && cw) data.left = dw - o.minWidth;
			if (ismaxw && cw) data.left = dw - o.maxWidth;
			if (isminh && ch)	data.top = dh - o.minHeight;
			if (ismaxh && ch)	data.top = dh - o.maxHeight;
			
			// fixing jump error on top/left - bug #2330
			var isNotwh = !data.width && !data.height;
			if (isNotwh && !data.left && data.top) data.top = null;
			else if (isNotwh && !data.top && data.left) data.left = null;
			
			return data;
		},
		
		_proportionallyResize: function() {
			var o = this.options;
			if (!o.proportionallyResize) return;
			var prel = o.proportionallyResize, el = this.helper || this.element;
		 
			if (!o.borderDif) {
				var b = [prel.css('borderTopWidth'), prel.css('borderRightWidth'), prel.css('borderBottomWidth'), prel.css('borderLeftWidth')],
					p = [prel.css('paddingTop'), prel.css('paddingRight'), prel.css('paddingBottom'), prel.css('paddingLeft')];
				 
				o.borderDif = $.map(b, function(v, i) {
					var border = parseInt(v,10)||0, padding = parseInt(p[i],10)||0;
					return border + padding; 
				});
			}
			prel.css({
				height: (el.height() - o.borderDif[0] - o.borderDif[2]) + "px",
				width: (el.width() - o.borderDif[1] - o.borderDif[3]) + "px"
			});
		},
		
		change: {
			e: function(e, dx, dy) {
				return { width: this.originalSize.width + dx };
			},
			w: function(e, dx, dy) {
				var o = this.options, cs = this.originalSize, sp = this.originalPosition;
				return { left: sp.left + dx, width: cs.width - dx };
			},
			n: function(e, dx, dy) {
				var o = this.options, cs = this.originalSize, sp = this.originalPosition;
				return { top: sp.top + dy, height: cs.height - dy };
			},
			s: function(e, dx, dy) {
				return { height: this.originalSize.height + dy };
			},
			se: function(e, dx, dy) {
				return $.extend(this.change.s.apply(this, arguments), this.change.e.apply(this, [e, dx, dy]));
			},
			sw: function(e, dx, dy) {
				return $.extend(this.change.s.apply(this, arguments), this.change.w.apply(this, [e, dx, dy]));
			},
			ne: function(e, dx, dy) {
				return $.extend(this.change.n.apply(this, arguments), this.change.e.apply(this, [e, dx, dy]));
			},
			nw: function(e, dx, dy) {
				return $.extend(this.change.n.apply(this, arguments), this.change.w.apply(this, [e, dx, dy]));
			}
		}
	});

/*
 * Resizable Extensions
 */

	$.ui.plugin.add("resizable", "containment", {
		
		start: function(e, ui) {
			var o = ui.options, self = ui.instance, el = self.element;
			var oc = o.containment,	ce = (oc instanceof jQuery) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
			if (!ce) return;
			
			if (/document/.test(oc) || oc == document) {
				self.containerOffset = { left: 0, top: 0 };

				self.parentData = { 
					element: $(document), left: 0, top: 0, width: $(document).width(),
					height: $(document).height() || document.body.parentNode.scrollHeight
				};
			}
			
			// i'm a node, so compute top, left, right, bottom
			else{
				self.containerOffset = $(ce).offset(), self.containerSize = { height: $(ce).innerHeight(), width: $(ce).innerWidth() };
			
				var co = self.containerOffset, ch = self.containerSize.height,	cw = self.containerSize.width, 
							width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw ), height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
			
				self.parentData = { 
					element: ce, left: co.left, top: co.top, width: width, height: height
				};
			}
		},
		
		resize: function(e, ui) {
			var o = ui.options, self = ui.instance, ps = self.containerSize, 
						co = self.containerOffset, cs = self.size, cp = self.position,
							pRatio = o._aspectRatio || e.shiftKey;
			
			if (cp.left < (o.proxy ? co.left : 0)) {
				self.size.width = self.size.width + (o.proxy ? (self.position.left - co.left) : self.position.left);
				if (pRatio) self.size.height = self.size.width * o.aspectRatio;
				self.position.left = o.proxy ? co.left : 0;
			}
			
			if (cp.top < (o.proxy ? co.top : 0)) {
				self.size.height = self.size.height + (o.proxy ? (self.position.top - co.top) : self.position.top);
				if (pRatio) self.size.width = self.size.height / o.aspectRatio;
				self.position.top = o.proxy ? co.top : 0;
			}
			
			var woset = (o.proxy ? self.offset.left - co.left : self.position.left) + self.sizeDiff.width, 
						hoset = (o.proxy ? self.offset.top - co.top : self.position.top) + self.sizeDiff.height;
			
			if (woset + self.size.width >= self.parentData.width) {
				self.size.width = self.parentData.width - woset;
				if (pRatio) self.size.height = self.size.width * o.aspectRatio;
			}
			
			if (hoset + self.size.height >= self.parentData.height) {
				self.size.height = self.parentData.height - hoset;
				if (pRatio) self.size.width = self.size.height / o.aspectRatio;
			}
		}
	});
	
	$.ui.plugin.add("resizable", "grid", {
		
		resize: function(e, ui) {
			var o = ui.options, self =  ui.instance, cs = self.size, os = self.originalSize, op = self.originalPosition, a = self.axis, ratio = o._aspectRatio || e.shiftKey;
			o.grid = typeof o.grid == "number" ? [o.grid, o.grid] : o.grid;
			var ox = Math.round((cs.width - os.width) / o.grid[0]) * o.grid[0], oy = Math.round((cs.height - os.height) / o.grid[1]) * o.grid[1];
			
			if (/^(se|s|e)$/.test(a)) {
				self.size.width = os.width + ox;
				self.size.height = os.height + oy;
			}
			else if (/^(ne)$/.test(a)) {
				self.size.width = os.width + ox;
				self.size.height = os.height + oy;
				self.position.top = op.top - oy;
			}
			else if (/^(sw)$/.test(a)) {
				self.size.width = os.width + ox;
				self.size.height = os.height + oy;
				self.position.left = op.left - ox;
			}
			else {
				self.size.width = os.width + ox;
				self.size.height = os.height + oy;
				self.position.top = op.top - oy;
				self.position.left = op.left - ox;
			}
		}
		
	});
	
	$.ui.plugin.add("resizable", "animate", {
		
		stop: function(e, ui) {
			var o = ui.options, self =  ui.instance;

			var pr = o.proportionallyResize, ista = pr && /textarea/i.test(pr.get(0).nodeName), 
							soffseth = ista && $.ui.hasScroll(pr.get(0), 'left') /* TODO - jump height */ ? 0 : self.sizeDiff.height,
								soffsetw = ista ? 0 : self.sizeDiff.width;
			
			var style = { width: (self.size.width - soffsetw), height: (self.size.height - soffseth) },
						left = parseInt(self.element.css('left'), 10) + (self.position.left - self.originalPosition.left), 
							top = parseInt(self.element.css('top'), 10) + (self.position.top - self.originalPosition.top); 
			
			self.element.animate(
				$.extend(style, { top: top, left: left }),
				{ 
					duration: o.animateDuration || "slow", 
					easing: o.animateEasing || "swing", 
					step: function() {
						if (pr) pr.css({ width: self.element.css('width'), height: self.element.css('height') });
					}
				}
			);
		}
		
	});
	
	$.ui.plugin.add("resizable", "ghost", {
		
		start: function(e, ui) {
			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize, cs = self.size;
			
			if (!pr) self.ghost = self.element.clone();
			else self.ghost = pr.clone();
			
			self.ghost.css(
				{ opacity: .25, display: 'block', position: 'relative', height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 }
			)
			.addClass('ui-resizable-ghost').addClass(typeof o.ghost == 'string' ? o.ghost : '');
			
			self.ghost.appendTo(self.helper);
			
		},
		
		resize: function(e, ui){
			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize;
			
			if (self.ghost) self.ghost.css({ position: 'relative', height: self.size.height, width: self.size.width });
			
		},
		
		stop: function(e, ui){
			var o = ui.options, self =  ui.instance, pr = o.proportionallyResize;
			if (self.ghost && self.helper) self.helper.get(0).removeChild(self.ghost.get(0));
		}
		
	});

})(jQuery);


/*
 * jQuery UI Draggable
 *
 * Copyright (c) 2008 Paul Bakaus
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 * 
 * http://docs.jquery.com/UI/Draggables
 *
 * Depends:
 *   ui.base.js
 *
 * Revision: $Id: ui.draggable.js 5154 2008-03-31 14:46:15Z rdworth $
 */
;(function($) {

	$.fn.extend({
		draggable: function(options) {
			var args = Array.prototype.slice.call(arguments, 1);
			
			return this.each(function() {
				if (typeof options == "string") {
					var drag = $.data(this, "draggable");
					if(drag) drag[options].apply(drag, args);

				} else if(!$.data(this, "draggable"))
					new $.ui.draggable(this, options);
			});
		}
	});
	
	$.ui.draggable = function(element, options) {
		//Initialize needed constants
		var self = this;
		
		this.element = $(element);
		
		$.data(element, "draggable", this);
		this.element.addClass("ui-draggable");
		
		//Prepare the passed options
		this.options = $.extend({}, options);
		var o = this.options;
		$.extend(o, {
			helper: o.ghosting == true ? 'clone' : (o.helper || 'original'),
			handle : o.handle ? ($(o.handle, element)[0] ? $(o.handle, element) : this.element) : this.element,
			appendTo: o.appendTo || 'parent'		
		});
		
		$(element).bind("setData.draggable", function(event, key, value){
			self.options[key] = value;
		}).bind("getData.draggable", function(event, key){
			return self.options[key];
		});
		
		//Initialize mouse events for interaction
		$(o.handle).mouseInteraction({
			executor: this,
			delay: o.delay,
			distance: o.distance || 1,
			dragPrevention: o.cancel || o.cancel === '' ? o.cancel.toLowerCase().split(',') : ['input','textarea','button','select','option'],
			start: this.start,
			stop: this.stop,
			drag: this.drag,
			condition: function(e) { return !(e.target.className.indexOf("ui-resizable-handle") != -1 || this.options.disabled); }
		});
		
		//Position the node
		if(o.helper == 'original' && (this.element.css('position') == 'static' || this.element.css('position') == ''))
			this.element.css('position', 'relative');
			
		//Prepare cursorAt
		if(o.cursorAt && o.cursorAt.constructor == Array)
			o.cursorAt = { left: o.cursorAt[0], top: o.cursorAt[1] };
		
	};
	
	$.extend($.ui.draggable.prototype, {
		plugins: {},
		ui: function(e) {
			return {
				helper: this.helper,
				position: this.position,
				absolutePosition: this.positionAbs,
				instance: this,
				options: this.options,
				element: this.element				
			};
		},
		propagate: function(n,e) {
			$.ui.plugin.call(this, n, [e, this.ui()]);
			return this.element.triggerHandler(n == "drag" ? n : "drag"+n, [e, this.ui()], this.options[n]);
		},
		destroy: function() {
			if(!$.data(this.element[0], 'draggable')) return;
			this.options.handle.removeMouseInteraction();
			this.element
				.removeClass("ui-draggable ui-draggable-disabled")
				.removeData("draggable")
				.unbind(".draggable");
		},
		enable: function() {
			this.element.removeClass("ui-draggable-disabled");
			this.options.disabled = false;
		},
		disable: function() {
			this.element.addClass("ui-draggable-disabled");
			this.options.disabled = true;
		},
		setContrains: function(minLeft,maxLeft,minTop,maxTop) {
			this.minLeft = minLeft; this.maxLeft = maxLeft;
			this.minTop = minTop; this.maxTop = maxTop;
			this.constrainsSet = true;
		},
		checkConstrains: function() {
			if(!this.constrainsSet) return;
			if(this.position.left < this.minLeft) this.position.left = this.minLeft;
			if(this.position.left > this.maxLeft - this.helperProportions.width) this.position.left = this.maxLeft - this.helperProportions.width;
			if(this.position.top < this.minTop) this.position.top = this.minTop;
			if(this.position.top > this.maxTop - this.helperProportions.height) this.position.top = this.maxTop - this.helperProportions.height;
		},
		recallOffset: function(e) {

			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top };
			var r = this.helper.css('position') == 'relative';

			//Generate the original position
			this.originalPosition = {
				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)),
				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop))
			};
			
			//Generate a flexible offset that will later be subtracted from e.pageX/Y
			this.offset = {left: this._pageX - this.originalPosition.left, top: this._pageY - this.originalPosition.top };
			
		},
		start: function(e) {
			var o = this.options;
			if($.ui.ddmanager) $.ui.ddmanager.current = this;
			
			//Create and append the visible helper
			this.helper = typeof o.helper == 'function' ? $(o.helper.apply(this.element[0], [e])) : (o.helper == 'clone' ? this.element.clone().appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo)) : this.element);
			if(this.helper[0] != this.element[0]) this.helper.css('position', 'absolute');
			if(!this.helper.parents('body').length) this.helper.appendTo((o.appendTo == 'parent' ? this.element[0].parentNode : o.appendTo));
			
			
			//Find out the next positioned parent
			this.offsetParent = (function(cp) {
				while(cp) {
					if(cp.style && (/(absolute|relative|fixed)/).test($.css(cp,'position'))) return $(cp);
					cp = cp.parentNode ? cp.parentNode : null;
				}; return $("body");		
			})(this.helper[0].parentNode);
			
			//Prepare variables for position generation
			this.elementOffset = this.element.offset();
			this.offsetParentOffset = this.offsetParent.offset();
			var elementPosition = { left: this.elementOffset.left - this.offsetParentOffset.left, top: this.elementOffset.top - this.offsetParentOffset.top };
			this._pageX = e.pageX; this._pageY = e.pageY;
			this.clickOffset = { left: e.pageX - this.elementOffset.left, top: e.pageY - this.elementOffset.top };
			var r = this.helper.css('position') == 'relative';

			//Generate the original position
			this.originalPosition = {
				left: (r ? parseInt(this.helper.css('left'),10) || 0 : elementPosition.left + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollLeft)),
				top: (r ? parseInt(this.helper.css('top'),10) || 0 : elementPosition.top + (this.offsetParent[0] == document.body ? 0 : this.offsetParent[0].scrollTop))
			};
			
			//If we have a fixed element, we must subtract the scroll offset again
			if(this.element.css('position') == 'fixed') {
				this.originalPosition.top -= this.offsetParent[0] == document.body ? $(document).scrollTop() : this.offsetParent[0].scrollTop;
				this.originalPosition.left -= this.offsetParent[0] == document.body ? $(document).scrollLeft() : this.offsetParent[0].scrollLeft;
			}
			
			//Generate a flexible offset that will later be subtracted from e.pageX/Y
			this.offset = {left: e.pageX - this.originalPosition.left, top: e.pageY - this.originalPosition.top };
			
			//Substract margins
			if(this.element[0] != this.helper[0]) {
				this.offset.left += parseInt(this.element.css('marginLeft'),10) || 0;
				this.offset.top += parseInt(this.element.css('marginTop'),10) || 0;
			}
			
			//Call plugins and callbacks
			this.propagate("start", e);

			this.helperProportions = { width: this.helper.outerWidth(), height: this.helper.outerHeight() };
			if ($.ui.ddmanager && !o.dropBehaviour) $.ui.ddmanager.prepareOffsets(this, e);
			
			//If we have something in cursorAt, we'll use it
			if(o.cursorAt) {
				if(o.cursorAt.top != undefined || o.cursorAt.bottom != undefined) {
					this.offset.top -= this.clickOffset.top - (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom));
					this.clickOffset.top = (o.cursorAt.top != undefined ? o.cursorAt.top : (this.helperProportions.height - o.cursorAt.bottom));
				}
				if(o.cursorAt.left != undefined || o.cursorAt.right != undefined) {
					this.offset.left -= this.clickOffset.left - (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right));
					this.clickOffset.left = (o.cursorAt.left != undefined ? o.cursorAt.left : (this.helperProportions.width - o.cursorAt.right));
				}
			}

			return false;

		},
		clear: function() {
			if($.ui.ddmanager) $.ui.ddmanager.current = null;
			this.helper = null;
		},
		stop: function(e) {

			//If we are using droppables, inform the manager about the drop
			if ($.ui.ddmanager && !this.options.dropBehaviour)
				$.ui.ddmanager.drop(this, e);
				
			//Call plugins and trigger callbacks
			this.propagate("stop", e);
			
			if(this.cancelHelperRemoval) return false;			
			if(this.options.helper != 'original') this.helper.remove();
			this.clear();

			return false;
		},
		drag: function(e) {

			//Compute the helpers position
			this.position = { top: e.pageY - this.offset.top, left: e.pageX - this.offset.left };
			this.positionAbs = { left: e.pageX - this.clickOffset.left, top: e.pageY - this.clickOffset.top };

			//Call plugins and callbacks
			this.checkConstrains();			
			this.position = this.propagate("drag", e) || this.position;
			this.checkConstrains();
			
			$(this.helper).css({ left: this.position.left+'px', top: this.position.top+'px' }); // Stick the helper to the cursor
			if($.ui.ddmanager) $.ui.ddmanager.drag(this, e);
			return false;
			
		}
	});
	
/*
 * Draggable Extensions
 */
	 
	$.ui.plugin.add("draggable", "cursor", {
		start: function(e, ui) {
			var t = $('body');
			if (t.css("cursor")) ui.options._cursor = t.css("cursor");
			t.css("cursor", ui.options.cursor);
		},
		stop: function(e, ui) {
			if (ui.options._cursor) $('body').css("cursor", ui.options._cursor);
		}
	});

	$.ui.plugin.add("draggable", "zIndex", {
		start: function(e, ui) {
			var t = $(ui.helper);
			if(t.css("zIndex")) ui.options._zIndex = t.css("zIndex");
			t.css('zIndex', ui.options.zIndex);
		},
		stop: function(e, ui) {
			if(ui.options._zIndex) $(ui.helper).css('zIndex', ui.options._zIndex);
		}
	});

	$.ui.plugin.add("draggable", "opacity", {
		start: function(e, ui) {
			var t = $(ui.helper);
			if(t.css("opacity")) ui.options._opacity = t.css("opacity");
			t.css('opacity', ui.options.opacity);
		},
		stop: function(e, ui) {
			if(ui.options._opacity) $(ui.helper).css('opacity', ui.options._opacity);
		}
	});


	$.ui.plugin.add("draggable", "revert", {
		stop: function(e, ui) {
			var self = ui.instance, helper = $(self.helper);
			self.cancelHelperRemoval = true;
			
			$(ui.helper).animate({ left: self.originalPosition.left, top: self.originalPosition.top }, parseInt(ui.options.revert, 10) || 500, function() {
				if(ui.options.helper != 'original') helper.remove();
				if (!helper) self.clear();
			});
		}
	});

	$.ui.plugin.add("draggable", "iframeFix", {
		start: function(e, ui) {

			var o = ui.options;
			if(ui.instance.slowMode) return; // Make clones on top of iframes (only if we are not in slowMode)
			
			if(o.iframeFix.constructor == Array) {
				for(var i=0;i<o.iframeFix.length;i++) {
					var co = $(o.iframeFix[i]).offset({ border: false });
					$('<div class="DragDropIframeFix"" style="background: #fff;"></div>').css("width", $(o.iframeFix[i])[0].offsetWidth+"px").css("height", $(o.iframeFix[i])[0].offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body");
				}		
			} else {
				$("iframe").each(function() {					
					var co = $(this).offset({ border: false });
					$('<div class="DragDropIframeFix" style="background: #fff;"></div>').css("width", this.offsetWidth+"px").css("height", this.offsetHeight+"px").css("position", "absolute").css("opacity", "0.001").css("z-index", "1000").css("top", co.top+"px").css("left", co.left+"px").appendTo("body");
				});							
			}

		},
		stop: function(e, ui) {
			if(ui.options.iframeFix) $("div.DragDropIframeFix").each(function() { this.parentNode.removeChild(this); }); //Remove frame helpers	
		}
	});
	
	$.ui.plugin.add("draggable", "containment", {
		start: function(e, ui) {

			var o = ui.options;
			var self = ui.instance;
			if((o.containment.left != undefined || o.containment.constructor == Array) && !o._containment) return;
			if(!o._containment) o._containment = o.containment;

			if(o._containment == 'parent') o._containment = this[0].parentNode;
			if(o._containment == 'document') {
				o.containment = [
					0,
					0,
					$(document).width(),
					($(document).height() || document.body.parentNode.scrollHeight)
				];
			} else { //I'm a node, so compute top/left/right/bottom

				var ce = $(o._containment)[0];
				var co = $(o._containment).offset();

				o.containment = [
					co.left,
					co.top,
					co.left+(ce.offsetWidth || ce.scrollWidth),
					co.top+(ce.offsetHeight || ce.scrollHeight)
				];
			}
			
			var c = o.containment;
			ui.instance.setContrains(
				c[0] - (self.offset.left - self.clickOffset.left), //min left
				c[2] - (self.offset.left - self.clickOffset.left), //max left
				c[1] - (self.offset.top - self.clickOffset.top), //min top
				c[3] - (self.offset.top - self.clickOffset.top) //max top
			);

		}
	});

	$.ui.plugin.add("draggable", "grid", {
		drag: function(e, ui) {
			var o = ui.options;
			var newLeft = ui.instance.originalPosition.left + Math.round((e.pageX - ui.instance._pageX) / o.grid[0]) * o.grid[0];
			var newTop = ui.instance.originalPosition.top + Math.round((e.pageY - ui.instance._pageY) / o.grid[1]) * o.grid[1];
			
			ui.instance.position.left = newLeft;
			ui.instance.position.top = newTop;

		}
	});

	$.ui.plugin.add("draggable", "axis", {
		drag: function(e, ui) {
			var o = ui.options;
			if(o.constraint) o.axis = o.constraint; //Legacy check
			switch (o.axis) {
				case 'x' : ui.instance.position.top = ui.instance.originalPosition.top; break;
				case 'y' : ui.instance.position.left = ui.instance.originalPosition.left; break;
			}
		}
	});

	$.ui.plugin.add("draggable", "scroll", {
		start: function(e, ui) {
			var o = ui.options;
			o.scrollSensitivity	= o.scrollSensitivity || 20;
			o.scrollSpeed		= o.scrollSpeed || 20;

			ui.instance.overflowY = function(el) {
				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-y'))) return el; el = el.parent(); } while (el[0].parentNode);
				return $(document);
			}(this);
			ui.instance.overflowX = function(el) {
				do { if(/auto|scroll/.test(el.css('overflow')) || (/auto|scroll/).test(el.css('overflow-x'))) return el; el = el.parent(); } while (el[0].parentNode);
				return $(document);
			}(this);
		},
		drag: function(e, ui) {
			
			var o = ui.options;
			var i = ui.instance;

			if(i.overflowY[0] != document && i.overflowY[0].tagName != 'HTML') {
				if(i.overflowY[0].offsetHeight - (ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity)
					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop + o.scrollSpeed;
				if((ui.position.top - i.overflowY[0].scrollTop + i.clickOffset.top) < o.scrollSensitivity)
					i.overflowY[0].scrollTop = i.overflowY[0].scrollTop - o.scrollSpeed;				
			} else {
				//$(document.body).append('<p>'+(e.pageY - $(document).scrollTop())+'</p>');
				if(e.pageY - $(document).scrollTop() < o.scrollSensitivity)
					$(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
				if($(window).height() - (e.pageY - $(document).scrollTop()) < o.scrollSensitivity)
					$(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
			}
			
			if(i.overflowX[0] != document && i.overflowX[0].tagName != 'HTML') {
				if(i.overflowX[0].offsetWidth - (ui.position.left - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity)
					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft + o.scrollSpeed;
				if((ui.position.top - i.overflowX[0].scrollLeft + i.clickOffset.left) < o.scrollSensitivity)
					i.overflowX[0].scrollLeft = i.overflowX[0].scrollLeft - o.scrollSpeed;				
			} else {
				if(e.pageX - $(document).scrollLeft() < o.scrollSensitivity)
					$(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
				if($(window).width() - (e.pageX - $(document).scrollLeft()) < o.scrollSensitivity)
					$(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
			}
			
			ui.instance.recallOffset(e);

		}
	});
	
	$.ui.plugin.add("draggable", "snap", {
		start: function(e, ui) {
			
			ui.instance.snapElements = [];
			$(ui.options.snap === true ? '.ui-draggable' : ui.options.snap).each(function() {
				var $t = $(this); var $o = $t.offset();
				if(this != ui.instance.element[0]) ui.instance.snapElements.push({
					item: this,
					width: $t.outerWidth(),
					height: $t.outerHeight(),
					top: $o.top,
					left: $o.left
				});
			});
			
		},
		drag: function(e, ui) {

			var d = ui.options.snapTolerance || 20;
			var x1 = ui.absolutePosition.left, x2 = x1 + ui.instance.helperProportions.width,
			    y1 = ui.absolutePosition.top, y2 = y1 + ui.instance.helperProportions.height;

			for (var i = ui.instance.snapElements.length - 1; i >= 0; i--){

				var l = ui.instance.snapElements[i].left, r = l + ui.instance.snapElements[i].width, 
				    t = ui.instance.snapElements[i].top,  b = t + ui.instance.snapElements[i].height;

				//Yes, I know, this is insane ;)
				if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) continue;

				if(ui.options.snapMode != 'inner') {
					var ts = Math.abs(t - y2) <= 20;
					var bs = Math.abs(b - y1) <= 20;
					var ls = Math.abs(l - x2) <= 20;
					var rs = Math.abs(r - x1) <= 20;
					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height;
					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top;
					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width;
					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left;
				}
				
				if(ui.options.snapMode != 'outer') {
					var ts = Math.abs(t - y1) <= 20;
					var bs = Math.abs(b - y2) <= 20;
					var ls = Math.abs(l - x1) <= 20;
					var rs = Math.abs(r - x2) <= 20;
					if(ts) ui.position.top = t - ui.instance.offset.top + ui.instance.clickOffset.top;
					if(bs) ui.position.top = b - ui.instance.offset.top + ui.instance.clickOffset.top - ui.instance.helperProportions.height;
					if(ls) ui.position.left = l - ui.instance.offset.left + ui.instance.clickOffset.left;
					if(rs) ui.position.left = r - ui.instance.offset.left + ui.instance.clickOffset.left - ui.instance.helperProportions.width;
				}

			};
		}
	});

	//TODO: wrapHelper

})(jQuery);



/*
 * SYL image tagger jQuery extension 0.1
 *
 * Copyright (c) 2007 Denis Kuznetsov
 *
 */
 (function ($) {
    $.fn.sylImageTagger = function(options) {
        if($.metadata) {
            options = $.extend($.fn.sylImageTagger.defaultOptions, (typeof options == 'undefined' ? {} : options));
            return this.each(function(){
                var img = $('img', this);
                img.css('display', 'block');
                var sel = $('div.tag-Selection', this);
                var tal = $('#lnkTagPic', this);
                var tn = $('div.tag-New', this);
                var dr = $('div.ui-wrapper', tn);
                var ni = img.clone().removeAttr('id');
                ni.css({
                    'position': 'absolute',
                    'display': 'block',
                    'width': img.attr('width') + 'px',
                    'height': img.attr('height') + 'px'
                });
                dr.prepend(ni);
                sel.find('form').bind('submit', {i:img,tn:tn,s:sel,d:dr,ta:tal}, $.fn.sylImageTagger.onSubmit);
                if($.browser.msie) {
                    tn.css({
                        'margin-top': '-' + (img.height() + 2) + 'px',
                        'width': img.width() + 'px',
                        'height': (img.height() - 2) + 'px'
                    });
                }
                else {
                    tn.css({
                        'margin-top': '-' + img.height() + 'px',
                        'width': img.width() + 'px',
                        'height': img.height() + 'px'
                    });
                }
                if($.browser.msie && $.browser.version.number < 7) {
                    var iew = $('<div class="ie-wrapper">&nbsp;</div>');
                    iew.css({
                        'position': 'absolute',
                        'width': img.width() + 'px',
                        'height': (img.height() - 2) + 'px',
                        'display': 'block',
                        'visibility': 'visible',
                        'padding': '0',
                        'margin': '0'
                    });
                    tn.prepend(iew);
                }
                sel.find('#tag-Selection-cancel').bind('click', {i:img,tn:tn,s:sel,d:dr,ta:tal}, $.fn.sylImageTagger.onCancel);
                tal.one('click', {i:img,tn:tn,s:sel,d:dr,ta:tal}, $.fn.sylImageTagger.onAddTagClick);
            });
        }
        else if(widnow.console) {
            window.console.log('Metadata plugin required!');
        }
    };

    $.fn.sylImageTagger.onAddTagClick = function(e) {
        var i = $(e.data.i);
        var tn = $(e.data.tn);
        var sel = $(e.data.s);
        var dr = $(e.data.d);
        tn.prevAll('div.tag-Overlay').css({
            'visibility': 'hidden',
            'display': 'none'
        });
        tn.show();
        var drt = Math.round(i.height()/2 - $.fn.sylImageTagger.defaultTagOptions.minHeight/2);
        var drl = Math.round(i.width()/2 - $.fn.sylImageTagger.defaultTagOptions.minWidth/2);
        dr.css({
            'width': $.fn.sylImageTagger.defaultTagOptions.minWidth + 'px',
            'height': $.fn.sylImageTagger.defaultTagOptions.minHeight + 'px',
            'top': drt + 'px',
            'left': drl + 'px'
        });
        dr.children('img').css({
            'margin-top': '-' + drt + 'px',
            'margin-left': '-' + drl + 'px'
        });
        sel.show().css({
            'margin-top': '-' + Math.round(i.height() - (i.height()/2 - $.fn.sylImageTagger.defaultTagOptions.minHeight/2) + 3) + 'px',
            'margin-left': Math.round(i.width()/2 - $.fn.sylImageTagger.defaultTagOptions.minWidth/2 + $.fn.sylImageTagger.defaultTagOptions.minWidth + 6) + 'px'
        });
        var reo = {};
        reo.maxWidth = i.width();
        reo.maxHeight = i.height();
        reo.containment = tn;
        reo.start = $.sylImageTagger.startModification;
        reo.resize = $.sylImageTagger.moveBackground;
        reo.stop = $.sylImageTagger.stopModification;
        reo = $.extend($.fn.sylImageTagger.defaultTagOptions, reo);
        var dro = {};
        dro.containment = tn;
        dro.start = $.sylImageTagger.startModification;
        dro.drag = $.sylImageTagger.moveBackground;
        dro.stop = $.sylImageTagger.stopModification;
        dr.draggable(dro);
        dr.resizable(reo);
        tn.css('visibility', 'visible');
		sel.css('visibility', 'visible');
		tn.click(function(e) {
            if(!dr.get(0).preventionFlag)
            {
                var x = e.pageX;
    			var y = e.pageY;
    			var of = tn.offset();
    			x = Math.round(x - $(this).offset().left - dr.width()/2);
       			y = Math.round(y - $(this).offset().top - dr.height()/2);
    			if (x < 0) {
                    x = 0;
                }
    			if (y < 0) {
                    y = 0;
                }
    			if (x > tn.width() - dr.width()) {
                    x = tn.width() - dr.width() - 1;
                }
    			if (y > tn.height() - dr.height()) {
                    y = tn.height() - dr.height() - 1;
                }
    			dr.css({
    				'top': y + 'px',
    				'left': x + 'px'
    			});
                dr.find('img').css({
                    'margin-top': '-' + y + 'px',
                    'margin-left': '-' + x + 'px'
                });
                var pe = {target: dr.get(0)};
                $.sylImageTagger.stopModification(pe, null);
            }
            else {
                dr.get(0).preventionFlag = false;
            }
		});

		//adding email input when start typing
		$('#tag-Selection-from').show();
		$('#tag-Selection-email').hide();
		$('#tag-text').keyup(function(e) {
			if($('#tag-text').val() !== '') {
				$('#tag-Selection-from').hide();
				$('#tag-Selection-email').show();
			}
			else {
				$('#tag-Selection-from').show();
				$('#tag-Selection-email').hide();
			}
		});
    };

    $.fn.sylImageTagger.onSubmit = function(e) {
        var d = $(e.data.d);
        var pof = d.offsetParent().offset();
        var of = d.offset();
        var opt = {};
        opt.data = {};
        opt.data.handler = 'AJAX_JSON_WSUserPictureTagManager';
        opt.data.__callHandler = 'setTag';
        opt.data.pictureId = $('#tag-Selection-pictureId', this).val();
        opt.data.x0 = of.left - pof.left;
        opt.data.y0 = of.top - pof.top;
        opt.data.x1 = opt.data.x0 + d.width();
        opt.data.y1 = opt.data.y0 + d.height();
        var checkedUser = $('div.tag-Selection-list :radio:checked', this);
        if(checkedUser.length > 0) {
            opt.data.userIdTo = checkedUser.val();
            opt.data.text = checkedUser.nextAll('label').text();
			opt.data.email = '';
        }
        else {
            opt.data.userIdTo = 0;
            opt.data.text = $('#tag-text', this).val();
			opt.data.email = $('#tag-email', this).val();
        }
        opt.callback = $.fn.sylImageTagger.onSubmitCallback;
        opt.submitEvent = $.extend({}, e);
        $.mrAjax(opt);
    };

    $.fn.sylImageTagger.onSubmitCallback = function(stat, data) {
        var e = this.submitEvent;
        $.fn.sylImageTagger.removeTagFrame(e);
        if(data.Response == '1' || data.Response == 1) {
            var tc = $('#user-picture-tags');
            var i = $('#user-gallery-image');
            var ov = i.children('div.tag-Overlay');
            ov.css({
                'display': 'block',
                'visibility': 'visible'
            });
            var tf = $('div.tag-Frame', i);
            var nti = tc.find('li:last-child');
            $.sylImageTaggerInitTag(nti, tf, i);
            $.sylImageTaggerOverlayInit(ov, nti);
            tc.parent().show();
        }
    };

    $.fn.sylImageTagger.onCancel = function(e) {
        $.fn.sylImageTagger.removeTagFrame(e);
    };

    $.fn.sylImageTagger.removeTagFrame = function(e) {
        var m = $('#user-gallery-image');
        var tn = m.find('div.tag-New');
        var dr = tn.find('div.ui-wrapper');
        var sel = m.find('div.tag-Selection');
        var tal = m.find('#lnkTagPic');
        tn.css({
            'visibility': 'hidden',
            'display': 'none'
        });
        sel.css({
            'visibility': 'hidden',
            'display': 'none'
        });
        m.children('div.tag-Overlay').css({
            'display': 'block',
            'visibility': 'visible'
        });
        sel.find(':radio:checked').removeAttr('checked');
        sel.find(':text').val('');
        $(['l', 'r', 't', 'b']).each(function(){
            sel.removeClass('tag-Selection-arrow-' + this);
        });
        sel.addClass('tag-Selection-arrow-l');
        dr.resizableDestroy();
        dr.draggableDestroy();
        tal.one('click', e.data, $.fn.sylImageTagger.onAddTagClick);
    };

    $.sylImageTagger = {};

    $.sylImageTagger.moveBackground = function(e, ui) {
        var $this = $(this);
        if(e.type == 'resize' && ui.axis != 'e' && ui.axis != 'se' && ui.axis != 's') {
            var pof = $this.offsetParent().offset();
            var of = $this.offset();
            $this.find('img').css({
                'margin-top': '-' + (of.top - pof.top) + 'px',
                'margin-left': '-' + (of.left - pof.left) + 'px'
            });
        }
        else if (e.type == 'drag') {
            $this.find('img').css({
                'margin-top': '-' + (ui.position.top) + 'px',
                'margin-left': '-' + (ui.position.left) + 'px'
            });
        }
    };

    $.sylImageTagger.startModification = function(e, ui) {
        e.stopPropagation();
        $(this).parents('#user-gallery-image').find('div.tag-Selection').hide();
        $(this).get(0).preventionFlag = true;
    };

    $.sylImageTagger.stopModification = function(e, ui) {
        var elm = typeof e.type == 'undefined' ? $(e.target) : $(this);
        var c = elm.parents('#user-gallery-image');
        var l = c.find('div.tag-Selection');
        var i = c.find('img');
        var r = elm;
        var pof = elm.offsetParent().offset();
        var pw = elm.offsetParent().width();
        var ph = elm.offsetParent().height();
        var of = elm.offset();
        var x0 = of.left - pof.left;
        var y0 = of.top - pof.top;
        var x1 = x0 + elm.width();
        var y1 = y0 + elm.height();
        $(['l', 'r', 't', 'b']).each(function(){
            l.removeClass('tag-Selection-arrow-' + this);
        });
        l.css('visibility', 'hidden').show();
        if((x0 + (x1 - x0)/2) <= pw/2) {
            l.addClass('tag-Selection-arrow-l');
            l.css({
                'margin-top': '-' + ((ph - y0) + 3) + 'px',
                'margin-left': (x1 + 6) + 'px'
            });
        }
        else {
            l.addClass('tag-Selection-arrow-r');
            l.css({
                'margin-top': '-' + ((ph - y0) + 3) + 'px',
                'margin-left': Math.round(x0 - l.width() - 13) + 'px'
            });
        }
        l.css('visibility', 'visible');
    };

    $.fn.sylImageTagger.defaultTagOptions = {
        minWidth: 50,
        minHeight: 50,
        maxWidth: 500,
        maxHeight: 500
    };

    $.sylImageTagger.beforeRemoveTag = function(id) {
		if (confirm('TEXT_CONFIRM_DELETE_IMAGE_TAG'.translate())) {
			var t = $('#tag-lnkRemove-' + id);
			var opt = {};
			opt.data = t.metadata();
			$.mrAjax(opt);
    	}
    };

    $.sylImageTaggerRemoveTag = function(id) {
        var t = $('#user-picture-tag-' + id), ov;
        if(t.length > 0) {
            var td = t.metadata();
            ov = $('#user-gallery-image>div.tag-Overlay');
            var p = t.parent();
            $('*', t).unbind();
            t.remove();
            $('#user-gallery-image div.tag-Frame').css({
                'visibility': 'hidden',
                'display': 'none'
            });
            if(p.find('li').length === 0) {
                p.parents('div.addTags').hide();
            }
            if(ov.length > 0) {
                ov = ov.get(0);
                var tda = ov.tagData;
                if(typeof tda != 'undefined' && tda.length > 0) {
                    var newtda = [];
                    $(tda).each(function(){
                        if(this.x0 != td.x0 || this.x1 != td.x1 || this.y0 != td.y0 || this.y1 != td.y1) {
                            newtda.push(this);
                        }
                        else {
                            $(this.f).remove();
                        }
                    });
                    ov.tagData = newtda;
                }
            }
        }
    };

    $.sylImageTaggerInitTag = function(tag, frame, img) {
        var d = {f:frame,o:tag.metadata(),i:img};
        tag.bind('mouseover', d, function(e){
            $(e.data.f).show();
            $(e.data.f).css({
                'margin-top': '-' + (e.data.i.height() - e.data.o.y0) + 'px',
                'margin-left': e.data.o.x0 + 'px',
                'visibility': 'visible'
            });
            $('div', e.data.f).css({
                'width': ((e.data.o.x1 - e.data.o.x0 - 4) + 'px'),
                'height': ((e.data.o.y1 - e.data.o.y0 - 4) + 'px')
            });
        });
        tag.bind('mouseout', d, function(e){
            $(e.data.f).css({
                'visibility': 'hidden',
                'display': 'none'
            });
        });
    };

    $.sylImageTaggerOverlayInit = function($o, $i) {
        if($i.length > 0 && $o.length > 0 && $.metadata) {
            var o = $o.get(0);
            if (typeof o.tagData == 'undefined') {
                o.tagData = [];
            }
            $i.each(function () {
                var io = $(this).metadata();
                var un = $('.tag-UserName', this);
                if (io.x0 && io.x1 && io.y0 && io.y1 && un.text().length > 0) {
                    var f = $('<div class="frame"></div>').css({
                        'visibility': 'hidden',
                        'display': 'none',
                        'margin-top': io.y0 + 'px',
                        'margin-left': io.x0 + 'px'
                    });
                    var fi = $('<div></div>').css({
                        'width': (io.x1 - io.x0 - 2) + 'px',
                        'height': (io.y1 - io.y0 - 2) + 'px'
                    });
                    if (un.is('a[href]')) {
                        fi.append('<a href="' + un.attr('href') + '">' + un.text() + '</a>');
                    }
                    else {
                        fi.append('<span>' + un.text() + '</span>');
                    }
                    $('a,span', fi).css({
                        'min-width': (io.x1 - io.x0 - 12) + 'px'
                    });
                    if ($.browser.msie && $.browser.version.number <= 6) {
                        $('a,span', fi).css('width', (io.x1 - io.x0 - 12) + 'px');
                    }
                    f.append(fi);
                    $o.append(f);
                    io = $.extend(io, {t:un, f:f});
                    o.tagData.push(io);
                }
            });
        }
    };

    $.sylImageTaggerOverlayMouseMove = function (e) {
        var o = this;
        var $o = $(o);
        if ($o.is(':visible') && typeof o.tagData != 'undefined') {
            var to = $o.offset();
            var x = e.pageX - to.left;
            var y = e.pageY - to.top;
            $(o.tagData).each(function () {
                var f = $(this.f);
                if (x >= this.x0 && x <= this.x1 && y >= this.y0 && y <= this.y1) {
                    f.css({
                        'visibility': 'visible',
                        'display': 'block'
                    });
                }
                else {
                    f.css({
                        'visibility': 'hidden',
                        'display': 'none'
                    });
                }
            });
        }
    };
	
	/*
    $(function (e) {
        var i = $('#user-gallery-image');
        var to = i.children('div.tag-Overlay');
        var tf = $('div.tag-Frame', i);
        var tc = $('#user-picture-tags');
        var t = tc.children('li');
        i.sylImageTagger();
        i = $('img', i);
        t.each(function(){
            $.sylImageTaggerInitTag($(this), tf, i);
        });
        to.css({
            'margin-top': '-' + i.height() + 'px',
            'width': i.width() + 'px',
            'height': i.height() + 'px',
            'visibility': 'visible',
            'display': 'block'
        });
        $.sylImageTaggerOverlayInit(to, t);
        to.bind('mousemove', $.sylImageTaggerOverlayMouseMove);
    });
    */
})(jQuery);


/*
 * jQuery mrPopup plugin 0.1
 *
 * Copyright (c) 2007 Denis Kuznetsov
 *
 */

/*
 * Requires plugins: browser, dimensions, bgiframe, metadata (optional) 
 * 
 */
(function ($) {
    $.fn.mrPopup = function (options) {
        if (!$.browser.msie || ($.browser.msie && $.browser.version.number > 5.5)) {            
            // extending default options with options passed into
            options = $.extend({                
                minWidth:          100,
                minHeight:         100,
                maxWidth:          500,
                maxHeight:         500,
                content:           '',
                url:               '',
                timeout:           30,
                event:             'click',
                imgsPath:          STATIC_CONTENT_SCHEME + '/i/popup/',
                overlayClickClose: true,
                escapePressClose:  true,
                loading:           'Loading&hellip;'
            }, options);            
            $(window).unload($.fn.mrPopup.unload);            
            // let's add chainability magic :)            
            return this.each(function () {                
                var $this = $(this);                
                // extending global settings with settings from metadata plugin if it present
                var opts = $.metadata ? $.extend(options, {content: $this.attr('title')}, $this.metadata()) : options;                
                // getting all required blocks
                $(['overlay', 'loading', 'window']).each(function () {
                    ($this.get(0))[this] = $.fn.mrPopup.getPopupBlock((this.substr(0,1).toUpperCase() + this.substr(1)), opts).hide();                     
                });                
                // trying to create our custom events and attach callbacks if it present
                $(['Init', 'Ready', 'Update', 'Show', 'Close']).each(function () {
                    if (opts['on' + this]) {
                        $this.bind(('popup' + this), opts, opts['on' + this]);                                                
                    }                   
                });                
                // binding close event
                $this.bind(('popupClose'), opts, $.fn.mrPopup.close);                
                // reference to options
                this.opts = opts;                
                // attaching main event handler to element
                $this.bind(opts.event, {o:opts}, $.fn.mrPopup.init);                
            });
        }
    };    
    // initialisation
    $.fn.mrPopup.init = function (event) {		        
        var e = event.target;
        var $e = $(e);        
		$e.trigger('popupInit');
        if (event.data.o.overlayClickClose) {
            $(e.overlay).css('cursor', 'pointer').one('click', {o:event.data.o,e:$e}, function (event) {
                $(event.data.e).trigger('popupClose');
            });
            if ($.browser.msie && $.browser.version.number < 7) {
                $(e.overlay).css('cursor', 'hand');                
            }                    
        }               
        if (event.data.o.escapePressClose) {
            $(document).one('keypress', {o:event.data.o,e:$e}, function (event) {
                if (event.keyCode == 27) {
                    $(event.data.e).trigger('popupClose');
                }                
            });
        }
        $(e.overlay).show();
        $(e.loading).show();		
        $(e.window).css({
            minWidth: event.data.o.minWidth + 'px',
            maxWidth: event.data.o.maxWidth + 'px',
            minHeight: event.data.o.minHeight + 'px',
            maxHeight: event.data.o.maxHeight + 'px'
        });
        if (event.data.o.url.length > 0) {
            $(e.window).load(event.data.o.url, function (data, xml) {
                $(e.window).show();
                $e.trigger('popupReady');
                $.fn.mrPopup.setWindowSize(e);
                $.fn.mrPopup.setWindowMargins(e);
                $.fn.mrPopup.attachDefaultHandlers(e);
                $(e.window).css('visibility', 'visible');              
                $e.trigger('popupShow');                
                $(e.loading).hide();
            });                                    
        } else if (event.data.o.content.length > 0) {
            if (event.data.o.content.substr(0,1) == '#') {
                $(e.window).html($(event.data.o.content).html());
            } 
			else {
                $(e.window).html(event.data.o.content);                
            }
            $(e.window).show();
            $e.trigger('popupReady');
            $.fn.mrPopup.setWindowSize(e);
            $.fn.mrPopup.setWindowMargins(e);
            $.fn.mrPopup.attachDefaultHandlers(e);
			if ($.browser.msie && $.browser.version.number < 7) {
                $(e.window).trigger('resize');
            }
            $(e.window).css('visibility', 'visible');            
            $e.trigger('popupShow');
            $(e.loading).hide();
        }
    };    
    // default handlers
    $.fn.mrPopup.attachDefaultHandlers = function (e) {
        $('a.close,input.close,button.close', e.window).one('click', {o:e.opts,e:$(e)}, function (event) {
            $(event.data.e).trigger('popupClose');
        });        
        $(['resize', 'scroll']).each(function () {
            $(window).bind(this, {e:e}, $.fn.mrPopup.windowScrollResize);                            
        });        
    };    
    // safari, ie 6 window size
    $.fn.mrPopup.setWindowSize = function (e) {
		var opts;		
        if ($.browser.msie && $.browser.version.number < 7) {			
            opts = $(e).get(0).opts;
			$(e.window).css('width', (opts.maxWidth + 'px'));
            if ($(e.window).width() > opts.maxWidth) {
                $(e.window).css('width', (opts.maxWidth + 'px'));
            } 
			else if ($(e.window).width() < opts.minWidth) {
                $(e.window).css('width', (opts.minWidth + 'px'));
            }
        }	 
		if ($.browser.safari) {
			opts = $(e).get(0).opts;
			if (($(e.window).css('width').length) === 0) {
				$(e.window).css('width', (opts.maxWidth + 'px'));
				if ($(e.window).width() > opts.maxWidth) {
					$(e.window).css('width', (opts.maxWidth + 'px'));
				}
				else if ($(e.window).width() < opts.minWidth) {
					$(e.window).css('width', (opts.minWidth + 'px'));
				}
			}
		}
    };    
    // ie 6 window scroll resize handler
    $.fn.mrPopup.windowScrollResize = function (event) {
        $.fn.mrPopup.setWindowMargins(event.data.e);         
    };    
    // window margins
    $.fn.mrPopup.setWindowMargins = function (e) {
        if ($.browser.msie && $.browser.version.number < 7) {
            $(e.window).css('margin', '0px');
            var scrollTop = $(document).scrollTop();
            var vpHeight = $.boxModel && document.documentElement ? document.documentElement.clientHeight : document.body.clientHeight;
            var vpWidth = $.boxModel && document.documentElement ? document.documentElement.clientWidth : document.body.clientWidth;
            $(e.window).css('margin-top', ((Math.round((vpHeight - $(e.window).height()) / 2) + scrollTop) + 'px'));
            $(e.window).css('margin-left', (Math.round((vpWidth - $('.popupContainer>.m', e.window).width()) / 2) + 'px'));
        }
        else {
            $(e.window).css('top', (Math.floor(($(window).height() - $(e.window).height()) / 2 + $(document).scrollTop()) + 'px'));			
        	$(e.window).css('left', (Math.floor((($(window).width() < 1000 ? 1000 : $(window).width()) - $(e.window).width()) / 2 + ($(window).width() < 1000 ? $(document).scrollLeft() : 0)) + 'px'));
        }
    };    
    // close
    $.fn.mrPopup.close = function (event) {
        var e = event.target;        
        $([e.window, e.loading, e.overlay]).each(function () { 
            $(this).hide(); 
        }).each(function () { 
            $('*', this).unbind(); 
        });
        if ($.browser.msie && $.browser.version.number < 7) {
            $(['resize', 'scroll']).each(function () {
                $(window).unbind(this, $.fn.mrPopup.windowScrollResize);
            });
        }
    };    
    // trying to delete blocks and unbind all events to avoid memory leaks
    $.fn.mrPopup.unload = function (event) {
        if ($.browser.msie && $.browser.version.number < 7) {
            $(['resize', 'scroll']).each(function () {
                $(window).unbind(this, $.fn.mrPopup.windowScrollResize);
            });
        }
        var lrs = $('#popupWindow,#popupLoading,#popupOverlay');
        lrs.each(function () { $('*', this).unbind(); });
        lrs.unbind().remove();
    };    
    // get exists block or generate new if required block doesn't exists  
    $.fn.mrPopup.getPopupBlock = function (name, opts) {        
        var n = (typeof name == 'undefined' || (['Window', 'Overlay', 'Loading']).indexOf(name) == -1) ? 'Window' : name;
        var o = $('#popup' + n);
        if(o.length === 0) {
            o = $('<div id="popup' + n + '"></div>');
            $('body').append(o);
            switch (n) {
                case 'Overlay':
                    if ($.browser.msie && $.browser.version.number < 7) {
                        o.bgiframe().css( 'height', Math.max(parseInt($(window).height(), 10), parseInt($(document).height(), 10), (parseInt($(document.documentElement).height(), 10) - 4)) + 'px' );
                    }
                    if ($.browser.opera && $.browser.version.number < 9) {
                        o.css('background', 'transparent url(' + opts.imgsPath + 'overlay.png) fixed');
                    }
                    o.css('cursor', 'default');
                    break;
                case 'Loading':
                    o.html(opts.loading);                    
                    o.css('margin', ('-' + (Math.round(o.height()/2)) + 'px 0px 0px -' + (Math.round(o.width()/2)) + 'px'));
                    break;
            }
        }      
        return o.unbind();
    };
})(jQuery);

/*
 * jQuery mrPopup Image plugin 0.1
 *
 * Copyright (c) 2008 Denis Kuznetsov
 *
 */
/*
 * Requires plugins: browser, dimensions, bgiframe, mrpopup, mrajax, metadata
 *
 */
(function($){
    $.extend({
        mrPopupImage: {
            defaultTagOptions: {
                minWidth: 50,
                minHeight: 50,
                maxWidth: 500,
                maxHeight: 500
            },
			defaultCropOptions: {
                minWidth: 100,
                minHeight: 100
            },
            minImageWidth: 500,
            init: function(node){						
                var w = window;
                var $node = $(node);
                var options = $.extend({}, $node.metadata());
                node.options = options;
                $node.mrPopup({
                    url: '',
                    maxWidth: 180,
                    maxHeight: 800,
                    content: (
						'<div class="popupContainer popupImageContainer">' +
                    		'<div class="t clr">' +
                    			'<div class="r"></div>' +
                    			'<div class="l"></div>' +
                    		'</div>' +
                    		'<div class="m">' +
								($.browser.msie && $.browser.version.number < 7 ? '<div class="crutches"></div>' : '') +
                    			'<div class="h" style="display:none;">' +
                    				'<div class="clr">' +
                    					'<div class="close">' +
                    						'<a href="javascript:void(0)" class="close">' +
                    							'CLOSE'.translate() +
                    						'</a>' +
                    					'</div>' +
                    					'<div class="ttl"></div>' +
                    				'</div>' +
                    			'</div>' +
                    			'<div class="c cent">' +
                    				'<div class="base" style="height:150px;width:150px;">' +
                    					'<div class="tag-Overlay" style="visibility:hidden;display:none;">' +
											'<div class="tag-Overlay tag-Overlay-arrow-l" style="display:none;visibility:hidden;">' +
    											'<div class="tag-Overlay-i">' +
    												'<div class="tag-Overlay-t">&nbsp;</div>' +
    												'<div class="tag-Overlay-m">&nbsp;</div>' +
    												'<div class="tag-Overlay-b">&nbsp;</div>' +
    												'<div class="tag-Overlay-a">&nbsp;</div>' +
    											'</div>' +
    										'</div>' +
										'</div>' +
                    					'<div class="tag-Frame" style="visibility:hidden;display:none;"><div>&nbsp;</div></div>' +
                    					(options.editable ? 
										'<div class="tag-New" style="visibility:hidden;display:none;">' +
											(($.browser.msie && $.browser.version.number < 7) ? '<div class="ie-wrapper">&nbsp;</div>' : '') +
                    						'<div class="ui-wrapper">' +
                    							'<div class="ui-resizable-n ui-resizable-handle"></div>' +
							                    '<div class="ui-resizable-e ui-resizable-handle"></div>' +
							                    '<div class="ui-resizable-s ui-resizable-handle"></div>' +
							                    '<div class="ui-resizable-w ui-resizable-handle"></div>' +
							                    '<div class="ui-resizable-se ui-resizable-handle"></div>' +
							                    '<div class="ui-resizable-sw ui-resizable-handle"></div>' +
							                    '<div class="ui-resizable-ne ui-resizable-handle"></div>' +
							                    '<div class="ui-resizable-nw ui-resizable-handle"></div>' +
							                    '<div>&nbsp;</div>' +
                    						'</div>' +
                    					'</div>' +
                    					'<div class="tag-Selection tag-Selection-arrow-l" style="display:none;visibility:hidden;">' +
                    						'<div class="tag-Selection-i">' +
                    							'<div class="tag-Selection-t">&nbsp;</div>' +
                    							'<div class="tag-Selection-m">' +
								                    '<form action="javascript:void(0)" class="tag-Selection-f">' +
														'<div class="crop-Description" style="display:none;">' + 
															'Please, adjuct the crop area by resizing it and press the OK button to proceed.'.translate() + 
														'</div>' +
									                    '<div class="tag-Selection-manual">' +
									                    	'<div class="name">' +
									                    		'<label for="tag-Selection-text">' +
									                    			'Enter name'.translate() +
									                    		'</label>' +
									                    		'<input type="text" maxlength="255" name="text" class="tag-Selection-text" id="tag-text" />' +
									                    	'</div>' +
									                    	'<div class="email" style="display:none;"></div>' +
									                    '</div>' +
									                    '<div class="tag-Selection-from" id="tag-Selection-from" style="display:none;visibility:hidden;">' +
									                    	'<label class="top">' +
									                    		'or choose from your Friends'.translate() +
									                    	'</label>' +
									                    	'<div class="tag-Selection-list"></div>' +
									                    '</div>' +
									                    '<div style="display:none" class="tag-Selection-email" id="tag-Selection-email">' +
									                    	'<label for="email" class="top">' +
									                    		'Notify your friend by e-mail'.translate() +
									                    	'</label>' +
									                    	'<input type="text" maxlength="255" name="email" class="tag-Selection-text" id="tag-email" />' +
									                    '</div>' +
									                    '<div class="tag-Selection-but">' +
									                    	'<input type="submit" id="tag-Selection-submit" value="' + 'OK'.translate() + '" />' +
									                    	'\n' +
															'<input type="button" id="tag-Selection-cancel" value="' + 'Cancel'.translate() + '" />' +
															'<input type="hidden" name="pictureId" id="tag-Selection-pictureId" value="" />' +
															'<input type="hidden" name="type" id="tag-Selection-type" value="" />' +
									                    '</div>' +                    
                    								'</form>' +
                    							'</div>' +
							                    '<div class="tag-Selection-b">&nbsp;</div>' +
							                    '<div class="tag-Selection-a">&nbsp;</div>' +
                   							 '</div>' +
                    					'</div>' : '') +
                    				'</div>' +
                    			'</div>' +
                    			'<div class="f" style="display:none;"></div>' +
                    		'</div>' +
                    		'<div class="b clr">' +
                    			'<div class="r"></div>' +
                    			'<div class="l"></div>' +
                    		'</div>' +
                    	'</div>'
					),
                    onReady: function(e){
                        $(e.window).find('div.popupImageContainer div.base').css('background', 'transparent url(' + STATIC_CONTENT + '/i/gallery-loader.gif) center center no-repeat');
                        if (typeof w.syl_Cache == 'undefined') {
                            w.syl_Cache = {};
                            w.syl_Cache.users = {};
                            w.syl_Cache.users['u_' + options.userId] = {};
                            w.syl_Cache.users['u_' + options.userId].albums = {};
                        }
                        else 
                            if (typeof w.syl_Cache.users == 'undefined') {
                                w.syl_Cache.users = {};
                                w.syl_Cache.users['u_' + options.userId] = {};
                                w.syl_Cache.users['u_' + options.userId].albums = {};
                            }
                            else 
                                if (typeof w.syl_Cache.users['u_' + options.userId] == 'undefined') {
                                    w.syl_Cache.users['u_' + options.userId] = {};
                                    w.syl_Cache.users['u_' + options.userId].albums = {};
                                }
                                else 
                                    if (typeof w.syl_Cache.users['u_' + options.userId].albums == 'undefined') {
                                        w.syl_Cache.users['u_' + options.userId].albums = {};
                                    }
                        if (typeof w.syl_Cache.users['u_' + options.userId].albums['a_' + options.albumId] == 'undefined' || (options.editable && typeof w.syl_Cache.users['u_' + options.userId].friends == 'undefined')) {
                            node.req = $.mrAjax({
                                data: {
                                    handler: 'AJAX_JSON_Galleries',
                                    __callHandler: 'getAlbum',
                                    userId: options.userId,
                                    albumId: options.albumId
                                },
                                error: function(req, err){
                                    $(req.piNode).trigger('popupClose');
                                },
                                async: true,
                                piNode: node,
                                piOpts: options,
                                callback: function (stat, data) {
                                    if (stat == 'success' && typeof data.Error.Code != 'undefined' && data.Error.Code == '0') {
                                        var w = window;
                                        var that = this;
                                        if (typeof data.Response.images != 'undefined' && data.Response.images instanceof Array && data.Response.images.length > 0) {
                                            w.syl_Cache.users['u_' + this.piOpts.userId].albums['a_' + this.piOpts.albumId] = data.Response.images;
                                            $(w.syl_Cache.users['u_' + this.piOpts.userId].albums['a_' + this.piOpts.albumId]).each(function(i, v){
                                                var t = w.syl_Cache.users['u_' + that.piOpts.userId].albums['a_' + that.piOpts.albumId][i];
                                                t.obj = new Image();
                                                $(t.obj).attr('src', t.src).attr('width', t.width).attr('height', t.height).css({
                                                    'visibility': 'hidden',
                                                    'display': 'block'
                                                }).addClass('photo').bind('load', function(e){
                                                    $(this).css({
                                                        'visibility': 'inherit'
                                                    });
                                                });
                                            });
                                        }
                                        if (typeof data.Response.friends != 'undefined' && data.Response.friends instanceof Array && data.Response.friends.length > 0) {
                                            w.syl_Cache.users['u_' + this.piOpts.userId].friends = data.Response.friends;
                                        }
                                    }
                                    $.mrPopupImage.showImage.apply(this.piNode);
                                }
                            });
                        }
                        else {
                            $.mrPopupImage.showImage.apply(this);
                        }
                    },
                    onClose: function(e){
						if (node.req) {
							node.req.abort();	
						}
                        node.albumData = null;						
                        node.userFriendsData = null;
                        node.tagFriendsList = null;
                        $('#popupImageNext,#popupImagePrev').each(function(){
                            $(this).unbind();
                            $(this).remove();
                        });
						$(document).unmousewheel();
                    }
                });

                if ($node.is('.popup-image-active')) {
                    $(window).load(function(e){
						var f = function () {							
							$node.click();	
						};
                        window.setTimeout(f, 1000);
                    });
                }
            },
			findImageIdxById: function (id) {
				if (typeof this != 'undefined' && this instanceof Array && this.length > 0) {
					id = parseInt(id, 10);
					for (var i = 0; i < this.length; i++) {
						if(parseInt(this[i].id, 10) === id) {
							return i;
						}
					}
				}
				return false;
			},
            showImage: function(){
                var w = window;
                var node = this;
                var $node = $(node);
                if (typeof node.albumData == 'undefined' || node.albumData === null) {
                    node.albumData = w.syl_Cache.users['u_' + node.options.userId].albums['a_' + node.options.albumId];
                    node.albumData.currentImage = $.mrPopupImage.findImageIdxById.apply(node.albumData, [node.options.current]); 
					//node.options.current;
                }
                var pw = $(node.window);
                if (node.options.editable && pw.find('div.tag-Selection-list>div').length === 0 && (typeof node.tagFriendsList == 'undefined' || node.tagFriendsList === null)) {
                    node.userFriendsData = w.syl_Cache.users['u_' + node.options.userId].friends;
                    node.tagFriendsList = $('<div class="tag-Selection-list"></div>');
                    $(node.tagFriendsList).append(
						'<div class="tag-Selection-list-item clr">' +
                    		'<input type="radio" name="userId" id="tag-Selection-id-' + node.options.userId + '" value="' + node.options.userId + '" />\n' +
                    		'<label for="tag-Selection-id-' + node.options.userId + '">' +
                    			node.options.userName +
                    		'</label>' +
                    	'</div>'
					);
                    if (typeof node.userFriendsData != 'undefined' && node.userFriendsData instanceof Array && node.userFriendsData.length > 0) {
                        $(node.userFriendsData).each(function () {
                            $(node.tagFriendsList).append(
								'<div class="tag-Selection-list-item clr">' +
                            		'<input type="radio" name="userId" id="tag-Selection-id-' + this.id + '" value="' + this.id + '" />\n' + 
									'<label for="tag-Selection-id-' + this.id + '">' + this.name + '</label>' + 
								'</div>'
							);
                        });
                    }
                    pw.find('div.tag-Selection-list').replaceWith(node.tagFriendsList);
                }
                if (node.options.editable) {
                    pw.find('#tag-Selection-pictureId').val(node.albumData[node.albumData.currentImage].id);
                    pw.find('div.tag-Selection-list label').unbind().bind('click', function(e){
                        $(this).siblings('#' + $(this).attr('for')).trigger('click');
						$('#tag-Selection-submit').removeAttr('disabled');
                    });
					pw.find('div.tag-Selection-list input').unbind().bind('click', function(e){
						$('#tag-Selection-submit').removeAttr('disabled');
                    });
                }
                if ($(node.albumData[node.albumData.currentImage].obj).is(':hidden') && node.albumData[node.albumData.currentImage].obj.complete) {
                    $(node.albumData[node.albumData.currentImage].obj).css('visibility', 'inherit');
                }
                var img = node.albumData[node.albumData.currentImage].obj;
                var imgWidth = parseInt(node.albumData[node.albumData.currentImage].width, 10);
                var imgHeight = parseInt(node.albumData[node.albumData.currentImage].height, 10);
                pw.width((imgWidth < $.mrPopupImage.minImageWidth ? $.mrPopupImage.minImageWidth : imgWidth) + 30).css({
                    'max-width': ''
                }).css({
                    'visibility': 'hidden'
                }).find('div.popupImageContainer').css({
                    'width': ((imgWidth < $.mrPopupImage.minImageWidth ? $.mrPopupImage.minImageWidth : imgWidth) + 30) + 'px'
                }).end().find('div.base').children('img.photo').remove().end().css({
                    'width': (imgWidth < $.mrPopupImage.minImageWidth ? ($.mrPopupImage.minImageWidth - ($.mrPopupImage.minImageWidth - imgWidth)) : imgWidth) + 'px',
                    'height': imgHeight + 'px',
					'border-left': (imgWidth < $.mrPopupImage.minImageWidth ? (Math.ceil(($.mrPopupImage.minImageWidth - imgWidth) / 2) + 'px') : '0px') + ' solid #FFFFFF',
					'border-right': (imgWidth < $.mrPopupImage.minImageWidth ? (Math.floor(($.mrPopupImage.minImageWidth - imgWidth) / 2) + 'px') : '0px') + ' solid #FFFFFF'
                }).prepend(img);
                var h = pw.find('div.h');
                h.show();
                var ttl = h.find('div.ttl');
                ttl.find('a,:input,form').unbind().end()
				   .empty()
				   .append(
				       (node.options.editable ? 
					   '<a href="javascript:void(0)" class="edit-me">' + 
					       (node.albumData[node.albumData.currentImage].title.length > 0 ? 
						   node.albumData[node.albumData.currentImage].title 
						   : 'CLICK_TO_CHANGE_DESCRIPTION'.translate()) +
						   ('<span>&nbsp;</span><img style="vertical-align:middle;position:absolute;" src="' + STATIC_CONTENT_SCHEME + '/i/popup/image/icon/edit.gif" alt="Edit" />') +						   
                		'</a>' +
						'<form action="javascript:void(0)" style="display:none;">' +
							'<div class="fld">' + 
								'<input maxlength="255" type="text" class="txt" value="' + (node.albumData[node.albumData.currentImage].title.length > 0 ? node.albumData[node.albumData.currentImage].title : '') + '" />' +
							'</div>' + 
							'<div class="but">' +
								'<input type="submit" value="' + 'Save'.translate() + '" class="sbmt" />' +
								'<span>&nbsp;&nbsp;</span>' + 
								'<small><a href="javascript:void(0)" class="cancel">' + 'Cancel'.translate() + '</a></small>' +
							'</div>' +
						'</form>' : 
						'<span>' + (node.albumData[node.albumData.currentImage].title.length > 0 ? 
						node.albumData[node.albumData.currentImage].title : 
						/*'Untitled'.translate()*/'') + '</span>'
						)
					);
				ttl.find('a.edit-me').bind('click', {n:node}, function (e) {
					e.preventDefault();
					$(this).hide().next('form').show().find('input.txt').val(e.data.n.albumData[node.albumData.currentImage].title);
					$.fn.mrPopup.setWindowMargins(e.data.n);
				});
				ttl.find('a.cancel').bind('click', {n:node}, $.mrPopupImage.onEditDescriptionClick);
				ttl.find('form').bind('submit', {n:node}, function (e) {
					e.preventDefault();
					var node = e.data.n;
					var $this = $(this);
					var txt = $this.find('input.txt');
					var val = $.trim(txt.val());					
					if (val.length > 0 && val != (node.albumData[node.albumData.currentImage].title)) {
						$this.find('a.cancel').unbind().css('opacity', '0.5');
						$this.find(':input').attr('disabled', 'disabled');
						$.mrAjax({
							data: {
								handler :      'AJAX_JSON_ProcessPicture',
								__callHandler: 'saveDescription',
								id :           node.albumData[node.albumData.currentImage].id,
								desc:          val
							},
							newVal: val, 
							frm: $this, 
							piNode: node,  
							callback: function (stat, data) {
								if ((data.Error.Code == '0' || data.Error.Code === 0) && (data.Response == '1' || data.Response === 1)) {
									var lnk = this.frm.prev('a.edit-me');						
									lnk.empty().append(this.newVal + '<span>&nbsp;</span><img style="vertical-align:middle;position:absolute;" src="' + STATIC_CONTENT_SCHEME + '/i/popup/image/icon/edit.gif" alt="' + 'EDIT'.translate() + '" />');
									this.piNode.albumData[this.piNode.albumData.currentImage].title = this.newVal;
									this.frm.find(':input').removeAttr('disabled').end()
									        .find('a.cancel').css('opacity', '1').bind('click', {n:this.piNode}, $.mrPopupImage.onEditDescriptionClick).trigger('click');	
								}
								else {
									this.frm.find(':input').removeAttr('disabled').end()
								       .find('a.cancel').css('opacity', '1').bind('click', {n:req.piNode}, $.mrPopupImage.onEditDescriptionClick).trigger('click');
								}
							},
							error: function (req, err) {
								req.frm.find(':input').removeAttr('disabled').end()
								       .find('a.cancel').css('opacity', '1').bind('click', {n:req.piNode}, $.mrPopupImage.onEditDescriptionClick).trigger('click');
							}
						});						
					}
					else {
						$(this).find('a.cancel').trigger('click');
					}
				});
                var actions = h.find('ul.actions');
                if (actions.length > 0) {
                    actions.find('a').unbind();
                }
                else 
                    if (node.options.editable) {
                        h.append(
							'<ul class="menu menu-f-l clr actions">' +
                        		'<li><a href="javascript:void(0)" class="rotate rotate-left">' + 'Rotate left'.translate() + '</a></li>' +
                        		'<li><a href="javascript:void(0)" class="rotate rotate-right">' + 'Rotate right'.translate() + '</a></li>' +
                        		'<li><a href="javascript:void(0)" class="crop">' + 'Crop'.translate() + '</a></li>' + 
								'<li><a href="javascript:void(0)" class="add-tag">' + 'Add tag'.translate() + '</a></li>' + 
								'<li><a href="javascript:void(0)" class="delete">' + 'Delete'.translate() + '</a></li>' +
                        	'</ul>'
							+ '<div class="warning" id="popup-image-error" style="float:none; display:none;"><div id="popup-image-error-text" class="warn-text" style="width:auto;"> </div></div>'
						);
                        actions = h.find('ul.actions');
                    }
                $.mrPopupImage.attachActionHandlers.apply(actions.find('a'), [node]);
                $.mrPopupImage.addTags.apply(this);
                $.mrPopupImage.setTagsOverlay.apply(this);
                $.mrPopupImage.setImageMeta.apply(this);
                $.mrPopupImage.defaultTagOptions.maxWidth = node.albumData[node.albumData.currentImage].width;
                $.mrPopupImage.defaultTagOptions.maxHeight = node.albumData[node.albumData.currentImage].height;
                $.mrPopupImage.addTagInit.apply(this);
                $.fn.mrPopup.setWindowMargins(node);
                pw.css('visibility', 'visible');
                $.mrPopupImage.genNavBlocks.apply(this);
            },
			onEditDescriptionClick: function (e) {
				e.preventDefault();
		 		$(this).parents('form').hide().prev('a.edit-me').show();
		 		$.fn.mrPopup.setWindowMargins(e.data.n);
			},
            addTagInit: function(){
                if (this.options.editable) {
					var pw = $(this.window);
					var bs = pw.find('div.base');
                    var img = bs.children('img.photo');
                    var sel = bs.children('div.tag-Selection');
                    var tn = bs.children('div.tag-New');
                    var dr = tn.find('div.ui-wrapper');
                    tn.css({
                        'margin-top': '-' + img.height() + 'px',
                        'width': img.width() + 'px',
                        'height': img.height() + 'px'
                    });
                    if ($.browser.msie && $.browser.version.number < 7) {
						var iew = tn.children('div.ie-wrapper');						
						iew.css({
                            'position': 'absolute',
                            'width': img.width() + 'px',
                            'height': img.height() + 'px',
                            'display': 'block',
                            'visibility': 'visible',
                            'padding': '0',
                            'margin': '0'
                        });
                    }
                    sel.find('form').unbind('submit').bind('submit', {i: img, tn: tn, s: sel, d: dr, n: this}, $.mrPopupImage.onResizableSubmit)
					   .find('#tag-Selection-cancel').bind('click', {i: img, tn: tn, s: sel, d: dr, n: this}, $.mrPopupImage.onResizableCancel);
					
                }
            },            
            onStartResizableModification: function(e, ui){
                e.stopPropagation();
                $(this).parents('div.base').find('div.tag-Selection').hide();
                this.preventionFlag = true;
            },
            moveResizableBackground: function(e, ui){
                $(this).find('img').css({
                    'margin-top': '-' + (ui.instance.position.top) + 'px',
                    'margin-left': '-' + (ui.instance.position.left) + 'px'
                });
            },
            onStopResizableModification: function(e, ui){
                var elm = typeof e.type == 'undefined' ? $(e.target) : $(this);
                var c = elm.parents('div.base');
                var l = c.find('div.tag-Selection');
                var i = c.find('img.photo');
                var r = elm;
                var pof = elm.offsetParent().offset();
                var pw = elm.offsetParent().width();
                var ph = elm.offsetParent().height();
                var of = elm.offset();
                var x0 = of.left - pof.left;
                var y0 = of.top - pof.top;
                var x1 = x0 + elm.width();
                var y1 = y0 + elm.height();
                $(['l', 'r', 't', 'b']).each(function(){
                    l.removeClass('tag-Selection-arrow-' + this);
                });
                l.css('visibility', 'hidden').show();
                if ((x0 + (x1 - x0) / 2) <= pw / 2) {
                    l.addClass('tag-Selection-arrow-l');
                    l.css({
                        'margin-top': '-' + ((ph - y0) + 3) + 'px',
                        'margin-left': (x1 + 6) + 'px'
                    });
                }
                else {
                    l.addClass('tag-Selection-arrow-r');
                    l.css({
                        'margin-top': '-' + ((ph - y0) + 3) + 'px',
                        'margin-left': Math.round(x0 - l.width() - 13) + 'px'
                    });
                }
                l.css('visibility', 'visible');
            },
            onResizableSubmit: function (e) {
                $(this).find(':input').attr('disabled', true).trigger('blur');
                $(this).find('div.tag-Selection-but').addClass('tag-Selection-but-process');
				var type = $(this).find('#tag-Selection-type').val();
                var n = e.data.n;
                var d = $(e.data.d);
                var pof = d.offsetParent().offset();
                var of = d.offset();
				var opt = {};
                opt.data = {};
				switch (type) {
					case 'tag':
						opt.data.handler = 'AJAX_JSON_WSUserPictureTagManager';
                		opt.data.__callHandler = 'setTag';
						var checkedUser = $('div.tag-Selection-list :radio:checked', this);
		                if (checkedUser.length > 0) {
		                    opt.data.userIdTo = checkedUser.val();
		                    opt.data.text = checkedUser.nextAll('label').text();
		                    opt.data.email = '';
		                }
		                else {
		                    opt.data.userIdTo = 0;
		                    opt.data.text = $('#tag-text', this).val();
		                    opt.data.email = $('#tag-email', this).val();
		                }
						opt.data.pictureId = $('#tag-Selection-pictureId', this).val();
		                opt.callback = $.mrPopupImage.onAddTagSubmitCallback;								                
						break;
					case 'crop':
						opt.data.handler = 'AJAX_JSON_Galleries';
                		opt.data.__callHandler = 'cropImage';
						opt.data.id_image = $('#tag-Selection-pictureId', this).val();
						opt.piNode = e.data.n;
						opt.callback = function (stat, data) {
							var n = this.piNode;
							var e = this.submitEvent;
							if (data.Error.Code == '0' || data.Error.Code === 0) {
								var d = window.syl_Cache.users['u_' + n.options.userId].albums['a_' + n.options.albumId][n.albumData.currentImage];
								var src = data.Response.url.split(/\*\*/);
								if (src instanceof Array && src.length >= 3) {
									var re = /\?+/;
									var t = new Date();
									$(d.obj).css({'opacity': '0', 'visibility': 'hidden'});
									d.src = src[2];
									d.width = data.Response.width;
									d.height = data.Response.height;
									d.tags = data.Response.tags;
									d.obj.src = src[2] + (re.test(src[2]) ? '&' : '?') + 'ts=' + (t.getTime());
									d.obj.width = data.Response.width;
									d.obj.height = data.Response.height;
									$(e.target)
										.find(':input').removeAttr('disabled').end()
										.find(':radio:checked').removeAttr('checked').end()
										.find('#tag-email,#tag-text').val('').end()
										.find('div.tag-Selection-but').removeClass('tag-Selection-but-process')
										.find('#tag-Selection-cancel').trigger('click'); 
									$.mrPopupImage.unBlockInterface.apply(n);
									$.mrPopupImage.showImage.apply(n);
									$(d.obj).css('opacity', '1');												
								}
								else {
									$.mrPopupImage.unBlockInterface.apply(n);												
								}																																												
							}
							else {
								$.mrPopupImage.unBlockInterface.apply(n);											
							}
                        };
						break;
				}					                        
                opt.data.x0 = of.left - pof.left;
                opt.data.y0 = of.top - pof.top;
                opt.data.x1 = opt.data.x0 + d.width();
                opt.data.y1 = opt.data.y0 + d.height();
				opt.dataSource = opt.data;
				opt.submitEvent = $.extend({}, e);	                
                n.req = $.mrAjax(opt);
            },
            onAddTagSubmitCallback: function(stat, data){
                var e = this.submitEvent;
                var node = e.data.n;
                if (data.Response !== '0' && data.Response !== 0) {
                    var tagData = {};
                    var f = $('<div class="frame"></div>').css({
                        'visibility': 'hidden',
                        'display': 'none',
                        'top': this.dataSource.y0 + 'px',
                        'left': this.dataSource.x0 + 'px'
                    });
                    var fi = $('<div></div>').css({
                        'width': (this.dataSource.x1 - this.dataSource.x0 - 2) + 'px',
                        'height': (this.dataSource.y1 - this.dataSource.y0 - 2) + 'px'
                    });
                    var found = false, userData;
					var that = this;
                    if (this.dataSource.userIdTo > 0) {
                        $(node.userFriendsData).each(function(){
                            if (parseInt(this.id, 10) == parseInt(that.dataSource.userIdTo, 10)) {
                                found = true;
                                userData = this;
                            }
                        });
                        if (!found && (parseInt(this.dataSource.userIdTo, 10) == parseInt(node.options.userId, 10))) {
                            found = true;
                            userData = {
                                'id': node.options.userId,
                                'name': node.options.userName,
                                'url': node.options.userUrl
                            };
                        }
                    }
                    tagData.id = parseInt(data.Response, 10);
                    tagData.pictureId = this.dataSource.pictureId;
                    tagData.userId = node.options.userId;
                    tagData.x0 = this.dataSource.x0;
                    tagData.x1 = this.dataSource.x1;
                    tagData.y0 = this.dataSource.y0;
                    tagData.y1 = this.dataSource.y1;
                    if (found) {
                        tagData.text = userData.name;
                        tagData.userIdTo = userData.id;
                        tagData.userUrl = userData.url;
                    }
                    else {
                        tagData.text = this.dataSource.text;
                        tagData.userIdTo = '0';
                        tagData.userUrl = '';
                    }
                    var ct = window.syl_Cache.users['u_' + node.options.userId].albums['a_' + node.options.albumId][node.albumData.currentImage];
                    if (typeof ct.tags == 'undefined' || !(ct.tags instanceof Array)) {
                        ct.tags = [];
                    }
                    ct.tags.push(tagData);
                    if (typeof tagData.userUrl == 'undefined' || tagData.userUrl.length === 0) {
                        fi.append('<span>' + tagData.text + '</span>');
                    }
                    else {
                        fi.append('<a href="' + tagData.userUrl + '">' + tagData.text + '</a>');
                    }
                    $('a,span', fi).css({
                        'min-width': (tagData.x1 - tagData.x0 - 12) + 'px'
                    });
                    if ($.browser.msie && $.browser.version.number <= 6) {
                        $('a,span', fi).css('width', (tagData.x1 - tagData.x0 - 12) + 'px');
                    }
                    f.append(fi);
                    var frame = $(node.window).find('div.base>div.tag-New');
                    var tags = $(node.window).find('div.tags');
                    var tag = $('<span class="tag" id="tag-' + tagData.id + '">' +
                    	(typeof tagData.userUrl != 'undefined' && tagData.userUrl.length > 0 ? ('<a href="' + tagData.userUrl + '">' + tagData.text + '</a>') : tagData.text) +
                    	(node.options.editable ? '<span>&nbsp;</span>' + '<small>(<a href="javascript:void(0)" class="remove">' + 'remove'.translate() + '</a>)</small></span>' : '')
					);
					tag.find('a.remove').one('click', {n:node}, $.mrPopupImage.onRemoveTagClick);
					var o = $(e.data.i).siblings('div.tag-Overlay').append(f).get(0);
                    if (tags.length > 0) {
                        tags.append('<span>, </span>').append(tag);
                    }
                    else {
                        tags = $('<div class="tags"><span>' + 'On this photo:'.translate() + '&nbsp;</span></div>');
						tags.append(tag);
						$(node.window).find('div.f').prepend(tags);                        
                    }
                    tag[0].options = tagData;
                    if (typeof o.tagData == 'undefined' || !(o.tagData instanceof Array)) {
                        o.tagData = [];
                    }
                    o.tagData.push($.extend({
                        'f': f,
                        't': tag[0]
                    }, tagData));
                    tag.css('cursor', 'pointer')
					   .bind('mouseover', {f: frame, i: $(e.data.i), n: node}, $.mrPopupImage.onTagListItemMouseOver)
					   .bind('mouseout', {f: frame}, $.mrPopupImage.onTagListItemMouseOut);
                }
                $(e.target)
					.find(':input').removeAttr('disabled').end()
					.find(':radio:checked').removeAttr('checked').end()
					.find('#tag-email,#tag-text').val('').end()
					.find('div.tag-Selection-but').removeClass('tag-Selection-but-process').find('#tag-Selection-cancel').trigger('click');
				$.fn.mrPopup.setWindowMargins(node);
            },
			onRemoveTagClick: function (e) {			
				var node = e.data.n;
				var pw = $(node.window);
				var $t = $(this).parents('span.tag').trigger('mouseout').unbind();
				var t = $t.get(0);
				var tags = window.syl_Cache.users['u_' + node.options.userId].albums['a_' + node.options.albumId][node.albumData.currentImage].tags, index = -1;
				$(tags).each(function (i, v) {
					if (parseInt(v.id, 10) == parseInt(t.options.id, 10)) {
						index = i;
					}					
				});
				if (index > -1) {
					$.mrPopupImage.blockInterface.apply(node);
					node.req = $.mrAjax({
						data: {
							'handler': 'AJAX_JSON_WSUserPictureTagManager',
							'__callHandler': 'removeTag',
							'pictureId': node.albumData[node.albumData.currentImage].id,
							'tagId': t.options.id,
							'picOwner': 1
						},
						clickEvent: $.extend({}, e),
						error: function(req, err){
							$(req.piNode).trigger('popupClose');
						},
						async: true,
						piNode: node,
						tags: tags,
						tag: $t,
						tagIndex: index,
						callback: function (stat, data) {
							var pw = $(this.piNode.window);
							this.tags.splice(this.tagIndex, 1);
							var $o = pw.find('div.base>div.tag-Overlay');
							var o = $o.get(0);
							o.tagData[this.tagIndex].f.remove();
							o.tagData.splice(this.tagIndex, 1);
							var alone = (this.tag.siblings('span.tag').length === 0);														
							if (alone) {
								this.tag.parent('div.tags').remove();
							}
							else {
								if (this.tag.nextAll('span.tag').length === 0) {
									this.tag.prev('span:contains(, )').remove().end().remove();
								}
								else {
									this.tag.next('span:contains(, )').remove().end().remove();
								}	
							}
							$.fn.mrPopup.setWindowMargins(this.piNode);
							$.mrPopupImage.unBlockInterface.apply(this.piNode);
						}
					});				
				}							 
			},
            onResizableCancel: function (e) {
                var i = e.data.i;
                var n = e.data.n;
                var m = i.parent();
                var tn = e.data.tn;
                var dr = e.data.d;
                var sel = e.data.s;
                tn.css({
                    'visibility': 'hidden',
                    'display': 'none'
                });
                sel.css({
                    'visibility': 'hidden',
                    'display': 'none'
                });
                m.children('div.tag-Overlay').css({
                    'display': 'block',
                    'visibility': 'visible'
                });
                sel.find(':radio:checked').removeAttr('checked');
                sel.find(':text').val('');
                $(['l', 'r', 't', 'b']).each(function(){
                    sel.removeClass('tag-Selection-arrow-' + this);
                });
                sel.addClass('tag-Selection-arrow-l');
                dr.resizable('destroy');
                dr.draggable('destroy');
                $.mrPopupImage.unBlockInterface.apply(n);
            },
            setImageLoadHandler: function(){
                $('#popupWindow div.popupImageContainer img.photo').unbind().bind('load', {
                    node: this
                }, function(event){
                    $(this).css({
                        'visibility': 'visible'
                    });
                });
            },
            setTagsOverlay: function() {
                var that = this;
                var $o = $(this.window).find('div.popupImageContainer div.base>div.tag-Overlay').css({
                    'margin-top': ('-' + this.albumData[this.albumData.currentImage].height + 'px'),
                    'height': (this.albumData[this.albumData.currentImage].height + 'px'),
                    'width': (this.albumData[this.albumData.currentImage].width + 'px'),
                    'visibility': 'visible',
                    'display': 'block'
                }).unbind().find('div.frame').unbind().remove().end().bind('mousemove', $.mrPopupImage.onTagsOverlayMouseMove).bind('mouseout', $.mrPopupImage.onTagsOverlayMouseMove);                
                if (typeof this.albumData[this.albumData.currentImage].tags != 'undefined' && this.albumData[this.albumData.currentImage].tags instanceof Array && this.albumData[this.albumData.currentImage].tags.length > 0 && $o.length > 0) {
                    var o = $o.get(0), f, fi, io;
                    o.tagData = [];
                    $(this.albumData[this.albumData.currentImage].tags).each(function(){
                        f = $('<div class="frame"></div>').css({
                            'visibility': 'hidden',
                            'display': 'none',
                            'top': this.y0 + 'px',
                            'left': this.x0 + 'px'
                        });
                        fi = $('<div></div>').css({
                            'width': (this.x1 - this.x0 - 2) + 'px',
                            'height': (this.y1 - this.y0 - 2) + 'px'
                        });
                        if (typeof this.userUrl == 'undefined' || this.userUrl.length === 0) {
                            fi.append('<span>' + this.text + '</span>');
                        }
                        else {
                            fi.append('<a href="' + this.userUrl + '">' + this.text + '</a>');
                        }
                        $('a,span', fi).css({
                            'min-width': (this.x1 - this.x0 - 12) + 'px'
                        });
                        if ($.browser.msie && $.browser.version.number <= 6) {
                            $('a,span', fi).css('width', (this.x1 - this.x0 - 12) + 'px');
                        }
                        f.append(fi);
                        $o.append(f);
                        o.tagData.push($.extend({}, this, {
                            t: $('#popupWindow #tag-' + this.id),
                            f: f
                        }));
                    });
                }
            },
            onTagsOverlayMouseMove: function(e){
                var o = this;
                var $o = $(o);
                if ($o.is(':visible') && typeof o.tagData != 'undefined' && o.tagData instanceof Array && o.tagData.length > 0) {
                    var to = $o.offset();
                    var x = e.pageX - to.left;
                    var y = e.pageY - to.top;
                    $(o.tagData).each(function(){
                        var f = $(this.f);
                        if (x >= this.x0 && x <= this.x1 && y >= this.y0 && y <= this.y1) {
                            f.css({
                                'visibility': 'visible',
                                'display': 'block'
                            });
                        }
                        else {
                            f.css({
                                'visibility': 'hidden',
                                'display': 'none'
                            });
                        }
                    });
                }
            },
            onTagsOverlayMouseOut: function(e){
                if (e.target === this) {
                    $(this).find('div.frame:visible').css({
                        'visibility': 'hidden',
                        'display': 'none'
                    });
                }
            },
            setImageMeta: function(){
                var context = $(this.window).find('div.f');
                var meta = $('<div class="meta clr">' +
                (typeof this.albumData[this.albumData.currentImage].addCommentUrl != 'undefined' ? ('<div class="comments">' +
                ((typeof this.albumData[this.albumData.currentImage].totalComments != 'undefined' && typeof this.albumData[this.albumData.currentImage].commentsUrl != 'undefined' && parseInt(this.albumData[this.albumData.currentImage].totalComments, 10) > 0) ? ('<a href="' + this.albumData[this.albumData.currentImage].commentsUrl + '">' + '%num% comments'.translate({
                    num: this.albumData[this.albumData.currentImage].totalComments
                }) + '</a>&nbsp;&nbsp;'+((this.options.editable)?'&nbsp;|&nbsp;':'')) : ('')) +
                ((this.albumData[this.albumData.currentImage].canAddComment)?('<a href="' + this.albumData[this.albumData.currentImage].addCommentUrl + '">' + 'Post a comment'.translate() + '</a>') : '') +
                '</div>') : '') +
                '<div class="counter">' +
                '%current% of %total%'.translate({
                    current: (this.albumData.currentImage + 1),
                    total: this.albumData.length
                }) +
                '</div>' +
                '</div>');
                var oMeta = context.find('div.meta');
                if (oMeta.length > 0) {
                    oMeta.replaceWith(meta);
                }
                else {
                    context.append(meta);
                }
            },
            addTags: function(){
                var context = $(this.window).find('div.popupImageContainer');
                var node = this;
                var t = context.find('div.tags');
                if (this.albumData[this.albumData.currentImage].tags instanceof Array) {
                    var tagsLength = this.albumData[this.albumData.currentImage].tags.length;
                    var that = this;
                    var tags = $('<div class="tags"><span>' + 'On this photo:'.translate() + '&nbsp;</span></div>'), tag, d;
                    var img = $('img.photo', context);
                    var frame = context.find('div.tag-Frame');
                    $(this.albumData[this.albumData.currentImage].tags).each(function(idx, val){
                        tag = $(
							'<span class="tag" id="tag-' + val.id + '">' +
                        		(typeof val.userUrl != 'undefined' && val.userUrl.length > 0 ? ('<a href="' + val.userUrl + '">' + val.text + '</a>') : val.text) +
                        		(that.options.editable ? 
								'<span> </span>' +
                        		'<small>(<a href="javascript:void(0)" class="remove">' + 'remove'.translate() + '</a>)</small>' : 
								'') +
							'</span>' +
                        	(tagsLength > idx + 1 ? '<span>, </span>' : ''));
                        	$(tags).append(tag);
                        	tag[0].options = val;
	                        $(tag[0])
								.css('cursor', 'pointer')
								.bind('mouseover', {f: frame, i: img, n: node }, $.mrPopupImage.onTagListItemMouseOver)
								.bind('mouseout', {f: frame}, $.mrPopupImage.onTagListItemMouseOut);
                    });
                    if (t.length > 0) {
                        t.find('span.tag,a.remove').unbind();
                        if (tagsLength > 0) {
                            t.replaceWith(tags);
                        }
                        else {
                            t.remove();
                        }
                    }
                    else 
                        if (tagsLength > 0) {
                            context.find('div.f').prepend(tags);
                        }
					tags.find('a.remove').one('click', {n:node}, $.mrPopupImage.onRemoveTagClick);
                }
                else 
                    if (t.length > 0) {
                        t.find('span.tag,a.remove').unbind().end().remove();
                    }
                context.find('div.f').show();
            },
            onTagListItemMouseOver: function(e){
                var node = e.data.n;
                $(this).addClass('tag-over');
                $(e.data.f).show();
                $(e.data.f).css({
                    'margin-top': '-' + (e.data.i.height() - this.options.y0) + 'px',
                    'margin-left': this.options.x0 + 'px',
                    'visibility': 'visible'
                });
                $('div', e.data.f).css({
                    'width': ((this.options.x1 - this.options.x0 - 4) + 'px'),
                    'height': ((this.options.y1 - this.options.y0 - 4) + 'px')
                });
            },
            onTagListItemMouseOut: function(e){
                $(this).removeClass('tag-over');
                $(e.data.f).css({
                    'visibility': 'hidden',
                    'display': 'none'
                });
            },
            attachActionHandlers: function(node){
                if (this.length > 0) {
                    this.each(function(){
                        var $this = $(this);
                        if ($this.is('a.rotate')) {
                            $this.bind('click', {
                                node: node
                            }, function(event){
                                var node = event.data.node;
                                $.mrPopupImage.blockInterface.apply(node);
								var d = {
                                    handler: 'AJAX_JSON_Galleries',
                                    __callHandler: 'rotateImage',
                                    angle: ($this.is('.rotate-left') ? 270 : 90),
                                    id_image: node.albumData[node.albumData.currentImage].id
                                }; 
                                var options = {
                                    data: d,
									piNode: node,
                                    callback: function (stat, data) {
										var n = this.piNode;
										if ((data.Error.Code == '0' || data.Error.Code === 0)&&(typeof data.Response.error == 'undefined')) {
											var d = window.syl_Cache.users['u_' + n.options.userId].albums['a_' + n.options.albumId][n.albumData.currentImage];
											var src = data.Response.url.split(/\*\*/);
											if (src instanceof Array && src.length >= 3) {
												var re = /\?+/;
												var t = new Date();
												$(d.obj).css({'opacity': '0', 'visibility': 'hidden'});
												d.src = src[2];
												d.width = data.Response.width;
												d.height = data.Response.height;
												d.tags = data.Response.tags;
												d.obj.src = src[2] + (re.test(src[2]) ? '&' : '?') + 'ts=' + (t.getTime());
												d.obj.width = data.Response.width;
												d.obj.height = data.Response.height; 
												$.mrPopupImage.unBlockInterface.apply(n);
												$.mrPopupImage.showImage.apply(n);
												$(d.obj).css('opacity', '1');												
												jQuery('#popup-image-error').hide(200);
											}
											else {
												$.mrPopupImage.unBlockInterface.apply(n);												
											}																																												
										}
										else {
											if (data.Response.error>0) {
												jQuery('#popup-image-error').show(200);
												jQuery('#popup-image-error-text').text(data.Response.message);
											}
											$.mrPopupImage.unBlockInterface.apply(n);											
										}
                                    }
                                };
                                $.mrAjax(options);
                            });
                        }
                        if ($this.is('a.crop')) {
                        	$this.bind('click', {node: node}, function (e) {								
                                e.preventDefault();
								$.mrPopupImage.blockInterface.apply(e.data.node);
								$.mrPopupImage.onAddResizableClick.apply(e.data.node, [e]);
                            });
                        }
                        if ($this.is('a.add-tag')) {
                            $this.bind('click', {node: node}, function (e) {
                                e.preventDefault();
                                $.mrPopupImage.blockInterface.apply(e.data.node);
                                $.mrPopupImage.onAddResizableClick.apply(e.data.node, [e]);
								$('#tag-Selection-submit').attr('disabled', 'disabled');
                            });
                        }
                        if ($this.is('a.delete')) {
                        	$this.bind('click', {node:node}, function (e) {
								e.preventDefault();
								if (confirm('DELETE_PHOTO'.translate())) {
									var n = e.data.node; 
									$.mrPopupImage.blockInterface.apply(n);
									n.req = $.mrAjax({
										data: {
											handler: 'AJAX_JSON_Galleries',
                                    		__callHandler: 'deleteImage',                                    		
                                    		id_image: n.albumData[n.albumData.currentImage].id
										},
										piNode: n,
										callback: function (stat, data) {
											var n = this.piNode;
											if ((data.Error.Code === '0' || data.Error.Code === 0) && (data.Response === '1' || data.Response === 1)) {
												var albums = window.syl_Cache.users['u_' + n.options.userId].albums;												
												var album = albums['a_' + n.options.albumId];
												var idx = n.albumData.currentImage;
												if (n.albumData.length > 1 && idx <= (n.albumData.length - 1)) {
													if (idx == (n.albumData.length - 1)) {
														n.albumData.currentImage--;																																																										
													}
													album.splice(idx, 1);
													$.mrPopupImage.genNavBlocks.apply(n);
													$.mrPopupImage.showImage.apply(n);
													$.mrPopupImage.unBlockInterface.apply(n);
												}
												else {
													albums['a_' + n.options.albumId] = undefined;
													$(n).trigger('popupClose');
													window.location.href = window.location.href.replace(/\?.*$/i, '?a=' + n.options.albumId); 
												} 																																																								
											}
											else {
												$.mrPopupImage.unBlockInterface.apply(n);											
											}
	                                    }
									});
								}
							});
                        }
                    });
                }
            },
			onAddResizableClick: function (e) {
				var type = $(e.target).is('a.crop') ? 'crop' : 'tag';
				var pw = $(this.window);
				var bs = pw.find('div.base'); 
                var i = bs.children('img.photo');
                var tn = bs.children('div.tag-New');				
                var sel = bs.children('div.tag-Selection');				
                var dr = tn.find('div.ui-wrapper');
                var ni = i.clone().removeClass('photo');				
                ni.css({
                    'position': 'absolute',
                    'display': 'block',
                    'width': i.attr('width') + 'px',
                    'height': i.attr('height') + 'px',
                    'visibility': 'visible'
                });
				var niw = $('<div class="image-wrapper"></div>').append(ni);				
                var oi = dr.find('div.image-wrapper');
                if (oi.length > 0) {
                    oi.replaceWith(niw);
                }
                else {
                    dr.prepend(niw);
                }				
                tn.prevAll('div.tag-Overlay').css({
                    'visibility': 'hidden',
                    'display': 'none'
                });
                tn.show();
                var drt = Math.round(i.height() / 2 - (type == 'crop' ? $.mrPopupImage.defaultCropOptions.minHeight : $.mrPopupImage.defaultTagOptions.minHeight) / 2);
                var drl = Math.round(i.width() / 2 - (type == 'crop' ? $.mrPopupImage.defaultCropOptions.minWidth : $.mrPopupImage.defaultTagOptions.minWidth) / 2);
                dr.css({
                    'width': (type == 'crop' ? $.mrPopupImage.defaultCropOptions.minWidth : $.mrPopupImage.defaultTagOptions.minWidth) + 'px',
                    'height': (type == 'crop' ? $.mrPopupImage.defaultCropOptions.minHeight : $.mrPopupImage.defaultTagOptions.minHeight) + 'px',
                    'top': drt + 'px',
                    'left': drl + 'px'
                });
                dr.find('img').css({
                    'margin-top': '-' + drt + 'px',
                    'margin-left': '-' + drl + 'px'
                });
                sel.show().css({
                    'margin-top': '-' + Math.round(i.height() - (i.height() / 2 - (type == 'crop' ? $.mrPopupImage.defaultCropOptions.minHeight : $.mrPopupImage.defaultTagOptions.minHeight) / 2) + 3) + 'px',
                    'margin-left': Math.round(i.width() / 2 - (type == 'crop' ? $.mrPopupImage.defaultCropOptions.minWidth : $.mrPopupImage.defaultTagOptions.minWidth) / 2 + (type == 'crop' ? $.mrPopupImage.defaultCropOptions.minWidth : $.mrPopupImage.defaultTagOptions.minWidth) + 6) + 'px'
                });
                var reo = {};
                reo.maxWidth = i.width();
                reo.maxHeight = i.height();
                reo.containment = tn;
                reo.start = $.mrPopupImage.onStartResizableModification;
                reo.resize = $.mrPopupImage.moveResizableBackground;
                reo.stop = $.mrPopupImage.onStopResizableModification;
                reo = $.extend({}, (type == 'crop' ? $.mrPopupImage.defaultCropOptions : $.mrPopupImage.defaultTagOptions), reo);
                var dro = {};
                dro.containment = tn;
                dro.start = reo.start;
                dro.drag = reo.resize;
                dro.stop = reo.stop;
                dr.draggable(dro);
                dr.resizable(reo);
                tn.css('visibility', 'visible');
                sel.css('visibility', 'visible');
                sel.find(':input').removeAttr('disabled');
                tn.unbind().bind('click', function(e){
                    if (!dr.get(0).preventionFlag) {
                        var x = e.pageX;
                        var y = e.pageY;
                        var of = tn.offset();
                        x = Math.round(x - $(this).offset().left - dr.width() / 2);
                        y = Math.round(y - $(this).offset().top - dr.height() / 2);
                        if (x < 0) {
                            x = 0;
                        }
                        if (y < 0) {
                            y = 0;
                        }
                        if (x > tn.width() - dr.width()) {
                            x = tn.width() - dr.width() - 1;
                        }
                        if (y > tn.height() - dr.height()) {
                            y = tn.height() - dr.height() - 1;
                        }
                        dr.css({
                            'top': y + 'px',
                            'left': x + 'px'
                        });
                        dr.find('img').css({
                            'margin-top': '-' + y + 'px',
                            'margin-left': '-' + x + 'px'
                        });
                        var pe = {
                            target: dr.get(0)
                        };
                        $.mrPopupImage.onStopResizableModification(pe, null);
                    }
                    else {
                        dr.get(0).preventionFlag = false;
                    }
                });	
				switch (type) {
					case 'crop':
						sel.find('form>#tag-Selection-from,form>.tag-Selection-manual,form>#tag-Selection-email').hide();		                
						sel.find('form>.crop-Description').show();
						sel.find('#tag-Selection-type').val('crop');		                								
						break;
					case 'tag':
						sel.find('form>.tag-Selection-manual').show();
						sel.find('form>#tag-Selection-from').css('visibility', 'visible').show();
		                sel.find('form>#tag-Selection-email,form>.crop-Description').hide();
		                sel.find('#tag-text').unbind().attr('autocomplete', 'off').keyup(function(e){
		                    var p = $(this).parents('.tag-Selection-manual');
		                    if ($(this).val().length > 0) {
								$('#tag-Selection-submit').removeAttr('disabled');
		                        p.siblings('#tag-Selection-from').hide().end()
								 .siblings('#tag-Selection-email').show().end()
								 .siblings('#tag-Selection-from').find(':radio:checked').removeAttr('checked');
		                    }
		                    else {
								$('#tag-Selection-submit').attr('disabled', true);
		                        p.siblings('#tag-Selection-from').show().end()
								 .siblings('#tag-Selection-email').hide().find('#tag-email').val('');
		                    }
		                });
						sel.find('#tag-Selection-type').val('tag');		
						break;
				}
				/*alert(bs.html());*/
			},
            blockInterface: function(){
                $(this.window).find('ul.actions a,div.tags span.tag,div.tags a.remove').unbind().bind('click', $.mrPopupImage.dummyHandler).bind('focus', function(e){
                    $(this).trigger('blur');
                }).trigger('blur').css('cursor', 'default').end().find('ul.actions,div.tags').css('opacity', 0.33);
            },
            unBlockInterface: function(){
                var c = $(this.window);
                var cn = c.find('ul.actions,div.tags').css('opacity', '1');
                var a = c.find('ul.actions a').unbind().css('cursor', 'pointer');
                var t = c.find('div.tags span.tag,div.tags a.remove')
				         .css('cursor', 'pointer').unbind()
				         .filter('span').css('cursor', 'pointer')
						 .find('a.remove').one('click', {n:this}, $.mrPopupImage.onRemoveTagClick).end();
                var f = c.find('div.tag-Frame');
                var i = c.find('div.base>img.photo');
                t.bind('mouseover', {f: f,i: i,n: this}, $.mrPopupImage.onTagListItemMouseOver);
				t.bind('mouseout', {f: f}, $.mrPopupImage.onTagListItemMouseOut);
                $.mrPopupImage.attachActionHandlers.apply(a, [this]);
            },
            dummyHandler: function(event){
                event.preventDefault();
            },
            genNavBlocks: function(){
                var nav = false;
                if (this.albumData.currentImage < (this.albumData.length - 1)) {
                    var next = $('#popupImageNext');
                    if (next.length > 0) {
                        next.show();
                    }
                    else {
                        next = $('<a href="javascript:void(0)" id="popupImageNext">' + 'Next'.translate() + '</a>');
                        $('#popupWindow').after(next);
                    }
                    next.bind('click', {node: this}, function (e) {
						$(e.data.node.window).find('#tag-Selection-cancel:visible').trigger('click');
                        $('#popupImagePrev').add(this).unbind();
                        e.data.node.albumData.currentImage++;
                        $.mrPopupImage.moveImage(e.data.node, 'next');
                    });
                    nav = true;
                }
                else {
                    $('#popupImageNext').hide();
                }
                if (this.albumData.currentImage > 0) {
                    var prev = $('#popupImagePrev');
                    if (prev.length > 0) {
                        prev.show();
                    }
                    else {
                        prev = $('<a href="javascript:void(0)" id="popupImagePrev">' + 'Previous'.translate() + '</a>');
                        $('#popupWindow').after(prev);
                    }
                    prev.bind('click', {
                        node: this
                    }, function(e){
                        $(e.data.node.window).find('#tag-Selection-cancel:visible').trigger('click');
                        $('#popupImageNext').add(this).unbind();
                        e.data.node.albumData.currentImage--;
                        $.mrPopupImage.moveImage(e.data.node, 'prev');
                    });
                    nav = true;
                }
                else {
                    $('#popupImagePrev').hide();
                }
				var mw = $(document).unmousewheel();				 
				if (nav) {
					mw.mousewheel($.mrPopupImage.onMouseWheel);					
				}
            },
			onMouseWheel: function (e, d) {
				if (!$(e.target).is('textarea')) {
					e.preventDefault();
					$('#popupImage' + (((!$.browser.opera && d < 0) || ($.browser.opera && d > 0)) ? 'Next' : 'Prev') + ':visible').trigger('click');	
				}
			},
            moveImage: function(node, direction){
                $.mrPopupImage.genNavBlocks.apply(node);
                $.mrPopupImage.showImage.apply(node);
            }
        }
    });
    
    // plugin entry point
    $.fn.mrPopupImage = function(){
        return this.each(function(){
            $.mrPopupImage.init(this);
        });
    };
    
    // automatic popup image plugin attach
    $(function(event){
        $('.popup-image').mrPopupImage();		
    });	
    
})(jQuery);

/**
 * jQuery.ScrollTo - Easy element scrolling using jQuery.
 * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com
 * Licensed under GPL license (http://www.opensource.org/licenses/gpl-license.php).
 * Date: 1/2/2008
 * @author Ariel Flesler
 * @version 1.3
 */
;(function($){$.scrollTo=function(a,b,c){$($.browser.safari?'body':'html').scrollTo(a,b,c)};$.scrollTo.defaults={axis:'y',duration:1};$.fn.scrollTo=function(c,d,f){if(typeof d=='object'){f=d;d=0}f=$.extend({},$.scrollTo.defaults,f);if(!d)d=f.speed||f.duration;f.queue=f.queue&&f.axis.length==2;if(f.queue)d=Math.ceil(d/2);if(typeof f.offset=='number')f.offset={left:f.offset,top:f.offset};return this.each(function(){var e=this,$e=$(e),t=c,toff,j={},w=$e.is('html,body');switch(typeof t){case'number':case'string':if(/^([+-]=)?\d+(px)?$/.test(t)){t={top:t,left:t};break}t=$(t,this);case'object':if(t.is||t.style)toff=(t=$(t)).offset()}$.each(f.axis.split(''),parse);animate(f.onAfter);function parse(i,a){var P=a=='x'?'Left':'Top',p=P.toLowerCase(),k='scroll'+P,u=e[k];if(toff){j[k]=toff[p]+(w?0:u-$e.offset()[p]);if(f.margin){j[k]-=parseInt(t.css('margin'+P))||0;j[k]-=parseInt(t.css('border'+P+'Width'))||0}if(f.offset&&f.offset[p])j[k]+=f.offset[p]}else{j[k]=t[p]}if(/^\d+$/.test(j[k]))j[k]=j[k]<=0?0:Math.min(j[k],max(a));if(!i&&f.queue){if(u!=j[k])animate(f.onAfterFirst);delete j[k]}};function animate(a){$e.animate(j,d,f.easing,function(){if(a)a.call(this,$e,j,t)})};function max(a){var b=w?$.browser.opera?document.body:document.documentElement:e,D=a=='x'?'Width':'Height';return b['scroll'+D]-b['client'+D]}})}})(jQuery);

/* Copyright (c) 2006 Brandon Aaron (brandon.aaron@gmail.com || http://brandonaaron.net)
 * Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
 * Thanks to: http://adomas.org/javascript-mouse-wheel/ for some pointers.
 * Thanks to: Mathias Bank(http://www.mathias-bank.de) for a scope bug fix.
 *
 * $LastChangedDate: 2007-12-15 07:57:10 +0200 (Сб, 15 дек 2007) $
 * $Rev: 4163 $
 *
 * Version: @VERSION
 * 
 * Requires: $ 1.2.2+
 */

(function($) {

$.event.special.mousewheel = {
	setup: function() {
		var handler = $.event.special.mousewheel.handler;
		
		// Fix pageX, pageY, clientX and clientY for mozilla
		if ( $.browser.mozilla )
			$(this).bind('mousemove.mousewheel', function(event) {
				$.data(this, 'mwcursorposdata', {
					pageX: event.pageX,
					pageY: event.pageY,
					clientX: event.clientX,
					clientY: event.clientY
				});
			});
	
		if ( this.addEventListener )
			this.addEventListener( ($.browser.mozilla ? 'DOMMouseScroll' : 'mousewheel'), handler, false);
		else
			this.onmousewheel = handler;
	},
	
	teardown: function() {
		var handler = $.event.special.mousewheel.handler;
		
		$(this).unbind('mousemove.mousewheel');
		
		if ( this.removeEventListener )
			this.removeEventListener( ($.browser.mozilla ? 'DOMMouseScroll' : 'mousewheel'), handler, false);
		else
			this.onmousewheel = function(){};
		
		$.removeData(this, 'mwcursorposdata');
	},
	
	handler: function(event) {
		var args = Array.prototype.slice.call( arguments, 1 );
		
		event = $.event.fix(event || window.event);
		// Get correct pageX, pageY, clientX and clientY for mozilla
		$.extend( event, $.data(this, 'mwcursorposdata') || {} );
		var delta = 0, returnValue = true;
		
		if ( event.wheelDelta ) delta = event.wheelDelta/120;
		if ( event.detail     ) delta = -event.detail/3;
		if ( $.browser.opera  ) delta = -event.wheelDelta;
		
		event.data  = event.data || {};
		event.type  = "mousewheel";
		
		// Add delta to the front of the arguments
		args.unshift(delta);
		// Add event to the front of the arguments
		args.unshift(event);

		return $.event.handle.apply(this, args);
	}
};

$.fn.extend({
	mousewheel: function(fn) {
		return fn ? this.bind("mousewheel", fn) : this.trigger("mousewheel");
	},
	
	unmousewheel: function(fn) {
		return this.unbind("mousewheel", fn);
	}
});

})(jQuery);

eval(function(p,a,c,k,e,r){e=function(c){return(c<a?'':e(parseInt(c/a)))+((c=c%a)>35?String.fromCharCode(c+29):c.toString(36))};if(!''.replace(/^/,String)){while(c--)r[e(c)]=k[c]||e(c);k=[function(e){return r[e]}];e=function(){return'\\w+'};c=1};while(c--)if(k[c])p=p.replace(new RegExp('\\b'+e(c)+'\\b','g'),k[c]);return p}('2(!6.G){G=5(){5 f(n){3 n<10?\'0\'+n:n}Q.C.q=5(){3 6.K()+\'-\'+f(6.I()+1)+\'-\'+f(6.1d())+\'T\'+f(6.Y())+\':\'+f(6.V())+\':\'+f(6.R())+\'Z\'};9 m={\'\\b\':\'\\\\b\',\'\\t\':\'\\\\t\',\'\\n\':\'\\\\n\',\'\\f\':\'\\\\f\',\'\\r\':\'\\\\r\',\'"\':\'\\\\"\',\'\\\\\':\'\\\\\\\\\'};5 4(b,d){9 a,i,k,l,r=/["\\\\\\1b-\\15\\12-\\11]/g,v;U(7 b){e\'u\':3 r.E(b)?\'"\'+b.o(r,5(a){9 c=m[a];2(c){3 c}c=a.P();3\'\\\\O\'+N.M(c/16).B(16)+(c%16).B(16)})+\'"\':\'"\'+b+\'"\';e\'D\':3 L(b)?A(b):\'8\';e\'J\':e\'8\':3 A(b);e\'z\':2(!b){3\'8\'}2(7 b.q===\'5\'){3 4(b.q())}a=[];2(7 b.p===\'D\'&&!(b.H(\'p\'))){l=b.p;h(i=0;i<l;i+=1){a.x(4(b[i],d)||\'8\')}3\'[\'+a.y(\',\')+\']\'}2(d){l=d.p;h(i=0;i<l;i+=1){k=d[i];2(7 k===\'u\'){v=4(b[k],d);2(v){a.x(4(k)+\':\'+v)}}}}1g{h(k F b){2(7 k===\'u\'){v=4(b[k],d);2(v){a.x(4(k)+\':\'+v)}}}}3\'{\'+a.y(\',\')+\'}\'}}3{4:4,1f:5(a,b){9 j;5 w(k,v){9 i,n;2(v&&7 v===\'z\'){h(i F v){2(18.C.14.13(v,[i])){n=w(i,v[i]);2(n!==17){v[i]=n}}}}3 b(k,v)}2(/^[\\],:{}\\s]*$/.E(a.o(/\\\\./g,\'@\').o(/"[^"\\\\\\n\\r]*"|19|1a|8|-?\\d+(?:\\.\\d*)?(:?[X][+\\-]?\\d+)?/g,\']\').o(/(?:^|:|,)(?:\\s*\\[)+/g,\'\'))){j=1c(\'(\'+a+\')\');3 7 b===\'5\'?w(\'\',j):j}W 1e S(\'1h\');}}}()}',62,80,'||if|return|stringify|function|this|typeof|null|var|||||case|||for|||||||replace|length|toJSON||||string||walk|push|join|object|String|toString|prototype|number|test|in|JSON|propertyIsEnumerable|getUTCMonth|boolean|getUTCFullYear|isFinite|floor|Math|u00|charCodeAt|Date|getUTCSeconds|SyntaxError||switch|getUTCMinutes|throw|eE|getUTCHours|||x9f|x7f|apply|hasOwnProperty|x1f||undefined|Object|true|false|x00|eval|getUTCDate|new|parse|else|parseJSON'.split('|'),0,{}))

function expandselect(id, size) {
	var select = document.getElementById(id);
	select.size = select.options.length;
}

Location =
{
defaultAcParams:
	{
		extraParams: {},
		max: 15,
		width: 312,
		cacheLength: 0,
		matchSubset: false,
		minChars: 3,
		selectFirst: false,
		moreItems: false,
		formatItem: function(row)
		{
			return row[0];
		},
		formatResult: function(row)
		{
			return row[0];
		},
		scroll: true
	},

	init: function(event)
	{
		/**
		 * @todo Implement Default Options setup for the loaction
		 */
		var defaultOptions = {};
		$this = this;
		$this.locationTextbox = (typeof defaultOptions.locationTextbox != "undefined") ? defaultOptions.locationTextbox : '#locationJQ';
		$this.locationHidden  = (typeof defaultOptions.locationHidden != "undefined") ? defaultOptions.locationHidden : '#location_id';
		$this.locationCountry = (typeof defaultOptions.locationCountry != "undefined") ? defaultOptions.locationCountry : '#locationJQCountry';
		Location.locationText = jQuery('#locationJQ').attr('value');
		if(jQuery($this.locationTextbox).length > 0)
		{
			if (typeof jQuery('#locationJQ').attr('value')== "undefined" || jQuery('#locationJQ').attr('value').length==0)
			{
				jQuery('#location_id').attr('value',jQuery('#locationJQCountry').attr('value')+'_0_0' );
			}

			locInput = jQuery($this.locationTextbox);
			locInput.bind("focus",function() {
				locInput.select();
			});

			if (jQuery($this.locationCountry).length > 0) Location.defaultAcParams.minChars = 0;

			var acParams = {
				extraParams: {
					handler: 'Locations',
					action:  'searchCitiesByName',
					limit: 20,
					countryId:  function() {
						if (jQuery($this.locationCountry).length > 0) {
							return jQuery($this.locationCountry).val();
						}
						return 0;
					}
				}
			};

			acParams = $.extend(Location.defaultAcParams, acParams);

			jQuery($this.locationTextbox).autocomplete(DOMAIN_URI+'/ajax.php', acParams);

			jQuery($this.locationTextbox).result(function(event, data, formatted) {
				var hidden = jQuery($this.locationHidden);
				hidden.val(data[1]);
				hidden.trigger('customChange');
			});

			locInput.bind("keyup",function(e) {
				if (Location.locationText!=jQuery('#locationJQ').attr('value'))
					jQuery('#location_id').attr('value',jQuery('#locationJQCountry').attr('value')+'_0_0' );
			});


			jQuery('#locationJQCountry').change(function (event) {
				jQuery('#location_id').attr('value',jQuery('#locationJQCountry').attr('value')+'_0_0' );
				jQuery('#locationJQ').attr('value','');
			});

			jQuery($this.locationTextbox).blur(function () {
				if (this.value == '') {
					jQuery('#location_id').attr('value',jQuery('#locationJQCountry').attr('value')+'_0_0' );
				}
			});


			jQuery('#selectLocation').change(function (event) {
				if (this.value == 'other') {
					jQuery('#CountryCity').show();
					if (!$.browser.msie || ($.browser.msie && $.browser.version.number > 6)) {
						expandselect('locationJQCountry');
						jQuery('#select-container').before('<select id="select-temp" size="1" class="maxWidth"><option>' + jQuery('#locationJQCountry option:selected').html() + '</option></select>');
						jQuery('#select-container').height('0');
						jQuery('#locationJQCountry').height('11.5em');
						jQuery(document).click(function() {
							if (!$.browser.msie && !$.browser.version.number == 7) {
								jQuery('#select-container').height(jQuery('#select-temp').height()+4);
							} else {
								jQuery('#select-container').height('1em');
							}
							jQuery('#locationJQCountry').attr('size', '1');
							jQuery('#locationJQCountry').height('auto');
							jQuery('#select-temp').remove();
						});
					}
					jQuery('#Location').remove();
					jQuery('#visibleCountryCity').val(1);
					
				}
			});


			if (jQuery('#visibleCountryCity').val() == 1) {
				jQuery('#CountryCity').show();
			}
		}
	}
}

jQuery(Location.init);


var syl_Chat = {
	isSessionAlive: null,
	initialize: function()
	{
	/*
		$$('a.open_chat').each
		(
			function(e)
			{
				var id = 0;
				var regex = new RegExp("[\\?&]uid=([^&#]*)");
				var results = regex.exec(e.href);
				if( results != null ) id = results[1];
				Event.observe(e, 'click', function(event)
				{
					if(oLinkToLock != null)
					{
						return;
					}
					oLinkToLock = e;
					setTimeout('oLinkToLock = null;', 5000);
					syl_Chat.chat(id);
				})
			}
		);
	*/
	},
	chat: function(uid)
	{
		this.uid = uid;
		// Check session availability 
		/*var ajax = new Ajax.Request(syl_Main.getAjaxUri(), {
			asynchronous: false,
			parameters: {
				handler: 'Session',
				action: 'getAvailability'
			},
			onSuccess: function(transport) {
				var response = transport.responseText.evalJSON();
				syl_Chat.isSessionAlive = response.sessionAvailable;
			}
		});*/
		this.isSessionAlive = true;
		if (this.isSessionAlive) {
			//if(!isNaN(oLinkToLock)){ return; }
			if(isNaN(this.uid) || this.uid < 0) { this.uid = 0; }
			//oLinkToLock = this.uid;
			setTimeout('oLinkToLock = "-";', 5000);
			window.open(DOMAIN_URI + '/chat/' + (!isNaN(this.uid) && this.uid > 0 ? '?uid='+this.uid : ''), "messenger", "width=600, height=500, resizable=1");
		}
		else {
			document.location.href = DOMAIN_URI + '/signin/';
		}
	}
};


var Wink =
{
	indicatorId : '',
	successMsgId : '',
	errorMsgId : '',
	linkId : '',

	send : function(iUserId, iOpponentId, indicatorId, successMsgId, errorMsgId, linkId)
	{
		Wink.indicatorId = indicatorId;
		Wink.successMsgId = successMsgId;
		Wink.errorMsgId = errorMsgId;
		Wink.linkId = linkId;

		if(indicatorId)
		{
			jQuery('#' + indicatorId).show();
		}

		var options = {
			url : '/messenger/index.php',
			type : 'POST',
			data : {
				rqst : JSON.stringify({
					action : 'postSystemMessage',
					userId : iUserId,
					opponentId : iOpponentId,
					type : 2,
					message : '%)'
				})
			},
			success : this.sendCallBack,
			error : function()
			{
				if(errorMsgId)
				{
					jQuery('#' + errorMsgId).show();
				}
				if(linkId)
				{
					jQuery('#' + linkId).hide();
				}
				if(indicatorId)
				{
					jQuery('#' + indicatorId).hide();
				}
			}
		};
		jQuery.ajax(options);

		/**
		 * Send email message
		 */
		jQuery.mrAjax({
			bind: 'none',
			data: {
				handler:       'AJAX_JSON_SendAWink',
				__callHandler: 'sendEmailNotification',
				userId :       iOpponentId
			}
		});
	},

	sendCallBack : function(data, status)
	{
		data = JSON.parse(data);
		if(data.iStatus == 1)
		{
			if(Wink.successMsgId)
			{
				jQuery('#' + Wink.successMsgId).show();
			}
		}
		else
		{
			if(Wink.errorMsgId)
			{
				jQuery('#' + Wink.errorMsgId).show();
			}
		}
		if(Wink.indicatorId)
		{
			jQuery('#' + Wink.indicatorId).hide();
		}
		if(Wink.linkId)
		{
			jQuery('#' + Wink.linkId).hide();
		}
	}
}


var Friendship = 
{
	indicatorId : '',
	successMsgId : '',
	errorMsgId : '',
	linkId : '',

	send : function(iUserId, iOpponentId, indicatorId, successMsgId, errorMsgId, linkId)
	{
		Wink.indicatorId = indicatorId;
		Wink.successMsgId = successMsgId;
		Wink.errorMsgId = errorMsgId;
		Wink.linkId = linkId;
		
		if(indicatorId)
		{
			jQuery('#' + indicatorId).show();
		}

		var options = {
			url : '/ajax.php?handler=Messenger',
			type : 'POST',
			data : {
				action : 'requestFriendship',
				cid : iOpponentId
			},
			success : this.sendCallBack,
			error : function()
			{
				if(errorMsgId)
				{
					jQuery('#' + errorMsgId).show();
				}
				if(linkId)
				{
					jQuery('#' + linkId).hide();
				}
				if(indicatorId)
				{
					jQuery('#' + indicatorId).hide();
				}
			}
		};
		jQuery.ajax(options);
	},
	
	sendCallBack : function(data, status)
	{
		data = JSON.parse(data);
		if(data.iStatus == 1)
		{
			if(Wink.successMsgId)
			{
				jQuery('#' + Wink.successMsgId).show();
			}
		}
		else
		{
			if(Wink.errorMsgId)
			{
				jQuery('#' + Wink.errorMsgId).show();
			}
		}
		if(Wink.indicatorId)
		{
			jQuery('#' + Wink.indicatorId).hide();
		}
		if(Wink.linkId)
		{
			jQuery('#' + Wink.linkId).hide();
		}
	}
}


var Invitation = 
{
	className : 'mail',
	inviteTypesCount : 6,
	classNames : ['mail', 'icq', 'msn', 'yahoo', 'hotmail', 'gmail'],
	typeNames : ['mail', 'icq', 'msn', 'yahoo', 'hotmail', 'gtalk'],
	resultClassName : 'stress',

	checkType : function(iType)
	{
		if(iType > this.inviteTypesCount-1 || iType < 0)
		{
			return 0;
		}
		return iType;
	},

	showInviteBlock : function(iType)
	{
		iType = this.checkType(iType);
		for(var i=0; i<this.inviteTypesCount; i++)
		{
			if(i == iType)
			{
				jQuery('#inviteBlock' + iType).show();
			}
			else
			{
				jQuery('#inviteBlock' + i).hide();
			}
		}
	},

	changeType : function(iType)
	{
		iType = this.checkType(iType);
		jQuery('#inviteTypeIcon').removeClass(this.className); 
		this.className = this.classNames[iType];
		jQuery('#inviteTypeIcon').addClass(this.className); 
		this.showInviteBlock(iType);
	},
	
	submitInvite : function()
	{
		jQuery('span.frm-main-about-cancel').hide();
		jQuery('#processingIndicator').show();
           var iType = jQuery('#frm-cnt-invite-select').val();
           var sType = this.typeNames[iType];
           if(iType > 0)
           {
            var login = jQuery('#txtLogin' + iType).val();
            var password = jQuery('#txtPassword' + iType).val();
			var options = {
				timeout: 60000,
				data: {
                    handler: 'AJAX_JSON_Invitation',
                    __callHandler: 'sendInvitation',
                    'login' : login,
                    'password' : password,
                    'type' : sType
                },
                callback: this.inviteCallBack
            };
           }
           else
           {
			var options = {
				timeout: 60000,
				data: {
                    handler: 'AJAX_JSON_Invitation',
                    __callHandler: 'searchFriends',
                    'emails' : jQuery('#frm-main-emails-desc').val()
                },
                callback: this.searchFriendsCallBack
            };
		}
		jQuery.mrAjax(options);            
	},
	
	inviteCallBack : function(status, data)
	{
		jQuery('#processingIndicator').hide();
		jQuery('#inviteFormBlock').hide();
		jQuery('#inviteResultBlock').show();
		
		jQuery('#invitationResultIcon').removeClass(this.resultClassName); 
		
		if(status == 'success' && data.Response.length == 0)
		{
			this.resultClassName = 'check';
			jQuery('#inviteResultDescriptionError').hide();
			jQuery('#inviteResultDescriptionSuccess').show(); 
			jQuery('#inviteResultText').text(jQuery('#inviteSuccessResultText').val());
		}
		else
		{
			this.resultClassName = 'stress';
			jQuery('#inviteResultDescriptionError').show(); 
			jQuery('#inviteResultDescriptionSuccess').hide(); 
			jQuery('#inviteResultText').text(data.Response);
		}
		jQuery('#invitationResultIcon').addClass(this.resultClassName); 
	},
	
	searchFriendsCallBack : function(status, data)
	{
		jQuery('#processingIndicator').hide();
		jQuery('#searchFriendsResultIcon').removeClass(this.resultClassName); 
		
		jQuery('#searchFriendsResultBlockSuccess').hide();
		jQuery('#searchFriendsResultBlockErrorLIMIT').hide();
		jQuery('#searchFriendsResultBlockErrorEMPTY').hide();
		jQuery('#searchFriendsResultBlockErrorINVALID').hide();
		jQuery('#searchFriendsResultBlockErrorDUPLICATE').hide();
		jQuery('#searchFriendsResultBlockErrorITSME').hide();
		
		var sStatus = data.Response.status;
		if(sStatus == 'SUCCESS')
		{
			jQuery('#searchFriendsResultBlockSuccess').show();
			this.resultClassName = 'check';

			var l = data.Response.response.status1.length;
			if( l > 0)
			{
				jQuery('#searchFriendsResultAddedCount').text(l);
				jQuery('#searchFriendsResultAdded').show();
			}
			else
			{
				jQuery('#searchFriendsResultAdded').hide();
			}

			var l = data.Response.response.status0.length;
			if( l > 0)
			{
				jQuery('#searchFriendsResultInvitedCount').text(l);
				jQuery('#searchFriendsResultInvited').show();
			}
			else
			{
				jQuery('#searchFriendsResultInvited').hide();
			}
		}
		else
		{
			switch(sStatus)
			{
				case 'ERROR_LIMIT':
				{
					var sBlockId = 'searchFriendsResultBlockErrorLIMIT';
					break;
				}
				case 'ERROR_EMPTY':
				{
					var sBlockId = 'searchFriendsResultBlockErrorEMPTY';
					break;
				}
				case 'ERROR_INVALID':
				{
					var sBlockId = 'searchFriendsResultBlockErrorINVALID';
					jQuery('#searchFriendsResultTextErrorINVALID').text(data.Response.list.join(', '));
					break;
				}
				case 'ERROR_DUPLICATE':
				{
					var sBlockId = 'searchFriendsResultBlockErrorDUPLICATE';
					jQuery('#searchFriendsResultTextErrorDUPLICATE').text(data.Response.list.join(', '));
					break;
				}
				case 'ERROR_ITS_ME':
				{
					var sBlockId = 'searchFriendsResultBlockErrorITSME';
					break;
				}
			}
			jQuery('#' + sBlockId).show();
			this.resultClassName = 'stress';
		}
		jQuery('#searchFriendsResultIcon').addClass(this.resultClassName); 
		jQuery('#inviteFormBlock').hide();
		jQuery('#searchFriendsResultBlock').show();
	},
	
	tryAgain : function()
	{
		jQuery('#inviteFormBlock').show();
		jQuery('#inviteResultBlock').hide();
		jQuery('#searchFriendsResultBlock').hide();
		jQuery('span.frm-main-about-cancel').show();
	},
	
	thanks : function()
	{
		document.location = jQuery('#btnThanksUrl').val();
	}
};

jQuery(function(){
	Invitation.changeType(jQuery("#frm-cnt-invite-select").val());
});

(function($){
	$(function(event){
		$('#frm-cnt-invite-select').change(function (){
			if ($('#inviteBlock0').css('display') == 'block') {
				$('#frm-cnt-experience-submit').attr('disabled', 'disabled');
				$('#frm-main-emails-desc').bind('keyup', function (){
					if ($(this).val() != '') {
						$('#frm-cnt-experience-submit').attr('disabled', '');
					} else {
						$('#frm-cnt-experience-submit').attr('disabled', 'disabled');
					}
				});
			} else {
				$('#frm-cnt-experience-submit').attr('disabled', '');
			}
		});
	});
})(jQuery);

/**
 * SWFObject v1.5: Flash Player detection and embed - http://blog.deconcept.com/swfobject/
 *
 * SWFObject is (c) 2007 Geoff Stearns and is released under the MIT License:
 * http://www.opensource.org/licenses/mit-license.php
 *
 */
if(typeof deconcept=="undefined"){var deconcept=new Object();}if(typeof deconcept.util=="undefined"){deconcept.util=new Object();}if(typeof deconcept.SWFObjectUtil=="undefined"){deconcept.SWFObjectUtil=new Object();}deconcept.SWFObject=function(_1,id,w,h,_5,c,_7,_8,_9,_a){if(!document.getElementById){return;}this.DETECT_KEY=_a?_a:"detectflash";this.skipDetect=deconcept.util.getRequestParameter(this.DETECT_KEY);this.params=new Object();this.variables=new Object();this.attributes=new Array();if(_1){this.setAttribute("swf",_1);}if(id){this.setAttribute("id",id);}if(w){this.setAttribute("width",w);}if(h){this.setAttribute("height",h);}if(_5){this.setAttribute("version",new deconcept.PlayerVersion(_5.toString().split(".")));}this.installedVer=deconcept.SWFObjectUtil.getPlayerVersion();if(!window.opera&&document.all&&this.installedVer.major>7){deconcept.SWFObject.doPrepUnload=true;}if(c){this.addParam("bgcolor",c);}var q=_7?_7:"high";this.addParam("quality",q);this.setAttribute("useExpressInstall",false);this.setAttribute("doExpressInstall",false);var _c=(_8)?_8:window.location;this.setAttribute("xiRedirectUrl",_c);this.setAttribute("redirectUrl","");if(_9){this.setAttribute("redirectUrl",_9);}};deconcept.SWFObject.prototype={useExpressInstall:function(_d){this.xiSWFPath=!_d?"expressinstall.swf":_d;this.setAttribute("useExpressInstall",true);},setAttribute:function(_e,_f){this.attributes[_e]=_f;},getAttribute:function(_10){return this.attributes[_10];},addParam:function(_11,_12){this.params[_11]=_12;},getParams:function(){return this.params;},addVariable:function(_13,_14){this.variables[_13]=_14;},getVariable:function(_15){return this.variables[_15];},getVariables:function(){return this.variables;},getVariablePairs:function(){var _16=new Array();var key;var _18=this.getVariables();for(key in _18){_16[_16.length]=key+"="+_18[key];}return _16;},getSWFHTML:function(){var _19="";if(navigator.plugins&&navigator.mimeTypes&&navigator.mimeTypes.length){if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","PlugIn");this.setAttribute("swf",this.xiSWFPath);}_19="<embed type=\"application/x-shockwave-flash\" src=\""+this.getAttribute("swf")+"\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\"";_19+=" id=\""+this.getAttribute("id")+"\" name=\""+this.getAttribute("id")+"\" ";var _1a=this.getParams();for(var key in _1a){_19+=[key]+"=\""+_1a[key]+"\" ";}var _1c=this.getVariablePairs().join("&");if(_1c.length>0){_19+="flashvars=\""+_1c+"\"";}_19+="/>";}else{if(this.getAttribute("doExpressInstall")){this.addVariable("MMplayerType","ActiveX");this.setAttribute("swf",this.xiSWFPath);}_19="<object id=\""+this.getAttribute("id")+"\" classid=\"clsid:D27CDB6E-AE6D-11cf-96B8-444553540000\" width=\""+this.getAttribute("width")+"\" height=\""+this.getAttribute("height")+"\" style=\""+this.getAttribute("style")+"\">";_19+="<param name=\"movie\" value=\""+this.getAttribute("swf")+"\" />";var _1d=this.getParams();for(var key in _1d){_19+="<param name=\""+key+"\" value=\""+_1d[key]+"\" />";}var _1f=this.getVariablePairs().join("&");if(_1f.length>0){_19+="<param name=\"flashvars\" value=\""+_1f+"\" />";}_19+="</object>";}return _19;},write:function(_20){if(this.getAttribute("useExpressInstall")){var _21=new deconcept.PlayerVersion([6,0,65]);if(this.installedVer.versionIsValid(_21)&&!this.installedVer.versionIsValid(this.getAttribute("version"))){this.setAttribute("doExpressInstall",true);this.addVariable("MMredirectURL",escape(this.getAttribute("xiRedirectUrl")));document.title=document.title.slice(0,47)+" - Flash Player Installation";this.addVariable("MMdoctitle",document.title);}}if(this.skipDetect||this.getAttribute("doExpressInstall")||this.installedVer.versionIsValid(this.getAttribute("version"))){var n=(typeof _20=="string")?document.getElementById(_20):_20;n.innerHTML=this.getSWFHTML();return true;}else{if(this.getAttribute("redirectUrl")!=""){document.location.replace(this.getAttribute("redirectUrl"));}}return false;}};deconcept.SWFObjectUtil.getPlayerVersion=function(){var _23=new deconcept.PlayerVersion([0,0,0]);if(navigator.plugins&&navigator.mimeTypes.length){var x=navigator.plugins["Shockwave Flash"];if(x&&x.description){_23=new deconcept.PlayerVersion(x.description.replace(/([a-zA-Z]|\s)+/,"").replace(/(\s+r|\s+b[0-9]+)/,".").split("."));}}else{if(navigator.userAgent&&navigator.userAgent.indexOf("Windows CE")>=0){var axo=1;var _26=3;while(axo){try{_26++;axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash."+_26);_23=new deconcept.PlayerVersion([_26,0,0]);}catch(e){axo=null;}}}else{try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.7");}catch(e){try{var axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash.6");_23=new deconcept.PlayerVersion([6,0,21]);axo.AllowScriptAccess="always";}catch(e){if(_23.major==6){return _23;}}try{axo=new ActiveXObject("ShockwaveFlash.ShockwaveFlash");}catch(e){}}if(axo!=null){_23=new deconcept.PlayerVersion(axo.GetVariable("$version").split(" ")[1].split(","));}}}return _23;};deconcept.PlayerVersion=function(_29){this.major=_29[0]!=null?parseInt(_29[0]):0;this.minor=_29[1]!=null?parseInt(_29[1]):0;this.rev=_29[2]!=null?parseInt(_29[2]):0;};deconcept.PlayerVersion.prototype.versionIsValid=function(fv){if(this.major<fv.major){return false;}if(this.major>fv.major){return true;}if(this.minor<fv.minor){return false;}if(this.minor>fv.minor){return true;}if(this.rev<fv.rev){return false;}return true;};deconcept.util={getRequestParameter:function(_2b){var q=document.location.search||document.location.hash;if(_2b==null){return q;}if(q){var _2d=q.substring(1).split("&");for(var i=0;i<_2d.length;i++){if(_2d[i].substring(0,_2d[i].indexOf("="))==_2b){return _2d[i].substring((_2d[i].indexOf("=")+1));}}}return "";}};deconcept.SWFObjectUtil.cleanupSWFs=function(){var _2f=document.getElementsByTagName("OBJECT");for(var i=_2f.length-1;i>=0;i--){_2f[i].style.display="none";for(var x in _2f[i]){if(typeof _2f[i][x]=="function"){_2f[i][x]=function(){};}}}};if(deconcept.SWFObject.doPrepUnload){if(!deconcept.unloadSet){deconcept.SWFObjectUtil.prepUnload=function(){__flash_unloadHandler=function(){};__flash_savedUnloadHandler=function(){};window.attachEvent("onunload",deconcept.SWFObjectUtil.cleanupSWFs);};window.attachEvent("onbeforeunload",deconcept.SWFObjectUtil.prepUnload);deconcept.unloadSet=true;}}if(!document.getElementById&&document.all){document.getElementById=function(id){return document.all[id];};}var getQueryParamValue=deconcept.util.getRequestParameter;var FlashObject=deconcept.SWFObject;var SWFObject=deconcept.SWFObject;
