
/** File: javascript/date.js **/

/*
 * 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;
		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 :(
	};
	
})();

/** File: javascript/jquery.js **/

/*!
 * jQuery JavaScript Library v1.5.1
 * http://jquery.com/
 *
 * Copyright 2011, John Resig
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * Includes Sizzle.js
 * http://sizzlejs.com/
 * Copyright 2011, The Dojo Foundation
 * Released under the MIT, BSD, and GPL Licenses.
 *
 * Date: Wed Feb 23 13:55:29 2011 -0500
 */
(function( window, undefined ) {

// Use the correct document accordingly with window argument (sandbox)
var document = window.document;
var jQuery = (function() {

// Define a local copy of jQuery
var jQuery = function( selector, context ) {
		// The jQuery object is actually just the init constructor 'enhanced'
		return new jQuery.fn.init( selector, context, rootjQuery );
	},

	// Map over jQuery in case of overwrite
	_jQuery = window.jQuery,

	// Map over the $ in case of overwrite
	_$ = window.$,

	// A central reference to the root jQuery(document)
	rootjQuery,

	// A simple way to check for HTML strings or ID strings
	// (both of which we optimize for)
	quickExpr = /^(?:[^<]*(<[\w\W]+>)[^>]*$|#([\w\-]+)$)/,

	// Check if a string has a non-whitespace character in it
	rnotwhite = /\S/,

	// Used for trimming whitespace
	trimLeft = /^\s+/,
	trimRight = /\s+$/,

	// Check for digits
	rdigit = /\d/,

	// Match a standalone tag
	rsingleTag = /^<(\w+)\s*\/?>(?:<\/\1>)?$/,

	// JSON RegExp
	rvalidchars = /^[\],:{}\s]*$/,
	rvalidescape = /\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,
	rvalidtokens = /"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,
	rvalidbraces = /(?:^|:|,)(?:\s*\[)+/g,

	// Useragent RegExp
	rwebkit = /(webkit)[ \/]([\w.]+)/,
	ropera = /(opera)(?:.*version)?[ \/]([\w.]+)/,
	rmsie = /(msie) ([\w.]+)/,
	rmozilla = /(mozilla)(?:.*? rv:([\w.]+))?/,

	// Keep a UserAgent string for use with jQuery.browser
	userAgent = navigator.userAgent,

	// For matching the engine and version of the browser
	browserMatch,

	// Has the ready events already been bound?
	readyBound = false,

	// The deferred used on DOM ready
	readyList,

	// Promise methods
	promiseMethods = "then done fail isResolved isRejected promise".split( " " ),

	// The ready event handler
	DOMContentLoaded,

	// Save a reference to some core methods
	toString = Object.prototype.toString,
	hasOwn = Object.prototype.hasOwnProperty,
	push = Array.prototype.push,
	slice = Array.prototype.slice,
	trim = String.prototype.trim,
	indexOf = Array.prototype.indexOf,

	// [[Class]] -> type pairs
	class2type = {};

jQuery.fn = jQuery.prototype = {
	constructor: jQuery,
	init: function( selector, context, rootjQuery ) {
		var match, elem, ret, doc;

		// Handle $(""), $(null), or $(undefined)
		if ( !selector ) {
			return this;
		}

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

		// The body element only exists once, optimize finding it
		if ( selector === "body" && !context && document.body ) {
			this.context = document;
			this[0] = document.body;
			this.selector = "body";
			this.length = 1;
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			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] ) {
					context = context instanceof jQuery ? context[0] : context;
					doc = (context ? context.ownerDocument || context : document);

					// If a single string is passed in and it's a single tag
					// just do a createElement and skip the rest
					ret = rsingleTag.exec( selector );

					if ( ret ) {
						if ( jQuery.isPlainObject( context ) ) {
							selector = [ document.createElement( ret[1] ) ];
							jQuery.fn.attr.call( selector, context, true );

						} else {
							selector = [ doc.createElement( ret[1] ) ];
						}

					} else {
						ret = jQuery.buildFragment( [ match[1] ], [ doc ] );
						selector = (ret.cacheable ? jQuery.clone(ret.fragment) : ret.fragment).childNodes;
					}

					return jQuery.merge( this, selector );

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

					// Check parentNode to catch when Blackberry 4.6 returns
					// nodes that are no longer in the document #6963
					if ( elem && elem.parentNode ) {
						// Handle the case where IE and Opera return items
						// by name instead of ID
						if ( elem.id !== match[2] ) {
							return rootjQuery.find( selector );
						}

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

					this.context = document;
					this.selector = selector;
					return this;
				}

			// HANDLE: $(expr, $(...))
			} else if ( !context || context.jquery ) {
				return (context || rootjQuery).find( selector );

			// HANDLE: $(expr, context)
			// (which is just equivalent to: $(context).find(expr)
			} else {
				return this.constructor( context ).find( selector );
			}

		// HANDLE: $(function)
		// Shortcut for document ready
		} else if ( jQuery.isFunction( selector ) ) {
			return rootjQuery.ready( selector );
		}

		if (selector.selector !== undefined) {
			this.selector = selector.selector;
			this.context = selector.context;
		}

		return jQuery.makeArray( selector, this );
	},

	// Start with an empty selector
	selector: "",

	// The current version of jQuery being used
	jquery: "1.5.1",

	// The default length of a jQuery object is 0
	length: 0,

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

	toArray: function() {
		return slice.call( this, 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 == null ?

			// Return a 'clean' array
			this.toArray() :

			// Return just the object
			( num < 0 ? this[ this.length + num ] : this[ num ] );
	},

	// Take an array of elements and push it onto the stack
	// (returning the new matched element set)
	pushStack: function( elems, name, selector ) {
		// Build a new jQuery matched element set
		var ret = this.constructor();

		if ( jQuery.isArray( elems ) ) {
			push.apply( ret, elems );

		} else {
			jQuery.merge( ret, elems );
		}

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

		ret.context = this.context;

		if ( name === "find" ) {
			ret.selector = this.selector + (this.selector ? " " : "") + selector;
		} else if ( name ) {
			ret.selector = this.selector + "." + name + "(" + selector + ")";
		}

		// Return the newly-formed element set
		return ret;
	},

	// 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 );
	},

	ready: function( fn ) {
		// Attach the listeners
		jQuery.bindReady();

		// Add the callback
		readyList.done( fn );

		return this;
	},

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

	first: function() {
		return this.eq( 0 );
	},

	last: function() {
		return this.eq( -1 );
	},

	slice: function() {
		return this.pushStack( slice.apply( this, arguments ),
			"slice", slice.call(arguments).join(",") );
	},

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

	end: function() {
		return this.prevObject || this.constructor(null);
	},

	// For internal use only.
	// Behaves like an Array's method, not like a jQuery method.
	push: push,
	sort: [].sort,
	splice: [].splice
};

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

jQuery.extend = jQuery.fn.extend = function() {
	var options, name, src, copy, copyIsArray, clone,
		target = arguments[0] || {},
		i = 1,
		length = arguments.length,
		deep = false;

	// Handle a deep copy situation
	if ( typeof target === "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" && !jQuery.isFunction(target) ) {
		target = {};
	}

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

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

				// Prevent never-ending loop
				if ( target === copy ) {
					continue;
				}

				// Recurse if we're merging plain objects or arrays
				if ( deep && copy && ( jQuery.isPlainObject(copy) || (copyIsArray = jQuery.isArray(copy)) ) ) {
					if ( copyIsArray ) {
						copyIsArray = false;
						clone = src && jQuery.isArray(src) ? src : [];

					} else {
						clone = src && jQuery.isPlainObject(src) ? src : {};
					}

					// Never move original objects, clone them
					target[ name ] = jQuery.extend( deep, clone, copy );

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

	// Return the modified object
	return target;
};

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

		if ( deep ) {
			window.jQuery = _jQuery;
		}

		return jQuery;
	},

	// Is the DOM ready to be used? Set to true once it occurs.
	isReady: false,

	// A counter to track how many items to wait for before
	// the ready event fires. See #6781
	readyWait: 1,

	// Handle when the DOM is ready
	ready: function( wait ) {
		// A third-party is pushing the ready event forwards
		if ( wait === true ) {
			jQuery.readyWait--;
		}

		// Make sure that the DOM is not already loaded
		if ( !jQuery.readyWait || (wait !== true && !jQuery.isReady) ) {
			// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
			if ( !document.body ) {
				return setTimeout( jQuery.ready, 1 );
			}

			// Remember that the DOM is ready
			jQuery.isReady = true;

			// If a normal DOM Ready event fired, decrement, and wait if need be
			if ( wait !== true && --jQuery.readyWait > 0 ) {
				return;
			}

			// If there are functions bound, to execute
			readyList.resolveWith( document, [ jQuery ] );

			// Trigger any bound ready events
			if ( jQuery.fn.trigger ) {
				jQuery( document ).trigger( "ready" ).unbind( "ready" );
			}
		}
	},

	bindReady: function() {
		if ( readyBound ) {
			return;
		}

		readyBound = true;

		// Catch cases where $(document).ready() is called after the
		// browser event has already occurred.
		if ( document.readyState === "complete" ) {
			// Handle it asynchronously to allow scripts the opportunity to delay ready
			return setTimeout( jQuery.ready, 1 );
		}

		// Mozilla, Opera and webkit nightlies currently support this event
		if ( document.addEventListener ) {
			// Use the handy event callback
			document.addEventListener( "DOMContentLoaded", DOMContentLoaded, false );

			// A fallback to window.onload, that will always work
			window.addEventListener( "load", jQuery.ready, false );

		// If IE event model is used
		} else if ( document.attachEvent ) {
			// ensure firing before onload,
			// maybe late but safe also for iframes
			document.attachEvent("onreadystatechange", DOMContentLoaded);

			// A fallback to window.onload, that will always work
			window.attachEvent( "onload", jQuery.ready );

			// If IE and not a frame
			// continually check to see if the document is ready
			var toplevel = false;

			try {
				toplevel = window.frameElement == null;
			} catch(e) {}

			if ( document.documentElement.doScroll && toplevel ) {
				doScrollCheck();
			}
		}
	},

	// See test/unit/core.js for details concerning isFunction.
	// Since version 1.3, DOM methods and functions like alert
	// aren't supported. They return false on IE (#2968).
	isFunction: function( obj ) {
		return jQuery.type(obj) === "function";
	},

	isArray: Array.isArray || function( obj ) {
		return jQuery.type(obj) === "array";
	},

	// A crude way of determining if an object is a window
	isWindow: function( obj ) {
		return obj && typeof obj === "object" && "setInterval" in obj;
	},

	isNaN: function( obj ) {
		return obj == null || !rdigit.test( obj ) || isNaN( obj );
	},

	type: function( obj ) {
		return obj == null ?
			String( obj ) :
			class2type[ toString.call(obj) ] || "object";
	},

	isPlainObject: function( obj ) {
		// Must be an Object.
		// Because of IE, we also have to check the presence of the constructor property.
		// Make sure that DOM nodes and window objects don't pass through, as well
		if ( !obj || jQuery.type(obj) !== "object" || obj.nodeType || jQuery.isWindow( obj ) ) {
			return false;
		}

		// Not own constructor property must be Object
		if ( obj.constructor &&
			!hasOwn.call(obj, "constructor") &&
			!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
			return false;
		}

		// Own properties are enumerated firstly, so to speed up,
		// if last one is own, then all properties are own.

		var key;
		for ( key in obj ) {}

		return key === undefined || hasOwn.call( obj, key );
	},

	isEmptyObject: function( obj ) {
		for ( var name in obj ) {
			return false;
		}
		return true;
	},

	error: function( msg ) {
		throw msg;
	},

	parseJSON: function( data ) {
		if ( typeof data !== "string" || !data ) {
			return null;
		}

		// Make sure leading/trailing whitespace is removed (IE can't handle it)
		data = jQuery.trim( data );

		// Make sure the incoming data is actual JSON
		// Logic borrowed from http://json.org/json2.js
		if ( rvalidchars.test(data.replace(rvalidescape, "@")
			.replace(rvalidtokens, "]")
			.replace(rvalidbraces, "")) ) {

			// Try to use the native JSON parser first
			return window.JSON && window.JSON.parse ?
				window.JSON.parse( data ) :
				(new Function("return " + data))();

		} else {
			jQuery.error( "Invalid JSON: " + data );
		}
	},

	// Cross-browser xml parsing
	// (xml & tmp used internally)
	parseXML: function( data , xml , tmp ) {

		if ( window.DOMParser ) { // Standard
			tmp = new DOMParser();
			xml = tmp.parseFromString( data , "text/xml" );
		} else { // IE
			xml = new ActiveXObject( "Microsoft.XMLDOM" );
			xml.async = "false";
			xml.loadXML( data );
		}

		tmp = xml.documentElement;

		if ( ! tmp || ! tmp.nodeName || tmp.nodeName === "parsererror" ) {
			jQuery.error( "Invalid XML: " + data );
		}

		return xml;
	},

	noop: function() {},

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

			if ( jQuery.support.scriptEval() ) {
				script.appendChild( document.createTextNode( data ) );
			} else {
				script.text = data;
			}

			// Use insertBefore instead of appendChild to circumvent an IE6 bug.
			// This arises when a base node is used (#2709).
			head.insertBefore( script, head.firstChild );
			head.removeChild( script );
		}
	},

	nodeName: function( elem, name ) {
		return elem.nodeName && elem.nodeName.toUpperCase() === name.toUpperCase();
	},

	// args is for internal usage only
	each: function( object, callback, args ) {
		var name, i = 0,
			length = object.length,
			isObj = length === undefined || jQuery.isFunction(object);

		if ( args ) {
			if ( isObj ) {
				for ( name in object ) {
					if ( callback.apply( object[ name ], args ) === false ) {
						break;
					}
				}
			} else {
				for ( ; i < length; ) {
					if ( callback.apply( object[ i++ ], args ) === false ) {
						break;
					}
				}
			}

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

		return object;
	},

	// Use native String.trim function wherever possible
	trim: trim ?
		function( text ) {
			return text == null ?
				"" :
				trim.call( text );
		} :

		// Otherwise use our own trimming functionality
		function( text ) {
			return text == null ?
				"" :
				text.toString().replace( trimLeft, "" ).replace( trimRight, "" );
		},

	// results is for internal usage only
	makeArray: function( array, results ) {
		var ret = results || [];

		if ( array != null ) {
			// The window, strings (and functions) also have 'length'
			// The extra typeof function check is to prevent crashes
			// in Safari 2 (See: #3039)
			// Tweaked logic slightly to handle Blackberry 4.7 RegExp issues #6930
			var type = jQuery.type(array);

			if ( array.length == null || type === "string" || type === "function" || type === "regexp" || jQuery.isWindow( array ) ) {
				push.call( ret, array );
			} else {
				jQuery.merge( ret, array );
			}
		}

		return ret;
	},

	inArray: function( elem, array ) {
		if ( array.indexOf ) {
			return array.indexOf( elem );
		}

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

		return -1;
	},

	merge: function( first, second ) {
		var i = first.length,
			j = 0;

		if ( typeof second.length === "number" ) {
			for ( var l = second.length; j < l; j++ ) {
				first[ i++ ] = second[ j ];
			}

		} else {
			while ( second[j] !== undefined ) {
				first[ i++ ] = second[ j++ ];
			}
		}

		first.length = i;

		return first;
	},

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

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

		return ret;
	},

	// arg is for internal usage only
	map: function( elems, callback, arg ) {
		var ret = [], value;

		// 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++ ) {
			value = callback( elems[ i ], i, arg );

			if ( value != null ) {
				ret[ ret.length ] = value;
			}
		}

		// Flatten any nested arrays
		return ret.concat.apply( [], ret );
	},

	// A global GUID counter for objects
	guid: 1,

	proxy: function( fn, proxy, thisObject ) {
		if ( arguments.length === 2 ) {
			if ( typeof proxy === "string" ) {
				thisObject = fn;
				fn = thisObject[ proxy ];
				proxy = undefined;

			} else if ( proxy && !jQuery.isFunction( proxy ) ) {
				thisObject = proxy;
				proxy = undefined;
			}
		}

		if ( !proxy && fn ) {
			proxy = function() {
				return fn.apply( thisObject || this, arguments );
			};
		}

		// Set the guid of unique handler to the same of original handler, so it can be removed
		if ( fn ) {
			proxy.guid = fn.guid = fn.guid || proxy.guid || jQuery.guid++;
		}

		// So proxy can be declared as an argument
		return proxy;
	},

	// Mutifunctional method to get and set values to a collection
	// The value/s can be optionally by executed if its a function
	access: function( elems, key, value, exec, fn, pass ) {
		var length = elems.length;

		// Setting many attributes
		if ( typeof key === "object" ) {
			for ( var k in key ) {
				jQuery.access( elems, k, key[k], exec, fn, value );
			}
			return elems;
		}

		// Setting one attribute
		if ( value !== undefined ) {
			// Optionally, function values get executed if exec is true
			exec = !pass && exec && jQuery.isFunction(value);

			for ( var i = 0; i < length; i++ ) {
				fn( elems[i], key, exec ? value.call( elems[i], i, fn( elems[i], key ) ) : value, pass );
			}

			return elems;
		}

		// Getting an attribute
		return length ? fn( elems[0], key ) : undefined;
	},

	now: function() {
		return (new Date()).getTime();
	},

	// Create a simple deferred (one callbacks list)
	_Deferred: function() {
		var // callbacks list
			callbacks = [],
			// stored [ context , args ]
			fired,
			// to avoid firing when already doing so
			firing,
			// flag to know if the deferred has been cancelled
			cancelled,
			// the deferred itself
			deferred  = {

				// done( f1, f2, ...)
				done: function() {
					if ( !cancelled ) {
						var args = arguments,
							i,
							length,
							elem,
							type,
							_fired;
						if ( fired ) {
							_fired = fired;
							fired = 0;
						}
						for ( i = 0, length = args.length; i < length; i++ ) {
							elem = args[ i ];
							type = jQuery.type( elem );
							if ( type === "array" ) {
								deferred.done.apply( deferred, elem );
							} else if ( type === "function" ) {
								callbacks.push( elem );
							}
						}
						if ( _fired ) {
							deferred.resolveWith( _fired[ 0 ], _fired[ 1 ] );
						}
					}
					return this;
				},

				// resolve with given context and args
				resolveWith: function( context, args ) {
					if ( !cancelled && !fired && !firing ) {
						firing = 1;
						try {
							while( callbacks[ 0 ] ) {
								callbacks.shift().apply( context, args );
							}
						}
						// We have to add a catch block for
						// IE prior to 8 or else the finally
						// block will never get executed
						catch (e) {
							throw e;
						}
						finally {
							fired = [ context, args ];
							firing = 0;
						}
					}
					return this;
				},

				// resolve with this as context and given arguments
				resolve: function() {
					deferred.resolveWith( jQuery.isFunction( this.promise ) ? this.promise() : this, arguments );
					return this;
				},

				// Has this deferred been resolved?
				isResolved: function() {
					return !!( firing || fired );
				},

				// Cancel
				cancel: function() {
					cancelled = 1;
					callbacks = [];
					return this;
				}
			};

		return deferred;
	},

	// Full fledged deferred (two callbacks list)
	Deferred: function( func ) {
		var deferred = jQuery._Deferred(),
			failDeferred = jQuery._Deferred(),
			promise;
		// Add errorDeferred methods, then and promise
		jQuery.extend( deferred, {
			then: function( doneCallbacks, failCallbacks ) {
				deferred.done( doneCallbacks ).fail( failCallbacks );
				return this;
			},
			fail: failDeferred.done,
			rejectWith: failDeferred.resolveWith,
			reject: failDeferred.resolve,
			isRejected: failDeferred.isResolved,
			// Get a promise for this deferred
			// If obj is provided, the promise aspect is added to the object
			promise: function( obj ) {
				if ( obj == null ) {
					if ( promise ) {
						return promise;
					}
					promise = obj = {};
				}
				var i = promiseMethods.length;
				while( i-- ) {
					obj[ promiseMethods[i] ] = deferred[ promiseMethods[i] ];
				}
				return obj;
			}
		} );
		// Make sure only one callback list will be used
		deferred.done( failDeferred.cancel ).fail( deferred.cancel );
		// Unexpose cancel
		delete deferred.cancel;
		// Call given func if any
		if ( func ) {
			func.call( deferred, deferred );
		}
		return deferred;
	},

	// Deferred helper
	when: function( object ) {
		var lastIndex = arguments.length,
			deferred = lastIndex <= 1 && object && jQuery.isFunction( object.promise ) ?
				object :
				jQuery.Deferred(),
			promise = deferred.promise();

		if ( lastIndex > 1 ) {
			var array = slice.call( arguments, 0 ),
				count = lastIndex,
				iCallback = function( index ) {
					return function( value ) {
						array[ index ] = arguments.length > 1 ? slice.call( arguments, 0 ) : value;
						if ( !( --count ) ) {
							deferred.resolveWith( promise, array );
						}
					};
				};
			while( ( lastIndex-- ) ) {
				object = array[ lastIndex ];
				if ( object && jQuery.isFunction( object.promise ) ) {
					object.promise().then( iCallback(lastIndex), deferred.reject );
				} else {
					--count;
				}
			}
			if ( !count ) {
				deferred.resolveWith( promise, array );
			}
		} else if ( deferred !== object ) {
			deferred.resolve( object );
		}
		return promise;
	},

	// Use of jQuery.browser is frowned upon.
	// More details: http://docs.jquery.com/Utilities/jQuery.browser
	uaMatch: function( ua ) {
		ua = ua.toLowerCase();

		var match = rwebkit.exec( ua ) ||
			ropera.exec( ua ) ||
			rmsie.exec( ua ) ||
			ua.indexOf("compatible") < 0 && rmozilla.exec( ua ) ||
			[];

		return { browser: match[1] || "", version: match[2] || "0" };
	},

	sub: function() {
		function jQuerySubclass( selector, context ) {
			return new jQuerySubclass.fn.init( selector, context );
		}
		jQuery.extend( true, jQuerySubclass, this );
		jQuerySubclass.superclass = this;
		jQuerySubclass.fn = jQuerySubclass.prototype = this();
		jQuerySubclass.fn.constructor = jQuerySubclass;
		jQuerySubclass.subclass = this.subclass;
		jQuerySubclass.fn.init = function init( selector, context ) {
			if ( context && context instanceof jQuery && !(context instanceof jQuerySubclass) ) {
				context = jQuerySubclass(context);
			}

			return jQuery.fn.init.call( this, selector, context, rootjQuerySubclass );
		};
		jQuerySubclass.fn.init.prototype = jQuerySubclass.fn;
		var rootjQuerySubclass = jQuerySubclass(document);
		return jQuerySubclass;
	},

	browser: {}
});

// Create readyList deferred
readyList = jQuery._Deferred();

// Populate the class2type map
jQuery.each("Boolean Number String Function Array Date RegExp Object".split(" "), function(i, name) {
	class2type[ "[object " + name + "]" ] = name.toLowerCase();
});

browserMatch = jQuery.uaMatch( userAgent );
if ( browserMatch.browser ) {
	jQuery.browser[ browserMatch.browser ] = true;
	jQuery.browser.version = browserMatch.version;
}

// Deprecated, use jQuery.browser.webkit instead
if ( jQuery.browser.webkit ) {
	jQuery.browser.safari = true;
}

if ( indexOf ) {
	jQuery.inArray = function( elem, array ) {
		return indexOf.call( array, elem );
	};
}

// IE doesn't match non-breaking spaces with \s
if ( rnotwhite.test( "\xA0" ) ) {
	trimLeft = /^[\s\xA0]+/;
	trimRight = /[\s\xA0]+$/;
}

// All jQuery objects should point back to these
rootjQuery = jQuery(document);

// Cleanup functions for the document ready method
if ( document.addEventListener ) {
	DOMContentLoaded = function() {
		document.removeEventListener( "DOMContentLoaded", DOMContentLoaded, false );
		jQuery.ready();
	};

} else if ( document.attachEvent ) {
	DOMContentLoaded = function() {
		// Make sure body exists, at least, in case IE gets a little overzealous (ticket #5443).
		if ( document.readyState === "complete" ) {
			document.detachEvent( "onreadystatechange", DOMContentLoaded );
			jQuery.ready();
		}
	};
}

// The DOM ready check for Internet Explorer
function doScrollCheck() {
	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(e) {
		setTimeout( doScrollCheck, 1 );
		return;
	}

	// and execute any waiting functions
	jQuery.ready();
}

// Expose jQuery to the global object
return jQuery;

})();


(function() {

	jQuery.support = {};

	var div = document.createElement("div");

	div.style.display = "none";
	div.innerHTML = "   <link/><table></table><a href='/a' style='color:red;float:left;opacity:.55;'>a</a><input type='checkbox'/>";

	var all = div.getElementsByTagName("*"),
		a = div.getElementsByTagName("a")[0],
		select = document.createElement("select"),
		opt = select.appendChild( document.createElement("option") ),
		input = div.getElementsByTagName("input")[0];

	// Can't get basic test support
	if ( !all || !all.length || !a ) {
		return;
	}

	jQuery.support = {
		// IE strips leading whitespace when .innerHTML is used
		leadingWhitespace: div.firstChild.nodeType === 3,

		// Make sure that tbody elements aren't automatically inserted
		// IE will insert them into empty tables
		tbody: !div.getElementsByTagName("tbody").length,

		// Make sure that link elements get serialized correctly by innerHTML
		// This requires a wrapper element in IE
		htmlSerialize: !!div.getElementsByTagName("link").length,

		// Get the style information from getAttribute
		// (IE uses .cssText insted)
		style: /red/.test( a.getAttribute("style") ),

		// Make sure that URLs aren't manipulated
		// (IE normalizes it by default)
		hrefNormalized: a.getAttribute("href") === "/a",

		// Make sure that element opacity exists
		// (IE uses filter instead)
		// Use a regex to work around a WebKit issue. See #5145
		opacity: /^0.55$/.test( a.style.opacity ),

		// Verify style float existence
		// (IE uses styleFloat instead of cssFloat)
		cssFloat: !!a.style.cssFloat,

		// Make sure that if no value is specified for a checkbox
		// that it defaults to "on".
		// (WebKit defaults to "" instead)
		checkOn: input.value === "on",

		// Make sure that a selected-by-default option has a working selected property.
		// (WebKit defaults to false instead of true, IE too, if it's in an optgroup)
		optSelected: opt.selected,

		// Will be defined later
		deleteExpando: true,
		optDisabled: false,
		checkClone: false,
		noCloneEvent: true,
		noCloneChecked: true,
		boxModel: null,
		inlineBlockNeedsLayout: false,
		shrinkWrapBlocks: false,
		reliableHiddenOffsets: true
	};

	input.checked = true;
	jQuery.support.noCloneChecked = input.cloneNode( true ).checked;

	// Make sure that the options inside disabled selects aren't marked as disabled
	// (WebKit marks them as diabled)
	select.disabled = true;
	jQuery.support.optDisabled = !opt.disabled;

	var _scriptEval = null;
	jQuery.support.scriptEval = function() {
		if ( _scriptEval === null ) {
			var root = document.documentElement,
				script = document.createElement("script"),
				id = "script" + jQuery.now();

			try {
				script.appendChild( document.createTextNode( "window." + id + "=1;" ) );
			} catch(e) {}

			root.insertBefore( script, root.firstChild );

			// Make sure that the execution of code works by injecting a script
			// tag with appendChild/createTextNode
			// (IE doesn't support this, fails, and uses .text instead)
			if ( window[ id ] ) {
				_scriptEval = true;
				delete window[ id ];
			} else {
				_scriptEval = false;
			}

			root.removeChild( script );
			// release memory in IE
			root = script = id  = null;
		}

		return _scriptEval;
	};

	// Test to see if it's possible to delete an expando from an element
	// Fails in Internet Explorer
	try {
		delete div.test;

	} catch(e) {
		jQuery.support.deleteExpando = false;
	}

	if ( !div.addEventListener && div.attachEvent && div.fireEvent ) {
		div.attachEvent("onclick", function click() {
			// Cloning a node shouldn't copy over any
			// bound event handlers (IE does this)
			jQuery.support.noCloneEvent = false;
			div.detachEvent("onclick", click);
		});
		div.cloneNode(true).fireEvent("onclick");
	}

	div = document.createElement("div");
	div.innerHTML = "<input type='radio' name='radiotest' checked='checked'/>";

	var fragment = document.createDocumentFragment();
	fragment.appendChild( div.firstChild );

	// WebKit doesn't clone checked state correctly in fragments
	jQuery.support.checkClone = fragment.cloneNode(true).cloneNode(true).lastChild.checked;

	// Figure out if the W3C box model works as expected
	// document.body must exist before we can do this
	jQuery(function() {
		var div = document.createElement("div"),
			body = document.getElementsByTagName("body")[0];

		// Frameset documents with no body should not run this code
		if ( !body ) {
			return;
		}

		div.style.width = div.style.paddingLeft = "1px";
		body.appendChild( div );
		jQuery.boxModel = jQuery.support.boxModel = div.offsetWidth === 2;

		if ( "zoom" in div.style ) {
			// Check if natively block-level elements act like inline-block
			// elements when setting their display to 'inline' and giving
			// them layout
			// (IE < 8 does this)
			div.style.display = "inline";
			div.style.zoom = 1;
			jQuery.support.inlineBlockNeedsLayout = div.offsetWidth === 2;

			// Check if elements with layout shrink-wrap their children
			// (IE 6 does this)
			div.style.display = "";
			div.innerHTML = "<div style='width:4px;'></div>";
			jQuery.support.shrinkWrapBlocks = div.offsetWidth !== 2;
		}

		div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
		var tds = div.getElementsByTagName("td");

		// Check if table cells still have offsetWidth/Height when they are set
		// to display:none and there are still other visible table cells in a
		// table row; if so, offsetWidth/Height are not reliable for use when
		// determining if an element has been hidden directly using
		// display:none (it is still safe to use offsets if a parent element is
		// hidden; don safety goggles and see bug #4512 for more information).
		// (only IE 8 fails this test)
		jQuery.support.reliableHiddenOffsets = tds[0].offsetHeight === 0;

		tds[0].style.display = "";
		tds[1].style.display = "none";

		// Check if empty table cells still have offsetWidth/Height
		// (IE < 8 fail this test)
		jQuery.support.reliableHiddenOffsets = jQuery.support.reliableHiddenOffsets && tds[0].offsetHeight === 0;
		div.innerHTML = "";

		body.removeChild( div ).style.display = "none";
		div = tds = null;
	});

	// Technique from Juriy Zaytsev
	// http://thinkweb2.com/projects/prototype/detecting-event-support-without-browser-sniffing/
	var eventSupported = function( eventName ) {
		var el = document.createElement("div");
		eventName = "on" + eventName;

		// We only care about the case where non-standard event systems
		// are used, namely in IE. Short-circuiting here helps us to
		// avoid an eval call (in setAttribute) which can cause CSP
		// to go haywire. See: https://developer.mozilla.org/en/Security/CSP
		if ( !el.attachEvent ) {
			return true;
		}

		var isSupported = (eventName in el);
		if ( !isSupported ) {
			el.setAttribute(eventName, "return;");
			isSupported = typeof el[eventName] === "function";
		}
		el = null;

		return isSupported;
	};

	jQuery.support.submitBubbles = eventSupported("submit");
	jQuery.support.changeBubbles = eventSupported("change");

	// release memory in IE
	div = all = a = null;
})();



var rbrace = /^(?:\{.*\}|\[.*\])$/;

jQuery.extend({
	cache: {},

	// Please use with caution
	uuid: 0,

	// Unique for each copy of jQuery on the page
	// Non-digits removed to match rinlinejQuery
	expando: "jQuery" + ( jQuery.fn.jquery + Math.random() ).replace( /\D/g, "" ),

	// The following elements throw uncatchable exceptions if you
	// attempt to add expando properties to them.
	noData: {
		"embed": true,
		// Ban all objects except for Flash (which handle expandos)
		"object": "clsid:D27CDB6E-AE6D-11cf-96B8-444553540000",
		"applet": true
	},

	hasData: function( elem ) {
		elem = elem.nodeType ? jQuery.cache[ elem[jQuery.expando] ] : elem[ jQuery.expando ];

		return !!elem && !isEmptyDataObject( elem );
	},

	data: function( elem, name, data, pvt /* Internal Use Only */ ) {
		if ( !jQuery.acceptData( elem ) ) {
			return;
		}

		var internalKey = jQuery.expando, getByName = typeof name === "string", thisCache,

			// We have to handle DOM nodes and JS objects differently because IE6-7
			// can't GC object references properly across the DOM-JS boundary
			isNode = elem.nodeType,

			// Only DOM nodes need the global jQuery cache; JS object data is
			// attached directly to the object so GC can occur automatically
			cache = isNode ? jQuery.cache : elem,

			// Only defining an ID for JS objects if its cache already exists allows
			// the code to shortcut on the same path as a DOM node with no cache
			id = isNode ? elem[ jQuery.expando ] : elem[ jQuery.expando ] && jQuery.expando;

		// Avoid doing any more work than we need to when trying to get data on an
		// object that has no data at all
		if ( (!id || (pvt && id && !cache[ id ][ internalKey ])) && getByName && data === undefined ) {
			return;
		}

		if ( !id ) {
			// Only DOM nodes need a new unique ID for each element since their data
			// ends up in the global cache
			if ( isNode ) {
				elem[ jQuery.expando ] = id = ++jQuery.uuid;
			} else {
				id = jQuery.expando;
			}
		}

		if ( !cache[ id ] ) {
			cache[ id ] = {};

			// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
			// metadata on plain JS objects when the object is serialized using
			// JSON.stringify
			if ( !isNode ) {
				cache[ id ].toJSON = jQuery.noop;
			}
		}

		// An object can be passed to jQuery.data instead of a key/value pair; this gets
		// shallow copied over onto the existing cache
		if ( typeof name === "object" || typeof name === "function" ) {
			if ( pvt ) {
				cache[ id ][ internalKey ] = jQuery.extend(cache[ id ][ internalKey ], name);
			} else {
				cache[ id ] = jQuery.extend(cache[ id ], name);
			}
		}

		thisCache = cache[ id ];

		// Internal jQuery data is stored in a separate object inside the object's data
		// cache in order to avoid key collisions between internal data and user-defined
		// data
		if ( pvt ) {
			if ( !thisCache[ internalKey ] ) {
				thisCache[ internalKey ] = {};
			}

			thisCache = thisCache[ internalKey ];
		}

		if ( data !== undefined ) {
			thisCache[ name ] = data;
		}

		// TODO: This is a hack for 1.5 ONLY. It will be removed in 1.6. Users should
		// not attempt to inspect the internal events object using jQuery.data, as this
		// internal data object is undocumented and subject to change.
		if ( name === "events" && !thisCache[name] ) {
			return thisCache[ internalKey ] && thisCache[ internalKey ].events;
		}

		return getByName ? thisCache[ name ] : thisCache;
	},

	removeData: function( elem, name, pvt /* Internal Use Only */ ) {
		if ( !jQuery.acceptData( elem ) ) {
			return;
		}

		var internalKey = jQuery.expando, isNode = elem.nodeType,

			// See jQuery.data for more information
			cache = isNode ? jQuery.cache : elem,

			// See jQuery.data for more information
			id = isNode ? elem[ jQuery.expando ] : jQuery.expando;

		// If there is already no cache entry for this object, there is no
		// purpose in continuing
		if ( !cache[ id ] ) {
			return;
		}

		if ( name ) {
			var thisCache = pvt ? cache[ id ][ internalKey ] : cache[ id ];

			if ( thisCache ) {
				delete thisCache[ name ];

				// If there is no data left in the cache, we want to continue
				// and let the cache object itself get destroyed
				if ( !isEmptyDataObject(thisCache) ) {
					return;
				}
			}
		}

		// See jQuery.data for more information
		if ( pvt ) {
			delete cache[ id ][ internalKey ];

			// Don't destroy the parent cache unless the internal data object
			// had been the only thing left in it
			if ( !isEmptyDataObject(cache[ id ]) ) {
				return;
			}
		}

		var internalCache = cache[ id ][ internalKey ];

		// Browsers that fail expando deletion also refuse to delete expandos on
		// the window, but it will allow it on all other JS objects; other browsers
		// don't care
		if ( jQuery.support.deleteExpando || cache != window ) {
			delete cache[ id ];
		} else {
			cache[ id ] = null;
		}

		// We destroyed the entire user cache at once because it's faster than
		// iterating through each key, but we need to continue to persist internal
		// data if it existed
		if ( internalCache ) {
			cache[ id ] = {};
			// TODO: This is a hack for 1.5 ONLY. Avoids exposing jQuery
			// metadata on plain JS objects when the object is serialized using
			// JSON.stringify
			if ( !isNode ) {
				cache[ id ].toJSON = jQuery.noop;
			}

			cache[ id ][ internalKey ] = internalCache;

		// Otherwise, we need to eliminate the expando on the node to avoid
		// false lookups in the cache for entries that no longer exist
		} else if ( isNode ) {
			// IE does not allow us to delete expando properties from nodes,
			// nor does it have a removeAttribute function on Document nodes;
			// we must handle all of these cases
			if ( jQuery.support.deleteExpando ) {
				delete elem[ jQuery.expando ];
			} else if ( elem.removeAttribute ) {
				elem.removeAttribute( jQuery.expando );
			} else {
				elem[ jQuery.expando ] = null;
			}
		}
	},

	// For internal use only.
	_data: function( elem, name, data ) {
		return jQuery.data( elem, name, data, true );
	},

	// A method for determining if a DOM node can handle the data expando
	acceptData: function( elem ) {
		if ( elem.nodeName ) {
			var match = jQuery.noData[ elem.nodeName.toLowerCase() ];

			if ( match ) {
				return !(match === true || elem.getAttribute("classid") !== match);
			}
		}

		return true;
	}
});

jQuery.fn.extend({
	data: function( key, value ) {
		var data = null;

		if ( typeof key === "undefined" ) {
			if ( this.length ) {
				data = jQuery.data( this[0] );

				if ( this[0].nodeType === 1 ) {
					var attr = this[0].attributes, name;
					for ( var i = 0, l = attr.length; i < l; i++ ) {
						name = attr[i].name;

						if ( name.indexOf( "data-" ) === 0 ) {
							name = name.substr( 5 );
							dataAttr( this[0], name, data[ name ] );
						}
					}
				}
			}

			return data;

		} else if ( typeof key === "object" ) {
			return this.each(function() {
				jQuery.data( this, key );
			});
		}

		var parts = key.split(".");
		parts[1] = parts[1] ? "." + parts[1] : "";

		if ( value === undefined ) {
			data = this.triggerHandler("getData" + parts[1] + "!", [parts[0]]);

			// Try to fetch any internally stored data first
			if ( data === undefined && this.length ) {
				data = jQuery.data( this[0], key );
				data = dataAttr( this[0], key, data );
			}

			return data === undefined && parts[1] ?
				this.data( parts[0] ) :
				data;

		} else {
			return this.each(function() {
				var $this = jQuery( this ),
					args = [ parts[0], value ];

				$this.triggerHandler( "setData" + parts[1] + "!", args );
				jQuery.data( this, key, value );
				$this.triggerHandler( "changeData" + parts[1] + "!", args );
			});
		}
	},

	removeData: function( key ) {
		return this.each(function() {
			jQuery.removeData( this, key );
		});
	}
});

function dataAttr( elem, key, data ) {
	// If nothing was found internally, try to fetch any
	// data from the HTML5 data-* attribute
	if ( data === undefined && elem.nodeType === 1 ) {
		data = elem.getAttribute( "data-" + key );

		if ( typeof data === "string" ) {
			try {
				data = data === "true" ? true :
				data === "false" ? false :
				data === "null" ? null :
				!jQuery.isNaN( data ) ? parseFloat( data ) :
					rbrace.test( data ) ? jQuery.parseJSON( data ) :
					data;
			} catch( e ) {}

			// Make sure we set the data so it isn't changed later
			jQuery.data( elem, key, data );

		} else {
			data = undefined;
		}
	}

	return data;
}

// TODO: This is a hack for 1.5 ONLY to allow objects with a single toJSON
// property to be considered empty objects; this property always exists in
// order to make sure JSON.stringify does not expose internal metadata
function isEmptyDataObject( obj ) {
	for ( var name in obj ) {
		if ( name !== "toJSON" ) {
			return false;
		}
	}

	return true;
}




jQuery.extend({
	queue: function( elem, type, data ) {
		if ( !elem ) {
			return;
		}

		type = (type || "fx") + "queue";
		var q = jQuery._data( elem, type );

		// Speed up dequeue by getting out quickly if this is just a lookup
		if ( !data ) {
			return q || [];
		}

		if ( !q || jQuery.isArray(data) ) {
			q = jQuery._data( elem, type, jQuery.makeArray(data) );

		} else {
			q.push( data );
		}

		return q;
	},

	dequeue: function( elem, type ) {
		type = type || "fx";

		var queue = jQuery.queue( elem, type ),
			fn = queue.shift();

		// If the fx queue is dequeued, always remove the progress sentinel
		if ( fn === "inprogress" ) {
			fn = queue.shift();
		}

		if ( fn ) {
			// Add a progress sentinel to prevent the fx queue from being
			// automatically dequeued
			if ( type === "fx" ) {
				queue.unshift("inprogress");
			}

			fn.call(elem, function() {
				jQuery.dequeue(elem, type);
			});
		}

		if ( !queue.length ) {
			jQuery.removeData( elem, type + "queue", true );
		}
	}
});

jQuery.fn.extend({
	queue: function( type, data ) {
		if ( typeof type !== "string" ) {
			data = type;
			type = "fx";
		}

		if ( data === undefined ) {
			return jQuery.queue( this[0], type );
		}
		return this.each(function( i ) {
			var queue = jQuery.queue( this, type, data );

			if ( type === "fx" && queue[0] !== "inprogress" ) {
				jQuery.dequeue( this, type );
			}
		});
	},
	dequeue: function( type ) {
		return this.each(function() {
			jQuery.dequeue( this, type );
		});
	},

	// Based off of the plugin by Clint Helfers, with permission.
	// http://blindsignals.com/index.php/2009/07/jquery-delay/
	delay: function( time, type ) {
		time = jQuery.fx ? jQuery.fx.speeds[time] || time : time;
		type = type || "fx";

		return this.queue( type, function() {
			var elem = this;
			setTimeout(function() {
				jQuery.dequeue( elem, type );
			}, time );
		});
	},

	clearQueue: function( type ) {
		return this.queue( type || "fx", [] );
	}
});




var rclass = /[\n\t\r]/g,
	rspaces = /\s+/,
	rreturn = /\r/g,
	rspecialurl = /^(?:href|src|style)$/,
	rtype = /^(?:button|input)$/i,
	rfocusable = /^(?:button|input|object|select|textarea)$/i,
	rclickable = /^a(?:rea)?$/i,
	rradiocheck = /^(?:radio|checkbox)$/i;

jQuery.props = {
	"for": "htmlFor",
	"class": "className",
	readonly: "readOnly",
	maxlength: "maxLength",
	cellspacing: "cellSpacing",
	rowspan: "rowSpan",
	colspan: "colSpan",
	tabindex: "tabIndex",
	usemap: "useMap",
	frameborder: "frameBorder"
};

jQuery.fn.extend({
	attr: function( name, value ) {
		return jQuery.access( this, name, value, true, jQuery.attr );
	},

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

	addClass: function( value ) {
		if ( jQuery.isFunction(value) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.addClass( value.call(this, i, self.attr("class")) );
			});
		}

		if ( value && typeof value === "string" ) {
			var classNames = (value || "").split( rspaces );

			for ( var i = 0, l = this.length; i < l; i++ ) {
				var elem = this[i];

				if ( elem.nodeType === 1 ) {
					if ( !elem.className ) {
						elem.className = value;

					} else {
						var className = " " + elem.className + " ",
							setClass = elem.className;

						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
							if ( className.indexOf( " " + classNames[c] + " " ) < 0 ) {
								setClass += " " + classNames[c];
							}
						}
						elem.className = jQuery.trim( setClass );
					}
				}
			}
		}

		return this;
	},

	removeClass: function( value ) {
		if ( jQuery.isFunction(value) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.removeClass( value.call(this, i, self.attr("class")) );
			});
		}

		if ( (value && typeof value === "string") || value === undefined ) {
			var classNames = (value || "").split( rspaces );

			for ( var i = 0, l = this.length; i < l; i++ ) {
				var elem = this[i];

				if ( elem.nodeType === 1 && elem.className ) {
					if ( value ) {
						var className = (" " + elem.className + " ").replace(rclass, " ");
						for ( var c = 0, cl = classNames.length; c < cl; c++ ) {
							className = className.replace(" " + classNames[c] + " ", " ");
						}
						elem.className = jQuery.trim( className );

					} else {
						elem.className = "";
					}
				}
			}
		}

		return this;
	},

	toggleClass: function( value, stateVal ) {
		var type = typeof value,
			isBool = typeof stateVal === "boolean";

		if ( jQuery.isFunction( value ) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				self.toggleClass( value.call(this, i, self.attr("class"), stateVal), stateVal );
			});
		}

		return this.each(function() {
			if ( type === "string" ) {
				// toggle individual class names
				var className,
					i = 0,
					self = jQuery( this ),
					state = stateVal,
					classNames = value.split( rspaces );

				while ( (className = classNames[ i++ ]) ) {
					// check each className given, space seperated list
					state = isBool ? state : !self.hasClass( className );
					self[ state ? "addClass" : "removeClass" ]( className );
				}

			} else if ( type === "undefined" || type === "boolean" ) {
				if ( this.className ) {
					// store className if set
					jQuery._data( this, "__className__", this.className );
				}

				// toggle whole className
				this.className = this.className || value === false ? "" : jQuery._data( this, "__className__" ) || "";
			}
		});
	},

	hasClass: function( selector ) {
		var className = " " + selector + " ";
		for ( var i = 0, l = this.length; i < l; i++ ) {
			if ( (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
				return true;
			}
		}

		return false;
	},

	val: function( value ) {
		if ( !arguments.length ) {
			var elem = this[0];

			if ( elem ) {
				if ( jQuery.nodeName( elem, "option" ) ) {
					// attributes.value is undefined in Blackberry 4.7 but
					// uses .value. See #6932
					var val = elem.attributes.value;
					return !val || val.specified ? elem.value : elem.text;
				}

				// 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 ];

						// Don't return options that are disabled or in a disabled optgroup
						if ( option.selected && (jQuery.support.optDisabled ? !option.disabled : option.getAttribute("disabled") === null) &&
								(!option.parentNode.disabled || !jQuery.nodeName( option.parentNode, "optgroup" )) ) {

							// Get the specific value for the option
							value = jQuery(option).val();

							// We don't need an array for one selects
							if ( one ) {
								return value;
							}

							// Multi-Selects return an array
							values.push( value );
						}
					}

					// Fixes Bug #2551 -- select.val() broken in IE after form.reset()
					if ( one && !values.length && options.length ) {
						return jQuery( options[ index ] ).val();
					}

					return values;
				}

				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
				if ( rradiocheck.test( elem.type ) && !jQuery.support.checkOn ) {
					return elem.getAttribute("value") === null ? "on" : elem.value;
				}

				// Everything else, we just grab the value
				return (elem.value || "").replace(rreturn, "");

			}

			return undefined;
		}

		var isFunction = jQuery.isFunction(value);

		return this.each(function(i) {
			var self = jQuery(this), val = value;

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

			if ( isFunction ) {
				val = value.call(this, i, self.val());
			}

			// Treat null/undefined as ""; convert numbers to string
			if ( val == null ) {
				val = "";
			} else if ( typeof val === "number" ) {
				val += "";
			} else if ( jQuery.isArray(val) ) {
				val = jQuery.map(val, function (value) {
					return value == null ? "" : value + "";
				});
			}

			if ( jQuery.isArray(val) && rradiocheck.test( this.type ) ) {
				this.checked = jQuery.inArray( self.val(), val ) >= 0;

			} else if ( jQuery.nodeName( this, "select" ) ) {
				var values = jQuery.makeArray(val);

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

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

			} else {
				this.value = val;
			}
		});
	}
});

jQuery.extend({
	attrFn: {
		val: true,
		css: true,
		html: true,
		text: true,
		data: true,
		width: true,
		height: true,
		offset: true
	},

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

		if ( pass && name in jQuery.attrFn ) {
			return jQuery(elem)[name](value);
		}

		var notxml = elem.nodeType !== 1 || !jQuery.isXMLDoc( elem ),
			// Whether we are setting (or getting)
			set = value !== undefined;

		// Try to normalize/fix the name
		name = notxml && jQuery.props[ name ] || name;

		// Only do all the following if this is a node (faster for style)
		if ( elem.nodeType === 1 ) {
			// These attributes require special treatment
			var special = rspecialurl.test( name );

			// Safari mis-reports the default selected property of an option
			// Accessing the parent's selectedIndex property fixes it
			if ( name === "selected" && !jQuery.support.optSelected ) {
				var parent = elem.parentNode;
				if ( parent ) {
					parent.selectedIndex;

					// Make sure that it also works with optgroups, see #5701
					if ( parent.parentNode ) {
						parent.parentNode.selectedIndex;
					}
				}
			}

			// If applicable, access the attribute via the DOM 0 way
			// 'in' checks fail in Blackberry 4.7 #6931
			if ( (name in elem || elem[ name ] !== undefined) && notxml && !special ) {
				if ( set ) {
					// We can't allow the type property to be changed (since it causes problems in IE)
					if ( name === "type" && rtype.test( elem.nodeName ) && elem.parentNode ) {
						jQuery.error( "type property can't be changed" );
					}

					if ( value === null ) {
						if ( elem.nodeType === 1 ) {
							elem.removeAttribute( name );
						}

					} else {
						elem[ name ] = value;
					}
				}

				// browsers index elements by id/name on forms, give priority to attributes.
				if ( jQuery.nodeName( elem, "form" ) && elem.getAttributeNode(name) ) {
					return elem.getAttributeNode( name ).nodeValue;
				}

				// elem.tabIndex doesn't always return the correct value when it hasn't been explicitly set
				// http://fluidproject.org/blog/2008/01/09/getting-setting-and-removing-tabindex-values-with-javascript/
				if ( name === "tabIndex" ) {
					var attributeNode = elem.getAttributeNode( "tabIndex" );

					return attributeNode && attributeNode.specified ?
						attributeNode.value :
						rfocusable.test( elem.nodeName ) || rclickable.test( elem.nodeName ) && elem.href ?
							0 :
							undefined;
				}

				return elem[ name ];
			}

			if ( !jQuery.support.style && notxml && name === "style" ) {
				if ( set ) {
					elem.style.cssText = "" + value;
				}

				return elem.style.cssText;
			}

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

			// Ensure that missing attributes return undefined
			// Blackberry 4.7 returns "" from getAttribute #6938
			if ( !elem.attributes[ name ] && (elem.hasAttribute && !elem.hasAttribute( name )) ) {
				return undefined;
			}

			var attr = !jQuery.support.hrefNormalized && notxml && special ?
					// Some attributes require a special call on IE
					elem.getAttribute( name, 2 ) :
					elem.getAttribute( name );

			// Non-existent attributes return null, we normalize to undefined
			return attr === null ? undefined : attr;
		}
		// Handle everything which isn't a DOM element node
		if ( set ) {
			elem[ name ] = value;
		}
		return elem[ name ];
	}
});




var rnamespaces = /\.(.*)$/,
	rformElems = /^(?:textarea|input|select)$/i,
	rperiod = /\./g,
	rspace = / /g,
	rescape = /[^\w\s.|`]/g,
	fcleanup = function( nm ) {
		return nm.replace(rescape, "\\$&");
	};

/*
 * A number of helper functions used for managing events.
 * Many of the ideas behind this code originated 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;
		}

		// TODO :: Use a try/catch until it's safe to pull this out (likely 1.6)
		// Minor release fix for bug #8018
		try {
			// For whatever reason, IE has trouble passing the window object
			// around, causing it to be cloned in the process
			if ( jQuery.isWindow( elem ) && ( elem !== window && !elem.frameElement ) ) {
				elem = window;
			}
		}
		catch ( e ) {}

		if ( handler === false ) {
			handler = returnFalse;
		} else if ( !handler ) {
			// Fixes bug #7229. Fix recommended by jdalton
			return;
		}

		var handleObjIn, handleObj;

		if ( handler.handler ) {
			handleObjIn = handler;
			handler = handleObjIn.handler;
		}

		// Make sure that the function being executed has a unique ID
		if ( !handler.guid ) {
			handler.guid = jQuery.guid++;
		}

		// Init the element's event structure
		var elemData = jQuery._data( elem );

		// If no elemData is found then we must be trying to bind to one of the
		// banned noData elements
		if ( !elemData ) {
			return;
		}

		var events = elemData.events,
			eventHandle = elemData.handle;

		if ( !events ) {
			elemData.events = events = {};
		}

		if ( !eventHandle ) {
			elemData.handle = eventHandle = function() {
				// Handle the second event of a trigger and when
				// an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && !jQuery.event.triggered ?
					jQuery.event.handle.apply( eventHandle.elem, arguments ) :
					undefined;
			};
		}

		// Add elem as a property of the handle function
		// This is to prevent a memory leak with non-native events in IE.
		eventHandle.elem = elem;

		// Handle multiple events separated by a space
		// jQuery(...).bind("mouseover mouseout", fn);
		types = types.split(" ");

		var type, i = 0, namespaces;

		while ( (type = types[ i++ ]) ) {
			handleObj = handleObjIn ?
				jQuery.extend({}, handleObjIn) :
				{ handler: handler, data: data };

			// Namespaced event handlers
			if ( type.indexOf(".") > -1 ) {
				namespaces = type.split(".");
				type = namespaces.shift();
				handleObj.namespace = namespaces.slice(0).sort().join(".");

			} else {
				namespaces = [];
				handleObj.namespace = "";
			}

			handleObj.type = type;
			if ( !handleObj.guid ) {
				handleObj.guid = handler.guid;
			}

			// Get the current list of functions bound to this event
			var handlers = events[ type ],
				special = jQuery.event.special[ 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 ( !special.setup || special.setup.call( elem, data, namespaces, eventHandle ) === false ) {
					// Bind the global event handler to the element
					if ( elem.addEventListener ) {
						elem.addEventListener( type, eventHandle, false );

					} else if ( elem.attachEvent ) {
						elem.attachEvent( "on" + type, eventHandle );
					}
				}
			}

			if ( special.add ) {
				special.add.call( elem, handleObj );

				if ( !handleObj.handler.guid ) {
					handleObj.handler.guid = handler.guid;
				}
			}

			// Add the function to the element's handler list
			handlers.push( handleObj );

			// 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;
	},

	global: {},

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

		if ( handler === false ) {
			handler = returnFalse;
		}

		var ret, type, fn, j, i = 0, all, namespaces, namespace, special, eventType, handleObj, origType,
			elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
			events = elemData && elemData.events;

		if ( !elemData || !events ) {
			return;
		}

		// types is actually an event object here
		if ( types && types.type ) {
			handler = types.handler;
			types = types.type;
		}

		// Unbind all events for the element
		if ( !types || typeof types === "string" && types.charAt(0) === "." ) {
			types = types || "";

			for ( type in events ) {
				jQuery.event.remove( elem, type + types );
			}

			return;
		}

		// Handle multiple events separated by a space
		// jQuery(...).unbind("mouseover mouseout", fn);
		types = types.split(" ");

		while ( (type = types[ i++ ]) ) {
			origType = type;
			handleObj = null;
			all = type.indexOf(".") < 0;
			namespaces = [];

			if ( !all ) {
				// Namespaced event handlers
				namespaces = type.split(".");
				type = namespaces.shift();

				namespace = new RegExp("(^|\\.)" +
					jQuery.map( namespaces.slice(0).sort(), fcleanup ).join("\\.(?:.*\\.)?") + "(\\.|$)");
			}

			eventType = events[ type ];

			if ( !eventType ) {
				continue;
			}

			if ( !handler ) {
				for ( j = 0; j < eventType.length; j++ ) {
					handleObj = eventType[ j ];

					if ( all || namespace.test( handleObj.namespace ) ) {
						jQuery.event.remove( elem, origType, handleObj.handler, j );
						eventType.splice( j--, 1 );
					}
				}

				continue;
			}

			special = jQuery.event.special[ type ] || {};

			for ( j = pos || 0; j < eventType.length; j++ ) {
				handleObj = eventType[ j ];

				if ( handler.guid === handleObj.guid ) {
					// remove the given handler for the given type
					if ( all || namespace.test( handleObj.namespace ) ) {
						if ( pos == null ) {
							eventType.splice( j--, 1 );
						}

						if ( special.remove ) {
							special.remove.call( elem, handleObj );
						}
					}

					if ( pos != null ) {
						break;
					}
				}
			}

			// remove generic event handler if no more handlers exist
			if ( eventType.length === 0 || pos != null && eventType.length === 1 ) {
				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
					jQuery.removeEvent( elem, type, elemData.handle );
				}

				ret = null;
				delete events[ type ];
			}
		}

		// Remove the expando if it's no longer used
		if ( jQuery.isEmptyObject( events ) ) {
			var handle = elemData.handle;
			if ( handle ) {
				handle.elem = null;
			}

			delete elemData.events;
			delete elemData.handle;

			if ( jQuery.isEmptyObject( elemData ) ) {
				jQuery.removeData( elem, undefined, true );
			}
		}
	},

	// bubbling is internal
	trigger: function( event, data, elem /*, bubbling */ ) {
		// Event object or event type
		var type = event.type || event,
			bubbling = arguments[3];

		if ( !bubbling ) {
			event = typeof event === "object" ?
				// jQuery.Event object
				event[ jQuery.expando ] ? event :
				// Object literal
				jQuery.extend( jQuery.Event(type), event ) :
				// Just the event type (string)
				jQuery.Event(type);

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

			// Handle a global trigger
			if ( !elem ) {
				// Don't bubble custom events when global (to avoid too much overhead)
				event.stopPropagation();

				// Only trigger if we've ever bound an event for it
				if ( jQuery.event.global[ type ] ) {
					// XXX This code smells terrible. event.js should not be directly
					// inspecting the data cache
					jQuery.each( jQuery.cache, function() {
						// internalKey variable is just used to make it easier to find
						// and potentially change this stuff later; currently it just
						// points to jQuery.expando
						var internalKey = jQuery.expando,
							internalCache = this[ internalKey ];
						if ( internalCache && internalCache.events && internalCache.events[ type ] ) {
							jQuery.event.trigger( event, data, internalCache.handle.elem );
						}
					});
				}
			}

			// Handle triggering a single element

			// don't do events on text and comment nodes
			if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 ) {
				return undefined;
			}

			// Clean up in case it is reused
			event.result = undefined;
			event.target = elem;

			// Clone the incoming data, if any
			data = jQuery.makeArray( data );
			data.unshift( event );
		}

		event.currentTarget = elem;

		// Trigger the event, it is assumed that "handle" is a function
		var handle = jQuery._data( elem, "handle" );

		if ( handle ) {
			handle.apply( elem, data );
		}

		var parent = elem.parentNode || elem.ownerDocument;

		// Trigger an inline bound script
		try {
			if ( !(elem && elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()]) ) {
				if ( elem[ "on" + type ] && elem[ "on" + type ].apply( elem, data ) === false ) {
					event.result = false;
					event.preventDefault();
				}
			}

		// prevent IE from throwing an error for some elements with some event types, see #3533
		} catch (inlineError) {}

		if ( !event.isPropagationStopped() && parent ) {
			jQuery.event.trigger( event, data, parent, true );

		} else if ( !event.isDefaultPrevented() ) {
			var old,
				target = event.target,
				targetType = type.replace( rnamespaces, "" ),
				isClick = jQuery.nodeName( target, "a" ) && targetType === "click",
				special = jQuery.event.special[ targetType ] || {};

			if ( (!special._default || special._default.call( elem, event ) === false) &&
				!isClick && !(target && target.nodeName && jQuery.noData[target.nodeName.toLowerCase()]) ) {

				try {
					if ( target[ targetType ] ) {
						// Make sure that we don't accidentally re-trigger the onFOO events
						old = target[ "on" + targetType ];

						if ( old ) {
							target[ "on" + targetType ] = null;
						}

						jQuery.event.triggered = true;
						target[ targetType ]();
					}

				// prevent IE from throwing an error for some elements with some event types, see #3533
				} catch (triggerError) {}

				if ( old ) {
					target[ "on" + targetType ] = old;
				}

				jQuery.event.triggered = false;
			}
		}
	},

	handle: function( event ) {
		var all, handlers, namespaces, namespace_re, events,
			namespace_sort = [],
			args = jQuery.makeArray( arguments );

		event = args[0] = jQuery.event.fix( event || window.event );
		event.currentTarget = this;

		// Namespaced event handlers
		all = event.type.indexOf(".") < 0 && !event.exclusive;

		if ( !all ) {
			namespaces = event.type.split(".");
			event.type = namespaces.shift();
			namespace_sort = namespaces.slice(0).sort();
			namespace_re = new RegExp("(^|\\.)" + namespace_sort.join("\\.(?:.*\\.)?") + "(\\.|$)");
		}

		event.namespace = event.namespace || namespace_sort.join(".");

		events = jQuery._data(this, "events");

		handlers = (events || {})[ event.type ];

		if ( events && handlers ) {
			// Clone the handlers to prevent manipulation
			handlers = handlers.slice(0);

			for ( var j = 0, l = handlers.length; j < l; j++ ) {
				var handleObj = handlers[ j ];

				// Filter the functions by class
				if ( all || namespace_re.test( handleObj.namespace ) ) {
					// Pass in a reference to the handler function itself
					// So that we can later remove it
					event.handler = handleObj.handler;
					event.data = handleObj.data;
					event.handleObj = handleObj;

					var ret = handleObj.handler.apply( this, args );

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

					if ( event.isImmediatePropagationStopped() ) {
						break;
					}
				}
			}
		}

		return event.result;
	},

	props: "altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode layerX layerY metaKey newValue offsetX offsetY pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),

	fix: function( event ) {
		if ( event[ jQuery.expando ] ) {
			return event;
		}

		// store a copy of the original event object
		// and "clone" to set read-only properties
		var originalEvent = event;
		event = jQuery.Event( originalEvent );

		for ( var i = this.props.length, prop; i; ) {
			prop = this.props[ --i ];
			event[ prop ] = originalEvent[ prop ];
		}

		// Fix target property, if necessary
		if ( !event.target ) {
			// Fixes #1925 where srcElement might not be defined either
			event.target = event.srcElement || document;
		}

		// check if target is a textnode (safari)
		if ( event.target.nodeType === 3 ) {
			event.target = event.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 && doc.clientLeft || body && body.clientLeft || 0);
			event.pageY = event.clientY + (doc && doc.scrollTop  || body && body.scrollTop  || 0) - (doc && doc.clientTop  || body && body.clientTop  || 0);
		}

		// Add which for key events
		if ( event.which == null && (event.charCode != null || event.keyCode != null) ) {
			event.which = event.charCode != null ? 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 !== undefined ) {
			event.which = (event.button & 1 ? 1 : ( event.button & 2 ? 3 : ( event.button & 4 ? 2 : 0 ) ));
		}

		return event;
	},

	// Deprecated, use jQuery.guid instead
	guid: 1E8,

	// Deprecated, use jQuery.proxy instead
	proxy: jQuery.proxy,

	special: {
		ready: {
			// Make sure the ready event is setup
			setup: jQuery.bindReady,
			teardown: jQuery.noop
		},

		live: {
			add: function( handleObj ) {
				jQuery.event.add( this,
					liveConvert( handleObj.origType, handleObj.selector ),
					jQuery.extend({}, handleObj, {handler: liveHandler, guid: handleObj.handler.guid}) );
			},

			remove: function( handleObj ) {
				jQuery.event.remove( this, liveConvert( handleObj.origType, handleObj.selector ), handleObj );
			}
		},

		beforeunload: {
			setup: function( data, namespaces, eventHandle ) {
				// We only want to do this special case on windows
				if ( jQuery.isWindow( this ) ) {
					this.onbeforeunload = eventHandle;
				}
			},

			teardown: function( namespaces, eventHandle ) {
				if ( this.onbeforeunload === eventHandle ) {
					this.onbeforeunload = null;
				}
			}
		}
	}
};

jQuery.removeEvent = document.removeEventListener ?
	function( elem, type, handle ) {
		if ( elem.removeEventListener ) {
			elem.removeEventListener( type, handle, false );
		}
	} :
	function( elem, type, handle ) {
		if ( elem.detachEvent ) {
			elem.detachEvent( "on" + type, handle );
		}
	};

jQuery.Event = function( src ) {
	// Allow instantiation without the 'new' keyword
	if ( !this.preventDefault ) {
		return new jQuery.Event( src );
	}

	// Event object
	if ( src && src.type ) {
		this.originalEvent = src;
		this.type = src.type;

		// Events bubbling up the document may have been marked as prevented
		// by a handler lower down the tree; reflect the correct value.
		this.isDefaultPrevented = (src.defaultPrevented || src.returnValue === false ||
			src.getPreventDefault && src.getPreventDefault()) ? returnTrue : returnFalse;

	// Event type
	} else {
		this.type = src;
	}

	// timeStamp is buggy for some events on Firefox(#3843)
	// So we won't rely on the native value
	this.timeStamp = jQuery.now();

	// Mark it as fixed
	this[ jQuery.expando ] = true;
};

function returnFalse() {
	return false;
}
function returnTrue() {
	return true;
}

// jQuery.Event is based on DOM3 Events as specified by the ECMAScript Language Binding
// http://www.w3.org/TR/2003/WD-DOM-Level-3-Events-20030331/ecma-script-binding.html
jQuery.Event.prototype = {
	preventDefault: function() {
		this.isDefaultPrevented = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}

		// if preventDefault exists run it on the original event
		if ( e.preventDefault ) {
			e.preventDefault();

		// otherwise set the returnValue property of the original event to false (IE)
		} else {
			e.returnValue = false;
		}
	},
	stopPropagation: function() {
		this.isPropagationStopped = returnTrue;

		var e = this.originalEvent;
		if ( !e ) {
			return;
		}
		// if stopPropagation exists run it on the original event
		if ( e.stopPropagation ) {
			e.stopPropagation();
		}
		// otherwise set the cancelBubble property of the original event to true (IE)
		e.cancelBubble = true;
	},
	stopImmediatePropagation: function() {
		this.isImmediatePropagationStopped = returnTrue;
		this.stopPropagation();
	},
	isDefaultPrevented: returnFalse,
	isPropagationStopped: returnFalse,
	isImmediatePropagationStopped: returnFalse
};

// Checks if an event happened on an element within another element
// Used in jQuery.event.special.mouseenter and mouseleave handlers
var withinElement = function( event ) {
	// Check if mouse(over|out) are still within the same parent element
	var parent = event.relatedTarget;

	// Firefox sometimes assigns relatedTarget a XUL element
	// which we cannot access the parentNode property of
	try {

		// Chrome does something similar, the parentNode property
		// can be accessed but is null.
		if ( parent !== document && !parent.parentNode ) {
			return;
		}
		// Traverse up the tree
		while ( parent && parent !== this ) {
			parent = parent.parentNode;
		}

		if ( parent !== this ) {
			// set the correct event type
			event.type = event.data;

			// handle event if we actually just moused on to a non sub-element
			jQuery.event.handle.apply( this, arguments );
		}

	// assuming we've left the element since we most likely mousedover a xul element
	} catch(e) { }
},

// In case of event delegation, we only need to rename the event.type,
// liveHandler will take care of the rest.
delegate = function( event ) {
	event.type = event.data;
	jQuery.event.handle.apply( this, arguments );
};

// Create mouseenter and mouseleave events
jQuery.each({
	mouseenter: "mouseover",
	mouseleave: "mouseout"
}, function( orig, fix ) {
	jQuery.event.special[ orig ] = {
		setup: function( data ) {
			jQuery.event.add( this, fix, data && data.selector ? delegate : withinElement, orig );
		},
		teardown: function( data ) {
			jQuery.event.remove( this, fix, data && data.selector ? delegate : withinElement );
		}
	};
});

// submit delegation
if ( !jQuery.support.submitBubbles ) {

	jQuery.event.special.submit = {
		setup: function( data, namespaces ) {
			if ( this.nodeName && this.nodeName.toLowerCase() !== "form" ) {
				jQuery.event.add(this, "click.specialSubmit", function( e ) {
					var elem = e.target,
						type = elem.type;

					if ( (type === "submit" || type === "image") && jQuery( elem ).closest("form").length ) {
						trigger( "submit", this, arguments );
					}
				});

				jQuery.event.add(this, "keypress.specialSubmit", function( e ) {
					var elem = e.target,
						type = elem.type;

					if ( (type === "text" || type === "password") && jQuery( elem ).closest("form").length && e.keyCode === 13 ) {
						trigger( "submit", this, arguments );
					}
				});

			} else {
				return false;
			}
		},

		teardown: function( namespaces ) {
			jQuery.event.remove( this, ".specialSubmit" );
		}
	};

}

// change delegation, happens here so we have bind.
if ( !jQuery.support.changeBubbles ) {

	var changeFilters,

	getVal = function( elem ) {
		var type = elem.type, val = elem.value;

		if ( type === "radio" || type === "checkbox" ) {
			val = elem.checked;

		} else if ( type === "select-multiple" ) {
			val = elem.selectedIndex > -1 ?
				jQuery.map( elem.options, function( elem ) {
					return elem.selected;
				}).join("-") :
				"";

		} else if ( elem.nodeName.toLowerCase() === "select" ) {
			val = elem.selectedIndex;
		}

		return val;
	},

	testChange = function testChange( e ) {
		var elem = e.target, data, val;

		if ( !rformElems.test( elem.nodeName ) || elem.readOnly ) {
			return;
		}

		data = jQuery._data( elem, "_change_data" );
		val = getVal(elem);

		// the current data will be also retrieved by beforeactivate
		if ( e.type !== "focusout" || elem.type !== "radio" ) {
			jQuery._data( elem, "_change_data", val );
		}

		if ( data === undefined || val === data ) {
			return;
		}

		if ( data != null || val ) {
			e.type = "change";
			e.liveFired = undefined;
			jQuery.event.trigger( e, arguments[1], elem );
		}
	};

	jQuery.event.special.change = {
		filters: {
			focusout: testChange,

			beforedeactivate: testChange,

			click: function( e ) {
				var elem = e.target, type = elem.type;

				if ( type === "radio" || type === "checkbox" || elem.nodeName.toLowerCase() === "select" ) {
					testChange.call( this, e );
				}
			},

			// Change has to be called before submit
			// Keydown will be called before keypress, which is used in submit-event delegation
			keydown: function( e ) {
				var elem = e.target, type = elem.type;

				if ( (e.keyCode === 13 && elem.nodeName.toLowerCase() !== "textarea") ||
					(e.keyCode === 32 && (type === "checkbox" || type === "radio")) ||
					type === "select-multiple" ) {
					testChange.call( this, e );
				}
			},

			// Beforeactivate happens also before the previous element is blurred
			// with this event you can't trigger a change event, but you can store
			// information
			beforeactivate: function( e ) {
				var elem = e.target;
				jQuery._data( elem, "_change_data", getVal(elem) );
			}
		},

		setup: function( data, namespaces ) {
			if ( this.type === "file" ) {
				return false;
			}

			for ( var type in changeFilters ) {
				jQuery.event.add( this, type + ".specialChange", changeFilters[type] );
			}

			return rformElems.test( this.nodeName );
		},

		teardown: function( namespaces ) {
			jQuery.event.remove( this, ".specialChange" );

			return rformElems.test( this.nodeName );
		}
	};

	changeFilters = jQuery.event.special.change.filters;

	// Handle when the input is .focus()'d
	changeFilters.focus = changeFilters.beforeactivate;
}

function trigger( type, elem, args ) {
	// Piggyback on a donor event to simulate a different one.
	// Fake originalEvent to avoid donor's stopPropagation, but if the
	// simulated event prevents default then we do the same on the donor.
	// Don't pass args or remember liveFired; they apply to the donor event.
	var event = jQuery.extend( {}, args[ 0 ] );
	event.type = type;
	event.originalEvent = {};
	event.liveFired = undefined;
	jQuery.event.handle.call( elem, event );
	if ( event.isDefaultPrevented() ) {
		args[ 0 ].preventDefault();
	}
}

// Create "bubbling" focus and blur events
if ( document.addEventListener ) {
	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {
		jQuery.event.special[ fix ] = {
			setup: function() {
				this.addEventListener( orig, handler, true );
			},
			teardown: function() {
				this.removeEventListener( orig, handler, true );
			}
		};

		function handler( e ) {
			e = jQuery.event.fix( e );
			e.type = fix;
			return jQuery.event.handle.call( this, e );
		}
	});
}

jQuery.each(["bind", "one"], function( i, name ) {
	jQuery.fn[ name ] = function( type, data, fn ) {
		// Handle object literals
		if ( typeof type === "object" ) {
			for ( var key in type ) {
				this[ name ](key, data, type[key], fn);
			}
			return this;
		}

		if ( jQuery.isFunction( data ) || data === false ) {
			fn = data;
			data = undefined;
		}

		var handler = name === "one" ? jQuery.proxy( fn, function( event ) {
			jQuery( this ).unbind( event, handler );
			return fn.apply( this, arguments );
		}) : fn;

		if ( type === "unload" && name !== "one" ) {
			this.one( type, data, fn );

		} else {
			for ( var i = 0, l = this.length; i < l; i++ ) {
				jQuery.event.add( this[i], type, handler, data );
			}
		}

		return this;
	};
});

jQuery.fn.extend({
	unbind: function( type, fn ) {
		// Handle object literals
		if ( typeof type === "object" && !type.preventDefault ) {
			for ( var key in type ) {
				this.unbind(key, type[key]);
			}

		} else {
			for ( var i = 0, l = this.length; i < l; i++ ) {
				jQuery.event.remove( this[i], type, fn );
			}
		}

		return this;
	},

	delegate: function( selector, types, data, fn ) {
		return this.live( types, data, fn, selector );
	},

	undelegate: function( selector, types, fn ) {
		if ( arguments.length === 0 ) {
				return this.unbind( "live" );

		} else {
			return this.die( types, null, fn, selector );
		}
	},

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

	triggerHandler: function( type, data ) {
		if ( this[0] ) {
			var event = jQuery.Event( type );
			event.preventDefault();
			event.stopPropagation();
			jQuery.event.trigger( event, data, this[0] );
			return event.result;
		}
	},

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

		// link all the functions, so any of them can unbind this click handler
		while ( i < args.length ) {
			jQuery.proxy( fn, args[ i++ ] );
		}

		return this.click( jQuery.proxy( fn, function( event ) {
			// Figure out which function to execute
			var lastToggle = ( jQuery._data( this, "lastToggle" + fn.guid ) || 0 ) % i;
			jQuery._data( this, "lastToggle" + fn.guid, lastToggle + 1 );

			// Make sure that clicks stop
			event.preventDefault();

			// and execute the function
			return args[ lastToggle ].apply( this, arguments ) || false;
		}));
	},

	hover: function( fnOver, fnOut ) {
		return this.mouseenter( fnOver ).mouseleave( fnOut || fnOver );
	}
});

var liveMap = {
	focus: "focusin",
	blur: "focusout",
	mouseenter: "mouseover",
	mouseleave: "mouseout"
};

jQuery.each(["live", "die"], function( i, name ) {
	jQuery.fn[ name ] = function( types, data, fn, origSelector /* Internal Use Only */ ) {
		var type, i = 0, match, namespaces, preType,
			selector = origSelector || this.selector,
			context = origSelector ? this : jQuery( this.context );

		if ( typeof types === "object" && !types.preventDefault ) {
			for ( var key in types ) {
				context[ name ]( key, data, types[key], selector );
			}

			return this;
		}

		if ( jQuery.isFunction( data ) ) {
			fn = data;
			data = undefined;
		}

		types = (types || "").split(" ");

		while ( (type = types[ i++ ]) != null ) {
			match = rnamespaces.exec( type );
			namespaces = "";

			if ( match )  {
				namespaces = match[0];
				type = type.replace( rnamespaces, "" );
			}

			if ( type === "hover" ) {
				types.push( "mouseenter" + namespaces, "mouseleave" + namespaces );
				continue;
			}

			preType = type;

			if ( type === "focus" || type === "blur" ) {
				types.push( liveMap[ type ] + namespaces );
				type = type + namespaces;

			} else {
				type = (liveMap[ type ] || type) + namespaces;
			}

			if ( name === "live" ) {
				// bind live handler
				for ( var j = 0, l = context.length; j < l; j++ ) {
					jQuery.event.add( context[j], "live." + liveConvert( type, selector ),
						{ data: data, selector: selector, handler: fn, origType: type, origHandler: fn, preType: preType } );
				}

			} else {
				// unbind live handler
				context.unbind( "live." + liveConvert( type, selector ), fn );
			}
		}

		return this;
	};
});

function liveHandler( event ) {
	var stop, maxLevel, related, match, handleObj, elem, j, i, l, data, close, namespace, ret,
		elems = [],
		selectors = [],
		events = jQuery._data( this, "events" );

	// Make sure we avoid non-left-click bubbling in Firefox (#3861) and disabled elements in IE (#6911)
	if ( event.liveFired === this || !events || !events.live || event.target.disabled || event.button && event.type === "click" ) {
		return;
	}

	if ( event.namespace ) {
		namespace = new RegExp("(^|\\.)" + event.namespace.split(".").join("\\.(?:.*\\.)?") + "(\\.|$)");
	}

	event.liveFired = this;

	var live = events.live.slice(0);

	for ( j = 0; j < live.length; j++ ) {
		handleObj = live[j];

		if ( handleObj.origType.replace( rnamespaces, "" ) === event.type ) {
			selectors.push( handleObj.selector );

		} else {
			live.splice( j--, 1 );
		}
	}

	match = jQuery( event.target ).closest( selectors, event.currentTarget );

	for ( i = 0, l = match.length; i < l; i++ ) {
		close = match[i];

		for ( j = 0; j < live.length; j++ ) {
			handleObj = live[j];

			if ( close.selector === handleObj.selector && (!namespace || namespace.test( handleObj.namespace )) && !close.elem.disabled ) {
				elem = close.elem;
				related = null;

				// Those two events require additional checking
				if ( handleObj.preType === "mouseenter" || handleObj.preType === "mouseleave" ) {
					event.type = handleObj.preType;
					related = jQuery( event.relatedTarget ).closest( handleObj.selector )[0];
				}

				if ( !related || related !== elem ) {
					elems.push({ elem: elem, handleObj: handleObj, level: close.level });
				}
			}
		}
	}

	for ( i = 0, l = elems.length; i < l; i++ ) {
		match = elems[i];

		if ( maxLevel && match.level > maxLevel ) {
			break;
		}

		event.currentTarget = match.elem;
		event.data = match.handleObj.data;
		event.handleObj = match.handleObj;

		ret = match.handleObj.origHandler.apply( match.elem, arguments );

		if ( ret === false || event.isPropagationStopped() ) {
			maxLevel = match.level;

			if ( ret === false ) {
				stop = false;
			}
			if ( event.isImmediatePropagationStopped() ) {
				break;
			}
		}
	}

	return stop;
}

function liveConvert( type, selector ) {
	return (type && type !== "*" ? type + "." : "") + selector.replace(rperiod, "`").replace(rspace, "&");
}

jQuery.each( ("blur focus focusin focusout load resize scroll unload click dblclick " +
	"mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave " +
	"change select submit keydown keypress keyup error").split(" "), function( i, name ) {

	// Handle event binding
	jQuery.fn[ name ] = function( data, fn ) {
		if ( fn == null ) {
			fn = data;
			data = null;
		}

		return arguments.length > 0 ?
			this.bind( name, data, fn ) :
			this.trigger( name );
	};

	if ( jQuery.attrFn ) {
		jQuery.attrFn[ name ] = true;
	}
});


/*!
 * Sizzle CSS Selector Engine
 *  Copyright 2011, The Dojo Foundation
 *  Released under the MIT, BSD, and GPL Licenses.
 *  More information: http://sizzlejs.com/
 */
(function(){

var chunker = /((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^\[\]]*\]|['"][^'"]*['"]|[^\[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?((?:.|\r|\n)*)/g,
	done = 0,
	toString = Object.prototype.toString,
	hasDuplicate = false,
	baseHasDuplicate = true,
	rBackslash = /\\/g,
	rNonWord = /\W/;

// Here we check if the JavaScript engine is using some sort of
// optimization where it does not always call our comparision
// function. If that is the case, discard the hasDuplicate value.
//   Thus far that includes Google Chrome.
[0, 0].sort(function() {
	baseHasDuplicate = false;
	return 0;
});

var Sizzle = function( selector, context, results, seed ) {
	results = results || [];
	context = context || document;

	var origContext = context;

	if ( context.nodeType !== 1 && context.nodeType !== 9 ) {
		return [];
	}
	
	if ( !selector || typeof selector !== "string" ) {
		return results;
	}

	var m, set, checkSet, extra, ret, cur, pop, i,
		prune = true,
		contextXML = Sizzle.isXML( context ),
		parts = [],
		soFar = selector;
	
	// Reset the position of the chunker regexp (start from head)
	do {
		chunker.exec( "" );
		m = chunker.exec( soFar );

		if ( m ) {
			soFar = m[3];
		
			parts.push( m[1] );
		
			if ( m[2] ) {
				extra = m[3];
				break;
			}
		}
	} while ( m );

	if ( parts.length > 1 && origPOS.exec( selector ) ) {

		if ( parts.length === 2 && Expr.relative[ parts[0] ] ) {
			set = posProcess( parts[0] + parts[1], context );

		} else {
			set = Expr.relative[ parts[0] ] ?
				[ context ] :
				Sizzle( parts.shift(), context );

			while ( parts.length ) {
				selector = parts.shift();

				if ( Expr.relative[ selector ] ) {
					selector += parts.shift();
				}
				
				set = posProcess( selector, set );
			}
		}

	} else {
		// Take a shortcut and set the context if the root selector is an ID
		// (but not if it'll be faster if the inner selector is an ID)
		if ( !seed && parts.length > 1 && context.nodeType === 9 && !contextXML &&
				Expr.match.ID.test(parts[0]) && !Expr.match.ID.test(parts[parts.length - 1]) ) {

			ret = Sizzle.find( parts.shift(), context, contextXML );
			context = ret.expr ?
				Sizzle.filter( ret.expr, ret.set )[0] :
				ret.set[0];
		}

		if ( context ) {
			ret = seed ?
				{ expr: parts.pop(), set: makeArray(seed) } :
				Sizzle.find( parts.pop(), parts.length === 1 && (parts[0] === "~" || parts[0] === "+") && context.parentNode ? context.parentNode : context, contextXML );

			set = ret.expr ?
				Sizzle.filter( ret.expr, ret.set ) :
				ret.set;

			if ( parts.length > 0 ) {
				checkSet = makeArray( set );

			} else {
				prune = false;
			}

			while ( parts.length ) {
				cur = parts.pop();
				pop = cur;

				if ( !Expr.relative[ cur ] ) {
					cur = "";
				} else {
					pop = parts.pop();
				}

				if ( pop == null ) {
					pop = context;
				}

				Expr.relative[ cur ]( checkSet, pop, contextXML );
			}

		} else {
			checkSet = parts = [];
		}
	}

	if ( !checkSet ) {
		checkSet = set;
	}

	if ( !checkSet ) {
		Sizzle.error( cur || selector );
	}

	if ( toString.call(checkSet) === "[object Array]" ) {
		if ( !prune ) {
			results.push.apply( results, checkSet );

		} else if ( context && context.nodeType === 1 ) {
			for ( i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && (checkSet[i] === true || checkSet[i].nodeType === 1 && Sizzle.contains(context, checkSet[i])) ) {
					results.push( set[i] );
				}
			}

		} else {
			for ( i = 0; checkSet[i] != null; i++ ) {
				if ( checkSet[i] && checkSet[i].nodeType === 1 ) {
					results.push( set[i] );
				}
			}
		}

	} else {
		makeArray( checkSet, results );
	}

	if ( extra ) {
		Sizzle( extra, origContext, results, seed );
		Sizzle.uniqueSort( results );
	}

	return results;
};

Sizzle.uniqueSort = function( results ) {
	if ( sortOrder ) {
		hasDuplicate = baseHasDuplicate;
		results.sort( sortOrder );

		if ( hasDuplicate ) {
			for ( var i = 1; i < results.length; i++ ) {
				if ( results[i] === results[ i - 1 ] ) {
					results.splice( i--, 1 );
				}
			}
		}
	}

	return results;
};

Sizzle.matches = function( expr, set ) {
	return Sizzle( expr, null, null, set );
};

Sizzle.matchesSelector = function( node, expr ) {
	return Sizzle( expr, null, null, [node] ).length > 0;
};

Sizzle.find = function( expr, context, isXML ) {
	var set;

	if ( !expr ) {
		return [];
	}

	for ( var i = 0, l = Expr.order.length; i < l; i++ ) {
		var match,
			type = Expr.order[i];
		
		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
			var left = match[1];
			match.splice( 1, 1 );

			if ( left.substr( left.length - 1 ) !== "\\" ) {
				match[1] = (match[1] || "").replace( rBackslash, "" );
				set = Expr.find[ type ]( match, context, isXML );

				if ( set != null ) {
					expr = expr.replace( Expr.match[ type ], "" );
					break;
				}
			}
		}
	}

	if ( !set ) {
		set = typeof context.getElementsByTagName !== "undefined" ?
			context.getElementsByTagName( "*" ) :
			[];
	}

	return { set: set, expr: expr };
};

Sizzle.filter = function( expr, set, inplace, not ) {
	var match, anyFound,
		old = expr,
		result = [],
		curLoop = set,
		isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );

	while ( expr && set.length ) {
		for ( var type in Expr.filter ) {
			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
				var found, item,
					filter = Expr.filter[ type ],
					left = match[1];

				anyFound = false;

				match.splice(1,1);

				if ( left.substr( left.length - 1 ) === "\\" ) {
					continue;
				}

				if ( curLoop === result ) {
					result = [];
				}

				if ( Expr.preFilter[ type ] ) {
					match = Expr.preFilter[ type ]( match, curLoop, inplace, result, not, isXMLFilter );

					if ( !match ) {
						anyFound = found = true;

					} else if ( match === true ) {
						continue;
					}
				}

				if ( match ) {
					for ( var i = 0; (item = curLoop[i]) != null; i++ ) {
						if ( item ) {
							found = filter( item, match, i, curLoop );
							var pass = not ^ !!found;

							if ( inplace && found != null ) {
								if ( pass ) {
									anyFound = true;

								} else {
									curLoop[i] = false;
								}

							} else if ( pass ) {
								result.push( item );
								anyFound = true;
							}
						}
					}
				}

				if ( found !== undefined ) {
					if ( !inplace ) {
						curLoop = result;
					}

					expr = expr.replace( Expr.match[ type ], "" );

					if ( !anyFound ) {
						return [];
					}

					break;
				}
			}
		}

		// Improper expression
		if ( expr === old ) {
			if ( anyFound == null ) {
				Sizzle.error( expr );

			} else {
				break;
			}
		}

		old = expr;
	}

	return curLoop;
};

Sizzle.error = function( msg ) {
	throw "Syntax error, unrecognized expression: " + msg;
};

var Expr = Sizzle.selectors = {
	order: [ "ID", "NAME", "TAG" ],

	match: {
		ID: /#((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
		CLASS: /\.((?:[\w\u00c0-\uFFFF\-]|\\.)+)/,
		NAME: /\[name=['"]*((?:[\w\u00c0-\uFFFF\-]|\\.)+)['"]*\]/,
		ATTR: /\[\s*((?:[\w\u00c0-\uFFFF\-]|\\.)+)\s*(?:(\S?=)\s*(?:(['"])(.*?)\3|(#?(?:[\w\u00c0-\uFFFF\-]|\\.)*)|)|)\s*\]/,
		TAG: /^((?:[\w\u00c0-\uFFFF\*\-]|\\.)+)/,
		CHILD: /:(only|nth|last|first)-child(?:\(\s*(even|odd|(?:[+\-]?\d+|(?:[+\-]?\d*)?n\s*(?:[+\-]\s*\d+)?))\s*\))?/,
		POS: /:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^\-]|$)/,
		PSEUDO: /:((?:[\w\u00c0-\uFFFF\-]|\\.)+)(?:\((['"]?)((?:\([^\)]+\)|[^\(\)]*)+)\2\))?/
	},

	leftMatch: {},

	attrMap: {
		"class": "className",
		"for": "htmlFor"
	},

	attrHandle: {
		href: function( elem ) {
			return elem.getAttribute( "href" );
		},
		type: function( elem ) {
			return elem.getAttribute( "type" );
		}
	},

	relative: {
		"+": function(checkSet, part){
			var isPartStr = typeof part === "string",
				isTag = isPartStr && !rNonWord.test( part ),
				isPartStrNotTag = isPartStr && !isTag;

			if ( isTag ) {
				part = part.toLowerCase();
			}

			for ( var i = 0, l = checkSet.length, elem; i < l; i++ ) {
				if ( (elem = checkSet[i]) ) {
					while ( (elem = elem.previousSibling) && elem.nodeType !== 1 ) {}

					checkSet[i] = isPartStrNotTag || elem && elem.nodeName.toLowerCase() === part ?
						elem || false :
						elem === part;
				}
			}

			if ( isPartStrNotTag ) {
				Sizzle.filter( part, checkSet, true );
			}
		},

		">": function( checkSet, part ) {
			var elem,
				isPartStr = typeof part === "string",
				i = 0,
				l = checkSet.length;

			if ( isPartStr && !rNonWord.test( part ) ) {
				part = part.toLowerCase();

				for ( ; i < l; i++ ) {
					elem = checkSet[i];

					if ( elem ) {
						var parent = elem.parentNode;
						checkSet[i] = parent.nodeName.toLowerCase() === part ? parent : false;
					}
				}

			} else {
				for ( ; i < l; i++ ) {
					elem = checkSet[i];

					if ( elem ) {
						checkSet[i] = isPartStr ?
							elem.parentNode :
							elem.parentNode === part;
					}
				}

				if ( isPartStr ) {
					Sizzle.filter( part, checkSet, true );
				}
			}
		},

		"": function(checkSet, part, isXML){
			var nodeCheck,
				doneName = done++,
				checkFn = dirCheck;

			if ( typeof part === "string" && !rNonWord.test( part ) ) {
				part = part.toLowerCase();
				nodeCheck = part;
				checkFn = dirNodeCheck;
			}

			checkFn( "parentNode", part, doneName, checkSet, nodeCheck, isXML );
		},

		"~": function( checkSet, part, isXML ) {
			var nodeCheck,
				doneName = done++,
				checkFn = dirCheck;

			if ( typeof part === "string" && !rNonWord.test( part ) ) {
				part = part.toLowerCase();
				nodeCheck = part;
				checkFn = dirNodeCheck;
			}

			checkFn( "previousSibling", part, doneName, checkSet, nodeCheck, isXML );
		}
	},

	find: {
		ID: function( match, context, isXML ) {
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);
				// Check parentNode to catch when Blackberry 4.6 returns
				// nodes that are no longer in the document #6963
				return m && m.parentNode ? [m] : [];
			}
		},

		NAME: function( match, context ) {
			if ( typeof context.getElementsByName !== "undefined" ) {
				var ret = [],
					results = context.getElementsByName( match[1] );

				for ( var i = 0, l = results.length; i < l; i++ ) {
					if ( results[i].getAttribute("name") === match[1] ) {
						ret.push( results[i] );
					}
				}

				return ret.length === 0 ? null : ret;
			}
		},

		TAG: function( match, context ) {
			if ( typeof context.getElementsByTagName !== "undefined" ) {
				return context.getElementsByTagName( match[1] );
			}
		}
	},
	preFilter: {
		CLASS: function( match, curLoop, inplace, result, not, isXML ) {
			match = " " + match[1].replace( rBackslash, "" ) + " ";

			if ( isXML ) {
				return match;
			}

			for ( var i = 0, elem; (elem = curLoop[i]) != null; i++ ) {
				if ( elem ) {
					if ( not ^ (elem.className && (" " + elem.className + " ").replace(/[\t\n\r]/g, " ").indexOf(match) >= 0) ) {
						if ( !inplace ) {
							result.push( elem );
						}

					} else if ( inplace ) {
						curLoop[i] = false;
					}
				}
			}

			return false;
		},

		ID: function( match ) {
			return match[1].replace( rBackslash, "" );
		},

		TAG: function( match, curLoop ) {
			return match[1].replace( rBackslash, "" ).toLowerCase();
		},

		CHILD: function( match ) {
			if ( match[1] === "nth" ) {
				if ( !match[2] ) {
					Sizzle.error( match[0] );
				}

				match[2] = match[2].replace(/^\+|\s*/g, '');

				// parse equations like 'even', 'odd', '5', '2n', '3n+2', '4n-1', '-n+6'
				var test = /(-?)(\d*)(?:n([+\-]?\d*))?/.exec(
					match[2] === "even" && "2n" || match[2] === "odd" && "2n+1" ||
					!/\D/.test( match[2] ) && "0n+" + match[2] || match[2]);

				// calculate the numbers (first)n+(last) including if they are negative
				match[2] = (test[1] + (test[2] || 1)) - 0;
				match[3] = test[3] - 0;
			}
			else if ( match[2] ) {
				Sizzle.error( match[0] );
			}

			// TODO: Move to normal caching system
			match[0] = done++;

			return match;
		},

		ATTR: function( match, curLoop, inplace, result, not, isXML ) {
			var name = match[1] = match[1].replace( rBackslash, "" );
			
			if ( !isXML && Expr.attrMap[name] ) {
				match[1] = Expr.attrMap[name];
			}

			// Handle if an un-quoted value was used
			match[4] = ( match[4] || match[5] || "" ).replace( rBackslash, "" );

			if ( match[2] === "~=" ) {
				match[4] = " " + match[4] + " ";
			}

			return match;
		},

		PSEUDO: function( match, curLoop, inplace, result, not ) {
			if ( match[1] === "not" ) {
				// If we're dealing with a complex expression, or a simple one
				if ( ( chunker.exec(match[3]) || "" ).length > 1 || /^\w/.test(match[3]) ) {
					match[3] = Sizzle(match[3], null, null, curLoop);

				} else {
					var ret = Sizzle.filter(match[3], curLoop, inplace, true ^ not);

					if ( !inplace ) {
						result.push.apply( result, ret );
					}

					return false;
				}

			} else if ( Expr.match.POS.test( match[0] ) || Expr.match.CHILD.test( match[0] ) ) {
				return true;
			}
			
			return match;
		},

		POS: function( match ) {
			match.unshift( true );

			return match;
		}
	},
	
	filters: {
		enabled: function( elem ) {
			return elem.disabled === false && elem.type !== "hidden";
		},

		disabled: function( elem ) {
			return elem.disabled === true;
		},

		checked: function( elem ) {
			return elem.checked === true;
		},
		
		selected: function( elem ) {
			// Accessing this property makes selected-by-default
			// options in Safari work properly
			if ( elem.parentNode ) {
				elem.parentNode.selectedIndex;
			}
			
			return elem.selected === true;
		},

		parent: function( elem ) {
			return !!elem.firstChild;
		},

		empty: function( elem ) {
			return !elem.firstChild;
		},

		has: function( elem, i, match ) {
			return !!Sizzle( match[3], elem ).length;
		},

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

		text: function( elem ) {
			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 
			// use getAttribute instead to test this case
			return "text" === elem.getAttribute( 'type' );
		},
		radio: function( elem ) {
			return "radio" === elem.type;
		},

		checkbox: function( elem ) {
			return "checkbox" === elem.type;
		},

		file: function( elem ) {
			return "file" === elem.type;
		},
		password: function( elem ) {
			return "password" === elem.type;
		},

		submit: function( elem ) {
			return "submit" === elem.type;
		},

		image: function( elem ) {
			return "image" === elem.type;
		},

		reset: function( elem ) {
			return "reset" === elem.type;
		},

		button: function( elem ) {
			return "button" === elem.type || elem.nodeName.toLowerCase() === "button";
		},

		input: function( elem ) {
			return (/input|select|textarea|button/i).test( elem.nodeName );
		}
	},
	setFilters: {
		first: function( elem, i ) {
			return i === 0;
		},

		last: function( elem, i, match, array ) {
			return i === array.length - 1;
		},

		even: function( elem, i ) {
			return i % 2 === 0;
		},

		odd: function( elem, i ) {
			return i % 2 === 1;
		},

		lt: function( elem, i, match ) {
			return i < match[3] - 0;
		},

		gt: function( elem, i, match ) {
			return i > match[3] - 0;
		},

		nth: function( elem, i, match ) {
			return match[3] - 0 === i;
		},

		eq: function( elem, i, match ) {
			return match[3] - 0 === i;
		}
	},
	filter: {
		PSEUDO: function( elem, match, i, array ) {
			var name = match[1],
				filter = Expr.filters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );

			} else if ( name === "contains" ) {
				return (elem.textContent || elem.innerText || Sizzle.getText([ elem ]) || "").indexOf(match[3]) >= 0;

			} else if ( name === "not" ) {
				var not = match[3];

				for ( var j = 0, l = not.length; j < l; j++ ) {
					if ( not[j] === elem ) {
						return false;
					}
				}

				return true;

			} else {
				Sizzle.error( name );
			}
		},

		CHILD: function( elem, match ) {
			var type = match[1],
				node = elem;

			switch ( type ) {
				case "only":
				case "first":
					while ( (node = node.previousSibling) )	 {
						if ( node.nodeType === 1 ) { 
							return false; 
						}
					}

					if ( type === "first" ) { 
						return true; 
					}

					node = elem;

				case "last":
					while ( (node = node.nextSibling) )	 {
						if ( node.nodeType === 1 ) { 
							return false; 
						}
					}

					return true;

				case "nth":
					var first = match[2],
						last = match[3];

					if ( first === 1 && last === 0 ) {
						return true;
					}
					
					var doneName = match[0],
						parent = elem.parentNode;
	
					if ( parent && (parent.sizcache !== doneName || !elem.nodeIndex) ) {
						var count = 0;
						
						for ( node = parent.firstChild; node; node = node.nextSibling ) {
							if ( node.nodeType === 1 ) {
								node.nodeIndex = ++count;
							}
						} 

						parent.sizcache = doneName;
					}
					
					var diff = elem.nodeIndex - last;

					if ( first === 0 ) {
						return diff === 0;

					} else {
						return ( diff % first === 0 && diff / first >= 0 );
					}
			}
		},

		ID: function( elem, match ) {
			return elem.nodeType === 1 && elem.getAttribute("id") === match;
		},

		TAG: function( elem, match ) {
			return (match === "*" && elem.nodeType === 1) || elem.nodeName.toLowerCase() === match;
		},
		
		CLASS: function( elem, match ) {
			return (" " + (elem.className || elem.getAttribute("class")) + " ")
				.indexOf( match ) > -1;
		},

		ATTR: function( elem, match ) {
			var name = match[1],
				result = Expr.attrHandle[ name ] ?
					Expr.attrHandle[ name ]( elem ) :
					elem[ name ] != null ?
						elem[ name ] :
						elem.getAttribute( name ),
				value = result + "",
				type = match[2],
				check = match[4];

			return result == null ?
				type === "!=" :
				type === "=" ?
				value === check :
				type === "*=" ?
				value.indexOf(check) >= 0 :
				type === "~=" ?
				(" " + value + " ").indexOf(check) >= 0 :
				!check ?
				value && result !== false :
				type === "!=" ?
				value !== check :
				type === "^=" ?
				value.indexOf(check) === 0 :
				type === "$=" ?
				value.substr(value.length - check.length) === check :
				type === "|=" ?
				value === check || value.substr(0, check.length + 1) === check + "-" :
				false;
		},

		POS: function( elem, match, i, array ) {
			var name = match[2],
				filter = Expr.setFilters[ name ];

			if ( filter ) {
				return filter( elem, i, match, array );
			}
		}
	}
};

var origPOS = Expr.match.POS,
	fescape = function(all, num){
		return "\\" + (num - 0 + 1);
	};

for ( var type in Expr.match ) {
	Expr.match[ type ] = new RegExp( Expr.match[ type ].source + (/(?![^\[]*\])(?![^\(]*\))/.source) );
	Expr.leftMatch[ type ] = new RegExp( /(^(?:.|\r|\n)*?)/.source + Expr.match[ type ].source.replace(/\\(\d+)/g, fescape) );
}

var makeArray = function( array, results ) {
	array = Array.prototype.slice.call( array, 0 );

	if ( results ) {
		results.push.apply( results, array );
		return results;
	}
	
	return array;
};

// Perform a simple check to determine if the browser is capable of
// converting a NodeList to an array using builtin methods.
// Also verifies that the returned array holds DOM nodes
// (which is not the case in the Blackberry browser)
try {
	Array.prototype.slice.call( document.documentElement.childNodes, 0 )[0].nodeType;

// Provide a fallback method if it does not work
} catch( e ) {
	makeArray = function( array, results ) {
		var i = 0,
			ret = results || [];

		if ( toString.call(array) === "[object Array]" ) {
			Array.prototype.push.apply( ret, array );

		} else {
			if ( typeof array.length === "number" ) {
				for ( var l = array.length; i < l; i++ ) {
					ret.push( array[i] );
				}

			} else {
				for ( ; array[i]; i++ ) {
					ret.push( array[i] );
				}
			}
		}

		return ret;
	};
}

var sortOrder, siblingCheck;

if ( document.documentElement.compareDocumentPosition ) {
	sortOrder = function( a, b ) {
		if ( a === b ) {
			hasDuplicate = true;
			return 0;
		}

		if ( !a.compareDocumentPosition || !b.compareDocumentPosition ) {
			return a.compareDocumentPosition ? -1 : 1;
		}

		return a.compareDocumentPosition(b) & 4 ? -1 : 1;
	};

} else {
	sortOrder = function( a, b ) {
		var al, bl,
			ap = [],
			bp = [],
			aup = a.parentNode,
			bup = b.parentNode,
			cur = aup;

		// The nodes are identical, we can exit early
		if ( a === b ) {
			hasDuplicate = true;
			return 0;

		// If the nodes are siblings (or identical) we can do a quick check
		} else if ( aup === bup ) {
			return siblingCheck( a, b );

		// If no parents were found then the nodes are disconnected
		} else if ( !aup ) {
			return -1;

		} else if ( !bup ) {
			return 1;
		}

		// Otherwise they're somewhere else in the tree so we need
		// to build up a full list of the parentNodes for comparison
		while ( cur ) {
			ap.unshift( cur );
			cur = cur.parentNode;
		}

		cur = bup;

		while ( cur ) {
			bp.unshift( cur );
			cur = cur.parentNode;
		}

		al = ap.length;
		bl = bp.length;

		// Start walking down the tree looking for a discrepancy
		for ( var i = 0; i < al && i < bl; i++ ) {
			if ( ap[i] !== bp[i] ) {
				return siblingCheck( ap[i], bp[i] );
			}
		}

		// We ended someplace up the tree so do a sibling check
		return i === al ?
			siblingCheck( a, bp[i], -1 ) :
			siblingCheck( ap[i], b, 1 );
	};

	siblingCheck = function( a, b, ret ) {
		if ( a === b ) {
			return ret;
		}

		var cur = a.nextSibling;

		while ( cur ) {
			if ( cur === b ) {
				return -1;
			}

			cur = cur.nextSibling;
		}

		return 1;
	};
}

// Utility function for retreiving the text value of an array of DOM nodes
Sizzle.getText = function( elems ) {
	var ret = "", elem;

	for ( var i = 0; elems[i]; i++ ) {
		elem = elems[i];

		// Get the text from text nodes and CDATA nodes
		if ( elem.nodeType === 3 || elem.nodeType === 4 ) {
			ret += elem.nodeValue;

		// Traverse everything else, except comment nodes
		} else if ( elem.nodeType !== 8 ) {
			ret += Sizzle.getText( elem.childNodes );
		}
	}

	return ret;
};

// Check to see if the browser returns elements by name when
// querying by getElementById (and provide a workaround)
(function(){
	// We're going to inject a fake input element with a specified name
	var form = document.createElement("div"),
		id = "script" + (new Date()).getTime(),
		root = document.documentElement;

	form.innerHTML = "<a name='" + id + "'/>";

	// Inject it into the root element, check its status, and remove it quickly
	root.insertBefore( form, root.firstChild );

	// The workaround has to do additional checks after a getElementById
	// Which slows things down for other browsers (hence the branching)
	if ( document.getElementById( id ) ) {
		Expr.find.ID = function( match, context, isXML ) {
			if ( typeof context.getElementById !== "undefined" && !isXML ) {
				var m = context.getElementById(match[1]);

				return m ?
					m.id === match[1] || typeof m.getAttributeNode !== "undefined" && m.getAttributeNode("id").nodeValue === match[1] ?
						[m] :
						undefined :
					[];
			}
		};

		Expr.filter.ID = function( elem, match ) {
			var node = typeof elem.getAttributeNode !== "undefined" && elem.getAttributeNode("id");

			return elem.nodeType === 1 && node && node.nodeValue === match;
		};
	}

	root.removeChild( form );

	// release memory in IE
	root = form = null;
})();

(function(){
	// Check to see if the browser returns only elements
	// when doing getElementsByTagName("*")

	// Create a fake element
	var div = document.createElement("div");
	div.appendChild( document.createComment("") );

	// Make sure no comments are found
	if ( div.getElementsByTagName("*").length > 0 ) {
		Expr.find.TAG = function( match, context ) {
			var results = context.getElementsByTagName( match[1] );

			// Filter out possible comments
			if ( match[1] === "*" ) {
				var tmp = [];

				for ( var i = 0; results[i]; i++ ) {
					if ( results[i].nodeType === 1 ) {
						tmp.push( results[i] );
					}
				}

				results = tmp;
			}

			return results;
		};
	}

	// Check to see if an attribute returns normalized href attributes
	div.innerHTML = "<a href='#'></a>";

	if ( div.firstChild && typeof div.firstChild.getAttribute !== "undefined" &&
			div.firstChild.getAttribute("href") !== "#" ) {

		Expr.attrHandle.href = function( elem ) {
			return elem.getAttribute( "href", 2 );
		};
	}

	// release memory in IE
	div = null;
})();

if ( document.querySelectorAll ) {
	(function(){
		var oldSizzle = Sizzle,
			div = document.createElement("div"),
			id = "__sizzle__";

		div.innerHTML = "<p class='TEST'></p>";

		// Safari can't handle uppercase or unicode characters when
		// in quirks mode.
		if ( div.querySelectorAll && div.querySelectorAll(".TEST").length === 0 ) {
			return;
		}
	
		Sizzle = function( query, context, extra, seed ) {
			context = context || document;

			// Only use querySelectorAll on non-XML documents
			// (ID selectors don't work in non-HTML documents)
			if ( !seed && !Sizzle.isXML(context) ) {
				// See if we find a selector to speed up
				var match = /^(\w+$)|^\.([\w\-]+$)|^#([\w\-]+$)/.exec( query );
				
				if ( match && (context.nodeType === 1 || context.nodeType === 9) ) {
					// Speed-up: Sizzle("TAG")
					if ( match[1] ) {
						return makeArray( context.getElementsByTagName( query ), extra );
					
					// Speed-up: Sizzle(".CLASS")
					} else if ( match[2] && Expr.find.CLASS && context.getElementsByClassName ) {
						return makeArray( context.getElementsByClassName( match[2] ), extra );
					}
				}
				
				if ( context.nodeType === 9 ) {
					// Speed-up: Sizzle("body")
					// The body element only exists once, optimize finding it
					if ( query === "body" && context.body ) {
						return makeArray( [ context.body ], extra );
						
					// Speed-up: Sizzle("#ID")
					} else if ( match && match[3] ) {
						var elem = context.getElementById( match[3] );

						// Check parentNode to catch when Blackberry 4.6 returns
						// nodes that are no longer in the document #6963
						if ( elem && elem.parentNode ) {
							// Handle the case where IE and Opera return items
							// by name instead of ID
							if ( elem.id === match[3] ) {
								return makeArray( [ elem ], extra );
							}
							
						} else {
							return makeArray( [], extra );
						}
					}
					
					try {
						return makeArray( context.querySelectorAll(query), extra );
					} catch(qsaError) {}

				// qSA works strangely on Element-rooted queries
				// We can work around this by specifying an extra ID on the root
				// and working up from there (Thanks to Andrew Dupont for the technique)
				// IE 8 doesn't work on object elements
				} else if ( context.nodeType === 1 && context.nodeName.toLowerCase() !== "object" ) {
					var oldContext = context,
						old = context.getAttribute( "id" ),
						nid = old || id,
						hasParent = context.parentNode,
						relativeHierarchySelector = /^\s*[+~]/.test( query );

					if ( !old ) {
						context.setAttribute( "id", nid );
					} else {
						nid = nid.replace( /'/g, "\\$&" );
					}
					if ( relativeHierarchySelector && hasParent ) {
						context = context.parentNode;
					}

					try {
						if ( !relativeHierarchySelector || hasParent ) {
							return makeArray( context.querySelectorAll( "[id='" + nid + "'] " + query ), extra );
						}

					} catch(pseudoError) {
					} finally {
						if ( !old ) {
							oldContext.removeAttribute( "id" );
						}
					}
				}
			}
		
			return oldSizzle(query, context, extra, seed);
		};

		for ( var prop in oldSizzle ) {
			Sizzle[ prop ] = oldSizzle[ prop ];
		}

		// release memory in IE
		div = null;
	})();
}

(function(){
	var html = document.documentElement,
		matches = html.matchesSelector || html.mozMatchesSelector || html.webkitMatchesSelector || html.msMatchesSelector,
		pseudoWorks = false;

	try {
		// This should fail with an exception
		// Gecko does not error, returns false instead
		matches.call( document.documentElement, "[test!='']:sizzle" );
	
	} catch( pseudoError ) {
		pseudoWorks = true;
	}

	if ( matches ) {
		Sizzle.matchesSelector = function( node, expr ) {
			// Make sure that attribute selectors are quoted
			expr = expr.replace(/\=\s*([^'"\]]*)\s*\]/g, "='$1']");

			if ( !Sizzle.isXML( node ) ) {
				try { 
					if ( pseudoWorks || !Expr.match.PSEUDO.test( expr ) && !/!=/.test( expr ) ) {
						return matches.call( node, expr );
					}
				} catch(e) {}
			}

			return Sizzle(expr, null, null, [node]).length > 0;
		};
	}
})();

(function(){
	var div = document.createElement("div");

	div.innerHTML = "<div class='test e'></div><div class='test'></div>";

	// Opera can't find a second classname (in 9.6)
	// Also, make sure that getElementsByClassName actually exists
	if ( !div.getElementsByClassName || div.getElementsByClassName("e").length === 0 ) {
		return;
	}

	// Safari caches class attributes, doesn't catch changes (in 3.2)
	div.lastChild.className = "e";

	if ( div.getElementsByClassName("e").length === 1 ) {
		return;
	}
	
	Expr.order.splice(1, 0, "CLASS");
	Expr.find.CLASS = function( match, context, isXML ) {
		if ( typeof context.getElementsByClassName !== "undefined" && !isXML ) {
			return context.getElementsByClassName(match[1]);
		}
	};

	// release memory in IE
	div = null;
})();

function dirNodeCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];

		if ( elem ) {
			var match = false;

			elem = elem[dir];

			while ( elem ) {
				if ( elem.sizcache === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 && !isXML ){
					elem.sizcache = doneName;
					elem.sizset = i;
				}

				if ( elem.nodeName.toLowerCase() === cur ) {
					match = elem;
					break;
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

function dirCheck( dir, cur, doneName, checkSet, nodeCheck, isXML ) {
	for ( var i = 0, l = checkSet.length; i < l; i++ ) {
		var elem = checkSet[i];

		if ( elem ) {
			var match = false;
			
			elem = elem[dir];

			while ( elem ) {
				if ( elem.sizcache === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 ) {
					if ( !isXML ) {
						elem.sizcache = doneName;
						elem.sizset = i;
					}

					if ( typeof cur !== "string" ) {
						if ( elem === cur ) {
							match = true;
							break;
						}

					} else if ( Sizzle.filter( cur, [elem] ).length > 0 ) {
						match = elem;
						break;
					}
				}

				elem = elem[dir];
			}

			checkSet[i] = match;
		}
	}
}

if ( document.documentElement.contains ) {
	Sizzle.contains = function( a, b ) {
		return a !== b && (a.contains ? a.contains(b) : true);
	};

} else if ( document.documentElement.compareDocumentPosition ) {
	Sizzle.contains = function( a, b ) {
		return !!(a.compareDocumentPosition(b) & 16);
	};

} else {
	Sizzle.contains = function() {
		return false;
	};
}

Sizzle.isXML = function( elem ) {
	// documentElement is verified for cases where it doesn't yet exist
	// (such as loading iframes in IE - #4833) 
	var documentElement = (elem ? elem.ownerDocument || elem : 0).documentElement;

	return documentElement ? documentElement.nodeName !== "HTML" : false;
};

var posProcess = function( selector, context ) {
	var match,
		tmpSet = [],
		later = "",
		root = context.nodeType ? [context] : context;

	// Position selectors must be done after the filter
	// And so must :not(positional) so we move all PSEUDOs to the end
	while ( (match = Expr.match.PSEUDO.exec( selector )) ) {
		later += match[0];
		selector = selector.replace( Expr.match.PSEUDO, "" );
	}

	selector = Expr.relative[selector] ? selector + "*" : selector;

	for ( var i = 0, l = root.length; i < l; i++ ) {
		Sizzle( selector, root[i], tmpSet );
	}

	return Sizzle.filter( later, tmpSet );
};

// EXPOSE
jQuery.find = Sizzle;
jQuery.expr = Sizzle.selectors;
jQuery.expr[":"] = jQuery.expr.filters;
jQuery.unique = Sizzle.uniqueSort;
jQuery.text = Sizzle.getText;
jQuery.isXMLDoc = Sizzle.isXML;
jQuery.contains = Sizzle.contains;


})();


var runtil = /Until$/,
	rparentsprev = /^(?:parents|prevUntil|prevAll)/,
	// Note: This RegExp should be improved, or likely pulled from Sizzle
	rmultiselector = /,/,
	isSimple = /^.[^:#\[\.,]*$/,
	slice = Array.prototype.slice,
	POS = jQuery.expr.match.POS,
	// methods guaranteed to produce a unique set when starting from a unique set
	guaranteedUnique = {
		children: true,
		contents: true,
		next: true,
		prev: true
	};

jQuery.fn.extend({
	find: function( selector ) {
		var ret = this.pushStack( "", "find", selector ),
			length = 0;

		for ( var i = 0, l = this.length; i < l; i++ ) {
			length = ret.length;
			jQuery.find( selector, this[i], ret );

			if ( i > 0 ) {
				// Make sure that the results are unique
				for ( var n = length; n < ret.length; n++ ) {
					for ( var r = 0; r < length; r++ ) {
						if ( ret[r] === ret[n] ) {
							ret.splice(n--, 1);
							break;
						}
					}
				}
			}
		}

		return ret;
	},

	has: function( target ) {
		var targets = jQuery( target );
		return this.filter(function() {
			for ( var i = 0, l = targets.length; i < l; i++ ) {
				if ( jQuery.contains( this, targets[i] ) ) {
					return true;
				}
			}
		});
	},

	not: function( selector ) {
		return this.pushStack( winnow(this, selector, false), "not", selector);
	},

	filter: function( selector ) {
		return this.pushStack( winnow(this, selector, true), "filter", selector );
	},

	is: function( selector ) {
		return !!selector && jQuery.filter( selector, this ).length > 0;
	},

	closest: function( selectors, context ) {
		var ret = [], i, l, cur = this[0];

		if ( jQuery.isArray( selectors ) ) {
			var match, selector,
				matches = {},
				level = 1;

			if ( cur && selectors.length ) {
				for ( i = 0, l = selectors.length; i < l; i++ ) {
					selector = selectors[i];

					if ( !matches[selector] ) {
						matches[selector] = jQuery.expr.match.POS.test( selector ) ?
							jQuery( selector, context || this.context ) :
							selector;
					}
				}

				while ( cur && cur.ownerDocument && cur !== context ) {
					for ( selector in matches ) {
						match = matches[selector];

						if ( match.jquery ? match.index(cur) > -1 : jQuery(cur).is(match) ) {
							ret.push({ selector: selector, elem: cur, level: level });
						}
					}

					cur = cur.parentNode;
					level++;
				}
			}

			return ret;
		}

		var pos = POS.test( selectors ) ?
			jQuery( selectors, context || this.context ) : null;

		for ( i = 0, l = this.length; i < l; i++ ) {
			cur = this[i];

			while ( cur ) {
				if ( pos ? pos.index(cur) > -1 : jQuery.find.matchesSelector(cur, selectors) ) {
					ret.push( cur );
					break;

				} else {
					cur = cur.parentNode;
					if ( !cur || !cur.ownerDocument || cur === context ) {
						break;
					}
				}
			}
		}

		ret = ret.length > 1 ? jQuery.unique(ret) : ret;

		return this.pushStack( ret, "closest", selectors );
	},

	// Determine the position of an element within
	// the matched set of elements
	index: function( elem ) {
		if ( !elem || typeof elem === "string" ) {
			return jQuery.inArray( this[0],
				// If it receives a string, the selector is used
				// If it receives nothing, the siblings are used
				elem ? jQuery( elem ) : this.parent().children() );
		}
		// Locate the position of the desired element
		return jQuery.inArray(
			// If it receives a jQuery object, the first element is used
			elem.jquery ? elem[0] : elem, this );
	},

	add: function( selector, context ) {
		var set = typeof selector === "string" ?
				jQuery( selector, context ) :
				jQuery.makeArray( selector ),
			all = jQuery.merge( this.get(), set );

		return this.pushStack( isDisconnected( set[0] ) || isDisconnected( all[0] ) ?
			all :
			jQuery.unique( all ) );
	},

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

// A painfully simple check to see if an element is disconnected
// from a document (should be improved, where feasible).
function isDisconnected( node ) {
	return !node || !node.parentNode || node.parentNode.nodeType === 11;
}

jQuery.each({
	parent: function( elem ) {
		var parent = elem.parentNode;
		return parent && parent.nodeType !== 11 ? parent : null;
	},
	parents: function( elem ) {
		return jQuery.dir( elem, "parentNode" );
	},
	parentsUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "parentNode", until );
	},
	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" );
	},
	nextUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "nextSibling", until );
	},
	prevUntil: function( elem, i, until ) {
		return jQuery.dir( elem, "previousSibling", until );
	},
	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( until, selector ) {
		var ret = jQuery.map( this, fn, until ),
			// The variable 'args' was introduced in
			// https://github.com/jquery/jquery/commit/52a0238
			// to work around a bug in Chrome 10 (Dev) and should be removed when the bug is fixed.
			// http://code.google.com/p/v8/issues/detail?id=1050
			args = slice.call(arguments);

		if ( !runtil.test( name ) ) {
			selector = until;
		}

		if ( selector && typeof selector === "string" ) {
			ret = jQuery.filter( selector, ret );
		}

		ret = this.length > 1 && !guaranteedUnique[ name ] ? jQuery.unique( ret ) : ret;

		if ( (this.length > 1 || rmultiselector.test( selector )) && rparentsprev.test( name ) ) {
			ret = ret.reverse();
		}

		return this.pushStack( ret, name, args.join(",") );
	};
});

jQuery.extend({
	filter: function( expr, elems, not ) {
		if ( not ) {
			expr = ":not(" + expr + ")";
		}

		return elems.length === 1 ?
			jQuery.find.matchesSelector(elems[0], expr) ? [ elems[0] ] : [] :
			jQuery.find.matches(expr, elems);
	},

	dir: function( elem, dir, until ) {
		var matched = [],
			cur = elem[ dir ];

		while ( cur && cur.nodeType !== 9 && (until === undefined || cur.nodeType !== 1 || !jQuery( cur ).is( until )) ) {
			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 && n !== elem ) {
				r.push( n );
			}
		}

		return r;
	}
});

// Implement the identical functionality for filter and not
function winnow( elements, qualifier, keep ) {
	if ( jQuery.isFunction( qualifier ) ) {
		return jQuery.grep(elements, function( elem, i ) {
			var retVal = !!qualifier.call( elem, i, elem );
			return retVal === keep;
		});

	} else if ( qualifier.nodeType ) {
		return jQuery.grep(elements, function( elem, i ) {
			return (elem === qualifier) === keep;
		});

	} else if ( typeof qualifier === "string" ) {
		var filtered = jQuery.grep(elements, function( elem ) {
			return elem.nodeType === 1;
		});

		if ( isSimple.test( qualifier ) ) {
			return jQuery.filter(qualifier, filtered, !keep);
		} else {
			qualifier = jQuery.filter( qualifier, filtered );
		}
	}

	return jQuery.grep(elements, function( elem, i ) {
		return (jQuery.inArray( elem, qualifier ) >= 0) === keep;
	});
}




var rinlinejQuery = / jQuery\d+="(?:\d+|null)"/g,
	rleadingWhitespace = /^\s+/,
	rxhtmlTag = /<(?!area|br|col|embed|hr|img|input|link|meta|param)(([\w:]+)[^>]*)\/>/ig,
	rtagName = /<([\w:]+)/,
	rtbody = /<tbody/i,
	rhtml = /<|&#?\w+;/,
	rnocache = /<(?:script|object|embed|option|style)/i,
	// checked="checked" or checked
	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
	wrapMap = {
		option: [ 1, "<select multiple='multiple'>", "</select>" ],
		legend: [ 1, "<fieldset>", "</fieldset>" ],
		thead: [ 1, "<table>", "</table>" ],
		tr: [ 2, "<table><tbody>", "</tbody></table>" ],
		td: [ 3, "<table><tbody><tr>", "</tr></tbody></table>" ],
		col: [ 2, "<table><tbody></tbody><colgroup>", "</colgroup></table>" ],
		area: [ 1, "<map>", "</map>" ],
		_default: [ 0, "", "" ]
	};

wrapMap.optgroup = wrapMap.option;
wrapMap.tbody = wrapMap.tfoot = wrapMap.colgroup = wrapMap.caption = wrapMap.thead;
wrapMap.th = wrapMap.td;

// IE can't serialize <link> and <script> tags normally
if ( !jQuery.support.htmlSerialize ) {
	wrapMap._default = [ 1, "div<div>", "</div>" ];
}

jQuery.fn.extend({
	text: function( text ) {
		if ( jQuery.isFunction(text) ) {
			return this.each(function(i) {
				var self = jQuery( this );

				self.text( text.call(this, i, self.text()) );
			});
		}

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

		return jQuery.text( this );
	},

	wrapAll: function( html ) {
		if ( jQuery.isFunction( html ) ) {
			return this.each(function(i) {
				jQuery(this).wrapAll( html.call(this, i) );
			});
		}

		if ( this[0] ) {
			// The elements to wrap the target around
			var wrap = jQuery( html, this[0].ownerDocument ).eq(0).clone(true);

			if ( this[0].parentNode ) {
				wrap.insertBefore( this[0] );
			}

			wrap.map(function() {
				var elem = this;

				while ( elem.firstChild && elem.firstChild.nodeType === 1 ) {
					elem = elem.firstChild;
				}

				return elem;
			}).append(this);
		}

		return this;
	},

	wrapInner: function( html ) {
		if ( jQuery.isFunction( html ) ) {
			return this.each(function(i) {
				jQuery(this).wrapInner( html.call(this, i) );
			});
		}

		return this.each(function() {
			var self = jQuery( this ),
				contents = self.contents();

			if ( contents.length ) {
				contents.wrapAll( html );

			} else {
				self.append( html );
			}
		});
	},

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

	unwrap: function() {
		return this.parent().each(function() {
			if ( !jQuery.nodeName( this, "body" ) ) {
				jQuery( this ).replaceWith( this.childNodes );
			}
		}).end();
	},

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

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

	before: function() {
		if ( this[0] && this[0].parentNode ) {
			return this.domManip(arguments, false, function( elem ) {
				this.parentNode.insertBefore( elem, this );
			});
		} else if ( arguments.length ) {
			var set = jQuery(arguments[0]);
			set.push.apply( set, this.toArray() );
			return this.pushStack( set, "before", arguments );
		}
	},

	after: function() {
		if ( this[0] && this[0].parentNode ) {
			return this.domManip(arguments, false, function( elem ) {
				this.parentNode.insertBefore( elem, this.nextSibling );
			});
		} else if ( arguments.length ) {
			var set = this.pushStack( this, "after", arguments );
			set.push.apply( set, jQuery(arguments[0]).toArray() );
			return set;
		}
	},

	// keepData is for internal use only--do not document
	remove: function( selector, keepData ) {
		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
			if ( !selector || jQuery.filter( selector, [ elem ] ).length ) {
				if ( !keepData && elem.nodeType === 1 ) {
					jQuery.cleanData( elem.getElementsByTagName("*") );
					jQuery.cleanData( [ elem ] );
				}

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

		return this;
	},

	empty: function() {
		for ( var i = 0, elem; (elem = this[i]) != null; i++ ) {
			// Remove element nodes and prevent memory leaks
			if ( elem.nodeType === 1 ) {
				jQuery.cleanData( elem.getElementsByTagName("*") );
			}

			// Remove any remaining nodes
			while ( elem.firstChild ) {
				elem.removeChild( elem.firstChild );
			}
		}

		return this;
	},

	clone: function( dataAndEvents, deepDataAndEvents ) {
		dataAndEvents = dataAndEvents == null ? false : dataAndEvents;
		deepDataAndEvents = deepDataAndEvents == null ? dataAndEvents : deepDataAndEvents;

		return this.map( function () {
			return jQuery.clone( this, dataAndEvents, deepDataAndEvents );
		});
	},

	html: function( value ) {
		if ( value === undefined ) {
			return this[0] && this[0].nodeType === 1 ?
				this[0].innerHTML.replace(rinlinejQuery, "") :
				null;

		// See if we can take a shortcut and just use innerHTML
		} else if ( typeof value === "string" && !rnocache.test( value ) &&
			(jQuery.support.leadingWhitespace || !rleadingWhitespace.test( value )) &&
			!wrapMap[ (rtagName.exec( value ) || ["", ""])[1].toLowerCase() ] ) {

			value = value.replace(rxhtmlTag, "<$1></$2>");

			try {
				for ( var i = 0, l = this.length; i < l; i++ ) {
					// Remove element nodes and prevent memory leaks
					if ( this[i].nodeType === 1 ) {
						jQuery.cleanData( this[i].getElementsByTagName("*") );
						this[i].innerHTML = value;
					}
				}

			// If using innerHTML throws an exception, use the fallback method
			} catch(e) {
				this.empty().append( value );
			}

		} else if ( jQuery.isFunction( value ) ) {
			this.each(function(i){
				var self = jQuery( this );

				self.html( value.call(this, i, self.html()) );
			});

		} else {
			this.empty().append( value );
		}

		return this;
	},

	replaceWith: function( value ) {
		if ( this[0] && this[0].parentNode ) {
			// Make sure that the elements are removed from the DOM before they are inserted
			// this can help fix replacing a parent with child elements
			if ( jQuery.isFunction( value ) ) {
				return this.each(function(i) {
					var self = jQuery(this), old = self.html();
					self.replaceWith( value.call( this, i, old ) );
				});
			}

			if ( typeof value !== "string" ) {
				value = jQuery( value ).detach();
			}

			return this.each(function() {
				var next = this.nextSibling,
					parent = this.parentNode;

				jQuery( this ).remove();

				if ( next ) {
					jQuery(next).before( value );
				} else {
					jQuery(parent).append( value );
				}
			});
		} else {
			return this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value );
		}
	},

	detach: function( selector ) {
		return this.remove( selector, true );
	},

	domManip: function( args, table, callback ) {
		var results, first, fragment, parent,
			value = args[0],
			scripts = [];

		// We can't cloneNode fragments that contain checked, in WebKit
		if ( !jQuery.support.checkClone && arguments.length === 3 && typeof value === "string" && rchecked.test( value ) ) {
			return this.each(function() {
				jQuery(this).domManip( args, table, callback, true );
			});
		}

		if ( jQuery.isFunction(value) ) {
			return this.each(function(i) {
				var self = jQuery(this);
				args[0] = value.call(this, i, table ? self.html() : undefined);
				self.domManip( args, table, callback );
			});
		}

		if ( this[0] ) {
			parent = value && value.parentNode;

			// If we're in a fragment, just use that instead of building a new one
			if ( jQuery.support.parentNode && parent && parent.nodeType === 11 && parent.childNodes.length === this.length ) {
				results = { fragment: parent };

			} else {
				results = jQuery.buildFragment( args, this, scripts );
			}

			fragment = results.fragment;

			if ( fragment.childNodes.length === 1 ) {
				first = fragment = fragment.firstChild;
			} else {
				first = fragment.firstChild;
			}

			if ( first ) {
				table = table && jQuery.nodeName( first, "tr" );

				for ( var i = 0, l = this.length, lastIndex = l - 1; i < l; i++ ) {
					callback.call(
						table ?
							root(this[i], first) :
							this[i],
						// Make sure that we do not leak memory by inadvertently discarding
						// the original fragment (which might have attached data) instead of
						// using it; in addition, use the original fragment object for the last
						// item instead of first because it can end up being emptied incorrectly
						// in certain situations (Bug #8070).
						// Fragments from the fragment cache must always be cloned and never used
						// in place.
						results.cacheable || (l > 1 && i < lastIndex) ?
							jQuery.clone( fragment, true, true ) :
							fragment
					);
				}
			}

			if ( scripts.length ) {
				jQuery.each( scripts, evalScript );
			}
		}

		return this;
	}
});

function root( elem, cur ) {
	return jQuery.nodeName(elem, "table") ?
		(elem.getElementsByTagName("tbody")[0] ||
		elem.appendChild(elem.ownerDocument.createElement("tbody"))) :
		elem;
}

function cloneCopyEvent( src, dest ) {

	if ( dest.nodeType !== 1 || !jQuery.hasData( src ) ) {
		return;
	}

	var internalKey = jQuery.expando,
		oldData = jQuery.data( src ),
		curData = jQuery.data( dest, oldData );

	// Switch to use the internal data object, if it exists, for the next
	// stage of data copying
	if ( (oldData = oldData[ internalKey ]) ) {
		var events = oldData.events;
				curData = curData[ internalKey ] = jQuery.extend({}, oldData);

		if ( events ) {
			delete curData.handle;
			curData.events = {};

			for ( var type in events ) {
				for ( var i = 0, l = events[ type ].length; i < l; i++ ) {
					jQuery.event.add( dest, type + ( events[ type ][ i ].namespace ? "." : "" ) + events[ type ][ i ].namespace, events[ type ][ i ], events[ type ][ i ].data );
				}
			}
		}
	}
}

function cloneFixAttributes(src, dest) {
	// We do not need to do anything for non-Elements
	if ( dest.nodeType !== 1 ) {
		return;
	}

	var nodeName = dest.nodeName.toLowerCase();

	// clearAttributes removes the attributes, which we don't want,
	// but also removes the attachEvent events, which we *do* want
	dest.clearAttributes();

	// mergeAttributes, in contrast, only merges back on the
	// original attributes, not the events
	dest.mergeAttributes(src);

	// IE6-8 fail to clone children inside object elements that use
	// the proprietary classid attribute value (rather than the type
	// attribute) to identify the type of content to display
	if ( nodeName === "object" ) {
		dest.outerHTML = src.outerHTML;

	} else if ( nodeName === "input" && (src.type === "checkbox" || src.type === "radio") ) {
		// IE6-8 fails to persist the checked state of a cloned checkbox
		// or radio button. Worse, IE6-7 fail to give the cloned element
		// a checked appearance if the defaultChecked value isn't also set
		if ( src.checked ) {
			dest.defaultChecked = dest.checked = src.checked;
		}

		// IE6-7 get confused and end up setting the value of a cloned
		// checkbox/radio button to an empty string instead of "on"
		if ( dest.value !== src.value ) {
			dest.value = src.value;
		}

	// IE6-8 fails to return the selected option to the default selected
	// state when cloning options
	} else if ( nodeName === "option" ) {
		dest.selected = src.defaultSelected;

	// IE6-8 fails to set the defaultValue to the correct value when
	// cloning other types of input fields
	} else if ( nodeName === "input" || nodeName === "textarea" ) {
		dest.defaultValue = src.defaultValue;
	}

	// Event data gets referenced instead of copied if the expando
	// gets copied too
	dest.removeAttribute( jQuery.expando );
}

jQuery.buildFragment = function( args, nodes, scripts ) {
	var fragment, cacheable, cacheresults,
		doc = (nodes && nodes[0] ? nodes[0].ownerDocument || nodes[0] : document);

	// Only cache "small" (1/2 KB) HTML strings that are associated with the main document
	// Cloning options loses the selected state, so don't cache them
	// IE 6 doesn't like it when you put <object> or <embed> elements in a fragment
	// Also, WebKit does not clone 'checked' attributes on cloneNode, so don't cache
	if ( args.length === 1 && typeof args[0] === "string" && args[0].length < 512 && doc === document &&
		args[0].charAt(0) === "<" && !rnocache.test( args[0] ) && (jQuery.support.checkClone || !rchecked.test( args[0] )) ) {

		cacheable = true;
		cacheresults = jQuery.fragments[ args[0] ];
		if ( cacheresults ) {
			if ( cacheresults !== 1 ) {
				fragment = cacheresults;
			}
		}
	}

	if ( !fragment ) {
		fragment = doc.createDocumentFragment();
		jQuery.clean( args, doc, fragment, scripts );
	}

	if ( cacheable ) {
		jQuery.fragments[ args[0] ] = cacheresults ? fragment : 1;
	}

	return { fragment: fragment, cacheable: cacheable };
};

jQuery.fragments = {};

jQuery.each({
	appendTo: "append",
	prependTo: "prepend",
	insertBefore: "before",
	insertAfter: "after",
	replaceAll: "replaceWith"
}, function( name, original ) {
	jQuery.fn[ name ] = function( selector ) {
		var ret = [],
			insert = jQuery( selector ),
			parent = this.length === 1 && this[0].parentNode;

		if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
			insert[ original ]( this[0] );
			return this;

		} else {
			for ( var i = 0, l = insert.length; i < l; i++ ) {
				var elems = (i > 0 ? this.clone(true) : this).get();
				jQuery( insert[i] )[ original ]( elems );
				ret = ret.concat( elems );
			}

			return this.pushStack( ret, name, insert.selector );
		}
	};
});

function getAll( elem ) {
	if ( "getElementsByTagName" in elem ) {
		return elem.getElementsByTagName( "*" );
	
	} else if ( "querySelectorAll" in elem ) {
		return elem.querySelectorAll( "*" );

	} else {
		return [];
	}
}

jQuery.extend({
	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
		var clone = elem.cloneNode(true),
				srcElements,
				destElements,
				i;

		if ( (!jQuery.support.noCloneEvent || !jQuery.support.noCloneChecked) &&
				(elem.nodeType === 1 || elem.nodeType === 11) && !jQuery.isXMLDoc(elem) ) {
			// IE copies events bound via attachEvent when using cloneNode.
			// Calling detachEvent on the clone will also remove the events
			// from the original. In order to get around this, we use some
			// proprietary methods to clear the events. Thanks to MooTools
			// guys for this hotness.

			cloneFixAttributes( elem, clone );

			// Using Sizzle here is crazy slow, so we use getElementsByTagName
			// instead
			srcElements = getAll( elem );
			destElements = getAll( clone );

			// Weird iteration because IE will replace the length property
			// with an element if you are cloning the body and one of the
			// elements on the page has a name or id of "length"
			for ( i = 0; srcElements[i]; ++i ) {
				cloneFixAttributes( srcElements[i], destElements[i] );
			}
		}

		// Copy the events from the original to the clone
		if ( dataAndEvents ) {
			cloneCopyEvent( elem, clone );

			if ( deepDataAndEvents ) {
				srcElements = getAll( elem );
				destElements = getAll( clone );

				for ( i = 0; srcElements[i]; ++i ) {
					cloneCopyEvent( srcElements[i], destElements[i] );
				}
			}
		}

		// Return the cloned set
		return clone;
},
	clean: function( elems, context, fragment, scripts ) {
		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;
		}

		var ret = [];

		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
			if ( typeof elem === "number" ) {
				elem += "";
			}

			if ( !elem ) {
				continue;
			}

			// Convert html string into DOM nodes
			if ( typeof elem === "string" && !rhtml.test( elem ) ) {
				elem = context.createTextNode( elem );

			} else if ( typeof elem === "string" ) {
				// Fix "XHTML"-style tags in all browsers
				elem = elem.replace(rxhtmlTag, "<$1></$2>");

				// Trim whitespace, otherwise indexOf won't work as expected
				var tag = (rtagName.exec( elem ) || ["", ""])[1].toLowerCase(),
					wrap = wrapMap[ tag ] || wrapMap._default,
					depth = wrap[0],
					div = context.createElement("div");

				// Go to html and back, then peel off extra wrappers
				div.innerHTML = wrap[1] + elem + wrap[2];

				// Move to the right depth
				while ( depth-- ) {
					div = div.lastChild;
				}

				// Remove IE's autoinserted <tbody> from table fragments
				if ( !jQuery.support.tbody ) {

					// String was a <table>, *may* have spurious <tbody>
					var hasBody = rtbody.test(elem),
						tbody = tag === "table" && !hasBody ?
							div.firstChild && div.firstChild.childNodes :

							// String was a bare <thead> or <tfoot>
							wrap[1] === "<table>" && !hasBody ?
								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 ( !jQuery.support.leadingWhitespace && rleadingWhitespace.test( elem ) ) {
					div.insertBefore( context.createTextNode( rleadingWhitespace.exec(elem)[0] ), div.firstChild );
				}

				elem = div.childNodes;
			}

			if ( elem.nodeType ) {
				ret.push( elem );
			} else {
				ret = jQuery.merge( ret, elem );
			}
		}

		if ( fragment ) {
			for ( i = 0; ret[i]; i++ ) {
				if ( scripts && jQuery.nodeName( ret[i], "script" ) && (!ret[i].type || ret[i].type.toLowerCase() === "text/javascript") ) {
					scripts.push( ret[i].parentNode ? ret[i].parentNode.removeChild( ret[i] ) : ret[i] );

				} else {
					if ( ret[i].nodeType === 1 ) {
						ret.splice.apply( ret, [i + 1, 0].concat(jQuery.makeArray(ret[i].getElementsByTagName("script"))) );
					}
					fragment.appendChild( ret[i] );
				}
			}
		}

		return ret;
	},

	cleanData: function( elems ) {
		var data, id, cache = jQuery.cache, internalKey = jQuery.expando, special = jQuery.event.special,
			deleteExpando = jQuery.support.deleteExpando;

		for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
			if ( elem.nodeName && jQuery.noData[elem.nodeName.toLowerCase()] ) {
				continue;
			}

			id = elem[ jQuery.expando ];

			if ( id ) {
				data = cache[ id ] && cache[ id ][ internalKey ];

				if ( data && data.events ) {
					for ( var type in data.events ) {
						if ( special[ type ] ) {
							jQuery.event.remove( elem, type );

						// This is a shortcut to avoid jQuery.event.remove's overhead
						} else {
							jQuery.removeEvent( elem, type, data.handle );
						}
					}

					// Null the DOM reference to avoid IE6/7/8 leak (#7054)
					if ( data.handle ) {
						data.handle.elem = null;
					}
				}

				if ( deleteExpando ) {
					delete elem[ jQuery.expando ];

				} else if ( elem.removeAttribute ) {
					elem.removeAttribute( jQuery.expando );
				}

				delete cache[ id ];
			}
		}
	}
});

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 );
	}
}




var ralpha = /alpha\([^)]*\)/i,
	ropacity = /opacity=([^)]*)/,
	rdashAlpha = /-([a-z])/ig,
	rupper = /([A-Z])/g,
	rnumpx = /^-?\d+(?:px)?$/i,
	rnum = /^-?\d/,

	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
	cssWidth = [ "Left", "Right" ],
	cssHeight = [ "Top", "Bottom" ],
	curCSS,

	getComputedStyle,
	currentStyle,

	fcamelCase = function( all, letter ) {
		return letter.toUpperCase();
	};

jQuery.fn.css = function( name, value ) {
	// Setting 'undefined' is a no-op
	if ( arguments.length === 2 && value === undefined ) {
		return this;
	}

	return jQuery.access( this, name, value, true, function( elem, name, value ) {
		return value !== undefined ?
			jQuery.style( elem, name, value ) :
			jQuery.css( elem, name );
	});
};

jQuery.extend({
	// Add in style property hooks for overriding the default
	// behavior of getting and setting a style property
	cssHooks: {
		opacity: {
			get: function( elem, computed ) {
				if ( computed ) {
					// We should always get a number back from opacity
					var ret = curCSS( elem, "opacity", "opacity" );
					return ret === "" ? "1" : ret;

				} else {
					return elem.style.opacity;
				}
			}
		}
	},

	// Exclude the following css properties to add px
	cssNumber: {
		"zIndex": true,
		"fontWeight": true,
		"opacity": true,
		"zoom": true,
		"lineHeight": true
	},

	// Add in properties whose names you wish to fix before
	// setting or getting the value
	cssProps: {
		// normalize float css property
		"float": jQuery.support.cssFloat ? "cssFloat" : "styleFloat"
	},

	// Get and set the style property on a DOM Node
	style: function( elem, name, value, extra ) {
		// Don't set styles on text and comment nodes
		if ( !elem || elem.nodeType === 3 || elem.nodeType === 8 || !elem.style ) {
			return;
		}

		// Make sure that we're working with the right name
		var ret, origName = jQuery.camelCase( name ),
			style = elem.style, hooks = jQuery.cssHooks[ origName ];

		name = jQuery.cssProps[ origName ] || origName;

		// Check if we're setting a value
		if ( value !== undefined ) {
			// Make sure that NaN and null values aren't set. See: #7116
			if ( typeof value === "number" && isNaN( value ) || value == null ) {
				return;
			}

			// If a number was passed in, add 'px' to the (except for certain CSS properties)
			if ( typeof value === "number" && !jQuery.cssNumber[ origName ] ) {
				value += "px";
			}

			// If a hook was provided, use that value, otherwise just set the specified value
			if ( !hooks || !("set" in hooks) || (value = hooks.set( elem, value )) !== undefined ) {
				// Wrapped to prevent IE from throwing errors when 'invalid' values are provided
				// Fixes bug #5509
				try {
					style[ name ] = value;
				} catch(e) {}
			}

		} else {
			// If a hook was provided get the non-computed value from there
			if ( hooks && "get" in hooks && (ret = hooks.get( elem, false, extra )) !== undefined ) {
				return ret;
			}

			// Otherwise just get the value from the style object
			return style[ name ];
		}
	},

	css: function( elem, name, extra ) {
		// Make sure that we're working with the right name
		var ret, origName = jQuery.camelCase( name ),
			hooks = jQuery.cssHooks[ origName ];

		name = jQuery.cssProps[ origName ] || origName;

		// If a hook was provided get the computed value from there
		if ( hooks && "get" in hooks && (ret = hooks.get( elem, true, extra )) !== undefined ) {
			return ret;

		// Otherwise, if a way to get the computed value exists, use that
		} else if ( curCSS ) {
			return curCSS( elem, name, origName );
		}
	},

	// 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 ( name in options ) {
			elem.style[ name ] = old[ name ];
		}
	},

	camelCase: function( string ) {
		return string.replace( rdashAlpha, fcamelCase );
	}
});

// DEPRECATED, Use jQuery.css() instead
jQuery.curCSS = jQuery.css;

jQuery.each(["height", "width"], function( i, name ) {
	jQuery.cssHooks[ name ] = {
		get: function( elem, computed, extra ) {
			var val;

			if ( computed ) {
				if ( elem.offsetWidth !== 0 ) {
					val = getWH( elem, name, extra );

				} else {
					jQuery.swap( elem, cssShow, function() {
						val = getWH( elem, name, extra );
					});
				}

				if ( val <= 0 ) {
					val = curCSS( elem, name, name );

					if ( val === "0px" && currentStyle ) {
						val = currentStyle( elem, name, name );
					}

					if ( val != null ) {
						// Should return "auto" instead of 0, use 0 for
						// temporary backwards-compat
						return val === "" || val === "auto" ? "0px" : val;
					}
				}

				if ( val < 0 || val == null ) {
					val = elem.style[ name ];

					// Should return "auto" instead of 0, use 0 for
					// temporary backwards-compat
					return val === "" || val === "auto" ? "0px" : val;
				}

				return typeof val === "string" ? val : val + "px";
			}
		},

		set: function( elem, value ) {
			if ( rnumpx.test( value ) ) {
				// ignore negative width and height values #1599
				value = parseFloat(value);

				if ( value >= 0 ) {
					return value + "px";
				}

			} else {
				return value;
			}
		}
	};
});

if ( !jQuery.support.opacity ) {
	jQuery.cssHooks.opacity = {
		get: function( elem, computed ) {
			// IE uses filters for opacity
			return ropacity.test((computed && elem.currentStyle ? elem.currentStyle.filter : elem.style.filter) || "") ?
				(parseFloat(RegExp.$1) / 100) + "" :
				computed ? "1" : "";
		},

		set: function( elem, value ) {
			var style = elem.style;

			// IE has trouble with opacity if it does not have layout
			// Force it by setting the zoom level
			style.zoom = 1;

			// Set the alpha filter to set the opacity
			var opacity = jQuery.isNaN(value) ?
				"" :
				"alpha(opacity=" + value * 100 + ")",
				filter = style.filter || "";

			style.filter = ralpha.test(filter) ?
				filter.replace(ralpha, opacity) :
				style.filter + ' ' + opacity;
		}
	};
}

if ( document.defaultView && document.defaultView.getComputedStyle ) {
	getComputedStyle = function( elem, newName, name ) {
		var ret, defaultView, computedStyle;

		name = name.replace( rupper, "-$1" ).toLowerCase();

		if ( !(defaultView = elem.ownerDocument.defaultView) ) {
			return undefined;
		}

		if ( (computedStyle = defaultView.getComputedStyle( elem, null )) ) {
			ret = computedStyle.getPropertyValue( name );
			if ( ret === "" && !jQuery.contains( elem.ownerDocument.documentElement, elem ) ) {
				ret = jQuery.style( elem, name );
			}
		}

		return ret;
	};
}

if ( document.documentElement.currentStyle ) {
	currentStyle = function( elem, name ) {
		var left,
			ret = elem.currentStyle && elem.currentStyle[ name ],
			rsLeft = elem.runtimeStyle && elem.runtimeStyle[ name ],
			style = elem.style;

		// 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 ( !rnumpx.test( ret ) && rnum.test( ret ) ) {
			// Remember the original values
			left = style.left;

			// Put in the new values to get a computed value out
			if ( rsLeft ) {
				elem.runtimeStyle.left = elem.currentStyle.left;
			}
			style.left = name === "fontSize" ? "1em" : (ret || 0);
			ret = style.pixelLeft + "px";

			// Revert the changed values
			style.left = left;
			if ( rsLeft ) {
				elem.runtimeStyle.left = rsLeft;
			}
		}

		return ret === "" ? "auto" : ret;
	};
}

curCSS = getComputedStyle || currentStyle;

function getWH( elem, name, extra ) {
	var which = name === "width" ? cssWidth : cssHeight,
		val = name === "width" ? elem.offsetWidth : elem.offsetHeight;

	if ( extra === "border" ) {
		return val;
	}

	jQuery.each( which, function() {
		if ( !extra ) {
			val -= parseFloat(jQuery.css( elem, "padding" + this )) || 0;
		}

		if ( extra === "margin" ) {
			val += parseFloat(jQuery.css( elem, "margin" + this )) || 0;

		} else {
			val -= parseFloat(jQuery.css( elem, "border" + this + "Width" )) || 0;
		}
	});

	return val;
}

if ( jQuery.expr && jQuery.expr.filters ) {
	jQuery.expr.filters.hidden = function( elem ) {
		var width = elem.offsetWidth,
			height = elem.offsetHeight;

		return (width === 0 && height === 0) || (!jQuery.support.reliableHiddenOffsets && (elem.style.display || jQuery.css( elem, "display" )) === "none");
	};

	jQuery.expr.filters.visible = function( elem ) {
		return !jQuery.expr.filters.hidden( elem );
	};
}




var r20 = /%20/g,
	rbracket = /\[\]$/,
	rCRLF = /\r?\n/g,
	rhash = /#.*$/,
	rheaders = /^(.*?):[ \t]*([^\r\n]*)\r?$/mg, // IE leaves an \r character at EOL
	rinput = /^(?:color|date|datetime|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
	// #7653, #8125, #8152: local protocol detection
	rlocalProtocol = /(?:^file|^widget|\-extension):$/,
	rnoContent = /^(?:GET|HEAD)$/,
	rprotocol = /^\/\//,
	rquery = /\?/,
	rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
	rselectTextarea = /^(?:select|textarea)/i,
	rspacesAjax = /\s+/,
	rts = /([?&])_=[^&]*/,
	rucHeaders = /(^|\-)([a-z])/g,
	rucHeadersFunc = function( _, $1, $2 ) {
		return $1 + $2.toUpperCase();
	},
	rurl = /^([\w\+\.\-]+:)\/\/([^\/?#:]*)(?::(\d+))?/,

	// Keep a copy of the old load method
	_load = jQuery.fn.load,

	/* Prefilters
	 * 1) They are useful to introduce custom dataTypes (see ajax/jsonp.js for an example)
	 * 2) These are called:
	 *    - BEFORE asking for a transport
	 *    - AFTER param serialization (s.data is a string if s.processData is true)
	 * 3) key is the dataType
	 * 4) the catchall symbol "*" can be used
	 * 5) execution will start with transport dataType and THEN continue down to "*" if needed
	 */
	prefilters = {},

	/* Transports bindings
	 * 1) key is the dataType
	 * 2) the catchall symbol "*" can be used
	 * 3) selection will start with transport dataType and THEN go to "*" if needed
	 */
	transports = {},

	// Document location
	ajaxLocation,

	// Document location segments
	ajaxLocParts;

// #8138, IE may throw an exception when accessing
// a field from document.location if document.domain has been set
try {
	ajaxLocation = document.location.href;
} catch( e ) {
	// Use the href attribute of an A element
	// since IE will modify it given document.location
	ajaxLocation = document.createElement( "a" );
	ajaxLocation.href = "";
	ajaxLocation = ajaxLocation.href;
}

// Segment location into parts
ajaxLocParts = rurl.exec( ajaxLocation.toLowerCase() );

// Base "constructor" for jQuery.ajaxPrefilter and jQuery.ajaxTransport
function addToPrefiltersOrTransports( structure ) {

	// dataTypeExpression is optional and defaults to "*"
	return function( dataTypeExpression, func ) {

		if ( typeof dataTypeExpression !== "string" ) {
			func = dataTypeExpression;
			dataTypeExpression = "*";
		}

		if ( jQuery.isFunction( func ) ) {
			var dataTypes = dataTypeExpression.toLowerCase().split( rspacesAjax ),
				i = 0,
				length = dataTypes.length,
				dataType,
				list,
				placeBefore;

			// For each dataType in the dataTypeExpression
			for(; i < length; i++ ) {
				dataType = dataTypes[ i ];
				// We control if we're asked to add before
				// any existing element
				placeBefore = /^\+/.test( dataType );
				if ( placeBefore ) {
					dataType = dataType.substr( 1 ) || "*";
				}
				list = structure[ dataType ] = structure[ dataType ] || [];
				// then we add to the structure accordingly
				list[ placeBefore ? "unshift" : "push" ]( func );
			}
		}
	};
}

//Base inspection function for prefilters and transports
function inspectPrefiltersOrTransports( structure, options, originalOptions, jqXHR,
		dataType /* internal */, inspected /* internal */ ) {

	dataType = dataType || options.dataTypes[ 0 ];
	inspected = inspected || {};

	inspected[ dataType ] = true;

	var list = structure[ dataType ],
		i = 0,
		length = list ? list.length : 0,
		executeOnly = ( structure === prefilters ),
		selection;

	for(; i < length && ( executeOnly || !selection ); i++ ) {
		selection = list[ i ]( options, originalOptions, jqXHR );
		// If we got redirected to another dataType
		// we try there if executing only and not done already
		if ( typeof selection === "string" ) {
			if ( !executeOnly || inspected[ selection ] ) {
				selection = undefined;
			} else {
				options.dataTypes.unshift( selection );
				selection = inspectPrefiltersOrTransports(
						structure, options, originalOptions, jqXHR, selection, inspected );
			}
		}
	}
	// If we're only executing or nothing was selected
	// we try the catchall dataType if not done already
	if ( ( executeOnly || !selection ) && !inspected[ "*" ] ) {
		selection = inspectPrefiltersOrTransports(
				structure, options, originalOptions, jqXHR, "*", inspected );
	}
	// unnecessary when only executing (prefilters)
	// but it'll be ignored by the caller in that case
	return selection;
}

jQuery.fn.extend({
	load: function( url, params, callback ) {
		if ( typeof url !== "string" && _load ) {
			return _load.apply( this, arguments );

		// Don't do a request if no elements are being requested
		} else if ( !this.length ) {
			return this;
		}

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

		// 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 = undefined;

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

		var self = this;

		// Request the remote document
		jQuery.ajax({
			url: url,
			type: type,
			dataType: "html",
			data: params,
			// Complete callback (responseText is used internally)
			complete: function( jqXHR, status, responseText ) {
				// Store the response as specified by the jqXHR object
				responseText = jqXHR.responseText;
				// If successful, inject the HTML into all the matched elements
				if ( jqXHR.isResolved() ) {
					// #4825: Get the actual response in case
					// a dataFilter is present in ajaxSettings
					jqXHR.done(function( r ) {
						responseText = r;
					});
					// 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(responseText.replace(rscript, ""))

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

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

				if ( callback ) {
					self.each( callback, [ responseText, status, jqXHR ] );
				}
			}
		});

		return this;
	},

	serialize: function() {
		return jQuery.param( this.serializeArray() );
	},

	serializeArray: function() {
		return this.map(function(){
			return this.elements ? jQuery.makeArray( this.elements ) : this;
		})
		.filter(function(){
			return this.name && !this.disabled &&
				( this.checked || rselectTextarea.test( this.nodeName ) ||
					rinput.test( this.type ) );
		})
		.map(function( i, elem ){
			var val = jQuery( this ).val();

			return val == null ?
				null :
				jQuery.isArray( val ) ?
					jQuery.map( val, function( val, i ){
						return { name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
					}) :
					{ name: elem.name, value: val.replace( rCRLF, "\r\n" ) };
		}).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 );
	};
} );

jQuery.each( [ "get", "post" ], function( i, method ) {
	jQuery[ method ] = function( url, data, callback, type ) {
		// shift arguments if data argument was omitted
		if ( jQuery.isFunction( data ) ) {
			type = type || callback;
			callback = data;
			data = undefined;
		}

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

jQuery.extend({

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

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

	// Creates a full fledged settings object into target
	// with both ajaxSettings and settings fields.
	// If target is omitted, writes into ajaxSettings.
	ajaxSetup: function ( target, settings ) {
		if ( !settings ) {
			// Only one parameter, we extend ajaxSettings
			settings = target;
			target = jQuery.extend( true, jQuery.ajaxSettings, settings );
		} else {
			// target was provided, we extend into it
			jQuery.extend( true, target, jQuery.ajaxSettings, settings );
		}
		// Flatten fields we don't want deep extended
		for( var field in { context: 1, url: 1 } ) {
			if ( field in settings ) {
				target[ field ] = settings[ field ];
			} else if( field in jQuery.ajaxSettings ) {
				target[ field ] = jQuery.ajaxSettings[ field ];
			}
		}
		return target;
	},

	ajaxSettings: {
		url: ajaxLocation,
		isLocal: rlocalProtocol.test( ajaxLocParts[ 1 ] ),
		global: true,
		type: "GET",
		contentType: "application/x-www-form-urlencoded",
		processData: true,
		async: true,
		/*
		timeout: 0,
		data: null,
		dataType: null,
		username: null,
		password: null,
		cache: null,
		traditional: false,
		headers: {},
		crossDomain: null,
		*/

		accepts: {
			xml: "application/xml, text/xml",
			html: "text/html",
			text: "text/plain",
			json: "application/json, text/javascript",
			"*": "*/*"
		},

		contents: {
			xml: /xml/,
			html: /html/,
			json: /json/
		},

		responseFields: {
			xml: "responseXML",
			text: "responseText"
		},

		// List of data converters
		// 1) key format is "source_type destination_type" (a single space in-between)
		// 2) the catchall symbol "*" can be used for source_type
		converters: {

			// Convert anything to text
			"* text": window.String,

			// Text to html (true = no transformation)
			"text html": true,

			// Evaluate text as a json expression
			"text json": jQuery.parseJSON,

			// Parse text as xml
			"text xml": jQuery.parseXML
		}
	},

	ajaxPrefilter: addToPrefiltersOrTransports( prefilters ),
	ajaxTransport: addToPrefiltersOrTransports( transports ),

	// Main method
	ajax: function( url, options ) {

		// If url is an object, simulate pre-1.5 signature
		if ( typeof url === "object" ) {
			options = url;
			url = undefined;
		}

		// Force options to be an object
		options = options || {};

		var // Create the final options object
			s = jQuery.ajaxSetup( {}, options ),
			// Callbacks context
			callbackContext = s.context || s,
			// Context for global events
			// It's the callbackContext if one was provided in the options
			// and if it's a DOM node or a jQuery collection
			globalEventContext = callbackContext !== s &&
				( callbackContext.nodeType || callbackContext instanceof jQuery ) ?
						jQuery( callbackContext ) : jQuery.event,
			// Deferreds
			deferred = jQuery.Deferred(),
			completeDeferred = jQuery._Deferred(),
			// Status-dependent callbacks
			statusCode = s.statusCode || {},
			// ifModified key
			ifModifiedKey,
			// Headers (they are sent all at once)
			requestHeaders = {},
			// Response headers
			responseHeadersString,
			responseHeaders,
			// transport
			transport,
			// timeout handle
			timeoutTimer,
			// Cross-domain detection vars
			parts,
			// The jqXHR state
			state = 0,
			// To know if global events are to be dispatched
			fireGlobals,
			// Loop variable
			i,
			// Fake xhr
			jqXHR = {

				readyState: 0,

				// Caches the header
				setRequestHeader: function( name, value ) {
					if ( !state ) {
						requestHeaders[ name.toLowerCase().replace( rucHeaders, rucHeadersFunc ) ] = value;
					}
					return this;
				},

				// Raw string
				getAllResponseHeaders: function() {
					return state === 2 ? responseHeadersString : null;
				},

				// Builds headers hashtable if needed
				getResponseHeader: function( key ) {
					var match;
					if ( state === 2 ) {
						if ( !responseHeaders ) {
							responseHeaders = {};
							while( ( match = rheaders.exec( responseHeadersString ) ) ) {
								responseHeaders[ match[1].toLowerCase() ] = match[ 2 ];
							}
						}
						match = responseHeaders[ key.toLowerCase() ];
					}
					return match === undefined ? null : match;
				},

				// Overrides response content-type header
				overrideMimeType: function( type ) {
					if ( !state ) {
						s.mimeType = type;
					}
					return this;
				},

				// Cancel the request
				abort: function( statusText ) {
					statusText = statusText || "abort";
					if ( transport ) {
						transport.abort( statusText );
					}
					done( 0, statusText );
					return this;
				}
			};

		// Callback for when everything is done
		// It is defined here because jslint complains if it is declared
		// at the end of the function (which would be more logical and readable)
		function done( status, statusText, responses, headers ) {

			// Called once
			if ( state === 2 ) {
				return;
			}

			// State is "done" now
			state = 2;

			// Clear timeout if it exists
			if ( timeoutTimer ) {
				clearTimeout( timeoutTimer );
			}

			// Dereference transport for early garbage collection
			// (no matter how long the jqXHR object will be used)
			transport = undefined;

			// Cache response headers
			responseHeadersString = headers || "";

			// Set readyState
			jqXHR.readyState = status ? 4 : 0;

			var isSuccess,
				success,
				error,
				response = responses ? ajaxHandleResponses( s, jqXHR, responses ) : undefined,
				lastModified,
				etag;

			// If successful, handle type chaining
			if ( status >= 200 && status < 300 || status === 304 ) {

				// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
				if ( s.ifModified ) {

					if ( ( lastModified = jqXHR.getResponseHeader( "Last-Modified" ) ) ) {
						jQuery.lastModified[ ifModifiedKey ] = lastModified;
					}
					if ( ( etag = jqXHR.getResponseHeader( "Etag" ) ) ) {
						jQuery.etag[ ifModifiedKey ] = etag;
					}
				}

				// If not modified
				if ( status === 304 ) {

					statusText = "notmodified";
					isSuccess = true;

				// If we have data
				} else {

					try {
						success = ajaxConvert( s, response );
						statusText = "success";
						isSuccess = true;
					} catch(e) {
						// We have a parsererror
						statusText = "parsererror";
						error = e;
					}
				}
			} else {
				// We extract error from statusText
				// then normalize statusText and status for non-aborts
				error = statusText;
				if( !statusText || status ) {
					statusText = "error";
					if ( status < 0 ) {
						status = 0;
					}
				}
			}

			// Set data for the fake xhr object
			jqXHR.status = status;
			jqXHR.statusText = statusText;

			// Success/Error
			if ( isSuccess ) {
				deferred.resolveWith( callbackContext, [ success, statusText, jqXHR ] );
			} else {
				deferred.rejectWith( callbackContext, [ jqXHR, statusText, error ] );
			}

			// Status-dependent callbacks
			jqXHR.statusCode( statusCode );
			statusCode = undefined;

			if ( fireGlobals ) {
				globalEventContext.trigger( "ajax" + ( isSuccess ? "Success" : "Error" ),
						[ jqXHR, s, isSuccess ? success : error ] );
			}

			// Complete
			completeDeferred.resolveWith( callbackContext, [ jqXHR, statusText ] );

			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxComplete", [ jqXHR, s] );
				// Handle the global AJAX counter
				if ( !( --jQuery.active ) ) {
					jQuery.event.trigger( "ajaxStop" );
				}
			}
		}

		// Attach deferreds
		deferred.promise( jqXHR );
		jqXHR.success = jqXHR.done;
		jqXHR.error = jqXHR.fail;
		jqXHR.complete = completeDeferred.done;

		// Status-dependent callbacks
		jqXHR.statusCode = function( map ) {
			if ( map ) {
				var tmp;
				if ( state < 2 ) {
					for( tmp in map ) {
						statusCode[ tmp ] = [ statusCode[tmp], map[tmp] ];
					}
				} else {
					tmp = map[ jqXHR.status ];
					jqXHR.then( tmp, tmp );
				}
			}
			return this;
		};

		// Remove hash character (#7531: and string promotion)
		// Add protocol if not provided (#5866: IE7 issue with protocol-less urls)
		// We also use the url parameter if available
		s.url = ( ( url || s.url ) + "" ).replace( rhash, "" ).replace( rprotocol, ajaxLocParts[ 1 ] + "//" );

		// Extract dataTypes list
		s.dataTypes = jQuery.trim( s.dataType || "*" ).toLowerCase().split( rspacesAjax );

		// Determine if a cross-domain request is in order
		if ( !s.crossDomain ) {
			parts = rurl.exec( s.url.toLowerCase() );
			s.crossDomain = !!( parts &&
				( parts[ 1 ] != ajaxLocParts[ 1 ] || parts[ 2 ] != ajaxLocParts[ 2 ] ||
					( parts[ 3 ] || ( parts[ 1 ] === "http:" ? 80 : 443 ) ) !=
						( ajaxLocParts[ 3 ] || ( ajaxLocParts[ 1 ] === "http:" ? 80 : 443 ) ) )
			);
		}

		// Convert data if not already a string
		if ( s.data && s.processData && typeof s.data !== "string" ) {
			s.data = jQuery.param( s.data, s.traditional );
		}

		// Apply prefilters
		inspectPrefiltersOrTransports( prefilters, s, options, jqXHR );

		// If request was aborted inside a prefiler, stop there
		if ( state === 2 ) {
			return false;
		}

		// We can fire global events as of now if asked to
		fireGlobals = s.global;

		// Uppercase the type
		s.type = s.type.toUpperCase();

		// Determine if request has content
		s.hasContent = !rnoContent.test( s.type );

		// Watch for a new set of requests
		if ( fireGlobals && jQuery.active++ === 0 ) {
			jQuery.event.trigger( "ajaxStart" );
		}

		// More options handling for requests with no content
		if ( !s.hasContent ) {

			// If data is available, append data to url
			if ( s.data ) {
				s.url += ( rquery.test( s.url ) ? "&" : "?" ) + s.data;
			}

			// Get ifModifiedKey before adding the anti-cache parameter
			ifModifiedKey = s.url;

			// Add anti-cache in url if needed
			if ( s.cache === false ) {

				var ts = jQuery.now(),
					// try replacing _= if it is there
					ret = s.url.replace( rts, "$1_=" + ts );

				// if nothing was replaced, add timestamp to the end
				s.url = ret + ( (ret === s.url ) ? ( rquery.test( s.url ) ? "&" : "?" ) + "_=" + ts : "" );
			}
		}

		// Set the correct header, if data is being sent
		if ( s.data && s.hasContent && s.contentType !== false || options.contentType ) {
			requestHeaders[ "Content-Type" ] = s.contentType;
		}

		// Set the If-Modified-Since and/or If-None-Match header, if in ifModified mode.
		if ( s.ifModified ) {
			ifModifiedKey = ifModifiedKey || s.url;
			if ( jQuery.lastModified[ ifModifiedKey ] ) {
				requestHeaders[ "If-Modified-Since" ] = jQuery.lastModified[ ifModifiedKey ];
			}
			if ( jQuery.etag[ ifModifiedKey ] ) {
				requestHeaders[ "If-None-Match" ] = jQuery.etag[ ifModifiedKey ];
			}
		}

		// Set the Accepts header for the server, depending on the dataType
		requestHeaders.Accept = s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
			s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", */*; q=0.01" : "" ) :
			s.accepts[ "*" ];

		// Check for headers option
		for ( i in s.headers ) {
			jqXHR.setRequestHeader( i, s.headers[ i ] );
		}

		// Allow custom headers/mimetypes and early abort
		if ( s.beforeSend && ( s.beforeSend.call( callbackContext, jqXHR, s ) === false || state === 2 ) ) {
				// Abort if not done already
				jqXHR.abort();
				return false;

		}

		// Install callbacks on deferreds
		for ( i in { success: 1, error: 1, complete: 1 } ) {
			jqXHR[ i ]( s[ i ] );
		}

		// Get transport
		transport = inspectPrefiltersOrTransports( transports, s, options, jqXHR );

		// If no transport, we auto-abort
		if ( !transport ) {
			done( -1, "No Transport" );
		} else {
			jqXHR.readyState = 1;
			// Send global event
			if ( fireGlobals ) {
				globalEventContext.trigger( "ajaxSend", [ jqXHR, s ] );
			}
			// Timeout
			if ( s.async && s.timeout > 0 ) {
				timeoutTimer = setTimeout( function(){
					jqXHR.abort( "timeout" );
				}, s.timeout );
			}

			try {
				state = 1;
				transport.send( requestHeaders, done );
			} catch (e) {
				// Propagate exception as error if not done
				if ( status < 2 ) {
					done( -1, e );
				// Simply rethrow otherwise
				} else {
					jQuery.error( e );
				}
			}
		}

		return jqXHR;
	},

	// Serialize an array of form elements or a set of
	// key/values into a query string
	param: function( a, traditional ) {
		var s = [],
			add = function( key, value ) {
				// If value is a function, invoke it and return its value
				value = jQuery.isFunction( value ) ? value() : value;
				s[ s.length ] = encodeURIComponent( key ) + "=" + encodeURIComponent( value );
			};

		// Set traditional to true for jQuery <= 1.3.2 behavior.
		if ( traditional === undefined ) {
			traditional = jQuery.ajaxSettings.traditional;
		}

		// If an array was passed in, assume that it is an array of form elements.
		if ( jQuery.isArray( a ) || ( a.jquery && !jQuery.isPlainObject( a ) ) ) {
			// Serialize the form elements
			jQuery.each( a, function() {
				add( this.name, this.value );
			} );

		} else {
			// If traditional, encode the "old" way (the way 1.3.2 or older
			// did it), otherwise encode params recursively.
			for ( var prefix in a ) {
				buildParams( prefix, a[ prefix ], traditional, add );
			}
		}

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

function buildParams( prefix, obj, traditional, add ) {
	if ( jQuery.isArray( obj ) && obj.length ) {
		// Serialize array item.
		jQuery.each( obj, function( i, v ) {
			if ( traditional || rbracket.test( prefix ) ) {
				// Treat each array item as a scalar.
				add( prefix, v );

			} else {
				// If array item is non-scalar (array or object), encode its
				// numeric index to resolve deserialization ambiguity issues.
				// Note that rack (as of 1.0.0) can't currently deserialize
				// nested arrays properly, and attempting to do so may cause
				// a server error. Possible fixes are to modify rack's
				// deserialization algorithm or to provide an option or flag
				// to force array serialization to be shallow.
				buildParams( prefix + "[" + ( typeof v === "object" || jQuery.isArray(v) ? i : "" ) + "]", v, traditional, add );
			}
		});

	} else if ( !traditional && obj != null && typeof obj === "object" ) {
		// If we see an array here, it is empty and should be treated as an empty
		// object
		if ( jQuery.isArray( obj ) || jQuery.isEmptyObject( obj ) ) {
			add( prefix, "" );

		// Serialize object item.
		} else {
			for ( var name in obj ) {
				buildParams( prefix + "[" + name + "]", obj[ name ], traditional, add );
			}
		}

	} else {
		// Serialize scalar item.
		add( prefix, obj );
	}
}

// This is still on the jQuery object... for now
// Want to move this to jQuery.ajax some day
jQuery.extend({

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

	// Last-Modified header cache for next request
	lastModified: {},
	etag: {}

});

/* Handles responses to an ajax request:
 * - sets all responseXXX fields accordingly
 * - finds the right dataType (mediates between content-type and expected dataType)
 * - returns the corresponding response
 */
function ajaxHandleResponses( s, jqXHR, responses ) {

	var contents = s.contents,
		dataTypes = s.dataTypes,
		responseFields = s.responseFields,
		ct,
		type,
		finalDataType,
		firstDataType;

	// Fill responseXXX fields
	for( type in responseFields ) {
		if ( type in responses ) {
			jqXHR[ responseFields[type] ] = responses[ type ];
		}
	}

	// Remove auto dataType and get content-type in the process
	while( dataTypes[ 0 ] === "*" ) {
		dataTypes.shift();
		if ( ct === undefined ) {
			ct = s.mimeType || jqXHR.getResponseHeader( "content-type" );
		}
	}

	// Check if we're dealing with a known content-type
	if ( ct ) {
		for ( type in contents ) {
			if ( contents[ type ] && contents[ type ].test( ct ) ) {
				dataTypes.unshift( type );
				break;
			}
		}
	}

	// Check to see if we have a response for the expected dataType
	if ( dataTypes[ 0 ] in responses ) {
		finalDataType = dataTypes[ 0 ];
	} else {
		// Try convertible dataTypes
		for ( type in responses ) {
			if ( !dataTypes[ 0 ] || s.converters[ type + " " + dataTypes[0] ] ) {
				finalDataType = type;
				break;
			}
			if ( !firstDataType ) {
				firstDataType = type;
			}
		}
		// Or just use first one
		finalDataType = finalDataType || firstDataType;
	}

	// If we found a dataType
	// We add the dataType to the list if needed
	// and return the corresponding response
	if ( finalDataType ) {
		if ( finalDataType !== dataTypes[ 0 ] ) {
			dataTypes.unshift( finalDataType );
		}
		return responses[ finalDataType ];
	}
}

// Chain conversions given the request and the original response
function ajaxConvert( s, response ) {

	// Apply the dataFilter if provided
	if ( s.dataFilter ) {
		response = s.dataFilter( response, s.dataType );
	}

	var dataTypes = s.dataTypes,
		converters = {},
		i,
		key,
		length = dataTypes.length,
		tmp,
		// Current and previous dataTypes
		current = dataTypes[ 0 ],
		prev,
		// Conversion expression
		conversion,
		// Conversion function
		conv,
		// Conversion functions (transitive conversion)
		conv1,
		conv2;

	// For each dataType in the chain
	for( i = 1; i < length; i++ ) {

		// Create converters map
		// with lowercased keys
		if ( i === 1 ) {
			for( key in s.converters ) {
				if( typeof key === "string" ) {
					converters[ key.toLowerCase() ] = s.converters[ key ];
				}
			}
		}

		// Get the dataTypes
		prev = current;
		current = dataTypes[ i ];

		// If current is auto dataType, update it to prev
		if( current === "*" ) {
			current = prev;
		// If no auto and dataTypes are actually different
		} else if ( prev !== "*" && prev !== current ) {

			// Get the converter
			conversion = prev + " " + current;
			conv = converters[ conversion ] || converters[ "* " + current ];

			// If there is no direct converter, search transitively
			if ( !conv ) {
				conv2 = undefined;
				for( conv1 in converters ) {
					tmp = conv1.split( " " );
					if ( tmp[ 0 ] === prev || tmp[ 0 ] === "*" ) {
						conv2 = converters[ tmp[1] + " " + current ];
						if ( conv2 ) {
							conv1 = converters[ conv1 ];
							if ( conv1 === true ) {
								conv = conv2;
							} else if ( conv2 === true ) {
								conv = conv1;
							}
							break;
						}
					}
				}
			}
			// If we found no converter, dispatch an error
			if ( !( conv || conv2 ) ) {
				jQuery.error( "No conversion from " + conversion.replace(" "," to ") );
			}
			// If found converter is not an equivalence
			if ( conv !== true ) {
				// Convert with 1 or 2 converters accordingly
				response = conv ? conv( response ) : conv2( conv1(response) );
			}
		}
	}
	return response;
}




var jsc = jQuery.now(),
	jsre = /(\=)\?(&|$)|()\?\?()/i;

// Default jsonp settings
jQuery.ajaxSetup({
	jsonp: "callback",
	jsonpCallback: function() {
		return jQuery.expando + "_" + ( jsc++ );
	}
});

// Detect, normalize options and install callbacks for jsonp requests
jQuery.ajaxPrefilter( "json jsonp", function( s, originalSettings, jqXHR ) {

	var dataIsString = ( typeof s.data === "string" );

	if ( s.dataTypes[ 0 ] === "jsonp" ||
		originalSettings.jsonpCallback ||
		originalSettings.jsonp != null ||
		s.jsonp !== false && ( jsre.test( s.url ) ||
				dataIsString && jsre.test( s.data ) ) ) {

		var responseContainer,
			jsonpCallback = s.jsonpCallback =
				jQuery.isFunction( s.jsonpCallback ) ? s.jsonpCallback() : s.jsonpCallback,
			previous = window[ jsonpCallback ],
			url = s.url,
			data = s.data,
			replace = "$1" + jsonpCallback + "$2",
			cleanUp = function() {
				// Set callback back to previous value
				window[ jsonpCallback ] = previous;
				// Call if it was a function and we have a response
				if ( responseContainer && jQuery.isFunction( previous ) ) {
					window[ jsonpCallback ]( responseContainer[ 0 ] );
				}
			};

		if ( s.jsonp !== false ) {
			url = url.replace( jsre, replace );
			if ( s.url === url ) {
				if ( dataIsString ) {
					data = data.replace( jsre, replace );
				}
				if ( s.data === data ) {
					// Add callback manually
					url += (/\?/.test( url ) ? "&" : "?") + s.jsonp + "=" + jsonpCallback;
				}
			}
		}

		s.url = url;
		s.data = data;

		// Install callback
		window[ jsonpCallback ] = function( response ) {
			responseContainer = [ response ];
		};

		// Install cleanUp function
		jqXHR.then( cleanUp, cleanUp );

		// Use data converter to retrieve json after script execution
		s.converters["script json"] = function() {
			if ( !responseContainer ) {
				jQuery.error( jsonpCallback + " was not called" );
			}
			return responseContainer[ 0 ];
		};

		// force json dataType
		s.dataTypes[ 0 ] = "json";

		// Delegate to script
		return "script";
	}
} );




// Install script dataType
jQuery.ajaxSetup({
	accepts: {
		script: "text/javascript, application/javascript, application/ecmascript, application/x-ecmascript"
	},
	contents: {
		script: /javascript|ecmascript/
	},
	converters: {
		"text script": function( text ) {
			jQuery.globalEval( text );
			return text;
		}
	}
});

// Handle cache's special case and global
jQuery.ajaxPrefilter( "script", function( s ) {
	if ( s.cache === undefined ) {
		s.cache = false;
	}
	if ( s.crossDomain ) {
		s.type = "GET";
		s.global = false;
	}
} );

// Bind script tag hack transport
jQuery.ajaxTransport( "script", function(s) {

	// This transport only deals with cross domain requests
	if ( s.crossDomain ) {

		var script,
			head = document.head || document.getElementsByTagName( "head" )[0] || document.documentElement;

		return {

			send: function( _, callback ) {

				script = document.createElement( "script" );

				script.async = "async";

				if ( s.scriptCharset ) {
					script.charset = s.scriptCharset;
				}

				script.src = s.url;

				// Attach handlers for all browsers
				script.onload = script.onreadystatechange = function( _, isAbort ) {

					if ( !script.readyState || /loaded|complete/.test( script.readyState ) ) {

						// Handle memory leak in IE
						script.onload = script.onreadystatechange = null;

						// Remove the script
						if ( head && script.parentNode ) {
							head.removeChild( script );
						}

						// Dereference the script
						script = undefined;

						// Callback if not abort
						if ( !isAbort ) {
							callback( 200, "success" );
						}
					}
				};
				// Use insertBefore instead of appendChild  to circumvent an IE6 bug.
				// This arises when a base node is used (#2709 and #4378).
				head.insertBefore( script, head.firstChild );
			},

			abort: function() {
				if ( script ) {
					script.onload( 0, 1 );
				}
			}
		};
	}
} );




var // #5280: next active xhr id and list of active xhrs' callbacks
	xhrId = jQuery.now(),
	xhrCallbacks,

	// XHR used to determine supports properties
	testXHR;

// #5280: Internet Explorer will keep connections alive if we don't abort on unload
function xhrOnUnloadAbort() {
	jQuery( window ).unload(function() {
		// Abort all pending requests
		for ( var key in xhrCallbacks ) {
			xhrCallbacks[ key ]( 0, 1 );
		}
	});
}

// Functions to create xhrs
function createStandardXHR() {
	try {
		return new window.XMLHttpRequest();
	} catch( e ) {}
}

function createActiveXHR() {
	try {
		return new window.ActiveXObject( "Microsoft.XMLHTTP" );
	} catch( e ) {}
}

// Create the request object
// (This is still attached to ajaxSettings for backward compatibility)
jQuery.ajaxSettings.xhr = window.ActiveXObject ?
	/* Microsoft failed to properly
	 * implement the XMLHttpRequest in IE7 (can't request local files),
	 * so we use the ActiveXObject when it is available
	 * Additionally XMLHttpRequest can be disabled in IE7/IE8 so
	 * we need a fallback.
	 */
	function() {
		return !this.isLocal && createStandardXHR() || createActiveXHR();
	} :
	// For all other browsers, use the standard XMLHttpRequest object
	createStandardXHR;

// Test if we can create an xhr object
testXHR = jQuery.ajaxSettings.xhr();
jQuery.support.ajax = !!testXHR;

// Does this browser support crossDomain XHR requests
jQuery.support.cors = testXHR && ( "withCredentials" in testXHR );

// No need for the temporary xhr anymore
testXHR = undefined;

// Create transport if the browser can provide an xhr
if ( jQuery.support.ajax ) {

	jQuery.ajaxTransport(function( s ) {
		// Cross domain only allowed if supported through XMLHttpRequest
		if ( !s.crossDomain || jQuery.support.cors ) {

			var callback;

			return {
				send: function( headers, complete ) {

					// Get a new xhr
					var xhr = s.xhr(),
						handle,
						i;

					// Open the socket
					// Passing null username, generates a login popup on Opera (#2865)
					if ( s.username ) {
						xhr.open( s.type, s.url, s.async, s.username, s.password );
					} else {
						xhr.open( s.type, s.url, s.async );
					}

					// Apply custom fields if provided
					if ( s.xhrFields ) {
						for ( i in s.xhrFields ) {
							xhr[ i ] = s.xhrFields[ i ];
						}
					}

					// Override mime type if needed
					if ( s.mimeType && xhr.overrideMimeType ) {
						xhr.overrideMimeType( s.mimeType );
					}

					// Requested-With header
					// Not set for crossDomain requests with no content
					// (see why at http://trac.dojotoolkit.org/ticket/9486)
					// Won't change header if already provided
					if ( !( s.crossDomain && !s.hasContent ) && !headers["X-Requested-With"] ) {
						headers[ "X-Requested-With" ] = "XMLHttpRequest";
					}

					// Need an extra try/catch for cross domain requests in Firefox 3
					try {
						for ( i in headers ) {
							xhr.setRequestHeader( i, headers[ i ] );
						}
					} catch( _ ) {}

					// Do send the request
					// This may raise an exception which is actually
					// handled in jQuery.ajax (so no try/catch here)
					xhr.send( ( s.hasContent && s.data ) || null );

					// Listener
					callback = function( _, isAbort ) {

						var status,
							statusText,
							responseHeaders,
							responses,
							xml;

						// Firefox throws exceptions when accessing properties
						// of an xhr when a network error occured
						// http://helpful.knobs-dials.com/index.php/Component_returned_failure_code:_0x80040111_(NS_ERROR_NOT_AVAILABLE)
						try {

							// Was never called and is aborted or complete
							if ( callback && ( isAbort || xhr.readyState === 4 ) ) {

								// Only called once
								callback = undefined;

								// Do not keep as active anymore
								if ( handle ) {
									xhr.onreadystatechange = jQuery.noop;
									delete xhrCallbacks[ handle ];
								}

								// If it's an abort
								if ( isAbort ) {
									// Abort it manually if needed
									if ( xhr.readyState !== 4 ) {
										xhr.abort();
									}
								} else {
									status = xhr.status;
									responseHeaders = xhr.getAllResponseHeaders();
									responses = {};
									xml = xhr.responseXML;

									// Construct response list
									if ( xml && xml.documentElement /* #4958 */ ) {
										responses.xml = xml;
									}
									responses.text = xhr.responseText;

									// Firefox throws an exception when accessing
									// statusText for faulty cross-domain requests
									try {
										statusText = xhr.statusText;
									} catch( e ) {
										// We normalize with Webkit giving an empty statusText
										statusText = "";
									}

									// Filter status for non standard behaviors

									// If the request is local and we have data: assume a success
									// (success with no data won't get notified, that's the best we
									// can do given current implementations)
									if ( !status && s.isLocal && !s.crossDomain ) {
										status = responses.text ? 200 : 404;
									// IE - #1450: sometimes returns 1223 when it should be 204
									} else if ( status === 1223 ) {
										status = 204;
									}
								}
							}
						} catch( firefoxAccessException ) {
							if ( !isAbort ) {
								complete( -1, firefoxAccessException );
							}
						}

						// Call complete if needed
						if ( responses ) {
							complete( status, statusText, responses, responseHeaders );
						}
					};

					// if we're in sync mode or it's in cache
					// and has been retrieved directly (IE6 & IE7)
					// we need to manually fire the callback
					if ( !s.async || xhr.readyState === 4 ) {
						callback();
					} else {
						// Create the active xhrs callbacks list if needed
						// and attach the unload handler
						if ( !xhrCallbacks ) {
							xhrCallbacks = {};
							xhrOnUnloadAbort();
						}
						// Add to list of active xhrs callbacks
						handle = xhrId++;
						xhr.onreadystatechange = xhrCallbacks[ handle ] = callback;
					}
				},

				abort: function() {
					if ( callback ) {
						callback(0,1);
					}
				}
			};
		}
	});
}




var elemdisplay = {},
	rfxtypes = /^(?:toggle|show|hide)$/,
	rfxnum = /^([+\-]=)?([\d+.\-]+)([a-z%]*)$/i,
	timerId,
	fxAttrs = [
		// height animations
		[ "height", "marginTop", "marginBottom", "paddingTop", "paddingBottom" ],
		// width animations
		[ "width", "marginLeft", "marginRight", "paddingLeft", "paddingRight" ],
		// opacity animations
		[ "opacity" ]
	];

jQuery.fn.extend({
	show: function( speed, easing, callback ) {
		var elem, display;

		if ( speed || speed === 0 ) {
			return this.animate( genFx("show", 3), speed, easing, callback);

		} else {
			for ( var i = 0, j = this.length; i < j; i++ ) {
				elem = this[i];
				display = elem.style.display;

				// Reset the inline display of this element to learn if it is
				// being hidden by cascaded rules or not
				if ( !jQuery._data(elem, "olddisplay") && display === "none" ) {
					display = elem.style.display = "";
				}

				// Set elements which have been overridden with display: none
				// in a stylesheet to whatever the default browser style is
				// for such an element
				if ( display === "" && jQuery.css( elem, "display" ) === "none" ) {
					jQuery._data(elem, "olddisplay", defaultDisplay(elem.nodeName));
				}
			}

			// Set the display of most of the elements in a second loop
			// to avoid the constant reflow
			for ( i = 0; i < j; i++ ) {
				elem = this[i];
				display = elem.style.display;

				if ( display === "" || display === "none" ) {
					elem.style.display = jQuery._data(elem, "olddisplay") || "";
				}
			}

			return this;
		}
	},

	hide: function( speed, easing, callback ) {
		if ( speed || speed === 0 ) {
			return this.animate( genFx("hide", 3), speed, easing, callback);

		} else {
			for ( var i = 0, j = this.length; i < j; i++ ) {
				var display = jQuery.css( this[i], "display" );

				if ( display !== "none" && !jQuery._data( this[i], "olddisplay" ) ) {
					jQuery._data( this[i], "olddisplay", display );
				}
			}

			// Set the display of the elements in a second loop
			// to avoid the constant reflow
			for ( i = 0; i < j; i++ ) {
				this[i].style.display = "none";
			}

			return this;
		}
	},

	// Save the old toggle function
	_toggle: jQuery.fn.toggle,

	toggle: function( fn, fn2, callback ) {
		var bool = typeof fn === "boolean";

		if ( jQuery.isFunction(fn) && jQuery.isFunction(fn2) ) {
			this._toggle.apply( this, arguments );

		} else if ( fn == null || bool ) {
			this.each(function() {
				var state = bool ? fn : jQuery(this).is(":hidden");
				jQuery(this)[ state ? "show" : "hide" ]();
			});

		} else {
			this.animate(genFx("toggle", 3), fn, fn2, callback);
		}

		return this;
	},

	fadeTo: function( speed, to, easing, callback ) {
		return this.filter(":hidden").css("opacity", 0).show().end()
					.animate({opacity: to}, speed, easing, callback);
	},

	animate: function( prop, speed, easing, callback ) {
		var optall = jQuery.speed(speed, easing, callback);

		if ( jQuery.isEmptyObject( prop ) ) {
			return this.each( optall.complete );
		}

		return this[ optall.queue === false ? "each" : "queue" ](function() {
			// XXX 'this' does not always have a nodeName when running the
			// test suite

			var opt = jQuery.extend({}, optall), p,
				isElement = this.nodeType === 1,
				hidden = isElement && jQuery(this).is(":hidden"),
				self = this;

			for ( p in prop ) {
				var name = jQuery.camelCase( p );

				if ( p !== name ) {
					prop[ name ] = prop[ p ];
					delete prop[ p ];
					p = name;
				}

				if ( prop[p] === "hide" && hidden || prop[p] === "show" && !hidden ) {
					return opt.complete.call(this);
				}

				if ( isElement && ( p === "height" || p === "width" ) ) {
					// Make sure that nothing sneaks out
					// Record all 3 overflow attributes because IE does not
					// change the overflow attribute when overflowX and
					// overflowY are set to the same value
					opt.overflow = [ this.style.overflow, this.style.overflowX, this.style.overflowY ];

					// Set display property to inline-block for height/width
					// animations on inline elements that are having width/height
					// animated
					if ( jQuery.css( this, "display" ) === "inline" &&
							jQuery.css( this, "float" ) === "none" ) {
						if ( !jQuery.support.inlineBlockNeedsLayout ) {
							this.style.display = "inline-block";

						} else {
							var display = defaultDisplay(this.nodeName);

							// inline-level elements accept inline-block;
							// block-level elements need to be inline with layout
							if ( display === "inline" ) {
								this.style.display = "inline-block";

							} else {
								this.style.display = "inline";
								this.style.zoom = 1;
							}
						}
					}
				}

				if ( jQuery.isArray( prop[p] ) ) {
					// Create (if needed) and add to specialEasing
					(opt.specialEasing = opt.specialEasing || {})[p] = prop[p][1];
					prop[p] = prop[p][0];
				}
			}

			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 ( rfxtypes.test(val) ) {
					e[ val === "toggle" ? hidden ? "show" : "hide" : val ]( prop );

				} else {
					var parts = rfxnum.exec(val),
						start = e.cur();

					if ( parts ) {
						var end = parseFloat( parts[2] ),
							unit = parts[3] || ( jQuery.cssNumber[ name ] ? "" : "px" );

						// We need to compute starting value
						if ( unit !== "px" ) {
							jQuery.style( self, name, (end || 1) + unit);
							start = ((end || 1) / e.cur()) * start;
							jQuery.style( self, 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;
		});
	},

	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;
	}

});

function genFx( type, num ) {
	var obj = {};

	jQuery.each( fxAttrs.concat.apply([], fxAttrs.slice(0,num)), function() {
		obj[ this ] = type;
	});

	return obj;
}

// Generate shortcuts for custom animations
jQuery.each({
	slideDown: genFx("show", 1),
	slideUp: genFx("hide", 1),
	slideToggle: genFx("toggle", 1),
	fadeIn: { opacity: "show" },
	fadeOut: { opacity: "hide" },
	fadeToggle: { opacity: "toggle" }
}, function( name, props ) {
	jQuery.fn[ name ] = function( speed, easing, callback ) {
		return this.animate( props, speed, easing, callback );
	};
});

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

		opt.duration = jQuery.fx.off ? 0 : typeof opt.duration === "number" ? opt.duration :
			opt.duration in jQuery.fx.speeds ? jQuery.fx.speeds[opt.duration] : jQuery.fx.speeds._default;

		// Queueing
		opt.old = opt.complete;
		opt.complete = function() {
			if ( opt.queue !== false ) {
				jQuery(this).dequeue();
			}
			if ( jQuery.isFunction( opt.old ) ) {
				opt.old.call( 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: [],

	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.call( this.elem, this.now, this );
		}

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

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

		var parsed,
			r = jQuery.css( this.elem, this.prop );
		// Empty strings, null, undefined and "auto" are converted to 0,
		// complex values such as "rotate(1rad)" are returned as is,
		// simple values such as "10px" are parsed to Float.
		return isNaN( parsed = parseFloat( r ) ) ? !r || r === "auto" ? 0 : r : parsed;
	},

	// Start an animation from one number to another
	custom: function( from, to, unit ) {
		var self = this,
			fx = jQuery.fx;

		this.startTime = jQuery.now();
		this.start = from;
		this.end = to;
		this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );
		this.now = this.start;
		this.pos = this.state = 0;

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

		t.elem = this.elem;

		if ( t() && jQuery.timers.push(t) && !timerId ) {
			timerId = setInterval(fx.tick, fx.interval);
		}
	},

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

		// Begin the animation
		// Make sure that we start at a small width/height to avoid any
		// flash of content
		this.custom(this.prop === "width" || this.prop === "height" ? 1 : 0, this.cur());

		// 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.style( this.elem, this.prop );
		this.options.hide = true;

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

	// Each step of an animation
	step: function( gotoEnd ) {
		var t = jQuery.now(), done = true;

		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;

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

			if ( done ) {
				// Reset the overflow
				if ( this.options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {
					var elem = this.elem,
						options = this.options;

					jQuery.each( [ "", "X", "Y" ], function (index, value) {
						elem.style[ "overflow" + value ] = options.overflow[index];
					} );
				}

				// Hide the element if the "hide" operation was done
				if ( this.options.hide ) {
					jQuery(this.elem).hide();
				}

				// 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.style( this.elem, p, this.options.orig[p] );
					}
				}

				// Execute the complete function
				this.options.complete.call( this.elem );
			}

			return false;

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

			// Perform the easing function, defaults to swing
			var specialEasing = this.options.specialEasing && this.options.specialEasing[this.prop];
			var defaultEasing = this.options.easing || (jQuery.easing.swing ? "swing" : "linear");
			this.pos = jQuery.easing[specialEasing || defaultEasing](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.extend( jQuery.fx, {
	tick: function() {
		var timers = jQuery.timers;

		for ( var i = 0; i < timers.length; i++ ) {
			if ( !timers[i]() ) {
				timers.splice(i--, 1);
			}
		}

		if ( !timers.length ) {
			jQuery.fx.stop();
		}
	},

	interval: 13,

	stop: function() {
		clearInterval( timerId );
		timerId = null;
	},

	speeds: {
		slow: 600,
		fast: 200,
		// Default speed
		_default: 400
	},

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

		_default: function( fx ) {
			if ( fx.elem.style && fx.elem.style[ fx.prop ] != null ) {
				fx.elem.style[ fx.prop ] = (fx.prop === "width" || fx.prop === "height" ? Math.max(0, fx.now) : fx.now) + fx.unit;
			} else {
				fx.elem[ fx.prop ] = fx.now;
			}
		}
	}
});

if ( jQuery.expr && jQuery.expr.filters ) {
	jQuery.expr.filters.animated = function( elem ) {
		return jQuery.grep(jQuery.timers, function( fn ) {
			return elem === fn.elem;
		}).length;
	};
}

function defaultDisplay( nodeName ) {
	if ( !elemdisplay[ nodeName ] ) {
		var elem = jQuery("<" + nodeName + ">").appendTo("body"),
			display = elem.css("display");

		elem.remove();

		if ( display === "none" || display === "" ) {
			display = "block";
		}

		elemdisplay[ nodeName ] = display;
	}

	return elemdisplay[ nodeName ];
}




var rtable = /^t(?:able|d|h)$/i,
	rroot = /^(?:body|html)$/i;

if ( "getBoundingClientRect" in document.documentElement ) {
	jQuery.fn.offset = function( options ) {
		var elem = this[0], box;

		if ( options ) {
			return this.each(function( i ) {
				jQuery.offset.setOffset( this, options, i );
			});
		}

		if ( !elem || !elem.ownerDocument ) {
			return null;
		}

		if ( elem === elem.ownerDocument.body ) {
			return jQuery.offset.bodyOffset( elem );
		}

		try {
			box = elem.getBoundingClientRect();
		} catch(e) {}

		var doc = elem.ownerDocument,
			docElem = doc.documentElement;

		// Make sure we're not dealing with a disconnected DOM node
		if ( !box || !jQuery.contains( docElem, elem ) ) {
			return box ? { top: box.top, left: box.left } : { top: 0, left: 0 };
		}

		var body = doc.body,
			win = getWindow(doc),
			clientTop  = docElem.clientTop  || body.clientTop  || 0,
			clientLeft = docElem.clientLeft || body.clientLeft || 0,
			scrollTop  = (win.pageYOffset || jQuery.support.boxModel && docElem.scrollTop  || body.scrollTop ),
			scrollLeft = (win.pageXOffset || jQuery.support.boxModel && docElem.scrollLeft || body.scrollLeft),
			top  = box.top  + scrollTop  - clientTop,
			left = box.left + scrollLeft - clientLeft;

		return { top: top, left: left };
	};

} else {
	jQuery.fn.offset = function( options ) {
		var elem = this[0];

		if ( options ) {
			return this.each(function( i ) {
				jQuery.offset.setOffset( this, options, i );
			});
		}

		if ( !elem || !elem.ownerDocument ) {
			return null;
		}

		if ( elem === elem.ownerDocument.body ) {
			return jQuery.offset.bodyOffset( elem );
		}

		jQuery.offset.initialize();

		var computedStyle,
			offsetParent = elem.offsetParent,
			prevOffsetParent = elem,
			doc = elem.ownerDocument,
			docElem = doc.documentElement,
			body = doc.body,
			defaultView = doc.defaultView,
			prevComputedStyle = defaultView ? defaultView.getComputedStyle( elem, null ) : elem.currentStyle,
			top = elem.offsetTop,
			left = elem.offsetLeft;

		while ( (elem = elem.parentNode) && elem !== body && elem !== docElem ) {
			if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
				break;
			}

			computedStyle = defaultView ? defaultView.getComputedStyle(elem, null) : elem.currentStyle;
			top  -= elem.scrollTop;
			left -= elem.scrollLeft;

			if ( elem === offsetParent ) {
				top  += elem.offsetTop;
				left += elem.offsetLeft;

				if ( jQuery.offset.doesNotAddBorder && !(jQuery.offset.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
					top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
				}

				prevOffsetParent = offsetParent;
				offsetParent = elem.offsetParent;
			}

			if ( jQuery.offset.subtractsBorderForOverflowNotVisible && computedStyle.overflow !== "visible" ) {
				top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
				left += parseFloat( computedStyle.borderLeftWidth ) || 0;
			}

			prevComputedStyle = computedStyle;
		}

		if ( prevComputedStyle.position === "relative" || prevComputedStyle.position === "static" ) {
			top  += body.offsetTop;
			left += body.offsetLeft;
		}

		if ( jQuery.offset.supportsFixedPosition && prevComputedStyle.position === "fixed" ) {
			top  += Math.max( docElem.scrollTop, body.scrollTop );
			left += Math.max( docElem.scrollLeft, body.scrollLeft );
		}

		return { top: top, left: left };
	};
}

jQuery.offset = {
	initialize: function() {
		var body = document.body, container = document.createElement("div"), innerDiv, checkDiv, table, td, bodyMarginTop = parseFloat( jQuery.css(body, "marginTop") ) || 0,
			html = "<div style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;'><div></div></div><table style='position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;' cellpadding='0' cellspacing='0'><tr><td></td></tr></table>";

		jQuery.extend( container.style, { position: "absolute", top: 0, left: 0, margin: 0, border: 0, width: "1px", height: "1px", visibility: "hidden" } );

		container.innerHTML = html;
		body.insertBefore( container, body.firstChild );
		innerDiv = container.firstChild;
		checkDiv = innerDiv.firstChild;
		td = innerDiv.nextSibling.firstChild.firstChild;

		this.doesNotAddBorder = (checkDiv.offsetTop !== 5);
		this.doesAddBorderForTableAndCells = (td.offsetTop === 5);

		checkDiv.style.position = "fixed";
		checkDiv.style.top = "20px";

		// safari subtracts parent border width here which is 5px
		this.supportsFixedPosition = (checkDiv.offsetTop === 20 || checkDiv.offsetTop === 15);
		checkDiv.style.position = checkDiv.style.top = "";

		innerDiv.style.overflow = "hidden";
		innerDiv.style.position = "relative";

		this.subtractsBorderForOverflowNotVisible = (checkDiv.offsetTop === -5);

		this.doesNotIncludeMarginInBodyOffset = (body.offsetTop !== bodyMarginTop);

		body.removeChild( container );
		body = container = innerDiv = checkDiv = table = td = null;
		jQuery.offset.initialize = jQuery.noop;
	},

	bodyOffset: function( body ) {
		var top = body.offsetTop,
			left = body.offsetLeft;

		jQuery.offset.initialize();

		if ( jQuery.offset.doesNotIncludeMarginInBodyOffset ) {
			top  += parseFloat( jQuery.css(body, "marginTop") ) || 0;
			left += parseFloat( jQuery.css(body, "marginLeft") ) || 0;
		}

		return { top: top, left: left };
	},

	setOffset: function( elem, options, i ) {
		var position = jQuery.css( elem, "position" );

		// set position first, in-case top/left are set even on static elem
		if ( position === "static" ) {
			elem.style.position = "relative";
		}

		var curElem = jQuery( elem ),
			curOffset = curElem.offset(),
			curCSSTop = jQuery.css( elem, "top" ),
			curCSSLeft = jQuery.css( elem, "left" ),
			calculatePosition = (position === "absolute" && jQuery.inArray('auto', [curCSSTop, curCSSLeft]) > -1),
			props = {}, curPosition = {}, curTop, curLeft;

		// need to be able to calculate position if either top or left is auto and position is absolute
		if ( calculatePosition ) {
			curPosition = curElem.position();
		}

		curTop  = calculatePosition ? curPosition.top  : parseInt( curCSSTop,  10 ) || 0;
		curLeft = calculatePosition ? curPosition.left : parseInt( curCSSLeft, 10 ) || 0;

		if ( jQuery.isFunction( options ) ) {
			options = options.call( elem, i, curOffset );
		}

		if (options.top != null) {
			props.top = (options.top - curOffset.top) + curTop;
		}
		if (options.left != null) {
			props.left = (options.left - curOffset.left) + curLeft;
		}

		if ( "using" in options ) {
			options.using.call( elem, props );
		} else {
			curElem.css( props );
		}
	}
};


jQuery.fn.extend({
	position: function() {
		if ( !this[0] ) {
			return null;
		}

		var elem = this[0],

		// Get *real* offsetParent
		offsetParent = this.offsetParent(),

		// Get correct offsets
		offset       = this.offset(),
		parentOffset = rroot.test(offsetParent[0].nodeName) ? { top: 0, left: 0 } : offsetParent.offset();

		// Subtract element margins
		// note: when an element has margin: auto the offsetLeft and marginLeft
		// are the same in Safari causing offset.left to incorrectly be 0
		offset.top  -= parseFloat( jQuery.css(elem, "marginTop") ) || 0;
		offset.left -= parseFloat( jQuery.css(elem, "marginLeft") ) || 0;

		// Add offsetParent borders
		parentOffset.top  += parseFloat( jQuery.css(offsetParent[0], "borderTopWidth") ) || 0;
		parentOffset.left += parseFloat( jQuery.css(offsetParent[0], "borderLeftWidth") ) || 0;

		// Subtract the two offsets
		return {
			top:  offset.top  - parentOffset.top,
			left: offset.left - parentOffset.left
		};
	},

	offsetParent: function() {
		return this.map(function() {
			var offsetParent = this.offsetParent || document.body;
			while ( offsetParent && (!rroot.test(offsetParent.nodeName) && jQuery.css(offsetParent, "position") === "static") ) {
				offsetParent = offsetParent.offsetParent;
			}
			return offsetParent;
		});
	}
});


// Create scrollLeft and scrollTop methods
jQuery.each( ["Left", "Top"], function( i, name ) {
	var method = "scroll" + name;

	jQuery.fn[ method ] = function(val) {
		var elem = this[0], win;

		if ( !elem ) {
			return null;
		}

		if ( val !== undefined ) {
			// Set the scroll offset
			return this.each(function() {
				win = getWindow( this );

				if ( win ) {
					win.scrollTo(
						!i ? val : jQuery(win).scrollLeft(),
						i ? val : jQuery(win).scrollTop()
					);

				} else {
					this[ method ] = val;
				}
			});
		} else {
			win = getWindow( elem );

			// Return the scroll offset
			return win ? ("pageXOffset" in win) ? win[ i ? "pageYOffset" : "pageXOffset" ] :
				jQuery.support.boxModel && win.document.documentElement[ method ] ||
					win.document.body[ method ] :
				elem[ method ];
		}
	};
});

function getWindow( elem ) {
	return jQuery.isWindow( elem ) ?
		elem :
		elem.nodeType === 9 ?
			elem.defaultView || elem.parentWindow :
			false;
}




// Create innerHeight, innerWidth, outerHeight and outerWidth methods
jQuery.each([ "Height", "Width" ], function( i, name ) {

	var type = name.toLowerCase();

	// innerHeight and innerWidth
	jQuery.fn["inner" + name] = function() {
		return this[0] ?
			parseFloat( jQuery.css( this[0], type, "padding" ) ) :
			null;
	};

	// outerHeight and outerWidth
	jQuery.fn["outer" + name] = function( margin ) {
		return this[0] ?
			parseFloat( jQuery.css( this[0], type, margin ? "margin" : "border" ) ) :
			null;
	};

	jQuery.fn[ type ] = function( size ) {
		// Get window width or height
		var elem = this[0];
		if ( !elem ) {
			return size == null ? null : this;
		}

		if ( jQuery.isFunction( size ) ) {
			return this.each(function( i ) {
				var self = jQuery( this );
				self[ type ]( size.call( this, i, self[ type ]() ) );
			});
		}

		if ( jQuery.isWindow( elem ) ) {
			// Everyone else use document.documentElement or document.body depending on Quirks vs Standards mode
			// 3rd condition allows Nokia support, as it supports the docElem prop but not CSS1Compat
			var docElemProp = elem.document.documentElement[ "client" + name ];
			return elem.document.compatMode === "CSS1Compat" && docElemProp ||
				elem.document.body[ "client" + name ] || docElemProp;

		// Get document width or height
		} else if ( elem.nodeType === 9 ) {
			// Either scroll[Width/Height] or offset[Width/Height], whichever is greater
			return Math.max(
				elem.documentElement["client" + name],
				elem.body["scroll" + name], elem.documentElement["scroll" + name],
				elem.body["offset" + name], elem.documentElement["offset" + name]
			);

		// Get or set width or height on the element
		} else if ( size === undefined ) {
			var orig = jQuery.css( elem, type ),
				ret = parseFloat( orig );

			return jQuery.isNaN( ret ) ? orig : ret;

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

});


window.jQuery = window.$ = jQuery;
})(window);

/** File: javascript/jquery.dimensions.js **/

/* 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 08:46:55 -0600 (Thu, 20 Dec 2007) $
 * $Rev: 4259 $
 *
 * Version: 1.2
 *
 * Requires: jQuery 1.2+
 */

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

// 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;
	}
});

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

})(jQuery);

/** File: javascript/jquery.bgiframe.js **/

/* 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$
 * $Rev$
 *
 * 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 && (parseInt($.browser.version) == 6)) {
		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);

/** File: javascript/jquery.form.js **/

/*!
 * jQuery Form Plugin
 * version: 2.73 (03-MAY-2011)
 * @requires jQuery v1.3.2 or later
 *
 * Examples and documentation at: http://malsup.com/jquery/form/
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
;(function($) {

/*
  Usage Note:
  -----------
  Do not use both ajaxSubmit and ajaxForm on the same form.  These
  functions are intended to be exclusive.  Use ajaxSubmit if you want
  to bind your own submit handler to the form.  For example,

  $(document).ready(function() {
    $('#myForm').bind('submit', function(e) {
      e.preventDefault(); // <-- important
      $(this).ajaxSubmit({
        target: '#output'
      });
    });
  });

  Use ajaxForm when you want the plugin to manage all the event binding
  for you.  For example,

  $(document).ready(function() {
    $('#myForm').ajaxForm({
      target: '#output'
    });
  });

  When using ajaxForm, the ajaxSubmit function will be invoked for you
  at the appropriate time.
*/

/**
 * ajaxSubmit() provides a mechanism for immediately submitting
 * an HTML form using AJAX.
 */
$.fn.ajaxSubmit = function(options) {
  // fast fail if nothing selected (http://dev.jquery.com/ticket/2752)
  if (!this.length) {
    log('ajaxSubmit: skipping submit process - no element selected');
    return this;
  }

  if (typeof options == 'function') {
    options = { success: options };
  }

  var action = this.attr('action');
  var url = (typeof action === 'string') ? $.trim(action) : '';
  if (url) {
    // clean url (don't include hash vaue)
    url = (url.match(/^([^#]+)/)||[])[1];
  }
  url = url || window.location.href || '';

  options = $.extend(true, {
    url:  url,
    success: $.ajaxSettings.success,
    type: this[0].getAttribute('method') || 'GET', // IE7 massage (see issue 57)
    iframeSrc: /^https/i.test(window.location.href || '') ? 'javascript:false' : 'about:blank'
  }, options);

  // hook for manipulating the form data before it is extracted;
  // convenient for use with rich editors like tinyMCE or FCKEditor
  var veto = {};
  this.trigger('form-pre-serialize', [this, options, veto]);
  if (veto.veto) {
    log('ajaxSubmit: submit vetoed via form-pre-serialize trigger');
    return this;
  }

  // provide opportunity to alter form data before it is serialized
  if (options.beforeSerialize && options.beforeSerialize(this, options) === false) {
    log('ajaxSubmit: submit aborted via beforeSerialize callback');
    return this;
  }

  var n,v,a = this.formToArray(options.semantic);
  if (options.data) {
    options.extraData = options.data;
    for (n in options.data) {
      if(options.data[n] instanceof Array) {
        for (var k in options.data[n]) {
          a.push( { name: n, value: options.data[n][k] } );
        }
      }
      else {
        v = options.data[n];
        v = $.isFunction(v) ? v() : v; // if value is fn, invoke it
        a.push( { name: n, value: v } );
      }
    }
  }

  // give pre-submit callback an opportunity to abort the submit
  if (options.beforeSubmit && options.beforeSubmit(a, this, options) === false) {
    log('ajaxSubmit: submit aborted via beforeSubmit callback');
    return this;
  }

  // fire vetoable 'validate' event
  this.trigger('form-submit-validate', [a, this, options, veto]);
  if (veto.veto) {
    log('ajaxSubmit: submit vetoed via form-submit-validate trigger');
    return this;
  }

  var q = $.param(a);

  if (options.type.toUpperCase() == 'GET') {
    options.url += (options.url.indexOf('?') >= 0 ? '&' : '?') + q;
    options.data = null;  // data is null for 'get'
  }
  else {
    options.data = q; // data is the query string for 'post'
  }

  var $form = this, callbacks = [];
  if (options.resetForm) {
    callbacks.push(function() { $form.resetForm(); });
  }
  if (options.clearForm) {
    callbacks.push(function() { $form.clearForm(); });
  }

  // perform a load on the target only if dataType is not provided
  if (!options.dataType && options.target) {
    var oldSuccess = options.success || function(){};
    callbacks.push(function(data) {
      var fn = options.replaceTarget ? 'replaceWith' : 'html';
      $(options.target)[fn](data).each(oldSuccess, arguments);
    });
  }
  else if (options.success) {
    callbacks.push(options.success);
  }

  options.success = function(data, status, xhr) { // jQuery 1.4+ passes xhr as 3rd arg
    var context = options.context || options;   // jQuery 1.4+ supports scope context 
    for (var i=0, max=callbacks.length; i < max; i++) {
      callbacks[i].apply(context, [data, status, xhr || $form, $form]);
    }
  };

  // are there files to upload?
  var fileInputs = $('input:file', this).length > 0;
  var mp = 'multipart/form-data';
  var multipart = ($form.attr('enctype') == mp || $form.attr('encoding') == mp);

  // options.iframe allows user to force iframe mode
  // 06-NOV-09: now defaulting to iframe mode if file input is detected
   if (options.iframe !== false && (fileInputs || options.iframe || multipart)) {
     // hack to fix Safari hang (thanks to Tim Molendijk for this)
     // see:  http://groups.google.com/group/jquery-dev/browse_thread/thread/36395b7ab510dd5d
     if (options.closeKeepAlive) {
       $.get(options.closeKeepAlive, fileUpload);
    }
     else {
       fileUpload();
    }
   }
   else {
    $.ajax(options);
   }

  // fire 'notify' event
  this.trigger('form-submit-notify', [this, options]);
  return this;


  // private function for handling file uploads (hat tip to YAHOO!)
  function fileUpload() {
    var form = $form[0];

    if ($(':input[name=submit],:input[id=submit]', form).length) {
      // if there is an input with a name or id of 'submit' then we won't be
      // able to invoke the submit fn on the form (at least not x-browser)
      alert('Error: Form elements must not have name or id of "submit".');
      return;
    }

    var s = $.extend(true, {}, $.ajaxSettings, options);
    s.context = s.context || s;
    var id = 'jqFormIO' + (new Date().getTime()), fn = '_'+id;
    var $io = $('<iframe id="' + id + '" name="' + id + '" src="'+ s.iframeSrc +'" />');
    var io = $io[0];

    $io.css({ position: 'absolute', top: '-1000px', left: '-1000px' });

    var xhr = { // mock object
      aborted: 0,
      responseText: null,
      responseXML: null,
      status: 0,
      statusText: 'n/a',
      getAllResponseHeaders: function() {},
      getResponseHeader: function() {},
      setRequestHeader: function() {},
      abort: function(status) {
        var e = (status === 'timeout' ? 'timeout' : 'aborted');
        log('aborting upload... ' + e);
        this.aborted = 1;
        $io.attr('src', s.iframeSrc); // abort op in progress
        xhr.error = e;
        s.error && s.error.call(s.context, xhr, e, e);
        g && $.event.trigger("ajaxError", [xhr, s, e]);
        s.complete && s.complete.call(s.context, xhr, e);
      }
    };

    var g = s.global;
    // trigger ajax global events so that activity/block indicators work like normal
    if (g && ! $.active++) {
      $.event.trigger("ajaxStart");
    }
    if (g) {
      $.event.trigger("ajaxSend", [xhr, s]);
    }

    if (s.beforeSend && s.beforeSend.call(s.context, xhr, s) === false) {
      if (s.global) { 
        $.active--;
      }
      return;
    }
    if (xhr.aborted) {
      return;
    }

    var timedOut = 0, timeoutHandle;

    // add submitting element to data if we know it
    var sub = form.clk;
    if (sub) {
      var n = sub.name;
      if (n && !sub.disabled) {
        s.extraData = s.extraData || {};
        s.extraData[n] = sub.value;
        if (sub.type == "image") {
          s.extraData[n+'.x'] = form.clk_x;
          s.extraData[n+'.y'] = form.clk_y;
        }
      }
    }

    // take a breath so that pending repaints get some cpu time before the upload starts
    function doSubmit() {
      // make sure form attrs are set
      var t = $form.attr('target'), a = $form.attr('action');

      // update form attrs in IE friendly way
      form.setAttribute('target',id);
      if (form.getAttribute('method') != 'POST') {
        form.setAttribute('method', 'POST');
      }
      if (form.getAttribute('action') != s.url) {
        form.setAttribute('action', s.url);
      }

      // ie borks in some cases when setting encoding
      if (! s.skipEncodingOverride) {
        $form.attr({
          encoding: 'multipart/form-data',
          enctype:  'multipart/form-data'
        });
      }

      // support timout
      if (s.timeout) {
        timeoutHandle = setTimeout(function() { timedOut = true; cb(true); }, s.timeout);
      }

      // add "extra" data to form if provided in options
      var extraInputs = [];
      try {
        if (s.extraData) {
          for (var n in s.extraData) {
            extraInputs.push(
              $('<input type="hidden" name="'+n+'" value="'+s.extraData[n]+'" />')
                .appendTo(form)[0]);
          }
        }

        // add iframe to doc and submit the form
        $io.appendTo('body');
                io.attachEvent ? io.attachEvent('onload', cb) : io.addEventListener('load', cb, false);
        form.submit();
      }
      finally {
        // reset attrs and remove "extra" input elements
        form.setAttribute('action',a);
        if(t) {
          form.setAttribute('target', t);
        } else {
          $form.removeAttr('target');
        }
        $(extraInputs).remove();
      }
    }

    if (s.forceSync) {
      doSubmit();
    }
    else {
      setTimeout(doSubmit, 10); // this lets dom updates render
    }

    var data, doc, domCheckCount = 50, callbackProcessed;

    function cb(e) {
      if (xhr.aborted || callbackProcessed) {
        return;
      }
      if (e === true && xhr) {
        xhr.abort('timeout');
        return;
      }

      var doc = io.contentWindow ? io.contentWindow.document : io.contentDocument ? io.contentDocument : io.document;
      if (!doc || doc.location.href == s.iframeSrc) {
        // response not received yet
        if (!timedOut)
          return;
      }
            io.detachEvent ? io.detachEvent('onload', cb) : io.removeEventListener('load', cb, false);

      var ok = true;
      try {
        if (timedOut) {
          throw 'timeout';
        }

        var isXml = s.dataType == 'xml' || doc.XMLDocument || $.isXMLDoc(doc);
        log('isXml='+isXml);
        if (!isXml && window.opera && (doc.body == null || doc.body.innerHTML == '')) {
          if (--domCheckCount) {
            // in some browsers (Opera) the iframe DOM is not always traversable when
            // the onload callback fires, so we loop a bit to accommodate
            log('requeing onLoad callback, DOM not available');
            setTimeout(cb, 250);
            return;
          }
          // let this fall through because server response could be an empty document
          //log('Could not access iframe DOM after mutiple tries.');
          //throw 'DOMException: not available';
        }

        //log('response detected');
        xhr.responseText = doc.body ? doc.body.innerHTML : doc.documentElement ? doc.documentElement.innerHTML : null; 
        xhr.responseXML = doc.XMLDocument ? doc.XMLDocument : doc;
        if (isXml)
          s.dataType = 'xml';
        xhr.getResponseHeader = function(header){
          var headers = {'content-type': s.dataType};
          return headers[header];
        };

        var scr = /(json|script|text)/.test(s.dataType);
        if (scr || s.textarea) {
          // see if user embedded response in textarea
          var ta = doc.getElementsByTagName('textarea')[0];
          if (ta) {
            xhr.responseText = ta.value;
          }
          else if (scr) {
            // account for browsers injecting pre around json response
            var pre = doc.getElementsByTagName('pre')[0];
            var b = doc.getElementsByTagName('body')[0];
            if (pre) {
              xhr.responseText = pre.textContent;
            }
            else if (b) {
              xhr.responseText = b.innerHTML;
            }
          }       
        }
        else if (s.dataType == 'xml' && !xhr.responseXML && xhr.responseText != null) {
          xhr.responseXML = toXml(xhr.responseText);
        }

        data = httpData(xhr, s.dataType, s);
      }
      catch(e){
        log('error caught:',e);
        ok = false;
        xhr.error = e;
        s.error && s.error.call(s.context, xhr, 'error', e);
        g && $.event.trigger("ajaxError", [xhr, s, e]);
      }

      if (xhr.aborted) {
        log('upload aborted');
        ok = false;
      }

      // ordering of these callbacks/triggers is odd, but that's how $.ajax does it
      if (ok) {
        s.success && s.success.call(s.context, data, 'success', xhr);
        g && $.event.trigger("ajaxSuccess", [xhr, s]);
      }

      g && $.event.trigger("ajaxComplete", [xhr, s]);

      if (g && ! --$.active) {
        $.event.trigger("ajaxStop");
      }

      s.complete && s.complete.call(s.context, xhr, ok ? 'success' : 'error');

      callbackProcessed = true;
      if (s.timeout)
        clearTimeout(timeoutHandle);

      // clean up
      setTimeout(function() {
        $io.removeData('form-plugin-onload');
        $io.remove();
        xhr.responseXML = null;
      }, 100);
    }

    var toXml = $.parseXML || function(s, doc) { // use parseXML if available (jQuery 1.5+)
      if (window.ActiveXObject) {
        doc = new ActiveXObject('Microsoft.XMLDOM');
        doc.async = 'false';
        doc.loadXML(s);
      }
      else {
        doc = (new DOMParser()).parseFromString(s, 'text/xml');
      }
      return (doc && doc.documentElement && doc.documentElement.nodeName != 'parsererror') ? doc : null;
    };
    var parseJSON = $.parseJSON || function(s) {
      return window['eval']('(' + s + ')');
    };

    var httpData = function( xhr, type, s ) { // mostly lifted from jq1.4.4
      var ct = xhr.getResponseHeader('content-type') || '',
        xml = type === 'xml' || !type && ct.indexOf('xml') >= 0,
        data = xml ? xhr.responseXML : xhr.responseText;

      if (xml && data.documentElement.nodeName === 'parsererror') {
        $.error && $.error('parsererror');
      }
      if (s && s.dataFilter) {
        data = s.dataFilter(data, type);
      }
      if (typeof data === 'string') {
        if (type === 'json' || !type && ct.indexOf('json') >= 0) {
          data = parseJSON(data);
        } else if (type === "script" || !type && ct.indexOf("javascript") >= 0) {
          $.globalEval(data);
        }
      }
      return data;
    };
  }
};

/**
 * ajaxForm() provides a mechanism for fully automating form submission.
 *
 * The advantages of using this method instead of ajaxSubmit() are:
 *
 * 1: This method will include coordinates for <input type="image" /> elements (if the element
 *  is used to submit the form).
 * 2. This method will include the submit element's name/value data (for the element that was
 *  used to submit the form).
 * 3. This method binds the submit() method to the form for you.
 *
 * The options argument for ajaxForm works exactly as it does for ajaxSubmit.  ajaxForm merely
 * passes the options argument along after properly binding events for submit elements and
 * the form itself.
 */
$.fn.ajaxForm = function(options) {
  // in jQuery 1.3+ we can fix mistakes with the ready state
  if (this.length === 0) {
    var o = { s: this.selector, c: this.context };
    if (!$.isReady && o.s) {
      log('DOM not ready, queuing ajaxForm');
      $(function() {
        $(o.s,o.c).ajaxForm(options);
      });
      return this;
    }
    // is your DOM ready?  http://docs.jquery.com/Tutorials:Introducing_$(document).ready()
    log('terminating; zero elements found by selector' + ($.isReady ? '' : ' (DOM not ready)'));
    return this;
  }

  return this.ajaxFormUnbind().bind('submit.form-plugin', function(e) {
    if (!e.isDefaultPrevented()) { // if event has been canceled, don't proceed
      e.preventDefault();
      $(this).ajaxSubmit(options);
    }
  }).bind('click.form-plugin', function(e) {
    var target = e.target;
    var $el = $(target);
    if (!($el.is(":submit,input:image"))) {
      // is this a child element of the submit el?  (ex: a span within a button)
      var t = $el.closest(':submit');
      if (t.length == 0) {
        return;
      }
      target = t[0];
    }
    var form = this;
    form.clk = target;
    if (target.type == 'image') {
      if (e.offsetX != undefined) {
        form.clk_x = e.offsetX;
        form.clk_y = e.offsetY;
      } else if (typeof $.fn.offset == 'function') { // try to use dimensions plugin
        var offset = $el.offset();
        form.clk_x = e.pageX - offset.left;
        form.clk_y = e.pageY - offset.top;
      } else {
        form.clk_x = e.pageX - target.offsetLeft;
        form.clk_y = e.pageY - target.offsetTop;
      }
    }
    // clear form vars
    setTimeout(function() { form.clk = form.clk_x = form.clk_y = null; }, 100);
  });
};

// ajaxFormUnbind unbinds the event handlers that were bound by ajaxForm
$.fn.ajaxFormUnbind = function() {
  return this.unbind('submit.form-plugin click.form-plugin');
};

/**
 * formToArray() gathers form element data into an array of objects that can
 * be passed to any of the following ajax functions: $.get, $.post, or load.
 * Each object in the array has both a 'name' and 'value' property.  An example of
 * an array for a simple login form might be:
 *
 * [ { name: 'username', value: 'jresig' }, { name: 'password', value: 'secret' } ]
 *
 * It is this array that is passed to pre-submit callback functions provided to the
 * ajaxSubmit() and ajaxForm() methods.
 */
$.fn.formToArray = function(semantic) {
  var a = [];
  if (this.length === 0) {
    return a;
  }

  var form = this[0];
  var els = semantic ? form.getElementsByTagName('*') : form.elements;
  if (!els) {
    return a;
  }

  var i,j,n,v,el,max,jmax;
  for(i=0, max=els.length; i < max; i++) {
    el = els[i];
    n = el.name;
    if (!n) {
      continue;
    }

    if (semantic && form.clk && el.type == "image") {
      // handle image inputs on the fly when semantic == true
      if(!el.disabled && form.clk == el) {
        a.push({name: n, value: $(el).val()});
        a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
      }
      continue;
    }

    v = $.fieldValue(el, true);
    if (v && v.constructor == Array) {
      for(j=0, jmax=v.length; j < jmax; j++) {
        a.push({name: n, value: v[j]});
      }
    }
    else if (v !== null && typeof v != 'undefined') {
      a.push({name: n, value: v});
    }
  }

  if (!semantic && form.clk) {
    // input type=='image' are not found in elements array! handle it here
    var $input = $(form.clk), input = $input[0];
    n = input.name;
    if (n && !input.disabled && input.type == 'image') {
      a.push({name: n, value: $input.val()});
      a.push({name: n+'.x', value: form.clk_x}, {name: n+'.y', value: form.clk_y});
    }
  }
  return a;
};

/**
 * Serializes form data into a 'submittable' string. This method will return a string
 * in the format: name1=value1&amp;name2=value2
 */
$.fn.formSerialize = function(semantic) {
  //hand off to jQuery.param for proper encoding
  return $.param(this.formToArray(semantic));
};

/**
 * Serializes all field elements in the jQuery object into a query string.
 * This method will return a string in the format: name1=value1&amp;name2=value2
 */
$.fn.fieldSerialize = function(successful) {
  var a = [];
  this.each(function() {
    var n = this.name;
    if (!n) {
      return;
    }
    var v = $.fieldValue(this, successful);
    if (v && v.constructor == Array) {
      for (var i=0,max=v.length; i < max; i++) {
        a.push({name: n, value: v[i]});
      }
    }
    else if (v !== null && typeof v != 'undefined') {
      a.push({name: this.name, value: v});
    }
  });
  //hand off to jQuery.param for proper encoding
  return $.param(a);
};

/**
 * Returns the value(s) of the element in the matched set.  For example, consider the following form:
 *
 *  <form><fieldset>
 *    <input name="A" type="text" />
 *    <input name="A" type="text" />
 *    <input name="B" type="checkbox" value="B1" />
 *    <input name="B" type="checkbox" value="B2"/>
 *    <input name="C" type="radio" value="C1" />
 *    <input name="C" type="radio" value="C2" />
 *  </fieldset></form>
 *
 *  var v = $(':text').fieldValue();
 *  // if no values are entered into the text inputs
 *  v == ['','']
 *  // if values entered into the text inputs are 'foo' and 'bar'
 *  v == ['foo','bar']
 *
 *  var v = $(':checkbox').fieldValue();
 *  // if neither checkbox is checked
 *  v === undefined
 *  // if both checkboxes are checked
 *  v == ['B1', 'B2']
 *
 *  var v = $(':radio').fieldValue();
 *  // if neither radio is checked
 *  v === undefined
 *  // if first radio is checked
 *  v == ['C1']
 *
 * The successful argument controls whether or not the field element must be 'successful'
 * (per http://www.w3.org/TR/html4/interact/forms.html#successful-controls).
 * The default value of the successful argument is true.  If this value is false the value(s)
 * for each element is returned.
 *
 * Note: This method *always* returns an array.  If no valid value can be determined the
 *     array will be empty, otherwise it will contain one or more values.
 */
$.fn.fieldValue = function(successful) {
  for (var val=[], i=0, max=this.length; i < max; i++) {
    var el = this[i];
    var v = $.fieldValue(el, successful);
    if (v === null || typeof v == 'undefined' || (v.constructor == Array && !v.length)) {
      continue;
    }
    v.constructor == Array ? $.merge(val, v) : val.push(v);
  }
  return val;
};

/**
 * Returns the value of the field element.
 */
$.fieldValue = function(el, successful) {
  var n = el.name, t = el.type, tag = el.tagName.toLowerCase();
  if (successful === undefined) {
    successful = true;
  }

  if (successful && (!n || el.disabled || t == 'reset' || t == 'button' ||
    (t == 'checkbox' || t == 'radio') && !el.checked ||
    (t == 'submit' || t == 'image') && el.form && el.form.clk != el ||
    tag == 'select' && el.selectedIndex == -1)) {
      return null;
  }

  if (tag == 'select') {
    var index = el.selectedIndex;
    if (index < 0) {
      return null;
    }
    var a = [], ops = el.options;
    var one = (t == 'select-one');
    var max = (one ? index+1 : ops.length);
    for(var i=(one ? index : 0); i < max; i++) {
      var op = ops[i];
      if (op.selected) {
        var v = op.value;
        if (!v) { // extra pain for IE...
          v = (op.attributes && op.attributes['value'] && !(op.attributes['value'].specified)) ? op.text : op.value;
        }
        if (one) {
          return v;
        }
        a.push(v);
      }
    }
    return a;
  }
  return $(el).val();
};

/**
 * Clears the form data.  Takes the following actions on the form's input fields:
 *  - input text fields will have their 'value' property set to the empty string
 *  - select elements will have their 'selectedIndex' property set to -1
 *  - checkbox and radio inputs will have their 'checked' property set to false
 *  - inputs of type submit, button, reset, and hidden will *not* be effected
 *  - button elements will *not* be effected
 */
$.fn.clearForm = function() {
  return this.each(function() {
    $('input,select,textarea', this).clearFields();
  });
};

/**
 * Clears the selected form elements.
 */
$.fn.clearFields = $.fn.clearInputs = function() {
  return this.each(function() {
    var t = this.type, tag = this.tagName.toLowerCase();
    if (t == 'text' || t == 'password' || tag == 'textarea') {
      this.value = '';
    }
    else if (t == 'checkbox' || t == 'radio') {
      this.checked = false;
    }
    else if (tag == 'select') {
      this.selectedIndex = -1;
    }
  });
};

/**
 * Resets the form data.  Causes all form elements to be reset to their original value.
 */
$.fn.resetForm = function() {
  return this.each(function() {
    // guard against an input with the name of 'reset'
    // note that IE reports the reset function as an 'object'
    if (typeof this.reset == 'function' || (typeof this.reset == 'object' && !this.reset.nodeType)) {
      this.reset();
    }
  });
};

/**
 * Enables or disables any matching elements.
 */
$.fn.enable = function(b) {
  if (b === undefined) {
    b = true;
  }
  return this.each(function() {
    this.disabled = !b;
  });
};

/**
 * Checks/unchecks any matching checkboxes or radio buttons and
 * selects/deselects and matching option elements.
 */
$.fn.selected = function(select) {
  if (select === undefined) {
    select = true;
  }
  return this.each(function() {
    var t = this.type;
    if (t == 'checkbox' || t == 'radio') {
      this.checked = select;
    }
    else if (this.tagName.toLowerCase() == 'option') {
      var $sel = $(this).parent('select');
      if (select && $sel[0] && $sel[0].type == 'select-one') {
        // deselect all other options
        $sel.find('option').selected(false);
      }
      this.selected = select;
    }
  });
};

// helper fn for console logging
// set $.fn.ajaxSubmit.debug to true to enable debug logging
function log() {
  if ($.fn.ajaxSubmit.debug) {
    var msg = '[jquery.form] ' + Array.prototype.join.call(arguments,'');
    if (window.console && window.console.log) {
      window.console.log(msg);
    }
    else if (window.opera && window.opera.postError) {
      window.opera.postError(msg);
    }
  }
};

})(jQuery);


/** File: javascript/jquery.blockui.js **/

/*
 * jQuery blockUI plugin
 * Version 2.10 (10/22/2008)
 * @requires jQuery v1.2.3 or later
 *
 * Examples at: http://malsup.com/jquery/block/
 * Copyright (c) 2007-2008 M. Alsup
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 * 
 * Thanks to Amir-Hossein Sobhi for some excellent contributions!
 */

;(function($) {

if (/1\.(0|1|2)\.(0|1|2)/.test($.fn.jquery) || /^1.1/.test($.fn.jquery)) {
    alert('blockUI requires jQuery v1.2.3 or later!  You are using v' + $.fn.jquery);
    return;
}

// global $ methods for blocking/unblocking the entire page
$.blockUI   = function(opts) { install(window, opts); };
$.unblockUI = function(opts) { remove(window, opts); };

// plugin method for blocking element content
$.fn.block = function(opts) {
    return this.each(function() {
        if ($.css(this,'position') == 'static')
            this.style.position = 'relative';
        if ($.browser.msie) 
            this.style.zoom = 1; // force 'hasLayout'
        install(this, opts);
    });
};

// plugin method for unblocking element content
$.fn.unblock = function(opts) {
    return this.each(function() {
        remove(this, opts);
    });
};

$.blockUI.version = 2.09; // 2nd generation blocking at no extra cost!

// override these in your code to change the default behavior and style
$.blockUI.defaults = {
    // message displayed when blocking (use null for no message)
    message:  '',
    
    // styles for the message when blocking; if you wish to disable
    // these and use an external stylesheet then do this in your code:
    // $.blockUI.defaults.css = {};
    css: { 
        padding:        0,
        margin:         0,
        width:          '30%', 
        top:            '40%', 
        left:           '35%', 
        textAlign:      'center', 
        color:          '#000', 
        border:         '3px solid #aaa',
        backgroundColor:'#fff',
        cursor:         'wait'
    },
    
    // styles for the overlay
    overlayCSS:  { 
        backgroundColor:'#FFF', 
        opacity:        '0.7' 
    },
    
    // z-index for the blocking overlay
    baseZ: 1000,
    
    // set these to true to have the message automatically centered
    centerX: true, // <-- only effects element blocking (page block controlled via css above)
    centerY: true,
    
    // allow body element to be stetched in ie6; this makes blocking look better
    // on "short" pages.  disable if you wish to prevent changes to the body height
    allowBodyStretch: true,
    
    // be default blockUI will supress tab navigation from leaving blocking content;
    constrainTabKey: true,
    
    // fadeOut time in millis; set to 0 to disable fadeout on unblock
    fadeOut:  400,
    
    // if true, focus will be placed in the first available input field when
    // page blocking
    focusInput: true,
    
    // suppresses the use of overlay styles on FF/Linux (due to performance issues with opacity)
    applyPlatformOpacityRules: true,
    
    // callback method invoked when unblocking has completed; the callback is
    // passed the element that has been unblocked (which is the window object for page
    // blocks) and the options that were passed to the unblock call:
    //     onUnblock(element, options)
    onUnblock: null,
    
    // don't ask (if you really must know: http://groups.google.com/group/jquery-en/browse_thread/thread/36640a8730503595/2f6a79a77a78e493#2f6a79a77a78e493)
    quirksmodeOffsetHack: 4
};

// private data and functions follow...

var ie6 = $.browser.msie && /MSIE 6.0/.test(navigator.userAgent);
var pageBlock = null;
var pageBlockEls = [];

function install(el, opts) {
    var full = (el == window);
    var msg = opts && opts.message !== undefined ? opts.message : undefined;
    opts = $.extend({}, $.blockUI.defaults, opts || {});
    opts.overlayCSS = $.extend({}, $.blockUI.defaults.overlayCSS, opts.overlayCSS || {});
    var css = $.extend({}, $.blockUI.defaults.css, opts.css || {});
    msg = msg === undefined ? opts.message : msg;

    // remove the current block (if there is one)
    if (full && pageBlock) 
        remove(window, {fadeOut:0}); 
    
    // if an existing element is being used as the blocking content then we capture
    // its current place in the DOM (and current display style) so we can restore
    // it when we unblock
    if (msg && typeof msg != 'string' && (msg.parentNode || msg.jquery)) {
        var node = msg.jquery ? msg[0] : msg;
        var data = {};
        $(el).data('blockUI.history', data);
        data.el = node;
        data.parent = node.parentNode;
        data.display = node.style.display;
        data.position = node.style.position;
        data.parent.removeChild(node);
    }
    
    var z = opts.baseZ;
    
    // blockUI uses 3 layers for blocking, for simplicity they are all used on every platform;
    // layer1 is the iframe layer which is used to supress bleed through of underlying content
    // layer2 is the overlay layer which has opacity and a wait cursor
    // layer3 is the message content that is displayed while blocking
    
    var lyr1 = ($.browser.msie) ? $('<iframe class="blockUI" style="z-index:'+ z++ +';border:none;margin:0;padding:0;position:absolute;width:100%;height:100%;top:0;left:0" src="javascript:false;"></iframe>')
                                : $('<div class="blockUI" style="display:none"></div>');
    var lyr2 = $('<div class="blockUI blockOverlay" style="z-index:'+ z++ +';cursor:wait;border:none;margin:0;padding:0;width:100%;height:100%;top:0;left:0"></div>');
    var lyr3 = full ? $('<div class="blockUI blockMsg blockPage" style="z-index:'+z+';position:fixed"></div>')
                    : $('<div class="blockUI blockMsg blockElement" style="z-index:'+z+';display:none;position:absolute"></div>');

    // if we have a message, style it
    if (msg) 
        lyr3.css(css);

    // style the overlay
    if (!opts.applyPlatformOpacityRules || !($.browser.mozilla && /Linux/.test(navigator.platform))) 
        lyr2.css(opts.overlayCSS);
    lyr2.css('position', full ? 'fixed' : 'absolute');
    
    // make iframe layer transparent in IE
    if ($.browser.msie) 
        lyr1.css('opacity','0.0');

    $([lyr1[0],lyr2[0],lyr3[0]]).appendTo(full ? 'body' : el);
    
    // ie7 must use absolute positioning in quirks mode and to account for activex issues (when scrolling)
    var expr = $.browser.msie && (!$.boxModel || $('object,embed', full ? null : el).length > 0);
    if (ie6 || expr) {
        // give body 100% height
        if (full && opts.allowBodyStretch && $.boxModel)
            $('html,body').css('height','100%');

        // fix ie6 issue when blocked element has a border width
        if ((ie6 || !$.boxModel) && !full) {
            var t = sz(el,'borderTopWidth'), l = sz(el,'borderLeftWidth');
            var fixT = t ? '(0 - '+t+')' : 0;
            var fixL = l ? '(0 - '+l+')' : 0;
        }

        // simulate fixed position
        $.each([lyr1,lyr2,lyr3], function(i,o) {
            var s = o[0].style;
            s.position = 'absolute';
            if (i < 2) {
                full ? s.setExpression('height','Math.max(document.body.scrollHeight, document.body.offsetHeight) - (jQuery.boxModel?0:'+opts.quirksmodeOffsetHack+') + "px"')
                     : s.setExpression('height','this.parentNode.offsetHeight + "px"');
                full ? s.setExpression('width','jQuery.boxModel && document.documentElement.clientWidth || document.body.clientWidth + "px"')
                     : s.setExpression('width','this.parentNode.offsetWidth + "px"');
                if (fixL) s.setExpression('left', fixL);
                if (fixT) s.setExpression('top', fixT);
            }
            else if (opts.centerY) {
                if (full) s.setExpression('top','(document.documentElement.clientHeight || document.body.clientHeight) / 2 - (this.offsetHeight / 2) + (blah = document.documentElement.scrollTop ? document.documentElement.scrollTop : document.body.scrollTop) + "px"');
                s.marginTop = 0;
            }
        });
    }
    
    // show the message
    lyr3.append(msg).show();
    if (msg && (msg.jquery || msg.nodeType))
        $(msg).show();

    // bind key and mouse events
    bind(1, el, opts);
        
    if (full) {
        pageBlock = lyr3[0];
        pageBlockEls = $(':input:enabled:visible',pageBlock);
        if (opts.focusInput)
            setTimeout(focus, 20);
    }
    else
        center(lyr3[0], opts.centerX, opts.centerY);
};

// remove the block
function remove(el, opts) {
    var full = el == window;
    var data = $(el).data('blockUI.history');
    opts = $.extend({}, $.blockUI.defaults, opts || {});
    bind(0, el, opts); // unbind events
    var els = full ? $('body').children().filter('.blockUI') : $('.blockUI', el);
    
    if (full) 
        pageBlock = pageBlockEls = null;

    if (opts.fadeOut) {
        els.fadeOut(opts.fadeOut);
        setTimeout(function() { reset(els,data,opts,el); }, opts.fadeOut);
    }
    else
        reset(els, data, opts, el);
};

// move blocking element back into the DOM where it started
function reset(els,data,opts,el) {
    els.each(function(i,o) {
        // remove via DOM calls so we don't lose event handlers
        if (this.parentNode) 
            this.parentNode.removeChild(this);
    });
    if (data && data.el) {
        data.el.style.display = data.display;
        data.el.style.position = data.position;
        data.parent.appendChild(data.el);
        $(data.el).removeData('blockUI.history');
    }
    if (typeof opts.onUnblock == 'function')
        opts.onUnblock(el,opts);
};

// bind/unbind the handler
function bind(b, el, opts) {
    var full = el == window, $el = $(el);
    
    // don't bother unbinding if there is nothing to unbind
    if (!b && (full && !pageBlock || !full && !$el.data('blockUI.isBlocked'))) 
        return;
    if (!full) 
        $el.data('blockUI.isBlocked', b);
        
    // bind anchors and inputs for mouse and key events
    var events = 'mousedown mouseup keydown keypress click';
    b ? $(document).bind(events, opts, handler) : $(document).unbind(events, handler);

// former impl...
//    var $e = $('a,:input');
//    b ? $e.bind(events, opts, handler) : $e.unbind(events, handler);
};

// event handler to suppress keyboard/mouse events when blocking
function handler(e) {
    // allow tab navigation (conditionally)
    if (e.keyCode && e.keyCode == 9) {
        if (pageBlock && e.data.constrainTabKey) {
            var els = pageBlockEls;
            var fwd = !e.shiftKey && e.target == els[els.length-1];
            var back = e.shiftKey && e.target == els[0];
            if (fwd || back) {
                setTimeout(function(){focus(back)},10);
                return false;
            }
        }
    }
    // allow events within the message content
    if ($(e.target).parents('div.blockMsg').length > 0)
        return true;
        
    // allow events for content that is not being blocked
    return $(e.target).parents().children().filter('div.blockUI').length == 0;
};

function focus(back) {
    if (!pageBlockEls) 
        return;
    var e = pageBlockEls[back===true ? pageBlockEls.length-1 : 0];
    if (e) 
        e.focus();
};

function center(el, x, y) {
    var p = el.parentNode, s = el.style;
    var l = ((p.offsetWidth - el.offsetWidth)/2) - sz(p,'borderLeftWidth');
    var t = ((p.offsetHeight - el.offsetHeight)/2) - sz(p,'borderTopWidth');
    if (x) s.left = l > 0 ? (l+'px') : '0';
    if (y) s.top  = t > 0 ? (t+'px') : '0';
};

function sz(el, p) { 
    return parseInt($.css(el,p))||0; 
};

})(jQuery);


/** File: javascript/jquery.jeditable.js **/

/*
+-----------------------------------------------------------------------+
| Copyright (c) 2006-2007 Mika Tuupola, Dylan Verheul                   |
| All rights reserved.                                                  |
|                                                                       |
| Redistribution and use in source and binary forms, with or without    |
| modification, are permitted provided that the following conditions    |
| are met:                                                              |
|                                                                       |
| o Redistributions of source code must retain the above copyright      |
|   notice, this list of conditions and the following disclaimer.       |
| o Redistributions in binary form must reproduce the above copyright   |
|   notice, this list of conditions and the following disclaimer in the |
|   documentation and/or other materials provided with the distribution.|
|                                                                       |
| THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS   |
| "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT     |
| LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR |
| A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT  |
| OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, |
| SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT      |
| LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
| DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
| THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT   |
| (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE |
| OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.  |
|                                                                       |
+-----------------------------------------------------------------------+
*/

/* $Id: jquery.jeditable.js 134 2007-03-13 17:29:52Z tuupola $ */

/**
  * jQuery inplace editor plugin (version 1.2.1)  
  *
  * Based on editable by Dylan Verheul <dylan@dyve.net>
  * http://www.dyve.net/jquery/?editable
  *
  * @name  jEditable
  * @type  jQuery
  * @param String  target             POST URL or function name to send edited content
  * @param Hash    settings            additional options 
  * @param String  settings[name]      POST parameter name of edited content
  * @param String  settings[id]        POST parameter name of edited div id
  * @param String  settings[type]      text, textarea or select
  * @param Integer settings[rows]      number of rows if using textarea
  * @param Integer settings[cols]      number of columns if using textarea
  * @param String  settings[loadurl]   URL to fetch content before editing
  * @param String  settings[loadtype]  Request type for load url. Should be GET or POST.
  * @param String  settings[data]      Or content given as paramameter.
  * @param String  settings[indicator] indicator html to show when saving
  * @param String  settings[tooltip]   optional tooltip text via title attribute
  * @param String  settings[event]     jQuery event such as 'click' of 'dblclick'
  * @param String  settings[onblur]    'cancel', 'submit' or 'ignore'
  * @param String  settings[submit]    submit button value, empty means no button
  * @param String  settings[cancel]    cancel button value, empty means no button
  * @param String  settings[cssclass]  CSS class to apply to input form. 'inherit' to copy from parent.
  * @param String  settings[style]     Style to apply to input form 'inherit' to copy from parent.
  * @param String  settings[select]    true or false, when true text is highlighted
  *             
  */

jQuery.fn.editable = function(target, settings) {

    /* prevent elem has no properties error */
    if (this.length == 0) { 
        return(this); 
    };
    
    settings = jQuery.extend({
      target      : target,
      name        : 'value',
      id          : 'id',
      type        : 'text',
      event       : 'dblclick',
      onblur      : 'cancel',
      loadtype    : 'POST',
      field_class : null
    }, settings);
      
    jQuery(this).attr('title', settings.tooltip);

    jQuery(this)[settings.event](function(e) {

        /* save this to self because this changes when scope changes */
        var self = this;

        /* prevent throwing an exeption if edit field is clicked again */
        if (self.editing) {
            return;
        }

        self.editing    = true;
        self.revert     = jQuery(self).html();
        self.innerHTML  = '';

        /* create the form object */
        var f = document.createElement('form');
        
        /* apply css or style or both */
        if (settings.cssclass) {
            if ('inherit' == settings.cssclass) {
                jQuery(f).attr('class', jQuery(self).attr('class'));
            } else {
                jQuery(f).attr('class', settings.cssclass);
            }
        }
        
        if (settings.style) {
            if ('inherit' == settings.style) {
                jQuery(f).attr('style', jQuery(self).attr('style'));
            } else {
                jQuery(f).attr('style', settings.style);
            }
        }
        
        /*  main input element */
        var i;
        switch (settings.type) {
            case 'textarea':
                i = document.createElement('textarea');
                break;
            case 'select':
                i = document.createElement('select');
                break;
            default:
                i = document.createElement('input');
                i.type  = settings.type;
                /* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */
                i.setAttribute('autocomplete','off');
        }
        
        if(settings.field_class) {
          $(i).addClass(settings.field_class);
        }
        
        /* maintain bc with 1.1.1 and earlier versions */        
        if (settings.getload) {
            settings.loadurl    = settings.getload;
            settings.loadtype = 'GET';
        } else if (settings.postload) {
            settings.loadurl    = settings.postload;
            settings.loadtype = 'POST';
        }

        /* set input content via POST, GET, given data or existing value */
        if (settings.loadurl) {
            var data = {};
            data[settings.id] = self.id;
            jQuery.ajax({
               type : settings.loadtype,
               url  : settings.loadurl,
               data : data,
               success: function(str) {
                  setInputContent(str);
               }
            });
        } else if (settings.data) {
            setInputContent(settings.data);
        } else { 
            setInputContent(self.revert);
        }

        i.name  = settings.name;
        f.appendChild(i);
        
        /** Buttons div **/
        var buttons = $(document.createElement('div'));
        buttons.addClass('editableButtons');
        
        /** Submit button **/
        var submit_button = $(document.createElement('button'));
        submit_button.attr('type', 'submit');
        submit_button.html(settings.submit ? settings.submit : '<span>Submit</span>');
        
        /** Cancel button **/
        var cancel_button = $(document.createElement('button'));
        cancel_button.attr('type', 'button');
        cancel_button.html(settings.cancel ? settings.cancel : '<span>Cancel</span>');
        cancel_button.click(function() {
          reset();
        });
        
        /** And build **/
        buttons.append(submit_button);
        buttons.append(' ');
        buttons.append(cancel_button);
        
        $(f).append(buttons);

        /* add created form to self */
        self.appendChild(f);

        i.focus();
        
        /* highlight input contents when requested */
        if (settings.select) {
            i.select();
        }
         
        /* discard changes if pressing esc */
        jQuery(i).keydown(function(e) {
            if (e.keyCode == 27) {
                e.preventDefault();
                reset();
            }
        });

        /* discard, submit or nothing with changes when clicking outside */
        /* do nothing is usable when navigating with tab */
        var t;
        if ('cancel' == settings.onblur) {
            jQuery(i).blur(function(e) {
                t = setTimeout(reset, 500)
            });
        /* TODO: does not currently work */
        } else if ('submit' == settings.onblur) {
            jQuery(i).blur(function(e) {
                jQuery(f).submit();
            });
        } else {
            jQuery(i).blur(function(e) {
              /* TODO: maybe something here */
            });
        }

        jQuery(f).submit(function(e) {

            if (t) { 
                clearTimeout(t);
            }

            /* do no submit */
            e.preventDefault(); 

            /* check if given target is function */
            if (Function == settings.target.constructor) {
                var str = settings.target.apply(self, [jQuery(i).val()]);
                self.innerHTML = str;
                self.editing = false;
            } else {
                /* add edited content and id of edited element to POST */           
                var p = {'submitted' : 'submitted'};
                p[i.name] = jQuery(i).val();
                p[settings.id] = self.id;

                /* show the saving indicator */
                jQuery(self).html(settings.indicator);
                jQuery.post(settings.target, p, function(str) {
                    self.innerHTML = str;
                    self.editing = false;
                });
            }
            return false;
        });

        function reset() {
            self.innerHTML = self.revert;
            self.editing   = false;
        };
        
        function setInputContent(str) {
            switch (settings.type) { 	 
                case 'select': 	 
                    if (String == str.constructor) { 	 
                        eval ("var json = " + str);
                        for (var key in json) {
                            if ('selected' == key) {
                                continue;
                            } 
                            o = document.createElement('option'); 	 
                            o.value = key;
                            var text = document.createTextNode(json[key]);
                            o.appendChild(text)
                            if (key == json['selected']) {
                                o.selected = true;
                            }
                            i.appendChild(o); 	 
                        }
                    } 	 
                    break; 	 
                default: 	 
                    i.value = str; 	 
                    break; 	 
            } 	 
        }

    });

    return(this);
}


/** File: javascript/jquery.uni-form.js **/

/**
 * Uniform module
 */
UniForm = function() {
  
  /**
   * Counter used for form ID generation
   *
   * @var integer
   */
  var form_counter = 0;
  
  /**
   * Forms that are initialized
   *
   * @var Object
   */
  var forms = {};
  
  /**
   * Supported validators
   *
   * @var Object
   */
  var validators = {
    
    /**
     * Check if value of specific field is present
     *
     * @param jQuery field
     * @param string caption
     */
    required : function(field, caption) {
      if(jQuery.trim(field.val()) == '') {
        return App.lang('Required');
      } else {
        return true;
      }
    },
    
    /**
     * Validate is value of given field is shorter than supported
     *
     * @param jQuery field
     * @param sting caption
     */
    validate_minlength : function(field, caption) {
      var min_length = 0;
      var classes = field.attr('class').split(' ');
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'validate_minlength') {
          if((classes[i + 1] != 'undefined') && !isNaN(classes[i + 1])) {
            min_length = parseInt(classes[i + 1]);
            break;
          } // if
        } // if
      } // for
      
      if((min_length > 0) && (field.val().length < min_length)) {
        return App.lang('Min :min characters long', { min : min_length });
      } else {
        return true;
      } // if
    },
    
    /**
     * Validate if field value is longer than allowed
     *
     * @param jQuery field
     * @param string caption
     */
    validate_maxlength : function(field, caption) {
      var max_length = 0;
      var classes = field.attr('class').split(' ');
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'validate_maxlength') {
          if((classes[i + 1] != 'undefined') && !isNaN(classes[i + 1])) {
            max_length = parseInt(classes[i + 1]);
            break;
          } // if
        } // if
      } // for
      
      if((max_length > 0) && (field.val().length > max_length)) {
        return App.lang('Max :max characters long', { max : max_length });
      } else {
        return true;
      } // if
    },
    
    /**
     * Make sure that field has same value as the value of target field
     *
     * @param jQuery field
     * @param string caption
     */
    validate_same_as : function(field, caption) {
      var classes = field.attr('class').split(' ');
      var target_field_name = '';
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'validate_same_as') {
          if(classes[i + 1] != 'undefined') {
            target_field_name = classes[i + 1];
            break;
          } // if
        } // if
      } // for
      
      if(target_field_name) {
        var target_field = jQuery('#' + target_field_name);
        if(target_field.length > 0) {
          var target_field_caption = field_caption($('#' + target_field_name));
          
          if(target_field.val() != field.val()) {
            return App.lang('Values do not match');
          } // if
        } // if
      } // if
      
      return true;
    },
    
    /**
     * Validate if provided value is valid email address
     *
     * @param jQuery field
     * @param string caption
     */
    validate_email : function(field, caption) {
      if(field.val().match(/^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$/i)) {
        return true;
      } else {
        return App.lang('Invalid address format');
      }
    },
    
    /**
     * Validate if provided value is valid URL
     *
     * @param jQuery field
     * @param string caption
     */
    validate_url : function(field, caption) {
      if(field.val().match(/^(http|https|ftp):\/\/(([A-Z0-9][A-Z0-9_-]*)(\.[A-Z0-9][A-Z0-9_-]*)+)(:(\d+))?\/?/i)) {
        return true;
      } else {
        return App.lang('Invalid URL format');
      }
    }, 
    
    /**
     * Number is only valid value (integers and floats)
     *
     * @param jQuery field
     * @param string caption
     */
    validate_number : function(field, caption) {
      if(field.val().match(/(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/)) {
        return true;
      } else {
        return App.lang('Value need to be a number');
      }
    },
    
    /**
     * Whole numbers are allowed
     *
     * @param jQuery field
     * @param string caption
     */
    validate_integer : function(field, caption) {
      if(field.val().match(/(^-?\d\d*$)/)) {
        return true;
      } else {
        return App.lang('Value need to be a whole number');
      }
    },
    
    /**
     * Letters only
     *
     * @param jQuery field
     * @param string caption
     */
    validate_alpha : function(field, caption) {
      if(field.val().match(/^[a-zA-Z]+$/)) {
        return true;
      } else {
        return App.lang('Value should contain only letters');
      }
    },
    
    /**
     * Letters and numbers
     *
     * @param jQuery field
     * @param string caption
     */
    validate_alphanum : function(field, caption) {
      if(field.val().match(/\W/)) {
        return App.lang('Value should contain only numbers and letters');
      } else {
        return true;
      }
    },
    
    /**
     * Callback validator
     *
     * Lets you define your own validators. Usage:
     *
     * <input name="myinput" class="validate_callback my_callback" />
     *
     * This will result in UniForm searching for window.my_callback funciton and 
     * executing it with field and caption arguments. Sample implementation:
     *
     * window.my_callback = function(field, caption) {
     *   if(field.val() == 'A51') {
     *     return true;
     *   } else {
     *     return caption + ' value should be "A51"!';
     *   }
     * }
     *
     * @param jQuery field
     * @param caption
     */
    validate_callback : function(field, caption) {
      var classes = field.attr('class').split(' ');
      var callback_function = '';
      
      for(var i = 0; i < classes.length; i++) {
        if(classes[i] == 'validate_callback') {
          if(classes[i + 1] != 'undefined') {
            callback_function = classes[i + 1];
            break;
          } // if
        } // if
      } // for
      
      if(window[callback_function] != 'undefined' && (typeof window[callback_function] == 'function')) {
        return window[callback_function](field, caption);
      } // if
      
      //return 'Failed to validate ' + caption + ' field. Validator function (' + callback_function + ') is not defined!';
      return true;
    }
    
  };
  
  /**
   * Go through form fields and validate their values
   *
   * @param jQuery for_form
   * @param boolean all_fields If true all fields will be validated. If not only 
   *   fields user focused will be validated
   * @param boolean
   */
  var validate_form = function(for_form, all_fields) {
    var result = true;
    
    forms[for_form.attr('id')]['is_valid'] = true;
    
    if(typeof(forms[for_form.attr('id')]['validation']) == 'object') {
      for(var field_name in forms[for_form.attr('id')]['validation']) {
      
        if(all_fields || forms[for_form.attr('id')]['focused_fields'][field_name]) {
          var field = forms[for_form.attr('id')]['validation'][field_name]['field'];
          var field_caption = forms[for_form.attr('id')]['validation'][field_name]['caption'];
          var field_validators = forms[for_form.attr('id')]['validation'][field_name]['validators'];
          
          for(var validator in field_validators) {
            var validation_result = validators[validator](field, field_caption, for_form);
        
            if(typeof(validation_result) == 'string') {
              if(forms[for_form.attr('id')]['show_errors']) {
                set_field_error(field, validation_result);
              } else {
                set_field_error(field, false);
              } // if
              
              result = false;
              break;
            } else {
              remove_field_error(field);
            } // if
          } // for
        } // if
        
      }  // if
    } // if
    
    forms[for_form.attr('id')]['is_valid'] = result;
    return result;
  };
  
  /**
   * Set field error
   *
   * @param jQuery for_field
   * @param string error_message
   * @return void
   */
  var set_field_error = function(for_field, error_message) {
    var holder = find_field_holder(for_field);
    if(holder === false) {
      return;
    } // if
    
    holder.removeClass('error').find('p.errorField').remove();
    if(error_message) {
      holder.addClass('error').prepend('<p class="errorField"><strong>' + error_message + '</strong></p>');
    } else {
      holder.addClass('error');
    } // if
  };

  /**
   * Remove error div for a given field
   *
   * @param jQuery for_field
   * @return void
   */
  var remove_field_error = function(for_field) {
    var holder = find_field_holder(for_field);
    if(holder === false) {
      return;
    } // if
    
    holder.removeClass('error').find('p.errorField').remove();
  };
  
  /**
   * Return holder DIV for a given field
   *
   * @param jQuery for_field
   * @return jQuery or false if holder is not found
   */
  var find_field_holder = function(for_field) {
    var parent = for_field.parent();
      
    while(typeof(parent) == 'object') {
      if((parent[0].nodeName == 'FORM') || (parent[0].nodeName == 'BODY')) {
        return false; // exit on FORM or BODY
      } // if
      
      if(parent[0].className.indexOf('ctrlHolder') >= 0) {
        return parent;
      } // if
      parent = jQuery(parent.parent());
    } // while
    
    return false;
  };
  
  /**
   * Mark a specific field as forcused
   *
   * @param jQuery for_form
   * @param jQuery for_field
   * @return void
   */
  var mark_as_focused = function(for_form, for_field) {
    remove_field_error(for_field);
    
    if(typeof(forms[for_form.attr('id')]['focused_fields'][for_field.attr('name')]) == 'undefined') {
      forms[for_form.attr('id')]['focused_fields'][for_field.attr('name')] = true;
    } // if
    
    var holder = find_field_holder(for_field);
    if(typeof(holder) == 'object') {
      if(holder.attr('class').indexOf('focused') == -1) {
        for_form.find('.' + 'focused').removeClass('focused'); // everything else should lose focus
        holder.addClass('focused'); // and we should focus this element
      } // if
    } // if
  };
  
  /**
   * Get caption for a given field (extract it from label)
   *
   * @param jQuery for_field
   * @return string
   */
  var field_caption = function(for_field) {
    var field_id = for_field.attr('id');
    if(field_id) {
      var label = jQuery('label[for=' + field_id + ']');
      if(typeof(label) == 'object') {
        var text = label.text();
        if(text.substr(text.length - 1, 1) == '*') {
          return text.substring(0, text.length - 1);
        } else {
          return text;
        } // if
      } // if
    } // if
    return 'Field';
  };
  
  /**
   * Prepare form ID for a given form if it is not already set by the user
   *
   * @param jQuery for_form
   * @return string
   */
  var get_form_id = function(for_form) {
    var form_id = for_form.attr('id');
      
    if(!form_id) {
      form_counter++;
      form_id = 'uniform_form_' + form_counter;
      for_form.attr('id', form_id);
    } // if
    
    return form_id;
  };
  
  /**
   * Attach onunload event that will show confirmation dialog if something is 
   * changed in the form
   *
   * @param jQuery for_form
   * @return void
   */
  var ask_on_leave = function(for_form) {
    var func = function() {
      // this fixes problems with serializing tinyMCEs
      if (App.isset(window.tinyMCE) && App.isset(window.tinyMCE.activeEditor)) {
        var mce_current_raw_content = tinyMCE.activeEditor.getContent({format : 'raw'});
        if ((mce_current_raw_content == '<br mce_bogus="1">') || (mce_current_raw_content=='<br>')) {
          window.tinyMCE.activeEditor.setContent('');
        } // if
      } // if
      window.tinyMCE.activeEditor.save();
      if(!forms[for_form.attr('id')]['ok_to_submit']) {
        if(for_form.serialize() != forms[for_form.attr('id')]['initial_data']) {
          return App.lang('All changes you have made to this page will be lost!');
        } // if
      } // if
    };
        
    var oldOnBeforeUnload = window.onbeforeunload;
    if(typeof(window.onbeforeunload) != 'function') {
      window.onbeforeunload = func;
    } else {
      window.onbeforeunload = function() {
        oldOnBeforeUnload();
        func();
      } // function
    } // if
  };
  
  /**
   * Public interface
   */
  return {
    
    /**
     * Initialize form
     *
     * @param jQuery form
     * @return void
     */
    init : function(form) {
      var fields = form.find('input, select, textarea');
      var form_id = get_form_id(form);
      
      // Register form
      forms[form_id] = {
        'form'           : form,
        'fields'         : fields,
        'initial_data'   : form.serialize(),
        'validation'     : {},
        'focused_fields' : {},
        'show_errors'    : form.attr('class').indexOf('showErrors') != -1,
        'is_valid'       : true,
        'ok_to_submit'   : false
      };
      
      // Attach on unload behavior
      if(form.attr('class').indexOf('askOnLeave') != -1) {
        ask_on_leave(form);
      } // if
      
      // Walk through defined validators and maku sure that they do their trick
      for(validator in validators) {
        form.find('.' + validator).each(function() {
          var field = $(this);
          var field_name = field.attr('name');
          
          if(typeof forms[form_id]['validation'][field_name] != 'object') {
            forms[form_id]['validation'][field_name] = {
              'field'      : field,
              'caption'    : field_caption(field),
              'validators' : {}
            };
          } // if
          
          forms[form_id]['validation'][field_name]['validators'][validator] = validators[validator];
        });
      } // for
      
      fields.focus(function() {
        mark_as_focused(form, $(this));
      }).blur(function() {
        validate_form(form, false);
      });
      
      // Form submission handler
      form.submit(function(event) {
        var is_valid = validate_form(form, true);
        if(is_valid) {
          forms[form.attr('id')]['ok_to_submit'] = true;
          return true;
        } else {
          return false;
        } // if
      });
      
      if(form.attr('class').indexOf('focusFirstField') != -1) {
        UniForm.focus_first_field(form);
      } // if
      
      // ctrlHolder toggler behaviour
      form.find('.ctrlHolderToggler').each(function () {
        var holder_toggler_button = $(this);
        var holder_parent = holder_toggler_button.parent();
        if (holder_parent.is('.ctrlHolderContainer')) {
          var holder_toggled = holder_parent.find('.ctrlHolderToggled');
          if (holder_toggled.length > 0) {
            holder_toggled.hide();
          } else {
            holder_parent.find(':not(.form_ctr_holder_toggler):not(script)').hide();
          } // if         
          holder_toggler_button.show();
          
          holder_toggler_button.click(function () {
            if (holder_toggled.length > 0) {
              holder_toggled.show();
            } else {
              holder_parent.find(':not(.form_ctr_holder_toggler):not(script)').show();
            } // if  
            $(this).remove();
            return false;
          });
        } else {
          holder_toggler_button.remove();
        } // if
      });      
      
    }, // init
    
    /**
     * Returns true if specific form is inited
     *
     * @param string form_id
     * @return boolean
     */
    is_inited : function(form_id) {
      return typeof(forms[form_id]) == 'object';
    },
    
    /**
     * Focust first field in a given form
     *
     * @param jQuery form
     * @return void
     */
    focus_first_field : function(form) {
      var first_field = form.find('input, select, textarea').get(0);
      if(first_field) {
        first_field.focus();
      } // if
    }, // focus_first_field
    
    /**
     * Clear error messages in a given form
     *
     * @param jQuery form
     * @return void
     */
    clear_error_messages : function(form) {
      form.find('.ctrlHolder.error').removeClass('error').find('p.errorField').remove();
    }, // clear_error_messages
    
    /**
     * Go through form and do the validation
     *
     * @param jQuery form
     * @param boolean all_fields
     * @return boolean
     */
    validate : function(form, all_fields) {
      return validate_form(form, all_fields);
    }, // validate
    
    /**
     * Returns true if form is valid
     *
     * If form is not validated true will be returned because this function does 
     * not know whether form is valid or not
     *
     * @param jQuery form
     * @return boolean
     */
    is_valid : function(form) {
      if(typeof(forms[form.attr('id')]) == 'object') {
        return forms[form.attr('id')]['is_valid'];
      } else {
        return true;
      } // if
    }, // is_valid
    
    /**
     * Mark given field as focused
     *
     * @param jQuery form
     * @param jQuery field
     * @return void
     */
    focus_field : function(form, field) {
      mark_as_focused(form, field);
    } // focus_field
    
  };
  
}();

/**
 * Register jQuery plugin
 */
jQuery.fn.uniform = function() {
  return this.each(function() {
    UniForm.init($(this));
  });
}; // uniform

/**
 * Focus first field in selected forms
 */
jQuery.fn.focusFirstField = function() {
  return this.each(function() {
    UniForm.focus_first_field($(this));
  });
}; //focusFirstField

/**
 * Clear error messages in selected forms
 */
jQuery.fn.clearErrorMessages = function() {
  return this.each(function() {
    UniForm.clear_error_messages($(this));
  });
};

/** File: javascript/jquery.checkboxes.js **/

/**
 * Build behavior that is required for a group of checkboxes, action select box 
 * and submit button to work as expected
 *
 * Settings:
 *
 * - master_checkbox_class - class of master checkbox
 * - slave_checkbox_class - class that slave checkboxe use
 * - select_action_class - class of select action box (needs to be SELECT element)
 * - submit_action_class - class of submit button box (needs to be BUTTON element)
 */
jQuery.fn.checkboxes = function(settings) {
  settings = jQuery.extend({
    master_checkbox_class : 'master_checkbox',
    slave_checkbox_class  : 'slave_checkbox'
  }, settings);
  
  return this.each(function() {
    var parent = $(this);
    
    var master_checkbox = parent.find('input.' + settings.master_checkbox_class);
    var slave_checkboxes = parent.find('input.' + settings.slave_checkbox_class);
    var select_action = jQuery('#' + parent.attr('id') + '_action');
    var submit_action = jQuery('#' + parent.attr('id') + '_submit');
    
    /**
     * Simple handler that is called when we change something to see if submit 
     * button needs to be enabled or disabled
     */
    var enabled_disable_submit_button = function() {
      var submit_enabled = (select_action.val() != '') && (parent.find('input.' + settings.slave_checkbox_class + ':checked').length > 0);
      if(submit_enabled) {
        submit_action.attr('disabled', '').removeClass('button_disabled');
      } else {
        submit_action.attr('disabled', 'submit').addClass('button_disabled');
      } // if
    } // enabled_disable_submit_button
    
    // execute button disable function on initialisation
    enabled_disable_submit_button();
    
    /**
     * Click on master checkbox checks or unchecks all slave checkboxes (plus 
     * submit disabled / enabled value needs to be refreshed)
     */
    master_checkbox.click(function() {
      if(this.checked) {
        slave_checkboxes.checkCheckboxes();
      } else {
        slave_checkboxes.uncheckCheckboxes();
      } // if
      enabled_disable_submit_button();
    });
    
    /**
     * Click on slave checkbox can change checked value of master checkbox
     */
    slave_checkboxes.click(function() {
      var all_checked = true;
      slave_checkboxes.each(function() {
        if(!this.checked) {
          all_checked = false;
        } // if
      });
      
      master_checkbox[0].checked = all_checked;
      enabled_disable_submit_button();
    });
    
    /**
     * Select box change also results in recheck whether submit button needs to 
     * be enabled or disabled
     */
    select_action
      .change(enabled_disable_submit_button)
      .click(enabled_disable_submit_button)
      .keypress(enabled_disable_submit_button);
    
  }); // each
};

/**
 * Mark all checkboxes as checked
 */
jQuery.fn.checkCheckboxes = function() {
  return this.each(function() {
    this.checked = true;
  });
};

/**
 * Mark all checkboxes as unchecked
 */
jQuery.fn.uncheckCheckboxes = function() {
  return this.each(function() {
    this.checked = false;
  });
};

/** File: javascript/jquery.datepicker.js **/

/**
 * Copyright (c) 2008 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 18 2008-12-23 23:37:34Z 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({}, $.fn.datePicker.defaults, 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;
			var weeksToDraw = Math.ceil(( (-1*firstDayOffset+1) + currentDate.getDaysInMonth() ) /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++<weeksToDraw) {
				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 String startDate The first date date can be selected.
 * @option String endDate The last date that can be selected.
 * @option Boolean inline Whether to create the datePicker as inline (e.g. always on the page) or as a model popup. Default is false (== modal popup)
 * @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({}, $.fn.datePicker.defaults, s);
			
			return this.each(
				function()
				{
					var $this = $(this);
					var alreadyExists = true;
					
					if (!this._dpId) {
						this._dpId = $.event.guid++;
						$.event._dpCache[this._dpId] = new DatePicker(this);
						alreadyExists = false;
					}
					
					if (s.inline) {
						s.createButton = false;
						s.displayClose = false;
						s.closeOnSelect = false;
						$this.empty();
					}
					
					var controller = $.event._dpCache[this._dpId];
					
					controller.init(s);
					
					if (!alreadyExists && s.createButton) {
						// create it!
						controller.button = $('<a href="#" class="dp-choose-date" title="' + $.dpText.TEXT_CHOOSE_DATE + '">' + $.dpText.TEXT_CHOOSE_DATE + '</a>')
								.bind(
									'click',
									function()
									{
									  var parents = $this.parents('.form_right_col');									  
									  if (($('body').innerWidth() < 1190) && (parents.length > 0)) {
									    $this.dpSetPosition($.dpConst.POS_TOP, $.dpConst.POS_RIGHT);
									  } else {
									    $this.dpSetPosition($.dpConst.POS_TOP, $.dpConst.POS_LEFT);
									  } // if
										$this.dpDisplay(this);
										this.blur();
										return false;
									}
								);
						$this.after(controller.button);
					}
					
					if (!alreadyExists && $this.is(':text')) {
						$this
							.bind(
								'dateSelected',
								function(e, selectedDate, $td)
								{
									this.value = selectedDate.asString();
								}
							).bind(
								'change',
								function()
								{
									if (this.value != '') {
										var d = Date.fromString(this.value);
										if (d) {
											controller.setSelected(d, true, true);
										}
									}
								}
							);
						if (s.clickInput) {
							$this.bind(
								'click',
								function()
								{
									$this.dpDisplay();
								}
							);
						}
						var d = Date.fromString(this.value);
						if (this.value != '' && d) {
							controller.setSelected(d, true, true);
						}
					}
					
					$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, true);
		},
/**
 * 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), true);
		},
/**
 * 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);
		},
/**
 * Closes the open date picker associated with this element.
 *
 * @type jQuery
 * @name dpClose
 * @cat plugins/datePicker
 * @author Kelvin Luck (http://www.kelvinluck.com/)
 *
 * @example $('.date-pick')
 *		.datePicker()
 *		.bind(
 *			'focus',
 *			function()
 *			{
 *				$(this).dpDisplay();
 *			}
 *		).bind(
 *			'blur',
 *			function()
 *			{
 *				$(this).dpClose();
 *			}
 *		);
 * @desc Creates a date picker and makes it appear when the relevant element is focused and disappear when it is blurred.
 **/
		dpClose : function()
		{
			return _w.call(this, '_closeCalendar', false, this[0]);
		},
		// 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, a4)
	{
		return this.each(
			function()
			{
				var c = _getController(this);
				if (c) {
					c[f](a1, a2, a3, a4);
				}
			}
		);
	};
	
	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		=	{};
		this.inline				=	null;
		this.context			=	'#dp-popup';
	};
	$.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);
				this.inline = s.inline;
				if (this.inline) {
					this.context = this.ele;
					this.display();
				}
			},
			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, rerender)
			{
				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 ((!m && !y) || (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;
				}
				var oldMonth = this.displayedMonth;
				var oldYear = this.displayedYear;
				this.displayedMonth = t.getMonth();
				this.displayedYear = t.getFullYear();

				if (rerender && (this.displayedMonth != oldMonth || this.displayedYear != oldYear))
				{
					this._rerenderCalendar();
					$(this.ele).trigger('dpMonthChanged', [this.displayedMonth, this.displayedYear]);
				}
			},
			setSelected : function(d, v, moveToMonth, dispatchEvents)
			{
				if (v == this.isSelected(d)) // this date is already un/selected
				{
					return;
				}
				if (this.selectMultiple == false) {
					this.selectedDates = {};
					$('td.selected', this.context).removeClass('selected');
				}
				if (moveToMonth && this.displayedMonth != d.getMonth()) {
					this.setDisplayedMonth(d.getMonth(), d.getFullYear(), true);
				}
				this.selectedDates[d.toString()] = v;
				
				var selectorString = 'td.';
				selectorString += d.getMonth() == this.displayedMonth ? 'current-month' : 'other-month';
				selectorString += ':contains("' + d.getDate() + '")';
				var $td;
				$(selectorString, this.ele).each(
					function()
					{
						if ($(this).text() == d.getDate())
						{
							$td = $(this);
							$td[v ? 'addClass' : 'removeClass']('selected');
						}
					}
				);
				
				if (dispatchEvents)
				{
					var s = this.isSelected(d);
					$e = $(this.ele);
					var dClone = Date.fromString(d.asString());
					$e.trigger('dateSelected', [dClone, $td, s]);
					$e.trigger('change');
				}
			},
			isSelected : function(d)
			{
				return this.selectedDates[d.toString()];
			},
			getSelected : function()
			{
				var r = [];
				for(s in this.selectedDates) {
					if (this.selectedDates[s] == true) {
						r.push(Date.parse(s));
					}
				}
				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 $createIn;
				var attrs;
				var attrsCalendarHolder;
				var cssRules;
				
				if (c.inline) {
					$createIn = $(this.ele);
					attrs = {
						'id'		:	'calendar-' + this.ele._dpId,
						'className'	:	'dp-popup dp-popup-inline'
					};
					cssRules = {
					};
				} else {
					$createIn = $('body');
					attrs = {
						'id'		:	'dp-popup',
						'className'	:	'dp-popup'
					};
					cssRules = {
						'top'	:	eleOffset.top + c.verticalOffset,
						'left'	:	eleOffset.left + c.horizontalOffset
					};
					
					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);
				}
				
				
				$createIn
					.append(
						$('<div></div>')
							.attr(attrs)
							.css(cssRules)
							.append(
								$('<h2></h2>'),
								$('<div class="dp-nav-prev"></div>')
									.append(
										$('<a class="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 class="dp-nav-prev-month" href="#" title="' + $.dpText.TEXT_PREV_MONTH + '">&lt;</a>')
											.bind(
												'click',
												function()
												{
													return c._displayNewMonth.call(c, this, -1, 0);
												}
											)
									),
								$('<div class="dp-nav-next"></div>')
									.append(
										$('<a class="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 class="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('className', 'dp-calendar')
							)
							.bgIframe()
						);
					
				var $pop = this.inline ? $('.dp-popup', this.context) : $('#dp-popup');
				
				if (this.showYearNavigation == false) {
					$('.dp-nav-prev-year, .dp-nav-next-year', c.context).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();
				
				$(this.ele).trigger('dpDisplayed', $pop);
				
				if (!c.inline) {
					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);
					}
					$(document).bind('mousedown', this._checkMouse);
				}
			},
			setRenderCallback : function(a)
			{
				if (a == null) return;
				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, false, true);
							if (c.closeOnSelect) {
								c._closeCalendar();
							}
						}
					}
				);
				
				if (c.isSelected(d)) {
					$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, true);
				}
				ele.blur();
				return false;
			},
			_rerenderCalendar : function()
			{
				this._clearCalendar();
				this._renderCalendar();
			},
			_renderCalendar : function()
			{
				// set the title...
				$('h2', this.context).html(Date.monthNames[this.displayedMonth] + ' ' + this.displayedYear);
				
				// render the calendar...
				$('.dp-calendar', this.context).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', this.context).addClass('disabled');
					$('.dp-nav-prev-month', this.context).addClass('disabled');
					$('.dp-calendar td.other-month', this.context).each(
						function()
						{
							var $this = $(this);
							if (Number($this.text()) > 20) {
								$this.addClass('disabled');
							}
						}
					);
					var d = this.startDate.getDate();
					$('.dp-calendar td.current-month', this.context).each(
						function()
						{
							var $this = $(this);
							if (Number($this.text()) < d) {
								$this.addClass('disabled');
							}
						}
					);
				} else {
					$('.dp-nav-prev-year', this.context).removeClass('disabled');
					$('.dp-nav-prev-month', this.context).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', this.context).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', this.context).addClass('disabled');
					$('.dp-nav-next-month', this.context).addClass('disabled');
					$('.dp-calendar td.other-month', this.context).each(
						function()
						{
							var $this = $(this);
							if (Number($this.text()) < 14) {
								$this.addClass('disabled');
							}
						}
					);
					var d = this.endDate.getDate();
					$('.dp-calendar td.current-month', this.context).each(
						function()
						{
							var $this = $(this);
							if (Number($this.text()) > d) {
								$this.addClass('disabled');
							}
						}
					);
				} else {
					$('.dp-nav-next-year', this.context).removeClass('disabled');
					$('.dp-nav-next-month', this.context).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', this.context).each(
								function()
								{
									var $this = $(this);
									if (Number($this.text()) > d) {
										$this.addClass('disabled');
									}
								}
							);
						}
					}
				}
			},
			_closeCalendar : function(programatic, ele)
			{
				if (!ele || ele == this.ele)
				{
					$(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', this.context).unbind();
				$('.dp-calendar', this.context).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 18 2008-12-23 23:37:34Z kelvin.luck $';

	$.fn.datePicker.defaults = {
		month				: undefined,
		year				: undefined,
		showHeader			: $.dpConst.SHOW_HEADER_SHORT,
		startDate			: undefined,
		endDate				: undefined,
		inline				: false,
		renderCallback		: null,
		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'
	};

	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);


/** File: javascript/jquery.scrollTo.js **/

/**
 * jQuery.ScrollTo
 * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.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.
 * Date: 2/19/2008
 *
 * @projectDescription Easy element scrolling using jQuery.
 * Tested with jQuery 1.2.1. On FF 2.0.0.11, IE 6, Opera 9.22 and Safari 3 beta. on Windows.
 *
 * @author Ariel Flesler
 * @version 1.3.3
 *
 * @id jQuery.scrollTo
 * @id jQuery.fn.scrollTo
 * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
 *	  The different options for target are:
 *		- A number position (will be applied to all axes).
 *		- A string position ('44', '100px', '+=90', etc ) will be applied to all axes
 *		- A jQuery/DOM element ( logically, child of the element to scroll )
 *		- A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
 *		- A hash { top:x, left:y }, x and y can be any kind of number/string like above.
 * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
 * @param {Object} settings Hash of settings, optional.
 *	 @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
 *	 @option {Number} duration The OVERALL length of the animation.
 *	 @option {String} easing The easing method for the animation.
 *	 @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
 *	 @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
 *	 @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
 *	 @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
 *	 @option {Function} onAfter Function to be called after the scrolling ends. 
 *	 @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @example $('div').scrollTo( 340 );
 *
 * @example $('div').scrollTo( '+=340px', { axis:'y' } );
 *
 * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
 *
 * @example var second_child = document.getElementById('container').firstChild.nextSibling;
 *			$('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
 *				alert('scrolled!!');																   
 *			}});
 *
 * @example $('div').scrollTo( { top: 300, left:'+=200' }, { offset:-20 } );
 *
 * Notes:
 *  - jQuery.scrollTo will make the whole window scroll, it accepts the same arguments as jQuery.fn.scrollTo.
 *	- If you are interested in animated anchor navigation, check http://jquery.com/plugins/project/LocalScroll.
 *	- The options margin, offset and over are ignored, if the target is not a jQuery object or a DOM element.
 *	- The option 'queue' won't be taken into account, if only 1 axis is given.
 */
;(function( $ ){

	var $scrollTo = $.scrollTo = function( target, duration, settings ){
		$scrollTo.window().scrollTo( target, duration, settings );
	};

	$scrollTo.defaults = {
		axis:'y',
		duration:1
	};

	//returns the element that needs to be animated to scroll the window
	$scrollTo.window = function(){
		return $( $.browser.safari ? 'body' : 'html' );
	};

	$.fn.scrollTo = function( target, duration, settings ){
		if( typeof duration == 'object' ){
			settings = duration;
			duration = 0;
		}
		settings = $.extend( {}, $scrollTo.defaults, settings );
		duration = duration || settings.speed || settings.duration;//speed is still recognized for backwards compatibility
		settings.queue = settings.queue && settings.axis.length > 1;//make sure the settings are given right
		if( settings.queue )
			duration /= 2;//let's keep the overall speed, the same.
		settings.offset = both( settings.offset );
		settings.over = both( settings.over );

		return this.each(function(){
			var elem = this, $elem = $(elem),
				t = target, toff, attr = {},
				win = $elem.is('html,body');
			switch( typeof t ){
				case 'number'://will pass the regex
				case 'string':
					if( /^([+-]=)?\d+(px)?$/.test(t) ){
						t = both( t );
						break;//we are done
					}
					t = $(t,this);// relative selector, no break!
				case 'object':
					if( t.is || t.style )//DOM/jQuery
						toff = (t = $(t)).offset();//get the real position of the target 
			}
			$.each( settings.axis.split(''), function( i, axis ){
				var Pos	= axis == 'x' ? 'Left' : 'Top',
					pos = Pos.toLowerCase(),
					key = 'scroll' + Pos,
					act = elem[key],
					Dim = axis == 'x' ? 'Width' : 'Height',
					dim = Dim.toLowerCase();

				if( toff ){//jQuery/DOM
					attr[key] = toff[pos] + ( win ? 0 : act - $elem.offset()[pos] );

					if( settings.margin ){//if it's a dom element, reduce the margin
						attr[key] -= parseInt(t.css('margin'+Pos)) || 0;
						attr[key] -= parseInt(t.css('border'+Pos+'Width')) || 0;
					}
					
					attr[key] += settings.offset[pos] || 0;//add/deduct the offset
					
					if( settings.over[pos] )//scroll to a fraction of its width/height
						attr[key] += t[dim]() * settings.over[pos];
				}else
					attr[key] = t[pos];//remove the unnecesary 'px'

				if( /^\d+$/.test(attr[key]) )//number or 'number'
					attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(Dim) );//check the limits

				if( !i && settings.queue ){//queueing each axis is required					
					if( act != attr[key] )//don't waste time animating, if there's no need.
						animate( settings.onAfterFirst );//intermediate animation
					delete attr[key];//don't animate this axis again in the next iteration.
				}
			});			
			animate( settings.onAfter );			

			function animate( callback ){
				$elem.animate( attr, duration, settings.easing, callback && function(){
					callback.call(this, target);
				});
			};
			function max( Dim ){
				var el = win ? $.browser.opera ? document.body : document.documentElement : elem;
				return el['scroll'+Dim] - el['client'+Dim];
			};
		});
	};

	function both( val ){
		return typeof val == 'object' ? val : { top:val, left:val };
	};

})( jQuery );

/** File: javascript/jquery.scrollTo.js **/

/**
 * jQuery.ScrollTo
 * Copyright (c) 2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.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.
 * Date: 2/19/2008
 *
 * @projectDescription Easy element scrolling using jQuery.
 * Tested with jQuery 1.2.1. On FF 2.0.0.11, IE 6, Opera 9.22 and Safari 3 beta. on Windows.
 *
 * @author Ariel Flesler
 * @version 1.3.3
 *
 * @id jQuery.scrollTo
 * @id jQuery.fn.scrollTo
 * @param {String, Number, DOMElement, jQuery, Object} target Where to scroll the matched elements.
 *	  The different options for target are:
 *		- A number position (will be applied to all axes).
 *		- A string position ('44', '100px', '+=90', etc ) will be applied to all axes
 *		- A jQuery/DOM element ( logically, child of the element to scroll )
 *		- A string selector, that will be relative to the element to scroll ( 'li:eq(2)', etc )
 *		- A hash { top:x, left:y }, x and y can be any kind of number/string like above.
 * @param {Number} duration The OVERALL length of the animation, this argument can be the settings object instead.
 * @param {Object} settings Hash of settings, optional.
 *	 @option {String} axis Which axis must be scrolled, use 'x', 'y', 'xy' or 'yx'.
 *	 @option {Number} duration The OVERALL length of the animation.
 *	 @option {String} easing The easing method for the animation.
 *	 @option {Boolean} margin If true, the margin of the target element will be deducted from the final position.
 *	 @option {Object, Number} offset Add/deduct from the end position. One number for both axes or { top:x, left:y }.
 *	 @option {Object, Number} over Add/deduct the height/width multiplied by 'over', can be { top:x, left:y } when using both axes.
 *	 @option {Boolean} queue If true, and both axis are given, the 2nd axis will only be animated after the first one ends.
 *	 @option {Function} onAfter Function to be called after the scrolling ends. 
 *	 @option {Function} onAfterFirst If queuing is activated, this function will be called after the first scrolling ends.
 * @return {jQuery} Returns the same jQuery object, for chaining.
 *
 * @example $('div').scrollTo( 340 );
 *
 * @example $('div').scrollTo( '+=340px', { axis:'y' } );
 *
 * @example $('div').scrollTo( 'p.paragraph:eq(2)', 500, { easing:'swing', queue:true, axis:'xy' } );
 *
 * @example var second_child = document.getElementById('container').firstChild.nextSibling;
 *			$('#container').scrollTo( second_child, { duration:500, axis:'x', onAfter:function(){
 *				alert('scrolled!!');																   
 *			}});
 *
 * @example $('div').scrollTo( { top: 300, left:'+=200' }, { offset:-20 } );
 *
 * Notes:
 *  - jQuery.scrollTo will make the whole window scroll, it accepts the same arguments as jQuery.fn.scrollTo.
 *	- If you are interested in animated anchor navigation, check http://jquery.com/plugins/project/LocalScroll.
 *	- The options margin, offset and over are ignored, if the target is not a jQuery object or a DOM element.
 *	- The option 'queue' won't be taken into account, if only 1 axis is given.
 */
;(function( $ ){

	var $scrollTo = $.scrollTo = function( target, duration, settings ){
		$scrollTo.window().scrollTo( target, duration, settings );
	};

	$scrollTo.defaults = {
		axis:'y',
		duration:1
	};

	//returns the element that needs to be animated to scroll the window
	$scrollTo.window = function(){
		return $( $.browser.safari ? 'body' : 'html' );
	};

	$.fn.scrollTo = function( target, duration, settings ){
		if( typeof duration == 'object' ){
			settings = duration;
			duration = 0;
		}
		settings = $.extend( {}, $scrollTo.defaults, settings );
		duration = duration || settings.speed || settings.duration;//speed is still recognized for backwards compatibility
		settings.queue = settings.queue && settings.axis.length > 1;//make sure the settings are given right
		if( settings.queue )
			duration /= 2;//let's keep the overall speed, the same.
		settings.offset = both( settings.offset );
		settings.over = both( settings.over );

		return this.each(function(){
			var elem = this, $elem = $(elem),
				t = target, toff, attr = {},
				win = $elem.is('html,body');
			switch( typeof t ){
				case 'number'://will pass the regex
				case 'string':
					if( /^([+-]=)?\d+(px)?$/.test(t) ){
						t = both( t );
						break;//we are done
					}
					t = $(t,this);// relative selector, no break!
				case 'object':
					if( t.is || t.style )//DOM/jQuery
						toff = (t = $(t)).offset();//get the real position of the target 
			}
			$.each( settings.axis.split(''), function( i, axis ){
				var Pos	= axis == 'x' ? 'Left' : 'Top',
					pos = Pos.toLowerCase(),
					key = 'scroll' + Pos,
					act = elem[key],
					Dim = axis == 'x' ? 'Width' : 'Height',
					dim = Dim.toLowerCase();

				if( toff ){//jQuery/DOM
					attr[key] = toff[pos] + ( win ? 0 : act - $elem.offset()[pos] );

					if( settings.margin ){//if it's a dom element, reduce the margin
						attr[key] -= parseInt(t.css('margin'+Pos)) || 0;
						attr[key] -= parseInt(t.css('border'+Pos+'Width')) || 0;
					}
					
					attr[key] += settings.offset[pos] || 0;//add/deduct the offset
					
					if( settings.over[pos] )//scroll to a fraction of its width/height
						attr[key] += t[dim]() * settings.over[pos];
				}else
					attr[key] = t[pos];//remove the unnecesary 'px'

				if( /^\d+$/.test(attr[key]) )//number or 'number'
					attr[key] = attr[key] <= 0 ? 0 : Math.min( attr[key], max(Dim) );//check the limits

				if( !i && settings.queue ){//queueing each axis is required					
					if( act != attr[key] )//don't waste time animating, if there's no need.
						animate( settings.onAfterFirst );//intermediate animation
					delete attr[key];//don't animate this axis again in the next iteration.
				}
			});			
			animate( settings.onAfter );			

			function animate( callback ){
				$elem.animate( attr, duration, settings.easing, callback && function(){
					callback.call(this, target);
				});
			};
			function max( Dim ){
				var el = win ? $.browser.opera ? document.body : document.documentElement : elem;
				return el['scroll'+Dim] - el['client'+Dim];
			};
		});
	};

	function both( val ){
		return typeof val == 'object' ? val : { top:val, left:val };
	};

})( jQuery );

/** File: javascript/jquery.scalebigimages.js **/

/**
 * Walk through images in a wrapper and make sure that they are not wider than 
 * the wrapper itself
 */
jQuery.fn.scaleBigImages = function() {
  return this.each(function() {
    var wrapper = $(this);
    var wrapper_width = wrapper.width();
    
    wrapper.find('img').each(function() {
      var image = $(this);
      
      image.load(function () {
        var width = image.width();
        
        if(width > wrapper_width) {
          if (image.parents('a').length == 0) {
            var link = $('<a></a>')
              .attr('href', image.attr('src'))
              .attr('title', App.lang('Open Full Size (:widthx:heightpx)', { 'width' : image.width(), 'height' : image.height() }))
              .click(function() {
                window.open($(this).attr('href'), App.lang('Full Size Image'));
                return false;
              });
            
            image.after(link).appendTo(link);
          } // if
          
          var scale = wrapper_width / width;
          
          image.css('height', Math.round(image.height() * scale));
          image.css('width', wrapper_width);
        } // if
      });
    });
  });
};

/** File: javascript/jquery.ui.js **/

/*
 * jQuery UI 1.7
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI
 */jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla&&(parseFloat(c.browser.version)<1.9);c.ui={version:"1.7",plugin:{add:function(k,l,n){var m=c.ui[k].prototype;for(var j in n){m.plugins[j]=m.plugins[j]||[];m.plugins[j].push([l,n[j]])}},call:function(j,l,k){var n=j.plugins[l];if(!n||!j.element[0].parentNode){return}for(var m=0;m<n.length;m++){if(j.options[n[m][0]]){n[m][1].apply(j.element,k)}}}},contains:function(k,j){return document.compareDocumentPosition?k.compareDocumentPosition(j)&16:k!==j&&k.contains(j)},hasScroll:function(m,k){if(c(m).css("overflow")=="hidden"){return false}var j=(k&&k=="left")?"scrollLeft":"scrollTop",l=false;if(m[j]>0){return true}m[j]=1;l=(m[j]>0);m[j]=0;return l},isOverAxis:function(k,j,l){return(k>j)&&(k<(j+l))},isOver:function(o,k,n,m,j,l){return c.ui.isOverAxis(o,n,j)&&c.ui.isOverAxis(k,m,l)},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(d){var f=c.attr,e=c.fn.removeAttr,h="http://www.w3.org/2005/07/aaa",a=/^aria-/,b=/^wairole:/;c.attr=function(k,j,l){var m=l!==undefined;return(j=="role"?(m?f.call(this,k,j,"wairole:"+l):(f.apply(this,arguments)||"").replace(b,"")):(a.test(j)?(m?k.setAttributeNS(h,j.replace(a,"aaa:"),l):f.call(this,k,j.replace(a,"aaa:"))):f.apply(this,arguments)))};c.fn.removeAttr=function(j){return(a.test(j)?this.each(function(){this.removeAttributeNS(h,j.replace(a,""))}):e.call(this,j))}}c.fn.extend({remove:function(){c("*",this).add(this).each(function(){c(this).triggerHandler("remove")});return i.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","").unbind("selectstart.ui")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})},scrollParent:function(){var j;if((c.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){j=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(c.curCSS(this,"position",1))&&(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}else{j=this.parents().filter(function(){return(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!j.length?c(document):j}});c.extend(c.expr[":"],{data:function(l,k,j){return !!c.data(l,j[3])},focusable:function(k){var l=k.nodeName.toLowerCase(),j=c.attr(k,"tabindex");return(/input|select|textarea|button|object/.test(l)?!k.disabled:"a"==l||"area"==l?k.href||!isNaN(j):!isNaN(j))&&!c(k)["area"==l?"parents":"closest"](":hidden").length},tabbable:function(k){var j=c.attr(k,"tabindex");return(isNaN(j)||j>=0)&&c(k).is(":focusable")}});function g(m,n,o,l){function k(q){var p=c[m][n][q]||[];return(typeof p=="string"?p.split(/,?\s+/):p)}var j=k("getter");if(l.length==1&&typeof l[0]=="string"){j=j.concat(k("getterSetter"))}return(c.inArray(o,j)!=-1)}c.widget=function(k,j){var l=k.split(".")[0];k=k.split(".")[1];c.fn[k]=function(p){var n=(typeof p=="string"),o=Array.prototype.slice.call(arguments,1);if(n&&p.substring(0,1)=="_"){return this}if(n&&g(l,k,p,o)){var m=c.data(this[0],k);return(m?m[p].apply(m,o):undefined)}return this.each(function(){var q=c.data(this,k);(!q&&!n&&c.data(this,k,new c[l][k](this,p))._init());(q&&n&&c.isFunction(q[p])&&q[p].apply(q,o))})};c[l]=c[l]||{};c[l][k]=function(o,n){var m=this;this.namespace=l;this.widgetName=k;this.widgetEventPrefix=c[l][k].eventPrefix||k;this.widgetBaseClass=l+"-"+k;this.options=c.extend({},c.widget.defaults,c[l][k].defaults,c.metadata&&c.metadata.get(o)[k],n);this.element=c(o).bind("setData."+k,function(q,p,r){if(q.target==o){return m._setData(p,r)}}).bind("getData."+k,function(q,p){if(q.target==o){return m._getData(p)}}).bind("remove",function(){return m.destroy()})};c[l][k].prototype=c.extend({},c.widget.prototype,j);c[l][k].getterSetter="option"};c.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled")},option:function(l,m){var k=l,j=this;if(typeof l=="string"){if(m===undefined){return this._getData(l)}k={};k[l]=m}c.each(k,function(n,o){j._setData(n,o)})},_getData:function(j){return this.options[j]},_setData:function(j,k){this.options[j]=k;if(j=="disabled"){this.element[k?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",k)}},enable:function(){this._setData("disabled",false)},disable:function(){this._setData("disabled",true)},_trigger:function(l,m,n){var p=this.options[l],j=(l==this.widgetEventPrefix?l:this.widgetEventPrefix+l);m=c.Event(m);m.type=j;if(m.originalEvent){for(var k=c.event.props.length,o;k;){o=c.event.props[--k];m[o]=m.originalEvent[o]}}this.element.trigger(m,n);return !(c.isFunction(p)&&p.call(this.element[0],m,n)===false||m.isDefaultPrevented())}};c.widget.defaults={disabled:false};c.ui.mouse={_mouseInit:function(){var j=this;this.element.bind("mousedown."+this.widgetName,function(k){return j._mouseDown(k)}).bind("click."+this.widgetName,function(k){if(j._preventClickEvent){j._preventClickEvent=false;k.stopImmediatePropagation();return false}});if(c.browser.msie){this._mouseUnselectable=this.element.attr("unselectable");this.element.attr("unselectable","on")}this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);(c.browser.msie&&this.element.attr("unselectable",this._mouseUnselectable))},_mouseDown:function(l){l.originalEvent=l.originalEvent||{};if(l.originalEvent.mouseHandled){return}(this._mouseStarted&&this._mouseUp(l));this._mouseDownEvent=l;var k=this,m=(l.which==1),j=(typeof this.options.cancel=="string"?c(l.target).parents().add(l.target).filter(this.options.cancel).length:false);if(!m||j||!this._mouseCapture(l)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){k.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(l)&&this._mouseDelayMet(l)){this._mouseStarted=(this._mouseStart(l)!==false);if(!this._mouseStarted){l.preventDefault();return true}}this._mouseMoveDelegate=function(n){return k._mouseMove(n)};this._mouseUpDelegate=function(n){return k._mouseUp(n)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);(c.browser.safari||l.preventDefault());l.originalEvent.mouseHandled=true;return true},_mouseMove:function(j){if(c.browser.msie&&!j.button){return this._mouseUp(j)}if(this._mouseStarted){this._mouseDrag(j);return j.preventDefault()}if(this._mouseDistanceMet(j)&&this._mouseDelayMet(j)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,j)!==false);(this._mouseStarted?this._mouseDrag(j):this._mouseUp(j))}return !this._mouseStarted},_mouseUp:function(j){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(j.target==this._mouseDownEvent.target);this._mouseStop(j)}return false},_mouseDistanceMet:function(j){return(Math.max(Math.abs(this._mouseDownEvent.pageX-j.pageX),Math.abs(this._mouseDownEvent.pageY-j.pageY))>=this.options.distance)},_mouseDelayMet:function(j){return this.mouseDelayMet},_mouseStart:function(j){},_mouseDrag:function(j){},_mouseStop:function(j){},_mouseCapture:function(j){return true}};c.ui.mouse.defaults={cancel:null,distance:1,delay:0}})(jQuery);;/*
 * jQuery UI Draggable 1.7
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Draggables
 *
 * Depends:
 *	ui.core.js
 */(function(a){a.widget("ui.draggable",a.extend({},a.ui.mouse,{_init:function(){if(this.options.helper=="original"&&!(/^(?:r|a|f)/).test(this.element.css("position"))){this.element[0].style.position="relative"}(this.options.addClasses&&this.element.addClass("ui-draggable"));(this.options.disabled&&this.element.addClass("ui-draggable-disabled"));this._mouseInit()},destroy:function(){if(!this.element.data("draggable")){return}this.element.removeData("draggable").unbind(".draggable").removeClass("ui-draggable ui-draggable-dragging ui-draggable-disabled");this._mouseDestroy()},_mouseCapture:function(b){var c=this.options;if(this.helper||c.disabled||a(b.target).is(".ui-resizable-handle")){return false}this.handle=this._getHandle(b);if(!this.handle){return false}return true},_mouseStart:function(b){var c=this.options;this.helper=this._createHelper(b);this._cacheHelperProportions();if(a.ui.ddmanager){a.ui.ddmanager.current=this}this._cacheMargins();this.cssPosition=this.helper.css("position");this.scrollParent=this.helper.scrollParent();this.offset=this.element.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};a.extend(this.offset,{click:{left:b.pageX-this.offset.left,top:b.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(b);this.originalPageX=b.pageX;this.originalPageY=b.pageY;if(c.cursorAt){this._adjustOffsetFromHelper(c.cursorAt)}if(c.containment){this._setContainment()}this._trigger("start",b);this._cacheHelperProportions();if(a.ui.ddmanager&&!c.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,b)}this.helper.addClass("ui-draggable-dragging");this._mouseDrag(b,true);return true},_mouseDrag:function(b,d){this.position=this._generatePosition(b);this.positionAbs=this._convertPositionTo("absolute");if(!d){var c=this._uiHash();this._trigger("drag",b,c);this.position=c.position}if(!this.options.axis||this.options.axis!="y"){this.helper[0].style.left=this.position.left+"px"}if(!this.options.axis||this.options.axis!="x"){this.helper[0].style.top=this.position.top+"px"}if(a.ui.ddmanager){a.ui.ddmanager.drag(this,b)}return false},_mouseStop:function(c){var d=false;if(a.ui.ddmanager&&!this.options.dropBehaviour){d=a.ui.ddmanager.drop(this,c)}if(this.dropped){d=this.dropped;this.dropped=false}if((this.options.revert=="invalid"&&!d)||(this.options.revert=="valid"&&d)||this.options.revert===true||(a.isFunction(this.options.revert)&&this.options.revert.call(this.element,d))){var b=this;a(this.helper).animate(this.originalPosition,parseInt(this.options.revertDuration,10),function(){b._trigger("stop",c);b._clear()})}else{this._trigger("stop",c);this._clear()}return false},_getHandle:function(b){var c=!this.options.handle||!a(this.options.handle,this.element).length?true:false;a(this.options.handle,this.element).find("*").andSelf().each(function(){if(this==b.target){c=true}});return c},_createHelper:function(c){var d=this.options;var b=a.isFunction(d.helper)?a(d.helper.apply(this.element[0],[c])):(d.helper=="clone"?this.element.clone():this.element);if(!b.parents("body").length){b.appendTo((d.appendTo=="parent"?this.element[0].parentNode:d.appendTo))}if(b[0]!=this.element[0]&&!(/(fixed|absolute)/).test(b.css("position"))){b.css("position","absolute")}return b},_adjustOffsetFromHelper:function(b){if(b.left!=undefined){this.offset.click.left=b.left+this.margins.left}if(b.right!=undefined){this.offset.click.left=this.helperProportions.width-b.right+this.margins.left}if(b.top!=undefined){this.offset.click.top=b.top+this.margins.top}if(b.bottom!=undefined){this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top}},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){b.left+=this.scrollParent.scrollLeft();b.top+=this.scrollParent.scrollTop()}if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)){b={top:0,left:0}}return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var b=this.element.position();return{top:b.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:b.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else{return{top:0,left:0}}},_cacheMargins:function(){this.margins={left:(parseInt(this.element.css("marginLeft"),10)||0),top:(parseInt(this.element.css("marginTop"),10)||0)}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e=this.options;if(e.containment=="parent"){e.containment=this.helper[0].parentNode}if(e.containment=="document"||e.containment=="window"){this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(e.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(e.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]}if(!(/^(document|window|parent)$/).test(e.containment)&&e.containment.constructor!=Array){var c=a(e.containment)[0];if(!c){return}var d=a(e.containment).offset();var b=(a(c).css("overflow")!="hidden");this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(b?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(b?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}else{if(e.containment.constructor==Array){this.containment=e.containment}}},_convertPositionTo:function(f,h){if(!h){h=this.position}var c=f=="absolute"?1:-1;var e=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=(/(html|body)/i).test(b[0].tagName);return{top:(h.top+this.offset.relative.top*c+this.offset.parent.top*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(g?0:b.scrollTop()))*c)),left:(h.left+this.offset.relative.left*c+this.offset.parent.left*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:b.scrollLeft())*c))}},_generatePosition:function(e){var h=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,i=(/(html|body)/i).test(b[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset()}var d=e.pageX;var c=e.pageY;if(this.originalPosition){if(this.containment){if(e.pageX-this.offset.click.left<this.containment[0]){d=this.containment[0]+this.offset.click.left}if(e.pageY-this.offset.click.top<this.containment[1]){c=this.containment[1]+this.offset.click.top}if(e.pageX-this.offset.click.left>this.containment[2]){d=this.containment[2]+this.offset.click.left}if(e.pageY-this.offset.click.top>this.containment[3]){c=this.containment[3]+this.offset.click.top}}if(h.grid){var g=this.originalPageY+Math.round((c-this.originalPageY)/h.grid[1])*h.grid[1];c=this.containment?(!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:(!(g-this.offset.click.top<this.containment[1])?g-h.grid[1]:g+h.grid[1])):g;var f=this.originalPageX+Math.round((d-this.originalPageX)/h.grid[0])*h.grid[0];d=this.containment?(!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:(!(f-this.offset.click.left<this.containment[0])?f-h.grid[0]:f+h.grid[0])):f}}return{top:(c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(i?0:b.scrollTop())))),left:(d-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:b.scrollLeft())))}},_clear:function(){this.helper.removeClass("ui-draggable-dragging");if(this.helper[0]!=this.element[0]&&!this.cancelHelperRemoval){this.helper.remove()}this.helper=null;this.cancelHelperRemoval=false},_trigger:function(b,c,d){d=d||this._uiHash();a.ui.plugin.call(this,b,[c,d]);if(b=="drag"){this.positionAbs=this._convertPositionTo("absolute")}return a.widget.prototype._trigger.call(this,b,c,d)},plugins:{},_uiHash:function(b){return{helper:this.helper,position:this.position,absolutePosition:this.positionAbs,offset:this.positionAbs}}}));a.extend(a.ui.draggable,{version:"1.7",eventPrefix:"drag",defaults:{addClasses:true,appendTo:"parent",axis:false,cancel:":input,option",connectToSortable:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,grid:false,handle:false,helper:"original",iframeFix:false,opacity:false,refreshPositions:false,revert:false,revertDuration:500,scope:"default",scroll:true,scrollSensitivity:20,scrollSpeed:20,snap:false,snapMode:"both",snapTolerance:20,stack:false,zIndex:false}});a.ui.plugin.add("draggable","connectToSortable",{start:function(c,e){var d=a(this).data("draggable"),f=d.options,b=a.extend({},e,{item:d.element});d.sortables=[];a(f.connectToSortable).each(function(){var g=a.data(this,"sortable");if(g&&!g.options.disabled){d.sortables.push({instance:g,shouldRevert:g.options.revert});g._refreshItems();g._trigger("activate",c,b)}})},stop:function(c,e){var d=a(this).data("draggable"),b=a.extend({},e,{item:d.element});a.each(d.sortables,function(){if(this.instance.isOver){this.instance.isOver=0;d.cancelHelperRemoval=true;this.instance.cancelHelperRemoval=false;if(this.shouldRevert){this.instance.options.revert=true}this.instance._mouseStop(c);this.instance.options.helper=this.instance.options._helper;if(d.options.helper=="original"){this.instance.currentItem.css({top:"auto",left:"auto"})}}else{this.instance.cancelHelperRemoval=false;this.instance._trigger("deactivate",c,b)}})},drag:function(c,f){var e=a(this).data("draggable"),b=this;var d=function(i){var n=this.offset.click.top,m=this.offset.click.left;var g=this.positionAbs.top,k=this.positionAbs.left;var j=i.height,l=i.width;var p=i.top,h=i.left;return a.ui.isOver(g+n,k+m,p,h,j,l)};a.each(e.sortables,function(g){this.instance.positionAbs=e.positionAbs;this.instance.helperProportions=e.helperProportions;this.instance.offset.click=e.offset.click;if(this.instance._intersectsWith(this.instance.containerCache)){if(!this.instance.isOver){this.instance.isOver=1;this.instance.currentItem=a(b).clone().appendTo(this.instance.element).data("sortable-item",true);this.instance.options._helper=this.instance.options.helper;this.instance.options.helper=function(){return f.helper[0]};c.target=this.instance.currentItem[0];this.instance._mouseCapture(c,true);this.instance._mouseStart(c,true,true);this.instance.offset.click.top=e.offset.click.top;this.instance.offset.click.left=e.offset.click.left;this.instance.offset.parent.left-=e.offset.parent.left-this.instance.offset.parent.left;this.instance.offset.parent.top-=e.offset.parent.top-this.instance.offset.parent.top;e._trigger("toSortable",c);e.dropped=this.instance.element;e.currentItem=e.element;this.instance.fromOutside=e}if(this.instance.currentItem){this.instance._mouseDrag(c)}}else{if(this.instance.isOver){this.instance.isOver=0;this.instance.cancelHelperRemoval=true;this.instance.options.revert=false;this.instance._trigger("out",c,this.instance._uiHash(this.instance));this.instance._mouseStop(c,true);this.instance.options.helper=this.instance.options._helper;this.instance.currentItem.remove();if(this.instance.placeholder){this.instance.placeholder.remove()}e._trigger("fromSortable",c);e.dropped=false}}})}});a.ui.plugin.add("draggable","cursor",{start:function(c,d){var b=a("body"),e=a(this).data("draggable").options;if(b.css("cursor")){e._cursor=b.css("cursor")}b.css("cursor",e.cursor)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._cursor){a("body").css("cursor",d._cursor)}}});a.ui.plugin.add("draggable","iframeFix",{start:function(b,c){var d=a(this).data("draggable").options;a(d.iframeFix===true?"iframe":d.iframeFix).each(function(){a('<div class="ui-draggable-iframeFix" style="background: #fff;"></div>').css({width:this.offsetWidth+"px",height:this.offsetHeight+"px",position:"absolute",opacity:"0.001",zIndex:1000}).css(a(this).offset()).appendTo("body")})},stop:function(b,c){a("div.ui-draggable-iframeFix").each(function(){this.parentNode.removeChild(this)})}});a.ui.plugin.add("draggable","opacity",{start:function(c,d){var b=a(d.helper),e=a(this).data("draggable").options;if(b.css("opacity")){e._opacity=b.css("opacity")}b.css("opacity",e.opacity)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._opacity){a(c.helper).css("opacity",d._opacity)}}});a.ui.plugin.add("draggable","scroll",{start:function(c,d){var b=a(this).data("draggable");if(b.scrollParent[0]!=document&&b.scrollParent[0].tagName!="HTML"){b.overflowOffset=b.scrollParent.offset()}},drag:function(d,e){var c=a(this).data("draggable"),f=c.options,b=false;if(c.scrollParent[0]!=document&&c.scrollParent[0].tagName!="HTML"){if(!f.axis||f.axis!="x"){if((c.overflowOffset.top+c.scrollParent[0].offsetHeight)-d.pageY<f.scrollSensitivity){c.scrollParent[0].scrollTop=b=c.scrollParent[0].scrollTop+f.scrollSpeed}else{if(d.pageY-c.overflowOffset.top<f.scrollSensitivity){c.scrollParent[0].scrollTop=b=c.scrollParent[0].scrollTop-f.scrollSpeed}}}if(!f.axis||f.axis!="y"){if((c.overflowOffset.left+c.scrollParent[0].offsetWidth)-d.pageX<f.scrollSensitivity){c.scrollParent[0].scrollLeft=b=c.scrollParent[0].scrollLeft+f.scrollSpeed}else{if(d.pageX-c.overflowOffset.left<f.scrollSensitivity){c.scrollParent[0].scrollLeft=b=c.scrollParent[0].scrollLeft-f.scrollSpeed}}}}else{if(!f.axis||f.axis!="x"){if(d.pageY-a(document).scrollTop()<f.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()-f.scrollSpeed)}else{if(a(window).height()-(d.pageY-a(document).scrollTop())<f.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()+f.scrollSpeed)}}}if(!f.axis||f.axis!="y"){if(d.pageX-a(document).scrollLeft()<f.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()-f.scrollSpeed)}else{if(a(window).width()-(d.pageX-a(document).scrollLeft())<f.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()+f.scrollSpeed)}}}}if(b!==false&&a.ui.ddmanager&&!f.dropBehaviour){a.ui.ddmanager.prepareOffsets(c,d)}}});a.ui.plugin.add("draggable","snap",{start:function(c,d){var b=a(this).data("draggable"),e=b.options;b.snapElements=[];a(e.snap.constructor!=String?(e.snap.items||":data(draggable)"):e.snap).each(function(){var g=a(this);var f=g.offset();if(this!=b.element[0]){b.snapElements.push({item:this,width:g.outerWidth(),height:g.outerHeight(),top:f.top,left:f.left})}})},drag:function(u,p){var g=a(this).data("draggable"),q=g.options;var y=q.snapTolerance;var x=p.offset.left,w=x+g.helperProportions.width,f=p.offset.top,e=f+g.helperProportions.height;for(var v=g.snapElements.length-1;v>=0;v--){var s=g.snapElements[v].left,n=s+g.snapElements[v].width,m=g.snapElements[v].top,A=m+g.snapElements[v].height;if(!((s-y<x&&x<n+y&&m-y<f&&f<A+y)||(s-y<x&&x<n+y&&m-y<e&&e<A+y)||(s-y<w&&w<n+y&&m-y<f&&f<A+y)||(s-y<w&&w<n+y&&m-y<e&&e<A+y))){if(g.snapElements[v].snapping){(g.options.snap.release&&g.options.snap.release.call(g.element,u,a.extend(g._uiHash(),{snapItem:g.snapElements[v].item})))}g.snapElements[v].snapping=false;continue}if(q.snapMode!="inner"){var c=Math.abs(m-e)<=y;var z=Math.abs(A-f)<=y;var j=Math.abs(s-w)<=y;var k=Math.abs(n-x)<=y;if(c){p.position.top=g._convertPositionTo("relative",{top:m-g.helperProportions.height,left:0}).top-g.margins.top}if(z){p.position.top=g._convertPositionTo("relative",{top:A,left:0}).top-g.margins.top}if(j){p.position.left=g._convertPositionTo("relative",{top:0,left:s-g.helperProportions.width}).left-g.margins.left}if(k){p.position.left=g._convertPositionTo("relative",{top:0,left:n}).left-g.margins.left}}var h=(c||z||j||k);if(q.snapMode!="outer"){var c=Math.abs(m-f)<=y;var z=Math.abs(A-e)<=y;var j=Math.abs(s-x)<=y;var k=Math.abs(n-w)<=y;if(c){p.position.top=g._convertPositionTo("relative",{top:m,left:0}).top-g.margins.top}if(z){p.position.top=g._convertPositionTo("relative",{top:A-g.helperProportions.height,left:0}).top-g.margins.top}if(j){p.position.left=g._convertPositionTo("relative",{top:0,left:s}).left-g.margins.left}if(k){p.position.left=g._convertPositionTo("relative",{top:0,left:n-g.helperProportions.width}).left-g.margins.left}}if(!g.snapElements[v].snapping&&(c||z||j||k||h)){(g.options.snap.snap&&g.options.snap.snap.call(g.element,u,a.extend(g._uiHash(),{snapItem:g.snapElements[v].item})))}g.snapElements[v].snapping=(c||z||j||k||h)}}});a.ui.plugin.add("draggable","stack",{start:function(b,c){var e=a(this).data("draggable").options;var d=a.makeArray(a(e.stack.group)).sort(function(g,f){return(parseInt(a(g).css("zIndex"),10)||e.stack.min)-(parseInt(a(f).css("zIndex"),10)||e.stack.min)});a(d).each(function(f){this.style.zIndex=e.stack.min+f});this[0].style.zIndex=e.stack.min+d.length}});a.ui.plugin.add("draggable","zIndex",{start:function(c,d){var b=a(d.helper),e=a(this).data("draggable").options;if(b.css("zIndex")){e._zIndex=b.css("zIndex")}b.css("zIndex",e.zIndex)},stop:function(b,c){var d=a(this).data("draggable").options;if(d._zIndex){a(c.helper).css("zIndex",d._zIndex)}}})})(jQuery);;/*
 * jQuery UI Droppable 1.7
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Droppables
 *
 * Depends:
 *	ui.core.js
 *	ui.draggable.js
 */(function(a){a.widget("ui.droppable",{_init:function(){var c=this.options,b=c.accept;this.isover=0;this.isout=1;this.options.accept=this.options.accept&&a.isFunction(this.options.accept)?this.options.accept:function(e){return e.is(b)};this.proportions={width:this.element[0].offsetWidth,height:this.element[0].offsetHeight};a.ui.ddmanager.droppables[this.options.scope]=a.ui.ddmanager.droppables[this.options.scope]||[];a.ui.ddmanager.droppables[this.options.scope].push(this);(this.options.addClasses&&this.element.addClass("ui-droppable"))},destroy:function(){var b=a.ui.ddmanager.droppables[this.options.scope];for(var c=0;c<b.length;c++){if(b[c]==this){b.splice(c,1)}}this.element.removeClass("ui-droppable ui-droppable-disabled").removeData("droppable").unbind(".droppable")},_setData:function(b,c){if(b=="accept"){this.options.accept=c&&a.isFunction(c)?c:function(e){return e.is(accept)}}else{a.widget.prototype._setData.apply(this,arguments)}},_activate:function(c){var b=a.ui.ddmanager.current;if(this.options.activeClass){this.element.addClass(this.options.activeClass)}(b&&this._trigger("activate",c,this.ui(b)))},_deactivate:function(c){var b=a.ui.ddmanager.current;if(this.options.activeClass){this.element.removeClass(this.options.activeClass)}(b&&this._trigger("deactivate",c,this.ui(b)))},_over:function(c){var b=a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.hoverClass){this.element.addClass(this.options.hoverClass)}this._trigger("over",c,this.ui(b))}},_out:function(c){var b=a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.hoverClass){this.element.removeClass(this.options.hoverClass)}this._trigger("out",c,this.ui(b))}},_drop:function(c,d){var b=d||a.ui.ddmanager.current;if(!b||(b.currentItem||b.element)[0]==this.element[0]){return false}var e=false;this.element.find(":data(droppable)").not(".ui-draggable-dragging").each(function(){var f=a.data(this,"droppable");if(f.options.greedy&&a.ui.intersect(b,a.extend(f,{offset:f.element.offset()}),f.options.tolerance)){e=true;return false}});if(e){return false}if(this.options.accept.call(this.element[0],(b.currentItem||b.element))){if(this.options.activeClass){this.element.removeClass(this.options.activeClass)}if(this.options.hoverClass){this.element.removeClass(this.options.hoverClass)}this._trigger("drop",c,this.ui(b));return this.element}return false},ui:function(b){return{draggable:(b.currentItem||b.element),helper:b.helper,position:b.position,absolutePosition:b.positionAbs,offset:b.positionAbs}}});a.extend(a.ui.droppable,{version:"1.7",eventPrefix:"drop",defaults:{accept:"*",activeClass:false,addClasses:true,greedy:false,hoverClass:false,scope:"default",tolerance:"intersect"}});a.ui.intersect=function(q,j,o){if(!j.offset){return false}var e=(q.positionAbs||q.position.absolute).left,d=e+q.helperProportions.width,n=(q.positionAbs||q.position.absolute).top,m=n+q.helperProportions.height;var g=j.offset.left,c=g+j.proportions.width,p=j.offset.top,k=p+j.proportions.height;switch(o){case"fit":return(g<e&&d<c&&p<n&&m<k);break;case"intersect":return(g<e+(q.helperProportions.width/2)&&d-(q.helperProportions.width/2)<c&&p<n+(q.helperProportions.height/2)&&m-(q.helperProportions.height/2)<k);break;case"pointer":var h=((q.positionAbs||q.position.absolute).left+(q.clickOffset||q.offset.click).left),i=((q.positionAbs||q.position.absolute).top+(q.clickOffset||q.offset.click).top),f=a.ui.isOver(i,h,p,g,j.proportions.height,j.proportions.width);return f;break;case"touch":return((n>=p&&n<=k)||(m>=p&&m<=k)||(n<p&&m>k))&&((e>=g&&e<=c)||(d>=g&&d<=c)||(e<g&&d>c));break;default:return false;break}};a.ui.ddmanager={current:null,droppables:{"default":[]},prepareOffsets:function(e,g){var b=a.ui.ddmanager.droppables[e.options.scope];var f=g?g.type:null;var h=(e.currentItem||e.element).find(":data(droppable)").andSelf();droppablesLoop:for(var d=0;d<b.length;d++){if(b[d].options.disabled||(e&&!b[d].options.accept.call(b[d].element[0],(e.currentItem||e.element)))){continue}for(var c=0;c<h.length;c++){if(h[c]==b[d].element[0]){b[d].proportions.height=0;continue droppablesLoop}}b[d].visible=b[d].element.css("display")!="none";if(!b[d].visible){continue}b[d].offset=b[d].element.offset();b[d].proportions={width:b[d].element[0].offsetWidth,height:b[d].element[0].offsetHeight};if(f=="mousedown"){b[d]._activate.call(b[d],g)}}},drop:function(b,c){var d=false;a.each(a.ui.ddmanager.droppables[b.options.scope],function(){if(!this.options){return}if(!this.options.disabled&&this.visible&&a.ui.intersect(b,this,this.options.tolerance)){d=this._drop.call(this,c)}if(!this.options.disabled&&this.visible&&this.options.accept.call(this.element[0],(b.currentItem||b.element))){this.isout=1;this.isover=0;this._deactivate.call(this,c)}});return d},drag:function(b,c){if(b.options.refreshPositions){a.ui.ddmanager.prepareOffsets(b,c)}a.each(a.ui.ddmanager.droppables[b.options.scope],function(){if(this.options.disabled||this.greedyChild||!this.visible){return}var e=a.ui.intersect(b,this,this.options.tolerance);var g=!e&&this.isover==1?"isout":(e&&this.isover==0?"isover":null);if(!g){return}var f;if(this.options.greedy){var d=this.element.parents(":data(droppable):eq(0)");if(d.length){f=a.data(d[0],"droppable");f.greedyChild=(g=="isover"?1:0)}}if(f&&g=="isover"){f.isover=0;f.isout=1;f._out.call(f,c)}this[g]=1;this[g=="isout"?"isover":"isout"]=0;this[g=="isover"?"_over":"_out"].call(this,c);if(f&&g=="isout"){f.isout=0;f.isover=1;f._over.call(f,c)}})}}})(jQuery);;/*
 * jQuery UI Resizable 1.7
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Resizables
 *
 * Depends:
 *	ui.core.js
 */(function(c){c.widget("ui.resizable",c.extend({},c.ui.mouse,{_init:function(){var e=this,j=this.options;this.element.addClass("ui-resizable");c.extend(this,{_aspectRatio:!!(j.aspectRatio),aspectRatio:j.aspectRatio,originalElement:this.element,_proportionallyResizeElements:[],_helper:j.helper||j.ghost||j.animate?j.helper||"ui-resizable-helper":null});if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)){if(/relative/.test(this.element.css("position"))&&c.browser.opera){this.element.css({position:"relative",top:"auto",left:"auto"})}this.element.wrap(c('<div class="ui-wrapper" style="overflow: hidden;"></div>').css({position:this.element.css("position"),width:this.element.outerWidth(),height:this.element.outerHeight(),top:this.element.css("top"),left:this.element.css("left")}));this.element=this.element.parent().data("resizable",this.element.data("resizable"));this.elementIsWrapper=true;this.element.css({marginLeft:this.originalElement.css("marginLeft"),marginTop:this.originalElement.css("marginTop"),marginRight:this.originalElement.css("marginRight"),marginBottom:this.originalElement.css("marginBottom")});this.originalElement.css({marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});this.originalResizeStyle=this.originalElement.css("resize");this.originalElement.css("resize","none");this._proportionallyResizeElements.push(this.originalElement.css({position:"static",zoom:1,display:"block"}));this.originalElement.css({margin:this.originalElement.css("margin")});this._proportionallyResize()}this.handles=j.handles||(!c(".ui-resizable-handle",this.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(this.handles.constructor==String){if(this.handles=="all"){this.handles="n,e,s,w,se,sw,ne,nw"}var k=this.handles.split(",");this.handles={};for(var f=0;f<k.length;f++){var h=c.trim(k[f]),d="ui-resizable-"+h;var g=c('<div class="ui-resizable-handle '+d+'"></div>');if(/sw|se|ne|nw/.test(h)){g.css({zIndex:++j.zIndex})}if("se"==h){g.addClass("ui-icon ui-icon-gripsmall-diagonal-se")}this.handles[h]=".ui-resizable-"+h;this.element.append(g)}}this._renderAxis=function(p){p=p||this.element;for(var m in this.handles){if(this.handles[m].constructor==String){this.handles[m]=c(this.handles[m],this.element).show()}if(this.elementIsWrapper&&this.originalElement[0].nodeName.match(/textarea|input|select|button/i)){var n=c(this.handles[m],this.element),o=0;o=/sw|ne|nw|se|n|s/.test(m)?n.outerHeight():n.outerWidth();var l=["padding",/ne|nw|n/.test(m)?"Top":/se|sw|s/.test(m)?"Bottom":/^e$/.test(m)?"Right":"Left"].join("");p.css(l,o);this._proportionallyResize()}if(!c(this.handles[m]).length){continue}}};this._renderAxis(this.element);this._handles=c(".ui-resizable-handle",this.element).disableSelection();this._handles.mouseover(function(){if(!e.resizing){if(this.className){var i=this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i)}e.axis=i&&i[1]?i[1]:"se"}});if(j.autoHide){this._handles.hide();c(this.element).addClass("ui-resizable-autohide").hover(function(){c(this).removeClass("ui-resizable-autohide");e._handles.show()},function(){if(!e.resizing){c(this).addClass("ui-resizable-autohide");e._handles.hide()}})}this._mouseInit()},destroy:function(){this._mouseDestroy();var d=function(f){c(f).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing").removeData("resizable").unbind(".resizable").find(".ui-resizable-handle").remove()};if(this.elementIsWrapper){d(this.element);var e=this.element;e.parent().append(this.originalElement.css({position:e.css("position"),width:e.outerWidth(),height:e.outerHeight(),top:e.css("top"),left:e.css("left")})).end().remove()}this.originalElement.css("resize",this.originalResizeStyle);d(this.originalElement)},_mouseCapture:function(e){var f=false;for(var d in this.handles){if(c(this.handles[d])[0]==e.target){f=true}}return this.options.disabled||!!f},_mouseStart:function(f){var i=this.options,e=this.element.position(),d=this.element;this.resizing=true;this.documentScroll={top:c(document).scrollTop(),left:c(document).scrollLeft()};if(d.is(".ui-draggable")||(/absolute/).test(d.css("position"))){d.css({position:"absolute",top:e.top,left:e.left})}if(c.browser.opera&&(/relative/).test(d.css("position"))){d.css({position:"relative",top:"auto",left:"auto"})}this._renderProxy();var j=b(this.helper.css("left")),g=b(this.helper.css("top"));if(i.containment){j+=c(i.containment).scrollLeft()||0;g+=c(i.containment).scrollTop()||0}this.offset=this.helper.offset();this.position={left:j,top:g};this.size=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalSize=this._helper?{width:d.outerWidth(),height:d.outerHeight()}:{width:d.width(),height:d.height()};this.originalPosition={left:j,top:g};this.sizeDiff={width:d.outerWidth()-d.width(),height:d.outerHeight()-d.height()};this.originalMousePosition={left:f.pageX,top:f.pageY};this.aspectRatio=(typeof i.aspectRatio=="number")?i.aspectRatio:((this.originalSize.width/this.originalSize.height)||1);var h=c(".ui-resizable-"+this.axis).css("cursor");c("body").css("cursor",h=="auto"?this.axis+"-resize":h);d.addClass("ui-resizable-resizing");this._propagate("start",f);return true},_mouseDrag:function(d){var g=this.helper,f=this.options,l={},p=this,i=this.originalMousePosition,m=this.axis;var q=(d.pageX-i.left)||0,n=(d.pageY-i.top)||0;var h=this._change[m];if(!h){return false}var k=h.apply(this,[d,q,n]),j=c.browser.msie&&c.browser.version<7,e=this.sizeDiff;if(this._aspectRatio||d.shiftKey){k=this._updateRatio(k,d)}k=this._respectSize(k,d);this._propagate("resize",d);g.css({top:this.position.top+"px",left:this.position.left+"px",width:this.size.width+"px",height:this.size.height+"px"});if(!this._helper&&this._proportionallyResizeElements.length){this._proportionallyResize()}this._updateCache(k);this._trigger("resize",d,this.ui());return false},_mouseStop:function(g){this.resizing=false;var h=this.options,l=this;if(this._helper){var f=this._proportionallyResizeElements,d=f.length&&(/textarea/i).test(f[0].nodeName),e=d&&c.ui.hasScroll(f[0],"left")?0:l.sizeDiff.height,j=d?0:l.sizeDiff.width;var m={width:(l.size.width-j),height:(l.size.height-e)},i=(parseInt(l.element.css("left"),10)+(l.position.left-l.originalPosition.left))||null,k=(parseInt(l.element.css("top"),10)+(l.position.top-l.originalPosition.top))||null;if(!h.animate){this.element.css(c.extend(m,{top:k,left:i}))}l.helper.height(l.size.height);l.helper.width(l.size.width);if(this._helper&&!h.animate){this._proportionallyResize()}}c("body").css("cursor","auto");this.element.removeClass("ui-resizable-resizing");this._propagate("stop",g);if(this._helper){this.helper.remove()}return false},_updateCache:function(d){var e=this.options;this.offset=this.helper.offset();if(a(d.left)){this.position.left=d.left}if(a(d.top)){this.position.top=d.top}if(a(d.height)){this.size.height=d.height}if(a(d.width)){this.size.width=d.width}},_updateRatio:function(g,f){var h=this.options,i=this.position,e=this.size,d=this.axis;if(g.height){g.width=(e.height*this.aspectRatio)}else{if(g.width){g.height=(e.width/this.aspectRatio)}}if(d=="sw"){g.left=i.left+(e.width-g.width);g.top=null}if(d=="nw"){g.top=i.top+(e.height-g.height);g.left=i.left+(e.width-g.width)}return g},_respectSize:function(k,f){var i=this.helper,h=this.options,q=this._aspectRatio||f.shiftKey,p=this.axis,s=a(k.width)&&h.maxWidth&&(h.maxWidth<k.width),l=a(k.height)&&h.maxHeight&&(h.maxHeight<k.height),g=a(k.width)&&h.minWidth&&(h.minWidth>k.width),r=a(k.height)&&h.minHeight&&(h.minHeight>k.height);if(g){k.width=h.minWidth}if(r){k.height=h.minHeight}if(s){k.width=h.maxWidth}if(l){k.height=h.maxHeight}var e=this.originalPosition.left+this.originalSize.width,n=this.position.top+this.size.height;var j=/sw|nw|w/.test(p),d=/nw|ne|n/.test(p);if(g&&j){k.left=e-h.minWidth}if(s&&j){k.left=e-h.maxWidth}if(r&&d){k.top=n-h.minHeight}if(l&&d){k.top=n-h.maxHeight}var m=!k.width&&!k.height;if(m&&!k.left&&k.top){k.top=null}else{if(m&&!k.top&&k.left){k.left=null}}return k},_proportionallyResize:function(){var j=this.options;if(!this._proportionallyResizeElements.length){return}var f=this.helper||this.element;for(var e=0;e<this._proportionallyResizeElements.length;e++){var g=this._proportionallyResizeElements[e];if(!this.borderDif){var d=[g.css("borderTopWidth"),g.css("borderRightWidth"),g.css("borderBottomWidth"),g.css("borderLeftWidth")],h=[g.css("paddingTop"),g.css("paddingRight"),g.css("paddingBottom"),g.css("paddingLeft")];this.borderDif=c.map(d,function(k,m){var l=parseInt(k,10)||0,n=parseInt(h[m],10)||0;return l+n})}if(c.browser.msie&&!(!(c(f).is(":hidden")||c(f).parents(":hidden").length))){continue}g.css({height:(f.height()-this.borderDif[0]-this.borderDif[2])||0,width:(f.width()-this.borderDif[1]-this.borderDif[3])||0})}},_renderProxy:function(){var e=this.element,h=this.options;this.elementOffset=e.offset();if(this._helper){this.helper=this.helper||c('<div style="overflow:hidden;"></div>');var d=c.browser.msie&&c.browser.version<7,f=(d?1:0),g=(d?2:-1);this.helper.addClass(this._helper).css({width:this.element.outerWidth()+g,height:this.element.outerHeight()+g,position:"absolute",left:this.elementOffset.left-f+"px",top:this.elementOffset.top-f+"px",zIndex:++h.zIndex});this.helper.appendTo("body").disableSelection()}else{this.helper=this.element}},_change:{e:function(f,e,d){return{width:this.originalSize.width+e}},w:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{left:h.left+e,width:f.width-e}},n:function(g,e,d){var i=this.options,f=this.originalSize,h=this.originalPosition;return{top:h.top+d,height:f.height-d}},s:function(f,e,d){return{height:this.originalSize.height+d}},se:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},sw:function(f,e,d){return c.extend(this._change.s.apply(this,arguments),this._change.w.apply(this,[f,e,d]))},ne:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.e.apply(this,[f,e,d]))},nw:function(f,e,d){return c.extend(this._change.n.apply(this,arguments),this._change.w.apply(this,[f,e,d]))}},_propagate:function(e,d){c.ui.plugin.call(this,e,[d,this.ui()]);(e!="resize"&&this._trigger(e,d,this.ui()))},plugins:{},ui:function(){return{originalElement:this.originalElement,element:this.element,helper:this.helper,position:this.position,size:this.size,originalSize:this.originalSize,originalPosition:this.originalPosition}}}));c.extend(c.ui.resizable,{version:"1.7",eventPrefix:"resize",defaults:{alsoResize:false,animate:false,animateDuration:"slow",animateEasing:"swing",aspectRatio:false,autoHide:false,cancel:":input,option",containment:false,delay:0,distance:1,ghost:false,grid:false,handles:"e,s,se",helper:false,maxHeight:null,maxWidth:null,minHeight:10,minWidth:10,zIndex:1000}});c.ui.plugin.add("resizable","alsoResize",{start:function(e,f){var d=c(this).data("resizable"),g=d.options;_store=function(h){c(h).each(function(){c(this).data("resizable-alsoresize",{width:parseInt(c(this).width(),10),height:parseInt(c(this).height(),10),left:parseInt(c(this).css("left"),10),top:parseInt(c(this).css("top"),10)})})};if(typeof(g.alsoResize)=="object"&&!g.alsoResize.parentNode){if(g.alsoResize.length){g.alsoResize=g.alsoResize[0];_store(g.alsoResize)}else{c.each(g.alsoResize,function(h,i){_store(h)})}}else{_store(g.alsoResize)}},resize:function(f,h){var e=c(this).data("resizable"),i=e.options,g=e.originalSize,k=e.originalPosition;var j={height:(e.size.height-g.height)||0,width:(e.size.width-g.width)||0,top:(e.position.top-k.top)||0,left:(e.position.left-k.left)||0},d=function(l,m){c(l).each(function(){var p=c(this),q=c(this).data("resizable-alsoresize"),o={},n=m&&m.length?m:["width","height","top","left"];c.each(n||["width","height","top","left"],function(r,t){var s=(q[t]||0)+(j[t]||0);if(s&&s>=0){o[t]=s||null}});if(/relative/.test(p.css("position"))&&c.browser.opera){e._revertToRelativePosition=true;p.css({position:"absolute",top:"auto",left:"auto"})}p.css(o)})};if(typeof(i.alsoResize)=="object"&&!i.alsoResize.nodeType){c.each(i.alsoResize,function(l,m){d(l,m)})}else{d(i.alsoResize)}},stop:function(e,f){var d=c(this).data("resizable");if(d._revertToRelativePosition&&c.browser.opera){d._revertToRelativePosition=false;el.css({position:"relative"})}c(this).removeData("resizable-alsoresize-start")}});c.ui.plugin.add("resizable","animate",{stop:function(h,m){var n=c(this).data("resizable"),i=n.options;var g=n._proportionallyResizeElements,d=g.length&&(/textarea/i).test(g[0].nodeName),e=d&&c.ui.hasScroll(g[0],"left")?0:n.sizeDiff.height,k=d?0:n.sizeDiff.width;var f={width:(n.size.width-k),height:(n.size.height-e)},j=(parseInt(n.element.css("left"),10)+(n.position.left-n.originalPosition.left))||null,l=(parseInt(n.element.css("top"),10)+(n.position.top-n.originalPosition.top))||null;n.element.animate(c.extend(f,l&&j?{top:l,left:j}:{}),{duration:i.animateDuration,easing:i.animateEasing,step:function(){var o={width:parseInt(n.element.css("width"),10),height:parseInt(n.element.css("height"),10),top:parseInt(n.element.css("top"),10),left:parseInt(n.element.css("left"),10)};if(g&&g.length){c(g[0]).css({width:o.width,height:o.height})}n._updateCache(o);n._propagate("resize",h)}})}});c.ui.plugin.add("resizable","containment",{start:function(e,q){var s=c(this).data("resizable"),i=s.options,k=s.element;var f=i.containment,j=(f instanceof c)?f.get(0):(/parent/.test(f))?k.parent().get(0):f;if(!j){return}s.containerElement=c(j);if(/document/.test(f)||f==document){s.containerOffset={left:0,top:0};s.containerPosition={left:0,top:0};s.parentData={element:c(document),left:0,top:0,width:c(document).width(),height:c(document).height()||document.body.parentNode.scrollHeight}}else{var m=c(j),h=[];c(["Top","Right","Left","Bottom"]).each(function(p,o){h[p]=b(m.css("padding"+o))});s.containerOffset=m.offset();s.containerPosition=m.position();s.containerSize={height:(m.innerHeight()-h[3]),width:(m.innerWidth()-h[1])};var n=s.containerOffset,d=s.containerSize.height,l=s.containerSize.width,g=(c.ui.hasScroll(j,"left")?j.scrollWidth:l),r=(c.ui.hasScroll(j)?j.scrollHeight:d);s.parentData={element:j,left:n.left,top:n.top,width:g,height:r}}},resize:function(f,p){var s=c(this).data("resizable"),h=s.options,e=s.containerSize,n=s.containerOffset,l=s.size,m=s.position,q=h._aspectRatio||f.shiftKey,d={top:0,left:0},g=s.containerElement;if(g[0]!=document&&(/static/).test(g.css("position"))){d=n}if(m.left<(s._helper?n.left:0)){s.size.width=s.size.width+(s._helper?(s.position.left-n.left):(s.position.left-d.left));if(q){s.size.height=s.size.width/h.aspectRatio}s.position.left=h.helper?n.left:0}if(m.top<(s._helper?n.top:0)){s.size.height=s.size.height+(s._helper?(s.position.top-n.top):s.position.top);if(q){s.size.width=s.size.height*h.aspectRatio}s.position.top=s._helper?n.top:0}s.offset.left=s.parentData.left+s.position.left;s.offset.top=s.parentData.top+s.position.top;var k=Math.abs((s._helper?s.offset.left-d.left:(s.offset.left-d.left))+s.sizeDiff.width),r=Math.abs((s._helper?s.offset.top-d.top:(s.offset.top-n.top))+s.sizeDiff.height);var j=s.containerElement.get(0)==s.element.parent().get(0),i=/relative|absolute/.test(s.containerElement.css("position"));if(j&&i){k-=s.parentData.left}if(k+s.size.width>=s.parentData.width){s.size.width=s.parentData.width-k;if(q){s.size.height=s.size.width/h.aspectRatio}}if(r+s.size.height>=s.parentData.height){s.size.height=s.parentData.height-r;if(q){s.size.width=s.size.height*h.aspectRatio}}},stop:function(e,m){var p=c(this).data("resizable"),f=p.options,k=p.position,l=p.containerOffset,d=p.containerPosition,g=p.containerElement;var i=c(p.helper),q=i.offset(),n=i.outerWidth()-p.sizeDiff.width,j=i.outerHeight()-p.sizeDiff.height;if(p._helper&&!f.animate&&(/relative/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}if(p._helper&&!f.animate&&(/static/).test(g.css("position"))){c(this).css({left:q.left-d.left-l.left,width:n,height:j})}}});c.ui.plugin.add("resizable","ghost",{start:function(f,g){var d=c(this).data("resizable"),h=d.options,e=d.size;d.ghost=d.originalElement.clone();d.ghost.css({opacity:0.25,display:"block",position:"relative",height:e.height,width:e.width,margin:0,left:0,top:0}).addClass("ui-resizable-ghost").addClass(typeof h.ghost=="string"?h.ghost:"");d.ghost.appendTo(d.helper)},resize:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost){d.ghost.css({position:"relative",height:d.size.height,width:d.size.width})}},stop:function(e,f){var d=c(this).data("resizable"),g=d.options;if(d.ghost&&d.helper){d.helper.get(0).removeChild(d.ghost.get(0))}}});c.ui.plugin.add("resizable","grid",{resize:function(d,l){var n=c(this).data("resizable"),g=n.options,j=n.size,h=n.originalSize,i=n.originalPosition,m=n.axis,k=g._aspectRatio||d.shiftKey;g.grid=typeof g.grid=="number"?[g.grid,g.grid]:g.grid;var f=Math.round((j.width-h.width)/(g.grid[0]||1))*(g.grid[0]||1),e=Math.round((j.height-h.height)/(g.grid[1]||1))*(g.grid[1]||1);if(/^(se|s|e)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e}else{if(/^(ne)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e}else{if(/^(sw)$/.test(m)){n.size.width=h.width+f;n.size.height=h.height+e;n.position.left=i.left-f}else{n.size.width=h.width+f;n.size.height=h.height+e;n.position.top=i.top-e;n.position.left=i.left-f}}}}});var b=function(d){return parseInt(d,10)||0};var a=function(d){return !isNaN(parseInt(d,10))}})(jQuery);;/*
 * jQuery UI Sortable 1.7
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Sortables
 *
 * Depends:
 *	ui.core.js
 */(function(a){a.widget("ui.sortable",a.extend({},a.ui.mouse,{_init:function(){var b=this.options;this.containerCache={};this.element.addClass("ui-sortable");this.refresh();this.floating=this.items.length?(/left|right/).test(this.items[0].item.css("float")):false;this.offset=this.element.offset();this._mouseInit()},destroy:function(){this.element.removeClass("ui-sortable ui-sortable-disabled").removeData("sortable").unbind(".sortable");this._mouseDestroy();for(var b=this.items.length-1;b>=0;b--){this.items[b].item.removeData("sortable-item")}},_mouseCapture:function(e,f){if(this.reverting){return false}if(this.options.disabled||this.options.type=="static"){return false}this._refreshItems(e);var d=null,c=this,b=a(e.target).parents().each(function(){if(a.data(this,"sortable-item")==c){d=a(this);return false}});if(a.data(e.target,"sortable-item")==c){d=a(e.target)}if(!d){return false}if(this.options.handle&&!f){var g=false;a(this.options.handle,d).find("*").andSelf().each(function(){if(this==e.target){g=true}});if(!g){return false}}this.currentItem=d;this._removeCurrentsFromItems();return true},_mouseStart:function(e,f,b){var g=this.options,c=this;this.currentContainer=this;this.refreshPositions();this.helper=this._createHelper(e);this._cacheHelperProportions();this._cacheMargins();this.scrollParent=this.helper.scrollParent();this.offset=this.currentItem.offset();this.offset={top:this.offset.top-this.margins.top,left:this.offset.left-this.margins.left};this.helper.css("position","absolute");this.cssPosition=this.helper.css("position");a.extend(this.offset,{click:{left:e.pageX-this.offset.left,top:e.pageY-this.offset.top},parent:this._getParentOffset(),relative:this._getRelativeOffset()});this.originalPosition=this._generatePosition(e);this.originalPageX=e.pageX;this.originalPageY=e.pageY;if(g.cursorAt){this._adjustOffsetFromHelper(g.cursorAt)}this.domPosition={prev:this.currentItem.prev()[0],parent:this.currentItem.parent()[0]};if(this.helper[0]!=this.currentItem[0]){this.currentItem.hide()}this._createPlaceholder();if(g.containment){this._setContainment()}if(g.cursor){if(a("body").css("cursor")){this._storedCursor=a("body").css("cursor")}a("body").css("cursor",g.cursor)}if(g.opacity){if(this.helper.css("opacity")){this._storedOpacity=this.helper.css("opacity")}this.helper.css("opacity",g.opacity)}if(g.zIndex){if(this.helper.css("zIndex")){this._storedZIndex=this.helper.css("zIndex")}this.helper.css("zIndex",g.zIndex)}if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){this.overflowOffset=this.scrollParent.offset()}this._trigger("start",e,this._uiHash());if(!this._preserveHelperProportions){this._cacheHelperProportions()}if(!b){for(var d=this.containers.length-1;d>=0;d--){this.containers[d]._trigger("activate",e,c._uiHash(this))}}if(a.ui.ddmanager){a.ui.ddmanager.current=this}if(a.ui.ddmanager&&!g.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,e)}this.dragging=true;this.helper.addClass("ui-sortable-helper");this._mouseDrag(e);return true},_mouseDrag:function(f){this.position=this._generatePosition(f);this.positionAbs=this._convertPositionTo("absolute");if(!this.lastPositionAbs){this.lastPositionAbs=this.positionAbs}if(this.options.scroll){var g=this.options,b=false;if(this.scrollParent[0]!=document&&this.scrollParent[0].tagName!="HTML"){if((this.overflowOffset.top+this.scrollParent[0].offsetHeight)-f.pageY<g.scrollSensitivity){this.scrollParent[0].scrollTop=b=this.scrollParent[0].scrollTop+g.scrollSpeed}else{if(f.pageY-this.overflowOffset.top<g.scrollSensitivity){this.scrollParent[0].scrollTop=b=this.scrollParent[0].scrollTop-g.scrollSpeed}}if((this.overflowOffset.left+this.scrollParent[0].offsetWidth)-f.pageX<g.scrollSensitivity){this.scrollParent[0].scrollLeft=b=this.scrollParent[0].scrollLeft+g.scrollSpeed}else{if(f.pageX-this.overflowOffset.left<g.scrollSensitivity){this.scrollParent[0].scrollLeft=b=this.scrollParent[0].scrollLeft-g.scrollSpeed}}}else{if(f.pageY-a(document).scrollTop()<g.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()-g.scrollSpeed)}else{if(a(window).height()-(f.pageY-a(document).scrollTop())<g.scrollSensitivity){b=a(document).scrollTop(a(document).scrollTop()+g.scrollSpeed)}}if(f.pageX-a(document).scrollLeft()<g.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()-g.scrollSpeed)}else{if(a(window).width()-(f.pageX-a(document).scrollLeft())<g.scrollSensitivity){b=a(document).scrollLeft(a(document).scrollLeft()+g.scrollSpeed)}}}if(b!==false&&a.ui.ddmanager&&!g.dropBehaviour){a.ui.ddmanager.prepareOffsets(this,f)}}this.positionAbs=this._convertPositionTo("absolute");if(!this.options.axis||this.options.axis!="y"){this.helper[0].style.left=this.position.left+"px"}if(!this.options.axis||this.options.axis!="x"){this.helper[0].style.top=this.position.top+"px"}for(var d=this.items.length-1;d>=0;d--){var e=this.items[d],c=e.item[0],h=this._intersectsWithPointer(e);if(!h){continue}if(c!=this.currentItem[0]&&this.placeholder[h==1?"next":"prev"]()[0]!=c&&!a.ui.contains(this.placeholder[0],c)&&(this.options.type=="semi-dynamic"?!a.ui.contains(this.element[0],c):true)){this.direction=h==1?"down":"up";if(this.options.tolerance=="pointer"||this._intersectsWithSides(e)){this._rearrange(f,e)}else{break}this._trigger("change",f,this._uiHash());break}}this._contactContainers(f);if(a.ui.ddmanager){a.ui.ddmanager.drag(this,f)}this._trigger("sort",f,this._uiHash());this.lastPositionAbs=this.positionAbs;return false},_mouseStop:function(c,d){if(!c){return}if(a.ui.ddmanager&&!this.options.dropBehaviour){a.ui.ddmanager.drop(this,c)}if(this.options.revert){var b=this;var e=b.placeholder.offset();b.reverting=true;a(this.helper).animate({left:e.left-this.offset.parent.left-b.margins.left+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollLeft),top:e.top-this.offset.parent.top-b.margins.top+(this.offsetParent[0]==document.body?0:this.offsetParent[0].scrollTop)},parseInt(this.options.revert,10)||500,function(){b._clear(c)})}else{this._clear(c,d)}return false},cancel:function(){var b=this;if(this.dragging){this._mouseUp();if(this.options.helper=="original"){this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else{this.currentItem.show()}for(var c=this.containers.length-1;c>=0;c--){this.containers[c]._trigger("deactivate",null,b._uiHash(this));if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",null,b._uiHash(this));this.containers[c].containerCache.over=0}}}if(this.placeholder[0].parentNode){this.placeholder[0].parentNode.removeChild(this.placeholder[0])}if(this.options.helper!="original"&&this.helper&&this.helper[0].parentNode){this.helper.remove()}a.extend(this,{helper:null,dragging:false,reverting:false,_noFinalSort:null});if(this.domPosition.prev){a(this.domPosition.prev).after(this.currentItem)}else{a(this.domPosition.parent).prepend(this.currentItem)}return true},serialize:function(d){var b=this._getItemsAsjQuery(d&&d.connected);var c=[];d=d||{};a(b).each(function(){var e=(a(d.item||this).attr(d.attribute||"id")||"").match(d.expression||(/(.+)[-=_](.+)/));if(e){c.push((d.key||e[1]+"[]")+"="+(d.key&&d.expression?e[1]:e[2]))}});return c.join("&")},toArray:function(d){var b=this._getItemsAsjQuery(d&&d.connected);var c=[];d=d||{};b.each(function(){c.push(a(d.item||this).attr(d.attribute||"id")||"")});return c},_intersectsWith:function(m){var e=this.positionAbs.left,d=e+this.helperProportions.width,k=this.positionAbs.top,j=k+this.helperProportions.height;var f=m.left,c=f+m.width,n=m.top,i=n+m.height;var o=this.offset.click.top,h=this.offset.click.left;var g=(k+o)>n&&(k+o)<i&&(e+h)>f&&(e+h)<c;if(this.options.tolerance=="pointer"||this.options.forcePointerForContainers||(this.options.tolerance!="pointer"&&this.helperProportions[this.floating?"width":"height"]>m[this.floating?"width":"height"])){return g}else{return(f<e+(this.helperProportions.width/2)&&d-(this.helperProportions.width/2)<c&&n<k+(this.helperProportions.height/2)&&j-(this.helperProportions.height/2)<i)}},_intersectsWithPointer:function(d){var e=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,d.top,d.height),c=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,d.left,d.width),g=e&&c,b=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();if(!g){return false}return this.floating?(((f&&f=="right")||b=="down")?2:1):(b&&(b=="down"?2:1))},_intersectsWithSides:function(e){var c=a.ui.isOverAxis(this.positionAbs.top+this.offset.click.top,e.top+(e.height/2),e.height),d=a.ui.isOverAxis(this.positionAbs.left+this.offset.click.left,e.left+(e.width/2),e.width),b=this._getDragVerticalDirection(),f=this._getDragHorizontalDirection();if(this.floating&&f){return((f=="right"&&d)||(f=="left"&&!d))}else{return b&&((b=="down"&&c)||(b=="up"&&!c))}},_getDragVerticalDirection:function(){var b=this.positionAbs.top-this.lastPositionAbs.top;return b!=0&&(b>0?"down":"up")},_getDragHorizontalDirection:function(){var b=this.positionAbs.left-this.lastPositionAbs.left;return b!=0&&(b>0?"right":"left")},refresh:function(b){this._refreshItems(b);this.refreshPositions()},_connectWith:function(){var b=this.options;return b.connectWith.constructor==String?[b.connectWith]:b.connectWith},_getItemsAsjQuery:function(b){var l=this;var g=[];var e=[];var h=this._connectWith();if(h&&b){for(var d=h.length-1;d>=0;d--){var k=a(h[d]);for(var c=k.length-1;c>=0;c--){var f=a.data(k[c],"sortable");if(f&&f!=this&&!f.options.disabled){e.push([a.isFunction(f.options.items)?f.options.items.call(f.element):a(f.options.items,f.element).not(".ui-sortable-helper"),f])}}}}e.push([a.isFunction(this.options.items)?this.options.items.call(this.element,null,{options:this.options,item:this.currentItem}):a(this.options.items,this.element).not(".ui-sortable-helper"),this]);for(var d=e.length-1;d>=0;d--){e[d][0].each(function(){g.push(this)})}return a(g)},_removeCurrentsFromItems:function(){var d=this.currentItem.find(":data(sortable-item)");for(var c=0;c<this.items.length;c++){for(var b=0;b<d.length;b++){if(d[b]==this.items[c].item[0]){this.items.splice(c,1)}}}},_refreshItems:function(b){this.items=[];this.containers=[this];var h=this.items;var p=this;var f=[[a.isFunction(this.options.items)?this.options.items.call(this.element[0],b,{item:this.currentItem}):a(this.options.items,this.element),this]];var l=this._connectWith();if(l){for(var e=l.length-1;e>=0;e--){var m=a(l[e]);for(var d=m.length-1;d>=0;d--){var g=a.data(m[d],"sortable");if(g&&g!=this&&!g.options.disabled){f.push([a.isFunction(g.options.items)?g.options.items.call(g.element[0],b,{item:this.currentItem}):a(g.options.items,g.element),g]);this.containers.push(g)}}}}for(var e=f.length-1;e>=0;e--){var k=f[e][1];var c=f[e][0];for(var d=0,n=c.length;d<n;d++){var o=a(c[d]);o.data("sortable-item",k);h.push({item:o,instance:k,width:0,height:0,left:0,top:0})}}},refreshPositions:function(b){if(this.offsetParent&&this.helper){this.offset.parent=this._getParentOffset()}for(var d=this.items.length-1;d>=0;d--){var e=this.items[d];if(e.instance!=this.currentContainer&&this.currentContainer&&e.item[0]!=this.currentItem[0]){continue}var c=this.options.toleranceElement?a(this.options.toleranceElement,e.item):e.item;if(!b){e.width=c.outerWidth();e.height=c.outerHeight()}var f=c.offset();e.left=f.left;e.top=f.top}if(this.options.custom&&this.options.custom.refreshContainers){this.options.custom.refreshContainers.call(this)}else{for(var d=this.containers.length-1;d>=0;d--){var f=this.containers[d].element.offset();this.containers[d].containerCache.left=f.left;this.containers[d].containerCache.top=f.top;this.containers[d].containerCache.width=this.containers[d].element.outerWidth();this.containers[d].containerCache.height=this.containers[d].element.outerHeight()}}},_createPlaceholder:function(d){var b=d||this,e=b.options;if(!e.placeholder||e.placeholder.constructor==String){var c=e.placeholder;e.placeholder={element:function(){var f=a(document.createElement(b.currentItem[0].nodeName)).addClass(c||b.currentItem[0].className+" ui-sortable-placeholder").removeClass("ui-sortable-helper")[0];if(!c){f.style.visibility="hidden"}return f},update:function(f,g){if(c&&!e.forcePlaceholderSize){return}if(!g.height()){g.height(b.currentItem.innerHeight()-parseInt(b.currentItem.css("paddingTop")||0,10)-parseInt(b.currentItem.css("paddingBottom")||0,10))}if(!g.width()){g.width(b.currentItem.innerWidth()-parseInt(b.currentItem.css("paddingLeft")||0,10)-parseInt(b.currentItem.css("paddingRight")||0,10))}}}}b.placeholder=a(e.placeholder.element.call(b.element,b.currentItem));b.currentItem.after(b.placeholder);e.placeholder.update(b,b.placeholder)},_contactContainers:function(d){for(var c=this.containers.length-1;c>=0;c--){if(this._intersectsWith(this.containers[c].containerCache)){if(!this.containers[c].containerCache.over){if(this.currentContainer!=this.containers[c]){var h=10000;var g=null;var e=this.positionAbs[this.containers[c].floating?"left":"top"];for(var b=this.items.length-1;b>=0;b--){if(!a.ui.contains(this.containers[c].element[0],this.items[b].item[0])){continue}var f=this.items[b][this.containers[c].floating?"left":"top"];if(Math.abs(f-e)<h){h=Math.abs(f-e);g=this.items[b]}}if(!g&&!this.options.dropOnEmpty){continue}this.currentContainer=this.containers[c];g?this._rearrange(d,g,null,true):this._rearrange(d,null,this.containers[c].element,true);this._trigger("change",d,this._uiHash());this.containers[c]._trigger("change",d,this._uiHash(this));this.options.placeholder.update(this.currentContainer,this.placeholder)}this.containers[c]._trigger("over",d,this._uiHash(this));this.containers[c].containerCache.over=1}}else{if(this.containers[c].containerCache.over){this.containers[c]._trigger("out",d,this._uiHash(this));this.containers[c].containerCache.over=0}}}},_createHelper:function(c){var d=this.options;var b=a.isFunction(d.helper)?a(d.helper.apply(this.element[0],[c,this.currentItem])):(d.helper=="clone"?this.currentItem.clone():this.currentItem);if(!b.parents("body").length){a(d.appendTo!="parent"?d.appendTo:this.currentItem[0].parentNode)[0].appendChild(b[0])}if(b[0]==this.currentItem[0]){this._storedCSS={width:this.currentItem[0].style.width,height:this.currentItem[0].style.height,position:this.currentItem.css("position"),top:this.currentItem.css("top"),left:this.currentItem.css("left")}}if(b[0].style.width==""||d.forceHelperSize){b.width(this.currentItem.width())}if(b[0].style.height==""||d.forceHelperSize){b.height(this.currentItem.height())}return b},_adjustOffsetFromHelper:function(b){if(b.left!=undefined){this.offset.click.left=b.left+this.margins.left}if(b.right!=undefined){this.offset.click.left=this.helperProportions.width-b.right+this.margins.left}if(b.top!=undefined){this.offset.click.top=b.top+this.margins.top}if(b.bottom!=undefined){this.offset.click.top=this.helperProportions.height-b.bottom+this.margins.top}},_getParentOffset:function(){this.offsetParent=this.helper.offsetParent();var b=this.offsetParent.offset();if(this.cssPosition=="absolute"&&this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0])){b.left+=this.scrollParent.scrollLeft();b.top+=this.scrollParent.scrollTop()}if((this.offsetParent[0]==document.body)||(this.offsetParent[0].tagName&&this.offsetParent[0].tagName.toLowerCase()=="html"&&a.browser.msie)){b={top:0,left:0}}return{top:b.top+(parseInt(this.offsetParent.css("borderTopWidth"),10)||0),left:b.left+(parseInt(this.offsetParent.css("borderLeftWidth"),10)||0)}},_getRelativeOffset:function(){if(this.cssPosition=="relative"){var b=this.currentItem.position();return{top:b.top-(parseInt(this.helper.css("top"),10)||0)+this.scrollParent.scrollTop(),left:b.left-(parseInt(this.helper.css("left"),10)||0)+this.scrollParent.scrollLeft()}}else{return{top:0,left:0}}},_cacheMargins:function(){this.margins={left:(parseInt(this.currentItem.css("marginLeft"),10)||0),top:(parseInt(this.currentItem.css("marginTop"),10)||0)}},_cacheHelperProportions:function(){this.helperProportions={width:this.helper.outerWidth(),height:this.helper.outerHeight()}},_setContainment:function(){var e=this.options;if(e.containment=="parent"){e.containment=this.helper[0].parentNode}if(e.containment=="document"||e.containment=="window"){this.containment=[0-this.offset.relative.left-this.offset.parent.left,0-this.offset.relative.top-this.offset.parent.top,a(e.containment=="document"?document:window).width()-this.helperProportions.width-this.margins.left,(a(e.containment=="document"?document:window).height()||document.body.parentNode.scrollHeight)-this.helperProportions.height-this.margins.top]}if(!(/^(document|window|parent)$/).test(e.containment)){var c=a(e.containment)[0];var d=a(e.containment).offset();var b=(a(c).css("overflow")!="hidden");this.containment=[d.left+(parseInt(a(c).css("borderLeftWidth"),10)||0)+(parseInt(a(c).css("paddingLeft"),10)||0)-this.margins.left,d.top+(parseInt(a(c).css("borderTopWidth"),10)||0)+(parseInt(a(c).css("paddingTop"),10)||0)-this.margins.top,d.left+(b?Math.max(c.scrollWidth,c.offsetWidth):c.offsetWidth)-(parseInt(a(c).css("borderLeftWidth"),10)||0)-(parseInt(a(c).css("paddingRight"),10)||0)-this.helperProportions.width-this.margins.left,d.top+(b?Math.max(c.scrollHeight,c.offsetHeight):c.offsetHeight)-(parseInt(a(c).css("borderTopWidth"),10)||0)-(parseInt(a(c).css("paddingBottom"),10)||0)-this.helperProportions.height-this.margins.top]}},_convertPositionTo:function(f,h){if(!h){h=this.position}var c=f=="absolute"?1:-1;var e=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,g=(/(html|body)/i).test(b[0].tagName);return{top:(h.top+this.offset.relative.top*c+this.offset.parent.top*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(g?0:b.scrollTop()))*c)),left:(h.left+this.offset.relative.left*c+this.offset.parent.left*c-(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():g?0:b.scrollLeft())*c))}},_generatePosition:function(e){var h=this.options,b=this.cssPosition=="absolute"&&!(this.scrollParent[0]!=document&&a.ui.contains(this.scrollParent[0],this.offsetParent[0]))?this.offsetParent:this.scrollParent,i=(/(html|body)/i).test(b[0].tagName);if(this.cssPosition=="relative"&&!(this.scrollParent[0]!=document&&this.scrollParent[0]!=this.offsetParent[0])){this.offset.relative=this._getRelativeOffset()}var d=e.pageX;var c=e.pageY;if(this.originalPosition){if(this.containment){if(e.pageX-this.offset.click.left<this.containment[0]){d=this.containment[0]+this.offset.click.left}if(e.pageY-this.offset.click.top<this.containment[1]){c=this.containment[1]+this.offset.click.top}if(e.pageX-this.offset.click.left>this.containment[2]){d=this.containment[2]+this.offset.click.left}if(e.pageY-this.offset.click.top>this.containment[3]){c=this.containment[3]+this.offset.click.top}}if(h.grid){var g=this.originalPageY+Math.round((c-this.originalPageY)/h.grid[1])*h.grid[1];c=this.containment?(!(g-this.offset.click.top<this.containment[1]||g-this.offset.click.top>this.containment[3])?g:(!(g-this.offset.click.top<this.containment[1])?g-h.grid[1]:g+h.grid[1])):g;var f=this.originalPageX+Math.round((d-this.originalPageX)/h.grid[0])*h.grid[0];d=this.containment?(!(f-this.offset.click.left<this.containment[0]||f-this.offset.click.left>this.containment[2])?f:(!(f-this.offset.click.left<this.containment[0])?f-h.grid[0]:f+h.grid[0])):f}}return{top:(c-this.offset.click.top-this.offset.relative.top-this.offset.parent.top+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollTop():(i?0:b.scrollTop())))),left:(d-this.offset.click.left-this.offset.relative.left-this.offset.parent.left+(a.browser.safari&&this.cssPosition=="fixed"?0:(this.cssPosition=="fixed"?-this.scrollParent.scrollLeft():i?0:b.scrollLeft())))}},_rearrange:function(g,f,c,e){c?c[0].appendChild(this.placeholder[0]):f.item[0].parentNode.insertBefore(this.placeholder[0],(this.direction=="down"?f.item[0]:f.item[0].nextSibling));this.counter=this.counter?++this.counter:1;var d=this,b=this.counter;window.setTimeout(function(){if(b==d.counter){d.refreshPositions(!e)}},0)},_clear:function(d,e){this.reverting=false;var f=[],b=this;if(!this._noFinalSort&&this.currentItem[0].parentNode){this.placeholder.before(this.currentItem)}this._noFinalSort=null;if(this.helper[0]==this.currentItem[0]){for(var c in this._storedCSS){if(this._storedCSS[c]=="auto"||this._storedCSS[c]=="static"){this._storedCSS[c]=""}}this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper")}else{this.currentItem.show()}if(this.fromOutside&&!e){f.push(function(g){this._trigger("receive",g,this._uiHash(this.fromOutside))})}if((this.fromOutside||this.domPosition.prev!=this.currentItem.prev().not(".ui-sortable-helper")[0]||this.domPosition.parent!=this.currentItem.parent()[0])&&!e){f.push(function(g){this._trigger("update",g,this._uiHash())})}if(!a.ui.contains(this.element[0],this.currentItem[0])){if(!e){f.push(function(g){this._trigger("remove",g,this._uiHash())})}for(var c=this.containers.length-1;c>=0;c--){if(a.ui.contains(this.containers[c].element[0],this.currentItem[0])&&!e){f.push((function(g){return function(h){g._trigger("receive",h,this._uiHash(this))}}).call(this,this.containers[c]));f.push((function(g){return function(h){g._trigger("update",h,this._uiHash(this))}}).call(this,this.containers[c]))}}}for(var c=this.containers.length-1;c>=0;c--){if(!e){f.push((function(g){return function(h){g._trigger("deactivate",h,this._uiHash(this))}}).call(this,this.containers[c]))}if(this.containers[c].containerCache.over){f.push((function(g){return function(h){g._trigger("out",h,this._uiHash(this))}}).call(this,this.containers[c]));this.containers[c].containerCache.over=0}}if(this._storedCursor){a("body").css("cursor",this._storedCursor)}if(this._storedOpacity){this.helper.css("opacity",this._storedOpacity)}if(this._storedZIndex){this.helper.css("zIndex",this._storedZIndex=="auto"?"":this._storedZIndex)}this.dragging=false;if(this.cancelHelperRemoval){if(!e){this._trigger("beforeStop",d,this._uiHash());for(var c=0;c<f.length;c++){f[c].call(this,d)}this._trigger("stop",d,this._uiHash())}return false}if(!e){this._trigger("beforeStop",d,this._uiHash())}this.placeholder[0].parentNode.removeChild(this.placeholder[0]);if(this.helper[0]!=this.currentItem[0]){this.helper.remove()}this.helper=null;if(!e){for(var c=0;c<f.length;c++){f[c].call(this,d)}this._trigger("stop",d,this._uiHash())}this.fromOutside=false;return true},_trigger:function(){if(a.widget.prototype._trigger.apply(this,arguments)===false){this.cancel()}},_uiHash:function(c){var b=c||this;return{helper:b.helper,placeholder:b.placeholder||a([]),position:b.position,absolutePosition:b.positionAbs,offset:b.positionAbs,item:b.currentItem,sender:c?c.element:null}}}));a.extend(a.ui.sortable,{getter:"serialize toArray",version:"1.7",eventPrefix:"sort",defaults:{appendTo:"parent",axis:false,cancel:":input,option",connectWith:false,containment:false,cursor:"auto",cursorAt:false,delay:0,distance:1,dropOnEmpty:true,forcePlaceholderSize:false,forceHelperSize:false,grid:false,handle:false,helper:"original",items:"> *",opacity:false,placeholder:false,revert:false,scroll:true,scrollSensitivity:20,scrollSpeed:20,scope:"default",tolerance:"intersect",zIndex:1000}})})(jQuery);;/*
 * jQuery UI Dialog 1.7
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Dialog
 *
 * Depends:
 *	ui.core.js
 *	ui.draggable.js
 *	ui.resizable.js
 */(function(c){var b={dragStart:"start.draggable",drag:"drag.draggable",dragStop:"stop.draggable",maxHeight:"maxHeight.resizable",minHeight:"minHeight.resizable",maxWidth:"maxWidth.resizable",minWidth:"minWidth.resizable",resizeStart:"start.resizable",resize:"drag.resizable",resizeStop:"stop.resizable"},a="ui-dialog ui-widget ui-widget-content ui-corner-all ";c.widget("ui.dialog",{_init:function(){this.originalTitle=this.element.attr("title");var l=this,m=this.options,j=m.title||this.originalTitle||"&nbsp;",e=c.ui.dialog.getTitleId(this.element),k=(this.uiDialog=c("<div/>")).appendTo(document.body).hide().addClass(a+m.dialogClass).css({position:"absolute",overflow:"hidden",zIndex:m.zIndex}).attr("tabIndex",-1).css("outline",0).keydown(function(n){(m.closeOnEscape&&n.keyCode&&n.keyCode==c.ui.keyCode.ESCAPE&&l.close(n))}).attr({role:"dialog","aria-labelledby":e}).mousedown(function(n){l.moveToTop(false,n)}),g=this.element.show().removeAttr("title").addClass("ui-dialog-content ui-widget-content").appendTo(k),f=(this.uiDialogTitlebar=c("<div></div>")).addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix").prependTo(k),i=c('<a href="#"/>').addClass("ui-dialog-titlebar-close ui-corner-all").attr("role","button").hover(function(){i.addClass("ui-state-hover")},function(){i.removeClass("ui-state-hover")}).focus(function(){i.addClass("ui-state-focus")}).blur(function(){i.removeClass("ui-state-focus")}).mousedown(function(n){n.stopPropagation()}).click(function(n){l.close(n);return false}).appendTo(f),h=(this.uiDialogTitlebarCloseText=c("<span/>")).addClass("ui-icon ui-icon-closethick").text(m.closeText).appendTo(i),d=c("<span/>").addClass("ui-dialog-title").attr("id",e).html(j).prependTo(f);f.find("*").add(f).disableSelection();(m.draggable&&c.fn.draggable&&this._makeDraggable());(m.resizable&&c.fn.resizable&&this._makeResizable());this._createButtons(m.buttons);this._isOpen=false;(m.bgiframe&&c.fn.bgiframe&&k.bgiframe());(m.autoOpen&&this.open())},destroy:function(){(this.overlay&&this.overlay.destroy());this.uiDialog.hide();this.element.unbind(".dialog").removeData("dialog").removeClass("ui-dialog-content ui-widget-content").hide().appendTo("body");this.uiDialog.remove();(this.originalTitle&&this.element.attr("title",this.originalTitle))},close:function(e){var d=this;if(false===d._trigger("beforeclose",e)){return}(d.overlay&&d.overlay.destroy());d.uiDialog.unbind("keypress.ui-dialog");(d.options.hide?d.uiDialog.hide(d.options.hide,function(){d._trigger("close",e)}):d.uiDialog.hide()&&d._trigger("close",e));c.ui.dialog.overlay.resize();d._isOpen=false},isOpen:function(){return this._isOpen},moveToTop:function(f,e){if((this.options.modal&&!f)||(!this.options.stack&&!this.options.modal)){return this._trigger("focus",e)}if(this.options.zIndex>c.ui.dialog.maxZ){c.ui.dialog.maxZ=this.options.zIndex}(this.overlay&&this.overlay.$el.css("z-index",c.ui.dialog.overlay.maxZ=++c.ui.dialog.maxZ));var d={scrollTop:this.element.attr("scrollTop"),scrollLeft:this.element.attr("scrollLeft")};this.uiDialog.css("z-index",++c.ui.dialog.maxZ);this.element.attr(d);this._trigger("focus",e)},open:function(){if(this._isOpen){return}var e=this.options,d=this.uiDialog;this.overlay=e.modal?new c.ui.dialog.overlay(this):null;(d.next().length&&d.appendTo("body"));this._size();this._position(e.position);d.show(e.show);this.moveToTop(true);(e.modal&&d.bind("keypress.ui-dialog",function(h){if(h.keyCode!=c.ui.keyCode.TAB){return}var g=c(":tabbable",this),i=g.filter(":first")[0],f=g.filter(":last")[0];if(h.target==f&&!h.shiftKey){setTimeout(function(){i.focus()},1)}else{if(h.target==i&&h.shiftKey){setTimeout(function(){f.focus()},1)}}}));c([]).add(d.find(".ui-dialog-content :tabbable:first")).add(d.find(".ui-dialog-buttonpane :tabbable:first")).add(d).filter(":first").focus();this._trigger("open");this._isOpen=true},_createButtons:function(g){var f=this,d=false,e=c("<div></div>").addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");this.uiDialog.find(".ui-dialog-buttonpane").remove();(typeof g=="object"&&g!==null&&c.each(g,function(){return !(d=true)}));if(d){c.each(g,function(h,i){c('<button type="button"></button>').addClass("ui-state-default ui-corner-all").text(h).click(function(){i.apply(f.element[0],arguments)}).hover(function(){c(this).addClass("ui-state-hover")},function(){c(this).removeClass("ui-state-hover")}).focus(function(){c(this).addClass("ui-state-focus")}).blur(function(){c(this).removeClass("ui-state-focus")}).appendTo(e)});e.appendTo(this.uiDialog)}},_makeDraggable:function(){var d=this,f=this.options,e;this.uiDialog.draggable({cancel:".ui-dialog-content",handle:".ui-dialog-titlebar",containment:"document",start:function(){e=f.height;c(this).height(c(this).height()).addClass("ui-dialog-dragging");(f.dragStart&&f.dragStart.apply(d.element[0],arguments))},drag:function(){(f.drag&&f.drag.apply(d.element[0],arguments))},stop:function(){c(this).removeClass("ui-dialog-dragging").height(e);(f.dragStop&&f.dragStop.apply(d.element[0],arguments));c.ui.dialog.overlay.resize()}})},_makeResizable:function(g){g=(g===undefined?this.options.resizable:g);var d=this,f=this.options,e=typeof g=="string"?g:"n,e,s,w,se,sw,ne,nw";this.uiDialog.resizable({cancel:".ui-dialog-content",alsoResize:this.element,maxWidth:f.maxWidth,maxHeight:f.maxHeight,minWidth:f.minWidth,minHeight:f.minHeight,start:function(){c(this).addClass("ui-dialog-resizing");(f.resizeStart&&f.resizeStart.apply(d.element[0],arguments))},resize:function(){(f.resize&&f.resize.apply(d.element[0],arguments))},handles:e,stop:function(){c(this).removeClass("ui-dialog-resizing");f.height=c(this).height();f.width=c(this).width();(f.resizeStop&&f.resizeStop.apply(d.element[0],arguments));c.ui.dialog.overlay.resize()}}).find(".ui-resizable-se").addClass("ui-icon ui-icon-grip-diagonal-se")},_position:function(i){var e=c(window),f=c(document),g=f.scrollTop(),d=f.scrollLeft(),h=g;if(c.inArray(i,["center","top","right","bottom","left"])>=0){i=[i=="right"||i=="left"?i:"center",i=="top"||i=="bottom"?i:"middle"]}if(i.constructor!=Array){i=["center","middle"]}if(i[0].constructor==Number){d+=i[0]}else{switch(i[0]){case"left":d+=0;break;case"right":d+=e.width()-this.uiDialog.outerWidth();break;default:case"center":d+=(e.width()-this.uiDialog.outerWidth())/2}}if(i[1].constructor==Number){g+=i[1]}else{switch(i[1]){case"top":g+=0;break;case"bottom":g+=e.height()-this.uiDialog.outerHeight();break;default:case"middle":g+=(e.height()-this.uiDialog.outerHeight())/2}}g=Math.max(g,h);this.uiDialog.css({top:g,left:d})},_setData:function(e,f){(b[e]&&this.uiDialog.data(b[e],f));switch(e){case"buttons":this._createButtons(f);break;case"closeText":this.uiDialogTitlebarCloseText.text(f);break;case"dialogClass":this.uiDialog.removeClass(this.options.dialogClass).addClass(a+f);break;case"draggable":(f?this._makeDraggable():this.uiDialog.draggable("destroy"));break;case"height":this.uiDialog.height(f);break;case"position":this._position(f);break;case"resizable":var d=this.uiDialog,g=this.uiDialog.is(":data(resizable)");(g&&!f&&d.resizable("destroy"));(g&&typeof f=="string"&&d.resizable("option","handles",f));(g||this._makeResizable(f));break;case"title":c(".ui-dialog-title",this.uiDialogTitlebar).html(f||"&nbsp;");break;case"width":this.uiDialog.width(f);break}c.widget.prototype._setData.apply(this,arguments)},_size:function(){var e=this.options;this.element.css({height:0,minHeight:0,width:"auto"});var d=this.uiDialog.css({height:"auto",width:e.width}).height();this.element.css({minHeight:Math.max(e.minHeight-d,0),height:e.height=="auto"?"auto":Math.max(e.height-d,0)})}});c.extend(c.ui.dialog,{version:"1.7",defaults:{autoOpen:true,bgiframe:false,buttons:{},closeOnEscape:true,closeText:"close",dialogClass:"",draggable:true,hide:null,height:"auto",maxHeight:false,maxWidth:false,minHeight:150,minWidth:150,modal:false,position:"center",resizable:true,show:null,stack:true,title:"",width:300,zIndex:1000},getter:"isOpen",uuid:0,maxZ:0,getTitleId:function(d){return"ui-dialog-title-"+(d.attr("id")||++this.uuid)},overlay:function(d){this.$el=c.ui.dialog.overlay.create(d)}});c.extend(c.ui.dialog.overlay,{instances:[],maxZ:0,events:c.map("focus,mousedown,mouseup,keydown,keypress,click".split(","),function(d){return d+".dialog-overlay"}).join(" "),create:function(e){if(this.instances.length===0){setTimeout(function(){c(document).bind(c.ui.dialog.overlay.events,function(f){var g=c(f.target).parents(".ui-dialog").css("zIndex")||0;return(g>c.ui.dialog.overlay.maxZ)})},1);c(document).bind("keydown.dialog-overlay",function(f){(e.options.closeOnEscape&&f.keyCode&&f.keyCode==c.ui.keyCode.ESCAPE&&e.close(f))});c(window).bind("resize.dialog-overlay",c.ui.dialog.overlay.resize)}var d=c("<div></div>").appendTo(document.body).addClass("ui-widget-overlay").css({width:this.width(),height:this.height()});(e.options.bgiframe&&c.fn.bgiframe&&d.bgiframe());this.instances.push(d);return d},destroy:function(d){this.instances.splice(c.inArray(this.instances,d),1);if(this.instances.length===0){c([document,window]).unbind(".dialog-overlay")}d.remove()},height:function(){if(c.browser.msie&&c.browser.version<7){var e=Math.max(document.documentElement.scrollHeight,document.body.scrollHeight);var d=Math.max(document.documentElement.offsetHeight,document.body.offsetHeight);if(e<d){return c(window).height()+"px"}else{return e+"px"}}else{return c(document).height()+"px"}},width:function(){if(c.browser.msie&&c.browser.version<7){var d=Math.max(document.documentElement.scrollWidth,document.body.scrollWidth);var e=Math.max(document.documentElement.offsetWidth,document.body.offsetWidth);if(d<e){return c(window).width()+"px"}else{return d+"px"}}else{return c(document).width()+"px"}},resize:function(){var d=c([]);c.each(c.ui.dialog.overlay.instances,function(){d=d.add(this)});d.css({width:0,height:0}).css({width:c.ui.dialog.overlay.width(),height:c.ui.dialog.overlay.height()})}});c.extend(c.ui.dialog.overlay.prototype,{destroy:function(){c.ui.dialog.overlay.destroy(this.$el)}})})(jQuery);;/*
 * jQuery UI Effects 1.7
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/
 */jQuery.effects||(function(d){d.effects={version:"1.7",save:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.data("ec.storage."+h[f],g[0].style[h[f]])}}},restore:function(g,h){for(var f=0;f<h.length;f++){if(h[f]!==null){g.css(h[f],g.data("ec.storage."+h[f]))}}},setMode:function(f,g){if(g=="toggle"){g=f.is(":hidden")?"show":"hide"}return g},getBaseline:function(g,h){var i,f;switch(g[0]){case"top":i=0;break;case"middle":i=0.5;break;case"bottom":i=1;break;default:i=g[0]/h.height}switch(g[1]){case"left":f=0;break;case"center":f=0.5;break;case"right":f=1;break;default:f=g[1]/h.width}return{x:f,y:i}},createWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent()}var g={width:f.outerWidth(true),height:f.outerHeight(true),"float":f.css("float")};f.wrap('<div class="ui-effects-wrapper" style="font-size:100%;background:transparent;border:none;margin:0;padding:0"></div>');var j=f.parent();if(f.css("position")=="static"){j.css({position:"relative"});f.css({position:"relative"})}else{var i=f.css("top");if(isNaN(parseInt(i,10))){i="auto"}var h=f.css("left");if(isNaN(parseInt(h,10))){h="auto"}j.css({position:f.css("position"),top:i,left:h,zIndex:f.css("z-index")}).show();f.css({position:"relative",top:0,left:0})}j.css(g);return j},removeWrapper:function(f){if(f.parent().is(".ui-effects-wrapper")){return f.parent().replaceWith(f)}return f},setTransition:function(g,i,f,h){h=h||{};d.each(i,function(k,j){unit=g.cssUnit(j);if(unit[0]>0){h[j]=unit[0]*f+unit[1]}});return h},animateClass:function(h,i,k,j){var f=(typeof k=="function"?k:(j?j:null));var g=(typeof k=="string"?k:null);return this.each(function(){var q={};var o=d(this);var p=o.attr("style")||"";if(typeof p=="object"){p=p.cssText}if(h.toggle){o.hasClass(h.toggle)?h.remove=h.toggle:h.add=h.toggle}var l=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.addClass(h.add)}if(h.remove){o.removeClass(h.remove)}var m=d.extend({},(document.defaultView?document.defaultView.getComputedStyle(this,null):this.currentStyle));if(h.add){o.removeClass(h.add)}if(h.remove){o.addClass(h.remove)}for(var r in m){if(typeof m[r]!="function"&&m[r]&&r.indexOf("Moz")==-1&&r.indexOf("length")==-1&&m[r]!=l[r]&&(r.match(/color/i)||(!r.match(/color/i)&&!isNaN(parseInt(m[r],10))))&&(l.position!="static"||(l.position=="static"&&!r.match(/left|top|bottom|right/)))){q[r]=m[r]}}o.animate(q,i,g,function(){if(typeof d(this).attr("style")=="object"){d(this).attr("style")["cssText"]="";d(this).attr("style")["cssText"]=p}else{d(this).attr("style",p)}if(h.add){d(this).addClass(h.add)}if(h.remove){d(this).removeClass(h.remove)}if(f){f.apply(this,arguments)}})})}};function c(g,f){var i=g[1]&&g[1].constructor==Object?g[1]:{};if(f){i.mode=f}var h=g[1]&&g[1].constructor!=Object?g[1]:(i.duration?i.duration:g[2]);h=d.fx.off?0:typeof h==="number"?h:d.fx.speeds[h]||d.fx.speeds._default;var j=i.callback||(d.isFunction(g[1])&&g[1])||(d.isFunction(g[2])&&g[2])||(d.isFunction(g[3])&&g[3]);return[g[0],i,h,j]}d.fn.extend({_show:d.fn.show,_hide:d.fn.hide,__toggle:d.fn.toggle,_addClass:d.fn.addClass,_removeClass:d.fn.removeClass,_toggleClass:d.fn.toggleClass,effect:function(g,f,h,i){return d.effects[g]?d.effects[g].call(this,{method:g,options:f||{},duration:h,callback:i}):null},show:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._show.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"show"))}},hide:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))){return this._hide.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"hide"))}},toggle:function(){if(!arguments[0]||(arguments[0].constructor==Number||(/(slow|normal|fast)/).test(arguments[0]))||(arguments[0].constructor==Function)){return this.__toggle.apply(this,arguments)}else{return this.effect.apply(this,c(arguments,"toggle"))}},addClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{add:g},f,i,h]):this._addClass(g)},removeClass:function(g,f,i,h){return f?d.effects.animateClass.apply(this,[{remove:g},f,i,h]):this._removeClass(g)},toggleClass:function(g,f,i,h){return((typeof f!=="boolean")&&f)?d.effects.animateClass.apply(this,[{toggle:g},f,i,h]):this._toggleClass(g,f)},morph:function(f,h,g,j,i){return d.effects.animateClass.apply(this,[{add:h,remove:f},g,j,i])},switchClass:function(){return this.morph.apply(this,arguments)},cssUnit:function(f){var g=this.css(f),h=[];d.each(["em","px","%","pt"],function(j,k){if(g.indexOf(k)>0){h=[parseFloat(g),k]}});return h}});d.each(["backgroundColor","borderBottomColor","borderLeftColor","borderRightColor","borderTopColor","color","outlineColor"],function(g,f){d.fx.step[f]=function(h){if(h.state==0){h.start=e(h.elem,f);h.end=b(h.end)}h.elem.style[f]="rgb("+[Math.max(Math.min(parseInt((h.pos*(h.end[0]-h.start[0]))+h.start[0],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[1]-h.start[1]))+h.start[1],10),255),0),Math.max(Math.min(parseInt((h.pos*(h.end[2]-h.start[2]))+h.start[2],10),255),0)].join(",")+")"}});function b(g){var f;if(g&&g.constructor==Array&&g.length==3){return g}if(f=/rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(g)){return[parseInt(f[1],10),parseInt(f[2],10),parseInt(f[3],10)]}if(f=/rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(g)){return[parseFloat(f[1])*2.55,parseFloat(f[2])*2.55,parseFloat(f[3])*2.55]}if(f=/#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(g)){return[parseInt(f[1],16),parseInt(f[2],16),parseInt(f[3],16)]}if(f=/#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(g)){return[parseInt(f[1]+f[1],16),parseInt(f[2]+f[2],16),parseInt(f[3]+f[3],16)]}if(f=/rgba\(0, 0, 0, 0\)/.exec(g)){return a.transparent}return a[d.trim(g).toLowerCase()]}function e(h,f){var g;do{g=d.curCSS(h,f);if(g!=""&&g!="transparent"||d.nodeName(h,"body")){break}f="backgroundColor"}while(h=h.parentNode);return b(g)}var a={aqua:[0,255,255],azure:[240,255,255],beige:[245,245,220],black:[0,0,0],blue:[0,0,255],brown:[165,42,42],cyan:[0,255,255],darkblue:[0,0,139],darkcyan:[0,139,139],darkgrey:[169,169,169],darkgreen:[0,100,0],darkkhaki:[189,183,107],darkmagenta:[139,0,139],darkolivegreen:[85,107,47],darkorange:[255,140,0],darkorchid:[153,50,204],darkred:[139,0,0],darksalmon:[233,150,122],darkviolet:[148,0,211],fuchsia:[255,0,255],gold:[255,215,0],green:[0,128,0],indigo:[75,0,130],khaki:[240,230,140],lightblue:[173,216,230],lightcyan:[224,255,255],lightgreen:[144,238,144],lightgrey:[211,211,211],lightpink:[255,182,193],lightyellow:[255,255,224],lime:[0,255,0],magenta:[255,0,255],maroon:[128,0,0],navy:[0,0,128],olive:[128,128,0],orange:[255,165,0],pink:[255,192,203],purple:[128,0,128],violet:[128,0,128],red:[255,0,0],silver:[192,192,192],white:[255,255,255],yellow:[255,255,0],transparent:[255,255,255]};d.easing.jswing=d.easing.swing;d.extend(d.easing,{def:"easeOutQuad",swing:function(g,h,f,j,i){return d.easing[d.easing.def](g,h,f,j,i)},easeInQuad:function(g,h,f,j,i){return j*(h/=i)*h+f},easeOutQuad:function(g,h,f,j,i){return -j*(h/=i)*(h-2)+f},easeInOutQuad:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h+f}return -j/2*((--h)*(h-2)-1)+f},easeInCubic:function(g,h,f,j,i){return j*(h/=i)*h*h+f},easeOutCubic:function(g,h,f,j,i){return j*((h=h/i-1)*h*h+1)+f},easeInOutCubic:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h+f}return j/2*((h-=2)*h*h+2)+f},easeInQuart:function(g,h,f,j,i){return j*(h/=i)*h*h*h+f},easeOutQuart:function(g,h,f,j,i){return -j*((h=h/i-1)*h*h*h-1)+f},easeInOutQuart:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h+f}return -j/2*((h-=2)*h*h*h-2)+f},easeInQuint:function(g,h,f,j,i){return j*(h/=i)*h*h*h*h+f},easeOutQuint:function(g,h,f,j,i){return j*((h=h/i-1)*h*h*h*h+1)+f},easeInOutQuint:function(g,h,f,j,i){if((h/=i/2)<1){return j/2*h*h*h*h*h+f}return j/2*((h-=2)*h*h*h*h+2)+f},easeInSine:function(g,h,f,j,i){return -j*Math.cos(h/i*(Math.PI/2))+j+f},easeOutSine:function(g,h,f,j,i){return j*Math.sin(h/i*(Math.PI/2))+f},easeInOutSine:function(g,h,f,j,i){return -j/2*(Math.cos(Math.PI*h/i)-1)+f},easeInExpo:function(g,h,f,j,i){return(h==0)?f:j*Math.pow(2,10*(h/i-1))+f},easeOutExpo:function(g,h,f,j,i){return(h==i)?f+j:j*(-Math.pow(2,-10*h/i)+1)+f},easeInOutExpo:function(g,h,f,j,i){if(h==0){return f}if(h==i){return f+j}if((h/=i/2)<1){return j/2*Math.pow(2,10*(h-1))+f}return j/2*(-Math.pow(2,-10*--h)+2)+f},easeInCirc:function(g,h,f,j,i){return -j*(Math.sqrt(1-(h/=i)*h)-1)+f},easeOutCirc:function(g,h,f,j,i){return j*Math.sqrt(1-(h=h/i-1)*h)+f},easeInOutCirc:function(g,h,f,j,i){if((h/=i/2)<1){return -j/2*(Math.sqrt(1-h*h)-1)+f}return j/2*(Math.sqrt(1-(h-=2)*h)+1)+f},easeInElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return -(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f},easeOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l)==1){return f+m}if(!k){k=l*0.3}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}return h*Math.pow(2,-10*i)*Math.sin((i*l-j)*(2*Math.PI)/k)+m+f},easeInOutElastic:function(g,i,f,m,l){var j=1.70158;var k=0;var h=m;if(i==0){return f}if((i/=l/2)==2){return f+m}if(!k){k=l*(0.3*1.5)}if(h<Math.abs(m)){h=m;var j=k/4}else{var j=k/(2*Math.PI)*Math.asin(m/h)}if(i<1){return -0.5*(h*Math.pow(2,10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k))+f}return h*Math.pow(2,-10*(i-=1))*Math.sin((i*l-j)*(2*Math.PI)/k)*0.5+m+f},easeInBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*(h/=j)*h*((i+1)*h-i)+f},easeOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}return k*((h=h/j-1)*h*((i+1)*h+i)+1)+f},easeInOutBack:function(g,h,f,k,j,i){if(i==undefined){i=1.70158}if((h/=j/2)<1){return k/2*(h*h*(((i*=(1.525))+1)*h-i))+f}return k/2*((h-=2)*h*(((i*=(1.525))+1)*h+i)+2)+f},easeInBounce:function(g,h,f,j,i){return j-d.easing.easeOutBounce(g,i-h,0,j,i)+f},easeOutBounce:function(g,h,f,j,i){if((h/=i)<(1/2.75)){return j*(7.5625*h*h)+f}else{if(h<(2/2.75)){return j*(7.5625*(h-=(1.5/2.75))*h+0.75)+f}else{if(h<(2.5/2.75)){return j*(7.5625*(h-=(2.25/2.75))*h+0.9375)+f}else{return j*(7.5625*(h-=(2.625/2.75))*h+0.984375)+f}}}},easeInOutBounce:function(g,h,f,j,i){if(h<i/2){return d.easing.easeInBounce(g,h*2,0,j,i)*0.5+f}return d.easing.easeOutBounce(g,h*2-i,0,j,i)*0.5+j*0.5+f}})})(jQuery);;/*
 * jQuery UI Effects Blind 1.7
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Blind
 *
 * Depends:
 *	effects.core.js
 */(function(a){a.effects.blind=function(b){return this.queue(function(){var d=a(this),c=["position","top","left"];var h=a.effects.setMode(d,b.options.mode||"hide");var g=b.options.direction||"vertical";a.effects.save(d,c);d.show();var j=a.effects.createWrapper(d).css({overflow:"hidden"});var e=(g=="vertical")?"height":"width";var i=(g=="vertical")?j.height():j.width();if(h=="show"){j.css(e,0)}var f={};f[e]=h=="show"?i:0;j.animate(f,b.duration,b.options.easing,function(){if(h=="hide"){d.hide()}a.effects.restore(d,c);a.effects.removeWrapper(d);if(b.callback){b.callback.apply(d[0],arguments)}d.dequeue()})})}})(jQuery);;/*
 * jQuery UI Effects Slide 1.7
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Slide
 *
 * Depends:
 *	effects.core.js
 */(function(a){a.effects.slide=function(b){return this.queue(function(){var e=a(this),d=["position","top","left"];var i=a.effects.setMode(e,b.options.mode||"show");var h=b.options.direction||"left";a.effects.save(e,d);e.show();a.effects.createWrapper(e).css({overflow:"hidden"});var f=(h=="up"||h=="down")?"top":"left";var c=(h=="up"||h=="left")?"pos":"neg";var j=b.options.distance||(f=="top"?e.outerHeight({margin:true}):e.outerWidth({margin:true}));if(i=="show"){e.css(f,c=="pos"?-j:j)}var g={};g[f]=(i=="show"?(c=="pos"?"+=":"-="):(c=="pos"?"-=":"+="))+j;e.animate(g,{queue:false,duration:b.duration,easing:b.options.easing,complete:function(){if(i=="hide"){e.hide()}a.effects.restore(e,d);a.effects.removeWrapper(e);if(b.callback){b.callback.apply(this,arguments)}e.dequeue()}})})}})(jQuery);;

/** File: javascript/jquery.cookie.js **/

/**
 * Cookie plugin
 *
 * Copyright (c) 2006 Klaus Hartl (stilbuero.de)
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 *
 */

/**
 * Create a cookie with the given name and value and other optional parameters.
 *
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Set the value of a cookie.
 * @example $.cookie('the_cookie', 'the_value', { expires: 7, path: '/', domain: 'jquery.com', secure: true });
 * @desc Create a cookie with all available options.
 * @example $.cookie('the_cookie', 'the_value');
 * @desc Create a session cookie.
 * @example $.cookie('the_cookie', null);
 * @desc Delete a cookie by passing null as value. Keep in mind that you have to use the same path and domain
 *       used when the cookie was set.
 *
 * @param String name The name of the cookie.
 * @param String value The value of the cookie.
 * @param Object options An object literal containing key/value pairs to provide optional cookie attributes.
 * @option Number|Date expires Either an integer specifying the expiration date from now on in days or a Date object.
 *                             If a negative value is specified (e.g. a date in the past), the cookie will be deleted.
 *                             If set to null or omitted, the cookie will be a session cookie and will not be retained
 *                             when the the browser exits.
 * @option String path The value of the path atribute of the cookie (default: path of page that created the cookie).
 * @option String domain The value of the domain attribute of the cookie (default: domain of page that created the cookie).
 * @option Boolean secure If true, the secure attribute of the cookie will be set and the cookie transmission will
 *                        require a secure protocol (like HTTPS).
 * @type undefined
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */

/**
 * Get the value of a cookie with the given name.
 *
 * @example $.cookie('the_cookie');
 * @desc Get the value of a cookie.
 *
 * @param String name The name of the cookie.
 * @return The value of the cookie.
 * @type String
 *
 * @name $.cookie
 * @cat Plugins/Cookie
 * @author Klaus Hartl/klaus.hartl@stilbuero.de
 */
jQuery.cookie = function(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};

/** File: javascript/jquery.insertAtCursor.js **/

/**
 * insert text at carret location.
 */
jQuery.fn.insertAtCursor = function(string_to_insert) {
  return this.each(function() {
    var input_field = $(this);

    if ($.browser.msie) {
      input_field.focus();
      document.selection.createRange().text = string_to_insert;
      input_field.focus();
    } else {
      // find selection boundaries
      var selection_start = input_field[0].selectionStart;
      var selection_end = input_field[0].selectionEnd;   
      
      if (selection_start || selection_start == '0') {
        // make new string and insert it in input
        var new_string = input_field.val().substring(0, selection_start) + string_to_insert + input_field.val().substring(selection_end, input_field.val().length);
        input_field.val(new_string);
        input_field[0].selectionStart = input_field[0].selectionEnd = selection_start + string_to_insert.length;       
      } else {
        input_field.val(input_field.val() + string_to_insert);
      } // if
      input_field.focus();
    } // if
  });
};

/** File: javascript/jquery.tree_component.js **/

/*
 * jsTree 0.9.5
 * (jstree.com)
 *
 * Copyright (c) 2008 Ivan Bozhanov (vakata.com)
 *
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 *
 * Date: 2009-01-12
 *
 */

// jQuery plugin
jQuery.fn.tree = function (opts) {
	return this.each(function() {
		if(tree_component.inst && tree_component.inst[jQuery(this).attr('id')]) 
			tree_component.inst[jQuery(this).attr('id')].destroy();
		if(opts !== false) {
			var tmp = new tree_component();
			tmp.init(this, opts);
		}
	});
};

// core
function tree_component () {
	// instance manager
	if(typeof tree_component.inst == "undefined") {
		tree_component.cntr = 0;
		tree_component.inst = new Array();
		tree_component.drop = new Array();

		tree_component.focusInst = function () {
			return tree_component.inst[tree_component.focused];
		}
		tree_component.mousedown = function(event) {
			var _this = tree_component.focusInst();
			if(!_this) return;
			
			var tmp = jQuery(event.target);
			if(tree_component.drop.length && tmp.is("." + tree_component.drop.join(", .")) ) {
				_this.drag = jQuery("<li id='dragged' class='dragged foreign " + event.target.className + "'><a href='#'>" + tmp.text() + "</a></li>");
				_this._drag = _this.drag;
				_this.isdown	= true;
				_this.foreign	= tmp;
				tmp.blur();
				event.preventDefault(); 
				event.stopPropagation();
				return false;
			}
			event.stopPropagation();
			return true;
		};
		tree_component.mouseup = function(event) {
			var _this = tree_component.focusInst();
			if(!_this) return;

			// CLEAR TIMEOUT FOR OPENING HOVERED NODES WHILE DRAGGING
			if(tree_component.to)	clearTimeout(tree_component.to);
			if(tree_component.sto)	clearTimeout(tree_component.sto);
			if(_this.foreign === false && _this.drag && _this.drag.parentNode && _this.drag.parentNode == jQuery(_this.container).children("ul:eq(0)").get(0)) {
				jQuery(_this.drag).remove();
				// CALL FUNCTION FOR COMPLETING MOVE
				if(_this.moveType) {
					var tmp = tree_component.inst[jQuery(_this.moveRef).parents(".tree:eq(0)").attr("id")];
					if(tmp) { 
						tmp.moved(_this.container.find("li.dragged"), _this.moveRef, _this.moveType, false, (_this.settings.rules.drag_copy == "on" || (_this.settings.rules.drag_copy == "ctrl" && event.ctrlKey) ) );
					}
				}
				_this.moveType = false;
				_this.moveRef = false;
			}
			if(_this.drag && _this.foreign !== false) {
				jQuery(_this.drag).remove();
				if(_this.moveType) {
					var tmp = tree_component.inst[jQuery(_this.moveRef).parents(".tree:eq(0)").attr("id")];
					if(tmp) { 
						tmp.settings.callback.ondrop.call(null, _this.foreign.get(0), _this.get_node( _this.moveRef).get(0), _this.moveType, _this);
					}
				}
				_this.foreign = false;
				_this.moveType = false;
				_this.moveRef = false;
			}
			// RESET EVERYTHING
			jQuery("#marker").hide();
			_this._drag		= false;
			_this.drag		= false;
			_this.isdown	= false;
			_this.appended	= false;
			_this.container.find("li.dragged").removeClass("dragged");
			event.preventDefault(); 
			event.stopPropagation();
			return false;
		};
		tree_component.mousemove = function(event) {
			var _this = tree_component.focusInst();
			if(!_this) return;

			if(_this.locked) return _this.error("LOCKED");
			if(_this.isdown) {
				// CLEAR TIMEOUT FOR OPENING HOVERED NODES WHILE DRAGGING
				if(tree_component.to) clearTimeout(tree_component.to);
				if(!_this.appended) {
					_this.container.children("ul:eq(0)").append(_this.drag);
					var tmp = jQuery(_this.drag).offsetParent();
					if(tmp.is("html")) tmp = jQuery("body");
					_this.po = tmp.offset();
					_this.appended = true;
				}
				jQuery(_this.drag).css({ "left" : (event.pageX - _this.po.left - (_this.settings.ui.rtl ? jQuery(_this.drag).width() : -5 ) ), "top" : (event.pageY - _this.po.top  + (jQuery.browser.opera ? _this.container.scrollTop() : 0) + 15) });

				if(event.target.tagName == "IMG" && event.target.id == "marker") return false;

				var cnt = jQuery(event.target).parents(".tree:eq(0)");

				// if not moving over a tree
				if(cnt.size() == 0) {
					if(tree_component.sto) clearTimeout(tree_component.sto);
					if(jQuery(_this.drag).children("IMG").size() == 0) {
						jQuery(_this.drag).append("<img style='position:absolute; " + (_this.settings.ui.rtl ? "right" : "left" ) + ":4px; top:0px; background:white; padding:2px;' src='" + _this.settings.ui.theme_path + "default/remove.png' />");
					}
					_this.moveType = false;
					_this.moveRef  = false;
					jQuery("#marker").hide();
					return false;
				}

				tree_component.inst[cnt.attr("id")].off_height();

				// if moving over another tree and multitree is false
				if( _this.foreign === false && cnt.get(0) != _this.container.get(0) && (!_this.settings.rules.multitree || !tree_component.inst[cnt.attr("id")].settings.rules.multitree) ) {
					if(jQuery(_this.drag).children("IMG").size() == 0) {
						jQuery(_this.drag).append("<img style='position:absolute; " + (_this.settings.ui.rtl ? "right" : "left" ) + ":4px; top:0px; background:white; padding:2px;' src='" + _this.settings.ui.theme_path + "default/remove.png' />");
					}
					_this.moveType = false;
					_this.moveRef  = false;
					jQuery("#marker").hide();
					return false;
				}

				if(tree_component.sto) clearTimeout(tree_component.sto);
				tree_component.sto = setTimeout( function() { tree_component.inst[cnt.attr("id")].scrollCheck(event.pageX,event.pageY); }, 50);

				var mov = false;
				var st = cnt.scrollTop();

				if(event.target.tagName == "A" ) {
					// just in case if hover is over the draggable
					if(jQuery(event.target).is("#dragged")) return false;

					var goTo = { 
						x : (jQuery(event.target).offset().left - 1),
						y : (event.pageY - tree_component.inst[cnt.attr("id")].offset.top)
					}
					if(cnt.hasClass("rtl")) {
						goTo.x += jQuery(event.target).width() - 8;
					}
					if( (goTo.y + st)%_this.li_height < _this.li_height/3 + 1 ) {
						mov = "before";
						goTo.y = event.pageY - (goTo.y + st)%_this.li_height - 2 ;
					}
					else if((goTo.y + st)%_this.li_height > _this.li_height*2/3 - 1 ) {
						mov = "after";
						goTo.y = event.pageY - (goTo.y + st)%_this.li_height + _this.li_height - 2 ;
					}
					else {
						mov = "inside";
						goTo.x -= 2;
						if(cnt.hasClass("rtl")) {
							goTo.x += 36;
						}
						goTo.y = event.pageY - (goTo.y + st)%_this.li_height + Math.floor(_this.li_height/2) - 2 ;
						if(_this.get_node(event.target).hasClass("closed")) {
							tree_component.to = setTimeout( function () { _this.open_branch(_this.get_node(event.target)); }, 500);
						}
					}

					if(tree_component.inst[cnt.attr("id")].checkMove(_this.container.find("li.dragged"), jQuery(event.target), mov)) {
						if(mov == "inside")	jQuery("#marker").attr("src", _this.settings.ui.theme_path + "default/plus.gif").width(11);
						else {
							if(cnt.hasClass("rtl"))	{ jQuery("#marker").attr("src", _this.settings.ui.theme_path + "default/marker_rtl.gif").width(40); }
							else					{ jQuery("#marker").attr("src", _this.settings.ui.theme_path + "default/marker.gif").width(40); }
						}
						_this.moveType	= mov;
						_this.moveRef	= event.target;
						jQuery(_this.drag).children("IMG").remove();
						jQuery("#marker").css({ "left" : goTo.x , "top" : goTo.y }).show();
					}
					else {
						if(jQuery(_this.drag).children("IMG").size() == 0) {
							jQuery(_this.drag).append("<img style='position:absolute; " + (_this.settings.ui.rtl ? "right:0px;" : "left:4px;" ) + " top:0px; background:white; padding:2px;' src='" + _this.settings.ui.theme_path + "default/remove.png' />");
						}
						_this.moveType = false;
						_this.moveRef = false;
						jQuery("#marker").hide();
					}
				}
				else {
					if(jQuery(_this.drag).children("IMG").size() == 0) {
						jQuery(_this.drag).append("<img style='position:absolute; " + (_this.settings.ui.rtl ? "right:0px;" : "left:4px;" ) + " top:0px; background:white; padding:2px;' src='" + _this.settings.ui.theme_path + "default/remove.png' />");
					}
					_this.moveType = false;
					_this.moveRef = false;
					jQuery("#marker").hide();
				}
				event.preventDefault();
				event.stopPropagation();
				return false;
			}
			return true;
		};
	}
	return {
		cntr : tree_component.cntr ++,
		settings : {
			data	: {
				type	: "predefined",	// ENUM [json, xml_flat, xml_nested, predefined]
				method	: "GET",		// HOW TO REQUEST FILES
				async	: false,		// BOOL - async loading onopen
				async_data : function (NODE) { return { id : jQuery(NODE).attr("id") || 0 } }, // PARAMETERS PASSED TO SERVER
				url		: false,		// FALSE or STRING - url to document to be used (async or not)
				json	: false			// FALSE or OBJECT if type is JSON and async is false - the tree dump as json
			},
			selected	: false,		// FALSE or STRING or ARRAY
			opened		: [],			// ARRAY OF INITIALLY OPENED NODES
			languages	: [],			// ARRAY of string values (which will be used as CSS classes - si they must be valid)
			path		: false,		// FALSE or STRING (if false - will be autodetected)
			cookies		: false,		// FALSE or OBJECT (prefix, opts - from jqCookie - expires, path, domain, secure)
			ui		: {
				dots		: true,		// BOOL - dots or no dots
				rtl			: false,	// BOOL - is the tree right-to-left
				animation	: 0,		// INT - duration of open/close animations in miliseconds
				hover_mode	: true,		// SHOULD get_* functions chage focus or change hovered item
				scroll_spd	: 4,
				theme_path	: false,	// Path to themes
				theme_name	: "default",// Name of theme
				context		: [ 
					{
						id		: "create",
						label	: "Create", 
						icon	: "create.png",
						visible	: function (NODE, TREE_OBJ) { if(NODE.length != 1) return false; return TREE_OBJ.check("creatable", NODE); }, 
						action	: function (NODE, TREE_OBJ) { TREE_OBJ.create(false, NODE); } 
					},
					"separator",
					{ 
						id		: "rename",
						label	: "Rename", 
						icon	: "rename.png",
						visible	: function (NODE, TREE_OBJ) { if(NODE.length != 1) return false; return TREE_OBJ.check("renameable", NODE); }, 
						action	: function (NODE, TREE_OBJ) { TREE_OBJ.rename(); } 
					},
					{ 
						id		: "delete",
						label	: "Delete",
						icon	: "remove.png",
						visible	: function (NODE, TREE_OBJ) { return TREE_OBJ.check("deletable", NODE); }, 
						action	: function (NODE, TREE_OBJ) { NODE.each( function () { TREE_OBJ.remove(this); }); } 
					}
				]
			},
			rules	: {
				multiple	: false,	// FALSE | CTRL | ON - multiple selection off/ with or without holding Ctrl
				metadata	: false,	// FALSE or STRING - attribute name (use metadata plugin)
				type_attr	: "rel",	// STRING attribute name (where is the type stored if no metadata)
				multitree	: false,	// BOOL - is drag n drop between trees allowed
				createat	: "bottom",	// STRING (top or bottom) new nodes get inserted at top or bottom
				use_inline	: false,	// CHECK FOR INLINE RULES - REQUIRES METADATA
				clickable	: "all",	// which node types can the user select | default - all
				renameable	: "all",	// which node types can the user select | default - all
				deletable	: "all",	// which node types can the user delete | default - all
				creatable	: "all",	// which node types can the user create in | default - all
				draggable	: "none",	// which node types can the user move | default - none | "all"
				dragrules	: "all",	// what move operations between nodes are allowed | default - none | "all"
				drag_copy	: false,	// FALSE | CTRL | ON - drag to copy off/ with or without holding Ctrl
				droppable	: []
			},
			lang : {
				new_node	: "New folder",
				loading		: "Loading ..."
			},
			callback	: {				// various callbacks to attach custom logic to
				// before focus  - should return true | false
				beforechange: function(NODE,TREE_OBJ) { return true },
				// before move   - should return true | false
				beforemove  : function(NODE,REF_NODE,TYPE,TREE_OBJ) { return true }, 
				// before create - should return true | false
				beforecreate: function(NODE,REF_NODE,TYPE,TREE_OBJ) { return true }, 
				// before rename - should return true | false
				beforerename: function(NODE,LANG,TREE_OBJ) { return true }, 
				// before delete - should return true | false
				beforedelete: function(NODE,TREE_OBJ) { return true }, 

				onchange	: function(NODE,TREE_OBJ) { },					// focus changed
				onrename	: function(NODE,LANG,TREE_OBJ) { },				// node renamed ISNEW - TRUE|FALSE, current language
				onmove		: function(NODE,REF_NODE,TYPE,TREE_OBJ) { },	// move completed (TYPE is BELOW|ABOVE|INSIDE)
				oncopy		: function(NODE,REF_NODE,TYPE,TREE_OBJ) { },	// copy completed (TYPE is BELOW|ABOVE|INSIDE)
				oncreate	: function(NODE,REF_NODE,TYPE,TREE_OBJ) { },	// node created, parent node (TYPE is insertAt)
				ondelete	: function(NODE, TREE_OBJ) { },					// node deleted
				onopen		: function(NODE, TREE_OBJ) { },					// node opened
				onclose		: function(NODE, TREE_OBJ) { },					// node closed
				error		: function(TEXT, TREE_OBJ) { },					// error occured
				// double click on node - defaults to open/close & select
				ondblclk	: function(NODE, TREE_OBJ) { TREE_OBJ.toggle_branch.call(TREE_OBJ, NODE); TREE_OBJ.select_branch.call(TREE_OBJ, NODE); },
				// right click - to prevent use: EV.preventDefault(); EV.stopPropagation(); return false
				onrgtclk	: function(NODE, TREE_OBJ, EV) { },
				onload		: function(TREE_OBJ) { },
				onfocus		: function(TREE_OBJ) { },
				ondrop		: function(NODE,REF_NODE,TYPE,TREE_OBJ) {}
			}
		},
		// INITIALIZATION
		init : function(elem, opts) {
			var _this = this;
			this.container		= jQuery(elem);
			if(this.container.size == 0) { alert("Invalid container node!"); return }

			tree_component.inst[this.cntr] = this;
			if(!this.container.attr("id")) this.container.attr("id","jstree_" + this.cntr); 
			tree_component.inst[this.container.attr("id")] = tree_component.inst[this.cntr];
			tree_component.focused = this.cntr;

			// MERGE OPTIONS WITH DEFAULTS
			if(opts && opts.cookies) {
				this.settings.cookies = jQuery.extend({},this.settings.cookies,opts.cookies);
				delete opts.cookies;
				if(!this.settings.cookies.opts) this.settings.cookies.opts = {};
			}
			if(opts && opts.callback) {
				this.settings.callback = jQuery.extend({},this.settings.callback,opts.callback);
				delete opts.callback;
			}
			if(opts && opts.data) {
				this.settings.data = jQuery.extend({},this.settings.data,opts.data);
				delete opts.data;
			}
			if(opts && opts.ui) {
				this.settings.ui = jQuery.extend({},this.settings.ui,opts.ui);
				delete opts.ui;
			}
			if(opts && opts.rules) {
				this.settings.rules = jQuery.extend({},this.settings.rules,opts.rules);
				delete opts.rules;
			}
			if(opts && opts.lang) {
				this.settings.lang = jQuery.extend({},this.settings.lang,opts.lang);
				delete opts.lang;
			}
			this.settings		= jQuery.extend({},this.settings,opts);

			// PATH TO IMAGES AND XSL
			if(this.settings.path == false) {
				this.path = "";
				jQuery("script").each( function () { 
					if(this.src.toString().match(/tree_component.*?js$/)) {
						_this.path = this.src.toString().replace(/tree_component.*?js$/, "");
					}
				});
			}
			else this.path = this.settings.path;

			// DEAL WITH LANGUAGE VERSIONS
			this.current_lang	= this.settings.languages && this.settings.languages.length ? this.settings.languages[0] : false;
			if(this.settings.languages && this.settings.languages.length) {
				this.sn = get_sheet_num("tree_component.css");
				var st = false;
				var id = this.container.attr("id") ? "#" + this.container.attr("id") : ".tree";
				for(var ln = 0; ln < this.settings.languages.length; ln++) {
					st = add_css(id + " ." + this.settings.languages[ln], this.sn);
					if(st !== false) {
						if(this.settings.languages[ln] == this.current_lang)	st.style.display = "inline";
						else													st.style.display = "none";
					}
				}
			}

			// DROPPABLES 
			if(this.settings.rules.droppable.length) {
				for(i in this.settings.rules.droppable) {
					tree_component.drop.push(this.settings.rules.droppable[i]);
					tree_component.drop = jQuery.unique(tree_component.drop);
				}
			}

			// THEMES
			if(this.settings.ui.theme_path === false) this.settings.ui.theme_path = this.path + "themes/";
			this.theme = this.settings.ui.theme_path + _this.settings.ui.theme_name + "/";
			add_sheet(_this.settings.ui.theme_path + "default/style.css");
			if(this.settings.ui.theme_name != "default") add_sheet(_this.theme + "style.css");

			this.container.addClass("tree");
			if(this.settings.ui.rtl) this.container.addClass("rtl");
			if(this.settings.rules.multiple) this.selected_arr = [];
			this.offset = false;

			if(this.settings.ui.dots == false) this.container.addClass("no_dots");

			// CONTEXT MENU
			this.context = false;
			if(this.settings.ui.context != false) {
				var str = '<div class="context">';
				for(i in this.settings.ui.context) {
					if(this.settings.ui.context[i] == "separator") {
						str += "<span class='separator'>&nbsp;</span>";
						continue;
					}
					var icn = "";
					if(this.settings.ui.context[i].icon) icn = 'background-image:url(\'' + ( this.settings.ui.context[i].icon.indexOf("/") == -1 ? this.theme + this.settings.ui.context[i].icon : this.settings.ui.context[i].icon ) + '\');';
					str += '<a rel="' + this.settings.ui.context[i].id + '" href="#" style="' + icn + '">' + this.settings.ui.context[i].label + '</a>';
				}
				str += '</div>';
				this.context = jQuery(str);
				this.context.hide();
				this.context.append = false;
			}

			this.hovered = false;
			this.locked = false;

			// CREATE DUMMY FOR MOVING
			if(this.settings.rules.draggable != "none" && this.settings.rules.dragrules != "none") {
				var _this = this;
				jQuery("<img>")
					.attr({
						id		: "marker", 
						src	: _this.settings.ui.theme_path + "default/marker.gif"
					})
					.css({
						height		: "5px",
						width		: "40px",
						display		: "block",
						position	: "absolute",
						left		: "30px",
						top			: "30px",
						zIndex		: "1000"
					}).hide().appendTo("body");
			}
			this.refresh();
			this.attachEvents();
			this.focus();
		},
		off_height : function () {
			if(this.offset === false) {
				this.container.css({ position : "relative" });
				this.offset = this.container.offset();
				var tmp = 0;
				tmp = parseInt(jQuery.curCSS(this.container.get(0), "paddingTop", true),10);
				if(tmp) this.offset.top += tmp;
				tmp = parseInt(jQuery.curCSS(this.container.get(0), "borderTopWidth", true),10);
				if(tmp) this.offset.top += tmp;
				this.container.css({ position : "" });
			}
			if(!this.li_height) {
				var tmp = this.container.find("ul li:eq(0)");
				this.li_height = tmp.height();
				if(tmp.children("ul:eq(0)").size()) this.li_height -= tmp.children("ul:eq(0)").height();
				if(!this.li_height) this.li_height = 18;
			}
		},
		// REPAINT TREE
		refresh : function (obj) {
			if(this.locked) return this.error("LOCKED");
			var _this = this;

			// SAVE OPENED
			this.opened = Array();
			if(this.settings.cookies && jQuery.cookie(this.settings.cookies.prefix + '_open')) {
				var str = jQuery.cookie(this.settings.cookies.prefix + '_open');
				var tmp = str.split(",");
				jQuery.each(tmp, function () {
					_this.opened.push("#" + this.replace(/^#/,""));
				});
				this.settings.opened = false;
			}
			else if(this.settings.opened != false) {
				jQuery.each(this.settings.opened, function (i, item) {
					_this.opened.push("#" + this.replace(/^#/,""));
				});
				this.settings.opened = false;
			}
			else {
				this.container.find("li.open").each(function (i) { _this.opened.push("#" + this.id); });
			}

			// SAVE SELECTED
			if(this.selected) {
				this.settings.selected = Array();
				if(this.selected_arr) {
					jQuery.each(this.selected_arr, function () {
						_this.settings.selected.push("#" + this.attr("id"));
					});
				}
				else this.settings.selected.push("#" + this.selected.attr("id"));
			}
			else if(this.settings.cookies && jQuery.cookie(this.settings.cookies.prefix + '_selected')) {
				this.settings.selected = Array();
				var str = jQuery.cookie(this.settings.cookies.prefix + '_selected');
				var tmp = str.split(",");
				jQuery.each(tmp, function () {
					_this.settings.selected.push("#" + this.replace(/^#/,""));
				});
			}
			else if(this.settings.selected !== false) {
				var tmp = Array();
				if((typeof this.settings.selected).toLowerCase() == "object") {
					jQuery.each(this.settings.selected, function () {
						tmp.push("#" + this.replace(/^#/,""));
					});
				}
				else tmp.push("#" + this.settings.selected.replace(/^#/,""));
				this.settings.selected = tmp;
			}

			if(obj && this.settings.data.async) {
				this.opened = Array();
				obj = this.get_node(obj);
				obj.find("li.open").each(function (i) { _this.opened.push("#" + this.id); });
				this.close_branch(obj, true);
				obj.children("ul:eq(0)").html("");
				return this.open_branch(obj, true, function () { _this.reselect.apply(_this); });
			}

			var cls = "tree-default";
			if(this.settings.ui.theme_name != "default") cls += " tree-" + _this.settings.ui.theme_name;

			if(this.settings.data.type == "xml_flat" || this.settings.data.type == "xml_nested") {
				this.scrtop = this.container.get(0).scrollTop;
				var xsl = (this.settings.data.type == "xml_flat") ? "flat.xsl" : "nested.xsl";
				this.container.getTransform(this.path + xsl, this.settings.data.url, { params : { theme_name : cls, theme_path : _this.theme }, meth : _this.settings.data.method ,callback: function () { _this.reselect.apply(_this); } });
				return;
			}
			else if(this.settings.data.type == "json") {
				if(this.settings.data.json) {
					var str = "";
					if(this.settings.data.json.length) {
						for(var i = 0; i < this.settings.data.json.length; i++) {
							str += this.parseJSON(this.settings.data.json[i]);
						}
					} else str = this.parseJSON(this.settings.data.json);
					this.container.html("<ul class='" + cls + "'>" + str + "</ul>");
					this.container.find("li:last-child").addClass("last").end().find("li:has(ul)").not(".open").addClass("closed");
					this.container.find("li").not(".open").not(".closed").addClass("leaf");
					this.reselect();
				}
				else {
					var _this = this;
					jQuery.ajax({
						type		: this.settings.data.method,
						url			: this.settings.data.url, 
						data		: this.settings.data.async_data(false), 
						dataType	: "json",
						success		: function (data) {
							var str = "";
							if(data.length) {
								for(var i = 0; i < data.length; i++) {
									str += _this.parseJSON(data[i]);
								}
							} else str = _this.parseJSON(data);
							_this.container.html("<ul class='" + cls + "'>" + str + "</ul>");
							_this.container.find("li:last-child").addClass("last").end().find("li:has(ul)").not(".open").addClass("closed");
							_this.container.find("li").not(".open").not(".closed").addClass("leaf");
							_this.reselect.apply(_this);
						} 
					});
				}
			}
			else {
				this.container.children("ul:eq(0)").attr("class", cls);
				this.container.find("li:last-child").addClass("last").end().find("li:has(ul)").not(".open").addClass("closed");
				this.container.find("li").not(".open").not(".closed").addClass("leaf");
				this.reselect();
			}
		},
		// CONVERT JSON TO HTML
		parseJSON : function (data) {
			if(!data || !data.data) return "";
			var str = "";
			str += "<li ";
			var cls = false;
			if(data.attributes) {
				for(i in data.attributes) {
					if(i == "class") {
						str += " class='" + data.attributes[i] + " ";
						if(data.state == "closed" || data.state == "open") str += " " + data.state + " ";
						str += "' ";
						cls = true;
					}
					else str += " " + i + "='" + data.attributes[i] + "' ";
				}
			}
			if(!cls && (data.state == "closed" || data.state == "open")) str += " class='" + data.state + "' ";
			str += ">";
			if(this.settings.languages.length) {
				for(var i = 0; i < this.settings.languages.length; i++) {
					var attr = [];
					attr["href"] = "#";
					attr["style"] = "";
					attr["class"] = this.settings.languages[i];
					if(data.data[this.settings.languages[i]] && (typeof data.data[this.settings.languages[i]].attributes).toLowerCase() != "undefined") {
						for(j in data.data[this.settings.languages[i]].attributes) {
							if(j == "style" || j == "class")	attr[j] += " " + data.data[this.settings.languages[i]].attributes[j];
							else								attr[j]  = data.data[this.settings.languages[i]].attributes[j];
						}
					}
					if(data.data[this.settings.languages[i]] && data.data[this.settings.languages[i]].icon) {
						var icn = data.data[this.settings.languages[i]].icon.indexOf("/") == -1 ? this.theme + data.data[this.settings.languages[i]].icon : data.data[this.settings.languages[i]].icon;
						attr["style"] += " ; background-image:url('" + icn + "'); ";
					}
					str += "<a";
					for(j in attr) str += ' ' + j + '="' + attr[j] + '" ';
					str += ">" + ( (typeof data.data[this.settings.languages[i]].title).toLowerCase() != "undefined" ? data.data[this.settings.languages[i]].title : data.data[this.settings.languages[i]] ) + "</a>";
				}
			}
			else {
				var attr = [];
				attr["href"] = "#";
				attr["style"] = "";
				attr["class"] = "";
				if((typeof data.data.attributes).toLowerCase() != "undefined") {
					for(i in data.data.attributes) {
						if(i == "style" || i == "class")	attr[i] += " " + data.data.attributes[i];
						else								attr[i]  = data.data.attributes[i];
					}
				}
				if(data.data.icon) {
					var icn = data.data.icon.indexOf("/") == -1 ? this.theme + data.data.icon : data.data.icon;
					attr["style"] += " ; background-image:url('" + icn + "');";
				}
				str += "<a";
				for(i in attr) str += ' ' + i + '="' + attr[i] + '" ';
				str += ">" + ( (typeof data.data.title).toLowerCase() != "undefined" ? data.data.title : data.data ) + "</a>";
			}
			if(data.children && data.children.length) {
				str += '<ul>';
				for(var i = 0; i < data.children.length; i++) {
					str += this.parseJSON(data.children[i]);
				}
				str += '</ul>';
			}
			str += "</li>";
			return str;
		},
		// getJSON from HTML
		getJSON : function (nod, outer_attrib, inner_attrib, force) {
			var _this = this;
			if(!nod || jQuery(nod).size() == 0) {
				nod = this.container.children("ul").children("li");
			}
			else nod = jQuery(nod);

			if(nod.size() > 1) {
				var arr = [];
				nod.each(function () {
					arr.push(_this.getJSON(this, outer_attrib, inner_attrib));
				});
				return arr;
			}

			if(!outer_attrib) outer_attrib = [ "id", "rel", "class" ];
			if(!inner_attrib) inner_attrib = [ ];
			var obj = { attributes : {}, data : false };
			for(i in outer_attrib) {
				obj.attributes[outer_attrib[i]] = nod.attr(outer_attrib[i]);
			}
			if(this.settings.languages.length) {
				obj.data = {};
				for(i in this.settings.languages) {
					var a = nod.children("a." + this.settings.languages[i]);
					if(force || inner_attrib.length || a.get(0).style.backgroundImage.toString().length) {
						obj.data[this.settings.languages[i]] = {};
						obj.data[this.settings.languages[i]].title = a.text();
						if(a.get(0).style.backgroundImage.length) {
							obj.data[this.settings.languages[i]].icon = a.get(0).style.backgroundImage.replace("url(","").replace(")","");
						}
						if(inner_attrib.length) {
							obj.data[this.settings.languages[i]].attributes = {};
							for(j in inner_attrib) {
								obj.data[this.settings.languages[i]].attributes[inner_attrib[j]] = a.attr(inner_attrib[j]);
							}
						}
					}
					else {
						obj.data[this.settings.languages[i]] = a.text();
					}
				}
			}
			else {
				var a = nod.children("a");
				if(force || inner_attrib.length || a.get(0).style.backgroundImage.toString().length) {
					obj.data = {};
					obj.data.title = a.text();
					if(a.get(0).style.backgroundImage.length) {
						obj.data.icon = a.get(0).style.backgroundImage.replace("url(","").replace(")","");
					}
					if(inner_attrib.length) {
						obj.data.attributes = {};
						for(j in inner_attrib) {
							obj.data.attributes[inner_attrib[j]] = a.attr(inner_attrib[j]);
						}
					}
				}
				else {
					obj.data = a.text();
				}
			}

			if(nod.children("ul").size() > 0) {
				obj.children = [];
				nod.children("ul").children("li").each(function () {
					obj.children.push(_this.getJSON(this, outer_attrib, inner_attrib));
				});
			}
			return obj;
		},
		focus : function () {
			if(this.locked) return false;
			if(tree_component.focused != this.cntr) {
				tree_component.focused = this.cntr;
				this.settings.callback.onfocus.call(null, this);
			}
		},
		show_context : function (obj, x, y) {
			var tmp = this.context.show().offsetParent();
			if(tmp.is("html")) tmp = jQuery("body");
			tmp = tmp.offset();
			this.context.css({ "left" : (x - tmp.left - (this.settings.ui.rtl ? jQuery(this.context).width() : -5 ) ), "top" : (y - tmp.top  + (jQuery.browser.opera ? this.container.scrollTop() : 0) + 15) });
		},
		hide_context : function () {
			this.context.hide();
		},
		// ALL EVENTS
		attachEvents : function () {
			var _this = this;

			this.container
				.bind("mouseup", function (event) {
					setTimeout( function() { _this.focus.apply(_this); }, 5);
				})
				.bind("click", function (event) { 
					event.stopPropagation(); 
					return true;
				})
				.listen("click", "li", function(event) { // WHEN CLICK IS ON THE ARROW
					_this.toggle_branch.apply(_this, [event.target]);
					event.stopPropagation();
				})
				.listen("click", "a", function (event) { // WHEN CLICK IS ON THE TEXT OR ICON
					if(_this.locked) {
						event.preventDefault(); 
						event.target.blur();
						return _this.error("LOCKED");
					}
					_this.select_branch.apply(_this, [event.target, event.ctrlKey || _this.settings.rules.multiple == "on"]);
					if(_this.inp) { _this.inp.blur(); }
					event.preventDefault(); 
					event.target.blur();
					return false;
				})
				.listen("dblclick", "a", function (event) { // WHEN DOUBLECLICK ON TEXT OR ICON
					if(_this.locked) {
						event.preventDefault(); 
						event.stopPropagation();
						event.target.blur();
						return _this.error("LOCKED");
					}
					_this.settings.callback.ondblclk.call(null, _this.get_node(event.target).get(0), _this);
					event.preventDefault(); 
					event.stopPropagation();
					event.target.blur();
				})
				.listen("contextmenu", "a", function (event) {
					if(_this.locked) {
						event.target.blur();
						return _this.error("LOCKED");
					}
					var val = _this.settings.callback.onrgtclk.call(null, _this.get_node(event.target).get(0), _this, event);
					if(_this.context) {
						if(_this.context.append == false) {
							_this.container.find("ul:eq(0)").append(_this.context);
							_this.context.append = true;
							for(i in _this.settings.ui.context) {
								if(_this.settings.ui.context[i] == "separator") continue;
								(function () {
									var func = _this.settings.ui.context[i].action;
									_this.context.children("[rel=" + _this.settings.ui.context[i].id +"]")
										.bind("click", function (event) {
											if(!$(this).hasClass("disabled")) {
												func.call(null, _this.selected_arr || _this.selected, _this);
												_this.hide_context();
											}
											event.stopPropagation();
											event.preventDefault();
											return false;
										})
										.bind("mouseup", function (event) {
											this.blur();
											if($(this).hasClass("disabled")) {
												event.stopPropagation();
												event.preventDefault();
												return false;
											}
										});
								})();
							}
						}
						var obj = _this.get_node(event.target);
						if(_this.inp) { _this.inp.blur(); }
						if(obj) {
							if(!obj.children("a:eq(0)").hasClass("clicked")) {
								_this.select_branch.apply(_this, [event.target, event.ctrlKey || _this.settings.rules.multiple == "on"]);
								event.target.blur();
							}
							_this.context.children("a").removeClass("disabled").show();
							var go = false;
							for(i in _this.settings.ui.context) {
								if(_this.settings.ui.context[i] == "separator") continue;
								var state = _this.settings.ui.context[i].visible.call(null, _this.selected_arr || _this.selected, _this);
								if(state === false)	_this.context.children("[rel=" + _this.settings.ui.context[i].id +"]").addClass("disabled");
								if(state === -1)	_this.context.children("[rel=" + _this.settings.ui.context[i].id +"]").hide();
								else				go = true;
							}
							if(go == true) _this.show_context(obj, event.pageX, event.pageY);
							event.preventDefault(); 
							event.stopPropagation(); 
							return false;
						}
					}
					return val;
				})
				.listen("mouseover", "a", function (event) {
					if(_this.locked) {
						event.preventDefault();
						event.stopPropagation();
						return _this.error("LOCKED");
					}
					if(_this.settings.ui.hover_mode && _this.hovered !== false && event.target.tagName == "A") {
						_this.hovered.children("a").removeClass("hover");
						_this.hovered = false;
					}
				});

				// ATTACH DRAG & DROP ONLY IF NEEDED
				if(this.settings.rules.draggable != "none" && this.settings.rules.dragrules != "none") {
					this.container
						.listen("mousedown", "a", function (event) {
							_this.focus.apply(_this);
							if(_this.locked) return _this.error("LOCKED");
							// SELECT LIST ITEM NODE
							var obj = _this.get_node(event.target);
							// IF ITEM IS DRAGGABLE
							if(_this.settings.rules.multiple != false && _this.selected_arr.length > 1 && obj.children("a:eq(0)").hasClass("clicked")) {
								var counter = 0;
								for(i in _this.selected_arr) {
									if(_this.check("draggable", _this.selected_arr[i])) {
										_this.selected_arr[i].addClass("dragged");
										counter ++;
									}
								}
								if(counter > 0) {
									if(_this.check("draggable", obj))	_this._drag = obj;
									else								_this._drag = _this.container.find("li.dragged:eq(0)");
									_this.isdown	= true;
									_this.drag		= _this._drag.get(0).cloneNode(true);
									_this.drag.id	= "dragged";
									jQuery(_this.drag).children("a").html("Multiple selection").end().children("ul").remove();
								}
							}
							else {
								if(_this.check("draggable", obj)) {
									_this._drag		= obj;
									_this.drag		= obj.get(0).cloneNode(true);
									_this.drag.id	= "dragged";
									_this.isdown	= true;
									_this.foreign	= false;
									obj.addClass("dragged");
								}
							}
							obj.blur();
							event.preventDefault(); 
							event.stopPropagation();
							return false;
						});
					jQuery(document)
						.bind("mousedown",	tree_component.mousedown)
						.bind("mouseup",	tree_component.mouseup)
						.bind("mousemove",	tree_component.mousemove);
				} 
				// ENDIF OF DRAG & DROP FUNCTIONS
			if(_this.context) jQuery(document).bind("mouseup", function() { _this.hide_context(); });
		},
		checkMove : function (NODES, REF_NODE, TYPE) {
			if(this.locked) return this.error("LOCKED");
			var _this = this;
			// OVER SELF OR CHILDREN
			if(REF_NODE.parents("li.dragged").size() > 0 || REF_NODE.is(".dragged")) return this.error("MOVE: NODE OVER SELF");
			// CHECK AGAINST DRAG_RULES
			if(NODES.size() == 1) {
				var NODE = NODES.eq(0);
				if(NODE.hasClass("foreign")) {
					if(this.settings.rules.droppable.length == 0) return false;
					if(!NODE.is("." + this.settings.rules.droppable.join(", ."))) return false;
					var ok = false;
					for(i in this.settings.rules.droppable) {
						if(NODE.is("." + this.settings.rules.droppable[i])) {
							if(this.settings.rules.metadata) {
								jQuery.metadata.setType("attr", this.settings.rules.metadata);
								NODE.attr(this.settings.rules.metadata, "type: '" + this.settings.rules.droppable[i] + "'");
							}
							else {
								NODE.attr(this.settings.rules.type_attr, this.settings.rules.droppable[i]);
							}
							ok = true;
							break;
						}
					}
					if(!ok) return false;
				}
				if(!this.check("dragrules", [NODE, TYPE, REF_NODE.parents("li:eq(0)")])) return this.error("MOVE: AGAINST DRAG RULES");
			}
			else {
				var ok = true;
				NODES.each(function (i) {
					if(ok == false) return false;
					if(i > 0) {
						var ref = NODES.eq( (i - 1) );
						var mv = "after";
					}
					else {
						var ref = REF_NODE;
						var mv = TYPE;
					}
					if(!_this.check.apply(_this,["dragrules", [jQuery(this), mv, ref]])) ok = false;
				});
				if(ok == false) return this.error("MOVE: AGAINST DRAG RULES");
			}
			// CHECK AGAINST METADATA
			if(this.settings.rules.use_inline && this.settings.rules.metadata) {
				var nd = false;
				if(TYPE == "inside")	nd = REF_NODE.parents("li:eq(0)");
				else					nd = REF_NODE.parents("li:eq(1)");
				if(nd.size()) {
					// VALID CHILDREN CHECK
					if(typeof nd.metadata()["valid_children"] != "undefined") {
						var tmp = nd.metadata()["valid_children"];
						var ok = true;
						NODES.each(function (i) {
							if(ok == false) return false;
							if(jQuery.inArray(_this.get_type(this), tmp) == -1) ok = false;
						});
						if(ok == false) return this.error("MOVE: NOT A VALID CHILD");
					}
					// CHECK IF PARENT HAS FREE SLOTS FOR CHILDREN
					if(typeof nd.metadata()["max_children"] != "undefined") {
						if((nd.children("ul:eq(0)").children("li").not(".dragged").size() + NODES.size()) > nd.metadata().max_children) return this.error("MOVE: MAX CHILDREN REACHED");
					}
					// CHECK FOR MAXDEPTH UP THE CHAIN
					var incr = 0;
					NODES.each(function (i) {
						var i = 1;
						var t = jQuery(this);
						while(i < 100) {
							t = t.children("ul:eq(0)");
							if(t.size() == 0) break;
							i ++
						}
						incr = Math.max(i,incr);
					});
					var ok = true;
					nd.parents("li").each(function(i) {
						if(ok == false) return false;
						if(jQuery(this).metadata().max_depth) {
							if( (i + incr) >= jQuery(this).metadata().max_depth) ok = false;
						}
					});
					if(ok == false) return this.error("MOVE: MAX_DEPTH REACHED");
				}
			}
			return true;
		},
		// USED AFTER REFRESH
		reselect : function () {
			var _this = this;
			// REOPEN BRANCHES
			if(this.opened && this.opened.length) {
				var opn = false;
				for(var j = 0; j < this.opened.length; j++) {
					if(this.settings.data.async) {
						if(this.get_node(this.opened[j]).size() > 0) {
							opn = true;
							var tmp = this.opened[j];
							delete this.opened[j];
							this.open_branch(tmp, true, function () { _this.reselect.apply(_this); } )
						}
					}
					else this.open_branch(this.opened[j], true);
				}
				if(this.settings.data.async && opn) return;
				delete this.opened;
			}
			// REPOSITION SCROLL
			if(this.scrtop) {
				this.container.scrollTop(_this.scrtop);
				delete this.scrtop;
			}
			// RESELECT PREVIOUSLY SELECTED
			if(this.settings.selected !== false) {
				jQuery.each(this.settings.selected, function (i) {
					_this.select_branch(jQuery(_this.settings.selected[i]), (_this.settings.rules.multiple !== false && i > 0) );
				});
				this.settings.selected = false;
			}
			this.settings.callback.onload.call(null, _this);
		},
		// GET THE EXTENDED LI ELEMENT
		get_node : function (obj) {
			var obj = jQuery(obj);
			return obj.is("li") ? obj : obj.parents("li:eq(0)");
		},
		// GET THE TYPE OF THE NODE
		get_type : function (obj) {
			obj = !obj ? this.selected : this.get_node(obj);
			if(!obj) return;
			if(this.settings.rules.metadata) {
				jQuery.metadata.setType("attr", this.settings.rules.metadata);
				var tmp = obj.metadata().type;
				if(tmp) return tmp;
			} 
			return obj.attr(this.settings.rules.type_attr);
		},
		// SCROLL CONTAINER WHILE DRAGGING
		scrollCheck : function (x,y) { 
			var _this = this;
			var cnt = _this.container;
			var off = _this.offset;

			var st = cnt.scrollTop();
			var sl = cnt.scrollLeft();
			// DETECT HORIZONTAL SCROLL
			var h_cor = (cnt.get(0).scrollWidth > cnt.width()) ? 40 : 20;

			if(y - off.top < 20)						cnt.scrollTop(Math.max( (st - _this.settings.ui.scroll_spd) ,0));	// NEAR TOP
			if(cnt.height() - (y - off.top) < h_cor)	cnt.scrollTop(st + _this.settings.ui.scroll_spd);					// NEAR BOTTOM
			if(x - off.left < 20)						cnt.scrollLeft(Math.max( (sl - _this.settings.ui.scroll_spd),0));	// NEAR LEFT
			if(cnt.width() - (x - off.left) < 40)		cnt.scrollLeft(sl + _this.settings.ui.scroll_spd);					// NEAR RIGHT

			if(cnt.scrollLeft() != sl || cnt.scrollTop() != st) {
				_this.moveType = false;
				_this.moveRef = false;
				jQuery("#marker").hide();
			}
			tree_component.sto = setTimeout( function() { _this.scrollCheck(x,y); }, 50);
		},
		check : function (rule, nodes) {
			if(this.locked) return this.error("LOCKED");
			// CHECK LOCAL RULES IF METADATA
			if(rule != "dragrules" && this.settings.rules.use_inline && this.settings.rules.metadata) {
				jQuery.metadata.setType("attr", this.settings.rules.metadata);
				if(typeof this.get_node(nodes).metadata()[rule] != "undefined") return this.get_node(nodes).metadata()[rule];
			}
			if(!this.settings.rules[rule])			return false;
			if(this.settings.rules[rule] == "none")	return false;
			if(this.settings.rules[rule] == "all")	return true;
			if(rule == "dragrules") {
				var nds = new Array();
				nds[0] = this.get_type(nodes[0]);
				nds[1] = nodes[1];
				nds[2] = this.get_type(nodes[2]);
				for(var i = 0; i < this.settings.rules.dragrules.length; i++) {
					var r = this.settings.rules.dragrules[i];
					var n = (r.indexOf("!") === 0) ? false : true;
					if(!n) r = r.replace("!","");
					var tmp = r.split(" ");
					for(var j = 0; j < 3; j++) {
						if(tmp[j] == nds[j] || tmp[j] == "*") tmp[j] = true;
					}
					if(tmp[0] === true && tmp[1] === true && tmp[2] === true) return n;
				}
				return false;
			}
			else 
				return (jQuery.inArray(this.get_type(nodes),this.settings.rules[rule]) != -1) ? true : false;
		},
		hover_branch : function (obj) {
			if(this.locked) return this.error("LOCKED");
			if(this.settings.ui.hover_mode == false) return this.select_branch(obj);
			var _this = this;
			var obj = _this.get_node(obj);
			if(!obj.size()) return this.error("HOVER: NOT A VALID NODE");
			// CHECK AGAINST RULES FOR SELECTABLE NODES
			if(!_this.check("clickable", obj)) return this.error("SELECT: NODE NOT SELECTABLE");
			if(this.hovered) this.hovered.children("A").removeClass("hover");

			// SAVE NEWLY SELECTED
			this.hovered = obj;

			// FOCUS NEW NODE AND OPEN ALL PARENT NODES IF CLOSED
			this.hovered.children("a").removeClass("hover").addClass("hover");

			// SCROLL SELECTED NODE INTO VIEW
			var off_t = this.hovered.offset().top;
			var beg_t = this.container.offset().top;
			var end_t = beg_t + this.container.height();
			var h_cor = (this.container.get(0).scrollWidth > this.container.width()) ? 40 : 20;
			if(off_t + 5 < beg_t) this.container.scrollTop(this.container.scrollTop() - (beg_t - off_t + 5) );
			if(off_t + h_cor > end_t) this.container.scrollTop(this.container.scrollTop() + (off_t + h_cor - end_t) );
		},
		select_branch : function (obj, multiple) {
			if(this.locked) return this.error("LOCKED");
			if(!obj && this.hovered !== false) obj = this.hovered;
			var _this = this;
			obj = _this.get_node(obj);
			if(!obj.size()) return this.error("SELECT: NOT A VALID NODE");
			obj.children("a").removeClass("hover");
			// CHECK AGAINST RULES FOR SELECTABLE NODES
			if(!_this.check("clickable", obj)) return this.error("SELECT: NODE NOT SELECTABLE");
			if(_this.settings.callback.beforechange.call(null,obj.get(0),_this) === false) return this.error("SELECT: STOPPED BY USER");
			// IF multiple AND obj IS ALREADY SELECTED - DESELECT IT
			if(this.settings.rules.multiple != false && multiple && obj.children("a.clicked").size() > 0) {
				return this.deselect_branch(obj);
			}
			if(this.settings.rules.multiple != false && multiple) {
				this.selected_arr.push(obj);
			}
			if(this.settings.rules.multiple != false && !multiple) {
				for(i in this.selected_arr) {
					this.selected_arr[i].children("A").removeClass("clicked");
				}
				this.selected_arr = [];
				this.selected_arr.push(obj);
				if(this.selected) this.selected.children("A").removeClass("clicked");
			}
			if(!this.settings.rules.multiple) {
				if(this.selected) this.selected.children("A").removeClass("clicked");
			}
			// SAVE NEWLY SELECTED
			this.selected = obj;
			if(this.settings.ui.hover_mode && this.hovered !== false) {
				this.hovered.children("A").removeClass("hover");
				this.hovered = obj;
			}

			// FOCUS NEW NODE AND OPEN ALL PARENT NODES IF CLOSED
			this.selected.children("a").removeClass("clicked").addClass("clicked").end().parents("li.closed").each( function () { _this.open_branch(this, true); });

			// SCROLL SELECTED NODE INTO VIEW
			var off_t = this.selected.offset().top;
			var beg_t = this.container.offset().top;
			var end_t = beg_t + this.container.height();
			var h_cor = (this.container.get(0).scrollWidth > this.container.width()) ? 40 : 20;
			if(off_t + 5 < beg_t) this.container.scrollTop(this.container.scrollTop() - (beg_t - off_t + 5) );
			if(off_t + h_cor > end_t) this.container.scrollTop(this.container.scrollTop() + (off_t + h_cor - end_t) );

			this.set_cookie("selected");
			this.settings.callback.onchange.call(null, this.selected.get(0), _this);
		},
		deselect_branch : function (obj) {
			if(this.locked) return this.error("LOCKED");
			var _this = this;
			var obj = this.get_node(obj);
			obj.children("a").removeClass("clicked");
			if(this.settings.rules.multiple != false && this.selected_arr.length > 1) {
				this.selected_arr = [];
				this.container.find("a.clicked").filter(":first-child").parent().each(function () {
					_this.selected_arr.push(jQuery(this));
				});
				if(obj.get(0) == this.selected.get(0)) {
					this.selected = this.selected_arr[0];
					this.set_cookie("selected");
				}
			}
			else {
				if(this.settings.rules.multiple != false) this.selected_arr = [];
				this.selected = false;
				this.set_cookie("selected");
			}
			if(this.selected)	this.settings.callback.onchange.call(null, this.selected.get(0), _this);
			else				this.settings.callback.onchange.call(null, false, _this);
		},
		toggle_branch : function (obj) {
			if(this.locked) return this.error("LOCKED");
			var obj = this.get_node(obj);
			if(obj.hasClass("closed"))	return this.open_branch(obj);
			if(obj.hasClass("open"))	return this.close_branch(obj); 
		},
		open_branch : function (obj, disable_animation, callback) {
			if(this.locked) return this.error("LOCKED");
			var obj = this.get_node(obj);
			if(!obj.size()) return this.error("OPEN: NO SUCH NODE");
			if(obj.hasClass("leaf")) return this.error("OPEN: OPENING LEAF NODE");

			if(this.settings.data.async && obj.find("li").size() == 0) {
				var _this = this;
				obj.children("ul:eq(0)").remove().end().append("<ul><li class='last'><a class='loading' href='#'>" + (_this.settings.lang.loading || "Loading ...") + "</a></li></ul>");
				obj.removeClass("closed").addClass("open");
				if(this.settings.data.type == "xml_flat" || this.settings.data.type == "xml_nested") {
					var xsl = (this.settings.data.type == "xml_flat") ? "flat.xsl" : "nested.xsl";
					var str = (this.settings.data.url.indexOf("?") == -1) ? "?id=" + encodeURIComponent(obj.attr("id")) : "&id=" + encodeURIComponent(obj.attr("id"));
					obj.children("ul:eq(0)").getTransform(this.path + xsl, this.settings.data.url + str, { params : { theme_path : _this.theme }, meth : this.settings.data.method, repl : true, callback: function (str, json) { 
							if(str.length < 15) {
								obj.removeClass("closed").removeClass("open").addClass("leaf").children("ul").remove();
								if(callback) callback.call();
								return;
							}
							_this.open_branch.apply(_this, [obj]); 
							if(callback) callback.call();
						} 
					});
				}
				else {
					jQuery.ajax({
						type		: this.settings.data.method,
						url			: this.settings.data.url, 
						data		: this.settings.data.async_data(obj), 
						dataType	: "json",
						success		: function (data, textStatus) {
							if(!data || data.length == 0) {
								obj.removeClass("closed").removeClass("open").addClass("leaf").children("ul").remove();
								if(callback) callback.call();
								return;
							}
							var str = "";
							if(data.length) {
								for(var i = 0; i < data.length; i++) {
									str += _this.parseJSON(data[i]);
								}
							}
							else str = _this.parseJSON(data);
							if(str.length > 0) {
								obj.children("ul:eq(0)").replaceWith("<ul>" + str + "</ul>");
								obj.find("li:last-child").addClass("last").end().find("li:has(ul)").not(".open").addClass("closed");
								obj.find("li").not(".open").not(".closed").addClass("leaf");
								_this.open_branch.apply(_this, [obj]);
							}
							else obj.removeClass("closed").removeClass("open").addClass("leaf").children("ul").remove();
							if(callback) callback.call();
						}
					});
				}
				return true;
			}
			else {
				if(parseInt(this.settings.ui.animation) > 0 && !disable_animation && !(jQuery.browser.msie && jQuery.browser.version < 7) ) {
					obj.children("ul:eq(0)").css("display","none");
					obj.removeClass("closed").addClass("open");
					obj.children("ul:eq(0)").slideDown(parseInt(this.settings.ui.animation), function() {
						jQuery(this).css("display","");
						if(callback) callback.call();
					});
				} else {
					obj.removeClass("closed").addClass("open");
					if(callback) callback.call();
				}
				this.set_cookie("open");
				this.settings.callback.onopen.call(null, obj.get(0), this);
				return true;
			}
		},
		close_branch : function (obj, disable_animation) {
			if(this.locked) return this.error("LOCKED");
			var _this = this;
			var obj = this.get_node(obj);
			if(parseInt(this.settings.ui.animation) > 0 && !disable_animation && !(jQuery.browser.msie && jQuery.browser.version < 7) && obj.children("ul:eq(0)").size() == 1) {
				obj.children("ul:eq(0)").slideUp(parseInt(this.settings.ui.animation), function() {
					obj.removeClass("open").addClass("closed");
					_this.set_cookie("open");
					jQuery(this).css("display","");
				});
			} 
			else {
				obj.removeClass("open").addClass("closed");
				this.set_cookie("open");
			}
			if(this.selected && obj.children("ul:eq(0)").find("a.clicked").size() > 0) {
				obj.find("li:has(a.clicked)").each(function() {
					_this.deselect_branch(this);
				});
				if(obj.children("a.clicked").size() == 0) this.select_branch(obj, (this.settings.rules.multiple != false && this.selected_arr.length > 0) );
			}
			this.settings.callback.onclose.call(null, obj.get(0), this);
		},
		open_all : function (obj) {
			if(this.locked) return this.error("LOCKED");
			var _this = this;
			obj = obj ? jQuery(obj) : this.container;
			obj.find("li.closed").each( function () { var __this = this; _this.open_branch.apply(_this, [this, true, function() { _this.open_all.apply(_this, [__this]); } ]); });
		},
		close_all : function () {
			if(this.locked) return this.error("LOCKED");
			var _this = this;
			jQuery(this.container).find("li.open").each( function () { _this.close_branch(this, true); });
		},
		show_lang : function (i) { 
			if(this.locked) return this.error("LOCKED");
			if(this.settings.languages[i] == this.current_lang) return true;
			var st = false;
			var id = this.container.attr("id") ? "#" + this.container.attr("id") : ".tree";
			st = get_css(id + " ." + this.current_lang, this.sn);
			if(st !== false) st.style.display = "none";
			st = get_css(id + " ." + this.settings.languages[i], this.sn);
			if(st !== false) st.style.display = "block";
			this.current_lang = this.settings.languages[i];
			return true;
		},
		cycle_lang : function() {
			if(this.locked) return this.error("LOCKED");
			var i = jQuery.inArray(this.current_lang, this.settings.languages);
			i ++;
			if(i > this.settings.languages.length - 1) i = 0;
			this.show_lang(i);
		},
		create : function (type, obj, data, icon, id ) {
			if(this.locked) return this.error("LOCKED");
			// NOTHING SELECTED
			obj = obj ? this.get_node(obj) : this.selected;
			if(!obj || !obj.size()) return this.error("CREATE: NO NODE SELECTED");
			if(!this.check("creatable", obj)) return this.error("CREATE: CANNOT CREATE IN NODE");

			var t = type || this.get_type(obj) || "";
			if(this.settings.rules.use_inline && this.settings.rules.metadata) {
				jQuery.metadata.setType("attr", this.settings.rules.metadata);
				if(typeof obj.metadata()["valid_children"] != "undefined") {
					if(jQuery.inArray(t, obj.metadata()["valid_children"]) == -1) return this.error("CREATE: NODE NOT A VALID CHILD");
				}
				if(typeof obj.metadata()["max_children"] != "undefined") {
					if( (obj.children("ul:eq(0)").children("li").size() + 1) > obj.metadata().max_children) return this.error("CREATE: MAX_CHILDREN REACHED");
				}
				var ok = true;
				obj.parents("li").each(function(i) {
					if(jQuery(this).metadata().max_depth) {
						if( (i + 1) >= jQuery(this).metadata().max_depth) {
							ok = false;
						}
					}
				});
				if(!ok) return this.error("CREATE: MAX_DEPTH REACHED");
			}
			if(obj.hasClass("closed")) {
				var _this = this;
				return this.open_branch(obj, true, function () { _this.create.apply(_this, [type, obj, data, icon, id]); } );
			}

			if(id)	$li = jQuery("<li id='" + id + "' />");
			else	$li = jQuery("<li />");
			// NEW NODE IS OF PASSED TYPE OR PARENT'S TYPE
			if(this.settings.rules.metadata) {
				jQuery.metadata.setType("attr", this.settings.rules.metadata);
				$li.attr(this.settings.rules.metadata, "type: '" + t + "'");
			}
			else {
				$li.attr(this.settings.rules.type_attr, t)
			}

			var icn = "";
			if((typeof icon).toLowerCase() == "string") {
				icn = icon;
				icn = icn.indexOf("/") == -1 ? this.theme + icn : icn;
			}
			if(this.settings.languages.length) {
				for(i = 0; i < this.settings.languages.length; i++) {
					if((typeof data).toLowerCase() == "string") val = data;
					else if(data && data[i]) {
						val = data[i];
					}
					else if(this.settings.lang.new_node) {
						if((typeof this.settings.lang.new_node).toLowerCase() != "string" && this.settings.lang.new_node[i]) 
							val = this.settings.lang.new_node[i];
						else 
							val = this.settings.lang.new_node;
					}
					else {
						val = "New folder";
					}
					if((typeof icon).toLowerCase() != "string" && icon && icon[i]) {
						icn = icon[i];
						icn = icn.indexOf("/") == -1 ? this.theme + icn : icn;
					}
					$li.append("<a href='#'" + ( icn.length ? " style='background-image:url(\"" + icn + "\");' " : " ") + "class='" + this.settings.languages[i] + "'>" + val + "</a>");
				}
			}
			else { $li.append("<a href='#'" + ( icn.length ? " style='background-image:url(\"" + icn + "\");' " : " ") + ">" + (data || this.settings.lang.new_node || "New folder") + "</a>"); }
			$li.addClass("leaf");
			if(this.settings.rules.createat == "top" || obj.children("ul").size() == 0) {
				this.moved($li,obj.children("a:eq(0)"),"inside", true);
			}
			else {
				this.moved($li,obj.children("ul:eq(0)").children("li:last").children("a:eq(0)"),"after",true);
			}
			this.select_branch($li.children("a:eq(0)"));
			if(!data) this.rename();
			return $li;
		},
		rename : function () {
			if(this.locked) return this.error("LOCKED");
			if(this.selected) {
				var _this = this;
				if(!this.check("renameable", this.selected)) return this.error("RENAME: NODE NOT RENAMABLE");
				if(!this.settings.callback.beforerename.call(null,this.selected.get(0), _this.current_lang, _this)) return this.error("RENAME: STOPPED BY USER");
				var obj = this.selected;
				if(this.current_lang)	obj = obj.find("a." + this.current_lang).get(0);
				else					obj = obj.find("a:first").get(0);
				last_value = obj.innerHTML;
				_this.inp = jQuery("<input type='text' />");
				_this.inp
					.val(last_value)
					.bind("mousedown",		function (event) { event.stopPropagation(); })
					.bind("mouseup",		function (event) { event.stopPropagation(); })
					.bind("click",			function (event) { event.stopPropagation(); })
					.bind("keyup",			function (event) { 
							var key = event.keyCode || event.which;
							if(key == 27) { this.value = last_value; this.blur(); return }
							if(key == 13) { this.blur(); return }
						});
				_this.inp.blur(function(event) {
						if(this.value == "") this.value == last_value; 
						jQuery(obj).html( jQuery(obj).parent().find("input").eq(0).attr("value") ).get(0).style.display = ""; 
						jQuery(obj).prevAll("span").remove(); 
						if(this.value != last_value) _this.settings.callback.onrename.call(null, _this.get_node(obj).get(0), _this.current_lang, _this);
						_this.inp = false;
					});
				var spn = jQuery("<span />").addClass(obj.className).append(_this.inp);
				spn.attr("style", jQuery(obj).attr("style"));
				obj.style.display = "none";
				jQuery(obj).parent().prepend(spn);
				_this.inp.get(0).focus();
				_this.inp.get(0).select();
			}
			else return this.error("RENAME: NO NODE SELECTED");
		},
		// REMOVE NODES
		remove : function(obj) {
			if(this.locked) return this.error("LOCKED");
			if(obj) {
				obj = this.get_node(obj);
				if(obj.size()) {
					if(!this.check("deletable", obj)) return this.error("DELETE: NODE NOT DELETABLE");
					if(!this.settings.callback.beforedelete.call(null,obj.get(0), _this)) return this.error("DELETE: STOPPED BY USER");
					$parent = obj.parent();
					obj = obj.remove();
					$parent.children("li:last").addClass("last");
					if($parent.children("li").size() == 0) {
						$li = $parent.parents("li:eq(0)");
						$li.removeClass("open").removeClass("closed").addClass("leaf").children("ul").remove();
						this.set_cookie("open");
					}
					this.settings.callback.ondelete.call(null, obj, this);
				}
			}
			else if(this.selected) {
				if(!this.check("deletable", this.selected)) return this.error("DELETE: NODE NOT DELETABLE");
				if(!this.settings.callback.beforedelete.call(null,this.selected.get(0), _this)) return this.error("DELETE: STOPPED BY USER");
				$parent = this.selected.parent();
				var obj = this.selected;
				if(this.settings.rules.multiple == false || this.selected_arr.length == 1) {
					var stop = true;
					var tmp = (this.selected.prev("li:eq(0)").size()) ? this.selected.prev("li:eq(0)") : this.selected.parents("li:eq(0)");
					// this.get_prev(true);
				}
				obj = obj.remove();
				$parent.children("li:last").addClass("last");
				if($parent.children("li").size() == 0) {
					$li = $parent.parents("li:eq(0)");
					$li.removeClass("open").removeClass("closed").addClass("leaf").children("ul").remove();
					this.set_cookie("open");
				}
				//this.selected = false;
				this.settings.callback.ondelete.call(null, obj, this);
				if(stop && tmp) this.select_branch(tmp);
				if(this.settings.rules.multiple != false && !stop) {
					var _this = this;
					this.selected_arr = [];
					this.container.find("a.clicked").filter(":first-child").parent().each(function () {
						_this.selected_arr.push(jQuery(this));
					});
					if(this.selected_arr.length > 0) {
						this.selected = this.selected_arr[0];
						this.remove();
					}
				}
			}
			else return this.error("DELETE: NO NODE SELECTED");
		},
		// FOR EXPLORER-LIKE KEYBOARD SHORTCUTS
		get_next : function(force) {
			var obj = this.hovered || this.selected;
			if(obj) {
				if(obj.hasClass("open"))						return force ? this.select_branch(obj.find("li:eq(0)")) : this.hover_branch(obj.find("li:eq(0)"));
				else if(jQuery(obj).nextAll("li").size() > 0)	return force ? this.select_branch(obj.nextAll("li:eq(0)")) : this.hover_branch(obj.nextAll("li:eq(0)"));
				else											return force ? this.select_branch(obj.parents("li").next("li").eq(0)) : this.hover_branch(obj.parents("li").next("li").eq(0));
			}
		},
		get_prev : function(force) {
			var obj = this.hovered || this.selected;
			if(obj) {
				if(obj.prev("li").size()) {
					var obj = obj.prev("li").eq(0);
					while(obj.hasClass("open")) obj = obj.children("ul:eq(0)").children("li:last");
					return force ? this.select_branch(obj) : this.hover_branch(obj);
				}
				else { return force ? this.select_branch(obj.parents("li:eq(0)")) : this.hover_branch(obj.parents("li:eq(0)")); }
			}
		},
		get_left : function(force, rtl) {
			if(this.settings.ui.rtl && !rtl) return this.get_right(force, true);
			var obj = this.hovered || this.selected;
			if(obj) {
				if(obj.hasClass("open"))	this.close_branch(obj);
				else {
					return force ? this.select_branch(obj.parents("li:eq(0)")) : this.hover_branch(obj.parents("li:eq(0)"));
				}
			}
		},
		get_right : function(force, rtl) {
			if(this.settings.ui.rtl && !rtl) return this.get_left(force, true);
			var obj = this.hovered || this.selected;
			if(obj) {
				if(obj.hasClass("closed"))	this.open_branch(obj);
				else {
					return force ? this.select_branch(obj.find("li:eq(0)")) : this.hover_branch(obj.find("li:eq(0)"));
				}
			}
		},
		toggleDots : function () {
			this.container.toggleClass("no_dots");
		},
		set_cookie : function (type) {
			if(this.settings.cookies === false) return false;
			switch(type) {
				case "selected":
					if(this.settings.rules.multiple != false && this.selected_arr.length > 1) {
						var val = Array();
						jQuery.each(this.selected_arr, function () {
							val.push(this.attr("id"));
						});
						val = val.join(",");
					}
					else var val = this.selected ? this.selected.attr("id") : false;
					jQuery.cookie(this.settings.cookies.prefix + '_selected',val,this.settings.cookies.opts);
					break;
				case "open":
					var str = "";
					this.container.find("li.open").each(function (i) { str += this.id + ","; });
					jQuery.cookie(this.settings.cookies.prefix + '_open',str.replace(/,$/ig,""),this.settings.cookies.opts);
					break;
			}
		},
		moved : function (what, where, how, is_new, is_copy) {
			var what	= jQuery(what);
			var $parent	= jQuery(what).parents("ul:eq(0)");
			var $where	= jQuery(where);
			// IF MULTIPLE
			if(what.size() > 1) {
				var _this = this;
				var tmp = this.moved(what.eq(0),where,how, false, is_copy);
				what.each(function (i) {
					if(i == 0) return;
					tmp = _this.moved(this, tmp.children("a:eq(0)"), "after", false, is_copy);
				})
				return;
			}
			if(is_copy) {
				what = what.clone();
				what.each(function (i) {
					this.id = this.id + "_copy";
					jQuery(this).find("li").each(function () {
						this.id = this.id + "_copy";
					})
					jQuery(this).find("a.clicked").removeClass("clicked");
				});
			}
			if(is_new) {
				if(!this.settings.callback.beforecreate.call(null,this.get_node(what).get(0), this.get_node(where).get(0),how,this)) return;
			}
			else {
				if(!this.settings.callback.beforemove.call(null,this.get_node(what).get(0), this.get_node(where).get(0),how,this)) return;
			}
			
			if(!is_new) {
				var tmp = jQuery(what).parents(".tree:eq(0)");
				// if different trees
				if(tmp.get(0) != this.container.get(0)) {
					tmp = tree_component.inst[tmp.attr("id")];
					// if there are languages - otherwise - no cleanup needed
					if(tmp.settings.languages.length) {
						var res = [];
						// if new tree has no languages - use current visible
						if(this.settings.languages.length == 0) res.push("." + tmp.current_lang);
						else {
							for(i in this.settings.languages) {
								for(j in tmp.settings.languages) {
									if(this.settings.languages[i] == tmp.settings.languages[j]) res.push("." + this.settings.languages[i]);
								}
							}
						}
						if(res.length == 0) return this.error("MOVE: NO COMMON LANGUAGES");
						what.find("a").removeClass("clicked").not(res.join(",")).remove();
					}
				}
			}

			// ADD NODE TO NEW PLACE
			switch(how) {
				case "before":
					$where.parents("ul:eq(0)").children("li.last").removeClass("last");
					$where.parent().before(what.removeClass("last"));
					$where.parents("ul:eq(0)").children("li:last").addClass("last");
					break;
				case "after":
					$where.parents("ul:eq(0)").children("li.last").removeClass("last");
					$where.parent().after(what.removeClass("last"));
					$where.parents("ul:eq(0)").children("li:last").addClass("last");
					break;
				case "inside":
					if(this.settings.data.async) {
						var obj = this.get_node($where);
						if(obj.hasClass("closed")) {
							var _this = this;
							return this.open_branch(obj, true, function () { _this.moved.apply(_this, [what, where, how, is_new, is_copy]); })
						}
					}
					if($where.parent().children("ul:first").size()) {
						if(this.settings.rules.createat == "top")	$where.parent().children("ul:first").prepend(what.removeClass("last")).children("li:last").addClass("last");
						else										$where.parent().children("ul:first").children(".last").removeClass("last").end().append(what.removeClass("last")).children("li:last").addClass("last");
					}
					else {
						what.addClass("last");
						$where.parent().append("<ul/>").removeClass("leaf").addClass("closed");
						$where.parent().children("ul:first").prepend(what);
					}
					if(!this.settings.data.async) {
						this.open_branch($where);
					}
					break;
				default:
					break;
			}
			// CLEANUP OLD PARENT
			if($parent.find("li").size() == 0) {
				var $li = $parent.parent();
				$li.removeClass("open").removeClass("closed").addClass("leaf").children("ul").remove();
				$li.parents("ul:eq(0)").children("li.last").removeClass("last").end().children("li:last").addClass("last");
				this.set_cookie("open");
			}
			else {
				$parent.children("li.last").removeClass("last");
				$parent.children("li:last").addClass("last");
			}
			if(is_new && how != "inside") where = this.get_node(where).parents("li:eq(0)");
			if(is_copy)		this.settings.callback.oncopy.call(null, this.get_node(what).get(0), this.get_node(where).get(0), how, this)
			else if(is_new)	this.settings.callback.oncreate.call(null, this.get_node(what).get(0), this.get_node(where).get(0), this.settings.insertAt, this);
			else			this.settings.callback.onmove.call(null, this.get_node(what).get(0), this.get_node(where).get(0), how, this);
			return what;
		},
		error : function (code) {
			this.settings.callback.error.call(null,code,this);
			return false;
		},
		lock : function (state) {
			this.locked = state;
			if(this.locked)	this.container.addClass("locked");
			else			this.container.removeClass("locked");
		},
		cut : function () {
			if(this.locked) return this.error("LOCKED");
			if(!this.selected) return this.error("CUT: NO NODE SELECTED");
			this.copy_nodes = false;
			this.cut_nodes = this.container.find("a.clicked").filter(":first-child").parent();
		},
		copy : function () {
			if(this.locked) return this.error("LOCKED");
			if(!this.selected) return this.error("COPY: NO NODE SELECTED");
			this.copy_nodes = this.container.find("a.clicked").filter(":first-child").parent();
			this.cut_nodes = false;
		},
		paste : function () {
			if(this.locked) return this.error("LOCKED");
			if(!this.selected) return this.error("PASTE: NO NODE SELECTED");
			if(!this.copy_nodes && !this.cut_nodes) return this.error("PASTE: NOTHING TO DO");
			if(this.copy_nodes && this.copy_nodes.size()) {
				if(!this.checkMove(this.copy_nodes, this.selected.children("a:eq(0)"), "inside")) return false;
				this.moved(this.copy_nodes, this.selected.children("a:eq(0)"), "inside", false, true);
				this.copy_nodes = false;
			}
			if(this.cut_nodes && this.cut_nodes.size()) {
				if(!this.checkMove(this.cut_nodes, this.selected.children("a:eq(0)"), "inside")) return false;
				this.moved(this.cut_nodes, this.selected.children("a:eq(0)"), "inside");
				this.cut_nodes = false;
			}
		},
		search : function(str) {
			var _this = this;
			if(!str || (this.srch && str != this.srch) ) {
				this.srch = "";
				this.srch_opn = false;
				this.container.find("a.search").removeClass("search");
			}
			this.srch = str;
			if(!str) return;
			if(this.settings.data.async) {
				if(!this.srch_opn) {
					var dd = jQuery.extend( { "search" : str } , this.settings.data.async_data(false) );
					jQuery.ajax({
						type		: this.settings.data.method,
						url			: this.settings.data.url, 
						data		: dd, 
						dataType	: "text",
						success		: function (data) {
							_this.srch_opn = jQuery.unique(data.split(","));
							_this.search.apply(_this,[str]);
						} 
					});
				}
				else if(this.srch_opn.length) {
					if(this.srch_opn && this.srch_opn.length) {
						var opn = false;
						for(var j = 0; j < this.srch_opn.length; j++) {
							if(this.get_node("#" + this.srch_opn[j]).size() > 0) {
								opn = true;
								var tmp = "#" + this.srch_opn[j];
								delete this.srch_opn[j];
								this.open_branch(tmp, true, function () { _this.search.apply(_this,[str]); } );
							}
						}
						if(!opn) {
							this.srch_opn = [];
							 _this.search.apply(_this,[str]);
						}
					}
				}
				else {
					var selector = "a";
					// IF LANGUAGE VERSIONS
					if(this.settings.languages.length) selector += "." + this.current_lang;
					this.container.find(selector + ":contains('" + str + "')").addClass("search");
					this.srch_opn = false;
				}
			}
			else {
				var selector = "a";
				// IF LANGUAGE VERSIONS
				if(this.settings.languages.length) selector += "." + this.current_lang;
				this.container.find(selector + ":contains('" + str + "')").addClass("search").parents("li.closed").each( function () { _this.open_branch(this, true); });
			}
		},

		destroy : function() {
			try {
				var evts = ["click","dblclick","contextmenu","mouseover","mousedown"];
				for(i in evts) {
					var idxer = this.container.indexer(evts[i]);
					idxer.stop();
					jQuery.removeData( idxer.listener, idxer.event + '.indexer' );
				}
			} catch(err) { }
			this.container.unbind();

			this.container.removeClass("tree").children("ul").removeClass("tree-" + this.settings.ui.theme_name).find("li").removeClass("leaf").removeClass("open").removeClass("closed").removeClass("last").children("a").removeClass("clicked");

			if(this.cntr == tree_component.focused) {
				for(i in tree_component.inst) {
					if(i != this.cntr && i != this.container.attr("id")) {
						tree_component.inst[i].focus();
						break;
					}
				}
			}
			delete tree_component.inst[this.cntr];
			delete tree_component.inst[this.container.attr("id")];
			tree_component.cntr --;
		}
	}
};

/** File: javascript/jquery.tree_component_css.js **/

function get_css(rule_name, stylesheet, delete_flag) {
	if (!document.styleSheets) return false;
	rule_name = rule_name.toLowerCase(); stylesheet = stylesheet || 0;
	for (var i = stylesheet; i < document.styleSheets.length; i++) { 
		var styleSheet = document.styleSheets[i]; css_rules = document.styleSheets[i].cssRules || document.styleSheets[i].rules;
		if(!css_rules) continue;
		var j = 0;
		do {
			if(css_rules[j].selectorText.toLowerCase() == rule_name) {
				if(delete_flag == true) {
					if(document.styleSheets[i].removeRule) document.styleSheets[i].removeRule(j);
					if(document.styleSheets[i].deleteRule) document.styleSheets[i].deleteRule(j);
					return true;
				}
				else return css_rules[j];
			}
		}
		while (css_rules[++j]);
	}
	return false;
}
function add_css(rule_name, stylesheet) {
	rule_name = rule_name.toLowerCase(); stylesheet = stylesheet || 0;
	if (!document.styleSheets || get_css(rule_name, stylesheet)) return false;
	(document.styleSheets[stylesheet].addRule) ? document.styleSheets[stylesheet].addRule(rule_name, null, 0) : document.styleSheets[stylesheet].insertRule(rule_name+' { }', 0);
	return get_css(rule_name);
}
function get_sheet_num (href_name) {
	if (!document.styleSheets) return false;
	for (var i = 0; i < document.styleSheets.length; i++) { if(document.styleSheets[i].href && document.styleSheets[i].href.toString().match(href_name)) return i; } 
	return false;
}
function remove_css(rule_name, stylesheet) { return get_css(rule_name, stylesheet, true); }

function add_sheet(url, media) {
	if(document.createStyleSheet) {
		document.createStyleSheet(url);
	}
	else {
		var newSS	= document.createElement('link');
		newSS.rel	= 'stylesheet';
		newSS.type	= 'text/css';
		newSS.media	= media || "all";

		newSS.href	= url;
		// var styles	= "@import url(' " + url + " ');";
		// newSS.href	='data:text/css,'+escape(styles);
		document.getElementsByTagName("head")[0].appendChild(newSS);
	}
}

/** File: javascript/jquery.listen.js **/

/**
 * jQuery.Listen - Light and fast event handling, using event delegation.
 * Copyright (c) 2007-2008 Ariel Flesler - aflesler(at)gmail(dot)com | http://flesler.blogspot.com
 * Dual licensed under MIT and GPL.
 * Date: 3/7/2008
 * http://flesler.blogspot.com/2007/10/jquerylisten.html
 * @version 1.0.3
 */
;(function($){var a='indexer',h=$.event,j=h.special,k=$.listen=function(c,d,e,f){if(typeof d!='object'){f=e;e=d;d=document}o(c.split(/\s+/),function(a){a=k.fixes[a]||a;var b=m(d,a)||m(d,a,new n(a,d));b.append(e,f);b.start()})},m=function(b,c,d){return $.data(b,c+'.'+a,d)};$.fn[a]=function(a){return this[0]&&m(this[0],a)||null};$[a]=function(a){return m(document,a)};$.extend(k,{regex:/^((?:\w*?|\*))(?:([#.])([\w-]+))?$/,fixes:{focus:'focusin',blur:'focusout'},cache:function(a){this.caching=a}});$.each(k.fixes,function(a,b){j[b]={setup:function(){if($.browser.msie)return!1;this.addEventListener(a,j[b].handler,!0)},teardown:function(){if($.browser.msie)return!1;this.removeEventListener(a,j[b].handler,!0)},handler:function(e){arguments[0]=e=h.fix(e);e.type=b;return h.handle.apply(this,arguments)}}});$.fn.listen=function(a,b,c){return this.each(function(){k(a,this,b,c)})};function n(a,b){$.extend(this,{ids:{},tags:{},listener:b,event:a});this.id=n.instances.push(this)};n.instances=[];n.prototype={constructor:n,handle:function(e){var a=e.stopPropagation;e.stopPropagation=function(){e.stopped=1;a.apply(this,arguments)};m(this,e.type).parse(e);e.stopPropagation=a;a=e.data=null},on:0,bubbles:0,start:function(){var a=this;if(!a.on){h.add(a.listener,a.event,a.handle);a.on=1}},stop:function(){var a=this;if(a.on){h.remove(a.listener,a.event,a.handle);a.on=0}},cache:function(a,b){return $.data(a,'listenCache_'+this.id,b)},parse:function(e){var z=this,c=e.data||e.target,d=arguments,f;if(!k.caching||!(f=z.cache(c))){f=[];if(c.id&&z.ids[c.id])p(f,z.ids[c.id]);o([c.nodeName,'*'],function(a){var b=z.tags[a];if(b)o((c.className+' *').split(' '),function(a){if(a&&b[a])p(f,b[a])})});if(k.caching)z.cache(c,f)}if(f[0]){o(f,function(a){if(a.apply(c,d)===!1){e.preventDefault();e.stopPropagation()}})}if(!e.stopped&&(c=c.parentNode)&&(c.nodeName=='A'||z.bubbles&&c!=z.listener)){e.data=c;z.parse(e)}f=d=c=null},append:function(f,g){var z=this;o(f.split(/\s*,\s*/),function(a){var b=k.regex.exec(a);if(!b)throw'$.listen > "'+a+'" is not a supported selector.';var c=b[2]=='#'&&b[3],d=b[1].toUpperCase()||'*',e=b[3]||'*';if(c)(z.ids[c]||(z.ids[c]=[])).push(g);else if(d){d=z.tags[d]=z.tags[d]||{};(d[e]||(d[e]=[])).push(g)}})}};function o(a,b,c){for(var i=0,l=a.length;i<l;i++)b.call(c,a[i],i)};function p(a,b){a.push.apply(a,b);return a};$(window).unload(function(){if(typeof n=='function')o(n.instances,function(b){b.stop();$.removeData(b.listener,b.event+'.'+a);b.ids=b.names=b.listener=null})})})(jQuery);

/** File: javascript/app-base.js **/

var App = window.App || {};

/** We will put all of our variables and resources (URL-s, listings etc) **/
App.data = {};

// All widgets should be defined here
App.widgets = {};

/**
 * Send post request to specific link
 *
 * @param string the_link
 */
App.postLink = function(the_link) {
  var form = $(document.createElement('form'));
  form.attr({
    'action' : the_link,
    'method' : 'post'
  });
  
  var submitted_field = $(document.createElement('input'));
  submitted_field.attr({
    'type'  : 'hidden',
    'name'  : 'submitted',
    'value' : 'submitted'
  });
  
  form.append(submitted_field);
  
  $('body').append(form);
  
  form.submit();
  return false;
};

/**
 * Convert & -> &amp; < -> &lt; and > -> &gt;
 *
 * @param str
 * @return string
 */
App.clean = function(str) {
  if(typeof(str) == 'string') {
    str = str.replace(/&/g, '&amp;');
    str = str.replace(/\>/g, '&gt;');
    str = str.replace(/\</g, '&lt;');
  }
  
  return str;
};

/**
 * JS version of lang function / helper
 *
 * @param string content
 * @param object params
 */
App.lang = function(content, params) {
  var translation = content;
  
  if(typeof(App.langs) == 'object') {
    if(App.langs[content]) {
      translation = App.langs[content];
    }
  }
  
  if(typeof params == 'object') {
    for(key in params) {
      translation = translation.replace(':' + key, App.clean(params[key]));
    } // if
  } // if
  return translation;
};

/**
 * JavaScript implementation of isset() function
 *
 * Usage example:
 *
 * if(isset(undefined, true) || isset('Something')) {
 *   // Do stuff
 * }
 *
 * @param value
 * @return boolean
 */
App.isset = function(value) {
  return !(typeof(value) == 'undefined' || value === null);
};

/**
 * Add async variables to async link
 *
 * @param string link
 * @return string
 */
App.makeAsyncUrl = function(link) {
  if (link) {
    if (link.indexOf('?') < 0) {
      link += '?async=1&skip_layout=1'
    } else {
      link += '&async=1&skip_layout=1'
    } // if
    return link;
  } else {
    return false;
  }
};

/**
 * Convert MySQL formatted datetime string to Date() object
 *
 * @params String timestamp
 * @return Date
 */
App.mysqlToDate = function(timestamp) {
  var regex=/^([0-9]{2,4})-([0-1][0-9])-([0-3][0-9]) (?:([0-2][0-9]):([0-5][0-9]):([0-5][0-9]))?$/;
  var parts=timestamp.replace(regex, "$1 $2 $3 $4 $5 $6").split(' ');
  return new Date(parts[0], parts[1], parts[2], parts[3], parts[4], parts[5]);
};

/**
 * Attach more parameters to URL
 *
 * @param string url
 * @param object extend_with
 */
App.extendUrl = function(url, extend_with) {
  if(!url || !extend_with) {
    return url;
  } // if
  
  var extended_url = url;
  var parameters = [];
  
  extended_url += extended_url.indexOf('?') < 0 ? '?' : '&';
  
  for(var i in extend_with) {
    if(typeof(extend_with[i]) == 'object') {
      for(var j in extend_with[i]) {
        parameters.push(i + '[' + j + ']' + '=' + extend_with[i][j]);
      } // for
    } else {
      parameters.push(i + '=' + extend_with[i]);
    } // if
  } // for
  
  return extended_url + parameters.join('&');
};

/**
 * Parse numeric value and return integer or float
 *
 * @param String value
 * @return mixed
 */
App.parseNumeric = function(value) {
  if(typeof(value) == 'number') {
    return value;
  } else if(typeof(value) == 'string') {
    if(value.indexOf('.') > -1) {
      var separator = '.';
    } else if(value.indexOf(',') > -1) {
      var separator = ',';
    } else {
      return value == '' ? 0 : parseInt(value);
    } // if
       
    var separator_pos = value.indexOf(separator);
    var whole_number = parseInt(value.substring(0, separator_pos));
    var decimal = parseFloat('0.' + value.substring(separator_pos + 1));    

    return value.indexOf('-', 0) ? whole_number + decimal : whole_number - decimal;
  } else {
    return NaN;
  }
};

/**
 * Parse string and return version object
 *
 * @param String str
 * @return Object
 */
App.parseVersionString = function (str) {
    if (typeof(str) != 'string') { return false; }
    var x = str.split('.');
    // parse from string or default to 0 if can't parse
    var maj = parseInt(x[0]) || 0;
    var min = parseInt(x[1]) || 0;
    var pat = parseInt(x[2]) || 0;
    return {
        major: maj,
        minor: min,
        patch: pat
    }
}; // parseVersionString

/**
 * compare versions, if they are same returns 0, if first is lower returns -1, and
 * if second is lower returns 1
 *
 * @var string version1
 * @var string version2
 * @return int
 */
App.compareVersions = function (version1, version2) {
  version1 = App.parseVersionString(version1);
  version2 = App.parseVersionString(version2);
    
  if (version1.major < version2.major) {
    return -1;
  } else if (version1.major > version2.major) {
    return 1;
  } else {
    if (version1.minor < version2.minor) {
      return -1;
    } else if (version1.minor > version2.minor) {
      return 1;
    } else {
      if (version1.patch < version2.patch) {
        return -1;
      } if (version1.patch > version2.patch) {
        return 1;
      } else {
        return 0;
      } // if
    } // if
  } // if
} // compareVersions

jQuery.fn.highlightFade = function() {
  return this.effect("highlight", {}, 1000)
};

function ucfirst( str ) {
  str += '';
  var f = str.charAt(0).toUpperCase();
  return f + str.substr(1);
}

/** File: javascript/app.js **/

// Do stuff that we need to do on every page...
$(document).ready(function() {
  App.layout.init();
  App.RefreshSession.init();
  App.PrintPreview.init();
  App.widgets.SendReminder.init();
});

/** Layout **/
App.layout = function() {
  
  // Result
  return {
  
    /**
     * Initialize layout
     */
    init : function() {
      // Preload indicator...
      var indicator = new Image();
      indicator.src = App.data.indicator_url;
      
      // Jump to project button
      var project_menu_item = $('#menu_item_projects');
      project_menu_item.append('<span class="additional"><a href="' + App.data.jump_to_project_url + '"><span>' + App.lang('Jump to Project') + '</span></a></span>');
      project_menu_item.find('span.additional a').click(function() {
        App.ModalDialog.show('jump_to_project', App.lang('Jump to Project'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(App.data.jump_to_project_url), {});
        return false;
      });
      
      // Search button
      var search_menu_item = $('#menu_item_search a').click(function() {
        var quick_search_url = App.extendUrl($(this).attr('href'), { 
          skip_layout : 1, 
          async : 1 
        });
        App.ModalDialog.show('quick_search', App.lang('Quick Search'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(quick_search_url), {
          buttons : false
        });
        return false;
      });
      
      $('#page_actions .with_subitems>a').click(function() {
        return false;
      });
      
      // Quick add button
      $('#menu_item_quick_add a').click(function() {
        var url = App.extendUrl(App.data.quick_add_url, { skip_layout : 1});
        
        App.ModalDialog.show('quick_add', App.lang('Quick Add'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(url), {
          buttons : false,
          width: 560
        });
        return false;
      });
      
      // Flash
      $('#success, #error').click(function() {
        $(this).hide('fast');
      });
      
      // Hoverable
      $('.hoverable').hover(function() {
        $(this).addClass('hover');
      }, function() {
        $(this).removeClass('hover');
      });
      
      // Card
      $('.card div.options').each(function() {
        wrapper = $(this);
        var first_list_item = wrapper.find('li.first');
        wrapper.find('a').hover(function() {
          first_list_item.text($(this).attr('title'));
        }, function() {
          first_list_item.html('&nbsp;');
        });
      });
      
      // Scale big images in object description blocks
      $('div.body.content').scaleBigImages();
      
      $('.button_dropdown').each(function () {
        var dropdown_button = $(this);
        var dropdown_menu = dropdown_button.find('.dropdown_container');
        dropdown_button.hover(function () {
          
        }, function () {
          dropdown_menu.fadeOut(100);
        }).click(function () {
          if (dropdown_menu.is(':visible')) {
            dropdown_menu.fadeOut(100);  
          } else {
            dropdown_menu.fadeIn(100);
          } // if
        });
      });
    },
    
    /**
     * Init star unstar link
     *
     * @param string id
     * @return null
     */
    init_star_unstar_link : function(id) {
      $('#' + id).click(function() {
        var link = $(this);
        var parent = link.parent();
      
        // Block additional clicks
        if(link[0].block_clicks) {
          return false;
        } else {
          link[0].block_clicks = true;
        } // if
        
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : App.extendUrl(link.attr('href'), { async : 1 }),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
            parent.empty();
            parent.append(response);
          },
          error   : function() {
            img.attr('src', old_src);
          }
        });
        
        return false;
      });
    },
    
    /**
     * Complete / reopen task
     *
     * @param string id
     */
    init_complete_open_link : function(id) {
      $('#' + id).click(function() {
        var link = $(this);
        var parent = link.parent();
      
        // Block additional clicks
        if(link[0].block_clicks) {
          return false;
        } else {
          link[0].block_clicks = true;
        } // if
        
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : App.extendUrl(link.attr('href'), { async : 1 }),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
            parent.empty();
            parent.append(response);
          },
          error   : function() {
            img.attr('src', old_src);
          }
        });
        
        return false;
      });
    },
    
    /**
     * Initialize subscribe / unsubscribe link
     *
     * @param string wrapper_id
     * @return null
     */
    init_subscribe_unsubscribe_link : function(wrapper_id) {
      $('#' + wrapper_id + ' a').click(function(e) {
        var link = $(this);
        var parent = link.parent();
      
        // Block additional clicks
        if(link[0].block_clicks) {
          return false;
        } else {
          link[0].block_clicks = true;
        } // if
        
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : App.extendUrl(link.attr('href'), { async : 1 }),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
            parent.empty();
            parent.append(response);
          },
          error   : function() {
            img.attr('src', old_src);
          }
        });
        
        return false;
      });
    },
    
    /**
     * Reindex opened tasks table, change colors of rows, and display hidden row if necessarry
     *
     * @param string table
     * @return null
     */
    reindex_task_table: function (table) {
      table = $(table);
      var counter = 0;
      table.find('li:not(.empty_row):not(.ui-sortable-helper):not(.sort_placeholder)').each(function() {
        row = $(this);
        if ((counter % 2) == 1) {
          row.removeClass('odd');
          row.addClass('even');
        } else {
          row.removeClass('even');
          row.addClass('odd');
        } // if
        counter++;
      });     
      
      if (counter<1) {
        table.find('.empty_row').show();
      } else {
        table.find('.empty_row').hide();
      } // if
    },
    
    /**
     * Init row in tasks table
     *
     * @param object row
     * @param object wrapper
     */
    init_object_task: function (row, wrapper) {
      if (wrapper.drag_enabled==true) {
        row.find('.drag_handle').show();
      } else {
        row.find('.drag_handle').hide();
      }
      
      // complete task
      row.find('a.complete_task').click(function() {
        var link = $(this);
        var complete_tasks_table = link.parents('.object_tasks').find('.completed_tasks_table');
        
        // Block additional clicks
        if(link[0].block_clicks) {
          return false;
        } else {
          link[0].block_clicks = true;
        } // if
        
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : link.attr('href'),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
            var response_obj = $(response);
            var open_tasks_table = link.parents('.object_tasks').find('.tasks_table');
            complete_tasks_table.prepend(response_obj);
            row.remove();
            App.layout.init_object_task(response_obj,wrapper);
            App.layout.reindex_task_table(open_tasks_table);
          },
          error   : function() {
            img.attr('src', old_src);
          }
        });
        
        return false;
      });
      
      // open task
      row.find('a.open_task').click(function() {
        var link = $(this);
        var open_tasks_table = link.parents('.object_tasks').find('.open_tasks_table');
        
        // Block additional clicks
        if(link[0].block_clicks) {
          return false;
        } else {
          link[0].block_clicks = true;
        } // if
        
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : link.attr('href'),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
            var response_obj = $(response);
            open_tasks_table.append(response_obj);
            row.remove();
            App.layout.init_object_task(response_obj,wrapper);
            App.layout.reindex_task_table(open_tasks_table);
          },
          error   : function() {
            img.attr('src', old_src);
          }
        });
        
        return false;
      });
      
      // Remove buttons
      row.find('a.remove_task').click(function() {
        var link = $(this);
        
        // Block additional clicks
        if(link[0].block_clicks) {
          return false;
        } else {
          link[0].block_clicks = true;
        } // if
        
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : App.extendUrl(link.attr('href'), {'async' : 1}),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function() {
            row.remove();
          },
          error   : function() {
            img.attr('src', old_src);
          }
        });
        
        return false;
      });
    },
    
    /**
     * Initialize tasks table
     *
     * @param string wrapper_id ID of wrapper div
     */
    init_object_tasks : function(wrapper_id, enable_reordering) {
        var wrapper = $('#' + wrapper_id);
        var form_wrapper = wrapper.find('div.add_task_form');
        var show_form = wrapper.find('a.add_task_link');
        var hide_form = wrapper.find('a.cancel_button');
        var active_tasks_table = wrapper.find('.tasks_table.open_tasks_table');
        
        form_wrapper.find('.show_due_date_and_priority a').click(function () {
          $(this).parent().hide();
          form_wrapper.find('.due_date_and_priority').slideDown();
          return false;
        });
        form_wrapper.find('.due_date_and_priority').hide();
                
        // Submit add task form
        form_wrapper.find('form').submit(function() {
          var form = $(this);
          if(UniForm.is_valid(form)) {       
            var old_form_action = form.attr('action');
            
            form.attr('action', App.extendUrl(old_form_action, { async : 1 }));
            
            var loading_row = '<li><img src="' + App.data.indicator_url + '" alt="loading" /> <strong>' + App.lang('Working') + '</strong></li>';
            active_tasks_table.append(loading_row);
            var temp_row = active_tasks_table.find('li:last');
          
            // submit form via ajax
            form.ajaxSubmit({
              success : function(response) {
                var response_obj = $(response);
                // insert real row in table
                response_obj.insertAfter(temp_row);
                // remove fake row
                temp_row.remove();
                App.layout.init_object_task(response_obj, wrapper);
                App.layout.reindex_task_table(active_tasks_table);
              },
              error : function (response) {
                // remove fake row
                temp_row.remove();
              }
            });
            
            // empty task message
            form.attr('action', old_form_action).find('input:first').val('').focus();
          } // if
          
          return false;
        });
        
        // Show task form
        show_form.click(function() {
          show_form.hide();
          $('.main_object .resource.object_tasks').show();
          form_wrapper.show().focusFirstField();
          return false;
        });
        
        $('#object_quick_option_new_task a').click(function () {
          show_form.hide();
          $('.main_object .resource.object_tasks').show();
          form_wrapper.show().focusFirstField();
          return false;
        });
        
        // Hide task form
        hide_form.click(function() {
          show_form.show();
          form_wrapper.clearErrorMessages().hide();
          form_wrapper.find('input:eq(0)').val('');
          return false;
        });
        
        form_wrapper.find('input').keypress(function(e) {
          if (e.keyCode == 27) {
            hide_form.click();
          } // if
        });
        
        if (enable_reordering > 0) {
          // init sortable behvaiour
          wrapper.find('.open_tasks_table').sortable({
            axis : 'y',      
            cursor: 'move',
            items: 'li.sort',
            delay: 3,
            revert: false,
            connectWith: ['.open_tasks_table'],
            tolerance : 'pointer',
            placeholder: 'sort_placeholder',
            forcePlaceholderSize : false,
            update: function (e, ui) {
              var sort_form = $(this).parents('form.sort_form');
              ui.item.parent().attr('style','');
              sort_form.ajaxSubmit({
                method : 'POST'
              });
              App.layout.reindex_task_table($(this));
            },
            over: function (table_object,ui) {
              $(this).addClass('dragging');
            },
            out: function (table_object,ui) {
              $(this).removeClass('dragging');
            },
            receive : function (event, ui) {
              App.layout.reindex_task_table($(this));
            },
            remove : function (event, ui) {
              App.layout.reindex_task_table($(this));
            }
          });
        } // if
               
        // init every row in table
        wrapper.find('.tasks_table li, .completed_tasks_table li').each(function () {
          App.layout.init_object_task($(this), wrapper);
        });
        
        // 'view all completed' behaviour
        wrapper.find('.completed_tasks_table li.list_all_completed a').click(function () {
          var anchor = $(this);
          var completed_tasks_table = anchor.parents('ul.completed_tasks_table:first');
          anchor.after('<span class="loading"><img src="' + App.data.indicator_url + '" alt="" />' + App.lang('Loading...') + '</a>');
          var loading_block = anchor.parent().find('.loading:first');
          anchor.hide();
          
          $.ajax({
            url : App.extendUrl(anchor.attr('href'), {async : 1, skip_layout : 1}),
            success : function (response) {
              completed_tasks_table.html(response);
              completed_tasks_table.find('li').each(function () {
                App.layout.init_object_task($(this), wrapper);
              });
            },
            error : function () {
              loading_block.remove();
              anchor.show();   
            }
          });
          return false;
        });
    }
  
  } // init
  
}();

/**
 * Modal dialog module
 */
App.ModalDialog = function() {
  
  /**
   * Current dialog reference
   *
   * @var jQuery
   */
  var dialog_object;
  
  // Let's return public interface object
  return {
    
    /**
     * Show modal dialog
     *
     *
     * @param String name
     * @param String title
     * @param mixed body
     * @param mixed settings
     */
    show : function(name, title, body, settings) {
      // dialog options
      var options = {
        modal     : true,
        draggable : false,
        resizable : true,
        title     : title,
        id        : name,
        position  : 'top',
        bgiframe  : true,
        close     : function (type,data) {
          if (settings.close) {
            settings.close();
          } // if
          dialog_object.dialog('destroy').remove();
        },
        resizeStart : function (type,data) {

        }
      };

      if (settings) {
        // width and height settings
        options.width = settings.width ? settings.width : 410;
        options.height = settings.height ? settings.height : 'auto';        
        // additional buttons
        options.buttons = {};
        if (settings && settings.buttons) {
          for (var x = 0; x < settings.buttons.length; x++) {
            if (settings.buttons[x].callback) {
              options.buttons[settings.buttons[x].label] = settings.buttons[x].callback;
            } else {
              options.buttons[settings.buttons[x].label] = function () {
                dialog_object.dialog('close');
              } // function
            } // if
          } // if
        } // if
      } // if

      options.maxWidth = options.width;
      options.minWidth = options.width;
      
      dialog_object = $(body).dialog(options);
     
      var counter = 0;
      dialog_object.parent().parent().find('.ui-dialog-buttonpane button').each(function () {
        var button = $(this);
        button.removeClass('ui-state-default').removeClass('ui-corner-all');

        var label = button.html();
        button.html('<span><span>' + label + '</span></span>');
        if (counter != 0) {
          button.addClass('alternative');
        } // if
        counter++;
      });
    },
    
    /**
     * Close the dialog
     */
    close : function() {
      dialog_object.dialog('destroy').remove();
    },
    
    /**
     * sets width of dialog
     */
    setWidth : function (width_px) {     
      var dom_dialog = $('.ui-dialog');
      var position = dom_dialog.position();
      var new_left_offset = position.left - ((width_px - dom_dialog.width())/2);
      dom_dialog.css('width' , width_px+'px').css('left', new_left_offset+'px');
    },
    
    /**
     * Sets dialog title
     */
    setTitle : function (title) {
     var dom_dialog = $('.ui-dialog .ui-dialog-titlebar span.ui-dialog-title').html(title);
    },
    
    /**
     * Checks if dialog is open
     */
    isOpen : function () {
      if ($('.ui-dialog').length > 0) {
        return true;
      } else {
        return false;
      }
    }
  };
  
}();


/**
 * Print preview module
 */
App.PrintPreview = function() {
  /**
   * Dom element of main css
   *
   * @var jQuery
   */
  var css_main;
  /**
   * Dom element of theme css
   *
   * @var jQuery
   */
  var css_theme;
  /**
   * Dom element of css preview
   *
   * @var jQuery
   */
  var css_print_preview;
  
  var href_theme,
      href_main,
      href_print;
  
  // Return value
  return {
    
    /**
     * Initialize print preview behavior
     *
     * @param void
     * @return null
     */
    init : function() {
      $('#print_button').click(function(e) {
        App.PrintPreview.open();
        e.stopPropagation();
        return false;
      });
      
      $('#print_preview_header #print_preview_close').click(function() {
        App.PrintPreview.close();
        return false;
      });
      
      $('#print_preview_header #print_preview_print').click(function() {
        window.print();
        return false;
      });
      
      css_main = $('#style_main_css');
      css_theme = $('#style_theme_css');
      css_print_preview = $('#print_preview_css');
      
      href_theme = css_theme.attr('href');
      href_main = css_main.attr('href');
      href_print = css_print_preview.attr('href');
    },
    
    /**
     * Show print preview view
     *
     * @param void
     * @return null
     */
    open : function() {
      css_main.attr('href', href_print);
      css_theme.attr('href', '');
    },

    /**
     * Close print preview view
     *
     * @param void
     * @return null
     */
    close : function() {
      css_main.attr('href', href_main);
      css_theme.attr('href', href_theme);
    }
    
  };
  
}();

/**
 * Comment options behavior
 */
App.CommentOptions = function() {
  
  /**
   * Result
   */
  return {
    
    /**
     * Initialize
     *
     * @param string wrapper_id ID of warpper div
     * @return void
     */
    init : function(wrapper_id) {
      $('#' + wrapper_id).each(function() {
        var wrapper = $(this);
        var first_element = wrapper.find('li.comment_options_first');
        
        wrapper.find('a, span').hover(function() {
          first_element.html($(this).attr('title'));
        }, function() {
          first_element.html('&nbsp;');
        });
      });
    } // init
    
  }
  
}();

App.EmailObject = function() {
  return {
    init : function (object_id) {
      var email_object = $('#'+object_id);
      var blockquotes = email_object.find('>blockquote');
      blockquotes.each(function () {
        var blockquote = $(this);
        if (!blockquote.parent().is('div.content')) {
          blockquote = blockquote.parent();
        } // if
        blockquote.before('<a href="#" class="hidden_history">' + App.lang('Hidden Email History') + '</a>');
        blockquote.hide();
        var blockquote_anchor = blockquote.prev();
        
        blockquote_anchor.click(function () {
          blockquote.slideDown();
          $(this).remove();
          return false;
        });
      });
    }
  }
}();

// Refresh session requests
App.RefreshSession = function() {
  
  /**
   * Interval object used to call refresh function
   */
  var refresh_interval = null;
  
  // Return value
  return {
    
    /**
     * Initialize refresh interval
     *
     * @params void
     * @return void
     */
    init : function() {
      if(App.data.keep_alive_interval > 0) {
        refresh_interval = setInterval('App.RefreshSession.refresh()', App.data.keep_alive_interval);
      } // if
    },
    
    /**
     * Function used to refresh session
     *
     * @param void
     * @return null
     */
    refresh : function() {
      $.ajax({
        url : App.data.refresh_session_url
      });
    }
  }
  
}();

/**
 * Quick search module
 */
App.QuickSearch = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize quick search form
     *
     * @param void
     * @return undefined
     */
    init : function() {
      $('#quick_search_form').submit(function() {
        $('#quick_search_button').hide();
        $('#quick_search_indicator').show();
        
        var form = $(this);
        var results = $('#quick_search_results');
        
        results.empty();
        
        $.ajax({
          type : 'POST',
          url : App.extendUrl(form.attr('action'), { async : 1}),
          data : {
            submitted : 'submitted',
            search_for : $('#quick_search_input').val(),
            search_type : $('#quick_search_type').val()
          },
          success : function(response) {
            results.append(response);
            
            $('#quick_search_button').show();
            $('#quick_search_indicator').hide();
          }
        });
        return false;
      });
      
      $('#quick_search_form ul li').click(function() {
        var list_element = $(this);
        
        $('#quick_search_form ul li').removeClass('selected');
        list_element.addClass('selected');
        
        $('#quick_search_type').val(list_element.attr('id').substr(7));
      });
      
      $('#quick_search_form #quick_search_input')[0].focus();
    }
  };
  
}();

/**
 * Functions for main menu
 */
App.MainMenu = function() {
  var menu
  
  // Public interface
  return {
    
    /**
     * Initialize main menu
     *
     * @param void
     * @return undefined
     */
    init : function(menu_id) {
      menu = $('#'+menu_id);
    },
    
    /**
     * add item to menu
     *
     *  @param object item
     *  @param string group_id
     *  @return null
     */
    addToGroup: function (item, group_id) {
      var button_class = 'last';
      
      var group = $('#menu_group_'+group_id, menu);
      if (group.length > 0) {
        var button_text = "<li id='menu_item_" + item.id + "' class='item " + button_class + "'>";
        button_text +=    "<a class='main' href='" + item.href + "'><span class='outer'>";
        button_text +=    "<span style='background-image: url(" + item.icon + ");' class='inner'>";
        if (item.badge_value > 0) {
          button_text +=    "<span class='badge'>" + item.badge_value + "</span>"
        } // if
        button_text +=    item.label;
        button_text +=    "</span>";
        button_text +=    "</span></a>";
        button_text +=    "</li>";
        $('li.item:last', group).removeClass('last').removeClass('single').addClass('middle');
        group.append(button_text);
      } // if
    },
    
    /**
     * Check if item with id item exists in group with group_id
     *
     *  @param string item
     *  @param string group_id
     *  @return bolean
     */
    itemExists: function (item_id, group_id) {
      var group = $('#menu_group_'+group_id, menu);
      if (group.length > 0) {
        var menu_item = $('#menu_item_' + item_id, group);
        if (menu_item.length > 0) {
          return true;
        } // if
      };
      return false;
    },
    
    /**
     * Remove item if exists
     *
     *  @param string item
     *  @param string group_id
     *  @return bolean
     */
    removeButton: function (item_id, group_id) {
      var group = $('#menu_group_'+group_id, menu);
      if (group.length > 0) {
        var previous_class = 'last'
        if ($('li', group).length <= 2) {
          previous_class = 'single';
        } // if
        $('#menu_item_' + item_id, group).remove();
        $('li:last', group).removeClass('middle').addClass(previous_class);
      };
    },
    
    /**
     * Set badge value for item
     *
     *  @param string item
     *  @param string group_id
     *  @param string badge_value
     *  @return bolean
     */
    setItemBadgeValue: function (item_id, group_id, badge_value) {
      var group = $('#menu_group_'+group_id, menu);
      if (group.length > 0) {
        var menu_item = $('#menu_item_' + item_id, group);
        if (menu_item.length) {
          if (badge_value > 0) {
            var badge = $('span.badge', menu_item);
            if (badge.length > 0) {
              badge.text(badge_value);
            } else {
              $('a>span>span', menu_item).prepend('<span class="badge">' + badge_value + '</span>');
            } // if
            return true;
          } else {
            $('span.badge', menu_item).remove();
            return true;
          } // if
        } // if
      } // if
      return false;
    }
  };
}();

/*
App.Menu = function() {
  
  return {
    set_badge_value : function(item_id, value) {     
      if(value > 0) {
        var parent = $('#' + item_id + '>a>span>span');
        var badge = parent.find('span.badge');
        if(badge.length > 0) {
          badge.text(value);
        } else {
          parent.prepend('<span class="badge">' + value + '</span>');
        } // if
      } else {
        $('#' + item_id + ' span.badge').remove();
      }
    }
    
  };
  
}();
*/

/** File: modules/system/javascript/main.js **/

App.system = {
  controllers : {},
  models      : {}
};

/**
 * People controller client side behavior
 */
App.system.controllers.dashboard = {
  
  /**
   * Prepare dashboard index page
   */
  index : function() {
    $(document).ready(function() {
      
      // Active reminders
      $('#active_reminders').each(function() {
        var wrapper = $(this);
        
        wrapper.find('table tr.with_comment').each(function() {
          var row = $(this);
          row.find('td.name').prepend('<span class="show_hide_reminder_comment"><a href="#">' + App.lang('Show Comment') + '</a></span>');
          row.find('td.name span.show_hide_reminder_comment a').click(function() {
            var note = row.find('td.name span.reminder_comment');
            var link = $(this);
            
            if(note.length) {
              if(note.css('display') == 'none') {
                note.show('fast');
                link.text(App.lang('Hide Comment'));
              } else {
                note.hide('fast');
                link.text(App.lang('Show Comment'));
              } // if
            } // if
            return false;
          });
        });
        
        var reindex_odd_even_rows = function() {
          var counter = 1;
          wrapper.find('tr').each(function() {
            var row = $(this);
            row.removeClass('even').removeClass('odd');
            if(counter % 2 == 1) {
              row.addClass('odd');
            } else {
              row.addClass('even');
            } // if
            counter++;
          });
        };
        
        wrapper.find('table a.dismiss_reminder').click(function() {
          var link = $(this);
        
          // Block additional clicks
          if(link[0].block_clicks) {
            return false;
          } else {
            link[0].block_clicks = true;
          } // if
          
          var img = link.find('img');
          var old_src = img.attr('src');
          
          img.attr('src', App.data.indicator_url);
          
          $.ajax({
            url     : link.attr('href'),
            type    : 'POST',
            data    : {'submitted' : 'submitted'},
            success : function() {
              link.parent().parent().remove();
              reindex_odd_even_rows();
              if(wrapper.find('table tr').length < 1) {
                wrapper.find('div.section_container').append('<p class="details center">' + App.lang('All reminders dismissed') + '</p>');
              } // if
            },
            error   : function() {
              img.attr('src', old_src);
            }
          });
          
          return false;
        });
      });
      
      $('#active_projects .pinned a').click(function() {
				var link = $(this);
				var wrapper = link.parents('.pinned');
				var row = wrapper.parent();
				var container = row.parents('.section_container');
				
				/**
		     * Reindex table rows
		     */
		    var reindex_odd_even_rows = function() {
		      var counter = 1;
		      container.find('tr').each(function() {
		        var rows = $(this);
		        rows.removeClass('even').removeClass('odd');
		        if(counter % 2 == 1) {
		          rows.addClass('even');
		        } else {
		          rows.addClass('odd');
		        } // if
		        counter++;
		      });
		    }; // reindex_table_rows
				
				link.hide();
				wrapper.prepend('<img src="' + App.data.indicator_url  + '" class="indicator" alt="" />');
				
				$.ajax({
					url     : App.extendUrl(link.attr('href'), { async : 1 }),
					type    : 'POST',
					data    : {'submitted' : 'submitted'},
					success : function(response) {
						
					if (link.is('.pin_to_top')){
						row.prependTo(container.find('#pinned_active_projects tbody'));
						row.highlightFade();
						row.find('img.indicator').remove();
						link.attr({
							'href'  : response,
							'title' : App.lang('Unpin')
						}).show().find('img').attr({
							'src'   : App.data.pin_icon_url,
							'title' : App.lang('Unpin')
						});
						link.removeClass('pin_to_top').addClass('unpin');
					} else if(link.is('.unpin')) {
						row.appendTo(container.find('#other_active_projects tbody'));
						row.highlightFade();
						row.find('img.indicator').remove();
						link.attr({
							'href'  : response,
							'title' : App.lang('Pin to top')
						}).show().find('img').attr({
							'src'   : App.data.unpin_icon_url,
							'title' : App.lang('Pin to top')
						});
						link.removeClass('unpin').addClass('pin_to_top');
					}
						reindex_odd_even_rows();
					},
					error   : function() {
						link.show();
					}
				});
				
				return false;
			});
      
    });
  },
  
  /**
   * Search page behavior
   */
  search : function() {
    $(document).ready(function() {
      $('#search_form').submit(function() {
        var form = $(this);
        
        var search_for = jQuery.trim($("#search_for_input").val());
        if(search_for == '') {
          return false;
        } // if
        
        form.block(App.lang('Working...'));
        
        location.href = App.extendUrl(form.attr('action'), {
          q : search_for,
          type : $('#search_for_type').val()
        });
        
        return false;
      });
    });
  },
  
  /**
   * Trash page behavior
   */
  trash : function() {
    $(document).ready(function() {
      $('#trashed_objects_form').submit(function() {
        var form = $(this);
        var selected_action = form.find('option:selected').val();
        
        if(selected_action == 'delete') {
          return confirm(App.lang('Are you sure that you wish to permanently delete selected item(s)?'));
        } // if
      });
    });
  }
  
};

/**
 * Handlers for settings section
 */
App.system.controllers.settings = {
  
  /**
   * General options
   */
  general : function() {
    $(document).ready(function() {
      
      /**
       * Show/Hide on_logout_url option
       */
      var show_hide_logout_url_field = function() {
        var checked_option = $('input[name=use_on_logout_url]:checked').val();
        var use_logout_url = $('#on_logout_url_container');
        if (checked_option == 0) {
          use_logout_url.hide('fast');
        }
        else {
          use_logout_url.show('fast', function() {
            use_logout_url.find('input')[0].focus();
          });
        }
      };
      
      $('input[name=use_on_logout_url]').click(show_hide_logout_url_field);
      show_hide_logout_url_field();
    });
  },
  
  
  /**
   * Mailing settings
   */
  mailing : function() {
    $(document).ready(function() {
      
      /**
       * Enable or disable SMTP settings block
       */
      var enable_disable_smtp_settings = function() {
        if($('#mailingType').val() == 'smtp') {
          $('#smtp_mailer_settings').show();
          $('#smtp_mailer_settings input').attr('disabled', '');
          $('#mailingSecurity').attr('disabled', '');
          
          $('#native_mailer_settings').hide();
        } else {
          $('#smtp_mailer_settings').hide();
          $('#smtp_mailer_settings input').attr('disabled', 'disabled');
          $('#mailingSecurity').attr('disabled', 'disabled');
          
          $('#native_mailer_settings').show();
        } // if
      };
      
      var enable_disable_smpt_authentication = function() {
        if($('#mailingAuthenticateRadioWrapper input:checked').val() == '0') {
          $('#mailingAuthenticateWrapper')
            .find('input').val('').end()
            .find('select').val('off').end();
          $('#mailingAuthenticateWrapper').hide('fast');
        } else {
          $('#mailingAuthenticateWrapper').show('fast');
        } // if
      };
      
      $('#mailingType').change(enable_disable_smtp_settings);
      enable_disable_smtp_settings();
      
      $('#mailingAuthenticateRadioWrapper input[type=radio]').click(enable_disable_smpt_authentication);
      enable_disable_smpt_authentication();

      
      
      var mailbox_form = $('#mailing_settings_admin');
      var result_container = $('#test_connection .test_connection_results', mailbox_form);
      var result_image = $('img:eq(0)', result_container);
      var result_output = $('span:eq(0)', result_container);
      
      $('#test_connection button').click(function () {
        result_output.text('');
        result_image.attr('src', App.data.indicator_url);

        mailbox_form.ajaxSubmit({
          dataType : 'json',
          success:    function(response) {
            result_output.text(response.message);
            if (response.isSuccess) {
              result_image.attr('src', App.data.ok_indicator_url);
              result_container.removeClass('connection_error');
              result_container.addClass('connection_ok');              
            } else {
              result_image.attr('src', App.data.error_indicator_url);
              result_container.removeClass('connection_ok');
              result_container.addClass('connection_error');
            } // if
          },
          error:      function(response) {
            result_output.text(App.lang('Could not connect to server with given parameters'));
            result_image.attr('src', App.data.error_indicator_url);
            result_container.removeClass('connection_ok');
            result_container.addClass('connection_error');
          },
          url: App.data.test_smtp_connection_url
        });
      });
      
    });
  }
};

/**
 * Handlers for roles administration controller
 */
App.system.controllers.roles_admin = {
  
  /**
   * Roles admin behavior
   */
  index : function() {
    $(document).ready(function() {
      $('#system_roles td.checkbox input').click(function() {
        var checkbox = $(this);
        var cell = checkbox.parent();
        
        // Status is not changed to checked (status is set before callback)
        if(this.checked) {
          this.checked = false;
        } else {
          return false;
        } // if
        
        if(confirm(App.lang('Are you sure that you want to set this role as a default role? Please check description in "About Roles" section to learn what is default role and why is it important'))) {
          checkbox.hide();
          cell.append('<img src="' + App.data.indicator_url + '" />');
          
          $.ajax({
            url  : App.extendUrl(checkbox.attr('set_as_default_url'), { async : 1 }),
            type : 'POST',
            data : {
              submitted : 'submitted'
            },
            success : function() {
              $('#system_roles td.checkbox input').each(function() {
                this.checked = false;
              });
              
              checkbox[0].checked = true;
              
              cell.find('img').remove();
              checkbox.show();
              return true;
            },
            error : function() {
              cell.find('img').remove();
              checkbox.show();
              
              alert(App.lang('Failed to set this role as default role'));
              
              return false;
            }
          });
        } // if
        
        return false;
      });
    });
  }
  
};

/**
 * Languages controller behavior
 */
App.system.controllers.languages_admin = {
  
  /**
   * Language administration index page behavior
   */
  index : function() {
    $(document).ready(function() {
      $('#languages td.checkbox input').click(function() {
        var checkbox = $(this);
        var cell = checkbox.parent();
        
        // Status is not changed to checked (status is set before callback)
        if(this.checked) {
          this.checked = false;
        } else {
          return false;
        } // if
        
        if(confirm(App.lang('Are you sure that you want to set this language as a default?'))) {
          checkbox.hide();
          cell.append('<img src="' + App.data.indicator_url + '" />');
          
          $.ajax({
            url  : App.extendUrl(checkbox.attr('set_as_default_url'), { async : 1 }),
            type : 'POST',
            data : {
              submitted : 'submitted'
            },
            success : function() {
              $('#languages td.checkbox input').each(function() {
                this.checked = false;
              });
              
              checkbox[0].checked = true;
              
              cell.find('img').remove();
              checkbox.show();
              return true;
            },
            error : function() {
              cell.find('img').remove();
              checkbox.show();
              
              alert(App.lang('Failed to set this language as default'));
              
              return false;
            }
          });
        } // if
        
        return false;
      });
    });
  },
  
  /**
   * Edit translation page
   */
  edit_translation_file : function() {
    $(document).ready(function() {
      $('.common_table.lang_table tr td input').focus(function() {
        $(this).parent().parent().addClass('focused');
        $(this).parent().removeClass('new');
      });
      
      $('.common_table.lang_table tr td input').blur(function() {
        $(this).parent().parent().removeClass('focused');
        if ($(this).val()) {
          $(this).parent().removeClass('new');
        } else {
          $(this).parent().addClass('new');
        }
      });
      
      $('.common_table.lang_table .copy_arrow img').click(function() {
        var string = $(this).parent().siblings('.dictionary').text();
        $(this).parent().siblings('.input').children('input').each(function() {
          $(this).val(string);
          $(this).parent().removeClass('new');
        });
      });
    });
  } // edit_translation_file
  
};

/**
 * Project controller actions behavior
 */
App.system.controllers.project = {
  
  /**
   * Add project form behavior
   */
  add : function() {
    $(document).ready(function() {
      $('#projectTemplate').change(function() {
        if($(this).val() == '') {
          $('#users_from_template').hide();
          $('#users_from_auto_assignment').show();
        } else {
          $('#users_from_auto_assignment').hide();
          $('#users_from_template').show();
        } // if
      });
    });
  },
  
  /**
   * User tasks page
   */
  user_tasks : function() {
    $(document).ready(function() {
      $('#assignments a.complete_assignment, #assignments a.remove_assignment').click(function() {
        var link = $(this);
        
        // Block additional clicks
        if(link[0].block_clicks) {
          return false;
        } else {
          link[0].block_clicks = true;
        } // if
        
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : link.attr('href'),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
            link.parent().parent().remove();
            
            var counter = 1;
            $('#assignments tr.assignment_row').each(function() {
              var new_class = counter % 2 == 1 ? 'odd' : 'even';
              $(this).removeClass('even').removeClass('odd').addClass(new_class);
              counter++;
            });
          },
          error   : function() {
            img.attr('src', old_src);
            link[0].block_clicks = false;
          }
        });
        
        return false;
      });
    });
  }
  
};

/**
 * Projects section
 */
App.system.controllers.projects = {
  
  /**
   * Projects administration index page
   */
  index: function() { 
    $(document).ready(function() {
      $('#projects').checkboxes();
    });
  },
  
  /**
   * Projects administration archive page
   */
  archive: function() { 
    $(document).ready(function() {
      $('#projects').checkboxes();
    });
  }
  
};

/**
 * Project groups administration behavior
 */
App.system.controllers.project_groups = {
  
  /**
   * View projects group
   */
  view : function() { 
    $(document).ready(function() {
      $('#projectGroup').checkboxes();
    });
  }
  
};

/**
 * User profile controller behavior
 */
App.system.controllers.users = {
  
  /**
   * View user profile behavior
   */
  view : function() {
    $(document).ready(function() {
      $('#send_welcome_message_page_action a').click(function() {
        var send_welcome_message_url = App.extendUrl($(this).attr('href'), { async : 1 });
        
        App.ModalDialog.show('send_welcome_message_popup', App.lang('Send Welcome Message'), $('<p><img src="' + App.data.indicator_url + '" alt="" /> ' + App.lang('Loading...') + '</p>').load(send_welcome_message_url), {
          width: 500
        });
        
        return false;
      });
    });
  },
  
  /**
   * Create user page behavior
   */
  add : function() {
    $(document).ready(function() {
      $('#new_user div.additional_step').each(function() {
        var wrapper = $(this);
        var body = wrapper.find('div.body');
        
        wrapper.find('div.head input[type=checkbox]').each(function() {
          if(this.checked) {
            body.show('fast');
          } else {
            body.hide();
          } // if
          
          $(this).click(function() {
            if(this.checked) {
              body.show('fast');
            } else {
              body.hide();
            } // if
          });
        });
      });
    });
  },
  
  /**
   * Edit user settings page behavior
   */
  edit_settings : function() {
    $(document).ready(function() {
      $('#userAutoAssignYesInput').click(function() {
        $('#auto_assign_role_and_permissions').show();
      });
      
      $('#userAutoAssignNoInput').click(function() {
        $('#auto_assign_role_and_permissions').hide();
      });
    });
  }
  
};

/**
 * Dashboard sections behavior implementation
 */
App.widgets.DashboardSections = function() {
  
  /**
   * Wrapper instance
   *
   * @var jQuery
   */
  var wrapper;
  
  /**
   * Content block wrapper
   *
   * @var jQuery
   */
  var section_content_wrapper;
  
  // Public interface
  return {
    
    /**
     * Initialize dashboard sections
     *
     * @param String wrapper_id
     */
    init : function(wrapper_id) {
      wrapper = $('#' + wrapper_id);
      section_content_wrapper = wrapper.find('div.top_tabs_object_list .dashboard_wide_sidebar_inner_2');
      
      wrapper.find('ul.dashboard_tabs a').click(function(e) {
        var link = $(this);
        var list_item = link.parent();
        
        if(list_item.is('li.selected')) {
          return false;
        } // if
        
        var section_content_id = list_item.attr('id') + '_content';
        
        // Hide all visible content blocks
        section_content_wrapper.find('div.dashboard_section_content').hide();
        
        // Find or load section content
        var section_content = section_content_wrapper.find('#' + section_content_id);
        if(section_content.length == 0) {
          section_content = $('<div id="' + section_content_id + '" class="dashboard_section_content"><p class="dashboard_sections_loading"><img src="' + App.data.big_indicator_url + '" alt="" /></p></div>').appendTo(section_content_wrapper);
          section_content.load(App.extendUrl(link.attr('href'), {
            'async' : 1,
            'for_dashboard_section' : 1
          }));
        } // if
        
        section_content.show();
        
        // Mark tab as selected
        wrapper.find('ul.dashboard_tabs li').removeClass('selected');
        list_item.addClass('selected');
        
        return false;
      });
      
      // Select first section automatically
      wrapper.find('ul.dashboard_tabs li:first a').click(); 
    }
    
  };
  
}();

/**
 * Dashboard favorite projects behavior implementation
 */
App.widgets.DashboardFavoriteProjects = function() {
  
  /**
   * Wrapper instance
   *
   * @var jQuery
   */
  var wrapper;
  
  /**
   * initialize favorite row
   
   */
  var init_favorite_row = function (favorite_row) {
    
      favorite_row.find('a.unpin').click(function () {
        var anchor = $(this);
        var anchor_container = anchor.parents('li.pinned_project:first');
        var anchor_list = anchor.parents('ul:first');
        anchor_container.block();
        $.ajax({
          data    : '&submitted=submitted',
          url     : App.extendUrl(anchor.attr('href'), {async : 1, skip_layout : 1}),
          type    : 'POST',
          success : function () {
            anchor_container.remove();
            check_favorite_list(anchor_list);
          },
          error   : function () {
            anchor_container.unblock();
          }
        });
        
        return false;
      });
      
      favorite_row.hover(function () {
        $(this).find('a.unpin').show();
      }, function () {
        $(this).find('a.unpin').hide();
      });
      
      return favorite_row;
  };
  
  var check_favorite_list = function (favorite_list) {
    if (favorite_list.find('li').length==1) {
      favorite_list.find('li.drop_here').show();
    } else {
      favorite_list.find('li.drop_here').hide();
    } // if
  };
  
  // Public interface
  return {
    
    /**
     * Initialize dashboard sections
     *
     * @param String wrapper_id
     */
    init : function(wrapper_id) {
      wrapper = $('#' + wrapper_id);
      check_favorite_list(wrapper.find('ul:first'));
      
      wrapper.find('li.pinned_project').each(function () {
        init_favorite_row($(this));
      });
      
      wrapper.find('ul').droppable({
        accept      : '.active_project',
        hoverClass  : 'droppable_active',
        tolerance   : 'pointer',
        drop        : function(event, ui) {
          var project_id = ui.helper.attr('id');
          var favorite_list = $(this);
          var existing_favorite = favorite_list.find('li[id='+project_id+']');
          if (existing_favorite.length == 0) {
            var new_entry = '<li class="with_icon pinned_project" id="'+project_id+'">' +
              '<a href="' + ui.helper.attr('unpin_url') + '" class="unpin"><img src="' + App.data.assets_url + '/images/dismiss.gif" alt="" /></a>' +
              ui.helper.find('td.icon').html() +
              '<span class="name">' + ui.helper.find('td.name').html() + '</span>' +
            '</li>';
            
            var new_favorite_row = favorite_list.find('.drop_here').before(new_entry).prev();
            init_favorite_row(new_favorite_row);
            
            $.ajax({
              data    : '&submitted=submitted',
              url     : App.extendUrl(ui.helper.attr('pin_url'), {async : 1, skip_layout : 1}),
              type    : 'POST',
              success : function () {
              },
              error   : function () {
                new_favorite_row.remove();
                check_favorite_list(favorite_list);
              }
            });
            check_favorite_list(favorite_list);
            
            ui.helper.remove();
          } else {
            existing_favorite.highlightFade();
          }
        }
      });
    }
    
  };
}();

/**
 * Dashboard active projects behavior implementation
 */
App.widgets.ActiveProjects = function() {
  
  /**
   * Wrapper instance
   *
   * @var jQuery
   */
  var wrapper;
  
 
  // Public interface
  return {
    
    /**
     * Initialize dashboard sections
     *
     * @param String wrapper_id
     */
    init : function(wrapper_id) {
      wrapper = $('#' + wrapper_id);
      
      wrapper.find('.active_project').draggable({
        helper: 'clone',
        scroll: true,
        distance: 3,
        revert: true
      });
    }
    
  };
}();

/**
 * Dashboard important items behavior implementation
 */
App.widgets.DashboardImportantItems = function() {
  
  /**
   * Wrapper instance
   *
   * @var jQuery
   */
  var wrapper;
  
 
  // Public interface
  return {
    
    /**
     * Initialize dashboard important items
     *
     * @param String wrapper_id
     */
    init : function(wrapper_id) {
      wrapper = $('#' + wrapper_id);
      
      
      // Show and initialize reminders      
      wrapper.find('li.reminders a').click(function () {
        var anchor = $(this);
        var popup_url = App.extendUrl(anchor.attr('href'), {async : 1, skip_layout : 1});
        App.ModalDialog.show('reminders_popup', App.lang('Active Reminders'), $('<p><img src="' + App.data.indicator_url + '" alt="" /> ' + App.lang('Loading...') + '</p>').load(popup_url), { 
          buttons : [
            { label: App.lang('Close'), callback: null }
          ],
          width: 700
        });
        return false;
      });
            
    },
    
    /**
     * Remove item from list
     */
    removeItem : function(classname) {
      wrapper.find('li.'+classname).remove();
      if (wrapper.find('li').length == 0) {
        wrapper.hide();
      } // if
    } // removeItem
    
  };
}();

/**
 * Create new object from select box behavior
 */
jQuery.fn.new_object_from_select = function() {
  return this.each(function() {
    var select = $(this);
    
    var new_object_option = select.find('option.new_object_option');
    if(new_object_option.length > 0) {
      select.change(function() {
        var settings = {
          add_object_url     : App.extendUrl(select.attr('add_object_url'), { async : 1 }),
          object_name        : select.attr('object_name'),
          add_object_message : select.attr('add_object_message')
        };
      
        var selected_option = select.find('option:selected');
        if(selected_option.attr('class') == 'new_object_option') {
          var object_name = jQuery.trim(prompt(settings.add_object_message, ''));
          if(object_name) {
            var name_used = false;
            select.find('option.object_option').each(function() {
              if($(this).text().toLowerCase() == object_name.toLowerCase()) {
                name_used = $(this).attr('value');
              } // if
            });
            
            if(name_used) {
              select.val(name_used);
              return;
            } // if
            
            select.attr('disabled', true);
            
            var post_data = { 'submitted' : 'submitted' };
            post_data[settings.object_name + '[name]'] = object_name;
            
            $.ajax({
              url : settings.add_object_url,
              type : 'POST',
              data : post_data,
              success : function(response) {
                select.attr('disabled', false);
                
                var new_object_option = $('<option></option>').addClass('object_option').attr('value', response).text(object_name);
                select.find('option.object_option:last').after(new_object_option);
                select.val(response);
              },
              error : function() {
                select.attr('disabled', false);
                
                alert(App.lang('Failed to create new :name based on data you provided. Please try again later', { name : settings.object_name }));
              }
            });
          } // if
        } // if
      });
    } // if
  });
};

/**
 * Select multiple users dialog that can be attached to any control
 *
 * Settings:
 *
 * - exclude_ids  - Array of user ID-s that need to be excluded
 * - selected_ids - Array of user ID-s that are already selected. In some 
 *                  situations we do not know who the selected people are on 
 *                  time of initialization so this parameter can also be a 
 *                  callback function
 * - company_id   - Show only users that belong to this company
 * - project_id   - Show only users that have access to this project
 * - widget_id    - ID of the widget
 * - on_ok        - Callback function called when user hits OK button. Array of 
 *                  selected users is provided as parameter
 */
jQuery.fn.select_multiple_users = function(settings) {
  settings = jQuery.extend({
    exclude_ids  : null,
    selected_ids : null,
    widget_id    : null,
    company_id   : null,
    project_id   : null,
    on_ok        : null
  }, settings);
  
  $(this).click(function() {
    widget_popup = null;
    select_users_table = null;
    
    var select_users_url_data = {
      'widget_id' : settings.widget_id
    };
    
    // We need selected user ID-s
    if(settings.selected_ids) {
      
      // Do we have an array or a callback?
      if(typeof(settings.selected_ids) == 'function') {
        var selected_ids = settings.selected_ids();
      } else {
        var selected_ids = settings.selected_ids;
      } // if
      
      // If we have selected users add them to the list of request parameters
      if(selected_ids.length > 0) {
        select_users_url_data['selected_user_ids'] = [];
        for(var i = 0; i < selected_ids.length; i++) {
          if(selected_ids[i]) {
            select_users_url_data['selected_user_ids'].push(selected_ids[i]);
          } // if
        } // for
        select_users_url_data['selected_user_ids'] = select_users_url_data['selected_user_ids'].join(',');
      } // if
    } // if
    
    // Exclude ID-s
    if(settings.exclude_ids && (settings.exclude_ids.length > 0)) {
      select_users_url_data['exclude_user_ids'] = [];
      for(var i = 0; i < settings.exclude_ids.length; i++) {
        if(settings.exclude_ids[i]) {
          select_users_url_data['exclude_user_ids'].push(settings.exclude_ids[i]);
        } // if
      } // for
      select_users_url_data['exclude_user_ids'] = select_users_url_data['exclude_user_ids'].join(',');
    } // if
    
    if(settings.company_id) {
      select_users_url_data['company_id'] = settings.company_id;
    } // if
    
    if(settings.project_id) {
      select_users_url_data['project_id'] = settings.project_id;
    } // if
    
    var select_users_url = App.data.path_info_through_query_string ? 
      App.extendUrl(App.data.url_base, { 'path_info' : 'select-users' }) : 
      App.data.url_base + '/select-users';
      
    select_users_url = App.extendUrl(select_users_url, select_users_url_data);
    
    App.ModalDialog.show(
      'select_users_popup', // name
      App.lang('Select Users'),  // caption
      $('<p><img src="' + App.data.indicator_url + '" alt="" /> ' + App.lang('Loading...') + '</p>').load(select_users_url, function() {
        
        // We'll need these references later on
        widget_popup = $('#' + settings.widget_id + '_popup');
        selected_users_table = widget_popup.find('td.selected_users div.selected_users_list table');
        
        // These are just use locally
        var available_users = widget_popup.find('select');
        var selected_users_table_wrapper = widget_popup.find('td.selected_users div.selected_users_list');
        
        /**
         * Reindex even / odd classes in selected users table
         *
         * @param void
         * @return null
         */
        var reindex_odd_even_rows = function() {
          var counter = 1;
          selected_users_table.find('td').attr('style', ''); // clear style attributes left by higlightFade
          selected_users_table.find('tr').each(function() {
            $(this).removeClass('even').removeClass('odd').addClass(
              ((counter % 2) == 0) ? 'even' : 'odd'
            );
            counter++;
          });
        };
        
        /**
         * Move selected items from availale list to selected list
         *
         * @param void
         * @return null
         */
        var available_users_to_selected_users = function() {
          var users = available_users.val();
          
          if(users && users.length > 0) {
            for(var i = 0; i < users.length; i++) {
              var option = available_users.find('option[value=' + users[i] + ']');
              var row_id = settings.widget_id + '_user_' + users[i];
              var row = selected_users_table.find('#' + row_id);
              
              if(row.length == 0) {
                var row_class = (selected_users_table.find('tr').length % 2) == 0 ? 'odd' : 'even';
                
                selected_users_table.append('<tr id="' + row_id + '" class="' + row_class + '"><td class="display_name">' +
                App.lang('<span>:username</span> of :company', {
                  'username' : option.text(),
                  'company'  : option.parent().attr('label')
                }) + '</td><td class="remove"><img src="' + App.data.assets_url + '/images/gray-delete.gif" alt="" title="' + App.lang('Remove from the list') + '" /></td></tr>');
                
                row = selected_users_table.find('#' + row_id);
                row.find('td.remove img').click(remove_selected_user_row);
                
                if(selected_users_table_wrapper.css('display') == 'none') {
                  selected_users_table_wrapper.css('display', 'block');
                  widget_popup.find('td.selected_users p.no_users_selected').css('display', 'none');
                } // if
              } // if
              
              row.find('td').highlightFade();
            } // for
          } // if
        };
        
        /**
         * Remove user row from the list when clicked on the image
         *
         * @param void
         * @return null
         */
        var remove_selected_user_row = function(event) {
          $(this).parent().parent().remove();
          
          if(selected_users_table.find('tr').length == 0) {
            selected_users_table_wrapper.css('display', 'none');
            widget_popup.find('td.selected_users p.no_users_selected').css('display', 'block');
          } else {
            reindex_odd_even_rows();
          } // if
          
          event.stopPropagation();
        };
        
        // If we already have a list of selected users
        selected_users_table.find('td.remove img').click(remove_selected_user_row);
        
        // User manipulation
        widget_popup.find('td.divider img').click(available_users_to_selected_users);
        available_users.dblclick(available_users_to_selected_users);
      }), // body
      { 
        buttons : [
          {
            label: App.lang('Ok'),
            callback: function() {
              if(settings.on_ok) {
                var selected_users = [];
                widget_popup.find('td.selected_users div.selected_users_list table tr').each(function() {
                  var row = $(this);
                  selected_users.push({
                    'id'   : parseInt(row.attr('id').substr(settings.widget_id.length + 6)),
                    'name' : row.find('span').text()
                  });
                });
                settings.on_ok(selected_users);
              } // if
              App.ModalDialog.close();
            } // callback            
          },
          {
            label: App.lang('Cancel'),
            callback: null
          }
        ], // buttons
        width: 630
      } // options
    );
    
    return false;
  });
};

/**
 * Select users widget
 */
App.widgets.SelectUsers = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize select users widget
     *
     * @param string widget_id
     * @param string control_name
     * @param string company_id
     * @param string project_id
     * @param Array exclude_ids
     * @return void
     */
    init : function(widget_id, control_name, company_id, project_id, exclude_ids) {
      var widget = $('#' + widget_id);
      
      widget.find('.assignees_button').select_multiple_users({
        'widget_id'    : widget_id,
        'company_id'   : company_id,
        'project_id'   : project_id,
        'selected_ids' : function() {
          var selected_ids = [];
          $('#' + widget_id + ' div.select_users_widget_users input[type=hidden]').each(function() {
            selected_ids.push($(this).attr('value'));
          });
          return selected_ids;
        },
        'exclude_ids'  : exclude_ids,
        'on_ok'        : function(selected_users) {
          widget.find('div.select_users_widget_users').empty();
          
          if(selected_users.length > 0) {
            for(var i = 0; i < selected_users.length; i++) {
              App.widgets.SelectUsers.add_user(widget_id, control_name, selected_users[i]['id'], selected_users[i]['name']);
            } // for
          } else {
            widget.find('div.select_users_widget_users').append('<p class="details">' + App.lang('No users selected') + '</p>');
          } // if
        }
      });
      
      return false;
    },
    
    /**
     * Add new user to the list
     *
     * @param integer widget_id
     * @param string control_name
     * @param integer user_id
     * @param string display_name
     * @return void
     */
    add_user : function(widget_id, control_name, user_id, display_name) {
      var widget = $('#' + widget_id);
      var users_list = widget.find('div.select_users_widget_users ul.users_list');
      
      if(users_list.length == 0) {
        widget.find('div.select_users_widget_users').empty();
        users_list = $('<ul class="users_list"</ul>');
        widget.find('div.select_users_widget_users').append(users_list);
      } // if
      
      users_list.append('<li>' + App.clean(display_name) + '</li>');
      users_list.after('<input type="hidden" name="' + control_name + '[]" value="' + user_id + '" />');
    }
    
  };
  
}();

/**
 * Select projects widget behavior
 */
App.widgets.SelectProjects = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize widget
     *
     * @param String widget_id
     * @param String control_name
     * @param Boolean active_only
     * @param Boolean show_all
     * @param Array exclude_ids
     */
    init : function(widget_id, control_name, active_only, show_all, exclude_ids) {
      var widget = $('#' + widget_id);
      
      widget.find('a.projects_button').click(function() {
        // Prepare popup URL
        var popup_url = App.data.path_info_through_query_string ? 
          App.extendUrl(App.data.url_base, { 'path_info' : 'select-projects' }) : 
          App.data.url_base + '/select-projects';
          
        var popup_data = {
          'widget_id' : widget_id,
          'active_only' : active_only ? 1 : 0,
          'show_all' : show_all ? 1 : 0
        };
        
        var counter = 0;
        $('#' + widget_id + ' div.select_projects_widget_projects input[type=hidden]').each(function() {
          popup_data['selected_ids[' + counter +']'] = $(this).attr('value');
          counter++;
        });
        
        if(exclude_ids && exclude_ids.length > 0) {
          popup_data['exclude_ids'] = exclude_ids.join(',');
        } // if
        
        popup_url = App.extendUrl(popup_url, popup_data);
        
        var widget_popup = false;
        
        // Show and initialize popup
        App.ModalDialog.show('select_projects_popup', App.lang('Select Projects'), $('<p><img src="' + App.data.indicator_url + '" alt="" /> ' + App.lang('Loading...') + '</p>').load(popup_url, function() {
          widget_popup = $('#' + widget_id + '_popup');
        }), { 
          buttons : [
            {
              label: App.lang('Ok'),
              callback: function() {
                if(widget_popup) {
                  widget.find('div.select_users_widget_users').empty();
                  
                  var checkboxes = widget_popup.find('input:checked');
                  
                  if(checkboxes.length > 0) {
                    widget.find('div.select_projects_widget_projects').empty();
                    
                    checkboxes.each(function() {
                      var checkbox = $(this);
                      var row = checkbox.parent().parent();
                      
                      App.widgets.SelectProjects.add_project(widget_id, control_name, checkbox.attr('value'), row.find('td.name').text());
                    });
                  } else {
                    widget.find('div.select_projects_widget_projects').empty().append('<p class="details">' + App.lang('No projects selected') + '</p>');
                  } // if
                } // if
                App.ModalDialog.close();
              } // callback            
            }, {
              label: App.lang('Cancel'),
              callback: null
            }
          ]
        });
        
        return false;
      });
    },
    
    /**
     * Add project to the list
     *
     * @param String wrapper_id
     * @param String control_name
     * @param Integer project_id
     * @param String project_name
     */
    add_project : function(widget_id, control_name, project_id, project_name) {
      var widget = $('#' + widget_id);
      var projects_list = widget.find('div.select_projects_widget_projects ul.projects_list');
      
      if(projects_list.length == 0) {
        widget.find('div.select_projects_widget_projects').empty();
        projects_list = $('<ul class="projects_list"</ul>');
        widget.find('div.select_projects_widget_projects').append(projects_list);
      } // if
      
      var item_class = 'selected_project_' + project_id;
      if(projects_list.find('li.' + item_class).length == 0) {
        projects_list.append('<li class="' + item_class + '">' + App.clean(project_name) + '</li>');
        projects_list.after('<input type="hidden" name="' + control_name + '[]" value="' + project_id + '" />');
      } // if
    }
    
  };
  
}();

/**
 * Select project permissions widget behavior
 */
App.widgets.SelectProjectPermissions = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize select project permissions widget
     *
     * @param string wrapper_id
     */
    init : function(wrapper_id) {
      // removed obsolete code
      // saving this for future use
    }
    
  };
  
}();

/**
 * Select user project permissions widget behavior
 */
App.widgets.SelectUserProjectPermissions = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize select user project permissions widget
     *
     * @param string wrapper_id
     */
    init : function(wrapper_id) {
      var wrapper = $('#' + wrapper_id);
      wrapper.find('td.radio input').click(function() {
        if($(this).attr('value') == '0') {
          wrapper.find('td div.custom_permissions').show('fast');
        } else {
          wrapper.find('td div.custom_permissions').hide('fast');
        } // if
      });
    }
    
  };
  
}();

/**
 * Object visibility widget
 */
App.widgets.ObjectVisibility = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize object visibility link
     *
     * @param String link_id
     */
    init : function(link_id) {
      var link = $('#' + link_id);
      link.click(function() {
        var dialog_link = App.extendUrl(link.attr('href'), { async : 1 });
        App.ModalDialog.show('object_visibility', link.attr('title'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(dialog_link), {
          buttons : false
        });
        return false;
      });
    }
    
  };
  
}();

/**
 * Manage project group behavior
 */
App.system.ManageProjectGroups = function() {
  
  /**
   * Manage project groups tab used to initialize the popup
   *
   * This value is present only on pages where we have project groups tabs
   *
   * @var jQuery
   */
  var manage_project_groups_tab = false;
  
  /**
   * Initialize single project group table row
   *
   * @var jQuery
   */
  var init_row = function(row) {
    var table = row.parent().parent();
    
    // Rename project group
    row.find('td.options a.rename_project_group').click(function() {
      var link = $(this);
      
      // Block additional clicks
      if(link[0].block_clicks) {
        return false;
      } // if
      
      var row = link.parent().parent().addClass('renaming');
      var name_cell = row.find('td.name');
      var name_link = name_cell.find('a');
      
      // Remember start name and start URL
      var start_name = name_link.text();
      var start_url = name_link.attr('href');
      
      link[0].block_clicks = true;
      
      name_cell.empty();
      
      var input = $('<input type="text" />').val(start_name).appendTo(name_cell);
      var save_button = $('<button class="simple">' + App.lang('Save') + '</button>').appendTo(name_cell);
      
      input[0].focus();
      
      // Submission indicator
      var submitting_changes = false;
      
      /**
       * Do submit changes we made
       */
      var submit_changes = function() {
        if(submitting_changes) {
          return;
        } // if
        
        var new_project_group_name = jQuery.trim(input.val());
        if(new_project_group_name == '') {
          input[0].focus();
        } // if
        
        // Check if new project group name is already in use
        var name_used = false;
        table.find('td.name').each(function() {
          var current_row = $(this);
          if(current_row.attr('class').indexOf('renaming') == -1 && current_row.text() == new_project_group_name) {
            name_used = true;
            current_row.highlightFade();
          } // if
        });
        
        if(name_used) {
          return;
        } // if
        
        // And submit the request
        save_button.text(App.lang('Saving ...'));
        input.attr('disabled', 'disabled');
        submitting_changes = true;
        
        $.ajax({
          type : 'POST',
          url : App.extendUrl(link.attr('href'), { async : 1 }),
          data : {
            'submitted' : 'submitted',
            'project_group[name]' : new_project_group_name
          },
          success : function(response) {
            if(manage_project_groups_tab) {
              var project_group_id = row.attr('project_group_id');
              manage_project_groups_tab.parent().find('li').each(function() {
                if($(this).attr('project_group_id') == project_group_id) {
                  $(this).find('a span').text(response);
                } // if
              });
            } // if
            
            name_cell.empty().append($('<a></a>').attr('href', start_url).text(response));
            row.find('td').highlightFade();
            submitting_changes = false;
          },
          error : function() {
            name_cell.empty().append($('<a></a>').attr('href', start_url).text(start_name));
            submitting_changes = false;
            
            alert(App.lang('Failed to rename selected project group'));
          }
        });
        
        link[0].block_clicks = false;
      };
      
      /**
       * Cancel changes
       */
      var cancel_changes = function() {
        name_cell.empty().append($('<a></a>').attr('href', start_url).text(start_name));
        link[0].block_clicks = false;
      };
      
      // Input key handling
      input.keydown(function(e) {
        //e.stopPropagation(); // Don't close dialog!
      }).keypress(function(e) {
        switch(e.keyCode) {
          case 13:
            submit_changes();
            break;
          case 27:
            cancel_changes();
            break;
          default:
            return true;
        } // if
        
        e.stopPropagation();
        return false;
      });
      
      // Button click 
      save_button.click(function() {
        submit_changes();
      });
      
      return false;
    });
    
    // Delete project group
    row.find('td.options a.delete_project_group').click(function() {
      var link = $(this);
      
      // Block additional clicks
      if(link[0].block_clicks) {
        return false;
      } // if
      
      if(confirm(App.lang('Are you sure that you want to delete this project group? There is no undo for this operation!'))) {
        link[0].block_clicks = true;
        
        var row = link.parent().parent();
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : App.extendUrl(link.attr('href'), { async : 1 }),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
            if(manage_project_groups_tab) {
              var project_group_id = row.attr('project_group_id');
              manage_project_groups_tab.parent().find('li').each(function() {
                if($(this).attr('project_group_id') == project_group_id) {
                  $(this).remove();
                } // if
              });
            } // if
            
            row.remove();
            if(table.find('tr').length > 0) {
              reindex_even_odd_rows(table);
            } else {
              table.hide();
              $('#manage_project_groups_empty_list').show();
            } // if
          },
          error   : function() {
            img.attr('src', old_src);
          }
        });
      } // if
      
      return false;
    });
  };
  
  /**
   * Reindex table even odd rows
   *
   * @param jQuery wrapper
   */
  var reindex_even_odd_rows = function(table) {
    var counter = 1;
    table.find('tr').each(function() {
      var new_class = counter % 2 ? 'odd' : 'even';
      $(this).removeClass('odd').removeClass('even').addClass(new_class);
      counter++;
    });
  };
  
  // Public interface
  return {
    
    /**
     * Initialize manage project group popup
     *
     * @param String list_item_id
     */
    init : function(list_item_id) {
      manage_project_groups_tab = $('#' + list_item_id); // Remember manage project group tab!
      
      var link = manage_project_groups_tab.find('a');
      
      link.click(function() {
        var open_url = App.extendUrl(link.attr('href'), {
          skip_layout : 1,
          async : 1
        });
        
        App.ModalDialog.show('manage_project_groups_popup', App.lang('Manage Project Groups'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(open_url), {});
        return false;
      });
    },
    
    /**
     * Initialize project groups list behavior
     *
     * @param String wrapper_id
     */
    init_page : function(wrapper_id) {
      var wrapper = $('#' + wrapper_id);
      
      // New project group implementation
      var form = wrapper.find('form');
      var new_project_group_input = form.find('input');
      var new_project_group_icon = form.find('img');
      
      var default_text = App.lang('New Project Group...');
      new_project_group_input.focus(function() {
        if(new_project_group_input.val() == default_text) {
          new_project_group_input.val('');
        } // if
      }).blur(function() {
        if(new_project_group_input.val() == '') {
          new_project_group_input.val(default_text);
        } // if
      }).val(default_text);
      
      // Submitting form indicator
      var submitting_new_project_group = false;
      
      // Click on + image
      new_project_group_icon.click(function() {
        if(!submitting_new_project_group) {
          form.submit();
        } // if
      });
      
      // Create new project group...
      form.submit(function() {
        if(submitting_new_project_group) {
          return false;
        } // if
        
        var new_project_group_name = jQuery.trim(new_project_group_input.val());
        if(new_project_group_name == '') {
          new_project_group_input[0].focus();
        } // if
        
        // Check if new project group name is already in use
        var name_used = false;
        wrapper.find('td.name').each(function() {
          var current_row = $(this);
          if(current_row.text() == new_project_group_name) {
            name_used = true;
            current_row.highlightFade();
          } // if
        });
        
        if(name_used) {
          return false;
        } // if
        
        var old_icon_url = new_project_group_icon.attr('src');
        
        submitting_new_project_group = true;
        new_project_group_input.attr('disabled', 'disabled');
        new_project_group_icon.attr('src', App.data.indicator_url);
        
        $.ajax({
          type : 'POST',
          url : App.extendUrl(form.attr('action'), { async : 1}),
          data : {
            'submitted' : 'submitted',
            'project_group[name]' : new_project_group_name
          },
          success : function(response) {
            $('#manage_project_groups_empty_list').hide();
            
            var new_row = $(response);
            var table = wrapper.find('table');
            
            table.append(new_row).show();
            init_row(new_row);
            reindex_even_odd_rows(table);
            
            new_row.find('td').highlightFade();
            
            new_project_group_input.attr('disabled', '').val('')[0].focus();
            submitting_new_project_group = false;
            new_project_group_icon.attr('src', old_icon_url);
            
            // Add to list of project group tabs
            if(manage_project_groups_tab) {
              var new_tab = $('<li><a><span></span></a></li>');
              
              new_tab.attr('project_group_id', new_row.attr('project_group_id'));
              
              var new_project_group_link = new_row.find('td.name a');
              new_tab.find('a').attr('href', new_project_group_link.attr('href'));
              new_tab.find('span').text(new_project_group_link.text());
              
              manage_project_groups_tab.before(new_tab);
            } // if
          },
          error : function() {
            submitting_new_project_group = false;
            new_project_group_input.attr('disabled', '');
            new_project_group_icon.attr('src', old_icon_url);
            
            alert(App.lang('Failed to create new project group ":name"', { 'name' :  new_project_group_name}));
          }
        });
        
        return false;
      });
      
      wrapper.find('table tr').each(function() {
        init_row($(this));
      }); 
    }
    
  };
  
}();

/**
 * Quick add module
 */
App.system.QuickAdd = function() {
  
  /**
   * wrapper
   */
  var wrapper;
  
  /**
   * Wizzard step 1
   *
   * var jQuery
   */
  var step_1;
  
  /**
   * Wizzard step 2
   *
   * var jQuery
   */
  var step_2;
  
  /**
   * Variable that contains preloader string
   *
   * var String
   */
  var preloader_string;
  
  /**
   * Current object type
   *
   * var String
   */
  var current_object_type;
  
  /**
   * Current project id
   *
   * var integer
   */
  var current_project_id;
  
  /**
   * Tells if step 1 was already initialied
   *
   * var boolean
   */
  var step_1_initialized;

  
  // Public interface
  return {
    
    /**
     * initial initialize
     *
     * @param void
     * @return null
     */
    init : function () {
      wrapper = $('#quick_add');
      step_1 = wrapper.find('#quick_add_step_1');
      step_2 = wrapper.find('#quick_add_step_2');
      step_3 = wrapper.find('#quick_add_step_3');
      preloader_string = '<p class="quick_add_loading"><img src="' + App.data.big_indicator_url + '" alt="" /></p>';
      step_1_initialized = false;
      App.system.QuickAdd.init_step_1();
    },
    
    /**
     * Initialize Step 1 - project chooser
     *
     * @param boolean skip_initial
     * @return null
     */
    init_step_1 : function(skip_initial) {
      step_1.show();
      step_2.hide();
            
      if (App.ModalDialog.isOpen) {
        App.ModalDialog.setWidth(560);
        App.ModalDialog.setTitle(App.lang('Quick Add'));
      } // if
      
      if (!step_1_initialized) {
        if (App.ModalDialog.isOpen) {
          step_1.find('.wizzard_back').click(function () {
            App.ModalDialog.close();
            return false;
          });
        } else {
          step_1.find('.wizzard_back').hide();
        } // if
              
        step_1.find('.continue').click(function () {
          App.system.QuickAdd.init_step_2(
            project_chooser.find('input:checked').val(), // project id
            object_chooser.find('input:checked').val(), // object type
            object_chooser.find('input:checked').attr('quick_add_url'), // quick_add url
            project_chooser.find('input:checked').parent().text(), // project name
            object_chooser.find('input:checked').parent().text() // translated object type
          );
          return false;
        });
        
        var project_chooser = step_1.find('#project_id:first');
        var object_chooser = step_1.find('#object_chooser:first');
        
        project_chooser.find('label').hover(function () {
          $(this).addClass('hover');
        }, function () {
          $(this).removeClass('hover');
        });
               
        project_chooser.find('input').click(function () {
          var previous_object_type = object_chooser.find('input:checked:first');
          if (previous_object_type.length > 0) {
            var previous_object_type = previous_object_type.attr('value');
          } else {
            var cookie_previous_object_type = $.cookie('quick_add_object_type');
            if (cookie_previous_object_type) {
              previous_object_type = cookie_previous_object_type;
            } else {
              previous_object_type = previous_object_type;
            } // if
          } // if
          
          var radio_button = $(this);
          if(radio_button.attr('checked') == true) {
            project_chooser.find('label').removeClass('selected');
            radio_button.parent().addClass('selected');
          } // if
          
          var project_objects = App.data.quick_add_map[radio_button.val()]['permissions'];
          
          object_chooser.find('label').remove();
          for (var counter = 0; counter < project_objects.length; counter++) {
            var type_name =  project_objects[counter]['name'];
            var type_title =  project_objects[counter]['title'];
            
            var label = $('<label></label>').attr('for', 'type_' + type_name);
            var radio = $('<input type="radio" name="object_type" class="input_radio" />').attr({
              'name'          : 'object_type',
              'class'         : 'input_radio',
              'id'            : 'type_' + type_name,
              'value'         : type_name,
              'quick_add_url' : App.data.quick_add_urls[type_name]
            }).appendTo(label);
            
            label.append(ucfirst(type_title)).appendTo(object_chooser);
          } // for
          
          object_chooser.find('label').hover(function () {
            $(this).addClass('hover');
          }, function () {
            $(this).removeClass('hover');
          });
          
          object_chooser.find('input').click(function () {
            var radio_button = $(this);
            if (radio_button.attr('checked') == true) {
              object_chooser.find('label').removeClass('selected');
              radio_button.parent().addClass('selected');
            } // if       
          }).keydown(function(event) {
            if ((event.keyCode == 13) || (event.keyCode == 32)) {
              App.system.QuickAdd.init_step_2(
                project_chooser.find('input:checked').val(), // project id
                object_chooser.find('input:checked').val(), // object type
                object_chooser.find('input:checked').attr('quick_add_url'), // quick_add url
                project_chooser.find('input:checked').parent().text(), // project name
                object_chooser.find('input:checked').parent().text() // translated object type
              );
            } // if
            if (event.keyCode == 9) {
              step_1.find('.wizzard_continue').focus();
            } // if
          });
          
          if (previous_object_type) {
            previous_object_type = object_chooser.find('input[value='+previous_object_type+']:first');
            if (previous_object_type.length > 0) {
              previous_object_type.attr('checked', 'checked').click();
            } else {
              object_chooser.find('input:first').attr('checked', 'checked').click();
            } // if
          } else {
            object_chooser.find('input:first').attr('checked', 'checked').click();
          } // if
          
        }).keydown(function(event) {
          if ((event.keyCode == 13) || (event.keyCode == 32)) {
            object_chooser.find('input:checked').focus();
          } // if
        });
        
        if (!skip_initial) {
          var initial_project;
          if (App.data.active_project_id && (App.data.active_project_id > 0)) {
            initial_project = project_chooser.find('#quickadd_project_'+App.data.active_project_id);
          } else {
            initial_project = project_chooser.find('input:first');
          } // if
          initial_project.attr('checked', 'checked').focus().click();
        } // if
        step_1_initialized = true;
      } // if
    },
    
    /**
     * Initialize Step 2 - quick add form
     *
     * @param integer project_id
     * @param string object_type
     * @return null
     */
    init_step_2 : function (project_id, object_type, object_add_url, project_name, object_translated_type) {
      step_1.hide();
      step_2.show();
      
      current_project_id = project_id;
      current_object_type = object_type;
      
      if (!object_translated_type) {
        object_translated_type = object_type;
      } // if
      
      $.cookie('quick_add_object_type', object_type);
      
      object_add_url = object_add_url.replace(/\-PROJECT\-ID\-/, project_id);
           
      step_2.html(preloader_string);
      var preloader = step_2.find('p.quick_add_loading');
      
      $.ajax({
        url : object_add_url,
        success : function (response) {
          step_2.html(response);
          if (App.ModalDialog.isOpen) {
            App.ModalDialog.setTitle(App.lang('Quick Add :object_type in :project_name', {'object_type' : ucfirst(object_translated_type), 'project_name' : project_name}));
          } // if
          App.system.QuickAdd.init_object_form();
        },
        error : function (response) {
          App.system.QuickAdd.init_step_1(true);
        }
      });
    },
    
    init_object_form : function () {
      var object_form = step_2.find('form');
      object_form.find('input:first').focus();
      
      // flush behaviour
      step_2.find('.flash').click(function () {
        $(this).hide('fast');
      });
      
      // back button
      step_2.find('.wizzard_back').click(function () {
        App.system.QuickAdd.init_step_1(true);
        return false;
      });
      
      object_form.submit(function () {
        step_2.find('.flash').hide();
        step_2.prepend(preloader_string);
        var preloader = wrapper.find('.quick_add_loading');
        object_form.hide();
        
        object_form.ajaxSubmit({
          success : function (response) {
            step_2.html(response);
            App.system.QuickAdd.init_object_form();
          },
          error : function (response) {
            object_form.show();
            preloader.remove();
            alert(response.responseText);
          }
        });
        
        return false;
      });
    }
  };
  
}();

/**
 * String list behavior
 */
App.system.StringList = function() {
  
  /**
   * Init specific row
   *
   * @param jQuery row
   * @return void
   */
  var init_row = function(row) {
    var wrapper = row.parent().parent();
    
    row.find('td.remove a').click(function() {
      row.remove();
      reindex_row_data(wrapper);
    });
  };
  
  /**
   * Reindex row numbers
   *
   * @param jQuery wrapper
   * @return void
   */
  var reindex_row_data = function(wrapper) {
    var counter = 1;
    wrapper.find('tr.item').each(function() {
      var row = $(this);
      row.removeClass('even').removeClass('odd');
      if((counter % 2) > 0) {
        row.addClass('odd');
      } else {
        row.addClass('even');
      } // if
      row.find('td.num').text('#' + counter);
      
      counter++;
    });
  };
  
  /**
   * Create a new list item
   *
   * @param jQuery wrapper
   * @param string item_title
   * @param string input_name
   * @return void
   */
  var add_item_to_the_list = function(wrapper, item_title, input_name) {
    if(item_title == '') {
      return false;
    } else if(jQuery.trim(item_title).length < 3) {
      alert(App.lang('Project group name should be at least 3 characters long'));
      return false;
    } // if
    
    var exists = false;
    
    // Check if value already exists
    wrapper.find('tr.item').each(function() {
      var row = $(this);
      
      if(row.find('input[type=hidden]').val().toLowerCase() == item_title.toLowerCase()) {
        exists = true;
        row.find('td.value').highlightFade();
      }
    });
    
    // Add an item
    if(exists) {
      return false;
    } else {
      var row = $('<tr class="item">' +
        '<td class="num">#</td>' +
        '<td class="value"><span></span> <sup>' + App.lang('Unsaved') + '</sup> <input type="hidden" /></td>' +
        '<td class="remove"><a href="javascript: return false;"><img src="' + App.data.assets_url + '/images/gray-delete.gif" alt="" /></a></td>' +
      '</tr>');
      
      row.find('td.value span').text(item_title);
      row.find('input[type=hidden]').val(item_title).attr('name', input_name + '[]');
      
      wrapper.find('table').append(row);
      
      init_row(row);
      reindex_row_data(wrapper);
      
      row.find('td').highlightFade();
      
      return true;
    } // if
  };
  
  // Public interface
  return {
    
    /**
     * Initialize string list
     *
     * @param string wrapper_id
     * @return void
     */
    init : function(wrapper_id, name) {
      var wrapper = $('#' + wrapper_id);
      
      var add_item_input = wrapper.find('input.add_list_item_name');
      
      var default_add_item_input_text = add_item_input.val();
      
      var handle_submission = function() {
        add_item_to_the_list(wrapper, add_item_input.val(), name);
        add_item_input.val('');
        return false;
      };
      
      wrapper.find('input.add_list_item_button').click(function(e) {
        if(add_item_input.val() == default_add_item_input_text) {
          add_item_input[0].focus();
        } else {
          handle_submission();
        } // if
        e.preventDefault();
      });
      
      add_item_input.keypress(function(e) {
        if(e.which == 13) {
          handle_submission();
          e.preventDefault();
        } // if
      });
      
      // Focus / blur behavior
      add_item_input.focus(function() {
        if(add_item_input.val() == default_add_item_input_text) {
          add_item_input.val('');
        }
      }).blur(function() {
        if(add_item_input.val() == '') {
          add_item_input.val(default_add_item_input_text);
        }
      });
      
      // Init rows
      wrapper.find('tr.item').each(function() {
        init_row($(this));
      });
    }
    
  };
  
}();

/**
 * Dashboard sections behavior implementation
 */
App.widgets.IconPicker = function() {
  
  /**
   * icon_container
   *
   * @var jQuery
   */
  var icon_container;
  
  /**
   * icon_container
   *
   * @var jQuery
   */
  var picker_url;
  
  // Public interface
  return {
    
    /**
     * Initialize icon picker button
     *
     */
    init : function (icon_picker, icon_to_update, icon_title) {
      icon_container = $('#' + icon_to_update);
      picker_url = App.extendUrl(icon_container.attr('href'), {async : 1, skip_layout : 1});
            
      icon_container.click(function () {
        App.ModalDialog.show('icon_picker', icon_title, $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(picker_url, function () {
          App.widgets.IconPicker.upload_form(icon_picker, icon_to_update);
        }), {
          buttons : false
        });
        return false;
      });
    },
    
    /**
     *  initialize upload icon form
     *
     */
    upload_form : function (container_id, icon_to_update) {
      var upload_container = $('#'+container_id);
      var upload_container_form = upload_container.find('form');
      
      if (icon_to_update) {
        $('#'+icon_to_update+' img').attr('src', upload_container.find('#updated_icon img').attr('src'));
      } // if
      
      // submit upload form assync
      upload_container_form.submit(function () {
        upload_container.block();
        upload_container_form.ajaxSubmit({
          url : App.extendUrl(upload_container_form.attr('action'), {async : 1, skip_layout : 1}),
          type : 'post',
          success : function(response) {
            $('#'+icon_to_update+' img').attr('src', $(response).find('#updated_icon img').attr('src'));
            App.ModalDialog.close();
          },
          error : function (response) {
            upload_container.unblock();
            alert(response.statusText);
          }
        });
        return false;
      });
          
      // delete icon
      upload_container_form.find('.details a.delete_current:eq(0)').click(function () {
        var delete_url = App.extendUrl($(this).attr('href'), {async : 1, skip_layout : 1});
        upload_container.block();
        $.ajax({
          url: delete_url,
          type: 'post',
          data: 'submitted=submitted',
          success : function (response) {
            eval ('response = ' + response);
            if (typeof response == 'object') {
              $('#'+icon_to_update+' img').attr('src', response.icon);
              App.ModalDialog.close();
            } // if
          }
        });
        return false;
      });
    }
    
  };
}();

/**
 * Mark all new objects as read
 */
App.system.MarkAllAsRead = function() {
  
  // Public interface
  return {
    
    /**
     * Mark all new object as read
     *
     * @param String wrapper_id
     */
    init : function(wrapper_id) {
      var wrapper = $('#' + wrapper_id);
      
      wrapper.find('#mark_all_read_link').click(function () {
        var anchor = $(this);
        
        wrapper.hide();
        wrapper.before('<p class="dashboard_sections_loading" id="new_since_last_visit_preloader"><img src="' + App.data.big_indicator_url + '" alt="" /></p>');
        
        $.ajax({
          type: 'post',
          data: { 
            'submitted' : 'submitted' 
          },
          url: App.extendUrl(anchor.attr('href'), {
            async : 1
          }),
          success : function () {
            $('#dashboard_section_recent_activities a:first').click();
            $('#dashboard_section_new_updated').remove();
            wrapper.remove();
          },
          error : function () {
            $('#new_since_last_visit_preloader').remove();
            wrapper.show();
          }
        });
        return false;
      });
    }
  };
  
}();

/**
 * Send welcome message behavior
 */
App.system.SendWelcomeMessage = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize welcome message form
     *
     * @param String wrapper_id
     */
    init : function(wrapper_id) {
      var wrapper = $('#send_welcome_message');
      var form = wrapper.find('form');
      
      form.submit(function() {
        form.block('Sending...');
      
        $.ajax({
          url : App.extendUrl(form.attr('action'), { async : 1 }),
          type : 'post',
          data : {
            'submitted' : 'submitted',
            'welcome_message[message]' : form.find('textarea').val()
          },
          success : function(response) {
            form.unblock();
            wrapper.empty().append($('<p></p>').text(response));
          },
          error : function(response) {
            form.unblock();
            wrapper.empty().append($('<p></p>').text(App.lang('Failed to send welcome message. Please try again later')));
          }
        });
        
        return false;
      });
    }
    
  };
  
}();

/**
 * Role permission value behavior
 */
App.system.RolePermissionValue = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize role permission value behavior for a single checkbox
     *
     * @param String checkbox_id
     */
    init : function(checkbox_id) {
      var checkbox = $('#' + checkbox_id);
      var cell = checkbox.parent();
      
      checkbox.click(function() {
        checkbox.hide();
        cell.append('<img src="' + App.data.indicator_url + '" />');
        
        $.ajax({
          url  : App.extendUrl(checkbox.attr('set_permission_value_url'), { async : 1 }),
          type : 'POST',
          data : {
            submitted : 'submitted',
            value : this.checked ? 1 : 0
          },
          success : function() {
            cell.find('img').remove();
            checkbox.show();
            return true;
          },
          error : function() {
            cell.find('img').remove();
            checkbox.show();
            
            alert(App.lang('Failed to set value of this role'));
            
            return false;
          }
        });
      });
    }
    
  };
  
}();

/** File: modules/resources/javascript/main.js **/

App.resources = {
  controllers : {},
  models      : {}
};

/**
 * Assignments controller behavior
 */
App.resources.controllers.assignments = {
  
  /**
   * Assignments index page
   */
  index : function() {
    $(document).ready(function() {
      $('#assignments_filter_select select').change(function() {
        var filter_url = $(this).val();
        if(filter_url != location.href) {
          $(this).after(' ' + App.lang('Loading ...')).attr('disabled', 'disabled');
          location.href = filter_url;
        } // if
      });
      
      $('#assignments_filter_options a').hover(function() {
        $('#assignments_filter_options span.tooltip').text($(this).attr('title'));
      }, function() {
        $('#assignments_filter_options span.tooltip').text('');
      }); 
      
      $('#toggle_filter_details').click(function() {
        $('#assignments_filter_details').toggle('fast');
        return false;
      });
      
      // Complete / Move to trash tasks
      $('#assignments a.complete_assignment, #assignments a.remove_assignment').click(function() {
        var link = $(this);
        
        // Block additional clicks
        if(link[0].block_clicks) {
          return false;
        } else {
          link[0].block_clicks = true;
        } // if
        
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : link.attr('href'),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
            link.parent().parent().remove();
            
            var counter = 1;
            $('#assignments tr.assignment_row').each(function() {
              var new_class = counter % 2 == 1 ? 'odd' : 'even';
              $(this).removeClass('even').removeClass('odd').addClass(new_class);
              counter++;
            });
          },
          error   : function() {
            img.attr('src', old_src);
            link[0].block_clicks = false;
          }
        });
        
        return false;
      });
    });
  }
  
}

/**
 * Select assignees widget
 */
App.widgets.SelectAssignees = function() {
  
  /**
   * Update value of hidden owner_id field based on selected user
   *
   * @param string widget_id
   * @param string control_name
   * @return undefined
   */
  var update_responsible_user = function(widget_id, control_name) {
    var widget = $('#' + widget_id);
    var users_list = widget.find('div.select_assignees_widget_users ul.users_list');
    
    if(users_list.length == 0) {
      widget.find('input.responsible_assignee_id').remove();
    } else {
      var responsible_user = users_list.find('li.responsible');
      var responsible_user_id = 0;
      
      if(responsible_user.length == 0) {
        var responsible_user = users_list.find('li:first');
        responsible_user.addClass('responsible');
        responsible_user_id = responsible_user.attr('user_id');
      } else {
        var responsible_user_id = responsible_user.attr('user_id');
      } // if
      
      var hidden_field = widget.find('input.responsible_assignee_id');
      if(hidden_field.length > 0) {
        hidden_field.attr('value', responsible_user_id);
      } else {
        hidden_field = users_list.after('<input type="hidden" name="' + control_name + '[1]" value="' + responsible_user_id + '" class="responsible_assignee_id" />');
      } // if
    } // if
  };
  
  /**
   * Initialize behavior of user list item in an user list
   *
   * @param string widget_id
   * @param string control_name
   * @return undefined
   */
  var init_user_list_items = function(widget_id, control_name) {
    var users_list = $('#' + widget_id + ' div.select_assignees_widget_users ul.users_list');
    var list_items = users_list.find('li');
    
    list_items.hover(function() {
      $(this).attr('title', App.lang('Set as responsible')).addClass('hovered');
    }, function() {
      $(this).attr('title', '').removeClass('hovered');
    }).click(function() {
      list_items.removeClass('responsible');
      $(this).addClass('responsible');
      update_responsible_user(widget_id, control_name);
    });
  };
  
  // Public interface
  return {
    
    /**
     * Initialize select users widget
     *
     * @param string widget_id
     * @param string control_name
     * @param string company_id
     * @param string project_id
     * @param Array exclude_ids
     * @return void
     */
    init : function(widget_id, control_name, company_id, project_id, exclude_ids) {
      var widget = $('#' + widget_id);
      
      widget.find('.assignees_button').select_multiple_users({
        'widget_id'    : widget_id,
        'company_id'   : company_id,
        'project_id'   : project_id,
        'selected_ids' : function() {
          var selected_ids = [];
          $('#' + widget_id + ' div.select_assignees_widget_users input[type=hidden]').each(function() {
            selected_ids.push($(this).attr('value'));
          });
          return selected_ids;
        },
        'exclude_ids'  : exclude_ids,
        'on_ok'        : function(selected_users) {
          var responsible_user_id = widget.find('input.responsible_assignee_id').val();
          
          widget.find('div.select_assignees_widget_users').empty();
          
          if(selected_users.length > 0) {
            for(var i = 0; i < selected_users.length; i++) {
              App.widgets.SelectAssignees.add_user(widget_id, control_name, selected_users[i]['id'], selected_users[i]['name'], responsible_user_id == selected_users[i]['id']);
            } // for
            
            // Done adding users
            update_responsible_user(widget_id, control_name);
            init_user_list_items(widget_id, control_name);
          } else {
            widget.find('div.select_assignees_widget_users').append('<p class="details">' + App.lang('No users selected') + '</p>');
          } // if
        } // function
      });
      
      return false;
    },
    
    /**
     * Add new user to the list
     *
     * @param integer widget_id
     * @param string control_name
     * @param integer user_id
     * @param string display_name
     * @param boolean is_owner
     * @return void
     */
    add_user : function(widget_id, control_name, user_id, display_name, is_owner) {
      var widget = $('#' + widget_id);
      var users_list = widget.find('div.select_assignees_widget_users ul.users_list');
      
      if(users_list.length == 0) {
        widget.find('div.select_assignees_widget_users').empty();
        users_list = $('<ul class="users_list"</ul>');
        widget.find('div.select_assignees_widget_users').append(users_list);
      } // if
      
      var list_item_class = is_owner ? 'responsible' : 'not_responsible'; 
      
      users_list.append('<li class="' + list_item_class + '" user_id="' + user_id + '">' + App.clean(display_name) + '</li>');
      users_list.after('<input type="hidden" name="' + control_name + '[0][]" value="' + user_id + '" />');
    },
    
    /**
     * When we are done adding users we should call this method to initialize 
     * widget behaviro
     *
     * @param string widget_id
     * @param string control_name
     * @return undefined
     */
    done_adding_users : function(widget_id, control_name) {
      update_responsible_user(widget_id, control_name);
      init_user_list_items(widget_id, control_name);
    }
    
  };
  
}();

/**
 * Select assignees widget
 */
App.widgets.SelectAsigneesInlineWidget = function () {
  /**
   * Wrapper that containts this widget
   *
   * @var jQuery
   */
  var wrapper;
  
  /**
   * Hidden field that contains value of responsible person
   *
   * @var jQuery
   */
  var responsible_field;
  
  /**
   * Block that contains information about currently responsible person
   *
   * @var jQuery
   */
  var responsible_information_block;
  
  /**
   * Enable responsible person
   *
   * @var boolean
   */
  var enable_responsible;
  
  /**
   * Sets current checkbox to be responsible one
   * 
   * @param jQuery checkbox
   * @return null
   */
  var set_as_responsible = function (checkbox) {
    var responsible_span = checkbox.next();
    if (!checkbox.attr('checked')) {
      checkbox.attr('checked','checked');
      checkbox.change();
    } //if
    wrapper.find('span.responsible_setter.responsible').removeClass('responsible');
    responsible_span.addClass('responsible');
    responsible_field.val(checkbox.val());
    responsible_information_block.html(App.lang('<strong>:user</strong> is responsible', {
      'user' : responsible_span.html()
    }));
    responsible_information_block.find('strong').highlightFade();
  };
  
  /**
   * Sets current checkbox as not responsible
   * 
   * @param jQuery checkbox
   * @return null
   */
  var set_as_not_responsible = function (checkbox) {
    var responsible_span = checkbox.next();
    responsible_span.removeClass('responsible');
    
    var first_checked = wrapper.find('.company_user input:checked:first');
    if (first_checked.length < 1) {
      responsible_field.val('');
      responsible_information_block.html(App.lang('No one is responsible'));
    } else {
      set_as_responsible(first_checked);
    } // if
  };
  
  return {
    /**
     * Function that handles all widget behaviour
     *
     * @param string wrapper_id
     * @param boolean wrapper_id
     */
    init  : function (wrapper_obj, wrapper_id, choose_responsible, responsible_id) {
      wrapper = wrapper_obj;
      enable_responsible = choose_responsible;
      if (enable_responsible) {
        responsible_field = wrapper.find('#'+wrapper_id+'_responsible');
        responsible_information_block = wrapper.find('.select_asignees_inline_widget_responsible_block .placeholder');
      } // if
           
      // handle company checkboxes behaviour
      wrapper.find('.company_name input').click(function () {
        var company_checkbox = $(this);
        var company_group = company_checkbox.parents('.user_group:first');
        
        // set all user checkbox states to current company checkbox state
        company_group.find('.company_user input').attr('checked', company_checkbox.attr('checked'));
        
        if (enable_responsible) {
          if (!company_checkbox.attr('checked')) {
            // checks if there is responsible in group and if yes make it not responsible
            var group_responsible = company_group.find('.company_user input').next('.responsible');
            if (group_responsible.length > 0) {
              set_as_not_responsible(group_responsible.prev());
            } // if
          } else {
            // check if there is a responsible person and if not, it uses first in the group as responsible
            if (wrapper.find('.company_user input').next('.responsible').length == 0) {
              set_as_responsible(company_group.find('.company_user input:first'));
            } // if
          } // if
          
        } // if
        
        company_checkbox.blur();
      });
      
      // handle user checkboxes behaviour
      wrapper.find('.company_user input').change(function () {
        var company_user = $(this);
        var responsible_span = company_user.next();
        
        var company_checkbox = company_user.parents('.user_group:first').find('.company_name input:first');
        
        var total_group_checkboxes_count = company_user.parents('.user_group:first').find('.company_user input').length;
        var checked_group_checkboxes_count = company_user.parents('.user_group:first').find('.company_user input:checked').length;
        
        // if all checkboxes in group are checked, we need to check company checkbox, otherwise we need to uncheck it
        if (total_group_checkboxes_count == checked_group_checkboxes_count) {
          company_checkbox.attr('checked', 'checked');
        } else {
          company_checkbox.attr('checked', '');
        } // if
        
        if (enable_responsible) {
          // if uncheck responsible person it becomes not responsible
          if (!company_user.attr('checked') && responsible_span.is('.responsible')) {
            set_as_not_responsible(company_user);
          } // if
          
          // if you check assignee and, he is only assignee it automatically becomes responsible one
          if (company_user.attr('checked') && (wrapper.find('.company_user input:checked').length == 1)) {
            set_as_responsible(company_user);
          } // if
        } // if
        
        company_user.blur();
      });
      
      if (enable_responsible) {
        // if enable_responsible is true we need to setup responsible person chooser
        wrapper.find('.responsible_setter').hover(function () {
          $(this).css('text-decoration', 'underline');
        }, function () {
          $(this).css('text-decoration', 'none');
        }).click(function () {
          var this_span = $(this);
          var this_checkbox = this_span.prev();
          set_as_responsible(this_checkbox);
        });
      } else {
        // otherwise we need to simulate label clicking
        wrapper.find('.responsible_setter').click(function () {
          var this_span = $(this);
          var this_checkbox = this_span.prev();
          if (this_checkbox.attr('checked')==false) {
            this_checkbox.attr('checked','checked');
          } else {
            this_checkbox.attr('checked','');
          } // if
          this_checkbox.change();
        });
      } // if
      
      // initial setup
      wrapper.find('.user_group').each(function () {
        $(this).find('.company_user input:first').change();
      });
      
      if (enable_responsible && responsible_id) {
        var init_responsible = wrapper.find('#' + wrapper_id + '_user_' + responsible_id + ':first');
        if (init_responsible.length > 0) {
          set_as_responsible(init_responsible);
        } // if
      } // if
      //$_select_assignees_responsible
    }
  }
}();

/**
 * Send reminder behavior
 */
App.widgets.SendReminder = function() {
  
  /**
   * Public interface
   */
  return {
    
    /**
     * Initialize send reminder link if present
     */
    init : function() {
      $('li.send_reminder a').click(function() {
        var link = $(this);
        
        var reminder_url = App.extendUrl(link.attr('href'), { 
          skip_layout : 1 
        });
        
        App.ModalDialog.show(
          'send_reminder_users', // name
          App.lang('Remind'),  // caption
          $('<p><img src="' + App.data.indicator_url + '" alt="" /> ' + App.lang('Loading...') + '</p>').load(reminder_url, function() {
            var form = $('#send_reminder_users_form');
            form.submit(function() {
              form.attr('action', form.attr('action') + '&skip_layout=1');
              form.block(App.lang('Working...'));
              form.ajaxSubmit({
                success : function(response) {
                  form.after(response);
                  form.remove();
                }
              });
              return false;
            });
          }), // body
          {
            buttons : false,
            width: 500
          }
        );
        return false;
      });
    },
    
    /**
     * Initialize form behavior
     */
    init_form : function() {
      var form = $('#send_reminder_users_form');
            
      /**
       * Change details in who radio group
       */
      var change_who = function() {
        form.find('div.content_wrapper').hide();
        form.find('div.label_wrapper input:checked').each(function() {
          $(this).parent().parent().find('div.content_wrapper').show();
        });
      };
      
      form.find('div.label_wrapper input').click(change_who);
      change_who();
    }
    
  };
  
}();

/**
 * Add / Edit assignments filter form behavior
 */
App.resources.AssignmentFilterForm = function() {
  
  /**
   * Form instance
   *
   * @var jQuery
   */
  var form;
  
  // Public interface
  return {
    
    /**
     * Initialize assignment filter form
     *
     * @param string form_id
     * @param string partial_generator_url
     * @return void
     */
    init : function(form_id, partial_generator_url) {
      form = $('#' + form_id);
      
      form.find('select.filter_async_select').change(function() {
        var select = $(this);
        var row = select.parent().parent();
        var cell_additional = row.find('td.filter_select_additional');
        var option = select.find('option[value=' + select.val() + ']');
        
        if(option.attr('class') == 'filter_async_option') {
          cell_additional.each(function() {
            cell_additional.empty().append('<img src="' +  App.data.indicator_url + '" alt="" />');
            $.ajax({
              url     : partial_generator_url,
              type    : 'GET',
              data    : {
                'select_box'   : select.attr('name'),
                'option_value' : option.val()
              },
              success : function(response) {
                cell_additional.empty();
                cell_additional.append(response);
              },
              error   : function() {
                cell_additional.empty();
              }
            });
          })
        } else {
          cell_additional.empty();
        }
      })
    }
    
  };
  
}();

/**
 * Object assignments form behavior
 */
App.resources.ObjectAttachments = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize behavior
     *
     * @param string wrapper_id
     */
    init : function(wrapper_id) {
      var wrapper = $('#' + wrapper_id);
      
      /**
       * File details
       */
      wrapper.find('a.show_file_details').click(function() {
        var brief = wrapper.find('div.brief_files_view');
        var full = wrapper.find('div.full_files_view')
        
        if(brief.css('display') == 'none') {
          full.css('display', 'none');
          brief.css('display', 'block');
          
          $(this).text(App.lang('Show Details'));
        } else {
          brief.css('display', 'none');
          full.css('display', 'block');
          
          $(this).text(App.lang('Hide Details'));
        }
        
        return false;
      });
      
      /**
       * Reindex table rows
       */
      var reindex_odd_even_rows = function() {
        var counter = 1;
        wrapper.find('tr').each(function() {
          var row = $(this);
          row.removeClass('even').removeClass('odd');
          if(counter % 2 == 1) {
            row.addClass('odd');
          } else {
            row.addClass('even');
          } // if
          counter++;
        });
      };
      
      /**
       * Prepare details row
       */
      var prepare_details_row = function(row) {
        row.find('td.options a').click(function() {
          var link = $(this);
          
          if (!confirm(App.lang('Are you sure that you want to permanently remove this attachment? There is no Undo!'))) {
            return false;
          } // if
          
          // Block additional clicks
          if(link[0].block_clicks) {
            return false;
          } else {
            link[0].block_clicks = true;
          } // if
          
          var img = link.find('img');
          var old_src = img.attr('src');
          
          img.attr('src', App.data.indicator_url);
          
          $.ajax({
            url     : App.extendUrl(link.attr('href'), {async: 1}),
            type    : 'POST',
            data    : {'submitted' : 'submitted'},
            success : function() {
              var row = link.parent().parent();
              wrapper.find('li.attachment_' + row.attr('attachment_id')).remove(); // remove from brief view
              row.remove(); // remove from detail
              
              reindex_odd_even_rows();
              if(wrapper.find('table tr').length < 1) {
                wrapper.find('div.body').append('<p class="details center files_moved_to_trash">' + App.lang('All files moved to Trash') + '</p>');
              } // if
            },
            error   : function() {
              img.attr('src', old_src);
            }
          });
          
          return false;
        });
      };
      
      // Initialize rows
      wrapper.find('div.full_files_view table tr').each(function() {
        prepare_details_row($(this));
      });
      
      // Prepare form behavior
      var form_wrapper = wrapper.find('div.attach_another_file');
      var form = form_wrapper.find('form');
      
      form.submit(function() {
        var initial_action = form.attr('action');
        
        // Alter form action
        form.attr('action', App.extendUrl(initial_action, { async : 1 }));
        
        var list = wrapper.find('div.brief_files_view ul');
        var details = wrapper.find('div.full_files_view table tbody');
        
        if(UniForm.is_valid(form)) {
          form_wrapper.block(App.lang('Working...'));
          form.ajaxSubmit({
            success : function(response) {
              // Lets get rid of the notification if we already removed all 
              // attachments
              wrapper.find('p.files_moved_to_trash').remove();
              
              // jQuery acts a bit weird here. Insted of providing response as 
              // a string it tries to append it to the BODY so some markup 
              // (tr, td) gets discarded. That is why we need to use temp 
              // table in order to get properly marked-up row
              var tmp_table = $(response);
              var row = tmp_table.find('tr');
              
              details.append(row);
              tmp_table.remove();
              
              var row_class = details.find('tr').length % 2  == 1 ? 'odd' : 'even';
              
              row.addClass(row_class);
              prepare_details_row(row);
              row.find('td').highlightFade({
                complete : function() {
                  $(this).attr('style', '');
                }
              });
              
              // Now, lets create brief list entry (extract data from row)
              var brief = $('<li class="attachment_' + row.attr('attachment_id') + '"></li>');
              
              row.find('a.filename').clone().appendTo(brief);
              brief.append(' <span class="details">(' + row.find('span.filesize').text() + ')</span>');
              list.append(brief);
              brief.highlightFade();
              
              // Unblock and reset
              form_wrapper.unblock();
              form[0].reset();
            },
            error : function() {
              form_wrapper.unblock();
              form[0].reset();
            }
          });
        } // if
        
        // Revert back to initial action
        form.attr('action', initial_action);
        return false;
      });
      
      /**
       * Attach another file
       */
      wrapper.find('a.attach_another_file').click(function() {
        var link = $(this);
        
        // Toggle section options
        if(form_wrapper.css('display') == 'block') {
          form_wrapper.css('display', 'none');
          link.text(App.lang('Attach Another File'));
        } else {
          form_wrapper.css('display', 'block');
          link.text(App.lang('Done Adding Files'));
        } // if
        
        return false;
      });
    }
  };
}();

/**
 * Attach files widget behavior
 */
App.resources.AttachFiles = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize widget behavior
     *
     * @param String wrapper_id
     */
    init : function(wrapper_id) {
      var wrapper = $('#' + wrapper_id);
      var name_counter = 1;
      
      var inputs_wrapper = $('<div class="attach_files_inputs"></div>').prependTo(wrapper);
      var max_files = parseInt(wrapper.attr('max_files'));
      
      if(max_files > 1) {
        var attach_another_wrapper = $('<p class="attach_files_add_another"></p>');
        inputs_wrapper.after(attach_another_wrapper);
        $('<div class="clear"></div>').insertAfter(attach_another_wrapper);
        
        var attach_another = $('<a href="#" class="button_add">' + App.lang('Attach Another File') + '</a>').appendTo(attach_another_wrapper).click(function() {
          add_input();
          show_hide_attach_another();
          return false;
        });
      } // if
      
      /**
       * Add single file input to the list of inputs
       */
      var add_input = function() {
        var input_wrapper = $('<div class="attach_files_input"></div>');
        var input = $('<input type="file" name="attach_from_files_file_' + name_counter +'" />').appendTo(input_wrapper);
        name_counter++;
        if(max_files > 1) {
          var remove_link = $('<a href="#"><img src="' + App.data.assets_url + '/images/dismiss.gif" /></a>').appendTo(input_wrapper).click(function() {
            if(inputs_wrapper.find('div.attach_files_input').length > 1) {
              input_wrapper.remove();
              show_hide_attach_another();
            } // if
            return false;
          });
        } // if
        
        inputs_wrapper.append(input_wrapper); // and add...
      };
      
      var show_hide_attach_another = function() {
        if(inputs_wrapper.find('div.attach_files_input').length >= max_files) {
          attach_another_wrapper.hide();
        } else {
          attach_another_wrapper.show();
        } // if
      };
      
      add_input(); // add input
    }
    
  };
  
}();

/**
 * Manage categories behavior
 */
App.resources.ManageCategories = function() {
  
  /**
   * Manage categories tab used to initialize the popup
   *
   * This value is present only on pages where we have categories tabs
   *
   * @var jQuery
   */
  var manage_categories_tab = false;
  
  /**
   * Initialize single categories table row
   *
   * @var jQuery
   */
  var init_row = function(row) {
    var table = row.parent().parent();
    
    // Rename category
    row.find('td.options a.rename_category').click(function() {
      var link = $(this);
      
      // Block additional clicks
      if(link[0].block_clicks) {
        return false;
      } // if
      
      var row = link.parent().parent().addClass('renaming');
      var name_cell = row.find('td.name');
      var name_link = name_cell.find('a');
      
      // Remember start name and start URL
      var start_name = name_link.text();
      var start_url = name_link.attr('href');
      
      link[0].block_clicks = true;
      
      name_cell.empty();
      
      var input = $('<input type="text" />').val(start_name).appendTo(name_cell);
      var save_button = $('<button class="simple">' + App.lang('Save') + '</button>').appendTo(name_cell);
      
      input[0].focus();
      
      // Submission indicator
      var submitting_changes = false;
      
      /**
       * Do submit changes we made
       */
      var submit_changes = function() {
        if(submitting_changes) {
          return;
        } // if
        
        var new_category_name = jQuery.trim(input.val());
        if(new_category_name == '') {
          input[0].focus();
        } // if
        
        // Check if new category name is already in use
        var name_used = false;
        table.find('td.name').each(function() {
          var current_row = $(this);
          if(current_row.attr('class').indexOf('renaming') == -1 && current_row.text() == new_category_name) {
            name_used = true;
            current_row.highlightFade();
          } // if
        });
        
        if(name_used) {
          return;
        } // if
        
        // And submit the request
        save_button.text(App.lang('Saving ...'));
        input.attr('disabled', 'disabled');
        submitting_changes = true;
        
        $.ajax({
          type : 'POST',
          url : App.extendUrl(link.attr('href'), { async : 1 }),
          data : {
            'submitted' : 'submitted',
            'category[name]' : new_category_name
          },
          success : function(response) {
            if(manage_categories_tab) {
              var category_id = row.attr('category_id');
              manage_categories_tab.parent().find('li').each(function() {
                if($(this).attr('category_id') == category_id) {
                  $(this).find('a span').text(response);
                } // if
              });
            } // if
            
            name_cell.empty().append($('<a></a>').attr('href', start_url).text(response));
            row.find('td').highlightFade();
            submitting_changes = false;
          },
          error : function() {
            name_cell.empty().append($('<a></a>').attr('href', start_url).text(start_name));
            submitting_changes = false;
            
            alert(App.lang('Failed to rename selected category'));
          }
        });
        
        link[0].block_clicks = false;
      };
      
      /**
       * Cancel changes
       */
      var cancel_changes = function() {
        name_cell.empty().append($('<a></a>').attr('href', start_url).text(start_name));
        link[0].block_clicks = false;
      };
      
      // Input key handling
      input.keydown(function(e) {
        //e.stopPropagation(); // Don't close dialog!
      }).keypress(function(e) {
        switch(e.keyCode) {
          case 13:
            submit_changes();
            break;
          case 27:
            cancel_changes();
            break;
          default:
            return true;
        } // if
        
        e.stopPropagation();
        return false;
      });
      
      // Button click 
      save_button.click(function() {
        submit_changes();
      });
      
      return false;
    });
    
    // Delete category implementation
    row.find('td.options a.move_category_to_trash').click(function() {
      var link = $(this);
      
      // Block additional clicks
      if(link[0].block_clicks) {
        return false;
      } // if
      
      if(confirm(App.lang('Are you sure that you want to delete this category? Objects that are currently within it will be marked as uncategorized, but will not be deleted. There is no Undo!'))) {
        link[0].block_clicks = true;
        
        var row = link.parent().parent();
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : App.extendUrl(link.attr('href'), { async : 1 }),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
            if(manage_categories_tab) {
              var category_id = row.attr('category_id');
              manage_categories_tab.parent().find('li').each(function() {
                if($(this).attr('category_id') == category_id) {
                  $(this).remove();
                } // if
              });
            } // if
            
            row.remove();
            if(table.find('tr').length > 0) {
              reindex_even_odd_rows(table);
            } else {
              table.hide();
              $('#manage_categories_empty_list').show();
            } // if
          },
          error   : function() {
            img.attr('src', old_src);
          }
        });
      } // if
      
      return false;
    });
  };
  
  /**
   * Reindex table even odd rows
   *
   * @param jQuery wrapper
   */
  var reindex_even_odd_rows = function(table) {
    var counter = 1;
    table.find('tr').each(function() {
      var new_class = counter % 2 ? 'odd' : 'even';
      $(this).removeClass('odd').removeClass('even').addClass(new_class);
      counter++;
    });
  }
  
  // Public interface
  return {
    
    /**
     * Initialize manage categories popup
     *
     * @param String list_item_id
     */
    init : function(list_item_id) {
      manage_categories_tab = $('#' + list_item_id); // Remember manage categories tab!
      
      var link = manage_categories_tab.find('a');
      
      link.click(function() {
        var open_url = App.extendUrl(link.attr('href'), {
          skip_layout : 1,
          async : 1
        });
        
        App.ModalDialog.show('manage_categories_popup', App.lang('Manage Categories'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(open_url), {});
        return false;
      });
    },
    
    /**
     * Initialize categories list behavior
     *
     * @param String wrapper_id
     */
    init_page : function(wrapper_id) {
      var wrapper = $('#' + wrapper_id);
      
      // New category implementation
      var form = wrapper.find('form');
      var new_category_input = form.find('input');
      var new_category_icon = form.find('img');
      
      var default_text = App.lang('New Category...');
      new_category_input.focus(function() {
        if(new_category_input.val() == default_text) {
          new_category_input.val('');
        } // if
      }).blur(function() {
        if(new_category_input.val() == '') {
          new_category_input.val(default_text);
        } // if
      }).val(default_text);
      
      // Submitting form indicator
      var submitting_new_category = false;
      
      // Click on + image
      new_category_icon.click(function() {
        if(!submitting_new_category) {
          form.submit();
        } // if
      });
      
      // Create new category...
      form.submit(function() {
        if(submitting_new_category) {
          return false;
        } // if
        
        var new_category_name = jQuery.trim(new_category_input.val());
        if(new_category_name == '') {
          new_category_input[0].focus();
        } // if
        
        // Check if new category name is already in use
        var name_used = false;
        wrapper.find('td.name').each(function() {
          var current_row = $(this);
          if(current_row.text() == new_category_name) {
            name_used = true;
            current_row.highlightFade();
          } // if
        });
        
        if(name_used) {
          return false;
        } // if
        
        var old_icon_url = new_category_icon.attr('src');
        
        submitting_new_category = true;
        new_category_input.attr('disabled', 'disabled');
        new_category_icon.attr('src', App.data.indicator_url);
        
        $.ajax({
          type : 'POST',
          url : App.extendUrl(form.attr('action'), { async : 1}),
          data : {
            'submitted' : 'submitted',
            'category[name]' : new_category_name
          },
          success : function(response) {
            $('#manage_categories_empty_list').hide();
            
            var new_row = $(response);
            var table = wrapper.find('table');
            
            table.append(new_row).show();
            init_row(new_row);
            reindex_even_odd_rows(table);
            
            new_row.find('td').highlightFade();
            
            new_category_input.attr('disabled', '').val('')[0].focus();
            submitting_new_category = false;
            new_category_icon.attr('src', old_icon_url);
            
            // Add to list of category tabs
            if(manage_categories_tab) {
              var new_tab = $('<li><a><span></span></a></li>');
              
              new_tab.attr('category_id', new_row.attr('category_id'));
              
              var new_category_link = new_row.find('td.name a');
              new_tab.find('a').attr('href', new_category_link.attr('href'));
              new_tab.find('span').text(new_category_link.text());
              
              manage_categories_tab.before(new_tab);
            } // if
          },
          error : function() {
            submitting_new_category = false;
            new_category_input.attr('disabled', '');
            new_category_icon.attr('src', old_icon_url);
            
            alert(App.lang('Failed to create new category ":name"', { 'name' :  new_category_name}));
          }
        });
        
        return false;
      });
      
      wrapper.find('table tr').each(function() {
        init_row($(this));
      }); 
    }
    
  };
  
}();

/**
 * Manage subscriptions popup and section behavior
 */
App.resources.ManageSubscriptions = function() {
  
  /**
   * Wrapper block
   *
   * @var jQuery
   */
  var wrapper;
  
  // Public interface
  return {
    
    /**
     * Initialize block behavior
     *
     * @param String wrapper_id
     * @param String object_type
     */
    init : function(wrapper_id, object_type) {
      wrapper = $('#' + wrapper_id);
      
      $('#manage_subscriptions_page_action a, #' + wrapper_id+ ' a.open_manage_subscriptions').click(function() {
        if(wrapper.css('display') != 'block') {
          wrapper.show();
        } // if
        
        var popup_url = wrapper.attr('popup_url');
        
        App.ModalDialog.show('manage_object_subscriptions_popup', App.lang('Manage Subscriptions'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(popup_url, function() {
          $('#object_subscriptions table td.subscription input[type=checkbox]').click(function() {
            var checkbox = $(this);
            var cell = checkbox.parent();
            
            checkbox.hide();
            cell.append('<img src="' + App.data.indicator_url + '" alt="" />');
            
            if(this.checked) {
              var url = checkbox.attr('subscribe_url');
            } else {
              var url = checkbox.attr('unsubscribe_url');
            } // if
            
            $.ajax({
              url  : App.extendUrl(url, { async : 1 }),
              type : 'POST',
              data : {
                submitted : 'submitted'
              },
              success : function() {
                cell.find('img').remove();
                checkbox.show();
                
                // Lets update list of users
                var subscribed_users = [];
                $('#object_subscriptions table td.subscription input:checked').each(function() {
                  subscribed_users.push($(this).parent().parent().find('td.name a').clone());
                });
                
                var subscribed_users_list_wrapper = wrapper.find('div.object_subscriptions_list_wrapper').empty();
                var subscribed_users_length = subscribed_users.length;
                
                if(subscribed_users_length == 0) {
                  subscribed_users_list_wrapper.append(App.lang('There are no users subscribed to this :type', { type : object_type }));
                } else if(subscribed_users_length == 1) {
                  subscribed_users_list_wrapper.append(subscribed_users[0]).append(' ' + App.lang('is subscribed to this :type', { type : object_type }));
                } else {
                  if (subscribed_users_length <= App.data.max_subscribers_count) {
                    for(var i = 0; i < subscribed_users_length; i++) {
                      subscribed_users_list_wrapper.append(subscribed_users[i]);
                      
                      if(i < (subscribed_users_length - 2)) {
                        subscribed_users_list_wrapper.append(', ');
                      } else if(i == (subscribed_users_length - 2)) {
                        subscribed_users_list_wrapper.append(App.lang(' and '));
                      } // if
                    } // for
                    
                    subscribed_users_list_wrapper.append(' ' + App.lang('are subscribed to this :type', { type : object_type }));
                  } else {
                    subscribed_users_list_wrapper.append(' ' + App.lang(':subscribers_count people subscribed to this :type', { subscribers_count: subscribed_users_length,  type : object_type }));
                  } // if
                } // if
              },
              error : function() {
                cell.find('img').remove();
                checkbox[0].checked = !checkbox[0].checked;
                checkbox.show();
              }
            });
          });
        }), {
          height: 400,
          buttons : [{
            label : App.lang('Close')
          }]          
        });
        
        return false;
      });
    }
    
  };
  
}();

/**
 * Insert image editor widget
 */
App.widgets.EditorImagePicker = function() {
  /**
   * Editor instance
   */
  var editor_instance = null;
  
  /**
   * element in which editor is contained
   */
  var editor_container = null;
  
  /**
   * variable name for hidden fields
   */
  var hidden_input_variable_name = null;
  
  /**
   * disable image upload
   */
  var disable_image_upload = false;
  
  /**
   * Dialog container
   */
  var dialog_container;
  
  /**
   * cursor position
   */
  var cursor_position = null;
  
  // public interface
  return {
    /**
     * Display dialog
     */
    show : function (editor_instance_object, variable_name) {
      editor_instance = editor_instance_object;
      editor_container = $(editor_instance_object.contentAreaContainer).parents('table:first').parent().parent();
      editor_instance.focus();
      cursor_position = editor_instance.selection.getBookmark();
      
      hidden_input_variable_name = variable_name;
      
      var picker_url;
      if (App.widgets.EditorImagePicker.disable_image_upload) {
        picker_url = App.extendUrl(App.data.image_picker_url, {async:1, skip_layout:1, disable_upload : true});
      } else {
        picker_url = App.extendUrl(App.data.image_picker_url, {async:1, skip_layout:1});
      } // if
      
      App.ModalDialog.show('image_picker_dialog', App.lang('Choose or Upload Image'), $('<p><img src="' + App.data.indicator_url + '" alt="" /> ' + App.lang('Loading...') + '</p>').load(picker_url), {
        width: 500
      });
    },
    
    /**
     * Initialize dialog
     */
    init : function (container_id) {      
      dialog_container = $(container_id +':first');
      
      dialog_container.find('.top_tabs a').click(function () {
        var anchor = $(this);
        anchor.parent().parent().find('li').removeClass('selected');
        anchor.parent().addClass('selected');
        dialog_container.find('.top_tabs_object_list>div').hide();
        dialog_container.find('.top_tabs_object_list #container_'+anchor.attr('id')).show();
        return false;
      });
      dialog_container.find('.top_tabs a:first').click();
      
      
      // upload image behaviour
      $('#upload_image_form').resetForm();
      $('#upload_image_form').submit(function () {
                      
        $('#upload_image_form').ajaxSubmit({
          url               : App.data.image_picker_url,
          type              : 'post',
          success           : function (response) {
            var jquery_response = $(response);
            if (jquery_response.is('img')) {
              App.widgets.EditorImagePicker.update_editor(jquery_response.attr('src'), jquery_response.attr('attachment_id'));
            } else {
              alert(response);
            } // if
          },
          error : function (response) {
            alert(response.statusText);
          }
        });
        return false;
      });
      
      $('#link_image_form').submit(function () {
        var image_url = $('#link_image_form').find('input[type=text]').val();
        if (image_url) {
          App.widgets.EditorImagePicker.update_editor(image_url);
        } // if
        return false;
      });
    },
    
    update_editor : function (image_url, attachment_id) {
      if (editor_instance) {
      editor_instance.focus();
      editor_instance.selection.moveToBookmark(cursor_position);
      
        editor_instance.execCommand('mceInsertContent', false, "<img src='"+image_url+"' />");
        if (attachment_id) {
          if (editor_container.find('input[name='+hidden_input_variable_name+'][value='+attachment_id+']').length == 0) {
            editor_container.prepend('<input type="hidden" name="'+hidden_input_variable_name+'" value="'+attachment_id+'" />');
          } // if
        } // if
        App.ModalDialog.close();
      } // if
    }
  }
}();

/**
 * Select assignees widget
 */
App.widgets.EditorLinkPicker = function() {
  /**
   * Editor instance
   */
  var editor_instance = null;
  
  /**
   * element in which editor is contained
   */
  var editor_container = null;
  
  /**
   * cursor position
   */
  var cursor_position = null;
  
  /**
   * Dialog container
   */
  var dialog_container;
  
  // public interface
  return {
    /**
     * Display dialog
     */
    show : function (editor_instance_object) {
      editor_instance = editor_instance_object;
      editor_container = $(editor_instance_object.contentAreaContainer).parents('table:first').parent().parent();
      editor_instance.focus();
      cursor_position = editor_instance.selection.getBookmark();
      
      var initial_text = editor_instance.selection.getContent();

      var dialog_body = 
      '<div id="editor_link_container">'+
        '<form method="GET" action="#" class="uniForm showErrors">'+
        '<div class="blockLabels">'+
          '<div class="ctrlHolder">'+
            '<label for="url">'+App.lang('Link URL')+'<em>*</em></label>'+
            '<input type="text" class="title required" id="url" name="link_url" value="http://" />'+
          '</div>';
      if (!initial_text || initial_text.length < 1) {
        dialog_body = dialog_body +
          '<div class="ctrlHolder">'+
            '<label for="link_text">'+App.lang('Link Text')+'</label>'+
            '<input type="text" class="title required" id="link_text" name="link_text" value="'+initial_text+'"/>'+
          '</div>';
      } // if
        dialog_body = dialog_body +
          '<div class="buttonHolder">'+
            '<button accesskey="s" type="submit"><span><span>'+App.lang('Insert link')+'</span></span></button>'+
          '</div>'+
        '</div>'+
        '</form>'+
      '</div>';
      
      App.ModalDialog.show('editor_link_picker', App.lang('Insert Link'), dialog_body, {
        width: 500
      });
      
      $('#editor_link_container').find('form input[name=link_url]:first').focus();
      
      $('#editor_link_container').find('.buttonHolder button:first').click(function () {
        var link_url = $('#editor_link_container').find('form input[name=link_url]:first').val();
        if (!initial_text) {
          var link_text = $('#editor_link_container').find('form input[name=link_text]:first').val();
        } else {
          link_text = initial_text;
        } // if
        if (link_url) {
          App.widgets.EditorLinkPicker.insert(link_text, link_url);
        } // if
        return false;
      });
    },
    /**
     * insert link into body
     */
    insert : function (link_text, link_url) {
      if (!link_text) {
        link_text = link_url;
      } // if
      editor_instance.focus();
      editor_instance.selection.moveToBookmark(cursor_position);
      editor_instance.execCommand('mceInsertContent', false, '<a href="'+link_url+'">'+link_text+'</a>');  
      App.ModalDialog.close();
    }
  }
}();

App.widgets.EditorCleanTextDialog = function () {
  /**
   * Editor instance
   */
  var editor_instance = null;
  
  /**
   * Cursor position
   */
  var cursor_position = null;
  
  /**
   * Clean word HTML
   */
  var cleanWordHtml = function (content) { 
		if (!content || content.length < 1) {
		  return '';
		} // if
		
		var bull = String.fromCharCode(8226);
		var middot = String.fromCharCode(183);     
		
		var rl = '\u2122,<sup>TM</sup>,\u2026,...,\x93|\x94|\u201c|\u201d,",\x60|\x91|\x92|\u2018|\u2019,\',\u2013|\u2014|\u2015|\u2212,-'.split(',');
		for (var i=0; i < rl.length; i+=2)
			content = content.replace(new RegExp(rl[i], 'gi'), rl[i+1]);

    // convert headers to strong
		content = content.replace(new RegExp('<p class=MsoHeading.*?>(.*?)<\/p>', 'gi'), '<p><b>$1</b></p>');
		content = content.replace(new RegExp('tab-stops: list [0-9]+.0pt">', 'gi'), '">' + "--list--");
		content = content.replace(new RegExp(bull + "(.*?)<BR>", "gi"), "<p>" + middot + "$1</p>");
		content = content.replace(new RegExp('<SPAN style="mso-list: Ignore">', 'gi'), "<span>" + bull); // Covert to bull list
		content = content.replace(/<o:p><\/o:p>/gi, "");
		content = content.replace(new RegExp('<br style="page-break-before: always;.*>', 'gi'), '-- page break --'); // Replace pagebreaks
		content = content.replace(/<!--([\s\S]*?)-->|<style>[\s\S]*?<\/style>/g, "");  // Word comments
		content = content.replace(/<(meta|link)[^>]+>/g, ""); // Header elements

		// remove spans
		content = content.replace(/<\/?span[^>]*>/gi, "");
    // remove styles
		content = content.replace(new RegExp('<(\\w[^>]*) style=\'(.*?)\'([^>]*)', 'gi'), "<$1$3");
		content = content.replace(new RegExp('<(\\w[^>]*) style="(.*?)"([^>]*)', 'gi'), "<$1$3");
    // remove fonts
		content = content.replace(/<\/?font[^>]*>/gi, "");
    // remove class atributes
    content = content.replace(/<(\w[^>]*) class="(.*?)"([^>]*)/gi, "<$1$3");
    content = content.replace(/<(\w[^>]*) class=([^ |>]*)([^>]*)/gi, "<$1$3");

		content = content.replace(/<(\w[^>]*) lang=([^ |>]*)([^>]*)/gi, "<$1$3");
		content = content.replace(/<\\?\?xml[^>]*>/gi, "");
		content = content.replace(/<\/?\w+:[^>]*>/gi, "");
		content = content.replace(/-- page break --\s*<p>&nbsp;<\/p>/gi, ""); // Remove pagebreaks
		content = content.replace(/-- page break --/gi, ""); // Remove pagebreaks
		content = content.replace(/--list--/gi, ""); // Remove --list--
		
		// remove empty paragraphs
    content = content.replace(/<p>&nbsp;<\/p>/gi, '');
    content = content.replace(/<p><\/p>/gi, '');
    // remove empty lines
    content = content.replace(/\/?&nbsp;*/gi, "");
    // remove div's
		content = content.replace(/<\/?div[^>]*>/gi, "");

		// Convert all middlot lists to UL lists
		// var div = ed.dom.create("div", null, content);
		// var className = this.editor.getParam("paste_unindented_list_class", "unIndentedList");
		// while (this._convertMiddots(div, "--list--")) ; // bull
		// while (this._convertMiddots(div, middot, className)) ; // Middot
		// while (this._convertMiddots(div, bull)) ; // bull
		// content = div.innerHTML;

    // Replace all headers with strong and fix some other issues
		//content = content.replace(/<h[1-6]>&nbsp;<\/h[1-6]>/gi, '<p>&nbsp;&nbsp;</p>');
		//content = content.replace(/<h[1-6]>/gi, '<p><b>');
		//content = content.replace(/<\/h[1-6]>/gi, '</b></p>');
		//content = content.replace(/<b>&nbsp;<\/b>/gi, '<b>&nbsp;&nbsp;</b>');
		//content = content.replace(/^(&nbsp;)*/gi, '');
    return content;
	};
  
  return {
    show : function (editor_instance_object) {
      editor_instance = editor_instance_object;
      editor_instance.focus();
      cursor_position = editor_instance.selection.getBookmark();
      
      var dialog_body = 
      '<div id="editor_clean_text_dialog_container">' +
        '<form method="post" action="#" class="uniForm">' +
          '<div class="blockLabels">' +
            '<div class="ctrlHolder">'+
              '<label for="pasted_text">'+App.lang('Use CTRL+V on your keyboard to paste the text into the window')+'</label>'+
              '<textarea id="pasted_text" name="pasted_text"></textarea>'+
            '</div>' +
            '<div class="buttonHolder">'+
              '<button accesskey="s" type="submit"><span><span>'+App.lang('Insert Cleaned Text')+'</span></span></button>'+
            '</div>'+
          '</div>' +
        '</form>' +
      '</div>';
      
      App.ModalDialog.show('editor_clean_text_dialog', App.lang('Clean Text'), dialog_body, {
        width: 500
      });
      
      $('#pasted_text').focus();
      
      $('#editor_clean_text_dialog_container').find('.buttonHolder button:first').click(function () {
        var content = $('#editor_clean_text_dialog_container textarea:first').val();
        content = content.replace(/(\r\n|[\r\n])/g, "<br />");
        App.widgets.EditorCleanTextDialog.insert(content);
        return false;
      });
    },
    
    /**
     * insert cleaned text into body
     */
    insert : function (cleaned_text) {
      editor_instance.focus();
      editor_instance.selection.moveToBookmark(cursor_position);
      editor_instance.execCommand('mceInsertContent', false, cleaned_text);
      App.ModalDialog.close();
    }
  }
}();

/**
 * initialize Active Reminders
 */
App.widgets.ActiveReminders = function() {
  
  /**
   * Wrapper instance
   *
   * @var jQuery
   */
  var wrapper;
  
 
  // Public interface
  return {
    
    /**
     * Initialize Active Reminders
     *
     * @param String wrapper_id
     */
    init : function(wrapper_id) {
      wrapper = $('#' + wrapper_id);
      
      wrapper.find('td.options a').click(function () {
        var anchor = $(this);
        var ajax_url = App.extendUrl(anchor.attr('href'), { async: 1, skip_layout : 1 });
        var delete_image_element = anchor.find('img');
        var delete_icon = delete_image_element.attr('src');
        
        delete_image_element.attr('src', App.data.indicator_url);
        $.ajax({
          url     : ajax_url,
          type    : 'post',
          data    : '&submitted=submitted',
          success : function () {
            anchor.parents('tr:first').remove();
            if (wrapper.find('tr').length == 1) {
              wrapper.parent().find('.empty_page').show();
              wrapper.parent().find('#active_reminders').hide();
              if (App.widgets.DashboardImportantItems) {
                App.widgets.DashboardImportantItems.removeItem('reminders');
              } // if
            } // if
          },
          error   : function () {
            delete_image_element.attr('src', delete_icon);
          }
        });       

        return false;
      });
            
    }
    
  }
}();


/**
 * Simple show/hide for the 'new comment' form
 */
App.resources.newCommentForm = function() {
  return {
    init : function() {
      var comment_form = $('div.quick_comment_form');
      var comment_link = $('a.comments_toggle_form');
      
      comment_form.show();
      comment_link.click(function() {
        comment_form.toggle();
        
        if (comment_form.is(":visible")) {
          tinymce.execCommand('mceFocus', false, 'commentBody');
        } // if
        
        return false;
      });
    } // init
  } // return
}(); // newCommentForm


/**
 * Resource module behavior initialized on every page
 */
$(document).ready(function() {
  
  // Starred
  $('#menu_item_starred_folder a').click(function() {
    var link = $(this);
    
    App.ModalDialog.show('starred_objects_popup', App.lang('Starred'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(App.extendUrl(link.attr('href'), { async : 1 })), {
      width: '500px'
    });
    
    return false;
  });
   
  if (!App.data.copyright_removed && $('#footer #powered_by a[href="http://www.activecollab.com/"]').length == 0) {
    if ($('#footer').length == 0) {
      $('body').append('<div id="footer"></div>');
    } // if
    $('#footer').prepend('<p id="powered_by"><a href="http://www.activecollab.com/" target="_blank"><img src="' + App.data.assets_url + '/images/acpowered.gif" alt="powered by activeCollab" /></a></p>').css('display', 'block').css('visibility','visible').css('position', 'static');
    $('#powered_by').css('display', 'block').css('visibility','visible').css('position', 'static');
  } // if
});

/** File: javascript/jumptop.js **/

/***********************************************
* Jump To Top Link Script- © Dynamic Drive (www.dynamicdrive.com)
* Last updated Nov 13th, 03'.
* This notice MUST stay intact for legal use
* Visit http://www.dynamicdrive.com/ for full source code
***********************************************/

//Specify the text to display
var displayed="<nobr><b>[Top]</b></nobr>"

///////////////////////////Do not edit below this line////////////

var logolink='javascript:window.scrollTo(0,0)'
var ns4=document.layers
var ie4=document.all
var ns6=document.getElementById&&!document.all

function ietruebody(){
return (document.compatMode && document.compatMode!="BackCompat")? document.documentElement : document.body
}

function regenerate(){
window.location.reload()
}
function regenerate2(){
if (ns4)
setTimeout("window.onresize=regenerate",400)
}

if (ie4||ns6)
document.write('<span id="logo" style="position:absolute;top:-300px;z-index:100">'+displayed+'</span>')

function createtext(){ //function for NS4
staticimage=new Layer(5)
staticimage.left=-300
staticimage.document.write('<a href="'+logolink+'">'+displayed+'</a>')
staticimage.document.close()
staticimage.visibility="show"
regenerate2()
staticitns()
}

function staticit(){ //function for IE4/ NS6
var w2=ns6? pageXOffset+w : ietruebody().scrollLeft+w
var h2=ns6? pageYOffset+h : ietruebody().scrollTop+h
crosslogo.style.left=w2+"px"
crosslogo.style.top=h2+"px"
}

function staticit2(){ //function for NS4
staticimage.left=pageXOffset+window.innerWidth-staticimage.document.width-28
staticimage.top=pageYOffset+window.innerHeight-staticimage.document.height-10
}

function inserttext(){ //function for IE4/ NS6
if (ie4)
crosslogo=document.all.logo
else if (ns6)
crosslogo=document.getElementById("logo")
crosslogo.innerHTML='<a href="'+logolink+'">'+displayed+'</a>'
w=ns6 || window.opera? window.innerWidth-crosslogo.offsetWidth-20 : ietruebody().clientWidth-crosslogo.offsetWidth-10
h=ns6 || window.opera? window.innerHeight-crosslogo.offsetHeight-15 : ietruebody().clientHeight-crosslogo.offsetHeight-10
crosslogo.style.left=w+"px"
crosslogo.style.top=h+"px"
if (ie4)
window.onscroll=staticit
else if (ns6)
startstatic=setInterval("staticit()",100)
}

if (ie4||ns6){
if (window.addEventListener)
window.addEventListener("load", inserttext, false)
else if (window.attachEvent)
window.attachEvent("onload", inserttext)
else
window.onload=inserttext
window.onresize=new Function("window.location.reload()")
}
else if (ns4)
window.onload=createtext

function staticitns(){ //function for NS4
startstatic=setInterval("staticit2()",90)
}


/** File: modules/hr_manager/javascript/main.js **/


; // don't delete!! very important fix!

(function($) {
	$.fn.tipsy = function(opts) {

		opts = $.extend({fade: false, gravity: 'n'}, opts || {});
		var tip = null, cancelHide = false;

		this.hover(function() {
			
			$.data(this, 'cancel.tipsy', true);

			var tip = $.data(this, 'active.tipsy');
			if (!tip) {
				tip = $('<div class="tipsy"><div class="tipsy-inner">' + $(this).attr('title') + '</div></div>');
				tip.css({position: 'absolute', zIndex: 100000});
				$(this).attr('title', '');
				$.data(this, 'active.tipsy', tip);
			}
			
			var pos = $.extend({}, $(this).offset(), {width: this.offsetWidth, height: this.offsetHeight});
			tip.remove().css({top: 0, left: 0, visibility: 'hidden', display: 'block'}).appendTo(document.body);
			var actualWidth = tip[0].offsetWidth, actualHeight = tip[0].offsetHeight;
			
			switch (opts.gravity.charAt(0)) {
				case 'n':
					tip.css({top: pos.top + pos.height, left: pos.left + pos.width / 2 - actualWidth / 2}).addClass('tipsy-north');
					break;
				case 's':
					tip.css({top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2}).addClass('tipsy-south');
					break;
				case 'e':
					tip.css({top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth}).addClass('tipsy-east');
					break;
				case 'w':
					tip.css({top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width}).addClass('tipsy-west');
					break;
			}

			if (opts.fade) {
				tip.css({opacity: 0, display: 'block', visibility: 'visible'}).animate({opacity: 1});
			} else {
				tip.css({visibility: 'visible'});
			}

		}, function() {
			$.data(this, 'cancel.tipsy', false);
			var self = this;
			setTimeout(function() {
				if ($.data(this, 'cancel.tipsy')) return;
				var tip = $.data(self, 'active.tipsy');
				if (opts.fade) {
					tip.stop().fadeOut(function() {$(this).remove();});
				} else {
					tip.remove();
				}
			}, 100);
			
		});

	};
})(jQuery);




/**
 * jscolor, JavaScript Color Picker
 *
 * @version 1.3.1
 * @license GNU Lesser General Public License, http://www.gnu.org/copyleft/lesser.html
 * @author  Jan Odvarko, http://odvarko.cz
 * @created 2008-06-15
 * @updated 2010-01-23
 * @link    http://jscolor.com
 */
var jscolor = {

	dir : '', // location of jscolor directory (leave empty to autodetect)
	bindClass : 'colorpicker', // class name
	binding : true, // automatic binding via <input class="...">
	preloading : true, // use image preloading?


	install : function() {
		jscolor.addEvent(window, 'load', jscolor.init);
	},


	init : function() {
		if(jscolor.binding) {
			jscolor.bind();
		}
		if(jscolor.preloading) {
			jscolor.preload();
		}
	},


	getDir : function() {
		/**
		 * Tui Kiken fix
		 *
		if(!jscolor.dir) {
			var detected = jscolor.detectDir();
			jscolor.dir = detected!==false ? detected : 'jscolor/';
		}
		return jscolor.dir;
		*/

		return App.data.color_picker_img;
	},


	detectDir : function() {
		var base = location.href;

		var e = document.getElementsByTagName('base');
		for(var i=0; i<e.length; i+=1) {
			if(e[i].href) {base = e[i].href;}
		}

		var e = document.getElementsByTagName('script');
		for(var i=0; i<e.length; i+=1) {
			if(e[i].src && /(^|\/)jscolor\.js([?#].*)?$/i.test(e[i].src)) {
				var src = new jscolor.URI(e[i].src);
				var srcAbs = src.toAbsolute(base);
				srcAbs.path = srcAbs.path.replace(/[^\/]+$/, ''); // remove filename
				srcAbs.query = null;
				srcAbs.fragment = null;
				return srcAbs.toString();
			}
		}
		return false;
	},


	bind : function() {
		var matchClass = new RegExp('(^|\\s)('+jscolor.bindClass+')\\s*(\\{[^}]*\\})?', 'i');
		var e = document.getElementsByTagName('input');
		for(var i=0; i<e.length; i+=1) {
			var m;
			if(!e[i].color && e[i].className && (m = e[i].className.match(matchClass))) {
				var prop = {};
				if(m[3]) {
					try {
						eval('prop='+m[3]);
					} catch(eInvalidProp) {}
				}
				e[i].color = new jscolor.color(e[i], prop);
			}
		}
	},


	preload : function() {
		for(var fn in jscolor.imgRequire) {
			if(jscolor.imgRequire.hasOwnProperty(fn)) {
				jscolor.loadImage(fn);
			}
		}
	},


	images : {
		pad : [ 181, 101 ],
		sld : [ 16, 101 ],
		cross : [ 15, 15 ],
		arrow : [ 7, 11 ]
	},


	imgRequire : {},
	imgLoaded : {},


	requireImage : function(filename) {
		jscolor.imgRequire[filename] = true;
	},


	loadImage : function(filename) {
		if(!jscolor.imgLoaded[filename]) {
			jscolor.imgLoaded[filename] = new Image();
			jscolor.imgLoaded[filename].src = jscolor.getDir()+filename;
		}
	},


	fetchElement : function(mixed) {
		return typeof mixed === 'string' ? document.getElementById(mixed) : mixed;
	},


	addEvent : function(el, evnt, func) {
		if(el.addEventListener) {
			el.addEventListener(evnt, func, false);
		} else if(el.attachEvent) {
			el.attachEvent('on'+evnt, func);
		}
	},


	fireEvent : function(el, evnt) {
		if(!el) {
			return;
		}
		if(document.createEventObject) {
			var ev = document.createEventObject();
			el.fireEvent('on'+evnt, ev);
		} else if(document.createEvent) {
			var ev = document.createEvent('HTMLEvents');
			ev.initEvent(evnt, true, true);
			el.dispatchEvent(ev);
		} else if(el['on'+evnt]) { // alternatively use the traditional event model (IE5)
			el['on'+evnt]();
		}
	},


	getElementPos : function(e) {
		var e1=e, e2=e;
		var x=0, y=0;
		if(e1.offsetParent) {
			do {
				x += e1.offsetLeft;
				y += e1.offsetTop;
			} while(e1 = e1.offsetParent);
		}
		while((e2 = e2.parentNode) && e2.nodeName.toUpperCase() !== 'BODY') {
			x -= e2.scrollLeft;
			y -= e2.scrollTop;
		}
		return [x, y];
	},


	getElementSize : function(e) {
		return [e.offsetWidth, e.offsetHeight];
	},


	getMousePos : function(e) {
		if(!e) {e = window.event;}
		if(typeof e.pageX === 'number') {
			return [e.pageX, e.pageY];
		} else if(typeof e.clientX === 'number') {
			return [
				e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft,
				e.clientY + document.body.scrollTop + document.documentElement.scrollTop
			];
		}
	},


	getViewPos : function() {
		if(typeof window.pageYOffset === 'number') {
			return [window.pageXOffset, window.pageYOffset];
		} else if(document.body && (document.body.scrollLeft || document.body.scrollTop)) {
			return [document.body.scrollLeft, document.body.scrollTop];
		} else if(document.documentElement && (document.documentElement.scrollLeft || document.documentElement.scrollTop)) {
			return [document.documentElement.scrollLeft, document.documentElement.scrollTop];
		} else {
			return [0, 0];
		}
	},


	getViewSize : function() {
		if(typeof window.innerWidth === 'number') {
			return [window.innerWidth, window.innerHeight];
		} else if(document.body && (document.body.clientWidth || document.body.clientHeight)) {
			return [document.body.clientWidth, document.body.clientHeight];
		} else if(document.documentElement && (document.documentElement.clientWidth || document.documentElement.clientHeight)) {
			return [document.documentElement.clientWidth, document.documentElement.clientHeight];
		} else {
			return [0, 0];
		}
	},


	URI : function(uri) { // See RFC3986

		this.scheme = null;
		this.authority = null;
		this.path = '';
		this.query = null;
		this.fragment = null;

		this.parse = function(uri) {
			var m = uri.match(/^(([A-Za-z][0-9A-Za-z+.-]*)(:))?((\/\/)([^\/?#]*))?([^?#]*)((\?)([^#]*))?((#)(.*))?/);
			this.scheme = m[3] ? m[2] : null;
			this.authority = m[5] ? m[6] : null;
			this.path = m[7];
			this.query = m[9] ? m[10] : null;
			this.fragment = m[12] ? m[13] : null;
			return this;
		};

		this.toString = function() {
			var result = '';
			if(this.scheme !== null) {result = result + this.scheme + ':';}
			if(this.authority !== null) {result = result + '//' + this.authority;}
			if(this.path !== null) {result = result + this.path;}
			if(this.query !== null) {result = result + '?' + this.query;}
			if(this.fragment !== null) {result = result + '#' + this.fragment;}
			return result;
		};

		this.toAbsolute = function(base) {
			var base = new jscolor.URI(base);
			var r = this;
			var t = new jscolor.URI;

			if(base.scheme === null) {return false;}

			if(r.scheme !== null && r.scheme.toLowerCase() === base.scheme.toLowerCase()) {
				r.scheme = null;
			}

			if(r.scheme !== null) {
				t.scheme = r.scheme;
				t.authority = r.authority;
				t.path = removeDotSegments(r.path);
				t.query = r.query;
			} else {
				if(r.authority !== null) {
					t.authority = r.authority;
					t.path = removeDotSegments(r.path);
					t.query = r.query;
				} else {
					if(r.path === '') { // TODO: == or === ?
						t.path = base.path;
						if(r.query !== null) {
							t.query = r.query;
						} else {
							t.query = base.query;
						}
					} else {
						if(r.path.substr(0,1) === '/') {
							t.path = removeDotSegments(r.path);
						} else {
							if(base.authority !== null && base.path === '') { // TODO: == or === ?
								t.path = '/'+r.path;
							} else {
								t.path = base.path.replace(/[^\/]+$/,'')+r.path;
							}
							t.path = removeDotSegments(t.path);
						}
						t.query = r.query;
					}
					t.authority = base.authority;
				}
				t.scheme = base.scheme;
			}
			t.fragment = r.fragment;

			return t;
		};

		function removeDotSegments(path) {
			var out = '';
			while(path) {
				if(path.substr(0,3)==='../' || path.substr(0,2)==='./') {
					path = path.replace(/^\.+/,'').substr(1);
				} else if(path.substr(0,3)==='/./' || path==='/.') {
					path = '/'+path.substr(3);
				} else if(path.substr(0,4)==='/../' || path==='/..') {
					path = '/'+path.substr(4);
					out = out.replace(/\/?[^\/]*$/, '');
				} else if(path==='.' || path==='..') {
					path = '';
				} else {
					var rm = path.match(/^\/?[^\/]*/)[0];
					path = path.substr(rm.length);
					out = out + rm;
				}
			}
			return out;
		}

		if(uri) {
			this.parse(uri);
		}

	},


	/*
	 * Usage example:
	 * var myColor = new jscolor.color(myInputElement)
	 */

	color : function(target, prop) {


		this.required = true; // refuse empty values?
		this.adjust = true; // adjust value to uniform notation?
		this.hash = false; // prefix color with # symbol?
		this.caps = true; // uppercase?
		this.valueElement = target; // value holder
		this.styleElement = target; // where to reflect current color
		this.hsv = [0, 0, 1]; // read-only  0-6, 0-1, 0-1
		this.rgb = [1, 1, 1]; // read-only  0-1, 0-1, 0-1

		this.pickerOnfocus = true; // display picker on focus?
		this.pickerMode = 'HSV'; // HSV | HVS
		this.pickerPosition = 'bottom'; // left | right | top | bottom
		this.pickerFace = 10; // px
		this.pickerFaceColor = 'ThreeDFace'; // CSS color
		this.pickerBorder = 1; // px
		this.pickerBorderColor = 'ThreeDHighlight ThreeDShadow ThreeDShadow ThreeDHighlight'; // CSS color
		this.pickerInset = 1; // px
		this.pickerInsetColor = 'ThreeDShadow ThreeDHighlight ThreeDHighlight ThreeDShadow'; // CSS color
		this.pickerZIndex = 10000;


		for(var p in prop) {
			if(prop.hasOwnProperty(p)) {
				this[p] = prop[p];
			}
		}


		this.hidePicker = function() {
			if(isPickerOwner()) {
				removePicker();
			}
		};


		this.showPicker = function() {
			if(!isPickerOwner()) {
				var tp = jscolor.getElementPos(target); // target pos
				var ts = jscolor.getElementSize(target); // target size
				var vp = jscolor.getViewPos(); // view pos
				var vs = jscolor.getViewSize(); // view size
				var ps = [ // picker size
					2*this.pickerBorder + 4*this.pickerInset + 2*this.pickerFace + jscolor.images.pad[0] + 2*jscolor.images.arrow[0] + jscolor.images.sld[0],
					2*this.pickerBorder + 2*this.pickerInset + 2*this.pickerFace + jscolor.images.pad[1]
				];
				var a, b, c;
				switch(this.pickerPosition.toLowerCase()) {
					case 'left':a=1;b=0;c=-1;break;
					case 'right':a=1;b=0;c=1;break;
					case 'top':a=0;b=1;c=-1;break;
					default:a=0;b=1;c=1;break;
				}
				var l = (ts[b]+ps[b])/2;
				var pp = [ // picker pos
					-vp[a]+tp[a]+ps[a] > vs[a] ?
						(-vp[a]+tp[a]+ts[a]/2 > vs[a]/2 && tp[a]+ts[a]-ps[a] >= 0 ? tp[a]+ts[a]-ps[a] : tp[a]) :
						tp[a],
					-vp[b]+tp[b]+ts[b]+ps[b]-l+l*c > vs[b] ?
						(-vp[b]+tp[b]+ts[b]/2 > vs[b]/2 && tp[b]+ts[b]-l-l*c >= 0 ? tp[b]+ts[b]-l-l*c : tp[b]+ts[b]-l+l*c) :
						(tp[b]+ts[b]-l+l*c >= 0 ? tp[b]+ts[b]-l+l*c : tp[b]+ts[b]-l-l*c)
				];
				drawPicker(pp[a], pp[b]);
			}
		};


		this.importColor = function() {
			if(!valueElement) {
				this.exportColor();
			} else {
				if(!this.adjust) {
					if(!this.fromString(valueElement.value, leaveValue)) {
						styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
						styleElement.style.color = styleElement.jscStyle.color;
						this.exportColor(leaveValue | leaveStyle);
					}
				} else if(!this.required && /^\s*$/.test(valueElement.value)) {
					valueElement.value = '';
					styleElement.style.backgroundColor = styleElement.jscStyle.backgroundColor;
					styleElement.style.color = styleElement.jscStyle.color;
					this.exportColor(leaveValue | leaveStyle);

				} else if(this.fromString(valueElement.value)) {
					// OK
				} else {
					this.exportColor();
				}
			}
		};


		this.exportColor = function(flags) {
			if(!(flags & leaveValue) && valueElement) {
				var value = this.toString();
				if(this.caps) {value = value.toUpperCase();}
				if(this.hash) {value = '#'+value;}
				valueElement.value = value;
			}
			if(!(flags & leaveStyle) && styleElement) {
				styleElement.style.backgroundColor =
					'#'+this.toString();
				styleElement.style.color =
					0.213 * this.rgb[0] +
					0.715 * this.rgb[1] +
					0.072 * this.rgb[2]
					< 0.5 ? '#FFF' : '#000';
			}
			if(!(flags & leavePad) && isPickerOwner()) {
				redrawPad();
			}
			if(!(flags & leaveSld) && isPickerOwner()) {
				redrawSld();
			}
		};


		this.fromHSV = function(h, s, v, flags) { // null = don't change
			h<0 && (h=0) || h>6 && (h=6);
			s<0 && (s=0) || s>1 && (s=1);
			v<0 && (v=0) || v>1 && (v=1);
			this.rgb = HSV_RGB(
				h===null ? this.hsv[0] : (this.hsv[0]=h),
				s===null ? this.hsv[1] : (this.hsv[1]=s),
				v===null ? this.hsv[2] : (this.hsv[2]=v)
			);
			this.exportColor(flags);
		};


		this.fromRGB = function(r, g, b, flags) { // null = don't change
			r<0 && (r=0) || r>1 && (r=1);
			g<0 && (g=0) || g>1 && (g=1);
			b<0 && (b=0) || b>1 && (b=1);
			var hsv = RGB_HSV(
				r===null ? this.rgb[0] : (this.rgb[0]=r),
				g===null ? this.rgb[1] : (this.rgb[1]=g),
				b===null ? this.rgb[2] : (this.rgb[2]=b)
			);
			if(hsv[0] !== null) {
				this.hsv[0] = hsv[0];
			}
			if(hsv[2] !== 0) {
				this.hsv[1] = hsv[1];
			}
			this.hsv[2] = hsv[2];
			this.exportColor(flags);
		};


		this.fromString = function(hex, flags) {
			var m = hex.match(/^\W*([0-9A-F]{3}([0-9A-F]{3})?)\W*$/i);
			if(!m) {
				return false;
			} else {
				if(m[1].length === 6) { // 6-char notation
					this.fromRGB(
						parseInt(m[1].substr(0,2),16) / 255,
						parseInt(m[1].substr(2,2),16) / 255,
						parseInt(m[1].substr(4,2),16) / 255,
						flags
					);
				} else { // 3-char notation
					this.fromRGB(
						parseInt(m[1].charAt(0)+m[1].charAt(0),16) / 255,
						parseInt(m[1].charAt(1)+m[1].charAt(1),16) / 255,
						parseInt(m[1].charAt(2)+m[1].charAt(2),16) / 255,
						flags
					);
				}
				return true;
			}
		};


		this.toString = function() {
			return (
				(0x100 | Math.round(255*this.rgb[0])).toString(16).substr(1) +
				(0x100 | Math.round(255*this.rgb[1])).toString(16).substr(1) +
				(0x100 | Math.round(255*this.rgb[2])).toString(16).substr(1)
			);
		};


		function RGB_HSV(r, g, b) {
			var n = Math.min(Math.min(r,g),b);
			var v = Math.max(Math.max(r,g),b);
			var m = v - n;
			if(m === 0) {return [ null, 0, v ];}
			var h = r===n ? 3+(b-g)/m : (g===n ? 5+(r-b)/m : 1+(g-r)/m);
			return [ h===6?0:h, m/v, v ];
		}


		function HSV_RGB(h, s, v) {
			if(h === null) {return [ v, v, v ];}
			var i = Math.floor(h);
			var f = i%2 ? h-i : 1-(h-i);
			var m = v * (1 - s);
			var n = v * (1 - s*f);
			switch(i) {
				case 6:
				case 0:return [v,n,m];
				case 1:return [n,v,m];
				case 2:return [m,v,n];
				case 3:return [m,n,v];
				case 4:return [n,m,v];
				case 5:return [v,m,n];
			}
		}


		function removePicker() {
			delete jscolor.picker.owner;
			document.getElementsByTagName('body')[0].removeChild(jscolor.picker.boxB);
		}


		function drawPicker(x, y) {
			if(!jscolor.picker) {
				jscolor.picker = {
					box : document.createElement('div'),
					boxB : document.createElement('div'),
					pad : document.createElement('div'),
					padB : document.createElement('div'),
					padM : document.createElement('div'),
					sld : document.createElement('div'),
					sldB : document.createElement('div'),
					sldM : document.createElement('div')
				};
				for(var i=0,segSize=4; i<jscolor.images.sld[1]; i+=segSize) {
					var seg = document.createElement('div');
					seg.style.height = segSize+'px';
					seg.style.fontSize = '1px';
					seg.style.lineHeight = '0';
					jscolor.picker.sld.appendChild(seg);
				}
				jscolor.picker.sldB.appendChild(jscolor.picker.sld);
				jscolor.picker.box.appendChild(jscolor.picker.sldB);
				jscolor.picker.box.appendChild(jscolor.picker.sldM);
				jscolor.picker.padB.appendChild(jscolor.picker.pad);
				jscolor.picker.box.appendChild(jscolor.picker.padB);
				jscolor.picker.box.appendChild(jscolor.picker.padM);
				jscolor.picker.boxB.appendChild(jscolor.picker.box);
			}

			var p = jscolor.picker;

			// recompute controls positions
			posPad = [
				x+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset,
				y+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset ];
			posSld = [
				null,
				y+THIS.pickerBorder+THIS.pickerFace+THIS.pickerInset ];

			// controls interaction
			p.box.onmouseup =
			p.box.onmouseout = function() {target.focus();};
			p.box.onmousedown = function() {abortBlur=true;};
			p.box.onmousemove = function(e) {holdPad && setPad(e);holdSld && setSld(e);};
			p.padM.onmouseup =
			p.padM.onmouseout = function() {if(holdPad) {holdPad=false;jscolor.fireEvent(valueElement,'change');}};
			p.padM.onmousedown = function(e) {holdPad=true;setPad(e);};
			p.sldM.onmouseup =
			p.sldM.onmouseout = function() {if(holdSld) {holdSld=false;jscolor.fireEvent(valueElement,'change');}};
			p.sldM.onmousedown = function(e) {holdSld=true;setSld(e);};

			// picker
			p.box.style.width = 4*THIS.pickerInset + 2*THIS.pickerFace + jscolor.images.pad[0] + 2*jscolor.images.arrow[0] + jscolor.images.sld[0] + 'px';
			p.box.style.height = 2*THIS.pickerInset + 2*THIS.pickerFace + jscolor.images.pad[1] + 'px';

			// picker border
			p.boxB.style.position = 'absolute';
			p.boxB.style.clear = 'both';
			p.boxB.style.left = x+'px';
			p.boxB.style.top = y+'px';
			p.boxB.style.zIndex = THIS.pickerZIndex;
			p.boxB.style.border = THIS.pickerBorder+'px solid';
			p.boxB.style.borderColor = THIS.pickerBorderColor;
			p.boxB.style.background = THIS.pickerFaceColor;

			// pad image
			p.pad.style.width = jscolor.images.pad[0]+'px';
			p.pad.style.height = jscolor.images.pad[1]+'px';

			// pad border
			p.padB.style.position = 'absolute';
			p.padB.style.left = THIS.pickerFace+'px';
			p.padB.style.top = THIS.pickerFace+'px';
			p.padB.style.border = THIS.pickerInset+'px solid';
			p.padB.style.borderColor = THIS.pickerInsetColor;

			// pad mouse area
			p.padM.style.position = 'absolute';
			p.padM.style.left = '0';
			p.padM.style.top = '0';
			p.padM.style.width = THIS.pickerFace + 2*THIS.pickerInset + jscolor.images.pad[0] + jscolor.images.arrow[0] + 'px';
			p.padM.style.height = p.box.style.height;
			p.padM.style.cursor = 'crosshair';

			// slider image
			p.sld.style.overflow = 'hidden';
			p.sld.style.width = jscolor.images.sld[0]+'px';
			p.sld.style.height = jscolor.images.sld[1]+'px';

			// slider border
			p.sldB.style.position = 'absolute';
			p.sldB.style.right = THIS.pickerFace+'px';
			p.sldB.style.top = THIS.pickerFace+'px';
			p.sldB.style.border = THIS.pickerInset+'px solid';
			p.sldB.style.borderColor = THIS.pickerInsetColor;

			// slider mouse area
			p.sldM.style.position = 'absolute';
			p.sldM.style.right = '0';
			p.sldM.style.top = '0';
			p.sldM.style.width = jscolor.images.sld[0] + jscolor.images.arrow[0] + THIS.pickerFace + 2*THIS.pickerInset + 'px';
			p.sldM.style.height = p.box.style.height;
			try {
				p.sldM.style.cursor = 'pointer';
			} catch(eOldIE) {
				p.sldM.style.cursor = 'hand';
			}

			// load images in optimal order
			switch(modeID) {
				case 0:var padImg = 'hs.png';break;
				case 1:var padImg = 'hv.png';break;
			}
			p.padM.style.background = "url('"+jscolor.getDir()+"cross.gif') no-repeat";
			p.sldM.style.background = "url('"+jscolor.getDir()+"arrow.gif') no-repeat";
			p.pad.style.background = "url('"+jscolor.getDir()+padImg+"') 0 0 no-repeat";

			// place pointers
			redrawPad();
			redrawSld();

			jscolor.picker.owner = THIS;
			document.getElementsByTagName('body')[0].appendChild(p.boxB);
		}


		function redrawPad() {
			// redraw the pad pointer
			switch(modeID) {
				case 0:var yComponent = 1;break;
				case 1:var yComponent = 2;break;
			}
			var x = Math.round((THIS.hsv[0]/6) * (jscolor.images.pad[0]-1));
			var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.pad[1]-1));
			jscolor.picker.padM.style.backgroundPosition =
				(THIS.pickerFace+THIS.pickerInset+x - Math.floor(jscolor.images.cross[0]/2)) + 'px ' +
				(THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.cross[1]/2)) + 'px';

			// redraw the slider image
			var seg = jscolor.picker.sld.childNodes;

			switch(modeID) {
				case 0:
					var rgb = HSV_RGB(THIS.hsv[0], THIS.hsv[1], 1);
					for(var i=0; i<seg.length; i+=1) {
						seg[i].style.backgroundColor = 'rgb('+
							(rgb[0]*(1-i/seg.length)*100)+'%,'+
							(rgb[1]*(1-i/seg.length)*100)+'%,'+
							(rgb[2]*(1-i/seg.length)*100)+'%)';
					}
					break;
				case 1:
					var rgb, s, c = [ THIS.hsv[2], 0, 0 ];
					var i = Math.floor(THIS.hsv[0]);
					var f = i%2 ? THIS.hsv[0]-i : 1-(THIS.hsv[0]-i);
					switch(i) {
						case 6:
						case 0:rgb=[0,1,2];break;
						case 1:rgb=[1,0,2];break;
						case 2:rgb=[2,0,1];break;
						case 3:rgb=[2,1,0];break;
						case 4:rgb=[1,2,0];break;
						case 5:rgb=[0,2,1];break;
					}
					for(var i=0; i<seg.length; i+=1) {
						s = 1 - 1/(seg.length-1)*i;
						c[1] = c[0] * (1 - s*f);
						c[2] = c[0] * (1 - s);
						seg[i].style.backgroundColor = 'rgb('+
							(c[rgb[0]]*100)+'%,'+
							(c[rgb[1]]*100)+'%,'+
							(c[rgb[2]]*100)+'%)';
					}
					break;
			}
		}


		function redrawSld() {
			// redraw the slider pointer
			switch(modeID) {
				case 0:var yComponent = 2;break;
				case 1:var yComponent = 1;break;
			}
			var y = Math.round((1-THIS.hsv[yComponent]) * (jscolor.images.sld[1]-1));
			jscolor.picker.sldM.style.backgroundPosition =
				'0 ' + (THIS.pickerFace+THIS.pickerInset+y - Math.floor(jscolor.images.arrow[1]/2)) + 'px';
		}


		function isPickerOwner() {
			return jscolor.picker && jscolor.picker.owner === THIS;
		}


		function blurTarget() {
			if(valueElement === target) {
				THIS.importColor();
			}
			if(THIS.pickerOnfocus) {
				THIS.hidePicker();
			}
		}


		function blurValue() {
			if(valueElement !== target) {
				THIS.importColor();
			}
		}


		function setPad(e) {
			var posM = jscolor.getMousePos(e);
			var x = posM[0]-posPad[0];
			var y = posM[1]-posPad[1];
			switch(modeID) {
				case 0:THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), 1 - y/(jscolor.images.pad[1]-1), null, leaveSld);break;
				case 1:THIS.fromHSV(x*(6/(jscolor.images.pad[0]-1)), null, 1 - y/(jscolor.images.pad[1]-1), leaveSld);break;
			}
		}


		function setSld(e) {
			var posM = jscolor.getMousePos(e);
			var y = posM[1]-posPad[1];
			switch(modeID) {
				case 0:THIS.fromHSV(null, null, 1 - y/(jscolor.images.sld[1]-1), leavePad);break;
				case 1:THIS.fromHSV(null, 1 - y/(jscolor.images.sld[1]-1), null, leavePad);break;
			}
		}


		var THIS = this;
		var modeID = this.pickerMode.toLowerCase()==='hvs' ? 1 : 0;
		var abortBlur = false;
		var
			valueElement = jscolor.fetchElement(this.valueElement),
			styleElement = jscolor.fetchElement(this.styleElement);
		var
			holdPad = false,
			holdSld = false;
		var
			posPad,
			posSld;
		var
			leaveValue = 1<<0,
			leaveStyle = 1<<1,
			leavePad = 1<<2,
			leaveSld = 1<<3;

		// target
		jscolor.addEvent(target, 'focus', function() {
			if(THIS.pickerOnfocus) {THIS.showPicker();}
		});
		jscolor.addEvent(target, 'blur', function() {
			if(!abortBlur) {
				window.setTimeout(function(){abortBlur || blurTarget();abortBlur=false;}, 0);
			} else {
				abortBlur = false;
			}
		});

		// valueElement
		if(valueElement) {
			var updateField = function() {
				THIS.fromString(valueElement.value, leaveValue);
			};
			jscolor.addEvent(valueElement, 'keyup', updateField);
			jscolor.addEvent(valueElement, 'input', updateField);
			jscolor.addEvent(valueElement, 'blur', blurValue);
			valueElement.setAttribute('autocomplete', 'off');
		}

		// styleElement
		if(styleElement) {
			styleElement.jscStyle = {
				backgroundColor : styleElement.style.backgroundColor,
				color : styleElement.style.color
			};
		}

		// require images
		switch(modeID) {
			case 0:jscolor.requireImage('hs.png');break;
			case 1:jscolor.requireImage('hv.png');break;
		}
		jscolor.requireImage('cross.gif');
		jscolor.requireImage('arrow.gif');

		this.importColor();
	}

};

$(window).load(function () {
    var loc = window.location.href;
    if (loc.indexOf('people') > 0 && loc.indexOf('users') > 0 && App.data.user_birthday != '') {
        $('.properties').append('<dt>'+App.lang('Birthday')+'</dt><dd>'+App.data.user_birthday+'</dd>');
    }
    if (loc.indexOf('people') > 0 && loc.indexOf('users') > 0 && App.data.user_hired != '') {
        $('.properties').append('<dt>'+App.lang('Employment Date')+'</dt><dd>'+App.data.user_hired+'</dd>');
    }
//    if (loc.indexOf('people') > 0 && loc.indexOf('users') > 0 && App.data.user_type != '') {
//        $('.properties dt').each(function(){
//            if($(this).html() == 'Role'){
//                dd = $(this).next();
//                dd.html(dd.html()+', '+App.lang(App.data.user_type));
//            }
//        });
//    }
//    if (loc.indexOf('people') > 0 && loc.indexOf('users') > 0 && App.data.user_rate_type != '') {
//        $('.properties').append('<dt>'+App.lang('Rate')+'</dt><dd>'+App.lang(App.data.user_rate_type)+'</dd>');
//    }
    if (loc.indexOf('people') > 0 ) {
        App.hr_manager_tabs.init();
    }
});


/**
 * Manage subscriptions popup and section behavior
 */
App.hr_manager_vacation_visibility = {

    init : function() {

      var wrapper_id = 'vacation_visibility';
      var object_type = 'visibility';

      wrapper = $('#' + wrapper_id);

      $('#vacation_visibility').click(function() {
        if(wrapper.css('display') != 'block') {
          wrapper.show();
        } // if

        var popup_url = wrapper.attr('popup_url');

        App.ModalDialog.show('manage_object_subscriptions_popup', App.lang('Manage Subscriptions'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(popup_url, function() {
          $('#object_subscriptions table td.subscription input[type=checkbox]').click(function() {
            var checkbox = $(this);
            var cell = checkbox.parent();

            checkbox.hide();
            cell.append('<img src="' + App.data.indicator_url + '" alt="" />');

            if(this.checked) {
              var url = checkbox.attr('subscribe_url');
            } else {
              var url = checkbox.attr('unsubscribe_url');
            } // if

            $.ajax({
              url  : App.extendUrl(url, {async : 1}),
              type : 'POST',
              data : {
                submitted : 'submitted'
              },
              success : function() {
                cell.find('img').remove();
                checkbox.show();

                // Lets update list of users
                var subscribed_users = [];
                $('#object_subscriptions table td.subscription input:checked').each(function() {
                  subscribed_users.push($(this).parent().parent().find('td.name a').clone());
                });

                var subscribed_users_list_wrapper = wrapper.find('div.object_subscriptions_list_wrapper').empty();
                var subscribed_users_length = subscribed_users.length;

                if(subscribed_users_length == 0) {
                  subscribed_users_list_wrapper.append(App.lang('There are no users subscribed to this :type', {type : object_type}));
                } else if(subscribed_users_length == 1) {
                  subscribed_users_list_wrapper.append(subscribed_users[0]).append(' ' + App.lang('is subscribed to this :type', {type : object_type}));
                } else {
                  for(var i = 0; i < subscribed_users_length; i++) {
                    subscribed_users_list_wrapper.append(subscribed_users[i]);

                    if(i < (subscribed_users_length - 2)) {
                      subscribed_users_list_wrapper.append(', ');
                    } else if(i == (subscribed_users_length - 2)) {
                      subscribed_users_list_wrapper.append(App.lang(' and '));
                    } // if
                  } // for

                  subscribed_users_list_wrapper.append(' ' + App.lang('are subscribed to this :type', {type : object_type}));
                } // if
              },
              error : function() {
                cell.find('img').remove();
                checkbox[0].checked = !checkbox[0].checked;
                checkbox.show();
              }
            });
          });
        }), {
          height: 400,
          buttons : [{
            label : App.lang('Close')
          }]
        });

        return false;
      });
    }
};


App.hr_manager = {
  controllers : {},
  models      : {}
};
App.hr_manager.controllers.vacation = {
  index: function(){
    $(document).ready(function() {
        App.hr_manager_tabs.init();
        
        var form = $("#add_vacation");
        form.submit(function(){
            var add_form = $(this);
            if(UniForm.validate(add_form, true)) {
              $("#add_vacation td.actions").prepend('<img id="load_indicator" src="' + App.data.assets_url + '/images/indicator.gif" class="indicator" alt="Working..." />').find('button').hide();
              $(this).ajaxSubmit({
                url    : App.extendUrl(add_form.attr('action'), {async : 1}),
                type : 'POST',
                data : {
                    'submitted' : 'submitted'
                },
                success: function(response) {
                  $('#add_vacation td.actions').find('img').remove();
                  $('#add_vacation td.actions').find('button').show();
                    alert(response);
                },
                error : function() {
                  $('#add_vacation td.actions').find('img').remove();
                  $('#add_vacation td.actions').find('button').show();
                    alert('Sorry. An error occured');
                }
              });
            }
            return false;
        });
		
		$('#add_vacation_button').click(function() {
			var status_update_url = App.extendUrl($(this).attr('href'), { 
			  async : 1 
			});
			
			App.ModalDialog.show('status_updates', App.lang('Add vacation'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(status_update_url), {
			  buttons : false
			});

			return false;
		});
		
		$('#vacation-filter').change(function(){
			var indicator_image_src =  App.data.assets_url + '/images/indicator.gif';
			$('#filter-loading').append('<div><img src="' + indicator_image_src + '" alt="" /> ' + App.lang('Loading...') + '</div>');
			window.location = $(this).val();
		});
		
		$('.vacation_type').tipsy({gravity:'s', fade:true});

        $('#vacation_infotable td > div').height($('#vacation_infotable').innerHeight()-20);
    });
  },

  weekends: function(){
    $(document).ready(function() {
      App.hr_manager_tabs.init();
     if(App.data.vacation_accessLevel*1 > 1) {
      $('#vacation_calendar td.day_cell').click(function() {
        var cell = $(this);
        var link = cell.find('div.day_num a');
        cell.prepend('<img id="load_indicator" src="' + App.data.assets_url + '/images/indicator.gif" class="indicator" style="float:right;padding:5px 5px 0 0" alt="Working..." />');
            $.ajax({
              url  : App.extendUrl(link.attr('href'), {async : 1}),
              type : 'POST',
              data : {
                'submitted' : 'submitted'
              },
              success : function(response) {
                $("#load_indicator").remove();
                if(response = "true"){
                    if(cell.hasClass('weekend')) {
                        cell.removeClass('weekend').addClass('weekday');
                    }else{
                        cell.removeClass('weekday').addClass('weekend');
                    }
                }else{
                    alert('Sorry. An error occured');
                }
              },
              error : function(response) {
                $("#load_indicator").remove();
                alert(App.lang('An error occured'));
              }
            });
        return false;
      });
    }
    });
  },
  types: function(){
    $(document).ready(function() {
        App.hr_manager_tabs.init();
    });
	jscolor.install();
  },
  edit_type: function(){
    $(document).ready(function() {
        App.hr_manager_tabs.init();
    });
	jscolor.install();
  },
  salary: function(){
    $(document).ready(function() {
        App.hr_manager_tabs.init();

        $('#vacation_visibility').click(function(){
            var popup_url = $(this).attr('href');
            popup_url = App.extendUrl(popup_url, { async : 1 })

            App.ModalDialog.show(
                'manage_object_visibility_popup',
                App.lang('Manage Visibility'),
                $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(popup_url, function() {

            }));

            return false;
        });
    });
  },
  edit_salary: function(){
    $(document).ready(function() {
        App.hr_manager_tabs.init();
    });
  },
  add_salary_bonus: function(){
    $(document).ready(function() {
        App.hr_manager_tabs.init();
    });
  },
  permissions: function(){
    $(document).ready(function() {
        App.hr_manager_tabs.init();
    });
  },
  edit_permissions: function(){
    $(document).ready(function() {
        App.hr_manager_tabs.init();
    });
  },
  add_vacation: function(){
    $(document).ready(function() {
        App.hr_manager_tabs.init();
    });
  },
  edit_vacation: function(){
    $(document).ready(function() {
        App.hr_manager_tabs.init();
    });
  }
};


App.hr_manager_tabs = {
    init: function(){
        var loc = window.location.href;
        if((($('#menu_item_people').hasClass('active') && !$('#tabs').length) || (loc.indexOf('people') > 0 && loc.indexOf('users') > 0)) && App.data.vacation_accessLevel*1 )
        {
            this.setTab("overview",App.data.vacation_people_url);
            this.setTab("general",App.data.vacation_index_url);
            this.setTab("salary",App.data.vacation_salary_url);
            this.setTab("types",App.data.vacation_types_url);
            this.setTab("weekends",App.data.vacation_weekends_url);
            this.setTab("permissions",App.data.vacation_permissions_url);
            

            var tabs = '<li id="page_tab_vacation_overview" class="first"><a href="#"><span>'+App.lang('Overview')+'</span></a></li>\n\
                        <li id="page_tab_vacation_general"><a href="#"><span>'+App.lang('HR Manager')+'</span></a></li>\n\
                        <li id="page_tab_vacation_salary"><a href="#"><span>'+App.lang('Salary')+'</span></a></li>';

            if(App.data.vacation_accessLevel*1 > 1){
               tabs += '<li id="page_tab_vacation_types"><a href="#"><span>'+App.lang('Events')+'</span></a></li>';
            }
            
            tabs += '<li id="page_tab_vacation_weekends"><a href="#"><span>'+App.lang('Calendar')+'</span></a></li>\n';

            if(App.data.vacation_accessLevel*1 > 2){
               tabs += '<li id="page_tab_vacation_permissions"><a href="#"><span>'+App.lang('Settings')+'</span></a></li>';
            }

            $('#top').after('<div id="tabs"><div class="container"><ul>' + tabs + '</ul></div></div>');

            for(var i in this.tabs){
                $('#page_tab_vacation_' + i +' a').attr('href', this.tabs[i])
            }

            if(App.data.page_tab){
                $('#page_tab_vacation_' + App.data.page_tab +' a').addClass('current');
            } else {
                 $('#page_tab_vacation_overview a').addClass('current');
            }
        }
    },
    setTab: function(name, url){
        this.tabs[name] = url;
    },
    tabs: []
}


App.layout.init_vacation_ajax_calendar_navigation = function(id) {

      var content = $('#' + id);
      $('a.calendar_navigation_item').click(function() {
        content.empty();
        $('<p class="dashboard_sections_loading"><img src="' + App.data.big_indicator_url + '" alt="" /></p>').appendTo(content);
        $.ajax({
          url     : App.makeAsyncUrl($(this).attr('href')),
          type    : 'GET',
          success : function(response) {
            content.empty();
            content.append(response);
          },
          error   : function() {
            content.empty();
          }
        });

        return false;
      });
}

/** File: modules/discussions/javascript/main.js **/

App.discussions = {
  controllers : {},
  models      : {}
};

/**
 * Main discussions JS file
 */
App.discussions.controllers.discussions = {
  view : function() {
    $(document).ready(function() {
      $('#object_quick_option_details').click(function () {
        $('.discussion_details_toggled').toggle();
        return false;
      });
    });
  }
}

/** File: modules/invoicing/javascript/main.js **/

App.invoicing = {
  controllers : {},
  models      : {}
};

/**
 * Invoicing controller
 */
App.invoicing.controllers.invoices = {
  /**
   * Behavior for send page
   */
  issue : function() {
    $(document).ready(function() {
      if ($('#select_invoice_recipients').length > 0) {
        if($('#issue_invoice table input[type=radio]:checked').length < 1) {
          $('#issue_invoice table input[type=radio]:first')[0].checked = true; // Select first user if nobody is selected
        } // if
        
        $('#select_invoice_recipients table tr').click(function() {
          $(this).find('input[type=radio]')[0].checked = true;
        });
        
        $('#issue_invoice p input[type=radio]').click(function() {
          if($('#issueFormSendEmailsYes')[0].checked) {
            $('#select_invoice_recipients').show('fast');
          } else {
            $('#select_invoice_recipients').hide('fast');
          } // if
        });
        
        if($('#issueFormSendEmailsYes')[0].checked) {
          $('#select_invoice_recipients').show();
        } // if
      } // if
    });
  },
  
  notify : function() {
    $(document).ready(function() {
      if($('#issue_invoice table input[type=radio]:checked').length < 1) {
        $('#issue_invoice table input[type=radio]:first')[0].checked = true; // Select first user if nobody is selected
      } // if
      
      $('#select_invoice_recipients table tr').click(function() {
        $(this).find('input[type=radio]')[0].checked = true;
      });
      
      $('#issue_invoice p input[type=radio]').click(function() {
        if($('#issueFormSendEmailsYes')[0].checked) {
          $('#select_invoice_recipients').show('fast');
        } else {
          $('#select_invoice_recipients').hide('fast');
        } // if
      });
      
      if($('#issueFormSendEmailsYes')[0].checked) {
        $('#select_invoice_recipients').show();
      } // if
    });
  }
};

/**
 * Invoice payments controller
 */
App.invoicing.controllers.invoice_payments = {
  add : function () {
    $(document).ready(function () {      
      var payment_value_input = $('#invoicePaymentAmount');
      var skip_email_notification = $('#notifyCompanyBlock');
      
      var payment_value_changed = function () {
        var max_value = parseFloat(App.data.max_invoice_payment);
        var current_value = parseFloat(payment_value_input.val());
        if (current_value >= max_value) {
          skip_email_notification.show();
        } else {
          skip_email_notification.hide();
        } // if
      }; // payment_value_changed
      payment_value_changed();
            
      payment_value_input.change(payment_value_changed).keyup(payment_value_changed);
    });
  }
};

/**
 * Currencies administration
 */
App.invoicing.controllers.currencies_admin = {
  
  /**
   * Currencies administration index behavior
   */
  index : function() {
    $(document).ready(function() {
      $('#currencies td.checkbox input').click(function() {
        var checkbox = $(this);
        var cell = checkbox.parent();
        
        // Status is not changed to checked (status is set before callback)
        if(this.checked) {
          this.checked = false;
        } else {
          return false;
        } // if
        
        if(confirm(App.lang('Are you sure that you want to set this currency as a default?'))) {
          checkbox.hide();
          cell.append('<img src="' + App.data.indicator_url + '" />');
          
          $.ajax({
            url  : App.extendUrl(checkbox.attr('set_as_default_url'), { async : 1 }),
            type : 'POST',
            data : {
              submitted : 'submitted'
            },
            success : function() {
              $('#currencies td.checkbox input').each(function() {
                this.checked = false;
              });
              
              checkbox[0].checked = true;
              
              cell.find('img').remove();
              checkbox.show();
              return true;
            },
            error : function() {
              cell.find('img').remove();
              checkbox.show();
              
              alert(App.lang('Failed to set this currencies as default'));
              
              return false;
            }
          });
        } // if
        
        return false;
      });
    });
  }
  
};

/**
 * PDF settings
 */
App.invoicing.controllers.pdf_settings_admin = {
  /**
   * Behavior for send page
   */
  index : function() {
    $(document).ready(function() {      
      $('.color_selector').each(function () {
        var picker = $(this);
        var input_control = $('input:eq(0)', picker.parent());
        var initial_color = '#' + input_control.val();
        
    		$('div', picker).css('backgroundColor', initial_color);
        picker.ColorPicker({
        	color: initial_color,
        	onShow: function (colpkr) {
        		$(colpkr).fadeIn(500);
        		return false;
        	},
        	onHide: function (colpkr) {
        		$(colpkr).fadeOut(500);
        		return false;
        	},
        	onSubmit: function (hsb, hex, rgb) {
        		$('div', picker).css('backgroundColor', '#' + hex);
        		input_control.val(hex);
        	}
        });
        
        input_control.change(function() {
      		$('div', picker).css('backgroundColor', '#' + $(this).val());
      		picker.ColorPickerSetColor($(this).val());
        });
      });
    });
  }
  
};

/**
 * Invoice form behavior
 */
App.invoicing.InvoiceForm = function() {
  
  /**
   * Instances reused in the code below
   *
   * @var jQuery
   */
  var form, items_table;
  
  /**
   * Registered tax rates
   *
   * @var Object
   */
  var tax_rates = {};
  
  /**
   * Reindex items rows
   */
  var reindex_items_rows = function() {
    var counter = 1;
    items_table.find('tr.item').each(function() {
      var row = $(this);
      row.removeClass('odd').removeClass('even').addClass((counter % 2 ? 'odd' : 'even')).find('td.num span').text('#' + counter).show();
      row.find('.move_handle').hide();
      counter++;
    });
    
    items_table.find('tr.item td.num').each(function () {
      var cell = $(this);
      var move_handle = cell.find('.move_handle');
      var num_span = cell.find('span');
     
      cell.hover(function () {
        move_handle.show();
        num_span.hide();
      }, function () {
        var row = $(this);
        move_handle.hide();
        num_span.show();        
      });
    });
    
    $('#invoice_items table').sortable('destroy');
    $('#invoice_items table').sortable({
      axis : 'y',
      items : 'tr.item',
      handle : '.move_handle',
      start : function () {
        $('#invoice_items table tr.item').removeClass('even').removeClass('odd');
      },
      stop : function () {
        reindex_items_rows();
      }
    });
  }; // reindex_items_rows 
  
  /**
   * Initialize item row
   *
   * @param jQuery row
   */
  var initialize_item_row = function(row) {
    row.find('td.tax_rate input[type=hidden]').each(function() {
      var input = $(this);
      var cell = input.parent();
      
      var select = $('<select><option value="0" rate="0">' + App.lang('No Tax') + '</option></select>').attr('name', input.attr('name'));
      for(var i in tax_rates) {
        var option = $('<option></option>').text(tax_rates[i]['name']).attr({
          'value'    : i,
          'rate'     : tax_rates[i]['rate']
        }).appendTo(select);
      } // for
      
      var tax_value = input.val();
      if(tax_value) {
        select.val(tax_value);
      } // if
      
      input.remove();
      cell.append(select);
    });
    
    /**
     * function that handles changes of item fields
     *
     * @param void
     * @return null
     */
    var handle_keyup = function() {
      var input_element = $(this);
      var input_element_cell = input_element.parents('td:first');     
      
      if (input_element_cell.is('.total')) {
        input_element.parents('tr').addClass('recalculate_unit_cost');
      } else {
        input_element.parents('tr').addClass('recalculate_total');
      } // if
      recalculate_total();
    }; // handle_keyup
    
    /**
     * filter keypresses that are not allowed
     *
     * @param mixed e
     * @return boolean
     */
    var handle_keypress = function (e) {
      if (handle_special_keypress(e, this) == false) {
        return false;
      } // if
      if ((e.which >= 48) && (e.which <= 57) || (e.which == 46) || (e.which = 43) || (e.altKey || e.metaKey || e.ctrlKey || (e.keyCode > 0))) {
        // check if dot is already present
        if (e.which == 46) {
          var value = $(this).val();
          if (value.indexOf('.') > 0) {
            return false;
          } // if
        } // if
        return true;
      } // if
      return false;
    }; // handle_keypress
    
    /**
     * filter enter keypress
     *
     * @param mixed e
     * @return boolean
     */
    var handle_special_keypress = function (e, input_element) {
      if (e.which == 13) {
        //if key is enter add new row
        if (input_element) {
          var next_row = $(input_element).parents('tr.item').next();
        } else {
          var next_row = $(this).parents('tr.item').next();
        } // if
        if (next_row.is('.item')) {
          next_row.find('td.description input').focus();
        } else {
          App.invoicing.InvoiceForm.add_row(true);  
        } // if
        return false;
      } else if (e.keyCode == 27 && e.charCode == 0) {
        if (input_element) {
          var this_row = $(input_element).parents('tr.item');
        } else {
          var this_row = $(this).parents('tr.item');
        } // if
        
        var delete_button = this_row.find('td.options .button_remove');
        var next_row_input = this_row.next().find('td.description input');
        var previous_row_input = this_row.prev().find('td.description input');
        
        delete_button.click();
        
        if (previous_row_input.length > 0) {
          previous_row_input.focus();
        } else if (next_row_input.length > 0) {
          next_row_input.focus();
        } // if
        return false;        
      } // if
      return true;
    }; // handle_special_keypress
    
    /**
     * handle blur events
     *
     * @param mixed e
     * @return boolean
     */
    var handle_blur = function (e) {
      var input_element = $(this);
      input_element.val(App.parseNumeric(input_element.val()).toFixed(App.data.invoicing_precision));
    }; // handle_blur
    
    row.find('td.quantity input').keyup(handle_keyup);
    row.find('td.unit_cost input').keyup(handle_keyup);
    row.find('td.total input').keyup(handle_keyup); 
    row.find('td.tax_rate select').change(handle_keyup);
    
    row.find('td.quantity input').keypress(handle_keypress);
    row.find('td.unit_cost input').keypress(handle_keypress);
    row.find('td.total input').keypress(handle_keypress);
    
    row.find('td.quantity input').blur(handle_blur);
    row.find('td.unit_cost input').blur(handle_blur);
    row.find('td.total input').blur(handle_blur);
    
    row.find('td.description input').keypress(handle_special_keypress);
    
    row.find('td.options img.button_remove').click(function() {
      if(items_table.find('tr.item').length > 1) {
        row.remove();
        recalculate_total();
        reindex_items_rows();
      } // if
    });
    
    row.find('input, select').focus(function() {
      UniForm.focus_field(form, $(this));
    });
  }; // initialize_item_row
    
  /**
   * Recalculate only total of totals
   */
  var recalculate_total = function() {
    var total_subtotal = 0;
    var total_of_totals = 0;
    
    // recalculate rows which are modified
    items_table.find('tr.item.recalculate_total, tr.item.recalculate_unit_cost').each(function() {
      var row = $(this);
      if (row.is('.recalculate_total')) {
        // recalculate total
        var quantity = App.parseNumeric(row.find('td.quantity input').val());
        var unit_cost = App.parseNumeric(row.find('td.unit_cost input').val());
        var tax_rate = App.parseNumeric(row.find('td.tax_rate select option:selected').attr('rate'));
        var total = 0;
        var subtotal = 0;
        
        if(isNaN(quantity) || isNaN(unit_cost) || isNaN(tax_rate)) {
          row.find('td.subtotal input').val(subtotal.toFixed(App.data.invoicing_precision));
          row.find('td.total input').val(total.toFixed(App.data.invoicing_precision));
        } else {
          var subtotal = quantity * unit_cost;
          var total = subtotal * (1 + tax_rate / 100);
          
          row.find('td.subtotal input').val(subtotal.toFixed(App.data.invoicing_precision));
          row.find('td.total input').val(total.toFixed(App.data.invoicing_precision));
        } // if
        row.removeClass('recalculate_total');
      } else {
        // recalculate unit cost
        var quantity = App.parseNumeric(row.find('td.quantity input').val());
        var unit_cost = 0;
        var tax_rate = App.parseNumeric(row.find('td.tax_rate select option:selected').attr('rate'));
        var total = App.parseNumeric(row.find('td.total input').val());
        var subtotal = 0;
        if(isNaN(quantity) || isNaN(total) || isNaN(tax_rate)) {
          row.find('td.subtotal input').val(subtotal.toFixed(App.data.invoicing_precision));
          row.find('td.unit_cost input').val(unit_cost.toFixed(App.data.invoicing_precision));
        } else {
          var unit_cost = total / (quantity * (1 + tax_rate / 100));
          var subtotal = quantity * unit_cost;
          
          row.find('td.subtotal input').val(subtotal.toFixed(App.data.invoicing_precision));
          row.find('td.unit_cost input').val(unit_cost.toFixed(App.data.invoicing_precision));
        } // if
        row.removeClass('recalculate_unit_cost');  
      } // if
    });
    
    // recalculate total subtotal
    items_table.find('tr.item td.subtotal input').each(function() {
      total_subtotal += App.parseNumeric($(this).val());
    });
    
    // recalculate total of totals
    items_table.find('tr.item td.total input').each(function() {
      var value = $(this).val();
      total_of_totals += App.parseNumeric($(this).val());
    });
    
    var currency_code = form.find('#currencyId option:selected').attr('code');
    var invoice_total_text = '<div>'+App.lang('Subtotal: :total :currency', {
      'total' : total_subtotal.toFixed(App.data.invoicing_precision),
      'currency' : currency_code
    })+ '</div>';
    invoice_total_text+= '<div><strong>'+App.lang('Total Due: :total :currency', {
      'total' : total_of_totals.toFixed(App.data.invoicing_precision),
      'currency' : currency_code
    })+ '</strong></div>';
    
    $('#invoice_sub_total').val(total_subtotal.toFixed(App.data.invoicing_precision));
    $('#invoice_total').val(total_of_totals.toFixed(App.data.invoicing_precision));
    items_table.find('tr.invoice_totals td.total').html(invoice_total_text);
  }; // recalculate_total
  
  /**
   * Validate invoice items
   *
   * @param jQuery field
   * @param String caption
   */
  window.validate_invoice_items = function(field, caption) {
    var error_message = false;
    var error_messages = new Array();
    
    var item_count = items_table.find('tr.item').length;
    
    items_table.find('tr.item').each(function() {
      var row = $(this);
      var description = jQuery.trim(row.find('td.description input').val());
      var quantity = App.parseNumeric(row.find('td.quantity input').val());
      var unit_cost = App.parseNumeric(row.find('td.unit_cost input').val());
      var total = App.parseNumeric(row.find('td.total input').val());
      
      if (!description && !total && !unit_cost) {
        // check if there are empty rows
        if (item_count > 1) {
          row.remove();
        } // if
      } else if (!description && (total && unit_cost)) {
        // check if there are missing descriptions
        error_messages[0] = App.lang('All descriptions are required.');
      } // if
    });
    
    var invoice_total = App.parseNumeric(items_table.find('#invoice_total').val());
    if (invoice_total <= 0) {
      error_messages[1] = App.lang('Invoce total is invalid. Invoice total must be greater than zero');
    } // if    
    
    if (error_messages.length > 0) {
      error_message = error_messages.join('<br />');
    } // if
    return error_message ? error_message : true;
  };
  
  // Public interface
  return {
    
    /**
     * Initialize invoice form
     *
     * @param String form_id
     */
    init : function(form_id, mode) {
      form = $('#' + form_id);
      
      var ID_autogenerate = $('#autogenerateID');
      var ID_manually = $('#manuallyID');
      
      ID_autogenerate.find('a').click(function () {
        ID_autogenerate.hide();
        ID_manually.show();
        return false;
      });
      
      ID_manually.find('a').click(function () {
        ID_autogenerate.show();
        ID_manually.hide();
        ID_manually.find('input').val('');
        return false;
      });
      
      // currency handler
      form.find('#currencyId').change(function() {
        recalculate_total();
      });

      var company_id = $('#companyId');
      var company_address = $('#companyAddress');
      
      var ajax_request;
      company_id.change(function () {
        var ajax_url = App.extendUrl(App.data.company_details_url, {
          company_id  : company_id.val(),
          async       : 1,
          skip_layout : 1
        });
        
        // abort request if already exists and it's active
        if ((ajax_request) && (ajax_request.readyState !=4)) {
          ajax_request.abort();
        } // if
        
        if (!company_address.is('loading')) {
          company_address.addClass('loading');
        } // if
        
        company_address.attr("disabled","disabled");
        company_id.attr("disabled","disabled");
        
        ajax_request = $.ajax({
          url         : ajax_url,
          success     : function (response) {
            company_address.val(response);
            company_address.removeClass('loading');
            company_address.removeAttr("disabled","disabled");
            company_id.removeAttr("disabled","disabled");
          }
        });
      });
      if (mode == 'add') {
        company_id.change();
      } // if
      
      items_table = form.find('#invoice_items table');
      items_table.find('a.button_add#add_new').click(function() {
        App.invoicing.InvoiceForm.add_row(true);
        return false;
      });
      
      items_table.find('span.button_dropdown#add_from_template a').click(function() {
        var link = $(this);
        link.parents('.dropdown_container').fadeOut(100);
        App.invoicing.InvoiceForm.add_from_template(link.attr('href'));
        return false;
      });
            
      // initialze preloaded rows     
      var item_rows = items_table.find('tr.item');
      if(item_rows.length < 1) {
        App.invoicing.InvoiceForm.add_row(false);
      } else {
        item_rows.each(function() {
          var row = $(this);
          initialize_item_row(row);
        });
      } // if
                 
      // predefined notes
      form.find('#show_invoice_note_link').click(function() {
        $(this).parent().remove();
        form.find('#invoice_note_wrapper').show('fast', function() {
          $(this).find('textarea')[0].focus();
        });
        return false;
      });
      
      var select_predefined = $('#predefined_notes');
      var note_field = $('#invoice_note');
      select_predefined.change(function () {
        var selected_id = select_predefined.attr('value');
        if (App.data.invoice_notes[selected_id] !== undefined) {
          note_field.val(App.data.invoice_notes[selected_id]);
          note_field.show();
        } else if (selected_id == 'empty') {
          note_field.val('');
          note_field.hide();
        } else if (selected_id == 'original') {
          note_field.val(App.data.original_note);
          note_field.show();
        } else if (selected_id == 'custom') {
          note_field.val('');
          note_field.show();
        } // if
      });
      
      select_predefined.change();
      
      recalculate_total();
      reindex_items_rows();
    },
    
    /**
     * Create a new row
     *
     * @param boolea auto_focus
     */
    add_row : function(auto_focus) {
      var row_number = 0;
      items_table.find('tr.item').each(function () {
        var loop_row = $(this);
        var loop_row_id = loop_row.attr('id');
        if (loop_row_id) {
          loop_row_id = parseInt(loop_row_id.substr(10));
          if (loop_row_id > row_number) {
            row_number = loop_row_id;
          } // if
        } // if
      });
      row_number++;
      var next_row_name = 'invoice[items][' + row_number + ']';
      var zero = 0;
      
      var row = $('<tr class="item" id="items_row_' + row_number + '">' +
        '<td class="num"><span></span><img src="' + App.data.move_icon_url + '" class="move_handle" /></td>' + 
        '<td class="description"><input type="text" name="' + next_row_name + '[description]" value="" /></td>' + 
        '<td class="unit_cost"><input type="text" name="' + next_row_name + '[unit_cost]" class="short" value="'+zero.toFixed(App.data.invoicing_precision)+'" /></td>' + 
        '<td class="quantity"><input type="text" name="' + next_row_name + '[quantity]" class="short" value="1" /></td>' + 
        '<td class="tax_rate"><input type="hidden" name="' + next_row_name + '[tax_rate_id]" value="" /></td>' + 
        '<td class="subtotal" style="display: none"><input type="hidden" name="' + next_row_name + '[subtotal]" value="" /></td>' +
        '<td class="total"><input type="text" name="invoice' + next_row_name + '[total]" value="'+zero.toFixed(App.data.invoicing_precision)+'"/></td>' + 
        '<td class="options"><img src="' + App.data.assets_url + '/images/gray-delete.gif" class="button_remove" /></td>' + 
      '</tr>');
      
      var last_item_row = items_table.find('tr.item:last');
      if(last_item_row.length > 0) {
        last_item_row.after(row);
      } else {
        items_table.find('tr.header').after(row);
      } // if
      reindex_items_rows();
      initialize_item_row(row);
      recalculate_total();
      
      if(auto_focus) {
        row.find('td.description input')[0].focus();
      } // if
    },
    
    /**
     * Create a new row
     *
     * @param boolea auto_focus
     */
    add_from_template : function(template_id, auto_focus) {
      var row_number = 0;
      items_table.find('tr.item').each(function () {
        var loop_row = $(this);
        var loop_row_id = loop_row.attr('id');
        if (loop_row_id) {
          loop_row_id = parseInt(loop_row_id.substr(10));
          if (loop_row_id > row_number) {
            row_number = loop_row_id;
          } // if
        } // if
      });
      row_number++;
      
      last_row = items_table.find('tr.item:last');
      last_row_description = last_row.find('td.description input:[type=text]:first').val();
      last_row_unit_cost = last_row.find('td.unit_cost input:[type=text]:first').val();
      last_row_unit_total = last_row.find('td.total input:[type=text]:first').val();
      
      if (!last_row_description && !parseInt(last_row_unit_cost) && !parseInt(last_row_unit_total)) {
        row_number--;
        last_row.remove();
      } // if
            
      var next_row_name = 'invoice[items][' + row_number + ']';
      var zero = 0;
      
      var row = $('<tr class="item recalculate_total" id="items_row_' + row_number + '">' +
        '<td class="num"><span></span><img src="' + App.data.move_icon_url + '" class="move_handle" /></td>' + 
        '<td class="description"><input type="text" name="' + next_row_name + '[description]" value="'+App.data.invoice_item_templates[template_id].description+'" /></td>' + 
        '<td class="unit_cost"><input type="text" name="' + next_row_name + '[unit_cost]" class="short" value="'+App.data.invoice_item_templates[template_id].unit_cost+'" /></td>' + 
        '<td class="quantity"><input type="text" name="' + next_row_name + '[quantity]" class="short" value="'+App.data.invoice_item_templates[template_id].quantity+'" /></td>' + 
        '<td class="tax_rate"><input type="hidden" name="' + next_row_name + '[tax_rate_id]" value="'+App.data.invoice_item_templates[template_id].tax_rate_id+'" /></td>' + 
        '<td class="subtotal" style="display: none"><input type="hidden" name="' + next_row_name + '[subtotal]" value="" /></td>' +
        '<td class="total"><input type="text" name="invoice' + next_row_name + '[total]" value="'+zero.toFixed(App.data.invoicing_precision)+'"/></td>' + 
        '<td class="options"><img src="' + App.data.assets_url + '/images/gray-delete.gif" class="button_remove" /></td>' + 
      '</tr>');
      
      var last_item_row = items_table.find('tr.item:last');
      if(last_item_row.length > 0) {
        last_item_row.after(row);
      } else {
        items_table.find('tr.header').after(row);
      } // if
      reindex_items_rows();
      initialize_item_row(row);
      recalculate_total();
      
      if(auto_focus) {
        row.find('td.description input')[0].focus();
      } // if
    },
    
    /**
     * Register a new tax rate
     *
     * @param String name
     * @param float rate
     */
    register_tax_rate : function(id, name, rate) {
      tax_rates[id] = {
        'name' : name,
        'rate' : rate
      };
    }
    
  };
  
}();

/**
 * Invoice item templates
 */
App.invoicing.controllers.invoice_item_templates_admin = {
  /**
   * Behavior for send page
   */
  index : function() {
    $(document).ready(function() {      
      $('#invoice_item_templates_list table').sortable({
        axis : 'y',
        items : 'tr.template',
        handle : '.move_handle img',
        forcePlaceholderSize : true,
        start : function () {
          $('#invoice_item_templates_list table tr').each(function () {
            var row = $(this);
            row.removeClass('even').removeClass('odd');
          });
        },
        stop : function () {
          var counter = 0;
          $('#invoice_item_templates_list table tr').each(function () {
            var row = $(this);
            row.removeClass('even').removeClass('odd');
            if (counter % 2 == 0) {
              row.addClass('even');
            } else {
              row.addClass('odd');
            } // if
            counter++;
          });
        },
        update : function () {
          $('#invoice_item_templates_list form').ajaxSubmit({
            type : 'post'
          });
        }
      });
    });
  }
};

/**
 * Invoice note templates
 */
App.invoicing.controllers.invoice_note_templates_admin = {
  /**
   * Behavior for send page
   */
  index : function() {
    $(document).ready(function() {      
      $('#invoice_item_templates_list table').sortable({
        axis : 'y',
        items : 'tr.template',
        handle : '.move_handle img',
        forcePlaceholderSize : true,
        start : function () {
          $('#invoice_item_templates_list table tr').each(function () {
            var row = $(this);
            row.removeClass('even').removeClass('odd');
          });
        },
        stop : function () {
          var counter = 0;
          $('#invoice_item_templates_list table tr').each(function () {
            var row = $(this);
            row.removeClass('even').removeClass('odd');
            if (counter % 2 == 0) {
              row.addClass('even');
            } else {
              row.addClass('odd');
            } // if
            counter++;
          });
        },
        update : function () {
          $('#invoice_item_templates_list form').ajaxSubmit({
            type : 'post'
          });
        }
      });
    });
  }
};

/**
 * Invoice number generator
 */
App.invoicing.controllers.invoice_number_generator_admin = {
  /**
   * Behavior for send page
   */
  index : function() {
    $(document).ready(function() {
      var pattern_input = $('.invoice_generator_pattern_input:first');
      var preview_input = $('.invoice_generator_preview_input:first');
      $('.generator_patterns_and_counters .invoice_generator_variables a').click(function () {
        pattern_input.insertAtCursor($(this).text()).change();
      });
      
      var do_the_preview = function () {
        var preview_string = $(this).val();
        $.each(App.data.pattern_variables, function (key, value) {
          var regexp = new RegExp(key, "g");
          preview_string = preview_string.replace(regexp, value);
        });
        preview_input.val(preview_string);
      }; // do_the_preview
      
      $('.edit_counter').click(function () {
    	var span_wrapper = $(this).parent();
    	var counter_value = parseInt(prompt(App.lang('Enter new counter value'), ""),10);
    	if (isNaN(counter_value) || (counter_value < 0)) {
            alert(App.lang('Counter value can only be a zero or a positive number'));
        } else {
        	span_wrapper.find('strong').hide();
        	span_wrapper.prepend('<img src="' + App.data.indicator_url + '" alt="loading..." />');
        	
        	$.ajax({
              url : App.extendUrl(App.data.edit_counter_url, {async : 1 , counter_value : counter_value, counter_type : span_wrapper.attr("counter_type")}),
              type : 'GET',
              success : function (data) {
                span_wrapper.find('img').remove();
                span_wrapper.find('strong').show().html(counter_value);
                switch (span_wrapper.attr("counter_type")) {
                  case '0':
                    App.data.pattern_variables[":invoice_in_total"] = parseInt(counter_value,10);
                    break;
                  case '1':
                    App.data.pattern_variables[":invoice_in_year"] = parseInt(counter_value,10);
                    break;    
                  case '2':
                    App.data.pattern_variables[":invoice_in_month"] = parseInt(counter_value,10);
                    break;
                } //switch
                pattern_input.change(do_the_preview);
                pattern_input.change();
              },
              error : function () {
              	span_wrapper.find('img').remove();
              	span_wrapper.find('strong').show();
              	return false;
              }
            });
          } // if
      });
      
      pattern_input.change(do_the_preview).keyup(do_the_preview);
      pattern_input.change();
    });
  }
};



/** File: modules/calendar/javascript/main.js **/

/**
 * Remember focused calendar cell ID
 */
jQuery.fn.calendarCurrentCellId = null;

/**
 * Focus single calendar cell
 */
jQuery.fn.calendarFocusCell = function() {
  var cell = $(this);
  var link = cell.find('div.day_num a');
  var details = cell.find('div.day_details');
  
  cell.addClass('zoomed');
          
  cell.find('div.day_brief').hide();
  
  if(details.children().length) {
    details.show();
  } else {
    details.show();
    details.append('<img src="' + App.data.assets_url + '/images/indicator.gif" class="indicator" alt="Working..." />');
    details.load(App.extendUrl(link.attr('href'), { skip_layout : 1 }), function() {
      details.find('a').click(function(e) {
        e.stopPropagation();
        return true;
      });
    });
  } // if
};

/**
 * Unfocus calendar cell
 */
jQuery.fn.calendarUnfocusCell = function() {
  var cell = $(this);
  
  cell.removeClass('collapsed').removeClass('zoomed');
  
  cell.find('div.day_brief').show();
  cell.find('div.day_details').hide();
};

/**
 * Attach calendar behavior to DOM
 */
$(document).ready(function() {
  $('#calendar td.day_cell').click(function() {
    var cell = $(this);
    var table = cell.parent().parent().parent();
    
    if(jQuery.fn.calendarCurrentCellId) {
      if(cell.attr('id') == jQuery.fn.calendarCurrentCellId) {
        table.find('td.day_cell').removeClass('collapsed').removeClass('zoomed');
        cell.calendarUnfocusCell();
        
        jQuery.fn.calendarCurrentCellId = null;
      } else {
        $('#' + jQuery.fn.calendarCurrentCellId).calendarUnfocusCell();
        table.find('td.day_cell').addClass('collapsed').removeClass('zoomed');
        cell.calendarFocusCell();
        
        jQuery.fn.calendarCurrentCellId = cell.attr('id');
      }
    } else {
      table.find('td.day_cell').addClass('collapsed').removeClass('zoomed');
      cell.calendarFocusCell();
      
      jQuery.fn.calendarCurrentCellId = cell.attr('id');
    } // if
    
    return false;
  });
  
  $('#calendar td.day_cell a').click(function(e) {
    e.stopPropagation();
    location.href = $(this).attr('href');
  });
});

/** File: modules/autojoin/javascript/main.js **/

$(window).load(function () {

    App.data.join_url = App.data.url_base + '?path_info=joiner';

    // Jump to project button
    $('#join_button').click(function() {
        App.ModalDialog.show('join_url', App.lang('Autojoin'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(App.data.join_url), {});
        App.ModalDialog.setWidth(560);
        return false;
    });
});

/** File: modules/milestones/javascript/main.js **/

App.milestones = {
  controllers : {},
  models      : {}
};

/**
 * Main milestones JS file
 */
App.milestones.controllers.milestones = {
  
  /**
   * Prepare stuff on reschedule form
   *
   * @param void
   * @return null
   */
  reschedule : function() {
    $(document).ready(function() {
      
      // Lets hide successive milestone. There must be a better way to do this 
      // but we'll leave it at this for now :)
      $('div.with_successive_milestones input[type=radio]').each(function() {
        if(this.checked && $(this).val() != 'move_selected') {
          $('div.with_successive_milestones div.successive_milestones').hide();
        }
      })
      
      // Click handler for action selectors
      $('div.with_successive_milestones input[type=radio]').click(function() {
        if($(this).val() == 'move_selected') {
          $('div.with_successive_milestones div.successive_milestones').show('fast');
        } else {
          $('div.with_successive_milestones div.successive_milestones').hide('fast');
        }
      });
    });
  }
  
}

/** File: modules/status/javascript/main.js **/

App.status = {
  controllers     : {},
  models          : {},
  msg_max_length  : 255,
  check_length    : function(status) {
    var left = App.status.msg_max_length - status.val().length;
    var status_counter = status.parent().find('.status_counter');
    if (left < 0) {
      left = 0;
      status.val(status.val().substring(0, App.status.msg_max_length));
      status_counter.animate({"color":"red"}, "fast");
      status_counter.animate({"color":"#333"}, "fast");
    }
    status_counter.text(App.lang("Characters left") + ": " + left);
  }
};

/**
 * Status update client side behaviour
 */
App.status.controllers.status = { 
  
  /**
   * Index page bahaviour
   */   
  index : function () {
    $(document).ready(function() {
      $('#select_user').change(function() {
        $("#status_update_archive_work_indicator").show();
        window.location = $(this).val();
      });
    });
  },
  
  /**
   * View status message page behavior
   */
  view : function() {
    $(document).ready(function() {
      var initial_status_message_reply = App.lang('Type your reply and hit Enter to post it');
      $('#status_update_details tr.status_update_reply').each(function() {
        var row = $(this);
        
        row.find('td.message textarea').each(function() {
          var status_message_reply = $(this).val(initial_status_message_reply);
          
          // Form
          status_message_reply.focus(function() {
            if(status_message_reply.attr('class').indexOf('focused') == -1) {
              status_message_reply.addClass('focused');
            } // if
            if(status_message_reply.val() == initial_status_message_reply) {
              status_message_reply.addClass('focused').val('');
            } // if
          }).blur(function() {
            if(status_message_reply.val() == '') {
              status_message_reply.removeClass('focused').val(initial_status_message_reply);
            } // if
          }).keydown(function(e) {
            if(e.keyCode == 13 && !status_message_reply.hasClass('in_processing')) {
              var status_message_reply_value = jQuery.trim(status_message_reply.val());
              if(status_message_reply_value) {
                status_message_reply.addClass('in_processing');
              
                $.ajax({
                  'url' : App.extendUrl(row.attr('reply_url'), { async : 1}),
                  type : 'POST',
                  data : {
                    'submitted' : 'submitted',
                    'reply[message]' : status_message_reply_value
                  },
                  success : function(response) {
                    row.before(response);
                    status_message_reply.removeClass('in_processing');
                    status_message_reply.val('')[0].focus();
                    status_message_reply.parent().find('.status_counter').text('');
                  },
                  error : function(response) {
                    status_message_reply.removeClass('in_processing');
                    status_message_reply.val(status_message_reply_value)[0].focus();
                    alert(App.lang('We are sorry, but system failed to save your status message. Please try again later.'));
                  }
                });
              } // if
            } // if
          }).keyup(function() {
            App.status.check_length($(this));
          });
        });
      })
    });
  }
  
};

/**
 * Update dialog behavior
 */
App.widgets.StatusUpdateDialog = function() {
  
  /**
   * Submit status update URL
   *
   * @param String
   */
  var submit_status_update_url;
  
  /**
   * Status messages table
   *
   * @var jQuery
   */
  var status_update_table;
  
  /**
   * Status updates table wrapper
   *
   * @var jQuery
   */
  var status_update_table_wrapper;
  
  /**
   * Empty new message textarea value
   *
   * @param jQuery
   */
  var initial_status_message = App.lang('Type your message and hit Enter to post it');
  
  /**
   * New status message textarea
   *
   * @var jQuery
   */
  var status_message;
  
  /**
   * Initialize single status update row
   *
   * @param jQuery row
   */
  var initialize_row = function(row) {
    row.find('td.message a.status_message_reply').click(function() {
      var textarea_row = row.find('td.message tr.status_update_reply_textarea');
      var link_row = row.find('td.message tr.status_update_reply_link');
      
      var reply_textarea = textarea_row.find('textarea').keydown(function(e) {
        if(e.keyCode == 13 && !reply_textarea.hasClass('in_processing')) {
          var value = jQuery.trim(reply_textarea.val());
          
          if(value) {
            reply_textarea.addClass('in_processing');
            submit_status_update(value, row.attr('status_update_id'), null, function() {
              reply_textarea.removeClass('in_processing');
            });
            
            return false;
          } // if
        }
      }).keyup(function() {
        App.status.check_length($(this));
      });
      
      link_row.hide();
      textarea_row.show().find('textarea').focus();
      
      return false;
    });
  };
  
  /**
   * Submit status update
   *
   * @param String submit_url
   * @param String text
   * @param Function on_success
   * @param Function on_error
   */
  var submit_status_update = function(text, reply_to_id, on_success, on_error) {
    $.ajax({
      url  : App.extendUrl(submit_status_update_url, { async : 1 }),
      type : 'POST',
      data : {
        'submitted' : 'submitted',
        'status[message]' : text, 
        'status[parent_id]' : reply_to_id
      },
      'success' : function(response) {
        var row = $(response);
        initialize_row(row);
        
        var status_update_id = row.attr('status_update_id');
        
        status_update_table.find('tr[status_update_id=' + status_update_id + ']').remove();
        
        status_update_table_wrapper.show().scrollTo(0);
        status_update_table.prepend(row);
        
        var counter = 1;
        status_update_table.find('tr.status_update').each(function() {
          var new_class = counter % 2 ? 'odd' : 'even';
          $(this).removeClass('odd').removeClass('even').addClass(new_class);
          counter++;
        });
        
        status_update_table.find('tr:first td').highlightFade();
        
        if(typeof(on_success) == 'function') {
          on_success();
        } // if
      },
      'error' : function(response) {
        if(typeof(on_error) == 'function') {
          on_error();
        } // if
        
        alert(App.lang('We are sorry, but system failed to save your status message. Please try again later.'));
      }
    });
  };
  
  // Public interface
  return {
    
    /**
     * Initalize status updates dialog
     *
     * @param String add_message_url
     */
    init : function(add_message_url) {
      submit_status_update_url = add_message_url;
      status_update_table = $("#status_updates_table tbody.first_level");
      status_update_table_wrapper = $("#status_updates_dialog div.table_wrapper");
      status_message = $('#status_updates_dialog #add_status_message textarea').val(initial_status_message);
      
      // Top links
      $('.status_update_top_links li a').hover(function () {
        $('li:eq(0)', $(this).parent().parent()).text($(this).attr('title'));
      }, function () {
        $('li:eq(0)', $(this).parent().parent()).text('');
      });
      
      status_update_table.find('tr.status_update').each(function() {
        initialize_row($(this));
      });
      
      // Form
      status_message.focus(function() {
        if(status_message.attr('class').indexOf('focused') == -1) {
          status_message.addClass('focused');
        } // if
        if(status_message.val() == initial_status_message) {
          status_message.addClass('focused').val('');
        } // if
      }).blur(function() {
        if(status_message.val() == '') {
          status_message.removeClass('focused').val(initial_status_message);
        } // if
      }).keydown(function(e) {
        if(e.keyCode == 13 && !status_message.hasClass('in_processing')) {
          var status_message_value = jQuery.trim(status_message.val());
          if(status_message_value) {
            status_message.addClass('in_processing');
            submit_status_update(status_message_value, null, function() {
              status_message.val('').focus();
              status_message.removeClass('in_processing');
              status_message.parent().find('.status_counter').text('');
            }, function() {
              status_message.val(status_message_value).focus();
              status_message.removeClass('in_processing');
            });
          } // if
          
          return false;
        } // if
      }).keyup(function() {
        App.status.check_length($(this));
      });
    }
  };
  
}();

$(document).ready(function() {
  
  // check if there are new messages
  var update_status_menu_badge_item = function () {
    var count_url = App.data.path_info_through_query_string ? 
      App.extendUrl(App.data.url_base, { path_info : 'status/count-new-messages' }) :
      App.data.url_base + '/status/count-new-messages';
    
    $.ajax({
      type: "GET",
      url: count_url,
      success : function (response) {
        App.MainMenu.setItemBadgeValue('status', 'main', response);
      }
    })
  } // update_status_menu_badge_item
  setInterval(update_status_menu_badge_item, 60000 * 3); 
  
  // init menu item button
  $('#menu_item_status a').click(function() {
    var status_update_url = App.extendUrl($(this).attr('href'), { 
      async : 1 
    });
    
    App.ModalDialog.show('status_updates', App.lang('Status Updates'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(status_update_url), {
      buttons : false,
      height : 405,
      width: 600
    });
    App.MainMenu.setItemBadgeValue('status', 'main', 0);
    return false;
  });
})


/** File: modules/assignments_plus/javascript/main.js **/

App.assignments_plus = {
  controllers : {},
  models      : {}
};

/**
 * Assignments controller behavior
 */
App.assignments_plus.controllers.assignments_plus = {
  
  /**
   * Assignments index page
   */
  index : function() {
    $(document).ready(function() {
    	
    	$('#assignments_plus_form_completed_on').hide();
    	if(($('#assignments_plus_form_status').val() != 'active')){
    		$('#assignments_plus_form_completed_on').show();
    	}	
    	
    	if(($('#assignments_plus_form_status').val() == 'active' || $('#assignments_plus_form_status').val() == 'all') && $('#assignments_plus_form_include #ticket').is(":checked") && App.data.is_tickets_plus_loaded){
			$('#assignment_form_workflow_status').show();
		} else {
			$('#assignment_form_workflow_status').hide();
		}
    	
    	// change into the status filter value
    	$('#assignments_plus_form_status').change(function() {
    		$('#assignment_form_workflow_status').hide();
    		if(($(this).val() == 'active' || $(this).val() == 'all') && $('#assignments_plus_form_include #ticket').is(":checked") && App.data.is_tickets_plus_loaded){
    			$('#assignment_form_workflow_status').show();
    		}
    		
    		if($(this).val() != 'active'){
    			$('#assignments_plus_form_completed_on').show();
    		} else {
    			$('#assignments_plus_form_completed_on').hide();
    		}
    			
    	});
    		
    	// change into the include type selection
    	$('#assignments_plus_form_include').change(function() {
    		$('#assignment_form_workflow_status').hide();
    		if(($('#assignments_plus_form_status').val() == 'active' || $('#assignments_plus_form_status').val() == 'all') && $('#assignments_plus_form_include #ticket').is(":checked") && App.data.is_tickets_plus_loaded){
    			$('#assignment_form_workflow_status').show();
    		}
    	});
    	
    	$('#toggle_runtime_filter').click(function() {
            $('#assignments_plus_filter_form').toggle('fast');
            return false;
         });
    	
    	$('.options').hide();    	
    	$('.assignment_row').hover(function() {
    		var id = $(this).attr('id'), row, options;
    		if (id.indexOf("option_") > 0) {
    			options = id;
    			row = id.substring(id.indexOf("option_"+1, id.length));
    		} else {
    			row = id;
    			options = 'option_' + id; 
    		}
    		if (row != "0") {
    			$('#'+row).addClass("hover_cls");
    			$('#'+options).show();
    		}
    	}, function() {
    		var id = $(this).attr('id'), row, options;
    		if (id.indexOf("option_") > 0) {
    			options = id;
    			row = id.substring(id.indexOf("option_"+1, id.length));
    		} else {
    			row = id;
    			options = 'option_' + id; 
    		}
    		$('#'+row).removeClass("hover_cls");
    		$('#'+options).hide();
    	});
    	
    	
    	// Show modal dialogs for details view and edit forms
    	$("#apIFrame").load(function() {
    		$('.ui-dialog-content .flash').remove();
    	    $('.ui-dialog-content').prepend($("#apIFrame").contents().find(".flash"));
    	});
    	
    	$("a[class='edit']").click(function(){
    		var url = App.extendUrl(this.href, {skip_layout: 1, async: 1});
    		App.ModalDialog.show('edit_assignment', App.lang('Edit'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(url, function() {
    			var form = $(".ui-dialog-content form");
    			form.attr('action', App.extendUrl(form.attr('action'), {skip_layout: 1, async: 1}));
    			form.attr('target', 'apIFrame');
    		}), {
                width : 870,
                height : 500
              });
    		return false;
    	});
    	$(".assignment_row .name a").click(function(){
    		var url = this.href, anchor = '';
    		if (url.indexOf("#") > 0) {
    			 anchor = url.substring(url.indexOf("#")+1, url.length);
    			 url = url.substring(0, url.indexOf("#"));
    		}
    		url = App.extendUrl(url, {skip_layout: 1, async: 1});
    		if (anchor != "") {
    			url = url + '#' + anchor;
    		}
    		App.ModalDialog.show('item_details', this.text, $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(url, function() {
    			$(".ui-dialog-content ul.object_options").hide();
    			$(".ui-dialog-content a").attr("target", "apdetails");
    			$(".ui-dialog-content form").attr("target", "apdetails");
    		}), {
                width : 800,
                height : 500
              });
    		return false;
    	});
    	
    	
    	// if there is no selection in first dropdown, it will disable second and third dropdown 
		if($('#group_by_1').val() == '' || $('#group_by_1').val() === undefined){
			$('#group_by_2').attr('disabled', 'disabled');
			$('#group_by_3').attr('disabled', 'disabled');
		}
		
		if($('#group_by_2').val() == '' || $('#group_by_2').val() === undefined){
			$('#group_by_3').attr('disabled', 'disabled');
		}
		
		// store summarize value in array
		var headings = App.data.group_by_options;

		if($('#group_by_1').val() != '' && $('#group_by_1').val() !== undefined) {
			 var selection1 = $('#group_by_1').val();
			 var selection2 = $('#group_by_2').val();
			 var selection3 = $('#group_by_3').val();
			 
			 $('#group_by_2 >option').remove();
			 $('#group_by_3 >option').remove();
			 
				 $.each(headings,function(key,value) {
					 if(key != selection1){
						 if(selection2 == key){
							 $('#group_by_2').append($('<option selected="selected"></option>').val(key).html(value));
					 
					 if(selection2 == '' || selection2 === undefined){
						 $('#group_by_3').attr('disabled', 'disabled');
						 $('#group_by_3').append($('<option selected="selected"></option>').val(key).html(value));
					 }
				 }else{
					 $('#group_by_2').append($('<option></option>').val(key).html(value));
					 if(selection3 == key){
						 $('#group_by_3').append($('<option selected="selected"></option>').val(key).html(value));
					 }else{
						 $('#group_by_3').append($('<option></option>').val(key).html(value));
						 }
					 }	 
				 }
			 });
		} // if something in summarize selects..

		// call this function on change event of an first summarize selection dropdown
		var summarizeByOne = function(){
			 $('#group_by_2').attr('value', '');
			 $('#group_by_3').attr('value', '');
			 
			 var selection = $('#group_by_1').val();
			 if(selection != '' && selection !== undefined)
			 {
				 $('#group_by_2').attr('disabled', '');
				 $('#group_by_2 >option').remove();
				 
				 $.each(headings,function(key,value){
					 if(key != selection){
						 $('#group_by_2').append($('<option></option>').val(key).html(value));
					 }	 
				 });
			 }else{
				 $('#group_by_2').attr('disabled', 'disabled');
				 $('#group_by_3').attr('disabled', 'disabled');
			 }
		};
	
		// call this function on change event of an second summarize selection dropdown
		var summarizeByTwo = function() {
			$('#group_by_3').attr('value', '');
		 
			 var selection1 = $('#group_by_1').val();
			 var selection2 = $('#group_by_2').val();
			 if(selection2 != '' && selection2 !== undefined)
			 {
				 	$('#group_by_3').attr('disabled', '');
				 	$('#group_by_3 >option').remove();
	            	$.each(headings,function(key,value){
		            	if(key != selection1 && key != selection2){
		            		$('#group_by_3').append($('<option></option>').val(key).html(value));
		            	}
	            	});
			 }else{
				 $('#group_by_3').attr('disabled', 'disabled');
				 $('#group_by_3').attr('value', '');
			 }	
		};
	
		 $('#group_by_1').change(function(){
			 summarizeByOne(); 
		 });
		 
		 
		 $('#group_by_2').change(function(){
			 summarizeByTwo();	 
		 });
    	
    	
      $('#assignments_filter_select select').change(function() {
        var filter_url = $(this).val();
        if(filter_url != location.href) {
          $(this).after(' ' + App.lang('Loading ...')).attr('disabled', 'disabled');
          location.href = filter_url;
        } // if
      });
      
      $('#assignments_filter_options a').hover(function() {
        $('#assignments_filter_options span.tooltip').text($(this).attr('title'));
      }, function() {
        $('#assignments_filter_options span.tooltip').text('');
      }); 
      
      $('#toggle_filter_details').click(function() {
    	  $('#assignments_plus_filter_form').toggle('fast');
        return false;
      });
      
      // Complete / Move to trash tasks
      $('#assignments a.complete_assignment, #assignments a.remove_assignment, #assignments a.reopen_assignment').click(function() {
        var link = $(this);
        var cls = link.attr('class');
        var url = link.attr('href');
        
        // Block additional clicks
        if(link[0].block_clicks) {
          return false;
        } else {
          link[0].block_clicks = true;
        } // if
        
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        $.ajax({
          url     : url,
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
        	 if(cls == 'complete_assignment') {
        		 var openUrl = url.replace('complete', 'open');
        		 link.attr('href', openUrl );
        		 link.attr('class', 'reopen_assignment');
        		 img.attr('src', App.data.assets_url + '/images/icons/checked.gif');
        		 link.parents('.assignment_row:first').addClass('completed');
        	 } else if(cls == 'reopen_assignment') {
        		 var completeUrl = url.replace('open', 'complete');
        		 img.attr('src', App.data.assets_url + '/images/icons/not-checked.gif');
        		 link.attr('class', 'complete_assignment');
        		 link.attr('href', completeUrl );
        		 link.parents('.assignment_row:first').removeClass('completed');
        	 } else if(cls == 'remove_assignment') {
        		 link.parents('.assignment_row:first').remove();
        	 }
        	 link[0].block_clicks = false;
          },
          error   : function() {
            img.attr('src', old_src);
            link[0].block_clicks = false;
          }
        });
        
        return false;
      });
      
      if (App.data.hide_ap_filters == true) {
  		$('#assignments_plus_filter_form').hide('fast');
  	  }
      
      // Live search
  	  $('.searchform .searchfield').keyup(function() {
		var search = $.trim($(this).val());
		if(search == ''){
			$('table.global_assignments *').parents('tr').show();
			$("table.global_assignments").parents('tr.heading0, tr.heading1, tr.heading2').show();
		} else {
			$('table.global_assignments *').parents('tr').hide();
		}
		
		$('table.global_assignments').unhighlight();
		$('table.global_assignments').highlight(search);
 		$("table.global_assignments span.highlight").parents('tr').show();
 		$('.empty_page').hide();
  	  });
    });
    
  }
  
}


jQuery.fn.unhighlight = function (options) {
    var settings = { className: 'highlight', element: 'span' };
    jQuery.extend(settings, options);

    return this.find(settings.element + "." + settings.className).each(function () {
        var parent = this.parentNode;
        parent.replaceChild(this.firstChild, this);
        parent.normalize();
    }).end();
};

jQuery.fn.highlight = function (words, options) {
    var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
    jQuery.extend(settings, options);
    
    if (words.constructor === String) {
        words = [words];
    }
    words = jQuery.grep(words, function(word, i){
      return word != '';
    });
    if (words.length == 0) { return this; };

    var flag = settings.caseSensitive ? "" : "i";
    var pattern = "(" + words.join("|") + ")";
    
    if (settings.wordsOnly) {
        pattern = "\\b" + pattern + "\\b";
    }
    var re = new RegExp(pattern, flag);
    
    return this.each(function () {
        jQuery.highlight(this, re, settings.element, settings.className);
    });
    
};

/** File: modules/documents/javascript/main.js **/

App.documents = {
	controllers : {},
	models      : {}
};

/**
 * Main files JS file
 */
App.documents.controllers.documents = {
	
	/**
   * Documents list page behavior
   */
	index : function() {
		
		$(document).ready(function() {
			$('.documents_table span.delete a').click(function() {
				var link = $(this);
				var wrapper = link.parent();
				var row = wrapper.parent().parent();
				var container = row.parent();
				
				/**
		     * Reindex table rows
		     */
		    var reindex_odd_even_rows = function() {
		      var counter = 1;
		      container.find('tr').each(function() {
		        var rows = $(this);
		        rows.removeClass('even').removeClass('odd');
		        if(counter % 2 == 1) {
		          rows.addClass('odd');
		        } else {
		          rows.addClass('even');
		        } // if
		        counter++;
		      });
		    } // reidex_table_rows
				
		    if(confirm(App.lang('Are you sure that you want to permanently delete this document?'))) {
					link.hide();
					wrapper.prepend('<img src="' + App.data.indicator_url  + '" alt="" />');
					
					$.ajax({
						url     : link.attr('href'),
						type    : 'POST',
						data    : {'submitted' : 'submitted'},
						success : function(response) {
							row.remove();
							reindex_odd_even_rows();
							
							if($('.documents_table tr').length < 1) {
								$('.documents_table').after('<p class="empty_page">' + App.lang('There are no documents to show.') + '</p>');
							} // if
						},
						error   : function() {
							link.show();
						}
					});
					
					return false;
				} // if
				
				return false;
			})
			
		$('.documents_table .pin a').click(function() {
				var link = $(this);
				var wrapper = link.parent();
				var row = wrapper.parent();
				var container = row.parent();
				
				/**
		     * Reindex table rows
		     */
		    var reindex_odd_even_rows = function() {
		      var counter = 1;
		      container.find('tr').each(function() {
		        var rows = $(this);
		        rows.removeClass('even').removeClass('odd');
		        if(counter % 2 == 1) {
		          rows.addClass('odd');
		        } else {
		          rows.addClass('even');
		        } // if
		        counter++;
		      });
		    } // reindex_table_rows
				
				link.hide();
				wrapper.prepend('<img src="' + App.data.indicator_url  + '" class="indicator" alt="" />');
				
				$.ajax({
					url     : App.extendUrl(link.attr('href'), { async : 1 }),
					type    : 'POST',
					data    : {'submitted' : 'submitted'},
					success : function(response) {
					if (link.is('.not_pinned')){
						container.prepend(row);
						row.highlightFade();
						row.find('img.indicator').remove();
						link.attr({
							'href'  : response
						}).show().find('img').attr({
							'src'   : App.data.pin_icon_url,
							'title' : App.lang('Unpin'),
							'alt'   : App.lang('Unpin')
						});
						link.removeClass('not_pinned').addClass('pinned')
					} else {
						container.append(row);
						row.highlightFade();
						row.find('img.indicator').remove();
						link.attr({
							'href'  : response
						}).show().find('img').attr({
							'src'   : App.data.unpin_icon_url,
							'title' : App.lang('Pin to top'),
							'alt'   : App.lang('Pin to top')
						});
						link.removeClass('pinned').addClass('not_pinned')
					}
						reindex_odd_even_rows();
					},
					error   : function() {
						link.show();
					}
				});
				
				return false;
			});
		});
	}
	
}

/**
 * Main files JS file
 */
App.documents.controllers.document_categories = {
	
	/**
   * Manage categories page behavior
   */
	index : function() {
		$(document).ready(function() {
			$('.common_table span.delete a').click(function() {
				var link = $(this);
				var wrapper = link.parent();
				var row = wrapper.parent().parent();
				var container = row.parent();
				
				/**
         * Reindex table rows
         */
        var reindex_odd_even_rows = function() {
          var counter = 1;
          container.find('tr').each(function() {
            var rows = $(this);
            rows.removeClass('even').removeClass('odd');
            if(counter % 2 == 1) {
              rows.addClass('odd');
            } else {
              rows.addClass('even');
            } // if
            counter++;
          });
        };
				
				if(confirm(App.lang('Are you sure that you want to delete this document category? You will also delete all documents belongs to category!'))) {
	        link.hide();
					wrapper.prepend('<img src="' + App.data.indicator_url  + '" alt="" />');
					
					$.ajax({
						url     : link.attr('href'),
						type    : 'POST',
						data    : {'submitted' : 'submitted'},
						success : function(response) {
							row.remove();
							reindex_odd_even_rows();
							
							if($('.documents_table tr').length < 1) {
								$('.documents_table').after('<p class="empty_page">' + App.lang('All document categories are deleted.') + '</p>');
							} // if
						},
						error   : function() {
							link.show();
						}
					});
				} // if
				
				return false;
			});
		});
	}, // index
	
	/**
   * Documents list inside category page behavior
   */
	view : function() {
		$(document).ready(function() {
			$('.documents_table span.delete a').click(function() {
				var link = $(this);
				var wrapper = link.parent();
				var row = wrapper.parent().parent();
				var container = row.parent();
				
				/**
         * Reindex table rows
         */
        var reindex_odd_even_rows = function() {
          var counter = 1;
          container.find('tr').each(function() {
            var rows = $(this);
            rows.removeClass('even').removeClass('odd');
            if(counter % 2 == 1) {
              rows.addClass('odd');
            } else {
              rows.addClass('even');
            } // if
            counter++;
          });
        };
				
        if(confirm(App.lang('Are you sure that you want to permanently delete this document?'))) {
					link.hide();
					wrapper.prepend('<img src="' + App.data.indicator_url  + '" alt="" />');
					
					$.ajax({
						url     : link.attr('href'),
						type    : 'POST',
						data    : {'submitted' : 'submitted'},
						success : function(response) {
							row.remove();
							reindex_odd_even_rows();
							
							if($('.documents_table tr').length < 1) {
								$('.documents_table').after('<p class="empty_page">' + App.lang('All files from this page are deleted.') + '</p>');
							} // if
						},
						error   : function() {
							link.show();
						}
					});
					
					return false;
        } // if
				
				return false;
			})
			
			$('.documents_table .pin a').click(function() {
				var link = $(this);
				var wrapper = link.parent();
				var row = wrapper.parent();
				var container = row.parent();
				
				/**
		     * Reindex table rows
		     */
		    var reindex_odd_even_rows = function() {
		      var counter = 1;
		      container.find('tr').each(function() {
		        var rows = $(this);
		        rows.removeClass('even').removeClass('odd');
		        if(counter % 2 == 1) {
		          rows.addClass('odd');
		        } else {
		          rows.addClass('even');
		        } // if
		        counter++;
		      });
		    } // reindex_table_rows
				
				link.hide();
				wrapper.prepend('<img src="' + App.data.indicator_url  + '" class="indicator" alt="" />');
				
				$.ajax({
					url     : App.extendUrl(link.attr('href'), { async : 1 }),
					type    : 'POST',
					data    : {'submitted' : 'submitted'},
					success : function(response) {
					if (link.is('.not_pinned')){
						container.prepend(row);
						row.find('img.indicator').remove();
						link.attr({
							'href'  : response
						}).show().find('img').attr({
							'src'   : App.data.pin_icon_url,
							'title' : App.lang('Unpin'),
							'alt'   : App.lang('Unpin')
						});
						link.removeClass('not_pinned').addClass('pinned')
					} else {
						container.append(row);
						row.find('img.indicator').remove();
						link.attr({
							'href'  : response
						}).show().find('img').attr({
							'src'   : App.data.unpin_icon_url,
							'title' : App.lang('Pin to top'),
							'alt'   : App.lang('Pin to top')
						});
						link.removeClass('pinned').addClass('not_pinned')
					}
						reindex_odd_even_rows();
					},
					error   : function() {
						link.show();
					}
				});
				
				return false;
			});
		});
	}
	
};

/**
 * Manage document categories behavior
 */
App.system.ManageDocumentCategories = function() {
  
  /**
   * Manage document categories tab used to initialize the popup
   *
   * This value is present only on pages where we have document categories tabs
   *
   * @var jQuery
   */
  var manage_document_categories_tab = false;
  
  /**
   * Initialize single document category table row
   *
   * @var jQuery
   */
  var init_row = function(row) {
    var table = row.parent().parent();
    
    // Rename document category
    row.find('td.options a.rename_document_category').click(function() {
      var link = $(this);
      
      // Block additional clicks
      if(link[0].block_clicks) {
        return false;
      } // if
      
      var row = link.parent().parent().addClass('renaming');
      var name_cell = row.find('td.name');
      var name_link = name_cell.find('a');
      
      // Remember start name and start URL
      var start_name = name_link.text();
      var start_url = name_link.attr('href');
      
      link[0].block_clicks = true;
      
      name_cell.empty();
      
      var input = $('<input type="text" />').val(start_name).appendTo(name_cell);
      var save_button = $('<button class="simple">' + App.lang('Save') + '</button>').appendTo(name_cell);
      
      input[0].focus();
      
      // Submission indicator
      var submitting_changes = false;
      
      /**
       * Do submit changes we made
       */
      var submit_changes = function() {
        if(submitting_changes) {
          return;
        } // if
        
        var new_document_category_name = jQuery.trim(input.val());
        if(new_document_category_name == '') {
          input[0].focus();
        } // if
        
        // Check if new document category name is already in use
        var name_used = false;
        table.find('td.name').each(function() {
          var current_row = $(this);
          if(current_row.attr('class').indexOf('renaming') == -1 && current_row.text() == new_document_category_name) {
            name_used = true;
            current_row.highlightFade();
          } // if
        });
        
        if(name_used) {
          return;
        } // if
        
        // And submit the request
        save_button.text(App.lang('Saving ...'));
        input.attr('disabled', 'disabled');
        submitting_changes = true;
        
        $.ajax({
          type : 'POST',
          url : App.extendUrl(link.attr('href'), { async : 1 }),
          data : {
            'submitted' : 'submitted',
            'category[name]' : new_document_category_name
          },
          success : function(response) {
            if(manage_document_categories_tab) {
              var document_category_id = row.attr('document_category_id');
              manage_document_categories_tab.parent().find('li').each(function() {
                if($(this).attr('document_category_id') == document_category_id) {
                  $(this).find('a span').text(response);
                } // if
              });
            } // if
            
            name_cell.empty().append($('<a></a>').attr('href', start_url).text(response));
            row.find('td').highlightFade();
            submitting_changes = false;
          },
          error : function() {
            name_cell.empty().append($('<a></a>').attr('href', start_url).text(start_name));
            submitting_changes = false;
            
            alert(App.lang('Failed to rename selected document category'));
          }
        });
        
        link[0].block_clicks = false;
      };
      
      /**
       * Cancel changes
       */
      var cancel_changes = function() {
        name_cell.empty().append($('<a></a>').attr('href', start_url).text(start_name));
        link[0].block_clicks = false;
      };
      
      // Input key handling
      input.keydown(function(e) {
        //e.stopPropagation(); // Don't close dialog!
      }).keypress(function(e) {
        switch(e.keyCode) {
          case 13:
            submit_changes();
            break;
          case 27:
            cancel_changes();
            break;
          default:
            return true;
        } // if
        
        e.stopPropagation();
        return false;
      });
      
      // Button click 
      save_button.click(function() {
        submit_changes();
      });
      
      return false;
    });
    
    // Delete document category
    row.find('td.options a.delete_document_category').click(function() {
      var link = $(this);
      
      // Block additional clicks
      if(link[0].block_clicks) {
        return false;
      } // if
      
      if(confirm(App.lang('Are you sure that you want to delete this document category? There is no undo for this operation!'))) {
        link[0].block_clicks = true;
        
        var row = link.parent().parent();
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : App.extendUrl(link.attr('href'), { async : 1 }),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
            if(manage_document_categories_tab) {
              var document_category_id = row.attr('document_category_id');
              manage_document_categories_tab.parent().find('li').each(function() {
                if($(this).attr('document_category_id') == document_category_id) {
                  $(this).remove();
                } // if
              });
            } // if
            
            row.remove();
            if(table.find('tr').length > 0) {
              reindex_even_odd_rows(table);
            } else {
              table.hide();
              $('#manage_document_categories_empty_list').show();
            } // if
          },
          error   : function() {
            img.attr('src', old_src);
          }
        });
      } // if
      
      return false;
    });
  };
  
  /**
   * Reindex table even odd rows
   *
   * @param jQuery wrapper
   */
  var reindex_even_odd_rows = function(table) {
    var counter = 1;
    table.find('tr').each(function() {
      var new_class = counter % 2 ? 'odd' : 'even';
      $(this).removeClass('odd').removeClass('even').addClass(new_class);
      counter++;
    });
  }
  
  // Public interface
  return {
    
    /**
     * Initialize manage document category popup
     *
     * @param String list_item_id
     */
    init : function(list_item_id) {
      manage_document_categories_tab = $('#' + list_item_id); // Remember manage document category tab!
      
      var link = manage_document_categories_tab.find('a');
      
      link.click(function() {
        var open_url = App.extendUrl(link.attr('href'), {
          skip_layout : 1,
          async : 1
        });
        
        App.ModalDialog.show('manage_document_categories_popup', App.lang('Manage Document Categories'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(open_url), {});
        return false;
      });
    },
    
    /**
     * Initialize document categoriess list behavior
     *
     * @param String wrapper_id
     */
    init_page : function(wrapper_id) {
      var wrapper = $('#' + wrapper_id);
      
      // New document categories implementation
      var form = wrapper.find('form');
      var new_document_category_input = form.find('input');
      var new_document_category_icon = form.find('img');
      
      var default_text = App.lang('New Document Category...');
      new_document_category_input.focus(function() {
        if(new_document_category_input.val() == default_text) {
          new_document_category_input.val('');
        } // if
      }).blur(function() {
        if(new_document_category_input.val() == '') {
          new_document_category_input.val(default_text);
        } // if
      }).val(default_text);
      
      // Submitting form indicator
      var submitting_new_document_category = false;
      
      // Click on + image
      new_document_category_icon.click(function() {
        if(!submitting_new_document_category) {
          form.submit();
        } // if
      });
      
      // Create new document category...
      form.submit(function() {
        if(submitting_new_document_category) {
          return false;
        } // if
        
        var new_document_category_name = jQuery.trim(new_document_category_input.val());
        if(new_document_category_name == '') {
          new_document_category_input[0].focus();
        } // if
        
        // Check if new document category name is already in use
        var name_used = false;
        wrapper.find('td.name').each(function() {
          var current_row = $(this);
          if(current_row.text() == new_document_category_name) {
            name_used = true;
            current_row.highlightFade();
          } // if
        });
        
        if(name_used) {
          return false;
        } // if
        
        var old_icon_url = new_document_category_icon.attr('src');
        
        submitting_new_document_category = true;
        new_document_category_input.attr('disabled', 'disabled');
        new_document_category_icon.attr('src', App.data.indicator_url);
        
        $.ajax({
          type : 'POST',
          url : App.extendUrl(form.attr('action'), { async : 1}),
          data : {
            'submitted' : 'submitted',
            'category[name]' : new_document_category_name
          },
          success : function(response) {
            $('#manage_document_categories_empty_list').hide();
            
            var new_row = $(response);
            var table = wrapper.find('table');
            
            table.append(new_row).show();
            init_row(new_row);
            reindex_even_odd_rows(table);
            
            new_row.find('td').highlightFade();
            
            new_document_category_input.attr('disabled', '').val('')[0].focus();
            submitting_new_document_category = false;
            new_document_category_icon.attr('src', old_icon_url);
            
            // Add to list of document category tabs
            if(manage_document_categories_tab) {
              var new_tab = $('<li><a><span></span></a></li>');
              
              new_tab.attr('document_category_id', new_row.attr('document_category_id'));
              
              var new_document_category_link = new_row.find('td.name a');
              new_tab.find('a').attr('href', new_document_category_link.attr('href'));
              new_tab.find('span').text(new_document_category_link.text());
              
              manage_document_categories_tab.before(new_tab);
            } // if
          },
          error : function() {
            submitting_new_document_category = false;
            new_document_category_input.attr('disabled', '');
            new_document_category_icon.attr('src', old_icon_url);
            
            alert(App.lang('Failed to create new document category ":name"', { 'name' :  new_document_category_name}));
          }
        });
        
        return false;
      });
      
      wrapper.find('table tr').each(function() {
        init_row($(this));
      }); 
    }
    
  };
  
}();

/** File: modules/tickets_merge/javascript/main.js **/

App.tickets_merge = {
  controllers : {},
  models      : {}
};



App.tickets_merge.controllers.tickets_merge = {
    
    settings : function(){
        $(document).ready(function(){
            $(".remove").bind('click',function(){
                if($(this).val() == 0){
                    $('#remove_tickets').show();
                }else{
                    $('#remove_tickets').hide();
                }
            });

            $(".main_ticket").bind('click',function(){
                $("#error").remove();
                $(".main_ticket").removeClass('selected');
                $(this).addClass('selected');
                $("#remove_tickets").find("*").show();
                $('#remove_tickets_'+$(this).find('input').val()).hide();
            });

            $(".main_ticket").hover(
                function(){
                    $(this).addClass('hover');
                },
                function () {
                    $(".main_ticket").removeClass('hover');
                }
            );

            $('#form_merge_settings').submit(function(){

                if($("#list_main_tickets input:checked").val() == void 0){
                    $("#error").remove();
                    $(".quick_add_col_container").prepend('<p class="flash" id="error"><span class="flash_inner">Please select main ticket</span></p>');
                    return false;
                }

            });

        });
    }
};

App.widgets.tickets_merge = function(){


  return {
    /**
     * Open chats on sections
     *
     * @param object chats
     */
    merge : function(){
                    if($('#tickets').html()){ 
                        $('#tickets_action').append('<option></option><optgroup label="Tickets Merge"><option value=merge>' + App.lang('Merge') + '</option></optgroup>');
                        
                        $('#tickets_action').bind('change',function(){
                            if($(this).find('option:selected').val() == 'merge'){
                                var url = $('.container #page_tab_overview a').attr('href') + '/tickets_merge';
                                $('#tickets form')/*.attr('action',url)*/.attr('onSubmit','return false;');
                                $('#mass_edit button').bind('click',function(){
                                    tickets = $('.tickets_list li .right_options .input_checkbox:checked');
                                    if(tickets.length>1){
                                        param = '';
                                        for(var i=0;i<tickets.length;i++){
                                            param += 'tickets['+i+']='+tickets[i].value + '&';
                                        }

                                        var url = App.data.path_info_through_query_string ?
                                                App.extendUrl(App.data.url_base, { path_info : 'projects/'+App.data.active_project_id+'/tickets_merge_settings&'+param }) :
                                                App.data.url_base +  'projects/'+App.data.active_project_id+'/tickets_merge_settings?'+param;

                                        App.ModalDialog.show('tickets_merge', App.lang('Tickets Merge'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(url), {
                                          width : 700

                                        });
                                    }else{
                                        alert("Please select at least 2 tickets to merge!");
                                    }
                                });
                            }
                        });

        }
    },

    options : function(id){

        $('#project_object_options_page_action ul').append('<li class="subaction" id="merge_ticket"><a href="#">Merge</a></li>');

        $('#merge_ticket').click(function(){

            var url = App.data.path_info_through_query_string ?
                App.extendUrl(App.data.url_base, { path_info : 'projects/'+App.data.active_project_id+'/tickets_merge_settings&ticket_id='+id }) :
                App.data.url_base +  'projects/'+App.data.active_project_id+'/tickets_merge_settings?ticket_id='+id;

            App.ModalDialog.show('tickets_merge', App.lang('Ticket Merge'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(url), {
              width : 700,
              height : 500
            });

        });
    }
  }
}();

/** File: modules/estimated_time/javascript/main.js **/

$(window).load(function () {
	var loc = window.location.href;	
	if (loc.indexOf('projects') > 0 && ( (loc.indexOf('tickets') > 0) || (loc.indexOf('tasks') > 0) ) ) {
	} else {
		return;
	}	
	
	var locArr = null;
	if (loc.indexOf('path_info') > 0) {
		locArr = loc.split("%2F");
	} else {
		locArr = loc.split("/");
	}
	
	var start = 0;
	for (var i = 0; i < locArr.length; i++) {
		if (locArr[i].indexOf('projects') >= 0) {
			start = i;
			break;
		}
	}
	
	var pid = locArr[start + 2];
	var tid = locArr[start + 4];
	var estimatedTimeCallback = "/projects/estimatedtime?pid="+pid+"&tid="+tid;


	if (loc.indexOf('add') > 0) {
		$(".form_right_col").append('<div class="ctrlHolder">'+
			'<label for="estimatedTime">Estimated hours</label>'+
			'<input style="width:70px;" id="estimatedTime" type="text" value="" project="Object" name="ticket[estimated_time]"/>hh'+
			'</div>');
	} else if (loc.indexOf('edit') > 0) {
		$.getJSON(estimatedTimeCallback,
    function(data){
    	var time = 0;
    	if (data && data['time']) {
    		time = data['time'] / 3600;
    	}
        if (loc.indexOf('tickets') > 0) {
 			$(".form_right_col").append('<div class="ctrlHolder">'+
				'<label for="estimatedTime">Estimated hours</label>'+
				'<input style="width:70px;" id="estimatedTime" type="text" value="'+time+'" project="Object" name="ticket[estimated_time]"/>hh'+
				'</div>');
        }else{
      			$(".form_full_view").append('<div style="position:relative;margin-left:0px;margin-top:0px;">'+
				'<label style="font-size:10px;font-weight:bold;width:auto;display:block;float:none;" for="estimatedTime">Estimated hours</label>'+
				'<input style="width:70px;" id="estimatedTime" type="text" value="'+time+'" project="Object" name="ticket[estimated_time]"/>hh'+
				'</div>');
        }
    });
	} else if (tid) {
      var estimatedTimeTaskCallback = "";
      var allTasksTime = 0;
	  var i = 0;
	  var tasksCount = $("ul.tasks_table>li").length-1;
      $("ul.tasks_table>li").each(function(){
			task_id = $(this).attr('id').replace("task","");
			estimatedTimeTaskCallback = "/projects/estimatedtime?pid="+pid+"&tid="+task_id;
		  $.getJSON(estimatedTimeTaskCallback,
		  function(data){
			var time = 0;
			if (data && data['time']) {
				time = data['time'] / 3600;
			}
			allTasksTime = allTasksTime + time;
			if (time > 0) {
				$("#task"+data['tid']+">.task>.main_data>.details").append("| Estimated: "+time+" hours");
			}
			});
	  if(i>=tasksCount){
	  	$.getJSON(estimatedTimeCallback,
	  function(data){
		var time = 0;
		if (data && data['time']) {
			time = data['time'] / 3600;
		}
		if ((time > 0) || (allTasksTime>0)) {
			$("div.ticket>.body>.properties").append("<dt>Estimated Hour(s)</dt><dd>"+(time+allTasksTime)+" hours - "+time+" for the ticket and "+allTasksTime+" for tasks</dd>");
		}
			$("div.columns>.form_left_col>.due_date_and_priority").append('<div style="position:absolute;width:100px;text-align:right;padding-top:10px;margin-left:450px">'+
			'<label for="estimatedTime">Estimated hours</label>'+
			'<input style="width:70px" id="estimatedTime" type="text" value="" project="Object" name="task[estimated_time]"/>hh'+
			'</div>');
		});
	  }
	i++
	})

	}
});



/** File: modules/communications/javascript/main.js **/

App.communications = {
  controllers : {},
  models      : {}
};

App.communications.utilities = {
	activate_delete_handler : function() {
		  	$('tr.communication_reply_row').live("mouseover",function(event){
		  		$('td.message a.delete').hide();
		  		var id = this.id;
		  		var str =  "#" +id+ " a.delete ";
		  		$(str).show();
		  	});
		  	
		  	$('tr.communication_reply_row').live("mouseout",function(event){
		  		$('td.message a.delete').hide();
		  	});
		  },
    old_title : '',
    timeout_id : 0,
    showNotifications : false,
    startNotifications : function() {
			  this.showNotifications = true;
		  },
    silenceNotifications : function() {
			  clearInterval(this.timeout_id);
			  document.title = this.old_title;
			  this.showNotifications = false;
		  },
    notifyForUpdates : function() {
			    var msg = App.lang("New Message!");
			    clearInterval(this.timeout_id);
			    if (this.showNotifications == true) {
			    	this.playSound();
			    	this.timeout_id = setInterval(function() {
			    		document.title = document.title == msg ? App.communications.utilities.old_title : msg;
			  		}, 3000);
			    }
			},
		  
	  toggleSidebar : function(show) {
				var img_url = App.data.assets_url+'/modules/communications/images/';
				if (show == true) {
					$.cookie("comm_sidebar_toggle", true);
					$('#communication_sidebar').animate({marginRight: "0px"});
					$('#sidebar_toggle_image img').attr("src", img_url+"collapse.gif");
				} else {
					$.cookie("comm_sidebar_toggle", false);
					$('#communication_sidebar').animate({marginRight: "-25%"});
					$('#sidebar_toggle_image img').attr("src", img_url+"expand.gif");
					
				}
			},
	  playSound : function() {
				if("Audio" in window){
				  var a = new Audio();
				  var format = 'mp3';
				  if(!!(a.canPlayType && a.canPlayType('audio/ogg; codecs="vorbis"').replace(/no/, '')))
				    format = 'ogg';
				  else if(!!(a.canPlayType && a.canPlayType('audio/mpeg;').replace(/no/, '')))
				    format = 'mp3';
				  else if(!!(a.canPlayType && a.canPlayType('audio/mp4; codecs="mp4a.40.2"').replace(/no/, '')))
				    format = 'm4a';
				  else
				    format = 'mp3';

				  a.src = App.data.assets_url+'/modules/communications/audio/elysium.' + format;
				  a.play();
				}
			return;
		}
}
/**
 * Communications client side behaviour
 */
App.communications.controllers.communications = { 
  
  recent_message_timeout_id : undefined,
  initial_communication_message_reply : App.lang('Type your reply and hit Enter to post it'),
  last_reply_id : 0,
  last_message: '',
  communication_message_reply: null,
  checks_without_activity : 0,
  check_interval : 3000,
  current_check_interval : 3000,
  img_url : App.data.assets_url+'/modules/communications/images/',
  send_result_pending: false,
  
  /**
   * Index page bahaviour
   */   
  index : function () {
    $(document).ready(function() {
    	// Filter communication messages by user and date 
  		var reloadMessages = function() {
  	 		$("#communication_archive_work_indicator").show();
  	 		var userId = $('#select_user').val();
  	 		var period =  $('#select_period').val();
  	 		var url;
  	 		
  	 		if(App.data.active_project_id){
  	 			url = App.data.path_info_through_query_string ? 
  	  	 		      App.extendUrl(App.data.communications_url, { user_id : userId, period: period, project_id : App.data.active_project_id}) :
  	  	 		      App.data.communications_url + '?user_id='+userId+'&period='+period+'&project_id='+App.data.active_project_id;
  	 		}else{
  	 			url = App.data.path_info_through_query_string ? 
  	 		      App.extendUrl(App.data.communications_url, { user_id : userId, period: period }) :
  	 		      App.data.communications_url + '?user_id='+userId+'&period='+period;
  	 		}     
  	 		window.location = url;
  	 	};
  	 	$('#select_user').change(reloadMessages);
  	 	$('#select_period').change(reloadMessages);
    });
  },
  
  add_or_edit : function () {
	  $(document).ready(function() {
		  
		  if($('input[name=communication[participants_selection]]:checked').val() == 'project'){
			  $('#select_participants').hide();
		  }else if($('input[name=communication[participants_selection]]:checked').val() == 'select'){
			  $('#select_project').hide();
		  }else{
			  $('#select_project').hide();
			  $('#select_participants').hide();
		  }
		  
		  $('#project_select').click(function() {
			  $('#select_project').slideDown();
			  $('#select_participants').hide();
		  });
		  
		  $('#participants_select').click(function() {
			  $('#select_participants').slideDown('fast');
			  $('#select_project').hide();
		  });
		  
		  $('#everyone').click(function() {
			  $('#select_participants').hide();
			  $('#select_project').hide();
		  });
	  });
	  
  },
  
  add : function() {
	  this.add_or_edit();
  	},
  edit : function() {
  		this.add_or_edit();
	},
	
  submit_communication : function(message, attachment_id, row) {
		message = jQuery.trim(message);
		if( attachment_id == null && (this.last_message == message || message == "" || jQuery.trim(this.initial_communication_message_reply) == message)) {
			return;
		}
        if (attachment_id != null && message == jQuery.trim(this.initial_communication_message_reply)) {
        	message = '';
        }
    	// Find last reply id
    	if ($('#communication_details table.communication_replies tr').length > 0) {
            try {
            	this.last_reply_id = $('#communication_details table.communication_replies tr:last').attr('id').split('_')[2];
            } catch (e) {
            	return;
            }
    	} else {
    		this.last_reply_id = 0;
    	}
    	this.last_message = message;
    	App.communications.utilities.silenceNotifications();    
        row.find('#communication_reply').block();
        clearTimeout(this.recent_message_timeout_id);
        this.send_result_pending = true;
          $.ajax({
            'url' : App.extendUrl(row.attr('reply_url'), { async : 1}),
            type : 'POST',
            data : {
              'submitted' : 'submitted',
              'reply[message]' : message,
              'reply[last_reply_id]' : this.last_reply_id,
              'reply[inline_attachments][]' : attachment_id,
            },
            success : function(response) {
              row.find('#communication_reply').unblock();
              response = jQuery.trim(response);
	          if (response.substr(0, 3) == '<tr') {
	        	  $('#communication_details table.communication_replies').append(response);
	        	  window.scrollTo(0, document.body.scrollHeight);
	          }
              this.send_result_pending = false;
              App.communications.controllers.communications.communication_message_reply.val('')[0].focus();
              App.communications.controllers.communications.checks_without_activity = 0;
              App.communications.controllers.communications.current_check_interval = App.communications.controllers.communications.check_interval;
              clearTimeout(App.communications.controllers.communications.recent_message_timeout_id);
              App.communications.controllers.communications.recent_message_timeout_id = setTimeout(function() { App.communications.controllers.communications.get_recent_messages(); }, App.communications.controllers.communications.current_check_interval);
            },
            error : function(response) {
              row.find('#communication_reply').unblock();
              this.send_result_pending = false;
              App.communications.controllers.communications.communication_message_reply.val(message)[0].focus();
              alert(App.lang('We are sorry, but system failed to save your message. Please try again later.'));
            }
          });
	},
  
	
	 // Set a timeout for getting recent messages
    get_recent_messages : function() {
  	  // Find last reply id
  	  if ($('#communication_details table.communication_replies tr').length > 0) {
	         try {
	        	 this.last_reply_id = $('#communication_details table.communication_replies tr:last').attr('id').split('_')[2];
	            } catch (e) {
	            	return;
	         }
	      } else {
	    	  this.last_reply_id = 0;
	      }
  	  $.ajax({
          'url' : App.extendUrl(App.data.recent_communications_url, { async : 1}),
          type : 'POST',
          data : {
            'submitted' : 'submitted',
            'last_reply_id' : this.last_reply_id
          },
          success : function(response) {
            if (response != '') {
            	App.communications.controllers.communications.checks_without_activity = 0;
            	App.communications.controllers.communications.current_check_interval = App.communications.controllers.communications.check_interval;

            	// If result of a save is pending, we can discard result of recent messages
            	// since we will get recent messages in the save result itself
	          	if (this.send_result_pending) {
	          	 return;
	          	}
	          
	          response = jQuery.trim(response);
	          if (response.substr(0, 3) == '<tr') {
	        	  $('#communication_details table.communication_replies').append(response);
	        	  window.scrollTo(0, document.body.scrollHeight);
          	  
	        	  // Change the window title to notify the user
	        	  App.communications.utilities.notifyForUpdates();
	          }
          	  
            } else {
          	  // slow down request to the server if there is no activity
            	App.communications.controllers.communications.checks_without_activity++;
          	  if (App.communications.controllers.communications.checks_without_activity > 10) {
          		App.communications.controllers.communications.current_check_interval = (App.communications.controllers.communications.check_interval * Math.floor(App.communications.controllers.communications.checks_without_activity/5));
          	  }
            }
            clearTimeout(App.communications.controllers.communications.recent_message_timeout_id);
            App.communications.controllers.communications.recent_message_timeout_id = setTimeout(function() { App.communications.controllers.communications.get_recent_messages(); }, App.communications.controllers.communications.current_check_interval);
          },
          error : function(response) {
          	// doing nothing for now
          }
        });
    },
    
  /**
   * View communication message page behavior
   */
  view : function() {
    $(document).ready(function() {
      

	  // Set title for later use
	  App.communications.utilities.old_title = $(document).attr('title');
    	  
      $(window).bind('focusin', function(event) {
	  		App.communications.utilities.silenceNotifications();
	  });
      $(window).bind('focusout', function(event) {
	  		App.communications.utilities.startNotifications();
	  });
      
    	
      if ($('#print_preview_header').is(':visible') == false) {
    	  
    	  $('#sidebar_toggle_image').click (function () {
    		  App.communications.utilities.toggleSidebar(!($.cookie("comm_sidebar_toggle") == 'true'));
    	  });
    	  App.communications.utilities.toggleSidebar(($.cookie("comm_sidebar_toggle") == 'true'));
    	  
	      $('#communication_reply_box').width($("#page .container").width()-42);
	      $('#footer').fadeTo('fast', 0);
	      //$('#page_header_container').css('zIndex', 5);
	      window.scrollTo(0, document.body.scrollHeight);
	      $('#communication_sidebar').slideDown();
	      $('#communication_reply_box').slideDown('slow');
	      $('#communication_sidebar').css('zIndex', 10);
	      $('#communication_reply_box').css('zIndex', 100);
      }
      App.communications.utilities.activate_delete_handler();
      
      $('#file_picker').click(function(){
    	  App.ModalDialog.show('communications', App.lang('Upload a file'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(App.extendUrl(App.data.file_picker_url, { async : 1})), {
    	  });
      });
      
      App.communications.controllers.communications.recent_message_timeout_id = setTimeout(function() { App.communications.controllers.communications.get_recent_messages(); }, App.communications.controllers.communications.current_check_interval);
      
      $('#communication_reply_box').each(function() {
        var row = $(this);
        var send_message = function () {
        	var message = jQuery.trim(App.communications.controllers.communications.communication_message_reply.val());
        	App.communications.controllers.communications.submit_communication(message, null, row);
        };
        
        row.find('button').click( function() { 
        	send_message();
        });
        
        row.find('textarea').each(function() {
        	App.communications.controllers.communications.communication_message_reply = $(this).val(App.communications.controllers.communications.initial_communication_message_reply);
          // Form
        	App.communications.controllers.communications.communication_message_reply.focus(function() {
            if(App.communications.controllers.communications.communication_message_reply.attr('class').indexOf('focused') == -1) {
            	App.communications.controllers.communications.communication_message_reply.addClass('focused');
            } // if
            if(App.communications.controllers.communications.communication_message_reply.val() == App.communications.controllers.communications.initial_communication_message_reply) {
            	App.communications.controllers.communications.communication_message_reply.addClass('focused').val('');
            } // if
          }).blur(function() {
            if(App.communications.controllers.communications.communication_message_reply.val() == '') {
            	App.communications.controllers.communications.communication_message_reply.removeClass('focused').val(App.communications.controllers.communications.initial_communication_message_reply);
            } // if
          }).keydown(function(e) {
            if(e.keyCode == 13) {
            	send_message();
              } // if
            } // if
          );
        });
    });
  });
  }
};

/**
 * Update dialog behavior
 */
App.widgets.CommunicationsDialog = function() {
  
  /**
   * Submit communication update URL
   *
   * @param String
   */
  var submit_communication_url;
  
  /**
   * Status messages table
   *
   * @var jQuery
   */
  var communication_table;
  
  /**
   * Status updates table wrapper
   *
   * @var jQuery
   */
  var communication_table_wrapper;
  
  /**
   * Empty new message textarea value
   *
   * @param jQuery
   */
  var initial_communication_message = App.lang('Type your message and hit Enter to post it');
  
  /**
   * New communication message textarea
   *
   * @var jQuery
   */
  var communication_message;
  
  /**
   * Initialize single communication update row
   *
   * @param jQuery row
   */
  var initialize_row = function(row) {
    row.find('td.message a.communication_message_reply').click(function() {
      var textarea_row = row.find('td.message tr.communication_reply_textarea');
      var link_row = row.find('td.message tr.communication_reply_link');
      
      var reply_textarea = textarea_row.find('textarea').keydown(function(e) {
        if(e.keyCode == 13) {
          var value = jQuery.trim(reply_textarea.val());
          
          if(value) {
            reply_textarea.block();
            submit_communication(value, row.attr('communication_id'));
            
            return false;
          } // if
        } // if
      });
      
      link_row.hide();
      textarea_row.show().find('textarea').focus();
      
      return false;
    });
  };
  
  /**
   * Submit communication message
   *
   * @param String submit_url
   * @param String text
   * @param Function on_success
   * @param Function on_error
   */
  var submit_communication = function(text, reply_to_id, on_success, on_error) {
	  
	 
    $.ajax({
      url  : App.extendUrl(submit_communication_url, { async : 1 }),
      type : 'POST',
      data : {
        'submitted' : 'submitted',
        'communication[message]' : text, 
        'communication[parent_id]' : reply_to_id
      },
      'success' : function(response) {
        var row = $(response);
        if (!row.find('td.message')) {
        	return;
        }
        initialize_row(row);
        
        var communication_id = row.attr('communication_id');
        
        communication_table.find('tr[communication_id=' + communication_id + ']').remove();
        
        communication_table_wrapper.show().scrollTo(0);
        communication_table.prepend(row);
        
        var counter = 1;
        communication_table.find('tr.communication').each(function() {
          var new_class = counter % 2 ? 'odd' : 'even';
          $(this).removeClass('odd').removeClass('even').addClass(new_class);
          counter++;
        });
        
        communication_table.find('tr:first td').highlightFade();
        
        if(typeof(on_success) == 'function') {
          on_success();
        } // if
      },
      'error' : function(response) {
        if(typeof(on_error) == 'function') {
          on_error();
        } // if
        
        alert(App.lang('We are sorry, but system failed to save your communication message. Please try again later.'));
      }
    });
  };
  
  // Public interface
  return {
    
    /**
     * Initalize communication updates dialog
     *
     * @param String add_message_url
     */
    init : function(add_message_url) {
      submit_communication_url = add_message_url;
      communication_table = $("#communications_table tbody.first_level");
      communication_table_wrapper = $("#communications_dialog div.table_wrapper");
      communication_message = $('#communications_dialog #add_communication_message textarea').val(initial_communication_message);
      
      App.communications.utilities.activate_delete_handler();
      
      // Top links
      $('.communication_top_links li a').hover(function () {
        $('li:eq(0)', $(this).parent().parent()).text($(this).attr('title'));
      }, function () {
        $('li:eq(0)', $(this).parent().parent()).text('');
      });
      
      communication_table.find('tr.communication').each(function() {
        initialize_row($(this));
      });
      
      // Form
      communication_message.focus(function() {
        if(communication_message.attr('class').indexOf('focused') == -1) {
          communication_message.addClass('focused');
        } // if
        if(communication_message.val() == initial_communication_message) {
          communication_message.addClass('focused').val('');
        } // if
      }).blur(function() {
        if(communication_message.val() == '') {
          communication_message.removeClass('focused').val(initial_communication_message);
        } // if
      }).keydown(function(e) {
        if(e.keyCode == 13) {
          var communication_message_value = jQuery.trim(communication_message.val());
          if(communication_message_value) {
            $('#communications_dialog #add_communication_message').block();
            
            submit_communication(communication_message_value, null, function() {
              $('#communications_dialog #add_communication_message').unblock();
              communication_message.val('').focus();
            }, function() {
              $('#communications_dialog #add_communication_message').unblock();
              communication_message.val(communication_message_value).focus();
            });
          } // if
          
          return false;
        } // if
      });
    }
  };
  
}();


/*  Ading file for= inline file_picker: Malay*/
/**
 * Insert image editor widget
 */
App.widgets.EditorFilePicker = function() {
  /**
   * Editor instance
   */
  var editor_instance = null;
  
  /**
   * element in which editor is contained
   */
  var editor_container = null;
  
  /**
   * variable name for hidden fields
   */
  var hidden_input_variable_name = null;
  
  /**
   * disable image upload
   */
  var disable_image_upload = false;
  
  /**
   * Dialog container
   */
  var dialog_container;
  
  /**
   * cursor position
   */
  var cursor_position = null;
  
  // public interface
  return {
    
    /**
     * Initialize dialog
     */
    init : function (container_id) {      
      dialog_container = $(container_id +':first');
      
      dialog_container.find('.top_tabs a').click(function () {
        var anchor = $(this);
        anchor.parent().parent().find('li').removeClass('selected');
        anchor.parent().addClass('selected');
        dialog_container.find('.top_tabs_object_list>div').hide();
        dialog_container.find('.top_tabs_object_list #container_'+anchor.attr('id')).show();
        return false;
      });
      dialog_container.find('.top_tabs a:first').click();
      
      
      // upload image behaviour
      $('#upload_image_form').resetForm();
      $('#upload_image_form').submit(function () {
                      
        $('#upload_image_form').ajaxSubmit({
          url               : App.data.file_picker_url,
          type              : 'post',
          success           : function (response) {
        	
            //var jquery_response = $(response);
            var jquery_response = JSON.parse(response);
            
            //App.widgets.EditorFilePicker.update_editor(jquery_response.src, jquery_response.attachment_id);
            App.widgets.EditorFilePicker.update_editor(jquery_response);
             
          },
          error : function (response) {
            alert(response.statusText);
          }
        });
        return false;
      });
      
      $('#link_image_form').submit(function () {
        var image_url = $('#link_image_form').find('input[type=text]').val();
        if (image_url) {
          App.widgets.EditorFilePicker.update_editor(image_url);
        } // if
        return false;
      });
    },
    
    update_editor : function (file_data) {
    	var message = jQuery.trim(App.communications.controllers.communications.communication_message_reply.val());
    	App.communications.controllers.communications.submit_communication(message, file_data.attachment_id, $('#communication_reply_box'));
    	App.ModalDialog.close('communications');
    }
  }
}();

/*complete */






$(document).ready(function() {
  
  // check if there are new messages
  var update_communications_menu_badge_item = function () {
    var count_url = App.data.path_info_through_query_string ? 
      App.extendUrl(App.data.url_base, { path_info : 'communications/count-new-messages' }) :
      App.data.url_base + '/communications/count-new-messages';
    
    $.ajax({
      type: "GET",
      url: count_url,
      success : function (response) {
        App.MainMenu.setItemBadgeValue('communications', 'main', response);
      }
    })
  } // update_communications_menu_badge_item
  setInterval(update_communications_menu_badge_item, 60000 * 3); 
  
  // init menu item button
  $('#menu_item_communications a').click(function() {
    var communication_url = App.extendUrl($(this).attr('href'), { 
      async : 1 
    });
    
    App.ModalDialog.show('communications', App.lang('Communications'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(communication_url), {
      buttons : false,
      height : 400,
      width: 600
    });
    App.MainMenu.setItemBadgeValue('communications', 'main', 0);
    return false;
  });
    
})




/** File: modules/incoming_mail/javascript/main.js **/

App.incoming_mail = {
  controllers : {},
  models      : {}
};

/**
 * Incoming mail client side behaviour
 */
App.incoming_mail.controllers.incoming_mail_admin = { 
  /**
   * Archive page bahaviour
   *
   */
  index       : function () {
    $(document).ready(function() {
      $('#only_active_toggler').change(function() {
        var toggle_form = $(this).parents('form');
        var url = toggle_form.attr('action');
        var checkbox = toggle_form.find('.input_checkbox:checked');
        
        url = App.extendUrl(url, {only_problematic : checkbox.length})
        window.location = url;
      });
    });
  },
  
  add_mailbox : function () {    
    $(document).ready(function() {
      App.incoming_mail.AddEditForm.init('mailbox_form');
    });
  },
  
  edit_mailbox : function () {    
    $(document).ready(function() {
      App.incoming_mail.AddEditForm.init('mailbox_form');
    });
  },
  
  view_mailbox : function () {
    $(document).ready(function() {
      $('#only_active_toggler').change(function() {
        var toggle_form = $(this).parents('form');
        var url = toggle_form.attr('action');
        var checkbox = toggle_form.find('.input_checkbox:checked');
        
        url = App.extendUrl(url, {only_problematic : checkbox.length})
        window.location = url;
      });
    });
  }
};

/**
* Incoming mail frontend
*/
App.incoming_mail.controllers.incoming_mail_frontend = {
  index: function () {    
    $(document).ready(function() {
      
       $('.incoming_mails_table').checkboxes();
      
        $('.incoming_mails_table .import_button').click(function() {
          return true;
          var anchor = $(this);
          var init_import_form = function() {
            $('#import_form .submit_button').click(function () {
              $('#import_form').ajaxSubmit({
                success : function(response) {
                  $('#import_mail.dialog div.body > p').html(response);
                  anchor.parent().parent().addClass('imported_sucessfully');
                },
                error : function(response) {
                  if (response.status == 409) {
                    $('#import_mail.dialog div.body > p').html(response.responseText);
                  } // if
                  init_import_form();
                }
              });
              $('#import_mail.dialog div.body > p').html('<img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...'));
              return false;
            });
          };
          
          var dialog_url = App.extendUrl(anchor.attr('href'), { 
            skip_layout : 1, 
            async : 1 
          });
          
          App.ModalDialog.show('import_mail', App.lang('Import Email'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(dialog_url, function() {
            init_import_form();
          }), {
            buttons : false,
            width : 978,
            height: 350
          });
          return false;
        });
    });
  }
};

App.incoming_mail.importPendingEmailForm = function() {
  var form;
  return {
    init : function(form_id) {
      form = $('#'+form_id);
      
      // set project select box behaviour
      $('#project_id', form).change(function () {
        // var ajax_request_url = App.data.additional_fields_url + $(this).val() + '&user_id=' + $('#user_id', form).val() + '&object_type=' + $('#object_type', form).val();

        var ajax_request_url = App.extendUrl(App.data.additional_fields_url, {
          'skip_layout' : 1,
          'async' : 1,
          'project_id' : $(this).val(),
          'user_id' : $('#user_id', form).val(),
          'object_type' : $('#object_type', form).val()
        });
        
        $('#additional_fields_loader', form).text(App.lang('Loading')).load(ajax_request_url, null, function () {
          // set object type selector behaviour
          $('#object_type', form).change(function () {
            if ($(this).val() == 'comment') {
              $('#parent_id_block', form).show()
            } else {
              $('#parent_id_block', form).hide()
            } // if
          });
          
          if ($('#object_type', form).val() != 'comment') {
            $('#parent_id_block', form).hide()
          } // if
        });
      });
      
      // set object type selector behaviour
      $('#object_type', form).change(function () {
        if ($(this).val() == 'comment') {
          $('#parent_id_block', form).show()
        } else {
          $('#parent_id_block', form).hide()
        } // if
      });
      
      if ($('#object_type', form).val() != 'comment') {
        $('#parent_id_block', form).hide()
      } // if
    }
  };
}();

App.incoming_mail.AddEditForm = function() {
  return {
    init : function(wrapper_id) {
      var mailbox_form = $('#' + wrapper_id);
      var result_container = $('#test_connection .test_connection_results', mailbox_form);
      var result_image = $('img:eq(0)', result_container);
      var result_output = $('span:eq(0)', result_container);
      
      $('#test_connection button').click(function () {
        result_output.text('');
        result_image.attr('src', App.data.indicator_url);
        
        mailbox_form.ajaxSubmit({ 
          success:    function(response) {
            result_output.text(response);
            result_image.attr('src', App.data.ok_indicator_url);
            result_container.removeClass('connection_error');
            result_container.addClass('connection_ok');
          },
          error:      function(response) {
            result_output.text(response.responseText);
            result_image.attr('src', App.data.error_indicator_url);
            result_container.removeClass('connection_ok');
            result_container.addClass('connection_error');
          },
          url: App.data.test_mailbox_connection_url
        });
      });
      
      // Change port value when type is change and port value is empty or 
      // uses default value of other type
      var type_change_handler = function() {
        var port_field = $('#mailboxPort');
        
        if($(this).val() == 'POP3') {
          if(port_field.val() == '' || port_field.val() == '143') {
            port_field.val('110').parent().highlightFade();
          } // if
        } else {
          if(port_field.val() == '' || port_field.val() == '110') {
            port_field.val('143').parent().highlightFade();
          } // if
        } // if
      };
      
      $('#mailboxType').click(type_change_handler).change(type_change_handler);
    }
    
  };
  
}();

$(document).ready(function() {  
  // check if there are problematic incoming mails
  var update_incoming_mail_menu_badge_item = function () {
    var count_url = App.data.path_info_through_query_string ? 
      App.extendUrl(App.data.url_base, { path_info : 'incoming-mail/count-pending' }) :
      App.data.url_base + '/incoming-mail/count-pending';
      
    var inbox_url = App.data.path_info_through_query_string ? 
      App.extendUrl(App.data.url_base, { path_info : 'incoming-mail' }) :
      App.data.url_base + '/incoming-mail';
      
    var group_id = 'main';
    var menu_item_id = 'incoming_mail';
    
    $.ajax({
      type: "GET",
      url: count_url,
      success : function (response) {
        if (response > 0) {
         if (!App.MainMenu.itemExists(menu_item_id, group_id)) {
      	   App.MainMenu.addToGroup({
      	     label       : App.lang('Inbox'),
      	     href        : inbox_url,
      	     icon        : App.data.assets_url + '/modules/incoming_mail/images/icon_menu.gif',
      	     id          : menu_item_id,
      	     badge_value : response
      	   }, group_id);
         } else {
           App.MainMenu.setItemBadgeValue(menu_item_id, group_id, response);
         }
        } else {
          App.MainMenu.removeButton(menu_item_id, group_id);
        } // if
      } // if
    })
  } // update_incoming_mail_menu_badge_item
  
  setInterval(update_incoming_mail_menu_badge_item, 60000 * 3); 
});

/** File: modules/agreements/javascript/main.js **/

App.agreements = {
  controllers : {},
  models      : {}
};

/**
 * Main agreements JS agreement
 */
App.agreements.controllers.agreements = {
  
  /**
   * Index page behavior
   */
  index : function() {
    $(document).ready(function() {
      $('#agreement_list').checkboxes();
    });
  },
  
  /**
   * Initial agreement details page behavior
   */
  view : function() {
    $(document).ready(function() {
      $('div.agreement_revisions').each(function() {
        var wrapper = $(this);
        
        /**
         * Reindex table rows
         */
        var reindex_odd_even_rows = function() {
          var counter = 1;
          wrapper.find('tr').each(function() {
            var row = $(this);
            row.removeClass('even').removeClass('odd');
            if(counter % 2 == 1) {
              row.addClass('odd');
            } else {
              row.addClass('even');
            } // if
            counter++;
          });
        };
        
        wrapper.find('td.options a').click(function() {
          var link = $(this);
            
          // Block additional clicks
          if(link[0].block_clicks) {
            return false;
          } else {
            link[0].block_clicks = true;
          } // if
          
          var img = link.find('img');
          var old_src = img.attr('src');
          
          img.attr('src', App.data.indicator_url);
          
          $.ajax({
            url     : link.attr('href'),
            type    : 'POST',
            data    : {'submitted' : 'submitted'},
            success : function() {
              link.parent().parent().remove();
              reindex_odd_even_rows();
              if(wrapper.find('table tr').length < 1) {
                wrapper.find('div.body').append('<p class="details center agreements_moved_to_trash">' + App.lang('All revision moved to Trash') + '</p>');
              } // if
            },
            error   : function() {
              img.attr('src', old_src);
            }
          });
          
          return false;
        });
      });
    });
  },
  
  /**
   * Upload agreements behavior
   */
  upload : function() {
    var rows_for_upload = new Array();
    
    var current_row_id = 0;
    var current_row;
    
    var main_form;
    var upload_form;
    var upload_table;
    
    var summary_table;
    
    var uploads_ok = 0;
    var uploads_failed = 0;
    
    /**
     * function to call to submit multiupload form
     */
    var submit_multiupload_form = function () {
      agreement_id = 0;
      start_upload();
    };
    
    /**
     * Reindex table rows (set odd,even classes and add row #)
     */
    var reindex_table_rows = function () {
      var counter = 0;
      $('tr', upload_table).each(function () {
        row = $(this);
        if ((counter % 2) == 0 ) {
          row.attr('class', 'odd');
        } else {
          row.attr('class', 'even');
        } // if
        $('.number', row).text('#'+counter);
        counter++;
      });
    } // reindex_table_rows
    
    /**
    * Init row in upload table (add remove button functionality)
    */
    var init_multiupload_row = function (row) {
      if (row) {
        $('.button_remove', row).click(function () {
          if ($('tr', upload_table).length > 2) {
            $(this).parent().parent().remove();
            reindex_table_rows();
          } // if
        });
        $('td.description input:eq(0)' ,row).keydown(function(e) {
          if (e.keyCode == 13) {
            submit_multiupload_form();
            return false;
          } // if
        });
      } // if
    } // init_multiupload_row
    
    /**
     * set up hidden form for upload (based on curently selected row from upload table)
     * and do the upload
     */
    var upload_single_agreement = function () {
      var current_row = rows_for_upload[current_row_id];
      
      // if no more uploads are left, then do some stuff like showing upload statistics
      if (!current_row) {
        var params = {
          agreements_uploaded : uploads_ok,
          agreements_failed : uploads_failed
        }
        
        // form result message dependable of number failed and number of succeeded uploads
        if (uploads_ok && uploads_failed) {
          var upload_message = App.lang("Done, :agreements_uploaded agreements uploaded and :agreements_failed uploads failed<br />", params);
        } else if (uploads_ok) {
          var upload_message = App.lang("Done, :agreements_uploaded agreements uploaded<br />", params);
        } else {
          var upload_message = App.lang("Done, :agreements_failed uploads failed<br />", params);
        } // if
        
        // generates links for view agreements and for multiupload agreements
        var category_id = $("#multiupload_parent_id").val();
        var upload_more_agreements_url = main_form.attr('action');
        if (category_id) {
          var agreements_section_url = App.extendUrl(App.data.agreements_section_url, { 
            'category_id' :  category_id
          });
          upload_more_agreements_url = App.extendUrl(upload_more_agreements_url, { 
            'category_id' :  category_id
          });
        } else {
          var agreements_section_url = App.data.agreements_section_url;
        } // if

        upload_message += App.lang('Upload <a href=":upload_url">more agreements</a> or go back to <a href=":agreements_url">Agreements</a> section', {
          agreements_url : agreements_section_url,
          upload_url : upload_more_agreements_url
        });
  
        $('#page_content').append("<div class='important_block'>" + upload_message + "</div>");
        return true;
      } // if
      
      // remove input field from hidden form
      var previous_input = $("input[name=attachment]", upload_form);
      if (previous_input) {
        previous_input.remove();
      } // if
      
      // select current input
      var this_agreement_agreement = $("input:eq(0)", current_row);
      var this_agreement_body = $("input:eq(1)", current_row);
      
      // set progress indicator
      $("tr:eq(" + (current_row_id + 1) + ") img:eq(0)", summary_table).attr('src', App.data.indicator_url);
      
      // move agreement input from old form to new form (we cannot use clone() function because of jquery explorer bug)
      this_agreement_agreement.prependTo(upload_form);
      $('#multiupload_body').val(this_agreement_body.val());
            
      // submit current form
      upload_form.submit();
      current_row_id++;
      
      return false;
    } // upload_single_agreement
    
    /**
     * Start upload (copy selected common parameters from main form to hidden
     * upload form, and call upload function for first row from upload table
     */
    var start_upload = function () {
      main_form.hide();
      
      // create upload summary table      
      $('#page_content').append('<table id="upload_table_result" class="common_table"><tr><th></th><th colspan="2">' + App.lang('Uploading agreements') + '</th></tr></table>');
      summary_table = $('#upload_table_result');
      $('tr', upload_table).each(function () {
        var row = $(this);
        if ($('input',row).val()) {
          rows_for_upload.push(row);
          summary_table.append(
            '<tr>' +
              '<td class="indicator"><img alt="status" src="' + App.data.pending_indicator_url + '"</td>' +
              '<td class="agreementname">' + $('input',row).val() + '</td>' +
              '<td class="log"></div>' +
            '</tr>'
          );
        } // if
      });
      
      // set category and other stuff      
      $("#multiupload_parent_id").val($("#main_form #agreementParent").val());
      $("#multiupload_milestone_id").val($("#main_form #agreementMilestone").val());
      $("#multiupload_tags").val($("#main_form #agreementTags").val());
      
      $("#multiupload_visibility").val(1);
      
      var visiblity_field_1 = $("#main_form #agreementVisibility_1");
      
      // Checkbox?
      if(visiblity_field_1.attr('type') == 'radio') {
        if (visiblity_field_1[0].checked) {
          $("#multiupload_visibility").val(1);
        } else {
          $("#multiupload_visibility").val(0);
        } // if
        
      // Nope. Hidden
      } else {
        $("#multiupload_visibility").val(visiblity_field_1.val());
      } // if
      
      $('.people', upload_form).remove();
      
      $("#main_form .select_asignees_inline_widget .company_user input:checked").each(function () {
        upload_form.append("<input type='hidden' name='notify_users[]' class='people' value='" + $(this).val() + "' />");
      });
      upload_single_agreement();
    } // start_upload
    
    /**
     * set up basic stuff when page finishes loading
     */
    $(document).ready(function() {
      main_form = $('#main_form');
      upload_form = $('#multiupload_form');
      upload_table = $('.multiupload_table');
      
      // init table rows
      $('tr', upload_table).each(function () {
        init_multiupload_row($(this));
      });
      
      // add "new agreement" button handler
      $('.button_add', main_form).click(function () {
        image_src = $('tr:eq(1) .button_column img:eq(0)', upload_table).attr('src');
        upload_table.append(''+
        '<tr>' +
          '<td class="number"></td>' +
          '<td class="input"><input type="file" value="" name="attachment"/></td>' +
          '<td class="description"><input type="text" name="agreement[body]" /></td>' +
          '<td class="button_column"><img src="' + image_src + '" class="button_remove" /></td>' +
        '</tr>');
        init_multiupload_row(row.next());
        reindex_table_rows();
        return false;
      });
      
      // reindex table rows
      reindex_table_rows();
      
      // define upload_form behaviour
      upload_form.ajaxForm({ 
        success:    function(response) {
          /*
            because of wodoo magic with ajaxForm and agreement uploads, we can't use 
            error and success callbacks as we used to use them. In this special case
            error callback is called only when request is failed, not when server
            returns some of error headers, so we need to set up our serverside script
            to return strings 'error' when there is some http error, and string
            'success' if return is http ok.
          */
          if (response!=='success') {
            $("tr:eq(" + (current_row_id) + ") img:eq(0)", summary_table).attr('src', App.data.error_indicator_url);
            uploads_failed++;
          } else {
            $("tr:eq(" + (current_row_id) + ") img:eq(0)", summary_table).attr('src', App.data.ok_indicator_url);
            uploads_ok++;
          } // if
          upload_single_agreement();
        } ,
        error:      function() {
          $("tr:eq(" + (current_row_id) + ") img:eq(0)", summary_table).attr('src', App.data.error_indicator_url);
          uploads_failed++;
          upload_single_agreement();
        }
      });
      
      // upload button functionality
      $('#upload_agreements').click(function () {
        submit_multiupload_form();
      });
    });
    
  }
  
}

/** File: modules/syntaxhighlight/javascript/main.js **/

function include(filename, filetype, callbackfunction) {
	var _head = document.getElementsByTagName('head')[0];
	if(_head) {
		
		switch (filetype) {
			case 'js' :
				var _code = document.createElement('script');
					_code.setAttribute('type','text/javascript');
					_code.setAttribute('src', filename);
				break;
			
			case 'css' : 
				var _code = document.createElement('link');
					_code.setAttribute("rel", "stylesheet");
					_code.setAttribute('type','text/css');
					_code.setAttribute('href', filename);
				break;

			default:
				alert('Load of '+filetype+' is not supported');
		}
		
		if (callbackfunction !== undefined) {
			if (filetype === 'js') {
				var loadFunction = function() {
					if (this.readyState == 'complete' || this.readyState == 'loaded')	{
						callbackfunction(); 
					}
				};
				_code.onreadystatechange = loadFunction;
		
				_code.onload = callbackfunction;
			} else {
				alert('Callback function is supported only by javascript file loading.');
			}
		}
				
		_head.appendChild(_code);
	}
}

var supportedLanguages = new Array(23);
	supportedLanguages['as3']			=	'AS3';
	supportedLanguages['bash']			=	'Bash';
	supportedLanguages['coldfusion']	=	'ColdFusion';
	supportedLanguages['cpp']			=	'Cpp';
	supportedLanguages['csharp']		=	'CSharp';
	supportedLanguages['css']			=	'Css';
	supportedLanguages['delphi']		=	'Delphi';
	supportedLanguages['diff']			=	'Diff';
	supportedLanguages['erlang']		=	'Erlang';
	supportedLanguages['groovy']		=	'Groovy';
	supportedLanguages['java']			=	'Java';
	supportedLanguages['javafx']		=	'JavaFX';
	supportedLanguages['jscript']		=	'JScript';
	supportedLanguages['perl']			=	'Perl';
	supportedLanguages['php']			=	'Php';
	supportedLanguages['plain']			=	'Plain';
	supportedLanguages['powershell']	=	'PowerShell';
	supportedLanguages['python']		=	'Python';
	supportedLanguages['ruby']			=	'Ruby';
	supportedLanguages['scala']			=	'Scala';
	supportedLanguages['sql']			=	'Sql';
	supportedLanguages['vb']			=	'Vb';
	supportedLanguages['xml']			=	'Xml';

var loadSYH = function () {
	SyntaxHighlighter.config.clipboardSwf = App.data.assets_url+"/modules/syntaxhighlight/javascript/clipboard.swf";
	SyntaxHighlighter.config.stripBrs = true;

	include(App.data.assets_url+"/modules/syntaxhighlight/stylesheets/shCore.css","css");
	include(App.data.assets_url+"/modules/syntaxhighlight/stylesheets/shThemeDefault.css","css");			
	include(App.data.assets_url+"/modules/syntaxhighlight/javascript/shLegacy.js","js");	
	var _j = 1;
	
	for (var _lang in supportedLanguages) {
		if (supportedLanguages.length === _j) {
			//Load sytax highlighter only when all the files of the highlighter are loaded.
			//By that we prevent the "brush not found" alerts.
			var fn = function () { 
				SyntaxHighlighter.highlight(); 
			};
		}
		include(App.data.assets_url+"/modules/syntaxhighlight/javascript/shBrush"+supportedLanguages[_lang]+".js","js", fn);
		++_j;
	}

	$("div[class*='content']").each(function() {
		var htmlCode = $(this).html();
		var newdiv = $('<div/>');
		
			newdiv.html(htmlCode
				.replace(/<pre>\[syh:([a-z0-9]+)\]|\[syh:([a-z0-9]+)\]/img, '<pre class="brush: $1$2">')
				.replace(/<span><\/span>/img, '\t')
				.replace(/\[\/syh]/img, '</pre>')
			);

		var v_buffer = '';
		newdiv.find('pre').each(function() {
			$(this).find('p').each(function() {
				v_buffer += $(this).html();
				$(this).remove();
			});
			
			$(this).append(v_buffer);
		});
		$(this).html('').append(newdiv.html());
	});
	
	$('button[type=submit]').click(function () {
		try {
			tinyMCE.activeEditor.setContent(tinyMCE.activeEditor.getContent().replace(/<span style="white-space: pre;">(\s+)<\/span>/img, "$1"))
		} catch (e) {}
	});
	
	try {
		$('a.hidden_history').live('click', function() {
			$('blockquote:hidden').slideDown();
			$(this).remove();
			return false; 
		});
	} catch (e) { }
};

$(document).ready(function() {
	include(App.data.assets_url+"/modules/syntaxhighlight/javascript/shCore.js","js", loadSYH);
});

/** File: modules/source/javascript/main.js **/

App.source = {
  controllers : {},
  models      : {}
};

App.source.controllers.repository = {

  /**
  * Add repository
  */
  add : function() {
    $(document).ready(function() {
      App.source.AddEditForm.init();
    });
  },


  /**
  * Edit repository
  */
  edit : function() {
    $(document).ready(function() {
      App.source.AddEditForm.init();
    });
  },


  /**
  * History page behaviour
  */
  history : function() {
    $(document).ready(function() {

      $('tr.commit div.commit_files').hide(); // hide all paths on page load
      $('#toggle_all_paths span').text(App.lang('Show all paths')); // set initial text

      // show/hide one
      $('tr.commit').each(function() {
        var wrapper = $(this);

        wrapper.find('a.toggle_files').click(function() {
          wrapper.find('div.commit_files').toggle();
          return false;
        });
      }); // show/hide one


      $('#repository_delete_page_action').click(function() {
        return confirm(App.lang('Are you sure that you wish to delete this repository from activeCollab?'));
      });
      
      // show/hide all
      var toggle_new_class = null;
      var link_text = null;

      $('#toggle_all_paths').click(function() {
        var toggle_button = $(this);

        if (toggle_button.is('.hide')) {
          $('tr.commit div.commit_files').hide();
          link_text = App.lang('Show all paths');
          toggle_button.removeClass('hide');
          toggle_button.addClass('show');
        }
        else {
          $('tr.commit div.commit_files').show();
          link_text = App.lang('Hide all paths');
          toggle_button.removeClass('show');
          toggle_button.addClass('hide');
        }
        $('span', toggle_button).text(link_text);

        return false;
      }); //show/hide all


      // Update repository
      /*
      $('#repository_ajax_update, a.repository_ajax_update').click(function() {
        var delimiter = App.data.path_info_through_query_string ? '&' : '?';
        App.ModalDialog.show('repository_update', App.lang('Repository update'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Checking for updates...') + '</p>').load($(this).attr('href')+ delimiter + 'skip_layout=1&async=1'), {
          buttons : false,
          width: 400
        });
        return false;
      });
      */


    });

  }, // history

  update : function() {
    var progress_div = $('#repository_update_progress');
    
    var delimiter = App.data.path_info_through_query_string ? '&' : '?';
    
    var notify_subscribers = function(total_commits) {
      $('#progress_content').append('<p class="subscribers"><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Sending subscriptions...') + ' </p>');

      $.ajax({
        url: App.data.repository_update_url + delimiter + 'async=1&notify=' + total_commits,
        type: 'GET',
        success : function(response) {
          $('#progress_content p.subscribers img').attr({
          'src' : App.data.assets_url + '/images/ok_indicator.gif'
          });

          $('#progress_content p.subscribers').append(App.lang('Done!'));
        }
      });
    }

    var get_logs = function() {
      var progress_content = $('#progress_content');
      progress_content.html('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Importing commits</p>'));
      $.ajax( {
        url: App.data.repository_update_url + delimiter + '&async=1',
        type: 'GET',
        success : function(response) {
          // if starts with 'success', update step went ok
          if (response == 'success') {
            get_logs();
          }
          
          // update finished
          else if (response == 'finished') {
            progress_content.html('<p><img src="' + App.data.assets_url + '/images/ok_indicator.gif" alt="" /> '+ App.lang('Repository successfully updated') + '</p>');
            notify_subscribers(total_commits);
          }
          
          // update error
          else {
            progress_content.html(response); // if not success, reponse is a svn error message
          } // if
        }
      });
    }


    if (App.data.repository_uptodate == 1) {
      progress_div.html('<p><img src="' + App.data.assets_url + '/images/ok_indicator.gif" alt="" /> '+ App.lang('Repository is already up-to-date') + '</p>');
    }
    else {
      total_commits = App.data.repository_head_revision - App.data.repository_last_revision;

      if (total_commits > 0) {
        progress_div.prepend('<p>There are new commits, please wait until the repository gets updated to revision #'+App.data.repository_head_revision+'</p>');
        get_logs();
      }
      else {
        progress_div.prepend('<p>' + App.lang('Error getting new commits') + ':</p>');
      }
    }


  }, // update
  
  browse : function() {
    $(document).ready(function () {
      
      App.widgets.SourceFilePages.init();
      
      $('a.source_item_info').each(function() {
        var link_obj = $(this);
        link_obj.click(function() {         
          App.ModalDialog.show('item_info', App.lang('Item info'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Fetching data...') + '</p>').load(link_obj.attr('href')), {
            buttons : false,
            width: 700
          });
          return false;
        });
      }); // show/hide one      
    })
  }, // browse
  
  
  repository_users : function() {
    $(document).ready(function () {
      
      var select_box = $('#repository_user');
      
      $('table.mapped_users').find('a.remove_source_user').click(function() {
        if (confirm(App.lang('Are you sure that you wish to delete remove this mapping?'))) {
          var link = $(this);
  
          var img = link.find('img');
          var old_src = img.attr('src');
  
          img.attr('src', App.data.indicator_url);
  
          $.ajax({
            url     : App.extendUrl(link.attr('href'), {'async' : 1}),
            type    : 'POST',
            data    : {'submitted' : 'submitted', 'repository_user' : link.attr('name')},
            success : function(response) {
              if (response == 'true') {
                link.parent().parent().remove();
                select_box.append('<option value="'+link.attr('name')+'">'+link.attr('name')+'</option>');
                
                $('#all_mapped').hide();
                $('#no_users').hide();
                $('#new_record').show();
                
                if ($('#records tbody').children().length == 0) {
                  $('#records').hide();
                }
                
              } else {
                img.attr('src', old_src);
              }
            }
          });

        }
        
        return false;
      });
      
      
      
      var form = $('form.map_user_form');
      form.attr('action', App.extendUrl(form.attr('action'), { async : 1 }));

      form.submit(function() {
        if ($('#user_id').find('option:selected').val() == '') {
          alert(App.lang('Please select activeCollab user'));
          return false;
        }
        
        var form = $(this);
        
        $('#new_record td.actions').prepend('<img src="' + App.data.indicator_url + '" alt="" />').find('button').hide();
        
        $(this).ajaxSubmit({
            success: function(responseText) {
              $('#records tbody').prepend(responseText);
              $('#records').show();
              
              $('#new_record td.actions').find('img').remove();
              $('#new_record td.actions').find('button').show();
              
              var new_row = $('#records tbody tr:first');
              new_row.find('td').highlightFade();
              
              select_box.find('option:selected').remove();
              
              if (select_box.children().length == 0) {
                $('#new_record').hide();
                $('#all_mapped').show();
              }
            },
            error : function() {
              $('#new_record td.actions').find('img').remove();
              $('#new_record td.actions').find('button').show();
            }
        });
          
        return false;
      });
      
      
    });
  }
  
};

/**
* Javascript for source administration
*/
App.source.controllers.source_admin = {

  index : function () {
    $(document).ready(function () {
      var test_results_div = $(this).find('.test_results');
      var test_div = test_results_div.parent();
      test_results_div.prepend('<img class="source_results_img" src="" alt=""/>');
      $('.source_results_img').hide();
      
      $('#check_svn_path button:eq(0)').click(function () {
        $('.source_results_img').show();
        var svn_path = $('#svn_path').val();
        var indicator_img = $('.source_results_img');
        var result_span = test_div.find('.test_results span:eq(0)');
        indicator_img.attr('src', App.data.indicator_url);
        result_span.html('');
        $.ajax({
          type: "GET",
          data: "svn_path=" + svn_path,
          url: App.data.test_svn_url,
          success: function(msg){
        	if (jQuery.trim(msg)=='true') {
              indicator_img.attr('src', App.data.ok_indicator_url);
              result_span.html(App.lang('Subversion executable found'));
            } else {
              indicator_img.attr('src', App.data.error_indicator_url);
              result_span.html(App.lang('Error accessing SVN executable') + ': ' + msg);
            } // if
          }
        });

      });
    });
  }

};

/**
* Init JS functions for source file pages
*/
App.widgets.SourceFilePages = function () {
  return {
    init : function () {
      var delimiter = '&';
      
      $('#object_quick_option_compare a').click(function () {
        var compared_revision = parseInt(prompt(App.lang('Enter revision number'), ""));
        
        if (isNaN(compared_revision)) {
          alert(App.lang('Please insert a revision number'));
        } else {
          window.location = App.data.compare_url + delimiter + 'compare_to=' + compared_revision + 'peg=' + App.data.active_revision;
        } // if

        return false;
      });
      
      $('#change_revision').click(function () {
        var new_revision = parseInt(prompt(App.lang('Enter new revision number'), ""));

        if (isNaN(new_revision)) {
          alert(App.lang('Please insert a revision number'));
        } else {
          window.location = App.data.browse_url + delimiter + 'r=' + new_revision + delimiter + 'peg=' + App.data.active_revision;
        } // if

        return false;
      });
    }
  }
} ();


/**
* Test repository connection
*/
App.source.AddEditForm = function() {
  return {
    init : function () {
      var result_container = $('#test_connection .test_connection_results');
      var result_image = $('img:eq(0)', result_container);
      var result_output = $('span:eq(0)', result_container);

      $('#test_connection button').click(function () {
        result_output.html(App.lang('Checking...'));
        result_image.attr('src', App.data.indicator_url);

        if ($('#repositoryUrl').attr('value') == undefined) {
          result_image.attr('src', App.data.error_indicator_url);
          result_output.html(App.lang('You need to enter repository URL first'));
        }
        else {
          var delimiter = App.data.path_info_through_query_string ? '&' : '?';
          $.ajax( {
            url: App.data.repository_test_connection_url + delimiter + 'url=' + $('#repositoryUrl').attr('value') + '&user=' + $('#repositoryUsername').attr('value') + '&pass=' + $('#repositoryPassword').attr('value') + '&engine=' + $('#repositoryType option:selected').attr('value'),
            type: 'GET',
            success : function(response) {
              if (response == 'ok') {
                result_image.attr('src', App.data.ok_indicator_url);
                result_output.html(App.lang('Connection parameters are valid'));
              }
              else {
                result_image.attr('src', App.data.error_indicator_url);
                result_output.html(App.lang('Could not connect to repository:') + ' ' + response); // if not success, reponse is a svn error message
              }
            }
          });
        }
      });
    }
  };
} ();

/** File: modules/todo/javascript/main.js **/

App.todo = {
  controllers : {},
  models      : {}
};

/**
 * Tabinator Pro Admin controller client side behavior
 */
App.todo.controllers.Todo = {

  /**
   * Prepare dashboard index page
   */
  index : function(){
    $(document).ready(function(){
        //Input message
        
        $('#todo_text').keyup(function(){
            var val = $(this).val();
            var length = val.length;
            var message_length = App.data.todo_settings.general.message_length;
            if(length > message_length){
                $(this).val(val.substr(0,message_length));
                length = message_length;
            }
            $("#col_todo_text").html(message_length - length);
        });
        $("#todo_due_on").dpSetRenderCallback(function(){
            this.dpController.selectedDates = {};
        });
        // Add todo
        var options = {
            beforeSubmit:  function(arr, $form, options){
                options.url += '&async=true';
                for(i in arr){
                    if((arr[i].name == 'todo[text]' && arr[i].value.length < 3) || (arr[i].name == 'todo[due_on]' && arr[i].value != '' && !arr[i].value.match(/^\d{4}\/\d{1,2}\/\d{1,2}$/))){
                        $("input[name="+arr[i].name+"]").parent().addClass("error");
                        return false;
                    }
                }
                $('#todo_add_button').hide();
                $('#todo_text').after('<div class="todo_indicator"><img src="'+App.data.indicator_url+'" /></div>');
                $('.todo_table').prepend('<div class="todo_indicator"><img src="'+App.data.indicator_url+'" /></div>');
            },
            success: function(responseText, statusText, xhr, $form){
                        //remember category_id
                        category = $("#todo_category")
                        category_id = (category.val() == '') ? 0 : category.val();
                        
                        //reset fields
                        category.val('');
                        $("#todo_text").val('');
                        $("#todo_due_on").val('');
                        created_to_id = $('#todo_created_to_id').val();
                        if($("#todo_filter option[value="+created_to_id+"]").val() == void 0){
                            $("#todo_filter").append("<option value='"+created_to_id+"'>"+$('#todo_created_to_id option[value='+created_to_id+']').html()+"</option>");
                        }

                        //set form
                        $('#todo_created_to_id').val(App.data.active_user_id);
                        $('#todo_adv_opt_content select[name=todo_Hour],select[name=todo_Minute]').val('00');

                        //display
                        $('#col_todo_text').html(App.data.todo_settings.general.message_length);
                        $('#todo_text').parent().removeClass('error');
                        $('#todo_due_on').parent().removeClass('error');
                        $("#todo_adv_opt").html(App.lang('Advanced Options'));
                        $("#todo_adv_opt_content").fadeOut();
                        $('#todo_add_button').show();
                        $('.todo_indicator').remove();
                        $('.todo_empty_row').hide();
                        if($("#todo_filter").val() == created_to_id || $("#todo_filter").val() == 0){
                            $('.todo_table').prepend(responseText);
                        }

                        //count todo
                        count = $("#todo_categories li a[id="+category_id+"] .count");
                        count.html(count.html()*1+1);
                        App.widgets.todo.bind();
                        App.widgets.todo.scrol();
                        
                        
            },
            clearForm: false

        };
        $("#todo_form_add").ajaxForm(options);

        //Show advance option
        $("#todo_adv_opt").click(function(){
           adv_opt = $("#todo_adv_opt_content");
           if(adv_opt.is(':hidden')){
               $(this).html(App.lang('Hide Options'));
               adv_opt.fadeIn();
           }else{
               $(this).html(App.lang('Advanced Options'));
               adv_opt.fadeOut();
           }
           
           return false;
        });

        //Select new filter
        $('#todo_filter').change(function(){
           App.widgets.todo.show({
               'filter_cat':$("#todo_categories li.selected a").attr("id"),
               'filter_usr':$(this).val(),
               'is_archive':$("#todo_is_archive").val()
           });
           return false;
        });
        
        //archiv
        $("#todo_archiv").click(function(){

               if($("#todo_is_archive").val() == 0){
                   var is_archive = 1;
                   $(this).html(App.lang("Back"));
                   $("#todo_text").attr("disabled",true);
                   $("#todo_add_button").attr("disabled",true);
               }else{
                   $("#todo_text").attr("disabled",false);
                   $("#todo_add_button").attr("disabled",false);
                   var is_archive = 0;
                   $(this).html(App.lang("Archive")+'(<b class="count">0</b>)');
               }
               $("#todo_is_archive").val(is_archive);
               App.widgets.todo.show({
                   'filter_cat':$("#todo_categories li.selected a").attr("id"),
                   'filter_usr':$('#todo_filter').val(),
                   'is_archive':is_archive
               });
               return false;
        });
    });
  }

};

App.todo.controllers.TodoTicket = {

  move_to_ticket : function(){
      $(document).ready(function(){
          var step_1 = $('#quick_add_step_1');
          var step_2 = $('#quick_add_step_2');
          var todo_ticket_form = $("#todo_ticket_form");
          todo_ticket_form.find("#todo_ticket_project").change(function(){
              $("#todo_ticket_ticket").attr("disabled",true);
              var url = App.data.path_info_through_query_string ?
                        App.extendUrl(App.data.url_base, {path_info : 'todo/move_to_ticket/get_tickets/'+$(this).val()}) :
                        App.data.url_base + 'todo/move_to_ticket/get_tickets/'+$(this).val();
              $.ajax({
                  async: true,
                  url: url,
                  type: 'GET',
                  success: function(response){
                      $("#todo_ticket_ticket").html(response);
                      $("#todo_ticket_ticket").attr("disabled",false);
                  }
              });
          });

          todo_ticket_form.find(".quick_add_col_left .input_radio").click(function(){
              if($(this).val() == 'new'){
                  $("#todo_ticket_submit").hide();
                  $("#todo_ticket_continue").show();
                  $("#todo_ticket_ticket").attr('disabled',true);
              }else{
                  $("#todo_ticket_continue").hide();
                  $("#todo_ticket_submit").show();
                  $("#todo_ticket_ticket").attr('disabled',false);
              }
          });

          todo_ticket_form.find('.wizzard_back').click(function () {
              App.ModalDialog.close();
              $("#todo_categories .selected a").click();
              return false;
          });
         
          $("#todo_ticket_submit").click(function(){
              url = App.data.path_info_through_query_string ?
                    $('#todo_ticket_form').attr('action') + '&async=1' :
                    $('#todo_ticket_form').attr('action') + '?async=1' ;
                
              options = {
                  url : url,
                  beforeSubmit:function(){
                      step_1.before('<div class="todo_indicator"><img src="'+App.data.big_indicator_url+'" /></div>');
                      step_1.hide();
                  },
                  success: function(responseText, statusText, xhr, $form){
                      $("#quick_add .form_wrapper").prepend(responseText);
                      $("#quick_add").find('*').attr('disabled',true);
                      step_1.show();
                      $("#quick_add .todo_indicator").remove();
                  }
              };
              $("#todo_ticket_form").ajaxSubmit(options);
          });
          todo_ticket_form.find("#todo_ticket_continue").click(function(){
              project_id = todo_ticket_form.find('#todo_ticket_project').val();
              var url = App.data.path_info_through_query_string ?
                        App.extendUrl(App.data.url_base, {path_info : 'projects/'+project_id+'/tickets/quick-add&async=1'}) :
                        App.data.url_base + '/projects/'+project_id+'/tickets/quick-add?async=1';
                    
              $('#quick_add_step_1').hide();
              step_2.show();

              $.cookie('quick_add_object_type', 'ticket');
              preloader_string = '<div class="todo_indicator"><img src="'+App.data.big_indicator_url+'" /></div>';
              step_2.html(preloader_string);

              $.ajax({
                url : url,
                success : function (response) {
                  html = response.replace('App.ModalDialog.setWidth(850);','App.ModalDialog.setWidth(700);');
                  step_2.html(html);
                  var text = '';var post = {'submitted' : 'submitted'};
                  todos = $("#todo_ticket_form").find(".todo_ticket_move").each(function(){
                        text += $(this).val() + "\n";
                        id = $(this).attr('name').match(/(\d*)]$/)[1];
                        post['todo_move['+id+']'] = id;
                    });
                  $("#quick_add_ticket_body").html(text);
                  if (App.ModalDialog.isOpen) {
                    $('.ui-dialog .ui-dialog-titlebar span.ui-dialog-title').eq(1).html(App.lang('Quick Add :object_type in :project_name', {'object_type' : ucfirst('ticket'), 'project_name' : $('#todo_ticket_project option:selected').text()}));
                  } // if
                  App.todo.controllers.TodoTicket.init_object_form(post);
                  
                },
                error : function (response) {
                      $('#quick_add_step_1').show();
                      step_2.hide();
                }
              });
              return false;
          });
      });
  },

  init_object_form : function(post){
      
      var step_2 = $('#quick_add_step_2');
      preloader_string = '<div class="todo_indicator"><img src="'+App.data.big_indicator_url+'" /></div>';
      
      var object_form = step_2.find('form');
      object_form.find('input:first').focus();

      $("#quick_add .wizzard_back").click(function () {
          $('#quick_add_step_1').show();
          step_2.hide();
          $('.ui-dialog .ui-dialog-titlebar span.ui-dialog-title').eq(1).html(App.lang('ToDo-Ticket Options'));
          var dom_dialog = $('.ui-dialog').eq(1);
          var position = dom_dialog.position();
          var new_left_offset = position.left - ((600 - dom_dialog.width())/2);
          dom_dialog.css('width' , 600+'px').css('left', new_left_offset+'px');
          return false;
      });

      // flush behaviour
      step_2.find('.flash').click(function () {
        $(this).hide('fast');
      });

      object_form.submit(function () {
        step_2.find('.flash').hide();
        step_2.prepend(preloader_string);
        var preloader = $('#quick_add .todo_indicator');
        object_form.hide();

        object_form.ajaxSubmit({
          success : function (response) {
            html = response.replace('App.ModalDialog.setWidth(850);','App.ModalDialog.setWidth(700);');
            step_2.html(html);
            if(post instanceof Object){
                post['move_to'] = $('#quick_add_step_1 .quick_add_col_right .list_chooser input:checked').val();
                //work with todo
                var url = App.data.path_info_through_query_string ?
                          App.extendUrl(App.data.url_base, {path_info : 'todo/move/&async=1'}) :
                          App.data.url_base + 'todo/move/?async=1';

                $.ajax({
                    async : true,
                    url : url,
                    type : 'POST',
                    data : post
                });
            }
            $("#quick_add").find('*').attr('disabled',true);
            App.todo.controllers.TodoTicket.init_object_form();
          },
          error : function (response) {
            object_form.show();
            preloader.remove();
            alert(response.responseText);
          }
        });

        return false;
      });
  }

}

/**
 * Tabinator Pro Admin controller client side behavior
 */
App.todo.controllers.TodoCategories = {

  /**
   * Prepare dashboard index page
   */
  index : function(){

    var options = {
        beforeSubmit:  function(arr, $form, options){
            options.url += '&async=true';
            for(i in arr){
                if(arr[i].value == ''){
                    $("input[name="+arr[i].name+"]").parent().addClass("error");
                    return false;
                }
            }
            $('#todo_add_cat').hide();
            $('#todo_cat_name').after('<div class="todo_indicator"><img src="'+App.data.indicator_url+'" /></div>');
        },
        success: function(responseText, statusText, xhr, $form){
            $("#todo_manage_categories_empty_list").remove();
            $("#todo_categories_show").show();
            $('.manage_todo_categories_table_wrapper .common_table').append(responseText);
            $('#todo_categories li.selected').before();
            $('#todo_add_cat').show();
            $('.todo_indicator').remove();
            li = $('.manage_todo_categories_table_wrapper .common_table').find('tr:last');
            id = li.attr('id').match(/\d*$/);
            name = li.find('.name a').html();
            $("#todo_categories_manager").parent().before('<li><a href="#" id="'+id+'"><span>'+name+'(<b class="count">0</b>)</span></a></li>');
            $('#todo_manage_categories_empty_list').remove();
            App.widgets.todo.bind();
            $(".delete_todo_category").unbind('click').bind('click',del_cat);
        },
        clearForm: true

    };
    $("#todo_category_add").ajaxForm(options);

    var del_cat = function(){
       $(this).find('img').attr('src',App.data.indicator_url);
       url = App.data.path_info_through_query_string ? $(this).attr("href") + '&async=true' : $(this).attr("href") + '?async=true';
       $.ajax({
          async: true,
          url : url,
          type : 'GET',
          success : function(response) {
              if(response >= 1){
                cat_count = $('#todo_categories li a[id='+response+'] .count').html()*1;
                count = $('#todo_categories li a[id=0] .count');
                count.html(count.html()*1+cat_count);
                $('#todo_category_'+response).remove();
                $('#todo_categories li a#'+response).parent().remove();
                $('#todo_category option[value='+response+']').remove();
                if($(".manage_todo_categories_table_wrapper .common_table tbody tr").html() == void 0){
                    $(".manage_todo_categories_table_wrapper .common_table").after('<p class="empty_page" id="todo_manage_categories_empty_list">'+App.lang('There are no categories')+'</p>');
                    $("#todo_categories_show").hide();
                }
              }
          },
          error : function() {
            alert(App.lang('Failed to complate Todo. Please try again later.'));
          }
        });
        
        return false;
    };

    $(".delete_todo_category").bind('click',del_cat);
    
        
  }
};

App.todo.controllers.TodoAdmin = 

     {

      index:function(){
          $(document).ready(function(){
              $("#todo_general_notify_in_advanceNoInput").change(function(){
                  $(".todo_general_notify_time").hide();
              });
              $("#todo_general_notify_in_advanceYesInput").change(function(){
                  $(".todo_general_notify_time").show();
              });
              $("#todo_general_use_plannerYesInput").change(function(){
                  $(".todo_general_notify_in_advance").show();
                  if($("#todo_general_notify_in_advanceYesInput").is(":checked")){
                      $(".todo_general_notify_time").show();
                  }
              });
              $("#todo_general_use_plannerNoInput").change(function(){
                  $(".todo_general_notify_in_advance").hide();
                  $(".todo_general_notify_time").hide();
              });

              $('#todo_play').click(function(){
                  $(this).attr('src',App.data.indicator_url);
                  sound = $('#todo_sound').val();
                  App.widgets.todo.sound(1,sound);
                  return false;
              });
          });
      }
    }

App.todo.controllers.TodoModuleAdmin = {

    module : function(){

        $(document).ready(function(){
            $(".todo_permission_set").change(function(){
                role_id = $(this).attr("name").match(/\d/);
                value = $(this).val();
                var url = App.data.path_info_through_query_string ?
                          App.extendUrl(App.data.url_base, {path_info : 'todo/permission/set/'}) :
                          App.data.url_base + '/todo/permission/set/';
                var input = $(this);
                input.hide();
                $(this).after('<img class="todo_permission_indicator" src="'+App.data.indicator_url+'" />');

                url = App.data.path_info_through_query_string ? url += '&async=true' : url += '?async=false';

                var data = {'submitted' : 'submitted'};
                    data['todo_permission[role_id]'] = role_id;
                    data['todo_permission[value]'] = value;

                $.ajax({
                  async: true,
                  url : url,
                  data : data,
                  type : 'POST',
                  success : function(response) {
                      input.show();
                      $(".todo_permission_indicator").hide();
                  },
                  error : function(){
                    alert(App.lang('Failed to edit Permission. Please try again later.'));
                  }
                });
            });
        });

    }

}

App.widgets.todo = function(){


  return {
    /**
     * Open chats on sections
     *
     * @param object chats
     */
    initSideWidget : function(count,color){
        //$(document).ready(function(){
            if($('#todo_open').html() == void 0){

                var url = App.data.path_info_through_query_string ?
                      App.extendUrl(App.data.url_base, {path_info : 'todo/index'}) :
                      App.data.url_base + '/todo/index';
                if (count != 0) count = '<span class="badge">'+count+'</span>';
                else count = '';
                $("#page").before('<div id="todo" class="todo">\n\
                                    <div id="todo_open">\n\
                                        '+count+'\n\
                                        <a id="todo_open_button" href="'+url+'"><img src="'+App.data.assets_url+'/modules/todo/images/todo.png" /></a>\n\
                                    </div>\n\
                                   </div>');
                if(color != '')
                    $('#todo_open').css('background-color','#'+color);

                App.widgets.todo.init();
            }
       // });

    },

    initWelcomBox : function(count,url){
        $(document).ready(function(){
            if($("#todo_welcom_box").html() == void 0){
                if(count > 0 ) text = count;
                else text = '';
                $('#logged_user .inner a').eq(0).before(' <ul style=\"display:inline;padding:0px\" id=\"todo_module\"><li class=\"todos\" style=\"display:inline\"><a id="todo_welcom_box" href=\"'+url+'\">'+text+' ToDo</a></li></ul> | ');
                App.widgets.todo.init();
            }
        });
    },

    init: function(){
        $(document).ready(function(){
                    // init menu item button
                    $('#menu_item_todo a, #todo_open_button, #todo_welcom_box').click(function() {
                        var todo_url = App.extendUrl($(this).attr('href'), {
                          async : 1
                        });
                        App.ModalDialog.show('todo_window', App.lang('ToDo'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(todo_url), {
                          width : 700
                        });
                        return false;
                    });
        });
    },

    bind: function(){

        $(".complete_todo,.remove_todo").unbind('click').bind('click',function(){
           $(this).find('img').attr('src',App.data.indicator_url);
           category_id = $("#todo_categories .selected a").attr('id');
           complete = $(this).hasClass("complete_todo");
           
           $.ajax({
              async: true,
              url : $(this).attr("href"),
              type : 'GET',
              success : function(response) {
                  if(response >= 1){
                    $('#todo'+response).remove();
                    //count todos
                    count = $("#todo_categories li a[id="+category_id+"] .count");
                    count.html(count.html()*1-1);
                    if(complete){
                        count = $("#todo_archiv .count");
                        count.html(count.html()*1+1);
                    }
                    //
                    if($("#todo_move ul.todo_table").find('li').length == 0){
                        $(".todo_empty_row").show();
                    }else{
                        App.widgets.todo.scrol();
                    }
                  }
              }
            });
            return false;
        });

        //Select new category
        $('#todo_categories li a').unbind('click').bind('click',function(){
            if($(this).attr('id') != 'todo_categories_manager'){
               $('#todo_archiv').show();
               $('#todo_category').val($(this).attr('id'));
               $("#todo_filter").removeAttr("disabled");
               $('#todo_categories li').removeClass("selected");
               $(this).parent().addClass("selected");
               App.widgets.todo.show({
                   'filter_cat':$(this).attr("id"),
                   'filter_usr':$('#todo_filter').val(),
                   'is_archive':$("#todo_is_archive").val()
               });
            }
            return false;

        });

        //Categories manager
        $('#todo_categories_manager').click(function(){
               $('#todo_archiv').hide();
               $("#todo_filter").attr("disabled", true);
               $('#todo_categories li').removeClass("selected");
               $(this).parent().addClass("selected");
            var url = App.data.path_info_through_query_string ?
                      App.extendUrl(App.data.url_base, {path_info : 'todo/categories'}) :
                      App.data.url_base + '/todo/categories';

            $('.todo_body_conteiner .todo_col_left').html('<img src="'+App.data.big_indicator_url+'" />');

            url = App.data.path_info_through_query_string ? url += '&async=true' : url += '?async=true';

            $.ajax({
              async: true,
              url : url,
              type : 'GET',
              success : function(response) {
                    $('.todo_body_conteiner .todo_col_left').html(response);
              },
              error : function() {
                alert(App.lang('Failed to create new Todo. Please try again later.'));
              }
            });
           return false;
        });

        // Move to category (add delete&complete)
        var options = {
            beforeSubmit:  function(arr, $form, options){
                options.url = App.data.path_info_through_query_string ? options.url + '&async=true' : options.url + '?async=true';
                error = true;to_ticket = false;todo_ids = '';
                for(i in arr){
                    if(arr[i].name == 'move_to'){
                        if(arr[i].value == ''){
                            alert(App.lang('Select action'));
                            return false;
                        }
                        if(arr[i].value == 'to_ticket'){
                            to_ticket = true
                        }
                    }
                    if(arr[i].name.substr(0,9) == 'todo_move'){
                        todo_ids += '&' + arr[i].name + '=' + arr[i].value;
                        error = false;
                    }
                }

                if(error){
                    alert(App.lang('Please select at least one ToDo!'));
                    return false;
                }
                //move to ticket
                if(to_ticket === true){
                    var url = App.data.path_info_through_query_string ?
                              App.extendUrl(App.data.url_base, {path_info : 'todo/move/to_ticket&async=1'+todo_ids}) :
                              App.data.url_base + '/todo/move/to_ticket?async=1'+todo_ids;
                    App.ModalDialog.show('todo_ticket_window', App.lang('ToDo-Ticket Options'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(url), {
                      width : 600
                    });
                    return false;
                }
                
                $('button.simple#todo_submit').remove();
                $('#todo_action').after('<img src='+App.data.indicator_url+' />');
            },
            success: function(responseText, statusText, xhr, $form){
                if(responseText == 0){
                    $("#todo_categories li.selected a").click();
                }else{
                    $("#todo_categories li a[id="+responseText+"]").click();
                }
                
            },
            clearForm: true

        };
        $("#todo_move").ajaxForm(options);

        var edit_text = function(){
            $(".todo_edit").unbind('click');
            text = $(this).html();
            $(this).html("<input type='text' class='todo_edit_input' name='todo[text]' value='"+text+"'/>");
            $(this).keydown(send_text);
        }

        var send_text = function(event){
            if (event.keyCode == '13'){
                $("#todo_move").unbind('click');
                el = $(".todo_edit input");
                if(el != void 0){
                    text = el.val();
                    if(text != ''){
                        id = el.parent().attr("id");
                        text = text.replace(/[<]/g,'&lt;');
                        text = text.replace(/[>]/g,'&gt;');
                        el.parent().html(text);
                        $(".todo_edit").bind('click',edit_text);

                        var url = App.data.path_info_through_query_string ?
                                  App.extendUrl(App.data.url_base, {path_info : 'todo/edit/&async=true'}) :
                                  App.data.url_base + '/todo/edit/?async=true';

                        var post_data = {'submitted' : 'submitted'};
                        post_data['todo[text]'] = text;
                        post_data['todo[id]'] = id;

                        $.ajax({
                          async: true,
                          url : url,
                          data : post_data,
                          type : 'POST',
                          success : function(response) {

                          },
                          error : function() {
                            alert(App.lang('Failed to edit Todo. Please try again later.'));
                          }
                        });
                    }else{
                        $(".todo_edit_input").css("background-color","#FFE9E9");
                        return false;
                    }

                }
            }
        }

        //edit
        $(".todo_edit").bind('click',edit_text);

        
    },

    show: function(param){

      $(document).ready(function(){

        if(param == void 0){
            param = {'filter_cat' : 0, filter_usr : 0, archive:0};
        }
        if(param.filter_cat == void 0) param.filter_cat = 0;
        if(param.filter_usr == void 0) param.filter_usr = 0;
        if(param.is_archive == void 0) param.is_archive = 0;

        var url = App.data.path_info_through_query_string ?
                  App.extendUrl(App.data.url_base, {path_info : 'todo/show/'+param.filter_cat+'/'+param.filter_usr + '/' +param.is_archive}) :
                  App.data.url_base + '/todo/show/'+param.filter_cat+'/'+param.filter_usr + '/' +param.is_archive;

        $('.todo_body_conteiner .todo_col_left').html('<img src="'+App.data.big_indicator_url+'" />');

        url = App.data.path_info_through_query_string ? url += '&async=true' : url += '?async=false';

        $.ajax({
          async: true,
          url : url,
          type : 'GET',
          success : function(response) {
                $('.todo_body_conteiner .todo_col_left').html(response);
                $("#todo_categories li a .count").html('0');
                for(key in App.data.count){
                    $("#todo_categories li a[id="+key+"] .count").html(App.data.count[key]);
                }
                $("#todo_archiv .count").html(App.data.count['archive']);
                App.widgets.todo.scrol();

          },
          error : function() {
            alert(App.lang('Failed to create new Todo. Please try again later.'));
          }
        });
       
    });

    },

    scrol : function(){

        ul = $('.todo_body_conteiner .object_list .todo_table');
        scrol = $("#scrolling");
        if(ul.height() >= 300){
            scrol.css('overflow-y','scroll');
            scrol.css('height','300px');
        }else{
            scrol.css('overflow-y','hidden');
            scrol.css('height','auto');
        }

    },

    sound : function(timeout,track){
        
            setTimeout(function(){
                $("#todo_play").attr('src','/public/assets/images/arrow-right-small.gif');
            },2000);
            
            setTimeout(function(){
                
                sound = '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="1" height="1"';
                sound += '    codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab">';
                sound += '    <param name="movie" value="'+App.data.assets_url+'/modules/todo/mp3/singlemp3player.swf?file='+App.data.assets_url+'/modules/todo/mp3/'+track+'&backColor=990000&frontColor=ddddff&repeatPlay=false&songVolume=100&autoStart=true" />';
                sound += '   <param name="wmode" value="transparent" />';
                sound += '   <embed wmode="transparent" width="1" height="1" src="'+App.data.assets_url+'/modules/todo/mp3/singlemp3player.swf?file='+App.data.assets_url+'/modules/todo/mp3/'+track+'&backColor=990000&frontColor=ddddff&repeatPlay=false&songVolume=100&autoStart=true"';
                sound += '   type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" />';
                sound += '</object>';
                
                $("#footer").before(sound);
                
            },timeout);

    },

    calendar : function(cells){

        for (var id in cells) {
            cell = $("#"+id+" .day_brief");
            text = '';
            if(cell.html().trim().length == 0) text += '<ul>';
            text += "<li id=\"todo"+cells[id].id+"\">\n\
                        <span class=\"task\">\n\
                                <span class=\"option checkbox\">\n\
                                    <a class=\"complete_todo_on_cal\" href=\""+cells[id].complete_url+"\"><img alt=\"toggle\" src=\""+App.data.assets_url+"/images/icons/not-checked.gif\"></a></span>\n\
                                </span>\n\
                                <span class=\"main_data\">\n\
                                    <span class=\"todo_for_edit\">ToDo : "+cells[id].text+"</span>\n\
                                </span>\n\
                                <span class=\"option\" style=\"float:right\">\n\
                                    <a class=\"remove_todo_on_cal\" title=\"Remove\" href=\""+cells[id].delete_url+"\"><img alt=\"\" src=\""+App.data.assets_url+"/images/gray-delete.gif\"></a></span>\n\
                                </span>\n\
                        </span>\n\
                    </li>";
            if(cell.html().trim().length == 0) text += '</ul>';
            if(cell.html().trim().length != 0){
                cell.find("ul").html(cell.find("ul").html() + text);
            }else{
                cell.html(cell.html() + text);
            }
        }

        $(".complete_todo_on_cal,.remove_todo_on_cal").click(function(){

           $(this).find('img').attr('src',App.data.indicator_url);

           $.ajax({
              async: false,
              url : $(this).attr("href"),
              type : 'GET',
              success : function(response) {
                  if(response >= 1){
                    $('#todo'+response).remove();
                  }
              }
            });
            return false;

        })

    }

  }
}();
$(document).ready(function(){
    if(App.data.todo_init instanceof Object){

        if(App.data.todo_init.init == 1){
          App.widgets.todo.initSideWidget(App.data.todo_init.count, App.data.todo_init.color);
        }
        if(App.data.todo_init.init == 2){
          App.widgets.todo.initWelcomBox(App.data.todo_init.count, App.data.todo_init.url);
        }
        if(App.data.todo_init.init == 3){
          App.widgets.todo.init();
        }
    }
    if(App.data.todo_init_sound instanceof Object){
        App.widgets.todo.sound(App.data.todo_init_sound.timeout,App.data.todo_init_sound.track);
    }

    if(App.data.todo_init_calendar instanceof Object){
        App.widgets.todo.calendar(App.data.todo_init_calendar);
    }
});

/** File: modules/videos/javascript/main.js **/

App.videos = {
  controllers : {},
  models      : {}
};

/**
 * Main videos JS video
 */
App.videos.controllers.videos = {
  
  /**
   * Index page behavior
   */
  index : function() {
    $(document).ready(function() {
      $('#video_list').checkboxes();
    });
  },
  
  /**
   * Initial video details page behavior
   */
  view : function() {
    $(document).ready(function() {
      $('div.video_revisions').each(function() {
        var wrapper = $(this);
        
        /**
         * Reindex table rows
         */
        var reindex_odd_even_rows = function() {
          var counter = 1;
          wrapper.find('tr').each(function() {
            var row = $(this);
            row.removeClass('even').removeClass('odd');
            if(counter % 2 == 1) {
              row.addClass('odd');
            } else {
              row.addClass('even');
            } // if
            counter++;
          });
        };
        
        wrapper.find('td.options a').click(function() {
          var link = $(this);
            
          // Block additional clicks
          if(link[0].block_clicks) {
            return false;
          } else {
            link[0].block_clicks = true;
          } // if
          
          var img = link.find('img');
          var old_src = img.attr('src');
          
          img.attr('src', App.data.indicator_url);
          
          $.ajax({
            url     : link.attr('href'),
            type    : 'POST',
            data    : {'submitted' : 'submitted'},
            success : function() {
              link.parent().parent().remove();
              reindex_odd_even_rows();
              if(wrapper.find('table tr').length < 1) {
                wrapper.find('div.body').append('<p class="details center videos_moved_to_trash">' + App.lang('All revision moved to Trash') + '</p>');
              } // if
            },
            error   : function() {
              img.attr('src', old_src);
            }
          });
          
          return false;
        });
      });
    });
  },
  
  /**
   * Upload videos behavior
   */
  upload : function() {
    var rows_for_upload = new Array();
    
    var current_row_id = 0;
    var current_row;
    
    var main_form;
    var upload_form;
    var upload_table;
    
    var summary_table;
    
    var uploads_ok = 0;
    var uploads_failed = 0;
    
    /**
     * function to call to submit multiupload form
     */
    var submit_multiupload_form = function () {
      video_id = 0;
      start_upload();
    };
    
    /**
     * Reindex table rows (set odd,even classes and add row #)
     */
    var reindex_table_rows = function () {
      var counter = 0;
      $('tr', upload_table).each(function () {
        row = $(this);
        if ((counter % 2) == 0 ) {
          row.attr('class', 'odd');
        } else {
          row.attr('class', 'even');
        } // if
        $('.number', row).text('#'+counter);
        counter++;
      });
    } // reindex_table_rows
    
    /**
    * Init row in upload table (add remove button functionality)
    */
    var init_multiupload_row = function (row) {
      if (row) {
        $('.button_remove', row).click(function () {
          if ($('tr', upload_table).length > 2) {
            $(this).parent().parent().remove();
            reindex_table_rows();
          } // if
        });
        $('td.description input:eq(0)' ,row).keydown(function(e) {
          if (e.keyCode == 13) {
            submit_multiupload_form();
            return false;
          } // if
        });
      } // if
    } // init_multiupload_row
    
    /**
     * set up hidden form for upload (based on curently selected row from upload table)
     * and do the upload
     */
    var upload_single_video = function () {
      var current_row = rows_for_upload[current_row_id];
      
      // if no more uploads are left, then do some stuff like showing upload statistics
      if (!current_row) {
        var params = {
          videos_uploaded : uploads_ok,
          videos_failed : uploads_failed
        }
        
        // form result message dependable of number failed and number of succeeded uploads
        if (uploads_ok && uploads_failed) {
          var upload_message = App.lang("Done, :videos_uploaded videos uploaded and :videos_failed uploads failed<br />", params);
        } else if (uploads_ok) {
          var upload_message = App.lang("Done, :videos_uploaded videos uploaded<br />", params);
        } else {
          var upload_message = App.lang("Done, :videos_failed uploads failed<br />", params);
        } // if
        
        // generates links for view videos and for multiupload videos
        var category_id = $("#multiupload_parent_id").val();
        var upload_more_videos_url = main_form.attr('action');
        if (category_id) {
          var videos_section_url = App.extendUrl(App.data.videos_section_url, { 
            'category_id' :  category_id
          });
          upload_more_videos_url = App.extendUrl(upload_more_videos_url, { 
            'category_id' :  category_id
          });
        } else {
          var videos_section_url = App.data.videos_section_url;
        } // if

        upload_message += App.lang('Upload <a href=":upload_url">more videos</a> or go back to <a href=":videos_url">Videos</a> section', {
          videos_url : videos_section_url,
          upload_url : upload_more_videos_url
        });
  
        $('#page_content').append("<div class='important_block'>" + upload_message + "</div>");
        return true;
      } // if
      
      // remove input field from hidden form
      var previous_input = $("input[name=attachment]", upload_form);
      if (previous_input) {
        previous_input.remove();
      } // if
      
      // select current input
      var this_video_video = $("input:eq(0)", current_row);
      var this_video_body = $("input:eq(1)", current_row);
      
      // set progress indicator
      $("tr:eq(" + (current_row_id + 1) + ") img:eq(0)", summary_table).attr('src', App.data.indicator_url);
      
      // move video input from old form to new form (we cannot use clone() function because of jquery explorer bug)
      this_video_video.prependTo(upload_form);
      $('#multiupload_body').val(this_video_body.val());
            
      // submit current form
      upload_form.submit();
      current_row_id++;
      
      return false;
    } // upload_single_video
    
    /**
     * Start upload (copy selected common parameters from main form to hidden
     * upload form, and call upload function for first row from upload table
     */
    var start_upload = function () {
      main_form.hide();
      
      // create upload summary table      
      $('#page_content').append('<table id="upload_table_result" class="common_table"><tr><th></th><th colspan="2">' + App.lang('Uploading videos') + '</th></tr></table>');
      summary_table = $('#upload_table_result');
      $('tr', upload_table).each(function () {
        var row = $(this);
        if ($('input',row).val()) {
          rows_for_upload.push(row);
          summary_table.append(
            '<tr>' +
              '<td class="indicator"><img alt="status" src="' + App.data.pending_indicator_url + '"</td>' +
              '<td class="videoname">' + $('input',row).val() + '</td>' +
              '<td class="log"></div>' +
            '</tr>'
          );
        } // if
      });
      
      // set category and other stuff      
      $("#multiupload_parent_id").val($("#main_form #videoParent").val());
      $("#multiupload_milestone_id").val($("#main_form #videoMilestone").val());
      $("#multiupload_tags").val($("#main_form #videoTags").val());
      
      $("#multiupload_visibility").val(1);
      
      var visiblity_field_1 = $("#main_form #videoVisibility_1");
      
      // Checkbox?
      if(visiblity_field_1.attr('type') == 'radio') {
        if (visiblity_field_1[0].checked) {
          $("#multiupload_visibility").val(1);
        } else {
          $("#multiupload_visibility").val(0);
        } // if
        
      // Nope. Hidden
      } else {
        $("#multiupload_visibility").val(visiblity_field_1.val());
      } // if
      
      $('.people', upload_form).remove();
      
      $("#main_form .select_asignees_inline_widget .company_user input:checked").each(function () {
        upload_form.append("<input type='hidden' name='notify_users[]' class='people' value='" + $(this).val() + "' />");
      });
      upload_single_video();
    } // start_upload
    
    /**
     * set up basic stuff when page finishes loading
     */
    $(document).ready(function() {
      main_form = $('#main_form');
      upload_form = $('#multiupload_form');
      upload_table = $('.multiupload_table');
      
      // init table rows
      $('tr', upload_table).each(function () {
        init_multiupload_row($(this));
      });
      
      // add "new video" button handler
      $('.button_add', main_form).click(function () {
        image_src = $('tr:eq(1) .button_column img:eq(0)', upload_table).attr('src');
        upload_table.append(''+
        '<tr>' +
          '<td class="number"></td>' +
          '<td class="input"><input type="file" value="" name="attachment"/></td>' +
          '<td class="description"><input type="text" name="video[body]" /></td>' +
          '<td class="button_column"><img src="' + image_src + '" class="button_remove" /></td>' +
        '</tr>');
        init_multiupload_row(row.next());
        reindex_table_rows();
        return false;
      });
      
      // reindex table rows
      reindex_table_rows();
      
      // define upload_form behaviour
      upload_form.ajaxForm({ 
        success:    function(response) {
          /*
            because of wodoo magic with ajaxForm and video uploads, we can't use 
            error and success callbacks as we used to use them. In this special case
            error callback is called only when request is failed, not when server
            returns some of error headers, so we need to set up our serverside script
            to return strings 'error' when there is some http error, and string
            'success' if return is http ok.
          */
          if (response!=='success') {
            $("tr:eq(" + (current_row_id) + ") img:eq(0)", summary_table).attr('src', App.data.error_indicator_url);
            uploads_failed++;
          } else {
            $("tr:eq(" + (current_row_id) + ") img:eq(0)", summary_table).attr('src', App.data.ok_indicator_url);
            uploads_ok++;
          } // if
          upload_single_video();
        } ,
        error:      function() {
          $("tr:eq(" + (current_row_id) + ") img:eq(0)", summary_table).attr('src', App.data.error_indicator_url);
          uploads_failed++;
          upload_single_video();
        }
      });
      
      // upload button functionality
      $('#upload_videos').click(function () {
        submit_multiupload_form();
      });
    });
    
  }
  
}

/** File: modules/checklists/javascript/main.js **/

App.checklists = {
  controllers : {},
  models      : {}
};

/**
 * Project Exporter client side behaviour
 */
App.checklists.controllers.checklists = { 
  /**
   * Archive page bahaviour
   *
   */   
  index : function () {   
    $(document).ready(function() {
      $('td.expander a').click(function () {
        var anchor = $(this);
        var anchor_row = anchor.parents('tr:first');
        var anchor_image = anchor.find('img');
        var ajax_url = App.extendUrl(anchor.attr('href'), {show_only_tasks : 'true', async : 1})
        var checklist_tasks_row = anchor.parents('div.checklist').find('.tasks_container:first');
        
        if (anchor.is('.collapsed')) {
          anchor.removeClass('collapsed');
          anchor_row.removeClass('collapsed');
          anchor_image.attr('src', App.data.indicator_url);
          if (!checklist_tasks_row.html()) {
            $.ajax({
              url : ajax_url,
              success : function (response) {
                anchor.addClass('expanded');
                anchor_row.addClass('expanded');
                anchor_row.removeClass('collapsed');
                anchor_image.attr('src', App.data.expander_expanded);
                checklist_tasks_row.hide();
                checklist_tasks_row.html(response);
                checklist_tasks_row.slideDown();
              },
              error : function(response) {
                anchor_image.attr('src', App.data.expander_collapsed);
              }
            });
          } else {
            anchor.addClass('expanded');
            anchor_row.addClass('expanded');
            anchor_row.removeClass('collapsed');
            anchor_image.attr('src', App.data.expander_expanded);
            checklist_tasks_row.slideDown();
          } // if
        } else if (anchor.is('.expanded')) {
          anchor.addClass('collapsed');
          anchor_row.addClass('collapsed');
          anchor_row.removeClass('expanded');
          anchor_image.attr('src', App.data.expander_collapsed);
          checklist_tasks_row.slideUp();
        } // if
        return false;
      });
      
      if(App.data.can_manage_checklists) {
        $('#checklists .checklists_container').sortable({
          items: 'div.checklist',
          axis: 'y',
          distance: '3',
          handle: 'table:first',
          update: function (event, ui) {
            var ajax_data = {
              'submitted' : 'submitted'
            };
            
            var counter = 0;
            $('#checklists div.checklists_container div.checklist:not(.ui-sortable-placeholder)').each(function () {
              ajax_data['checklists[' + counter + ']'] = $(this).attr('checklist_id');
              counter++;
            });
            $.ajax({
              type : 'post',
              data : ajax_data,
              url : App.extendUrl(App.data.reorder_checklists_url, { async : 1 })
            })
          }
        });
        $('#checklists .checklists_container .checklist:not(.ui-sortable-placeholder) table').css('cursor', 'move');
      } // if
    });
  }
};

App.widgets.reorder_checklists = function() {
  var reorder_list;
  var reorder_form;

  return {
    init : function(list_id) {
      reorder_list = $('#' + list_id);
      reorder_form = reorder_list.parents('form');
      
      var list_container = $('#checklists .checklists_container:first');
      var list_prefix = 'checklist_';
      
      reorder_list.sortable({
        axis        : 'y'
      });
      
      reorder_form.find('.buttonHolder button').click(function () {
        reorder_form.block();
        reorder_form.ajaxSubmit({
          method  : 'post',
          url  : App.makeAsyncUrl(reorder_form.attr('action')),
          success : function (response) {
            reorder_form.find('input').each(function () {
              list_container.append($('#'+list_prefix+$(this).val()));
            });
            App.ModalDialog.close();
          },
          error : function (response) {
            reorder_form.unblock();
          }
        });
      });
    }
  }
}();



/** File: modules/chat/javascript/main.js **/

App.chat = {
  controllers : {},
  models      : {}
};

/**
 * Chat update client side behaviour
 */
App.chat.controllers.chat = {

  /**
   * Index page bahaviour
   */
  index : function () {
    $(document).ready(function() {
        $('#addprojectchat').click(function() {
            var url = App.data.path_info_through_query_string ?
                    App.extendUrl(App.data.url_base, { path_info : 'chat/add_project' }) :
                    App.data.url_base + '/chat/add_project';

            App.ModalDialog.show('add_project_chat', App.lang('Add Project Chat'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(url), {});
        });

        $('#chathistory').click(function() {
            chatId = $('#chat_sections ul .selected a').attr('id');
            var url = App.data.path_info_through_query_string ?
                    App.extendUrl(App.data.url_base, { path_info : '/chat/history/' + chatId }) :
                    App.data.url_base + '/chat/history/' + chatId;

            App.ModalDialog.show('add_project_chat', App.lang('Chat History'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(url), {
              width : 600,
              height : 400
            });
        });

        $('#update_chat_form').submit(function(){
            $("#chat_update_button").click();
            return false;
        });

        $('#chat_message_to_user').live('click', function(){
            if ('all' != $(this).val()) {
                App.widgets.chat.messageTo('all', App.lang("All people"));
            }
        });
        
        $("#message_text").keydown(function (e) {
            if ((e.metaKey || e.ctrlKey) && e.keyCode == 13) {
                // Ctrl-Enter or Command+Enter pressed
                $("#chat_update_button").click();
            }
        });

        // Add messages to active chat
        $("#chat_update_button").bind('click',function(){
            var url = App.data.path_info_through_query_string ?
                    App.extendUrl(App.data.url_base, { path_info : 'chat/add_message' }) :
                    App.data.url_base + '/chat/add_message';

            var post_data = { 'submitted' : 'submitted' };
            post_data['message[message_text]'] = $('#message_text').val();
            post_data['message[chat_id]'] = $('#chat_sections ul .selected a').attr('id');
            post_data['message[posted_to_user_id]'] = $(".ctrlHolderTogglder").val();

           $.ajax({
              async: false,
              url : url,
              type : 'POST',
              data : post_data,
              beforeSend: function() {
                  switchSendMessagePreloader();
              },
              error: function() {
                  switchSendMessagePreloader();
              },
              success : function(response) {
                switchSendMessagePreloader();
                if (response == 1) {
                    $('#message_text').val('');
                }
                else {
                    $('#message_text').parent().addClass('error');

                }
              },
              error : function() {
                select.attr('disabled', false);

                alert(App.lang('Failed to create new :name based on data you provided. Please try again later', { name : settings.object_name }));
              }
            });
        });
    });
  },
  
  /**
   * Chat show page bahaviour
   */
  chat_show : function () {
    $(document).ready(function() {
        $(".table_wrapper").scrollTop(10000);
    });
  },

  /**
   * Add project chat page bahaviour
   */
  add_project_chat : function() {
    $(document).ready(function(){
        $("#submit_project_chat").bind('click',function(){

        /**
         *  Active projects FIX
         */
         var url = App.data.path_info_through_query_string ?
                    App.extendUrl(App.data.url_base, { path_info : 'chat/add_project' }) :
                    App.data.url_base + '/chat/add_project?active_only=1';

            var post_data = { 'submitted' : 'submitted' };
            var chat_id = $('input:radio:checked').val();
            post_data['chat[project_id]'] = chat_id;

            $.ajax({
              async: false,
              url : url,
              type : 'POST',
              data : post_data,
              success : function(response) {

                response = eval("(" + response + ")");
                
                if (response.open_chats){
                   if( !$("#dashboard_section_"+response.open_chats[0].chat_id).is('li') ){
                        App.ModalDialog.close();
                        App.widgets.chat.setCookie(response.cookie);
                        App.widgets.chat.open(response.open_chats);
                    }else{
                        $(".chat_add_projetc_error").html(App.lang("Chat already exists"));
                    }

                }else {
                    $(".chat_add_projetc_error").html(response.message);
                }
              },
              error : function() {
                select.attr('disabled', false);

                alert(App.lang('Failed to create new :name based on data you provided. Please try again later', { name : settings.object_name }));
              }
            });
        });

        $("#close_add_project_chat").bind('click',function(){
            App.ModalDialog.close();
        });
    });
  }
};

function switchSendMessagePreloader ()
{
    if ($('#chat_update_indicator').is(':hidden')) {
        $('#chat_update_indicator').show();
        $('#chat_update_button').hide();
    } else {
        $('#chat_update_indicator').hide();
        $('#chat_update_button').show();
    }
}

/**
 * Widgets Chat
 */
App.widgets.chat = function(){

  /**
   * Wrapper instance
   *
   * @var jQuery
   */
  var wrapper;

  /**
   * Content block wrapper
   *
   * @var jQuery
   */
  var section_content_wrapper;

  return {
    
    /**
     * Initialize dashboard sections
     *
     * @param String wrapper_id
     */
    sections : function(wrapper_id) {
      wrapper = $('#' + wrapper_id);
      section_content_wrapper = wrapper.find('div.top_tabs_object_list .dashboard_wide_sidebar_inner_2');

      wrapper.find('ul.dashboard_tabs a').click(function(e) {
        var link = $(this);
        var list_item = link.parent();

        if(list_item.is('li.selected')) {
          return false;
        } // if

        App.widgets.chat.messageTo('all', App.lang("All people"));

        var section_content_id = list_item.attr('id') + '_content';

        // Hide all visible content blocks
        section_content_wrapper.find('div.dashboard_section_content').hide();

        // Find or load section content
        var section_content = section_content_wrapper.find('#' + section_content_id);

        if(section_content.length == 0) {
            
          section_content = $('<div id="' + section_content_id + '" class="dashboard_section_content"><p class="dashboard_sections_loading"><img src="' + App.data.big_indicator_url + '" alt="" /></p></div>').appendTo(section_content_wrapper);

          section_content.load(App.extendUrl(link.attr('href'), {
            'async' : 1,
            'for_dashboard_section' : 1
          }));
        } // if

        section_content.show();

        // Mark tab as selected
        wrapper.find('ul.dashboard_tabs li').removeClass('selected');
        list_item.addClass('selected');

        list_item.find('.slip').html('');
        $(".table_wrapper").scrollTop(10000);

        return false;
      });

      // Select first section automatically
      wrapper.find('ul.dashboard_tabs li:first a').click();
    },

    update_chat_menu_badge_item : function () {
        var count_url = App.data.path_info_through_query_string ?
                        App.extendUrl(App.data.url_base, { path_info : 'chat/count-new-messages' }) :
                        App.data.url_base + '/chat/count-new-messages';

        $.ajax({
            type: "GET",
            url: count_url,
            success : function (response) {
                App.MainMenu.setItemBadgeValue('chat', 'main', response);
            }
        })
    }, // update_chat_menu_badge_item

    listen_active_chat : function (){

            var chat_id = $('#chat_sections ul .selected a').attr('id');
            var last_message_id = $('#dashboard_section_'+chat_id+'_content #chat_updates_table tbody tr:last').attr('id');

            if(chat_id != null){
                if (last_message_id == null) last_message_id = 0;

                var url = App.data.path_info_through_query_string ?
                        App.extendUrl(App.data.url_base, { path_info : 'chat/listen' }) :
                        App.data.url_base + '/chat/listen';

                $.ajax({
                    url : url,
                    type : 'GET',
                    data : {chat_id:[chat_id], last_message_id:[last_message_id]},
                    success : function(response) {
                        response = eval("(" + response + ")");
                        
                        if(response.active_chat.id == $('#chat_sections ul .selected a').attr('id')){

                            //Update active chat messages
                            if(response.active_chat.messages !=0){
                                for (var i=0;i<response.active_chat.messages.length;i++)
                                {

                                    if($('#chat_updates_table #'+response.active_chat.messages[i].id).html() === null){
                                        if(response.active_chat.messages[i].posted_to_user_id == 0){
                                            var posted_to = 'all';
                                        }else {
                                            var posted_to = '<a href="javascript:App.widgets.chat.messageTo('+response.active_chat.messages[i].posted_to_user_id+',\''+response.active_chat.messages[i].posted_to_user_name +'\')" class="user_link">'+response.active_chat.messages[i].posted_to_user_name+'</a>';
                                        }
                                        var tr = '<tr id='+response.active_chat.messages[i].id+' ><td><div class="chat_message_time">'+response.active_chat.messages[i].posted_on+'</div><a href="javascript:App.widgets.chat.messageTo('+response.active_chat.messages[i].posted_by_user_id+',\''+response.active_chat.messages[i].posted_by_user_name +'\')" class="user_link">'+response.active_chat.messages[i].posted_by_user_name+'</a> to '+posted_to+' : '+response.active_chat.messages[i].message_text+'</tr>';
                                        tr = tr.replace(' to all ', '');
                                        if(last_message_id == 0){
                                            $('#dashboard_section_'+response.active_chat.messages[i].chat_id+'_content #chat_updates_table tbody').html(tr);
                                        }else {
                                            $('#dashboard_section_'+response.active_chat.messages[i].chat_id+'_content #chat_updates_table tbody tr:last').after(tr);
                                        }
                                        $('#' + response.active_chat.messages[i].id).fadeTo('slow', 0.1, function(){$(this).fadeTo('slow', 1)});
                                    }
                                }
                                $(".table_wrapper").scrollTop(10000);
                            }

                            if (response.open_chats){
                                App.widgets.chat.open(response.open_chats);
                            }
                            
                            // Update who is online
                            $(".online_users_list li span div").removeClass();
                            $(".online_users_list li span div").addClass('chat_user_offline');
                            for (var i=0;i<response.active_chat.online_users.length;i++)
                            {
                                $(".online_users_list li#"+response.active_chat.online_users[i].id+" span div").removeClass();
                                $(".online_users_list li#"+response.active_chat.online_users[i].id+" span div").addClass('chat_user_online');
                            }

                            //Update other chat count messages
                            if(response.chats){
                                for(var i=0;i<response.chats.length;i++){
                                    if(response.chats[i].messages != 0){
                                        $('#chat_sections ul #dashboard_section_'+response.chats[i].chat_id+' a .slip').html(response.chats[i].messages);
                                    }
                                }
                            }

                            App.widgets.chat.setCookie(response.cookie);
                        }
                    }
                });
            }
        },
    /**
     * Open chats on sections
     *
     * @param object chats
     */
    open : function(chats){

        for(var i=0;i<chats.length;i++){

            var show_url = App.data.path_info_through_query_string ?
                           App.extendUrl(App.data.url_base, { path_info : 'chat/show/'+chats[i].chat_id }) :
                           App.data.url_base + '/chat/show/'+chats[i].chat_id;

            chat_existance_check = $('#dashboard_section_' + chats[i].chat_id);
            if (!$(chat_existance_check).is('li')) {
                $("#chat_sections .top_tabs li:last").after('<li id="dashboard_section_'+chats[i].chat_id+'"><a id="'+chats[i].chat_id+'" href="'+show_url+'" ><img src='+chats[i].chat_icon_url+' > <span>'+chats[i].chat_name+'</span>&nbsp;&nbsp;<span class="slip"></span></a></li>');
            }


        }

        App.widgets.chat.sections('chat_sections');
    },
    
    /**
     * Close chats on sections
     *
     * @param int chat_id
     */
    close: function(chat_id){

            var close_url = App.data.path_info_through_query_string ?
                            App.extendUrl(App.data.url_base, { path_info : 'chat/close/'+chat_id }) :
                            App.data.url_base + '/chat/close/'+chat_id;
            $.ajax({
                async: false,
                type: "GET",
                url: close_url,
                success : function (response){

                    if(response != 0){

                        response = eval("(" + response + ")");
                        App.widgets.chat.setCookie(response.cookie);
                        $('#dashboard_section_'+chat_id).remove();
                        $('#dashboard_section_'+chat_id+'_content').remove();
                        $('#chat_sections .top_tabs li:first a').click();
                    }
                }
            });
    },

    /**
     * Close chats on sections
     *
     * @param int chat_id
     */
    clean: function(chat_id){

            var close_url = App.data.path_info_through_query_string ?
                            App.extendUrl(App.data.url_base, { path_info : 'chat/clean/'+chat_id }) :
                            App.data.url_base + '/chat/clean/'+chat_id;
            $.ajax({
                async: false,
                type: "GET",
                url: close_url,
                success : function (response){

                    if(response != 0){

                        response = eval("(" + response + ")");

                        App.widgets.chat.setCookie(response.cookie);
                        $('#dashboard_section_'+chat_id+'_content #chat_updates_table tbody').html('');

                    }
                }
            });
    },

    messageTo : function (userId,userName){

            $('.ui-dialog-content').effect('transfer', { to: ".ctrlHolderTogglder", className: 'ui-effects-transfer' }, 500);
            $(".ctrlHolderTogglder").html(App.lang("To:") + " " +userName);
            $(".ctrlHolderTogglder").val(userId);

            if ('all' != userId) {
                $('#chat_message_to_user').addClass('button_del');
            } else {
                $('#chat_message_to_user').removeClass('button_del');
            }

            $('.ctrlHolderTogglder').fadeTo(500, 0.3, function(){
                $(this).fadeTo(500, 1);
            });
    },

    /**
     * set chat cookie
     *
     * @param json value
     */
    setCookie : function(value){

                var expiredays = 15;
                var exdate=new Date();
                exdate.setDate(exdate.getDate()+expiredays);
                document.cookie="chat=" +escape(value)+
                ((expiredays==null) ? "" : ";expires="+exdate.toUTCString()+";path=/");
            
            },

        /**
     * get chat cookie
     *
     * @param json value
     */
    getCookie : function getCookie() {
                c_name = chat;
                if (document.cookie.length>0)
                  {
                  c_start=document.cookie.indexOf(c_name + "=");
                  if (c_start!=-1)
                    {
                    c_start=c_start + c_name.length+1;
                    c_end=document.cookie.indexOf(";",c_start);
                    if (c_end==-1) c_end=document.cookie.length;
                    return unescape(document.cookie.substring(c_start,c_end));
                    }
                  }
                return "";
            }

   }
}();
  
  int_listen = 0;
  int_update = 0;

  
setInterval(function(){

 
    if($("#chat_updates_dialog").is(':visible')){

        
        if($(".select_projects_widget_popup").is('div')){

            clearInterval(this.int_listen);
            this.int_listen = 0;

        }else{
            
            if(this.int_update !=0 ){
                clearInterval(this.int_update);
                this.int_update = 0;
            }
            if(this.int_listen == 0){
                this.int_listen = setInterval("App.widgets.chat.listen_active_chat()", 5000);
            }
        }
    }else{

        if(this.int_listen != 0){
            clearInterval(this.int_listen);
            this.int_listen = 0;
        }
        if(this.int_update == 0){
            this.int_update = setInterval("App.widgets.chat.update_chat_menu_badge_item()", 5000);
        }
    }

},1000);

$(document).ready(function() {

  // init menu item button
  $('#menu_item_chat a').click(function() {
    var chat_update_url = App.extendUrl($(this).attr('href'), {
      async : 1
    });
    $(".ui-widget-content").remove();
    App.ModalDialog.show('chat_updates', App.lang('Chat'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(chat_update_url), {
      width : 800,
      height : 530
    });
      App.MainMenu.setItemBadgeValue('chat', 'main', 0);
    return false;
  });

  $('#getChatHistory').live('click', function() {

      chatId = $('#chat_sections ul .selected a').attr('id');
            var url = App.data.path_info_through_query_string ?
                    App.extendUrl(App.data.url_base, { path_info : '/chat/history_show/' + chatId }) :
                    App.data.url_base + '/chat/history_show/' + chatId;

      chatHistoryStart = $('#chatHistoryStart').val();
      chatHistoryEnd = $('#chatHistoryEnd').val();
      chatHistoryKeywords = $('#chatHistoryKeywords').val();
      chatHistoryUser = $('#chatHistoryUser').val();
      $.post(url, { chatHistoryStart: chatHistoryStart, chatHistoryEnd: chatHistoryEnd, chatHistoryKeywords: chatHistoryKeywords, chatHistoryUser: chatHistoryUser},
       function(data){
           $('#chat_history_msgs').html(data);
       });
  });

});

/*
 * jQuery UI Effects Transfer 1.7.3
 *
 * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT (MIT-LICENSE.txt)
 * and GPL (GPL-LICENSE.txt) licenses.
 *
 * http://docs.jquery.com/UI/Effects/Transfer
 *
 * Depends:
 *	effects.core.js
 */
(function($) {

$.effects.transfer = function(o) {
	return this.queue(function() {
		var elem = $(this),
			target = $(o.options.to),
			endPosition = target.offset(),
			animation = {
				top: endPosition.top,
				left: endPosition.left,
				height: target.innerHeight(),
				width: target.innerWidth()
			},
			startPosition = elem.offset(),
			transfer = $('<div class="ui-effects-transfer"></div>')
				.appendTo(document.body)
				.addClass(o.options.className)
				.css({
					top: startPosition.top,
					left: startPosition.left,
					height: elem.innerHeight(),
					width: elem.innerWidth(),
					position: 'absolute'
				})
				.animate(animation, o.duration, o.options.easing, function() {
					transfer.remove();
					(o.callback && o.callback.apply(elem[0], arguments));
					elem.dequeue();
				});
	});
};

})(jQuery);


/** File: modules/lightbox/javascript/main.js **/

/*
 * nyroModal - jQuery Plugin
 * http://nyromodal.nyrodev.com
 *
 * Copyright (c) 2008 Cedric Nirousset (nyrodev.com)
 * Licensed under the MIT license
 *
 * $Date: 2009-05-14 (Thu, 14 May 2009) $
 * $version: 1.5.0
 */
jQuery(function($){var userAgent=navigator.userAgent.toLowerCase();var browserVersion=(userAgent.match(/.+(?:rv|webkit|khtml|opera|msie)[\/: ]([\d.]+)/)||[0,'0'])[1];var isIE6=(/msie/.test(userAgent)&&!/opera/.test(userAgent)&&parseInt(browserVersion)<7&&!window.XMLHttpRequest);var body=$('body');var currentSettings;var shouldResize=false;var gallery={};var fixFF=false;var contentElt;var contentEltLast;var modal={started:false,ready:false,dataReady:false,anim:false,animContent:false,loadingShown:false,transition:false,resizing:false,closing:false,error:false,blocker:null,blockerVars:null,full:null,bg:null,loading:null,tmp:null,content:null,wrapper:null,contentWrapper:null,scripts:new Array(),scriptsShown:new Array()};var resized={width:false,height:false,windowResizing:false};var initSettingsSize={width:null,height:null,windowResizing:true};var windowResizeTimeout;$.fn.nyroModal=function(settings){if(!this)return false;return this.each(function(){var me=$(this);if(this.nodeName.toLowerCase()=='form'){me.unbind('submit.nyroModal').bind('submit.nyroModal',function(e){if(me.data('nyroModalprocessing'))return true;if(this.enctype=='multipart/form-data'){processModal($.extend(settings,{from:this}));return true}e.preventDefault();processModal($.extend(settings,{from:this}));return false})}else{me.unbind('click.nyroModal').bind('click.nyroModal',function(e){e.preventDefault();processModal($.extend(settings,{from:this}));return false})}})};$.fn.nyroModalManual=function(settings){if(!this.length)processModal(settings);return this.each(function(){processModal($.extend(settings,{from:this}))})};$.nyroModalManual=function(settings){processModal(settings)};$.nyroModalSettings=function(settings,deep1,deep2){setCurrentSettings(settings,deep1,deep2);if(!deep1&&modal.started){if(modal.bg&&settings.bgColor)currentSettings.updateBgColor(modal,currentSettings,function(){});if(modal.contentWrapper&&settings.title)setTitle();if(!modal.error&&(settings.windowResizing||(!modal.resizing&&(('width'in settings&&settings.width==currentSettings.width)||('height'in settings&&settings.height==currentSettings.height))))){modal.resizing=true;if(modal.contentWrapper)calculateSize(true);if(modal.contentWrapper&&modal.contentWrapper.is(':visible')&&!modal.animContent){if(fixFF)modal.content.css({position:''});currentSettings.resize(modal,currentSettings,function(){currentSettings.windowResizing=false;modal.resizing=false;if(fixFF)modal.content.css({position:'fixed'});if($.isFunction(currentSettings.endResize))currentSettings.endResize(modal,currentSettings)})}}}};$.nyroModalRemove=function(){removeModal()};$.nyroModalNext=function(){var link=getGalleryLink(1);if(link)return link.nyroModalManual(getCurrentSettingsNew());return false};$.nyroModalPrev=function(){var link=getGalleryLink(-1);if(link)return link.nyroModalManual(getCurrentSettingsNew());return false};$.fn.nyroModal.settings={debug:false,blocker:false,modal:false,type:'',from:'',hash:'',processHandler:null,selIndicator:'nyroModalSel',formIndicator:'nyroModal',content:null,bgColor:'#000000',ajax:{},swf:{wmode:'transparent'},width:null,height:null,minWidth:400,minHeight:300,resizable:true,autoSizable:true,padding:25,regexImg:'inline',addImageDivTitle:true,defaultImgAlt:'Image',setWidthImgTitle:true,ltr:true,gallery:null,galleryLinks:'<a href="#" class="nyroModalPrev">Prev</a><a href="#"  class="nyroModalNext">Next</a>',galleryCounts:galleryCounts,zIndexStart:100,css:{bg:{position:'absolute',overflow:'hidden',top:0,left:0,height:'100%',width:'100%'},wrapper:{position:'absolute',top:'50%',left:'50%'},wrapper2:{},content:{overflow:'auto'},loading:{position:'absolute',top:'50%',left:'50%',marginTop:'-50px',marginLeft:'-50px'}},wrap:{div:'<div class="wrapper"></div>',ajax:'<div class="wrapper"></div>',form:'<div class="wrapper"></div>',formData:'<div class="wrapper"></div>',image:'<div class="wrapperImg"></div>',swf:'<div class="wrapperSwf"></div>',iframe:'<div class="wrapperIframe"></div>',iframeForm:'<div class="wrapperIframe"></div>',manual:'<div class="wrapper"></div>'},closeButton:'<a href="#" class="nyroModalClose" id="closeBut" title="close">Close</a>',title:null,titleFromIframe:true,openSelector:'.nyroModal',closeSelector:'.nyroModalClose',contentLoading:'<a href="#" class="nyroModalClose">Cancel</a>',errorClass:'error',contentError:'The requested content cannot be loaded.<br />Please try again later.<br /><a href="#" class="nyroModalClose">Close</a>',handleError:null,showBackground:showBackground,hideBackground:hideBackground,endFillContent:null,showContent:showContent,endShowContent:null,beforeHideContent:null,hideContent:hideContent,showTransition:showTransition,hideTransition:hideTransition,showLoading:showLoading,hideLoading:hideLoading,resize:resize,endResize:null,updateBgColor:updateBgColor,endRemove:null};function processModal(settings){if(modal.loadingShown||modal.transition||modal.anim)return;debug('processModal');modal.started=true;setDefaultCurrentSettings(settings);if(!modal.full)modal.blockerVars=modal.blocker=null;modal.error=false;modal.closing=false;modal.dataReady=false;modal.scripts=new Array();modal.scriptsShown=new Array();currentSettings.type=fileType();if($.isFunction(currentSettings.processHandler))currentSettings.processHandler(currentSettings);from=currentSettings.from;url=currentSettings.url;initSettingsSize.width=currentSettings.width;initSettingsSize.height=currentSettings.height;if(currentSettings.type=='swf'){setCurrentSettings({overflow:'hidden'},'css','content');currentSettings.content='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="'+currentSettings.width+'" height="'+currentSettings.height+'"><param name="movie" value="'+url+'"></param>';var tmp='';$.each(currentSettings.swf,function(name,val){currentSettings.content+='<param name="'+name+'" value="'+val+'"></param>';tmp+=' '+name+'="'+val+'"'});currentSettings.content+='<embed src="'+url+'" type="application/x-shockwave-flash" width="'+currentSettings.width+'" height="'+currentSettings.height+'"'+tmp+'></embed></object>'}if(from){var jFrom=$(from);if(currentSettings.type=='form'){var data=$(from).serializeArray();data.push({name:currentSettings.formIndicator,value:1});if(currentSettings.selector)data.push({name:currentSettings.selIndicator,value:currentSettings.selector.substring(1)});$.ajax($.extend({},currentSettings.ajax,{url:url,data:data,type:jFrom.attr('method')?jFrom.attr('method'):'get',success:ajaxLoaded,error:loadingError}));debug('Form Ajax Load: '+jFrom.attr('action'));showModal()}else if(currentSettings.type=='formData'){initModal();jFrom.attr('target','nyroModalIframe');jFrom.attr('action',url);jFrom.prepend('<input type="hidden" name="'+currentSettings.formIndicator+'" value="1" />');if(currentSettings.selector)jFrom.prepend('<input type="hidden" name="'+currentSettings.selIndicator+'" value="'+currentSettings.selector.substring(1)+'" />');modal.tmp.html('<iframe frameborder="0" hspace="0" name="nyroModalIframe" src="javascript:false;"></iframe>');$('iframe',modal.tmp).css({width:currentSettings.width,height:currentSettings.height}).error(loadingError).load(formDataLoaded);debug('Form Data Load: '+jFrom.attr('action'));showModal();showContentOrLoading()}else if(currentSettings.type=='image'){debug('Image Load: '+url);var title=jFrom.attr('title')||currentSettings.defaultImgAlt;initModal();modal.tmp.html('<img id="nyroModalImg" />').find('img').attr('alt',title);modal.tmp.css({lineHeight:0});$('img',modal.tmp).error(loadingError).load(function(){debug('Image Loaded: '+this.src);$(this).unbind('load');var w=modal.tmp.width();var h=modal.tmp.height();modal.tmp.css({lineHeight:''});resized.width=w;resized.height=h;setCurrentSettings({width:w,height:h,imgWidth:w,imgHeight:h});initSettingsSize.width=w;initSettingsSize.height=h;setCurrentSettings({overflow:'hidden'},'css','content');modal.dataReady=true;if(modal.loadingShown||modal.transition)showContentOrLoading()}).attr('src',url);showModal()}else if(currentSettings.type=='iframeForm'){initModal();modal.tmp.html('<iframe frameborder="0" hspace="0" src="javascript:false;" name="nyroModalIframe" id="nyroModalIframe"></iframe>');debug('Iframe Form Load: '+url);$('iframe',modal.tmp).eq(0).css({width:'100%',height:$.support.boxModel?'99%':'100%'}).load(function(e){if(currentSettings.titleFromIframe&&url.indexOf(window.location.hostname)>-1)$.nyroModalSettings({title:$('iframe',modal.full).contents().find('title').text()})});modal.dataReady=true;showModal()}else if(currentSettings.type=='iframe'){initModal();modal.tmp.html('<iframe frameborder="0" hspace="0" src="'+url+'" name="nyroModalIframe" id="nyroModalIframe"></iframe>');debug('Iframe Load: '+url);$('iframe',modal.tmp).eq(0).css({width:'100%',height:$.support.boxModel?'99%':'100%'}).load(function(e){if(currentSettings.titleFromIframe&&url.indexOf(window.location.hostname)>-1)$.nyroModalSettings({title:$('iframe',modal.full).contents().find('title').text()})});modal.dataReady=true;showModal()}else if(currentSettings.type){debug('Content: '+currentSettings.type);initModal();modal.tmp.html(currentSettings.content);var w=modal.tmp.width();var h=modal.tmp.height();var div=$(currentSettings.type);if(div.length){setCurrentSettings({type:'div'});w=div.width();h=div.height();if(contentElt)contentEltLast=contentElt;contentElt=div;modal.tmp.append(div.contents())}initSettingsSize.width=w;initSettingsSize.height=h;setCurrentSettings({width:w,height:h});if(modal.tmp.html())modal.dataReady=true;else loadingError();if(!modal.ready)showModal();else endHideContent()}else{debug('Ajax Load: '+url);setCurrentSettings({type:'ajax'});var data=currentSettings.ajax.data||{};if(currentSettings.selector){if(typeof data=="string"){data+='&'+currentSettings.selIndicator+'='+currentSettings.selector.substring(1)}else{data[currentSettings.selIndicator]=currentSettings.selector.substring(1)}}$.ajax($.extend(true,currentSettings.ajax,{url:url,success:ajaxLoaded,error:loadingError,data:data}));showModal()}}else if(currentSettings.content){debug('Content: '+currentSettings.type);setCurrentSettings({type:'manual'});initModal();modal.tmp.html($('<div/>').html(currentSettings.content).contents());if(modal.tmp.html())modal.dataReady=true;else loadingError();showModal()}else{}}function setDefaultCurrentSettings(settings){debug('setDefaultCurrentSettings');currentSettings=$.extend(true,{},$.fn.nyroModal.settings,settings);currentSettings.selector='';currentSettings.borderW=0;currentSettings.borderH=0;currentSettings.resizable=true;setMargin()}function setCurrentSettings(settings,deep1,deep2){if(modal.started){if(deep1&&deep2){$.extend(true,currentSettings[deep1][deep2],settings)}else if(deep1){$.extend(true,currentSettings[deep1],settings)}else{if(modal.animContent){if('width'in settings){if(!modal.resizing){settings.setWidth=settings.width;shouldResize=true}delete settings['width']}if('height'in settings){if(!modal.resizing){settings.setHeight=settings.height;shouldResize=true}delete settings['height']}}$.extend(true,currentSettings,settings)}}else{if(deep1&&deep2){$.extend(true,$.fn.nyroModal.settings[deep1][deep2],settings)}else if(deep1){$.extend(true,$.fn.nyroModal.settings[deep1],settings)}else{$.extend(true,$.fn.nyroModal.settings,settings)}}}function setMarginScroll(){if(isIE6&&!modal.blocker){if(document.documentElement){currentSettings.marginScrollLeft=document.documentElement.scrollLeft;currentSettings.marginScrollTop=document.documentElement.scrollTop}else{currentSettings.marginScrollLeft=document.body.scrollLeft;currentSettings.marginScrollTop=document.body.scrollTop}}else{currentSettings.marginScrollLeft=0;currentSettings.marginScrollTop=0}}function setMargin(){setMarginScroll();currentSettings.marginLeft=-(currentSettings.width+currentSettings.borderW)/2;currentSettings.marginTop=-(currentSettings.height+currentSettings.borderH)/2;if(!modal.blocker){currentSettings.marginLeft+=currentSettings.marginScrollLeft;currentSettings.marginTop+=currentSettings.marginScrollTop}}function setMarginLoading(){setMarginScroll();var outer=getOuter(modal.loading);currentSettings.marginTopLoading=-(modal.loading.height()+outer.h.border+outer.h.padding)/2;currentSettings.marginLeftLoading=-(modal.loading.width()+outer.w.border+outer.w.padding)/2;if(!modal.blocker){currentSettings.marginLefttLoading+=currentSettings.marginScrollLeft;currentSettings.marginTopLoading+=currentSettings.marginScrollTop}}function setTitle(){var title=$('h1#nyroModalTitle',modal.contentWrapper);if(title.length)title.text(currentSettings.title);else modal.contentWrapper.prepend('<h1 id="nyroModalTitle">'+currentSettings.title+'</h1>')}function initModal(){debug('initModal');if(!modal.full){if(currentSettings.debug)setCurrentSettings({color:'white'},'css','bg');var full={zIndex:currentSettings.zIndexStart,position:'fixed',top:0,left:0,width:'100%',height:'100%'};var contain=body;var iframeHideIE='';if(currentSettings.blocker){modal.blocker=contain=$(currentSettings.blocker);var pos=modal.blocker.offset();var w=modal.blocker.outerWidth();var h=modal.blocker.outerHeight();if(isIE6){setCurrentSettings({height:'100%',width:'100%',top:0,left:0},'css','bg')}modal.blockerVars={top:pos.top,left:pos.left,width:w,height:h};var plusTop=(/msie/.test(userAgent)?0:getCurCSS(body.get(0),'borderTopWidth'));var plusLeft=(/msie/.test(userAgent)?0:getCurCSS(body.get(0),'borderLeftWidth'));full={position:'absolute',top:pos.top+plusTop,left:pos.left+plusLeft,width:w,height:h}}else if(isIE6){body.css({height:body.height()+'px',width:body.width()+'px',position:'static',overflow:'hidden'});$('html').css({overflow:'hidden'});setCurrentSettings({css:{bg:{position:'absolute',zIndex:currentSettings.zIndexStart+1,height:'110%',width:'110%',top:currentSettings.marginScrollTop+'px',left:currentSettings.marginScrollLeft+'px'},wrapper:{zIndex:currentSettings.zIndexStart+2},loading:{zIndex:currentSettings.zIndexStart+3}}});iframeHideIE=$('<iframe id="nyroModalIframeHideIe"></iframe>').css($.extend({},currentSettings.css.bg,{opacity:0,zIndex:50,border:'none'}))}contain.append($('<div id="nyroModalFull"><div id="nyroModalBg"></div><div id="nyroModalWrapper"><div id="nyroModalContent"></div></div><div id="nyrModalTmp"></div><div id="nyroModalLoading"></div></div>').hide());modal.full=$('#nyroModalFull').css(full).show();modal.bg=$('#nyroModalBg').css($.extend({backgroundColor:currentSettings.bgColor},currentSettings.css.bg)).before(iframeHideIE);if(!currentSettings.modal)modal.bg.click(removeModal);modal.loading=$('#nyroModalLoading').css(currentSettings.css.loading).hide();modal.contentWrapper=$('#nyroModalWrapper').css(currentSettings.css.wrapper).hide();modal.content=$('#nyroModalContent');modal.tmp=$('#nyrModalTmp').hide();if($.isFunction($.fn.mousewheel)){modal.content.mousewheel(function(e,d){var elt=modal.content.get(0);if((d>0&&elt.scrollTop==0)||(d<0&&elt.scrollHeight-elt.scrollTop==elt.clientHeight)){e.preventDefault();e.stopPropagation()}})}$(document).bind('keydown.nyroModal',keyHandler);modal.content.css({width:'auto',height:'auto'});modal.contentWrapper.css({width:'auto',height:'auto'});if(!currentSettings.blocker){$(window).bind('resize.nyroModal',function(){window.clearTimeout(windowResizeTimeout);windowResizeTimeout=window.setTimeout(windowResizeHandler,200)})}}}function windowResizeHandler(){$.nyroModalSettings(initSettingsSize)}function showModal(){debug('showModal');if(!modal.ready){initModal();modal.anim=true;currentSettings.showBackground(modal,currentSettings,endBackground)}else{modal.anim=true;modal.transition=true;currentSettings.showTransition(modal,currentSettings,function(){endHideContent();modal.anim=false;showContentOrLoading()})}}function keyHandler(e){if(e.keyCode==27){if(!currentSettings.modal)removeModal()}else if(currentSettings.gallery&&modal.ready&&modal.dataReady&&!modal.anim&&!modal.transition){if(e.keyCode==39||e.keyCode==40){e.preventDefault();$.nyroModalNext();return false}else if(e.keyCode==37||e.keyCode==38){e.preventDefault();$.nyroModalPrev();return false}}}function fileType(){if(currentSettings.forceType){var tmp=currentSettings.forceType;if(!currentSettings.content)currentSettings.from=true;currentSettings.forceType=null;return tmp}var from=currentSettings.from;var url;if(from&&from.nodeName){var jFrom=$(from);url=jFrom.attr(from.nodeName.toLowerCase()=='form'?'action':'href');if(!url)url=location.href.substring(window.location.host.length+7);currentSettings.url=url;if(jFrom.attr('rev')=='modal')currentSettings.modal=true;currentSettings.title=jFrom.attr('title');if(from&&from.rel&&from.rel.toLowerCase()!='nofollow')currentSettings.gallery=from.rel;var imgType=imageType(url,from);if(imgType)return imgType;if(isSwf(url))return'swf';var iframe=false;if(from.target&&from.target.toLowerCase()=='_blank'||(from.hostname&&from.hostname.replace(/:\d*$/,'')!=window.location.hostname.replace(/:\d*$/,''))){iframe=true}if(from.nodeName.toLowerCase()=='form'){if(iframe)return'iframeForm';setCurrentSettings(extractUrlSel(url));if(jFrom.attr('enctype')=='multipart/form-data')return'formData';return'form'}if(iframe)return'iframe'}else{url=currentSettings.url;if(!currentSettings.content)currentSettings.from=true;if(!url)return null;if(isSwf(url))return'swf';var reg1=new RegExp("^http://","g");if(url.match(reg1))return'iframe'}var imgType=imageType(url,from);if(imgType)return imgType;var tmp=extractUrlSel(url);setCurrentSettings(tmp);if(!tmp.url)return tmp.selector}function imageType(url,from){var image=new RegExp(currentSettings.regexImg,'i');if(image.test(url)){return'image'}}function isSwf(url){var swf=new RegExp('[^\.]\.(swf)\s*$','i');return swf.test(url)}function extractUrlSel(url){var ret={url:null,selector:null};if(url){var hash=getHash(url);var hashLoc=getHash(window.location.href);var curLoc=window.location.href.substring(0,window.location.href.length-hashLoc.length);var req=url.substring(0,url.length-hash.length);if(req==curLoc){ret.selector=hash}else{ret.url=req;ret.selector=hash}}return ret}function loadingError(){debug('loadingError');modal.error=true;if(!modal.ready)return;if($.isFunction(currentSettings.handleError))currentSettings.handleError(modal,currentSettings);modal.loading.addClass(currentSettings.errorClass).html(currentSettings.contentError);$(currentSettings.closeSelector,modal.loading).unbind('click.nyroModal').bind('click.nyroModal',removeModal);setMarginLoading();modal.loading.css({marginTop:currentSettings.marginTopLoading+'px',marginLeft:currentSettings.marginLeftLoading+'px'})}function fillContent(){debug('fillContent');if(!modal.tmp.html())return;modal.content.html(modal.tmp.contents());modal.tmp.empty();wrapContent();if(currentSettings.type=='iframeForm'){$(currentSettings.from).attr('target','nyroModalIframe').data('nyroModalprocessing',1).submit().attr('target','_blank').removeData('nyroModalprocessing')}if(!currentSettings.modal)modal.wrapper.prepend(currentSettings.closeButton);if($.isFunction(currentSettings.endFillContent))currentSettings.endFillContent(modal,currentSettings);modal.content.append(modal.scripts);$(currentSettings.closeSelector,modal.contentWrapper).unbind('click.nyroModal').bind('click.nyroModal',removeModal);$(currentSettings.openSelector,modal.contentWrapper).nyroModal(getCurrentSettingsNew())}function getCurrentSettingsNew(){var currentSettingsNew=$.extend(true,{},currentSettings);if(resized.width)currentSettingsNew.width=null;else currentSettingsNew.width=initSettingsSize.width;if(resized.height)currentSettingsNew.height=null;else currentSettingsNew.height=initSettingsSize.height;currentSettingsNew.css.content.overflow='auto';return currentSettingsNew}function wrapContent(){debug('wrapContent');var wrap=$(currentSettings.wrap[currentSettings.type]);modal.content.append(wrap.children().remove());modal.contentWrapper.wrapInner(wrap);if(currentSettings.gallery){modal.content.append(currentSettings.galleryLinks);gallery.links=$('[rel="'+currentSettings.gallery+'"]');gallery.index=gallery.links.index(currentSettings.from);if(currentSettings.galleryCounts&&$.isFunction(currentSettings.galleryCounts))currentSettings.galleryCounts(gallery.index+1,gallery.links.length,modal,currentSettings);var currentSettingsNew=getCurrentSettingsNew();var linkPrev=getGalleryLink(-1);if(linkPrev){var prev=$('.nyroModalPrev',modal.contentWrapper).attr('href',linkPrev.attr('href')).click(function(e){e.preventDefault();$.nyroModalPrev();return false});if(isIE6&&currentSettings.type=='swf'){prev.before($('<iframe id="nyroModalIframeHideIeGalleryPrev"></iframe>').css({position:prev.css('position'),top:prev.css('top'),left:prev.css('left'),width:prev.width(),height:prev.height(),opacity:0,border:'none'}))}}else{$('.nyroModalPrev',modal.contentWrapper).remove()}var linkNext=getGalleryLink(1);if(linkNext){var next=$('.nyroModalNext',modal.contentWrapper).attr('href',linkNext.attr('href')).click(function(e){e.preventDefault();$.nyroModalNext();return false});if(isIE6&&currentSettings.type=='swf'){next.before($('<iframe id="nyroModalIframeHideIeGalleryNext"></iframe>').css($.extend({},{position:next.css('position'),top:next.css('top'),left:next.css('left'),width:next.width(),height:next.height(),opacity:0,border:'none'})))}}else{$('.nyroModalNext',modal.contentWrapper).remove()}}calculateSize()}function getGalleryLink(dir){if(currentSettings.gallery){if(!currentSettings.ltr)dir*=-1;var index=gallery.index+dir;if(index>=0&&index<gallery.links.length)return gallery.links.eq(index)}return false}function calculateSize(resizing){debug('calculateSize');modal.wrapper=modal.contentWrapper.children('div:first');resized.width=false;resized.height=false;if(false&&!currentSettings.windowResizing){initSettingsSize.width=currentSettings.width;initSettingsSize.height=currentSettings.height}if(currentSettings.autoSizable&&(!currentSettings.width||!currentSettings.height)){modal.contentWrapper.css({opacity:0,width:'auto',height:'auto'}).show();var tmp={width:'auto',height:'auto'};if(currentSettings.width){tmp.width=currentSettings.width}else if(currentSettings.type=='iframe'){tmp.width=currentSettings.minWidth}if(currentSettings.height){tmp.height=currentSettings.height}else if(currentSettings.type=='iframe'){tmp.height=currentSettings.minHeight}modal.content.css(tmp);if(!currentSettings.width){currentSettings.width=modal.content.outerWidth(true);resized.width=true}if(!currentSettings.height){currentSettings.height=modal.content.outerHeight(true);resized.height=true}modal.contentWrapper.css({opacity:1});if(!resizing)modal.contentWrapper.hide()}if(currentSettings.type!='image'&&currentSettings.type!='swf'){currentSettings.width=Math.max(currentSettings.width,currentSettings.minWidth);currentSettings.height=Math.max(currentSettings.height,currentSettings.minHeight)}var outerWrapper=getOuter(modal.contentWrapper);var outerWrapper2=getOuter(modal.wrapper);var outerContent=getOuter(modal.content);var tmp={content:{width:currentSettings.width,height:currentSettings.height},wrapper2:{width:currentSettings.width+outerContent.w.total,height:currentSettings.height+outerContent.h.total},wrapper:{width:currentSettings.width+outerContent.w.total+outerWrapper2.w.total,height:currentSettings.height+outerContent.h.total+outerWrapper2.h.total}};if(currentSettings.resizable){var maxHeight=modal.blockerVars?modal.blockerVars.height:$(window).height()-outerWrapper.h.border-(tmp.wrapper.height-currentSettings.height);var maxWidth=modal.blockerVars?modal.blockerVars.width:$(window).width()-outerWrapper.w.border-(tmp.wrapper.width-currentSettings.width);maxHeight-=currentSettings.padding*2;maxWidth-=currentSettings.padding*2;if(tmp.content.height>maxHeight||tmp.content.width>maxWidth){if(currentSettings.type=='image'||currentSettings.type=='swf'){var useW=currentSettings.imgWidth?currentSettings.imgWidth:currentSettings.width;var useH=currentSettings.imgHeight?currentSettings.imgHeight:currentSettings.height;var diffW=tmp.content.width-useW;var diffH=tmp.content.height-useH;if(diffH<0)diffH=0;if(diffW<0)diffW=0;var calcH=maxHeight-diffH;var calcW=maxWidth-diffW;var ratio=Math.min(calcH/useH,calcW/useW);calcW=Math.floor(useW*ratio);calcH=Math.floor(useH*ratio);tmp.content.height=calcH+diffH;tmp.content.width=calcW+diffW}else{tmp.content.height=Math.min(tmp.content.height,maxHeight);tmp.content.width=Math.min(tmp.content.width,maxWidth)}tmp.wrapper2={width:tmp.content.width+outerContent.w.total,height:tmp.content.height+outerContent.h.total};tmp.wrapper={width:tmp.content.width+outerContent.w.total+outerWrapper2.w.total,height:tmp.content.height+outerContent.h.total+outerWrapper2.h.total}}}if(currentSettings.type=='swf'){$('object, embed',modal.content).attr('width',tmp.content.width).attr('height',tmp.content.height)}else if(currentSettings.type=='image'){$('img',modal.content).css({width:tmp.content.width,height:tmp.content.height})}modal.content.css($.extend({},tmp.content,currentSettings.css.content));modal.wrapper.css($.extend({},tmp.wrapper2,currentSettings.css.wrapper2));if(!resizing)modal.contentWrapper.css($.extend({},tmp.wrapper,currentSettings.css.wrapper));if(currentSettings.type=='image'&&currentSettings.addImageDivTitle){$('img',modal.content).removeAttr('alt');var divTitle=$('div',modal.content);if(currentSettings.title!=currentSettings.defaultImgAlt&&currentSettings.title){if(divTitle.length==0){divTitle=$('<div>'+currentSettings.title+'</div>');modal.content.append(divTitle)}if(currentSettings.setWidthImgTitle){var outerDivTitle=getOuter(divTitle);divTitle.css({width:(tmp.content.width+outerContent.w.padding-outerDivTitle.w.total)+'px'})}}else if(divTitle.length=0){divTitle.remove()}}if(currentSettings.title)setTitle();tmp.wrapper.borderW=outerWrapper.w.border;tmp.wrapper.borderH=outerWrapper.h.border;setCurrentSettings(tmp.wrapper);setMargin()}function removeModal(e){debug('removeModal');if(e)e.preventDefault();if(modal.full&&modal.ready){$(document).unbind('keydown.nyroModal');if(!currentSettings.blocker)$(window).unbind('resize.nyroModal');modal.ready=false;modal.anim=true;modal.closing=true;if(modal.loadingShown||modal.transition){currentSettings.hideLoading(modal,currentSettings,function(){modal.loading.hide();modal.loadingShown=false;modal.transition=false;currentSettings.hideBackground(modal,currentSettings,endRemove)})}else{if(fixFF)modal.content.css({position:''});modal.wrapper.css({overflow:'hidden'});modal.content.css({overflow:'hidden'});if($.isFunction(currentSettings.beforeHideContent)){currentSettings.beforeHideContent(modal,currentSettings,function(){currentSettings.hideContent(modal,currentSettings,function(){endHideContent();currentSettings.hideBackground(modal,currentSettings,endRemove)})})}else{currentSettings.hideContent(modal,currentSettings,function(){endHideContent();currentSettings.hideBackground(modal,currentSettings,endRemove)})}}}if(e)return false}function showContentOrLoading(){debug('showContentOrLoading');if(modal.ready&&!modal.anim){if(modal.dataReady){if(modal.tmp.html()){modal.anim=true;if(modal.transition){fillContent();modal.animContent=true;currentSettings.hideTransition(modal,currentSettings,function(){modal.loading.hide();modal.transition=false;modal.loadingShown=false;endShowContent()})}else{currentSettings.hideLoading(modal,currentSettings,function(){modal.loading.hide();modal.loadingShown=false;fillContent();setMarginLoading();setMargin();modal.animContent=true;currentSettings.showContent(modal,currentSettings,endShowContent)})}}}else if(!modal.loadingShown&&!modal.transition){modal.anim=true;modal.loadingShown=true;if(modal.error)loadingError();else modal.loading.html(currentSettings.contentLoading);$(currentSettings.closeSelector,modal.loading).unbind('click.nyroModal').bind('click.nyroModal',removeModal);setMarginLoading();currentSettings.showLoading(modal,currentSettings,function(){modal.anim=false;showContentOrLoading()})}}}function ajaxLoaded(data){debug('AjaxLoaded: '+this.url);modal.tmp.html(currentSettings.selector?filterScripts($('<div>'+data+'</div>').find(currentSettings.selector).contents()):filterScripts(data));if(modal.tmp.html()){modal.dataReady=true;showContentOrLoading()}else loadingError()}function formDataLoaded(){debug('formDataLoaded');var jFrom=$(currentSettings.from);jFrom.attr('action',jFrom.attr('action')+currentSettings.selector);jFrom.attr('target','');$('input[name='+currentSettings.formIndicator+']',currentSettings.from).remove();var iframe=modal.tmp.children('iframe');var iframeContent=iframe.unbind('load').contents().find(currentSettings.selector||'body').not('script[src]');iframe.attr('src','about:blank');modal.tmp.html(iframeContent.html());if(modal.tmp.html()){modal.dataReady=true;showContentOrLoading()}else loadingError()}function galleryCounts(nb,total,elts,settings){settings.title+=(settings.title?' - ':'')+nb+'/'+total}function endHideContent(){debug('endHideContent');modal.anim=false;if(contentEltLast){contentEltLast.append(modal.content.contents());contentEltLast=null}else if(contentElt){contentElt.append(modal.content.contents());contentElt=null}modal.content.empty();gallery={};modal.contentWrapper.hide().children().remove().empty().attr('style','').hide();if(modal.closing||modal.transition)modal.contentWrapper.hide();modal.contentWrapper.css(currentSettings.css.wrapper).append(modal.content);showContentOrLoading()}function endRemove(){debug('endRemove');$(document).unbind('keydown',keyHandler);modal.anim=false;modal.full.remove();modal.full=null;if(isIE6){body.css({height:'',width:'',position:'',overflow:''});$('html').css({overflow:''})}if($.isFunction(currentSettings.endRemove))currentSettings.endRemove(modal,currentSettings)}function endBackground(){debug('endBackground');modal.ready=true;modal.anim=false;showContentOrLoading()}function endShowContent(){debug('endShowContent');modal.anim=false;modal.animContent=false;modal.contentWrapper.css({opacity:''});fixFF=/mozilla/.test(userAgent)&&!/(compatible|webkit)/.test(userAgent)&&parseFloat(browserVersion)<1.9&&currentSettings.type!='image';if(fixFF)modal.content.css({position:'fixed'});modal.content.append(modal.scriptsShown);if(currentSettings.autoSizable&&currentSettings.type=='iframe'){var iframe=modal.content.find('iframe');if(iframe.length&&iframe.attr('src').indexOf(window.location.hostname)!==-1){var body=iframe.contents().find('body');if(body.height()>0){var h=body.outerHeight(true)+1;var w=body.outerWidth(true)+1;$.nyroModalSettings({height:h,width:w})}else{iframe.bind('load',function(){var body=iframe.contents().find('body');if(body.length&&body.height()>0){var h=body.outerHeight(true)+1;var w=body.outerWidth(true)+1;$.nyroModalSettings({height:h,width:w})}})}}}if($.isFunction(currentSettings.endShowContent))currentSettings.endShowContent(modal,currentSettings);if(shouldResize){shouldResize=false;$.nyroModalSettings({width:currentSettings.setWidth,height:currentSettings.setHeight});delete currentSettings['setWidth'];delete currentSettings['setHeight']}if(resized.width)setCurrentSettings({width:null});if(resized.height)setCurrentSettings({height:null})}function getHash(url){if(typeof url=='string'){var hashPos=url.indexOf('#');if(hashPos>-1)return url.substring(hashPos)}return''}function filterScripts(data){if(typeof data=='string')data=data.replace(/<\/?(html|head|body)([^>]*)>/gi,'');var tmp=new Array();$.each($.clean({0:data},this.ownerDocument),function(){if($.nodeName(this,"script")){if(!this.src||$(this).attr('rel')=='forceLoad'){if($(this).attr('rev')=='shown')modal.scriptsShown.push(this);else modal.scripts.push(this)}}else tmp.push(this)});return tmp}function getOuter(elm){elm=elm.get(0);var ret={h:{margin:getCurCSS(elm,'marginTop')+getCurCSS(elm,'marginBottom'),border:getCurCSS(elm,'borderTopWidth')+getCurCSS(elm,'borderBottomWidth'),padding:getCurCSS(elm,'paddingTop')+getCurCSS(elm,'paddingBottom')},w:{margin:getCurCSS(elm,'marginLeft')+getCurCSS(elm,'marginRight'),border:getCurCSS(elm,'borderLeftWidth')+getCurCSS(elm,'borderRightWidth'),padding:getCurCSS(elm,'paddingLeft')+getCurCSS(elm,'paddingRight')}};ret.h.outer=ret.h.margin+ret.h.border;ret.w.outer=ret.w.margin+ret.w.border;ret.h.inner=ret.h.padding+ret.h.border;ret.w.inner=ret.w.padding+ret.w.border;ret.h.total=ret.h.outer+ret.h.padding;ret.w.total=ret.w.outer+ret.w.padding;return ret}function getCurCSS(elm,name){var ret=parseInt($.curCSS(elm,name,true));if(isNaN(ret))ret=0;return ret}function debug(msg){if($.fn.nyroModal.settings.debug||currentSettings&&currentSettings.debug)nyroModalDebug(msg,modal,currentSettings||{})}function showBackground(elts,settings,callback){elts.bg.css({opacity:0}).fadeTo(500,0.75,callback)}function hideBackground(elts,settings,callback){elts.bg.fadeOut(300,callback)}function showLoading(elts,settings,callback){elts.loading.css({marginTop:settings.marginTopLoading+'px',marginLeft:settings.marginLeftLoading+'px',opacity:0}).show().animate({opacity:1},{complete:callback,duration:400})}function hideLoading(elts,settings,callback){callback()}function showContent(elts,settings,callback){elts.loading.css({marginTop:settings.marginTopLoading+'px',marginLeft:settings.marginLeftLoading+'px'}).show().animate({width:settings.width+'px',height:settings.height+'px',marginTop:settings.marginTop+'px',marginLeft:settings.marginLeft+'px'},{duration:350,complete:function(){elts.contentWrapper.css({width:settings.width+'px',height:settings.height+'px',marginTop:settings.marginTop+'px',marginLeft:settings.marginLeft+'px'}).show();elts.loading.fadeOut(200,callback)}})}function hideContent(elts,settings,callback){elts.contentWrapper.animate({height:'50px',width:'50px',marginTop:(-(25+settings.borderH)/2+settings.marginScrollTop)+'px',marginLeft:(-(25+settings.borderW)/2+settings.marginScrollLeft)+'px'},{duration:350,complete:function(){elts.contentWrapper.hide();callback()}})}function showTransition(elts,settings,callback){elts.loading.css({marginTop:elts.contentWrapper.css('marginTop'),marginLeft:elts.contentWrapper.css('marginLeft'),height:elts.contentWrapper.css('height'),width:elts.contentWrapper.css('width'),opacity:0}).show().fadeTo(400,1,function(){elts.contentWrapper.hide();callback()})}function hideTransition(elts,settings,callback){elts.contentWrapper.hide().css({width:settings.width+'px',height:settings.height+'px',marginLeft:settings.marginLeft+'px',marginTop:settings.marginTop+'px',opacity:1});elts.loading.animate({width:settings.width+'px',height:settings.height+'px',marginLeft:settings.marginLeft+'px',marginTop:settings.marginTop+'px'},{complete:function(){elts.contentWrapper.show();elts.loading.fadeOut(400,function(){elts.loading.hide();callback()})},duration:350})}function resize(elts,settings,callback){elts.contentWrapper.animate({width:settings.width+'px',height:settings.height+'px',marginLeft:settings.marginLeft+'px',marginTop:settings.marginTop+'px'},{complete:callback,duration:400})}function updateBgColor(elts,settings,callback){if(!$.fx.step.backgroundColor){elts.bg.css({backgroundColor:settings.bgColor});callback()}else elts.bg.animate({backgroundColor:settings.bgColor},{complete:callback,duration:400})}$($.fn.nyroModal.settings.openSelector).nyroModal()});function nyroModalDebug(msg,elts,settings){if(elts.full)elts.bg.prepend(msg+'<br />')}
$(document).ready(function() {
	$("a[href*='inline']:has(img)").attr("rel","nyro").nyroModal();
});

/** File: modules/timetracking/javascript/main.js **/

App.timetracking = {
  controllers : {},
  models      : {}
};

/**
 * Timetracking behavior
 */
App.timetracking.controllers.timetracking = {
  
  /**
   * Timetracking index action
   */
  index : function() {
    $(document).ready(function() {
      // Mass edit functionality
      var mass_edit = $('#mass_edit');
      
      var mass_edit_change = function () {
        if($('.time_record input:checked').length > 0) {
          mass_edit.find('select').attr('disabled', '');
          if(mass_edit.find('select').val() != '') {
            mass_edit.find('button').attr('disabled', '').removeClass('button_disabled');
          } else {
            mass_edit.find('button').attr('disabled', 'disabled').addClass('button_disabled');
          } // if
        } else {
          mass_edit.find('select').attr('disabled', 'disabled');
          mass_edit.find('button').attr('disabled', 'disabled').addClass('button_disabled');
        } // if
      } // mass_edit_change
      
      $('.time_record input').click(mass_edit_change);
      mass_edit.change(mass_edit_change).click(mass_edit_change);
      
      var form = $('#add_time_record_form');
      
      // Add time record form
      form.submit(function() {
        var add_form = $(this);
        var add_form_url = App.extendUrl(add_form.attr('action'), {async : 1});
       
        if(UniForm.validate(add_form, true)) {
          $('#new_record td.actions').prepend('<img src="' + App.data.indicator_url + '" alt="" />').find('button').hide();
          
          $(this).ajaxSubmit({
            url    : add_form_url,
            success: function(responseText) {
              $('#no_records').hide();
              $('#mass_edit').show();
              
              $('#timerecords table tbody tr:eq(0)').after(responseText);
              
              $('#new_record td.actions').find('img').remove();
              $('#new_record td.actions').find('button').show();
              
              $('#time_summary').val('');
              $('#time_hours').val('')[0].focus();
              
              var new_row = $('#timerecords table tbody tr:eq(1)');
              App.timetracking.records.init_mark_as_billed_link(new_row);
              App.timetracking.records.init_time_record_row(new_row, mass_edit);
              new_row.find('td').highlightFade();
              
              App.timetracking.records.rebuild_even_odd_classes();
            },
            error : function() {
              $('#new_record td.actions').find('img').remove();
              $('#new_record td.actions').find('button').show();
              
              $('#time_summary').val('');
              $('#time_hours').val('')[0].focus();
            }
          });
        } // if
        
        return false;
      });
      
      App.timetracking.records.init_mark_as_billed_link($('#timerecords table.timerecords'));
      App.timetracking.records.recalculate_total();
      
      // initialize time records table
      form.find('.time_record').each(function () {
        App.timetracking.records.init_time_record_row($(this), mass_edit);
      });      
      
      $('#records_submit').click(function () {
        hidden_form = $('<form method=post action="'+App.data.mass_update_url+'" style="display:none" id="hidden_mass_update"><input type="hidden" name="submitted" value="submitted" /><input type="hidden" value="'+mass_edit.find('select').val()+'" name="action" /></form>');
        hidden_form.prepend(form.find('.time_record input:checked').clone().attr('checked','checked'));
        $('body').append(hidden_form)
        $('#hidden_mass_update').submit();
      });
      
    });
  },
  
  /**
   * Prepare behavior for reports page
   *
   * @param void
   * @return null
   */
  reports : function() { 
    $(document).ready(function() {
      if($('#report_type').val() == 'custom') {
        $('#generate_report .select_date').show();
        $('#generate_report .date_separator').show();
        
      } else {
        $('#generate_report .select_date').hide();
        $('#generate_report .date_separator').hide();
      } // if
      
      $('#report_type').change( function() {
        if($(this).val() == 'custom') {
          $('#generate_report .select_date').show();
          $('#generate_report .date_separator').show();
        } else {
          $('#generate_report .select_date').hide();
          $('#generate_report .date_separator').hide();
        } // if
      });
      
      $('#generate_report').submit(function() {
        if($('#report_type').val() != 'custom') {
          $(this).find('.select_date').remove();
        } // if
        return true;
      });
      
      App.timetracking.records.init_mark_as_billed_link($('#records table'));
      App.timetracking.records.recalculate_total();
    });
  }
  
};

/**
 * Records management module
 */
App.timetracking.records = function() {
  
  /**
   * Public interface
   */
  return {
    
    /**
     * Make sure that even - odd classes are rebuilt when we add / remove 
     * records
     *
     * @param void
     * @return void
     */
    rebuild_even_odd_classes : function() {
      var counter = 0;
      $('table.timerecords tr.time_record').each(function() {
        var row = $(this);
        
        if(row.attr('id') != 'records_summary') {
          counter++;
        
          row.removeClass('even').removeClass('odd');
          if((counter % 2) > 0) {
            row.addClass('odd');
          } else {
            row.addClass('even');
          } // if
        } // if
      });
    }, // rebuild_even_odd_classes
    
    /**
     * Recalculate total time
     *
     * @param void
     * @return void
     */
    recalculate_total : function() {
      $('table.timerecords').each(function() {
        var wrapper = $(this);
        
        var reports_cell = wrapper.find('td.total');
        if(reports_cell.length > 0) {
          var total = 0;
          wrapper.find('td.hours').each(function() {
            total += parseFloat($(this).text());
          });
          
          reports_cell.text(App.lang('Total ') + total);
        } // if
      });
    }, // recalculate_total
    
    /**
     * Init mark as (not) billed link
     *
     * @param jQuery wrapper
     * @return void
     */
    init_mark_as_billed_link : function(wrapper) {
      wrapper.find('a.mark_time_record_as_billed').click(function() {
        var link = $(this);
        var parent_cell = link.parent();
        
        // Block additional clicks
        if(link[0].block_clicks) {
          return false;
        } else {
          link[0].block_clicks = true;
        } // if
        
        var img = link.find('img');
        var old_src = img.attr('src');
        
        img.attr('src', App.data.indicator_url);
        
        $.ajax({
          url     : App.extendUrl(link.attr('href'), {'async' : 1}),
          type    : 'POST',
          data    : {'submitted' : 'submitted'},
          success : function(response) {
            link.remove();
            parent_cell.prepend(response);
            App.timetracking.records.init_mark_as_billed_link(parent_cell);
            
            var link_href = link.attr('href');
            if(link_href.substr(link_href.indexOf('to=') + 3) == '1') {
              parent_cell.parent().addClass('billed');
            } else {
              parent_cell.parent().removeClass('billed');
            } // if
          },
          error   : function() {
            img.attr('src', old_src);
          }
        });
        
        return false;
      });
    }, // init_mark_as_billed_link
    
    /**
     * Initialize time record row
     */
    init_time_record_row : function (time_record_row, mass_edit) {
      var checkbox = time_record_row.find('input');
      checkbox.click(function () {
        if ($('table.timerecords').find('.time_record input:checked').length > 0) {
          mass_edit.enable();
        } else {
          mass_edit.disable();
        } // if
      });
    } // init_time_record_row
    
  };
  
}();

/**
 * Time popup behaviro
 */
App.TimePopup = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize timetracking widget
     *
     * @param string wrapper_id
     * @return void
     */
    init : function(wrapper_id) {
      var object_id = parseInt(wrapper_id.substr(19));
      
      $('#' + wrapper_id + ' a').click(function(e) {
        var link = $(this);
        var current_openner = link.parent();
        
        var indicator_image_src =  App.data.assets_url + '/images/indicator.gif';
        var time_popup_url = App.extendUrl(link.attr('href'), { 
          for_popup_dialog : 1 
        });
        
        App.ModalDialog.show('object_time', App.lang('Time'), $('<div><img src="' + indicator_image_src + '" alt="" /> ' + App.lang('Loading...') + '</div>').load(time_popup_url, function() {
          
          /**
           * Initialize popup behavior
           *
           * @param String popup_wrapper_id
           */
          var init_popup = function(popup_wrapper_id) {
            var wrapper = $('#' + popup_wrapper_id);
          
            wrapper.find('p.object_time_add_link a').click(function() {
              $(this).parent().hide();
              wrapper.find('div.object_time_add').show('fast', function() {
                wrapper.find('div.time_popup_hours_wrapper input')[0].focus();
              });
              
              return false;
            });
            
            wrapper.find('button.object_time_cancel_button').click(function() {
              wrapper.find('p.object_time_add_link').show();
              wrapper.find('div.object_time_add').hide();
              
              return false;
            });
            
            wrapper.find('form').submit(function() {
              var form = $(this);
              var popup_wrapper = form.parent().parent();
              
              form.block(App.lang('Working...'));
              
              form.ajaxSubmit({
                success : function(response) {
                  popup_wrapper.empty();
                  popup_wrapper.append(response);
                  popup_wrapper.find('div.object_time_popup_details dl span.time').highlightFade();
                  
                  if(current_openner.attr('class').indexOf('with_text') && popup_wrapper.find('div.object_time_popup_details dl dd.object_time').length > 0 && popup_wrapper.find('div.object_time_popup_details dl dd.tasks_time').length > 0) {
                    var object_time = App.parseNumeric(popup_wrapper.find('div.object_time_popup_details dl dd.object_time span.time').text());
                    var tasks_time = App.parseNumeric(popup_wrapper.find('div.object_time_popup_details dl dd.tasks_time span.time').text());
                    
                    if(object_time > 0 && tasks_time > 0) {
                      var total_time = object_time + tasks_time;
                      
                      ':total hours logged - :object_time for the ticket and :tasks_time for tasks'
                      current_openner.find('span.time_widget_text').text(App.lang(':total hours logged - :object_time for the ticket and :tasks_time for tasks', {
                        'total'       : parseFloat(total_time.toFixed(2)),
                        'object_time' : parseFloat(object_time.toFixed(2)),
                        'tasks_time'  : parseFloat(tasks_time.toFixed(2))
                      }));
                    } else {
                      current_openner.find('span.time_widget_text').text(App.lang(':total hours logged', {
                        'total' : parseFloat(object_time.toFixed(2))
                      }));
                    } // if
                  } // if
                  
                  current_openner.find('img').attr('src', App.data.assets_url + '/images/clock-small.gif');
                  
                  init_popup('object_time_popup_' + object_id);
                }
              });
              
              return false;
            });
          };
          
          init_popup('object_time_popup_' + object_id);
        }), {
          buttons : false,
          width: 450
        });
        return false;
      });
    }
    
  };
  
}();

App.timetracking.TimeReport = function() {
  
  // Public interface
  return {
    
    /**
     * Initialize report page
     */
    init : function() {
      $('#time_report_select select').change(function() {
        var report_url = $(this).val();
        if(report_url != location.href) {
          $(this).after(' ' + App.lang('Loading ...')).attr('disabled', 'disabled');
          location.href = report_url;
        } // if
      });
      
      $('#time_report_options a').hover(function() {
        $('#time_report_options span.tooltip').text($(this).attr('title'));
      }, function() {
        $('#time_report_options span.tooltip').text('');
      }); 
      
      $('#toggle_report_details').click(function() {
        $('#time_report_details').toggle('fast');
        return false;
      });
    }
    
  };
  
}();

/**
 * Add / Edit time report form behavior
 */
App.timetracking.TimeReportForm = function() {
  
  /**
   * Form instance
   *
   * @var jQuery
   */
  var form;
  
  // Public interface
  return {
    
    /**
     * Initialize time report form
     *
     * @param string form_id
     * @param string partial_generator_url
     * @return void
     */
    init : function(form_id, partial_generator_url) {
      form = $('#' + form_id);
      
      form.find('select.report_async_select').change(function() {
        var select = $(this);
        var row = select.parent().parent();
        var cell_additional = row.find('td.report_select_additional');
        var option = select.find('option[value=' + select.val() + ']');
        
        if(option.attr('class') == 'report_async_option') {
          cell_additional.each(function() {
            cell_additional.empty().append('<img src="' +  App.data.indicator_url + '" alt="" />');
            $.ajax({
              url     : partial_generator_url,
              type    : 'GET',
              data    : {
                'select_box'   : select.attr('name'),
                'option_value' : option.val()
              },
              success : function(response) {
                cell_additional.empty();
                cell_additional.append(response);
              },
              error   : function() {
                cell_additional.empty();
              }
            });
          })
        } else {
          cell_additional.empty();
        }
      })
    }
    
  };
  
}();

/** File: modules/tickets_reopen/javascript/main.js **/



App.widgets.ticket_reopen = function(){


  return {
    /**
     * Open chats on sections
     *
     * @param object chats
     */
    init : function(){

        $('document').ready(function(){
            text = '<label for="reopen" class="checkbox_is_reopen" style="width:95%"><input type="checkbox" class="inline" name="reopen" checked value="1" />Reopen ticket with this comment</label>';
            $('.real_textarea .ctrlHolder').eq(0).after(text);
        });

    }

  }
}();

/** File: modules/hide_people/javascript/main.js **/

App.hide_people = {
  controllers : {},
  models      : {}
};

/**
 * Main hide_people JS file
 */
$(document).ready(function() { 
	if (App.data.hide_people === true) {
		$("#page_tab_people").remove();
		$("#menu_item_people").remove();
		$("#menu_group_main li:first").removeClass("middle").addClass("first");
		if ($("#menu_group_main li:first").hasClass("active")) {
			$("#menu_group_main li:first .additional a").css("background-position", "-100px bottom");
		} else {
			$("#menu_group_main li:first .additional a").css("background-position", "-100px top");
		}
	}
});

/** File: modules/xprivate_comment/javascript/main.js **/

App.private_comment = {
  controllers : {},
  models      : {}
};

/**
 * Tickets behavior
 */

App.private_comment.controllers.tickets = {
  /**
   * Ticket index page behavior
   */
  view : function() {

        $('document').ready(function(){
            if(App.data.user_can_see_private == 1){
                $('.button_add.attachments').parent().before('<label class="checkbox_is_private" style="width:50%"><input type="checkbox" class="inline input_checkbox" value="true" id="isPrivate" name="comment[is_private]"> Private comment</label>');
                if($('.checkbox_complete').html() == void 0){
                    $('.checkbox_is_private').css('width','100%');
                }
                $('.checkbox_is_private').next().attr('style','clear:both');

                url = App.data.path_info_through_query_string ?
                          App.extendUrl(App.data.url_base, { path_info : 'projects/'+App.data.active_project_id+'/tickets/'+App.data.active_ticket_id+'&filter='}) :
                          App.data.url_base + 'projects/'+App.data.active_project_id+'/tickets/'+App.data.active_ticket_id+'?filter=';

                App.widgets.AddPrivateCommentsSort.init(url);
            }
        });


  }

};

/**
 * Tickets behavior
 */

App.private_comment.controllers.discussions = {
  /**
   * Ticket index page behavior
   */
  view : function() {

        $('document').ready(function(){
            if(App.data.user_can_see_private == 1){

                $('.blockLabels .ctrlHolder').after('<label class="checkbox_is_private"><input type="checkbox" class="inline input_checkbox" value="true" id="isPrivate" name="comment[is_private]"> Private comment</label>');
                $('.checkbox_is_private').next().attr('style','clear:both');
                
                url = App.data.path_info_through_query_string ?
                      App.extendUrl(App.data.url_base, { path_info : 'projects/'+App.data.active_project_id+'/discussions/'+App.data.active_discussion_id+'&filter=' }) :
                      App.data.url_base + 'projects/'+App.data.active_project_id+'/discussions/'+App.data.active_discussion_id+'?filter=';

                App.widgets.AddPrivateCommentsSort.init(url);
            }
        });


  }

};

App.private_comment.controllers.pages = {
  /**
   * Ticket index page behavior
   */
  view : function() {

        $('document').ready(function(){
            if(App.data.user_can_see_private == 1){

                $('.blockLabels .ctrlHolder').after('<label class="checkbox_is_private"><input type="checkbox" class="inline input_checkbox" value="true" id="isPrivate" name="comment[is_private]"> Private comment</label>');
                $('.checkbox_is_private').next().attr('style','clear:both');

                url = App.data.path_info_through_query_string ?
                      App.extendUrl(App.data.url_base, { path_info : 'projects/'+App.data.active_project_id+'/pages/'+App.data.active_page_id+'&filter=' }) :
                      App.data.url_base + 'projects/'+App.data.active_project_id+'/pages/'+App.data.active_page_id+'?filter=';

                App.widgets.AddPrivateCommentsSort.init(url);
            }
        });


  }

};

App.private_comment.controllers.files = {
  /**
   * Ticket index page behavior
   */
  view : function() {

        $('document').ready(function(){
            if(App.data.user_can_see_private == 1){

                $('.blockLabels .ctrlHolder').after('<label class="checkbox_is_private"><input type="checkbox" class="inline input_checkbox" value="true" id="isPrivate" name="comment[is_private]"> Private comment</label>');
                $('.checkbox_is_private').next().attr('style','clear:both');

                url = App.data.path_info_through_query_string ?
                      App.extendUrl(App.data.url_base, { path_info : 'projects/'+App.data.active_project_id+'/files/'+App.data.active_file_id+'&filter=' }) :
                      App.data.url_base + 'projects/'+App.data.active_project_id+'/files/'+App.data.active_file_id+'?filter=';

                App.widgets.AddPrivateCommentsSort.init(url);
            }
        });


  }

};

App.widgets.AddPrivateCommentsSort = {
    init : function(url){

                var text = '<div class="sort_comments">\n\
                                        Display Comments <select id="sort" name="sort">\n\
                                                <option value="2"';
                    text +=                         (App.data.comments_filter_id == 2) ? 'selected': '';
                    text +=                             '>All</option>\n\
                                                <option value="1"';
                    text +=                         (App.data.comments_filter_id == 1) ? 'selected': '';
                    text +=                             '>Visible</option>\n\
                                                <option value="0"';
                    text +=                         (App.data.comments_filter_id == 0) ? 'selected': '';
                    text +=                             '>Private</option>\n\
                                              </select>\n\
                                        </div>';

                $("#comments").before(text);

                $("#sort").change(function(){
                    url += $(this).val();
                    location.href = url;

                });
    }
};

App.resources.controllers.comments = {
    
  edit : function(){
        $('document').ready(function(){
            if(App.data.user_can_see_private == 1){
                text = '<label class="checkbox_is_private" style="width:95%">\n\
                            <input type="checkbox"';
                text += (App.data.active_comment_visibility == 0) ? 'checked=checked' : '';
                text +=         ' class="inline input_checkbox" value="true" id="isPrivate" name="comment[is_private]">\n\
                             Private comment\n\
                        </label>';
                $('.ctrlHolder').after(text);
            }
        });
  }
};

/** File: modules/files/javascript/main.js **/

App.files = {
  controllers : {},
  models      : {}
};

/**
 * Main files JS file
 */
App.files.controllers.files = {
  
  /**
   * Index page behavior
   */
  index : function() {
    $(document).ready(function() {
      $('#file_list').checkboxes();
    });
  },
  
  /**
   * Initial file details page behavior
   */
  view : function() {
    $(document).ready(function() {
      $('div.file_revisions').each(function() {
        var wrapper = $(this);
        
        /**
         * Reindex table rows
         */
        var reindex_odd_even_rows = function() {
          var counter = 1;
          wrapper.find('tr').each(function() {
            var row = $(this);
            row.removeClass('even').removeClass('odd');
            if(counter % 2 == 1) {
              row.addClass('odd');
            } else {
              row.addClass('even');
            } // if
            counter++;
          });
        };
        
        wrapper.find('td.options a').click(function() {
          var link = $(this);
            
          // Block additional clicks
          if(link[0].block_clicks) {
            return false;
          } else {
            link[0].block_clicks = true;
          } // if
          
          var img = link.find('img');
          var old_src = img.attr('src');
          
          img.attr('src', App.data.indicator_url);
          
          $.ajax({
            url     : link.attr('href'),
            type    : 'POST',
            data    : {'submitted' : 'submitted'},
            success : function() {
              link.parent().parent().remove();
              reindex_odd_even_rows();
              if(wrapper.find('table tr').length < 1) {
                wrapper.find('div.body').append('<p class="details center files_moved_to_trash">' + App.lang('All revision moved to Trash') + '</p>');
              } // if
            },
            error   : function() {
              img.attr('src', old_src);
            }
          });
          
          return false;
        });
      });
    });
  },
  
  /**
   * Upload files behavior
   */
  upload : function() {
    var rows_for_upload = new Array();
    
    var current_row_id = 0;
    var current_row;
    
    var main_form;
    var upload_form;
    var upload_table;
    
    var summary_table;
    
    var uploads_ok = 0;
    var uploads_failed = 0;
    
    /**
     * function to call to submit multiupload form
     */
    var submit_multiupload_form = function () {
      file_id = 0;
      start_upload();
    };
    
    /**
     * Reindex table rows (set odd,even classes and add row #)
     */
    var reindex_table_rows = function () {
      var counter = 0;
      $('tr', upload_table).each(function () {
        row = $(this);
        if ((counter % 2) == 0 ) {
          row.attr('class', 'odd');
        } else {
          row.attr('class', 'even');
        } // if
        $('.number', row).text('#'+counter);
        counter++;
      });
    } // reindex_table_rows
    
    /**
    * Init row in upload table (add remove button functionality)
    */
    var init_multiupload_row = function (row) {
      if (row) {
        $('.button_remove', row).click(function () {
          if ($('tr', upload_table).length > 2) {
            $(this).parent().parent().remove();
            reindex_table_rows();
          } // if
        });
        $('td.description input:eq(0)' ,row).keydown(function(e) {
          if (e.keyCode == 13) {
            submit_multiupload_form();
            return false;
          } // if
        });
      } // if
    } // init_multiupload_row
    
    /**
     * set up hidden form for upload (based on curently selected row from upload table)
     * and do the upload
     */
    var upload_single_file = function () {
      var current_row = rows_for_upload[current_row_id];
      
      // if no more uploads are left, then do some stuff like showing upload statistics
      if (!current_row) {
        var params = {
          files_uploaded : uploads_ok,
          files_failed : uploads_failed
        }
        
        // form result message dependable of number failed and number of succeeded uploads
        if (uploads_ok && uploads_failed) {
          var upload_message = App.lang("Done, :files_uploaded files uploaded and :files_failed uploads failed<br />", params);
        } else if (uploads_ok) {
          var upload_message = App.lang("Done, :files_uploaded files uploaded<br />", params);
        } else {
          var upload_message = App.lang("Done, :files_failed uploads failed<br />", params);
        } // if
        
        // generates links for view files and for multiupload files
        var category_id = $("#multiupload_parent_id").val();
        var upload_more_files_url = main_form.attr('action');
        if (category_id) {
          var files_section_url = App.extendUrl(App.data.files_section_url, { 
            'category_id' :  category_id
          });
          upload_more_files_url = App.extendUrl(upload_more_files_url, { 
            'category_id' :  category_id
          });
        } else {
          var files_section_url = App.data.files_section_url;
        } // if

        upload_message += App.lang('Upload <a href=":upload_url">more files</a> or go back to <a href=":files_url">Files</a> section', {
          files_url : files_section_url,
          upload_url : upload_more_files_url
        });
  
        $('#page_content').append("<div class='important_block'>" + upload_message + "</div>");
        return true;
      } // if
      
      // remove input field from hidden form
      var previous_input = $("input[name=attachment]", upload_form);
      if (previous_input) {
        previous_input.remove();
      } // if
      
      // select current input
      var this_file_file = $("input:eq(0)", current_row);
      var this_file_body = $("input:eq(1)", current_row);
      
      // set progress indicator
      $("tr:eq(" + (current_row_id + 1) + ") img:eq(0)", summary_table).attr('src', App.data.indicator_url);
      
      // move file input from old form to new form (we cannot use clone() function because of jquery explorer bug)
      this_file_file.prependTo(upload_form);
      $('#multiupload_body').val(this_file_body.val());
            
      // submit current form
      upload_form.submit();
      current_row_id++;
      
      return false;
    } // upload_single_file
    
    /**
     * Start upload (copy selected common parameters from main form to hidden
     * upload form, and call upload function for first row from upload table
     */
    var start_upload = function () {
      main_form.hide();
      
      // create upload summary table      
      $('#page_content').append('<table id="upload_table_result" class="common_table"><tr><th></th><th colspan="2">' + App.lang('Uploading files') + '</th></tr></table>');
      summary_table = $('#upload_table_result');
      $('tr', upload_table).each(function () {
        var row = $(this);
        if ($('input',row).val()) {
          rows_for_upload.push(row);
          summary_table.append(
            '<tr>' +
              '<td class="indicator"><img alt="status" src="' + App.data.pending_indicator_url + '"</td>' +
              '<td class="filename">' + $('input',row).val() + '</td>' +
              '<td class="log"></div>' +
            '</tr>'
          );
        } // if
      });
      
      // set category and other stuff      
      $("#multiupload_parent_id").val($("#main_form #fileParent").val());
      $("#multiupload_milestone_id").val($("#main_form #fileMilestone").val());
      $("#multiupload_tags").val($("#main_form #fileTags").val());
      
      $("#multiupload_visibility").val(1);
      var visiblity_field_1 = $("#main_form #fileVisibility_1");
      // Checkbox?
      if(visiblity_field_1.attr('type') == 'radio') {
          // acHack additions
    	  if ($("#main_form #fileVisibility_1")[0].checked) {
	         $("#multiupload_visibility").val(1);
    	  }else if($("#main_form #fileVisibility_0")[0].checked) {
	        $("#multiupload_visibility").val(0);
	      }else if($("#main_form #fileVisibility_-1")[0].checked){
	        $("#multiupload_visibility").val(-1);
	      }
          /*
          if (visiblity_field_1[0].checked) {
            $("#multiupload_visibility").val(1);
          } else {
            $("#multiupload_visibility").val(0);
          } // if
          */  
          // Over: acHack additions
    	  
	        
        
      // Nope. Hidden
      } else {
        $("#multiupload_visibility").val(visiblity_field_1.val());
      } // if
      
      $('.people', upload_form).remove();
      
      $("#main_form .select_asignees_inline_widget .company_user input:checked").each(function () {
        upload_form.append("<input type='hidden' name='notify_users[]' class='people' value='" + $(this).val() + "' />");
      });
      upload_single_file();
    } // start_upload
    
    /**
     * set up basic stuff when page finishes loading
     */
    $(document).ready(function() {
      main_form = $('#main_form');
      upload_form = $('#multiupload_form');
      upload_table = $('.multiupload_table');
      
      // init table rows
      $('tr', upload_table).each(function () {
        init_multiupload_row($(this));
      });
      
      // add "new file" button handler
      $('.button_add', main_form).click(function () {
        image_src = $('tr:eq(1) .button_column img:eq(0)', upload_table).attr('src');
        upload_table.append(''+
        '<tr>' +
          '<td class="number"></td>' +
          '<td class="input"><input type="file" value="" name="attachment"/></td>' +
          '<td class="description"><input type="text" name="file[body]" /></td>' +
          '<td class="button_column"><img src="' + image_src + '" class="button_remove" /></td>' +
        '</tr>');
        init_multiupload_row(row.next());
        reindex_table_rows();
        return false;
      });
      
      // reindex table rows
      reindex_table_rows();
      
      // define upload_form behaviour
      upload_form.ajaxForm({ 
        success:    function(response) {
          /*
            because of wodoo magic with ajaxForm and file uploads, we can't use 
            error and success callbacks as we used to use them. In this special case
            error callback is called only when request is failed, not when server
            returns some of error headers, so we need to set up our serverside script
            to return strings 'error' when there is some http error, and string
            'success' if return is http ok.
          */
          if (response!=='success') {
            $("tr:eq(" + (current_row_id) + ") img:eq(0)", summary_table).attr('src', App.data.error_indicator_url);
            uploads_failed++;
          } else {
            $("tr:eq(" + (current_row_id) + ") img:eq(0)", summary_table).attr('src', App.data.ok_indicator_url);
            uploads_ok++;
          } // if
          upload_single_file();
        } ,
        error:      function() {
          $("tr:eq(" + (current_row_id) + ") img:eq(0)", summary_table).attr('src', App.data.error_indicator_url);
          uploads_failed++;
          upload_single_file();
        }
      });
      
      // upload button functionality
      $('#upload_files').click(function () {
        submit_multiupload_form();
      });
    });
    
  }
  
}

/** File: modules/tickets/javascript/main.js **/

App.tickets = {
  controllers : {},
  models      : {}
};

/**
 * Tickets behavior
 */
App.tickets.controllers.tickets = {
  /**
   * Ticket index page behavior
   */
  index : function() {    
    $(document).ready(function () {
      reindex_tickets_table = function (table) {
        var counter = 0;
        table.find('li').each(function () {
          var row = $(this);
          if (row.html() && !row.is('.empty_row') && !row.is('.ui-sortable-helper')) {
            if ((counter % 2) == 0) {
              row.removeClass('even');
              row.addClass('odd');
            } else {
              row.removeClass('odd');
              row.addClass('even');
            } // if
            counter ++;
          } // if
        });
        if (counter<1) {
          table.find('.empty_row').show();
        } else {
          table.find('.empty_row').hide();
        } // if
      } // reindex_tickets_table

      if (App.data.can_manage_tickets) {
        $('.tickets_list').sortable({
          axis : 'y',      
          cursor: 'move',
          delay: 3,
          placeholder: 'drag_placeholder',
          forcePlaceholderSize : true,
          revert: false,
          connectWith: ['.tickets_list'],
          items: 'li.sort',
          update : function (e, ui) {
            var sortable_list = ui.item.parent();
            reindex_tickets_table(sortable_list);
            var reorder_data = sortable_list.find('input').serialize();
            if (reorder_data) {
              reorder_data+='&submitted=submitted';
              $.ajax({
                type: "POST",
                url: sortable_list.attr('reorder_url'),
                data: reorder_data
              });
            } // if
          },
          over: function (table_object,ui) {
            $(this).addClass('dragging');
          },
          out: function (table_object,ui) {
            $(this).removeClass('dragging');
          }
        });
      } // if
    });
  },
  
  /**
   * View ticket behavior
   */
  view : function() {
    $(document).ready(function() {
      $('#show_all_ticket_changes a').click(function() {
        var link = $(this);
        if(link.attr('loading') == 'loading') {
          return false;
        } else {
          link.attr('loading', 'loading');
        } // if
        
        var wrapper = $('#ticket_changes_wrapper');
        
        wrapper.block(App.lang('Loading...'));
        
        $.ajax({
          url : App.extendUrl(link.attr('href'), { async : 1}),
          success : function(response) {
            wrapper.empty().append(response).unblock().highlightFade();
            $('#show_all_ticket_changes').remove();
          },
          error : function() {
            wrapper.unblock();
            alert(App.lang('Failed to load all ticket changes'));
          }
        });
        
        return false;
      });
    });
  }
  
};

/* acHack additions */
App.tickets.controllers.comments = function() {
	/**
	 * Remember focused cell ID
	 */
	var current_cell_id = null;
	/**
	 * Focus single cell
	 */
	var focus_cell = function(cell) {
	    cell.find('div.content_container').slideDown();
	    cell.find('span.content_expander').addClass('collapsed');
	};
	/**
	 * Unfocus cell
	 */
	var unfocus_cell = function(cell) {
	    cell.find('div.content_container').slideUp();
	    cell.find('span.content_expander').removeClass('collapsed');
	};
	/**
	 * Toogle show hide
	 */
	var toggle_details = function(cell) {
		var $cell = $(cell).parent().parent();

	    if (current_cell_id) {
	        if ($cell.attr('id') == current_cell_id) {
	        	unfocus_cell($cell);
	        	
	            current_cell_id = null;
	        } else {
	            unfocus_cell($('#' + current_cell_id));
	            focus_cell($cell);
	            
	            current_cell_id = $cell.attr('id');
	        }
	    } else {
	        focus_cell($cell);
	
	        current_cell_id = $cell.attr('id');
	    }
	};
	
	return {
		init : function() {
			$('#tickets span.content_expander').click(function() {
				toggle_details(this);
		        return false;
		    });
		}
	}
}();

/**
 * Attach behavior to DOM
 */
$(document).ready(function() {
    App.tickets.controllers.comments.init();
});
/* Over: acHack additions */

/** File: modules/pages/javascript/main.js **/

App.pages = {
  controllers : {},
  models      : {}
};

/**
 * Revisions table behavior module
 */
App.pages.revisions_table = function() {
  
  // Public interface
  return {
    rebuild_even_odd_classes : function() {
      var counter = 0
      $('table.revisions_table tr').each(function() {
        counter++;
        
        var row = $(this);
        row.removeClass('even').removeClass('odd');
        if((counter % 2) > 0) {
          row.addClass('odd');
        } else {
          row.addClass('even');
        } // if
      });
    }
  };
  
}();

/**
 * reorder page behavior module
 */
App.pages.reorder_page = function() {
  
  // Public interface
  return {
    init  : function () {
      reorder_tree = new tree_component();
      reorder_tree.init($("#pages_reorder"),{
        ui    : {
          context     : false,
          theme_path  : App.data.assets_url + '/images/tree_component/',
          theme_name  : 'default'
        },
        rules : {
          draggable : 'all',
          dragrules : 'all',
          clickable   : "none",
          renameable  : "none",
          deletable   : "none",
          creatable   : "none"
        }
      });
      
      // force expand all pages
      $("#pages_reorder").find('li').each(function () {
        reorder_tree.open_branch($(this),true);
      });
      
      $('#reorder_form button:first').click(function () {
        var inputs = '';
        $('#pages_reorder ul li').each(function () {
          var li_element = $(this);
          var page_id = li_element.find('input:first').attr('value');
          var parent_li = li_element.parent().parent();
          if (parent_li.is('li')) {
            var parent_page_id = parent_li.find('input:first').attr('value');
          } else {
            var parent_page_id = 0;
          } // if
          inputs+= '<input type="hidden" name="ordered_pages['+page_id+']" value="'+parent_page_id+'" />';
        });
        
        inputs+= '<input type="hidden" name="submitted" value="submitted" />';
        var submit_url = $('#reorder_form').attr('action');
        
        if (!App.data.is_assync_call) {
          var hidden_form = $("<form method='post' action='"+submit_url+"' style='display:none' id='hidden_form'>"+inputs+"</form>");
          $('body').append(hidden_form);
          $('#hidden_form').submit();
          return false;
        } else {
          $('#reorder_form').before('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').hide();
          inputs = $(inputs);
          $('#page_content').block();
          App.ModalDialog.close()
          $.ajax({
            data    : inputs,
            url     : App.extendUrl(submit_url, {async : 1, skip_layout : 1}),
            type  : 'post',
            success : function (response) {
              $('#page_content').html(response);
            }
          });
          return false;
        } // if
      }) // click      
    }  
  };
  
}();

/**
 * Pages controller behavior
 */
App.pages.controllers.pages = {
  /**
   * Index page behaviour
   *
   * @param void
   * @return void
   */
  index : function () {
    $(document).ready(function () {
      $('#reorder_pages_button').click(function () {
        App.data.is_assync_call = true;
        var assync_url = App.extendUrl($(this).attr('href'), { async: 1 });
  
        App.ModalDialog.show('reorder_pages_dialog', App.lang('Reorder Pages'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(assync_url), {
          buttons : null 
        });
        return false;
      });
    });
  },
  
  /**
   * Prepare view page behavior
   *
   * @param void
   * @return void
   */
  view : function() {
    $(document).ready(function() {
      $('table.revisions_table a.remove_revision').click(function() {
        var link = $(this);
      
        // Block additional clicks
        if(link[0].block_clicks) {
          return false;
        } else {
          link[0].block_clicks = true;
        } // if
        
        if(confirm(App.lang('Are you sure that you want to delete this page version? There is no undo!'))) {
          var img = link.find('img');
          var old_src = img.attr('src');
          
          img.attr('src', App.data.indicator_url);
          
          $.ajax({
            url     : App.extendUrl(link.attr('href'), {'async' : 1}),
            type    : 'POST',
            data    : {'submitted' : 'submitted'},
            success : function() {
              link.parent().parent().remove();
              App.pages.revisions_table.rebuild_even_odd_classes();
            },
            error   : function() {
              img.attr('src', old_src);
            }
          });
        } // if
        
        return false;
      });
    });
    
  },
  
  /**
   * Compare page behavior
   */
  compare_versions : function() {
    $(document).ready(function() {
      var loading = false;
      
      $('#page_compare form').submit(function() {
        if(loading) {
          return false; // let the last operation be completed...
        } // if
        
        var form = $(this);
        
        var new_version = $('#new_version_select').val();
        var old_version = $('#old_version_select').val();
        
        if(new_version == old_version) {
          alert(App.lang('Please select different versions!'));
          return false;
        } // if
        
        loading = true;
        
        var compared_versions_wrapper = $('#compared_versions');
        compared_versions_wrapper.block(App.lang('Loading...'));
        form.find('select').attr('disabled', 'disabled');
        
        $.ajax({
          type : 'GET',
          url : App.extendUrl(App.data.compare_pages_url, {
            'new'   : new_version,
            'old'   : old_version,
            'async' : 1
          }),
          success : function(response) {
            compared_versions_wrapper.find('table').remove();
            compared_versions_wrapper.append(response);
            compared_versions_wrapper.unblock();
            form.find('select').attr('disabled', '');
            compared_versions_wrapper.highlightFade();
            
            loading = false;
          },
          error : function() {
            compared_versions_wrapper.unblock();
            
            loading = false;
          }
        });
        
        return false;
      });
    });
  }
  
};

/** File: modules/quick_access/javascript/main.js **/

$(window).load(function () {

    $('#top .container').prepend('<div id="logged_user" class="quick_access"><span class="inner"><img src="'+App.data.assets_url+'/modules/quick_access/images/icon.png" /><a id="quick_access_button" href="#">' + App.lang('Quick Access') + '</a></span></div>');

    //App.data.quick_access_url = App.data.url_base + 'quick-access';

    var quick_access_url = App.data.path_info_through_query_string ? 
      App.extendUrl(App.data.url_base, { path_info : 'quick-access' }) :
      App.data.url_base + '/quick-access';

    App.data.quick_access_url = quick_access_url;

    // Jump to project button
    $('#quick_access_button').click(function() {
        //alert( App.data.url_base);
        App.ModalDialog.show('quick_access_url', App.lang('Quick Access'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(App.data.quick_access_url), {});
        App.ModalDialog.setWidth(560);
        return false;
    });
});

/** File: modules/project_exporter/javascript/main.js **/

App.project_exporter = {
  controllers : {},
  models      : {}
};

/**
 * Project Exporter client side behaviour
 */
App.project_exporter.controllers.project_exporter = {
  
  /**
   * Index page bahaviour
   *
   */ 
  index : function () {
    $(document).ready(function() {
      var global_container = $('#project_exporter_container');
      var additional_controls = global_container.find('#additional_controls');
      var button_holder = global_container.find('.buttonHolder');
      var main_table = global_container.find('#main_table');
      
      button_holder.find('button:first').click(function () {
        additional_controls.hide();
        button_holder.hide();
 
        main_table.find('input:not(:checked)').each(function () {
          $(this).parents('tr:first').hide();
        });
 
        var modules = new Array();
        var loop = 0;
        main_table.find('input:checked').each(function () {
          var current_checkbox = $(this);
          var current_row = current_checkbox.parents('tr:first');
 
          if ((loop % 2) == 1) {
          current_row.removeClass('odd');
          current_row.addClass('even');
          } else {
          current_row.removeClass('even');
          current_row.addClass('odd');            
          } // if
 
          modules.push({
            module : current_row.attr('module'),
            url : current_row.attr('export_url')
          });
 
          current_checkbox.before('<img src="' + App.data.pending_indicator_url + '" alt="." />');
          current_checkbox.remove();
 
          loop++;
        });
 
        export_project(modules, additional_controls.find('#visibility input:checked').val(), additional_controls.find('#compress_container input:checked').length);
        return false;
      });
      
      /**
       * Start exporting project
       *
       * @param array modules
       * @param integer visibility
       * @param boolean compress_output
       * @return null
       */
      var export_project = function (modules, visibility, compress_output) {
      var response_obj;
      var imploded_modules = new Array();
      for (var counter=0; counter < modules.length; counter++) {
        var current_module = modules[counter].module;
        if (current_module != 'finalize') {
        imploded_modules.push(current_module);
        } // if
      } // for
      imploded_modules = imploded_modules.join(',');
      modules = modules.reverse();
 
      /**
       * Check if there is warning
       *
       * @param object execution_log
       * @return null
       */
      var warning_exists = function (execution_log) {
        if (execution_log == undefined) return true;
        for (x=0; x<execution_log.length; x++) {
        if (execution_log[x].status == 1) {
          return true
        } // if
        } // for
        return false;
      } // warning_exists
 
      /**
       * Export single module and ping next one
       *
       * @param object module
       * @return null
       */
      var export_module = function (module, visibility, compress_output) {
        if (typeof module != 'object') {
        if (compress_output && !warning_exists(response_obj.log)) {
          var message_block = 
          '<div id="download_link_block" style="display:block">' +
          App.lang('Download project archive using following link') + 
          ':<br /><div id="download_link">' + '<a href="'+App.data.download_url+'">'+App.data.download_url+'</a></div>' +
          '</div>';
        } else {
          var message_block = 
          '<div id="download_link_block" style="display:block">' +
          App.lang('Exported project is located') + 
          ':<br /><div id="download_link"><strong>' + App.data.download_ftp_url + '</strong></a></div>' +
          '</div>';              
        }
        main_table.after(message_block);
        return false;
        } // if
 
        row_status_indicator = main_table.find('#module_'+module.module+' .status_indicator img');
        row_log_field = main_table.find('#module_'+module.module+' .module_log');
 
        // indicate progress
        row_status_indicator.attr('src', App.data.indicator_url);
 
        var ping_url = App.extendUrl(module.url, {visibility : visibility, modules : imploded_modules, compress : compress_output})
 
        // do the magic
        $.ajax({
        url: ping_url,
        type: "GET",
        success: function (response) {
          response_obj = response;
          if (response_obj.error_count > 0) {
          row_status_indicator.attr('src', App.data.error_indicator_url);
          } else if ((response_obj.log.length > 0) && (warning_exists(response_obj.log))) {
          row_status_indicator.attr('src', App.data.warning_indicator_url);
          } else {
          row_status_indicator.attr('src', App.data.ok_indicator_url);
          } // if
 
          if (response_obj.log.length > 0) {
          status_message = new Array();
          for (x=0; x<response_obj.log.length; x++) {
            message = response_obj.log[x].message;
            message_status = response_obj.log[x].status;
            if (message_status == 1) {
            message = '<span class="status_warning">'+message+'</span>';
            } else if (message_status == 2) {
            message = '<span class="status_ok">'+message+'</span>';
            } else {
            message = '<span class="status_error">'+message+'</span>';
            }
            status_message.push(message);
          }
          row_log_field.html(status_message.join("<br />"));
          } // if
          export_module(modules.pop(), visibility, compress_output);         
        }
        })
 
      } // if
 
      export_module(modules.pop(), visibility, compress_output);
      } // if
    }) // document ready
  }
};

/** File: modules/quick_add_plus/javascript/main.js **/

App.quick_add_plus = {
  controllers : {},
  models      : {}
};

$(document).ready(function() {
	
	if(App.compareVersions(App.data.ac_version, '2.3.2') == 1) {
		
		(function(jQuery){
			
			jQuery.hotkeys = {
				version: "0.8",

				specialKeys: {
					8: "backspace", 9: "tab", 13: "return", 16: "shift", 17: "ctrl", 18: "alt", 19: "pause",
					20: "capslock", 27: "esc", 32: "space", 33: "pageup", 34: "pagedown", 35: "end", 36: "home",
					37: "left", 38: "up", 39: "right", 40: "down", 45: "insert", 46: "del", 
					96: "0", 97: "1", 98: "2", 99: "3", 100: "4", 101: "5", 102: "6", 103: "7",
					104: "8", 105: "9", 106: "*", 107: "+", 109: "-", 110: ".", 111 : "/", 
					112: "f1", 113: "f2", 114: "f3", 115: "f4", 116: "f5", 117: "f6", 118: "f7", 119: "f8", 
					120: "f9", 121: "f10", 122: "f11", 123: "f12", 144: "numlock", 145: "scroll", 191: "/", 224: "meta"
				},
			
				shiftNums: {
					"`": "~", "1": "!", "2": "@", "3": "#", "4": "$", "5": "%", "6": "^", "7": "&", 
					"8": "*", "9": "(", "0": ")", "-": "_", "=": "+", ";": ": ", "'": "\"", ",": "<", 
					".": ">",  "/": "?",  "\\": "|"
				}
			};

			function keyHandler( handleObj ) {
				// Only care when a possible input has been specified
				if ( typeof handleObj.data !== "string" ) {
					return;
				}
				
				var origHandler = handleObj.handler,
					keys = handleObj.data.toLowerCase().split(" ");
			
				handleObj.handler = function( event ) {
					// Don't fire in text-accepting inputs that we didn't directly bind to
					if ( this !== event.target && (/textarea|select|embed|object/i.test( event.target.nodeName ) ||
						 event.target.type === "text" || event.target.type === "password") ) { // fix for the flash & password fields: Apps Magnet > Malay
						return;
					}
					
					// Keypress represents characters, not special keys
					var special = event.type !== "keypress" && jQuery.hotkeys.specialKeys[ event.which ],
						character = String.fromCharCode( event.which ).toLowerCase(),
						key, modif = "", possible = {};

					// check combinations (alt|ctrl|shift+anything)
					if ( event.altKey && special !== "alt" ) {
						modif += "alt+";
					}

					if ( event.ctrlKey && special !== "ctrl" ) {
						modif += "ctrl+";
					}
					
					// TODO: Need to make sure this works consistently across platforms
					if ( event.metaKey && !event.ctrlKey && special !== "meta" ) {
						modif += "meta+";
					}

					if ( event.shiftKey && special !== "shift" ) {
						modif += "shift+";
					}

					if ( special ) {
						possible[ modif + special ] = true;

					} else {
						possible[ modif + character ] = true;
						possible[ modif + jQuery.hotkeys.shiftNums[ character ] ] = true;

						// "$" can be triggered as "Shift+4" or "Shift+$" or just "$"
						if ( modif === "shift+" ) {
							possible[ jQuery.hotkeys.shiftNums[ character ] ] = true;
						}
					}

					for ( var i = 0, l = keys.length; i < l; i++ ) {
						if ( possible[ keys[i] ] ) {
							return origHandler.apply( this, arguments );
						}
					}
				};
			}

			jQuery.each([ "keydown", "keyup", "keypress" ], function() {
				jQuery.event.special[ this ] = { add: keyHandler };
			});

		})( jQuery );
			

		$(document).bind('keydown', 'q', function (evt){ quick_add_handle_key('q');})
		.bind('keydown', 'p', function (evt){ quick_add_handle_key('p');})
		.bind('keydown', 's', function (evt){ quick_add_handle_key('s');})
		.bind('keydown', 'd', function (evt){ quick_add_handle_key('d');})
		
		
	}else {
		
		/*
		(c) Copyrights 2007 - 2008

		Original idea by by Binny V A, http://www.openjs.com/scripts/events/keyboard_shortcuts/
		 
		jQuery Plugin by Tzury Bar Yochay 
		tzury.by@gmail.com
		http://evalinux.wordpress.com
		http://facebook.com/profile.php?id=513676303

		Project's sites: 
		http://code.google.com/p/js-hotkeys/
		http://github.com/tzuryby/hotkeys/tree/master

		License: same as jQuery license. 

		USAGE:
		    // simple usage
		    $(document).bind('keydown', 'Ctrl+c', function(){ alert('copy anyone?');});
		    
		    // special options such as disableInIput
		    $(document).bind('keydown', {combi:'Ctrl+x', disableInInput: true} , function() {});
		    
		Note:
		    This plugin wraps the following jQuery methods: $.fn.find, $.fn.bind and $.fn.unbind
		*/

		 (function (jQuery){
		    // keep reference to the original $.fn.bind, $.fn.unbind and $.fn.find
		    jQuery.fn.__bind__ = jQuery.fn.bind;
		    jQuery.fn.__unbind__ = jQuery.fn.unbind;
		    jQuery.fn.__find__ = jQuery.fn.find;
		    
		    var hotkeys = {
		        version: '0.7.9',
		        override: /keypress|keydown|keyup/g,
		        triggersMap: {},
		        
		        specialKeys: { 27: 'esc', 9: 'tab', 32:'space', 13: 'return', 8:'backspace', 145: 'scroll', 
		            20: 'capslock', 144: 'numlock', 19:'pause', 45:'insert', 36:'home', 46:'del',
		            35:'end', 33: 'pageup', 34:'pagedown', 37:'left', 38:'up', 39:'right',40:'down', 
		            109: '-', 
		            112:'f1',113:'f2', 114:'f3', 115:'f4', 116:'f5', 117:'f6', 118:'f7', 119:'f8', 
		            120:'f9', 121:'f10', 122:'f11', 123:'f12', 191: '/'},
		        
		        shiftNums: { "`":"~", "1":"!", "2":"@", "3":"#", "4":"$", "5":"%", "6":"^", "7":"&", 
		            "8":"*", "9":"(", "0":")", "-":"_", "=":"+", ";":":", "'":"\"", ",":"<", 
		            ".":">",  "/":"?",  "\\":"|" },
		        
		        newTrigger: function (type, combi, callback) { 
		            // i.e. {'keyup': {'ctrl': {cb: callback, disableInInput: false}}}
		            var result = {};
		            result[type] = {};
		            result[type][combi] = {cb: callback, disableInInput: false};
		            return result;
		        }
		    };
		    // add firefox num pad char codes
		    //if (jQuery.browser.mozilla){
		    // add num pad char codes
		    hotkeys.specialKeys = jQuery.extend(hotkeys.specialKeys, { 96: '0', 97:'1', 98: '2', 99: 
		        '3', 100: '4', 101: '5', 102: '6', 103: '7', 104: '8', 105: '9', 106: '*', 
		        107: '+', 109: '-', 110: '.', 111 : '/'
		        });
		    //}
		    
		    // a wrapper around of $.fn.find 
		    // see more at: http://groups.google.com/group/jquery-en/browse_thread/thread/18f9825e8d22f18d
		    jQuery.fn.find = function( selector ) {
		        this.query = selector;
		        return jQuery.fn.__find__.apply(this, arguments);
			};
		    
		    jQuery.fn.unbind = function (type, combi, fn){
		        if (jQuery.isFunction(combi)){
		            fn = combi;
		            combi = null;
		        }
		        if (combi && typeof combi === 'string'){
		            var selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
		            var hkTypes = type.split(' ');
		            for (var x=0; x<hkTypes.length; x++){
		                delete hotkeys.triggersMap[selectorId][hkTypes[x]][combi];
		            }
		        }
		        // call jQuery original unbind
		        return  this.__unbind__(type, fn);
		    };
		    
		    jQuery.fn.bind = function(type, data, fn){
		        // grab keyup,keydown,keypress
		        var handle = type.match(hotkeys.override);
		        
		        if (jQuery.isFunction(data) || !handle){
		            // call jQuery.bind only
		            return this.__bind__(type, data, fn);
		        }
		        else{
		            // split the job
		            var result = null,            
		            // pass the rest to the original $.fn.bind
		            pass2jq = jQuery.trim(type.replace(hotkeys.override, ''));
		            
		            // see if there are other types, pass them to the original $.fn.bind
		            if (pass2jq){
		                result = this.__bind__(pass2jq, data, fn);
		            }            
		            
		            if (typeof data === "string"){
		                data = {'combi': data};
		            }
		            if(data.combi){
		                for (var x=0; x < handle.length; x++){
		                    var eventType = handle[x];
		                    var combi = data.combi.toLowerCase(),
		                        trigger = hotkeys.newTrigger(eventType, combi, fn),
		                        selectorId = ((this.prevObject && this.prevObject.query) || (this[0].id && this[0].id) || this[0]).toString();
		                        
		                    //trigger[eventType][combi].propagate = data.propagate;
		                    trigger[eventType][combi].disableInInput = data.disableInInput;
		                    
		                    // first time selector is bounded
		                    if (!hotkeys.triggersMap[selectorId]) {
		                        hotkeys.triggersMap[selectorId] = trigger;
		                    }
		                    // first time selector is bounded with this type
		                    else if (!hotkeys.triggersMap[selectorId][eventType]) {
		                        hotkeys.triggersMap[selectorId][eventType] = trigger[eventType];
		                    }
		                    // make trigger point as array so more than one handler can be bound
		                    var mapPoint = hotkeys.triggersMap[selectorId][eventType][combi];
		                    if (!mapPoint){
		                        hotkeys.triggersMap[selectorId][eventType][combi] = [trigger[eventType][combi]];
		                    }
		                    else if (mapPoint.constructor !== Array){
		                        hotkeys.triggersMap[selectorId][eventType][combi] = [mapPoint];
		                    }
		                    else {
		                        hotkeys.triggersMap[selectorId][eventType][combi][mapPoint.length] = trigger[eventType][combi];
		                    }
		                    
		                    // add attribute and call $.event.add per matched element
		                    this.each(function(){
		                        // jQuery wrapper for the current element
		                        var jqElem = jQuery(this);
		                        
		                        // element already associated with another collection
		                        if (jqElem.attr('hkId') && jqElem.attr('hkId') !== selectorId){
		                            selectorId = jqElem.attr('hkId') + ";" + selectorId;
		                        }
		                        jqElem.attr('hkId', selectorId);
		                    });
		                    result = this.__bind__(handle.join(' '), data, hotkeys.handler)
		                }
		            }
		            return result;
		        }
		    };
		    // work-around for opera and safari where (sometimes) the target is the element which was last 
		    // clicked with the mouse and not the document event it would make sense to get the document
		    hotkeys.findElement = function (elem){
		        if (!jQuery(elem).attr('hkId')){
		            if (jQuery.browser.opera || jQuery.browser.safari){
		                while (!jQuery(elem).attr('hkId') && elem.parentNode){
		                    elem = elem.parentNode;
		                }
		            }
		        }
		        return elem;
		    };
		    // the event handler
		    hotkeys.handler = function(event) {
		        var target = hotkeys.findElement(event.currentTarget), 
		            jTarget = jQuery(target),
		            ids = jTarget.attr('hkId');
		        
		        if(ids){
		            ids = ids.split(';');
		            var code = event.which,
		                type = event.type,
		                special = hotkeys.specialKeys[code],
		                // prevent f5 overlapping with 't' (or f4 with 's', etc.)
		                character = !special && String.fromCharCode(code).toLowerCase(),
		                shift = event.shiftKey,
		                ctrl = event.ctrlKey,            
		                // patch for jquery 1.2.5 && 1.2.6 see more at:  
		                // http://groups.google.com/group/jquery-en/browse_thread/thread/83e10b3bb1f1c32b
		                alt = event.altKey || event.originalEvent.altKey,
		                mapPoint = null;

		            for (var x=0; x < ids.length; x++){
		                if (hotkeys.triggersMap[ids[x]][type]){
		                    mapPoint = hotkeys.triggersMap[ids[x]][type];
		                    break;
		                }
		            }
		            
		            //find by: id.type.combi.options            
		            if (mapPoint){ 
		                var trigger;
		                // event type is associated with the hkId
		                if(!shift && !ctrl && !alt) { // No Modifiers
		                    trigger = mapPoint[special] ||  (character && mapPoint[character]);
		                }
		                else{
		                    // check combinations (alt|ctrl|shift+anything)
		                    var modif = '';
		                    if(alt) modif +='alt+';
		                    if(ctrl) modif+= 'ctrl+';
		                    if(shift) modif += 'shift+';
		                    // modifiers + special keys or modifiers + character or modifiers + shift character or just shift character
		                    trigger = mapPoint[modif+special];
		                    if (!trigger){
		                        if (character){
		                            trigger = mapPoint[modif+character] 
		                                || mapPoint[modif+hotkeys.shiftNums[character]]
		                                // '$' can be triggered as 'Shift+4' or 'Shift+$' or just '$'
		                                || (modif === 'shift+' && mapPoint[hotkeys.shiftNums[character]]);
		                        }
		                    }
		                }
		                if (trigger){
		                    var result = false;
		                    for (var x=0; x < trigger.length; x++){
		                        if(trigger[x].disableInInput){
		                            // double check event.currentTarget and event.target
		                            var elem = jQuery(event.target);
		                            if (jTarget.is("input") || jTarget.is("textarea") || jTarget.is("select") 
		                                || elem.is("input") || elem.is("textarea") || elem.is("select") 
                                        || elem.is("object") || jTarget.is("object")
                                        || elem.is("embed") || jTarget.is("embed")) {
		                                return true;
		                            }
		                        }                       
		                        // call the registered callback function
		                        result = result || trigger[x].cb.apply(this, [event]);
		                    }
		                    return result;
		                }
		            }
		        }
		    };
		    // place it under window so it can be extended and overridden by others
		    window.hotkeys = hotkeys;
		    return jQuery;
		})(jQuery);
		
		$(document).bind('keydown', {combi:'q', disableInInput: true}, function (evt){ quick_add_handle_key('q');});
		$(document).bind('keydown', {combi:'p', disableInInput: true}, function (evt){ quick_add_handle_key('p');});
		$(document).bind('keydown', {combi:'s', disableInInput: true}, function (evt){ quick_add_handle_key('s');});
		$(document).bind('keydown', {combi:'d', disableInInput: true}, function (evt){ quick_add_handle_key('d');});
	}
	
	/**
	 * Bind keyboard shortcuts
	 * q - Quick Add window
	 * p - Projects list
	 * s - Search window
	 * d - Starred items
	 */
	function quick_add_handle_key(key) {
		try {
			switch(key) {
			case 'q':
				$('#menu_item_quick_add a').click();
				break;
			case 'p':
				$('#menu_item_projects a').click();
				break;
			case 's':
				$('#menu_item_search a').click();
				break;
			case 'd':
				$('#menu_item_starred_folder a').click();
				break;
			}
		}
		catch(e) {
			
		}
	}

	
});





/** File: modules/inline_pagination/javascript/main.js **/

/**
 * Main inline_pagination JS file
 */
$(document).ready(function() {
	
	// Check if this page has any comments
	if ($('.body').find('.subobject_author').parent().length == 0) {
		return;
	}
	
	// Check if this page has next page link
	if ($('.next_page').length == 0) {
		return;
	}
	
	// add div to display new comments
	$('.next_page').before('<div id="next_comment"></div>');
	
	// onClick event
	$('.next_page a').click(function() {
		var anchor = $(this);
		
		// add loading image 
		anchor.after('<span class="loading"><img src="' + App.data.indicator_url + '" alt="" />' + App.lang('Loading...') + '</span>');
		var loading_block = anchor.parent().find('.loading:first');
		anchor.hide();
		
		var totalCommentsOnPage = $('.body').find('.subobject_author').parent().length;
		
		$.ajax({
	          url     : anchor.attr('href'),
	          success : function(response) {
				  var top_pagination = $(response).find('.inner_pagination').html();
				  $('.inner_pagination').html(top_pagination);
					  var newComments = '';
					  var comments = 1;
					  
					  // extract comments from response
					  $(response).find('.subobject_author').parent().each( function() {
						 if( (totalCommentsOnPage + comments) % 2 == 0) {
								 newComments += '<div class="subobject comment even">';
						 } else {
								 newComments += '<div class="subobject comment odd">';
						 }	 
						 comments++; 
				    	 newComments += $(this).html();
				    	 newComments += '</div>';
					  });
					  
					  // Append these comments
					  $('#next_comment').append(newComments);
					  
					  // Done, clean up and setup for next page
					  $('.loading').hide();
					  anchor.show();
					  
					  if ( $(response).find('.next_page a').attr('href') ) {
						var new_url = $(response).find('.next_page a').attr('href');
						anchor.attr('href',new_url);
					  } else {
						anchor.hide();
					  }
			       },
			  	   error : function () {
			    	   $('.loading').hide();
			           anchor.show();   
			       }
		  }, 'html');
		  return false;
	});
});


/** File: modules/time_reports_plus/javascript/main.js **/

App.time_reports_plus = {
  controllers : {},
  models      : {}
};


App.time_reports_plus.controllers.time_reports_plus = {
		
		report: function() {
			this.getReady();
		},

		mass_edit : function() {
			this.getReady();
		},
		
		getReady : function() {
			
			$(document).ready(function() {
				var globaltime_mass_edit = $('#globaltime_mass_edit');
		
				var setToPercent = function () {
					var str = prompt(App.lang("Enter % value to apply"), '100%');
					var prepareHtml = '';
					if(str){
						var lastCharacter = str.substring(str.length - 1);
						if(lastCharacter == '%'){
							var str = str.replace('%', '');
						}
						
						if(isNumeric(str)){
							prepareHtml = '<input type="hidden" name="adjust_to_percent" value="' + str + '" />';
							$('#globaltime_mass_edit').find('button').attr('disabled', '').removeClass('button_disabled');
						}else{
							alert(App.lang('Please Enter valid % value'));
							setToPercent();
						}
					}else{
						document.getElementById('timereports_action').selectedIndex = 0;
						$('#globaltime_mass_edit').find('button').attr('disabled', 'disabled').addClass('button_disabled');
						return false;
					}
					
					$('#globaltime_mass_edit').append(prepareHtml);
					return true;
					
			};
									
			var isNumeric = function (sText) {
				   var ValidChars = "0123456789.";
				   var IsNumber=true;
				   var Char;
	
				   for (i = 0; i < sText.length && IsNumber == true; i++) 
				   { 
				      Char = sText.charAt(i); 
				      if (ValidChars.indexOf(Char) == -1) 
				         {
				    	  	IsNumber = false;
				         }
				   }
				   return IsNumber;
			};
			
				$('#timereports_action').change(function(){
					var selection = $("#timereports_action option:selected").val();
					if(selection == 'adjust_to_percent'){
						var setTo = setToPercent();
						if(setTo){
							document.getElementById('globaltime_edit_form').submit();
						}
					}
				});
		
				var url;
				var data = App.data.js_assign_data;
				if(App.data.active_project_id){
					url = App.data.project_report_url;
				}else{
					url = App.data.global_report_url;
				}
		
				// Fix the "--None--" in company id selector
				if ($('#time_reports_plus_company_id').length > 0) {
					$('#time_reports_plus_company_id').children()[0].text = App.lang('Any');	
				}
		
				//var exportUrl = App.extendUrl (url, { report : data.report_filter_data, show_time_records : data.show_time_records, summary_options : data.summary_options, export_data : 1 });
				$('#time_report_footer_options a.csv').click(function () {
					$('#time_report_footer_options a.csv').attr('href', '#');
					$('#export_format').val('csv');
					$('#is_export').val('1');
					document.getElementById('time_reports_plus_form').submit();
					$('#export_format').val('on_screen');
					$('#is_export').val('0');
					return;
				});
				
				$('#time_report_footer_options a.html').click(function () {
					$('#time_report_footer_options a.html').attr('href', '#');
					$('#export_format').val('html');
					$('#is_export').val('1');
					document.getElementById('time_reports_plus_form').submit();
					$('#export_format').val('on_screen');
					$('#is_export').val('0');
					return false;
				});
				
				
				$('#time_report_footer_options a.invoice').click(function () {
					$('#time_report_footer_options a.invoice').attr('href', '#');
					$('#create_invoice').val('1');
					document.getElementById('time_reports_plus_form').submit();
					$('#create_invoice').val('0');
					return;
				});
		
		
		
				// if there is no selection in first dropdown, it will disable second and third dropdown 
				if($('#summarize_by_1').val() == '' || $('#summarize_by_1').val() === undefined){
					$('#summarize_by_2').attr('disabled', 'disabled');
					$('#summarize_by_3').attr('disabled', 'disabled');
					$('#show_time_records').hide();
					$('#show_estimate_comparison').hide();
				}
				
				// store summarize value in array
				var headings = App.data.summarized_array;
		
				if($('#summarize_by_1').val() != '' && $('#summarize_by_1').val() !== undefined) {
					 var selection1 = $('#summarize_by_1').val();
					 var selection2 = $('#summarize_by_2').val();
					 var selection3 = $('#summarize_by_3').val();
					 
					 $('#summarize_by_2 >option').remove();
					 $('#summarize_by_3 >option').remove();
					 
						 $.each(headings,function(key,value) {
							 if(key != selection1){
								 if(selection2 == key){
									 $('#summarize_by_2').append($('<option selected="selected"></option>').val(key).html(value));
							 
							 if(selection2 == '' || selection2 === undefined){
								 $('#summarize_by_3').attr('disabled', 'disabled');
								 $('#summarize_by_3').append($('<option selected="selected"></option>').val(key).html(value));
							 }
						 }else{
							 $('#summarize_by_2').append($('<option></option>').val(key).html(value));
							 if(selection3 == key){
								 $('#summarize_by_3').append($('<option selected="selected"></option>').val(key).html(value));
							 }else{
								 $('#summarize_by_3').append($('<option></option>').val(key).html(value));
								 }
							 }	 
						 }
					 });
				} // if something in summarize selects..
		
				// call this function on change event of an first summarize selection dropdown
				var summarizeByOne = function(){
					 $('#summarize_by_2').attr('value', '');
					 $('#summarize_by_3').attr('value', '');
					 
					 var selection = $('#summarize_by_1').val();
					 if(selection != '' && selection !== undefined)
					 {
						 $('#show_time_records').show();
						 $('#show_estimate_comparison').show();
						 $('#summarize_by_2').attr('disabled', '');
						 
						 $('#summarize_by_2 >option').remove();
						 
						 $.each(headings,function(key,value){
							 if(key != selection){
								 $('#summarize_by_2').append($('<option></option>').val(key).html(value));
							 }	 
						 });
					 }else{
						 $('#summarize_by_2').attr('disabled', 'disabled');
						 $('#summarize_by_3').attr('disabled', 'disabled');
						 $('#show_time_records').hide();
						 $('#show_estimate_comparison').hide();
					 }
				};
			
				// call this function on change event of an second summarize selection dropdown
				var summarizeByTwo = function() {
					$('#summarize_by_3').attr('value', '');
				 
					 var selection1 = $('#summarize_by_1').val();
					 var selection2 = $('#summarize_by_2').val();
					 if(selection2 != '' && selection2 !== undefined)
					 {
						 	$('#summarize_by_3').attr('disabled', '');
						 	$('#summarize_by_3 >option').remove();
			            	$.each(headings,function(key,value){
				            	if(key != selection1 && key != selection2){
				            		$('#summarize_by_3').append($('<option></option>').val(key).html(value));
				            	}
			            	});
					 }else{
						 $('#summarize_by_3').attr('disabled', 'disabled');
						 $('#summarize_by_3').attr('value', '');
					 }	
				};
			
			
				 $('#summarize_by_1').change(function(){
					 summarizeByOne(); 
				 });
				 
				 
				 $('#summarize_by_2').change(function(){
					 summarizeByTwo();	 
				 });
			 
			 
				 // Simple hack - just select all checkboxes for now...
				 $('#all_time_record_ids').click(function(){
			        $(document).find('form#globaltime_edit_form :checkbox').attr('checked', this.checked); 
				 });
			 
		 
			      var globaltime_mass_edit_change = function () {
			        if($('.global_time_record input:checked').length > 0) {
			        	$('#globaltime_mass_edit').find('select').attr('disabled', '');
			          if($('#globaltime_mass_edit').find('select').val() != '') {
			        	  $('#globaltimerecord_submit').removeClass('button_disabled');
			        	  $('#globaltime_mass_edit').find('button').attr('disabled', '')
			          } else {
			        	  $('#globaltimerecord_submit').addClass('button_disabled');
			          } // if
			        } else {
			        	$('#globaltime_mass_edit').find('select').attr('disabled', 'disabled');
			        	$('#globaltime_mass_edit').find('button').attr('disabled', 'disabled').addClass('button_disabled');
			        } // if
			      } // mass_edit_change
			      
			      $('.global_time_record input').click(globaltime_mass_edit_change);
			      
			      $('#globaltime_mass_edit').change(globaltime_mass_edit_change).click(globaltime_mass_edit_change);
			      
			      	
			      // initialize time records table
			      $('#globaltime_edit_form').find('.time_record').each(function () {
			        App.timetracking.records.init_time_record_row($(this), mass_edit);
			      }); 
			});
		}
}

/** File: modules/recurring_tasks/javascript/main.js **/

App.recurring_tasks = {
  controllers : {},
  models      : {}
};

/**
 * Recurring tasks behavior
 */
App.recurring_tasks.controllers.RecurringTasks = {
  /**
   * Recurring tasks index page behavior
   */
  index : function() {
    $(document).ready(function () {
      reindex_recurring_tasks_table = function (table) {
        var counter = 0;
        table.find('li').each(function () {
          var row = $(this);
          if (row.html() && !row.is('.empty_row') && !row.is('.ui-sortable-helper')) {
            if ((counter % 2) == 0) {
              row.removeClass('even');
              row.addClass('odd');
            } else {
              row.removeClass('odd');
              row.addClass('even');
            } // if
            counter ++;
          } // if
        });
        if (counter<1) {
          table.find('.empty_row').show();
        } else {
          table.find('.empty_row').hide();
        } // if
      } // reindex_tickets_table

      if (App.data.can_manage_recurring_tasks) {
        $('.recurring_tasks_list').sortable({
          axis : 'y',      
          cursor: 'move',
          delay: 3,
          placeholder: 'drag_placeholder',
          forcePlaceholderSize : true,
          revert: false,
          connectWith: ['.recurring_tasks_list'],
          items: 'li.sort',
          update : function (e, ui) {
            var sortable_list = ui.item.parent();
            reindex_recurring_tasks_table(sortable_list);
            var reorder_data = sortable_list.find('input').serialize();
            if (reorder_data) {
              reorder_data+='&submitted=submitted';
              $.ajax({
                type: "POST",
                url: sortable_list.attr('reorder_url'),
                data: reorder_data
              });
            } // if
          },
          over: function (table_object,ui) {
            $(this).addClass('dragging');
          },
          out: function (table_object,ui) {
            $(this).removeClass('dragging');
          }
        });
      } // if
    });
  },

  /**
   * Add page bahaviour
   */
  add : function () {
    $(document).ready(function(){
      $('#ticket_details').click(function() {
        var url = App.extendUrl($('#recurring_task_ticket option:selected').attr('rel'), {
          async : 1
        });
        App.ModalDialog.show('recurring_tasks', App.lang('Ticket Details'), $('<p><img src="' + App.data.assets_url + '/images/indicator.gif" alt="" /> ' + App.lang('Loading...') + '</p>').load(url), {
          buttons : false,
          width:810
        });
        return false;
      });

      function sortNumbers(a, b) {
        return (a - b) //causes an array to be sorted numerically and ascending
      }

      function addHidden (selected) {
          $('.form_left_col').prepend('<input type="hidden" name="recurring_task_data[every][]" value="'+selected+'" class="every_hidden" />');
          $('#every_clear').show();
      }

      $('#every_button').click(function(){
          var selected = $('#every_select option:selected').val();
          var items = $('#every_list').text();
          if ('' == items) {
              $('#every_list').text(selected);
              addHidden(selected);
          } else {
              items = items.split(', ');
              var exist = false;
              for (var key in items) {
                if (items[key] == selected) {
                    exist = true;
                }
              }
              if (!exist) {
                  addHidden(selected);
                  items.push(selected);
                  items.sort(sortNumbers);
                  $('#every_list').text(items.join(', '));
              }
          }
      });

      $('#every_clear').click(function(){
          $('#every_list').text('');
          $('.every_hidden').remove();
          $(this).hide();
      });

    });
  },

  /**
   * Edit page bahaviour
   */
  edit : function () {
    $(document).ready(function(){
      function sortNumbers(a, b) {
        return (a - b) //causes an array to be sorted numerically and ascending
      }

      function addHidden (selected) {
          $('.form_left_col').prepend('<input type="hidden" name="recurring_task_data[every][]" value="'+selected+'" class="every_hidden" />');
          $('#every_clear').show();
      }

      $('#every_button').click(function(){
          var selected = $('#every_select option:selected').val();
          var items = $('#every_list').text();
          if ('' == items) {
              $('#every_list').text(selected);
              addHidden(selected);
          } else {
              items = items.split(', ');
              var exist = false;
              for (var key in items) {
                if (items[key] == selected) {
                    exist = true;
                }
              }
              if (!exist) {
                  addHidden(selected);
                  items.push(selected);
                  items.sort(sortNumbers);
                  $('#every_list').text(items.join(', '));
              }
          }
      });

      $('#every_clear').click(function(){
          $('#every_list').text('');
          $('.every_hidden').remove();
          $(this).hide();
      });

    });
  }

};

/** File: modules/acgarage/javascript/main.js **/

App.acgarage = {
  controllers : {},
  models      : {}
};


$(document).ready(function() {
	if(App.data.new_products || App.data.available_updates) {
		var info = 'acGarage Update: <a href="' + App.data.acgarage_admin_url + '">' + App.lang(':updates updates and :new new products available.', {'updates': App.data.available_updates, 'new': App.data.new_products}) + '</a>'; 

		$('#breadcrumbs').after('<p id="update_info" class="flash"><span class="flash_inner"><span class="update_available">' + info +'</span></span></p>');
		$('#update_info').live('click', function() {
			$(this).hide('fast');
		});
	}
}); 
  
	  



/** File: modules/tickets_plus/javascript/main.js **/

App.tickets_plus = {
  controllers : {},
  models      : {}
};

/**
 * Tickets behavior
 */
App.tickets_plus.controllers.tickets_plus = {
  /**
   * Ticket index page behavior
   */
  index : function() {    
    $(document).ready(function () {
    	
    	
    	$('#tickets_jump').attr('disabled', 'disabled');
    	
    	$('#search_string').keyup(function(){
    		
    		var search = $.trim($(this).val());
    		if(search.substring(0, 1) == '#'){
    			$('#tickets_jump').attr('disabled', '');
    		}
    		
    		if(search == ''){
    			$('ul.tickets_list *').parents('li').show();
    		}else{
    			$('ul.tickets_list *').parents('li').hide();
    		}
    		
    		
    		$('ul.tickets_list').unhighlight();
    		$('ul.tickets_list').highlight(search);

     		$("ul.tickets_list span.highlight").parents('li').show();
     		$('.empty_row').hide();
    		
    		
    		
    	});
    	
    	
    	
      reindex_tickets_table = function (table) {
        var counter = 0;
        table.find('li').each(function () {
          var row = $(this);
          if (row.html() && !row.is('.empty_row') && !row.is('.ui-sortable-helper')) {
            if ((counter % 2) == 0) {
              row.removeClass('even');
              row.addClass('odd');
            } else {
              row.removeClass('odd');
              row.addClass('even');
            } // if
            counter ++;
          } // if
        });
        if (counter<1) {
          table.find('.empty_row').show();
        } else {
          table.find('.empty_row').hide();
        } // if
      } // reindex_tickets_table

      if (App.data.can_manage_tickets) {
        $('.tickets_list').sortable({
          axis : 'y',      
          cursor: 'move',
          delay: 3,
          placeholder: 'drag_placeholder',
          forcePlaceholderSize : true,
          revert: false,
          connectWith: ['.tickets_list'],
          items: 'li.sort',
          update : function (e, ui) {
            var sortable_list = ui.item.parent();
            reindex_tickets_table(sortable_list);
            var reorder_data = sortable_list.find('input').serialize();
            if (reorder_data) {
              reorder_data+='&submitted=submitted';
              $.ajax({
                type: "POST",
                url: sortable_list.attr('reorder_url'),
                data: reorder_data
              });
            } // if
          },
          over: function (table_object,ui) {
            $(this).addClass('dragging');
          },
          out: function (table_object,ui) {
            $(this).removeClass('dragging');
          }
        });
        $('.tickets_list').sortable();
      } // if
      
      
      $('#tickets span.content_expander').click(function() {
			toggle_details(this);
	        return false;
	    });
      
      
      /**
  	 * Remember focused cell ID
  	 */
  	var current_cell_id = null;
  	/**
  	 * Focus single cell
  	 */
  	var focus_cell = function(cell) {
  	    cell.find('div.content_container').slideDown();
  	    cell.find('span.content_expander').addClass('collapsed');
  	};
  	/**
  	 * Unfocus cell
  	 */
  	var unfocus_cell = function(cell) {
  	    cell.find('div.content_container').slideUp();
  	    cell.find('span.content_expander').removeClass('collapsed');
  	};
  	/**
  	 * Toogle show hide
  	 */
  	var toggle_details = function(cell) {
  		var $cell = $(cell).parent().parent();

  	    if (current_cell_id) {
  	        if ($cell.attr('id') == current_cell_id) {
  	        	unfocus_cell($cell);
  	        	
  	            current_cell_id = null;
  	        } else {
  	            unfocus_cell($('#' + current_cell_id));
  	            focus_cell($cell);
  	            
  	            current_cell_id = $cell.attr('id');
  	        }
  	    } else {
  	        focus_cell($cell);
  	
  	        current_cell_id = $cell.attr('id');
  	    }
  	};
      
      
    });
  },
  
  /**
   * View ticket behavior
   */
  view : function() {
    $(document).ready(function() {
    	// get the quick update html part and append into the QuickComment Part
    	var div = $('.quick_comment_form'),
    		form = $("form", div),
    		form_id = form.attr('id');
    		quick_update_html = $('#tickets_plus_quick_update_form .blockLabels').html();
    			
    		$('.checkbox_complete', div).remove();
    		$('.attachments', div).parent().before(quick_update_html);
    		$('#tickets_plus_quick_update_button', div).remove();
    		window.onbeforeunload = null;
    		$('#'+form_id).uniform();
    	
    	$('#show_all_ticket_changes a').click(function() {
    		var link = $(this);
    		if(link.attr('loading') == 'loading') {
    			return false;
    		} else {
    			link.attr('loading', 'loading');
    		} // if
        
        var wrapper = $('#ticket_changes_wrapper');
        wrapper.block(App.lang('Loading...'));
        
        $.ajax({
          url : App.extendUrl(link.attr('href'), { async : 1}),
          success : function(response) {
            wrapper.empty().append(response).unblock().highlightFade();
            $('#show_all_ticket_changes').remove();
          },
          error : function() {
            wrapper.unblock();
            alert(App.lang('Failed to load all ticket changes'));
          }
        });
        
        return false;
      });
    });
  }
  
};

/*
 * jQuery Highlight plugin
 *
 * Based on highlight v3 by Johann Burkard
 * http://johannburkard.de/blog/programming/javascript/highlight-javascript-text-higlighting-jquery-plugin.html
 *
 * Code a little bit refactored and cleaned (in my humble opinion).
 * Most important changes:
 *  - has an option to highlight only entire words (wordsOnly - false by default),
 *  - has an option to be case sensitive (caseSensitive - false by default)
 *  - highlight element tag and class names can be specified in options
 *
 * Usage:
 *   // wrap every occurrance of text 'lorem' in content
 *   // with <span class='highlight'> (default options)
 *   $('#content').highlight('lorem');
 *
 *   // search for and highlight more terms at once
 *   // so you can save some time on traversing DOM
 *   $('#content').highlight(['lorem', 'ipsum']);
 *   $('#content').highlight('lorem ipsum');
 *
 *   // search only for entire word 'lorem'
 *   $('#content').highlight('lorem', { wordsOnly: true });
 *
 *   // don't ignore case during search of term 'lorem'
 *   $('#content').highlight('lorem', { caseSensitive: true });
 *
 *   // wrap every occurrance of term 'ipsum' in content
 *   // with <em class='important'>
 *   $('#content').highlight('ipsum', { element: 'em', className: 'important' });
 *
 *   // remove default highlight
 *   $('#content').unhighlight();
 *
 *   // remove custom highlight
 *   $('#content').unhighlight({ element: 'em', className: 'important' });
 *
 *
 * Copyright (c) 2009 Bartek Szopka
 *
 * Licensed under MIT license.
 *
 */

jQuery.extend({
	
    highlight: function (node, re, nodeName, className) {
        if (node.nodeType === 3) {
            var match = node.data.match(re);
            if (match)
            {
                var highlight = document.createElement(nodeName || 'span');
                highlight.className = className || 'highlight';
                
                var wordNode = node.splitText(match.index);
                wordNode.splitText(match[0].length);
                
                var wordClone = wordNode.cloneNode(true);
                highlight.appendChild(wordClone);
                
                wordNode.parentNode.replaceChild(highlight, wordNode);
                
                
                return 1; //skip added node in parent
            }
        } else if ((node.nodeType === 1 && node.childNodes) && // only element nodes that have children
                !/(script|style)/i.test(node.tagName) && // ignore script and style nodes
                !(node.tagName === nodeName.toUpperCase() && node.className === className)) { // skip if already highlighted
            for (var i = 0; i < node.childNodes.length; i++) {
                i += jQuery.highlight(node.childNodes[i], re, nodeName, className);
            }
        }
        return 0;
    }
    
});

jQuery.fn.unhighlight = function (options) {
    var settings = { className: 'highlight', element: 'span' };
    jQuery.extend(settings, options);

    return this.find(settings.element + "." + settings.className).each(function () {
        var parent = this.parentNode;
        parent.replaceChild(this.firstChild, this);
        parent.normalize();
    }).end();
};



jQuery.fn.highlight = function (words, options) {
    var settings = { className: 'highlight', element: 'span', caseSensitive: false, wordsOnly: false };
    jQuery.extend(settings, options);
    
    if (words.constructor === String) {
        words = [words];
    }
    words = jQuery.grep(words, function(word, i){
      return word != '';
    });
    if (words.length == 0) { return this; };

    var flag = settings.caseSensitive ? "" : "i";
    var pattern = "(" + words.join("|") + ")";
    
    if (settings.wordsOnly) {
        pattern = "\\b" + pattern + "\\b";
    }
    var re = new RegExp(pattern, flag);
    
    return this.each(function () {
        jQuery.highlight(this, re, settings.element, settings.className);
    });
    
};

/* Over: acHack additions */







/** File: modules/tabinator_pro/javascript/main.js **/

App.tabinator_pro = {
  controllers : {},
  models      : {}
};

/**
 * Tabinator Pro Admin controller client side behavior
 */
App.tabinator_pro.controllers.TabinatorProAdmin = {

  /**
   * Prepare dashboard index page
   */
  index : function(){
    $(document).ready(function(){

        /// check count number of selected items
        $('.dashboard-tabs').click(function(){
            var roleId = $(this).attr('class').split('-')[2];
            var count = $('.role-'+roleId+':checked').length;
            if (count < 1) {
                alert(App.lang('At least one item should be selected'));
                return false;
            }
            if (count > App.data.limit) {
                alert(App.lang('You can not select more than '+App.data.limit+' items'));
                return false;
            }
        });
        
    });
  }
};

    function reorder_tabs (limit) {

            /// check count number of selected items
            $('.tab_checkbox').live('click', function(){                
                var count = $('.tab_checkbox:checked').length;
                if (count < 1) {
                    alert(App.lang('At least one item should be selected'));
                    return false;
                }
                if (count > limit) {
                    alert(App.lang('You can not select more than '+limit+' items'));
                    return false;
                }
            });
    
        reindex_table = function (table) {
        var counter = 0;
        table.find('tr').each(function () {
          var row = $(this);
          if (row.html() && !row.is('.empty_row') && !row.is('.ui-sortable-helper')) {
            if ((counter % 2) == 0) {
              row.removeClass('even');
              row.addClass('odd');
            } else {
              row.removeClass('odd');
              row.addClass('even');
            } // if
            counter ++;
          } // if
        });
      }

        $('.tabs_list').sortable({
          axis : 'y',
          cursor: 'move',
          delay: 3,
          placeholder: 'drag_placeholder',
          forcePlaceholderSize : true,
          revert: false,
          connectWith: ['.tabs_list'],
          items: 'tr.sort',
          update : function (e, ui) {
            var sortable_list = ui.item.parent().parent();
            reindex_table(sortable_list);
            var reorder_data = sortable_list.find('input').serialize();
            if (reorder_data) {
              reorder_data+='&submitted=submitted';
              $.ajax({
                type: "POST",
                url: sortable_list.attr('reorder_url'),
                data: reorder_data
              });
            } // if
          },
          over: function (table_object,ui) {
            $(this).addClass('dragging');
          },
          out: function (table_object,ui) {
            $(this).removeClass('dragging');
          }
        });
    }

/** File: modules/cust_fields/javascript/main.js **/

$(document).ready(function(){
	/*
	 * This event is fired earlier than window.load;
	 * I want to display some indicator that indicating retriving cust fields
	 */
	var loc = window.location.href;
	if (loc.indexOf('submit') > 0) {
	    $('head').append("<link rel=\"stylesheet\" href=\"assets/modules/cust_fields/stylesheets/public_submit_fix.css\" type=\"text/css\" media=\"screen\"/>");
	}
});

$(window).load(function () {
	var loc = window.location.href;
	
	//keyword "projects" includes Project and ProjectObject
	//keyword "people" includes Company and Profile
	if (loc.indexOf('projects') > 0 || loc.indexOf('people') > 0 || loc.indexOf('submit') > 0) {
	    var ajaxurl = App.data.path_info_through_query_string ? 
	      App.extendUrl(App.data.url_base, { path_info : 'cust_fields_parse' }) :
	      App.data.url_base + '/cust_fields_parse';	      
		
	    loc = loc.replace('http://', '');//for better compatibility
	    loc = loc.replace(/\//g, '~');//for better compatibility
	      
		$.getJSON(ajaxurl, {async : 1, url: loc }, function(data){
			$.each(data, function(i, point){
				$(point.selector).append(point.content);
			});
			$('form.uniForm').uniform();
		});
	} else {
		return;
	}
});
