
// file: 000-0-jquery-1.7.1.js
/*!
 * jQuery JavaScript Library v1.7.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: Mon Nov 21 21:11:03 2011 -0500
 */
(function( window, undefined ) {

// Use the correct document accordingly with window argument (sandbox)
var document = window.document,
	navigator = window.navigator,
	location = window.location;
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
	// Prioritize #id over <tag> to avoid XSS via location.hash (#9521)
	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+$/,

	// 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.]+))?/,

	// Matches dashed string for camelizing
	rdashAlpha = /-([a-z]|[0-9])/ig,
	rmsPrefix = /^-ms-/,

	// Used by jQuery.camelCase as callback to replace()
	fcamelCase = function( all, letter ) {
		return ( letter + "" ).toUpperCase();
	},

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

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

	// The deferred used on DOM ready
	readyList,

	// 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 = selector;
			this.length = 1;
			return this;
		}

		// Handle HTML strings
		if ( typeof selector === "string" ) {
			// Are we dealing with HTML string or an ID?
			if ( selector.charAt(0) === "<" && selector.charAt( selector.length - 1 ) === ">" && selector.length >= 3 ) {
				// Assume that strings that start and end with <> are HTML and skip the regex check
				match = [ null, selector, null ];

			} else {
				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.7.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.add( fn );

		return this;
	},

	eq: function( i ) {
		i = +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 ) {
		if ( window.$ === jQuery ) {
			window.$ = _$;
		}

		if ( deep && window.jQuery === jQuery ) {
			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,

	// Hold (or release) the ready event
	holdReady: function( hold ) {
		if ( hold ) {
			jQuery.readyWait++;
		} else {
			jQuery.ready( true );
		}
	},

	// Handle when the DOM is ready
	ready: function( wait ) {
		// Either a released hold or an DOMready/load event and not yet ready
		if ( (wait === true && !--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.fireWith( document, [ jQuery ] );

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

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

		readyList = jQuery.Callbacks( "once memory" );

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

	isNumeric: function( obj ) {
		return !isNaN( parseFloat(obj) ) && isFinite( 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;
		}

		try {
			// Not own constructor property must be Object
			if ( obj.constructor &&
				!hasOwn.call(obj, "constructor") &&
				!hasOwn.call(obj.constructor.prototype, "isPrototypeOf") ) {
				return false;
			}
		} catch ( e ) {
			// IE8,9 Will throw exceptions on certain host objects #9897
			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 new Error( 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 );

		// Attempt to parse using the native JSON parser first
		if ( window.JSON && window.JSON.parse ) {
			return window.JSON.parse( 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, "")) ) {

			return ( new Function( "return " + data ) )();

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

	// Cross-browser xml parsing
	parseXML: function( data ) {
		var xml, tmp;
		try {
			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 );
			}
		} catch( e ) {
			xml = undefined;
		}
		if ( !xml || !xml.documentElement || xml.getElementsByTagName( "parsererror" ).length ) {
			jQuery.error( "Invalid XML: " + data );
		}
		return xml;
	},

	noop: function() {},

	// Evaluates a script in a global context
	// Workarounds based on findings by Jim Driscoll
	// http://weblogs.java.net/blog/driscoll/archive/2009/09/08/eval-javascript-global-context
	globalEval: function( data ) {
		if ( data && rnotwhite.test( data ) ) {
			// We use execScript on Internet Explorer
			// We use an anonymous function so that context is window
			// rather than jQuery in Firefox
			( window.execScript || function( data ) {
				window[ "eval" ].call( window, data );
			} )( data );
		}
	},

	// Convert dashed to camelCase; used by the css and data modules
	// Microsoft forgot to hump their vendor prefix (#9572)
	camelCase: function( string ) {
		return string.replace( rmsPrefix, "ms-" ).replace( rdashAlpha, fcamelCase );
	},

	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 ( ; i < length; ) {
					if ( callback.call( object[ i ], i, object[ i++ ] ) === false ) {
						break;
					}
				}
			}
		}

		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'
			// 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, i ) {
		var len;

		if ( array ) {
			if ( indexOf ) {
				return indexOf.call( array, elem, i );
			}

			len = array.length;
			i = i ? i < 0 ? Math.max( 0, len + i ) : i : 0;

			for ( ; i < len; i++ ) {
				// Skip accessing in sparse arrays
				if ( i in array && 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 value, key, ret = [],
			i = 0,
			length = elems.length,
			// jquery objects are treated as arrays
			isArray = elems instanceof jQuery || length !== undefined && typeof length === "number" && ( ( length > 0 && elems[ 0 ] && elems[ length -1 ] ) || length === 0 || jQuery.isArray( elems ) ) ;

		// Go through the array, translating each of the items to their
		if ( isArray ) {
			for ( ; i < length; i++ ) {
				value = callback( elems[ i ], i, arg );

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

		// Go through every key on the object,
		} else {
			for ( key in elems ) {
				value = callback( elems[ key ], key, 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,

	// Bind a function to a context, optionally partially applying any
	// arguments.
	proxy: function( fn, context ) {
		if ( typeof context === "string" ) {
			var tmp = fn[ context ];
			context = fn;
			fn = tmp;
		}

		// Quick check to determine if target is callable, in the spec
		// this throws a TypeError, but we will just return undefined.
		if ( !jQuery.isFunction( fn ) ) {
			return undefined;
		}

		// Simulated bind
		var args = slice.call( arguments, 2 ),
			proxy = function() {
				return fn.apply( context, args.concat( slice.call( arguments ) ) );
			};

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

		return proxy;
	},

	// Mutifunctional method to get and set values to a collection
	// The value/s can optionally be executed if it's 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();
	},

	// 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 jQuerySub( selector, context ) {
			return new jQuerySub.fn.init( selector, context );
		}
		jQuery.extend( true, jQuerySub, this );
		jQuerySub.superclass = this;
		jQuerySub.fn = jQuerySub.prototype = this();
		jQuerySub.fn.constructor = jQuerySub;
		jQuerySub.sub = this.sub;
		jQuerySub.fn.init = function init( selector, context ) {
			if ( context && context instanceof jQuery && !(context instanceof jQuerySub) ) {
				context = jQuerySub( context );
			}

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

	browser: {}
});

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

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

return jQuery;

})();


// String to Object flags format cache
var flagsCache = {};

// Convert String-formatted flags into Object-formatted ones and store in cache
function createFlags( flags ) {
	var object = flagsCache[ flags ] = {},
		i, length;
	flags = flags.split( /\s+/ );
	for ( i = 0, length = flags.length; i < length; i++ ) {
		object[ flags[i] ] = true;
	}
	return object;
}

/*
 * Create a callback list using the following parameters:
 *
 *	flags:	an optional list of space-separated flags that will change how
 *			the callback list behaves
 *
 * By default a callback list will act like an event callback list and can be
 * "fired" multiple times.
 *
 * Possible flags:
 *
 *	once:			will ensure the callback list can only be fired once (like a Deferred)
 *
 *	memory:			will keep track of previous values and will call any callback added
 *					after the list has been fired right away with the latest "memorized"
 *					values (like a Deferred)
 *
 *	unique:			will ensure a callback can only be added once (no duplicate in the list)
 *
 *	stopOnFalse:	interrupt callings when a callback returns false
 *
 */
jQuery.Callbacks = function( flags ) {

	// Convert flags from String-formatted to Object-formatted
	// (we check in cache first)
	flags = flags ? ( flagsCache[ flags ] || createFlags( flags ) ) : {};

	var // Actual callback list
		list = [],
		// Stack of fire calls for repeatable lists
		stack = [],
		// Last fire value (for non-forgettable lists)
		memory,
		// Flag to know if list is currently firing
		firing,
		// First callback to fire (used internally by add and fireWith)
		firingStart,
		// End of the loop when firing
		firingLength,
		// Index of currently firing callback (modified by remove if needed)
		firingIndex,
		// Add one or several callbacks to the list
		add = function( args ) {
			var i,
				length,
				elem,
				type,
				actual;
			for ( i = 0, length = args.length; i < length; i++ ) {
				elem = args[ i ];
				type = jQuery.type( elem );
				if ( type === "array" ) {
					// Inspect recursively
					add( elem );
				} else if ( type === "function" ) {
					// Add if not in unique mode and callback is not in
					if ( !flags.unique || !self.has( elem ) ) {
						list.push( elem );
					}
				}
			}
		},
		// Fire callbacks
		fire = function( context, args ) {
			args = args || [];
			memory = !flags.memory || [ context, args ];
			firing = true;
			firingIndex = firingStart || 0;
			firingStart = 0;
			firingLength = list.length;
			for ( ; list && firingIndex < firingLength; firingIndex++ ) {
				if ( list[ firingIndex ].apply( context, args ) === false && flags.stopOnFalse ) {
					memory = true; // Mark as halted
					break;
				}
			}
			firing = false;
			if ( list ) {
				if ( !flags.once ) {
					if ( stack && stack.length ) {
						memory = stack.shift();
						self.fireWith( memory[ 0 ], memory[ 1 ] );
					}
				} else if ( memory === true ) {
					self.disable();
				} else {
					list = [];
				}
			}
		},
		// Actual Callbacks object
		self = {
			// Add a callback or a collection of callbacks to the list
			add: function() {
				if ( list ) {
					var length = list.length;
					add( arguments );
					// Do we need to add the callbacks to the
					// current firing batch?
					if ( firing ) {
						firingLength = list.length;
					// With memory, if we're not firing then
					// we should call right away, unless previous
					// firing was halted (stopOnFalse)
					} else if ( memory && memory !== true ) {
						firingStart = length;
						fire( memory[ 0 ], memory[ 1 ] );
					}
				}
				return this;
			},
			// Remove a callback from the list
			remove: function() {
				if ( list ) {
					var args = arguments,
						argIndex = 0,
						argLength = args.length;
					for ( ; argIndex < argLength ; argIndex++ ) {
						for ( var i = 0; i < list.length; i++ ) {
							if ( args[ argIndex ] === list[ i ] ) {
								// Handle firingIndex and firingLength
								if ( firing ) {
									if ( i <= firingLength ) {
										firingLength--;
										if ( i <= firingIndex ) {
											firingIndex--;
										}
									}
								}
								// Remove the element
								list.splice( i--, 1 );
								// If we have some unicity property then
								// we only need to do this once
								if ( flags.unique ) {
									break;
								}
							}
						}
					}
				}
				return this;
			},
			// Control if a given callback is in the list
			has: function( fn ) {
				if ( list ) {
					var i = 0,
						length = list.length;
					for ( ; i < length; i++ ) {
						if ( fn === list[ i ] ) {
							return true;
						}
					}
				}
				return false;
			},
			// Remove all callbacks from the list
			empty: function() {
				list = [];
				return this;
			},
			// Have the list do nothing anymore
			disable: function() {
				list = stack = memory = undefined;
				return this;
			},
			// Is it disabled?
			disabled: function() {
				return !list;
			},
			// Lock the list in its current state
			lock: function() {
				stack = undefined;
				if ( !memory || memory === true ) {
					self.disable();
				}
				return this;
			},
			// Is it locked?
			locked: function() {
				return !stack;
			},
			// Call all callbacks with the given context and arguments
			fireWith: function( context, args ) {
				if ( stack ) {
					if ( firing ) {
						if ( !flags.once ) {
							stack.push( [ context, args ] );
						}
					} else if ( !( flags.once && memory ) ) {
						fire( context, args );
					}
				}
				return this;
			},
			// Call all the callbacks with the given arguments
			fire: function() {
				self.fireWith( this, arguments );
				return this;
			},
			// To know if the callbacks have already been called at least once
			fired: function() {
				return !!memory;
			}
		};

	return self;
};




var // Static reference to slice
	sliceDeferred = [].slice;

jQuery.extend({

	Deferred: function( func ) {
		var doneList = jQuery.Callbacks( "once memory" ),
			failList = jQuery.Callbacks( "once memory" ),
			progressList = jQuery.Callbacks( "memory" ),
			state = "pending",
			lists = {
				resolve: doneList,
				reject: failList,
				notify: progressList
			},
			promise = {
				done: doneList.add,
				fail: failList.add,
				progress: progressList.add,

				state: function() {
					return state;
				},

				// Deprecated
				isResolved: doneList.fired,
				isRejected: failList.fired,

				then: function( doneCallbacks, failCallbacks, progressCallbacks ) {
					deferred.done( doneCallbacks ).fail( failCallbacks ).progress( progressCallbacks );
					return this;
				},
				always: function() {
					deferred.done.apply( deferred, arguments ).fail.apply( deferred, arguments );
					return this;
				},
				pipe: function( fnDone, fnFail, fnProgress ) {
					return jQuery.Deferred(function( newDefer ) {
						jQuery.each( {
							done: [ fnDone, "resolve" ],
							fail: [ fnFail, "reject" ],
							progress: [ fnProgress, "notify" ]
						}, function( handler, data ) {
							var fn = data[ 0 ],
								action = data[ 1 ],
								returned;
							if ( jQuery.isFunction( fn ) ) {
								deferred[ handler ](function() {
									returned = fn.apply( this, arguments );
									if ( returned && jQuery.isFunction( returned.promise ) ) {
										returned.promise().then( newDefer.resolve, newDefer.reject, newDefer.notify );
									} else {
										newDefer[ action + "With" ]( this === deferred ? newDefer : this, [ returned ] );
									}
								});
							} else {
								deferred[ handler ]( newDefer[ action ] );
							}
						});
					}).promise();
				},
				// Get a promise for this deferred
				// If obj is provided, the promise aspect is added to the object
				promise: function( obj ) {
					if ( obj == null ) {
						obj = promise;
					} else {
						for ( var key in promise ) {
							obj[ key ] = promise[ key ];
						}
					}
					return obj;
				}
			},
			deferred = promise.promise({}),
			key;

		for ( key in lists ) {
			deferred[ key ] = lists[ key ].fire;
			deferred[ key + "With" ] = lists[ key ].fireWith;
		}

		// Handle state
		deferred.done( function() {
			state = "resolved";
		}, failList.disable, progressList.lock ).fail( function() {
			state = "rejected";
		}, doneList.disable, progressList.lock );

		// Call given func if any
		if ( func ) {
			func.call( deferred, deferred );
		}

		// All done!
		return deferred;
	},

	// Deferred helper
	when: function( firstParam ) {
		var args = sliceDeferred.call( arguments, 0 ),
			i = 0,
			length = args.length,
			pValues = new Array( length ),
			count = length,
			pCount = length,
			deferred = length <= 1 && firstParam && jQuery.isFunction( firstParam.promise ) ?
				firstParam :
				jQuery.Deferred(),
			promise = deferred.promise();
		function resolveFunc( i ) {
			return function( value ) {
				args[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
				if ( !( --count ) ) {
					deferred.resolveWith( deferred, args );
				}
			};
		}
		function progressFunc( i ) {
			return function( value ) {
				pValues[ i ] = arguments.length > 1 ? sliceDeferred.call( arguments, 0 ) : value;
				deferred.notifyWith( promise, pValues );
			};
		}
		if ( length > 1 ) {
			for ( ; i < length; i++ ) {
				if ( args[ i ] && args[ i ].promise && jQuery.isFunction( args[ i ].promise ) ) {
					args[ i ].promise().then( resolveFunc(i), deferred.reject, progressFunc(i) );
				} else {
					--count;
				}
			}
			if ( !count ) {
				deferred.resolveWith( deferred, args );
			}
		} else if ( deferred !== firstParam ) {
			deferred.resolveWith( deferred, length ? [ firstParam ] : [] );
		}
		return promise;
	}
});




jQuery.support = (function() {

	var support,
		all,
		a,
		select,
		opt,
		input,
		marginDiv,
		fragment,
		tds,
		events,
		eventName,
		i,
		isSupported,
		div = document.createElement( "div" ),
		documentElement = document.documentElement;

	// Preliminary tests
	div.setAttribute("className", "t");
	div.innerHTML = "   <link/><table></table><a href='/a' style='top:1px;float:left;opacity:.55;'>a</a><input type='checkbox'/>";

	all = div.getElementsByTagName( "*" );
	a = div.getElementsByTagName( "a" )[ 0 ];

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

	// First batch of supports tests
	select = document.createElement( "select" );
	opt = select.appendChild( document.createElement("option") );
	input = div.getElementsByTagName( "input" )[ 0 ];

	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 instead)
		style: /top/.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,

		// Test setAttribute on camelCase class. If it works, we need attrFixes when doing get/setAttribute (ie6/7)
		getSetAttribute: div.className !== "t",

		// Tests for enctype support on a form(#6743)
		enctype: !!document.createElement("form").enctype,

		// Makes sure cloning an html5 element does not cause problems
		// Where outerHTML is undefined, this still works
		html5Clone: document.createElement("nav").cloneNode( true ).outerHTML !== "<:nav></:nav>",

		// Will be defined later
		submitBubbles: true,
		changeBubbles: true,
		focusinBubbles: false,
		deleteExpando: true,
		noCloneEvent: true,
		inlineBlockNeedsLayout: false,
		shrinkWrapBlocks: false,
		reliableMarginRight: true
	};

	// Make sure checked status is properly cloned
	input.checked = true;
	support.noCloneChecked = input.cloneNode( true ).checked;

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

	// Test to see if it's possible to delete an expando from an element
	// Fails in Internet Explorer
	try {
		delete div.test;
	} catch( e ) {
		support.deleteExpando = false;
	}

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

	// Check if a radio maintains its value
	// after being appended to the DOM
	input = document.createElement("input");
	input.value = "t";
	input.setAttribute("type", "radio");
	support.radioValue = input.value === "t";

	input.setAttribute("checked", "checked");
	div.appendChild( input );
	fragment = document.createDocumentFragment();
	fragment.appendChild( div.lastChild );

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

	// Check if a disconnected checkbox will retain its checked
	// value of true after appended to the DOM (IE6/7)
	support.appendChecked = input.checked;

	fragment.removeChild( input );
	fragment.appendChild( div );

	div.innerHTML = "";

	// Check if div with explicit width and no margin-right incorrectly
	// gets computed margin-right based on width of container. For more
	// info see bug #3333
	// Fails in WebKit before Feb 2011 nightlies
	// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
	if ( window.getComputedStyle ) {
		marginDiv = document.createElement( "div" );
		marginDiv.style.width = "0";
		marginDiv.style.marginRight = "0";
		div.style.width = "2px";
		div.appendChild( marginDiv );
		support.reliableMarginRight =
			( parseInt( ( window.getComputedStyle( marginDiv, null ) || { marginRight: 0 } ).marginRight, 10 ) || 0 ) === 0;
	}

	// Technique from Juriy Zaytsev
	// http://perfectionkills.com/detecting-event-support-without-browser-sniffing/
	// 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 ( div.attachEvent ) {
		for( i in {
			submit: 1,
			change: 1,
			focusin: 1
		}) {
			eventName = "on" + i;
			isSupported = ( eventName in div );
			if ( !isSupported ) {
				div.setAttribute( eventName, "return;" );
				isSupported = ( typeof div[ eventName ] === "function" );
			}
			support[ i + "Bubbles" ] = isSupported;
		}
	}

	fragment.removeChild( div );

	// Null elements to avoid leaks in IE
	fragment = select = opt = marginDiv = div = input = null;

	// Run tests that need a body at doc ready
	jQuery(function() {
		var container, outer, inner, table, td, offsetSupport,
			conMarginTop, ptlm, vb, style, html,
			body = document.getElementsByTagName("body")[0];

		if ( !body ) {
			// Return for frameset docs that don't have a body
			return;
		}

		conMarginTop = 1;
		ptlm = "position:absolute;top:0;left:0;width:1px;height:1px;margin:0;";
		vb = "visibility:hidden;border:0;";
		style = "style='" + ptlm + "border:5px solid #000;padding:0;'";
		html = "<div " + style + "><div></div></div>" +
			"<table " + style + " cellpadding='0' cellspacing='0'>" +
			"<tr><td></td></tr></table>";

		container = document.createElement("div");
		container.style.cssText = vb + "width:0;height:0;position:static;top:0;margin-top:" + conMarginTop + "px";
		body.insertBefore( container, body.firstChild );

		// Construct the test element
		div = document.createElement("div");
		container.appendChild( div );

		// 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)
		div.innerHTML = "<table><tr><td style='padding:0;border:0;display:none'></td><td>t</td></tr></table>";
		tds = div.getElementsByTagName( "td" );
		isSupported = ( 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)
		support.reliableHiddenOffsets = isSupported && ( tds[ 0 ].offsetHeight === 0 );

		// Figure out if the W3C box model works as expected
		div.innerHTML = "";
		div.style.width = div.style.paddingLeft = "1px";
		jQuery.boxModel = support.boxModel = div.offsetWidth === 2;

		if ( typeof div.style.zoom !== "undefined" ) {
			// 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;
			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>";
			support.shrinkWrapBlocks = ( div.offsetWidth !== 2 );
		}

		div.style.cssText = ptlm + vb;
		div.innerHTML = html;

		outer = div.firstChild;
		inner = outer.firstChild;
		td = outer.nextSibling.firstChild.firstChild;

		offsetSupport = {
			doesNotAddBorder: ( inner.offsetTop !== 5 ),
			doesAddBorderForTableAndCells: ( td.offsetTop === 5 )
		};

		inner.style.position = "fixed";
		inner.style.top = "20px";

		// safari subtracts parent border width here which is 5px
		offsetSupport.fixedPosition = ( inner.offsetTop === 20 || inner.offsetTop === 15 );
		inner.style.position = inner.style.top = "";

		outer.style.overflow = "hidden";
		outer.style.position = "relative";

		offsetSupport.subtractsBorderForOverflowNotVisible = ( inner.offsetTop === -5 );
		offsetSupport.doesNotIncludeMarginInBodyOffset = ( body.offsetTop !== conMarginTop );

		body.removeChild( container );
		div  = container = null;

		jQuery.extend( support, offsetSupport );
	});

	return support;
})();




var rbrace = /^(?:\{.*\}|\[.*\])$/,
	rmultiDash = /([A-Z])/g;

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 privateCache, thisCache, ret,
			internalKey = jQuery.expando,
			getByName = typeof name === "string",

			// 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[ internalKey ] : elem[ internalKey ] && internalKey,
			isEvents = name === "events";

		// 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 || !cache[id] || (!isEvents && !pvt && !cache[id].data)) && 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[ internalKey ] = id = ++jQuery.uuid;
			} else {
				id = internalKey;
			}
		}

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

			// 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 ] = jQuery.extend( cache[ id ], name );
			} else {
				cache[ id ].data = jQuery.extend( cache[ id ].data, name );
			}
		}

		privateCache = thisCache = cache[ id ];

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

			thisCache = thisCache.data;
		}

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

		// Users should not attempt to inspect the internal events object using jQuery.data,
		// it is undocumented and subject to change. But does anyone listen? No.
		if ( isEvents && !thisCache[ name ] ) {
			return privateCache.events;
		}

		// Check for both converted-to-camel and non-converted data property names
		// If a data property was specified
		if ( getByName ) {

			// First Try to find as-is property data
			ret = thisCache[ name ];

			// Test for null|undefined property data
			if ( ret == null ) {

				// Try to find the camelCased property
				ret = thisCache[ jQuery.camelCase( name ) ];
			}
		} else {
			ret = thisCache;
		}

		return ret;
	},

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

		var thisCache, i, l,

			// Reference to internal data cache key
			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[ internalKey ] : internalKey;

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

		if ( name ) {

			thisCache = pvt ? cache[ id ] : cache[ id ].data;

			if ( thisCache ) {

				// Support array or space separated string names for data keys
				if ( !jQuery.isArray( name ) ) {

					// try the string as a key before any manipulation
					if ( name in thisCache ) {
						name = [ name ];
					} else {

						// split the camel cased version by spaces unless a key with the spaces exists
						name = jQuery.camelCase( name );
						if ( name in thisCache ) {
							name = [ name ];
						} else {
							name = name.split( " " );
						}
					}
				}

				for ( i = 0, l = name.length; i < l; i++ ) {
					delete thisCache[ name[i] ];
				}

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

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

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

		// 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
		// Ensure that `cache` is not a window object #10080
		if ( jQuery.support.deleteExpando || !cache.setInterval ) {
			delete cache[ id ];
		} else {
			cache[ id ] = null;
		}

		// We destroyed the cache and need to eliminate the expando on the node to avoid
		// false lookups in the cache for entries that no longer exist
		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[ internalKey ];
			} else if ( elem.removeAttribute ) {
				elem.removeAttribute( internalKey );
			} else {
				elem[ internalKey ] = 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 parts, attr, name,
			data = null;

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

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

						if ( name.indexOf( "data-" ) === 0 ) {
							name = jQuery.camelCase( name.substring(5) );

							dataAttr( this[0], name, data[ name ] );
						}
					}
					jQuery._data( this[0], "parsedAttrs", true );
				}
			}

			return data;

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

		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 self = jQuery( this ),
					args = [ parts[0], value ];

				self.triggerHandler( "setData" + parts[1] + "!", args );
				jQuery.data( this, key, value );
				self.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 ) {

		var name = "data-" + key.replace( rmultiDash, "-$1" ).toLowerCase();

		data = elem.getAttribute( name );

		if ( typeof data === "string" ) {
			try {
				data = data === "true" ? true :
				data === "false" ? false :
				data === "null" ? null :
				jQuery.isNumeric( 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;
}

// checks a cache object for emptiness
function isEmptyDataObject( obj ) {
	for ( var name in obj ) {

		// if the public data object is empty, the private is still empty
		if ( name === "data" && jQuery.isEmptyObject( obj[name] ) ) {
			continue;
		}
		if ( name !== "toJSON" ) {
			return false;
		}
	}

	return true;
}




function handleQueueMarkDefer( elem, type, src ) {
	var deferDataKey = type + "defer",
		queueDataKey = type + "queue",
		markDataKey = type + "mark",
		defer = jQuery._data( elem, deferDataKey );
	if ( defer &&
		( src === "queue" || !jQuery._data(elem, queueDataKey) ) &&
		( src === "mark" || !jQuery._data(elem, markDataKey) ) ) {
		// Give room for hard-coded callbacks to fire first
		// and eventually mark/queue something else on the element
		setTimeout( function() {
			if ( !jQuery._data( elem, queueDataKey ) &&
				!jQuery._data( elem, markDataKey ) ) {
				jQuery.removeData( elem, deferDataKey, true );
				defer.fire();
			}
		}, 0 );
	}
}

jQuery.extend({

	_mark: function( elem, type ) {
		if ( elem ) {
			type = ( type || "fx" ) + "mark";
			jQuery._data( elem, type, (jQuery._data( elem, type ) || 0) + 1 );
		}
	},

	_unmark: function( force, elem, type ) {
		if ( force !== true ) {
			type = elem;
			elem = force;
			force = false;
		}
		if ( elem ) {
			type = type || "fx";
			var key = type + "mark",
				count = force ? 0 : ( (jQuery._data( elem, key ) || 1) - 1 );
			if ( count ) {
				jQuery._data( elem, key, count );
			} else {
				jQuery.removeData( elem, key, true );
				handleQueueMarkDefer( elem, type, "mark" );
			}
		}
	},

	queue: function( elem, type, data ) {
		var q;
		if ( elem ) {
			type = ( type || "fx" ) + "queue";
			q = jQuery._data( elem, type );

			// Speed up dequeue by getting out quickly if this is just a lookup
			if ( data ) {
				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(),
			hooks = {};

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

			jQuery._data( elem, type + ".run", hooks );
			fn.call( elem, function() {
				jQuery.dequeue( elem, type );
			}, hooks );
		}

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

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() {
			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( next, hooks ) {
			var timeout = setTimeout( next, time );
			hooks.stop = function() {
				clearTimeout( timeout );
			};
		});
	},
	clearQueue: function( type ) {
		return this.queue( type || "fx", [] );
	},
	// Get a promise resolved when queues of a certain type
	// are emptied (fx is the type by default)
	promise: function( type, object ) {
		if ( typeof type !== "string" ) {
			object = type;
			type = undefined;
		}
		type = type || "fx";
		var defer = jQuery.Deferred(),
			elements = this,
			i = elements.length,
			count = 1,
			deferDataKey = type + "defer",
			queueDataKey = type + "queue",
			markDataKey = type + "mark",
			tmp;
		function resolve() {
			if ( !( --count ) ) {
				defer.resolveWith( elements, [ elements ] );
			}
		}
		while( i-- ) {
			if (( tmp = jQuery.data( elements[ i ], deferDataKey, undefined, true ) ||
					( jQuery.data( elements[ i ], queueDataKey, undefined, true ) ||
						jQuery.data( elements[ i ], markDataKey, undefined, true ) ) &&
					jQuery.data( elements[ i ], deferDataKey, jQuery.Callbacks( "once memory" ), true ) )) {
				count++;
				tmp.add( resolve );
			}
		}
		resolve();
		return defer.promise();
	}
});




var rclass = /[\n\t\r]/g,
	rspace = /\s+/,
	rreturn = /\r/g,
	rtype = /^(?:button|input)$/i,
	rfocusable = /^(?:button|input|object|select|textarea)$/i,
	rclickable = /^a(?:rea)?$/i,
	rboolean = /^(?:autofocus|autoplay|async|checked|controls|defer|disabled|hidden|loop|multiple|open|readonly|required|scoped|selected)$/i,
	getSetAttribute = jQuery.support.getSetAttribute,
	nodeHook, boolHook, fixSpecified;

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

	removeAttr: function( name ) {
		return this.each(function() {
			jQuery.removeAttr( this, name );
		});
	},

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

	removeProp: function( name ) {
		name = jQuery.propFix[ name ] || name;
		return this.each(function() {
			// try/catch handles cases where IE balks (such as removing a property on window)
			try {
				this[ name ] = undefined;
				delete this[ name ];
			} catch( e ) {}
		});
	},

	addClass: function( value ) {
		var classNames, i, l, elem,
			setClass, c, cl;

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( j ) {
				jQuery( this ).addClass( value.call(this, j, this.className) );
			});
		}

		if ( value && typeof value === "string" ) {
			classNames = value.split( rspace );

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

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

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

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

		return this;
	},

	removeClass: function( value ) {
		var classNames, i, l, elem, className, c, cl;

		if ( jQuery.isFunction( value ) ) {
			return this.each(function( j ) {
				jQuery( this ).removeClass( value.call(this, j, this.className) );
			});
		}

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

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

				if ( elem.nodeType === 1 && elem.className ) {
					if ( value ) {
						className = (" " + elem.className + " ").replace( rclass, " " );
						for ( 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 ) {
				jQuery( this ).toggleClass( value.call(this, i, this.className, 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( rspace );

				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 + " ",
			i = 0,
			l = this.length;
		for ( ; i < l; i++ ) {
			if ( this[i].nodeType === 1 && (" " + this[i].className + " ").replace(rclass, " ").indexOf( className ) > -1 ) {
				return true;
			}
		}

		return false;
	},

	val: function( value ) {
		var hooks, ret, isFunction,
			elem = this[0];

		if ( !arguments.length ) {
			if ( elem ) {
				hooks = jQuery.valHooks[ elem.nodeName.toLowerCase() ] || jQuery.valHooks[ elem.type ];

				if ( hooks && "get" in hooks && (ret = hooks.get( elem, "value" )) !== undefined ) {
					return ret;
				}

				ret = elem.value;

				return typeof ret === "string" ?
					// handle most common string cases
					ret.replace(rreturn, "") :
					// handle cases where value is null/undef or number
					ret == null ? "" : ret;
			}

			return;
		}

		isFunction = jQuery.isFunction( value );

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

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

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

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

			hooks = jQuery.valHooks[ this.nodeName.toLowerCase() ] || jQuery.valHooks[ this.type ];

			// If set returns undefined, fall back to normal setting
			if ( !hooks || !("set" in hooks) || hooks.set( this, val, "value" ) === undefined ) {
				this.value = val;
			}
		});
	}
});

jQuery.extend({
	valHooks: {
		option: {
			get: function( elem ) {
				// 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;
			}
		},
		select: {
			get: function( elem ) {
				var value, i, max, option,
					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
				i = one ? index : 0;
				max = one ? index + 1 : options.length;
				for ( ; i < max; i++ ) {
					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;
			},

			set: function( elem, value ) {
				var values = jQuery.makeArray( value );

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

				if ( !values.length ) {
					elem.selectedIndex = -1;
				}
				return values;
			}
		}
	},

	attrFn: {
		val: true,
		css: true,
		html: true,
		text: true,
		data: true,
		width: true,
		height: true,
		offset: true
	},

	attr: function( elem, name, value, pass ) {
		var ret, hooks, notxml,
			nType = elem.nodeType;

		// don't get/set attributes on text, comment and attribute nodes
		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

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

		// Fallback to prop when attributes are not supported
		if ( typeof elem.getAttribute === "undefined" ) {
			return jQuery.prop( elem, name, value );
		}

		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

		// All attributes are lowercase
		// Grab necessary hook if one is defined
		if ( notxml ) {
			name = name.toLowerCase();
			hooks = jQuery.attrHooks[ name ] || ( rboolean.test( name ) ? boolHook : nodeHook );
		}

		if ( value !== undefined ) {

			if ( value === null ) {
				jQuery.removeAttr( elem, name );
				return;

			} else if ( hooks && "set" in hooks && notxml && (ret = hooks.set( elem, value, name )) !== undefined ) {
				return ret;

			} else {
				elem.setAttribute( name, "" + value );
				return value;
			}

		} else if ( hooks && "get" in hooks && notxml && (ret = hooks.get( elem, name )) !== null ) {
			return ret;

		} else {

			ret = elem.getAttribute( name );

			// Non-existent attributes return null, we normalize to undefined
			return ret === null ?
				undefined :
				ret;
		}
	},

	removeAttr: function( elem, value ) {
		var propName, attrNames, name, l,
			i = 0;

		if ( value && elem.nodeType === 1 ) {
			attrNames = value.toLowerCase().split( rspace );
			l = attrNames.length;

			for ( ; i < l; i++ ) {
				name = attrNames[ i ];

				if ( name ) {
					propName = jQuery.propFix[ name ] || name;

					// See #9699 for explanation of this approach (setting first, then removal)
					jQuery.attr( elem, name, "" );
					elem.removeAttribute( getSetAttribute ? name : propName );

					// Set corresponding property to false for boolean attributes
					if ( rboolean.test( name ) && propName in elem ) {
						elem[ propName ] = false;
					}
				}
			}
		}
	},

	attrHooks: {
		type: {
			set: function( elem, value ) {
				// We can't allow the type property to be changed (since it causes problems in IE)
				if ( rtype.test( elem.nodeName ) && elem.parentNode ) {
					jQuery.error( "type property can't be changed" );
				} else if ( !jQuery.support.radioValue && value === "radio" && jQuery.nodeName(elem, "input") ) {
					// Setting the type on a radio button after the value resets the value in IE6-9
					// Reset value to it's default in case type is set after value
					// This is for element creation
					var val = elem.value;
					elem.setAttribute( "type", value );
					if ( val ) {
						elem.value = val;
					}
					return value;
				}
			}
		},
		// Use the value property for back compat
		// Use the nodeHook for button elements in IE6/7 (#1954)
		value: {
			get: function( elem, name ) {
				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
					return nodeHook.get( elem, name );
				}
				return name in elem ?
					elem.value :
					null;
			},
			set: function( elem, value, name ) {
				if ( nodeHook && jQuery.nodeName( elem, "button" ) ) {
					return nodeHook.set( elem, value, name );
				}
				// Does not return so that setAttribute is also used
				elem.value = value;
			}
		}
	},

	propFix: {
		tabindex: "tabIndex",
		readonly: "readOnly",
		"for": "htmlFor",
		"class": "className",
		maxlength: "maxLength",
		cellspacing: "cellSpacing",
		cellpadding: "cellPadding",
		rowspan: "rowSpan",
		colspan: "colSpan",
		usemap: "useMap",
		frameborder: "frameBorder",
		contenteditable: "contentEditable"
	},

	prop: function( elem, name, value ) {
		var ret, hooks, notxml,
			nType = elem.nodeType;

		// don't get/set properties on text, comment and attribute nodes
		if ( !elem || nType === 3 || nType === 8 || nType === 2 ) {
			return;
		}

		notxml = nType !== 1 || !jQuery.isXMLDoc( elem );

		if ( notxml ) {
			// Fix name and attach hooks
			name = jQuery.propFix[ name ] || name;
			hooks = jQuery.propHooks[ name ];
		}

		if ( value !== undefined ) {
			if ( hooks && "set" in hooks && (ret = hooks.set( elem, value, name )) !== undefined ) {
				return ret;

			} else {
				return ( elem[ name ] = value );
			}

		} else {
			if ( hooks && "get" in hooks && (ret = hooks.get( elem, name )) !== null ) {
				return ret;

			} else {
				return elem[ name ];
			}
		}
	},

	propHooks: {
		tabIndex: {
			get: function( elem ) {
				// 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/
				var attributeNode = elem.getAttributeNode("tabindex");

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

// Add the tabIndex propHook to attrHooks for back-compat (different case is intentional)
jQuery.attrHooks.tabindex = jQuery.propHooks.tabIndex;

// Hook for boolean attributes
boolHook = {
	get: function( elem, name ) {
		// Align boolean attributes with corresponding properties
		// Fall back to attribute presence where some booleans are not supported
		var attrNode,
			property = jQuery.prop( elem, name );
		return property === true || typeof property !== "boolean" && ( attrNode = elem.getAttributeNode(name) ) && attrNode.nodeValue !== false ?
			name.toLowerCase() :
			undefined;
	},
	set: function( elem, value, name ) {
		var propName;
		if ( value === false ) {
			// Remove boolean attributes when set to false
			jQuery.removeAttr( elem, name );
		} else {
			// value is true since we know at this point it's type boolean and not false
			// Set boolean attributes to the same name and set the DOM property
			propName = jQuery.propFix[ name ] || name;
			if ( propName in elem ) {
				// Only set the IDL specifically if it already exists on the element
				elem[ propName ] = true;
			}

			elem.setAttribute( name, name.toLowerCase() );
		}
		return name;
	}
};

// IE6/7 do not support getting/setting some attributes with get/setAttribute
if ( !getSetAttribute ) {

	fixSpecified = {
		name: true,
		id: true
	};

	// Use this for any attribute in IE6/7
	// This fixes almost every IE6/7 issue
	nodeHook = jQuery.valHooks.button = {
		get: function( elem, name ) {
			var ret;
			ret = elem.getAttributeNode( name );
			return ret && ( fixSpecified[ name ] ? ret.nodeValue !== "" : ret.specified ) ?
				ret.nodeValue :
				undefined;
		},
		set: function( elem, value, name ) {
			// Set the existing or create a new attribute node
			var ret = elem.getAttributeNode( name );
			if ( !ret ) {
				ret = document.createAttribute( name );
				elem.setAttributeNode( ret );
			}
			return ( ret.nodeValue = value + "" );
		}
	};

	// Apply the nodeHook to tabindex
	jQuery.attrHooks.tabindex.set = nodeHook.set;

	// Set width and height to auto instead of 0 on empty string( Bug #8150 )
	// This is for removals
	jQuery.each([ "width", "height" ], function( i, name ) {
		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
			set: function( elem, value ) {
				if ( value === "" ) {
					elem.setAttribute( name, "auto" );
					return value;
				}
			}
		});
	});

	// Set contenteditable to false on removals(#10429)
	// Setting to empty string throws an error as an invalid value
	jQuery.attrHooks.contenteditable = {
		get: nodeHook.get,
		set: function( elem, value, name ) {
			if ( value === "" ) {
				value = "false";
			}
			nodeHook.set( elem, value, name );
		}
	};
}


// Some attributes require a special call on IE
if ( !jQuery.support.hrefNormalized ) {
	jQuery.each([ "href", "src", "width", "height" ], function( i, name ) {
		jQuery.attrHooks[ name ] = jQuery.extend( jQuery.attrHooks[ name ], {
			get: function( elem ) {
				var ret = elem.getAttribute( name, 2 );
				return ret === null ? undefined : ret;
			}
		});
	});
}

if ( !jQuery.support.style ) {
	jQuery.attrHooks.style = {
		get: function( elem ) {
			// Return undefined in the case of empty string
			// Normalize to lowercase since IE uppercases css property names
			return elem.style.cssText.toLowerCase() || undefined;
		},
		set: function( elem, value ) {
			return ( elem.style.cssText = "" + value );
		}
	};
}

// Safari mis-reports the default selected property of an option
// Accessing the parent's selectedIndex property fixes it
if ( !jQuery.support.optSelected ) {
	jQuery.propHooks.selected = jQuery.extend( jQuery.propHooks.selected, {
		get: function( elem ) {
			var parent = elem.parentNode;

			if ( parent ) {
				parent.selectedIndex;

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

// IE6/7 call enctype encoding
if ( !jQuery.support.enctype ) {
	jQuery.propFix.enctype = "encoding";
}

// Radios and checkboxes getter/setter
if ( !jQuery.support.checkOn ) {
	jQuery.each([ "radio", "checkbox" ], function() {
		jQuery.valHooks[ this ] = {
			get: function( elem ) {
				// Handle the case where in Webkit "" is returned instead of "on" if a value isn't specified
				return elem.getAttribute("value") === null ? "on" : elem.value;
			}
		};
	});
}
jQuery.each([ "radio", "checkbox" ], function() {
	jQuery.valHooks[ this ] = jQuery.extend( jQuery.valHooks[ this ], {
		set: function( elem, value ) {
			if ( jQuery.isArray( value ) ) {
				return ( elem.checked = jQuery.inArray( jQuery(elem).val(), value ) >= 0 );
			}
		}
	});
});




var rformElems = /^(?:textarea|input|select)$/i,
	rtypenamespace = /^([^\.]*)?(?:\.(.+))?$/,
	rhoverHack = /\bhover(\.\S+)?\b/,
	rkeyEvent = /^key/,
	rmouseEvent = /^(?:mouse|contextmenu)|click/,
	rfocusMorph = /^(?:focusinfocus|focusoutblur)$/,
	rquickIs = /^(\w*)(?:#([\w\-]+))?(?:\.([\w\-]+))?$/,
	quickParse = function( selector ) {
		var quick = rquickIs.exec( selector );
		if ( quick ) {
			//   0  1    2   3
			// [ _, tag, id, class ]
			quick[1] = ( quick[1] || "" ).toLowerCase();
			quick[3] = quick[3] && new RegExp( "(?:^|\\s)" + quick[3] + "(?:\\s|$)" );
		}
		return quick;
	},
	quickIs = function( elem, m ) {
		var attrs = elem.attributes || {};
		return (
			(!m[1] || elem.nodeName.toLowerCase() === m[1]) &&
			(!m[2] || (attrs.id || {}).value === m[2]) &&
			(!m[3] || m[3].test( (attrs[ "class" ] || {}).value ))
		);
	},
	hoverHack = function( events ) {
		return jQuery.event.special.hover ? events : events.replace( rhoverHack, "mouseenter$1 mouseleave$1" );
	};

/*
 * Helper functions for managing events -- not part of the public interface.
 * Props to Dean Edwards' addEvent library for many of the ideas.
 */
jQuery.event = {

	add: function( elem, types, handler, data, selector ) {

		var elemData, eventHandle, events,
			t, tns, type, namespaces, handleObj,
			handleObjIn, quick, handlers, special;

		// Don't attach events to noData or text/comment nodes (allow plain objects tho)
		if ( elem.nodeType === 3 || elem.nodeType === 8 || !types || !handler || !(elemData = jQuery._data( elem )) ) {
			return;
		}

		// Caller can pass in an object of custom data in lieu of the handler
		if ( handler.handler ) {
			handleObjIn = handler;
			handler = handleObjIn.handler;
		}

		// Make sure that the handler has a unique ID, used to find/remove it later
		if ( !handler.guid ) {
			handler.guid = jQuery.guid++;
		}

		// Init the element's event structure and main handler, if this is the first
		events = elemData.events;
		if ( !events ) {
			elemData.events = events = {};
		}
		eventHandle = elemData.handle;
		if ( !eventHandle ) {
			elemData.handle = eventHandle = function( e ) {
				// Discard the second event of a jQuery.event.trigger() and
				// when an event is called after a page has unloaded
				return typeof jQuery !== "undefined" && (!e || jQuery.event.triggered !== e.type) ?
					jQuery.event.dispatch.apply( eventHandle.elem, arguments ) :
					undefined;
			};
			// Add elem as a property of the handle fn to prevent a memory leak with IE non-native events
			eventHandle.elem = elem;
		}

		// Handle multiple events separated by a space
		// jQuery(...).bind("mouseover mouseout", fn);
		types = jQuery.trim( hoverHack(types) ).split( " " );
		for ( t = 0; t < types.length; t++ ) {

			tns = rtypenamespace.exec( types[t] ) || [];
			type = tns[1];
			namespaces = ( tns[2] || "" ).split( "." ).sort();

			// If event changes its type, use the special event handlers for the changed type
			special = jQuery.event.special[ type ] || {};

			// If selector defined, determine special event api type, otherwise given type
			type = ( selector ? special.delegateType : special.bindType ) || type;

			// Update special based on newly reset type
			special = jQuery.event.special[ type ] || {};

			// handleObj is passed to all event handlers
			handleObj = jQuery.extend({
				type: type,
				origType: tns[1],
				data: data,
				handler: handler,
				guid: handler.guid,
				selector: selector,
				quick: quickParse( selector ),
				namespace: namespaces.join(".")
			}, handleObjIn );

			// Init the event handler queue if we're the first
			handlers = events[ type ];
			if ( !handlers ) {
				handlers = events[ type ] = [];
				handlers.delegateCount = 0;

				// 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 to the element's handler list, delegates in front
			if ( selector ) {
				handlers.splice( handlers.delegateCount++, 0, handleObj );
			} else {
				handlers.push( handleObj );
			}

			// Keep track of which events have ever been used, for event optimization
			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, selector, mappedTypes ) {

		var elemData = jQuery.hasData( elem ) && jQuery._data( elem ),
			t, tns, type, origType, namespaces, origCount,
			j, events, special, handle, eventType, handleObj;

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

		// Once for each type.namespace in types; type may be omitted
		types = jQuery.trim( hoverHack( types || "" ) ).split(" ");
		for ( t = 0; t < types.length; t++ ) {
			tns = rtypenamespace.exec( types[t] ) || [];
			type = origType = tns[1];
			namespaces = tns[2];

			// Unbind all events (on this namespace, if provided) for the element
			if ( !type ) {
				for ( type in events ) {
					jQuery.event.remove( elem, type + types[ t ], handler, selector, true );
				}
				continue;
			}

			special = jQuery.event.special[ type ] || {};
			type = ( selector? special.delegateType : special.bindType ) || type;
			eventType = events[ type ] || [];
			origCount = eventType.length;
			namespaces = namespaces ? new RegExp("(^|\\.)" + namespaces.split(".").sort().join("\\.(?:.*\\.)?") + "(\\.|$)") : null;

			// Remove matching events
			for ( j = 0; j < eventType.length; j++ ) {
				handleObj = eventType[ j ];

				if ( ( mappedTypes || origType === handleObj.origType ) &&
					 ( !handler || handler.guid === handleObj.guid ) &&
					 ( !namespaces || namespaces.test( handleObj.namespace ) ) &&
					 ( !selector || selector === handleObj.selector || selector === "**" && handleObj.selector ) ) {
					eventType.splice( j--, 1 );

					if ( handleObj.selector ) {
						eventType.delegateCount--;
					}
					if ( special.remove ) {
						special.remove.call( elem, handleObj );
					}
				}
			}

			// Remove generic event handler if we removed something and no more handlers exist
			// (avoids potential for endless recursion during removal of special event handlers)
			if ( eventType.length === 0 && origCount !== eventType.length ) {
				if ( !special.teardown || special.teardown.call( elem, namespaces ) === false ) {
					jQuery.removeEvent( elem, type, elemData.handle );
				}

				delete events[ type ];
			}
		}

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

			// removeData also checks for emptiness and clears the expando if empty
			// so use it instead of delete
			jQuery.removeData( elem, [ "events", "handle" ], true );
		}
	},

	// Events that are safe to short-circuit if no handlers are attached.
	// Native DOM events should not be added, they may have inline handlers.
	customEvent: {
		"getData": true,
		"setData": true,
		"changeData": true
	},

	trigger: function( event, data, elem, onlyHandlers ) {
		// Don't do events on text and comment nodes
		if ( elem && (elem.nodeType === 3 || elem.nodeType === 8) ) {
			return;
		}

		// Event object or event type
		var type = event.type || event,
			namespaces = [],
			cache, exclusive, i, cur, old, ontype, special, handle, eventPath, bubbleType;

		// focus/blur morphs to focusin/out; ensure we're not firing them right now
		if ( rfocusMorph.test( type + jQuery.event.triggered ) ) {
			return;
		}

		if ( type.indexOf( "!" ) >= 0 ) {
			// Exclusive events trigger only for the exact event (no namespaces)
			type = type.slice(0, -1);
			exclusive = true;
		}

		if ( type.indexOf( "." ) >= 0 ) {
			// Namespaced trigger; create a regexp to match event type in handle()
			namespaces = type.split(".");
			type = namespaces.shift();
			namespaces.sort();
		}

		if ( (!elem || jQuery.event.customEvent[ type ]) && !jQuery.event.global[ type ] ) {
			// No jQuery handlers for this event type, and it can't have inline handlers
			return;
		}

		// Caller can pass in an Event, Object, or just an event type string
		event = typeof event === "object" ?
			// jQuery.Event object
			event[ jQuery.expando ] ? event :
			// Object literal
			new jQuery.Event( type, event ) :
			// Just the event type (string)
			new jQuery.Event( type );

		event.type = type;
		event.isTrigger = true;
		event.exclusive = exclusive;
		event.namespace = namespaces.join( "." );
		event.namespace_re = event.namespace? new RegExp("(^|\\.)" + namespaces.join("\\.(?:.*\\.)?") + "(\\.|$)") : null;
		ontype = type.indexOf( ":" ) < 0 ? "on" + type : "";

		// Handle a global trigger
		if ( !elem ) {

			// TODO: Stop taunting the data cache; remove global events and always attach to document
			cache = jQuery.cache;
			for ( i in cache ) {
				if ( cache[ i ].events && cache[ i ].events[ type ] ) {
					jQuery.event.trigger( event, data, cache[ i ].handle.elem, true );
				}
			}
			return;
		}

		// Clean up the event in case it is being reused
		event.result = undefined;
		if ( !event.target ) {
			event.target = elem;
		}

		// Clone any incoming data and prepend the event, creating the handler arg list
		data = data != null ? jQuery.makeArray( data ) : [];
		data.unshift( event );

		// Allow special events to draw outside the lines
		special = jQuery.event.special[ type ] || {};
		if ( special.trigger && special.trigger.apply( elem, data ) === false ) {
			return;
		}

		// Determine event propagation path in advance, per W3C events spec (#9951)
		// Bubble up to document, then to window; watch for a global ownerDocument var (#9724)
		eventPath = [[ elem, special.bindType || type ]];
		if ( !onlyHandlers && !special.noBubble && !jQuery.isWindow( elem ) ) {

			bubbleType = special.delegateType || type;
			cur = rfocusMorph.test( bubbleType + type ) ? elem : elem.parentNode;
			old = null;
			for ( ; cur; cur = cur.parentNode ) {
				eventPath.push([ cur, bubbleType ]);
				old = cur;
			}

			// Only add window if we got to document (e.g., not plain obj or detached DOM)
			if ( old && old === elem.ownerDocument ) {
				eventPath.push([ old.defaultView || old.parentWindow || window, bubbleType ]);
			}
		}

		// Fire handlers on the event path
		for ( i = 0; i < eventPath.length && !event.isPropagationStopped(); i++ ) {

			cur = eventPath[i][0];
			event.type = eventPath[i][1];

			handle = ( jQuery._data( cur, "events" ) || {} )[ event.type ] && jQuery._data( cur, "handle" );
			if ( handle ) {
				handle.apply( cur, data );
			}
			// Note that this is a bare JS function and not a jQuery handler
			handle = ontype && cur[ ontype ];
			if ( handle && jQuery.acceptData( cur ) && handle.apply( cur, data ) === false ) {
				event.preventDefault();
			}
		}
		event.type = type;

		// If nobody prevented the default action, do it now
		if ( !onlyHandlers && !event.isDefaultPrevented() ) {

			if ( (!special._default || special._default.apply( elem.ownerDocument, data ) === false) &&
				!(type === "click" && jQuery.nodeName( elem, "a" )) && jQuery.acceptData( elem ) ) {

				// Call a native DOM method on the target with the same name name as the event.
				// Can't use an .isFunction() check here because IE6/7 fails that test.
				// Don't do default actions on window, that's where global variables be (#6170)
				// IE<9 dies on focus/blur to hidden element (#1486)
				if ( ontype && elem[ type ] && ((type !== "focus" && type !== "blur") || event.target.offsetWidth !== 0) && !jQuery.isWindow( elem ) ) {

					// Don't re-trigger an onFOO event when we call its FOO() method
					old = elem[ ontype ];

					if ( old ) {
						elem[ ontype ] = null;
					}

					// Prevent re-triggering of the same event, since we already bubbled it above
					jQuery.event.triggered = type;
					elem[ type ]();
					jQuery.event.triggered = undefined;

					if ( old ) {
						elem[ ontype ] = old;
					}
				}
			}
		}

		return event.result;
	},

	dispatch: function( event ) {

		// Make a writable jQuery.Event from the native event object
		event = jQuery.event.fix( event || window.event );

		var handlers = ( (jQuery._data( this, "events" ) || {} )[ event.type ] || []),
			delegateCount = handlers.delegateCount,
			args = [].slice.call( arguments, 0 ),
			run_all = !event.exclusive && !event.namespace,
			handlerQueue = [],
			i, j, cur, jqcur, ret, selMatch, matched, matches, handleObj, sel, related;

		// Use the fix-ed jQuery.Event rather than the (read-only) native event
		args[0] = event;
		event.delegateTarget = this;

		// Determine handlers that should run if there are delegated events
		// Avoid disabled elements in IE (#6911) and non-left-click bubbling in Firefox (#3861)
		if ( delegateCount && !event.target.disabled && !(event.button && event.type === "click") ) {

			// Pregenerate a single jQuery object for reuse with .is()
			jqcur = jQuery(this);
			jqcur.context = this.ownerDocument || this;

			for ( cur = event.target; cur != this; cur = cur.parentNode || this ) {
				selMatch = {};
				matches = [];
				jqcur[0] = cur;
				for ( i = 0; i < delegateCount; i++ ) {
					handleObj = handlers[ i ];
					sel = handleObj.selector;

					if ( selMatch[ sel ] === undefined ) {
						selMatch[ sel ] = (
							handleObj.quick ? quickIs( cur, handleObj.quick ) : jqcur.is( sel )
						);
					}
					if ( selMatch[ sel ] ) {
						matches.push( handleObj );
					}
				}
				if ( matches.length ) {
					handlerQueue.push({ elem: cur, matches: matches });
				}
			}
		}

		// Add the remaining (directly-bound) handlers
		if ( handlers.length > delegateCount ) {
			handlerQueue.push({ elem: this, matches: handlers.slice( delegateCount ) });
		}

		// Run delegates first; they may want to stop propagation beneath us
		for ( i = 0; i < handlerQueue.length && !event.isPropagationStopped(); i++ ) {
			matched = handlerQueue[ i ];
			event.currentTarget = matched.elem;

			for ( j = 0; j < matched.matches.length && !event.isImmediatePropagationStopped(); j++ ) {
				handleObj = matched.matches[ j ];

				// Triggered event must either 1) be non-exclusive and have no namespace, or
				// 2) have namespace(s) a subset or equal to those in the bound event (both can have no namespace).
				if ( run_all || (!event.namespace && !handleObj.namespace) || event.namespace_re && event.namespace_re.test( handleObj.namespace ) ) {

					event.data = handleObj.data;
					event.handleObj = handleObj;

					ret = ( (jQuery.event.special[ handleObj.origType ] || {}).handle || handleObj.handler )
							.apply( matched.elem, args );

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

		return event.result;
	},

	// Includes some event props shared by KeyEvent and MouseEvent
	// *** attrChange attrName relatedNode srcElement  are not normalized, non-W3C, deprecated, will be removed in 1.8 ***
	props: "attrChange attrName relatedNode srcElement altKey bubbles cancelable ctrlKey currentTarget eventPhase metaKey relatedTarget shiftKey target timeStamp view which".split(" "),

	fixHooks: {},

	keyHooks: {
		props: "char charCode key keyCode".split(" "),
		filter: function( event, original ) {

			// Add which for key events
			if ( event.which == null ) {
				event.which = original.charCode != null ? original.charCode : original.keyCode;
			}

			return event;
		}
	},

	mouseHooks: {
		props: "button buttons clientX clientY fromElement offsetX offsetY pageX pageY screenX screenY toElement".split(" "),
		filter: function( event, original ) {
			var eventDoc, doc, body,
				button = original.button,
				fromElement = original.fromElement;

			// Calculate pageX/Y if missing and clientX/Y available
			if ( event.pageX == null && original.clientX != null ) {
				eventDoc = event.target.ownerDocument || document;
				doc = eventDoc.documentElement;
				body = eventDoc.body;

				event.pageX = original.clientX + ( doc && doc.scrollLeft || body && body.scrollLeft || 0 ) - ( doc && doc.clientLeft || body && body.clientLeft || 0 );
				event.pageY = original.clientY + ( doc && doc.scrollTop  || body && body.scrollTop  || 0 ) - ( doc && doc.clientTop  || body && body.clientTop  || 0 );
			}

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

			// Add which for click: 1 === left; 2 === middle; 3 === right
			// Note: button is not normalized, so don't use it
			if ( !event.which && button !== undefined ) {
				event.which = ( button & 1 ? 1 : ( button & 2 ? 3 : ( button & 4 ? 2 : 0 ) ) );
			}

			return event;
		}
	},

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

		// Create a writable copy of the event object and normalize some properties
		var i, prop,
			originalEvent = event,
			fixHook = jQuery.event.fixHooks[ event.type ] || {},
			copy = fixHook.props ? this.props.concat( fixHook.props ) : this.props;

		event = jQuery.Event( originalEvent );

		for ( i = copy.length; i; ) {
			prop = copy[ --i ];
			event[ prop ] = originalEvent[ prop ];
		}

		// Fix target property, if necessary (#1925, IE 6/7/8 & Safari2)
		if ( !event.target ) {
			event.target = originalEvent.srcElement || document;
		}

		// Target should not be a text node (#504, Safari)
		if ( event.target.nodeType === 3 ) {
			event.target = event.target.parentNode;
		}

		// For mouse/key events; add metaKey if it's not there (#3368, IE6/7/8)
		if ( event.metaKey === undefined ) {
			event.metaKey = event.ctrlKey;
		}

		return fixHook.filter? fixHook.filter( event, originalEvent ) : event;
	},

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

		load: {
			// Prevent triggered image.load events from bubbling to window.load
			noBubble: true
		},

		focus: {
			delegateType: "focusin"
		},
		blur: {
			delegateType: "focusout"
		},

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

	simulate: function( type, elem, event, bubble ) {
		// 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.
		var e = jQuery.extend(
			new jQuery.Event(),
			event,
			{ type: type,
				isSimulated: true,
				originalEvent: {}
			}
		);
		if ( bubble ) {
			jQuery.event.trigger( e, null, elem );
		} else {
			jQuery.event.dispatch.call( elem, e );
		}
		if ( e.isDefaultPrevented() ) {
			event.preventDefault();
		}
	}
};

// Some plugins are using, but it's undocumented/deprecated and will be removed.
// The 1.7 special event interface should provide all the hooks needed now.
jQuery.event.handle = jQuery.event.dispatch;

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, props ) {
	// Allow instantiation without the 'new' keyword
	if ( !(this instanceof jQuery.Event) ) {
		return new jQuery.Event( src, props );
	}

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

	// Put explicitly provided properties onto the event object
	if ( props ) {
		jQuery.extend( this, props );
	}

	// Create a timestamp if incoming event doesn't have one
	this.timeStamp = src && src.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
};

// Create mouseenter/leave events using mouseover/out and event-time checks
jQuery.each({
	mouseenter: "mouseover",
	mouseleave: "mouseout"
}, function( orig, fix ) {
	jQuery.event.special[ orig ] = {
		delegateType: fix,
		bindType: fix,

		handle: function( event ) {
			var target = this,
				related = event.relatedTarget,
				handleObj = event.handleObj,
				selector = handleObj.selector,
				ret;

			// For mousenter/leave call the handler if related is outside the target.
			// NB: No relatedTarget if the mouse left/entered the browser window
			if ( !related || (related !== target && !jQuery.contains( target, related )) ) {
				event.type = handleObj.origType;
				ret = handleObj.handler.apply( this, arguments );
				event.type = fix;
			}
			return ret;
		}
	};
});

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

	jQuery.event.special.submit = {
		setup: function() {
			// Only need this for delegated form submit events
			if ( jQuery.nodeName( this, "form" ) ) {
				return false;
			}

			// Lazy-add a submit handler when a descendant form may potentially be submitted
			jQuery.event.add( this, "click._submit keypress._submit", function( e ) {
				// Node name check avoids a VML-related crash in IE (#9807)
				var elem = e.target,
					form = jQuery.nodeName( elem, "input" ) || jQuery.nodeName( elem, "button" ) ? elem.form : undefined;
				if ( form && !form._submit_attached ) {
					jQuery.event.add( form, "submit._submit", function( event ) {
						// If form was submitted by the user, bubble the event up the tree
						if ( this.parentNode && !event.isTrigger ) {
							jQuery.event.simulate( "submit", this.parentNode, event, true );
						}
					});
					form._submit_attached = true;
				}
			});
			// return undefined since we don't need an event listener
		},

		teardown: function() {
			// Only need this for delegated form submit events
			if ( jQuery.nodeName( this, "form" ) ) {
				return false;
			}

			// Remove delegated handlers; cleanData eventually reaps submit handlers attached above
			jQuery.event.remove( this, "._submit" );
		}
	};
}

// IE change delegation and checkbox/radio fix
if ( !jQuery.support.changeBubbles ) {

	jQuery.event.special.change = {

		setup: function() {

			if ( rformElems.test( this.nodeName ) ) {
				// IE doesn't fire change on a check/radio until blur; trigger it on click
				// after a propertychange. Eat the blur-change in special.change.handle.
				// This still fires onchange a second time for check/radio after blur.
				if ( this.type === "checkbox" || this.type === "radio" ) {
					jQuery.event.add( this, "propertychange._change", function( event ) {
						if ( event.originalEvent.propertyName === "checked" ) {
							this._just_changed = true;
						}
					});
					jQuery.event.add( this, "click._change", function( event ) {
						if ( this._just_changed && !event.isTrigger ) {
							this._just_changed = false;
							jQuery.event.simulate( "change", this, event, true );
						}
					});
				}
				return false;
			}
			// Delegated event; lazy-add a change handler on descendant inputs
			jQuery.event.add( this, "beforeactivate._change", function( e ) {
				var elem = e.target;

				if ( rformElems.test( elem.nodeName ) && !elem._change_attached ) {
					jQuery.event.add( elem, "change._change", function( event ) {
						if ( this.parentNode && !event.isSimulated && !event.isTrigger ) {
							jQuery.event.simulate( "change", this.parentNode, event, true );
						}
					});
					elem._change_attached = true;
				}
			});
		},

		handle: function( event ) {
			var elem = event.target;

			// Swallow native change events from checkbox/radio, we already triggered them above
			if ( this !== elem || event.isSimulated || event.isTrigger || (elem.type !== "radio" && elem.type !== "checkbox") ) {
				return event.handleObj.handler.apply( this, arguments );
			}
		},

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

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

// Create "bubbling" focus and blur events
if ( !jQuery.support.focusinBubbles ) {
	jQuery.each({ focus: "focusin", blur: "focusout" }, function( orig, fix ) {

		// Attach a single capturing handler while someone wants focusin/focusout
		var attaches = 0,
			handler = function( event ) {
				jQuery.event.simulate( fix, event.target, jQuery.event.fix( event ), true );
			};

		jQuery.event.special[ fix ] = {
			setup: function() {
				if ( attaches++ === 0 ) {
					document.addEventListener( orig, handler, true );
				}
			},
			teardown: function() {
				if ( --attaches === 0 ) {
					document.removeEventListener( orig, handler, true );
				}
			}
		};
	});
}

jQuery.fn.extend({

	on: function( types, selector, data, fn, /*INTERNAL*/ one ) {
		var origFn, type;

		// Types can be a map of types/handlers
		if ( typeof types === "object" ) {
			// ( types-Object, selector, data )
			if ( typeof selector !== "string" ) {
				// ( types-Object, data )
				data = selector;
				selector = undefined;
			}
			for ( type in types ) {
				this.on( type, selector, data, types[ type ], one );
			}
			return this;
		}

		if ( data == null && fn == null ) {
			// ( types, fn )
			fn = selector;
			data = selector = undefined;
		} else if ( fn == null ) {
			if ( typeof selector === "string" ) {
				// ( types, selector, fn )
				fn = data;
				data = undefined;
			} else {
				// ( types, data, fn )
				fn = data;
				data = selector;
				selector = undefined;
			}
		}
		if ( fn === false ) {
			fn = returnFalse;
		} else if ( !fn ) {
			return this;
		}

		if ( one === 1 ) {
			origFn = fn;
			fn = function( event ) {
				// Can use an empty set, since event contains the info
				jQuery().off( event );
				return origFn.apply( this, arguments );
			};
			// Use same guid so caller can remove using origFn
			fn.guid = origFn.guid || ( origFn.guid = jQuery.guid++ );
		}
		return this.each( function() {
			jQuery.event.add( this, types, fn, data, selector );
		});
	},
	one: function( types, selector, data, fn ) {
		return this.on.call( this, types, selector, data, fn, 1 );
	},
	off: function( types, selector, fn ) {
		if ( types && types.preventDefault && types.handleObj ) {
			// ( event )  dispatched jQuery.Event
			var handleObj = types.handleObj;
			jQuery( types.delegateTarget ).off(
				handleObj.namespace? handleObj.type + "." + handleObj.namespace : handleObj.type,
				handleObj.selector,
				handleObj.handler
			);
			return this;
		}
		if ( typeof types === "object" ) {
			// ( types-object [, selector] )
			for ( var type in types ) {
				this.off( type, selector, types[ type ] );
			}
			return this;
		}
		if ( selector === false || typeof selector === "function" ) {
			// ( types [, fn] )
			fn = selector;
			selector = undefined;
		}
		if ( fn === false ) {
			fn = returnFalse;
		}
		return this.each(function() {
			jQuery.event.remove( this, types, fn, selector );
		});
	},

	bind: function( types, data, fn ) {
		return this.on( types, null, data, fn );
	},
	unbind: function( types, fn ) {
		return this.off( types, null, fn );
	},

	live: function( types, data, fn ) {
		jQuery( this.context ).on( types, this.selector, data, fn );
		return this;
	},
	die: function( types, fn ) {
		jQuery( this.context ).off( types, this.selector || "**", fn );
		return this;
	},

	delegate: function( selector, types, data, fn ) {
		return this.on( types, selector, data, fn );
	},
	undelegate: function( selector, types, fn ) {
		// ( namespace ) or ( selector, types [, fn] )
		return arguments.length == 1? this.off( selector, "**" ) : this.off( types, selector, fn );
	},

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

	toggle: function( fn ) {
		// Save reference to arguments for access in closure
		var args = arguments,
			guid = fn.guid || jQuery.guid++,
			i = 0,
			toggler = 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;
			};

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

		return this.click( toggler );
	},

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

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 contextmenu").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.on( name, null, data, fn ) :
			this.trigger( name );
	};

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

	if ( rkeyEvent.test( name ) ) {
		jQuery.event.fixHooks[ name ] = jQuery.event.keyHooks;
	}

	if ( rmouseEvent.test( name ) ) {
		jQuery.event.fixHooks[ name ] = jQuery.event.mouseHooks;
	}
});



/*!
 * 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,
	expando = "sizcache" + (Math.random() + '').replace('.', ''),
	done = 0,
	toString = Object.prototype.toString,
	hasDuplicate = false,
	baseHasDuplicate = true,
	rBackslash = /\\/g,
	rReturn = /\r\n/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, seed );

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

	} 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, i, len, match, type, left;

	if ( !expr ) {
		return [];
	}

	for ( i = 0, len = Expr.order.length; i < len; i++ ) {
		type = Expr.order[i];
		
		if ( (match = Expr.leftMatch[ type ].exec( expr )) ) {
			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,
		type, found, item, filter, left,
		i, pass,
		old = expr,
		result = [],
		curLoop = set,
		isXMLFilter = set && set[0] && Sizzle.isXML( set[0] );

	while ( expr && set.length ) {
		for ( type in Expr.filter ) {
			if ( (match = Expr.leftMatch[ type ].exec( expr )) != null && match[2] ) {
				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 ( i = 0; (item = curLoop[i]) != null; i++ ) {
						if ( item ) {
							found = filter( item, match, i, curLoop );
							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 new Error( "Syntax error, unrecognized expression: " + msg );
};

/**
 * Utility function for retreiving the text value of an array of DOM nodes
 * @param {Array|Element} elem
 */
var getText = Sizzle.getText = function( elem ) {
    var i, node,
		nodeType = elem.nodeType,
		ret = "";

	if ( nodeType ) {
		if ( nodeType === 1 || nodeType === 9 ) {
			// Use textContent || innerText for elements
			if ( typeof elem.textContent === 'string' ) {
				return elem.textContent;
			} else if ( typeof elem.innerText === 'string' ) {
				// Replace IE's carriage returns
				return elem.innerText.replace( rReturn, '' );
			} else {
				// Traverse it's children
				for ( elem = elem.firstChild; elem; elem = elem.nextSibling) {
					ret += getText( elem );
				}
			}
		} else if ( nodeType === 3 || nodeType === 4 ) {
			return elem.nodeValue;
		}
	} else {

		// If no nodeType, this is expected to be an array
		for ( i = 0; (node = elem[i]); i++ ) {
			// Do not traverse comment nodes
			if ( node.nodeType !== 8 ) {
				ret += getText( node );
			}
		}
	}
	return ret;
};

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 ) {
			var attr = elem.getAttribute( "type" ), type = elem.type;
			// IE6 and 7 will map elem.type to 'text' for new HTML5 types (search, etc) 
			// use getAttribute instead to test this case
			return elem.nodeName.toLowerCase() === "input" && "text" === type && ( attr === type || attr === null );
		},

		radio: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "radio" === elem.type;
		},

		checkbox: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "checkbox" === elem.type;
		},

		file: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "file" === elem.type;
		},

		password: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "password" === elem.type;
		},

		submit: function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return (name === "input" || name === "button") && "submit" === elem.type;
		},

		image: function( elem ) {
			return elem.nodeName.toLowerCase() === "input" && "image" === elem.type;
		},

		reset: function( elem ) {
			var name = elem.nodeName.toLowerCase();
			return (name === "input" || name === "button") && "reset" === elem.type;
		},

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

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

		focus: function( elem ) {
			return elem === elem.ownerDocument.activeElement;
		}
	},
	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 || 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 first, last,
				doneName, parent, cache,
				count, diff,
				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":
					first = match[2];
					last = match[3];

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

						parent[ expando ] = doneName;
					}
					
					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 && 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 = Sizzle.attr ?
					Sizzle.attr( elem, name ) :
					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 && Sizzle.attr ?
				result != null :
				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 ) {
		// The nodes are identical, we can exit early
		if ( a === b ) {
			hasDuplicate = true;
			return 0;

		// Fallback to using sourceIndex (in IE) if it's available on both nodes
		} else if ( a.sourceIndex && b.sourceIndex ) {
			return a.sourceIndex - b.sourceIndex;
		}

		var al, bl,
			ap = [],
			bp = [],
			aup = a.parentNode,
			bup = b.parentNode,
			cur = aup;

		// If the nodes are siblings (or identical) we can do a quick check
		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;
	};
}

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

	if ( matches ) {
		// Check to see if it's possible to do matchesSelector
		// on a disconnected node (IE 9 fails this)
		var disconnectedMatch = !matches.call( document.createElement( "div" ), "div" ),
			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;
		}

		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 ) ) {
						var ret = matches.call( node, expr );

						// IE 9's matchesSelector returns false on disconnected nodes
						if ( ret || !disconnectedMatch ||
								// As well, disconnected nodes are said to be in a document
								// fragment in IE 9, so check for that
								node.document && node.document.nodeType !== 11 ) {
							return ret;
						}
					}
				} 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[ expando ] === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 && !isXML ){
					elem[ expando ] = 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[ expando ] === doneName ) {
					match = checkSet[elem.sizset];
					break;
				}

				if ( elem.nodeType === 1 ) {
					if ( !isXML ) {
						elem[ expando ] = 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, seed ) {
	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, seed );
	}

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

// EXPOSE
// Override sizzle attribute retrieval
Sizzle.attr = jQuery.attr;
Sizzle.selectors.attrMap = {};
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 self = this,
			i, l;

		if ( typeof selector !== "string" ) {
			return jQuery( selector ).filter(function() {
				for ( i = 0, l = self.length; i < l; i++ ) {
					if ( jQuery.contains( self[ i ], this ) ) {
						return true;
					}
				}
			});
		}

		var ret = this.pushStack( "", "find", selector ),
			length, n, r;

		for ( 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 ( n = length; n < ret.length; n++ ) {
					for ( 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 && ( 
			typeof selector === "string" ?
				// If this is a positional selector, check membership in the returned set
				// so $("p:first").is("p:last") won't return true for a doc with two "p".
				POS.test( selector ) ? 
					jQuery( selector, this.context ).index( this[0] ) >= 0 :
					jQuery.filter( selector, this ).length > 0 :
				this.filter( selector ).length > 0 );
	},

	closest: function( selectors, context ) {
		var ret = [], i, l, cur = this[0];
		
		// Array (deprecated as of jQuery 1.7)
		if ( jQuery.isArray( selectors ) ) {
			var level = 1;

			while ( cur && cur.ownerDocument && cur !== context ) {
				for ( i = 0; i < selectors.length; i++ ) {

					if ( jQuery( cur ).is( selectors[ i ] ) ) {
						ret.push({ selector: selectors[ i ], elem: cur, level: level });
					}
				}

				cur = cur.parentNode;
				level++;
			}

			return ret;
		}

		// String
		var pos = POS.test( selectors ) || typeof selectors !== "string" ?
				jQuery( selectors, context || this.context ) :
				0;

		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 || cur.nodeType === 11 ) {
						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 ) {

		// No argument, return index in parent
		if ( !elem ) {
			return ( this[0] && this[0].parentNode ) ? this.prevAll().length : -1;
		}

		// index in selector
		if ( typeof elem === "string" ) {
			return jQuery.inArray( this[0], jQuery( elem ) );
		}

		// 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 && selector.nodeType ? [ selector ] : 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 );

		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, slice.call( arguments ).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 ) {

	// Can't pass null or undefined to indexOf in Firefox 4
	// Set to 0 to skip string check
	qualifier = qualifier || 0;

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




function createSafeFragment( document ) {
	var list = nodeNames.split( "|" ),
	safeFrag = document.createDocumentFragment();

	if ( safeFrag.createElement ) {
		while ( list.length ) {
			safeFrag.createElement(
				list.pop()
			);
		}
	}
	return safeFrag;
}

var nodeNames = "abbr|article|aside|audio|canvas|datalist|details|figcaption|figure|footer|" +
		"header|hgroup|mark|meter|nav|output|progress|section|summary|time|video",
	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+;/,
	rnoInnerhtml = /<(?:script|style)/i,
	rnocache = /<(?:script|object|embed|option|style)/i,
	rnoshimcache = new RegExp("<(?:" + nodeNames + ")", "i"),
	// checked="checked" or checked
	rchecked = /checked\s*(?:[^=]|=\s*.checked.)/i,
	rscriptType = /\/(java|ecma)script/i,
	rcleanScript = /^\s*<!(?:\[CDATA\[|\-\-)/,
	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, "", "" ]
	},
	safeFragment = createSafeFragment( document );

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 ) {
		var isFunction = jQuery.isFunction( html );

		return this.each(function(i) {
			jQuery( this ).wrapAll( isFunction ? html.call(this, i) : 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.clean( arguments );
			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.clean(arguments) );
			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" && !rnoInnerhtml.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.length ?
				this.pushStack( jQuery(jQuery.isFunction(value) ? value() : value), "replaceWith", value ) :
				this;
		}
	},

	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 type, i, l,
		oldData = jQuery._data( src ),
		curData = jQuery._data( dest, oldData ),
		events = oldData.events;

	if ( events ) {
		delete curData.handle;
		curData.events = {};

		for ( type in events ) {
			for ( 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 );
			}
		}
	}

	// make the cloned public data object a copy from the original
	if ( curData.data ) {
		curData.data = jQuery.extend( {}, curData.data );
	}
}

function cloneFixAttributes( src, dest ) {
	var nodeName;

	// We do not need to do anything for non-Elements
	if ( dest.nodeType !== 1 ) {
		return;
	}

	// clearAttributes removes the attributes, which we don't want,
	// but also removes the attachEvent events, which we *do* want
	if ( dest.clearAttributes ) {
		dest.clearAttributes();
	}

	// mergeAttributes, in contrast, only merges back on the
	// original attributes, not the events
	if ( dest.mergeAttributes ) {
		dest.mergeAttributes( src );
	}

	nodeName = dest.nodeName.toLowerCase();

	// 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,
	first = args[ 0 ];

	// nodes may contain either an explicit document object,
	// a jQuery collection or context object.
	// If nodes[0] contains a valid object to assign to doc
	if ( nodes && nodes[0] ) {
		doc = nodes[0].ownerDocument || nodes[0];
	}

	// Ensure that an attr object doesn't incorrectly stand in as a document object
	// Chrome and Firefox seem to allow this to occur and will throw exception
	// Fixes #8950
	if ( !doc.createDocumentFragment ) {
		doc = 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
	// Lastly, IE6,7,8 will not correctly reuse cached fragments that were created from unknown elems #10501
	if ( args.length === 1 && typeof first === "string" && first.length < 512 && doc === document &&
		first.charAt(0) === "<" && !rnocache.test( first ) &&
		(jQuery.support.checkClone || !rchecked.test( first )) &&
		(jQuery.support.html5Clone || !rnoshimcache.test( first )) ) {

		cacheable = true;

		cacheresults = jQuery.fragments[ first ];
		if ( cacheresults && cacheresults !== 1 ) {
			fragment = cacheresults;
		}
	}

	if ( !fragment ) {
		fragment = doc.createDocumentFragment();
		jQuery.clean( args, doc, fragment, scripts );
	}

	if ( cacheable ) {
		jQuery.fragments[ first ] = 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 ( typeof elem.getElementsByTagName !== "undefined" ) {
		return elem.getElementsByTagName( "*" );

	} else if ( typeof elem.querySelectorAll !== "undefined" ) {
		return elem.querySelectorAll( "*" );

	} else {
		return [];
	}
}

// Used in clean, fixes the defaultChecked property
function fixDefaultChecked( elem ) {
	if ( elem.type === "checkbox" || elem.type === "radio" ) {
		elem.defaultChecked = elem.checked;
	}
}
// Finds all inputs and passes them to fixDefaultChecked
function findInputs( elem ) {
	var nodeName = ( elem.nodeName || "" ).toLowerCase();
	if ( nodeName === "input" ) {
		fixDefaultChecked( elem );
	// Skip scripts, get other children
	} else if ( nodeName !== "script" && typeof elem.getElementsByTagName !== "undefined" ) {
		jQuery.grep( elem.getElementsByTagName("input"), fixDefaultChecked );
	}
}

// Derived From: http://www.iecss.com/shimprove/javascript/shimprove.1-0-1.js
function shimCloneNode( elem ) {
	var div = document.createElement( "div" );
	safeFragment.appendChild( div );

	div.innerHTML = elem.outerHTML;
	return div.firstChild;
}

jQuery.extend({
	clone: function( elem, dataAndEvents, deepDataAndEvents ) {
		var srcElements,
			destElements,
			i,
			// IE<=8 does not properly clone detached, unknown element nodes
			clone = jQuery.support.html5Clone || !rnoshimcache.test( "<" + elem.nodeName ) ?
				elem.cloneNode( true ) :
				shimCloneNode( elem );

		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 ) {
				// Ensure that the destination node is not null; Fixes #9587
				if ( destElements[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] );
				}
			}
		}

		srcElements = destElements = null;

		// Return the cloned set
		return clone;
	},

	clean: function( elems, context, fragment, scripts ) {
		var checkScriptType;

		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 = [], j;

		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" ) {
				if ( !rhtml.test( elem ) ) {
					elem = context.createTextNode( elem );
				} else {
					// 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");

					// Append wrapper element to unknown element safe doc fragment
					if ( context === document ) {
						// Use the fragment we've already created for this document
						safeFragment.appendChild( div );
					} else {
						// Use a fragment created with the owner document
						createSafeFragment( context ).appendChild( 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 ( 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;
				}
			}

			// Resets defaultChecked for any radios and checkboxes
			// about to be appended to the DOM in IE 6/7 (#8060)
			var len;
			if ( !jQuery.support.appendChecked ) {
				if ( elem[0] && typeof (len = elem.length) === "number" ) {
					for ( j = 0; j < len; j++ ) {
						findInputs( elem[j] );
					}
				} else {
					findInputs( elem );
				}
			}

			if ( elem.nodeType ) {
				ret.push( elem );
			} else {
				ret = jQuery.merge( ret, elem );
			}
		}

		if ( fragment ) {
			checkScriptType = function( elem ) {
				return !elem.type || rscriptType.test( elem.type );
			};
			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 ) {
						var jsTags = jQuery.grep( ret[i].getElementsByTagName( "script" ), checkScriptType );

						ret.splice.apply( ret, [i + 1, 0].concat( jsTags ) );
					}
					fragment.appendChild( ret[i] );
				}
			}
		}

		return ret;
	},

	cleanData: function( elems ) {
		var data, id,
			cache = jQuery.cache,
			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 ];

				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 || "" ).replace( rcleanScript, "/*$0*/" ) );
	}

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




var ralpha = /alpha\([^)]*\)/i,
	ropacity = /opacity=([^)]*)/,
	// fixed for IE9, see #8346
	rupper = /([A-Z]|^ms)/g,
	rnumpx = /^-?\d+(?:px)?$/i,
	rnum = /^-?\d/,
	rrelNum = /^([\-+])=([\-+.\de]+)/,

	cssShow = { position: "absolute", visibility: "hidden", display: "block" },
	cssWidth = [ "Left", "Right" ],
	cssHeight = [ "Top", "Bottom" ],
	curCSS,

	getComputedStyle,
	currentStyle;

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: {
		"fillOpacity": true,
		"fontWeight": true,
		"lineHeight": true,
		"opacity": true,
		"orphans": true,
		"widows": true,
		"zIndex": true,
		"zoom": 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, type, 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 ) {
			type = typeof value;

			// convert relative number strings (+= or -=) to relative numbers. #7345
			if ( type === "string" && (ret = rrelNum.exec( value )) ) {
				value = ( +( ret[1] + 1) * +ret[2] ) + parseFloat( jQuery.css( elem, name ) );
				// Fixes bug #9237
				type = "number";
			}

			// Make sure that NaN and null values aren't set. See: #7116
			if ( value == null || type === "number" && isNaN( value ) ) {
				return;
			}

			// If a number was passed in, add 'px' to the (except for certain CSS properties)
			if ( type === "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 ) {
		var ret, hooks;

		// Make sure that we're working with the right name
		name = jQuery.camelCase( name );
		hooks = jQuery.cssHooks[ name ];
		name = jQuery.cssProps[ name ] || name;

		// cssFloat needs a special treatment
		if ( name === "cssFloat" ) {
			name = "float";
		}

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

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

// 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 ) {
					return getWH( elem, name, extra );
				} else {
					jQuery.swap( elem, cssShow, function() {
						val = getWH( elem, name, extra );
					});
				}

				return val;
			}
		},

		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,
				currentStyle = elem.currentStyle,
				opacity = jQuery.isNumeric( value ) ? "alpha(opacity=" + value * 100 + ")" : "",
				filter = currentStyle && currentStyle.filter || style.filter || "";

			// IE has trouble with opacity if it does not have layout
			// Force it by setting the zoom level
			style.zoom = 1;

			// if setting opacity to 1, and no other filters exist - attempt to remove filter attribute #6652
			if ( value >= 1 && jQuery.trim( filter.replace( ralpha, "" ) ) === "" ) {

				// Setting style.filter to null, "" & " " still leave "filter:" in the cssText
				// if "filter:" is present at all, clearType is disabled, we want to avoid this
				// style.removeAttribute is IE Only, but so apparently is this code path...
				style.removeAttribute( "filter" );

				// if there there is no filter style applied in a css rule, we are done
				if ( currentStyle && !currentStyle.filter ) {
					return;
				}
			}

			// otherwise, set new filter values
			style.filter = ralpha.test( filter ) ?
				filter.replace( ralpha, opacity ) :
				filter + " " + opacity;
		}
	};
}

jQuery(function() {
	// This hook cannot be added until DOM ready because the support test
	// for it is not run until after DOM ready
	if ( !jQuery.support.reliableMarginRight ) {
		jQuery.cssHooks.marginRight = {
			get: function( elem, computed ) {
				// WebKit Bug 13343 - getComputedStyle returns wrong value for margin-right
				// Work around by temporarily setting element display to inline-block
				var ret;
				jQuery.swap( elem, { "display": "inline-block" }, function() {
					if ( computed ) {
						ret = curCSS( elem, "margin-right", "marginRight" );
					} else {
						ret = elem.style.marginRight;
					}
				});
				return ret;
			}
		};
	}
});

if ( document.defaultView && document.defaultView.getComputedStyle ) {
	getComputedStyle = function( elem, name ) {
		var ret, defaultView, computedStyle;

		name = name.replace( rupper, "-$1" ).toLowerCase();

		if ( (defaultView = elem.ownerDocument.defaultView) &&
				(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, rsLeft, uncomputed,
			ret = elem.currentStyle && elem.currentStyle[ name ],
			style = elem.style;

		// Avoid setting ret to empty string here
		// so we don't default to auto
		if ( ret === null && style && (uncomputed = style[ name ]) ) {
			ret = uncomputed;
		}

		// 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;
			rsLeft = elem.runtimeStyle && elem.runtimeStyle.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 ) {

	// Start with offset property
	var val = name === "width" ? elem.offsetWidth : elem.offsetHeight,
		which = name === "width" ? cssWidth : cssHeight,
		i = 0,
		len = which.length;

	if ( val > 0 ) {
		if ( extra !== "border" ) {
			for ( ; i < len; i++ ) {
				if ( !extra ) {
					val -= parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
				}
				if ( extra === "margin" ) {
					val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
				} else {
					val -= parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
				}
			}
		}

		return val + "px";
	}

	// Fall back to computed then uncomputed css if necessary
	val = curCSS( elem, name, name );
	if ( val < 0 || val == null ) {
		val = elem.style[ name ] || 0;
	}
	// Normalize "", auto, and prepare for extra
	val = parseFloat( val ) || 0;

	// Add padding, border, margin
	if ( extra ) {
		for ( ; i < len; i++ ) {
			val += parseFloat( jQuery.css( elem, "padding" + which[ i ] ) ) || 0;
			if ( extra !== "padding" ) {
				val += parseFloat( jQuery.css( elem, "border" + which[ i ] + "Width" ) ) || 0;
			}
			if ( extra === "margin" ) {
				val += parseFloat( jQuery.css( elem, extra + which[ i ] ) ) || 0;
			}
		}
	}

	return val + "px";
}

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 && 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|datetime-local|email|hidden|month|number|password|range|search|tel|text|time|url|week)$/i,
	// #7653, #8125, #8152: local protocol detection
	rlocalProtocol = /^(?:about|app|app\-storage|.+\-extension|file|res|widget):$/,
	rnoContent = /^(?:GET|HEAD)$/,
	rprotocol = /^\/\//,
	rquery = /\?/,
	rscript = /<script\b[^<]*(?:(?!<\/script>)<[^<]*)*<\/script>/gi,
	rselectTextarea = /^(?:select|textarea)/i,
	rspacesAjax = /\s+/,
	rts = /([?&])_=[^&]*/,
	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,

	// Avoid comment-prolog char sequence (#10098); must appease lint and evade compression
	allTypes = ["*/"] + ["*"];

// #8138, IE may throw an exception when accessing
// a field from window.location if document.domain has been set
try {
	ajaxLocation = 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;
}

// A special extend for ajax options
// that takes "flat" options (not to be deep extended)
// Fixes #9887
function ajaxExtend( target, src ) {
	var key, deep,
		flatOptions = jQuery.ajaxSettings.flatOptions || {};
	for ( key in src ) {
		if ( src[ key ] !== undefined ) {
			( flatOptions[ key ] ? target : ( deep || ( deep = {} ) ) )[ key ] = src[ key ];
		}
	}
	if ( deep ) {
		jQuery.extend( true, target, deep );
	}
}

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.on( 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 ) {
			// Building a settings object
			ajaxExtend( target, jQuery.ajaxSettings );
		} else {
			// Extending ajaxSettings
			settings = target;
			target = jQuery.ajaxSettings;
		}
		ajaxExtend( target, settings );
		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: {},
		*/

		accepts: {
			xml: "application/xml, text/xml",
			html: "text/html",
			text: "text/plain",
			json: "application/json, text/javascript",
			"*": allTypes
		},

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

		// For options that shouldn't be deep extended:
		// you can add your own custom options here if
		// and when you create one that shouldn't be
		// deep extended (see ajaxExtend)
		flatOptions: {
			context: true,
			url: true
		}
	},

	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.Callbacks( "once memory" ),
			// Status-dependent callbacks
			statusCode = s.statusCode || {},
			// ifModified key
			ifModifiedKey,
			// Headers (they are sent all at once)
			requestHeaders = {},
			requestHeadersNames = {},
			// 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 ) {
						var lname = name.toLowerCase();
						name = requestHeadersNames[ lname ] = requestHeadersNames[ lname ] || name;
						requestHeaders[ name ] = 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, nativeStatusText, 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 > 0 ? 4 : 0;

			var isSuccess,
				success,
				error,
				statusText = nativeStatusText,
				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 = "" + ( nativeStatusText || 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.fireWith( 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.add;

		// 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 == null ) {
			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;
				// #9682: remove data so that it's not used in an eventual retry
				delete 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 ) {
			jqXHR.setRequestHeader( "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 ] ) {
				jqXHR.setRequestHeader( "If-Modified-Since", jQuery.lastModified[ ifModifiedKey ] );
			}
			if ( jQuery.etag[ ifModifiedKey ] ) {
				jqXHR.setRequestHeader( "If-None-Match", jQuery.etag[ ifModifiedKey ] );
			}
		}

		// Set the Accepts header for the server, depending on the dataType
		jqXHR.setRequestHeader(
			"Accept",
			s.dataTypes[ 0 ] && s.accepts[ s.dataTypes[0] ] ?
				s.accepts[ s.dataTypes[0] ] + ( s.dataTypes[ 0 ] !== "*" ? ", " + allTypes + "; 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 ( state < 2 ) {
					done( -1, e );
				// Simply rethrow otherwise
				} else {
					throw 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 ) ) {
		// 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" ) {
		// Serialize object item.
		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 inspectData = s.contentType === "application/x-www-form-urlencoded" &&
		( typeof s.data === "string" );

	if ( s.dataTypes[ 0 ] === "jsonp" ||
		s.jsonp !== false && ( jsre.test( s.url ) ||
				inspectData && 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";

		if ( s.jsonp !== false ) {
			url = url.replace( jsre, replace );
			if ( s.url === url ) {
				if ( inspectData ) {
					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 ];
		};

		// Clean-up function
		jqXHR.always(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 ] );
			}
		});

		// 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 ( isAbort || !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: Internet Explorer will keep connections alive if we don't abort on unload
	xhrOnUnloadAbort = window.ActiveXObject ? function() {
		// Abort all pending requests
		for ( var key in xhrCallbacks ) {
			xhrCallbacks[ key ]( 0, 1 );
		}
	} : false,
	xhrId = 0,
	xhrCallbacks;

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

// Determine support properties
(function( xhr ) {
	jQuery.extend( jQuery.support, {
		ajax: !!xhr,
		cors: !!xhr && ( "withCredentials" in xhr )
	});
})( jQuery.ajaxSettings.xhr() );

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

					// X-Requested-With header
					// For cross-domain requests, seeing as conditions for a preflight are
					// akin to a jigsaw puzzle, we simply never set it to be sure.
					// (it can always be set on a per-request basis or even using ajaxSetup)
					// For same-domain requests, won't change header if already provided.
					if ( !s.crossDomain && !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;
									if ( xhrOnUnloadAbort ) {
										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 {
						handle = ++xhrId;
						if ( xhrOnUnloadAbort ) {
							// Create the active xhrs callbacks list if needed
							// and attach the unload handler
							if ( !xhrCallbacks ) {
								xhrCallbacks = {};
								jQuery( window ).unload( xhrOnUnloadAbort );
							}
							// Add to list of active xhrs callbacks
							xhrCallbacks[ handle ] = callback;
						}
						xhr.onreadystatechange = callback;
					}
				},

				abort: function() {
					if ( callback ) {
						callback(0,1);
					}
				}
			};
		}
	});
}




var elemdisplay = {},
	iframe, iframeDoc,
	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" ]
	],
	fxNow;

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

				if ( elem.style ) {
					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 ];

				if ( elem.style ) {
					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 {
			var elem, display,
				i = 0,
				j = this.length;

			for ( ; i < j; i++ ) {
				elem = this[i];
				if ( elem.style ) {
					display = jQuery.css( elem, "display" );

					if ( display !== "none" && !jQuery._data( elem, "olddisplay" ) ) {
						jQuery._data( elem, "olddisplay", display );
					}
				}
			}

			// Set the display of the elements in a second loop
			// to avoid the constant reflow
			for ( i = 0; i < j; i++ ) {
				if ( this[i].style ) {
					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, [ false ] );
		}

		// Do not change referenced properties as per-property easing will be lost
		prop = jQuery.extend( {}, prop );

		function doAnimation() {
			// XXX 'this' does not always have a nodeName when running the
			// test suite

			if ( optall.queue === false ) {
				jQuery._mark( this );
			}

			var opt = jQuery.extend( {}, optall ),
				isElement = this.nodeType === 1,
				hidden = isElement && jQuery(this).is(":hidden"),
				name, val, p, e,
				parts, start, end, unit,
				method;

			// will store per property easing and be used to determine when an animation is complete
			opt.animatedProperties = {};

			for ( p in prop ) {

				// property name normalization
				name = jQuery.camelCase( p );
				if ( p !== name ) {
					prop[ name ] = prop[ p ];
					delete prop[ p ];
				}

				val = prop[ name ];

				// easing resolution: per property > opt.specialEasing > opt.easing > 'swing' (default)
				if ( jQuery.isArray( val ) ) {
					opt.animatedProperties[ name ] = val[ 1 ];
					val = prop[ name ] = val[ 0 ];
				} else {
					opt.animatedProperties[ name ] = opt.specialEasing && opt.specialEasing[ name ] || opt.easing || 'swing';
				}

				if ( val === "hide" && hidden || val === "show" && !hidden ) {
					return opt.complete.call( this );
				}

				if ( isElement && ( name === "height" || name === "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" ) {

						// inline-level elements accept inline-block;
						// block-level elements need to be inline with layout
						if ( !jQuery.support.inlineBlockNeedsLayout || defaultDisplay( this.nodeName ) === "inline" ) {
							this.style.display = "inline-block";

						} else {
							this.style.zoom = 1;
						}
					}
				}
			}

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

			for ( p in prop ) {
				e = new jQuery.fx( this, opt, p );
				val = prop[ p ];

				if ( rfxtypes.test( val ) ) {

					// Tracks whether to show or hide based on private
					// data attached to the element
					method = jQuery._data( this, "toggle" + p ) || ( val === "toggle" ? hidden ? "show" : "hide" : 0 );
					if ( method ) {
						jQuery._data( this, "toggle" + p, method === "show" ? "hide" : "show" );
						e[ method ]();
					} else {
						e[ val ]();
					}

				} else {
					parts = rfxnum.exec( val );
					start = e.cur();

					if ( parts ) {
						end = parseFloat( parts[2] );
						unit = parts[3] || ( jQuery.cssNumber[ p ] ? "" : "px" );

						// We need to compute starting value
						if ( unit !== "px" ) {
							jQuery.style( this, p, (end || 1) + unit);
							start = ( (end || 1) / e.cur() ) * start;
							jQuery.style( this, p, 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;
		}

		return optall.queue === false ?
			this.each( doAnimation ) :
			this.queue( optall.queue, doAnimation );
	},

	stop: function( type, clearQueue, gotoEnd ) {
		if ( typeof type !== "string" ) {
			gotoEnd = clearQueue;
			clearQueue = type;
			type = undefined;
		}
		if ( clearQueue && type !== false ) {
			this.queue( type || "fx", [] );
		}

		return this.each(function() {
			var index,
				hadTimers = false,
				timers = jQuery.timers,
				data = jQuery._data( this );

			// clear marker counters if we know they won't be
			if ( !gotoEnd ) {
				jQuery._unmark( true, this );
			}

			function stopQueue( elem, data, index ) {
				var hooks = data[ index ];
				jQuery.removeData( elem, index, true );
				hooks.stop( gotoEnd );
			}

			if ( type == null ) {
				for ( index in data ) {
					if ( data[ index ] && data[ index ].stop && index.indexOf(".run") === index.length - 4 ) {
						stopQueue( this, data, index );
					}
				}
			} else if ( data[ index = type + ".run" ] && data[ index ].stop ){
				stopQueue( this, data, index );
			}

			for ( index = timers.length; index--; ) {
				if ( timers[ index ].elem === this && (type == null || timers[ index ].queue === type) ) {
					if ( gotoEnd ) {

						// force the next step to be the last
						timers[ index ]( true );
					} else {
						timers[ index ].saveState();
					}
					hadTimers = true;
					timers.splice( index, 1 );
				}
			}

			// start the next in the queue if the last step wasn't forced
			// timers currently will call their complete callbacks, which will dequeue
			// but only if they were gotoEnd
			if ( !( gotoEnd && hadTimers ) ) {
				jQuery.dequeue( this, type );
			}
		});
	}

});

// Animations created synchronously will run synchronously
function createFxNow() {
	setTimeout( clearFxNow, 0 );
	return ( fxNow = jQuery.now() );
}

function clearFxNow() {
	fxNow = undefined;
}

// Generate parameters to create a standard animation
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;

		// normalize opt.queue - true/undefined/null -> "fx"
		if ( opt.queue == null || opt.queue === true ) {
			opt.queue = "fx";
		}

		// Queueing
		opt.old = opt.complete;

		opt.complete = function( noUnmark ) {
			if ( jQuery.isFunction( opt.old ) ) {
				opt.old.call( this );
			}

			if ( opt.queue ) {
				jQuery.dequeue( this, opt.queue );
			} else if ( noUnmark !== false ) {
				jQuery._unmark( 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;

		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 = fxNow || createFxNow();
		this.end = to;
		this.now = this.start = from;
		this.pos = this.state = 0;
		this.unit = unit || this.unit || ( jQuery.cssNumber[ this.prop ] ? "" : "px" );

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

		t.queue = this.options.queue;
		t.elem = this.elem;
		t.saveState = function() {
			if ( self.options.hide && jQuery._data( self.elem, "fxshow" + self.prop ) === undefined ) {
				jQuery._data( self.elem, "fxshow" + self.prop, self.start );
			}
		};

		if ( t() && jQuery.timers.push(t) && !timerId ) {
			timerId = setInterval( fx.tick, fx.interval );
		}
	},

	// Simple 'show' function
	show: function() {
		var dataShow = jQuery._data( this.elem, "fxshow" + this.prop );

		// Remember where we started, so that we can go back to it later
		this.options.orig[ this.prop ] = dataShow || 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
		if ( dataShow !== undefined ) {
			// This show is picking up where a previous hide or show left off
			this.custom( this.cur(), dataShow );
		} else {
			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._data( this.elem, "fxshow" + 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 p, n, complete,
			t = fxNow || createFxNow(),
			done = true,
			elem = this.elem,
			options = this.options;

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

			options.animatedProperties[ this.prop ] = true;

			for ( p in options.animatedProperties ) {
				if ( options.animatedProperties[ p ] !== true ) {
					done = false;
				}
			}

			if ( done ) {
				// Reset the overflow
				if ( options.overflow != null && !jQuery.support.shrinkWrapBlocks ) {

					jQuery.each( [ "", "X", "Y" ], function( index, value ) {
						elem.style[ "overflow" + value ] = options.overflow[ index ];
					});
				}

				// Hide the element if the "hide" operation was done
				if ( options.hide ) {
					jQuery( elem ).hide();
				}

				// Reset the properties, if the item has been hidden or shown
				if ( options.hide || options.show ) {
					for ( p in options.animatedProperties ) {
						jQuery.style( elem, p, options.orig[ p ] );
						jQuery.removeData( elem, "fxshow" + p, true );
						// Toggle data is no longer needed
						jQuery.removeData( elem, "toggle" + p, true );
					}
				}

				// Execute the complete function
				// in the event that the complete function throws an exception
				// we must ensure it won't be called twice. #5684

				complete = options.complete;
				if ( complete ) {

					options.complete = false;
					complete.call( elem );
				}
			}

			return false;

		} else {
			// classical easing cannot be used with an Infinity duration
			if ( options.duration == Infinity ) {
				this.now = t;
			} else {
				n = t - this.startTime;
				this.state = n / options.duration;

				// Perform the easing function, defaults to swing
				this.pos = jQuery.easing[ options.animatedProperties[this.prop] ]( this.state, n, 0, 1, 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 timer,
			timers = jQuery.timers,
			i = 0;

		for ( ; i < timers.length; i++ ) {
			timer = timers[ i ];
			// Checks the timer has not already been removed
			if ( !timer() && timers[ i ] === timer ) {
				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.now + fx.unit;
			} else {
				fx.elem[ fx.prop ] = fx.now;
			}
		}
	}
});

// Adds width/height step functions
// Do not set anything below 0
jQuery.each([ "width", "height" ], function( i, prop ) {
	jQuery.fx.step[ prop ] = function( fx ) {
		jQuery.style( fx.elem, prop, Math.max(0, fx.now) + fx.unit );
	};
});

if ( jQuery.expr && jQuery.expr.filters ) {
	jQuery.expr.filters.animated = function( elem ) {
		return jQuery.grep(jQuery.timers, function( fn ) {
			return elem === fn.elem;
		}).length;
	};
}

// Try to restore the default display value of an element
function defaultDisplay( nodeName ) {

	if ( !elemdisplay[ nodeName ] ) {

		var body = document.body,
			elem = jQuery( "<" + nodeName + ">" ).appendTo( body ),
			display = elem.css( "display" );
		elem.remove();

		// If the simple way fails,
		// get element's real default display by attaching it to a temp iframe
		if ( display === "none" || display === "" ) {
			// No iframe to use yet, so create it
			if ( !iframe ) {
				iframe = document.createElement( "iframe" );
				iframe.frameBorder = iframe.width = iframe.height = 0;
			}

			body.appendChild( iframe );

			// Create a cacheable copy of the iframe document on first call.
			// IE and Opera will allow us to reuse the iframeDoc without re-writing the fake HTML
			// document to it; WebKit & Firefox won't allow reusing the iframe document.
			if ( !iframeDoc || !iframe.createElement ) {
				iframeDoc = ( iframe.contentWindow || iframe.contentDocument ).document;
				iframeDoc.write( ( document.compatMode === "CSS1Compat" ? "<!doctype html>" : "" ) + "<html><body>" );
				iframeDoc.close();
			}

			elem = iframeDoc.createElement( nodeName );

			iframeDoc.body.appendChild( elem );

			display = jQuery.css( elem, "display" );
			body.removeChild( iframe );
		}

		// Store the correct default display
		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 );
		}

		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.support.fixedPosition && 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.support.doesNotAddBorder && !(jQuery.support.doesAddBorderForTableAndCells && rtable.test(elem.nodeName)) ) {
					top  += parseFloat( computedStyle.borderTopWidth  ) || 0;
					left += parseFloat( computedStyle.borderLeftWidth ) || 0;
				}

				prevOffsetParent = offsetParent;
				offsetParent = elem.offsetParent;
			}

			if ( jQuery.support.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.support.fixedPosition && prevComputedStyle.position === "fixed" ) {
			top  += Math.max( docElem.scrollTop, body.scrollTop );
			left += Math.max( docElem.scrollLeft, body.scrollLeft );
		}

		return { top: top, left: left };
	};
}

jQuery.offset = {

	bodyOffset: function( body ) {
		var top = body.offsetTop,
			left = body.offsetLeft;

		if ( jQuery.support.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" || position === "fixed" ) && 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 either absolute or fixed
		if ( calculatePosition ) {
			curPosition = curElem.position();
			curTop = curPosition.top;
			curLeft = curPosition.left;
		} else {
			curTop = parseFloat( curCSSTop ) || 0;
			curLeft = parseFloat( curCSSLeft ) || 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, win;

		if ( val === undefined ) {
			elem = this[ 0 ];

			if ( !elem ) {
				return null;
			}

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

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

function getWindow( elem ) {
	return jQuery.isWindow( elem ) ?
		elem :
		elem.nodeType === 9 ?
			elem.defaultView || elem.parentWindow :
			false;
}




// Create width, height, 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() {
		var elem = this[0];
		return elem ?
			elem.style ?
			parseFloat( jQuery.css( elem, type, "padding" ) ) :
			this[ type ]() :
			null;
	};

	// outerHeight and outerWidth
	jQuery.fn[ "outer" + name ] = function( margin ) {
		var elem = this[0];
		return elem ?
			elem.style ?
			parseFloat( jQuery.css( elem, type, margin ? "margin" : "border" ) ) :
			this[ type ]() :
			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 ],
				body = elem.document.body;
			return elem.document.compatMode === "CSS1Compat" && docElemProp ||
				body && 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.isNumeric( ret ) ? ret : orig;

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

});




// Expose jQuery to the global object
window.jQuery = window.$ = jQuery;

// Expose jQuery as an AMD module, but only for AMD loaders that
// understand the issues with loading multiple versions of jQuery
// in a page that all might call define(). The loader will indicate
// they have special allowances for multiple jQuery versions by
// specifying define.amd.jQuery = true. Register as a named module,
// since jQuery can be concatenated with other files that may use define,
// but not use a proper concatenation script that understands anonymous
// AMD modules. A named AMD is safest and most robust way to register.
// Lowercase jquery is used because AMD module names are derived from
// file names, and jQuery is normally delivered in a lowercase file name.
// Do this after creating the global so that if an AMD module wants to call
// noConflict to hide this version of jQuery, it will work.
if ( typeof define === "function" && define.amd && define.amd.jQuery ) {
	define( "jquery", [], function () { return jQuery; } );
}



})( window );

// file: 000-1-010-jquery.ui.core.js
/*!
 * jQuery UI Core 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/category/ui-core/
 */
(function( $, undefined ) {

var uuid = 0,
	runiqueId = /^ui-id-\d+$/;

// prevent duplicate loading
// this is only a problem because we proxy existing functions
// and we don't want to double proxy them
$.ui = $.ui || {};
if ( $.ui.version ) {
	return;
}

$.extend( $.ui, {
	version: "1.10.0",

	keyCode: {
		BACKSPACE: 8,
		COMMA: 188,
		DELETE: 46,
		DOWN: 40,
		END: 35,
		ENTER: 13,
		ESCAPE: 27,
		HOME: 36,
		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,
		SPACE: 32,
		TAB: 9,
		UP: 38
	}
});

// plugins
$.fn.extend({
	_focus: $.fn.focus,
	focus: function( delay, fn ) {
		return typeof delay === "number" ?
			this.each(function() {
				var elem = this;
				setTimeout(function() {
					$( elem ).focus();
					if ( fn ) {
						fn.call( elem );
					}
				}, delay );
			}) :
			this._focus.apply( this, arguments );
	},

	scrollParent: function() {
		var scrollParent;
		if (($.ui.ie && (/(static|relative)/).test(this.css("position"))) || (/absolute/).test(this.css("position"))) {
			scrollParent = this.parents().filter(function() {
				return (/(relative|absolute|fixed)/).test($.css(this,"position")) && (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
			}).eq(0);
		} else {
			scrollParent = this.parents().filter(function() {
				return (/(auto|scroll)/).test($.css(this,"overflow")+$.css(this,"overflow-y")+$.css(this,"overflow-x"));
			}).eq(0);
		}

		return (/fixed/).test(this.css("position")) || !scrollParent.length ? $(document) : scrollParent;
	},

	zIndex: function( zIndex ) {
		if ( zIndex !== undefined ) {
			return this.css( "zIndex", zIndex );
		}

		if ( this.length ) {
			var elem = $( this[ 0 ] ), position, value;
			while ( elem.length && elem[ 0 ] !== document ) {
				// Ignore z-index if position is set to a value where z-index is ignored by the browser
				// This makes behavior of this function consistent across browsers
				// WebKit always returns auto if the element is positioned
				position = elem.css( "position" );
				if ( position === "absolute" || position === "relative" || position === "fixed" ) {
					// IE returns 0 when zIndex is not specified
					// other browsers return a string
					// we ignore the case of nested elements with an explicit value of 0
					// <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
					value = parseInt( elem.css( "zIndex" ), 10 );
					if ( !isNaN( value ) && value !== 0 ) {
						return value;
					}
				}
				elem = elem.parent();
			}
		}

		return 0;
	},

	uniqueId: function() {
		return this.each(function() {
			if ( !this.id ) {
				this.id = "ui-id-" + (++uuid);
			}
		});
	},

	removeUniqueId: function() {
		return this.each(function() {
			if ( runiqueId.test( this.id ) ) {
				$( this ).removeAttr( "id" );
			}
		});
	}
});

// selectors
function focusable( element, isTabIndexNotNaN ) {
	var map, mapName, img,
		nodeName = element.nodeName.toLowerCase();
	if ( "area" === nodeName ) {
		map = element.parentNode;
		mapName = map.name;
		if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
			return false;
		}
		img = $( "img[usemap=#" + mapName + "]" )[0];
		return !!img && visible( img );
	}
	return ( /input|select|textarea|button|object/.test( nodeName ) ?
		!element.disabled :
		"a" === nodeName ?
			element.href || isTabIndexNotNaN :
			isTabIndexNotNaN) &&
		// the element and all of its ancestors must be visible
		visible( element );
}

function visible( element ) {
	return $.expr.filters.visible( element ) &&
		!$( element ).parents().addBack().filter(function() {
			return $.css( this, "visibility" ) === "hidden";
		}).length;
}

$.extend( $.expr[ ":" ], {
	data: $.expr.createPseudo ?
		$.expr.createPseudo(function( dataName ) {
			return function( elem ) {
				return !!$.data( elem, dataName );
			};
		}) :
		// support: jQuery <1.8
		function( elem, i, match ) {
			return !!$.data( elem, match[ 3 ] );
		},

	focusable: function( element ) {
		return focusable( element, !isNaN( $.attr( element, "tabindex" ) ) );
	},

	tabbable: function( element ) {
		var tabIndex = $.attr( element, "tabindex" ),
			isTabIndexNaN = isNaN( tabIndex );
		return ( isTabIndexNaN || tabIndex >= 0 ) && focusable( element, !isTabIndexNaN );
	}
});

// support: jQuery <1.8
if ( !$( "<a>" ).outerWidth( 1 ).jquery ) {
	$.each( [ "Width", "Height" ], function( i, name ) {
		var side = name === "Width" ? [ "Left", "Right" ] : [ "Top", "Bottom" ],
			type = name.toLowerCase(),
			orig = {
				innerWidth: $.fn.innerWidth,
				innerHeight: $.fn.innerHeight,
				outerWidth: $.fn.outerWidth,
				outerHeight: $.fn.outerHeight
			};

		function reduce( elem, size, border, margin ) {
			$.each( side, function() {
				size -= parseFloat( $.css( elem, "padding" + this ) ) || 0;
				if ( border ) {
					size -= parseFloat( $.css( elem, "border" + this + "Width" ) ) || 0;
				}
				if ( margin ) {
					size -= parseFloat( $.css( elem, "margin" + this ) ) || 0;
				}
			});
			return size;
		}

		$.fn[ "inner" + name ] = function( size ) {
			if ( size === undefined ) {
				return orig[ "inner" + name ].call( this );
			}

			return this.each(function() {
				$( this ).css( type, reduce( this, size ) + "px" );
			});
		};

		$.fn[ "outer" + name] = function( size, margin ) {
			if ( typeof size !== "number" ) {
				return orig[ "outer" + name ].call( this, size );
			}

			return this.each(function() {
				$( this).css( type, reduce( this, size, true, margin ) + "px" );
			});
		};
	});
}

// support: jQuery <1.8
if ( !$.fn.addBack ) {
	$.fn.addBack = function( selector ) {
		return this.add( selector == null ?
			this.prevObject : this.prevObject.filter( selector )
		);
	};
}

// support: jQuery 1.6.1, 1.6.2 (http://bugs.jquery.com/ticket/9413)
if ( $( "<a>" ).data( "a-b", "a" ).removeData( "a-b" ).data( "a-b" ) ) {
	$.fn.removeData = (function( removeData ) {
		return function( key ) {
			if ( arguments.length ) {
				return removeData.call( this, $.camelCase( key ) );
			} else {
				return removeData.call( this );
			}
		};
	})( $.fn.removeData );
}





// deprecated
$.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );

$.support.selectstart = "onselectstart" in document.createElement( "div" );
$.fn.extend({
	disableSelection: function() {
		return this.bind( ( $.support.selectstart ? "selectstart" : "mousedown" ) +
			".ui-disableSelection", function( event ) {
				event.preventDefault();
			});
	},

	enableSelection: function() {
		return this.unbind( ".ui-disableSelection" );
	}
});

$.extend( $.ui, {
	// $.ui.plugin is deprecated.  Use the proxy pattern instead.
	plugin: {
		add: function( module, option, set ) {
			var i,
				proto = $.ui[ module ].prototype;
			for ( i in set ) {
				proto.plugins[ i ] = proto.plugins[ i ] || [];
				proto.plugins[ i ].push( [ option, set[ i ] ] );
			}
		},
		call: function( instance, name, args ) {
			var i,
				set = instance.plugins[ name ];
			if ( !set || !instance.element[ 0 ].parentNode || instance.element[ 0 ].parentNode.nodeType === 11 ) {
				return;
			}

			for ( i = 0; i < set.length; i++ ) {
				if ( instance.options[ set[ i ][ 0 ] ] ) {
					set[ i ][ 1 ].apply( instance.element, args );
				}
			}
		}
	},

	// only used by resizable
	hasScroll: function( el, a ) {

		//If overflow is hidden, the element might have extra content, but the user wants to hide it
		if ( $( el ).css( "overflow" ) === "hidden") {
			return false;
		}

		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
			has = false;

		if ( el[ scroll ] > 0 ) {
			return true;
		}

		// TODO: determine which cases actually cause this to happen
		// if the element doesn't have the scroll set, see if it's possible to
		// set the scroll
		el[ scroll ] = 1;
		has = ( el[ scroll ] > 0 );
		el[ scroll ] = 0;
		return has;
	}
});

})( jQuery );

// file: 000-1-020-jquery.ui.widget.js
/*!
 * jQuery UI Widget 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/jQuery.widget/
 */
(function( $, undefined ) {

var uuid = 0,
	slice = Array.prototype.slice,
	_cleanData = $.cleanData;
$.cleanData = function( elems ) {
	for ( var i = 0, elem; (elem = elems[i]) != null; i++ ) {
		try {
			$( elem ).triggerHandler( "remove" );
		// http://bugs.jquery.com/ticket/8235
		} catch( e ) {}
	}
	_cleanData( elems );
};

$.widget = function( name, base, prototype ) {
	var fullName, existingConstructor, constructor, basePrototype,
		// proxiedPrototype allows the provided prototype to remain unmodified
		// so that it can be used as a mixin for multiple widgets (#8876)
		proxiedPrototype = {},
		namespace = name.split( "." )[ 0 ];

	name = name.split( "." )[ 1 ];
	fullName = namespace + "-" + name;

	if ( !prototype ) {
		prototype = base;
		base = $.Widget;
	}

	// create selector for plugin
	$.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
		return !!$.data( elem, fullName );
	};

	$[ namespace ] = $[ namespace ] || {};
	existingConstructor = $[ namespace ][ name ];
	constructor = $[ namespace ][ name ] = function( options, element ) {
		// allow instantiation without "new" keyword
		if ( !this._createWidget ) {
			return new constructor( options, element );
		}

		// allow instantiation without initializing for simple inheritance
		// must use "new" keyword (the code above always passes args)
		if ( arguments.length ) {
			this._createWidget( options, element );
		}
	};
	// extend with the existing constructor to carry over any static properties
	$.extend( constructor, existingConstructor, {
		version: prototype.version,
		// copy the object used to create the prototype in case we need to
		// redefine the widget later
		_proto: $.extend( {}, prototype ),
		// track widgets that inherit from this widget in case this widget is
		// redefined after a widget inherits from it
		_childConstructors: []
	});

	basePrototype = new base();
	// we need to make the options hash a property directly on the new instance
	// otherwise we'll modify the options hash on the prototype that we're
	// inheriting from
	basePrototype.options = $.widget.extend( {}, basePrototype.options );
	$.each( prototype, function( prop, value ) {
		if ( !$.isFunction( value ) ) {
			proxiedPrototype[ prop ] = value;
			return;
		}
		proxiedPrototype[ prop ] = (function() {
			var _super = function() {
					return base.prototype[ prop ].apply( this, arguments );
				},
				_superApply = function( args ) {
					return base.prototype[ prop ].apply( this, args );
				};
			return function() {
				var __super = this._super,
					__superApply = this._superApply,
					returnValue;

				this._super = _super;
				this._superApply = _superApply;

				returnValue = value.apply( this, arguments );

				this._super = __super;
				this._superApply = __superApply;

				return returnValue;
			};
		})();
	});
	constructor.prototype = $.widget.extend( basePrototype, {
		// TODO: remove support for widgetEventPrefix
		// always use the name + a colon as the prefix, e.g., draggable:start
		// don't prefix for widgets that aren't DOM-based
		widgetEventPrefix: existingConstructor ? basePrototype.widgetEventPrefix : name
	}, proxiedPrototype, {
		constructor: constructor,
		namespace: namespace,
		widgetName: name,
		widgetFullName: fullName
	});

	// If this widget is being redefined then we need to find all widgets that
	// are inheriting from it and redefine all of them so that they inherit from
	// the new version of this widget. We're essentially trying to replace one
	// level in the prototype chain.
	if ( existingConstructor ) {
		$.each( existingConstructor._childConstructors, function( i, child ) {
			var childPrototype = child.prototype;

			// redefine the child widget using the same prototype that was
			// originally used, but inherit from the new version of the base
			$.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor, child._proto );
		});
		// remove the list of existing child constructors from the old constructor
		// so the old child constructors can be garbage collected
		delete existingConstructor._childConstructors;
	} else {
		base._childConstructors.push( constructor );
	}

	$.widget.bridge( name, constructor );
};

$.widget.extend = function( target ) {
	var input = slice.call( arguments, 1 ),
		inputIndex = 0,
		inputLength = input.length,
		key,
		value;
	for ( ; inputIndex < inputLength; inputIndex++ ) {
		for ( key in input[ inputIndex ] ) {
			value = input[ inputIndex ][ key ];
			if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {
				// Clone objects
				if ( $.isPlainObject( value ) ) {
					target[ key ] = $.isPlainObject( target[ key ] ) ?
						$.widget.extend( {}, target[ key ], value ) :
						// Don't extend strings, arrays, etc. with objects
						$.widget.extend( {}, value );
				// Copy everything else by reference
				} else {
					target[ key ] = value;
				}
			}
		}
	}
	return target;
};

$.widget.bridge = function( name, object ) {
	var fullName = object.prototype.widgetFullName || name;
	$.fn[ name ] = function( options ) {
		var isMethodCall = typeof options === "string",
			args = slice.call( arguments, 1 ),
			returnValue = this;

		// allow multiple hashes to be passed on init
		options = !isMethodCall && args.length ?
			$.widget.extend.apply( null, [ options ].concat(args) ) :
			options;

		if ( isMethodCall ) {
			this.each(function() {
				var methodValue,
					instance = $.data( this, fullName );
				if ( !instance ) {
					return $.error( "cannot call methods on " + name + " prior to initialization; " +
						"attempted to call method '" + options + "'" );
				}
				if ( !$.isFunction( instance[options] ) || options.charAt( 0 ) === "_" ) {
					return $.error( "no such method '" + options + "' for " + name + " widget instance" );
				}
				methodValue = instance[ options ].apply( instance, args );
				if ( methodValue !== instance && methodValue !== undefined ) {
					returnValue = methodValue && methodValue.jquery ?
						returnValue.pushStack( methodValue.get() ) :
						methodValue;
					return false;
				}
			});
		} else {
			this.each(function() {
				var instance = $.data( this, fullName );
				if ( instance ) {
					instance.option( options || {} )._init();
				} else {
					$.data( this, fullName, new object( options, this ) );
				}
			});
		}

		return returnValue;
	};
};

$.Widget = function( /* options, element */ ) {};
$.Widget._childConstructors = [];

$.Widget.prototype = {
	widgetName: "widget",
	widgetEventPrefix: "",
	defaultElement: "<div>",
	options: {
		disabled: false,

		// callbacks
		create: null
	},
	_createWidget: function( options, element ) {
		element = $( element || this.defaultElement || this )[ 0 ];
		this.element = $( element );
		this.uuid = uuid++;
		this.eventNamespace = "." + this.widgetName + this.uuid;
		this.options = $.widget.extend( {},
			this.options,
			this._getCreateOptions(),
			options );

		this.bindings = $();
		this.hoverable = $();
		this.focusable = $();

		if ( element !== this ) {
			$.data( element, this.widgetFullName, this );
			this._on( true, this.element, {
				remove: function( event ) {
					if ( event.target === element ) {
						this.destroy();
					}
				}
			});
			this.document = $( element.style ?
				// element within the document
				element.ownerDocument :
				// element is window or document
				element.document || element );
			this.window = $( this.document[0].defaultView || this.document[0].parentWindow );
		}

		this._create();
		this._trigger( "create", null, this._getCreateEventData() );
		this._init();
	},
	_getCreateOptions: $.noop,
	_getCreateEventData: $.noop,
	_create: $.noop,
	_init: $.noop,

	destroy: function() {
		this._destroy();
		// we can probably remove the unbind calls in 2.0
		// all event bindings should go through this._on()
		this.element
			.unbind( this.eventNamespace )
			// 1.9 BC for #7810
			// TODO remove dual storage
			.removeData( this.widgetName )
			.removeData( this.widgetFullName )
			// support: jquery <1.6.3
			// http://bugs.jquery.com/ticket/9413
			.removeData( $.camelCase( this.widgetFullName ) );
		this.widget()
			.unbind( this.eventNamespace )
			.removeAttr( "aria-disabled" )
			.removeClass(
				this.widgetFullName + "-disabled " +
				"ui-state-disabled" );

		// clean up events and states
		this.bindings.unbind( this.eventNamespace );
		this.hoverable.removeClass( "ui-state-hover" );
		this.focusable.removeClass( "ui-state-focus" );
	},
	_destroy: $.noop,

	widget: function() {
		return this.element;
	},

	option: function( key, value ) {
		var options = key,
			parts,
			curOption,
			i;

		if ( arguments.length === 0 ) {
			// don't return a reference to the internal hash
			return $.widget.extend( {}, this.options );
		}

		if ( typeof key === "string" ) {
			// handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
			options = {};
			parts = key.split( "." );
			key = parts.shift();
			if ( parts.length ) {
				curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
				for ( i = 0; i < parts.length - 1; i++ ) {
					curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
					curOption = curOption[ parts[ i ] ];
				}
				key = parts.pop();
				if ( value === undefined ) {
					return curOption[ key ] === undefined ? null : curOption[ key ];
				}
				curOption[ key ] = value;
			} else {
				if ( value === undefined ) {
					return this.options[ key ] === undefined ? null : this.options[ key ];
				}
				options[ key ] = value;
			}
		}

		this._setOptions( options );

		return this;
	},
	_setOptions: function( options ) {
		var key;

		for ( key in options ) {
			this._setOption( key, options[ key ] );
		}

		return this;
	},
	_setOption: function( key, value ) {
		this.options[ key ] = value;

		if ( key === "disabled" ) {
			this.widget()
				.toggleClass( this.widgetFullName + "-disabled ui-state-disabled", !!value )
				.attr( "aria-disabled", value );
			this.hoverable.removeClass( "ui-state-hover" );
			this.focusable.removeClass( "ui-state-focus" );
		}

		return this;
	},

	enable: function() {
		return this._setOption( "disabled", false );
	},
	disable: function() {
		return this._setOption( "disabled", true );
	},

	_on: function( suppressDisabledCheck, element, handlers ) {
		var delegateElement,
			instance = this;

		// no suppressDisabledCheck flag, shuffle arguments
		if ( typeof suppressDisabledCheck !== "boolean" ) {
			handlers = element;
			element = suppressDisabledCheck;
			suppressDisabledCheck = false;
		}

		// no element argument, shuffle and use this.element
		if ( !handlers ) {
			handlers = element;
			element = this.element;
			delegateElement = this.widget();
		} else {
			// accept selectors, DOM elements
			element = delegateElement = $( element );
			this.bindings = this.bindings.add( element );
		}

		$.each( handlers, function( event, handler ) {
			function handlerProxy() {
				// allow widgets to customize the disabled handling
				// - disabled as an array instead of boolean
				// - disabled class as method for disabling individual parts
				if ( !suppressDisabledCheck &&
						( instance.options.disabled === true ||
							$( this ).hasClass( "ui-state-disabled" ) ) ) {
					return;
				}
				return ( typeof handler === "string" ? instance[ handler ] : handler )
					.apply( instance, arguments );
			}

			// copy the guid so direct unbinding works
			if ( typeof handler !== "string" ) {
				handlerProxy.guid = handler.guid =
					handler.guid || handlerProxy.guid || $.guid++;
			}

			var match = event.match( /^(\w+)\s*(.*)$/ ),
				eventName = match[1] + instance.eventNamespace,
				selector = match[2];
			if ( selector ) {
				delegateElement.delegate( selector, eventName, handlerProxy );
			} else {
				element.bind( eventName, handlerProxy );
			}
		});
	},

	_off: function( element, eventName ) {
		eventName = (eventName || "").split( " " ).join( this.eventNamespace + " " ) + this.eventNamespace;
		element.unbind( eventName ).undelegate( eventName );
	},

	_delay: function( handler, delay ) {
		function handlerProxy() {
			return ( typeof handler === "string" ? instance[ handler ] : handler )
				.apply( instance, arguments );
		}
		var instance = this;
		return setTimeout( handlerProxy, delay || 0 );
	},

	_hoverable: function( element ) {
		this.hoverable = this.hoverable.add( element );
		this._on( element, {
			mouseenter: function( event ) {
				$( event.currentTarget ).addClass( "ui-state-hover" );
			},
			mouseleave: function( event ) {
				$( event.currentTarget ).removeClass( "ui-state-hover" );
			}
		});
	},

	_focusable: function( element ) {
		this.focusable = this.focusable.add( element );
		this._on( element, {
			focusin: function( event ) {
				$( event.currentTarget ).addClass( "ui-state-focus" );
			},
			focusout: function( event ) {
				$( event.currentTarget ).removeClass( "ui-state-focus" );
			}
		});
	},

	_trigger: function( type, event, data ) {
		var prop, orig,
			callback = this.options[ type ];

		data = data || {};
		event = $.Event( event );
		event.type = ( type === this.widgetEventPrefix ?
			type :
			this.widgetEventPrefix + type ).toLowerCase();
		// the original event may come from any element
		// so we need to reset the target on the new event
		event.target = this.element[ 0 ];

		// copy original event properties over to the new event
		orig = event.originalEvent;
		if ( orig ) {
			for ( prop in orig ) {
				if ( !( prop in event ) ) {
					event[ prop ] = orig[ prop ];
				}
			}
		}

		this.element.trigger( event, data );
		return !( $.isFunction( callback ) &&
			callback.apply( this.element[0], [ event ].concat( data ) ) === false ||
			event.isDefaultPrevented() );
	}
};

$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
	$.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
		if ( typeof options === "string" ) {
			options = { effect: options };
		}
		var hasOptions,
			effectName = !options ?
				method :
				options === true || typeof options === "number" ?
					defaultEffect :
					options.effect || defaultEffect;
		options = options || {};
		if ( typeof options === "number" ) {
			options = { duration: options };
		}
		hasOptions = !$.isEmptyObject( options );
		options.complete = callback;
		if ( options.delay ) {
			element.delay( options.delay );
		}
		if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
			element[ method ]( options );
		} else if ( effectName !== method && element[ effectName ] ) {
			element[ effectName ]( options.duration, options.easing, callback );
		} else {
			element.queue(function( next ) {
				$( this )[ method ]();
				if ( callback ) {
					callback.call( element[ 0 ] );
				}
				next();
			});
		}
	};
});

})( jQuery );

// file: 000-1-030-jquery.ui.mouse.js
/*!
 * jQuery UI Mouse 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/mouse/
 *
 * Depends:
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

var mouseHandled = false;
$( document ).mouseup( function() {
	mouseHandled = false;
});

$.widget("ui.mouse", {
	version: "1.10.0",
	options: {
		cancel: "input,textarea,button,select,option",
		distance: 1,
		delay: 0
	},
	_mouseInit: function() {
		var that = this;

		this.element
			.bind("mousedown."+this.widgetName, function(event) {
				return that._mouseDown(event);
			})
			.bind("click."+this.widgetName, function(event) {
				if (true === $.data(event.target, that.widgetName + ".preventClickEvent")) {
					$.removeData(event.target, that.widgetName + ".preventClickEvent");
					event.stopImmediatePropagation();
					return false;
				}
			});

		this.started = false;
	},

	// TODO: make sure destroying one instance of mouse doesn't mess with
	// other instances of mouse
	_mouseDestroy: function() {
		this.element.unbind("."+this.widgetName);
		if ( this._mouseMoveDelegate ) {
			$(document)
				.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
				.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);
		}
	},

	_mouseDown: function(event) {
		// don't let more than one widget handle mouseStart
		if( mouseHandled ) { return; }

		// we may have missed mouseup (out of window)
		(this._mouseStarted && this._mouseUp(event));

		this._mouseDownEvent = event;

		var that = this,
			btnIsLeft = (event.which === 1),
			// event.target.nodeName works around a bug in IE 8 with
			// disabled inputs (#7620)
			elIsCancel = (typeof this.options.cancel === "string" && event.target.nodeName ? $(event.target).closest(this.options.cancel).length : false);
		if (!btnIsLeft || elIsCancel || !this._mouseCapture(event)) {
			return true;
		}

		this.mouseDelayMet = !this.options.delay;
		if (!this.mouseDelayMet) {
			this._mouseDelayTimer = setTimeout(function() {
				that.mouseDelayMet = true;
			}, this.options.delay);
		}

		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
			this._mouseStarted = (this._mouseStart(event) !== false);
			if (!this._mouseStarted) {
				event.preventDefault();
				return true;
			}
		}

		// Click event may never have fired (Gecko & Opera)
		if (true === $.data(event.target, this.widgetName + ".preventClickEvent")) {
			$.removeData(event.target, this.widgetName + ".preventClickEvent");
		}

		// these delegates are required to keep context
		this._mouseMoveDelegate = function(event) {
			return that._mouseMove(event);
		};
		this._mouseUpDelegate = function(event) {
			return that._mouseUp(event);
		};
		$(document)
			.bind("mousemove."+this.widgetName, this._mouseMoveDelegate)
			.bind("mouseup."+this.widgetName, this._mouseUpDelegate);

		event.preventDefault();

		mouseHandled = true;
		return true;
	},

	_mouseMove: function(event) {
		// IE mouseup check - mouseup happened when mouse was out of window
		if ($.ui.ie && ( !document.documentMode || document.documentMode < 9 ) && !event.button) {
			return this._mouseUp(event);
		}

		if (this._mouseStarted) {
			this._mouseDrag(event);
			return event.preventDefault();
		}

		if (this._mouseDistanceMet(event) && this._mouseDelayMet(event)) {
			this._mouseStarted =
				(this._mouseStart(this._mouseDownEvent, event) !== false);
			(this._mouseStarted ? this._mouseDrag(event) : this._mouseUp(event));
		}

		return !this._mouseStarted;
	},

	_mouseUp: function(event) {
		$(document)
			.unbind("mousemove."+this.widgetName, this._mouseMoveDelegate)
			.unbind("mouseup."+this.widgetName, this._mouseUpDelegate);

		if (this._mouseStarted) {
			this._mouseStarted = false;

			if (event.target === this._mouseDownEvent.target) {
				$.data(event.target, this.widgetName + ".preventClickEvent", true);
			}

			this._mouseStop(event);
		}

		return false;
	},

	_mouseDistanceMet: function(event) {
		return (Math.max(
				Math.abs(this._mouseDownEvent.pageX - event.pageX),
				Math.abs(this._mouseDownEvent.pageY - event.pageY)
			) >= this.options.distance
		);
	},

	_mouseDelayMet: function(/* event */) {
		return this.mouseDelayMet;
	},

	// These are placeholder methods, to be overriden by extending plugin
	_mouseStart: function(/* event */) {},
	_mouseDrag: function(/* event */) {},
	_mouseStop: function(/* event */) {},
	_mouseCapture: function(/* event */) { return true; }
});

})(jQuery);

// file: 000-1-040-jquery.ui.draggable.js
/*!
 * jQuery UI Draggable 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/draggable/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

$.widget("ui.draggable", $.ui.mouse, {
	version: "1.10.0",
	widgetEventPrefix: "drag",
	options: {
		addClasses: true,
		appendTo: "parent",
		axis: false,
		connectToSortable: false,
		containment: false,
		cursor: "auto",
		cursorAt: false,
		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,

		// callbacks
		drag: null,
		start: null,
		stop: null
	},
	_create: function() {

		if (this.options.helper === "original" && !(/^(?:r|a|f)/).test(this.element.css("position"))) {
			this.element[0].style.position = "relative";
		}
		if (this.options.addClasses){
			this.element.addClass("ui-draggable");
		}
		if (this.options.disabled){
			this.element.addClass("ui-draggable-disabled");
		}

		this._mouseInit();

	},

	_destroy: function() {
		this.element.removeClass( "ui-draggable ui-draggable-dragging ui-draggable-disabled" );
		this._mouseDestroy();
	},

	_mouseCapture: function(event) {

		var o = this.options;

		// among others, prevent a drag on a resizable-handle
		if (this.helper || o.disabled || $(event.target).closest(".ui-resizable-handle").length > 0) {
			return false;
		}

		//Quit if we're not on a valid handle
		this.handle = this._getHandle(event);
		if (!this.handle) {
			return false;
		}

		$(o.iframeFix === true ? "iframe" : o.iframeFix).each(function() {
			$("<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($(this).offset())
			.appendTo("body");
		});

		return true;

	},

	_mouseStart: function(event) {

		var o = this.options;

		//Create and append the visible helper
		this.helper = this._createHelper(event);

		this.helper.addClass("ui-draggable-dragging");

		//Cache the helper size
		this._cacheHelperProportions();

		//If ddmanager is used for droppables, set the global draggable
		if($.ui.ddmanager) {
			$.ui.ddmanager.current = this;
		}

		/*
		 * - Position generation -
		 * This block generates everything position related - it's the core of draggables.
		 */

		//Cache the margins of the original element
		this._cacheMargins();

		//Store the helper's css position
		this.cssPosition = this.helper.css("position");
		this.scrollParent = this.helper.scrollParent();

		//The element's absolute position on the page minus margins
		this.offset = this.positionAbs = this.element.offset();
		this.offset = {
			top: this.offset.top - this.margins.top,
			left: this.offset.left - this.margins.left
		};

		$.extend(this.offset, {
			click: { //Where the click happened, relative to the element
				left: event.pageX - this.offset.left,
				top: event.pageY - this.offset.top
			},
			parent: this._getParentOffset(),
			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
		});

		//Generate the original position
		this.originalPosition = this.position = this._generatePosition(event);
		this.originalPageX = event.pageX;
		this.originalPageY = event.pageY;

		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));

		//Set a containment if given in the options
		if(o.containment) {
			this._setContainment();
		}

		//Trigger event + callbacks
		if(this._trigger("start", event) === false) {
			this._clear();
			return false;
		}

		//Recache the helper size
		this._cacheHelperProportions();

		//Prepare the droppable offsets
		if ($.ui.ddmanager && !o.dropBehaviour) {
			$.ui.ddmanager.prepareOffsets(this, event);
		}


		this._mouseDrag(event, true); //Execute the drag once - this causes the helper not to be visible before getting its correct position

		//If the ddmanager is used for droppables, inform the manager that dragging has started (see #5003)
		if ( $.ui.ddmanager ) {
			$.ui.ddmanager.dragStart(this, event);
		}

		return true;
	},

	_mouseDrag: function(event, noPropagation) {

		//Compute the helpers position
		this.position = this._generatePosition(event);
		this.positionAbs = this._convertPositionTo("absolute");

		//Call plugins and callbacks and use the resulting position if something is returned
		if (!noPropagation) {
			var ui = this._uiHash();
			if(this._trigger("drag", event, ui) === false) {
				this._mouseUp({});
				return false;
			}
			this.position = ui.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($.ui.ddmanager) {
			$.ui.ddmanager.drag(this, event);
		}

		return false;
	},

	_mouseStop: function(event) {

		//If we are using droppables, inform the manager about the drop
		var element,
			that = this,
			elementInDom = false,
			dropped = false;
		if ($.ui.ddmanager && !this.options.dropBehaviour) {
			dropped = $.ui.ddmanager.drop(this, event);
		}

		//if a drop comes from outside (a sortable)
		if(this.dropped) {
			dropped = this.dropped;
			this.dropped = false;
		}

		//if the original element is no longer in the DOM don't bother to continue (see #8269)
		element = this.element[0];
		while ( element && (element = element.parentNode) ) {
			if (element === document ) {
				elementInDom = true;
			}
		}
		if ( !elementInDom && this.options.helper === "original" ) {
			return false;
		}

		if((this.options.revert === "invalid" && !dropped) || (this.options.revert === "valid" && dropped) || this.options.revert === true || ($.isFunction(this.options.revert) && this.options.revert.call(this.element, dropped))) {
			$(this.helper).animate(this.originalPosition, parseInt(this.options.revertDuration, 10), function() {
				if(that._trigger("stop", event) !== false) {
					that._clear();
				}
			});
		} else {
			if(this._trigger("stop", event) !== false) {
				this._clear();
			}
		}

		return false;
	},

	_mouseUp: function(event) {
		//Remove frame helpers
		$("div.ui-draggable-iframeFix").each(function() {
			this.parentNode.removeChild(this);
		});

		//If the ddmanager is used for droppables, inform the manager that dragging has stopped (see #5003)
		if( $.ui.ddmanager ) {
			$.ui.ddmanager.dragStop(this, event);
		}

		return $.ui.mouse.prototype._mouseUp.call(this, event);
	},

	cancel: function() {

		if(this.helper.is(".ui-draggable-dragging")) {
			this._mouseUp({});
		} else {
			this._clear();
		}

		return this;

	},

	_getHandle: function(event) {

		var handle = !this.options.handle || !$(this.options.handle, this.element).length ? true : false;
		$(this.options.handle, this.element)
			.find("*")
			.addBack()
			.each(function() {
				if(this === event.target) {
					handle = true;
				}
			});

		return handle;

	},

	_createHelper: function(event) {

		var o = this.options,
			helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event])) : (o.helper === "clone" ? this.element.clone().removeAttr("id") : this.element);

		if(!helper.parents("body").length) {
			helper.appendTo((o.appendTo === "parent" ? this.element[0].parentNode : o.appendTo));
		}

		if(helper[0] !== this.element[0] && !(/(fixed|absolute)/).test(helper.css("position"))) {
			helper.css("position", "absolute");
		}

		return helper;

	},

	_adjustOffsetFromHelper: function(obj) {
		if (typeof obj === "string") {
			obj = obj.split(" ");
		}
		if ($.isArray(obj)) {
			obj = {left: +obj[0], top: +obj[1] || 0};
		}
		if ("left" in obj) {
			this.offset.click.left = obj.left + this.margins.left;
		}
		if ("right" in obj) {
			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
		}
		if ("top" in obj) {
			this.offset.click.top = obj.top + this.margins.top;
		}
		if ("bottom" in obj) {
			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
		}
	},

	_getParentOffset: function() {

		//Get the offsetParent and cache its position
		this.offsetParent = this.helper.offsetParent();
		var po = this.offsetParent.offset();

		// This is a special case where we need to modify a offset calculated on start, since the following happened:
		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
		if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
			po.left += this.scrollParent.scrollLeft();
			po.top += this.scrollParent.scrollTop();
		}

		//This needs to be actually done for all browsers, since pageX/pageY includes this information
		//Ugly IE fix
		if((this.offsetParent[0] === document.body) ||
			(this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
			po = { top: 0, left: 0 };
		}

		return {
			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
		};

	},

	_getRelativeOffset: function() {

		if(this.cssPosition === "relative") {
			var p = this.element.position();
			return {
				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
				left: p.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),
			right: (parseInt(this.element.css("marginRight"),10) || 0),
			bottom: (parseInt(this.element.css("marginBottom"),10) || 0)
		};
	},

	_cacheHelperProportions: function() {
		this.helperProportions = {
			width: this.helper.outerWidth(),
			height: this.helper.outerHeight()
		};
	},

	_setContainment: function() {

		var over, c, ce,
			o = this.options;

		if(o.containment === "parent") {
			o.containment = this.helper[0].parentNode;
		}
		if(o.containment === "document" || o.containment === "window") {
			this.containment = [
				o.containment === "document" ? 0 : $(window).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
				o.containment === "document" ? 0 : $(window).scrollTop() - this.offset.relative.top - this.offset.parent.top,
				(o.containment === "document" ? 0 : $(window).scrollLeft()) + $(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
				(o.containment === "document" ? 0 : $(window).scrollTop()) + ($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
			];
		}

		if(!(/^(document|window|parent)$/).test(o.containment) && o.containment.constructor !== Array) {
			c = $(o.containment);
			ce = c[0];

			if(!ce) {
				return;
			}

			over = ($(ce).css("overflow") !== "hidden");

			this.containment = [
				(parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0),
				(parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0),
				(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left - this.margins.right,
				(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top  - this.margins.bottom
			];
			this.relative_container = c;

		} else if(o.containment.constructor === Array) {
			this.containment = o.containment;
		}

	},

	_convertPositionTo: function(d, pos) {

		if(!pos) {
			pos = this.position;
		}

		var mod = d === "absolute" ? 1 : -1,
			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);

		return {
			top: (
				pos.top	+																// The absolute mouse position
				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
				this.offset.parent.top * mod -										// The offsetParent's offset without borders (offset + border)
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
			),
			left: (
				pos.left +																// The absolute mouse position
				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
			)
		};

	},

	_generatePosition: function(event) {

		var containment, co, top, left,
			o = this.options,
			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
			scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName),
			pageX = event.pageX,
			pageY = event.pageY;

		/*
		 * - Position constraining -
		 * Constrain the position to a mix of grid, containment.
		 */

		if(this.originalPosition) { //If we are not dragging yet, we won't check for options
			if(this.containment) {
			if (this.relative_container){
				co = this.relative_container.offset();
				containment = [ this.containment[0] + co.left,
					this.containment[1] + co.top,
					this.containment[2] + co.left,
					this.containment[3] + co.top ];
			}
			else {
				containment = this.containment;
			}

				if(event.pageX - this.offset.click.left < containment[0]) {
					pageX = containment[0] + this.offset.click.left;
				}
				if(event.pageY - this.offset.click.top < containment[1]) {
					pageY = containment[1] + this.offset.click.top;
				}
				if(event.pageX - this.offset.click.left > containment[2]) {
					pageX = containment[2] + this.offset.click.left;
				}
				if(event.pageY - this.offset.click.top > containment[3]) {
					pageY = containment[3] + this.offset.click.top;
				}
			}

			if(o.grid) {
				//Check for grid elements set to 0 to prevent divide by 0 error causing invalid argument errors in IE (see ticket #6950)
				top = o.grid[1] ? this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1] : this.originalPageY;
				pageY = containment ? ((top - this.offset.click.top >= containment[1] || top - this.offset.click.top > containment[3]) ? top : ((top - this.offset.click.top >= containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;

				left = o.grid[0] ? this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0] : this.originalPageX;
				pageX = containment ? ((left - this.offset.click.left >= containment[0] || left - this.offset.click.left > containment[2]) ? left : ((left - this.offset.click.left >= containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
			}

		}

		return {
			top: (
				pageY -																	// The absolute mouse position
				this.offset.click.top	-												// Click offset (relative to the element)
				this.offset.relative.top -												// Only for relative positioned nodes: Relative offset from element to offset parent
				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
			),
			left: (
				pageX -																	// The absolute mouse position
				this.offset.click.left -												// Click offset (relative to the element)
				this.offset.relative.left -												// Only for relative positioned nodes: Relative offset from element to offset parent
				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.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;
	},

	// From now on bulk stuff - mainly helpers

	_trigger: function(type, event, ui) {
		ui = ui || this._uiHash();
		$.ui.plugin.call(this, type, [event, ui]);
		//The absolute position has to be recalculated after plugins
		if(type === "drag") {
			this.positionAbs = this._convertPositionTo("absolute");
		}
		return $.Widget.prototype._trigger.call(this, type, event, ui);
	},

	plugins: {},

	_uiHash: function() {
		return {
			helper: this.helper,
			position: this.position,
			originalPosition: this.originalPosition,
			offset: this.positionAbs
		};
	}

});

$.ui.plugin.add("draggable", "connectToSortable", {
	start: function(event, ui) {

		var inst = $(this).data("ui-draggable"), o = inst.options,
			uiSortable = $.extend({}, ui, { item: inst.element });
		inst.sortables = [];
		$(o.connectToSortable).each(function() {
			var sortable = $.data(this, "ui-sortable");
			if (sortable && !sortable.options.disabled) {
				inst.sortables.push({
					instance: sortable,
					shouldRevert: sortable.options.revert
				});
				sortable.refreshPositions();	// Call the sortable's refreshPositions at drag start to refresh the containerCache since the sortable container cache is used in drag and needs to be up to date (this will ensure it's initialised as well as being kept in step with any changes that might have happened on the page).
				sortable._trigger("activate", event, uiSortable);
			}
		});

	},
	stop: function(event, ui) {

		//If we are still over the sortable, we fake the stop event of the sortable, but also remove helper
		var inst = $(this).data("ui-draggable"),
			uiSortable = $.extend({}, ui, { item: inst.element });

		$.each(inst.sortables, function() {
			if(this.instance.isOver) {

				this.instance.isOver = 0;

				inst.cancelHelperRemoval = true; //Don't remove the helper in the draggable instance
				this.instance.cancelHelperRemoval = false; //Remove it in the sortable instance (so sortable plugins like revert still work)

				//The sortable revert is supported, and we have to set a temporary dropped variable on the draggable to support revert: "valid/invalid"
				if(this.shouldRevert) {
					this.instance.options.revert = true;
				}

				//Trigger the stop of the sortable
				this.instance._mouseStop(event);

				this.instance.options.helper = this.instance.options._helper;

				//If the helper has been the original item, restore properties in the sortable
				if(inst.options.helper === "original") {
					this.instance.currentItem.css({ top: "auto", left: "auto" });
				}

			} else {
				this.instance.cancelHelperRemoval = false; //Remove the helper in the sortable instance
				this.instance._trigger("deactivate", event, uiSortable);
			}

		});

	},
	drag: function(event, ui) {

		var inst = $(this).data("ui-draggable"), that = this;

		$.each(inst.sortables, function() {

			var innermostIntersecting = false,
				thisSortable = this;

			//Copy over some variables to allow calling the sortable's native _intersectsWith
			this.instance.positionAbs = inst.positionAbs;
			this.instance.helperProportions = inst.helperProportions;
			this.instance.offset.click = inst.offset.click;

			if(this.instance._intersectsWith(this.instance.containerCache)) {
				innermostIntersecting = true;
				$.each(inst.sortables, function () {
					this.instance.positionAbs = inst.positionAbs;
					this.instance.helperProportions = inst.helperProportions;
					this.instance.offset.click = inst.offset.click;
					if (this !== thisSortable &&
						this.instance._intersectsWith(this.instance.containerCache) &&
						$.ui.contains(thisSortable.instance.element[0], this.instance.element[0])
					) {
						innermostIntersecting = false;
					}
					return innermostIntersecting;
				});
			}


			if(innermostIntersecting) {
				//If it intersects, we use a little isOver variable and set it once, so our move-in stuff gets fired only once
				if(!this.instance.isOver) {

					this.instance.isOver = 1;
					//Now we fake the start of dragging for the sortable instance,
					//by cloning the list group item, appending it to the sortable and using it as inst.currentItem
					//We can then fire the start event of the sortable with our passed browser event, and our own helper (so it doesn't create a new one)
					this.instance.currentItem = $(that).clone().removeAttr("id").appendTo(this.instance.element).data("ui-sortable-item", true);
					this.instance.options._helper = this.instance.options.helper; //Store helper option to later restore it
					this.instance.options.helper = function() { return ui.helper[0]; };

					event.target = this.instance.currentItem[0];
					this.instance._mouseCapture(event, true);
					this.instance._mouseStart(event, true, true);

					//Because the browser event is way off the new appended portlet, we modify a couple of variables to reflect the changes
					this.instance.offset.click.top = inst.offset.click.top;
					this.instance.offset.click.left = inst.offset.click.left;
					this.instance.offset.parent.left -= inst.offset.parent.left - this.instance.offset.parent.left;
					this.instance.offset.parent.top -= inst.offset.parent.top - this.instance.offset.parent.top;

					inst._trigger("toSortable", event);
					inst.dropped = this.instance.element; //draggable revert needs that
					//hack so receive/update callbacks work (mostly)
					inst.currentItem = inst.element;
					this.instance.fromOutside = inst;

				}

				//Provided we did all the previous steps, we can fire the drag event of the sortable on every draggable drag, when it intersects with the sortable
				if(this.instance.currentItem) {
					this.instance._mouseDrag(event);
				}

			} else {

				//If it doesn't intersect with the sortable, and it intersected before,
				//we fake the drag stop of the sortable, but make sure it doesn't remove the helper by using cancelHelperRemoval
				if(this.instance.isOver) {

					this.instance.isOver = 0;
					this.instance.cancelHelperRemoval = true;

					//Prevent reverting on this forced stop
					this.instance.options.revert = false;

					// The out event needs to be triggered independently
					this.instance._trigger("out", event, this.instance._uiHash(this.instance));

					this.instance._mouseStop(event, true);
					this.instance.options.helper = this.instance.options._helper;

					//Now we remove our currentItem, the list group clone again, and the placeholder, and animate the helper back to it's original size
					this.instance.currentItem.remove();
					if(this.instance.placeholder) {
						this.instance.placeholder.remove();
					}

					inst._trigger("fromSortable", event);
					inst.dropped = false; //draggable revert needs that
				}

			}

		});

	}
});

$.ui.plugin.add("draggable", "cursor", {
	start: function() {
		var t = $("body"), o = $(this).data("ui-draggable").options;
		if (t.css("cursor")) {
			o._cursor = t.css("cursor");
		}
		t.css("cursor", o.cursor);
	},
	stop: function() {
		var o = $(this).data("ui-draggable").options;
		if (o._cursor) {
			$("body").css("cursor", o._cursor);
		}
	}
});

$.ui.plugin.add("draggable", "opacity", {
	start: function(event, ui) {
		var t = $(ui.helper), o = $(this).data("ui-draggable").options;
		if(t.css("opacity")) {
			o._opacity = t.css("opacity");
		}
		t.css("opacity", o.opacity);
	},
	stop: function(event, ui) {
		var o = $(this).data("ui-draggable").options;
		if(o._opacity) {
			$(ui.helper).css("opacity", o._opacity);
		}
	}
});

$.ui.plugin.add("draggable", "scroll", {
	start: function() {
		var i = $(this).data("ui-draggable");
		if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {
			i.overflowOffset = i.scrollParent.offset();
		}
	},
	drag: function( event ) {

		var i = $(this).data("ui-draggable"), o = i.options, scrolled = false;

		if(i.scrollParent[0] !== document && i.scrollParent[0].tagName !== "HTML") {

			if(!o.axis || o.axis !== "x") {
				if((i.overflowOffset.top + i.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop + o.scrollSpeed;
				} else if(event.pageY - i.overflowOffset.top < o.scrollSensitivity) {
					i.scrollParent[0].scrollTop = scrolled = i.scrollParent[0].scrollTop - o.scrollSpeed;
				}
			}

			if(!o.axis || o.axis !== "y") {
				if((i.overflowOffset.left + i.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft + o.scrollSpeed;
				} else if(event.pageX - i.overflowOffset.left < o.scrollSensitivity) {
					i.scrollParent[0].scrollLeft = scrolled = i.scrollParent[0].scrollLeft - o.scrollSpeed;
				}
			}

		} else {

			if(!o.axis || o.axis !== "x") {
				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
				} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
				}
			}

			if(!o.axis || o.axis !== "y") {
				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
				} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
				}
			}

		}

		if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
			$.ui.ddmanager.prepareOffsets(i, event);
		}

	}
});

$.ui.plugin.add("draggable", "snap", {
	start: function() {

		var i = $(this).data("ui-draggable"),
			o = i.options;

		i.snapElements = [];

		$(o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap).each(function() {
			var $t = $(this),
				$o = $t.offset();
			if(this !== i.element[0]) {
				i.snapElements.push({
					item: this,
					width: $t.outerWidth(), height: $t.outerHeight(),
					top: $o.top, left: $o.left
				});
			}
		});

	},
	drag: function(event, ui) {

		var ts, bs, ls, rs, l, r, t, b, i, first,
			inst = $(this).data("ui-draggable"),
			o = inst.options,
			d = o.snapTolerance,
			x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
			y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;

		for (i = inst.snapElements.length - 1; i >= 0; i--){

			l = inst.snapElements[i].left;
			r = l + inst.snapElements[i].width;
			t = inst.snapElements[i].top;
			b = t + inst.snapElements[i].height;

			//Yes, I know, this is insane ;)
			if(!((l-d < x1 && x1 < r+d && t-d < y1 && y1 < b+d) || (l-d < x1 && x1 < r+d && t-d < y2 && y2 < b+d) || (l-d < x2 && x2 < r+d && t-d < y1 && y1 < b+d) || (l-d < x2 && x2 < r+d && t-d < y2 && y2 < b+d))) {
				if(inst.snapElements[i].snapping) {
					(inst.options.snap.release && inst.options.snap.release.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
				}
				inst.snapElements[i].snapping = false;
				continue;
			}

			if(o.snapMode !== "inner") {
				ts = Math.abs(t - y2) <= d;
				bs = Math.abs(b - y1) <= d;
				ls = Math.abs(l - x2) <= d;
				rs = Math.abs(r - x1) <= d;
				if(ts) {
					ui.position.top = inst._convertPositionTo("relative", { top: t - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
				}
				if(bs) {
					ui.position.top = inst._convertPositionTo("relative", { top: b, left: 0 }).top - inst.margins.top;
				}
				if(ls) {
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l - inst.helperProportions.width }).left - inst.margins.left;
				}
				if(rs) {
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r }).left - inst.margins.left;
				}
			}

			first = (ts || bs || ls || rs);

			if(o.snapMode !== "outer") {
				ts = Math.abs(t - y1) <= d;
				bs = Math.abs(b - y2) <= d;
				ls = Math.abs(l - x1) <= d;
				rs = Math.abs(r - x2) <= d;
				if(ts) {
					ui.position.top = inst._convertPositionTo("relative", { top: t, left: 0 }).top - inst.margins.top;
				}
				if(bs) {
					ui.position.top = inst._convertPositionTo("relative", { top: b - inst.helperProportions.height, left: 0 }).top - inst.margins.top;
				}
				if(ls) {
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: l }).left - inst.margins.left;
				}
				if(rs) {
					ui.position.left = inst._convertPositionTo("relative", { top: 0, left: r - inst.helperProportions.width }).left - inst.margins.left;
				}
			}

			if(!inst.snapElements[i].snapping && (ts || bs || ls || rs || first)) {
				(inst.options.snap.snap && inst.options.snap.snap.call(inst.element, event, $.extend(inst._uiHash(), { snapItem: inst.snapElements[i].item })));
			}
			inst.snapElements[i].snapping = (ts || bs || ls || rs || first);

		}

	}
});

$.ui.plugin.add("draggable", "stack", {
	start: function() {

		var min,
			o = $(this).data("ui-draggable").options,
			group = $.makeArray($(o.stack)).sort(function(a,b) {
				return (parseInt($(a).css("zIndex"),10) || 0) - (parseInt($(b).css("zIndex"),10) || 0);
			});

		if (!group.length) { return; }

		min = parseInt(group[0].style.zIndex, 10) || 0;
		$(group).each(function(i) {
			this.style.zIndex = min + i;
		});

		this[0].style.zIndex = min + group.length;

	}
});

$.ui.plugin.add("draggable", "zIndex", {
	start: function(event, ui) {
		var t = $(ui.helper), o = $(this).data("ui-draggable").options;
		if(t.css("zIndex")) {
			o._zIndex = t.css("zIndex");
		}
		t.css("zIndex", o.zIndex);
	},
	stop: function(event, ui) {
		var o = $(this).data("ui-draggable").options;
		if(o._zIndex) {
			$(ui.helper).css("zIndex", o._zIndex);
		}
	}
});

})(jQuery);

// file: 000-1-050-jquery.ui.droppable.js
/*!
 * jQuery UI Droppable 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/droppable/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.mouse.js
 *	jquery.ui.draggable.js
 */
(function( $, undefined ) {

function isOverAxis( x, reference, size ) {
	return ( x > reference ) && ( x < ( reference + size ) );
}

$.widget("ui.droppable", {
	version: "1.10.0",
	widgetEventPrefix: "drop",
	options: {
		accept: "*",
		activeClass: false,
		addClasses: true,
		greedy: false,
		hoverClass: false,
		scope: "default",
		tolerance: "intersect",

		// callbacks
		activate: null,
		deactivate: null,
		drop: null,
		out: null,
		over: null
	},
	_create: function() {

		var o = this.options,
			accept = o.accept;

		this.isover = false;
		this.isout = true;

		this.accept = $.isFunction(accept) ? accept : function(d) {
			return d.is(accept);
		};

		//Store the droppable's proportions
		this.proportions = { width: this.element[0].offsetWidth, height: this.element[0].offsetHeight };

		// Add the reference and positions to the manager
		$.ui.ddmanager.droppables[o.scope] = $.ui.ddmanager.droppables[o.scope] || [];
		$.ui.ddmanager.droppables[o.scope].push(this);

		(o.addClasses && this.element.addClass("ui-droppable"));

	},

	_destroy: function() {
		var i = 0,
			drop = $.ui.ddmanager.droppables[this.options.scope];

		for ( ; i < drop.length; i++ ) {
			if ( drop[i] === this ) {
				drop.splice(i, 1);
			}
		}

		this.element.removeClass("ui-droppable ui-droppable-disabled");
	},

	_setOption: function(key, value) {

		if(key === "accept") {
			this.accept = $.isFunction(value) ? value : function(d) {
				return d.is(value);
			};
		}
		$.Widget.prototype._setOption.apply(this, arguments);
	},

	_activate: function(event) {
		var draggable = $.ui.ddmanager.current;
		if(this.options.activeClass) {
			this.element.addClass(this.options.activeClass);
		}
		if(draggable){
			this._trigger("activate", event, this.ui(draggable));
		}
	},

	_deactivate: function(event) {
		var draggable = $.ui.ddmanager.current;
		if(this.options.activeClass) {
			this.element.removeClass(this.options.activeClass);
		}
		if(draggable){
			this._trigger("deactivate", event, this.ui(draggable));
		}
	},

	_over: function(event) {

		var draggable = $.ui.ddmanager.current;

		// Bail if draggable and droppable are same element
		if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
			return;
		}

		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
			if(this.options.hoverClass) {
				this.element.addClass(this.options.hoverClass);
			}
			this._trigger("over", event, this.ui(draggable));
		}

	},

	_out: function(event) {

		var draggable = $.ui.ddmanager.current;

		// Bail if draggable and droppable are same element
		if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
			return;
		}

		if (this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
			if(this.options.hoverClass) {
				this.element.removeClass(this.options.hoverClass);
			}
			this._trigger("out", event, this.ui(draggable));
		}

	},

	_drop: function(event,custom) {

		var draggable = custom || $.ui.ddmanager.current,
			childrenIntersection = false;

		// Bail if draggable and droppable are same element
		if (!draggable || (draggable.currentItem || draggable.element)[0] === this.element[0]) {
			return false;
		}

		this.element.find(":data(ui-droppable)").not(".ui-draggable-dragging").each(function() {
			var inst = $.data(this, "ui-droppable");
			if(
				inst.options.greedy &&
				!inst.options.disabled &&
				inst.options.scope === draggable.options.scope &&
				inst.accept.call(inst.element[0], (draggable.currentItem || draggable.element)) &&
				$.ui.intersect(draggable, $.extend(inst, { offset: inst.element.offset() }), inst.options.tolerance)
			) { childrenIntersection = true; return false; }
		});
		if(childrenIntersection) {
			return false;
		}

		if(this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
			if(this.options.activeClass) {
				this.element.removeClass(this.options.activeClass);
			}
			if(this.options.hoverClass) {
				this.element.removeClass(this.options.hoverClass);
			}
			this._trigger("drop", event, this.ui(draggable));
			return this.element;
		}

		return false;

	},

	ui: function(c) {
		return {
			draggable: (c.currentItem || c.element),
			helper: c.helper,
			position: c.position,
			offset: c.positionAbs
		};
	}

});

$.ui.intersect = function(draggable, droppable, toleranceMode) {

	if (!droppable.offset) {
		return false;
	}

	var draggableLeft, draggableTop,
		x1 = (draggable.positionAbs || draggable.position.absolute).left, x2 = x1 + draggable.helperProportions.width,
		y1 = (draggable.positionAbs || draggable.position.absolute).top, y2 = y1 + draggable.helperProportions.height,
		l = droppable.offset.left, r = l + droppable.proportions.width,
		t = droppable.offset.top, b = t + droppable.proportions.height;

	switch (toleranceMode) {
		case "fit":
			return (l <= x1 && x2 <= r && t <= y1 && y2 <= b);
		case "intersect":
			return (l < x1 + (draggable.helperProportions.width / 2) && // Right Half
				x2 - (draggable.helperProportions.width / 2) < r && // Left Half
				t < y1 + (draggable.helperProportions.height / 2) && // Bottom Half
				y2 - (draggable.helperProportions.height / 2) < b ); // Top Half
		case "pointer":
			draggableLeft = ((draggable.positionAbs || draggable.position.absolute).left + (draggable.clickOffset || draggable.offset.click).left);
			draggableTop = ((draggable.positionAbs || draggable.position.absolute).top + (draggable.clickOffset || draggable.offset.click).top);
			return isOverAxis( draggableTop, t, droppable.proportions.height ) && isOverAxis( draggableLeft, l, droppable.proportions.width );
		case "touch":
			return (
				(y1 >= t && y1 <= b) ||	// Top edge touching
				(y2 >= t && y2 <= b) ||	// Bottom edge touching
				(y1 < t && y2 > b)		// Surrounded vertically
			) && (
				(x1 >= l && x1 <= r) ||	// Left edge touching
				(x2 >= l && x2 <= r) ||	// Right edge touching
				(x1 < l && x2 > r)		// Surrounded horizontally
			);
		default:
			return false;
		}

};

/*
	This manager tracks offsets of draggables and droppables
*/
$.ui.ddmanager = {
	current: null,
	droppables: { "default": [] },
	prepareOffsets: function(t, event) {

		var i, j,
			m = $.ui.ddmanager.droppables[t.options.scope] || [],
			type = event ? event.type : null, // workaround for #2317
			list = (t.currentItem || t.element).find(":data(ui-droppable)").addBack();

		droppablesLoop: for (i = 0; i < m.length; i++) {

			//No disabled and non-accepted
			if(m[i].options.disabled || (t && !m[i].accept.call(m[i].element[0],(t.currentItem || t.element)))) {
				continue;
			}

			// Filter out elements in the current dragged item
			for (j=0; j < list.length; j++) {
				if(list[j] === m[i].element[0]) {
					m[i].proportions.height = 0;
					continue droppablesLoop;
				}
			}

			m[i].visible = m[i].element.css("display") !== "none";
			if(!m[i].visible) {
				continue;
			}

			//Activate the droppable if used directly from draggables
			if(type === "mousedown") {
				m[i]._activate.call(m[i], event);
			}

			m[i].offset = m[i].element.offset();
			m[i].proportions = { width: m[i].element[0].offsetWidth, height: m[i].element[0].offsetHeight };

		}

	},
	drop: function(draggable, event) {

		var dropped = false;
		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {

			if(!this.options) {
				return;
			}
			if (!this.options.disabled && this.visible && $.ui.intersect(draggable, this, this.options.tolerance)) {
				dropped = this._drop.call(this, event) || dropped;
			}

			if (!this.options.disabled && this.visible && this.accept.call(this.element[0],(draggable.currentItem || draggable.element))) {
				this.isout = true;
				this.isover = false;
				this._deactivate.call(this, event);
			}

		});
		return dropped;

	},
	dragStart: function( draggable, event ) {
		//Listen for scrolling so that if the dragging causes scrolling the position of the droppables can be recalculated (see #5003)
		draggable.element.parentsUntil( "body" ).bind( "scroll.droppable", function() {
			if( !draggable.options.refreshPositions ) {
				$.ui.ddmanager.prepareOffsets( draggable, event );
			}
		});
	},
	drag: function(draggable, event) {

		//If you have a highly dynamic page, you might try this option. It renders positions every time you move the mouse.
		if(draggable.options.refreshPositions) {
			$.ui.ddmanager.prepareOffsets(draggable, event);
		}

		//Run through all droppables and check their positions based on specific tolerance options
		$.each($.ui.ddmanager.droppables[draggable.options.scope] || [], function() {

			if(this.options.disabled || this.greedyChild || !this.visible) {
				return;
			}

			var parentInstance, scope, parent,
				intersects = $.ui.intersect(draggable, this, this.options.tolerance),
				c = !intersects && this.isover ? "isout" : (intersects && !this.isover ? "isover" : null);
			if(!c) {
				return;
			}

			if (this.options.greedy) {
				// find droppable parents with same scope
				scope = this.options.scope;
				parent = this.element.parents(":data(ui-droppable)").filter(function () {
					return $.data(this, "ui-droppable").options.scope === scope;
				});

				if (parent.length) {
					parentInstance = $.data(parent[0], "ui-droppable");
					parentInstance.greedyChild = (c === "isover");
				}
			}

			// we just moved into a greedy child
			if (parentInstance && c === "isover") {
				parentInstance.isover = false;
				parentInstance.isout = true;
				parentInstance._out.call(parentInstance, event);
			}

			this[c] = true;
			this[c === "isout" ? "isover" : "isout"] = false;
			this[c === "isover" ? "_over" : "_out"].call(this, event);

			// we just moved out of a greedy child
			if (parentInstance && c === "isout") {
				parentInstance.isout = false;
				parentInstance.isover = true;
				parentInstance._over.call(parentInstance, event);
			}
		});

	},
	dragStop: function( draggable, event ) {
		draggable.element.parentsUntil( "body" ).unbind( "scroll.droppable" );
		//Call prepareOffsets one final time since IE does not fire return scroll events when overflow was caused by drag (see #5003)
		if( !draggable.options.refreshPositions ) {
			$.ui.ddmanager.prepareOffsets( draggable, event );
		}
	}
};

})(jQuery);

// file: 000-1-060-jquery.ui.resizable.js
/*!
 * jQuery UI Resizable 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/resizable/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

function num(v) {
	return parseInt(v, 10) || 0;
}

function isNumber(value) {
	return !isNaN(parseInt(value, 10));
}

$.widget("ui.resizable", $.ui.mouse, {
	version: "1.10.0",
	widgetEventPrefix: "resize",
	options: {
		alsoResize: false,
		animate: false,
		animateDuration: "slow",
		animateEasing: "swing",
		aspectRatio: false,
		autoHide: false,
		containment: false,
		ghost: false,
		grid: false,
		handles: "e,s,se",
		helper: false,
		maxHeight: null,
		maxWidth: null,
		minHeight: 10,
		minWidth: 10,
		// See #7960
		zIndex: 90,

		// callbacks
		resize: null,
		start: null,
		stop: null
	},
	_create: function() {

		var n, i, handle, axis, hname,
			that = this,
			o = this.options;
		this.element.addClass("ui-resizable");

		$.extend(this, {
			_aspectRatio: !!(o.aspectRatio),
			aspectRatio: o.aspectRatio,
			originalElement: this.element,
			_proportionallyResizeElements: [],
			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
		});

		//Wrap the element if it cannot hold child nodes
		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {

			//Create a wrapper element and set the wrapper to the new current internal element
			this.element.wrap(
				$("<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")
				})
			);

			//Overwrite the original this.element
			this.element = this.element.parent().data(
				"ui-resizable", this.element.data("ui-resizable")
			);

			this.elementIsWrapper = true;

			//Move margins to the wrapper
			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});

			//Prevent Safari textarea resize
			this.originalResizeStyle = this.originalElement.css("resize");
			this.originalElement.css("resize", "none");

			//Push the actual element to our proportionallyResize internal array
			this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));

			// avoid IE jump (hard set the margin)
			this.originalElement.css({ margin: this.originalElement.css("margin") });

			// fix handlers offset
			this._proportionallyResize();

		}

		this.handles = o.handles || (!$(".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";
			}

			n = this.handles.split(",");
			this.handles = {};

			for(i = 0; i < n.length; i++) {

				handle = $.trim(n[i]);
				hname = "ui-resizable-"+handle;
				axis = $("<div class='ui-resizable-handle " + hname + "'></div>");

				// Apply zIndex to all handles - see #7960
				axis.css({ zIndex: o.zIndex });

				//TODO : What's going on here?
				if ("se" === handle) {
					axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
				}

				//Insert into internal handles object and append to element
				this.handles[handle] = ".ui-resizable-"+handle;
				this.element.append(axis);
			}

		}

		this._renderAxis = function(target) {

			var i, axis, padPos, padWrapper;

			target = target || this.element;

			for(i in this.handles) {

				if(this.handles[i].constructor === String) {
					this.handles[i] = $(this.handles[i], this.element).show();
				}

				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {

					axis = $(this.handles[i], this.element);

					//Checking the correct pad and border
					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();

					//The padding type i have to apply...
					padPos = [ "padding",
						/ne|nw|n/.test(i) ? "Top" :
						/se|sw|s/.test(i) ? "Bottom" :
						/^e$/.test(i) ? "Right" : "Left" ].join("");

					target.css(padPos, padWrapper);

					this._proportionallyResize();

				}

				//TODO: What's that good for? There's not anything to be executed left
				if(!$(this.handles[i]).length) {
					continue;
				}
			}
		};

		//TODO: make renderAxis a prototype function
		this._renderAxis(this.element);

		this._handles = $(".ui-resizable-handle", this.element)
			.disableSelection();

		//Matching axis name
		this._handles.mouseover(function() {
			if (!that.resizing) {
				if (this.className) {
					axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
				}
				//Axis, default = se
				that.axis = axis && axis[1] ? axis[1] : "se";
			}
		});

		//If we want to auto hide the elements
		if (o.autoHide) {
			this._handles.hide();
			$(this.element)
				.addClass("ui-resizable-autohide")
				.mouseenter(function() {
					if (o.disabled) {
						return;
					}
					$(this).removeClass("ui-resizable-autohide");
					that._handles.show();
				})
				.mouseleave(function(){
					if (o.disabled) {
						return;
					}
					if (!that.resizing) {
						$(this).addClass("ui-resizable-autohide");
						that._handles.hide();
					}
				});
		}

		//Initialize the mouse interaction
		this._mouseInit();

	},

	_destroy: function() {

		this._mouseDestroy();

		var wrapper,
			_destroy = function(exp) {
				$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
					.removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();
			};

		//TODO: Unwrap at same DOM position
		if (this.elementIsWrapper) {
			_destroy(this.element);
			wrapper = this.element;
			this.originalElement.css({
				position: wrapper.css("position"),
				width: wrapper.outerWidth(),
				height: wrapper.outerHeight(),
				top: wrapper.css("top"),
				left: wrapper.css("left")
			}).insertAfter( wrapper );
			wrapper.remove();
		}

		this.originalElement.css("resize", this.originalResizeStyle);
		_destroy(this.originalElement);

		return this;
	},

	_mouseCapture: function(event) {
		var i, handle,
			capture = false;

		for (i in this.handles) {
			handle = $(this.handles[i])[0];
			if (handle === event.target || $.contains(handle, event.target)) {
				capture = true;
			}
		}

		return !this.options.disabled && capture;
	},

	_mouseStart: function(event) {

		var curleft, curtop, cursor,
			o = this.options,
			iniPos = this.element.position(),
			el = this.element;

		this.resizing = true;

		// bugfix for http://dev.jquery.com/ticket/1749
		if ( (/absolute/).test( el.css("position") ) ) {
			el.css({ position: "absolute", top: el.css("top"), left: el.css("left") });
		} else if (el.is(".ui-draggable")) {
			el.css({ position: "absolute", top: iniPos.top, left: iniPos.left });
		}

		this._renderProxy();

		curleft = num(this.helper.css("left"));
		curtop = num(this.helper.css("top"));

		if (o.containment) {
			curleft += $(o.containment).scrollLeft() || 0;
			curtop += $(o.containment).scrollTop() || 0;
		}

		//Store needed variables
		this.offset = this.helper.offset();
		this.position = { left: curleft, top: curtop };
		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
		this.originalPosition = { left: curleft, top: curtop };
		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
		this.originalMousePosition = { left: event.pageX, top: event.pageY };

		//Aspect Ratio
		this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);

		cursor = $(".ui-resizable-" + this.axis).css("cursor");
		$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);

		el.addClass("ui-resizable-resizing");
		this._propagate("start", event);
		return true;
	},

	_mouseDrag: function(event) {

		//Increase performance, avoid regex
		var data,
			el = this.helper, props = {},
			smp = this.originalMousePosition,
			a = this.axis,
			prevTop = this.position.top,
			prevLeft = this.position.left,
			prevWidth = this.size.width,
			prevHeight = this.size.height,
			dx = (event.pageX-smp.left)||0,
			dy = (event.pageY-smp.top)||0,
			trigger = this._change[a];

		if (!trigger) {
			return false;
		}

		// Calculate the attrs that will be change
		data = trigger.apply(this, [event, dx, dy]);

		// Put this in the mouseDrag handler since the user can start pressing shift while resizing
		this._updateVirtualBoundaries(event.shiftKey);
		if (this._aspectRatio || event.shiftKey) {
			data = this._updateRatio(data, event);
		}

		data = this._respectSize(data, event);

		this._updateCache(data);

		// plugins callbacks need to be called first
		this._propagate("resize", event);

		if (this.position.top !== prevTop) {
			props.top = this.position.top + "px";
		}
		if (this.position.left !== prevLeft) {
			props.left = this.position.left + "px";
		}
		if (this.size.width !== prevWidth) {
			props.width = this.size.width + "px";
		}
		if (this.size.height !== prevHeight) {
			props.height = this.size.height + "px";
		}
		el.css(props);

		if (!this._helper && this._proportionallyResizeElements.length) {
			this._proportionallyResize();
		}

		// Call the user callback if the element was resized
		if ( ! $.isEmptyObject(props) ) {
			this._trigger("resize", event, this.ui());
		}

		return false;
	},

	_mouseStop: function(event) {

		this.resizing = false;
		var pr, ista, soffseth, soffsetw, s, left, top,
			o = this.options, that = this;

		if(this._helper) {

			pr = this._proportionallyResizeElements;
			ista = pr.length && (/textarea/i).test(pr[0].nodeName);
			soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;
			soffsetw = ista ? 0 : that.sizeDiff.width;

			s = { width: (that.helper.width()  - soffsetw), height: (that.helper.height() - soffseth) };
			left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;
			top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;

			if (!o.animate) {
				this.element.css($.extend(s, { top: top, left: left }));
			}

			that.helper.height(that.size.height);
			that.helper.width(that.size.width);

			if (this._helper && !o.animate) {
				this._proportionallyResize();
			}
		}

		$("body").css("cursor", "auto");

		this.element.removeClass("ui-resizable-resizing");

		this._propagate("stop", event);

		if (this._helper) {
			this.helper.remove();
		}

		return false;

	},

	_updateVirtualBoundaries: function(forceAspectRatio) {
		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
			o = this.options;

		b = {
			minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
			maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
			minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
			maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
		};

		if(this._aspectRatio || forceAspectRatio) {
			// We want to create an enclosing box whose aspect ration is the requested one
			// First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
			pMinWidth = b.minHeight * this.aspectRatio;
			pMinHeight = b.minWidth / this.aspectRatio;
			pMaxWidth = b.maxHeight * this.aspectRatio;
			pMaxHeight = b.maxWidth / this.aspectRatio;

			if(pMinWidth > b.minWidth) {
				b.minWidth = pMinWidth;
			}
			if(pMinHeight > b.minHeight) {
				b.minHeight = pMinHeight;
			}
			if(pMaxWidth < b.maxWidth) {
				b.maxWidth = pMaxWidth;
			}
			if(pMaxHeight < b.maxHeight) {
				b.maxHeight = pMaxHeight;
			}
		}
		this._vBoundaries = b;
	},

	_updateCache: function(data) {
		this.offset = this.helper.offset();
		if (isNumber(data.left)) {
			this.position.left = data.left;
		}
		if (isNumber(data.top)) {
			this.position.top = data.top;
		}
		if (isNumber(data.height)) {
			this.size.height = data.height;
		}
		if (isNumber(data.width)) {
			this.size.width = data.width;
		}
	},

	_updateRatio: function( data ) {

		var cpos = this.position,
			csize = this.size,
			a = this.axis;

		if (isNumber(data.height)) {
			data.width = (data.height * this.aspectRatio);
		} else if (isNumber(data.width)) {
			data.height = (data.width / this.aspectRatio);
		}

		if (a === "sw") {
			data.left = cpos.left + (csize.width - data.width);
			data.top = null;
		}
		if (a === "nw") {
			data.top = cpos.top + (csize.height - data.height);
			data.left = cpos.left + (csize.width - data.width);
		}

		return data;
	},

	_respectSize: function( data ) {

		var o = this._vBoundaries,
			a = this.axis,
			ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
			isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
			dw = this.originalPosition.left + this.originalSize.width,
			dh = this.position.top + this.size.height,
			cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
		if (isminw) {
			data.width = o.minWidth;
		}
		if (isminh) {
			data.height = o.minHeight;
		}
		if (ismaxw) {
			data.width = o.maxWidth;
		}
		if (ismaxh) {
			data.height = o.maxHeight;
		}

		if (isminw && cw) {
			data.left = dw - o.minWidth;
		}
		if (ismaxw && cw) {
			data.left = dw - o.maxWidth;
		}
		if (isminh && ch) {
			data.top = dh - o.minHeight;
		}
		if (ismaxh && ch) {
			data.top = dh - o.maxHeight;
		}

		// fixing jump error on top/left - bug #2330
		if (!data.width && !data.height && !data.left && data.top) {
			data.top = null;
		} else if (!data.width && !data.height && !data.top && data.left) {
			data.left = null;
		}

		return data;
	},

	_proportionallyResize: function() {

		if (!this._proportionallyResizeElements.length) {
			return;
		}

		var i, j, borders, paddings, prel,
			element = this.helper || this.element;

		for ( i=0; i < this._proportionallyResizeElements.length; i++) {

			prel = this._proportionallyResizeElements[i];

			if (!this.borderDif) {
				this.borderDif = [];
				borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];
				paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];

				for ( j = 0; j < borders.length; j++ ) {
					this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );
				}
			}

			prel.css({
				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
			});

		}

	},

	_renderProxy: function() {

		var el = this.element, o = this.options;
		this.elementOffset = el.offset();

		if(this._helper) {

			this.helper = this.helper || $("<div style='overflow:hidden;'></div>");

			this.helper.addClass(this._helper).css({
				width: this.element.outerWidth() - 1,
				height: this.element.outerHeight() - 1,
				position: "absolute",
				left: this.elementOffset.left +"px",
				top: this.elementOffset.top +"px",
				zIndex: ++o.zIndex //TODO: Don't modify option
			});

			this.helper
				.appendTo("body")
				.disableSelection();

		} else {
			this.helper = this.element;
		}

	},

	_change: {
		e: function(event, dx) {
			return { width: this.originalSize.width + dx };
		},
		w: function(event, dx) {
			var cs = this.originalSize, sp = this.originalPosition;
			return { left: sp.left + dx, width: cs.width - dx };
		},
		n: function(event, dx, dy) {
			var cs = this.originalSize, sp = this.originalPosition;
			return { top: sp.top + dy, height: cs.height - dy };
		},
		s: function(event, dx, dy) {
			return { height: this.originalSize.height + dy };
		},
		se: function(event, dx, dy) {
			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
		},
		sw: function(event, dx, dy) {
			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
		},
		ne: function(event, dx, dy) {
			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
		},
		nw: function(event, dx, dy) {
			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
		}
	},

	_propagate: function(n, event) {
		$.ui.plugin.call(this, n, [event, this.ui()]);
		(n !== "resize" && this._trigger(n, event, 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
		};
	}

});

/*
 * Resizable Extensions
 */

$.ui.plugin.add("resizable", "animate", {

	stop: function( event ) {
		var that = $(this).data("ui-resizable"),
			o = that.options,
			pr = that._proportionallyResizeElements,
			ista = pr.length && (/textarea/i).test(pr[0].nodeName),
			soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,
			soffsetw = ista ? 0 : that.sizeDiff.width,
			style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
			left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,
			top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;

		that.element.animate(
			$.extend(style, top && left ? { top: top, left: left } : {}), {
				duration: o.animateDuration,
				easing: o.animateEasing,
				step: function() {

					var data = {
						width: parseInt(that.element.css("width"), 10),
						height: parseInt(that.element.css("height"), 10),
						top: parseInt(that.element.css("top"), 10),
						left: parseInt(that.element.css("left"), 10)
					};

					if (pr && pr.length) {
						$(pr[0]).css({ width: data.width, height: data.height });
					}

					// propagating resize, and updating values for each animation step
					that._updateCache(data);
					that._propagate("resize", event);

				}
			}
		);
	}

});

$.ui.plugin.add("resizable", "containment", {

	start: function() {
		var element, p, co, ch, cw, width, height,
			that = $(this).data("ui-resizable"),
			o = that.options,
			el = that.element,
			oc = o.containment,
			ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;

		if (!ce) {
			return;
		}

		that.containerElement = $(ce);

		if (/document/.test(oc) || oc === document) {
			that.containerOffset = { left: 0, top: 0 };
			that.containerPosition = { left: 0, top: 0 };

			that.parentData = {
				element: $(document), left: 0, top: 0,
				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
			};
		}

		// i'm a node, so compute top, left, right, bottom
		else {
			element = $(ce);
			p = [];
			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });

			that.containerOffset = element.offset();
			that.containerPosition = element.position();
			that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };

			co = that.containerOffset;
			ch = that.containerSize.height;
			cw = that.containerSize.width;
			width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw );
			height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);

			that.parentData = {
				element: ce, left: co.left, top: co.top, width: width, height: height
			};
		}
	},

	resize: function( event ) {
		var woset, hoset, isParent, isOffsetRelative,
			that = $(this).data("ui-resizable"),
			o = that.options,
			co = that.containerOffset, cp = that.position,
			pRatio = that._aspectRatio || event.shiftKey,
			cop = { top:0, left:0 }, ce = that.containerElement;

		if (ce[0] !== document && (/static/).test(ce.css("position"))) {
			cop = co;
		}

		if (cp.left < (that._helper ? co.left : 0)) {
			that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
			if (pRatio) {
				that.size.height = that.size.width / that.aspectRatio;
			}
			that.position.left = o.helper ? co.left : 0;
		}

		if (cp.top < (that._helper ? co.top : 0)) {
			that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
			if (pRatio) {
				that.size.width = that.size.height * that.aspectRatio;
			}
			that.position.top = that._helper ? co.top : 0;
		}

		that.offset.left = that.parentData.left+that.position.left;
		that.offset.top = that.parentData.top+that.position.top;

		woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width );
		hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );

		isParent = that.containerElement.get(0) === that.element.parent().get(0);
		isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));

		if(isParent && isOffsetRelative) {
			woset -= that.parentData.left;
		}

		if (woset + that.size.width >= that.parentData.width) {
			that.size.width = that.parentData.width - woset;
			if (pRatio) {
				that.size.height = that.size.width / that.aspectRatio;
			}
		}

		if (hoset + that.size.height >= that.parentData.height) {
			that.size.height = that.parentData.height - hoset;
			if (pRatio) {
				that.size.width = that.size.height * that.aspectRatio;
			}
		}
	},

	stop: function(){
		var that = $(this).data("ui-resizable"),
			o = that.options,
			co = that.containerOffset,
			cop = that.containerPosition,
			ce = that.containerElement,
			helper = $(that.helper),
			ho = helper.offset(),
			w = helper.outerWidth() - that.sizeDiff.width,
			h = helper.outerHeight() - that.sizeDiff.height;

		if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) {
			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
		}

		if (that._helper && !o.animate && (/static/).test(ce.css("position"))) {
			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
		}

	}
});

$.ui.plugin.add("resizable", "alsoResize", {

	start: function () {
		var that = $(this).data("ui-resizable"),
			o = that.options,
			_store = function (exp) {
				$(exp).each(function() {
					var el = $(this);
					el.data("ui-resizable-alsoresize", {
						width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
						left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
					});
				});
			};

		if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
		}else{
			_store(o.alsoResize);
		}
	},

	resize: function (event, ui) {
		var that = $(this).data("ui-resizable"),
			o = that.options,
			os = that.originalSize,
			op = that.originalPosition,
			delta = {
				height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
				top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
			},

			_alsoResize = function (exp, c) {
				$(exp).each(function() {
					var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
						css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];

					$.each(css, function (i, prop) {
						var sum = (start[prop]||0) + (delta[prop]||0);
						if (sum && sum >= 0) {
							style[prop] = sum || null;
						}
					});

					el.css(style);
				});
			};

		if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
		}else{
			_alsoResize(o.alsoResize);
		}
	},

	stop: function () {
		$(this).removeData("resizable-alsoresize");
	}
});

$.ui.plugin.add("resizable", "ghost", {

	start: function() {

		var that = $(this).data("ui-resizable"), o = that.options, cs = that.size;

		that.ghost = that.originalElement.clone();
		that.ghost
			.css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
			.addClass("ui-resizable-ghost")
			.addClass(typeof o.ghost === "string" ? o.ghost : "");

		that.ghost.appendTo(that.helper);

	},

	resize: function(){
		var that = $(this).data("ui-resizable");
		if (that.ghost) {
			that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });
		}
	},

	stop: function() {
		var that = $(this).data("ui-resizable");
		if (that.ghost && that.helper) {
			that.helper.get(0).removeChild(that.ghost.get(0));
		}
	}

});

$.ui.plugin.add("resizable", "grid", {

	resize: function() {
		var that = $(this).data("ui-resizable"),
			o = that.options,
			cs = that.size,
			os = that.originalSize,
			op = that.originalPosition,
			a = that.axis,
			grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
			gridX = (grid[0]||1),
			gridY = (grid[1]||1),
			ox = Math.round((cs.width - os.width) / gridX) * gridX,
			oy = Math.round((cs.height - os.height) / gridY) * gridY,
			newWidth = os.width + ox,
			newHeight = os.height + oy,
			isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
			isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
			isMinWidth = o.minWidth && (o.minWidth > newWidth),
			isMinHeight = o.minHeight && (o.minHeight > newHeight);

		o.grid = grid;

		if (isMinWidth) {
			newWidth = newWidth + gridX;
		}
		if (isMinHeight) {
			newHeight = newHeight + gridY;
		}
		if (isMaxWidth) {
			newWidth = newWidth - gridX;
		}
		if (isMaxHeight) {
			newHeight = newHeight - gridY;
		}

		if (/^(se|s|e)$/.test(a)) {
			that.size.width = newWidth;
			that.size.height = newHeight;
		} else if (/^(ne)$/.test(a)) {
			that.size.width = newWidth;
			that.size.height = newHeight;
			that.position.top = op.top - oy;
		} else if (/^(sw)$/.test(a)) {
			that.size.width = newWidth;
			that.size.height = newHeight;
			that.position.left = op.left - ox;
		} else {
			that.size.width = newWidth;
			that.size.height = newHeight;
			that.position.top = op.top - oy;
			that.position.left = op.left - ox;
		}
	}

});

})(jQuery);

// file: 000-1-070-jquery.ui.selectable.js
/*!
 * jQuery UI Selectable 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/selectable/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

$.widget("ui.selectable", $.ui.mouse, {
	version: "1.10.0",
	options: {
		appendTo: "body",
		autoRefresh: true,
		distance: 0,
		filter: "*",
		tolerance: "touch",

		// callbacks
		selected: null,
		selecting: null,
		start: null,
		stop: null,
		unselected: null,
		unselecting: null
	},
	_create: function() {
		var selectees,
			that = this;

		this.element.addClass("ui-selectable");

		this.dragged = false;

		// cache selectee children based on filter
		this.refresh = function() {
			selectees = $(that.options.filter, that.element[0]);
			selectees.addClass("ui-selectee");
			selectees.each(function() {
				var $this = $(this),
					pos = $this.offset();
				$.data(this, "selectable-item", {
					element: this,
					$element: $this,
					left: pos.left,
					top: pos.top,
					right: pos.left + $this.outerWidth(),
					bottom: pos.top + $this.outerHeight(),
					startselected: false,
					selected: $this.hasClass("ui-selected"),
					selecting: $this.hasClass("ui-selecting"),
					unselecting: $this.hasClass("ui-unselecting")
				});
			});
		};
		this.refresh();

		this.selectees = selectees.addClass("ui-selectee");

		this._mouseInit();

		this.helper = $("<div class='ui-selectable-helper'></div>");
	},

	_destroy: function() {
		this.selectees
			.removeClass("ui-selectee")
			.removeData("selectable-item");
		this.element
			.removeClass("ui-selectable ui-selectable-disabled");
		this._mouseDestroy();
	},

	_mouseStart: function(event) {
		var that = this,
			options = this.options;

		this.opos = [event.pageX, event.pageY];

		if (this.options.disabled) {
			return;
		}

		this.selectees = $(options.filter, this.element[0]);

		this._trigger("start", event);

		$(options.appendTo).append(this.helper);
		// position helper (lasso)
		this.helper.css({
			"left": event.pageX,
			"top": event.pageY,
			"width": 0,
			"height": 0
		});

		if (options.autoRefresh) {
			this.refresh();
		}

		this.selectees.filter(".ui-selected").each(function() {
			var selectee = $.data(this, "selectable-item");
			selectee.startselected = true;
			if (!event.metaKey && !event.ctrlKey) {
				selectee.$element.removeClass("ui-selected");
				selectee.selected = false;
				selectee.$element.addClass("ui-unselecting");
				selectee.unselecting = true;
				// selectable UNSELECTING callback
				that._trigger("unselecting", event, {
					unselecting: selectee.element
				});
			}
		});

		$(event.target).parents().addBack().each(function() {
			var doSelect,
				selectee = $.data(this, "selectable-item");
			if (selectee) {
				doSelect = (!event.metaKey && !event.ctrlKey) || !selectee.$element.hasClass("ui-selected");
				selectee.$element
					.removeClass(doSelect ? "ui-unselecting" : "ui-selected")
					.addClass(doSelect ? "ui-selecting" : "ui-unselecting");
				selectee.unselecting = !doSelect;
				selectee.selecting = doSelect;
				selectee.selected = doSelect;
				// selectable (UN)SELECTING callback
				if (doSelect) {
					that._trigger("selecting", event, {
						selecting: selectee.element
					});
				} else {
					that._trigger("unselecting", event, {
						unselecting: selectee.element
					});
				}
				return false;
			}
		});

	},

	_mouseDrag: function(event) {

		this.dragged = true;

		if (this.options.disabled) {
			return;
		}

		var tmp,
			that = this,
			options = this.options,
			x1 = this.opos[0],
			y1 = this.opos[1],
			x2 = event.pageX,
			y2 = event.pageY;

		if (x1 > x2) { tmp = x2; x2 = x1; x1 = tmp; }
		if (y1 > y2) { tmp = y2; y2 = y1; y1 = tmp; }
		this.helper.css({left: x1, top: y1, width: x2-x1, height: y2-y1});

		this.selectees.each(function() {
			var selectee = $.data(this, "selectable-item"),
				hit = false;

			//prevent helper from being selected if appendTo: selectable
			if (!selectee || selectee.element === that.element[0]) {
				return;
			}

			if (options.tolerance === "touch") {
				hit = ( !(selectee.left > x2 || selectee.right < x1 || selectee.top > y2 || selectee.bottom < y1) );
			} else if (options.tolerance === "fit") {
				hit = (selectee.left > x1 && selectee.right < x2 && selectee.top > y1 && selectee.bottom < y2);
			}

			if (hit) {
				// SELECT
				if (selectee.selected) {
					selectee.$element.removeClass("ui-selected");
					selectee.selected = false;
				}
				if (selectee.unselecting) {
					selectee.$element.removeClass("ui-unselecting");
					selectee.unselecting = false;
				}
				if (!selectee.selecting) {
					selectee.$element.addClass("ui-selecting");
					selectee.selecting = true;
					// selectable SELECTING callback
					that._trigger("selecting", event, {
						selecting: selectee.element
					});
				}
			} else {
				// UNSELECT
				if (selectee.selecting) {
					if ((event.metaKey || event.ctrlKey) && selectee.startselected) {
						selectee.$element.removeClass("ui-selecting");
						selectee.selecting = false;
						selectee.$element.addClass("ui-selected");
						selectee.selected = true;
					} else {
						selectee.$element.removeClass("ui-selecting");
						selectee.selecting = false;
						if (selectee.startselected) {
							selectee.$element.addClass("ui-unselecting");
							selectee.unselecting = true;
						}
						// selectable UNSELECTING callback
						that._trigger("unselecting", event, {
							unselecting: selectee.element
						});
					}
				}
				if (selectee.selected) {
					if (!event.metaKey && !event.ctrlKey && !selectee.startselected) {
						selectee.$element.removeClass("ui-selected");
						selectee.selected = false;

						selectee.$element.addClass("ui-unselecting");
						selectee.unselecting = true;
						// selectable UNSELECTING callback
						that._trigger("unselecting", event, {
							unselecting: selectee.element
						});
					}
				}
			}
		});

		return false;
	},

	_mouseStop: function(event) {
		var that = this;

		this.dragged = false;

		$(".ui-unselecting", this.element[0]).each(function() {
			var selectee = $.data(this, "selectable-item");
			selectee.$element.removeClass("ui-unselecting");
			selectee.unselecting = false;
			selectee.startselected = false;
			that._trigger("unselected", event, {
				unselected: selectee.element
			});
		});
		$(".ui-selecting", this.element[0]).each(function() {
			var selectee = $.data(this, "selectable-item");
			selectee.$element.removeClass("ui-selecting").addClass("ui-selected");
			selectee.selecting = false;
			selectee.selected = true;
			selectee.startselected = true;
			that._trigger("selected", event, {
				selected: selectee.element
			});
		});
		this._trigger("stop", event);

		this.helper.remove();

		return false;
	}

});

})(jQuery);

// file: 000-1-080-jquery.ui.sortable.js
/*!
 * jQuery UI Sortable 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/sortable/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

/*jshint loopfunc: true */

function isOverAxis( x, reference, size ) {
	return ( x > reference ) && ( x < ( reference + size ) );
}

$.widget("ui.sortable", $.ui.mouse, {
	version: "1.10.0",
	widgetEventPrefix: "sort",
	ready: false,
	options: {
		appendTo: "parent",
		axis: false,
		connectWith: false,
		containment: false,
		cursor: "auto",
		cursorAt: false,
		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,

		// callbacks
		activate: null,
		beforeStop: null,
		change: null,
		deactivate: null,
		out: null,
		over: null,
		receive: null,
		remove: null,
		sort: null,
		start: null,
		stop: null,
		update: null
	},
	_create: function() {

		var o = this.options;
		this.containerCache = {};
		this.element.addClass("ui-sortable");

		//Get the items
		this.refresh();

		//Let's determine if the items are being displayed horizontally
		this.floating = this.items.length ? o.axis === "x" || (/left|right/).test(this.items[0].item.css("float")) || (/inline|table-cell/).test(this.items[0].item.css("display")) : false;

		//Let's determine the parent's offset
		this.offset = this.element.offset();

		//Initialize mouse events for interaction
		this._mouseInit();

		//We're ready to go
		this.ready = true;

	},

	_destroy: function() {
		this.element
			.removeClass("ui-sortable ui-sortable-disabled");
		this._mouseDestroy();

		for ( var i = this.items.length - 1; i >= 0; i-- ) {
			this.items[i].item.removeData(this.widgetName + "-item");
		}

		return this;
	},

	_setOption: function(key, value){
		if ( key === "disabled" ) {
			this.options[ key ] = value;

			this.widget().toggleClass( "ui-sortable-disabled", !!value );
		} else {
			// Don't call widget base _setOption for disable as it adds ui-state-disabled class
			$.Widget.prototype._setOption.apply(this, arguments);
		}
	},

	_mouseCapture: function(event, overrideHandle) {
		var currentItem = null,
			validHandle = false,
			that = this;

		if (this.reverting) {
			return false;
		}

		if(this.options.disabled || this.options.type === "static") {
			return false;
		}

		//We have to refresh the items data once first
		this._refreshItems(event);

		//Find out if the clicked node (or one of its parents) is a actual item in this.items
		$(event.target).parents().each(function() {
			if($.data(this, that.widgetName + "-item") === that) {
				currentItem = $(this);
				return false;
			}
		});
		if($.data(event.target, that.widgetName + "-item") === that) {
			currentItem = $(event.target);
		}

		if(!currentItem) {
			return false;
		}
		if(this.options.handle && !overrideHandle) {
			$(this.options.handle, currentItem).find("*").addBack().each(function() {
				if(this === event.target) {
					validHandle = true;
				}
			});
			if(!validHandle) {
				return false;
			}
		}

		this.currentItem = currentItem;
		this._removeCurrentsFromItems();
		return true;

	},

	_mouseStart: function(event, overrideHandle, noActivation) {

		var i,
			o = this.options;

		this.currentContainer = this;

		//We only need to call refreshPositions, because the refreshItems call has been moved to mouseCapture
		this.refreshPositions();

		//Create and append the visible helper
		this.helper = this._createHelper(event);

		//Cache the helper size
		this._cacheHelperProportions();

		/*
		 * - Position generation -
		 * This block generates everything position related - it's the core of draggables.
		 */

		//Cache the margins of the original element
		this._cacheMargins();

		//Get the next scrolling parent
		this.scrollParent = this.helper.scrollParent();

		//The element's absolute position on the page minus margins
		this.offset = this.currentItem.offset();
		this.offset = {
			top: this.offset.top - this.margins.top,
			left: this.offset.left - this.margins.left
		};

		$.extend(this.offset, {
			click: { //Where the click happened, relative to the element
				left: event.pageX - this.offset.left,
				top: event.pageY - this.offset.top
			},
			parent: this._getParentOffset(),
			relative: this._getRelativeOffset() //This is a relative to absolute position minus the actual position calculation - only used for relative positioned helper
		});

		// Only after we got the offset, we can change the helper's position to absolute
		// TODO: Still need to figure out a way to make relative sorting possible
		this.helper.css("position", "absolute");
		this.cssPosition = this.helper.css("position");

		//Generate the original position
		this.originalPosition = this._generatePosition(event);
		this.originalPageX = event.pageX;
		this.originalPageY = event.pageY;

		//Adjust the mouse offset relative to the helper if "cursorAt" is supplied
		(o.cursorAt && this._adjustOffsetFromHelper(o.cursorAt));

		//Cache the former DOM position
		this.domPosition = { prev: this.currentItem.prev()[0], parent: this.currentItem.parent()[0] };

		//If the helper is not the original, hide the original so it's not playing any role during the drag, won't cause anything bad this way
		if(this.helper[0] !== this.currentItem[0]) {
			this.currentItem.hide();
		}

		//Create the placeholder
		this._createPlaceholder();

		//Set a containment if given in the options
		if(o.containment) {
			this._setContainment();
		}

		if(o.cursor) { // cursor option
			if ($("body").css("cursor")) {
				this._storedCursor = $("body").css("cursor");
			}
			$("body").css("cursor", o.cursor);
		}

		if(o.opacity) { // opacity option
			if (this.helper.css("opacity")) {
				this._storedOpacity = this.helper.css("opacity");
			}
			this.helper.css("opacity", o.opacity);
		}

		if(o.zIndex) { // zIndex option
			if (this.helper.css("zIndex")) {
				this._storedZIndex = this.helper.css("zIndex");
			}
			this.helper.css("zIndex", o.zIndex);
		}

		//Prepare scrolling
		if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {
			this.overflowOffset = this.scrollParent.offset();
		}

		//Call callbacks
		this._trigger("start", event, this._uiHash());

		//Recache the helper size
		if(!this._preserveHelperProportions) {
			this._cacheHelperProportions();
		}


		//Post "activate" events to possible containers
		if( !noActivation ) {
			for ( i = this.containers.length - 1; i >= 0; i-- ) {
				this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
			}
		}

		//Prepare possible droppables
		if($.ui.ddmanager) {
			$.ui.ddmanager.current = this;
		}

		if ($.ui.ddmanager && !o.dropBehaviour) {
			$.ui.ddmanager.prepareOffsets(this, event);
		}

		this.dragging = true;

		this.helper.addClass("ui-sortable-helper");
		this._mouseDrag(event); //Execute the drag once - this causes the helper not to be visible before getting its correct position
		return true;

	},

	_mouseDrag: function(event) {
		var i, item, itemElement, intersection,
			o = this.options,
			scrolled = false;

		//Compute the helpers position
		this.position = this._generatePosition(event);
		this.positionAbs = this._convertPositionTo("absolute");

		if (!this.lastPositionAbs) {
			this.lastPositionAbs = this.positionAbs;
		}

		//Do scrolling
		if(this.options.scroll) {
			if(this.scrollParent[0] !== document && this.scrollParent[0].tagName !== "HTML") {

				if((this.overflowOffset.top + this.scrollParent[0].offsetHeight) - event.pageY < o.scrollSensitivity) {
					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop + o.scrollSpeed;
				} else if(event.pageY - this.overflowOffset.top < o.scrollSensitivity) {
					this.scrollParent[0].scrollTop = scrolled = this.scrollParent[0].scrollTop - o.scrollSpeed;
				}

				if((this.overflowOffset.left + this.scrollParent[0].offsetWidth) - event.pageX < o.scrollSensitivity) {
					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft + o.scrollSpeed;
				} else if(event.pageX - this.overflowOffset.left < o.scrollSensitivity) {
					this.scrollParent[0].scrollLeft = scrolled = this.scrollParent[0].scrollLeft - o.scrollSpeed;
				}

			} else {

				if(event.pageY - $(document).scrollTop() < o.scrollSensitivity) {
					scrolled = $(document).scrollTop($(document).scrollTop() - o.scrollSpeed);
				} else if($(window).height() - (event.pageY - $(document).scrollTop()) < o.scrollSensitivity) {
					scrolled = $(document).scrollTop($(document).scrollTop() + o.scrollSpeed);
				}

				if(event.pageX - $(document).scrollLeft() < o.scrollSensitivity) {
					scrolled = $(document).scrollLeft($(document).scrollLeft() - o.scrollSpeed);
				} else if($(window).width() - (event.pageX - $(document).scrollLeft()) < o.scrollSensitivity) {
					scrolled = $(document).scrollLeft($(document).scrollLeft() + o.scrollSpeed);
				}

			}

			if(scrolled !== false && $.ui.ddmanager && !o.dropBehaviour) {
				$.ui.ddmanager.prepareOffsets(this, event);
			}
		}

		//Regenerate the absolute position used for position checks
		this.positionAbs = this._convertPositionTo("absolute");

		//Set the helper 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";
		}

		//Rearrange
		for (i = this.items.length - 1; i >= 0; i--) {

			//Cache variables and intersection, continue if no intersection
			item = this.items[i];
			itemElement = item.item[0];
			intersection = this._intersectsWithPointer(item);
			if (!intersection) {
				continue;
			}

			// Only put the placeholder inside the current Container, skip all
			// items form other containers. This works because when moving
			// an item from one container to another the
			// currentContainer is switched before the placeholder is moved.
			//
			// Without this moving items in "sub-sortables" can cause the placeholder to jitter
			// beetween the outer and inner container.
			if (item.instance !== this.currentContainer) {
				continue;
			}

			// cannot intersect with itself
			// no useless actions that have been done before
			// no action if the item moved is the parent of the item checked
			if (itemElement !== this.currentItem[0] &&
				this.placeholder[intersection === 1 ? "next" : "prev"]()[0] !== itemElement &&
				!$.contains(this.placeholder[0], itemElement) &&
				(this.options.type === "semi-dynamic" ? !$.contains(this.element[0], itemElement) : true)
			) {

				this.direction = intersection === 1 ? "down" : "up";

				if (this.options.tolerance === "pointer" || this._intersectsWithSides(item)) {
					this._rearrange(event, item);
				} else {
					break;
				}

				this._trigger("change", event, this._uiHash());
				break;
			}
		}

		//Post events to containers
		this._contactContainers(event);

		//Interconnect with droppables
		if($.ui.ddmanager) {
			$.ui.ddmanager.drag(this, event);
		}

		//Call callbacks
		this._trigger("sort", event, this._uiHash());

		this.lastPositionAbs = this.positionAbs;
		return false;

	},

	_mouseStop: function(event, noPropagation) {

		if(!event) {
			return;
		}

		//If we are using droppables, inform the manager about the drop
		if ($.ui.ddmanager && !this.options.dropBehaviour) {
			$.ui.ddmanager.drop(this, event);
		}

		if(this.options.revert) {
			var that = this,
				cur = this.placeholder.offset();

			this.reverting = true;

			$(this.helper).animate({
				left: cur.left - this.offset.parent.left - this.margins.left + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollLeft),
				top: cur.top - this.offset.parent.top - this.margins.top + (this.offsetParent[0] === document.body ? 0 : this.offsetParent[0].scrollTop)
			}, parseInt(this.options.revert, 10) || 500, function() {
				that._clear(event);
			});
		} else {
			this._clear(event, noPropagation);
		}

		return false;

	},

	cancel: function() {

		if(this.dragging) {

			this._mouseUp({ target: null });

			if(this.options.helper === "original") {
				this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
			} else {
				this.currentItem.show();
			}

			//Post deactivating events to containers
			for (var i = this.containers.length - 1; i >= 0; i--){
				this.containers[i]._trigger("deactivate", null, this._uiHash(this));
				if(this.containers[i].containerCache.over) {
					this.containers[i]._trigger("out", null, this._uiHash(this));
					this.containers[i].containerCache.over = 0;
				}
			}

		}

		if (this.placeholder) {
			//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
			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();
			}

			$.extend(this, {
				helper: null,
				dragging: false,
				reverting: false,
				_noFinalSort: null
			});

			if(this.domPosition.prev) {
				$(this.domPosition.prev).after(this.currentItem);
			} else {
				$(this.domPosition.parent).prepend(this.currentItem);
			}
		}

		return this;

	},

	serialize: function(o) {

		var items = this._getItemsAsjQuery(o && o.connected),
			str = [];
		o = o || {};

		$(items).each(function() {
			var res = ($(o.item || this).attr(o.attribute || "id") || "").match(o.expression || (/(.+)[\-=_](.+)/));
			if (res) {
				str.push((o.key || res[1]+"[]")+"="+(o.key && o.expression ? res[1] : res[2]));
			}
		});

		if(!str.length && o.key) {
			str.push(o.key + "=");
		}

		return str.join("&");

	},

	toArray: function(o) {

		var items = this._getItemsAsjQuery(o && o.connected),
			ret = [];

		o = o || {};

		items.each(function() { ret.push($(o.item || this).attr(o.attribute || "id") || ""); });
		return ret;

	},

	/* Be careful with the following core functions */
	_intersectsWith: function(item) {

		var x1 = this.positionAbs.left,
			x2 = x1 + this.helperProportions.width,
			y1 = this.positionAbs.top,
			y2 = y1 + this.helperProportions.height,
			l = item.left,
			r = l + item.width,
			t = item.top,
			b = t + item.height,
			dyClick = this.offset.click.top,
			dxClick = this.offset.click.left,
			isOverElement = (y1 + dyClick) > t && (y1 + dyClick) < b && (x1 + dxClick) > l && (x1 + dxClick) < r;

		if ( this.options.tolerance === "pointer" ||
			this.options.forcePointerForContainers ||
			(this.options.tolerance !== "pointer" && this.helperProportions[this.floating ? "width" : "height"] > item[this.floating ? "width" : "height"])
		) {
			return isOverElement;
		} else {

			return (l < x1 + (this.helperProportions.width / 2) && // Right Half
				x2 - (this.helperProportions.width / 2) < r && // Left Half
				t < y1 + (this.helperProportions.height / 2) && // Bottom Half
				y2 - (this.helperProportions.height / 2) < b ); // Top Half

		}
	},

	_intersectsWithPointer: function(item) {

		var isOverElementHeight = (this.options.axis === "x") || isOverAxis(this.positionAbs.top + this.offset.click.top, item.top, item.height),
			isOverElementWidth = (this.options.axis === "y") || isOverAxis(this.positionAbs.left + this.offset.click.left, item.left, item.width),
			isOverElement = isOverElementHeight && isOverElementWidth,
			verticalDirection = this._getDragVerticalDirection(),
			horizontalDirection = this._getDragHorizontalDirection();

		if (!isOverElement) {
			return false;
		}

		return this.floating ?
			( ((horizontalDirection && horizontalDirection === "right") || verticalDirection === "down") ? 2 : 1 )
			: ( verticalDirection && (verticalDirection === "down" ? 2 : 1) );

	},

	_intersectsWithSides: function(item) {

		var isOverBottomHalf = isOverAxis(this.positionAbs.top + this.offset.click.top, item.top + (item.height/2), item.height),
			isOverRightHalf = isOverAxis(this.positionAbs.left + this.offset.click.left, item.left + (item.width/2), item.width),
			verticalDirection = this._getDragVerticalDirection(),
			horizontalDirection = this._getDragHorizontalDirection();

		if (this.floating && horizontalDirection) {
			return ((horizontalDirection === "right" && isOverRightHalf) || (horizontalDirection === "left" && !isOverRightHalf));
		} else {
			return verticalDirection && ((verticalDirection === "down" && isOverBottomHalf) || (verticalDirection === "up" && !isOverBottomHalf));
		}

	},

	_getDragVerticalDirection: function() {
		var delta = this.positionAbs.top - this.lastPositionAbs.top;
		return delta !== 0 && (delta > 0 ? "down" : "up");
	},

	_getDragHorizontalDirection: function() {
		var delta = this.positionAbs.left - this.lastPositionAbs.left;
		return delta !== 0 && (delta > 0 ? "right" : "left");
	},

	refresh: function(event) {
		this._refreshItems(event);
		this.refreshPositions();
		return this;
	},

	_connectWith: function() {
		var options = this.options;
		return options.connectWith.constructor === String ? [options.connectWith] : options.connectWith;
	},

	_getItemsAsjQuery: function(connected) {

		var i, j, cur, inst,
			items = [],
			queries = [],
			connectWith = this._connectWith();

		if(connectWith && connected) {
			for (i = connectWith.length - 1; i >= 0; i--){
				cur = $(connectWith[i]);
				for ( j = cur.length - 1; j >= 0; j--){
					inst = $.data(cur[j], this.widgetFullName);
					if(inst && inst !== this && !inst.options.disabled) {
						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element) : $(inst.options.items, inst.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), inst]);
					}
				}
			}
		}

		queries.push([$.isFunction(this.options.items) ? this.options.items.call(this.element, null, { options: this.options, item: this.currentItem }) : $(this.options.items, this.element).not(".ui-sortable-helper").not(".ui-sortable-placeholder"), this]);

		for (i = queries.length - 1; i >= 0; i--){
			queries[i][0].each(function() {
				items.push(this);
			});
		}

		return $(items);

	},

	_removeCurrentsFromItems: function() {

		var list = this.currentItem.find(":data(" + this.widgetName + "-item)");

		this.items = $.grep(this.items, function (item) {
			for (var j=0; j < list.length; j++) {
				if(list[j] === item.item[0]) {
					return false;
				}
			}
			return true;
		});

	},

	_refreshItems: function(event) {

		this.items = [];
		this.containers = [this];

		var i, j, cur, inst, targetData, _queries, item, queriesLength,
			items = this.items,
			queries = [[$.isFunction(this.options.items) ? this.options.items.call(this.element[0], event, { item: this.currentItem }) : $(this.options.items, this.element), this]],
			connectWith = this._connectWith();

		if(connectWith && this.ready) { //Shouldn't be run the first time through due to massive slow-down
			for (i = connectWith.length - 1; i >= 0; i--){
				cur = $(connectWith[i]);
				for (j = cur.length - 1; j >= 0; j--){
					inst = $.data(cur[j], this.widgetFullName);
					if(inst && inst !== this && !inst.options.disabled) {
						queries.push([$.isFunction(inst.options.items) ? inst.options.items.call(inst.element[0], event, { item: this.currentItem }) : $(inst.options.items, inst.element), inst]);
						this.containers.push(inst);
					}
				}
			}
		}

		for (i = queries.length - 1; i >= 0; i--) {
			targetData = queries[i][1];
			_queries = queries[i][0];

			for (j=0, queriesLength = _queries.length; j < queriesLength; j++) {
				item = $(_queries[j]);

				item.data(this.widgetName + "-item", targetData); // Data for target checking (mouse manager)

				items.push({
					item: item,
					instance: targetData,
					width: 0, height: 0,
					left: 0, top: 0
				});
			}
		}

	},

	refreshPositions: function(fast) {

		//This has to be redone because due to the item being moved out/into the offsetParent, the offsetParent's position will change
		if(this.offsetParent && this.helper) {
			this.offset.parent = this._getParentOffset();
		}

		var i, item, t, p;

		for (i = this.items.length - 1; i >= 0; i--){
			item = this.items[i];

			//We ignore calculating positions of all connected containers when we're not over them
			if(item.instance !== this.currentContainer && this.currentContainer && item.item[0] !== this.currentItem[0]) {
				continue;
			}

			t = this.options.toleranceElement ? $(this.options.toleranceElement, item.item) : item.item;

			if (!fast) {
				item.width = t.outerWidth();
				item.height = t.outerHeight();
			}

			p = t.offset();
			item.left = p.left;
			item.top = p.top;
		}

		if(this.options.custom && this.options.custom.refreshContainers) {
			this.options.custom.refreshContainers.call(this);
		} else {
			for (i = this.containers.length - 1; i >= 0; i--){
				p = this.containers[i].element.offset();
				this.containers[i].containerCache.left = p.left;
				this.containers[i].containerCache.top = p.top;
				this.containers[i].containerCache.width	= this.containers[i].element.outerWidth();
				this.containers[i].containerCache.height = this.containers[i].element.outerHeight();
			}
		}

		return this;
	},

	_createPlaceholder: function(that) {
		that = that || this;
		var className,
			o = that.options;

		if(!o.placeholder || o.placeholder.constructor === String) {
			className = o.placeholder;
			o.placeholder = {
				element: function() {

					var el = $(document.createElement(that.currentItem[0].nodeName))
						.addClass(className || that.currentItem[0].className+" ui-sortable-placeholder")
						.removeClass("ui-sortable-helper")[0];

					if(!className) {
						el.style.visibility = "hidden";
					}

					return el;
				},
				update: function(container, p) {

					// 1. If a className is set as 'placeholder option, we don't force sizes - the class is responsible for that
					// 2. The option 'forcePlaceholderSize can be enabled to force it even if a class name is specified
					if(className && !o.forcePlaceholderSize) {
						return;
					}

					//If the element doesn't have a actual height by itself (without styles coming from a stylesheet), it receives the inline height from the dragged item
					if(!p.height()) { p.height(that.currentItem.innerHeight() - parseInt(that.currentItem.css("paddingTop")||0, 10) - parseInt(that.currentItem.css("paddingBottom")||0, 10)); }
					if(!p.width()) { p.width(that.currentItem.innerWidth() - parseInt(that.currentItem.css("paddingLeft")||0, 10) - parseInt(that.currentItem.css("paddingRight")||0, 10)); }
				}
			};
		}

		//Create the placeholder
		that.placeholder = $(o.placeholder.element.call(that.element, that.currentItem));

		//Append it after the actual current item
		that.currentItem.after(that.placeholder);

		//Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
		o.placeholder.update(that, that.placeholder);

	},

	_contactContainers: function(event) {
		var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, base, cur, nearBottom,
			innermostContainer = null,
			innermostIndex = null;

		// get innermost container that intersects with item
		for (i = this.containers.length - 1; i >= 0; i--) {

			// never consider a container that's located within the item itself
			if($.contains(this.currentItem[0], this.containers[i].element[0])) {
				continue;
			}

			if(this._intersectsWith(this.containers[i].containerCache)) {

				// if we've already found a container and it's more "inner" than this, then continue
				if(innermostContainer && $.contains(this.containers[i].element[0], innermostContainer.element[0])) {
					continue;
				}

				innermostContainer = this.containers[i];
				innermostIndex = i;

			} else {
				// container doesn't intersect. trigger "out" event if necessary
				if(this.containers[i].containerCache.over) {
					this.containers[i]._trigger("out", event, this._uiHash(this));
					this.containers[i].containerCache.over = 0;
				}
			}

		}

		// if no intersecting containers found, return
		if(!innermostContainer) {
			return;
		}

		// move the item into the container if it's not there already
		if(this.containers.length === 1) {
			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
			this.containers[innermostIndex].containerCache.over = 1;
		} else {

			//When entering a new container, we will find the item with the least distance and append our item near it
			dist = 10000;
			itemWithLeastDistance = null;
			posProperty = this.containers[innermostIndex].floating ? "left" : "top";
			sizeProperty = this.containers[innermostIndex].floating ? "width" : "height";
			base = this.positionAbs[posProperty] + this.offset.click[posProperty];
			for (j = this.items.length - 1; j >= 0; j--) {
				if(!$.contains(this.containers[innermostIndex].element[0], this.items[j].item[0])) {
					continue;
				}
				if(this.items[j].item[0] === this.currentItem[0]) {
					continue;
				}
				cur = this.items[j].item.offset()[posProperty];
				nearBottom = false;
				if(Math.abs(cur - base) > Math.abs(cur + this.items[j][sizeProperty] - base)){
					nearBottom = true;
					cur += this.items[j][sizeProperty];
				}

				if(Math.abs(cur - base) < dist) {
					dist = Math.abs(cur - base); itemWithLeastDistance = this.items[j];
					this.direction = nearBottom ? "up": "down";
				}
			}

			//Check if dropOnEmpty is enabled
			if(!itemWithLeastDistance && !this.options.dropOnEmpty) {
				return;
			}

			this.currentContainer = this.containers[innermostIndex];
			itemWithLeastDistance ? this._rearrange(event, itemWithLeastDistance, null, true) : this._rearrange(event, null, this.containers[innermostIndex].element, true);
			this._trigger("change", event, this._uiHash());
			this.containers[innermostIndex]._trigger("change", event, this._uiHash(this));

			//Update the placeholder
			this.options.placeholder.update(this.currentContainer, this.placeholder);

			this.containers[innermostIndex]._trigger("over", event, this._uiHash(this));
			this.containers[innermostIndex].containerCache.over = 1;
		}


	},

	_createHelper: function(event) {

		var o = this.options,
			helper = $.isFunction(o.helper) ? $(o.helper.apply(this.element[0], [event, this.currentItem])) : (o.helper === "clone" ? this.currentItem.clone() : this.currentItem);

		//Add the helper to the DOM if that didn't happen already
		if(!helper.parents("body").length) {
			$(o.appendTo !== "parent" ? o.appendTo : this.currentItem[0].parentNode)[0].appendChild(helper[0]);
		}

		if(helper[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(!helper[0].style.width || o.forceHelperSize) {
			helper.width(this.currentItem.width());
		}
		if(!helper[0].style.height || o.forceHelperSize) {
			helper.height(this.currentItem.height());
		}

		return helper;

	},

	_adjustOffsetFromHelper: function(obj) {
		if (typeof obj === "string") {
			obj = obj.split(" ");
		}
		if ($.isArray(obj)) {
			obj = {left: +obj[0], top: +obj[1] || 0};
		}
		if ("left" in obj) {
			this.offset.click.left = obj.left + this.margins.left;
		}
		if ("right" in obj) {
			this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
		}
		if ("top" in obj) {
			this.offset.click.top = obj.top + this.margins.top;
		}
		if ("bottom" in obj) {
			this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
		}
	},

	_getParentOffset: function() {


		//Get the offsetParent and cache its position
		this.offsetParent = this.helper.offsetParent();
		var po = this.offsetParent.offset();

		// This is a special case where we need to modify a offset calculated on start, since the following happened:
		// 1. The position of the helper is absolute, so it's position is calculated based on the next positioned parent
		// 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't the document, which means that
		//    the scroll is included in the initial calculation of the offset of the parent, and never recalculated upon drag
		if(this.cssPosition === "absolute" && this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) {
			po.left += this.scrollParent.scrollLeft();
			po.top += this.scrollParent.scrollTop();
		}

		// This needs to be actually done for all browsers, since pageX/pageY includes this information
		// with an ugly IE fix
		if( this.offsetParent[0] === document.body || (this.offsetParent[0].tagName && this.offsetParent[0].tagName.toLowerCase() === "html" && $.ui.ie)) {
			po = { top: 0, left: 0 };
		}

		return {
			top: po.top + (parseInt(this.offsetParent.css("borderTopWidth"),10) || 0),
			left: po.left + (parseInt(this.offsetParent.css("borderLeftWidth"),10) || 0)
		};

	},

	_getRelativeOffset: function() {

		if(this.cssPosition === "relative") {
			var p = this.currentItem.position();
			return {
				top: p.top - (parseInt(this.helper.css("top"),10) || 0) + this.scrollParent.scrollTop(),
				left: p.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 ce, co, over,
			o = this.options;
		if(o.containment === "parent") {
			o.containment = this.helper[0].parentNode;
		}
		if(o.containment === "document" || o.containment === "window") {
			this.containment = [
				0 - this.offset.relative.left - this.offset.parent.left,
				0 - this.offset.relative.top - this.offset.parent.top,
				$(o.containment === "document" ? document : window).width() - this.helperProportions.width - this.margins.left,
				($(o.containment === "document" ? document : window).height() || document.body.parentNode.scrollHeight) - this.helperProportions.height - this.margins.top
			];
		}

		if(!(/^(document|window|parent)$/).test(o.containment)) {
			ce = $(o.containment)[0];
			co = $(o.containment).offset();
			over = ($(ce).css("overflow") !== "hidden");

			this.containment = [
				co.left + (parseInt($(ce).css("borderLeftWidth"),10) || 0) + (parseInt($(ce).css("paddingLeft"),10) || 0) - this.margins.left,
				co.top + (parseInt($(ce).css("borderTopWidth"),10) || 0) + (parseInt($(ce).css("paddingTop"),10) || 0) - this.margins.top,
				co.left+(over ? Math.max(ce.scrollWidth,ce.offsetWidth) : ce.offsetWidth) - (parseInt($(ce).css("borderLeftWidth"),10) || 0) - (parseInt($(ce).css("paddingRight"),10) || 0) - this.helperProportions.width - this.margins.left,
				co.top+(over ? Math.max(ce.scrollHeight,ce.offsetHeight) : ce.offsetHeight) - (parseInt($(ce).css("borderTopWidth"),10) || 0) - (parseInt($(ce).css("paddingBottom"),10) || 0) - this.helperProportions.height - this.margins.top
			];
		}

	},

	_convertPositionTo: function(d, pos) {

		if(!pos) {
			pos = this.position;
		}
		var mod = d === "absolute" ? 1 : -1,
			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent,
			scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);

		return {
			top: (
				pos.top	+																// The absolute mouse position
				this.offset.relative.top * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
				this.offset.parent.top * mod -											// The offsetParent's offset without borders (offset + border)
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod)
			),
			left: (
				pos.left +																// The absolute mouse position
				this.offset.relative.left * mod +										// Only for relative positioned nodes: Relative offset from element to offset parent
				this.offset.parent.left * mod	-										// The offsetParent's offset without borders (offset + border)
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ) * mod)
			)
		};

	},

	_generatePosition: function(event) {

		var top, left,
			o = this.options,
			pageX = event.pageX,
			pageY = event.pageY,
			scroll = this.cssPosition === "absolute" && !(this.scrollParent[0] !== document && $.contains(this.scrollParent[0], this.offsetParent[0])) ? this.offsetParent : this.scrollParent, scrollIsRootNode = (/(html|body)/i).test(scroll[0].tagName);

		// This is another very weird special case that only happens for relative elements:
		// 1. If the css position is relative
		// 2. and the scroll parent is the document or similar to the offset parent
		// we have to refresh the relative offset during the scroll so there are no jumps
		if(this.cssPosition === "relative" && !(this.scrollParent[0] !== document && this.scrollParent[0] !== this.offsetParent[0])) {
			this.offset.relative = this._getRelativeOffset();
		}

		/*
		 * - Position constraining -
		 * Constrain the position to a mix of grid, containment.
		 */

		if(this.originalPosition) { //If we are not dragging yet, we won't check for options

			if(this.containment) {
				if(event.pageX - this.offset.click.left < this.containment[0]) {
					pageX = this.containment[0] + this.offset.click.left;
				}
				if(event.pageY - this.offset.click.top < this.containment[1]) {
					pageY = this.containment[1] + this.offset.click.top;
				}
				if(event.pageX - this.offset.click.left > this.containment[2]) {
					pageX = this.containment[2] + this.offset.click.left;
				}
				if(event.pageY - this.offset.click.top > this.containment[3]) {
					pageY = this.containment[3] + this.offset.click.top;
				}
			}

			if(o.grid) {
				top = this.originalPageY + Math.round((pageY - this.originalPageY) / o.grid[1]) * o.grid[1];
				pageY = this.containment ? ( (top - this.offset.click.top >= this.containment[1] && top - this.offset.click.top <= this.containment[3]) ? top : ((top - this.offset.click.top >= this.containment[1]) ? top - o.grid[1] : top + o.grid[1])) : top;

				left = this.originalPageX + Math.round((pageX - this.originalPageX) / o.grid[0]) * o.grid[0];
				pageX = this.containment ? ( (left - this.offset.click.left >= this.containment[0] && left - this.offset.click.left <= this.containment[2]) ? left : ((left - this.offset.click.left >= this.containment[0]) ? left - o.grid[0] : left + o.grid[0])) : left;
			}

		}

		return {
			top: (
				pageY -																// The absolute mouse position
				this.offset.click.top -													// Click offset (relative to the element)
				this.offset.relative.top	-											// Only for relative positioned nodes: Relative offset from element to offset parent
				this.offset.parent.top +												// The offsetParent's offset without borders (offset + border)
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollTop() : ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ))
			),
			left: (
				pageX -																// The absolute mouse position
				this.offset.click.left -												// Click offset (relative to the element)
				this.offset.relative.left	-											// Only for relative positioned nodes: Relative offset from element to offset parent
				this.offset.parent.left +												// The offsetParent's offset without borders (offset + border)
				( ( this.cssPosition === "fixed" ? -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 : scroll.scrollLeft() ))
			)
		};

	},

	_rearrange: function(event, i, a, hardRefresh) {

		a ? a[0].appendChild(this.placeholder[0]) : i.item[0].parentNode.insertBefore(this.placeholder[0], (this.direction === "down" ? i.item[0] : i.item[0].nextSibling));

		//Various things done here to improve the performance:
		// 1. we create a setTimeout, that calls refreshPositions
		// 2. on the instance, we have a counter variable, that get's higher after every append
		// 3. on the local scope, we copy the counter variable, and check in the timeout, if it's still the same
		// 4. this lets only the last addition to the timeout stack through
		this.counter = this.counter ? ++this.counter : 1;
		var counter = this.counter;

		this._delay(function() {
			if(counter === this.counter) {
				this.refreshPositions(!hardRefresh); //Precompute after each DOM insertion, NOT on mousemove
			}
		});

	},

	_clear: function(event, noPropagation) {

		this.reverting = false;
		// We delay all events that have to be triggered to after the point where the placeholder has been removed and
		// everything else normalized again
		var i,
			delayedTriggers = [];

		// We first have to update the dom position of the actual currentItem
		// Note: don't do it if the current item is already removed (by a user), or it gets reappended (see #4088)
		if(!this._noFinalSort && this.currentItem.parent().length) {
			this.placeholder.before(this.currentItem);
		}
		this._noFinalSort = null;

		if(this.helper[0] === this.currentItem[0]) {
			for(i in this._storedCSS) {
				if(this._storedCSS[i] === "auto" || this._storedCSS[i] === "static") {
					this._storedCSS[i] = "";
				}
			}
			this.currentItem.css(this._storedCSS).removeClass("ui-sortable-helper");
		} else {
			this.currentItem.show();
		}

		if(this.fromOutside && !noPropagation) {
			delayedTriggers.push(function(event) { this._trigger("receive", event, 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]) && !noPropagation) {
			delayedTriggers.push(function(event) { this._trigger("update", event, this._uiHash()); }); //Trigger update callback if the DOM position has changed
		}

		// Check if the items Container has Changed and trigger appropriate
		// events.
		if (this !== this.currentContainer) {
			if(!noPropagation) {
				delayedTriggers.push(function(event) { this._trigger("remove", event, this._uiHash()); });
				delayedTriggers.push((function(c) { return function(event) { c._trigger("receive", event, this._uiHash(this)); };  }).call(this, this.currentContainer));
				delayedTriggers.push((function(c) { return function(event) { c._trigger("update", event, this._uiHash(this));  }; }).call(this, this.currentContainer));
			}
		}


		//Post events to containers
		for (i = this.containers.length - 1; i >= 0; i--){
			if(!noPropagation) {
				delayedTriggers.push((function(c) { return function(event) { c._trigger("deactivate", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
			}
			if(this.containers[i].containerCache.over) {
				delayedTriggers.push((function(c) { return function(event) { c._trigger("out", event, this._uiHash(this)); };  }).call(this, this.containers[i]));
				this.containers[i].containerCache.over = 0;
			}
		}

		//Do what was originally in plugins
		if(this._storedCursor) {
			$("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(!noPropagation) {
				this._trigger("beforeStop", event, this._uiHash());
				for (i=0; i < delayedTriggers.length; i++) {
					delayedTriggers[i].call(this, event);
				} //Trigger all delayed events
				this._trigger("stop", event, this._uiHash());
			}

			this.fromOutside = false;
			return false;
		}

		if(!noPropagation) {
			this._trigger("beforeStop", event, this._uiHash());
		}

		//$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately, it unbinds ALL events from the original node!
		this.placeholder[0].parentNode.removeChild(this.placeholder[0]);

		if(this.helper[0] !== this.currentItem[0]) {
			this.helper.remove();
		}
		this.helper = null;

		if(!noPropagation) {
			for (i=0; i < delayedTriggers.length; i++) {
				delayedTriggers[i].call(this, event);
			} //Trigger all delayed events
			this._trigger("stop", event, this._uiHash());
		}

		this.fromOutside = false;
		return true;

	},

	_trigger: function() {
		if ($.Widget.prototype._trigger.apply(this, arguments) === false) {
			this.cancel();
		}
	},

	_uiHash: function(_inst) {
		var inst = _inst || this;
		return {
			helper: inst.helper,
			placeholder: inst.placeholder || $([]),
			position: inst.position,
			originalPosition: inst.originalPosition,
			offset: inst.positionAbs,
			item: inst.currentItem,
			sender: _inst ? _inst.element : null
		};
	}

});

})(jQuery);

// file: 000-1-090-jquery.ui.effect.js
/*!
 * jQuery UI Effects 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/category/effects-core/
 */
;(jQuery.effects || (function($, undefined) {

var dataSpace = "ui-effects-";

$.effects = {
	effect: {}
};

/*!
 * jQuery Color Animations v2.1.2
 * https://github.com/jquery/jquery-color
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * Date: Wed Jan 16 08:47:09 2013 -0600
 */
(function( jQuery, undefined ) {

	var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",

	// plusequals test for += 100 -= 100
	rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
	// a set of RE's that can match strings and generate color tuples.
	stringParsers = [{
			re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
			parse: function( execResult ) {
				return [
					execResult[ 1 ],
					execResult[ 2 ],
					execResult[ 3 ],
					execResult[ 4 ]
				];
			}
		}, {
			re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
			parse: function( execResult ) {
				return [
					execResult[ 1 ] * 2.55,
					execResult[ 2 ] * 2.55,
					execResult[ 3 ] * 2.55,
					execResult[ 4 ]
				];
			}
		}, {
			// this regex ignores A-F because it's compared against an already lowercased string
			re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})/,
			parse: function( execResult ) {
				return [
					parseInt( execResult[ 1 ], 16 ),
					parseInt( execResult[ 2 ], 16 ),
					parseInt( execResult[ 3 ], 16 )
				];
			}
		}, {
			// this regex ignores A-F because it's compared against an already lowercased string
			re: /#([a-f0-9])([a-f0-9])([a-f0-9])/,
			parse: function( execResult ) {
				return [
					parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
					parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
					parseInt( execResult[ 3 ] + execResult[ 3 ], 16 )
				];
			}
		}, {
			re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
			space: "hsla",
			parse: function( execResult ) {
				return [
					execResult[ 1 ],
					execResult[ 2 ] / 100,
					execResult[ 3 ] / 100,
					execResult[ 4 ]
				];
			}
		}],

	// jQuery.Color( )
	color = jQuery.Color = function( color, green, blue, alpha ) {
		return new jQuery.Color.fn.parse( color, green, blue, alpha );
	},
	spaces = {
		rgba: {
			props: {
				red: {
					idx: 0,
					type: "byte"
				},
				green: {
					idx: 1,
					type: "byte"
				},
				blue: {
					idx: 2,
					type: "byte"
				}
			}
		},

		hsla: {
			props: {
				hue: {
					idx: 0,
					type: "degrees"
				},
				saturation: {
					idx: 1,
					type: "percent"
				},
				lightness: {
					idx: 2,
					type: "percent"
				}
			}
		}
	},
	propTypes = {
		"byte": {
			floor: true,
			max: 255
		},
		"percent": {
			max: 1
		},
		"degrees": {
			mod: 360,
			floor: true
		}
	},
	support = color.support = {},

	// element for support tests
	supportElem = jQuery( "<p>" )[ 0 ],

	// colors = jQuery.Color.names
	colors,

	// local aliases of functions called often
	each = jQuery.each;

// determine rgba support immediately
supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;

// define cache name and alpha properties
// for rgba and hsla spaces
each( spaces, function( spaceName, space ) {
	space.cache = "_" + spaceName;
	space.props.alpha = {
		idx: 3,
		type: "percent",
		def: 1
	};
});

function clamp( value, prop, allowEmpty ) {
	var type = propTypes[ prop.type ] || {};

	if ( value == null ) {
		return (allowEmpty || !prop.def) ? null : prop.def;
	}

	// ~~ is an short way of doing floor for positive numbers
	value = type.floor ? ~~value : parseFloat( value );

	// IE will pass in empty strings as value for alpha,
	// which will hit this case
	if ( isNaN( value ) ) {
		return prop.def;
	}

	if ( type.mod ) {
		// we add mod before modding to make sure that negatives values
		// get converted properly: -10 -> 350
		return (value + type.mod) % type.mod;
	}

	// for now all property types without mod have min and max
	return 0 > value ? 0 : type.max < value ? type.max : value;
}

function stringParse( string ) {
	var inst = color(),
		rgba = inst._rgba = [];

	string = string.toLowerCase();

	each( stringParsers, function( i, parser ) {
		var parsed,
			match = parser.re.exec( string ),
			values = match && parser.parse( match ),
			spaceName = parser.space || "rgba";

		if ( values ) {
			parsed = inst[ spaceName ]( values );

			// if this was an rgba parse the assignment might happen twice
			// oh well....
			inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
			rgba = inst._rgba = parsed._rgba;

			// exit each( stringParsers ) here because we matched
			return false;
		}
	});

	// Found a stringParser that handled it
	if ( rgba.length ) {

		// if this came from a parsed string, force "transparent" when alpha is 0
		// chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
		if ( rgba.join() === "0,0,0,0" ) {
			jQuery.extend( rgba, colors.transparent );
		}
		return inst;
	}

	// named colors
	return colors[ string ];
}

color.fn = jQuery.extend( color.prototype, {
	parse: function( red, green, blue, alpha ) {
		if ( red === undefined ) {
			this._rgba = [ null, null, null, null ];
			return this;
		}
		if ( red.jquery || red.nodeType ) {
			red = jQuery( red ).css( green );
			green = undefined;
		}

		var inst = this,
			type = jQuery.type( red ),
			rgba = this._rgba = [];

		// more than 1 argument specified - assume ( red, green, blue, alpha )
		if ( green !== undefined ) {
			red = [ red, green, blue, alpha ];
			type = "array";
		}

		if ( type === "string" ) {
			return this.parse( stringParse( red ) || colors._default );
		}

		if ( type === "array" ) {
			each( spaces.rgba.props, function( key, prop ) {
				rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
			});
			return this;
		}

		if ( type === "object" ) {
			if ( red instanceof color ) {
				each( spaces, function( spaceName, space ) {
					if ( red[ space.cache ] ) {
						inst[ space.cache ] = red[ space.cache ].slice();
					}
				});
			} else {
				each( spaces, function( spaceName, space ) {
					var cache = space.cache;
					each( space.props, function( key, prop ) {

						// if the cache doesn't exist, and we know how to convert
						if ( !inst[ cache ] && space.to ) {

							// if the value was null, we don't need to copy it
							// if the key was alpha, we don't need to copy it either
							if ( key === "alpha" || red[ key ] == null ) {
								return;
							}
							inst[ cache ] = space.to( inst._rgba );
						}

						// this is the only case where we allow nulls for ALL properties.
						// call clamp with alwaysAllowEmpty
						inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
					});

					// everything defined but alpha?
					if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
						// use the default of 1
						inst[ cache ][ 3 ] = 1;
						if ( space.from ) {
							inst._rgba = space.from( inst[ cache ] );
						}
					}
				});
			}
			return this;
		}
	},
	is: function( compare ) {
		var is = color( compare ),
			same = true,
			inst = this;

		each( spaces, function( _, space ) {
			var localCache,
				isCache = is[ space.cache ];
			if (isCache) {
				localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
				each( space.props, function( _, prop ) {
					if ( isCache[ prop.idx ] != null ) {
						same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
						return same;
					}
				});
			}
			return same;
		});
		return same;
	},
	_space: function() {
		var used = [],
			inst = this;
		each( spaces, function( spaceName, space ) {
			if ( inst[ space.cache ] ) {
				used.push( spaceName );
			}
		});
		return used.pop();
	},
	transition: function( other, distance ) {
		var end = color( other ),
			spaceName = end._space(),
			space = spaces[ spaceName ],
			startColor = this.alpha() === 0 ? color( "transparent" ) : this,
			start = startColor[ space.cache ] || space.to( startColor._rgba ),
			result = start.slice();

		end = end[ space.cache ];
		each( space.props, function( key, prop ) {
			var index = prop.idx,
				startValue = start[ index ],
				endValue = end[ index ],
				type = propTypes[ prop.type ] || {};

			// if null, don't override start value
			if ( endValue === null ) {
				return;
			}
			// if null - use end
			if ( startValue === null ) {
				result[ index ] = endValue;
			} else {
				if ( type.mod ) {
					if ( endValue - startValue > type.mod / 2 ) {
						startValue += type.mod;
					} else if ( startValue - endValue > type.mod / 2 ) {
						startValue -= type.mod;
					}
				}
				result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
			}
		});
		return this[ spaceName ]( result );
	},
	blend: function( opaque ) {
		// if we are already opaque - return ourself
		if ( this._rgba[ 3 ] === 1 ) {
			return this;
		}

		var rgb = this._rgba.slice(),
			a = rgb.pop(),
			blend = color( opaque )._rgba;

		return color( jQuery.map( rgb, function( v, i ) {
			return ( 1 - a ) * blend[ i ] + a * v;
		}));
	},
	toRgbaString: function() {
		var prefix = "rgba(",
			rgba = jQuery.map( this._rgba, function( v, i ) {
				return v == null ? ( i > 2 ? 1 : 0 ) : v;
			});

		if ( rgba[ 3 ] === 1 ) {
			rgba.pop();
			prefix = "rgb(";
		}

		return prefix + rgba.join() + ")";
	},
	toHslaString: function() {
		var prefix = "hsla(",
			hsla = jQuery.map( this.hsla(), function( v, i ) {
				if ( v == null ) {
					v = i > 2 ? 1 : 0;
				}

				// catch 1 and 2
				if ( i && i < 3 ) {
					v = Math.round( v * 100 ) + "%";
				}
				return v;
			});

		if ( hsla[ 3 ] === 1 ) {
			hsla.pop();
			prefix = "hsl(";
		}
		return prefix + hsla.join() + ")";
	},
	toHexString: function( includeAlpha ) {
		var rgba = this._rgba.slice(),
			alpha = rgba.pop();

		if ( includeAlpha ) {
			rgba.push( ~~( alpha * 255 ) );
		}

		return "#" + jQuery.map( rgba, function( v ) {

			// default to 0 when nulls exist
			v = ( v || 0 ).toString( 16 );
			return v.length === 1 ? "0" + v : v;
		}).join("");
	},
	toString: function() {
		return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
	}
});
color.fn.parse.prototype = color.fn;

// hsla conversions adapted from:
// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021

function hue2rgb( p, q, h ) {
	h = ( h + 1 ) % 1;
	if ( h * 6 < 1 ) {
		return p + (q - p) * h * 6;
	}
	if ( h * 2 < 1) {
		return q;
	}
	if ( h * 3 < 2 ) {
		return p + (q - p) * ((2/3) - h) * 6;
	}
	return p;
}

spaces.hsla.to = function ( rgba ) {
	if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
		return [ null, null, null, rgba[ 3 ] ];
	}
	var r = rgba[ 0 ] / 255,
		g = rgba[ 1 ] / 255,
		b = rgba[ 2 ] / 255,
		a = rgba[ 3 ],
		max = Math.max( r, g, b ),
		min = Math.min( r, g, b ),
		diff = max - min,
		add = max + min,
		l = add * 0.5,
		h, s;

	if ( min === max ) {
		h = 0;
	} else if ( r === max ) {
		h = ( 60 * ( g - b ) / diff ) + 360;
	} else if ( g === max ) {
		h = ( 60 * ( b - r ) / diff ) + 120;
	} else {
		h = ( 60 * ( r - g ) / diff ) + 240;
	}

	// chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
	// otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
	if ( diff === 0 ) {
		s = 0;
	} else if ( l <= 0.5 ) {
		s = diff / add;
	} else {
		s = diff / ( 2 - add );
	}
	return [ Math.round(h) % 360, s, l, a == null ? 1 : a ];
};

spaces.hsla.from = function ( hsla ) {
	if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
		return [ null, null, null, hsla[ 3 ] ];
	}
	var h = hsla[ 0 ] / 360,
		s = hsla[ 1 ],
		l = hsla[ 2 ],
		a = hsla[ 3 ],
		q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
		p = 2 * l - q;

	return [
		Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
		Math.round( hue2rgb( p, q, h ) * 255 ),
		Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
		a
	];
};


each( spaces, function( spaceName, space ) {
	var props = space.props,
		cache = space.cache,
		to = space.to,
		from = space.from;

	// makes rgba() and hsla()
	color.fn[ spaceName ] = function( value ) {

		// generate a cache for this space if it doesn't exist
		if ( to && !this[ cache ] ) {
			this[ cache ] = to( this._rgba );
		}
		if ( value === undefined ) {
			return this[ cache ].slice();
		}

		var ret,
			type = jQuery.type( value ),
			arr = ( type === "array" || type === "object" ) ? value : arguments,
			local = this[ cache ].slice();

		each( props, function( key, prop ) {
			var val = arr[ type === "object" ? key : prop.idx ];
			if ( val == null ) {
				val = local[ prop.idx ];
			}
			local[ prop.idx ] = clamp( val, prop );
		});

		if ( from ) {
			ret = color( from( local ) );
			ret[ cache ] = local;
			return ret;
		} else {
			return color( local );
		}
	};

	// makes red() green() blue() alpha() hue() saturation() lightness()
	each( props, function( key, prop ) {
		// alpha is included in more than one space
		if ( color.fn[ key ] ) {
			return;
		}
		color.fn[ key ] = function( value ) {
			var vtype = jQuery.type( value ),
				fn = ( key === "alpha" ? ( this._hsla ? "hsla" : "rgba" ) : spaceName ),
				local = this[ fn ](),
				cur = local[ prop.idx ],
				match;

			if ( vtype === "undefined" ) {
				return cur;
			}

			if ( vtype === "function" ) {
				value = value.call( this, cur );
				vtype = jQuery.type( value );
			}
			if ( value == null && prop.empty ) {
				return this;
			}
			if ( vtype === "string" ) {
				match = rplusequals.exec( value );
				if ( match ) {
					value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
				}
			}
			local[ prop.idx ] = value;
			return this[ fn ]( local );
		};
	});
});

// add cssHook and .fx.step function for each named hook.
// accept a space separated string of properties
color.hook = function( hook ) {
	var hooks = hook.split( " " );
	each( hooks, function( i, hook ) {
		jQuery.cssHooks[ hook ] = {
			set: function( elem, value ) {
				var parsed, curElem,
					backgroundColor = "";

				if ( value !== "transparent" && ( jQuery.type( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
					value = color( parsed || value );
					if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
						curElem = hook === "backgroundColor" ? elem.parentNode : elem;
						while (
							(backgroundColor === "" || backgroundColor === "transparent") &&
							curElem && curElem.style
						) {
							try {
								backgroundColor = jQuery.css( curElem, "backgroundColor" );
								curElem = curElem.parentNode;
							} catch ( e ) {
							}
						}

						value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
							backgroundColor :
							"_default" );
					}

					value = value.toRgbaString();
				}
				try {
					elem.style[ hook ] = value;
				} catch( e ) {
					// wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
				}
			}
		};
		jQuery.fx.step[ hook ] = function( fx ) {
			if ( !fx.colorInit ) {
				fx.start = color( fx.elem, hook );
				fx.end = color( fx.end );
				fx.colorInit = true;
			}
			jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
		};
	});

};

color.hook( stepHooks );

jQuery.cssHooks.borderColor = {
	expand: function( value ) {
		var expanded = {};

		each( [ "Top", "Right", "Bottom", "Left" ], function( i, part ) {
			expanded[ "border" + part + "Color" ] = value;
		});
		return expanded;
	}
};

// Basic color names only.
// Usage of any of the other color names requires adding yourself or including
// jquery.color.svg-names.js.
colors = jQuery.Color.names = {
	// 4.1. Basic color keywords
	aqua: "#00ffff",
	black: "#000000",
	blue: "#0000ff",
	fuchsia: "#ff00ff",
	gray: "#808080",
	green: "#008000",
	lime: "#00ff00",
	maroon: "#800000",
	navy: "#000080",
	olive: "#808000",
	purple: "#800080",
	red: "#ff0000",
	silver: "#c0c0c0",
	teal: "#008080",
	white: "#ffffff",
	yellow: "#ffff00",

	// 4.2.3. "transparent" color keyword
	transparent: [ null, null, null, 0 ],

	_default: "#ffffff"
};

})( jQuery );


/******************************************************************************/
/****************************** CLASS ANIMATIONS ******************************/
/******************************************************************************/
(function() {

var classAnimationActions = [ "add", "remove", "toggle" ],
	shorthandStyles = {
		border: 1,
		borderBottom: 1,
		borderColor: 1,
		borderLeft: 1,
		borderRight: 1,
		borderTop: 1,
		borderWidth: 1,
		margin: 1,
		padding: 1
	};

$.each([ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ], function( _, prop ) {
	$.fx.step[ prop ] = function( fx ) {
		if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
			jQuery.style( fx.elem, prop, fx.end );
			fx.setAttr = true;
		}
	};
});

function getElementStyles( elem ) {
	var key, len,
		style = elem.ownerDocument.defaultView ?
			elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
			elem.currentStyle,
		styles = {};

	if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
		len = style.length;
		while ( len-- ) {
			key = style[ len ];
			if ( typeof style[ key ] === "string" ) {
				styles[ $.camelCase( key ) ] = style[ key ];
			}
		}
	// support: Opera, IE <9
	} else {
		for ( key in style ) {
			if ( typeof style[ key ] === "string" ) {
				styles[ key ] = style[ key ];
			}
		}
	}

	return styles;
}


function styleDifference( oldStyle, newStyle ) {
	var diff = {},
		name, value;

	for ( name in newStyle ) {
		value = newStyle[ name ];
		if ( oldStyle[ name ] !== value ) {
			if ( !shorthandStyles[ name ] ) {
				if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
					diff[ name ] = value;
				}
			}
		}
	}

	return diff;
}

// support: jQuery <1.8
if ( !$.fn.addBack ) {
	$.fn.addBack = function( selector ) {
		return this.add( selector == null ?
			this.prevObject : this.prevObject.filter( selector )
		);
	};
}

$.effects.animateClass = function( value, duration, easing, callback ) {
	var o = $.speed( duration, easing, callback );

	return this.queue( function() {
		var animated = $( this ),
			baseClass = animated.attr( "class" ) || "",
			applyClassChange,
			allAnimations = o.children ? animated.find( "*" ).addBack() : animated;

		// map the animated objects to store the original styles.
		allAnimations = allAnimations.map(function() {
			var el = $( this );
			return {
				el: el,
				start: getElementStyles( this )
			};
		});

		// apply class change
		applyClassChange = function() {
			$.each( classAnimationActions, function(i, action) {
				if ( value[ action ] ) {
					animated[ action + "Class" ]( value[ action ] );
				}
			});
		};
		applyClassChange();

		// map all animated objects again - calculate new styles and diff
		allAnimations = allAnimations.map(function() {
			this.end = getElementStyles( this.el[ 0 ] );
			this.diff = styleDifference( this.start, this.end );
			return this;
		});

		// apply original class
		animated.attr( "class", baseClass );

		// map all animated objects again - this time collecting a promise
		allAnimations = allAnimations.map(function() {
			var styleInfo = this,
				dfd = $.Deferred(),
				opts = $.extend({}, o, {
					queue: false,
					complete: function() {
						dfd.resolve( styleInfo );
					}
				});

			this.el.animate( this.diff, opts );
			return dfd.promise();
		});

		// once all animations have completed:
		$.when.apply( $, allAnimations.get() ).done(function() {

			// set the final class
			applyClassChange();

			// for each animated element,
			// clear all css properties that were animated
			$.each( arguments, function() {
				var el = this.el;
				$.each( this.diff, function(key) {
					el.css( key, "" );
				});
			});

			// this is guarnteed to be there if you use jQuery.speed()
			// it also handles dequeuing the next anim...
			o.complete.call( animated[ 0 ] );
		});
	});
};

$.fn.extend({
	_addClass: $.fn.addClass,
	addClass: function( classNames, speed, easing, callback ) {
		return speed ?
			$.effects.animateClass.call( this,
				{ add: classNames }, speed, easing, callback ) :
			this._addClass( classNames );
	},

	_removeClass: $.fn.removeClass,
	removeClass: function( classNames, speed, easing, callback ) {
		return speed ?
			$.effects.animateClass.call( this,
				{ remove: classNames }, speed, easing, callback ) :
			this._removeClass( classNames );
	},

	_toggleClass: $.fn.toggleClass,
	toggleClass: function( classNames, force, speed, easing, callback ) {
		if ( typeof force === "boolean" || force === undefined ) {
			if ( !speed ) {
				// without speed parameter
				return this._toggleClass( classNames, force );
			} else {
				return $.effects.animateClass.call( this,
					(force ? { add: classNames } : { remove: classNames }),
					speed, easing, callback );
			}
		} else {
			// without force parameter
			return $.effects.animateClass.call( this,
				{ toggle: classNames }, force, speed, easing );
		}
	},

	switchClass: function( remove, add, speed, easing, callback) {
		return $.effects.animateClass.call( this, {
			add: add,
			remove: remove
		}, speed, easing, callback );
	}
});

})();

/******************************************************************************/
/*********************************** EFFECTS **********************************/
/******************************************************************************/

(function() {

$.extend( $.effects, {
	version: "1.10.0",

	// Saves a set of properties in a data storage
	save: function( element, set ) {
		for( var i=0; i < set.length; i++ ) {
			if ( set[ i ] !== null ) {
				element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
			}
		}
	},

	// Restores a set of previously saved properties from a data storage
	restore: function( element, set ) {
		var val, i;
		for( i=0; i < set.length; i++ ) {
			if ( set[ i ] !== null ) {
				val = element.data( dataSpace + set[ i ] );
				// support: jQuery 1.6.2
				// http://bugs.jquery.com/ticket/9917
				// jQuery 1.6.2 incorrectly returns undefined for any falsy value.
				// We can't differentiate between "" and 0 here, so we just assume
				// empty string since it's likely to be a more common value...
				if ( val === undefined ) {
					val = "";
				}
				element.css( set[ i ], val );
			}
		}
	},

	setMode: function( el, mode ) {
		if (mode === "toggle") {
			mode = el.is( ":hidden" ) ? "show" : "hide";
		}
		return mode;
	},

	// Translates a [top,left] array into a baseline value
	// this should be a little more flexible in the future to handle a string & hash
	getBaseline: function( origin, original ) {
		var y, x;
		switch ( origin[ 0 ] ) {
			case "top": y = 0; break;
			case "middle": y = 0.5; break;
			case "bottom": y = 1; break;
			default: y = origin[ 0 ] / original.height;
		}
		switch ( origin[ 1 ] ) {
			case "left": x = 0; break;
			case "center": x = 0.5; break;
			case "right": x = 1; break;
			default: x = origin[ 1 ] / original.width;
		}
		return {
			x: x,
			y: y
		};
	},

	// Wraps the element around a wrapper that copies position properties
	createWrapper: function( element ) {

		// if the element is already wrapped, return it
		if ( element.parent().is( ".ui-effects-wrapper" )) {
			return element.parent();
		}

		// wrap the element
		var props = {
				width: element.outerWidth(true),
				height: element.outerHeight(true),
				"float": element.css( "float" )
			},
			wrapper = $( "<div></div>" )
				.addClass( "ui-effects-wrapper" )
				.css({
					fontSize: "100%",
					background: "transparent",
					border: "none",
					margin: 0,
					padding: 0
				}),
			// Store the size in case width/height are defined in % - Fixes #5245
			size = {
				width: element.width(),
				height: element.height()
			},
			active = document.activeElement;

		// support: Firefox
		// Firefox incorrectly exposes anonymous content
		// https://bugzilla.mozilla.org/show_bug.cgi?id=561664
		try {
			active.id;
		} catch( e ) {
			active = document.body;
		}

		element.wrap( wrapper );

		// Fixes #7595 - Elements lose focus when wrapped.
		if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
			$( active ).focus();
		}

		wrapper = element.parent(); //Hotfix for jQuery 1.4 since some change in wrap() seems to actually lose the reference to the wrapped element

		// transfer positioning properties to the wrapper
		if ( element.css( "position" ) === "static" ) {
			wrapper.css({ position: "relative" });
			element.css({ position: "relative" });
		} else {
			$.extend( props, {
				position: element.css( "position" ),
				zIndex: element.css( "z-index" )
			});
			$.each([ "top", "left", "bottom", "right" ], function(i, pos) {
				props[ pos ] = element.css( pos );
				if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
					props[ pos ] = "auto";
				}
			});
			element.css({
				position: "relative",
				top: 0,
				left: 0,
				right: "auto",
				bottom: "auto"
			});
		}
		element.css(size);

		return wrapper.css( props ).show();
	},

	removeWrapper: function( element ) {
		var active = document.activeElement;

		if ( element.parent().is( ".ui-effects-wrapper" ) ) {
			element.parent().replaceWith( element );

			// Fixes #7595 - Elements lose focus when wrapped.
			if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
				$( active ).focus();
			}
		}


		return element;
	},

	setTransition: function( element, list, factor, value ) {
		value = value || {};
		$.each( list, function( i, x ) {
			var unit = element.cssUnit( x );
			if ( unit[ 0 ] > 0 ) {
				value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
			}
		});
		return value;
	}
});

// return an effect options object for the given parameters:
function _normalizeArguments( effect, options, speed, callback ) {

	// allow passing all options as the first parameter
	if ( $.isPlainObject( effect ) ) {
		options = effect;
		effect = effect.effect;
	}

	// convert to an object
	effect = { effect: effect };

	// catch (effect, null, ...)
	if ( options == null ) {
		options = {};
	}

	// catch (effect, callback)
	if ( $.isFunction( options ) ) {
		callback = options;
		speed = null;
		options = {};
	}

	// catch (effect, speed, ?)
	if ( typeof options === "number" || $.fx.speeds[ options ] ) {
		callback = speed;
		speed = options;
		options = {};
	}

	// catch (effect, options, callback)
	if ( $.isFunction( speed ) ) {
		callback = speed;
		speed = null;
	}

	// add options to effect
	if ( options ) {
		$.extend( effect, options );
	}

	speed = speed || options.duration;
	effect.duration = $.fx.off ? 0 :
		typeof speed === "number" ? speed :
		speed in $.fx.speeds ? $.fx.speeds[ speed ] :
		$.fx.speeds._default;

	effect.complete = callback || options.complete;

	return effect;
}

function standardSpeed( speed ) {
	// valid standard speeds
	if ( !speed || typeof speed === "number" || $.fx.speeds[ speed ] ) {
		return true;
	}

	// invalid strings - treat as "normal" speed
	return typeof speed === "string" && !$.effects.effect[ speed ];
}

$.fn.extend({
	effect: function( /* effect, options, speed, callback */ ) {
		var args = _normalizeArguments.apply( this, arguments ),
			mode = args.mode,
			queue = args.queue,
			effectMethod = $.effects.effect[ args.effect ];

		if ( $.fx.off || !effectMethod ) {
			// delegate to the original method (e.g., .show()) if possible
			if ( mode ) {
				return this[ mode ]( args.duration, args.complete );
			} else {
				return this.each( function() {
					if ( args.complete ) {
						args.complete.call( this );
					}
				});
			}
		}

		function run( next ) {
			var elem = $( this ),
				complete = args.complete,
				mode = args.mode;

			function done() {
				if ( $.isFunction( complete ) ) {
					complete.call( elem[0] );
				}
				if ( $.isFunction( next ) ) {
					next();
				}
			}

			// if the element is hiddden and mode is hide,
			// or element is visible and mode is show
			if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
				done();
			} else {
				effectMethod.call( elem[0], args, done );
			}
		}

		return queue === false ? this.each( run ) : this.queue( queue || "fx", run );
	},

	_show: $.fn.show,
	show: function( speed ) {
		if ( standardSpeed( speed ) ) {
			return this._show.apply( this, arguments );
		} else {
			var args = _normalizeArguments.apply( this, arguments );
			args.mode = "show";
			return this.effect.call( this, args );
		}
	},

	_hide: $.fn.hide,
	hide: function( speed ) {
		if ( standardSpeed( speed ) ) {
			return this._hide.apply( this, arguments );
		} else {
			var args = _normalizeArguments.apply( this, arguments );
			args.mode = "hide";
			return this.effect.call( this, args );
		}
	},

	// jQuery core overloads toggle and creates _toggle
	__toggle: $.fn.toggle,
	toggle: function( speed ) {
		if ( standardSpeed( speed ) || typeof speed === "boolean" || $.isFunction( speed ) ) {
			return this.__toggle.apply( this, arguments );
		} else {
			var args = _normalizeArguments.apply( this, arguments );
			args.mode = "toggle";
			return this.effect.call( this, args );
		}
	},

	// helper functions
	cssUnit: function(key) {
		var style = this.css( key ),
			val = [];

		$.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
			if ( style.indexOf( unit ) > 0 ) {
				val = [ parseFloat( style ), unit ];
			}
		});
		return val;
	}
});

})();

/******************************************************************************/
/*********************************** EASING ***********************************/
/******************************************************************************/

(function() {

// based on easing equations from Robert Penner (http://www.robertpenner.com/easing)

var baseEasings = {};

$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
	baseEasings[ name ] = function( p ) {
		return Math.pow( p, i + 2 );
	};
});

$.extend( baseEasings, {
	Sine: function ( p ) {
		return 1 - Math.cos( p * Math.PI / 2 );
	},
	Circ: function ( p ) {
		return 1 - Math.sqrt( 1 - p * p );
	},
	Elastic: function( p ) {
		return p === 0 || p === 1 ? p :
			-Math.pow( 2, 8 * (p - 1) ) * Math.sin( ( (p - 1) * 80 - 7.5 ) * Math.PI / 15 );
	},
	Back: function( p ) {
		return p * p * ( 3 * p - 2 );
	},
	Bounce: function ( p ) {
		var pow2,
			bounce = 4;

		while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
		return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
	}
});

$.each( baseEasings, function( name, easeIn ) {
	$.easing[ "easeIn" + name ] = easeIn;
	$.easing[ "easeOut" + name ] = function( p ) {
		return 1 - easeIn( 1 - p );
	};
	$.easing[ "easeInOut" + name ] = function( p ) {
		return p < 0.5 ?
			easeIn( p * 2 ) / 2 :
			1 - easeIn( p * -2 + 2 ) / 2;
	};
});

})();

})(jQuery));

// file: 000-1-100-jquery.ui.accordion.js
/*!
 * jQuery UI Accordion 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/accordion/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

var uid = 0,
	hideProps = {},
	showProps = {};

hideProps.height = hideProps.paddingTop = hideProps.paddingBottom =
	hideProps.borderTopWidth = hideProps.borderBottomWidth = "hide";
showProps.height = showProps.paddingTop = showProps.paddingBottom =
	showProps.borderTopWidth = showProps.borderBottomWidth = "show";

$.widget( "ui.accordion", {
	version: "1.10.0",
	options: {
		active: 0,
		animate: {},
		collapsible: false,
		event: "click",
		header: "> li > :first-child,> :not(li):even",
		heightStyle: "auto",
		icons: {
			activeHeader: "ui-icon-triangle-1-s",
			header: "ui-icon-triangle-1-e"
		},

		// callbacks
		activate: null,
		beforeActivate: null
	},

	_create: function() {
		var options = this.options;
		this.prevShow = this.prevHide = $();
		this.element.addClass( "ui-accordion ui-widget ui-helper-reset" )
			// ARIA
			.attr( "role", "tablist" );

		// don't allow collapsible: false and active: false / null
		if ( !options.collapsible && (options.active === false || options.active == null) ) {
			options.active = 0;
		}

		this._processPanels();
		// handle negative values
		if ( options.active < 0 ) {
			options.active += this.headers.length;
		}
		this._refresh();
	},

	_getCreateEventData: function() {
		return {
			header: this.active,
			content: !this.active.length ? $() : this.active.next()
		};
	},

	_createIcons: function() {
		var icons = this.options.icons;
		if ( icons ) {
			$( "<span>" )
				.addClass( "ui-accordion-header-icon ui-icon " + icons.header )
				.prependTo( this.headers );
			this.active.children( ".ui-accordion-header-icon" )
				.removeClass( icons.header )
				.addClass( icons.activeHeader );
			this.headers.addClass( "ui-accordion-icons" );
		}
	},

	_destroyIcons: function() {
		this.headers
			.removeClass( "ui-accordion-icons" )
			.children( ".ui-accordion-header-icon" )
				.remove();
	},

	_destroy: function() {
		var contents;

		// clean up main element
		this.element
			.removeClass( "ui-accordion ui-widget ui-helper-reset" )
			.removeAttr( "role" );

		// clean up headers
		this.headers
			.removeClass( "ui-accordion-header ui-accordion-header-active ui-helper-reset ui-state-default ui-corner-all ui-state-active ui-state-disabled ui-corner-top" )
			.removeAttr( "role" )
			.removeAttr( "aria-selected" )
			.removeAttr( "aria-controls" )
			.removeAttr( "tabIndex" )
			.each(function() {
				if ( /^ui-accordion/.test( this.id ) ) {
					this.removeAttribute( "id" );
				}
			});
		this._destroyIcons();

		// clean up content panels
		contents = this.headers.next()
			.css( "display", "" )
			.removeAttr( "role" )
			.removeAttr( "aria-expanded" )
			.removeAttr( "aria-hidden" )
			.removeAttr( "aria-labelledby" )
			.removeClass( "ui-helper-reset ui-widget-content ui-corner-bottom ui-accordion-content ui-accordion-content-active ui-state-disabled" )
			.each(function() {
				if ( /^ui-accordion/.test( this.id ) ) {
					this.removeAttribute( "id" );
				}
			});
		if ( this.options.heightStyle !== "content" ) {
			contents.css( "height", "" );
		}
	},

	_setOption: function( key, value ) {
		if ( key === "active" ) {
			// _activate() will handle invalid values and update this.options
			this._activate( value );
			return;
		}

		if ( key === "event" ) {
			if ( this.options.event ) {
				this._off( this.headers, this.options.event );
			}
			this._setupEvents( value );
		}

		this._super( key, value );

		// setting collapsible: false while collapsed; open first panel
		if ( key === "collapsible" && !value && this.options.active === false ) {
			this._activate( 0 );
		}

		if ( key === "icons" ) {
			this._destroyIcons();
			if ( value ) {
				this._createIcons();
			}
		}

		// #5332 - opacity doesn't cascade to positioned elements in IE
		// so we need to add the disabled class to the headers and panels
		if ( key === "disabled" ) {
			this.headers.add( this.headers.next() )
				.toggleClass( "ui-state-disabled", !!value );
		}
	},

	_keydown: function( event ) {
		/*jshint maxcomplexity:15*/
		if ( event.altKey || event.ctrlKey ) {
			return;
		}

		var keyCode = $.ui.keyCode,
			length = this.headers.length,
			currentIndex = this.headers.index( event.target ),
			toFocus = false;

		switch ( event.keyCode ) {
			case keyCode.RIGHT:
			case keyCode.DOWN:
				toFocus = this.headers[ ( currentIndex + 1 ) % length ];
				break;
			case keyCode.LEFT:
			case keyCode.UP:
				toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
				break;
			case keyCode.SPACE:
			case keyCode.ENTER:
				this._eventHandler( event );
				break;
			case keyCode.HOME:
				toFocus = this.headers[ 0 ];
				break;
			case keyCode.END:
				toFocus = this.headers[ length - 1 ];
				break;
		}

		if ( toFocus ) {
			$( event.target ).attr( "tabIndex", -1 );
			$( toFocus ).attr( "tabIndex", 0 );
			toFocus.focus();
			event.preventDefault();
		}
	},

	_panelKeyDown : function( event ) {
		if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
			$( event.currentTarget ).prev().focus();
		}
	},

	refresh: function() {
		var options = this.options;
		this._processPanels();

		// was collapsed or no panel
		if ( ( options.active === false && options.collapsible === true ) || !this.headers.length ) {
			options.active = false;
			this.active = $();
		// active false only when collapsible is true
		} if ( options.active === false ) {
			this._activate( 0 );
		// was active, but active panel is gone
		} else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
			// all remaining panel are disabled
			if ( this.headers.length === this.headers.find(".ui-state-disabled").length ) {
				options.active = false;
				this.active = $();
			// activate previous panel
			} else {
				this._activate( Math.max( 0, options.active - 1 ) );
			}
		// was active, active panel still exists
		} else {
			// make sure active index is correct
			options.active = this.headers.index( this.active );
		}

		this._destroyIcons();

		this._refresh();
	},

	_processPanels: function() {
		this.headers = this.element.find( this.options.header )
			.addClass( "ui-accordion-header ui-helper-reset ui-state-default ui-corner-all" );

		this.headers.next()
			.addClass( "ui-accordion-content ui-helper-reset ui-widget-content ui-corner-bottom" )
			.filter(":not(.ui-accordion-content-active)")
			.hide();
	},

	_refresh: function() {
		var maxHeight,
			options = this.options,
			heightStyle = options.heightStyle,
			parent = this.element.parent(),
			accordionId = this.accordionId = "ui-accordion-" +
				(this.element.attr( "id" ) || ++uid);

		this.active = this._findActive( options.active )
			.addClass( "ui-accordion-header-active ui-state-active" )
			.toggleClass( "ui-corner-all ui-corner-top" );
		this.active.next()
			.addClass( "ui-accordion-content-active" )
			.show();

		this.headers
			.attr( "role", "tab" )
			.each(function( i ) {
				var header = $( this ),
					headerId = header.attr( "id" ),
					panel = header.next(),
					panelId = panel.attr( "id" );
				if ( !headerId ) {
					headerId = accordionId + "-header-" + i;
					header.attr( "id", headerId );
				}
				if ( !panelId ) {
					panelId = accordionId + "-panel-" + i;
					panel.attr( "id", panelId );
				}
				header.attr( "aria-controls", panelId );
				panel.attr( "aria-labelledby", headerId );
			})
			.next()
				.attr( "role", "tabpanel" );

		this.headers
			.not( this.active )
			.attr({
				"aria-selected": "false",
				tabIndex: -1
			})
			.next()
				.attr({
					"aria-expanded": "false",
					"aria-hidden": "true"
				})
				.hide();

		// make sure at least one header is in the tab order
		if ( !this.active.length ) {
			this.headers.eq( 0 ).attr( "tabIndex", 0 );
		} else {
			this.active.attr({
				"aria-selected": "true",
				tabIndex: 0
			})
			.next()
				.attr({
					"aria-expanded": "true",
					"aria-hidden": "false"
				});
		}

		this._createIcons();

		this._setupEvents( options.event );

		if ( heightStyle === "fill" ) {
			maxHeight = parent.height();
			this.element.siblings( ":visible" ).each(function() {
				var elem = $( this ),
					position = elem.css( "position" );

				if ( position === "absolute" || position === "fixed" ) {
					return;
				}
				maxHeight -= elem.outerHeight( true );
			});

			this.headers.each(function() {
				maxHeight -= $( this ).outerHeight( true );
			});

			this.headers.next()
				.each(function() {
					$( this ).height( Math.max( 0, maxHeight -
						$( this ).innerHeight() + $( this ).height() ) );
				})
				.css( "overflow", "auto" );
		} else if ( heightStyle === "auto" ) {
			maxHeight = 0;
			this.headers.next()
				.each(function() {
					maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
				})
				.height( maxHeight );
		}
	},

	_activate: function( index ) {
		var active = this._findActive( index )[ 0 ];

		// trying to activate the already active panel
		if ( active === this.active[ 0 ] ) {
			return;
		}

		// trying to collapse, simulate a click on the currently active header
		active = active || this.active[ 0 ];

		this._eventHandler({
			target: active,
			currentTarget: active,
			preventDefault: $.noop
		});
	},

	_findActive: function( selector ) {
		return typeof selector === "number" ? this.headers.eq( selector ) : $();
	},

	_setupEvents: function( event ) {
		var events = {
			keydown: "_keydown"
		};
		if ( event ) {
			$.each( event.split(" "), function( index, eventName ) {
				events[ eventName ] = "_eventHandler";
			});
		}

		this._off( this.headers.add( this.headers.next() ) );
		this._on( this.headers, events );
		this._on( this.headers.next(), { keydown: "_panelKeyDown" });
		this._hoverable( this.headers );
		this._focusable( this.headers );
	},

	_eventHandler: function( event ) {
		var options = this.options,
			active = this.active,
			clicked = $( event.currentTarget ),
			clickedIsActive = clicked[ 0 ] === active[ 0 ],
			collapsing = clickedIsActive && options.collapsible,
			toShow = collapsing ? $() : clicked.next(),
			toHide = active.next(),
			eventData = {
				oldHeader: active,
				oldPanel: toHide,
				newHeader: collapsing ? $() : clicked,
				newPanel: toShow
			};

		event.preventDefault();

		if (
				// click on active header, but not collapsible
				( clickedIsActive && !options.collapsible ) ||
				// allow canceling activation
				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
			return;
		}

		options.active = collapsing ? false : this.headers.index( clicked );

		// when the call to ._toggle() comes after the class changes
		// it causes a very odd bug in IE 8 (see #6720)
		this.active = clickedIsActive ? $() : clicked;
		this._toggle( eventData );

		// switch classes
		// corner classes on the previously active header stay after the animation
		active.removeClass( "ui-accordion-header-active ui-state-active" );
		if ( options.icons ) {
			active.children( ".ui-accordion-header-icon" )
				.removeClass( options.icons.activeHeader )
				.addClass( options.icons.header );
		}

		if ( !clickedIsActive ) {
			clicked
				.removeClass( "ui-corner-all" )
				.addClass( "ui-accordion-header-active ui-state-active ui-corner-top" );
			if ( options.icons ) {
				clicked.children( ".ui-accordion-header-icon" )
					.removeClass( options.icons.header )
					.addClass( options.icons.activeHeader );
			}

			clicked
				.next()
				.addClass( "ui-accordion-content-active" );
		}
	},

	_toggle: function( data ) {
		var toShow = data.newPanel,
			toHide = this.prevShow.length ? this.prevShow : data.oldPanel;

		// handle activating a panel during the animation for another activation
		this.prevShow.add( this.prevHide ).stop( true, true );
		this.prevShow = toShow;
		this.prevHide = toHide;

		if ( this.options.animate ) {
			this._animate( toShow, toHide, data );
		} else {
			toHide.hide();
			toShow.show();
			this._toggleComplete( data );
		}

		toHide.attr({
			"aria-expanded": "false",
			"aria-hidden": "true"
		});
		toHide.prev().attr( "aria-selected", "false" );
		// if we're switching panels, remove the old header from the tab order
		// if we're opening from collapsed state, remove the previous header from the tab order
		// if we're collapsing, then keep the collapsing header in the tab order
		if ( toShow.length && toHide.length ) {
			toHide.prev().attr( "tabIndex", -1 );
		} else if ( toShow.length ) {
			this.headers.filter(function() {
				return $( this ).attr( "tabIndex" ) === 0;
			})
			.attr( "tabIndex", -1 );
		}

		toShow
			.attr({
				"aria-expanded": "true",
				"aria-hidden": "false"
			})
			.prev()
				.attr({
					"aria-selected": "true",
					tabIndex: 0
				});
	},

	_animate: function( toShow, toHide, data ) {
		var total, easing, duration,
			that = this,
			adjust = 0,
			down = toShow.length &&
				( !toHide.length || ( toShow.index() < toHide.index() ) ),
			animate = this.options.animate || {},
			options = down && animate.down || animate,
			complete = function() {
				that._toggleComplete( data );
			};

		if ( typeof options === "number" ) {
			duration = options;
		}
		if ( typeof options === "string" ) {
			easing = options;
		}
		// fall back from options to animation in case of partial down settings
		easing = easing || options.easing || animate.easing;
		duration = duration || options.duration || animate.duration;

		if ( !toHide.length ) {
			return toShow.animate( showProps, duration, easing, complete );
		}
		if ( !toShow.length ) {
			return toHide.animate( hideProps, duration, easing, complete );
		}

		total = toShow.show().outerHeight();
		toHide.animate( hideProps, {
			duration: duration,
			easing: easing,
			step: function( now, fx ) {
				fx.now = Math.round( now );
			}
		});
		toShow
			.hide()
			.animate( showProps, {
				duration: duration,
				easing: easing,
				complete: complete,
				step: function( now, fx ) {
					fx.now = Math.round( now );
					if ( fx.prop !== "height" ) {
						adjust += fx.now;
					} else if ( that.options.heightStyle !== "content" ) {
						fx.now = Math.round( total - toHide.outerHeight() - adjust );
						adjust = 0;
					}
				}
			});
	},

	_toggleComplete: function( data ) {
		var toHide = data.oldPanel;

		toHide
			.removeClass( "ui-accordion-content-active" )
			.prev()
				.removeClass( "ui-corner-top" )
				.addClass( "ui-corner-all" );

		// Work around for rendering bug in IE (#5421)
		if ( toHide.length ) {
			toHide.parent()[0].className = toHide.parent()[0].className;
		}

		this._trigger( "activate", null, data );
	}
});

})( jQuery );

// file: 000-1-110-jquery.ui.autocomplete.js
/*!
 * jQuery UI Autocomplete 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/autocomplete/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.position.js
 *	jquery.ui.menu.js
 */
(function( $, undefined ) {

// used to prevent race conditions with remote data sources
var requestIndex = 0;

$.widget( "ui.autocomplete", {
	version: "1.10.0",
	defaultElement: "<input>",
	options: {
		appendTo: null,
		autoFocus: false,
		delay: 300,
		minLength: 1,
		position: {
			my: "left top",
			at: "left bottom",
			collision: "none"
		},
		source: null,

		// callbacks
		change: null,
		close: null,
		focus: null,
		open: null,
		response: null,
		search: null,
		select: null
	},

	pending: 0,

	_create: function() {
		// Some browsers only repeat keydown events, not keypress events,
		// so we use the suppressKeyPress flag to determine if we've already
		// handled the keydown event. #7269
		// Unfortunately the code for & in keypress is the same as the up arrow,
		// so we use the suppressKeyPressRepeat flag to avoid handling keypress
		// events when we know the keydown event was used to modify the
		// search term. #7799
		var suppressKeyPress, suppressKeyPressRepeat, suppressInput;

		this.isMultiLine = this._isMultiLine();
		this.valueMethod = this.element[ this.element.is( "input,textarea" ) ? "val" : "text" ];
		this.isNewMenu = true;

		this.element
			.addClass( "ui-autocomplete-input" )
			.attr( "autocomplete", "off" );

		this._on( this.element, {
			keydown: function( event ) {
				/*jshint maxcomplexity:15*/
				if ( this.element.prop( "readOnly" ) ) {
					suppressKeyPress = true;
					suppressInput = true;
					suppressKeyPressRepeat = true;
					return;
				}

				suppressKeyPress = false;
				suppressInput = false;
				suppressKeyPressRepeat = false;
				var keyCode = $.ui.keyCode;
				switch( event.keyCode ) {
				case keyCode.PAGE_UP:
					suppressKeyPress = true;
					this._move( "previousPage", event );
					break;
				case keyCode.PAGE_DOWN:
					suppressKeyPress = true;
					this._move( "nextPage", event );
					break;
				case keyCode.UP:
					suppressKeyPress = true;
					this._keyEvent( "previous", event );
					break;
				case keyCode.DOWN:
					suppressKeyPress = true;
					this._keyEvent( "next", event );
					break;
				case keyCode.ENTER:
				case keyCode.NUMPAD_ENTER:
					// when menu is open and has focus
					if ( this.menu.active ) {
						// #6055 - Opera still allows the keypress to occur
						// which causes forms to submit
						suppressKeyPress = true;
						event.preventDefault();
						this.menu.select( event );
					}
					break;
				case keyCode.TAB:
					if ( this.menu.active ) {
						this.menu.select( event );
					}
					break;
				case keyCode.ESCAPE:
					if ( this.menu.element.is( ":visible" ) ) {
						this._value( this.term );
						this.close( event );
						// Different browsers have different default behavior for escape
						// Single press can mean undo or clear
						// Double press in IE means clear the whole form
						event.preventDefault();
					}
					break;
				default:
					suppressKeyPressRepeat = true;
					// search timeout should be triggered before the input value is changed
					this._searchTimeout( event );
					break;
				}
			},
			keypress: function( event ) {
				if ( suppressKeyPress ) {
					suppressKeyPress = false;
					event.preventDefault();
					return;
				}
				if ( suppressKeyPressRepeat ) {
					return;
				}

				// replicate some key handlers to allow them to repeat in Firefox and Opera
				var keyCode = $.ui.keyCode;
				switch( event.keyCode ) {
				case keyCode.PAGE_UP:
					this._move( "previousPage", event );
					break;
				case keyCode.PAGE_DOWN:
					this._move( "nextPage", event );
					break;
				case keyCode.UP:
					this._keyEvent( "previous", event );
					break;
				case keyCode.DOWN:
					this._keyEvent( "next", event );
					break;
				}
			},
			input: function( event ) {
				if ( suppressInput ) {
					suppressInput = false;
					event.preventDefault();
					return;
				}
				this._searchTimeout( event );
			},
			focus: function() {
				this.selectedItem = null;
				this.previous = this._value();
			},
			blur: function( event ) {
				if ( this.cancelBlur ) {
					delete this.cancelBlur;
					return;
				}

				clearTimeout( this.searching );
				this.close( event );
				this._change( event );
			}
		});

		this._initSource();
		this.menu = $( "<ul>" )
			.addClass( "ui-autocomplete" )
			.appendTo( this._appendTo() )
			.menu({
				// custom key handling for now
				input: $(),
				// disable ARIA support, the live region takes care of that
				role: null
			})
			.zIndex( this.element.zIndex() + 1 )
			.hide()
			.data( "ui-menu" );

		this._on( this.menu.element, {
			mousedown: function( event ) {
				// prevent moving focus out of the text field
				event.preventDefault();

				// IE doesn't prevent moving focus even with event.preventDefault()
				// so we set a flag to know when we should ignore the blur event
				this.cancelBlur = true;
				this._delay(function() {
					delete this.cancelBlur;
				});

				// clicking on the scrollbar causes focus to shift to the body
				// but we can't detect a mouseup or a click immediately afterward
				// so we have to track the next mousedown and close the menu if
				// the user clicks somewhere outside of the autocomplete
				var menuElement = this.menu.element[ 0 ];
				if ( !$( event.target ).closest( ".ui-menu-item" ).length ) {
					this._delay(function() {
						var that = this;
						this.document.one( "mousedown", function( event ) {
							if ( event.target !== that.element[ 0 ] &&
									event.target !== menuElement &&
									!$.contains( menuElement, event.target ) ) {
								that.close();
							}
						});
					});
				}
			},
			menufocus: function( event, ui ) {
				// #7024 - Prevent accidental activation of menu items in Firefox
				if ( this.isNewMenu ) {
					this.isNewMenu = false;
					if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
						this.menu.blur();

						this.document.one( "mousemove", function() {
							$( event.target ).trigger( event.originalEvent );
						});

						return;
					}
				}

				var item = ui.item.data( "ui-autocomplete-item" );
				if ( false !== this._trigger( "focus", event, { item: item } ) ) {
					// use value to match what will end up in the input, if it was a key event
					if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
						this._value( item.value );
					}
				} else {
					// Normally the input is populated with the item's value as the
					// menu is navigated, causing screen readers to notice a change and
					// announce the item. Since the focus event was canceled, this doesn't
					// happen, so we update the live region so that screen readers can
					// still notice the change and announce it.
					this.liveRegion.text( item.value );
				}
			},
			menuselect: function( event, ui ) {
				var item = ui.item.data( "ui-autocomplete-item" ),
					previous = this.previous;

				// only trigger when focus was lost (click on menu)
				if ( this.element[0] !== this.document[0].activeElement ) {
					this.element.focus();
					this.previous = previous;
					// #6109 - IE triggers two focus events and the second
					// is asynchronous, so we need to reset the previous
					// term synchronously and asynchronously :-(
					this._delay(function() {
						this.previous = previous;
						this.selectedItem = item;
					});
				}

				if ( false !== this._trigger( "select", event, { item: item } ) ) {
					this._value( item.value );
				}
				// reset the term after the select event
				// this allows custom select handling to work properly
				this.term = this._value();

				this.close( event );
				this.selectedItem = item;
			}
		});

		this.liveRegion = $( "<span>", {
				role: "status",
				"aria-live": "polite"
			})
			.addClass( "ui-helper-hidden-accessible" )
			.insertAfter( this.element );

		// turning off autocomplete prevents the browser from remembering the
		// value when navigating through history, so we re-enable autocomplete
		// if the page is unloaded before the widget is destroyed. #7790
		this._on( this.window, {
			beforeunload: function() {
				this.element.removeAttr( "autocomplete" );
			}
		});
	},

	_destroy: function() {
		clearTimeout( this.searching );
		this.element
			.removeClass( "ui-autocomplete-input" )
			.removeAttr( "autocomplete" );
		this.menu.element.remove();
		this.liveRegion.remove();
	},

	_setOption: function( key, value ) {
		this._super( key, value );
		if ( key === "source" ) {
			this._initSource();
		}
		if ( key === "appendTo" ) {
			this.menu.element.appendTo( this._appendTo() );
		}
		if ( key === "disabled" && value && this.xhr ) {
			this.xhr.abort();
		}
	},

	_appendTo: function() {
		var element = this.options.appendTo;

		if ( element ) {
			element = element.jquery || element.nodeType ?
				$( element ) :
				this.document.find( element ).eq( 0 );
		}

		if ( !element ) {
			element = this.element.closest( ".ui-front" );
		}

		if ( !element.length ) {
			element = this.document[0].body;
		}

		return element;
	},

	_isMultiLine: function() {
		// Textareas are always multi-line
		if ( this.element.is( "textarea" ) ) {
			return true;
		}
		// Inputs are always single-line, even if inside a contentEditable element
		// IE also treats inputs as contentEditable
		if ( this.element.is( "input" ) ) {
			return false;
		}
		// All other element types are determined by whether or not they're contentEditable
		return this.element.prop( "isContentEditable" );
	},

	_initSource: function() {
		var array, url,
			that = this;
		if ( $.isArray(this.options.source) ) {
			array = this.options.source;
			this.source = function( request, response ) {
				response( $.ui.autocomplete.filter( array, request.term ) );
			};
		} else if ( typeof this.options.source === "string" ) {
			url = this.options.source;
			this.source = function( request, response ) {
				if ( that.xhr ) {
					that.xhr.abort();
				}
				that.xhr = $.ajax({
					url: url,
					data: request,
					dataType: "json",
					success: function( data ) {
						response( data );
					},
					error: function() {
						response( [] );
					}
				});
			};
		} else {
			this.source = this.options.source;
		}
	},

	_searchTimeout: function( event ) {
		clearTimeout( this.searching );
		this.searching = this._delay(function() {
			// only search if the value has changed
			if ( this.term !== this._value() ) {
				this.selectedItem = null;
				this.search( null, event );
			}
		}, this.options.delay );
	},

	search: function( value, event ) {
		value = value != null ? value : this._value();

		// always save the actual value, not the one passed as an argument
		this.term = this._value();

		if ( value.length < this.options.minLength ) {
			return this.close( event );
		}

		if ( this._trigger( "search", event ) === false ) {
			return;
		}

		return this._search( value );
	},

	_search: function( value ) {
		this.pending++;
		this.element.addClass( "ui-autocomplete-loading" );
		this.cancelSearch = false;

		this.source( { term: value }, this._response() );
	},

	_response: function() {
		var that = this,
			index = ++requestIndex;

		return function( content ) {
			if ( index === requestIndex ) {
				that.__response( content );
			}

			that.pending--;
			if ( !that.pending ) {
				that.element.removeClass( "ui-autocomplete-loading" );
			}
		};
	},

	__response: function( content ) {
		if ( content ) {
			content = this._normalize( content );
		}
		this._trigger( "response", null, { content: content } );
		if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
			this._suggest( content );
			this._trigger( "open" );
		} else {
			// use ._close() instead of .close() so we don't cancel future searches
			this._close();
		}
	},

	close: function( event ) {
		this.cancelSearch = true;
		this._close( event );
	},

	_close: function( event ) {
		if ( this.menu.element.is( ":visible" ) ) {
			this.menu.element.hide();
			this.menu.blur();
			this.isNewMenu = true;
			this._trigger( "close", event );
		}
	},

	_change: function( event ) {
		if ( this.previous !== this._value() ) {
			this._trigger( "change", event, { item: this.selectedItem } );
		}
	},

	_normalize: function( items ) {
		// assume all items have the right format when the first item is complete
		if ( items.length && items[0].label && items[0].value ) {
			return items;
		}
		return $.map( items, function( item ) {
			if ( typeof item === "string" ) {
				return {
					label: item,
					value: item
				};
			}
			return $.extend({
				label: item.label || item.value,
				value: item.value || item.label
			}, item );
		});
	},

	_suggest: function( items ) {
		var ul = this.menu.element
			.empty()
			.zIndex( this.element.zIndex() + 1 );
		this._renderMenu( ul, items );
		this.menu.refresh();

		// size and position menu
		ul.show();
		this._resizeMenu();
		ul.position( $.extend({
			of: this.element
		}, this.options.position ));

		if ( this.options.autoFocus ) {
			this.menu.next();
		}
	},

	_resizeMenu: function() {
		var ul = this.menu.element;
		ul.outerWidth( Math.max(
			// Firefox wraps long text (possibly a rounding bug)
			// so we add 1px to avoid the wrapping (#7513)
			ul.width( "" ).outerWidth() + 1,
			this.element.outerWidth()
		) );
	},

	_renderMenu: function( ul, items ) {
		var that = this;
		$.each( items, function( index, item ) {
			that._renderItemData( ul, item );
		});
	},

	_renderItemData: function( ul, item ) {
		return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
	},

	_renderItem: function( ul, item ) {
		return $( "<li>" )
			.append( $( "<a>" ).text( item.label ) )
			.appendTo( ul );
	},

	_move: function( direction, event ) {
		if ( !this.menu.element.is( ":visible" ) ) {
			this.search( null, event );
			return;
		}
		if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
				this.menu.isLastItem() && /^next/.test( direction ) ) {
			this._value( this.term );
			this.menu.blur();
			return;
		}
		this.menu[ direction ]( event );
	},

	widget: function() {
		return this.menu.element;
	},

	_value: function() {
		return this.valueMethod.apply( this.element, arguments );
	},

	_keyEvent: function( keyEvent, event ) {
		if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
			this._move( keyEvent, event );

			// prevents moving cursor to beginning/end of the text field in some browsers
			event.preventDefault();
		}
	}
});

$.extend( $.ui.autocomplete, {
	escapeRegex: function( value ) {
		return value.replace(/[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&");
	},
	filter: function(array, term) {
		var matcher = new RegExp( $.ui.autocomplete.escapeRegex(term), "i" );
		return $.grep( array, function(value) {
			return matcher.test( value.label || value.value || value );
		});
	}
});


// live region extension, adding a `messages` option
// NOTE: This is an experimental API. We are still investigating
// a full solution for string manipulation and internationalization.
$.widget( "ui.autocomplete", $.ui.autocomplete, {
	options: {
		messages: {
			noResults: "No search results.",
			results: function( amount ) {
				return amount + ( amount > 1 ? " results are" : " result is" ) +
					" available, use up and down arrow keys to navigate.";
			}
		}
	},

	__response: function( content ) {
		var message;
		this._superApply( arguments );
		if ( this.options.disabled || this.cancelSearch ) {
			return;
		}
		if ( content && content.length ) {
			message = this.options.messages.results( content.length );
		} else {
			message = this.options.messages.noResults;
		}
		this.liveRegion.text( message );
	}
});

}( jQuery ));

// file: 000-1-120-jquery.ui.button.js
/*!
 * jQuery UI Button 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/button/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

var lastActive, startXPos, startYPos, clickDragged,
	baseClasses = "ui-button ui-widget ui-state-default ui-corner-all",
	stateClasses = "ui-state-hover ui-state-active ",
	typeClasses = "ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only",
	formResetHandler = function() {
		var buttons = $( this ).find( ":ui-button" );
		setTimeout(function() {
			buttons.button( "refresh" );
		}, 1 );
	},
	radioGroup = function( radio ) {
		var name = radio.name,
			form = radio.form,
			radios = $( [] );
		if ( name ) {
			name = name.replace( /'/g, "\\'" );
			if ( form ) {
				radios = $( form ).find( "[name='" + name + "']" );
			} else {
				radios = $( "[name='" + name + "']", radio.ownerDocument )
					.filter(function() {
						return !this.form;
					});
			}
		}
		return radios;
	};

$.widget( "ui.button", {
	version: "1.10.0",
	defaultElement: "<button>",
	options: {
		disabled: null,
		text: true,
		label: null,
		icons: {
			primary: null,
			secondary: null
		}
	},
	_create: function() {
		this.element.closest( "form" )
			.unbind( "reset" + this.eventNamespace )
			.bind( "reset" + this.eventNamespace, formResetHandler );

		if ( typeof this.options.disabled !== "boolean" ) {
			this.options.disabled = !!this.element.prop( "disabled" );
		} else {
			this.element.prop( "disabled", this.options.disabled );
		}

		this._determineButtonType();
		this.hasTitle = !!this.buttonElement.attr( "title" );

		var that = this,
			options = this.options,
			toggleButton = this.type === "checkbox" || this.type === "radio",
			activeClass = !toggleButton ? "ui-state-active" : "",
			focusClass = "ui-state-focus";

		if ( options.label === null ) {
			options.label = (this.type === "input" ? this.buttonElement.val() : this.buttonElement.html());
		}

		this._hoverable( this.buttonElement );

		this.buttonElement
			.addClass( baseClasses )
			.attr( "role", "button" )
			.bind( "mouseenter" + this.eventNamespace, function() {
				if ( options.disabled ) {
					return;
				}
				if ( this === lastActive ) {
					$( this ).addClass( "ui-state-active" );
				}
			})
			.bind( "mouseleave" + this.eventNamespace, function() {
				if ( options.disabled ) {
					return;
				}
				$( this ).removeClass( activeClass );
			})
			.bind( "click" + this.eventNamespace, function( event ) {
				if ( options.disabled ) {
					event.preventDefault();
					event.stopImmediatePropagation();
				}
			});

		this.element
			.bind( "focus" + this.eventNamespace, function() {
				// no need to check disabled, focus won't be triggered anyway
				that.buttonElement.addClass( focusClass );
			})
			.bind( "blur" + this.eventNamespace, function() {
				that.buttonElement.removeClass( focusClass );
			});

		if ( toggleButton ) {
			this.element.bind( "change" + this.eventNamespace, function() {
				if ( clickDragged ) {
					return;
				}
				that.refresh();
			});
			// if mouse moves between mousedown and mouseup (drag) set clickDragged flag
			// prevents issue where button state changes but checkbox/radio checked state
			// does not in Firefox (see ticket #6970)
			this.buttonElement
				.bind( "mousedown" + this.eventNamespace, function( event ) {
					if ( options.disabled ) {
						return;
					}
					clickDragged = false;
					startXPos = event.pageX;
					startYPos = event.pageY;
				})
				.bind( "mouseup" + this.eventNamespace, function( event ) {
					if ( options.disabled ) {
						return;
					}
					if ( startXPos !== event.pageX || startYPos !== event.pageY ) {
						clickDragged = true;
					}
			});
		}

		if ( this.type === "checkbox" ) {
			this.buttonElement.bind( "click" + this.eventNamespace, function() {
				if ( options.disabled || clickDragged ) {
					return false;
				}
			});
		} else if ( this.type === "radio" ) {
			this.buttonElement.bind( "click" + this.eventNamespace, function() {
				if ( options.disabled || clickDragged ) {
					return false;
				}
				$( this ).addClass( "ui-state-active" );
				that.buttonElement.attr( "aria-pressed", "true" );

				var radio = that.element[ 0 ];
				radioGroup( radio )
					.not( radio )
					.map(function() {
						return $( this ).button( "widget" )[ 0 ];
					})
					.removeClass( "ui-state-active" )
					.attr( "aria-pressed", "false" );
			});
		} else {
			this.buttonElement
				.bind( "mousedown" + this.eventNamespace, function() {
					if ( options.disabled ) {
						return false;
					}
					$( this ).addClass( "ui-state-active" );
					lastActive = this;
					that.document.one( "mouseup", function() {
						lastActive = null;
					});
				})
				.bind( "mouseup" + this.eventNamespace, function() {
					if ( options.disabled ) {
						return false;
					}
					$( this ).removeClass( "ui-state-active" );
				})
				.bind( "keydown" + this.eventNamespace, function(event) {
					if ( options.disabled ) {
						return false;
					}
					if ( event.keyCode === $.ui.keyCode.SPACE || event.keyCode === $.ui.keyCode.ENTER ) {
						$( this ).addClass( "ui-state-active" );
					}
				})
				// see #8559, we bind to blur here in case the button element loses
				// focus between keydown and keyup, it would be left in an "active" state
				.bind( "keyup" + this.eventNamespace + " blur" + this.eventNamespace, function() {
					$( this ).removeClass( "ui-state-active" );
				});

			if ( this.buttonElement.is("a") ) {
				this.buttonElement.keyup(function(event) {
					if ( event.keyCode === $.ui.keyCode.SPACE ) {
						// TODO pass through original event correctly (just as 2nd argument doesn't work)
						$( this ).click();
					}
				});
			}
		}

		// TODO: pull out $.Widget's handling for the disabled option into
		// $.Widget.prototype._setOptionDisabled so it's easy to proxy and can
		// be overridden by individual plugins
		this._setOption( "disabled", options.disabled );
		this._resetButton();
	},

	_determineButtonType: function() {
		var ancestor, labelSelector, checked;

		if ( this.element.is("[type=checkbox]") ) {
			this.type = "checkbox";
		} else if ( this.element.is("[type=radio]") ) {
			this.type = "radio";
		} else if ( this.element.is("input") ) {
			this.type = "input";
		} else {
			this.type = "button";
		}

		if ( this.type === "checkbox" || this.type === "radio" ) {
			// we don't search against the document in case the element
			// is disconnected from the DOM
			ancestor = this.element.parents().last();
			labelSelector = "label[for='" + this.element.attr("id") + "']";
			this.buttonElement = ancestor.find( labelSelector );
			if ( !this.buttonElement.length ) {
				ancestor = ancestor.length ? ancestor.siblings() : this.element.siblings();
				this.buttonElement = ancestor.filter( labelSelector );
				if ( !this.buttonElement.length ) {
					this.buttonElement = ancestor.find( labelSelector );
				}
			}
			this.element.addClass( "ui-helper-hidden-accessible" );

			checked = this.element.is( ":checked" );
			if ( checked ) {
				this.buttonElement.addClass( "ui-state-active" );
			}
			this.buttonElement.prop( "aria-pressed", checked );
		} else {
			this.buttonElement = this.element;
		}
	},

	widget: function() {
		return this.buttonElement;
	},

	_destroy: function() {
		this.element
			.removeClass( "ui-helper-hidden-accessible" );
		this.buttonElement
			.removeClass( baseClasses + " " + stateClasses + " " + typeClasses )
			.removeAttr( "role" )
			.removeAttr( "aria-pressed" )
			.html( this.buttonElement.find(".ui-button-text").html() );

		if ( !this.hasTitle ) {
			this.buttonElement.removeAttr( "title" );
		}
	},

	_setOption: function( key, value ) {
		this._super( key, value );
		if ( key === "disabled" ) {
			if ( value ) {
				this.element.prop( "disabled", true );
			} else {
				this.element.prop( "disabled", false );
			}
			return;
		}
		this._resetButton();
	},

	refresh: function() {
		//See #8237 & #8828
		var isDisabled = this.element.is( "input, button" ) ? this.element.is( ":disabled" ) : this.element.hasClass( "ui-button-disabled" );

		if ( isDisabled !== this.options.disabled ) {
			this._setOption( "disabled", isDisabled );
		}
		if ( this.type === "radio" ) {
			radioGroup( this.element[0] ).each(function() {
				if ( $( this ).is( ":checked" ) ) {
					$( this ).button( "widget" )
						.addClass( "ui-state-active" )
						.attr( "aria-pressed", "true" );
				} else {
					$( this ).button( "widget" )
						.removeClass( "ui-state-active" )
						.attr( "aria-pressed", "false" );
				}
			});
		} else if ( this.type === "checkbox" ) {
			if ( this.element.is( ":checked" ) ) {
				this.buttonElement
					.addClass( "ui-state-active" )
					.attr( "aria-pressed", "true" );
			} else {
				this.buttonElement
					.removeClass( "ui-state-active" )
					.attr( "aria-pressed", "false" );
			}
		}
	},

	_resetButton: function() {
		if ( this.type === "input" ) {
			if ( this.options.label ) {
				this.element.val( this.options.label );
			}
			return;
		}
		var buttonElement = this.buttonElement.removeClass( typeClasses ),
			buttonText = $( "<span></span>", this.document[0] )
				.addClass( "ui-button-text" )
				.html( this.options.label )
				.appendTo( buttonElement.empty() )
				.text(),
			icons = this.options.icons,
			multipleIcons = icons.primary && icons.secondary,
			buttonClasses = [];

		if ( icons.primary || icons.secondary ) {
			if ( this.options.text ) {
				buttonClasses.push( "ui-button-text-icon" + ( multipleIcons ? "s" : ( icons.primary ? "-primary" : "-secondary" ) ) );
			}

			if ( icons.primary ) {
				buttonElement.prepend( "<span class='ui-button-icon-primary ui-icon " + icons.primary + "'></span>" );
			}

			if ( icons.secondary ) {
				buttonElement.append( "<span class='ui-button-icon-secondary ui-icon " + icons.secondary + "'></span>" );
			}

			if ( !this.options.text ) {
				buttonClasses.push( multipleIcons ? "ui-button-icons-only" : "ui-button-icon-only" );

				if ( !this.hasTitle ) {
					buttonElement.attr( "title", $.trim( buttonText ) );
				}
			}
		} else {
			buttonClasses.push( "ui-button-text-only" );
		}
		buttonElement.addClass( buttonClasses.join( " " ) );
	}
});

$.widget( "ui.buttonset", {
	version: "1.10.0",
	options: {
		items: "button, input[type=button], input[type=submit], input[type=reset], input[type=checkbox], input[type=radio], a, :data(ui-button)"
	},

	_create: function() {
		this.element.addClass( "ui-buttonset" );
	},

	_init: function() {
		this.refresh();
	},

	_setOption: function( key, value ) {
		if ( key === "disabled" ) {
			this.buttons.button( "option", key, value );
		}

		this._super( key, value );
	},

	refresh: function() {
		var rtl = this.element.css( "direction" ) === "rtl";

		this.buttons = this.element.find( this.options.items )
			.filter( ":ui-button" )
				.button( "refresh" )
			.end()
			.not( ":ui-button" )
				.button()
			.end()
			.map(function() {
				return $( this ).button( "widget" )[ 0 ];
			})
				.removeClass( "ui-corner-all ui-corner-left ui-corner-right" )
				.filter( ":first" )
					.addClass( rtl ? "ui-corner-right" : "ui-corner-left" )
				.end()
				.filter( ":last" )
					.addClass( rtl ? "ui-corner-left" : "ui-corner-right" )
				.end()
			.end();
	},

	_destroy: function() {
		this.element.removeClass( "ui-buttonset" );
		this.buttons
			.map(function() {
				return $( this ).button( "widget" )[ 0 ];
			})
				.removeClass( "ui-corner-left ui-corner-right" )
			.end()
			.button( "destroy" );
	}
});

}( jQuery ) );

// file: 000-1-130-jquery.ui.datepicker.js
/*!
 * jQuery UI Datepicker 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/datepicker/
 *
 * Depends:
 *	jquery.ui.core.js
 */
(function( $, undefined ) {

$.extend($.ui, { datepicker: { version: "1.10.0" } });

var PROP_NAME = "datepicker",
	dpuuid = new Date().getTime(),
	instActive;

/* Date picker manager.
   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
   Settings for (groups of) date pickers are maintained in an instance object,
   allowing multiple different settings on the same page. */

function Datepicker() {
	this._curInst = null; // The current instance in use
	this._keyEvent = false; // If the last event was a key event
	this._disabledInputs = []; // List of date picker inputs that have been disabled
	this._datepickerShowing = false; // True if the popup picker is showing , false if not
	this._inDialog = false; // True if showing within a "dialog", false if not
	this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
	this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
	this._appendClass = "ui-datepicker-append"; // The name of the append marker class
	this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
	this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
	this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
	this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
	this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
	this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
	this.regional = []; // Available regional settings, indexed by language code
	this.regional[""] = { // Default regional settings
		closeText: "Done", // Display text for close link
		prevText: "Prev", // Display text for previous month link
		nextText: "Next", // Display text for next month link
		currentText: "Today", // Display text for current month link
		monthNames: ["January","February","March","April","May","June",
			"July","August","September","October","November","December"], // Names of months for drop-down and formatting
		monthNamesShort: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"], // For formatting
		dayNames: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"], // For formatting
		dayNamesShort: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"], // For formatting
		dayNamesMin: ["Su","Mo","Tu","We","Th","Fr","Sa"], // Column headings for days starting at Sunday
		weekHeader: "Wk", // Column header for week of the year
		dateFormat: "mm/dd/yy", // See format options on parseDate
		firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
		isRTL: false, // True if right-to-left language, false if left-to-right
		showMonthAfterYear: false, // True if the year select precedes month, false for month then year
		yearSuffix: "" // Additional text to append to the year in the month headers
	};
	this._defaults = { // Global defaults for all the date picker instances
		showOn: "focus", // "focus" for popup on focus,
			// "button" for trigger button, or "both" for either
		showAnim: "fadeIn", // Name of jQuery animation for popup
		showOptions: {}, // Options for enhanced animations
		defaultDate: null, // Used when field is blank: actual date,
			// +/-number for offset from today, null for today
		appendText: "", // Display text following the input box, e.g. showing the format
		buttonText: "...", // Text for trigger button
		buttonImage: "", // URL for trigger button image
		buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
		hideIfNoPrevNext: false, // True to hide next/previous month links
			// if not applicable, false to just disable them
		navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
		gotoCurrent: false, // True if today link goes back to current selection instead
		changeMonth: false, // True if month can be selected directly, false if only prev/next
		changeYear: false, // True if year can be selected directly, false if only prev/next
		yearRange: "c-10:c+10", // Range of years to display in drop-down,
			// either relative to today's year (-nn:+nn), relative to currently displayed year
			// (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
		showOtherMonths: false, // True to show dates in other months, false to leave blank
		selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
		showWeek: false, // True to show week of the year, false to not show it
		calculateWeek: this.iso8601Week, // How to calculate the week of the year,
			// takes a Date and returns the number of the week for it
		shortYearCutoff: "+10", // Short year values < this are in the current century,
			// > this are in the previous century,
			// string value starting with "+" for current year + value
		minDate: null, // The earliest selectable date, or null for no limit
		maxDate: null, // The latest selectable date, or null for no limit
		duration: "fast", // Duration of display/closure
		beforeShowDay: null, // Function that takes a date and returns an array with
			// [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
			// [2] = cell title (optional), e.g. $.datepicker.noWeekends
		beforeShow: null, // Function that takes an input field and
			// returns a set of custom settings for the date picker
		onSelect: null, // Define a callback function when a date is selected
		onChangeMonthYear: null, // Define a callback function when the month or year is changed
		onClose: null, // Define a callback function when the datepicker is closed
		numberOfMonths: 1, // Number of months to show at a time
		showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
		stepMonths: 1, // Number of months to step back/forward
		stepBigMonths: 12, // Number of months to step back/forward for the big links
		altField: "", // Selector for an alternate field to store selected dates into
		altFormat: "", // The date format to use for the alternate field
		constrainInput: true, // The input is constrained by the current date format
		showButtonPanel: false, // True to show button panel, false to not show it
		autoSize: false, // True to size the input for the date format, false to leave as is
		disabled: false // The initial disabled state
	};
	$.extend(this._defaults, this.regional[""]);
	this.dpDiv = bindHover($("<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>"));
}

$.extend(Datepicker.prototype, {
	/* Class name added to elements to indicate already configured with a date picker. */
	markerClassName: "hasDatepicker",

	//Keep track of the maximum number of rows displayed (see #7043)
	maxRows: 4,

	// TODO rename to "widget" when switching to widget factory
	_widgetDatepicker: function() {
		return this.dpDiv;
	},

	/* Override the default settings for all instances of the date picker.
	 * @param  settings  object - the new settings to use as defaults (anonymous object)
	 * @return the manager object
	 */
	setDefaults: function(settings) {
		extendRemove(this._defaults, settings || {});
		return this;
	},

	/* Attach the date picker to a jQuery selection.
	 * @param  target	element - the target input field or division or span
	 * @param  settings  object - the new settings to use for this date picker instance (anonymous)
	 */
	_attachDatepicker: function(target, settings) {
		var nodeName, inline, inst;
		nodeName = target.nodeName.toLowerCase();
		inline = (nodeName === "div" || nodeName === "span");
		if (!target.id) {
			this.uuid += 1;
			target.id = "dp" + this.uuid;
		}
		inst = this._newInst($(target), inline);
		inst.settings = $.extend({}, settings || {});
		if (nodeName === "input") {
			this._connectDatepicker(target, inst);
		} else if (inline) {
			this._inlineDatepicker(target, inst);
		}
	},

	/* Create a new instance object. */
	_newInst: function(target, inline) {
		var id = target[0].id.replace(/([^A-Za-z0-9_\-])/g, "\\\\$1"); // escape jQuery meta chars
		return {id: id, input: target, // associated target
			selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
			drawMonth: 0, drawYear: 0, // month being drawn
			inline: inline, // is datepicker inline or not
			dpDiv: (!inline ? this.dpDiv : // presentation div
			bindHover($("<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>")))};
	},

	/* Attach the date picker to an input field. */
	_connectDatepicker: function(target, inst) {
		var input = $(target);
		inst.append = $([]);
		inst.trigger = $([]);
		if (input.hasClass(this.markerClassName)) {
			return;
		}
		this._attachments(input, inst);
		input.addClass(this.markerClassName).keydown(this._doKeyDown).
			keypress(this._doKeyPress).keyup(this._doKeyUp);
		this._autoSize(inst);
		$.data(target, PROP_NAME, inst);
		//If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
		if( inst.settings.disabled ) {
			this._disableDatepicker( target );
		}
	},

	/* Make attachments based on settings. */
	_attachments: function(input, inst) {
		var showOn, buttonText, buttonImage,
			appendText = this._get(inst, "appendText"),
			isRTL = this._get(inst, "isRTL");

		if (inst.append) {
			inst.append.remove();
		}
		if (appendText) {
			inst.append = $("<span class='" + this._appendClass + "'>" + appendText + "</span>");
			input[isRTL ? "before" : "after"](inst.append);
		}

		input.unbind("focus", this._showDatepicker);

		if (inst.trigger) {
			inst.trigger.remove();
		}

		showOn = this._get(inst, "showOn");
		if (showOn === "focus" || showOn === "both") { // pop-up date picker when in the marked field
			input.focus(this._showDatepicker);
		}
		if (showOn === "button" || showOn === "both") { // pop-up date picker when button clicked
			buttonText = this._get(inst, "buttonText");
			buttonImage = this._get(inst, "buttonImage");
			inst.trigger = $(this._get(inst, "buttonImageOnly") ?
				$("<img/>").addClass(this._triggerClass).
					attr({ src: buttonImage, alt: buttonText, title: buttonText }) :
				$("<button type='button'></button>").addClass(this._triggerClass).
					html(!buttonImage ? buttonText : $("<img/>").attr(
					{ src:buttonImage, alt:buttonText, title:buttonText })));
			input[isRTL ? "before" : "after"](inst.trigger);
			inst.trigger.click(function() {
				if ($.datepicker._datepickerShowing && $.datepicker._lastInput === input[0]) {
					$.datepicker._hideDatepicker();
				} else if ($.datepicker._datepickerShowing && $.datepicker._lastInput !== input[0]) {
					$.datepicker._hideDatepicker();
					$.datepicker._showDatepicker(input[0]);
				} else {
					$.datepicker._showDatepicker(input[0]);
				}
				return false;
			});
		}
	},

	/* Apply the maximum length for the date format. */
	_autoSize: function(inst) {
		if (this._get(inst, "autoSize") && !inst.inline) {
			var findMax, max, maxI, i,
				date = new Date(2009, 12 - 1, 20), // Ensure double digits
				dateFormat = this._get(inst, "dateFormat");

			if (dateFormat.match(/[DM]/)) {
				findMax = function(names) {
					max = 0;
					maxI = 0;
					for (i = 0; i < names.length; i++) {
						if (names[i].length > max) {
							max = names[i].length;
							maxI = i;
						}
					}
					return maxI;
				};
				date.setMonth(findMax(this._get(inst, (dateFormat.match(/MM/) ?
					"monthNames" : "monthNamesShort"))));
				date.setDate(findMax(this._get(inst, (dateFormat.match(/DD/) ?
					"dayNames" : "dayNamesShort"))) + 20 - date.getDay());
			}
			inst.input.attr("size", this._formatDate(inst, date).length);
		}
	},

	/* Attach an inline date picker to a div. */
	_inlineDatepicker: function(target, inst) {
		var divSpan = $(target);
		if (divSpan.hasClass(this.markerClassName)) {
			return;
		}
		divSpan.addClass(this.markerClassName).append(inst.dpDiv);
		$.data(target, PROP_NAME, inst);
		this._setDate(inst, this._getDefaultDate(inst), true);
		this._updateDatepicker(inst);
		this._updateAlternate(inst);
		//If disabled option is true, disable the datepicker before showing it (see ticket #5665)
		if( inst.settings.disabled ) {
			this._disableDatepicker( target );
		}
		// Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
		// http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
		inst.dpDiv.css( "display", "block" );
	},

	/* Pop-up the date picker in a "dialog" box.
	 * @param  input element - ignored
	 * @param  date	string or Date - the initial date to display
	 * @param  onSelect  function - the function to call when a date is selected
	 * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
	 * @param  pos int[2] - coordinates for the dialog's position within the screen or
	 *					event - with x/y coordinates or
	 *					leave empty for default (screen centre)
	 * @return the manager object
	 */
	_dialogDatepicker: function(input, date, onSelect, settings, pos) {
		var id, browserWidth, browserHeight, scrollX, scrollY,
			inst = this._dialogInst; // internal instance

		if (!inst) {
			this.uuid += 1;
			id = "dp" + this.uuid;
			this._dialogInput = $("<input type='text' id='" + id +
				"' style='position: absolute; top: -100px; width: 0px;'/>");
			this._dialogInput.keydown(this._doKeyDown);
			$("body").append(this._dialogInput);
			inst = this._dialogInst = this._newInst(this._dialogInput, false);
			inst.settings = {};
			$.data(this._dialogInput[0], PROP_NAME, inst);
		}
		extendRemove(inst.settings, settings || {});
		date = (date && date.constructor === Date ? this._formatDate(inst, date) : date);
		this._dialogInput.val(date);

		this._pos = (pos ? (pos.length ? pos : [pos.pageX, pos.pageY]) : null);
		if (!this._pos) {
			browserWidth = document.documentElement.clientWidth;
			browserHeight = document.documentElement.clientHeight;
			scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
			scrollY = document.documentElement.scrollTop || document.body.scrollTop;
			this._pos = // should use actual width/height below
				[(browserWidth / 2) - 100 + scrollX, (browserHeight / 2) - 150 + scrollY];
		}

		// move input on screen for focus, but hidden behind dialog
		this._dialogInput.css("left", (this._pos[0] + 20) + "px").css("top", this._pos[1] + "px");
		inst.settings.onSelect = onSelect;
		this._inDialog = true;
		this.dpDiv.addClass(this._dialogClass);
		this._showDatepicker(this._dialogInput[0]);
		if ($.blockUI) {
			$.blockUI(this.dpDiv);
		}
		$.data(this._dialogInput[0], PROP_NAME, inst);
		return this;
	},

	/* Detach a datepicker from its control.
	 * @param  target	element - the target input field or division or span
	 */
	_destroyDatepicker: function(target) {
		var nodeName,
			$target = $(target),
			inst = $.data(target, PROP_NAME);

		if (!$target.hasClass(this.markerClassName)) {
			return;
		}

		nodeName = target.nodeName.toLowerCase();
		$.removeData(target, PROP_NAME);
		if (nodeName === "input") {
			inst.append.remove();
			inst.trigger.remove();
			$target.removeClass(this.markerClassName).
				unbind("focus", this._showDatepicker).
				unbind("keydown", this._doKeyDown).
				unbind("keypress", this._doKeyPress).
				unbind("keyup", this._doKeyUp);
		} else if (nodeName === "div" || nodeName === "span") {
			$target.removeClass(this.markerClassName).empty();
		}
	},

	/* Enable the date picker to a jQuery selection.
	 * @param  target	element - the target input field or division or span
	 */
	_enableDatepicker: function(target) {
		var nodeName, inline,
			$target = $(target),
			inst = $.data(target, PROP_NAME);

		if (!$target.hasClass(this.markerClassName)) {
			return;
		}

		nodeName = target.nodeName.toLowerCase();
		if (nodeName === "input") {
			target.disabled = false;
			inst.trigger.filter("button").
				each(function() { this.disabled = false; }).end().
				filter("img").css({opacity: "1.0", cursor: ""});
		} else if (nodeName === "div" || nodeName === "span") {
			inline = $target.children("." + this._inlineClass);
			inline.children().removeClass("ui-state-disabled");
			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
				prop("disabled", false);
		}
		this._disabledInputs = $.map(this._disabledInputs,
			function(value) { return (value === target ? null : value); }); // delete entry
	},

	/* Disable the date picker to a jQuery selection.
	 * @param  target	element - the target input field or division or span
	 */
	_disableDatepicker: function(target) {
		var nodeName, inline,
			$target = $(target),
			inst = $.data(target, PROP_NAME);

		if (!$target.hasClass(this.markerClassName)) {
			return;
		}

		nodeName = target.nodeName.toLowerCase();
		if (nodeName === "input") {
			target.disabled = true;
			inst.trigger.filter("button").
				each(function() { this.disabled = true; }).end().
				filter("img").css({opacity: "0.5", cursor: "default"});
		} else if (nodeName === "div" || nodeName === "span") {
			inline = $target.children("." + this._inlineClass);
			inline.children().addClass("ui-state-disabled");
			inline.find("select.ui-datepicker-month, select.ui-datepicker-year").
				prop("disabled", true);
		}
		this._disabledInputs = $.map(this._disabledInputs,
			function(value) { return (value === target ? null : value); }); // delete entry
		this._disabledInputs[this._disabledInputs.length] = target;
	},

	/* Is the first field in a jQuery collection disabled as a datepicker?
	 * @param  target	element - the target input field or division or span
	 * @return boolean - true if disabled, false if enabled
	 */
	_isDisabledDatepicker: function(target) {
		if (!target) {
			return false;
		}
		for (var i = 0; i < this._disabledInputs.length; i++) {
			if (this._disabledInputs[i] === target) {
				return true;
			}
		}
		return false;
	},

	/* Retrieve the instance data for the target control.
	 * @param  target  element - the target input field or division or span
	 * @return  object - the associated instance data
	 * @throws  error if a jQuery problem getting data
	 */
	_getInst: function(target) {
		try {
			return $.data(target, PROP_NAME);
		}
		catch (err) {
			throw "Missing instance data for this datepicker";
		}
	},

	/* Update or retrieve the settings for a date picker attached to an input field or division.
	 * @param  target  element - the target input field or division or span
	 * @param  name	object - the new settings to update or
	 *				string - the name of the setting to change or retrieve,
	 *				when retrieving also "all" for all instance settings or
	 *				"defaults" for all global defaults
	 * @param  value   any - the new value for the setting
	 *				(omit if above is an object or to retrieve a value)
	 */
	_optionDatepicker: function(target, name, value) {
		var settings, date, minDate, maxDate,
			inst = this._getInst(target);

		if (arguments.length === 2 && typeof name === "string") {
			return (name === "defaults" ? $.extend({}, $.datepicker._defaults) :
				(inst ? (name === "all" ? $.extend({}, inst.settings) :
				this._get(inst, name)) : null));
		}

		settings = name || {};
		if (typeof name === "string") {
			settings = {};
			settings[name] = value;
		}

		if (inst) {
			if (this._curInst === inst) {
				this._hideDatepicker();
			}

			date = this._getDateDatepicker(target, true);
			minDate = this._getMinMaxDate(inst, "min");
			maxDate = this._getMinMaxDate(inst, "max");
			extendRemove(inst.settings, settings);
			// reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
			if (minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined) {
				inst.settings.minDate = this._formatDate(inst, minDate);
			}
			if (maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined) {
				inst.settings.maxDate = this._formatDate(inst, maxDate);
			}
			if ( "disabled" in settings ) {
				if ( settings.disabled ) {
					this._disableDatepicker(target);
				} else {
					this._enableDatepicker(target);
				}
			}
			this._attachments($(target), inst);
			this._autoSize(inst);
			this._setDate(inst, date);
			this._updateAlternate(inst);
			this._updateDatepicker(inst);
		}
	},

	// change method deprecated
	_changeDatepicker: function(target, name, value) {
		this._optionDatepicker(target, name, value);
	},

	/* Redraw the date picker attached to an input field or division.
	 * @param  target  element - the target input field or division or span
	 */
	_refreshDatepicker: function(target) {
		var inst = this._getInst(target);
		if (inst) {
			this._updateDatepicker(inst);
		}
	},

	/* Set the dates for a jQuery selection.
	 * @param  target element - the target input field or division or span
	 * @param  date	Date - the new date
	 */
	_setDateDatepicker: function(target, date) {
		var inst = this._getInst(target);
		if (inst) {
			this._setDate(inst, date);
			this._updateDatepicker(inst);
			this._updateAlternate(inst);
		}
	},

	/* Get the date(s) for the first entry in a jQuery selection.
	 * @param  target element - the target input field or division or span
	 * @param  noDefault boolean - true if no default date is to be used
	 * @return Date - the current date
	 */
	_getDateDatepicker: function(target, noDefault) {
		var inst = this._getInst(target);
		if (inst && !inst.inline) {
			this._setDateFromField(inst, noDefault);
		}
		return (inst ? this._getDate(inst) : null);
	},

	/* Handle keystrokes. */
	_doKeyDown: function(event) {
		var onSelect, dateStr, sel,
			inst = $.datepicker._getInst(event.target),
			handled = true,
			isRTL = inst.dpDiv.is(".ui-datepicker-rtl");

		inst._keyEvent = true;
		if ($.datepicker._datepickerShowing) {
			switch (event.keyCode) {
				case 9: $.datepicker._hideDatepicker();
						handled = false;
						break; // hide on tab out
				case 13: sel = $("td." + $.datepicker._dayOverClass + ":not(." +
									$.datepicker._currentClass + ")", inst.dpDiv);
						if (sel[0]) {
							$.datepicker._selectDay(event.target, inst.selectedMonth, inst.selectedYear, sel[0]);
						}

						onSelect = $.datepicker._get(inst, "onSelect");
						if (onSelect) {
							dateStr = $.datepicker._formatDate(inst);

							// trigger custom callback
							onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);
						} else {
							$.datepicker._hideDatepicker();
						}

						return false; // don't submit the form
				case 27: $.datepicker._hideDatepicker();
						break; // hide on escape
				case 33: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
							-$.datepicker._get(inst, "stepBigMonths") :
							-$.datepicker._get(inst, "stepMonths")), "M");
						break; // previous month/year on page up/+ ctrl
				case 34: $.datepicker._adjustDate(event.target, (event.ctrlKey ?
							+$.datepicker._get(inst, "stepBigMonths") :
							+$.datepicker._get(inst, "stepMonths")), "M");
						break; // next month/year on page down/+ ctrl
				case 35: if (event.ctrlKey || event.metaKey) {
							$.datepicker._clearDate(event.target);
						}
						handled = event.ctrlKey || event.metaKey;
						break; // clear on ctrl or command +end
				case 36: if (event.ctrlKey || event.metaKey) {
							$.datepicker._gotoToday(event.target);
						}
						handled = event.ctrlKey || event.metaKey;
						break; // current on ctrl or command +home
				case 37: if (event.ctrlKey || event.metaKey) {
							$.datepicker._adjustDate(event.target, (isRTL ? +1 : -1), "D");
						}
						handled = event.ctrlKey || event.metaKey;
						// -1 day on ctrl or command +left
						if (event.originalEvent.altKey) {
							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
								-$.datepicker._get(inst, "stepBigMonths") :
								-$.datepicker._get(inst, "stepMonths")), "M");
						}
						// next month/year on alt +left on Mac
						break;
				case 38: if (event.ctrlKey || event.metaKey) {
							$.datepicker._adjustDate(event.target, -7, "D");
						}
						handled = event.ctrlKey || event.metaKey;
						break; // -1 week on ctrl or command +up
				case 39: if (event.ctrlKey || event.metaKey) {
							$.datepicker._adjustDate(event.target, (isRTL ? -1 : +1), "D");
						}
						handled = event.ctrlKey || event.metaKey;
						// +1 day on ctrl or command +right
						if (event.originalEvent.altKey) {
							$.datepicker._adjustDate(event.target, (event.ctrlKey ?
								+$.datepicker._get(inst, "stepBigMonths") :
								+$.datepicker._get(inst, "stepMonths")), "M");
						}
						// next month/year on alt +right
						break;
				case 40: if (event.ctrlKey || event.metaKey) {
							$.datepicker._adjustDate(event.target, +7, "D");
						}
						handled = event.ctrlKey || event.metaKey;
						break; // +1 week on ctrl or command +down
				default: handled = false;
			}
		} else if (event.keyCode === 36 && event.ctrlKey) { // display the date picker on ctrl+home
			$.datepicker._showDatepicker(this);
		} else {
			handled = false;
		}

		if (handled) {
			event.preventDefault();
			event.stopPropagation();
		}
	},

	/* Filter entered characters - based on date format. */
	_doKeyPress: function(event) {
		var chars, chr,
			inst = $.datepicker._getInst(event.target);

		if ($.datepicker._get(inst, "constrainInput")) {
			chars = $.datepicker._possibleChars($.datepicker._get(inst, "dateFormat"));
			chr = String.fromCharCode(event.charCode == null ? event.keyCode : event.charCode);
			return event.ctrlKey || event.metaKey || (chr < " " || !chars || chars.indexOf(chr) > -1);
		}
	},

	/* Synchronise manual entry and field/alternate field. */
	_doKeyUp: function(event) {
		var date,
			inst = $.datepicker._getInst(event.target);

		if (inst.input.val() !== inst.lastVal) {
			try {
				date = $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
					(inst.input ? inst.input.val() : null),
					$.datepicker._getFormatConfig(inst));

				if (date) { // only if valid
					$.datepicker._setDateFromField(inst);
					$.datepicker._updateAlternate(inst);
					$.datepicker._updateDatepicker(inst);
				}
			}
			catch (err) {
			}
		}
		return true;
	},

	/* Pop-up the date picker for a given input field.
	 * If false returned from beforeShow event handler do not show.
	 * @param  input  element - the input field attached to the date picker or
	 *					event - if triggered by focus
	 */
	_showDatepicker: function(input) {
		input = input.target || input;
		if (input.nodeName.toLowerCase() !== "input") { // find from button/image trigger
			input = $("input", input.parentNode)[0];
		}

		if ($.datepicker._isDisabledDatepicker(input) || $.datepicker._lastInput === input) { // already here
			return;
		}

		var inst, beforeShow, beforeShowSettings, isFixed,
			offset, showAnim, duration;

		inst = $.datepicker._getInst(input);
		if ($.datepicker._curInst && $.datepicker._curInst !== inst) {
			$.datepicker._curInst.dpDiv.stop(true, true);
			if ( inst && $.datepicker._datepickerShowing ) {
				$.datepicker._hideDatepicker( $.datepicker._curInst.input[0] );
			}
		}

		beforeShow = $.datepicker._get(inst, "beforeShow");
		beforeShowSettings = beforeShow ? beforeShow.apply(input, [input, inst]) : {};
		if(beforeShowSettings === false){
			return;
		}
		extendRemove(inst.settings, beforeShowSettings);

		inst.lastVal = null;
		$.datepicker._lastInput = input;
		$.datepicker._setDateFromField(inst);

		if ($.datepicker._inDialog) { // hide cursor
			input.value = "";
		}
		if (!$.datepicker._pos) { // position below input
			$.datepicker._pos = $.datepicker._findPos(input);
			$.datepicker._pos[1] += input.offsetHeight; // add the height
		}

		isFixed = false;
		$(input).parents().each(function() {
			isFixed |= $(this).css("position") === "fixed";
			return !isFixed;
		});

		offset = {left: $.datepicker._pos[0], top: $.datepicker._pos[1]};
		$.datepicker._pos = null;
		//to avoid flashes on Firefox
		inst.dpDiv.empty();
		// determine sizing offscreen
		inst.dpDiv.css({position: "absolute", display: "block", top: "-1000px"});
		$.datepicker._updateDatepicker(inst);
		// fix width for dynamic number of date pickers
		// and adjust position before showing
		offset = $.datepicker._checkOffset(inst, offset, isFixed);
		inst.dpDiv.css({position: ($.datepicker._inDialog && $.blockUI ?
			"static" : (isFixed ? "fixed" : "absolute")), display: "none",
			left: offset.left + "px", top: offset.top + "px"});

		if (!inst.inline) {
			showAnim = $.datepicker._get(inst, "showAnim");
			duration = $.datepicker._get(inst, "duration");
			inst.dpDiv.zIndex($(input).zIndex()+1);
			$.datepicker._datepickerShowing = true;

			if ( $.effects && $.effects.effect[ showAnim ] ) {
				inst.dpDiv.show(showAnim, $.datepicker._get(inst, "showOptions"), duration);
			} else {
				inst.dpDiv[showAnim || "show"](showAnim ? duration : null);
			}

			if (inst.input.is(":visible") && !inst.input.is(":disabled")) {
				inst.input.focus();
			}
			$.datepicker._curInst = inst;
		}
	},

	/* Generate the date picker content. */
	_updateDatepicker: function(inst) {
		this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
		instActive = inst; // for delegate hover events
		inst.dpDiv.empty().append(this._generateHTML(inst));
		this._attachHandlers(inst);
		inst.dpDiv.find("." + this._dayOverClass + " a").mouseover();

		var origyearshtml,
			numMonths = this._getNumberOfMonths(inst),
			cols = numMonths[1],
			width = 17;

		inst.dpDiv.removeClass("ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4").width("");
		if (cols > 1) {
			inst.dpDiv.addClass("ui-datepicker-multi-" + cols).css("width", (width * cols) + "em");
		}
		inst.dpDiv[(numMonths[0] !== 1 || numMonths[1] !== 1 ? "add" : "remove") +
			"Class"]("ui-datepicker-multi");
		inst.dpDiv[(this._get(inst, "isRTL") ? "add" : "remove") +
			"Class"]("ui-datepicker-rtl");

		// #6694 - don't focus the input if it's already focused
		// this breaks the change event in IE
		if (inst === $.datepicker._curInst && $.datepicker._datepickerShowing && inst.input &&
			inst.input.is(":visible") && !inst.input.is(":disabled") && inst.input[0] !== document.activeElement) {
			inst.input.focus();
		}

		// deffered render of the years select (to avoid flashes on Firefox)
		if( inst.yearshtml ){
			origyearshtml = inst.yearshtml;
			setTimeout(function(){
				//assure that inst.yearshtml didn't change.
				if( origyearshtml === inst.yearshtml && inst.yearshtml ){
					inst.dpDiv.find("select.ui-datepicker-year:first").replaceWith(inst.yearshtml);
				}
				origyearshtml = inst.yearshtml = null;
			}, 0);
		}
	},

	/* Retrieve the size of left and top borders for an element.
	 * @param  elem  (jQuery object) the element of interest
	 * @return  (number[2]) the left and top borders
	 */
	_getBorders: function(elem) {
		var convert = function(value) {
			return {thin: 1, medium: 2, thick: 3}[value] || value;
		};
		return [parseFloat(convert(elem.css("border-left-width"))),
			parseFloat(convert(elem.css("border-top-width")))];
	},

	/* Check positioning to remain on screen. */
	_checkOffset: function(inst, offset, isFixed) {
		var dpWidth = inst.dpDiv.outerWidth(),
			dpHeight = inst.dpDiv.outerHeight(),
			inputWidth = inst.input ? inst.input.outerWidth() : 0,
			inputHeight = inst.input ? inst.input.outerHeight() : 0,
			viewWidth = document.documentElement.clientWidth + (isFixed ? 0 : $(document).scrollLeft()),
			viewHeight = document.documentElement.clientHeight + (isFixed ? 0 : $(document).scrollTop());

		offset.left -= (this._get(inst, "isRTL") ? (dpWidth - inputWidth) : 0);
		offset.left -= (isFixed && offset.left === inst.input.offset().left) ? $(document).scrollLeft() : 0;
		offset.top -= (isFixed && offset.top === (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;

		// now check if datepicker is showing outside window viewport - move to a better place if so.
		offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
			Math.abs(offset.left + dpWidth - viewWidth) : 0);
		offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
			Math.abs(dpHeight + inputHeight) : 0);

		return offset;
	},

	/* Find an object's position on the screen. */
	_findPos: function(obj) {
		var position,
			inst = this._getInst(obj),
			isRTL = this._get(inst, "isRTL");

		while (obj && (obj.type === "hidden" || obj.nodeType !== 1 || $.expr.filters.hidden(obj))) {
			obj = obj[isRTL ? "previousSibling" : "nextSibling"];
		}

		position = $(obj).offset();
		return [position.left, position.top];
	},

	/* Hide the date picker from view.
	 * @param  input  element - the input field attached to the date picker
	 */
	_hideDatepicker: function(input) {
		var showAnim, duration, postProcess, onClose,
			inst = this._curInst;

		if (!inst || (input && inst !== $.data(input, PROP_NAME))) {
			return;
		}

		if (this._datepickerShowing) {
			showAnim = this._get(inst, "showAnim");
			duration = this._get(inst, "duration");
			postProcess = function() {
				$.datepicker._tidyDialog(inst);
			};

			// DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
			if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
				inst.dpDiv.hide(showAnim, $.datepicker._get(inst, "showOptions"), duration, postProcess);
			} else {
				inst.dpDiv[(showAnim === "slideDown" ? "slideUp" :
					(showAnim === "fadeIn" ? "fadeOut" : "hide"))]((showAnim ? duration : null), postProcess);
			}

			if (!showAnim) {
				postProcess();
			}
			this._datepickerShowing = false;

			onClose = this._get(inst, "onClose");
			if (onClose) {
				onClose.apply((inst.input ? inst.input[0] : null), [(inst.input ? inst.input.val() : ""), inst]);
			}

			this._lastInput = null;
			if (this._inDialog) {
				this._dialogInput.css({ position: "absolute", left: "0", top: "-100px" });
				if ($.blockUI) {
					$.unblockUI();
					$("body").append(this.dpDiv);
				}
			}
			this._inDialog = false;
		}
	},

	/* Tidy up after a dialog display. */
	_tidyDialog: function(inst) {
		inst.dpDiv.removeClass(this._dialogClass).unbind(".ui-datepicker-calendar");
	},

	/* Close date picker if clicked elsewhere. */
	_checkExternalClick: function(event) {
		if (!$.datepicker._curInst) {
			return;
		}

		var $target = $(event.target),
			inst = $.datepicker._getInst($target[0]);

		if ( ( ( $target[0].id !== $.datepicker._mainDivId &&
				$target.parents("#" + $.datepicker._mainDivId).length === 0 &&
				!$target.hasClass($.datepicker.markerClassName) &&
				!$target.closest("." + $.datepicker._triggerClass).length &&
				$.datepicker._datepickerShowing && !($.datepicker._inDialog && $.blockUI) ) ) ||
			( $target.hasClass($.datepicker.markerClassName) && $.datepicker._curInst !== inst ) ) {
				$.datepicker._hideDatepicker();
		}
	},

	/* Adjust one of the date sub-fields. */
	_adjustDate: function(id, offset, period) {
		var target = $(id),
			inst = this._getInst(target[0]);

		if (this._isDisabledDatepicker(target[0])) {
			return;
		}
		this._adjustInstDate(inst, offset +
			(period === "M" ? this._get(inst, "showCurrentAtPos") : 0), // undo positioning
			period);
		this._updateDatepicker(inst);
	},

	/* Action for current link. */
	_gotoToday: function(id) {
		var date,
			target = $(id),
			inst = this._getInst(target[0]);

		if (this._get(inst, "gotoCurrent") && inst.currentDay) {
			inst.selectedDay = inst.currentDay;
			inst.drawMonth = inst.selectedMonth = inst.currentMonth;
			inst.drawYear = inst.selectedYear = inst.currentYear;
		} else {
			date = new Date();
			inst.selectedDay = date.getDate();
			inst.drawMonth = inst.selectedMonth = date.getMonth();
			inst.drawYear = inst.selectedYear = date.getFullYear();
		}
		this._notifyChange(inst);
		this._adjustDate(target);
	},

	/* Action for selecting a new month/year. */
	_selectMonthYear: function(id, select, period) {
		var target = $(id),
			inst = this._getInst(target[0]);

		inst["selected" + (period === "M" ? "Month" : "Year")] =
		inst["draw" + (period === "M" ? "Month" : "Year")] =
			parseInt(select.options[select.selectedIndex].value,10);

		this._notifyChange(inst);
		this._adjustDate(target);
	},

	/* Action for selecting a day. */
	_selectDay: function(id, month, year, td) {
		var inst,
			target = $(id);

		if ($(td).hasClass(this._unselectableClass) || this._isDisabledDatepicker(target[0])) {
			return;
		}

		inst = this._getInst(target[0]);
		inst.selectedDay = inst.currentDay = $("a", td).html();
		inst.selectedMonth = inst.currentMonth = month;
		inst.selectedYear = inst.currentYear = year;
		this._selectDate(id, this._formatDate(inst,
			inst.currentDay, inst.currentMonth, inst.currentYear));
	},

	/* Erase the input field and hide the date picker. */
	_clearDate: function(id) {
		var target = $(id);
		this._selectDate(target, "");
	},

	/* Update the input field with the selected date. */
	_selectDate: function(id, dateStr) {
		var onSelect,
			target = $(id),
			inst = this._getInst(target[0]);

		dateStr = (dateStr != null ? dateStr : this._formatDate(inst));
		if (inst.input) {
			inst.input.val(dateStr);
		}
		this._updateAlternate(inst);

		onSelect = this._get(inst, "onSelect");
		if (onSelect) {
			onSelect.apply((inst.input ? inst.input[0] : null), [dateStr, inst]);  // trigger custom callback
		} else if (inst.input) {
			inst.input.trigger("change"); // fire the change event
		}

		if (inst.inline){
			this._updateDatepicker(inst);
		} else {
			this._hideDatepicker();
			this._lastInput = inst.input[0];
			if (typeof(inst.input[0]) !== "object") {
				inst.input.focus(); // restore focus
			}
			this._lastInput = null;
		}
	},

	/* Update any alternate field to synchronise with the main field. */
	_updateAlternate: function(inst) {
		var altFormat, date, dateStr,
			altField = this._get(inst, "altField");

		if (altField) { // update alternate field too
			altFormat = this._get(inst, "altFormat") || this._get(inst, "dateFormat");
			date = this._getDate(inst);
			dateStr = this.formatDate(altFormat, date, this._getFormatConfig(inst));
			$(altField).each(function() { $(this).val(dateStr); });
		}
	},

	/* Set as beforeShowDay function to prevent selection of weekends.
	 * @param  date  Date - the date to customise
	 * @return [boolean, string] - is this date selectable?, what is its CSS class?
	 */
	noWeekends: function(date) {
		var day = date.getDay();
		return [(day > 0 && day < 6), ""];
	},

	/* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
	 * @param  date  Date - the date to get the week for
	 * @return  number - the number of the week within the year that contains this date
	 */
	iso8601Week: function(date) {
		var time,
			checkDate = new Date(date.getTime());

		// Find Thursday of this week starting on Monday
		checkDate.setDate(checkDate.getDate() + 4 - (checkDate.getDay() || 7));

		time = checkDate.getTime();
		checkDate.setMonth(0); // Compare with Jan 1
		checkDate.setDate(1);
		return Math.floor(Math.round((time - checkDate) / 86400000) / 7) + 1;
	},

	/* Parse a string value into a date object.
	 * See formatDate below for the possible formats.
	 *
	 * @param  format string - the expected format of the date
	 * @param  value string - the date in the above format
	 * @param  settings Object - attributes include:
	 *					shortYearCutoff  number - the cutoff year for determining the century (optional)
	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
	 *					dayNames		string[7] - names of the days from Sunday (optional)
	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
	 *					monthNames		string[12] - names of the months (optional)
	 * @return  Date - the extracted date value or null if value is blank
	 */
	parseDate: function (format, value, settings) {
		if (format == null || value == null) {
			throw "Invalid arguments";
		}

		value = (typeof value === "object" ? value.toString() : value + "");
		if (value === "") {
			return null;
		}

		var iFormat, dim, extra,
			iValue = 0,
			shortYearCutoffTemp = (settings ? settings.shortYearCutoff : null) || this._defaults.shortYearCutoff,
			shortYearCutoff = (typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
				new Date().getFullYear() % 100 + parseInt(shortYearCutoffTemp, 10)),
			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
			year = -1,
			month = -1,
			day = -1,
			doy = -1,
			literal = false,
			date,
			// Check whether a format character is doubled
			lookAhead = function(match) {
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
				if (matches) {
					iFormat++;
				}
				return matches;
			},
			// Extract a number from the string value
			getNumber = function(match) {
				var isDoubled = lookAhead(match),
					size = (match === "@" ? 14 : (match === "!" ? 20 :
					(match === "y" && isDoubled ? 4 : (match === "o" ? 3 : 2)))),
					digits = new RegExp("^\\d{1," + size + "}"),
					num = value.substring(iValue).match(digits);
				if (!num) {
					throw "Missing number at position " + iValue;
				}
				iValue += num[0].length;
				return parseInt(num[0], 10);
			},
			// Extract a name from the string value and convert to an index
			getName = function(match, shortNames, longNames) {
				var index = -1,
					names = $.map(lookAhead(match) ? longNames : shortNames, function (v, k) {
						return [ [k, v] ];
					}).sort(function (a, b) {
						return -(a[1].length - b[1].length);
					});

				$.each(names, function (i, pair) {
					var name = pair[1];
					if (value.substr(iValue, name.length).toLowerCase() === name.toLowerCase()) {
						index = pair[0];
						iValue += name.length;
						return false;
					}
				});
				if (index !== -1) {
					return index + 1;
				} else {
					throw "Unknown name at position " + iValue;
				}
			},
			// Confirm that a literal character matches the string value
			checkLiteral = function() {
				if (value.charAt(iValue) !== format.charAt(iFormat)) {
					throw "Unexpected literal at position " + iValue;
				}
				iValue++;
			};

		for (iFormat = 0; iFormat < format.length; iFormat++) {
			if (literal) {
				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
					literal = false;
				} else {
					checkLiteral();
				}
			} else {
				switch (format.charAt(iFormat)) {
					case "d":
						day = getNumber("d");
						break;
					case "D":
						getName("D", dayNamesShort, dayNames);
						break;
					case "o":
						doy = getNumber("o");
						break;
					case "m":
						month = getNumber("m");
						break;
					case "M":
						month = getName("M", monthNamesShort, monthNames);
						break;
					case "y":
						year = getNumber("y");
						break;
					case "@":
						date = new Date(getNumber("@"));
						year = date.getFullYear();
						month = date.getMonth() + 1;
						day = date.getDate();
						break;
					case "!":
						date = new Date((getNumber("!") - this._ticksTo1970) / 10000);
						year = date.getFullYear();
						month = date.getMonth() + 1;
						day = date.getDate();
						break;
					case "'":
						if (lookAhead("'")){
							checkLiteral();
						} else {
							literal = true;
						}
						break;
					default:
						checkLiteral();
				}
			}
		}

		if (iValue < value.length){
			extra = value.substr(iValue);
			if (!/^\s+/.test(extra)) {
				throw "Extra/unparsed characters found in date: " + extra;
			}
		}

		if (year === -1) {
			year = new Date().getFullYear();
		} else if (year < 100) {
			year += new Date().getFullYear() - new Date().getFullYear() % 100 +
				(year <= shortYearCutoff ? 0 : -100);
		}

		if (doy > -1) {
			month = 1;
			day = doy;
			do {
				dim = this._getDaysInMonth(year, month - 1);
				if (day <= dim) {
					break;
				}
				month++;
				day -= dim;
			} while (true);
		}

		date = this._daylightSavingAdjust(new Date(year, month - 1, day));
		if (date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day) {
			throw "Invalid date"; // E.g. 31/02/00
		}
		return date;
	},

	/* Standard date formats. */
	ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
	COOKIE: "D, dd M yy",
	ISO_8601: "yy-mm-dd",
	RFC_822: "D, d M y",
	RFC_850: "DD, dd-M-y",
	RFC_1036: "D, d M y",
	RFC_1123: "D, d M yy",
	RFC_2822: "D, d M yy",
	RSS: "D, d M y", // RFC 822
	TICKS: "!",
	TIMESTAMP: "@",
	W3C: "yy-mm-dd", // ISO 8601

	_ticksTo1970: (((1970 - 1) * 365 + Math.floor(1970 / 4) - Math.floor(1970 / 100) +
		Math.floor(1970 / 400)) * 24 * 60 * 60 * 10000000),

	/* Format a date object into a string value.
	 * The format can be combinations of the following:
	 * d  - day of month (no leading zero)
	 * dd - day of month (two digit)
	 * o  - day of year (no leading zeros)
	 * oo - day of year (three digit)
	 * D  - day name short
	 * DD - day name long
	 * m  - month of year (no leading zero)
	 * mm - month of year (two digit)
	 * M  - month name short
	 * MM - month name long
	 * y  - year (two digit)
	 * yy - year (four digit)
	 * @ - Unix timestamp (ms since 01/01/1970)
	 * ! - Windows ticks (100ns since 01/01/0001)
	 * "..." - literal text
	 * '' - single quote
	 *
	 * @param  format string - the desired format of the date
	 * @param  date Date - the date value to format
	 * @param  settings Object - attributes include:
	 *					dayNamesShort	string[7] - abbreviated names of the days from Sunday (optional)
	 *					dayNames		string[7] - names of the days from Sunday (optional)
	 *					monthNamesShort string[12] - abbreviated names of the months (optional)
	 *					monthNames		string[12] - names of the months (optional)
	 * @return  string - the date in the above format
	 */
	formatDate: function (format, date, settings) {
		if (!date) {
			return "";
		}

		var iFormat,
			dayNamesShort = (settings ? settings.dayNamesShort : null) || this._defaults.dayNamesShort,
			dayNames = (settings ? settings.dayNames : null) || this._defaults.dayNames,
			monthNamesShort = (settings ? settings.monthNamesShort : null) || this._defaults.monthNamesShort,
			monthNames = (settings ? settings.monthNames : null) || this._defaults.monthNames,
			// Check whether a format character is doubled
			lookAhead = function(match) {
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
				if (matches) {
					iFormat++;
				}
				return matches;
			},
			// Format a number, with leading zero if necessary
			formatNumber = function(match, value, len) {
				var num = "" + value;
				if (lookAhead(match)) {
					while (num.length < len) {
						num = "0" + num;
					}
				}
				return num;
			},
			// Format a name, short or long as requested
			formatName = function(match, value, shortNames, longNames) {
				return (lookAhead(match) ? longNames[value] : shortNames[value]);
			},
			output = "",
			literal = false;

		if (date) {
			for (iFormat = 0; iFormat < format.length; iFormat++) {
				if (literal) {
					if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
						literal = false;
					} else {
						output += format.charAt(iFormat);
					}
				} else {
					switch (format.charAt(iFormat)) {
						case "d":
							output += formatNumber("d", date.getDate(), 2);
							break;
						case "D":
							output += formatName("D", date.getDay(), dayNamesShort, dayNames);
							break;
						case "o":
							output += formatNumber("o",
								Math.round((new Date(date.getFullYear(), date.getMonth(), date.getDate()).getTime() - new Date(date.getFullYear(), 0, 0).getTime()) / 86400000), 3);
							break;
						case "m":
							output += formatNumber("m", date.getMonth() + 1, 2);
							break;
						case "M":
							output += formatName("M", date.getMonth(), monthNamesShort, monthNames);
							break;
						case "y":
							output += (lookAhead("y") ? date.getFullYear() :
								(date.getYear() % 100 < 10 ? "0" : "") + date.getYear() % 100);
							break;
						case "@":
							output += date.getTime();
							break;
						case "!":
							output += date.getTime() * 10000 + this._ticksTo1970;
							break;
						case "'":
							if (lookAhead("'")) {
								output += "'";
							} else {
								literal = true;
							}
							break;
						default:
							output += format.charAt(iFormat);
					}
				}
			}
		}
		return output;
	},

	/* Extract all possible characters from the date format. */
	_possibleChars: function (format) {
		var iFormat,
			chars = "",
			literal = false,
			// Check whether a format character is doubled
			lookAhead = function(match) {
				var matches = (iFormat + 1 < format.length && format.charAt(iFormat + 1) === match);
				if (matches) {
					iFormat++;
				}
				return matches;
			};

		for (iFormat = 0; iFormat < format.length; iFormat++) {
			if (literal) {
				if (format.charAt(iFormat) === "'" && !lookAhead("'")) {
					literal = false;
				} else {
					chars += format.charAt(iFormat);
				}
			} else {
				switch (format.charAt(iFormat)) {
					case "d": case "m": case "y": case "@":
						chars += "0123456789";
						break;
					case "D": case "M":
						return null; // Accept anything
					case "'":
						if (lookAhead("'")) {
							chars += "'";
						} else {
							literal = true;
						}
						break;
					default:
						chars += format.charAt(iFormat);
				}
			}
		}
		return chars;
	},

	/* Get a setting value, defaulting if necessary. */
	_get: function(inst, name) {
		return inst.settings[name] !== undefined ?
			inst.settings[name] : this._defaults[name];
	},

	/* Parse existing date and initialise date picker. */
	_setDateFromField: function(inst, noDefault) {
		if (inst.input.val() === inst.lastVal) {
			return;
		}

		var dateFormat = this._get(inst, "dateFormat"),
			dates = inst.lastVal = inst.input ? inst.input.val() : null,
			defaultDate = this._getDefaultDate(inst),
			date = defaultDate,
			settings = this._getFormatConfig(inst);

		try {
			date = this.parseDate(dateFormat, dates, settings) || defaultDate;
		} catch (event) {
			dates = (noDefault ? "" : dates);
		}
		inst.selectedDay = date.getDate();
		inst.drawMonth = inst.selectedMonth = date.getMonth();
		inst.drawYear = inst.selectedYear = date.getFullYear();
		inst.currentDay = (dates ? date.getDate() : 0);
		inst.currentMonth = (dates ? date.getMonth() : 0);
		inst.currentYear = (dates ? date.getFullYear() : 0);
		this._adjustInstDate(inst);
	},

	/* Retrieve the default date shown on opening. */
	_getDefaultDate: function(inst) {
		return this._restrictMinMax(inst,
			this._determineDate(inst, this._get(inst, "defaultDate"), new Date()));
	},

	/* A date may be specified as an exact value or a relative one. */
	_determineDate: function(inst, date, defaultDate) {
		var offsetNumeric = function(offset) {
				var date = new Date();
				date.setDate(date.getDate() + offset);
				return date;
			},
			offsetString = function(offset) {
				try {
					return $.datepicker.parseDate($.datepicker._get(inst, "dateFormat"),
						offset, $.datepicker._getFormatConfig(inst));
				}
				catch (e) {
					// Ignore
				}

				var date = (offset.toLowerCase().match(/^c/) ?
					$.datepicker._getDate(inst) : null) || new Date(),
					year = date.getFullYear(),
					month = date.getMonth(),
					day = date.getDate(),
					pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
					matches = pattern.exec(offset);

				while (matches) {
					switch (matches[2] || "d") {
						case "d" : case "D" :
							day += parseInt(matches[1],10); break;
						case "w" : case "W" :
							day += parseInt(matches[1],10) * 7; break;
						case "m" : case "M" :
							month += parseInt(matches[1],10);
							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
							break;
						case "y": case "Y" :
							year += parseInt(matches[1],10);
							day = Math.min(day, $.datepicker._getDaysInMonth(year, month));
							break;
					}
					matches = pattern.exec(offset);
				}
				return new Date(year, month, day);
			},
			newDate = (date == null || date === "" ? defaultDate : (typeof date === "string" ? offsetString(date) :
				(typeof date === "number" ? (isNaN(date) ? defaultDate : offsetNumeric(date)) : new Date(date.getTime()))));

		newDate = (newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate);
		if (newDate) {
			newDate.setHours(0);
			newDate.setMinutes(0);
			newDate.setSeconds(0);
			newDate.setMilliseconds(0);
		}
		return this._daylightSavingAdjust(newDate);
	},

	/* Handle switch to/from daylight saving.
	 * Hours may be non-zero on daylight saving cut-over:
	 * > 12 when midnight changeover, but then cannot generate
	 * midnight datetime, so jump to 1AM, otherwise reset.
	 * @param  date  (Date) the date to check
	 * @return  (Date) the corrected date
	 */
	_daylightSavingAdjust: function(date) {
		if (!date) {
			return null;
		}
		date.setHours(date.getHours() > 12 ? date.getHours() + 2 : 0);
		return date;
	},

	/* Set the date(s) directly. */
	_setDate: function(inst, date, noChange) {
		var clear = !date,
			origMonth = inst.selectedMonth,
			origYear = inst.selectedYear,
			newDate = this._restrictMinMax(inst, this._determineDate(inst, date, new Date()));

		inst.selectedDay = inst.currentDay = newDate.getDate();
		inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
		inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
		if ((origMonth !== inst.selectedMonth || origYear !== inst.selectedYear) && !noChange) {
			this._notifyChange(inst);
		}
		this._adjustInstDate(inst);
		if (inst.input) {
			inst.input.val(clear ? "" : this._formatDate(inst));
		}
	},

	/* Retrieve the date(s) directly. */
	_getDate: function(inst) {
		var startDate = (!inst.currentYear || (inst.input && inst.input.val() === "") ? null :
			this._daylightSavingAdjust(new Date(
			inst.currentYear, inst.currentMonth, inst.currentDay)));
			return startDate;
	},

	/* Attach the onxxx handlers.  These are declared statically so
	 * they work with static code transformers like Caja.
	 */
	_attachHandlers: function(inst) {
		var stepMonths = this._get(inst, "stepMonths"),
			id = "#" + inst.id.replace( /\\\\/g, "\\" );
		inst.dpDiv.find("[data-handler]").map(function () {
			var handler = {
				prev: function () {
					window["DP_jQuery_" + dpuuid].datepicker._adjustDate(id, -stepMonths, "M");
				},
				next: function () {
					window["DP_jQuery_" + dpuuid].datepicker._adjustDate(id, +stepMonths, "M");
				},
				hide: function () {
					window["DP_jQuery_" + dpuuid].datepicker._hideDatepicker();
				},
				today: function () {
					window["DP_jQuery_" + dpuuid].datepicker._gotoToday(id);
				},
				selectDay: function () {
					window["DP_jQuery_" + dpuuid].datepicker._selectDay(id, +this.getAttribute("data-month"), +this.getAttribute("data-year"), this);
					return false;
				},
				selectMonth: function () {
					window["DP_jQuery_" + dpuuid].datepicker._selectMonthYear(id, this, "M");
					return false;
				},
				selectYear: function () {
					window["DP_jQuery_" + dpuuid].datepicker._selectMonthYear(id, this, "Y");
					return false;
				}
			};
			$(this).bind(this.getAttribute("data-event"), handler[this.getAttribute("data-handler")]);
		});
	},

	/* Generate the HTML for the current state of the date picker. */
	_generateHTML: function(inst) {
		var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
			controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
			monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
			selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
			cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
			printDate, dRow, tbody, daySettings, otherMonth, unselectable,
			tempDate = new Date(),
			today = this._daylightSavingAdjust(
				new Date(tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate())), // clear time
			isRTL = this._get(inst, "isRTL"),
			showButtonPanel = this._get(inst, "showButtonPanel"),
			hideIfNoPrevNext = this._get(inst, "hideIfNoPrevNext"),
			navigationAsDateFormat = this._get(inst, "navigationAsDateFormat"),
			numMonths = this._getNumberOfMonths(inst),
			showCurrentAtPos = this._get(inst, "showCurrentAtPos"),
			stepMonths = this._get(inst, "stepMonths"),
			isMultiMonth = (numMonths[0] !== 1 || numMonths[1] !== 1),
			currentDate = this._daylightSavingAdjust((!inst.currentDay ? new Date(9999, 9, 9) :
				new Date(inst.currentYear, inst.currentMonth, inst.currentDay))),
			minDate = this._getMinMaxDate(inst, "min"),
			maxDate = this._getMinMaxDate(inst, "max"),
			drawMonth = inst.drawMonth - showCurrentAtPos,
			drawYear = inst.drawYear;

		if (drawMonth < 0) {
			drawMonth += 12;
			drawYear--;
		}
		if (maxDate) {
			maxDraw = this._daylightSavingAdjust(new Date(maxDate.getFullYear(),
				maxDate.getMonth() - (numMonths[0] * numMonths[1]) + 1, maxDate.getDate()));
			maxDraw = (minDate && maxDraw < minDate ? minDate : maxDraw);
			while (this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1)) > maxDraw) {
				drawMonth--;
				if (drawMonth < 0) {
					drawMonth = 11;
					drawYear--;
				}
			}
		}
		inst.drawMonth = drawMonth;
		inst.drawYear = drawYear;

		prevText = this._get(inst, "prevText");
		prevText = (!navigationAsDateFormat ? prevText : this.formatDate(prevText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth - stepMonths, 1)),
			this._getFormatConfig(inst)));

		prev = (this._canAdjustMonth(inst, -1, drawYear, drawMonth) ?
			"<a class='ui-datepicker-prev ui-corner-all' data-handler='prev' data-event='click'" +
			" title='" + prevText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>" :
			(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-prev ui-corner-all ui-state-disabled' title='"+ prevText +"'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "e" : "w") + "'>" + prevText + "</span></a>"));

		nextText = this._get(inst, "nextText");
		nextText = (!navigationAsDateFormat ? nextText : this.formatDate(nextText,
			this._daylightSavingAdjust(new Date(drawYear, drawMonth + stepMonths, 1)),
			this._getFormatConfig(inst)));

		next = (this._canAdjustMonth(inst, +1, drawYear, drawMonth) ?
			"<a class='ui-datepicker-next ui-corner-all' data-handler='next' data-event='click'" +
			" title='" + nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>" :
			(hideIfNoPrevNext ? "" : "<a class='ui-datepicker-next ui-corner-all ui-state-disabled' title='"+ nextText + "'><span class='ui-icon ui-icon-circle-triangle-" + ( isRTL ? "w" : "e") + "'>" + nextText + "</span></a>"));

		currentText = this._get(inst, "currentText");
		gotoDate = (this._get(inst, "gotoCurrent") && inst.currentDay ? currentDate : today);
		currentText = (!navigationAsDateFormat ? currentText :
			this.formatDate(currentText, gotoDate, this._getFormatConfig(inst)));

		controls = (!inst.inline ? "<button type='button' class='ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all' data-handler='hide' data-event='click'>" +
			this._get(inst, "closeText") + "</button>" : "");

		buttonPanel = (showButtonPanel) ? "<div class='ui-datepicker-buttonpane ui-widget-content'>" + (isRTL ? controls : "") +
			(this._isInRange(inst, gotoDate) ? "<button type='button' class='ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all' data-handler='today' data-event='click'" +
			">" + currentText + "</button>" : "") + (isRTL ? "" : controls) + "</div>" : "";

		firstDay = parseInt(this._get(inst, "firstDay"),10);
		firstDay = (isNaN(firstDay) ? 0 : firstDay);

		showWeek = this._get(inst, "showWeek");
		dayNames = this._get(inst, "dayNames");
		dayNamesMin = this._get(inst, "dayNamesMin");
		monthNames = this._get(inst, "monthNames");
		monthNamesShort = this._get(inst, "monthNamesShort");
		beforeShowDay = this._get(inst, "beforeShowDay");
		showOtherMonths = this._get(inst, "showOtherMonths");
		selectOtherMonths = this._get(inst, "selectOtherMonths");
		defaultDate = this._getDefaultDate(inst);
		html = "";
		dow;
		for (row = 0; row < numMonths[0]; row++) {
			group = "";
			this.maxRows = 4;
			for (col = 0; col < numMonths[1]; col++) {
				selectedDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, inst.selectedDay));
				cornerClass = " ui-corner-all";
				calender = "";
				if (isMultiMonth) {
					calender += "<div class='ui-datepicker-group";
					if (numMonths[1] > 1) {
						switch (col) {
							case 0: calender += " ui-datepicker-group-first";
								cornerClass = " ui-corner-" + (isRTL ? "right" : "left"); break;
							case numMonths[1]-1: calender += " ui-datepicker-group-last";
								cornerClass = " ui-corner-" + (isRTL ? "left" : "right"); break;
							default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
						}
					}
					calender += "'>";
				}
				calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
					(/all|left/.test(cornerClass) && row === 0 ? (isRTL ? next : prev) : "") +
					(/all|right/.test(cornerClass) && row === 0 ? (isRTL ? prev : next) : "") +
					this._generateMonthYearHeader(inst, drawMonth, drawYear, minDate, maxDate,
					row > 0 || col > 0, monthNames, monthNamesShort) + // draw month headers
					"</div><table class='ui-datepicker-calendar'><thead>" +
					"<tr>";
				thead = (showWeek ? "<th class='ui-datepicker-week-col'>" + this._get(inst, "weekHeader") + "</th>" : "");
				for (dow = 0; dow < 7; dow++) { // days of the week
					day = (dow + firstDay) % 7;
					thead += "<th" + ((dow + firstDay + 6) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "") + ">" +
						"<span title='" + dayNames[day] + "'>" + dayNamesMin[day] + "</span></th>";
				}
				calender += thead + "</tr></thead><tbody>";
				daysInMonth = this._getDaysInMonth(drawYear, drawMonth);
				if (drawYear === inst.selectedYear && drawMonth === inst.selectedMonth) {
					inst.selectedDay = Math.min(inst.selectedDay, daysInMonth);
				}
				leadDays = (this._getFirstDayOfMonth(drawYear, drawMonth) - firstDay + 7) % 7;
				curRows = Math.ceil((leadDays + daysInMonth) / 7); // calculate the number of rows to generate
				numRows = (isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows); //If multiple months, use the higher number of rows (see #7043)
				this.maxRows = numRows;
				printDate = this._daylightSavingAdjust(new Date(drawYear, drawMonth, 1 - leadDays));
				for (dRow = 0; dRow < numRows; dRow++) { // create date picker rows
					calender += "<tr>";
					tbody = (!showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
						this._get(inst, "calculateWeek")(printDate) + "</td>");
					for (dow = 0; dow < 7; dow++) { // create date picker days
						daySettings = (beforeShowDay ?
							beforeShowDay.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
						otherMonth = (printDate.getMonth() !== drawMonth);
						unselectable = (otherMonth && !selectOtherMonths) || !daySettings[0] ||
							(minDate && printDate < minDate) || (maxDate && printDate > maxDate);
						tbody += "<td class='" +
							((dow + firstDay + 6) % 7 >= 5 ? " ui-datepicker-week-end" : "") + // highlight weekends
							(otherMonth ? " ui-datepicker-other-month" : "") + // highlight days from other months
							((printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent) || // user pressed key
							(defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime()) ?
							// or defaultDate is current printedDate and defaultDate is selectedDate
							" " + this._dayOverClass : "") + // highlight selected day
							(unselectable ? " " + this._unselectableClass + " ui-state-disabled": "") +  // highlight unselectable days
							(otherMonth && !showOtherMonths ? "" : " " + daySettings[1] + // highlight custom dates
							(printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "") + // highlight selected day
							(printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "")) + "'" + // highlight today (if different)
							((!otherMonth || showOtherMonths) && daySettings[2] ? " title='" + daySettings[2] + "'" : "") + // cell title
							(unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'") + ">" + // actions
							(otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
							(unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
							(printDate.getTime() === today.getTime() ? " ui-state-highlight" : "") +
							(printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "") + // highlight selected day
							(otherMonth ? " ui-priority-secondary" : "") + // distinguish dates from other months
							"' href='#'>" + printDate.getDate() + "</a>")) + "</td>"; // display selectable date
						printDate.setDate(printDate.getDate() + 1);
						printDate = this._daylightSavingAdjust(printDate);
					}
					calender += tbody + "</tr>";
				}
				drawMonth++;
				if (drawMonth > 11) {
					drawMonth = 0;
					drawYear++;
				}
				calender += "</tbody></table>" + (isMultiMonth ? "</div>" +
							((numMonths[0] > 0 && col === numMonths[1]-1) ? "<div class='ui-datepicker-row-break'></div>" : "") : "");
				group += calender;
			}
			html += group;
		}
		html += buttonPanel;
		inst._keyEvent = false;
		return html;
	},

	/* Generate the month and year header. */
	_generateMonthYearHeader: function(inst, drawMonth, drawYear, minDate, maxDate,
			secondary, monthNames, monthNamesShort) {

		var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
			changeMonth = this._get(inst, "changeMonth"),
			changeYear = this._get(inst, "changeYear"),
			showMonthAfterYear = this._get(inst, "showMonthAfterYear"),
			html = "<div class='ui-datepicker-title'>",
			monthHtml = "";

		// month selection
		if (secondary || !changeMonth) {
			monthHtml += "<span class='ui-datepicker-month'>" + monthNames[drawMonth] + "</span>";
		} else {
			inMinYear = (minDate && minDate.getFullYear() === drawYear);
			inMaxYear = (maxDate && maxDate.getFullYear() === drawYear);
			monthHtml += "<select class='ui-datepicker-month' data-handler='selectMonth' data-event='change'>";
			for ( month = 0; month < 12; month++) {
				if ((!inMinYear || month >= minDate.getMonth()) && (!inMaxYear || month <= maxDate.getMonth())) {
					monthHtml += "<option value='" + month + "'" +
						(month === drawMonth ? " selected='selected'" : "") +
						">" + monthNamesShort[month] + "</option>";
				}
			}
			monthHtml += "</select>";
		}

		if (!showMonthAfterYear) {
			html += monthHtml + (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "");
		}

		// year selection
		if ( !inst.yearshtml ) {
			inst.yearshtml = "";
			if (secondary || !changeYear) {
				html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
			} else {
				// determine range of years to display
				years = this._get(inst, "yearRange").split(":");
				thisYear = new Date().getFullYear();
				determineYear = function(value) {
					var year = (value.match(/c[+\-].*/) ? drawYear + parseInt(value.substring(1), 10) :
						(value.match(/[+\-].*/) ? thisYear + parseInt(value, 10) :
						parseInt(value, 10)));
					return (isNaN(year) ? thisYear : year);
				};
				year = determineYear(years[0]);
				endYear = Math.max(year, determineYear(years[1] || ""));
				year = (minDate ? Math.max(year, minDate.getFullYear()) : year);
				endYear = (maxDate ? Math.min(endYear, maxDate.getFullYear()) : endYear);
				inst.yearshtml += "<select class='ui-datepicker-year' data-handler='selectYear' data-event='change'>";
				for (; year <= endYear; year++) {
					inst.yearshtml += "<option value='" + year + "'" +
						(year === drawYear ? " selected='selected'" : "") +
						">" + year + "</option>";
				}
				inst.yearshtml += "</select>";

				html += inst.yearshtml;
				inst.yearshtml = null;
			}
		}

		html += this._get(inst, "yearSuffix");
		if (showMonthAfterYear) {
			html += (secondary || !(changeMonth && changeYear) ? "&#xa0;" : "") + monthHtml;
		}
		html += "</div>"; // Close datepicker_header
		return html;
	},

	/* Adjust one of the date sub-fields. */
	_adjustInstDate: function(inst, offset, period) {
		var year = inst.drawYear + (period === "Y" ? offset : 0),
			month = inst.drawMonth + (period === "M" ? offset : 0),
			day = Math.min(inst.selectedDay, this._getDaysInMonth(year, month)) + (period === "D" ? offset : 0),
			date = this._restrictMinMax(inst, this._daylightSavingAdjust(new Date(year, month, day)));

		inst.selectedDay = date.getDate();
		inst.drawMonth = inst.selectedMonth = date.getMonth();
		inst.drawYear = inst.selectedYear = date.getFullYear();
		if (period === "M" || period === "Y") {
			this._notifyChange(inst);
		}
	},

	/* Ensure a date is within any min/max bounds. */
	_restrictMinMax: function(inst, date) {
		var minDate = this._getMinMaxDate(inst, "min"),
			maxDate = this._getMinMaxDate(inst, "max"),
			newDate = (minDate && date < minDate ? minDate : date);
		return (maxDate && newDate > maxDate ? maxDate : newDate);
	},

	/* Notify change of month/year. */
	_notifyChange: function(inst) {
		var onChange = this._get(inst, "onChangeMonthYear");
		if (onChange) {
			onChange.apply((inst.input ? inst.input[0] : null),
				[inst.selectedYear, inst.selectedMonth + 1, inst]);
		}
	},

	/* Determine the number of months to show. */
	_getNumberOfMonths: function(inst) {
		var numMonths = this._get(inst, "numberOfMonths");
		return (numMonths == null ? [1, 1] : (typeof numMonths === "number" ? [1, numMonths] : numMonths));
	},

	/* Determine the current maximum date - ensure no time components are set. */
	_getMinMaxDate: function(inst, minMax) {
		return this._determineDate(inst, this._get(inst, minMax + "Date"), null);
	},

	/* Find the number of days in a given month. */
	_getDaysInMonth: function(year, month) {
		return 32 - this._daylightSavingAdjust(new Date(year, month, 32)).getDate();
	},

	/* Find the day of the week of the first of a month. */
	_getFirstDayOfMonth: function(year, month) {
		return new Date(year, month, 1).getDay();
	},

	/* Determines if we should allow a "next/prev" month display change. */
	_canAdjustMonth: function(inst, offset, curYear, curMonth) {
		var numMonths = this._getNumberOfMonths(inst),
			date = this._daylightSavingAdjust(new Date(curYear,
			curMonth + (offset < 0 ? offset : numMonths[0] * numMonths[1]), 1));

		if (offset < 0) {
			date.setDate(this._getDaysInMonth(date.getFullYear(), date.getMonth()));
		}
		return this._isInRange(inst, date);
	},

	/* Is the given date in the accepted range? */
	_isInRange: function(inst, date) {
		var yearSplit, currentYear,
			minDate = this._getMinMaxDate(inst, "min"),
			maxDate = this._getMinMaxDate(inst, "max"),
			minYear = null,
			maxYear = null,
			years = this._get(inst, "yearRange");
			if (years){
				yearSplit = years.split(":");
				currentYear = new Date().getFullYear();
				minYear = parseInt(yearSplit[0], 10) + currentYear;
				maxYear = parseInt(yearSplit[1], 10) + currentYear;
			}

		return ((!minDate || date.getTime() >= minDate.getTime()) &&
			(!maxDate || date.getTime() <= maxDate.getTime()) &&
			(!minYear || date.getFullYear() >= minYear) &&
			(!maxYear || date.getFullYear() <= maxYear));
	},

	/* Provide the configuration settings for formatting/parsing. */
	_getFormatConfig: function(inst) {
		var shortYearCutoff = this._get(inst, "shortYearCutoff");
		shortYearCutoff = (typeof shortYearCutoff !== "string" ? shortYearCutoff :
			new Date().getFullYear() % 100 + parseInt(shortYearCutoff, 10));
		return {shortYearCutoff: shortYearCutoff,
			dayNamesShort: this._get(inst, "dayNamesShort"), dayNames: this._get(inst, "dayNames"),
			monthNamesShort: this._get(inst, "monthNamesShort"), monthNames: this._get(inst, "monthNames")};
	},

	/* Format the given date for display. */
	_formatDate: function(inst, day, month, year) {
		if (!day) {
			inst.currentDay = inst.selectedDay;
			inst.currentMonth = inst.selectedMonth;
			inst.currentYear = inst.selectedYear;
		}
		var date = (day ? (typeof day === "object" ? day :
			this._daylightSavingAdjust(new Date(year, month, day))) :
			this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
		return this.formatDate(this._get(inst, "dateFormat"), date, this._getFormatConfig(inst));
	}
});

/*
 * Bind hover events for datepicker elements.
 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
 * Global instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
 */
function bindHover(dpDiv) {
	var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
	return dpDiv.delegate(selector, "mouseout", function() {
			$(this).removeClass("ui-state-hover");
			if (this.className.indexOf("ui-datepicker-prev") !== -1) {
				$(this).removeClass("ui-datepicker-prev-hover");
			}
			if (this.className.indexOf("ui-datepicker-next") !== -1) {
				$(this).removeClass("ui-datepicker-next-hover");
			}
		})
		.delegate(selector, "mouseover", function(){
			if (!$.datepicker._isDisabledDatepicker( instActive.inline ? dpDiv.parent()[0] : instActive.input[0])) {
				$(this).parents(".ui-datepicker-calendar").find("a").removeClass("ui-state-hover");
				$(this).addClass("ui-state-hover");
				if (this.className.indexOf("ui-datepicker-prev") !== -1) {
					$(this).addClass("ui-datepicker-prev-hover");
				}
				if (this.className.indexOf("ui-datepicker-next") !== -1) {
					$(this).addClass("ui-datepicker-next-hover");
				}
			}
		});
}

/* jQuery extend now ignores nulls! */
function extendRemove(target, props) {
	$.extend(target, props);
	for (var name in props) {
		if (props[name] == null) {
			target[name] = props[name];
		}
	}
	return target;
}

/* Invoke the datepicker functionality.
   @param  options  string - a command, optionally followed by additional parameters or
					Object - settings for attaching new datepicker functionality
   @return  jQuery object */
$.fn.datepicker = function(options){

	/* Verify an empty collection wasn't passed - Fixes #6976 */
	if ( !this.length ) {
		return this;
	}

	/* Initialise the date picker. */
	if (!$.datepicker.initialized) {
		$(document).mousedown($.datepicker._checkExternalClick);
		$.datepicker.initialized = true;
	}

	/* Append datepicker main container to body if not exist. */
	if ($("#"+$.datepicker._mainDivId).length === 0) {
		$("body").append($.datepicker.dpDiv);
	}

	var otherArgs = Array.prototype.slice.call(arguments, 1);
	if (typeof options === "string" && (options === "isDisabled" || options === "getDate" || options === "widget")) {
		return $.datepicker["_" + options + "Datepicker"].
			apply($.datepicker, [this[0]].concat(otherArgs));
	}
	if (options === "option" && arguments.length === 2 && typeof arguments[1] === "string") {
		return $.datepicker["_" + options + "Datepicker"].
			apply($.datepicker, [this[0]].concat(otherArgs));
	}
	return this.each(function() {
		typeof options === "string" ?
			$.datepicker["_" + options + "Datepicker"].
				apply($.datepicker, [this].concat(otherArgs)) :
			$.datepicker._attachDatepicker(this, options);
	});
};

$.datepicker = new Datepicker(); // singleton instance
$.datepicker.initialized = false;
$.datepicker.uuid = new Date().getTime();
$.datepicker.version = "1.10.0";

// Workaround for #4055
// Add another global to avoid noConflict issues with inline event handlers
window["DP_jQuery_" + dpuuid] = $;

})(jQuery);

// file: 000-1-140-jquery.ui.dialog.js
/*!
 * jQuery UI Dialog 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/dialog/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *  jquery.ui.button.js
 *	jquery.ui.draggable.js
 *	jquery.ui.mouse.js
 *	jquery.ui.position.js
 *	jquery.ui.resizable.js
 */
(function( $, undefined ) {

var sizeRelatedOptions = {
		buttons: true,
		height: true,
		maxHeight: true,
		maxWidth: true,
		minHeight: true,
		minWidth: true,
		width: true
	},
	resizableRelatedOptions = {
		maxHeight: true,
		maxWidth: true,
		minHeight: true,
		minWidth: true
	};

$.widget( "ui.dialog", {
	version: "1.10.0",
	options: {
		appendTo: "body",
		autoOpen: true,
		buttons: [],
		closeOnEscape: true,
		closeText: "close",
		dialogClass: "",
		draggable: true,
		hide: null,
		height: "auto",
		maxHeight: null,
		maxWidth: null,
		minHeight: 150,
		minWidth: 150,
		modal: false,
		position: {
			my: "center",
			at: "center",
			of: window,
			collision: "fit",
			// Ensure the titlebar is always visible
			using: function( pos ) {
				var topOffset = $( this ).css( pos ).offset().top;
				if ( topOffset < 0 ) {
					$( this ).css( "top", pos.top - topOffset );
				}
			}
		},
		resizable: true,
		show: null,
		title: null,
		width: 300,

		// callbacks
		beforeClose: null,
		close: null,
		drag: null,
		dragStart: null,
		dragStop: null,
		focus: null,
		open: null,
		resize: null,
		resizeStart: null,
		resizeStop: null
	},

	_create: function() {
		this.originalCss = {
			display: this.element[0].style.display,
			width: this.element[0].style.width,
			minHeight: this.element[0].style.minHeight,
			maxHeight: this.element[0].style.maxHeight,
			height: this.element[0].style.height
		};
		this.originalPosition = {
			parent: this.element.parent(),
			index: this.element.parent().children().index( this.element )
		};
		this.originalTitle = this.element.attr("title");
		this.options.title = this.options.title || this.originalTitle;

		this._createWrapper();

		this.element
			.show()
			.removeAttr("title")
			.addClass("ui-dialog-content ui-widget-content")
			.appendTo( this.uiDialog );

		this._createTitlebar();
		this._createButtonPane();

		if ( this.options.draggable && $.fn.draggable ) {
			this._makeDraggable();
		}
		if ( this.options.resizable && $.fn.resizable ) {
			this._makeResizable();
		}

		this._isOpen = false;
	},

	_init: function() {
		if ( this.options.autoOpen ) {
			this.open();
		}
	},

	_appendTo: function() {
		var element = this.options.appendTo;
		if ( element && (element.jquery || element.nodeType) ) {
			return $( element );
		}
		return this.document.find( element || "body" ).eq( 0 );
	},

	_destroy: function() {
		var next,
			originalPosition = this.originalPosition;

		this._destroyOverlay();

		this.element
			.removeUniqueId()
			.removeClass("ui-dialog-content ui-widget-content")
			.css( this.originalCss )
			// Without detaching first, the following becomes really slow
			.detach();

		this.uiDialog.stop( true, true ).remove();

		if ( this.originalTitle ) {
			this.element.attr( "title", this.originalTitle );
		}

		next = originalPosition.parent.children().eq( originalPosition.index );
		// Don't try to place the dialog next to itself (#8613)
		if ( next.length && next[0] !== this.element[0] ) {
			next.before( this.element );
		} else {
			originalPosition.parent.append( this.element );
		}
	},

	widget: function() {
		return this.uiDialog;
	},

	disable: $.noop,
	enable: $.noop,

	close: function( event ) {
		var that = this;

		if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
			return;
		}

		this._isOpen = false;
		this._destroyOverlay();

		if ( !this.opener.filter(":focusable").focus().length ) {
			// Hiding a focused element doesn't trigger blur in WebKit
			// so in case we have nothing to focus on, explicitly blur the active element
			// https://bugs.webkit.org/show_bug.cgi?id=47182
			$( this.document[0].activeElement ).blur();
		}

		this._hide( this.uiDialog, this.options.hide, function() {
			that._trigger( "close", event );
		});
	},

	isOpen: function() {
		return this._isOpen;
	},

	moveToTop: function() {
		this._moveToTop();
	},

	_moveToTop: function( event, silent ) {
		var moved = !!this.uiDialog.nextAll(":visible").insertBefore( this.uiDialog ).length;
		if ( moved && !silent ) {
			this._trigger( "focus", event );
		}
		return moved;
	},

	open: function() {
		if ( this._isOpen ) {
			if ( this._moveToTop() ) {
				this._focusTabbable();
			}
			return;
		}

		this.opener = $( this.document[0].activeElement );

		this._size();
		this._position();
		this._createOverlay();
		this._moveToTop( null, true );
		this._show( this.uiDialog, this.options.show );

		this._focusTabbable();

		this._isOpen = true;
		this._trigger("open");
		this._trigger("focus");
	},

	_focusTabbable: function() {
		// Set focus to the first match:
		// 1. First element inside the dialog matching [autofocus]
		// 2. Tabbable element inside the content element
		// 3. Tabbable element inside the buttonpane
		// 4. The close button
		// 5. The dialog itself
		var hasFocus = this.element.find("[autofocus]");
		if ( !hasFocus.length ) {
			hasFocus = this.element.find(":tabbable");
		}
		if ( !hasFocus.length ) {
			hasFocus = this.uiDialogButtonPane.find(":tabbable");
		}
		if ( !hasFocus.length ) {
			hasFocus = this.uiDialogTitlebarClose.filter(":tabbable");
		}
		if ( !hasFocus.length ) {
			hasFocus = this.uiDialog;
		}
		hasFocus.eq( 0 ).focus();
	},

	_keepFocus: function( event ) {
		function checkFocus() {
			var activeElement = this.document[0].activeElement,
				isActive = this.uiDialog[0] === activeElement ||
					$.contains( this.uiDialog[0], activeElement );
			if ( !isActive ) {
				this._focusTabbable();
			}
		}
		event.preventDefault();
		checkFocus.call( this );
		// support: IE
		// IE <= 8 doesn't prevent moving focus even with event.preventDefault()
		// so we check again later
		this._delay( checkFocus );
	},

	_createWrapper: function() {
		this.uiDialog = $("<div>")
			.addClass( "ui-dialog ui-widget ui-widget-content ui-corner-all ui-front " +
				this.options.dialogClass )
			.hide()
			.attr({
				// Setting tabIndex makes the div focusable
				tabIndex: -1,
				role: "dialog"
			})
			.appendTo( this._appendTo() );

		this._on( this.uiDialog, {
			keydown: function( event ) {
				if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
						event.keyCode === $.ui.keyCode.ESCAPE ) {
					event.preventDefault();
					this.close( event );
					return;
				}

				// prevent tabbing out of dialogs
				if ( event.keyCode !== $.ui.keyCode.TAB ) {
					return;
				}
				var tabbables = this.uiDialog.find(":tabbable"),
					first = tabbables.filter(":first"),
					last  = tabbables.filter(":last");

				if ( ( event.target === last[0] || event.target === this.uiDialog[0] ) && !event.shiftKey ) {
					first.focus( 1 );
					event.preventDefault();
				} else if ( ( event.target === first[0] || event.target === this.uiDialog[0] ) && event.shiftKey ) {
					last.focus( 1 );
					event.preventDefault();
				}
			},
			mousedown: function( event ) {
				if ( this._moveToTop( event ) ) {
					this._focusTabbable();
				}
			}
		});

		// We assume that any existing aria-describedby attribute means
		// that the dialog content is marked up properly
		// otherwise we brute force the content as the description
		if ( !this.element.find("[aria-describedby]").length ) {
			this.uiDialog.attr({
				"aria-describedby": this.element.uniqueId().attr("id")
			});
		}
	},

	_createTitlebar: function() {
		var uiDialogTitle;

		this.uiDialogTitlebar = $("<div>")
			.addClass("ui-dialog-titlebar ui-widget-header ui-corner-all ui-helper-clearfix")
			.prependTo( this.uiDialog );
		this._on( this.uiDialogTitlebar, {
			mousedown: function( event ) {
				// Don't prevent click on close button (#8838)
				// Focusing a dialog that is partially scrolled out of view
				// causes the browser to scroll it into view, preventing the click event
				if ( !$( event.target ).closest(".ui-dialog-titlebar-close") ) {
					// Dialog isn't getting focus when dragging (#8063)
					this.uiDialog.focus();
				}
			}
		});

		this.uiDialogTitlebarClose = $("<button></button>")
			.button({
				label: this.options.closeText,
				icons: {
					primary: "ui-icon-closethick"
				},
				text: false
			})
			.addClass("ui-dialog-titlebar-close")
			.appendTo( this.uiDialogTitlebar );
		this._on( this.uiDialogTitlebarClose, {
			click: function( event ) {
				event.preventDefault();
				this.close( event );
			}
		});

		uiDialogTitle = $("<span>")
			.uniqueId()
			.addClass("ui-dialog-title")
			.prependTo( this.uiDialogTitlebar );
		this._title( uiDialogTitle );

		this.uiDialog.attr({
			"aria-labelledby": uiDialogTitle.attr("id")
		});
	},

	_title: function( title ) {
		if ( !this.options.title ) {
			title.html("&#160;");
		}
		title.text( this.options.title );
	},

	_createButtonPane: function() {
		this.uiDialogButtonPane = $("<div>")
			.addClass("ui-dialog-buttonpane ui-widget-content ui-helper-clearfix");

		this.uiButtonSet = $("<div>")
			.addClass("ui-dialog-buttonset")
			.appendTo( this.uiDialogButtonPane );

		this._createButtons();
	},

	_createButtons: function() {
		var that = this,
			buttons = this.options.buttons;

		// if we already have a button pane, remove it
		this.uiDialogButtonPane.remove();
		this.uiButtonSet.empty();

		if ( $.isEmptyObject( buttons ) ) {
			this.uiDialog.removeClass("ui-dialog-buttons");
			return;
		}

		$.each( buttons, function( name, props ) {
			var click, buttonOptions;
			props = $.isFunction( props ) ?
				{ click: props, text: name } :
				props;
			// Default to a non-submitting button
			props = $.extend( { type: "button" }, props );
			// Change the context for the click callback to be the main element
			click = props.click;
			props.click = function() {
				click.apply( that.element[0], arguments );
			};
			buttonOptions = {
				icons: props.icons,
				text: props.showText
			};
			delete props.icons;
			delete props.showText;
			$( "<button></button>", props )
				.button( buttonOptions )
				.appendTo( that.uiButtonSet );
		});
		this.uiDialog.addClass("ui-dialog-buttons");
		this.uiDialogButtonPane.appendTo( this.uiDialog );
	},

	_makeDraggable: function() {
		var that = this,
			options = this.options;

		function filteredUi( ui ) {
			return {
				position: ui.position,
				offset: ui.offset
			};
		}

		this.uiDialog.draggable({
			cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
			handle: ".ui-dialog-titlebar",
			containment: "document",
			start: function( event, ui ) {
				$( this ).addClass("ui-dialog-dragging");
				that._trigger( "dragStart", event, filteredUi( ui ) );
			},
			drag: function( event, ui ) {
				that._trigger( "drag", event, filteredUi( ui ) );
			},
			stop: function( event, ui ) {
				options.position = [
					ui.position.left - that.document.scrollLeft(),
					ui.position.top - that.document.scrollTop()
				];
				$( this ).removeClass("ui-dialog-dragging");
				that._trigger( "dragStop", event, filteredUi( ui ) );
			}
		});
	},

	_makeResizable: function() {
		var that = this,
			options = this.options,
			handles = options.resizable,
			// .ui-resizable has position: relative defined in the stylesheet
			// but dialogs have to use absolute or fixed positioning
			position = this.uiDialog.css("position"),
			resizeHandles = typeof handles === "string" ?
				handles	:
				"n,e,s,w,se,sw,ne,nw";

		function filteredUi( ui ) {
			return {
				originalPosition: ui.originalPosition,
				originalSize: ui.originalSize,
				position: ui.position,
				size: ui.size
			};
		}

		this.uiDialog.resizable({
			cancel: ".ui-dialog-content",
			containment: "document",
			alsoResize: this.element,
			maxWidth: options.maxWidth,
			maxHeight: options.maxHeight,
			minWidth: options.minWidth,
			minHeight: this._minHeight(),
			handles: resizeHandles,
			start: function( event, ui ) {
				$( this ).addClass("ui-dialog-resizing");
				that._trigger( "resizeStart", event, filteredUi( ui ) );
			},
			resize: function( event, ui ) {
				that._trigger( "resize", event, filteredUi( ui ) );
			},
			stop: function( event, ui ) {
				options.height = $( this ).height();
				options.width = $( this ).width();
				$( this ).removeClass("ui-dialog-resizing");
				that._trigger( "resizeStop", event, filteredUi( ui ) );
			}
		})
		.css( "position", position );
	},

	_minHeight: function() {
		var options = this.options;

		return options.height === "auto" ?
			options.minHeight :
			Math.min( options.minHeight, options.height );
	},

	_position: function() {
		// Need to show the dialog to get the actual offset in the position plugin
		var isVisible = this.uiDialog.is(":visible");
		if ( !isVisible ) {
			this.uiDialog.show();
		}
		this.uiDialog.position( this.options.position );
		if ( !isVisible ) {
			this.uiDialog.hide();
		}
	},

	_setOptions: function( options ) {
		var that = this,
			resize = false,
			resizableOptions = {};

		$.each( options, function( key, value ) {
			that._setOption( key, value );

			if ( key in sizeRelatedOptions ) {
				resize = true;
			}
			if ( key in resizableRelatedOptions ) {
				resizableOptions[ key ] = value;
			}
		});

		if ( resize ) {
			this._size();
			this._position();
		}
		if ( this.uiDialog.is(":data(ui-resizable)") ) {
			this.uiDialog.resizable( "option", resizableOptions );
		}
	},

	_setOption: function( key, value ) {
		/*jshint maxcomplexity:15*/
		var isDraggable, isResizable,
			uiDialog = this.uiDialog;

		if ( key === "dialogClass" ) {
			uiDialog
				.removeClass( this.options.dialogClass )
				.addClass( value );
		}

		if ( key === "disabled" ) {
			return;
		}

		this._super( key, value );

		if ( key === "appendTo" ) {
			this.uiDialog.appendTo( this._appendTo() );
		}

		if ( key === "buttons" ) {
			this._createButtons();
		}

		if ( key === "closeText" ) {
			this.uiDialogTitlebarClose.button({
				// Ensure that we always pass a string
				label: "" + value
			});
		}

		if ( key === "draggable" ) {
			isDraggable = uiDialog.is(":data(ui-draggable)");
			if ( isDraggable && !value ) {
				uiDialog.draggable("destroy");
			}

			if ( !isDraggable && value ) {
				this._makeDraggable();
			}
		}

		if ( key === "position" ) {
			this._position();
		}

		if ( key === "resizable" ) {
			// currently resizable, becoming non-resizable
			isResizable = uiDialog.is(":data(ui-resizable)");
			if ( isResizable && !value ) {
				uiDialog.resizable("destroy");
			}

			// currently resizable, changing handles
			if ( isResizable && typeof value === "string" ) {
				uiDialog.resizable( "option", "handles", value );
			}

			// currently non-resizable, becoming resizable
			if ( !isResizable && value !== false ) {
				this._makeResizable();
			}
		}

		if ( key === "title" ) {
			this._title( this.uiDialogTitlebar.find(".ui-dialog-title") );
		}
	},

	_size: function() {
		// If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
		// divs will both have width and height set, so we need to reset them
		var nonContentHeight, minContentHeight, maxContentHeight,
			options = this.options;

		// Reset content sizing
		this.element.show().css({
			width: "auto",
			minHeight: 0,
			maxHeight: "none",
			height: 0
		});

		if ( options.minWidth > options.width ) {
			options.width = options.minWidth;
		}

		// reset wrapper sizing
		// determine the height of all the non-content elements
		nonContentHeight = this.uiDialog.css({
				height: "auto",
				width: options.width
			})
			.outerHeight();
		minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
		maxContentHeight = typeof options.maxHeight === "number" ?
			Math.max( 0, options.maxHeight - nonContentHeight ) :
			"none";

		if ( options.height === "auto" ) {
			this.element.css({
				minHeight: minContentHeight,
				maxHeight: maxContentHeight,
				height: "auto"
			});
		} else {
			this.element.height( Math.max( 0, options.height - nonContentHeight ) );
		}

		if (this.uiDialog.is(":data(ui-resizable)") ) {
			this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
		}
	},

	_createOverlay: function() {
		if ( !this.options.modal ) {
			return;
		}

		if ( !$.ui.dialog.overlayInstances ) {
			// Prevent use of anchors and inputs.
			// We use a delay in case the overlay is created from an
			// event that we're going to be cancelling. (#2804)
			this._delay(function() {
				// Handle .dialog().dialog("close") (#4065)
				if ( $.ui.dialog.overlayInstances ) {
					this._on( this.document, {
						focusin: function( event ) {
							if ( !$( event.target ).closest(".ui-dialog").length ) {
								event.preventDefault();
								$(".ui-dialog:visible:last .ui-dialog-content")
									.data("ui-dialog")._focusTabbable();
							}
						}
					});
				}
			});
		}

		this.overlay = $("<div>")
			.addClass("ui-widget-overlay ui-front")
			.appendTo( this.document[0].body );
		this._on( this.overlay, {
			mousedown: "_keepFocus"
		});
		$.ui.dialog.overlayInstances++;
	},

	_destroyOverlay: function() {
		if ( !this.options.modal ) {
			return;
		}

		$.ui.dialog.overlayInstances--;
		if ( !$.ui.dialog.overlayInstances ) {
			this._off( this.document, "focusin" );
		}
		this.overlay.remove();
	}
});

$.ui.dialog.overlayInstances = 0;

// DEPRECATED
if ( $.uiBackCompat !== false ) {
	// position option with array notation
	// just override with old implementation
	$.widget( "ui.dialog", $.ui.dialog, {
		_position: function() {
			var position = this.options.position,
				myAt = [],
				offset = [ 0, 0 ],
				isVisible;

			if ( position ) {
				if ( typeof position === "string" || (typeof position === "object" && "0" in position ) ) {
					myAt = position.split ? position.split(" ") : [ position[0], position[1] ];
					if ( myAt.length === 1 ) {
						myAt[1] = myAt[0];
					}

					$.each( [ "left", "top" ], function( i, offsetPosition ) {
						if ( +myAt[ i ] === myAt[ i ] ) {
							offset[ i ] = myAt[ i ];
							myAt[ i ] = offsetPosition;
						}
					});

					position = {
						my: myAt[0] + (offset[0] < 0 ? offset[0] : "+" + offset[0]) + " " +
							myAt[1] + (offset[1] < 0 ? offset[1] : "+" + offset[1]),
						at: myAt.join(" ")
					};
				}

				position = $.extend( {}, $.ui.dialog.prototype.options.position, position );
			} else {
				position = $.ui.dialog.prototype.options.position;
			}

			// need to show the dialog to get the actual offset in the position plugin
			isVisible = this.uiDialog.is(":visible");
			if ( !isVisible ) {
				this.uiDialog.show();
			}
			this.uiDialog.position( position );
			if ( !isVisible ) {
				this.uiDialog.hide();
			}
		}
	});
}

}( jQuery ) );

// file: 000-1-150-jquery.ui.effect-blind.js
/*!
 * jQuery UI Effects Blind 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/blind-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

var rvertical = /up|down|vertical/,
	rpositivemotion = /up|left|vertical|horizontal/;

$.effects.effect.blind = function( o, done ) {
	// Create element
	var el = $( this ),
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
		mode = $.effects.setMode( el, o.mode || "hide" ),
		direction = o.direction || "up",
		vertical = rvertical.test( direction ),
		ref = vertical ? "height" : "width",
		ref2 = vertical ? "top" : "left",
		motion = rpositivemotion.test( direction ),
		animation = {},
		show = mode === "show",
		wrapper, distance, margin;

	// if already wrapped, the wrapper's properties are my property. #6245
	if ( el.parent().is( ".ui-effects-wrapper" ) ) {
		$.effects.save( el.parent(), props );
	} else {
		$.effects.save( el, props );
	}
	el.show();
	wrapper = $.effects.createWrapper( el ).css({
		overflow: "hidden"
	});

	distance = wrapper[ ref ]();
	margin = parseFloat( wrapper.css( ref2 ) ) || 0;

	animation[ ref ] = show ? distance : 0;
	if ( !motion ) {
		el
			.css( vertical ? "bottom" : "right", 0 )
			.css( vertical ? "top" : "left", "auto" )
			.css({ position: "absolute" });

		animation[ ref2 ] = show ? margin : distance + margin;
	}

	// start at 0 if we are showing
	if ( show ) {
		wrapper.css( ref, 0 );
		if ( ! motion ) {
			wrapper.css( ref2, margin + distance );
		}
	}

	// Animate
	wrapper.animate( animation, {
		duration: o.duration,
		easing: o.easing,
		queue: false,
		complete: function() {
			if ( mode === "hide" ) {
				el.hide();
			}
			$.effects.restore( el, props );
			$.effects.removeWrapper( el );
			done();
		}
	});

};

})(jQuery);

// file: 000-1-160-jquery.ui.effect-bounce.js
/*!
 * jQuery UI Effects Bounce 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/bounce-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.bounce = function( o, done ) {
	var el = $( this ),
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],

		// defaults:
		mode = $.effects.setMode( el, o.mode || "effect" ),
		hide = mode === "hide",
		show = mode === "show",
		direction = o.direction || "up",
		distance = o.distance,
		times = o.times || 5,

		// number of internal animations
		anims = times * 2 + ( show || hide ? 1 : 0 ),
		speed = o.duration / anims,
		easing = o.easing,

		// utility:
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
		motion = ( direction === "up" || direction === "left" ),
		i,
		upAnim,
		downAnim,

		// we will need to re-assemble the queue to stack our animations in place
		queue = el.queue(),
		queuelen = queue.length;

	// Avoid touching opacity to prevent clearType and PNG issues in IE
	if ( show || hide ) {
		props.push( "opacity" );
	}

	$.effects.save( el, props );
	el.show();
	$.effects.createWrapper( el ); // Create Wrapper

	// default distance for the BIGGEST bounce is the outer Distance / 3
	if ( !distance ) {
		distance = el[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
	}

	if ( show ) {
		downAnim = { opacity: 1 };
		downAnim[ ref ] = 0;

		// if we are showing, force opacity 0 and set the initial position
		// then do the "first" animation
		el.css( "opacity", 0 )
			.css( ref, motion ? -distance * 2 : distance * 2 )
			.animate( downAnim, speed, easing );
	}

	// start at the smallest distance if we are hiding
	if ( hide ) {
		distance = distance / Math.pow( 2, times - 1 );
	}

	downAnim = {};
	downAnim[ ref ] = 0;
	// Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
	for ( i = 0; i < times; i++ ) {
		upAnim = {};
		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;

		el.animate( upAnim, speed, easing )
			.animate( downAnim, speed, easing );

		distance = hide ? distance * 2 : distance / 2;
	}

	// Last Bounce when Hiding
	if ( hide ) {
		upAnim = { opacity: 0 };
		upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;

		el.animate( upAnim, speed, easing );
	}

	el.queue(function() {
		if ( hide ) {
			el.hide();
		}
		$.effects.restore( el, props );
		$.effects.removeWrapper( el );
		done();
	});

	// inject all the animations we just queued to be first in line (after "inprogress")
	if ( queuelen > 1) {
		queue.splice.apply( queue,
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
	}
	el.dequeue();

};

})(jQuery);

// file: 000-1-170-jquery.ui.effect-clip.js
/*!
 * jQuery UI Effects Clip 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/clip-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.clip = function( o, done ) {
	// Create element
	var el = $( this ),
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
		mode = $.effects.setMode( el, o.mode || "hide" ),
		show = mode === "show",
		direction = o.direction || "vertical",
		vert = direction === "vertical",
		size = vert ? "height" : "width",
		position = vert ? "top" : "left",
		animation = {},
		wrapper, animate, distance;

	// Save & Show
	$.effects.save( el, props );
	el.show();

	// Create Wrapper
	wrapper = $.effects.createWrapper( el ).css({
		overflow: "hidden"
	});
	animate = ( el[0].tagName === "IMG" ) ? wrapper : el;
	distance = animate[ size ]();

	// Shift
	if ( show ) {
		animate.css( size, 0 );
		animate.css( position, distance / 2 );
	}

	// Create Animation Object:
	animation[ size ] = show ? distance : 0;
	animation[ position ] = show ? 0 : distance / 2;

	// Animate
	animate.animate( animation, {
		queue: false,
		duration: o.duration,
		easing: o.easing,
		complete: function() {
			if ( !show ) {
				el.hide();
			}
			$.effects.restore( el, props );
			$.effects.removeWrapper( el );
			done();
		}
	});

};

})(jQuery);

// file: 000-1-180-jquery.ui.effect-drop.js
/*!
 * jQuery UI Effects Drop 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/drop-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.drop = function( o, done ) {

	var el = $( this ),
		props = [ "position", "top", "bottom", "left", "right", "opacity", "height", "width" ],
		mode = $.effects.setMode( el, o.mode || "hide" ),
		show = mode === "show",
		direction = o.direction || "left",
		ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
		motion = ( direction === "up" || direction === "left" ) ? "pos" : "neg",
		animation = {
			opacity: show ? 1 : 0
		},
		distance;

	// Adjust
	$.effects.save( el, props );
	el.show();
	$.effects.createWrapper( el );

	distance = o.distance || el[ ref === "top" ? "outerHeight": "outerWidth" ]( true ) / 2;

	if ( show ) {
		el
			.css( "opacity", 0 )
			.css( ref, motion === "pos" ? -distance : distance );
	}

	// Animation
	animation[ ref ] = ( show ?
		( motion === "pos" ? "+=" : "-=" ) :
		( motion === "pos" ? "-=" : "+=" ) ) +
		distance;

	// Animate
	el.animate( animation, {
		queue: false,
		duration: o.duration,
		easing: o.easing,
		complete: function() {
			if ( mode === "hide" ) {
				el.hide();
			}
			$.effects.restore( el, props );
			$.effects.removeWrapper( el );
			done();
		}
	});
};

})(jQuery);

// file: 000-1-190-jquery.ui.effect-explode.js
/*!
 * jQuery UI Effects Explode 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/explode-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.explode = function( o, done ) {

	var rows = o.pieces ? Math.round( Math.sqrt( o.pieces ) ) : 3,
		cells = rows,
		el = $( this ),
		mode = $.effects.setMode( el, o.mode || "hide" ),
		show = mode === "show",

		// show and then visibility:hidden the element before calculating offset
		offset = el.show().css( "visibility", "hidden" ).offset(),

		// width and height of a piece
		width = Math.ceil( el.outerWidth() / cells ),
		height = Math.ceil( el.outerHeight() / rows ),
		pieces = [],

		// loop
		i, j, left, top, mx, my;

	// children animate complete:
	function childComplete() {
		pieces.push( this );
		if ( pieces.length === rows * cells ) {
			animComplete();
		}
	}

	// clone the element for each row and cell.
	for( i = 0; i < rows ; i++ ) { // ===>
		top = offset.top + i * height;
		my = i - ( rows - 1 ) / 2 ;

		for( j = 0; j < cells ; j++ ) { // |||
			left = offset.left + j * width;
			mx = j - ( cells - 1 ) / 2 ;

			// Create a clone of the now hidden main element that will be absolute positioned
			// within a wrapper div off the -left and -top equal to size of our pieces
			el
				.clone()
				.appendTo( "body" )
				.wrap( "<div></div>" )
				.css({
					position: "absolute",
					visibility: "visible",
					left: -j * width,
					top: -i * height
				})

			// select the wrapper - make it overflow: hidden and absolute positioned based on
			// where the original was located +left and +top equal to the size of pieces
				.parent()
				.addClass( "ui-effects-explode" )
				.css({
					position: "absolute",
					overflow: "hidden",
					width: width,
					height: height,
					left: left + ( show ? mx * width : 0 ),
					top: top + ( show ? my * height : 0 ),
					opacity: show ? 0 : 1
				}).animate({
					left: left + ( show ? 0 : mx * width ),
					top: top + ( show ? 0 : my * height ),
					opacity: show ? 1 : 0
				}, o.duration || 500, o.easing, childComplete );
		}
	}

	function animComplete() {
		el.css({
			visibility: "visible"
		});
		$( pieces ).remove();
		if ( !show ) {
			el.hide();
		}
		done();
	}
};

})(jQuery);

// file: 000-1-200-jquery.ui.effect-fade.js
/*!
 * jQuery UI Effects Fade 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/fade-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.fade = function( o, done ) {
	var el = $( this ),
		mode = $.effects.setMode( el, o.mode || "toggle" );

	el.animate({
		opacity: mode
	}, {
		queue: false,
		duration: o.duration,
		easing: o.easing,
		complete: done
	});
};

})( jQuery );

// file: 000-1-210-jquery.ui.effect-fold.js
/*!
 * jQuery UI Effects Fold 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/fold-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.fold = function( o, done ) {

	// Create element
	var el = $( this ),
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
		mode = $.effects.setMode( el, o.mode || "hide" ),
		show = mode === "show",
		hide = mode === "hide",
		size = o.size || 15,
		percent = /([0-9]+)%/.exec( size ),
		horizFirst = !!o.horizFirst,
		widthFirst = show !== horizFirst,
		ref = widthFirst ? [ "width", "height" ] : [ "height", "width" ],
		duration = o.duration / 2,
		wrapper, distance,
		animation1 = {},
		animation2 = {};

	$.effects.save( el, props );
	el.show();

	// Create Wrapper
	wrapper = $.effects.createWrapper( el ).css({
		overflow: "hidden"
	});
	distance = widthFirst ?
		[ wrapper.width(), wrapper.height() ] :
		[ wrapper.height(), wrapper.width() ];

	if ( percent ) {
		size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
	}
	if ( show ) {
		wrapper.css( horizFirst ? {
			height: 0,
			width: size
		} : {
			height: size,
			width: 0
		});
	}

	// Animation
	animation1[ ref[ 0 ] ] = show ? distance[ 0 ] : size;
	animation2[ ref[ 1 ] ] = show ? distance[ 1 ] : 0;

	// Animate
	wrapper
		.animate( animation1, duration, o.easing )
		.animate( animation2, duration, o.easing, function() {
			if ( hide ) {
				el.hide();
			}
			$.effects.restore( el, props );
			$.effects.removeWrapper( el );
			done();
		});

};

})(jQuery);

// file: 000-1-220-jquery.ui.effect-highlight.js
/*!
 * jQuery UI Effects Highlight 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/highlight-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.highlight = function( o, done ) {
	var elem = $( this ),
		props = [ "backgroundImage", "backgroundColor", "opacity" ],
		mode = $.effects.setMode( elem, o.mode || "show" ),
		animation = {
			backgroundColor: elem.css( "backgroundColor" )
		};

	if (mode === "hide") {
		animation.opacity = 0;
	}

	$.effects.save( elem, props );

	elem
		.show()
		.css({
			backgroundImage: "none",
			backgroundColor: o.color || "#ffff99"
		})
		.animate( animation, {
			queue: false,
			duration: o.duration,
			easing: o.easing,
			complete: function() {
				if ( mode === "hide" ) {
					elem.hide();
				}
				$.effects.restore( elem, props );
				done();
			}
		});
};

})(jQuery);

// file: 000-1-230-jquery.ui.effect-pulsate.js
/*!
 * jQuery UI Effects Pulsate 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/pulsate-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.pulsate = function( o, done ) {
	var elem = $( this ),
		mode = $.effects.setMode( elem, o.mode || "show" ),
		show = mode === "show",
		hide = mode === "hide",
		showhide = ( show || mode === "hide" ),

		// showing or hiding leaves of the "last" animation
		anims = ( ( o.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
		duration = o.duration / anims,
		animateTo = 0,
		queue = elem.queue(),
		queuelen = queue.length,
		i;

	if ( show || !elem.is(":visible")) {
		elem.css( "opacity", 0 ).show();
		animateTo = 1;
	}

	// anims - 1 opacity "toggles"
	for ( i = 1; i < anims; i++ ) {
		elem.animate({
			opacity: animateTo
		}, duration, o.easing );
		animateTo = 1 - animateTo;
	}

	elem.animate({
		opacity: animateTo
	}, duration, o.easing);

	elem.queue(function() {
		if ( hide ) {
			elem.hide();
		}
		done();
	});

	// We just queued up "anims" animations, we need to put them next in the queue
	if ( queuelen > 1 ) {
		queue.splice.apply( queue,
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
	}
	elem.dequeue();
};

})(jQuery);

// file: 000-1-240-jquery.ui.effect-scale.js
/*!
 * jQuery UI Effects Scale 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/scale-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.puff = function( o, done ) {
	var elem = $( this ),
		mode = $.effects.setMode( elem, o.mode || "hide" ),
		hide = mode === "hide",
		percent = parseInt( o.percent, 10 ) || 150,
		factor = percent / 100,
		original = {
			height: elem.height(),
			width: elem.width(),
			outerHeight: elem.outerHeight(),
			outerWidth: elem.outerWidth()
		};

	$.extend( o, {
		effect: "scale",
		queue: false,
		fade: true,
		mode: mode,
		complete: done,
		percent: hide ? percent : 100,
		from: hide ?
			original :
			{
				height: original.height * factor,
				width: original.width * factor,
				outerHeight: original.outerHeight * factor,
				outerWidth: original.outerWidth * factor
			}
	});

	elem.effect( o );
};

$.effects.effect.scale = function( o, done ) {

	// Create element
	var el = $( this ),
		options = $.extend( true, {}, o ),
		mode = $.effects.setMode( el, o.mode || "effect" ),
		percent = parseInt( o.percent, 10 ) ||
			( parseInt( o.percent, 10 ) === 0 ? 0 : ( mode === "hide" ? 0 : 100 ) ),
		direction = o.direction || "both",
		origin = o.origin,
		original = {
			height: el.height(),
			width: el.width(),
			outerHeight: el.outerHeight(),
			outerWidth: el.outerWidth()
		},
		factor = {
			y: direction !== "horizontal" ? (percent / 100) : 1,
			x: direction !== "vertical" ? (percent / 100) : 1
		};

	// We are going to pass this effect to the size effect:
	options.effect = "size";
	options.queue = false;
	options.complete = done;

	// Set default origin and restore for show/hide
	if ( mode !== "effect" ) {
		options.origin = origin || ["middle","center"];
		options.restore = true;
	}

	options.from = o.from || ( mode === "show" ? {
		height: 0,
		width: 0,
		outerHeight: 0,
		outerWidth: 0
	} : original );
	options.to = {
		height: original.height * factor.y,
		width: original.width * factor.x,
		outerHeight: original.outerHeight * factor.y,
		outerWidth: original.outerWidth * factor.x
	};

	// Fade option to support puff
	if ( options.fade ) {
		if ( mode === "show" ) {
			options.from.opacity = 0;
			options.to.opacity = 1;
		}
		if ( mode === "hide" ) {
			options.from.opacity = 1;
			options.to.opacity = 0;
		}
	}

	// Animate
	el.effect( options );

};

$.effects.effect.size = function( o, done ) {

	// Create element
	var original, baseline, factor,
		el = $( this ),
		props0 = [ "position", "top", "bottom", "left", "right", "width", "height", "overflow", "opacity" ],

		// Always restore
		props1 = [ "position", "top", "bottom", "left", "right", "overflow", "opacity" ],

		// Copy for children
		props2 = [ "width", "height", "overflow" ],
		cProps = [ "fontSize" ],
		vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
		hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],

		// Set options
		mode = $.effects.setMode( el, o.mode || "effect" ),
		restore = o.restore || mode !== "effect",
		scale = o.scale || "both",
		origin = o.origin || [ "middle", "center" ],
		position = el.css( "position" ),
		props = restore ? props0 : props1,
		zero = {
			height: 0,
			width: 0,
			outerHeight: 0,
			outerWidth: 0
		};

	if ( mode === "show" ) {
		el.show();
	}
	original = {
		height: el.height(),
		width: el.width(),
		outerHeight: el.outerHeight(),
		outerWidth: el.outerWidth()
	};

	if ( o.mode === "toggle" && mode === "show" ) {
		el.from = o.to || zero;
		el.to = o.from || original;
	} else {
		el.from = o.from || ( mode === "show" ? zero : original );
		el.to = o.to || ( mode === "hide" ? zero : original );
	}

	// Set scaling factor
	factor = {
		from: {
			y: el.from.height / original.height,
			x: el.from.width / original.width
		},
		to: {
			y: el.to.height / original.height,
			x: el.to.width / original.width
		}
	};

	// Scale the css box
	if ( scale === "box" || scale === "both" ) {

		// Vertical props scaling
		if ( factor.from.y !== factor.to.y ) {
			props = props.concat( vProps );
			el.from = $.effects.setTransition( el, vProps, factor.from.y, el.from );
			el.to = $.effects.setTransition( el, vProps, factor.to.y, el.to );
		}

		// Horizontal props scaling
		if ( factor.from.x !== factor.to.x ) {
			props = props.concat( hProps );
			el.from = $.effects.setTransition( el, hProps, factor.from.x, el.from );
			el.to = $.effects.setTransition( el, hProps, factor.to.x, el.to );
		}
	}

	// Scale the content
	if ( scale === "content" || scale === "both" ) {

		// Vertical props scaling
		if ( factor.from.y !== factor.to.y ) {
			props = props.concat( cProps ).concat( props2 );
			el.from = $.effects.setTransition( el, cProps, factor.from.y, el.from );
			el.to = $.effects.setTransition( el, cProps, factor.to.y, el.to );
		}
	}

	$.effects.save( el, props );
	el.show();
	$.effects.createWrapper( el );
	el.css( "overflow", "hidden" ).css( el.from );

	// Adjust
	if (origin) { // Calculate baseline shifts
		baseline = $.effects.getBaseline( origin, original );
		el.from.top = ( original.outerHeight - el.outerHeight() ) * baseline.y;
		el.from.left = ( original.outerWidth - el.outerWidth() ) * baseline.x;
		el.to.top = ( original.outerHeight - el.to.outerHeight ) * baseline.y;
		el.to.left = ( original.outerWidth - el.to.outerWidth ) * baseline.x;
	}
	el.css( el.from ); // set top & left

	// Animate
	if ( scale === "content" || scale === "both" ) { // Scale the children

		// Add margins/font-size
		vProps = vProps.concat([ "marginTop", "marginBottom" ]).concat(cProps);
		hProps = hProps.concat([ "marginLeft", "marginRight" ]);
		props2 = props0.concat(vProps).concat(hProps);

		el.find( "*[width]" ).each( function(){
			var child = $( this ),
				c_original = {
					height: child.height(),
					width: child.width(),
					outerHeight: child.outerHeight(),
					outerWidth: child.outerWidth()
				};
			if (restore) {
				$.effects.save(child, props2);
			}

			child.from = {
				height: c_original.height * factor.from.y,
				width: c_original.width * factor.from.x,
				outerHeight: c_original.outerHeight * factor.from.y,
				outerWidth: c_original.outerWidth * factor.from.x
			};
			child.to = {
				height: c_original.height * factor.to.y,
				width: c_original.width * factor.to.x,
				outerHeight: c_original.height * factor.to.y,
				outerWidth: c_original.width * factor.to.x
			};

			// Vertical props scaling
			if ( factor.from.y !== factor.to.y ) {
				child.from = $.effects.setTransition( child, vProps, factor.from.y, child.from );
				child.to = $.effects.setTransition( child, vProps, factor.to.y, child.to );
			}

			// Horizontal props scaling
			if ( factor.from.x !== factor.to.x ) {
				child.from = $.effects.setTransition( child, hProps, factor.from.x, child.from );
				child.to = $.effects.setTransition( child, hProps, factor.to.x, child.to );
			}

			// Animate children
			child.css( child.from );
			child.animate( child.to, o.duration, o.easing, function() {

				// Restore children
				if ( restore ) {
					$.effects.restore( child, props2 );
				}
			});
		});
	}

	// Animate
	el.animate( el.to, {
		queue: false,
		duration: o.duration,
		easing: o.easing,
		complete: function() {
			if ( el.to.opacity === 0 ) {
				el.css( "opacity", el.from.opacity );
			}
			if( mode === "hide" ) {
				el.hide();
			}
			$.effects.restore( el, props );
			if ( !restore ) {

				// we need to calculate our new positioning based on the scaling
				if ( position === "static" ) {
					el.css({
						position: "relative",
						top: el.to.top,
						left: el.to.left
					});
				} else {
					$.each([ "top", "left" ], function( idx, pos ) {
						el.css( pos, function( _, str ) {
							var val = parseInt( str, 10 ),
								toRef = idx ? el.to.left : el.to.top;

							// if original was "auto", recalculate the new value from wrapper
							if ( str === "auto" ) {
								return toRef + "px";
							}

							return val + toRef + "px";
						});
					});
				}
			}

			$.effects.removeWrapper( el );
			done();
		}
	});

};

})(jQuery);

// file: 000-1-250-jquery.ui.effect-shake.js
/*!
 * jQuery UI Effects Shake 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/shake-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.shake = function( o, done ) {

	var el = $( this ),
		props = [ "position", "top", "bottom", "left", "right", "height", "width" ],
		mode = $.effects.setMode( el, o.mode || "effect" ),
		direction = o.direction || "left",
		distance = o.distance || 20,
		times = o.times || 3,
		anims = times * 2 + 1,
		speed = Math.round(o.duration/anims),
		ref = (direction === "up" || direction === "down") ? "top" : "left",
		positiveMotion = (direction === "up" || direction === "left"),
		animation = {},
		animation1 = {},
		animation2 = {},
		i,

		// we will need to re-assemble the queue to stack our animations in place
		queue = el.queue(),
		queuelen = queue.length;

	$.effects.save( el, props );
	el.show();
	$.effects.createWrapper( el );

	// Animation
	animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
	animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
	animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;

	// Animate
	el.animate( animation, speed, o.easing );

	// Shakes
	for ( i = 1; i < times; i++ ) {
		el.animate( animation1, speed, o.easing ).animate( animation2, speed, o.easing );
	}
	el
		.animate( animation1, speed, o.easing )
		.animate( animation, speed / 2, o.easing )
		.queue(function() {
			if ( mode === "hide" ) {
				el.hide();
			}
			$.effects.restore( el, props );
			$.effects.removeWrapper( el );
			done();
		});

	// inject all the animations we just queued to be first in line (after "inprogress")
	if ( queuelen > 1) {
		queue.splice.apply( queue,
			[ 1, 0 ].concat( queue.splice( queuelen, anims + 1 ) ) );
	}
	el.dequeue();

};

})(jQuery);

// file: 000-1-260-jquery.ui.effect-slide.js
/*!
 * jQuery UI Effects Slide 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/slide-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.slide = function( o, done ) {

	// Create element
	var el = $( this ),
		props = [ "position", "top", "bottom", "left", "right", "width", "height" ],
		mode = $.effects.setMode( el, o.mode || "show" ),
		show = mode === "show",
		direction = o.direction || "left",
		ref = (direction === "up" || direction === "down") ? "top" : "left",
		positiveMotion = (direction === "up" || direction === "left"),
		distance,
		animation = {};

	// Adjust
	$.effects.save( el, props );
	el.show();
	distance = o.distance || el[ ref === "top" ? "outerHeight" : "outerWidth" ]( true );

	$.effects.createWrapper( el ).css({
		overflow: "hidden"
	});

	if ( show ) {
		el.css( ref, positiveMotion ? (isNaN(distance) ? "-" + distance : -distance) : distance );
	}

	// Animation
	animation[ ref ] = ( show ?
		( positiveMotion ? "+=" : "-=") :
		( positiveMotion ? "-=" : "+=")) +
		distance;

	// Animate
	el.animate( animation, {
		queue: false,
		duration: o.duration,
		easing: o.easing,
		complete: function() {
			if ( mode === "hide" ) {
				el.hide();
			}
			$.effects.restore( el, props );
			$.effects.removeWrapper( el );
			done();
		}
	});
};

})(jQuery);

// file: 000-1-270-jquery.ui.effect-transfer.js
/*!
 * jQuery UI Effects Transfer 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/transfer-effect/
 *
 * Depends:
 *	jquery.ui.effect.js
 */
(function( $, undefined ) {

$.effects.effect.transfer = function( o, done ) {
	var elem = $( this ),
		target = $( o.to ),
		targetFixed = target.css( "position" ) === "fixed",
		body = $("body"),
		fixTop = targetFixed ? body.scrollTop() : 0,
		fixLeft = targetFixed ? body.scrollLeft() : 0,
		endPosition = target.offset(),
		animation = {
			top: endPosition.top - fixTop ,
			left: endPosition.left - fixLeft ,
			height: target.innerHeight(),
			width: target.innerWidth()
		},
		startPosition = elem.offset(),
		transfer = $( "<div class='ui-effects-transfer'></div>" )
			.appendTo( document.body )
			.addClass( o.className )
			.css({
				top: startPosition.top - fixTop ,
				left: startPosition.left - fixLeft ,
				height: elem.innerHeight(),
				width: elem.innerWidth(),
				position: targetFixed ? "fixed" : "absolute"
			})
			.animate( animation, o.duration, o.easing, function() {
				transfer.remove();
				done();
			});
};

})(jQuery);

// file: 000-1-280-jquery.ui.menu.js
/*!
 * jQuery UI Menu 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/menu/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.position.js
 */
(function( $, undefined ) {

$.widget( "ui.menu", {
	version: "1.10.0",
	defaultElement: "<ul>",
	delay: 300,
	options: {
		icons: {
			submenu: "ui-icon-carat-1-e"
		},
		menus: "ul",
		position: {
			my: "left top",
			at: "right top"
		},
		role: "menu",

		// callbacks
		blur: null,
		focus: null,
		select: null
	},

	_create: function() {
		this.activeMenu = this.element;
		// flag used to prevent firing of the click handler
		// as the event bubbles up through nested menus
		this.mouseHandled = false;
		this.element
			.uniqueId()
			.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
			.toggleClass( "ui-menu-icons", !!this.element.find( ".ui-icon" ).length )
			.attr({
				role: this.options.role,
				tabIndex: 0
			})
			// need to catch all clicks on disabled menu
			// not possible through _on
			.bind( "click" + this.eventNamespace, $.proxy(function( event ) {
				if ( this.options.disabled ) {
					event.preventDefault();
				}
			}, this ));

		if ( this.options.disabled ) {
			this.element
				.addClass( "ui-state-disabled" )
				.attr( "aria-disabled", "true" );
		}

		this._on({
			// Prevent focus from sticking to links inside menu after clicking
			// them (focus should always stay on UL during navigation).
			"mousedown .ui-menu-item > a": function( event ) {
				event.preventDefault();
			},
			"click .ui-state-disabled > a": function( event ) {
				event.preventDefault();
			},
			"click .ui-menu-item:has(a)": function( event ) {
				var target = $( event.target ).closest( ".ui-menu-item" );
				if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
					this.mouseHandled = true;

					this.select( event );
					// Open submenu on click
					if ( target.has( ".ui-menu" ).length ) {
						this.expand( event );
					} else if ( !this.element.is( ":focus" ) ) {
						// Redirect focus to the menu
						this.element.trigger( "focus", [ true ] );

						// If the active item is on the top level, let it stay active.
						// Otherwise, blur the active item since it is no longer visible.
						if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
							clearTimeout( this.timer );
						}
					}
				}
			},
			"mouseenter .ui-menu-item": function( event ) {
				var target = $( event.currentTarget );
				// Remove ui-state-active class from siblings of the newly focused menu item
				// to avoid a jump caused by adjacent elements both having a class with a border
				target.siblings().children( ".ui-state-active" ).removeClass( "ui-state-active" );
				this.focus( event, target );
			},
			mouseleave: "collapseAll",
			"mouseleave .ui-menu": "collapseAll",
			focus: function( event, keepActiveItem ) {
				// If there's already an active item, keep it active
				// If not, activate the first item
				var item = this.active || this.element.children( ".ui-menu-item" ).eq( 0 );

				if ( !keepActiveItem ) {
					this.focus( event, item );
				}
			},
			blur: function( event ) {
				this._delay(function() {
					if ( !$.contains( this.element[0], this.document[0].activeElement ) ) {
						this.collapseAll( event );
					}
				});
			},
			keydown: "_keydown"
		});

		this.refresh();

		// Clicks outside of a menu collapse any open menus
		this._on( this.document, {
			click: function( event ) {
				if ( !$( event.target ).closest( ".ui-menu" ).length ) {
					this.collapseAll( event );
				}

				// Reset the mouseHandled flag
				this.mouseHandled = false;
			}
		});
	},

	_destroy: function() {
		// Destroy (sub)menus
		this.element
			.removeAttr( "aria-activedescendant" )
			.find( ".ui-menu" ).addBack()
				.removeClass( "ui-menu ui-widget ui-widget-content ui-corner-all ui-menu-icons" )
				.removeAttr( "role" )
				.removeAttr( "tabIndex" )
				.removeAttr( "aria-labelledby" )
				.removeAttr( "aria-expanded" )
				.removeAttr( "aria-hidden" )
				.removeAttr( "aria-disabled" )
				.removeUniqueId()
				.show();

		// Destroy menu items
		this.element.find( ".ui-menu-item" )
			.removeClass( "ui-menu-item" )
			.removeAttr( "role" )
			.removeAttr( "aria-disabled" )
			.children( "a" )
				.removeUniqueId()
				.removeClass( "ui-corner-all ui-state-hover" )
				.removeAttr( "tabIndex" )
				.removeAttr( "role" )
				.removeAttr( "aria-haspopup" )
				.children().each( function() {
					var elem = $( this );
					if ( elem.data( "ui-menu-submenu-carat" ) ) {
						elem.remove();
					}
				});

		// Destroy menu dividers
		this.element.find( ".ui-menu-divider" ).removeClass( "ui-menu-divider ui-widget-content" );
	},

	_keydown: function( event ) {
		/*jshint maxcomplexity:20*/
		var match, prev, character, skip, regex,
			preventDefault = true;

		function escape( value ) {
			return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
		}

		switch ( event.keyCode ) {
		case $.ui.keyCode.PAGE_UP:
			this.previousPage( event );
			break;
		case $.ui.keyCode.PAGE_DOWN:
			this.nextPage( event );
			break;
		case $.ui.keyCode.HOME:
			this._move( "first", "first", event );
			break;
		case $.ui.keyCode.END:
			this._move( "last", "last", event );
			break;
		case $.ui.keyCode.UP:
			this.previous( event );
			break;
		case $.ui.keyCode.DOWN:
			this.next( event );
			break;
		case $.ui.keyCode.LEFT:
			this.collapse( event );
			break;
		case $.ui.keyCode.RIGHT:
			if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
				this.expand( event );
			}
			break;
		case $.ui.keyCode.ENTER:
		case $.ui.keyCode.SPACE:
			this._activate( event );
			break;
		case $.ui.keyCode.ESCAPE:
			this.collapse( event );
			break;
		default:
			preventDefault = false;
			prev = this.previousFilter || "";
			character = String.fromCharCode( event.keyCode );
			skip = false;

			clearTimeout( this.filterTimer );

			if ( character === prev ) {
				skip = true;
			} else {
				character = prev + character;
			}

			regex = new RegExp( "^" + escape( character ), "i" );
			match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
				return regex.test( $( this ).children( "a" ).text() );
			});
			match = skip && match.index( this.active.next() ) !== -1 ?
				this.active.nextAll( ".ui-menu-item" ) :
				match;

			// If no matches on the current filter, reset to the last character pressed
			// to move down the menu to the first item that starts with that character
			if ( !match.length ) {
				character = String.fromCharCode( event.keyCode );
				regex = new RegExp( "^" + escape( character ), "i" );
				match = this.activeMenu.children( ".ui-menu-item" ).filter(function() {
					return regex.test( $( this ).children( "a" ).text() );
				});
			}

			if ( match.length ) {
				this.focus( event, match );
				if ( match.length > 1 ) {
					this.previousFilter = character;
					this.filterTimer = this._delay(function() {
						delete this.previousFilter;
					}, 1000 );
				} else {
					delete this.previousFilter;
				}
			} else {
				delete this.previousFilter;
			}
		}

		if ( preventDefault ) {
			event.preventDefault();
		}
	},

	_activate: function( event ) {
		if ( !this.active.is( ".ui-state-disabled" ) ) {
			if ( this.active.children( "a[aria-haspopup='true']" ).length ) {
				this.expand( event );
			} else {
				this.select( event );
			}
		}
	},

	refresh: function() {
		var menus,
			icon = this.options.icons.submenu,
			submenus = this.element.find( this.options.menus );

		// Initialize nested menus
		submenus.filter( ":not(.ui-menu)" )
			.addClass( "ui-menu ui-widget ui-widget-content ui-corner-all" )
			.hide()
			.attr({
				role: this.options.role,
				"aria-hidden": "true",
				"aria-expanded": "false"
			})
			.each(function() {
				var menu = $( this ),
					item = menu.prev( "a" ),
					submenuCarat = $( "<span>" )
						.addClass( "ui-menu-icon ui-icon " + icon )
						.data( "ui-menu-submenu-carat", true );

				item
					.attr( "aria-haspopup", "true" )
					.prepend( submenuCarat );
				menu.attr( "aria-labelledby", item.attr( "id" ) );
			});

		menus = submenus.add( this.element );

		// Don't refresh list items that are already adapted
		menus.children( ":not(.ui-menu-item):has(a)" )
			.addClass( "ui-menu-item" )
			.attr( "role", "presentation" )
			.children( "a" )
				.uniqueId()
				.addClass( "ui-corner-all" )
				.attr({
					tabIndex: -1,
					role: this._itemRole()
				});

		// Initialize unlinked menu-items containing spaces and/or dashes only as dividers
		menus.children( ":not(.ui-menu-item)" ).each(function() {
			var item = $( this );
			// hyphen, em dash, en dash
			if ( !/[^\-—–\s]/.test( item.text() ) ) {
				item.addClass( "ui-widget-content ui-menu-divider" );
			}
		});

		// Add aria-disabled attribute to any disabled menu item
		menus.children( ".ui-state-disabled" ).attr( "aria-disabled", "true" );

		// If the active item has been removed, blur the menu
		if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
			this.blur();
		}
	},

	_itemRole: function() {
		return {
			menu: "menuitem",
			listbox: "option"
		}[ this.options.role ];
	},

	_setOption: function( key, value ) {
		if ( key === "icons" ) {
			this.element.find( ".ui-menu-icon" )
				.removeClass( this.options.icons.submenu )
				.addClass( value.submenu );
		}
		this._super( key, value );
	},

	focus: function( event, item ) {
		var nested, focused;
		this.blur( event, event && event.type === "focus" );

		this._scrollIntoView( item );

		this.active = item.first();
		focused = this.active.children( "a" ).addClass( "ui-state-focus" );
		// Only update aria-activedescendant if there's a role
		// otherwise we assume focus is managed elsewhere
		if ( this.options.role ) {
			this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
		}

		// Highlight active parent menu item, if any
		this.active
			.parent()
			.closest( ".ui-menu-item" )
			.children( "a:first" )
			.addClass( "ui-state-active" );

		if ( event && event.type === "keydown" ) {
			this._close();
		} else {
			this.timer = this._delay(function() {
				this._close();
			}, this.delay );
		}

		nested = item.children( ".ui-menu" );
		if ( nested.length && ( /^mouse/.test( event.type ) ) ) {
			this._startOpening(nested);
		}
		this.activeMenu = item.parent();

		this._trigger( "focus", event, { item: item } );
	},

	_scrollIntoView: function( item ) {
		var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
		if ( this._hasScroll() ) {
			borderTop = parseFloat( $.css( this.activeMenu[0], "borderTopWidth" ) ) || 0;
			paddingTop = parseFloat( $.css( this.activeMenu[0], "paddingTop" ) ) || 0;
			offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
			scroll = this.activeMenu.scrollTop();
			elementHeight = this.activeMenu.height();
			itemHeight = item.height();

			if ( offset < 0 ) {
				this.activeMenu.scrollTop( scroll + offset );
			} else if ( offset + itemHeight > elementHeight ) {
				this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
			}
		}
	},

	blur: function( event, fromFocus ) {
		if ( !fromFocus ) {
			clearTimeout( this.timer );
		}

		if ( !this.active ) {
			return;
		}

		this.active.children( "a" ).removeClass( "ui-state-focus" );
		this.active = null;

		this._trigger( "blur", event, { item: this.active } );
	},

	_startOpening: function( submenu ) {
		clearTimeout( this.timer );

		// Don't open if already open fixes a Firefox bug that caused a .5 pixel
		// shift in the submenu position when mousing over the carat icon
		if ( submenu.attr( "aria-hidden" ) !== "true" ) {
			return;
		}

		this.timer = this._delay(function() {
			this._close();
			this._open( submenu );
		}, this.delay );
	},

	_open: function( submenu ) {
		var position = $.extend({
			of: this.active
		}, this.options.position );

		clearTimeout( this.timer );
		this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
			.hide()
			.attr( "aria-hidden", "true" );

		submenu
			.show()
			.removeAttr( "aria-hidden" )
			.attr( "aria-expanded", "true" )
			.position( position );
	},

	collapseAll: function( event, all ) {
		clearTimeout( this.timer );
		this.timer = this._delay(function() {
			// If we were passed an event, look for the submenu that contains the event
			var currentMenu = all ? this.element :
				$( event && event.target ).closest( this.element.find( ".ui-menu" ) );

			// If we found no valid submenu ancestor, use the main menu to close all sub menus anyway
			if ( !currentMenu.length ) {
				currentMenu = this.element;
			}

			this._close( currentMenu );

			this.blur( event );
			this.activeMenu = currentMenu;
		}, this.delay );
	},

	// With no arguments, closes the currently active menu - if nothing is active
	// it closes all menus.  If passed an argument, it will search for menus BELOW
	_close: function( startMenu ) {
		if ( !startMenu ) {
			startMenu = this.active ? this.active.parent() : this.element;
		}

		startMenu
			.find( ".ui-menu" )
				.hide()
				.attr( "aria-hidden", "true" )
				.attr( "aria-expanded", "false" )
			.end()
			.find( "a.ui-state-active" )
				.removeClass( "ui-state-active" );
	},

	collapse: function( event ) {
		var newItem = this.active &&
			this.active.parent().closest( ".ui-menu-item", this.element );
		if ( newItem && newItem.length ) {
			this._close();
			this.focus( event, newItem );
		}
	},

	expand: function( event ) {
		var newItem = this.active &&
			this.active
				.children( ".ui-menu " )
				.children( ".ui-menu-item" )
				.first();

		if ( newItem && newItem.length ) {
			this._open( newItem.parent() );

			// Delay so Firefox will not hide activedescendant change in expanding submenu from AT
			this._delay(function() {
				this.focus( event, newItem );
			});
		}
	},

	next: function( event ) {
		this._move( "next", "first", event );
	},

	previous: function( event ) {
		this._move( "prev", "last", event );
	},

	isFirstItem: function() {
		return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
	},

	isLastItem: function() {
		return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
	},

	_move: function( direction, filter, event ) {
		var next;
		if ( this.active ) {
			if ( direction === "first" || direction === "last" ) {
				next = this.active
					[ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
					.eq( -1 );
			} else {
				next = this.active
					[ direction + "All" ]( ".ui-menu-item" )
					.eq( 0 );
			}
		}
		if ( !next || !next.length || !this.active ) {
			next = this.activeMenu.children( ".ui-menu-item" )[ filter ]();
		}

		this.focus( event, next );
	},

	nextPage: function( event ) {
		var item, base, height;

		if ( !this.active ) {
			this.next( event );
			return;
		}
		if ( this.isLastItem() ) {
			return;
		}
		if ( this._hasScroll() ) {
			base = this.active.offset().top;
			height = this.element.height();
			this.active.nextAll( ".ui-menu-item" ).each(function() {
				item = $( this );
				return item.offset().top - base - height < 0;
			});

			this.focus( event, item );
		} else {
			this.focus( event, this.activeMenu.children( ".ui-menu-item" )
				[ !this.active ? "first" : "last" ]() );
		}
	},

	previousPage: function( event ) {
		var item, base, height;
		if ( !this.active ) {
			this.next( event );
			return;
		}
		if ( this.isFirstItem() ) {
			return;
		}
		if ( this._hasScroll() ) {
			base = this.active.offset().top;
			height = this.element.height();
			this.active.prevAll( ".ui-menu-item" ).each(function() {
				item = $( this );
				return item.offset().top - base + height > 0;
			});

			this.focus( event, item );
		} else {
			this.focus( event, this.activeMenu.children( ".ui-menu-item" ).first() );
		}
	},

	_hasScroll: function() {
		return this.element.outerHeight() < this.element.prop( "scrollHeight" );
	},

	select: function( event ) {
		// TODO: It should never be possible to not have an active item at this
		// point, but the tests don't trigger mouseenter before click.
		this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
		var ui = { item: this.active };
		if ( !this.active.has( ".ui-menu" ).length ) {
			this.collapseAll( event, true );
		}
		this._trigger( "select", event, ui );
	}
});

}( jQuery ));

// file: 000-1-290-jquery.ui.position.js
/*!
 * jQuery UI Position 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/position/
 */
(function( $, undefined ) {

$.ui = $.ui || {};

var cachedScrollbarWidth,
	max = Math.max,
	abs = Math.abs,
	round = Math.round,
	rhorizontal = /left|center|right/,
	rvertical = /top|center|bottom/,
	roffset = /[\+\-]\d+%?/,
	rposition = /^\w+/,
	rpercent = /%$/,
	_position = $.fn.position;

function getOffsets( offsets, width, height ) {
	return [
		parseInt( offsets[ 0 ], 10 ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
		parseInt( offsets[ 1 ], 10 ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
	];
}

function parseCss( element, property ) {
	return parseInt( $.css( element, property ), 10 ) || 0;
}

function getDimensions( elem ) {
	var raw = elem[0];
	if ( raw.nodeType === 9 ) {
		return {
			width: elem.width(),
			height: elem.height(),
			offset: { top: 0, left: 0 }
		};
	}
	if ( $.isWindow( raw ) ) {
		return {
			width: elem.width(),
			height: elem.height(),
			offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
		};
	}
	if ( raw.preventDefault ) {
		return {
			width: 0,
			height: 0,
			offset: { top: raw.pageY, left: raw.pageX }
		};
	}
	return {
		width: elem.outerWidth(),
		height: elem.outerHeight(),
		offset: elem.offset()
	};
}

$.position = {
	scrollbarWidth: function() {
		if ( cachedScrollbarWidth !== undefined ) {
			return cachedScrollbarWidth;
		}
		var w1, w2,
			div = $( "<div style='display:block;width:50px;height:50px;overflow:hidden;'><div style='height:100px;width:auto;'></div></div>" ),
			innerDiv = div.children()[0];

		$( "body" ).append( div );
		w1 = innerDiv.offsetWidth;
		div.css( "overflow", "scroll" );

		w2 = innerDiv.offsetWidth;

		if ( w1 === w2 ) {
			w2 = div[0].clientWidth;
		}

		div.remove();

		return (cachedScrollbarWidth = w1 - w2);
	},
	getScrollInfo: function( within ) {
		var overflowX = within.isWindow ? "" : within.element.css( "overflow-x" ),
			overflowY = within.isWindow ? "" : within.element.css( "overflow-y" ),
			hasOverflowX = overflowX === "scroll" ||
				( overflowX === "auto" && within.width < within.element[0].scrollWidth ),
			hasOverflowY = overflowY === "scroll" ||
				( overflowY === "auto" && within.height < within.element[0].scrollHeight );
		return {
			width: hasOverflowX ? $.position.scrollbarWidth() : 0,
			height: hasOverflowY ? $.position.scrollbarWidth() : 0
		};
	},
	getWithinInfo: function( element ) {
		var withinElement = $( element || window ),
			isWindow = $.isWindow( withinElement[0] );
		return {
			element: withinElement,
			isWindow: isWindow,
			offset: withinElement.offset() || { left: 0, top: 0 },
			scrollLeft: withinElement.scrollLeft(),
			scrollTop: withinElement.scrollTop(),
			width: isWindow ? withinElement.width() : withinElement.outerWidth(),
			height: isWindow ? withinElement.height() : withinElement.outerHeight()
		};
	}
};

$.fn.position = function( options ) {
	if ( !options || !options.of ) {
		return _position.apply( this, arguments );
	}

	// make a copy, we don't want to modify arguments
	options = $.extend( {}, options );

	var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
		target = $( options.of ),
		within = $.position.getWithinInfo( options.within ),
		scrollInfo = $.position.getScrollInfo( within ),
		collision = ( options.collision || "flip" ).split( " " ),
		offsets = {};

	dimensions = getDimensions( target );
	if ( target[0].preventDefault ) {
		// force left top to allow flipping
		options.at = "left top";
	}
	targetWidth = dimensions.width;
	targetHeight = dimensions.height;
	targetOffset = dimensions.offset;
	// clone to reuse original targetOffset later
	basePosition = $.extend( {}, targetOffset );

	// force my and at to have valid horizontal and vertical positions
	// if a value is missing or invalid, it will be converted to center
	$.each( [ "my", "at" ], function() {
		var pos = ( options[ this ] || "" ).split( " " ),
			horizontalOffset,
			verticalOffset;

		if ( pos.length === 1) {
			pos = rhorizontal.test( pos[ 0 ] ) ?
				pos.concat( [ "center" ] ) :
				rvertical.test( pos[ 0 ] ) ?
					[ "center" ].concat( pos ) :
					[ "center", "center" ];
		}
		pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
		pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";

		// calculate offsets
		horizontalOffset = roffset.exec( pos[ 0 ] );
		verticalOffset = roffset.exec( pos[ 1 ] );
		offsets[ this ] = [
			horizontalOffset ? horizontalOffset[ 0 ] : 0,
			verticalOffset ? verticalOffset[ 0 ] : 0
		];

		// reduce to just the positions without the offsets
		options[ this ] = [
			rposition.exec( pos[ 0 ] )[ 0 ],
			rposition.exec( pos[ 1 ] )[ 0 ]
		];
	});

	// normalize collision option
	if ( collision.length === 1 ) {
		collision[ 1 ] = collision[ 0 ];
	}

	if ( options.at[ 0 ] === "right" ) {
		basePosition.left += targetWidth;
	} else if ( options.at[ 0 ] === "center" ) {
		basePosition.left += targetWidth / 2;
	}

	if ( options.at[ 1 ] === "bottom" ) {
		basePosition.top += targetHeight;
	} else if ( options.at[ 1 ] === "center" ) {
		basePosition.top += targetHeight / 2;
	}

	atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
	basePosition.left += atOffset[ 0 ];
	basePosition.top += atOffset[ 1 ];

	return this.each(function() {
		var collisionPosition, using,
			elem = $( this ),
			elemWidth = elem.outerWidth(),
			elemHeight = elem.outerHeight(),
			marginLeft = parseCss( this, "marginLeft" ),
			marginTop = parseCss( this, "marginTop" ),
			collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) + scrollInfo.width,
			collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) + scrollInfo.height,
			position = $.extend( {}, basePosition ),
			myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );

		if ( options.my[ 0 ] === "right" ) {
			position.left -= elemWidth;
		} else if ( options.my[ 0 ] === "center" ) {
			position.left -= elemWidth / 2;
		}

		if ( options.my[ 1 ] === "bottom" ) {
			position.top -= elemHeight;
		} else if ( options.my[ 1 ] === "center" ) {
			position.top -= elemHeight / 2;
		}

		position.left += myOffset[ 0 ];
		position.top += myOffset[ 1 ];

		// if the browser doesn't support fractions, then round for consistent results
		if ( !$.support.offsetFractions ) {
			position.left = round( position.left );
			position.top = round( position.top );
		}

		collisionPosition = {
			marginLeft: marginLeft,
			marginTop: marginTop
		};

		$.each( [ "left", "top" ], function( i, dir ) {
			if ( $.ui.position[ collision[ i ] ] ) {
				$.ui.position[ collision[ i ] ][ dir ]( position, {
					targetWidth: targetWidth,
					targetHeight: targetHeight,
					elemWidth: elemWidth,
					elemHeight: elemHeight,
					collisionPosition: collisionPosition,
					collisionWidth: collisionWidth,
					collisionHeight: collisionHeight,
					offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
					my: options.my,
					at: options.at,
					within: within,
					elem : elem
				});
			}
		});

		if ( options.using ) {
			// adds feedback as second argument to using callback, if present
			using = function( props ) {
				var left = targetOffset.left - position.left,
					right = left + targetWidth - elemWidth,
					top = targetOffset.top - position.top,
					bottom = top + targetHeight - elemHeight,
					feedback = {
						target: {
							element: target,
							left: targetOffset.left,
							top: targetOffset.top,
							width: targetWidth,
							height: targetHeight
						},
						element: {
							element: elem,
							left: position.left,
							top: position.top,
							width: elemWidth,
							height: elemHeight
						},
						horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
						vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
					};
				if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
					feedback.horizontal = "center";
				}
				if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
					feedback.vertical = "middle";
				}
				if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
					feedback.important = "horizontal";
				} else {
					feedback.important = "vertical";
				}
				options.using.call( this, props, feedback );
			};
		}

		elem.offset( $.extend( position, { using: using } ) );
	});
};

$.ui.position = {
	fit: {
		left: function( position, data ) {
			var within = data.within,
				withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
				outerWidth = within.width,
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
				overLeft = withinOffset - collisionPosLeft,
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
				newOverRight;

			// element is wider than within
			if ( data.collisionWidth > outerWidth ) {
				// element is initially over the left side of within
				if ( overLeft > 0 && overRight <= 0 ) {
					newOverRight = position.left + overLeft + data.collisionWidth - outerWidth - withinOffset;
					position.left += overLeft - newOverRight;
				// element is initially over right side of within
				} else if ( overRight > 0 && overLeft <= 0 ) {
					position.left = withinOffset;
				// element is initially over both left and right sides of within
				} else {
					if ( overLeft > overRight ) {
						position.left = withinOffset + outerWidth - data.collisionWidth;
					} else {
						position.left = withinOffset;
					}
				}
			// too far left -> align with left edge
			} else if ( overLeft > 0 ) {
				position.left += overLeft;
			// too far right -> align with right edge
			} else if ( overRight > 0 ) {
				position.left -= overRight;
			// adjust based on position and margin
			} else {
				position.left = max( position.left - collisionPosLeft, position.left );
			}
		},
		top: function( position, data ) {
			var within = data.within,
				withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
				outerHeight = data.within.height,
				collisionPosTop = position.top - data.collisionPosition.marginTop,
				overTop = withinOffset - collisionPosTop,
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
				newOverBottom;

			// element is taller than within
			if ( data.collisionHeight > outerHeight ) {
				// element is initially over the top of within
				if ( overTop > 0 && overBottom <= 0 ) {
					newOverBottom = position.top + overTop + data.collisionHeight - outerHeight - withinOffset;
					position.top += overTop - newOverBottom;
				// element is initially over bottom of within
				} else if ( overBottom > 0 && overTop <= 0 ) {
					position.top = withinOffset;
				// element is initially over both top and bottom of within
				} else {
					if ( overTop > overBottom ) {
						position.top = withinOffset + outerHeight - data.collisionHeight;
					} else {
						position.top = withinOffset;
					}
				}
			// too far up -> align with top
			} else if ( overTop > 0 ) {
				position.top += overTop;
			// too far down -> align with bottom edge
			} else if ( overBottom > 0 ) {
				position.top -= overBottom;
			// adjust based on position and margin
			} else {
				position.top = max( position.top - collisionPosTop, position.top );
			}
		}
	},
	flip: {
		left: function( position, data ) {
			var within = data.within,
				withinOffset = within.offset.left + within.scrollLeft,
				outerWidth = within.width,
				offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
				collisionPosLeft = position.left - data.collisionPosition.marginLeft,
				overLeft = collisionPosLeft - offsetLeft,
				overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
				myOffset = data.my[ 0 ] === "left" ?
					-data.elemWidth :
					data.my[ 0 ] === "right" ?
						data.elemWidth :
						0,
				atOffset = data.at[ 0 ] === "left" ?
					data.targetWidth :
					data.at[ 0 ] === "right" ?
						-data.targetWidth :
						0,
				offset = -2 * data.offset[ 0 ],
				newOverRight,
				newOverLeft;

			if ( overLeft < 0 ) {
				newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth - outerWidth - withinOffset;
				if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
					position.left += myOffset + atOffset + offset;
				}
			}
			else if ( overRight > 0 ) {
				newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset + atOffset + offset - offsetLeft;
				if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
					position.left += myOffset + atOffset + offset;
				}
			}
		},
		top: function( position, data ) {
			var within = data.within,
				withinOffset = within.offset.top + within.scrollTop,
				outerHeight = within.height,
				offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
				collisionPosTop = position.top - data.collisionPosition.marginTop,
				overTop = collisionPosTop - offsetTop,
				overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
				top = data.my[ 1 ] === "top",
				myOffset = top ?
					-data.elemHeight :
					data.my[ 1 ] === "bottom" ?
						data.elemHeight :
						0,
				atOffset = data.at[ 1 ] === "top" ?
					data.targetHeight :
					data.at[ 1 ] === "bottom" ?
						-data.targetHeight :
						0,
				offset = -2 * data.offset[ 1 ],
				newOverTop,
				newOverBottom;
			if ( overTop < 0 ) {
				newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight - outerHeight - withinOffset;
				if ( ( position.top + myOffset + atOffset + offset) > overTop && ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) ) {
					position.top += myOffset + atOffset + offset;
				}
			}
			else if ( overBottom > 0 ) {
				newOverTop = position.top -  data.collisionPosition.marginTop + myOffset + atOffset + offset - offsetTop;
				if ( ( position.top + myOffset + atOffset + offset) > overBottom && ( newOverTop > 0 || abs( newOverTop ) < overBottom ) ) {
					position.top += myOffset + atOffset + offset;
				}
			}
		}
	},
	flipfit: {
		left: function() {
			$.ui.position.flip.left.apply( this, arguments );
			$.ui.position.fit.left.apply( this, arguments );
		},
		top: function() {
			$.ui.position.flip.top.apply( this, arguments );
			$.ui.position.fit.top.apply( this, arguments );
		}
	}
};

// fraction support test
(function () {
	var testElement, testElementParent, testElementStyle, offsetLeft, i,
		body = document.getElementsByTagName( "body" )[ 0 ],
		div = document.createElement( "div" );

	//Create a "fake body" for testing based on method used in jQuery.support
	testElement = document.createElement( body ? "div" : "body" );
	testElementStyle = {
		visibility: "hidden",
		width: 0,
		height: 0,
		border: 0,
		margin: 0,
		background: "none"
	};
	if ( body ) {
		$.extend( testElementStyle, {
			position: "absolute",
			left: "-1000px",
			top: "-1000px"
		});
	}
	for ( i in testElementStyle ) {
		testElement.style[ i ] = testElementStyle[ i ];
	}
	testElement.appendChild( div );
	testElementParent = body || document.documentElement;
	testElementParent.insertBefore( testElement, testElementParent.firstChild );

	div.style.cssText = "position: absolute; left: 10.7432222px;";

	offsetLeft = $( div ).offset().left;
	$.support.offsetFractions = offsetLeft > 10 && offsetLeft < 11;

	testElement.innerHTML = "";
	testElementParent.removeChild( testElement );
})();

}( jQuery ) );

// file: 000-1-300-jquery.ui.progressbar.js
/*!
 * jQuery UI Progressbar 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/progressbar/
 *
 * Depends:
 *   jquery.ui.core.js
 *   jquery.ui.widget.js
 */
(function( $, undefined ) {

$.widget( "ui.progressbar", {
	version: "1.10.0",
	options: {
		max: 100,
		value: 0,

		change: null,
		complete: null
	},

	min: 0,

	_create: function() {
		// Constrain initial value
		this.oldValue = this.options.value = this._constrainedValue();

		this.element
			.addClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
			.attr({
				// Only set static values, aria-valuenow and aria-valuemax are
				// set inside _refreshValue()
				role: "progressbar",
				"aria-valuemin": this.min
			});

		this.valueDiv = $( "<div class='ui-progressbar-value ui-widget-header ui-corner-left'></div>" )
			.appendTo( this.element );

		this._refreshValue();
	},

	_destroy: function() {
		this.element
			.removeClass( "ui-progressbar ui-widget ui-widget-content ui-corner-all" )
			.removeAttr( "role" )
			.removeAttr( "aria-valuemin" )
			.removeAttr( "aria-valuemax" )
			.removeAttr( "aria-valuenow" );

		this.valueDiv.remove();
	},

	value: function( newValue ) {
		if ( newValue === undefined ) {
			return this.options.value;
		}

		this.options.value = this._constrainedValue( newValue );
		this._refreshValue();
	},

	_constrainedValue: function( newValue ) {
		if ( newValue === undefined ) {
			newValue = this.options.value;
		}

		this.indeterminate = newValue === false;

		// sanitize value
		if ( typeof newValue !== "number" ) {
			newValue = 0;
		}

		return this.indeterminate ? false :
			Math.min( this.options.max, Math.max( this.min, newValue ) );
	},

	_setOptions: function( options ) {
		// Ensure "value" option is set after other values (like max)
		var value = options.value;
		delete options.value;

		this._super( options );

		this.options.value = this._constrainedValue( value );
		this._refreshValue();
	},

	_setOption: function( key, value ) {
		if ( key === "max" ) {
			// Don't allow a max less than min
			value = Math.max( this.min, value );
		}

		this._super( key, value );
	},

	_percentage: function() {
		return this.indeterminate ? 100 : 100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
	},

	_refreshValue: function() {
		var value = this.options.value,
			percentage = this._percentage();

		this.valueDiv
			.toggle( this.indeterminate || value > this.min )
			.toggleClass( "ui-corner-right", value === this.options.max )
			.width( percentage.toFixed(0) + "%" );

		this.element.toggleClass( "ui-progressbar-indeterminate", this.indeterminate );

		if ( this.indeterminate ) {
			this.element.removeAttr( "aria-valuenow" );
			if ( !this.overlayDiv ) {
				this.overlayDiv = $( "<div class='ui-progressbar-overlay'></div>" ).appendTo( this.valueDiv );
			}
		} else {
			this.element.attr({
				"aria-valuemax": this.options.max,
				"aria-valuenow": value
			});
			if ( this.overlayDiv ) {
				this.overlayDiv.remove();
				this.overlayDiv = null;
			}
		}

		if ( this.oldValue !== value ) {
			this.oldValue = value;
			this._trigger( "change" );
		}
		if ( value === this.options.max ) {
			this._trigger( "complete" );
		}
	}
});

})( jQuery );

// file: 000-1-310-jquery.ui.slider.js
/*!
 * jQuery UI Slider 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/slider/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.mouse.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

// number of pages in a slider
// (how many times can you page up/down to go through the whole range)
var numPages = 5;

$.widget( "ui.slider", $.ui.mouse, {
	version: "1.10.0",
	widgetEventPrefix: "slide",

	options: {
		animate: false,
		distance: 0,
		max: 100,
		min: 0,
		orientation: "horizontal",
		range: false,
		step: 1,
		value: 0,
		values: null,

		// callbacks
		change: null,
		slide: null,
		start: null,
		stop: null
	},

	_create: function() {
		var i, handleCount,
			o = this.options,
			existingHandles = this.element.find( ".ui-slider-handle" ).addClass( "ui-state-default ui-corner-all" ),
			handle = "<a class='ui-slider-handle ui-state-default ui-corner-all' href='#'></a>",
			handles = [];

		this._keySliding = false;
		this._mouseSliding = false;
		this._animateOff = true;
		this._handleIndex = null;
		this._detectOrientation();
		this._mouseInit();

		this.element
			.addClass( "ui-slider" +
				" ui-slider-" + this.orientation +
				" ui-widget" +
				" ui-widget-content" +
				" ui-corner-all");

		this.range = $([]);

		if ( o.range ) {
			if ( o.range === true ) {
				if ( !o.values ) {
					o.values = [ this._valueMin(), this._valueMin() ];
				} else if ( o.values.length && o.values.length !== 2 ) {
					o.values = [ o.values[0], o.values[0] ];
				} else if ( $.isArray( o.values ) ) {
					o.values = o.values.slice(0);
				}
			}

			this.range = $( "<div></div>" )
				.appendTo( this.element )
				.addClass( "ui-slider-range" +
				// note: this isn't the most fittingly semantic framework class for this element,
				// but worked best visually with a variety of themes
				" ui-widget-header" +
				( ( o.range === "min" || o.range === "max" ) ? " ui-slider-range-" + o.range : "" ) );
		}

		handleCount = ( o.values && o.values.length ) || 1;

		for ( i = existingHandles.length; i < handleCount; i++ ) {
			handles.push( handle );
		}

		this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );

		this.handle = this.handles.eq( 0 );

		this.handles.add( this.range ).filter( "a" )
			.click(function( event ) {
				event.preventDefault();
			})
			.mouseenter(function() {
				if ( !o.disabled ) {
					$( this ).addClass( "ui-state-hover" );
				}
			})
			.mouseleave(function() {
				$( this ).removeClass( "ui-state-hover" );
			})
			.focus(function() {
				if ( !o.disabled ) {
					$( ".ui-slider .ui-state-focus" ).removeClass( "ui-state-focus" );
					$( this ).addClass( "ui-state-focus" );
				} else {
					$( this ).blur();
				}
			})
			.blur(function() {
				$( this ).removeClass( "ui-state-focus" );
			});

		this.handles.each(function( i ) {
			$( this ).data( "ui-slider-handle-index", i );
		});

		this._setOption( "disabled", o.disabled );

		this._on( this.handles, this._handleEvents );

		this._refreshValue();

		this._animateOff = false;
	},

	_destroy: function() {
		this.handles.remove();
		this.range.remove();

		this.element
			.removeClass( "ui-slider" +
				" ui-slider-horizontal" +
				" ui-slider-vertical" +
				" ui-widget" +
				" ui-widget-content" +
				" ui-corner-all" );

		this._mouseDestroy();
	},

	_mouseCapture: function( event ) {
		var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
			that = this,
			o = this.options;

		if ( o.disabled ) {
			return false;
		}

		this.elementSize = {
			width: this.element.outerWidth(),
			height: this.element.outerHeight()
		};
		this.elementOffset = this.element.offset();

		position = { x: event.pageX, y: event.pageY };
		normValue = this._normValueFromMouse( position );
		distance = this._valueMax() - this._valueMin() + 1;
		this.handles.each(function( i ) {
			var thisDistance = Math.abs( normValue - that.values(i) );
			if (( distance > thisDistance ) ||
				( distance === thisDistance &&
					(i === that._lastChangedValue || that.values(i) === o.min ))) {
				distance = thisDistance;
				closestHandle = $( this );
				index = i;
			}
		});

		allowed = this._start( event, index );
		if ( allowed === false ) {
			return false;
		}
		this._mouseSliding = true;

		this._handleIndex = index;

		closestHandle
			.addClass( "ui-state-active" )
			.focus();

		offset = closestHandle.offset();
		mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
		this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
			left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
			top: event.pageY - offset.top -
				( closestHandle.height() / 2 ) -
				( parseInt( closestHandle.css("borderTopWidth"), 10 ) || 0 ) -
				( parseInt( closestHandle.css("borderBottomWidth"), 10 ) || 0) +
				( parseInt( closestHandle.css("marginTop"), 10 ) || 0)
		};

		if ( !this.handles.hasClass( "ui-state-hover" ) ) {
			this._slide( event, index, normValue );
		}
		this._animateOff = true;
		return true;
	},

	_mouseStart: function() {
		return true;
	},

	_mouseDrag: function( event ) {
		var position = { x: event.pageX, y: event.pageY },
			normValue = this._normValueFromMouse( position );

		this._slide( event, this._handleIndex, normValue );

		return false;
	},

	_mouseStop: function( event ) {
		this.handles.removeClass( "ui-state-active" );
		this._mouseSliding = false;

		this._stop( event, this._handleIndex );
		this._change( event, this._handleIndex );

		this._handleIndex = null;
		this._clickOffset = null;
		this._animateOff = false;

		return false;
	},

	_detectOrientation: function() {
		this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
	},

	_normValueFromMouse: function( position ) {
		var pixelTotal,
			pixelMouse,
			percentMouse,
			valueTotal,
			valueMouse;

		if ( this.orientation === "horizontal" ) {
			pixelTotal = this.elementSize.width;
			pixelMouse = position.x - this.elementOffset.left - ( this._clickOffset ? this._clickOffset.left : 0 );
		} else {
			pixelTotal = this.elementSize.height;
			pixelMouse = position.y - this.elementOffset.top - ( this._clickOffset ? this._clickOffset.top : 0 );
		}

		percentMouse = ( pixelMouse / pixelTotal );
		if ( percentMouse > 1 ) {
			percentMouse = 1;
		}
		if ( percentMouse < 0 ) {
			percentMouse = 0;
		}
		if ( this.orientation === "vertical" ) {
			percentMouse = 1 - percentMouse;
		}

		valueTotal = this._valueMax() - this._valueMin();
		valueMouse = this._valueMin() + percentMouse * valueTotal;

		return this._trimAlignValue( valueMouse );
	},

	_start: function( event, index ) {
		var uiHash = {
			handle: this.handles[ index ],
			value: this.value()
		};
		if ( this.options.values && this.options.values.length ) {
			uiHash.value = this.values( index );
			uiHash.values = this.values();
		}
		return this._trigger( "start", event, uiHash );
	},

	_slide: function( event, index, newVal ) {
		var otherVal,
			newValues,
			allowed;

		if ( this.options.values && this.options.values.length ) {
			otherVal = this.values( index ? 0 : 1 );

			if ( ( this.options.values.length === 2 && this.options.range === true ) &&
					( ( index === 0 && newVal > otherVal) || ( index === 1 && newVal < otherVal ) )
				) {
				newVal = otherVal;
			}

			if ( newVal !== this.values( index ) ) {
				newValues = this.values();
				newValues[ index ] = newVal;
				// A slide can be canceled by returning false from the slide callback
				allowed = this._trigger( "slide", event, {
					handle: this.handles[ index ],
					value: newVal,
					values: newValues
				} );
				otherVal = this.values( index ? 0 : 1 );
				if ( allowed !== false ) {
					this.values( index, newVal, true );
				}
			}
		} else {
			if ( newVal !== this.value() ) {
				// A slide can be canceled by returning false from the slide callback
				allowed = this._trigger( "slide", event, {
					handle: this.handles[ index ],
					value: newVal
				} );
				if ( allowed !== false ) {
					this.value( newVal );
				}
			}
		}
	},

	_stop: function( event, index ) {
		var uiHash = {
			handle: this.handles[ index ],
			value: this.value()
		};
		if ( this.options.values && this.options.values.length ) {
			uiHash.value = this.values( index );
			uiHash.values = this.values();
		}

		this._trigger( "stop", event, uiHash );
	},

	_change: function( event, index ) {
		if ( !this._keySliding && !this._mouseSliding ) {
			var uiHash = {
				handle: this.handles[ index ],
				value: this.value()
			};
			if ( this.options.values && this.options.values.length ) {
				uiHash.value = this.values( index );
				uiHash.values = this.values();
			}

			//store the last changed value index for reference when handles overlap
			this._lastChangedValue = index;

			this._trigger( "change", event, uiHash );
		}
	},

	value: function( newValue ) {
		if ( arguments.length ) {
			this.options.value = this._trimAlignValue( newValue );
			this._refreshValue();
			this._change( null, 0 );
			return;
		}

		return this._value();
	},

	values: function( index, newValue ) {
		var vals,
			newValues,
			i;

		if ( arguments.length > 1 ) {
			this.options.values[ index ] = this._trimAlignValue( newValue );
			this._refreshValue();
			this._change( null, index );
			return;
		}

		if ( arguments.length ) {
			if ( $.isArray( arguments[ 0 ] ) ) {
				vals = this.options.values;
				newValues = arguments[ 0 ];
				for ( i = 0; i < vals.length; i += 1 ) {
					vals[ i ] = this._trimAlignValue( newValues[ i ] );
					this._change( null, i );
				}
				this._refreshValue();
			} else {
				if ( this.options.values && this.options.values.length ) {
					return this._values( index );
				} else {
					return this.value();
				}
			}
		} else {
			return this._values();
		}
	},

	_setOption: function( key, value ) {
		var i,
			valsLength = 0;

		if ( $.isArray( this.options.values ) ) {
			valsLength = this.options.values.length;
		}

		$.Widget.prototype._setOption.apply( this, arguments );

		switch ( key ) {
			case "disabled":
				if ( value ) {
					this.handles.filter( ".ui-state-focus" ).blur();
					this.handles.removeClass( "ui-state-hover" );
					this.handles.prop( "disabled", true );
				} else {
					this.handles.prop( "disabled", false );
				}
				break;
			case "orientation":
				this._detectOrientation();
				this.element
					.removeClass( "ui-slider-horizontal ui-slider-vertical" )
					.addClass( "ui-slider-" + this.orientation );
				this._refreshValue();
				break;
			case "value":
				this._animateOff = true;
				this._refreshValue();
				this._change( null, 0 );
				this._animateOff = false;
				break;
			case "values":
				this._animateOff = true;
				this._refreshValue();
				for ( i = 0; i < valsLength; i += 1 ) {
					this._change( null, i );
				}
				this._animateOff = false;
				break;
			case "min":
			case "max":
				this._animateOff = true;
				this._refreshValue();
				this._animateOff = false;
				break;
		}
	},

	//internal value getter
	// _value() returns value trimmed by min and max, aligned by step
	_value: function() {
		var val = this.options.value;
		val = this._trimAlignValue( val );

		return val;
	},

	//internal values getter
	// _values() returns array of values trimmed by min and max, aligned by step
	// _values( index ) returns single value trimmed by min and max, aligned by step
	_values: function( index ) {
		var val,
			vals,
			i;

		if ( arguments.length ) {
			val = this.options.values[ index ];
			val = this._trimAlignValue( val );

			return val;
		} else {
			// .slice() creates a copy of the array
			// this copy gets trimmed by min and max and then returned
			vals = this.options.values.slice();
			for ( i = 0; i < vals.length; i+= 1) {
				vals[ i ] = this._trimAlignValue( vals[ i ] );
			}

			return vals;
		}
	},

	// returns the step-aligned value that val is closest to, between (inclusive) min and max
	_trimAlignValue: function( val ) {
		if ( val <= this._valueMin() ) {
			return this._valueMin();
		}
		if ( val >= this._valueMax() ) {
			return this._valueMax();
		}
		var step = ( this.options.step > 0 ) ? this.options.step : 1,
			valModStep = (val - this._valueMin()) % step,
			alignValue = val - valModStep;

		if ( Math.abs(valModStep) * 2 >= step ) {
			alignValue += ( valModStep > 0 ) ? step : ( -step );
		}

		// Since JavaScript has problems with large floats, round
		// the final value to 5 digits after the decimal point (see #4124)
		return parseFloat( alignValue.toFixed(5) );
	},

	_valueMin: function() {
		return this.options.min;
	},

	_valueMax: function() {
		return this.options.max;
	},

	_refreshValue: function() {
		var lastValPercent, valPercent, value, valueMin, valueMax,
			oRange = this.options.range,
			o = this.options,
			that = this,
			animate = ( !this._animateOff ) ? o.animate : false,
			_set = {};

		if ( this.options.values && this.options.values.length ) {
			this.handles.each(function( i ) {
				valPercent = ( that.values(i) - that._valueMin() ) / ( that._valueMax() - that._valueMin() ) * 100;
				_set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
				$( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
				if ( that.options.range === true ) {
					if ( that.orientation === "horizontal" ) {
						if ( i === 0 ) {
							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { left: valPercent + "%" }, o.animate );
						}
						if ( i === 1 ) {
							that.range[ animate ? "animate" : "css" ]( { width: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
						}
					} else {
						if ( i === 0 ) {
							that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { bottom: ( valPercent ) + "%" }, o.animate );
						}
						if ( i === 1 ) {
							that.range[ animate ? "animate" : "css" ]( { height: ( valPercent - lastValPercent ) + "%" }, { queue: false, duration: o.animate } );
						}
					}
				}
				lastValPercent = valPercent;
			});
		} else {
			value = this.value();
			valueMin = this._valueMin();
			valueMax = this._valueMax();
			valPercent = ( valueMax !== valueMin ) ?
					( value - valueMin ) / ( valueMax - valueMin ) * 100 :
					0;
			_set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
			this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );

			if ( oRange === "min" && this.orientation === "horizontal" ) {
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { width: valPercent + "%" }, o.animate );
			}
			if ( oRange === "max" && this.orientation === "horizontal" ) {
				this.range[ animate ? "animate" : "css" ]( { width: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
			}
			if ( oRange === "min" && this.orientation === "vertical" ) {
				this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( { height: valPercent + "%" }, o.animate );
			}
			if ( oRange === "max" && this.orientation === "vertical" ) {
				this.range[ animate ? "animate" : "css" ]( { height: ( 100 - valPercent ) + "%" }, { queue: false, duration: o.animate } );
			}
		}
	},

	_handleEvents: {
		keydown: function( event ) {
			/*jshint maxcomplexity:25*/
			var allowed, curVal, newVal, step,
				index = $( event.target ).data( "ui-slider-handle-index" );

			switch ( event.keyCode ) {
				case $.ui.keyCode.HOME:
				case $.ui.keyCode.END:
				case $.ui.keyCode.PAGE_UP:
				case $.ui.keyCode.PAGE_DOWN:
				case $.ui.keyCode.UP:
				case $.ui.keyCode.RIGHT:
				case $.ui.keyCode.DOWN:
				case $.ui.keyCode.LEFT:
					event.preventDefault();
					if ( !this._keySliding ) {
						this._keySliding = true;
						$( event.target ).addClass( "ui-state-active" );
						allowed = this._start( event, index );
						if ( allowed === false ) {
							return;
						}
					}
					break;
			}

			step = this.options.step;
			if ( this.options.values && this.options.values.length ) {
				curVal = newVal = this.values( index );
			} else {
				curVal = newVal = this.value();
			}

			switch ( event.keyCode ) {
				case $.ui.keyCode.HOME:
					newVal = this._valueMin();
					break;
				case $.ui.keyCode.END:
					newVal = this._valueMax();
					break;
				case $.ui.keyCode.PAGE_UP:
					newVal = this._trimAlignValue( curVal + ( (this._valueMax() - this._valueMin()) / numPages ) );
					break;
				case $.ui.keyCode.PAGE_DOWN:
					newVal = this._trimAlignValue( curVal - ( (this._valueMax() - this._valueMin()) / numPages ) );
					break;
				case $.ui.keyCode.UP:
				case $.ui.keyCode.RIGHT:
					if ( curVal === this._valueMax() ) {
						return;
					}
					newVal = this._trimAlignValue( curVal + step );
					break;
				case $.ui.keyCode.DOWN:
				case $.ui.keyCode.LEFT:
					if ( curVal === this._valueMin() ) {
						return;
					}
					newVal = this._trimAlignValue( curVal - step );
					break;
			}

			this._slide( event, index, newVal );
		},
		keyup: function( event ) {
			var index = $( event.target ).data( "ui-slider-handle-index" );

			if ( this._keySliding ) {
				this._keySliding = false;
				this._stop( event, index );
				this._change( event, index );
				$( event.target ).removeClass( "ui-state-active" );
			}
		}
	}

});

}(jQuery));

// file: 000-1-320-jquery.ui.spinner.js
/*!
 * jQuery UI Spinner 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/spinner/
 *
 * Depends:
 *  jquery.ui.core.js
 *  jquery.ui.widget.js
 *  jquery.ui.button.js
 */
(function( $ ) {

function modifier( fn ) {
	return function() {
		var previous = this.element.val();
		fn.apply( this, arguments );
		this._refresh();
		if ( previous !== this.element.val() ) {
			this._trigger( "change" );
		}
	};
}

$.widget( "ui.spinner", {
	version: "1.10.0",
	defaultElement: "<input>",
	widgetEventPrefix: "spin",
	options: {
		culture: null,
		icons: {
			down: "ui-icon-triangle-1-s",
			up: "ui-icon-triangle-1-n"
		},
		incremental: true,
		max: null,
		min: null,
		numberFormat: null,
		page: 10,
		step: 1,

		change: null,
		spin: null,
		start: null,
		stop: null
	},

	_create: function() {
		// handle string values that need to be parsed
		this._setOption( "max", this.options.max );
		this._setOption( "min", this.options.min );
		this._setOption( "step", this.options.step );

		// format the value, but don't constrain
		this._value( this.element.val(), true );

		this._draw();
		this._on( this._events );
		this._refresh();

		// turning off autocomplete prevents the browser from remembering the
		// value when navigating through history, so we re-enable autocomplete
		// if the page is unloaded before the widget is destroyed. #7790
		this._on( this.window, {
			beforeunload: function() {
				this.element.removeAttr( "autocomplete" );
			}
		});
	},

	_getCreateOptions: function() {
		var options = {},
			element = this.element;

		$.each( [ "min", "max", "step" ], function( i, option ) {
			var value = element.attr( option );
			if ( value !== undefined && value.length ) {
				options[ option ] = value;
			}
		});

		return options;
	},

	_events: {
		keydown: function( event ) {
			if ( this._start( event ) && this._keydown( event ) ) {
				event.preventDefault();
			}
		},
		keyup: "_stop",
		focus: function() {
			this.previous = this.element.val();
		},
		blur: function( event ) {
			if ( this.cancelBlur ) {
				delete this.cancelBlur;
				return;
			}

			this._refresh();
			if ( this.previous !== this.element.val() ) {
				this._trigger( "change", event );
			}
		},
		mousewheel: function( event, delta ) {
			if ( !delta ) {
				return;
			}
			if ( !this.spinning && !this._start( event ) ) {
				return false;
			}

			this._spin( (delta > 0 ? 1 : -1) * this.options.step, event );
			clearTimeout( this.mousewheelTimer );
			this.mousewheelTimer = this._delay(function() {
				if ( this.spinning ) {
					this._stop( event );
				}
			}, 100 );
			event.preventDefault();
		},
		"mousedown .ui-spinner-button": function( event ) {
			var previous;

			// We never want the buttons to have focus; whenever the user is
			// interacting with the spinner, the focus should be on the input.
			// If the input is focused then this.previous is properly set from
			// when the input first received focus. If the input is not focused
			// then we need to set this.previous based on the value before spinning.
			previous = this.element[0] === this.document[0].activeElement ?
				this.previous : this.element.val();
			function checkFocus() {
				var isActive = this.element[0] === this.document[0].activeElement;
				if ( !isActive ) {
					this.element.focus();
					this.previous = previous;
					// support: IE
					// IE sets focus asynchronously, so we need to check if focus
					// moved off of the input because the user clicked on the button.
					this._delay(function() {
						this.previous = previous;
					});
				}
			}

			// ensure focus is on (or stays on) the text field
			event.preventDefault();
			checkFocus.call( this );

			// support: IE
			// IE doesn't prevent moving focus even with event.preventDefault()
			// so we set a flag to know when we should ignore the blur event
			// and check (again) if focus moved off of the input.
			this.cancelBlur = true;
			this._delay(function() {
				delete this.cancelBlur;
				checkFocus.call( this );
			});

			if ( this._start( event ) === false ) {
				return;
			}

			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
		},
		"mouseup .ui-spinner-button": "_stop",
		"mouseenter .ui-spinner-button": function( event ) {
			// button will add ui-state-active if mouse was down while mouseleave and kept down
			if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
				return;
			}

			if ( this._start( event ) === false ) {
				return false;
			}
			this._repeat( null, $( event.currentTarget ).hasClass( "ui-spinner-up" ) ? 1 : -1, event );
		},
		// TODO: do we really want to consider this a stop?
		// shouldn't we just stop the repeater and wait until mouseup before
		// we trigger the stop event?
		"mouseleave .ui-spinner-button": "_stop"
	},

	_draw: function() {
		var uiSpinner = this.uiSpinner = this.element
			.addClass( "ui-spinner-input" )
			.attr( "autocomplete", "off" )
			.wrap( this._uiSpinnerHtml() )
			.parent()
				// add buttons
				.append( this._buttonHtml() );

		this.element.attr( "role", "spinbutton" );

		// button bindings
		this.buttons = uiSpinner.find( ".ui-spinner-button" )
			.attr( "tabIndex", -1 )
			.button()
			.removeClass( "ui-corner-all" );

		// IE 6 doesn't understand height: 50% for the buttons
		// unless the wrapper has an explicit height
		if ( this.buttons.height() > Math.ceil( uiSpinner.height() * 0.5 ) &&
				uiSpinner.height() > 0 ) {
			uiSpinner.height( uiSpinner.height() );
		}

		// disable spinner if element was already disabled
		if ( this.options.disabled ) {
			this.disable();
		}
	},

	_keydown: function( event ) {
		var options = this.options,
			keyCode = $.ui.keyCode;

		switch ( event.keyCode ) {
		case keyCode.UP:
			this._repeat( null, 1, event );
			return true;
		case keyCode.DOWN:
			this._repeat( null, -1, event );
			return true;
		case keyCode.PAGE_UP:
			this._repeat( null, options.page, event );
			return true;
		case keyCode.PAGE_DOWN:
			this._repeat( null, -options.page, event );
			return true;
		}

		return false;
	},

	_uiSpinnerHtml: function() {
		return "<span class='ui-spinner ui-widget ui-widget-content ui-corner-all'></span>";
	},

	_buttonHtml: function() {
		return "" +
			"<a class='ui-spinner-button ui-spinner-up ui-corner-tr'>" +
				"<span class='ui-icon " + this.options.icons.up + "'>&#9650;</span>" +
			"</a>" +
			"<a class='ui-spinner-button ui-spinner-down ui-corner-br'>" +
				"<span class='ui-icon " + this.options.icons.down + "'>&#9660;</span>" +
			"</a>";
	},

	_start: function( event ) {
		if ( !this.spinning && this._trigger( "start", event ) === false ) {
			return false;
		}

		if ( !this.counter ) {
			this.counter = 1;
		}
		this.spinning = true;
		return true;
	},

	_repeat: function( i, steps, event ) {
		i = i || 500;

		clearTimeout( this.timer );
		this.timer = this._delay(function() {
			this._repeat( 40, steps, event );
		}, i );

		this._spin( steps * this.options.step, event );
	},

	_spin: function( step, event ) {
		var value = this.value() || 0;

		if ( !this.counter ) {
			this.counter = 1;
		}

		value = this._adjustValue( value + step * this._increment( this.counter ) );

		if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false) {
			this._value( value );
			this.counter++;
		}
	},

	_increment: function( i ) {
		var incremental = this.options.incremental;

		if ( incremental ) {
			return $.isFunction( incremental ) ?
				incremental( i ) :
				Math.floor( i*i*i/50000 - i*i/500 + 17*i/200 + 1 );
		}

		return 1;
	},

	_precision: function() {
		var precision = this._precisionOf( this.options.step );
		if ( this.options.min !== null ) {
			precision = Math.max( precision, this._precisionOf( this.options.min ) );
		}
		return precision;
	},

	_precisionOf: function( num ) {
		var str = num.toString(),
			decimal = str.indexOf( "." );
		return decimal === -1 ? 0 : str.length - decimal - 1;
	},

	_adjustValue: function( value ) {
		var base, aboveMin,
			options = this.options;

		// make sure we're at a valid step
		// - find out where we are relative to the base (min or 0)
		base = options.min !== null ? options.min : 0;
		aboveMin = value - base;
		// - round to the nearest step
		aboveMin = Math.round(aboveMin / options.step) * options.step;
		// - rounding is based on 0, so adjust back to our base
		value = base + aboveMin;

		// fix precision from bad JS floating point math
		value = parseFloat( value.toFixed( this._precision() ) );

		// clamp the value
		if ( options.max !== null && value > options.max) {
			return options.max;
		}
		if ( options.min !== null && value < options.min ) {
			return options.min;
		}

		return value;
	},

	_stop: function( event ) {
		if ( !this.spinning ) {
			return;
		}

		clearTimeout( this.timer );
		clearTimeout( this.mousewheelTimer );
		this.counter = 0;
		this.spinning = false;
		this._trigger( "stop", event );
	},

	_setOption: function( key, value ) {
		if ( key === "culture" || key === "numberFormat" ) {
			var prevValue = this._parse( this.element.val() );
			this.options[ key ] = value;
			this.element.val( this._format( prevValue ) );
			return;
		}

		if ( key === "max" || key === "min" || key === "step" ) {
			if ( typeof value === "string" ) {
				value = this._parse( value );
			}
		}
		if ( key === "icons" ) {
			this.buttons.first().find( ".ui-icon" )
				.removeClass( this.options.icons.up )
				.addClass( value.up );
			this.buttons.last().find( ".ui-icon" )
				.removeClass( this.options.icons.down )
				.addClass( value.down );
		}

		this._super( key, value );

		if ( key === "disabled" ) {
			if ( value ) {
				this.element.prop( "disabled", true );
				this.buttons.button( "disable" );
			} else {
				this.element.prop( "disabled", false );
				this.buttons.button( "enable" );
			}
		}
	},

	_setOptions: modifier(function( options ) {
		this._super( options );
		this._value( this.element.val() );
	}),

	_parse: function( val ) {
		if ( typeof val === "string" && val !== "" ) {
			val = window.Globalize && this.options.numberFormat ?
				Globalize.parseFloat( val, 10, this.options.culture ) : +val;
		}
		return val === "" || isNaN( val ) ? null : val;
	},

	_format: function( value ) {
		if ( value === "" ) {
			return "";
		}
		return window.Globalize && this.options.numberFormat ?
			Globalize.format( value, this.options.numberFormat, this.options.culture ) :
			value;
	},

	_refresh: function() {
		this.element.attr({
			"aria-valuemin": this.options.min,
			"aria-valuemax": this.options.max,
			// TODO: what should we do with values that can't be parsed?
			"aria-valuenow": this._parse( this.element.val() )
		});
	},

	// update the value without triggering change
	_value: function( value, allowAny ) {
		var parsed;
		if ( value !== "" ) {
			parsed = this._parse( value );
			if ( parsed !== null ) {
				if ( !allowAny ) {
					parsed = this._adjustValue( parsed );
				}
				value = this._format( parsed );
			}
		}
		this.element.val( value );
		this._refresh();
	},

	_destroy: function() {
		this.element
			.removeClass( "ui-spinner-input" )
			.prop( "disabled", false )
			.removeAttr( "autocomplete" )
			.removeAttr( "role" )
			.removeAttr( "aria-valuemin" )
			.removeAttr( "aria-valuemax" )
			.removeAttr( "aria-valuenow" );
		this.uiSpinner.replaceWith( this.element );
	},

	stepUp: modifier(function( steps ) {
		this._stepUp( steps );
	}),
	_stepUp: function( steps ) {
		if ( this._start() ) {
			this._spin( (steps || 1) * this.options.step );
			this._stop();
		}
	},

	stepDown: modifier(function( steps ) {
		this._stepDown( steps );
	}),
	_stepDown: function( steps ) {
		if ( this._start() ) {
			this._spin( (steps || 1) * -this.options.step );
			this._stop();
		}
	},

	pageUp: modifier(function( pages ) {
		this._stepUp( (pages || 1) * this.options.page );
	}),

	pageDown: modifier(function( pages ) {
		this._stepDown( (pages || 1) * this.options.page );
	}),

	value: function( newVal ) {
		if ( !arguments.length ) {
			return this._parse( this.element.val() );
		}
		modifier( this._value ).call( this, newVal );
	},

	widget: function() {
		return this.uiSpinner;
	}
});

}( jQuery ) );

// file: 000-1-330-jquery.ui.tabs.js
/*!
 * jQuery UI Tabs 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/tabs/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function( $, undefined ) {

var tabId = 0,
	rhash = /#.*$/;

function getNextTabId() {
	return ++tabId;
}

function isLocal( anchor ) {
	return anchor.hash.length > 1 &&
		decodeURIComponent( anchor.href.replace( rhash, "" ) ) ===
			decodeURIComponent( location.href.replace( rhash, "" ) );
}

$.widget( "ui.tabs", {
	version: "1.10.0",
	delay: 300,
	options: {
		active: null,
		collapsible: false,
		event: "click",
		heightStyle: "content",
		hide: null,
		show: null,

		// callbacks
		activate: null,
		beforeActivate: null,
		beforeLoad: null,
		load: null
	},

	_create: function() {
		var that = this,
			options = this.options;

		this.running = false;

		this.element
			.addClass( "ui-tabs ui-widget ui-widget-content ui-corner-all" )
			.toggleClass( "ui-tabs-collapsible", options.collapsible )
			// Prevent users from focusing disabled tabs via click
			.delegate( ".ui-tabs-nav > li", "mousedown" + this.eventNamespace, function( event ) {
				if ( $( this ).is( ".ui-state-disabled" ) ) {
					event.preventDefault();
				}
			})
			// support: IE <9
			// Preventing the default action in mousedown doesn't prevent IE
			// from focusing the element, so if the anchor gets focused, blur.
			// We don't have to worry about focusing the previously focused
			// element since clicking on a non-focusable element should focus
			// the body anyway.
			.delegate( ".ui-tabs-anchor", "focus" + this.eventNamespace, function() {
				if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
					this.blur();
				}
			});

		this._processTabs();
		options.active = this._initialActive();

		// Take disabling tabs via class attribute from HTML
		// into account and update option properly.
		if ( $.isArray( options.disabled ) ) {
			options.disabled = $.unique( options.disabled.concat(
				$.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
					return that.tabs.index( li );
				})
			) ).sort();
		}

		// check for length avoids error when initializing empty list
		if ( this.options.active !== false && this.anchors.length ) {
			this.active = this._findActive( options.active );
		} else {
			this.active = $();
		}

		this._refresh();

		if ( this.active.length ) {
			this.load( options.active );
		}
	},

	_initialActive: function() {
		var active = this.options.active,
			collapsible = this.options.collapsible,
			locationHash = location.hash.substring( 1 );

		if ( active === null ) {
			// check the fragment identifier in the URL
			if ( locationHash ) {
				this.tabs.each(function( i, tab ) {
					if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
						active = i;
						return false;
					}
				});
			}

			// check for a tab marked active via a class
			if ( active === null ) {
				active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
			}

			// no active tab, set to false
			if ( active === null || active === -1 ) {
				active = this.tabs.length ? 0 : false;
			}
		}

		// handle numbers: negative, out of range
		if ( active !== false ) {
			active = this.tabs.index( this.tabs.eq( active ) );
			if ( active === -1 ) {
				active = collapsible ? false : 0;
			}
		}

		// don't allow collapsible: false and active: false
		if ( !collapsible && active === false && this.anchors.length ) {
			active = 0;
		}

		return active;
	},

	_getCreateEventData: function() {
		return {
			tab: this.active,
			panel: !this.active.length ? $() : this._getPanelForTab( this.active )
		};
	},

	_tabKeydown: function( event ) {
		/*jshint maxcomplexity:15*/
		var focusedTab = $( this.document[0].activeElement ).closest( "li" ),
			selectedIndex = this.tabs.index( focusedTab ),
			goingForward = true;

		if ( this._handlePageNav( event ) ) {
			return;
		}

		switch ( event.keyCode ) {
			case $.ui.keyCode.RIGHT:
			case $.ui.keyCode.DOWN:
				selectedIndex++;
				break;
			case $.ui.keyCode.UP:
			case $.ui.keyCode.LEFT:
				goingForward = false;
				selectedIndex--;
				break;
			case $.ui.keyCode.END:
				selectedIndex = this.anchors.length - 1;
				break;
			case $.ui.keyCode.HOME:
				selectedIndex = 0;
				break;
			case $.ui.keyCode.SPACE:
				// Activate only, no collapsing
				event.preventDefault();
				clearTimeout( this.activating );
				this._activate( selectedIndex );
				return;
			case $.ui.keyCode.ENTER:
				// Toggle (cancel delayed activation, allow collapsing)
				event.preventDefault();
				clearTimeout( this.activating );
				// Determine if we should collapse or activate
				this._activate( selectedIndex === this.options.active ? false : selectedIndex );
				return;
			default:
				return;
		}

		// Focus the appropriate tab, based on which key was pressed
		event.preventDefault();
		clearTimeout( this.activating );
		selectedIndex = this._focusNextTab( selectedIndex, goingForward );

		// Navigating with control key will prevent automatic activation
		if ( !event.ctrlKey ) {
			// Update aria-selected immediately so that AT think the tab is already selected.
			// Otherwise AT may confuse the user by stating that they need to activate the tab,
			// but the tab will already be activated by the time the announcement finishes.
			focusedTab.attr( "aria-selected", "false" );
			this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );

			this.activating = this._delay(function() {
				this.option( "active", selectedIndex );
			}, this.delay );
		}
	},

	_panelKeydown: function( event ) {
		if ( this._handlePageNav( event ) ) {
			return;
		}

		// Ctrl+up moves focus to the current tab
		if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
			event.preventDefault();
			this.active.focus();
		}
	},

	// Alt+page up/down moves focus to the previous/next tab (and activates)
	_handlePageNav: function( event ) {
		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
			this._activate( this._focusNextTab( this.options.active - 1, false ) );
			return true;
		}
		if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
			this._activate( this._focusNextTab( this.options.active + 1, true ) );
			return true;
		}
	},

	_findNextTab: function( index, goingForward ) {
		var lastTabIndex = this.tabs.length - 1;

		function constrain() {
			if ( index > lastTabIndex ) {
				index = 0;
			}
			if ( index < 0 ) {
				index = lastTabIndex;
			}
			return index;
		}

		while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
			index = goingForward ? index + 1 : index - 1;
		}

		return index;
	},

	_focusNextTab: function( index, goingForward ) {
		index = this._findNextTab( index, goingForward );
		this.tabs.eq( index ).focus();
		return index;
	},

	_setOption: function( key, value ) {
		if ( key === "active" ) {
			// _activate() will handle invalid values and update this.options
			this._activate( value );
			return;
		}

		if ( key === "disabled" ) {
			// don't use the widget factory's disabled handling
			this._setupDisabled( value );
			return;
		}

		this._super( key, value);

		if ( key === "collapsible" ) {
			this.element.toggleClass( "ui-tabs-collapsible", value );
			// Setting collapsible: false while collapsed; open first panel
			if ( !value && this.options.active === false ) {
				this._activate( 0 );
			}
		}

		if ( key === "event" ) {
			this._setupEvents( value );
		}

		if ( key === "heightStyle" ) {
			this._setupHeightStyle( value );
		}
	},

	_tabId: function( tab ) {
		return tab.attr( "aria-controls" ) || "ui-tabs-" + getNextTabId();
	},

	_sanitizeSelector: function( hash ) {
		return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
	},

	refresh: function() {
		var options = this.options,
			lis = this.tablist.children( ":has(a[href])" );

		// get disabled tabs from class attribute from HTML
		// this will get converted to a boolean if needed in _refresh()
		options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
			return lis.index( tab );
		});

		this._processTabs();

		// was collapsed or no tabs
		if ( options.active === false || !this.anchors.length ) {
			options.active = false;
			this.active = $();
		// was active, but active tab is gone
		} else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
			// all remaining tabs are disabled
			if ( this.tabs.length === options.disabled.length ) {
				options.active = false;
				this.active = $();
			// activate previous tab
			} else {
				this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
			}
		// was active, active tab still exists
		} else {
			// make sure active index is correct
			options.active = this.tabs.index( this.active );
		}

		this._refresh();
	},

	_refresh: function() {
		this._setupDisabled( this.options.disabled );
		this._setupEvents( this.options.event );
		this._setupHeightStyle( this.options.heightStyle );

		this.tabs.not( this.active ).attr({
			"aria-selected": "false",
			tabIndex: -1
		});
		this.panels.not( this._getPanelForTab( this.active ) )
			.hide()
			.attr({
				"aria-expanded": "false",
				"aria-hidden": "true"
			});

		// Make sure one tab is in the tab order
		if ( !this.active.length ) {
			this.tabs.eq( 0 ).attr( "tabIndex", 0 );
		} else {
			this.active
				.addClass( "ui-tabs-active ui-state-active" )
				.attr({
					"aria-selected": "true",
					tabIndex: 0
				});
			this._getPanelForTab( this.active )
				.show()
				.attr({
					"aria-expanded": "true",
					"aria-hidden": "false"
				});
		}
	},

	_processTabs: function() {
		var that = this;

		this.tablist = this._getList()
			.addClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
			.attr( "role", "tablist" );

		this.tabs = this.tablist.find( "> li:has(a[href])" )
			.addClass( "ui-state-default ui-corner-top" )
			.attr({
				role: "tab",
				tabIndex: -1
			});

		this.anchors = this.tabs.map(function() {
				return $( "a", this )[ 0 ];
			})
			.addClass( "ui-tabs-anchor" )
			.attr({
				role: "presentation",
				tabIndex: -1
			});

		this.panels = $();

		this.anchors.each(function( i, anchor ) {
			var selector, panel, panelId,
				anchorId = $( anchor ).uniqueId().attr( "id" ),
				tab = $( anchor ).closest( "li" ),
				originalAriaControls = tab.attr( "aria-controls" );

			// inline tab
			if ( isLocal( anchor ) ) {
				selector = anchor.hash;
				panel = that.element.find( that._sanitizeSelector( selector ) );
			// remote tab
			} else {
				panelId = that._tabId( tab );
				selector = "#" + panelId;
				panel = that.element.find( selector );
				if ( !panel.length ) {
					panel = that._createPanel( panelId );
					panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
				}
				panel.attr( "aria-live", "polite" );
			}

			if ( panel.length) {
				that.panels = that.panels.add( panel );
			}
			if ( originalAriaControls ) {
				tab.data( "ui-tabs-aria-controls", originalAriaControls );
			}
			tab.attr({
				"aria-controls": selector.substring( 1 ),
				"aria-labelledby": anchorId
			});
			panel.attr( "aria-labelledby", anchorId );
		});

		this.panels
			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
			.attr( "role", "tabpanel" );
	},

	// allow overriding how to find the list for rare usage scenarios (#7715)
	_getList: function() {
		return this.element.find( "ol,ul" ).eq( 0 );
	},

	_createPanel: function( id ) {
		return $( "<div>" )
			.attr( "id", id )
			.addClass( "ui-tabs-panel ui-widget-content ui-corner-bottom" )
			.data( "ui-tabs-destroy", true );
	},

	_setupDisabled: function( disabled ) {
		if ( $.isArray( disabled ) ) {
			if ( !disabled.length ) {
				disabled = false;
			} else if ( disabled.length === this.anchors.length ) {
				disabled = true;
			}
		}

		// disable tabs
		for ( var i = 0, li; ( li = this.tabs[ i ] ); i++ ) {
			if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
				$( li )
					.addClass( "ui-state-disabled" )
					.attr( "aria-disabled", "true" );
			} else {
				$( li )
					.removeClass( "ui-state-disabled" )
					.removeAttr( "aria-disabled" );
			}
		}

		this.options.disabled = disabled;
	},

	_setupEvents: function( event ) {
		var events = {
			click: function( event ) {
				event.preventDefault();
			}
		};
		if ( event ) {
			$.each( event.split(" "), function( index, eventName ) {
				events[ eventName ] = "_eventHandler";
			});
		}

		this._off( this.anchors.add( this.tabs ).add( this.panels ) );
		this._on( this.anchors, events );
		this._on( this.tabs, { keydown: "_tabKeydown" } );
		this._on( this.panels, { keydown: "_panelKeydown" } );

		this._focusable( this.tabs );
		this._hoverable( this.tabs );
	},

	_setupHeightStyle: function( heightStyle ) {
		var maxHeight,
			parent = this.element.parent();

		if ( heightStyle === "fill" ) {
			maxHeight = parent.height();
			maxHeight -= this.element.outerHeight() - this.element.height();

			this.element.siblings( ":visible" ).each(function() {
				var elem = $( this ),
					position = elem.css( "position" );

				if ( position === "absolute" || position === "fixed" ) {
					return;
				}
				maxHeight -= elem.outerHeight( true );
			});

			this.element.children().not( this.panels ).each(function() {
				maxHeight -= $( this ).outerHeight( true );
			});

			this.panels.each(function() {
				$( this ).height( Math.max( 0, maxHeight -
					$( this ).innerHeight() + $( this ).height() ) );
			})
			.css( "overflow", "auto" );
		} else if ( heightStyle === "auto" ) {
			maxHeight = 0;
			this.panels.each(function() {
				maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
			}).height( maxHeight );
		}
	},

	_eventHandler: function( event ) {
		var options = this.options,
			active = this.active,
			anchor = $( event.currentTarget ),
			tab = anchor.closest( "li" ),
			clickedIsActive = tab[ 0 ] === active[ 0 ],
			collapsing = clickedIsActive && options.collapsible,
			toShow = collapsing ? $() : this._getPanelForTab( tab ),
			toHide = !active.length ? $() : this._getPanelForTab( active ),
			eventData = {
				oldTab: active,
				oldPanel: toHide,
				newTab: collapsing ? $() : tab,
				newPanel: toShow
			};

		event.preventDefault();

		if ( tab.hasClass( "ui-state-disabled" ) ||
				// tab is already loading
				tab.hasClass( "ui-tabs-loading" ) ||
				// can't switch durning an animation
				this.running ||
				// click on active header, but not collapsible
				( clickedIsActive && !options.collapsible ) ||
				// allow canceling activation
				( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
			return;
		}

		options.active = collapsing ? false : this.tabs.index( tab );

		this.active = clickedIsActive ? $() : tab;
		if ( this.xhr ) {
			this.xhr.abort();
		}

		if ( !toHide.length && !toShow.length ) {
			$.error( "jQuery UI Tabs: Mismatching fragment identifier." );
		}

		if ( toShow.length ) {
			this.load( this.tabs.index( tab ), event );
		}
		this._toggle( event, eventData );
	},

	// handles show/hide for selecting tabs
	_toggle: function( event, eventData ) {
		var that = this,
			toShow = eventData.newPanel,
			toHide = eventData.oldPanel;

		this.running = true;

		function complete() {
			that.running = false;
			that._trigger( "activate", event, eventData );
		}

		function show() {
			eventData.newTab.closest( "li" ).addClass( "ui-tabs-active ui-state-active" );

			if ( toShow.length && that.options.show ) {
				that._show( toShow, that.options.show, complete );
			} else {
				toShow.show();
				complete();
			}
		}

		// start out by hiding, then showing, then completing
		if ( toHide.length && this.options.hide ) {
			this._hide( toHide, this.options.hide, function() {
				eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
				show();
			});
		} else {
			eventData.oldTab.closest( "li" ).removeClass( "ui-tabs-active ui-state-active" );
			toHide.hide();
			show();
		}

		toHide.attr({
			"aria-expanded": "false",
			"aria-hidden": "true"
		});
		eventData.oldTab.attr( "aria-selected", "false" );
		// If we're switching tabs, remove the old tab from the tab order.
		// If we're opening from collapsed state, remove the previous tab from the tab order.
		// If we're collapsing, then keep the collapsing tab in the tab order.
		if ( toShow.length && toHide.length ) {
			eventData.oldTab.attr( "tabIndex", -1 );
		} else if ( toShow.length ) {
			this.tabs.filter(function() {
				return $( this ).attr( "tabIndex" ) === 0;
			})
			.attr( "tabIndex", -1 );
		}

		toShow.attr({
			"aria-expanded": "true",
			"aria-hidden": "false"
		});
		eventData.newTab.attr({
			"aria-selected": "true",
			tabIndex: 0
		});
	},

	_activate: function( index ) {
		var anchor,
			active = this._findActive( index );

		// trying to activate the already active panel
		if ( active[ 0 ] === this.active[ 0 ] ) {
			return;
		}

		// trying to collapse, simulate a click on the current active header
		if ( !active.length ) {
			active = this.active;
		}

		anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
		this._eventHandler({
			target: anchor,
			currentTarget: anchor,
			preventDefault: $.noop
		});
	},

	_findActive: function( index ) {
		return index === false ? $() : this.tabs.eq( index );
	},

	_getIndex: function( index ) {
		// meta-function to give users option to provide a href string instead of a numerical index.
		if ( typeof index === "string" ) {
			index = this.anchors.index( this.anchors.filter( "[href$='" + index + "']" ) );
		}

		return index;
	},

	_destroy: function() {
		if ( this.xhr ) {
			this.xhr.abort();
		}

		this.element.removeClass( "ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible" );

		this.tablist
			.removeClass( "ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all" )
			.removeAttr( "role" );

		this.anchors
			.removeClass( "ui-tabs-anchor" )
			.removeAttr( "role" )
			.removeAttr( "tabIndex" )
			.removeUniqueId();

		this.tabs.add( this.panels ).each(function() {
			if ( $.data( this, "ui-tabs-destroy" ) ) {
				$( this ).remove();
			} else {
				$( this )
					.removeClass( "ui-state-default ui-state-active ui-state-disabled " +
						"ui-corner-top ui-corner-bottom ui-widget-content ui-tabs-active ui-tabs-panel" )
					.removeAttr( "tabIndex" )
					.removeAttr( "aria-live" )
					.removeAttr( "aria-busy" )
					.removeAttr( "aria-selected" )
					.removeAttr( "aria-labelledby" )
					.removeAttr( "aria-hidden" )
					.removeAttr( "aria-expanded" )
					.removeAttr( "role" );
			}
		});

		this.tabs.each(function() {
			var li = $( this ),
				prev = li.data( "ui-tabs-aria-controls" );
			if ( prev ) {
				li
					.attr( "aria-controls", prev )
					.removeData( "ui-tabs-aria-controls" );
			} else {
				li.removeAttr( "aria-controls" );
			}
		});

		this.panels.show();

		if ( this.options.heightStyle !== "content" ) {
			this.panels.css( "height", "" );
		}
	},

	enable: function( index ) {
		var disabled = this.options.disabled;
		if ( disabled === false ) {
			return;
		}

		if ( index === undefined ) {
			disabled = false;
		} else {
			index = this._getIndex( index );
			if ( $.isArray( disabled ) ) {
				disabled = $.map( disabled, function( num ) {
					return num !== index ? num : null;
				});
			} else {
				disabled = $.map( this.tabs, function( li, num ) {
					return num !== index ? num : null;
				});
			}
		}
		this._setupDisabled( disabled );
	},

	disable: function( index ) {
		var disabled = this.options.disabled;
		if ( disabled === true ) {
			return;
		}

		if ( index === undefined ) {
			disabled = true;
		} else {
			index = this._getIndex( index );
			if ( $.inArray( index, disabled ) !== -1 ) {
				return;
			}
			if ( $.isArray( disabled ) ) {
				disabled = $.merge( [ index ], disabled ).sort();
			} else {
				disabled = [ index ];
			}
		}
		this._setupDisabled( disabled );
	},

	load: function( index, event ) {
		index = this._getIndex( index );
		var that = this,
			tab = this.tabs.eq( index ),
			anchor = tab.find( ".ui-tabs-anchor" ),
			panel = this._getPanelForTab( tab ),
			eventData = {
				tab: tab,
				panel: panel
			};

		// not remote
		if ( isLocal( anchor[ 0 ] ) ) {
			return;
		}

		this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );

		// support: jQuery <1.8
		// jQuery <1.8 returns false if the request is canceled in beforeSend,
		// but as of 1.8, $.ajax() always returns a jqXHR object.
		if ( this.xhr && this.xhr.statusText !== "canceled" ) {
			tab.addClass( "ui-tabs-loading" );
			panel.attr( "aria-busy", "true" );

			this.xhr
				.success(function( response ) {
					// support: jQuery <1.8
					// http://bugs.jquery.com/ticket/11778
					setTimeout(function() {
						panel.html( response );
						that._trigger( "load", event, eventData );
					}, 1 );
				})
				.complete(function( jqXHR, status ) {
					// support: jQuery <1.8
					// http://bugs.jquery.com/ticket/11778
					setTimeout(function() {
						if ( status === "abort" ) {
							that.panels.stop( false, true );
						}

						tab.removeClass( "ui-tabs-loading" );
						panel.removeAttr( "aria-busy" );

						if ( jqXHR === that.xhr ) {
							delete that.xhr;
						}
					}, 1 );
				});
		}
	},

	_ajaxSettings: function( anchor, event, eventData ) {
		var that = this;
		return {
			url: anchor.attr( "href" ),
			beforeSend: function( jqXHR, settings ) {
				return that._trigger( "beforeLoad", event,
					$.extend( { jqXHR : jqXHR, ajaxSettings: settings }, eventData ) );
			}
		};
	},

	_getPanelForTab: function( tab ) {
		var id = $( tab ).attr( "aria-controls" );
		return this.element.find( this._sanitizeSelector( "#" + id ) );
	}
});

})( jQuery );

// file: 000-1-340-jquery.ui.tooltip.js
/*!
 * jQuery UI Tooltip 1.10.0
 * http://jqueryui.com
 *
 * Copyright 2013 jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 *
 * http://api.jqueryui.com/tooltip/
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 *	jquery.ui.position.js
 */
(function( $ ) {

var increments = 0;

function addDescribedBy( elem, id ) {
	var describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ );
	describedby.push( id );
	elem
		.data( "ui-tooltip-id", id )
		.attr( "aria-describedby", $.trim( describedby.join( " " ) ) );
}

function removeDescribedBy( elem ) {
	var id = elem.data( "ui-tooltip-id" ),
		describedby = (elem.attr( "aria-describedby" ) || "").split( /\s+/ ),
		index = $.inArray( id, describedby );
	if ( index !== -1 ) {
		describedby.splice( index, 1 );
	}

	elem.removeData( "ui-tooltip-id" );
	describedby = $.trim( describedby.join( " " ) );
	if ( describedby ) {
		elem.attr( "aria-describedby", describedby );
	} else {
		elem.removeAttr( "aria-describedby" );
	}
}

$.widget( "ui.tooltip", {
	version: "1.10.0",
	options: {
		content: function() {
			// support: IE<9, Opera in jQuery <1.7
			// .text() can't accept undefined, so coerce to a string
			var title = $( this ).attr( "title" ) || "";
			// Escape title, since we're going from an attribute to raw HTML
			return $( "<a>" ).text( title ).html();
		},
		hide: true,
		// Disabled elements have inconsistent behavior across browsers (#8661)
		items: "[title]:not([disabled])",
		position: {
			my: "left top+15",
			at: "left bottom",
			collision: "flipfit flip"
		},
		show: true,
		tooltipClass: null,
		track: false,

		// callbacks
		close: null,
		open: null
	},

	_create: function() {
		this._on({
			mouseover: "open",
			focusin: "open"
		});

		// IDs of generated tooltips, needed for destroy
		this.tooltips = {};
		// IDs of parent tooltips where we removed the title attribute
		this.parents = {};

		if ( this.options.disabled ) {
			this._disable();
		}
	},

	_setOption: function( key, value ) {
		var that = this;

		if ( key === "disabled" ) {
			this[ value ? "_disable" : "_enable" ]();
			this.options[ key ] = value;
			// disable element style changes
			return;
		}

		this._super( key, value );

		if ( key === "content" ) {
			$.each( this.tooltips, function( id, element ) {
				that._updateContent( element );
			});
		}
	},

	_disable: function() {
		var that = this;

		// close open tooltips
		$.each( this.tooltips, function( id, element ) {
			var event = $.Event( "blur" );
			event.target = event.currentTarget = element[0];
			that.close( event, true );
		});

		// remove title attributes to prevent native tooltips
		this.element.find( this.options.items ).addBack().each(function() {
			var element = $( this );
			if ( element.is( "[title]" ) ) {
				element
					.data( "ui-tooltip-title", element.attr( "title" ) )
					.attr( "title", "" );
			}
		});
	},

	_enable: function() {
		// restore title attributes
		this.element.find( this.options.items ).addBack().each(function() {
			var element = $( this );
			if ( element.data( "ui-tooltip-title" ) ) {
				element.attr( "title", element.data( "ui-tooltip-title" ) );
			}
		});
	},

	open: function( event ) {
		var that = this,
			target = $( event ? event.target : this.element )
				// we need closest here due to mouseover bubbling,
				// but always pointing at the same event target
				.closest( this.options.items );

		// No element to show a tooltip for or the tooltip is already open
		if ( !target.length || target.data( "ui-tooltip-id" ) ) {
			return;
		}

		if ( target.attr( "title" ) ) {
			target.data( "ui-tooltip-title", target.attr( "title" ) );
		}

		target.data( "ui-tooltip-open", true );

		// kill parent tooltips, custom or native, for hover
		if ( event && event.type === "mouseover" ) {
			target.parents().each(function() {
				var parent = $( this ),
					blurEvent;
				if ( parent.data( "ui-tooltip-open" ) ) {
					blurEvent = $.Event( "blur" );
					blurEvent.target = blurEvent.currentTarget = this;
					that.close( blurEvent, true );
				}
				if ( parent.attr( "title" ) ) {
					parent.uniqueId();
					that.parents[ this.id ] = {
						element: this,
						title: parent.attr( "title" )
					};
					parent.attr( "title", "" );
				}
			});
		}

		this._updateContent( target, event );
	},

	_updateContent: function( target, event ) {
		var content,
			contentOption = this.options.content,
			that = this,
			eventType = event ? event.type : null;

		if ( typeof contentOption === "string" ) {
			return this._open( event, target, contentOption );
		}

		content = contentOption.call( target[0], function( response ) {
			// ignore async response if tooltip was closed already
			if ( !target.data( "ui-tooltip-open" ) ) {
				return;
			}
			// IE may instantly serve a cached response for ajax requests
			// delay this call to _open so the other call to _open runs first
			that._delay(function() {
				// jQuery creates a special event for focusin when it doesn't
				// exist natively. To improve performance, the native event
				// object is reused and the type is changed. Therefore, we can't
				// rely on the type being correct after the event finished
				// bubbling, so we set it back to the previous value. (#8740)
				if ( event ) {
					event.type = eventType;
				}
				this._open( event, target, response );
			});
		});
		if ( content ) {
			this._open( event, target, content );
		}
	},

	_open: function( event, target, content ) {
		var tooltip, events, delayedShow,
			positionOption = $.extend( {}, this.options.position );

		if ( !content ) {
			return;
		}

		// Content can be updated multiple times. If the tooltip already
		// exists, then just update the content and bail.
		tooltip = this._find( target );
		if ( tooltip.length ) {
			tooltip.find( ".ui-tooltip-content" ).html( content );
			return;
		}

		// if we have a title, clear it to prevent the native tooltip
		// we have to check first to avoid defining a title if none exists
		// (we don't want to cause an element to start matching [title])
		//
		// We use removeAttr only for key events, to allow IE to export the correct
		// accessible attributes. For mouse events, set to empty string to avoid
		// native tooltip showing up (happens only when removing inside mouseover).
		if ( target.is( "[title]" ) ) {
			if ( event && event.type === "mouseover" ) {
				target.attr( "title", "" );
			} else {
				target.removeAttr( "title" );
			}
		}

		tooltip = this._tooltip( target );
		addDescribedBy( target, tooltip.attr( "id" ) );
		tooltip.find( ".ui-tooltip-content" ).html( content );

		function position( event ) {
			positionOption.of = event;
			if ( tooltip.is( ":hidden" ) ) {
				return;
			}
			tooltip.position( positionOption );
		}
		if ( this.options.track && event && /^mouse/.test( event.type ) ) {
			this._on( this.document, {
				mousemove: position
			});
			// trigger once to override element-relative positioning
			position( event );
		} else {
			tooltip.position( $.extend({
				of: target
			}, this.options.position ) );
		}

		tooltip.hide();

		this._show( tooltip, this.options.show );
		// Handle tracking tooltips that are shown with a delay (#8644). As soon
		// as the tooltip is visible, position the tooltip using the most recent
		// event.
		if ( this.options.show && this.options.show.delay ) {
			delayedShow = this.delayedShow = setInterval(function() {
				if ( tooltip.is( ":visible" ) ) {
					position( positionOption.of );
					clearInterval( delayedShow );
				}
			}, $.fx.interval );
		}

		this._trigger( "open", event, { tooltip: tooltip } );

		events = {
			keyup: function( event ) {
				if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
					var fakeEvent = $.Event(event);
					fakeEvent.currentTarget = target[0];
					this.close( fakeEvent, true );
				}
			},
			remove: function() {
				this._removeTooltip( tooltip );
			}
		};
		if ( !event || event.type === "mouseover" ) {
			events.mouseleave = "close";
		}
		if ( !event || event.type === "focusin" ) {
			events.focusout = "close";
		}
		this._on( true, target, events );
	},

	close: function( event ) {
		var that = this,
			target = $( event ? event.currentTarget : this.element ),
			tooltip = this._find( target );

		// disabling closes the tooltip, so we need to track when we're closing
		// to avoid an infinite loop in case the tooltip becomes disabled on close
		if ( this.closing ) {
			return;
		}

		// Clear the interval for delayed tracking tooltips
		clearInterval( this.delayedShow );

		// only set title if we had one before (see comment in _open())
		if ( target.data( "ui-tooltip-title" ) ) {
			target.attr( "title", target.data( "ui-tooltip-title" ) );
		}

		removeDescribedBy( target );

		tooltip.stop( true );
		this._hide( tooltip, this.options.hide, function() {
			that._removeTooltip( $( this ) );
		});

		target.removeData( "ui-tooltip-open" );
		this._off( target, "mouseleave focusout keyup" );
		// Remove 'remove' binding only on delegated targets
		if ( target[0] !== this.element[0] ) {
			this._off( target, "remove" );
		}
		this._off( this.document, "mousemove" );

		if ( event && event.type === "mouseleave" ) {
			$.each( this.parents, function( id, parent ) {
				$( parent.element ).attr( "title", parent.title );
				delete that.parents[ id ];
			});
		}

		this.closing = true;
		this._trigger( "close", event, { tooltip: tooltip } );
		this.closing = false;
	},

	_tooltip: function( element ) {
		var id = "ui-tooltip-" + increments++,
			tooltip = $( "<div>" )
				.attr({
					id: id,
					role: "tooltip"
				})
				.addClass( "ui-tooltip ui-widget ui-corner-all ui-widget-content " +
					( this.options.tooltipClass || "" ) );
		$( "<div>" )
			.addClass( "ui-tooltip-content" )
			.appendTo( tooltip );
		tooltip.appendTo( this.document[0].body );
		this.tooltips[ id ] = element;
		return tooltip;
	},

	_find: function( target ) {
		var id = target.data( "ui-tooltip-id" );
		return id ? $( "#" + id ) : $();
	},

	_removeTooltip: function( tooltip ) {
		tooltip.remove();
		delete this.tooltips[ tooltip.attr( "id" ) ];
	},

	_destroy: function() {
		var that = this;

		// close open tooltips
		$.each( this.tooltips, function( id, element ) {
			// Delegate to close method to handle common cleanup
			var event = $.Event( "blur" );
			event.target = event.currentTarget = element[0];
			that.close( event, true );

			// Remove immediately; destroying an open tooltip doesn't use the
			// hide animation
			$( "#" + id ).remove();

			// Restore the title
			if ( element.data( "ui-tooltip-title" ) ) {
				element.attr( "title", element.data( "ui-tooltip-title" ) );
				element.removeData( "ui-tooltip-title" );
			}
		});
	}
});

}( jQuery ) );

// file: 000-1-jquery.tmpl.js
/*!
 * jQuery Templates Plugin 1.0.0pre
 * http://github.com/jquery/jquery-tmpl
 * Requires jQuery 1.4.2
 *
 * Copyright Software Freedom Conservancy, Inc.
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 */
(function( jQuery, undefined ){
	var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
		newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];

	function newTmplItem( options, parentItem, fn, data ) {
		// Returns a template item data structure for a new rendered instance of a template (a 'template item').
		// The content field is a hierarchical array of strings and nested items (to be
		// removed and replaced by nodes field of dom elements, once inserted in DOM).
		var newItem = {
			data: data || (parentItem ? parentItem.data : {}),
			_wrap: parentItem ? parentItem._wrap : null,
			tmpl: null,
			parent: parentItem || null,
			nodes: [],
			calls: tiCalls,
			nest: tiNest,
			wrap: tiWrap,
			html: tiHtml,
			update: tiUpdate
		};
		if ( options ) {
			jQuery.extend( newItem, options, { nodes: [], parent: parentItem });
		}
		if ( fn ) {
			// Build the hierarchical content to be used during insertion into DOM
			newItem.tmpl = fn;
			newItem._ctnt = newItem._ctnt || newItem.tmpl( jQuery, newItem );
			newItem.key = ++itemKey;
			// Keep track of new template item, until it is stored as jQuery Data on DOM element
			(stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
		}
		return newItem;
	}

	// Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
	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 ), elems, i, l, tmplItems,
				parent = this.length === 1 && this[0].parentNode;

			appendToTmplItems = newTmplItems || {};
			if ( parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1 ) {
				insert[ original ]( this[0] );
				ret = this;
			} else {
				for ( i = 0, l = insert.length; i < l; i++ ) {
					cloneIndex = i;
					elems = (i > 0 ? this.clone(true) : this).get();
					jQuery( insert[i] )[ original ]( elems );
					ret = ret.concat( elems );
				}
				cloneIndex = 0;
				ret = this.pushStack( ret, name, insert.selector );
			}
			tmplItems = appendToTmplItems;
			appendToTmplItems = null;
			jQuery.tmpl.complete( tmplItems );
			return ret;
		};
	});

	jQuery.fn.extend({
		// Use first wrapped element as template markup.
		// Return wrapped set of template items, obtained by rendering template against data.
		tmpl: function( data, options, parentItem ) {
			return jQuery.tmpl( this[0], data, options, parentItem );
		},

		// Find which rendered template item the first wrapped DOM element belongs to
		tmplItem: function() {
			return jQuery.tmplItem( this[0] );
		},

		// Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
		template: function( name ) {
			return jQuery.template( name, this[0] );
		},

		domManip: function( args, table, callback, options ) {
			if ( args[0] && jQuery.isArray( args[0] )) {
				var dmArgs = jQuery.makeArray( arguments ), elems = args[0], elemsLength = elems.length, i = 0, tmplItem;
				while ( i < elemsLength && !(tmplItem = jQuery.data( elems[i++], "tmplItem" ))) {}
				if ( tmplItem && cloneIndex ) {
					dmArgs[2] = function( fragClone ) {
						// Handler called by oldManip when rendered template has been inserted into DOM.
						jQuery.tmpl.afterManip( this, fragClone, callback );
					};
				}
				oldManip.apply( this, dmArgs );
			} else {
				oldManip.apply( this, arguments );
			}
			cloneIndex = 0;
			if ( !appendToTmplItems ) {
				jQuery.tmpl.complete( newTmplItems );
			}
			return this;
		}
	});

	jQuery.extend({
		// Return wrapped set of template items, obtained by rendering template against data.
		tmpl: function( tmpl, data, options, parentItem ) {
			var ret, topLevel = !parentItem;
			if ( topLevel ) {
				// This is a top-level tmpl call (not from a nested template using {{tmpl}})
				parentItem = topTmplItem;
				tmpl = jQuery.template[tmpl] || jQuery.template( null, tmpl );
				wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
			} else if ( !tmpl ) {
				// The template item is already associated with DOM - this is a refresh.
				// Re-evaluate rendered template for the parentItem
				tmpl = parentItem.tmpl;
				newTmplItems[parentItem.key] = parentItem;
				parentItem.nodes = [];
				if ( parentItem.wrapped ) {
					updateWrapped( parentItem, parentItem.wrapped );
				}
				// Rebuild, without creating a new template item
				return jQuery( build( parentItem, null, parentItem.tmpl( jQuery, parentItem ) ));
			}
			if ( !tmpl ) {
				return []; // Could throw...
			}
			if ( typeof data === "function" ) {
				data = data.call( parentItem || {} );
			}
			if ( options && options.wrapped ) {
				updateWrapped( options, options.wrapped );
			}
			ret = jQuery.isArray( data ) ? 
				jQuery.map( data, function( dataItem ) {
					return dataItem ? newTmplItem( options, parentItem, tmpl, dataItem ) : null;
				}) :
				[ newTmplItem( options, parentItem, tmpl, data ) ];
			return topLevel ? jQuery( build( parentItem, null, ret ) ) : ret;
		},

		// Return rendered template item for an element.
		tmplItem: function( elem ) {
			var tmplItem;
			if ( elem instanceof jQuery ) {
				elem = elem[0];
			}
			while ( elem && elem.nodeType === 1 && !(tmplItem = jQuery.data( elem, "tmplItem" )) && (elem = elem.parentNode) ) {}
			return tmplItem || topTmplItem;
		},

		// Set:
		// Use $.template( name, tmpl ) to cache a named template,
		// where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
		// Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.

		// Get:
		// Use $.template( name ) to access a cached template.
		// Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
		// will return the compiled template, without adding a name reference.
		// If templateString includes at least one HTML tag, $.template( templateString ) is equivalent
		// to $.template( null, templateString )
		template: function( name, tmpl ) {
			if (tmpl) {
				// Compile template and associate with name
				if ( typeof tmpl === "string" ) {
					// This is an HTML string being passed directly in.
					tmpl = buildTmplFn( tmpl )
				} else if ( tmpl instanceof jQuery ) {
					tmpl = tmpl[0] || {};
				}
				if ( tmpl.nodeType ) {
					// If this is a template block, use cached copy, or generate tmpl function and cache.
					tmpl = jQuery.data( tmpl, "tmpl" ) || jQuery.data( tmpl, "tmpl", buildTmplFn( tmpl.innerHTML )); 
					// Issue: In IE, if the container element is not a script block, the innerHTML will remove quotes from attribute values whenever the value does not include white space. 
					// This means that foo="${x}" will not work if the value of x includes white space: foo="${x}" -> foo=value of x. 
					// To correct this, include space in tag: foo="${ x }" -> foo="value of x"
				}
				return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
			}
			// Return named compiled template
			return name ? (typeof name !== "string" ? jQuery.template( null, name ): 
				(jQuery.template[name] || 
					// If not in map, treat as a selector. (If integrated with core, use quickExpr.exec) 
					jQuery.template( null, htmlExpr.test( name ) ? name : jQuery( name )))) : null; 
		},

		encode: function( text ) {
			// Do HTML encoding replacing < > & and ' and " by corresponding entities.
			return ("" + text).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");
		}
	});

	jQuery.extend( jQuery.tmpl, {
		tag: {
			"tmpl": {
				_default: { $2: "null" },
				open: "if($notnull_1){_=_.concat($item.nest($1,$2));}"
				// tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
				// This means that {{tmpl foo}} treats foo as a template (which IS a function). 
				// Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
			},
			"wrap": {
				_default: { $2: "null" },
				open: "$item.calls(_,$1,$2);_=[];",
				close: "call=$item.calls();_=call._.concat($item.wrap(call,_));"
			},
			"each": {
				_default: { $2: "$index, $value" },
				open: "if($notnull_1){$.each($1a,function($2){with(this){",
				close: "}});}"
			},
			"if": {
				open: "if(($notnull_1) && $1a){",
				close: "}"
			},
			"else": {
				_default: { $1: "true" },
				open: "}else if(($notnull_1) && $1a){"
			},
			"html": {
				// Unecoded expression evaluation. 
				open: "if($notnull_1){_.push($1a);}"
			},
			"=": {
				// Encoded expression evaluation. Abbreviated form is ${}.
				_default: { $1: "$data" },
				open: "if($notnull_1){_.push($.encode($1a));}"
			},
			"!": {
				// Comment tag. Skipped by parser
				open: ""
			}
		},

		// This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
		complete: function( items ) {
			newTmplItems = {};
		},

		// Call this from code which overrides domManip, or equivalent
		// Manage cloning/storing template items etc.
		afterManip: function afterManip( elem, fragClone, callback ) {
			// Provides cloned fragment ready for fixup prior to and after insertion into DOM
			var content = fragClone.nodeType === 11 ?
				jQuery.makeArray(fragClone.childNodes) :
				fragClone.nodeType === 1 ? [fragClone] : [];

			// Return fragment to original caller (e.g. append) for DOM insertion
			callback.call( elem, fragClone );

			// Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
			storeTmplItems( content );
			cloneIndex++;
		}
	});

	//========================== Private helper functions, used by code above ==========================

	function build( tmplItem, nested, content ) {
		// Convert hierarchical content into flat string array 
		// and finally return array of fragments ready for DOM insertion
		var frag, ret = content ? jQuery.map( content, function( item ) {
			return (typeof item === "string") ? 
				// Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
				(tmplItem.key ? item.replace( /(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2" ) : item) :
				// This is a child template item. Build nested template.
				build( item, tmplItem, item._ctnt );
		}) : 
		// If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}. 
		tmplItem;
		if ( nested ) {
			return ret;
		}

		// top-level template
		ret = ret.join("");

		// Support templates which have initial or final text nodes, or consist only of text
		// Also support HTML entities within the HTML markup.
		ret.replace( /^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function( all, before, middle, after) {
			frag = jQuery( middle ).get();

			storeTmplItems( frag );
			if ( before ) {
				frag = unencode( before ).concat(frag);
			}
			if ( after ) {
				frag = frag.concat(unencode( after ));
			}
		});
		return frag ? frag : unencode( ret );
	}

	function unencode( text ) {
		// Use createElement, since createTextNode will not render HTML entities correctly
		var el = document.createElement( "div" );
		el.innerHTML = text;
		return jQuery.makeArray(el.childNodes);
	}

	// Generate a reusable function that will serve to render a template against data
	function buildTmplFn( markup ) {
		return new Function("jQuery","$item",
			"var $=jQuery,call,_=[],$data=$item.data;" +

			// Introduce the data as local variables using with(){}
			"with($data){_.push('" +

			// Convert the template into pure JavaScript
			jQuery.trim(markup)
				.replace( /([\\'])/g, "\\$1" )
				.replace( /[\r\t\n]/g, " " )
				.replace( /\$\{([^\}]*)\}/g, "{{= $1}}" )
				.replace( /\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
				function( all, slash, type, fnargs, target, parens, args ) {
					var tag = jQuery.tmpl.tag[ type ], def, expr, exprAutoFnDetect;
					if ( !tag ) {
						throw "Template command not found: " + type;
					}
					def = tag._default || [];
					if ( parens && !/\w$/.test(target)) {
						target += parens;
						parens = "";
					}
					if ( target ) {
						target = unescape( target ); 
						args = args ? ("," + unescape( args ) + ")") : (parens ? ")" : "");
						// Support for target being things like a.toLowerCase();
						// In that case don't call with template item as 'this' pointer. Just evaluate...
						expr = parens ? (target.indexOf(".") > -1 ? target + unescape( parens ) : ("(" + target + ").call($item" + args)) : target;
						exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
					} else {
						exprAutoFnDetect = expr = def.$1 || "null";
					}
					fnargs = unescape( fnargs );
					return "');" + 
						tag[ slash ? "close" : "open" ]
							.split( "$notnull_1" ).join( target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true" )
							.split( "$1a" ).join( exprAutoFnDetect )
							.split( "$1" ).join( expr )
							.split( "$2" ).join( fnargs || def.$2 || "" ) +
						"_.push('";
				}) +
			"');}return _;"
		);
	}
	function updateWrapped( options, wrapped ) {
		// Build the wrapped content. 
		options._wrap = build( options, true, 
			// Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
			jQuery.isArray( wrapped ) ? wrapped : [htmlExpr.test( wrapped ) ? wrapped : jQuery( wrapped ).html()]
		).join("");
	}

	function unescape( args ) {
		return args ? args.replace( /\\'/g, "'").replace(/\\\\/g, "\\" ) : null;
	}
	function outerHtml( elem ) {
		var div = document.createElement("div");
		div.appendChild( elem.cloneNode(true) );
		return div.innerHTML;
	}

	// Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
	function storeTmplItems( content ) {
		var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
		for ( i = 0, l = content.length; i < l; i++ ) {
			if ( (elem = content[i]).nodeType !== 1 ) {
				continue;
			}
			elems = elem.getElementsByTagName("*");
			for ( m = elems.length - 1; m >= 0; m-- ) {
				processItemKey( elems[m] );
			}
			processItemKey( elem );
		}
		function processItemKey( el ) {
			var pntKey, pntNode = el, pntItem, tmplItem, key;
			// Ensure that each rendered template inserted into the DOM has its own template item,
			if ( (key = el.getAttribute( tmplItmAtt ))) {
				while ( pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute( tmplItmAtt ))) { }
				if ( pntKey !== key ) {
					// The next ancestor with a _tmplitem expando is on a different key than this one.
					// So this is a top-level element within this template item
					// Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
					pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute( tmplItmAtt ) || 0)) : 0;
					if ( !(tmplItem = newTmplItems[key]) ) {
						// The item is for wrapped content, and was copied from the temporary parent wrappedItem.
						tmplItem = wrappedItems[key];
						tmplItem = newTmplItem( tmplItem, newTmplItems[pntNode]||wrappedItems[pntNode] );
						tmplItem.key = ++itemKey;
						newTmplItems[itemKey] = tmplItem;
					}
					if ( cloneIndex ) {
						cloneTmplItem( key );
					}
				}
				el.removeAttribute( tmplItmAtt );
			} else if ( cloneIndex && (tmplItem = jQuery.data( el, "tmplItem" )) ) {
				// This was a rendered element, cloned during append or appendTo etc.
				// TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
				cloneTmplItem( tmplItem.key );
				newTmplItems[tmplItem.key] = tmplItem;
				pntNode = jQuery.data( el.parentNode, "tmplItem" );
				pntNode = pntNode ? pntNode.key : 0;
			}
			if ( tmplItem ) {
				pntItem = tmplItem;
				// Find the template item of the parent element. 
				// (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
				while ( pntItem && pntItem.key != pntNode ) { 
					// Add this element as a top-level node for this rendered template item, as well as for any
					// ancestor items between this item and the item of its parent element
					pntItem.nodes.push( el );
					pntItem = pntItem.parent;
				}
				// Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
				delete tmplItem._ctnt;
				delete tmplItem._wrap;
				// Store template item as jQuery data on the element
				jQuery.data( el, "tmplItem", tmplItem );
			}
			function cloneTmplItem( key ) {
				key = key + keySuffix;
				tmplItem = newClonedItems[key] = 
					(newClonedItems[key] || newTmplItem( tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent ));
			}
		}
	}

	//---- Helper functions for template item ----

	function tiCalls( content, tmpl, data, options ) {
		if ( !content ) {
			return stack.pop();
		}
		stack.push({ _: content, tmpl: tmpl, item:this, data: data, options: options });
	}

	function tiNest( tmpl, data, options ) {
		// nested template, using {{tmpl}} tag
		return jQuery.tmpl( jQuery.template( tmpl ), data, options, this );
	}

	function tiWrap( call, wrapped ) {
		// nested template, using {{wrap}} tag
		var options = call.options || {};
		options.wrapped = wrapped;
		// Apply the template, which may incorporate wrapped content, 
		return jQuery.tmpl( jQuery.template( call.tmpl ), call.data, options, call.item );
	}

	function tiHtml( filter, textOnly ) {
		var wrapped = this._wrap;
		return jQuery.map(
			jQuery( jQuery.isArray( wrapped ) ? wrapped.join("") : wrapped ).filter( filter || "*" ),
			function(e) {
				return textOnly ?
					e.innerText || e.textContent :
					e.outerHTML || outerHtml(e);
			});
	}

	function tiUpdate() {
		var coll = this.nodes;
		jQuery.tmpl( null, null, null, this).insertBefore( coll[0] );
		jQuery( coll ).remove();
	}
})( jQuery );

// file: 000-compatibility.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
window.ieLevel = 0;
var userAgent = navigator.userAgent;
window.isWebKit = userAgent.indexOf('WebKit') >= 0;
if (userAgent.indexOf('Safari') >=0)
{
	window.browser = 'Safari';
}
else if (userAgent.indexOf('Gecko') >=0)
{
	window.browser = 'Mozilla';
}
else if (userAgent.indexOf('MSIE') >=0)
{
	window.browser = 'IE';
    if (document.documentMode) 
      ieLevel = document.documentMode;
   else // IE 5-7
   {
      ieLevel = 5; // Assume quirks mode unless proven otherwise
      if (document.compatMode)
      {
         if (document.compatMode == "CSS1Compat") // standards mode
         {
         	if (window.XmlHttpRequest) // Available in IE 7
            	ieLevel = 7; 
            else
            	ieLevel = 6; // IE 6.0
            
         }
      }
   }	
}
else 
{
	window.browser = 'Unknown';
}

function createXMLHTTPRequest()
{
	//TODO: better error reporting when XMLHTTPRequest is not supported
	if (window.XMLHttpRequest)
		return new XMLHttpRequest(); // Works on Mozilla and others
	else
		return new ActiveXObject("Microsoft.XMLHTTP"); // Works on IE
};

function createAnIFrame(parentWindow,name,url)
{
	if (window.browser == 'IE')
	{
		// Creating an iframe in the standard way doesn't work because IE somehow
		// Doesn't recogmize the newly created iframe (submitting a form targeted 
		// To the new iframe causes a new window to be created.
		var styleClause = '';
		if (! window.showServiceInvocations)
		{
			styleClause = 'class="hidden"';
		}
		var srcClause = url ? ' src="'+url+'"' :'';
		var html = '<iframe name="' + name + '" id="'+name+'"'+styleClause+srcClause+'></iframe>';
    	parentWindow.document.body.insertAdjacentHTML( "beforeEnd", html);
    	var iframe = parentWindow.frames[ name ];
    	return iframe;
    }
    else
    {
    	// Standard DOM implementation
    	var iframe = parentWindow.document.createElement('iframe');
		iframe.name = name;
		iframe.id = name;
		iframe.src=url?url:"blank.html";
		if (! window.showServiceInvocations)
			iframe.className = 'hidden';
		var body = parentWindow.document.body;
		body.appendChild(iframe);
		return iframe;
    }
}

function getIFrameWindow(iframe)
{
	if (iframe.contentWindow)
		return iframe.contentWindow;
	else
		return iframe;
};
function getIFrameDocument(iframe)
{
	if (iframe.contentWindow)
		return iframe.contentWindow.document;
	else
		return iframe.document;
};

function setCssFloat(node,value)
{
	if (window.browser == 'IE')
	{
		node.style.styleFloat=value;
	}
	else
	{
		node.style.cssFloat=value;
	};
	
};

function setEncType(form, enctype)
{
	// Althogh 'enctype' and 'encoding' are supposed to be synonyms, 
	// Setting 'enctype' (the DOM standard) doesn't work in IE
	if (window.browser == 'IE')
	{
		form.encoding = enctype;
	}
	else
	{
		form.enctype = enctype;
	};
	
}
function getStackTrace()
{
	var stack = '';
	var e;
	try
	{
		x.x;
	}
	catch(ex)
	{
		e = ex;
	}
	if (e.stack)
	{
		var tmp =  e.stack;
		var frames = tmp.split('\n');
		frames.splice(0,2);
		stack = frames.join('\n');
	}
	else
	{
		for (var func = arguments.caller; func != null; func = func.caller)
		{
			stack += '\n' + getFunctionName(func.callee) + '\n';
		}
	}
	return stack;
  };
  
  // Returns the position of the current event, relative to the window
  // On IE, the event is taken from the window
  // On other browsers, it is supplied as an argument
  function getEventPosition(win,e)
  {
  	var pos = new Position();
	if (window.browser != 'IE')
	{
  		pos.x = e.clientX;
  		pos.y = e.clientY;
  	}
	else
	{
  	 	pos.x = win.event.clientX;
  	 	pos.y = win.event.clientY;
  	 }
  	 return pos;
  };
  function Position() {};
  Position.prototype.equals = function (other)
  {
  	return other.x == this.x && other.y == this.y;
  };
  
  
function setScrollableTable(bodyNode, width, height)
{
	if (window.browser=='Mozilla')
	{
		bodyNode.style.overflow='auto';
		if (width)
			bodyNode.style.width = width;
		if (height)
			bodyNode.style.height = height;
	};
};
  
function isScrollable(node)
{
	return node.scrollHeight != node.offsetHeight || node == node.ownerDocument.body;
};  
function getOffsets(node)
{
	var x = 0;
	var y = 0;
	var currentNode = node;
	do
	{
		x+=currentNode.offsetLeft;
		y+=currentNode.offsetTop;
		currentNode = currentNode.offsetParent;
	}
	while (currentNode);
	return {'left':x, 'top':y};
};
// Returns the position of a node relative to the screen (taking scrolling into account)
function getScreenPosition(node)
{
	var x = 0;
	var y = 0;
	var currentNode = node;
/*	
	//Old calculation of offset relative to the document (doesn't always work correctly).  Currently using jQuery (see below)
	do
	{
		x+=currentNode.offsetLeft;
		y+=currentNode.offsetTop;
		currentNode = currentNode.offsetParent;
	}
	while (currentNode);
	*/
	var offset = $(node).offset();
	var $w = $(getParentWindow(node));
       /* Using jQuery's cross-browser solution to get global scrolling */
	offset.top -= $w.scrollTop();
	offset.left -= $w.scrollLeft();
	
	if (tersus.isIPhoneSafari)
	{
		offset.left -= window.pageXOffset;
		offset.top -= window.pageYOffset;
	}
	return offset;
};

function getScroll(node)
{
	var p = getScreenPosition(node);
	p.top -= node.offsetTop;
	p.left -= node.offsetLeft;
	return p;
};
function contains(node,position)
{
	var offsets = getScreenPosition(node);
	var size = getVisibleSize(node);
	return position.x >= offsets.left && position.y >= offsets.top && position.x <=offsets.left + size.width &&
	position.y <= offsets.top + size.height;
};

function getViewportSize(d)
{
	var n = d.compatMode == 'BackCompat' ? d.body : d.documentElement;
		
	return {'height':n.clientHeight, 'width':n.clientWidth};
}
function getWindowScroll(w)
{
	var scroll = {};
	if (w.pageYOffset != undefined) // For standards - compatible browsers
	{
		scroll.left = w.pageXOffset;
		scroll.top = w.pageYOffset;
	}
	else if (w.document.documentElement && w.document.documentElement.scrollTop) // IE 8 in standards mode
	{
		scroll.left = w.document.documentElement.scrollLeft;
		scroll.top = w.document.documentElement.scrollTop;
	}
	else if (w.document.body) //  IE in quirks mode
	{
		scroll.left = w.document.body.scrollLeft;
		scroll.top = w.document.body.scrollTop;
	}
	return scroll;		
}

function getVisibleSize(node)
{
	var width = node.offsetWidth;
	var height = node.offsetHeight;
	if (node == node.ownerDocument.body)
	{
		if ( node.clientHeight &&  ieLevel<7) // On IE 7 & 8 body.clientHeight is not the visible part of the body
		{
			height = node.clientHeight;
		}
	};
	return {'height':height,'width':width};
};
function getHeight(node)
{
	return node.offsetHeight;
};
function html2Node(t, document)
{
	var p;
	var pref3 = t.substring(0,3);
	if (pref3 == '<tr')
	{
		p = document.createElement('DIV');
		p.innerHTML='<table><tbody>'+t+'</tbody></table>';
		return p.firstChild.tBodies[0].firstChild;
	}
	if (pref3 == '<td' || pref3 == '<th')
	{
		p = document.createElement('DIV');
		p.innerHTML='<table><tbody><tr>'+t+'</tr></tbody></table>';
		return p.firstChild.tBodies[0].firstChild.firstChild;
	}
	else
	{
		p = document.createElement('DIV');
		p.innerHTML=t;
		return p.firstChild;
	}
}
function importNode(document, node)
{
	if (document.importNode && window.browser != 'IE')
		return document.importNode(node,true);
	else if (node.outerHTML)
	{
		var tmpNode = document.createElement('DIV');
		tmpNode.innerHTML = node.outerHTML;
		return tmpNode.firstChild;
	}
	else
	{
		tersus.error('importNode not implemented for this browser');
		return null;
	}
	
};
function getActualBackground(node)
{
	var current = node;
	while (current)
	{
		var background = getActualStyle(current,'background-color');
		if (background != 'transparent' && background != 'rgba(0, 0, 0, 0)') //Chrome has rgba(0, 0, 0, 0)
		{
			 return background;
		}
		current = current.parentNode;
	}
	return null;
};
tersus.getJsAttributeName = function(name)
{
	var parts = name.split('-');
	if (parts.length == 1)
		return parts[0];
	else
	{
		var t = parts[1];
		return parts[0]+t.charAt(0).toUpperCase()+t.substr(1);
	}
}; 

function getActualStyle(node,styleProp)
{
	var y=null;
	if (node.currentStyle)
	{
		var prop = tersus.getJsAttributeName(styleProp);
		if (prop == undefined)
			prop = styleProp;
		y = node.currentStyle[prop];
	}
	else if (window.getComputedStyle)
		y = node.ownerDocument.defaultView.getComputedStyle(node,null).getPropertyValue(styleProp);
	return y;
};
function getMeasure(node, property)
{
	var s = getActualStyle(node,property);
	var m = parseInt(s);
	return isNaN(m) ? 0 : m;
};
getActualStyle.propertyMap = {};
getActualStyle.propertyMap['background-color']='backgroundColor';
getActualStyle.propertyMap['margin-top']='marginTop';
getActualStyle.propertyMap['margin-bottom']='marginBottom';
function isVisible(node)
{
	if (node.tagName && node.tagName == 'HTML')
		return true;
	if (getActualStyle(node,'visibility')=='hidden')
		return false;
	else if (getActualStyle(node,'display') == 'none')
		return false;
	else if (node.parentNode)
		return isVisible(node.parentNode);
	else 
		return true;
};
function getPageSize(w)
{
	var size = {};
	if (w.innerHeight) 
	{
		size.width = w.innerWidth;
		size.height = w.innerHeight;
	}
	else if (w.document.documentElement && w.document.documentElement.clientHeight)
	{
		size.width = w.document.documentElement.clientWidth;
		size.height = w.document.documentElement.clientHeight;
	}
	else if (w.document.body) 
	{
		size.width = w.document.body.clientWidth;
		size.height = w.document.body.clientHeight;
	}
	return size;
};

function getPageScroll(w)
{
	var scroll = {};
	if (w.pageYOffset) 
	{
		scroll.x = w.pageXOffset;
		scroll.y = w.pageYOffset;
	}
	else if (w.document.documentElement && w.document.documentElement.scrollTop)
	{
		scroll.x = w.document.documentElement.scrollLeft;
		scroll.y = w.document.documentElement.scrollTop;
	}
	else if (w.document.body) // all other Explorers
	{
		scroll.x = w.document.body.scrollLeft;
		scroll.y = w.document.body.scrollTop;
	}
	return scroll;
};

function getParentWindow(node)
{
	if (node.parentWindow)
		return node.parentWindow;
	else if (node.defaultView)
		return node.defaultView;
	else if (node.ownerDocument)
		return getParentWindow(node.ownerDocument);
};

function clearSelection(w)
{
	if (w.document.selection && w.document.selection.empty)
		w.document.selection.empty();
	else if (w.getSelection && w.getSelection().removeAllRanges)
		w.getSelection().removeAllRanges();
};

function getEventAttributes(e)
{
	var atts = {};
	atts.type = e.type;
	atts.files = e.originalEvent && e.originalEvent.dataTransfer && e.originalEvent.dataTransfer.files;
	if (e.type.substring(0,3)=='key')
	{
		if (e.keyCode)
			atts.keyCode = e.keyCode;
		else 
			atts.keyCode = e.which;
	}
	atts.ctrlKey = e.ctrlKey;
	atts.shiftKey = e.shiftKey;
    atts.altKey = e.altKey;
    atts.metaKey = e.metaKey;
	var buttonCode = e.button;
	if (this.browser=='Mozilla' || this.browser=='Safari')
	{
		if (buttonCode == 0)
			atts.button = 'Left';
		else if (buttonCode == 1)
			atts.button = 'Middle';
		else if (buttonCode == 2)
			atts.button = 'Right';
	}
	else
	{
		if (buttonCode == 1)
			atts.button = 'Left';
		else if (buttonCode == 4)
			atts.button = 'Middle';
		else if (buttonCode == 2)
			atts.button = 'Right';
	}
	atts.clientX  = e.clientX;
	atts.clientY = e.clientY;
	atts.pageX  = e.pageX;
	atts.pageY = e.pageY;
	
	atts.targetElement = e.target ? e.target : e.srcElement;
	return atts;
};
// Javascript escaping/quoting: based on http://www.json.org/json2.js (public domain)
js_escapeable = /[\\\'\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g;
	js_meta = {    // table of character substitutions
                '\b': '\\b',
                '\t': '\\t',
                '\n': '\\n',
                '\f': '\\f',
                '\r': '\\r',
                "'" : "\\'",
                '\\': '\\\\'
            };
function js_quote(string) {
js_escapeable.lastIndex = 0;
return js_escapeable.test(string) ?
    '"' + string.replace(js_escapeable, function (a) {
        var c = js_meta[a];
        if (typeof c === 'string') {
            return c;
        }
        return '\\u' + ('0000' +
                (+(a.charCodeAt(0))).toString(16)).slice(-4);
    }) + '"' :
    '"' + string + '"';
}
function is_touch_device() {
  return !!('ontouchstart' in window) ? 1 : 0;
}

// file: 000-tersus.gwt.js

var $wnd = window;
var $doc = $wnd.document;
var $moduleName, $moduleBase;
var $stats = $wnd.__gwtStatsEvent ? function(a) {return $wnd.__gwtStatsEvent(a);} : null,
$sessionId = $wnd.__gwtStatsSessionId ? $wnd.__gwtStatsSessionId : null;
$stats && $stats({moduleName:'tersus.gwt.Util',sessionId:$sessionId,subSystem:'startup',evtGroup:'moduleStartup',millis:(new Date()).getTime(),type:'moduleEvalStart'});

var _, N8000000000000000_longLit = [0, -9223372036854775808], P0_longLit = [0, 0], P3e8_longLit = [1000, 0], P1000000_longLit = [16777216, 0], P7fffffffffffffff_longLit = [4294967295, 9223372032559808512];
function nullMethod(){
}

function equals(other){
  return this === (other == null?null:other);
}

function hashCode_0(){
  return this.$H || (this.$H = ++sNextHashId);
}

function Object_0(){
}

_ = Object_0.prototype = {};
_.equals$ = equals;
_.hashCode$ = hashCode_0;
_.typeMarker$ = nullMethod;
_.typeId$ = 1;
function $setStackTrace(stackTrace){
  var c, copy, i;
  copy = initDim(_3Ljava_lang_StackTraceElement_2_classLit, 39, 13, stackTrace.length, 0);
  for (i = 0 , c = stackTrace.length; i < c; ++i) {
    if (!stackTrace[i]) {
      throw $NullPointerException(new NullPointerException);
    }
    copy[i] = stackTrace[i];
  }
}

function Throwable(){
}

_ = Throwable.prototype = new Object_0;
_.typeId$ = 3;
function Exception(){
}

_ = Exception.prototype = new Throwable;
_.typeId$ = 4;
function RuntimeException(){
}

_ = RuntimeException.prototype = new Exception;
_.typeId$ = 5;
function $JavaScriptException(this$static, e){
  $fillInStackTrace();
  this$static.e = e;
  $createStackTrace(this$static);
  return this$static;
}

function JavaScriptException(){
}

_ = JavaScriptException.prototype = new RuntimeException;
_.typeId$ = 6;
_.e = null;
function equals__devirtual$(this$static, other){
  return this$static.typeMarker$ == nullMethod || this$static.typeId$ == 2?this$static.equals$(other):(this$static == null?null:this$static) === (other == null?null:other);
}

function hashCode__devirtual$(this$static){
  return this$static.typeMarker$ == nullMethod || this$static.typeId$ == 2?this$static.hashCode$():this$static.$H || (this$static.$H = ++sNextHashId);
}

function Scheduler(){
}

_ = Scheduler.prototype = new Object_0;
_.typeId$ = 0;
function entry_0(jsFunction){
  return function(){
    return entry0(jsFunction, this, arguments);
  }
  ;
}

function entry0(jsFunction, thisObj, arguments_0){
  var initialEntry;
  initialEntry = entryDepth++ == 0;
  try {
    return jsFunction.apply(thisObj, arguments_0);
  }
   finally {
    initialEntry && $flushFinallyCommands(($clinit_12() , INSTANCE));
    --entryDepth;
  }
}

var entryDepth = 0, sNextHashId = 0;
function $clinit_12(){
  $clinit_12 = nullMethod;
  INSTANCE = $SchedulerImpl(new SchedulerImpl);
}

function $SchedulerImpl(this$static){
  $clinit_12();
  this$static.flusher = $SchedulerImpl$1(new SchedulerImpl$1, this$static);
  $SchedulerImpl$2(new SchedulerImpl$2, this$static);
  this$static.deferredCommands = [];
  this$static.incrementalCommands = [];
  this$static.finallyCommands = [];
  return this$static;
}

function $flushFinallyCommands(this$static){
  var oldFinally;
  oldFinally = this$static.finallyCommands;
  this$static.finallyCommands = [];
  runScheduledTasks(oldFinally, this$static.finallyCommands);
}

function $flushPostEventPumpCommands(this$static){
  var oldDeferred;
  oldDeferred = this$static.deferredCommands;
  this$static.deferredCommands = [];
  runScheduledTasks(oldDeferred, this$static.incrementalCommands);
  this$static.incrementalCommands = runRepeatingTasks(this$static.incrementalCommands);
}

function $isWorkQueued(this$static){
  return this$static.deferredCommands.length > 0 || this$static.incrementalCommands.length > 0;
}

function execute(cmd){
  return cmd.execute();
}

function runRepeatingTasks(tasks){
  var canceledSomeTasks, i, length_0, newTasks, start, t;
  canceledSomeTasks = false;
  length_0 = tasks.length;
  start = (new Date).getTime();
  while ((new Date).getTime() - start < 100) {
    for (i = 0; i < length_0; ++i) {
      t = tasks[i];
      if (!t) {
        continue;
      }
      if (!t[0].execute()) {
        tasks[i] = null;
        canceledSomeTasks = true;
      }
    }
  }
  if (canceledSomeTasks) {
    newTasks = [];
    for (i = 0; i < length_0; ++i) {
      if (!tasks[i]) {
        continue;
      }
      newTasks[newTasks.length] = tasks[i];
    }
    return newTasks;
  }
   else {
    return tasks;
  }
}

function runScheduledTasks(tasks, rescheduled){
  var $e0, i, j, t;
  for (i = 0 , j = tasks.length; i < j; ++i) {
    t = tasks[i];
    try {
      t[1]?t[0].execute() && (rescheduled[rescheduled.length] = t , undefined):t[0].nullMethod();
    }
     catch ($e0) {
      $e0 = caught($e0);
      if (!instanceOf($e0, 2))
        throw $e0;
    }
  }
}

function scheduleFixedDelayImpl(cmd, delayMs){
  $clinit_12();
  $wnd.setTimeout(function(){
    var ret = $entry(execute)(cmd);
    ret && $wnd.setTimeout(arguments.callee, delayMs);
  }
  , delayMs);
}

function SchedulerImpl(){
}

_ = SchedulerImpl.prototype = new Scheduler;
_.typeId$ = 0;
_.flushRunning = false;
_.shouldBeRunning = false;
var INSTANCE;
function $SchedulerImpl$1(this$static, this$0){
  this$static.this$0 = this$0;
  return this$static;
}

function execute_0(){
  this.this$0.flushRunning = true;
  $flushPostEventPumpCommands(this.this$0);
  this.this$0.flushRunning = false;
  return this.this$0.shouldBeRunning = $isWorkQueued(this.this$0);
}

function SchedulerImpl$1(){
}

_ = SchedulerImpl$1.prototype = new Object_0;
_.execute = execute_0;
_.typeId$ = 0;
_.this$0 = null;
function $SchedulerImpl$2(this$static, this$0){
  this$static.this$0 = this$0;
  return this$static;
}

function execute_1(){
  this.this$0.flushRunning && scheduleFixedDelayImpl(this.this$0.flusher, 1);
  return this.this$0.shouldBeRunning;
}

function SchedulerImpl$2(){
}

_ = SchedulerImpl$2.prototype = new Object_0;
_.execute = execute_1;
_.typeId$ = 0;
_.this$0 = null;
function extractNameFromToString(fnToString){
  var index, start, toReturn;
  toReturn = '';
  fnToString = $trim(fnToString);
  index = fnToString.indexOf('(');
  if (index != -1) {
    start = fnToString.indexOf('function') == 0?8:0;
    toReturn = $trim(fnToString.substr(start, index - start));
  }
  return toReturn.length > 0?toReturn:'anonymous';
}

function $collect(this$static){
  var seen = {};
  var toReturn = [];
  var callee = arguments.callee.caller.caller;
  while (callee) {
    var name_0 = this$static.extractName(callee.toString());
    toReturn.push(name_0);
    var keyName = ':' + name_0;
    var withThisName = seen[keyName];
    if (withThisName) {
      var i, j;
      for (i = 0 , j = withThisName.length; i < j; i++) {
        if (withThisName[i] === callee) {
          return toReturn;
        }
      }
    }
    (withThisName || (seen[keyName] = [])).push(callee);
    callee = callee.caller;
  }
  return toReturn;
}

function $createStackTrace(e){
  var i, j, stack, stackTrace;
  stack = (instanceOfJso(e.e)?dynamicCastJso(e.e):null , []);
  stackTrace = initDim(_3Ljava_lang_StackTraceElement_2_classLit, 39, 13, stack.length, 0);
  for (i = 0 , j = stackTrace.length; i < j; ++i) {
    stackTrace[i] = $StackTraceElement(new StackTraceElement, 'Unknown', stack[i], 'Unknown source', 0);
  }
  $setStackTrace(stackTrace);
}

function $fillInStackTrace(){
  var i, j, stack, stackTrace;
  stack = $collect(new StackTraceCreator$Collector);
  stackTrace = initDim(_3Ljava_lang_StackTraceElement_2_classLit, 39, 13, stack.length, 0);
  for (i = 0 , j = stackTrace.length; i < j; ++i) {
    stackTrace[i] = $StackTraceElement(new StackTraceElement, 'Unknown', stack[i], 'Unknown source', 0);
  }
  $setStackTrace(stackTrace);
}

function extractName(fnToString){
  return extractNameFromToString(fnToString);
}

function StackTraceCreator$Collector(){
}

_ = StackTraceCreator$Collector.prototype = new Object_0;
_.extractName = extractName;
_.typeId$ = 0;
function $append(a, x){
  a[a.explicitLength++] = x;
}

function $append_0(a, x){
  a[a.explicitLength++] = x == null?'null':x;
}

function $appendNonNull(a, x){
  a[a.explicitLength++] = x;
}

function $replace(a, start, end, toInsert){
  var s;
  s = $takeString(a);
  $appendNonNull(a, s.substr(0, start - 0));
  a[a.explicitLength++] = toInsert == null?'null':toInsert;
  $appendNonNull(a, s.substr(end, s.length - end));
}

function $takeString(a){
  var s = a.join('');
  a.length = a.explicitLength = 0;
  return s;
}

function $toString(a){
  var s;
  s = $takeString(a);
  a[a.explicitLength++] = s;
  return s;
}

function $clinit_24(){
  $clinit_24 = nullMethod;
  instance = ($clinit_24() , new LocaleInfo);
}

function $ensureNumberConstants(this$static){
  !this$static.numberConstants && (this$static.numberConstants = new NumberConstantsImpl_);
}

function $getDateTimeConstants(this$static){
  !this$static.dateTimeConstants && (this$static.dateTimeConstants = $DateTimeConstantsImpl_(new DateTimeConstantsImpl_));
  return this$static.dateTimeConstants;
}

function LocaleInfo(){
}

_ = LocaleInfo.prototype = new Object_0;
_.typeId$ = 0;
_.dateTimeConstants = null;
_.numberConstants = null;
var instance;
function $clinit_27(){
  $clinit_27 = nullMethod;
  $ensureNumberConstants(($clinit_24() , $clinit_24() , instance));
}

function $NumberFormat(this$static, numberConstants, pattern, cdata, userSuppliedPattern){
  $clinit_27();
  if (!cdata) {
    throw $IllegalArgumentException(new IllegalArgumentException, 'Unknown currency code');
  }
  this$static.numberConstants = numberConstants;
  this$static.pattern = pattern;
  this$static.currencyCode = cdata[0];
  this$static.currencySymbol = cdata[1];
  $parsePattern(this$static, this$static.pattern);
  if (!userSuppliedPattern && this$static.isCurrencyFormat) {
    this$static.minimumFractionDigits = cdata[2] & 7;
    this$static.maximumFractionDigits = this$static.minimumFractionDigits;
  }
  return this$static;
}

function $addExponentPart(this$static, exponent, result){
  var exponentDigits, i, len;
  $append_0(result.data, 'E');
  if (exponent < 0) {
    exponent = -exponent;
    $append_0(result.data, '-');
  }
  exponentDigits = '' + exponent;
  len = exponentDigits.length;
  for (i = len; i < this$static.minExponentDigits; ++i) {
    $append_0(result.data, '0');
  }
  for (i = 0; i < len; ++i) {
    $append_1(result, exponentDigits.charCodeAt(i));
  }
}

function $format(this$static, number){
  var isNegative, result;
  result = $StringBuffer(new StringBuffer);
  if (isNaN(number)) {
    $append_0(result.data, '\uFFFD');
    return $toString(result.data);
  }
  isNegative = number < 0 || number == 0 && 1 / number < 0;
  $append_3(result, isNegative?this$static.negativePrefix:this$static.positivePrefix);
  if (!isFinite(number)) {
    $append_0(result.data, '\u0221');
  }
   else {
    isNegative && (number = -number);
    number *= this$static.multiplier;
    this$static.useExponentialNotation?$subformatExponential(this$static, number, result):$subformatFixed(this$static, number, result, this$static.minimumIntegerDigits);
  }
  $append_3(result, isNegative?this$static.negativeSuffix:this$static.positiveSuffix);
  return $toString(result.data);
}

function $getDigit(ch){
  if (48 <= ch && ch <= 57) {
    return ch - 48;
  }
   else {
    return 48 <= ch && ch <= 57?ch - 48:-1;
  }
}

function $parse(this$static, text){
  var pos, result;
  pos = initValues(_3I_classLit, 34, -1, [0]);
  result = $parse_0(this$static, text, pos);
  if (pos[0] == 0 || pos[0] != text.length) {
    throw $NumberFormatException(new NumberFormatException, text);
  }
  return result;
}

function $parse_0(this$static, text, inOutPos){
  var gotNegative, gotNegativePrefix, gotNegativeSuffix, gotPositive, gotPositivePrefix, gotPositiveSuffix, ret, tempPos, valueOnly;
  ret = 0;
  gotPositivePrefix = $startsWith(text, this$static.positivePrefix, inOutPos[0]);
  gotNegativePrefix = $startsWith(text, this$static.negativePrefix, inOutPos[0]);
  gotPositiveSuffix = $endsWith(text, this$static.positiveSuffix);
  gotNegativeSuffix = $endsWith(text, this$static.negativeSuffix);
  gotPositive = gotPositivePrefix && gotPositiveSuffix;
  gotNegative = gotNegativePrefix && gotNegativeSuffix;
  if (gotPositive && gotNegative) {
    this$static.positivePrefix.length > this$static.negativePrefix.length?(gotNegative = false):this$static.positivePrefix.length < this$static.negativePrefix.length?(gotPositive = false):this$static.positiveSuffix.length > this$static.negativeSuffix.length?(gotNegative = false):this$static.positiveSuffix.length < this$static.negativeSuffix.length?(gotPositive = false):(gotNegative = false);
  }
   else if (!gotPositive && !gotNegative) {
    throw $NumberFormatException(new NumberFormatException, text + ' does not have either positive or negative affixes');
  }
  valueOnly = null;
  if (gotPositive) {
    inOutPos[0] += this$static.positivePrefix.length;
    valueOnly = $substring_0(text, inOutPos[0], text.length - this$static.positiveSuffix.length);
  }
   else {
    inOutPos[0] += this$static.negativePrefix.length;
    valueOnly = $substring_0(text, inOutPos[0], text.length - this$static.negativeSuffix.length);
  }
  if ($equals_1(valueOnly, '\u0221')) {
    inOutPos[0] += 1;
    ret = Infinity;
  }
   else if ($equals_1(valueOnly, '\uFFFD')) {
    inOutPos[0] += 1;
    ret = NaN;
  }
   else {
    tempPos = initValues(_3I_classLit, 34, -1, [0]);
    ret = $parseNumber(this$static, valueOnly, tempPos);
    inOutPos[0] += tempPos[0];
  }
  gotPositive?(inOutPos[0] += this$static.positiveSuffix.length):gotNegative && (inOutPos[0] += this$static.negativeSuffix.length);
  gotNegative && (ret = -ret);
  return ret;
}

function $parseAffix(this$static, pattern, start, affix, inNegativePattern){
  var ch, inQuote, len, pos;
  $replace_0(affix, 0, $toString(affix.data).length, '');
  inQuote = false;
  len = pattern.length;
  for (pos = start; pos < len; ++pos) {
    ch = pattern.charCodeAt(pos);
    if (ch == 39) {
      if (pos + 1 < len && pattern.charCodeAt(pos + 1) == 39) {
        ++pos;
        $append_0(affix.data, "'");
      }
       else {
        inQuote = !inQuote;
      }
      continue;
    }
    if (inQuote) {
      $appendNonNull(affix.data, String.fromCharCode(ch));
    }
     else {
      switch (ch) {
        case 35:
        case 48:
        case 44:
        case 46:
        case 59:
          return pos - start;
        case 164:
          this$static.isCurrencyFormat = true;
          if (pos + 1 < len && pattern.charCodeAt(pos + 1) == 164) {
            ++pos;
            $append_3(affix, this$static.currencyCode);
          }
           else {
            $append_3(affix, this$static.currencySymbol);
          }

          break;
        case 37:
          if (!inNegativePattern) {
            if (this$static.multiplier != 1) {
              throw $IllegalArgumentException(new IllegalArgumentException, 'Too many percent/per mille characters in pattern "' + pattern + '"');
            }
            this$static.multiplier = 100;
          }

          $append_0(affix.data, '%');
          break;
        case 8240:
          if (!inNegativePattern) {
            if (this$static.multiplier != 1) {
              throw $IllegalArgumentException(new IllegalArgumentException, 'Too many percent/per mille characters in pattern "' + pattern + '"');
            }
            this$static.multiplier = 1000;
          }

          $append_0(affix.data, '\u2030');
          break;
        case 45:
          $append_0(affix.data, '-');
          break;
        default:$appendNonNull(affix.data, String.fromCharCode(ch));
      }
    }
  }
  return len - start;
}

function $parseNumber(this$static, text, pos){
  var $e0, ch, decimal, digit, grouping, normalizedText, ret, sawDecimal, sawDigit, sawExponent, scale;
  sawDecimal = false;
  sawExponent = false;
  sawDigit = false;
  scale = 1;
  decimal = this$static.isCurrencyFormat?'.':this$static.numberConstants.decimalSeparator;
  grouping = this$static.isCurrencyFormat?',':this$static.numberConstants.groupingSeparator;
  normalizedText = $StringBuffer(new StringBuffer);
  for (; pos[0] < text.length; ++pos[0]) {
    ch = text.charCodeAt(pos[0]);
    digit = $getDigit(ch);
    if (digit >= 0 && digit <= 9) {
      $appendNonNull(normalizedText.data, String.fromCharCode(digit + 48 & 65535));
      sawDigit = true;
    }
     else if (ch == decimal.charCodeAt(0)) {
      if (sawDecimal || sawExponent) {
        break;
      }
      $appendNonNull(normalizedText.data, '.');
      sawDecimal = true;
    }
     else if (ch == grouping.charCodeAt(0)) {
      if (sawDecimal || sawExponent) {
        break;
      }
      continue;
    }
     else if (ch == 69) {
      if (sawExponent) {
        break;
      }
      $appendNonNull(normalizedText.data, 'E');
      sawExponent = true;
    }
     else if (ch == 43 || ch == 45) {
      $appendNonNull(normalizedText.data, String.fromCharCode(ch));
    }
     else if (ch == 37) {
      if (scale != 1) {
        break;
      }
      scale = 100;
      if (sawDigit) {
        ++pos[0];
        break;
      }
    }
     else if (ch == 8240) {
      if (scale != 1) {
        break;
      }
      scale = 1000;
      if (sawDigit) {
        ++pos[0];
        break;
      }
    }
     else {
      break;
    }
  }
  try {
    ret = __parseAndValidateDouble($toString(normalizedText.data));
  }
   catch ($e0) {
    $e0 = caught($e0);
    if (instanceOf($e0, 3)) {
      throw $NumberFormatException(new NumberFormatException, text);
    }
     else 
      throw $e0;
  }
  ret = ret / scale;
  return ret;
}

function $parsePattern(this$static, pattern){
  var affix, pos;
  pos = 0;
  affix = $StringBuffer(new StringBuffer);
  pos += $parseAffix(this$static, pattern, pos, affix, false);
  this$static.positivePrefix = $toString(affix.data);
  pos += $parseTrunk(this$static, pattern, pos, false);
  pos += $parseAffix(this$static, pattern, pos, affix, false);
  this$static.positiveSuffix = $toString(affix.data);
  if (pos < pattern.length && pattern.charCodeAt(pos) == 59) {
    ++pos;
    pos += $parseAffix(this$static, pattern, pos, affix, true);
    this$static.negativePrefix = $toString(affix.data);
    pos += $parseTrunk(this$static, pattern, pos, true);
    pos += $parseAffix(this$static, pattern, pos, affix, true);
    this$static.negativeSuffix = $toString(affix.data);
  }
   else {
    this$static.negativePrefix = '-' + this$static.positivePrefix;
    this$static.negativeSuffix = this$static.positiveSuffix;
  }
}

function $parseTrunk(this$static, pattern, start, ignorePattern){
  var ch, decimalPos, digitLeftCount, digitRightCount, effectiveDecimalPos, groupingCount, len, loop, n, pos, totalDigits, zeroDigitCount;
  decimalPos = -1;
  digitLeftCount = 0;
  zeroDigitCount = 0;
  digitRightCount = 0;
  groupingCount = -1;
  len = pattern.length;
  pos = start;
  loop = true;
  for (; pos < len && loop; ++pos) {
    ch = pattern.charCodeAt(pos);
    switch (ch) {
      case 35:
        zeroDigitCount > 0?++digitRightCount:++digitLeftCount;
        groupingCount >= 0 && decimalPos < 0 && ++groupingCount;
        break;
      case 48:
        if (digitRightCount > 0) {
          throw $IllegalArgumentException(new IllegalArgumentException, "Unexpected '0' in pattern \"" + pattern + '"');
        }

        ++zeroDigitCount;
        groupingCount >= 0 && decimalPos < 0 && ++groupingCount;
        break;
      case 44:
        groupingCount = 0;
        break;
      case 46:
        if (decimalPos >= 0) {
          throw $IllegalArgumentException(new IllegalArgumentException, 'Multiple decimal separators in pattern "' + pattern + '"');
        }

        decimalPos = digitLeftCount + zeroDigitCount + digitRightCount;
        break;
      case 69:
        if (!ignorePattern) {
          if (this$static.useExponentialNotation) {
            throw $IllegalArgumentException(new IllegalArgumentException, 'Multiple exponential symbols in pattern "' + pattern + '"');
          }
          this$static.useExponentialNotation = true;
          this$static.minExponentDigits = 0;
        }

        while (pos + 1 < len && pattern.charCodeAt(pos + 1) == 48) {
          ++pos;
          !ignorePattern && ++this$static.minExponentDigits;
        }

        if (!ignorePattern && digitLeftCount + zeroDigitCount < 1 || this$static.minExponentDigits < 1) {
          throw $IllegalArgumentException(new IllegalArgumentException, 'Malformed exponential pattern "' + pattern + '"');
        }

        loop = false;
        break;
      default:--pos;
        loop = false;
    }
  }
  if (zeroDigitCount == 0 && digitLeftCount > 0 && decimalPos >= 0) {
    n = decimalPos;
    n == 0 && ++n;
    digitRightCount = digitLeftCount - n;
    digitLeftCount = n - 1;
    zeroDigitCount = 1;
  }
  if (decimalPos < 0 && digitRightCount > 0 || decimalPos >= 0 && (decimalPos < digitLeftCount || decimalPos > digitLeftCount + zeroDigitCount) || groupingCount == 0) {
    throw $IllegalArgumentException(new IllegalArgumentException, 'Malformed pattern "' + pattern + '"');
  }
  if (ignorePattern) {
    return pos - start;
  }
  totalDigits = digitLeftCount + zeroDigitCount + digitRightCount;
  this$static.maximumFractionDigits = decimalPos >= 0?totalDigits - decimalPos:0;
  if (decimalPos >= 0) {
    this$static.minimumFractionDigits = digitLeftCount + zeroDigitCount - decimalPos;
    this$static.minimumFractionDigits < 0 && (this$static.minimumFractionDigits = 0);
  }
  effectiveDecimalPos = decimalPos >= 0?decimalPos:totalDigits;
  this$static.minimumIntegerDigits = effectiveDecimalPos - digitLeftCount;
  if (this$static.useExponentialNotation) {
    this$static.maximumIntegerDigits = digitLeftCount + this$static.minimumIntegerDigits;
    this$static.maximumFractionDigits == 0 && this$static.minimumIntegerDigits == 0 && (this$static.minimumIntegerDigits = 1);
  }
  this$static.groupingSize = groupingCount > 0?groupingCount:0;
  this$static.decimalSeparatorAlwaysShown = decimalPos == 0 || decimalPos == totalDigits;
  return pos - start;
}

function $subformatExponential(this$static, number, result){
  var exponent, i, minIntDigits;
  if (number == 0) {
    $subformatFixed(this$static, number, result, this$static.minimumIntegerDigits);
    $addExponentPart(this$static, 0, result);
    return;
  }
  exponent = round_int(floor(Math.log(number) / Math.log(10)));
  number /= Math.pow(10, exponent);
  minIntDigits = this$static.minimumIntegerDigits;
  if (this$static.maximumIntegerDigits > 1 && this$static.maximumIntegerDigits > this$static.minimumIntegerDigits) {
    while (exponent % this$static.maximumIntegerDigits != 0) {
      number *= 10;
      --exponent;
    }
    minIntDigits = 1;
  }
   else {
    if (this$static.minimumIntegerDigits < 1) {
      ++exponent;
      number /= 10;
    }
     else {
      for (i = 1; i < this$static.minimumIntegerDigits; ++i) {
        --exponent;
        number *= 10;
      }
    }
  }
  $subformatFixed(this$static, number, result, minIntDigits);
  $addExponentPart(this$static, exponent, result);
}

function $subformatFixed(this$static, number, result, minIntDigits){
  var decimal, decimalIndex, digitLen, exponentIndex, fixedString, fracLen, fracPart, fracValue, fractionPresent, grouping, i, intPart, intValue, len, power;
  power = Math.pow(10, this$static.maximumFractionDigits);
  fixedString = number.toFixed(this$static.maximumFractionDigits + 3);
  intValue = 0;
  fracValue = 0;
  exponentIndex = fixedString.indexOf(fromCodePoint(101));
  if (exponentIndex != -1) {
    intValue = Math.floor(number);
  }
   else {
    decimalIndex = fixedString.indexOf(fromCodePoint(46));
    len = fixedString.length;
    decimalIndex == -1 && (decimalIndex = len);
    decimalIndex > 0 && (intValue = __parseAndValidateDouble(fixedString.substr(0, decimalIndex - 0)));
    if (decimalIndex < len - 1) {
      fracValue = __parseAndValidateDouble(fixedString.substr(decimalIndex + 1, fixedString.length - (decimalIndex + 1)));
      fracValue = ~~((~~Math.max(Math.min(fracValue, 2147483647), -2147483648) + 500) / 1000);
      if (fracValue >= power) {
        fracValue -= power;
        ++intValue;
      }
    }
  }
  fractionPresent = this$static.minimumFractionDigits > 0 || fracValue > 0;
  intPart = '' + intValue;
  grouping = this$static.isCurrencyFormat?',':this$static.numberConstants.groupingSeparator;
  decimal = this$static.isCurrencyFormat?'.':this$static.numberConstants.decimalSeparator;
  digitLen = intPart.length;
  if (intValue > 0 || minIntDigits > 0) {
    for (i = digitLen; i < minIntDigits; ++i) {
      $append_0(result.data, '0');
    }
    for (i = 0; i < digitLen; ++i) {
      $append_1(result, intPart.charCodeAt(i));
      digitLen - i > 1 && this$static.groupingSize > 0 && (digitLen - i) % this$static.groupingSize == 1 && $append_0(result.data, grouping);
    }
  }
   else 
    !fractionPresent && $append_0(result.data, '0');
  (this$static.decimalSeparatorAlwaysShown || fractionPresent) && $append_0(result.data, decimal);
  fracPart = '' + Math.floor(fracValue + power + 0.5);
  fracLen = fracPart.length;
  while (fracPart.charCodeAt(fracLen - 1) == 48 && fracLen > this$static.minimumFractionDigits + 1) {
    --fracLen;
  }
  for (i = 1; i < fracLen; ++i) {
    $append_1(result, fracPart.charCodeAt(i));
  }
}

function NumberFormat(){
}

_ = NumberFormat.prototype = new Object_0;
_.typeId$ = 0;
_.currencyCode = null;
_.currencySymbol = null;
_.decimalSeparatorAlwaysShown = false;
_.groupingSize = 3;
_.isCurrencyFormat = false;
_.maximumFractionDigits = 3;
_.maximumIntegerDigits = 40;
_.minExponentDigits = 0;
_.minimumFractionDigits = 0;
_.minimumIntegerDigits = 1;
_.multiplier = 1;
_.negativePrefix = '-';
_.negativeSuffix = '';
_.numberConstants = null;
_.pattern = null;
_.positivePrefix = '';
_.positiveSuffix = '';
_.useExponentialNotation = false;
function $getRFCTimeZoneString(this$static){
  var data, offset;
  offset = -this$static.standardOffset;
  data = initValues(_3C_classLit, 32, -1, [43, 48, 48, 48, 48]);
  if (offset < 0) {
    data[0] = 45;
    offset = -offset;
  }
  data[1] += ~~(~~(offset / 60) / 10);
  data[2] += ~~(offset / 60) % 10;
  data[3] += ~~(offset % 60 / 10);
  data[4] += offset % 10;
  return String.fromCharCode.apply(null, data);
}

function composeGMTString(offset){
  var data;
  data = initValues(_3C_classLit, 32, -1, [71, 77, 84, 45, 48, 48, 58, 48, 48]);
  if (offset <= 0) {
    data[3] = 43;
    offset = -offset;
  }
  data[4] += ~~(~~(offset / 60) / 10);
  data[5] += ~~(offset / 60) % 10;
  data[7] += ~~(offset % 60 / 10);
  data[8] += offset % 10;
  return String.fromCharCode.apply(null, data);
}

function composePOSIXTimeZoneID(offset){
  var str;
  if (offset == 0) {
    return 'Etc/GMT';
  }
  if (offset < 0) {
    offset = -offset;
    str = 'Etc/GMT-';
  }
   else {
    str = 'Etc/GMT+';
  }
  return str + offsetDisplay(offset);
}

function composeUTCString(offset){
  var str;
  if (offset == 0) {
    return 'UTC';
  }
  if (offset < 0) {
    offset = -offset;
    str = 'UTC+';
  }
   else {
    str = 'UTC-';
  }
  return str + offsetDisplay(offset);
}

function createTimeZone(timeZoneOffsetInMinutes){
  var tz;
  tz = new TimeZone;
  tz.standardOffset = timeZoneOffsetInMinutes;
  tz.timezoneID = composePOSIXTimeZoneID(timeZoneOffsetInMinutes);
  tz.tzNames = initDim(_3Ljava_lang_String_2_classLit, 40, 1, 2, 0);
  tz.tzNames[0] = composeUTCString(timeZoneOffsetInMinutes);
  tz.tzNames[1] = composeUTCString(timeZoneOffsetInMinutes);
  return tz;
}

function offsetDisplay(offset){
  var hour, mins;
  hour = ~~(offset / 60);
  mins = offset % 60;
  if (mins == 0) {
    return '' + hour;
  }
  return '' + hour + ':' + mins;
}

function TimeZone(){
}

_ = TimeZone.prototype = new Object_0;
_.typeId$ = 0;
_.standardOffset = 0;
_.timezoneID = null;
_.tzNames = null;
function $DateTimeConstantsImpl_(this$static){
  this$static.cache = $HashMap(new HashMap);
  return this$static;
}

function $ampms(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'ampms'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['AM', 'PM']);
    $put(this$static.cache, 'ampms', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $eraNames(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'eraNames'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['Before Christ', 'Anno Domini']);
    $put(this$static.cache, 'eraNames', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $eras(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'eras'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['BC', 'AD']);
    $put(this$static.cache, 'eras', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $months(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'months'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']);
    $put(this$static.cache, 'months', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $narrowMonths(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'narrowMonths'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D']);
    $put(this$static.cache, 'narrowMonths', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $narrowWeekdays(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'narrowWeekdays'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['S', 'M', 'T', 'W', 'T', 'F', 'S']);
    $put(this$static.cache, 'narrowWeekdays', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $quarters(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'quarters'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['1st quarter', '2nd quarter', '3rd quarter', '4th quarter']);
    $put(this$static.cache, 'quarters', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $shortMonths(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'shortMonths'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
    $put(this$static.cache, 'shortMonths', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $shortQuarters(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'shortQuarters'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['Q1', 'Q2', 'Q3', 'Q4']);
    $put(this$static.cache, 'shortQuarters', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $shortWeekdays(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'shortWeekdays'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
    $put(this$static.cache, 'shortWeekdays', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $standaloneMonths(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'standaloneMonths'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December']);
    $put(this$static.cache, 'standaloneMonths', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $standaloneNarrowMonths(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'standaloneNarrowMonths'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['J', 'F', 'M', 'A', 'M', 'J', 'J', 'A', 'S', 'O', 'N', 'D']);
    $put(this$static.cache, 'standaloneNarrowMonths', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $standaloneNarrowWeekdays(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'standaloneNarrowWeekdays'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['S', 'M', 'T', 'W', 'T', 'F', 'S']);
    $put(this$static.cache, 'standaloneNarrowWeekdays', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $standaloneShortMonths(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'standaloneShortMonths'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
    $put(this$static.cache, 'standaloneShortMonths', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $standaloneShortWeekdays(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'standaloneShortWeekdays'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
    $put(this$static.cache, 'standaloneShortWeekdays', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $standaloneWeekdays(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'standaloneWeekdays'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']);
    $put(this$static.cache, 'standaloneWeekdays', writer);
    return writer;
  }
   else {
    return args;
  }
}

function $weekdays(this$static){
  var args, writer;
  args = dynamicCast($get_1(this$static.cache, 'weekdays'), 4);
  if (args == null) {
    writer = initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday']);
    $put(this$static.cache, 'weekdays', writer);
    return writer;
  }
   else {
    return args;
  }
}

function DateTimeConstantsImpl_(){
}

_ = DateTimeConstantsImpl_.prototype = new Object_0;
_.typeId$ = 0;
function NumberConstantsImpl_(){
}

_ = NumberConstantsImpl_.prototype = new Object_0;
_.typeId$ = 0;
function $clinit_36(){
  $clinit_36 = nullMethod;
  initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']);
  initValues(_3Ljava_lang_String_2_classLit, 40, 1, ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec']);
}

function $Date(this$static){
  $clinit_36();
  this$static.jsdate = new Date;
  return this$static;
}

function $Date_0(this$static, date){
  $clinit_36();
  this$static.jsdate = new Date(date[1] + date[0]);
  return this$static;
}

function $getTime0(this$static){
  this$static.checkJsDate();
  return this$static.jsdate.getTime();
}

function $setDate(this$static, date){
  this$static.checkJsDate();
  var hours = this$static.jsdate.getHours();
  this$static.jsdate.setDate(date);
  this$static.fixDaylightSavings(hours);
}

function $setTime0(this$static, time){
  this$static.checkJsDate();
  this$static.jsdate.setTime(time);
}

function checkJsDate(){
  (!this.jsdate || typeof this.jsdate != 'object') && throwJsDateException('' + this.jsdate);
}

function equals_1(obj){
  return obj != null && canCast(obj.typeId$, 15) && eq(fromDouble((this.checkJsDate() , this.jsdate.getTime())), fromDouble($getTime0(dynamicCast(obj, 15))));
}

function fixDaylightSavings(hours){
  if (this.jsdate.getHours() % 24 != hours % 24) {
    var d = new Date;
    d.setTime(this.jsdate.getTime());
    var noff = d.getTimezoneOffset();
    d.setDate(d.getDate() + 1);
    var loff = d.getTimezoneOffset();
    var timeDiff = noff - loff;
    if (timeDiff > 0) {
      var year = this.jsdate.getYear() + 1900;
      var month = this.jsdate.getMonth();
      var day = this.jsdate.getDate();
      var badHours = this.jsdate.getHours();
      var minute = this.jsdate.getMinutes();
      var second = this.jsdate.getSeconds();
      badHours + timeDiff / 60 >= 24 && day++;
      var newTime = new Date(year, month, day, hours + timeDiff / 60, minute + timeDiff % 60, second);
      this.jsdate.setTime(newTime.getTime());
    }
  }
}

function hashCode_2(){
  return lowBits_0(xor(fromDouble((this.checkJsDate() , this.jsdate.getTime())), shru(fromDouble((this.checkJsDate() , this.jsdate.getTime())), 32)));
}

function setHours(hours){
  this.checkJsDate();
  this.jsdate.setHours(hours);
  this.fixDaylightSavings(hours);
}

function setMinutes(minutes){
  this.checkJsDate();
  var hours = this.jsdate.getHours() + minutes / 60;
  this.jsdate.setMinutes(minutes);
  this.fixDaylightSavings(hours);
}

function setMonth(month){
  this.checkJsDate();
  var hours = this.jsdate.getHours();
  this.jsdate.setMonth(month);
  this.fixDaylightSavings(hours);
}

function setSeconds(seconds){
  this.checkJsDate();
  var hours = this.jsdate.getHours() + seconds / (60 * 60);
  this.jsdate.setSeconds(seconds);
  this.fixDaylightSavings(hours);
}

function setYear(year){
  this.checkJsDate();
  var hours = this.jsdate.getHours();
  this.jsdate.setFullYear(year + 1900);
  this.fixDaylightSavings(hours);
}

function throwJsDateException(val){
  throw $IllegalStateException(new IllegalStateException, 'jsdate is ' + val);
}

function Date_0(){
}

_ = Date_0.prototype = new Object_0;
_.checkJsDate = checkJsDate;
_.equals$ = equals_1;
_.fixDaylightSavings = fixDaylightSavings;
_.hashCode$ = hashCode_2;
_.setHours_0 = setHours;
_.setMinutes_0 = setMinutes;
_.setMonth_0 = setMonth;
_.setSeconds_0 = setSeconds;
_.setYear = setYear;
_.typeId$ = 7;
_.jsdate = null;
function $clinit_37(){
  $clinit_37 = nullMethod;
  $clinit_36();
}

function $DateRecord(this$static){
  $clinit_37();
  this$static.jsdate = new Date;
  this$static.era = -1;
  this$static.ambiguousYear = false;
  this$static.year = -2147483648;
  this$static.month = -1;
  this$static.dayOfMonth = -1;
  this$static.ampm = -1;
  this$static.hours = -1;
  this$static.minutes = -1;
  this$static.seconds = -1;
  this$static.milliseconds = -1;
  this$static.dayOfWeek = -1;
  this$static.tzOffset = -2147483648;
  return this$static;
}

function $calcDate(this$static, date, strict){
  var adjustment, defaultCenturyStart, offset, orgDayOfMonth, orgMonth;
  this$static.era == 0 && this$static.year > 0 && (this$static.year = -(this$static.year - 1));
  this$static.year > -2147483648 && date.setYear(this$static.year - 1900);
  orgDayOfMonth = (date.checkJsDate() , date.jsdate.getDate());
  $setDate(date, 1);
  this$static.month >= 0 && date.setMonth_0(this$static.month);
  this$static.dayOfMonth >= 0?$setDate(date, this$static.dayOfMonth):$setDate(date, orgDayOfMonth);
  this$static.hours < 0 && (this$static.hours = (date.checkJsDate() , date.jsdate.getHours()));
  this$static.ampm > 0 && this$static.hours < 12 && (this$static.hours += 12);
  date.setHours_0(this$static.hours);
  this$static.minutes >= 0 && date.setMinutes_0(this$static.minutes);
  this$static.seconds >= 0 && date.setSeconds_0(this$static.seconds);
  this$static.milliseconds >= 0 && $setTime0(date, toDouble(add(mul(div(fromDouble((date.checkJsDate() , date.jsdate.getTime())), P3e8_longLit), P3e8_longLit), fromInt(this$static.milliseconds))));
  if (strict) {
    if (this$static.year > -2147483648 && this$static.year - 1900 != (date.checkJsDate() , date.jsdate.getFullYear() - 1900)) {
      return false;
    }
    if (this$static.month >= 0 && this$static.month != (date.checkJsDate() , date.jsdate.getMonth())) {
      return false;
    }
    if (this$static.dayOfMonth >= 0 && this$static.dayOfMonth != (date.checkJsDate() , date.jsdate.getDate())) {
      return false;
    }
    if (this$static.hours >= 24) {
      return false;
    }
    if (this$static.minutes >= 60) {
      return false;
    }
    if (this$static.seconds >= 60) {
      return false;
    }
    if (this$static.milliseconds >= 1000) {
      return false;
    }
  }
  if (this$static.tzOffset > -2147483648) {
    offset = (date.checkJsDate() , date.jsdate.getTimezoneOffset());
    $setTime0(date, toDouble(add(fromDouble((date.checkJsDate() , date.jsdate.getTime())), fromInt((this$static.tzOffset - offset) * 60 * 1000))));
  }
  if (this$static.ambiguousYear) {
    defaultCenturyStart = $Date(new Date_0);
    defaultCenturyStart.setYear((defaultCenturyStart.checkJsDate() , defaultCenturyStart.jsdate.getFullYear() - 1900) - 80);
    compare(fromDouble((date.checkJsDate() , date.jsdate.getTime())), fromDouble((defaultCenturyStart.checkJsDate() , defaultCenturyStart.jsdate.getTime()))) < 0 && date.setYear((defaultCenturyStart.checkJsDate() , defaultCenturyStart.jsdate.getFullYear() - 1900) + 100);
  }
  if (this$static.dayOfWeek >= 0) {
    if (this$static.dayOfMonth == -1) {
      adjustment = (7 + this$static.dayOfWeek - (date.checkJsDate() , date.jsdate.getDay())) % 7;
      adjustment > 3 && (adjustment -= 7);
      orgMonth = (date.checkJsDate() , date.jsdate.getMonth());
      $setDate(date, (date.checkJsDate() , date.jsdate.getDate()) + adjustment);
      (date.checkJsDate() , date.jsdate.getMonth()) != orgMonth && $setDate(date, (date.checkJsDate() , date.jsdate.getDate()) + (adjustment > 0?-7:7));
    }
     else {
      if ((date.checkJsDate() , date.jsdate.getDay()) != this$static.dayOfWeek) {
        return false;
      }
    }
  }
  return true;
}

function setHours_0(hours){
  this.hours = hours;
}

function setMinutes_0(minutes){
  this.minutes = minutes;
}

function setMonth_0(month){
  this.month = month;
}

function setSeconds_0(seconds){
  this.seconds = seconds;
}

function setYear_0(value){
  this.year = value;
}

function DateRecord(){
}

_ = DateRecord.prototype = new Date_0;
_.setHours_0 = setHours_0;
_.setMinutes_0 = setMinutes_0;
_.setMonth_0 = setMonth_0;
_.setSeconds_0 = setSeconds_0;
_.setYear = setYear_0;
_.typeId$ = 8;
_.ambiguousYear = false;
_.ampm = 0;
_.dayOfMonth = 0;
_.dayOfWeek = 0;
_.era = 0;
_.hours = 0;
_.milliseconds = 0;
_.minutes = 0;
_.month = 0;
_.seconds = 0;
_.tzOffset = 0;
_.year = 0;
function createFromSeed(seedType, length_0){
  var array = new Array(length_0);
  if (seedType > 0) {
    var value = [null, 0, false, [0, 0]][seedType];
    for (var i = 0; i < length_0; ++i) {
      array[i] = value;
    }
  }
  return array;
}

function initDim(arrayClass, typeId, queryId, length_0, seedType){
  var result;
  result = createFromSeed(seedType, length_0);
  $clinit_39();
  wrapArray(result, expandoNames_0, expandoValues_0);
  result.typeId$ = typeId;
  result.queryId$ = queryId;
  return result;
}

function initValues(arrayClass, typeId, queryId, array){
  $clinit_39();
  wrapArray(array, expandoNames_0, expandoValues_0);
  array.typeId$ = typeId;
  array.queryId$ = queryId;
  return array;
}

function setCheck(array, index, value){
  if (value != null) {
    if (array.queryId$ > 0 && !canCastUnsafe(value.typeId$, array.queryId$)) {
      throw $ArrayStoreException(new ArrayStoreException);
    }
    if (array.queryId$ < 0 && (value.typeMarker$ == nullMethod || value.typeId$ == 2)) {
      throw $ArrayStoreException(new ArrayStoreException);
    }
  }
  return array[index] = value;
}

function Array_0(){
}

_ = Array_0.prototype = new Object_0;
_.typeId$ = 0;
_.length = 0;
_.queryId$ = 0;
function $clinit_39(){
  $clinit_39 = nullMethod;
  expandoNames_0 = [];
  expandoValues_0 = [];
  initExpandos(new Array_0, expandoNames_0, expandoValues_0);
}

function initExpandos(protoType, expandoNames, expandoValues){
  var i = 0, value;
  for (var name_0 in protoType) {
    if (value = protoType[name_0]) {
      expandoNames[i] = name_0;
      expandoValues[i] = value;
      ++i;
    }
  }
}

function wrapArray(array, expandoNames, expandoValues){
  $clinit_39();
  for (var i = 0, c = expandoNames.length; i < c; ++i) {
    array[expandoNames[i]] = expandoValues[i];
  }
}

var expandoNames_0, expandoValues_0;
function canCast(srcId, dstId){
  return srcId && !!typeIdArray[srcId][dstId];
}

function canCastUnsafe(srcId, dstId){
  return srcId && typeIdArray[srcId][dstId];
}

function dynamicCast(src, dstId){
  if (src != null && !canCastUnsafe(src.typeId$, dstId)) {
    throw $ClassCastException(new ClassCastException);
  }
  return src;
}

function dynamicCastJso(src){
  if (src != null && (src.typeMarker$ == nullMethod || src.typeId$ == 2)) {
    throw $ClassCastException(new ClassCastException);
  }
  return src;
}

function instanceOf(src, dstId){
  return src != null && canCast(src.typeId$, dstId);
}

function instanceOfJso(src){
  return src != null && src.typeMarker$ != nullMethod && src.typeId$ != 2;
}

function round_int(x){
  return ~~Math.max(Math.min(x, 2147483647), -2147483648);
}

var typeIdArray = [{}, {}, {1:1, 10:1, 11:1, 12:1}, {5:1, 10:1}, {5:1, 10:1}, {2:1, 5:1, 10:1}, {2:1, 5:1, 10:1}, {10:1, 12:1, 15:1}, {10:1, 12:1, 15:1}, {2:1, 5:1, 10:1}, {2:1, 5:1, 10:1}, {5:1, 10:1}, {5:1, 10:1}, {2:1, 5:1, 10:1}, {2:1, 5:1, 10:1}, {2:1, 5:1, 10:1}, {2:1, 5:1, 10:1}, {2:1, 5:1, 10:1}, {2:1, 3:1, 5:1, 10:1}, {10:1, 13:1}, {11:1}, {2:1, 5:1, 10:1}, {9:1}, {6:1}, {6:1}, {6:1}, {7:1, 10:1}, {8:1, 10:1}, {6:1}, {2:1, 5:1, 10:1}, {16:1}, {17:1}, {10:1}, {10:1, 14:1}, {10:1}, {10:1}, {10:1}, {10:1}, {10:1}, {10:1}, {4:1, 10:1}, {10:1}];
function init(){
  !!$stats && $stats({moduleName:$moduleName, sessionId:$sessionId, subSystem:'startup', evtGroup:'moduleStartup', millis:(new Date).getTime(), type:'onModuleLoadStart', className:'tersus.gwt.client.Util'});
  $clinit_99();
  $wnd.gwtFormatNumber = formatNumber;
  $wnd.gwtParseNumber = parseNumber;
  $wnd.gwtFormatDateAndTime = formatDateAndTime;
  $wnd.gwtParseDateAndTime = parseDateAndTime;
}

function caught(e){
  if (e != null && canCast(e.typeId$, 5)) {
    return e;
  }
  return $JavaScriptException(new JavaScriptException, e);
}

function add(a, b){
  var newHigh, newLow;
  newHigh = a[1] + b[1];
  newLow = a[0] + b[0];
  return create(newLow, newHigh);
}

function addTimes(accum, a, b){
  if (a == 0) {
    return accum;
  }
  if (b == 0) {
    return accum;
  }
  return add(accum, create(a * b, 0));
}

function compare(a, b){
  var nega, negb;
  if (a[0] == b[0] && a[1] == b[1]) {
    return 0;
  }
  nega = a[1] < 0;
  negb = b[1] < 0;
  if (nega && !negb) {
    return -1;
  }
  if (!nega && negb) {
    return 1;
  }
  if (sub(a, b)[1] < 0) {
    return -1;
  }
   else {
    return 1;
  }
}

function create(valueLow, valueHigh){
  var diffHigh, diffLow;
  valueHigh %= 1.8446744073709552E19;
  valueLow %= 1.8446744073709552E19;
  diffHigh = valueHigh % 4294967296;
  diffLow = Math.floor(valueLow / 4294967296) * 4294967296;
  valueHigh = valueHigh - diffHigh + diffLow;
  valueLow = valueLow - diffLow + diffHigh;
  while (valueLow < 0) {
    valueLow += 4294967296;
    valueHigh -= 4294967296;
  }
  while (valueLow > 4294967295) {
    valueLow -= 4294967296;
    valueHigh += 4294967296;
  }
  valueHigh = valueHigh % 1.8446744073709552E19;
  while (valueHigh > 9223372032559808512) {
    valueHigh -= 1.8446744073709552E19;
  }
  while (valueHigh < -9223372036854775808) {
    valueHigh += 1.8446744073709552E19;
  }
  return [valueLow, valueHigh];
}

function div(a, b){
  var approx, deltaRem, deltaResult, halfa, rem, result;
  if (b[0] == 0 && b[1] == 0) {
    throw $ArithmeticException(new ArithmeticException, '/ by zero');
  }
  if (a[0] == 0 && a[1] == 0) {
    return $clinit_46() , ZERO;
  }
  if (eq(a, ($clinit_46() , MIN_VALUE))) {
    if (eq(b, ONE) || eq(b, NEG_ONE)) {
      return MIN_VALUE;
    }
    halfa = shr(a, 1);
    approx = shl(div(halfa, b), 1);
    rem = sub(a, mul(b, approx));
    return add(approx, div(rem, b));
  }
  if (eq(b, MIN_VALUE)) {
    return ZERO;
  }
  if (a[1] < 0) {
    if (b[1] < 0) {
      return div(neg(a), neg(b));
    }
     else {
      return neg(div(neg(a), b));
    }
  }
  if (b[1] < 0) {
    return neg(div(a, neg(b)));
  }
  result = ZERO;
  rem = a;
  while (compare(rem, b) >= 0) {
    deltaResult = fromDouble(Math.floor(toDoubleRoundDown(rem) / toDoubleRoundUp(b)));
    deltaResult[0] == 0 && deltaResult[1] == 0 && (deltaResult = ONE);
    deltaRem = mul(deltaResult, b);
    result = add(result, deltaResult);
    rem = sub(rem, deltaRem);
  }
  return result;
}

function eq(a, b){
  return a[0] == b[0] && a[1] == b[1];
}

function fromDouble(value){
  if (isNaN(value)) {
    return $clinit_46() , ZERO;
  }
  if (value < -9223372036854775808) {
    return $clinit_46() , MIN_VALUE;
  }
  if (value >= 9223372036854775807) {
    return $clinit_46() , MAX_VALUE;
  }
  if (value > 0) {
    return create(Math.floor(value), 0);
  }
   else {
    return create(Math.ceil(value), 0);
  }
}

function fromInt(value){
  var rebase, result;
  if (value > -129 && value < 128) {
    rebase = value + 128;
    result = ($clinit_45() , boxedValues)[rebase];
    result == null && (result = boxedValues[rebase] = internalFromInt(value));
    return result;
  }
  return internalFromInt(value);
}

function internalFromInt(value){
  if (value >= 0) {
    return [value, 0];
  }
   else {
    return [value + 4294967296, -4294967296];
  }
}

function lowBits_0(a){
  if (a[0] >= 2147483648) {
    return ~~Math.max(Math.min(a[0] - 4294967296, 2147483647), -2147483648);
  }
   else {
    return ~~Math.max(Math.min(a[0], 2147483647), -2147483648);
  }
}

function makeFromBits(highBits, lowBits){
  var high, low;
  high = highBits * 4294967296;
  low = lowBits;
  lowBits < 0 && (low += 4294967296);
  return [low, high];
}

function mod(a, b){
  return sub(a, mul(div(a, b), b));
}

function mul(a, b){
  var a1, a2, a3, a4, b1, b2, b3, b4, res;
  if (a[0] == 0 && a[1] == 0) {
    return $clinit_46() , ZERO;
  }
  if (b[0] == 0 && b[1] == 0) {
    return $clinit_46() , ZERO;
  }
  if (eq(a, ($clinit_46() , MIN_VALUE))) {
    return multByMinValue(b);
  }
  if (eq(b, MIN_VALUE)) {
    return multByMinValue(a);
  }
  if (a[1] < 0) {
    if (b[1] < 0) {
      return mul(neg(a), neg(b));
    }
     else {
      return neg(mul(neg(a), b));
    }
  }
  if (b[1] < 0) {
    return neg(mul(a, neg(b)));
  }
  if (compare(a, TWO_PWR_24) < 0 && compare(b, TWO_PWR_24) < 0) {
    return create((a[1] + a[0]) * (b[1] + b[0]), 0);
  }
  a3 = a[1] % 281474976710656;
  a4 = a[1] - a3;
  a1 = a[0] % 65536;
  a2 = a[0] - a1;
  b3 = b[1] % 281474976710656;
  b4 = b[1] - b3;
  b1 = b[0] % 65536;
  b2 = b[0] - b1;
  res = ZERO;
  res = addTimes(res, a4, b1);
  res = addTimes(res, a3, b2);
  res = addTimes(res, a3, b1);
  res = addTimes(res, a2, b3);
  res = addTimes(res, a2, b2);
  res = addTimes(res, a2, b1);
  res = addTimes(res, a1, b4);
  res = addTimes(res, a1, b3);
  res = addTimes(res, a1, b2);
  res = addTimes(res, a1, b1);
  return res;
}

function multByMinValue(a){
  if ((lowBits_0(a) & 1) == 1) {
    return $clinit_46() , MIN_VALUE;
  }
   else {
    return $clinit_46() , ZERO;
  }
}

function neg(a){
  var newHigh, newLow;
  if (eq(a, ($clinit_46() , MIN_VALUE))) {
    return MIN_VALUE;
  }
  newHigh = -a[1];
  newLow = -a[0];
  if (newLow > 4294967295) {
    newLow -= 4294967296;
    newHigh += 4294967296;
  }
  if (newLow < 0) {
    newLow += 4294967296;
    newHigh -= 4294967296;
  }
  return [newLow, newHigh];
}

function pwrAsDouble(n){
  if (n <= 30) {
    return 1 << n;
  }
   else {
    return pwrAsDouble(30) * pwrAsDouble(n - 30);
  }
}

function shl(a, n){
  var diff, newHigh, newLow, twoToN;
  n &= 63;
  if (eq(a, ($clinit_46() , MIN_VALUE))) {
    if (n == 0) {
      return a;
    }
     else {
      return ZERO;
    }
  }
  if (a[1] < 0) {
    return neg(shl(neg(a), n));
  }
  twoToN = pwrAsDouble(n);
  newHigh = a[1] * twoToN % 1.8446744073709552E19;
  newLow = a[0] * twoToN;
  diff = newLow - newLow % 4294967296;
  newHigh += diff;
  newLow -= diff;
  newHigh >= 9223372036854775807 && (newHigh -= 1.8446744073709552E19);
  return [newLow, newHigh];
}

function shr(a, n){
  var newHigh, newLow, shiftFact;
  n &= 63;
  shiftFact = pwrAsDouble(n);
  newHigh = Math.floor(a[1] / shiftFact);
  newLow = Math.floor(a[0] / shiftFact);
  return create(newLow, newHigh);
}

function shru(a, n){
  var sr;
  n &= 63;
  sr = shr(a, n);
  a[1] < 0 && (sr = add(sr, shl(($clinit_46() , TWO), 63 - n)));
  return sr;
}

function sub(a, b){
  var newHigh, newLow;
  newHigh = a[1] - b[1];
  newLow = a[0] - b[0];
  return create(newLow, newHigh);
}

function toDouble(a){
  return a[1] + a[0];
}

function toDoubleRoundDown(a){
  var diff, magnitute, toSubtract;
  magnitute = round_int(Math.log(a[1]) / ($clinit_46() , LN_2));
  if (magnitute <= 48) {
    return a[1] + a[0];
  }
   else {
    diff = magnitute - 48;
    toSubtract = (1 << diff) - 1;
    return a[1] + (a[0] - toSubtract);
  }
}

function toDoubleRoundUp(a){
  var diff, magnitute, toAdd;
  magnitute = round_int(Math.log(a[1]) / ($clinit_46() , LN_2));
  if (magnitute <= 48) {
    return a[1] + a[0];
  }
   else {
    diff = magnitute - 48;
    toAdd = (1 << diff) - 1;
    return a[1] + (a[0] + toAdd);
  }
}

function xor(a, b){
  return makeFromBits(~~Math.max(Math.min(a[1] / 4294967296, 2147483647), -2147483648) ^ ~~Math.max(Math.min(b[1] / 4294967296, 2147483647), -2147483648), lowBits_0(a) ^ lowBits_0(b));
}

function $clinit_45(){
  $clinit_45 = nullMethod;
  boxedValues = initDim(_3_3D_classLit, 41, 14, 256, 0);
}

var boxedValues;
function $clinit_46(){
  $clinit_46 = nullMethod;
  LN_2 = Math.log(2);
  MAX_VALUE = P7fffffffffffffff_longLit;
  MIN_VALUE = N8000000000000000_longLit;
  NEG_ONE = fromInt(-1);
  ONE = fromInt(1);
  TWO = fromInt(2);
  TWO_PWR_24 = P1000000_longLit;
  ZERO = fromInt(0);
}

var LN_2, MAX_VALUE, MIN_VALUE, NEG_ONE, ONE, TWO, TWO_PWR_24, ZERO;
function $ArithmeticException(this$static, explanation){
  $fillInStackTrace();
  return this$static;
}

function ArithmeticException(){
}

_ = ArithmeticException.prototype = new RuntimeException;
_.typeId$ = 9;
function $ArrayStoreException(this$static){
  $fillInStackTrace();
  return this$static;
}

function ArrayStoreException(){
}

_ = ArrayStoreException.prototype = new RuntimeException;
_.typeId$ = 10;
function Class(){
}

_ = Class.prototype = new Object_0;
_.typeId$ = 0;
function $ClassCastException(this$static){
  $fillInStackTrace();
  return this$static;
}

function ClassCastException(){
}

_ = ClassCastException.prototype = new RuntimeException;
_.typeId$ = 13;
function __parseAndValidateDouble(s){
  var toReturn;
  toReturn = __parseDouble(s);
  if (isNaN(toReturn)) {
    throw $NumberFormatException(new NumberFormatException, 'For input string: "' + s + '"');
  }
  return toReturn;
}

function __parseDouble(str){
  var floatRegex = floatRegex_0;
  !floatRegex && (floatRegex = floatRegex_0 = /^\s*[+-]?\d*\.?\d*([eE][+-]?\d+)?\s*$/i);
  if (floatRegex.test(str)) {
    return parseFloat(str);
  }
   else {
    return Number.NaN;
  }
}

var floatRegex_0 = null;
function $IllegalArgumentException(this$static, message){
  $fillInStackTrace();
  return this$static;
}

function IllegalArgumentException(){
}

_ = IllegalArgumentException.prototype = new RuntimeException;
_.typeId$ = 14;
function $IllegalStateException(this$static, s){
  $fillInStackTrace();
  return this$static;
}

function IllegalStateException(){
}

_ = IllegalStateException.prototype = new RuntimeException;
_.typeId$ = 15;
function $IndexOutOfBoundsException(this$static, message){
  $fillInStackTrace();
  return this$static;
}

function IndexOutOfBoundsException(){
}

_ = IndexOutOfBoundsException.prototype = new RuntimeException;
_.typeId$ = 16;
function floor(x){
  return Math.floor(x);
}

function $NullPointerException(this$static){
  $fillInStackTrace();
  return this$static;
}

function NullPointerException(){
}

_ = NullPointerException.prototype = new RuntimeException;
_.typeId$ = 17;
function $NumberFormatException(this$static, message){
  $fillInStackTrace();
  return this$static;
}

function NumberFormatException(){
}

_ = NumberFormatException.prototype = new IllegalArgumentException;
_.typeId$ = 18;
function $StackTraceElement(this$static, className, methodName, fileName, lineNumber){
  return this$static;
}

function StackTraceElement(){
}

_ = StackTraceElement.prototype = new Object_0;
_.typeId$ = 19;
function $endsWith(this$static, suffix){
  return this$static.lastIndexOf(suffix) != -1 && this$static.lastIndexOf(suffix) == this$static.length - suffix.length;
}

function $equals_1(this$static, other){
  if (!(other != null && canCast(other.typeId$, 1))) {
    return false;
  }
  return String(this$static) == other;
}

function $startsWith(this$static, prefix, toffset){
  if (toffset < 0 || toffset >= this$static.length) {
    return false;
  }
   else {
    return this$static.indexOf(prefix, toffset) == toffset;
  }
}

function $substring_0(this$static, beginIndex, endIndex){
  return this$static.substr(beginIndex, endIndex - beginIndex);
}

function $trim(this$static){
  if (this$static.length == 0 || this$static[0] > ' ' && this$static[this$static.length - 1] > ' ') {
    return this$static;
  }
  var r1 = this$static.replace(/^(\s*)/, '');
  var r2 = r1.replace(/\s*$/, '');
  return r2;
}

function equals_2(other){
  return $equals_1(this, other);
}

function fromCodePoint(codePoint){
  var hiSurrogate, loSurrogate;
  if (codePoint >= 65536) {
    hiSurrogate = 55296 + (codePoint - 65536 >> 10 & 1023) & 65535;
    loSurrogate = 56320 + (codePoint - 65536 & 1023) & 65535;
    return String.fromCharCode(hiSurrogate) + String.fromCharCode(loSurrogate);
  }
   else {
    return String.fromCharCode(codePoint & 65535);
  }
}

function hashCode_3(){
  return getHashCode_0(this);
}

_ = String.prototype;
_.equals$ = equals_2;
_.hashCode$ = hashCode_3;
_.typeId$ = 2;
function $clinit_69(){
  $clinit_69 = nullMethod;
  back = {};
  front = {};
}

function compute(str){
  var hashCode, i, n, nBatch;
  hashCode = 0;
  n = str.length;
  nBatch = n - 4;
  i = 0;
  while (i < nBatch) {
    hashCode = str.charCodeAt(i + 3) + 31 * (str.charCodeAt(i + 2) + 31 * (str.charCodeAt(i + 1) + 31 * (str.charCodeAt(i) + 31 * hashCode))) | 0;
    i += 4;
  }
  while (i < n) {
    hashCode = hashCode * 31 + str.charCodeAt(i++);
  }
  return hashCode | 0;
}

function getHashCode_0(str){
  $clinit_69();
  var key = ':' + str;
  var result = front[key];
  if (result != null) {
    return result;
  }
  result = back[key];
  result == null && (result = compute(str));
  increment();
  return front[key] = result;
}

function increment(){
  if (count_0 == 256) {
    back = front;
    front = {};
    count_0 = 0;
  }
  ++count_0;
}

var back, count_0 = 0, front;
function $StringBuffer(this$static){
  var array;
  this$static.data = (array = [] , array.explicitLength = 0 , array);
  return this$static;
}

function $StringBuffer_0(this$static){
  var array;
  this$static.data = (array = [] , array.explicitLength = 0 , array);
  return this$static;
}

function $append_1(this$static, x){
  $appendNonNull(this$static.data, String.fromCharCode(x));
  return this$static;
}

function $append_2(this$static, x){
  $appendNonNull(this$static.data, String.fromCharCode.apply(null, x));
  return this$static;
}

function $append_3(this$static, x){
  $append_0(this$static.data, x);
  return this$static;
}

function $replace_0(this$static, start, end, toInsert){
  $replace(this$static.data, start, end, toInsert);
  return this$static;
}

function StringBuffer(){
}

_ = StringBuffer.prototype = new Object_0;
_.typeId$ = 20;
function $UnsupportedOperationException(this$static, message){
  $fillInStackTrace();
  return this$static;
}

function UnsupportedOperationException(){
}

_ = UnsupportedOperationException.prototype = new RuntimeException;
_.typeId$ = 21;
function $advanceToFind(iter, o){
  var t;
  while (iter.hasNext()) {
    t = iter.next();
    if (o == null?t == null:equals__devirtual$(o, t)) {
      return iter;
    }
  }
  return null;
}

function add_0(o){
  throw $UnsupportedOperationException(new UnsupportedOperationException, 'Add not supported on this collection');
}

function contains(o){
  var iter;
  iter = $advanceToFind(this.iterator(), o);
  return !!iter;
}

function AbstractCollection(){
}

_ = AbstractCollection.prototype = new Object_0;
_.add = add_0;
_.contains = contains;
_.typeId$ = 0;
function equals_3(obj){
  var entry, entry$iterator, otherKey, otherMap, otherValue;
  if ((obj == null?null:obj) === this) {
    return true;
  }
  if (!(obj != null && canCast(obj.typeId$, 8))) {
    return false;
  }
  otherMap = dynamicCast(obj, 8);
  if (dynamicCast(this, 8).size != otherMap.size) {
    return false;
  }
  for (entry$iterator = $AbstractHashMap$EntrySetIterator(new AbstractHashMap$EntrySetIterator, $AbstractHashMap$EntrySet(new AbstractHashMap$EntrySet, otherMap).this$0); $hasNext_0(entry$iterator.iter);) {
    entry = dynamicCast($next_0(entry$iterator.iter), 6);
    otherKey = entry.getKey();
    otherValue = entry.getValue();
    if (!(otherKey == null?dynamicCast(this, 8).nullSlotLive:otherKey != null && canCast(otherKey.typeId$, 1)?$hasStringValue(dynamicCast(this, 8), dynamicCast(otherKey, 1)):$hasHashValue(dynamicCast(this, 8), otherKey, ~~hashCode__devirtual$(otherKey)))) {
      return false;
    }
    if (!equalsWithNullCheck(otherValue, otherKey == null?dynamicCast(this, 8).nullSlot:otherKey != null && canCast(otherKey.typeId$, 1)?dynamicCast(this, 8).stringMap[':' + dynamicCast(otherKey, 1)]:$getHashValue(dynamicCast(this, 8), otherKey, ~~hashCode__devirtual$(otherKey)))) {
      return false;
    }
  }
  return true;
}

function hashCode_4(){
  var entry, entry$iterator, hashCode;
  hashCode = 0;
  for (entry$iterator = $AbstractHashMap$EntrySetIterator(new AbstractHashMap$EntrySetIterator, $AbstractHashMap$EntrySet(new AbstractHashMap$EntrySet, dynamicCast(this, 8)).this$0); $hasNext_0(entry$iterator.iter);) {
    entry = dynamicCast($next_0(entry$iterator.iter), 6);
    hashCode += entry.hashCode$();
    hashCode = ~~hashCode;
  }
  return hashCode;
}

function AbstractMap(){
}

_ = AbstractMap.prototype = new Object_0;
_.equals$ = equals_3;
_.hashCode$ = hashCode_4;
_.typeId$ = 0;
function $addAllHashEntries(this$static, dest){
  var hashCodeMap = this$static.hashCodeMap;
  for (var hashCode in hashCodeMap) {
    if (hashCode == parseInt(hashCode)) {
      var array = hashCodeMap[hashCode];
      for (var i = 0, c = array.length; i < c; ++i) {
        dest.add(array[i]);
      }
    }
  }
}

function $addAllStringEntries(this$static, dest){
  var stringMap = this$static.stringMap;
  for (var key in stringMap) {
    if (key.charCodeAt(0) == 58) {
      var entry = new_$(this$static, key.substring(1));
      dest.add(entry);
    }
  }
}

function $containsKey(this$static, key){
  return key == null?this$static.nullSlotLive:key != null && canCast(key.typeId$, 1)?$hasStringValue(this$static, dynamicCast(key, 1)):$hasHashValue(this$static, key, ~~hashCode__devirtual$(key));
}

function $get_1(this$static, key){
  return key == null?this$static.nullSlot:key != null && canCast(key.typeId$, 1)?this$static.stringMap[':' + dynamicCast(key, 1)]:$getHashValue(this$static, key, ~~hashCode__devirtual$(key));
}

function $getHashValue(this$static, key, hashCode){
  var array = this$static.hashCodeMap[hashCode];
  if (array) {
    for (var i = 0, c = array.length; i < c; ++i) {
      var entry = array[i];
      var entryKey = entry.getKey();
      if (this$static.equalsBridge(key, entryKey)) {
        return entry.getValue();
      }
    }
  }
  return null;
}

function $hasHashValue(this$static, key, hashCode){
  var array = this$static.hashCodeMap[hashCode];
  if (array) {
    for (var i = 0, c = array.length; i < c; ++i) {
      var entry = array[i];
      var entryKey = entry.getKey();
      if (this$static.equalsBridge(key, entryKey)) {
        return true;
      }
    }
  }
  return false;
}

function $hasStringValue(this$static, key){
  return ':' + key in this$static.stringMap;
}

function $put(this$static, key, value){
  return key == null?$putNullSlot(this$static, value):key == null?$putHashValue(this$static, key, value, ~~getHashCode_0(key)):$putStringValue(this$static, key, value);
}

function $putHashValue(this$static, key, value, hashCode){
  var array = this$static.hashCodeMap[hashCode];
  if (array) {
    for (var i = 0, c = array.length; i < c; ++i) {
      var entry = array[i];
      var entryKey = entry.getKey();
      if (this$static.equalsBridge(key, entryKey)) {
        var previous = entry.getValue();
        entry.setValue(value);
        return previous;
      }
    }
  }
   else {
    array = this$static.hashCodeMap[hashCode] = [];
  }
  var entry = $MapEntryImpl(new MapEntryImpl, key, value);
  array.push(entry);
  ++this$static.size;
  return null;
}

function $putNullSlot(this$static, value){
  var result;
  result = this$static.nullSlot;
  this$static.nullSlot = value;
  if (!this$static.nullSlotLive) {
    this$static.nullSlotLive = true;
    ++this$static.size;
  }
  return result;
}

function $putStringValue(this$static, key, value){
  var result, stringMap = this$static.stringMap;
  key = ':' + key;
  key in stringMap?(result = stringMap[key]):++this$static.size;
  stringMap[key] = value;
  return result;
}

function equalsBridge(value1, value2){
  return (value1 == null?null:value1) === (value2 == null?null:value2) || value1 != null && equals__devirtual$(value1, value2);
}

function AbstractHashMap(){
}

_ = AbstractHashMap.prototype = new AbstractMap;
_.equalsBridge = equalsBridge;
_.typeId$ = 0;
_.hashCodeMap = null;
_.nullSlot = null;
_.nullSlotLive = false;
_.size = 0;
_.stringMap = null;
function equals_4(o){
  var iter, other, otherItem;
  if ((o == null?null:o) === this) {
    return true;
  }
  if (!(o != null && canCast(o.typeId$, 9))) {
    return false;
  }
  other = dynamicCast(o, 9);
  if (other.this$0.size != this.size_0()) {
    return false;
  }
  for (iter = $AbstractHashMap$EntrySetIterator(new AbstractHashMap$EntrySetIterator, other.this$0); $hasNext_0(iter.iter);) {
    otherItem = dynamicCast($next_0(iter.iter), 6);
    if (!this.contains(otherItem)) {
      return false;
    }
  }
  return true;
}

function hashCode_5(){
  var hashCode, iter, next;
  hashCode = 0;
  for (iter = this.iterator(); iter.hasNext();) {
    next = iter.next();
    if (next != null) {
      hashCode += hashCode__devirtual$(next);
      hashCode = ~~hashCode;
    }
  }
  return hashCode;
}

function AbstractSet(){
}

_ = AbstractSet.prototype = new AbstractCollection;
_.equals$ = equals_4;
_.hashCode$ = hashCode_5;
_.typeId$ = 0;
function $AbstractHashMap$EntrySet(this$static, this$0){
  this$static.this$0 = this$0;
  return this$static;
}

function contains_0(o){
  var entry, key, value;
  if (o != null && canCast(o.typeId$, 6)) {
    entry = dynamicCast(o, 6);
    key = entry.getKey();
    if ($containsKey(this.this$0, key)) {
      value = $get_1(this.this$0, key);
      return $equals_2(entry.getValue(), value);
    }
  }
  return false;
}

function iterator(){
  return $AbstractHashMap$EntrySetIterator(new AbstractHashMap$EntrySetIterator, this.this$0);
}

function size_0(){
  return this.this$0.size;
}

function AbstractHashMap$EntrySet(){
}

_ = AbstractHashMap$EntrySet.prototype = new AbstractSet;
_.contains = contains_0;
_.iterator = iterator;
_.size_0 = size_0;
_.typeId$ = 22;
_.this$0 = null;
function $AbstractHashMap$EntrySetIterator(this$static, this$0){
  var list;
  this$static.this$0 = this$0;
  list = $ArrayList(new ArrayList);
  this$static.this$0.nullSlotLive && $add(list, $AbstractHashMap$MapEntryNull(new AbstractHashMap$MapEntryNull, this$static.this$0));
  $addAllStringEntries(this$static.this$0, list);
  $addAllHashEntries(this$static.this$0, list);
  this$static.iter = $AbstractList$IteratorImpl(new AbstractList$IteratorImpl, list);
  return this$static;
}

function hasNext(){
  return $hasNext_0(this.iter);
}

function next_0(){
  return dynamicCast($next_0(this.iter), 6);
}

function AbstractHashMap$EntrySetIterator(){
}

_ = AbstractHashMap$EntrySetIterator.prototype = new Object_0;
_.hasNext = hasNext;
_.next = next_0;
_.typeId$ = 0;
_.iter = null;
_.this$0 = null;
function equals_5(other){
  var entry;
  if (other != null && canCast(other.typeId$, 6)) {
    entry = dynamicCast(other, 6);
    if (equalsWithNullCheck(this.getKey(), entry.getKey()) && equalsWithNullCheck(this.getValue(), entry.getValue())) {
      return true;
    }
  }
  return false;
}

function hashCode_6(){
  var keyHash, valueHash;
  keyHash = 0;
  valueHash = 0;
  this.getKey() != null && (keyHash = hashCode__devirtual$(this.getKey()));
  this.getValue() != null && (valueHash = hashCode__devirtual$(this.getValue()));
  return keyHash ^ valueHash;
}

function AbstractMapEntry(){
}

_ = AbstractMapEntry.prototype = new Object_0;
_.equals$ = equals_5;
_.hashCode$ = hashCode_6;
_.typeId$ = 23;
function $AbstractHashMap$MapEntryNull(this$static, this$0){
  this$static.this$0 = this$0;
  return this$static;
}

function getKey(){
  return null;
}

function getValue(){
  return this.this$0.nullSlot;
}

function setValue(object){
  return $putNullSlot(this.this$0, object);
}

function AbstractHashMap$MapEntryNull(){
}

_ = AbstractHashMap$MapEntryNull.prototype = new AbstractMapEntry;
_.getKey = getKey;
_.getValue = getValue;
_.setValue = setValue;
_.typeId$ = 24;
_.this$0 = null;
function $AbstractHashMap$MapEntryString(this$static, key, this$0){
  this$static.this$0 = this$0;
  this$static.key = key;
  return this$static;
}

function getKey_0(){
  return this.key;
}

function getValue_0(){
  return this.this$0.stringMap[':' + this.key];
}

function new_$(this$outer, key){
  return $AbstractHashMap$MapEntryString(new AbstractHashMap$MapEntryString, key, this$outer);
}

function setValue_0(object){
  return $putStringValue(this.this$0, this.key, object);
}

function AbstractHashMap$MapEntryString(){
}

_ = AbstractHashMap$MapEntryString.prototype = new AbstractMapEntry;
_.getKey = getKey_0;
_.getValue = getValue_0;
_.setValue = setValue_0;
_.typeId$ = 25;
_.key = null;
_.this$0 = null;
function add_1(obj){
  $add_0(this, this.size_0(), obj);
  return true;
}

function checkIndex(index, size){
  (index < 0 || index >= size) && indexOutOfBounds(index, size);
}

function equals_6(o){
  var elem, elemOther, iter, iterOther, other;
  if ((o == null?null:o) === this) {
    return true;
  }
  if (!(o != null && canCast(o.typeId$, 7))) {
    return false;
  }
  other = dynamicCast(o, 7);
  if (this.size_0() != other.size) {
    return false;
  }
  iter = $AbstractList$IteratorImpl(new AbstractList$IteratorImpl, dynamicCast(this, 7));
  iterOther = $AbstractList$IteratorImpl(new AbstractList$IteratorImpl, other);
  while (iter.i < iter.this$0.size) {
    elem = $next_0(iter);
    elemOther = $next_0(iterOther);
    if (!(elem == null?elemOther == null:equals__devirtual$(elem, elemOther))) {
      return false;
    }
  }
  return true;
}

function hashCode_7(){
  var iter, k, obj;
  k = 1;
  iter = $AbstractList$IteratorImpl(new AbstractList$IteratorImpl, dynamicCast(this, 7));
  while (iter.i < iter.this$0.size) {
    obj = $next_0(iter);
    k = 31 * k + (obj == null?0:hashCode__devirtual$(obj));
    k = ~~k;
  }
  return k;
}

function indexOutOfBounds(index, size){
  throw $IndexOutOfBoundsException(new IndexOutOfBoundsException, 'Index: ' + index + ', Size: ' + size);
}

function iterator_0(){
  return $AbstractList$IteratorImpl(new AbstractList$IteratorImpl, dynamicCast(this, 7));
}

function AbstractList(){
}

_ = AbstractList.prototype = new AbstractCollection;
_.add = add_1;
_.equals$ = equals_6;
_.hashCode$ = hashCode_7;
_.iterator = iterator_0;
_.typeId$ = 0;
function $AbstractList$IteratorImpl(this$static, this$0){
  this$static.this$0 = this$0;
  return this$static;
}

function $hasNext_0(this$static){
  return this$static.i < this$static.this$0.size;
}

function $next_0(this$static){
  if (this$static.i >= this$static.this$0.size) {
    throw $NoSuchElementException(new NoSuchElementException);
  }
  return $get_2(this$static.this$0, this$static.i++);
}

function hasNext_0(){
  return this.i < this.this$0.size;
}

function next_1(){
  return $next_0(this);
}

function AbstractList$IteratorImpl(){
}

_ = AbstractList$IteratorImpl.prototype = new Object_0;
_.hasNext = hasNext_0;
_.next = next_1;
_.typeId$ = 0;
_.i = 0;
_.this$0 = null;
function $ArrayList(this$static){
  this$static.array = initDim(_3Ljava_lang_Object_2_classLit, 38, 0, 0, 0);
  return this$static;
}

function $add(this$static, o){
  setCheck(this$static.array, this$static.size++, o);
  return true;
}

function $add_0(this$static, index, o){
  (index < 0 || index > this$static.size) && indexOutOfBounds(index, this$static.size);
  this$static.array.splice(index, 0, o);
  ++this$static.size;
}

function $get_2(this$static, index){
  checkIndex(index, this$static.size);
  return this$static.array[index];
}

function $indexOf_1(this$static, o, index){
  for (; index < this$static.size; ++index) {
    if (equalsWithNullCheck(o, this$static.array[index])) {
      return index;
    }
  }
  return -1;
}

function add_2(o){
  return setCheck(this.array, this.size++, o) , true;
}

function contains_1(o){
  return $indexOf_1(this, o, 0) != -1;
}

function size_1(){
  return this.size;
}

function ArrayList(){
}

_ = ArrayList.prototype = new AbstractList;
_.add = add_2;
_.contains = contains_1;
_.size_0 = size_1;
_.typeId$ = 26;
_.size = 0;
function $HashMap(this$static){
  this$static.hashCodeMap = [];
  this$static.stringMap = {};
  this$static.nullSlotLive = false;
  this$static.nullSlot = null;
  this$static.size = 0;
  return this$static;
}

function $equals_2(value1, value2){
  return (value1 == null?null:value1) === (value2 == null?null:value2) || value1 != null && equals__devirtual$(value1, value2);
}

function HashMap(){
}

_ = HashMap.prototype = new AbstractHashMap;
_.typeId$ = 27;
function $MapEntryImpl(this$static, key, value){
  this$static.key = key;
  this$static.value = value;
  return this$static;
}

function getKey_1(){
  return this.key;
}

function getValue_1(){
  return this.value;
}

function setValue_1(value){
  var old;
  old = this.value;
  this.value = value;
  return old;
}

function MapEntryImpl(){
}

_ = MapEntryImpl.prototype = new AbstractMapEntry;
_.getKey = getKey_1;
_.getValue = getValue_1;
_.setValue = setValue_1;
_.typeId$ = 28;
_.key = null;
_.value = null;
function $NoSuchElementException(this$static){
  $fillInStackTrace();
  return this$static;
}

function NoSuchElementException(){
}

_ = NoSuchElementException.prototype = new RuntimeException;
_.typeId$ = 29;
function equalsWithNullCheck(a, b){
  return (a == null?null:a) === (b == null?null:b) || a != null && equals__devirtual$(a, b);
}

function $DateTimeFormat(this$static, pattern, dateTimeConstants){
  this$static.patternParts = $ArrayList(new ArrayList);
  this$static.pattern = pattern;
  this$static.dateTimeConstants = dateTimeConstants;
  $parsePattern_0(this$static, pattern);
  return this$static;
}

function $addPart(this$static, buf, count){
  var oldLength;
  if ($toString(buf.data).length > 0) {
    $add(this$static.patternParts, $DateTimeFormat$PatternPart(new DateTimeFormat$PatternPart, $toString(buf.data), count));
    oldLength = $toString(buf.data).length;
    0 < oldLength?$replace(buf.data, 0, oldLength, ''):0 > oldLength && $append_2(buf, initDim(_3C_classLit, 32, -1, 0 - oldLength, 1));
  }
}

function $format_1(this$static, date, timeZone){
  var ch, diff, i, j, keepDate, keepTime, n, toAppendTo, trailQuote;
  diff = ((date.checkJsDate() , date.jsdate.getTimezoneOffset()) - timeZone.standardOffset) * 60000;
  keepDate = $Date_0(new Date_0, add(fromDouble((date.checkJsDate() , date.jsdate.getTime())), fromInt(diff)));
  keepTime = keepDate;
  if ((keepDate.checkJsDate() , keepDate.jsdate.getTimezoneOffset()) != (date.checkJsDate() , date.jsdate.getTimezoneOffset())) {
    diff > 0?(diff -= 86400000):(diff += 86400000);
    keepTime = $Date_0(new Date_0, add(fromDouble((date.checkJsDate() , date.jsdate.getTime())), fromInt(diff)));
  }
  toAppendTo = $StringBuffer_0(new StringBuffer);
  n = this$static.pattern.length;
  for (i = 0; i < n;) {
    ch = this$static.pattern.charCodeAt(i);
    if (ch >= 97 && ch <= 122 || ch >= 65 && ch <= 90) {
      for (j = i + 1; j < n && this$static.pattern.charCodeAt(j) == ch; ++j) {
      }
      $subFormat(this$static, toAppendTo, ch, j - i, keepDate, keepTime, timeZone);
      i = j;
    }
     else if (ch == 39) {
      ++i;
      if (i < n && this$static.pattern.charCodeAt(i) == 39) {
        $appendNonNull(toAppendTo.data, "'");
        ++i;
        continue;
      }
      trailQuote = false;
      while (!trailQuote) {
        j = i;
        while (j < n && this$static.pattern.charCodeAt(j) != 39) {
          ++j;
        }
        if (j >= n) {
          throw $IllegalArgumentException(new IllegalArgumentException, "Missing trailing '");
        }
        j + 1 < n && this$static.pattern.charCodeAt(j + 1) == 39?++j:(trailQuote = true);
        $append_3(toAppendTo, $substring_0(this$static.pattern, i, j));
        i = j + 1;
      }
    }
     else {
      $appendNonNull(toAppendTo.data, String.fromCharCode(ch));
      ++i;
    }
  }
  return $toString(toAppendTo.data);
}

function $formatFractionalSeconds(buf, count, date){
  var time, value;
  time = fromDouble((date.checkJsDate() , date.jsdate.getTime()));
  compare(time, P0_longLit) < 0?(value = 1000 - lowBits_0(mod(neg(time), P3e8_longLit))):(value = lowBits_0(mod(time, P3e8_longLit)));
  if (count == 1) {
    value = ~~((value + 50) / 100) < 9?~~((value + 50) / 100):9;
    $appendNonNull(buf.data, String.fromCharCode(48 + value & 65535));
  }
   else if (count == 2) {
    value = ~~((value + 5) / 10) < 99?~~((value + 5) / 10):99;
    $zeroPaddingNumber(buf, value, 2);
  }
   else {
    $zeroPaddingNumber(buf, value, 3);
    count > 3 && $zeroPaddingNumber(buf, 0, count - 3);
  }
}

function $formatMonth(this$static, buf, count, date){
  var value;
  value = (date.checkJsDate() , date.jsdate.getMonth());
  switch (count) {
    case 5:
      $append_3(buf, $narrowMonths(this$static.dateTimeConstants)[value]);
      break;
    case 4:
      $append_3(buf, $months(this$static.dateTimeConstants)[value]);
      break;
    case 3:
      $append_3(buf, $shortMonths(this$static.dateTimeConstants)[value]);
      break;
    default:$zeroPaddingNumber(buf, value + 1, count);
  }
}

function $getNextCharCountInPattern(pattern, start){
  var ch, next;
  ch = pattern.charCodeAt(start);
  next = start + 1;
  while (next < pattern.length && pattern.charCodeAt(next) == ch) {
    ++next;
  }
  return next - start;
}

function $identifyAbutStart(this$static){
  var abut, i, len;
  abut = false;
  len = this$static.patternParts.size;
  for (i = 0; i < len; ++i) {
    if ($isNumeric(dynamicCast($get_2(this$static.patternParts, i), 16))) {
      if (!abut && i + 1 < len && $isNumeric(dynamicCast($get_2(this$static.patternParts, i + 1), 16))) {
        abut = true;
        dynamicCast($get_2(this$static.patternParts, i), 16).abutStart = true;
      }
    }
     else {
      abut = false;
    }
  }
}

function $isNumeric(part){
  var i;
  if (part.count <= 0) {
    return false;
  }
  i = 'MLydhHmsSDkK'.indexOf(fromCodePoint(part.text.charCodeAt(0)));
  return i > 1 || i >= 0 && part.count < 3;
}

function $matchString(text, start, data, pos){
  var bestMatch, bestMatchLength, count, i, length_0, textInLowerCase;
  count = data.length;
  bestMatchLength = 0;
  bestMatch = -1;
  textInLowerCase = text.substr(start, text.length - start).toLowerCase();
  for (i = 0; i < count; ++i) {
    length_0 = data[i].length;
    if (length_0 > bestMatchLength && textInLowerCase.indexOf(data[i].toLowerCase()) == 0) {
      bestMatch = i;
      bestMatchLength = length_0;
    }
  }
  bestMatch >= 0 && (pos[0] = start + bestMatchLength);
  return bestMatch;
}

function $parse_1(this$static, text, start, date, strict, tzOffset){
  var abutPass, abutPat, abutStart, cal, count, i, parsePos, part, s;
  cal = $DateRecord(new DateRecord);
  cal.tzOffset = tzOffset;
  parsePos = initValues(_3I_classLit, 34, -1, [start]);
  abutPat = -1;
  abutStart = 0;
  abutPass = 0;
  for (i = 0; i < this$static.patternParts.size; ++i) {
    part = dynamicCast($get_2(this$static.patternParts, i), 16);
    if (part.count > 0) {
      if (abutPat < 0 && part.abutStart) {
        abutPat = i;
        abutStart = start;
        abutPass = 0;
      }
      if (abutPat >= 0) {
        count = part.count;
        if (i == abutPat) {
          count -= abutPass++;
          if (count == 0) {
            return 0;
          }
        }
        if (!$subParse(this$static, text, parsePos, part, count, cal)) {
          i = abutPat - 1;
          parsePos[0] = abutStart;
          continue;
        }
      }
       else {
        abutPat = -1;
        if (!$subParse(this$static, text, parsePos, part, 0, cal)) {
          return 0;
        }
      }
    }
     else {
      abutPat = -1;
      if (part.text.charCodeAt(0) == 32) {
        s = parsePos[0];
        $skipSpace(text, parsePos);
        if (parsePos[0] > s) {
          continue;
        }
      }
       else if ($startsWith(text, part.text, parsePos[0])) {
        parsePos[0] += part.text.length;
        continue;
      }
      return 0;
    }
  }
  if (!$calcDate(cal, date, strict)) {
    return 0;
  }
  return parsePos[0] - start;
}

function $parseInt(text, pos){
  var ch, ind, ret;
  ret = 0;
  ind = pos[0];
  ch = text.charCodeAt(ind);
  while (ch >= 48 && ch <= 57) {
    ret = ret * 10 + (ch - 48);
    ++ind;
    if (ind >= text.length) {
      break;
    }
    ch = text.charCodeAt(ind);
  }
  ind > pos[0]?(pos[0] = ind):(ret = -1);
  return ret;
}

function $parsePattern_0(this$static, pattern){
  var buf, ch, count, i, inQuote;
  buf = $StringBuffer_0(new StringBuffer);
  inQuote = false;
  for (i = 0; i < pattern.length; ++i) {
    ch = pattern.charCodeAt(i);
    if (ch == 32) {
      $addPart(this$static, buf, 0);
      $appendNonNull(buf.data, ' ');
      $addPart(this$static, buf, 0);
      while (i + 1 < pattern.length && pattern.charCodeAt(i + 1) == 32) {
        ++i;
      }
      continue;
    }
    if (inQuote) {
      if (ch == 39) {
        if (i + 1 < pattern.length && pattern.charCodeAt(i + 1) == 39) {
          $appendNonNull(buf.data, String.fromCharCode(ch));
          ++i;
        }
         else {
          inQuote = false;
        }
      }
       else {
        $appendNonNull(buf.data, String.fromCharCode(ch));
      }
      continue;
    }
    if ('GyMLdkHmsSEcDahKzZv'.indexOf(fromCodePoint(ch)) > 0) {
      $addPart(this$static, buf, 0);
      $appendNonNull(buf.data, String.fromCharCode(ch));
      count = $getNextCharCountInPattern(pattern, i);
      $addPart(this$static, buf, count);
      i += count - 1;
      continue;
    }
    if (ch == 39) {
      if (i + 1 < pattern.length && pattern.charCodeAt(i + 1) == 39) {
        $appendNonNull(buf.data, "'");
        ++i;
      }
       else {
        inQuote = true;
      }
    }
     else {
      $appendNonNull(buf.data, String.fromCharCode(ch));
    }
  }
  $addPart(this$static, buf, 0);
  $identifyAbutStart(this$static);
}

function $parseTimeZoneOffset(text, pos, cal){
  var offset, sign, st, value;
  if (pos[0] >= text.length) {
    cal.tzOffset = 0;
    return true;
  }
  switch (text.charCodeAt(pos[0])) {
    case 43:
      sign = 1;
      break;
    case 45:
      sign = -1;
      break;
    default:cal.tzOffset = 0;
      return true;
  }
  ++pos[0];
  st = pos[0];
  value = $parseInt(text, pos);
  if (value == 0 && pos[0] == st) {
    return false;
  }
  if (pos[0] < text.length && text.charCodeAt(pos[0]) == 58) {
    offset = value * 60;
    ++pos[0];
    st = pos[0];
    value = $parseInt(text, pos);
    if (value == 0 && pos[0] == st) {
      return false;
    }
    offset += value;
  }
   else {
    offset = value;
    offset < 24 && pos[0] - st <= 2?(offset *= 60):(offset = offset % 100 + ~~(offset / 100) * 60);
  }
  offset *= sign;
  cal.tzOffset = -offset;
  return true;
}

function $skipSpace(text, pos){
  while (pos[0] < text.length && ' \t\r\n'.indexOf(fromCodePoint(text.charCodeAt(pos[0]))) >= 0) {
    ++pos[0];
  }
}

function $subFormat(this$static, buf, ch, count, adjustedDate, adjustedTime, timezone){
  var value, value_0, value_1, value_2, value_3, value_4, value_5, value_6, value_7, value_8, value_9, value_10, value_11;
  switch (ch) {
    case 71:
      value = (adjustedDate.checkJsDate() , adjustedDate.jsdate.getFullYear() - 1900) >= -1900?1:0;
      count >= 4?$append_3(buf, $eraNames(this$static.dateTimeConstants)[value]):$append_3(buf, $eras(this$static.dateTimeConstants)[value]);
      break;
    case 121:
      value_0 = (adjustedDate.checkJsDate() , adjustedDate.jsdate.getFullYear() - 1900) + 1900;
      value_0 < 0 && (value_0 = -value_0);
      count == 2?$zeroPaddingNumber(buf, value_0 % 100, 2):$append(buf.data, value_0);
      break;
    case 77:
      $formatMonth(this$static, buf, count, adjustedDate);
      break;
    case 107:
      value_1 = (adjustedTime.checkJsDate() , adjustedTime.jsdate.getHours());
      value_1 == 0?$zeroPaddingNumber(buf, 24, count):$zeroPaddingNumber(buf, value_1, count);
      break;
    case 83:
      $formatFractionalSeconds(buf, count, adjustedTime);
      break;
    case 69:
      value_2 = (adjustedDate.checkJsDate() , adjustedDate.jsdate.getDay());
      count == 5?$append_3(buf, $narrowWeekdays(this$static.dateTimeConstants)[value_2]):count == 4?$append_3(buf, $weekdays(this$static.dateTimeConstants)[value_2]):$append_3(buf, $shortWeekdays(this$static.dateTimeConstants)[value_2]);
      break;
    case 97:
      (adjustedTime.checkJsDate() , adjustedTime.jsdate.getHours()) >= 12 && (adjustedTime.checkJsDate() , adjustedTime.jsdate.getHours()) < 24?$append_3(buf, $ampms(this$static.dateTimeConstants)[1]):$append_3(buf, $ampms(this$static.dateTimeConstants)[0]);
      break;
    case 104:
      value_3 = (adjustedTime.checkJsDate() , adjustedTime.jsdate.getHours()) % 12;
      value_3 == 0?$zeroPaddingNumber(buf, 12, count):$zeroPaddingNumber(buf, value_3, count);
      break;
    case 75:
      value_4 = (adjustedTime.checkJsDate() , adjustedTime.jsdate.getHours()) % 12;
      $zeroPaddingNumber(buf, value_4, count);
      break;
    case 72:
      value_5 = (adjustedTime.checkJsDate() , adjustedTime.jsdate.getHours());
      $zeroPaddingNumber(buf, value_5, count);
      break;
    case 99:
      value_6 = (adjustedDate.checkJsDate() , adjustedDate.jsdate.getDay());
      count == 5?$append_3(buf, $standaloneNarrowWeekdays(this$static.dateTimeConstants)[value_6]):count == 4?$append_3(buf, $standaloneWeekdays(this$static.dateTimeConstants)[value_6]):count == 3?$append_3(buf, $standaloneShortWeekdays(this$static.dateTimeConstants)[value_6]):$zeroPaddingNumber(buf, value_6, 1);
      break;
    case 76:
      value_7 = (adjustedDate.checkJsDate() , adjustedDate.jsdate.getMonth());
      count == 5?$append_3(buf, $standaloneNarrowMonths(this$static.dateTimeConstants)[value_7]):count == 4?$append_3(buf, $standaloneMonths(this$static.dateTimeConstants)[value_7]):count == 3?$append_3(buf, $standaloneShortMonths(this$static.dateTimeConstants)[value_7]):$zeroPaddingNumber(buf, value_7 + 1, count);
      break;
    case 81:
      value_8 = ~~((adjustedDate.checkJsDate() , adjustedDate.jsdate.getMonth()) / 3);
      count < 4?$append_3(buf, $shortQuarters(this$static.dateTimeConstants)[value_8]):$append_3(buf, $quarters(this$static.dateTimeConstants)[value_8]);
      break;
    case 100:
      value_9 = (adjustedDate.checkJsDate() , adjustedDate.jsdate.getDate());
      $zeroPaddingNumber(buf, value_9, count);
      break;
    case 109:
      value_10 = (adjustedTime.checkJsDate() , adjustedTime.jsdate.getMinutes());
      $zeroPaddingNumber(buf, value_10, count);
      break;
    case 115:
      value_11 = (adjustedTime.checkJsDate() , adjustedTime.jsdate.getSeconds());
      $zeroPaddingNumber(buf, value_11, count);
      break;
    case 122:
      count < 4?$append_3(buf, timezone.tzNames[0]):$append_3(buf, timezone.tzNames[1]);
      break;
    case 118:
      $append_3(buf, timezone.timezoneID);
      break;
    case 90:
      count < 4?$append_3(buf, $getRFCTimeZoneString(timezone)):$append_3(buf, composeGMTString(timezone.standardOffset));
      break;
    default:return false;
  }
  return true;
}

function $subParse(this$static, text, pos, part, digitCount, cal){
  var ch, start, value;
  $skipSpace(text, pos);
  start = pos[0];
  ch = part.text.charCodeAt(0);
  value = -1;
  if ($isNumeric(part)) {
    if (digitCount > 0) {
      if (start + digitCount > text.length) {
        return false;
      }
      value = $parseInt(text.substr(0, start + digitCount - 0), pos);
    }
     else {
      value = $parseInt(text, pos);
    }
  }
  switch (ch) {
    case 71:
      value = $matchString(text, start, $eras(this$static.dateTimeConstants), pos);
      cal.era = value;
      return true;
    case 77:
      return $subParseMonth(this$static, text, pos, cal, value, start);
    case 76:
      return $subParseStandaloneMonth(this$static, text, pos, cal, value, start);
    case 69:
      return $subParseDayOfWeek(this$static, text, pos, start, cal);
    case 99:
      return $subParseStandaloneDay(this$static, text, pos, start, cal);
    case 97:
      value = $matchString(text, start, $ampms(this$static.dateTimeConstants), pos);
      cal.ampm = value;
      return true;
    case 121:
      return $subParseYear(text, pos, start, value, part, cal);
    case 100:
      if (value <= 0) {
        return false;
      }

      cal.dayOfMonth = value;
      return true;
    case 83:
      return $subParseFractionalSeconds(value, start, pos[0], cal);
    case 104:
      value == 12 && (value = 0);
    case 75:
    case 72:
      cal.hours = value;
      return true;
    case 107:
      cal.hours = value;
      return true;
    case 109:
      cal.minutes = value;
      return true;
    case 115:
      cal.seconds = value;
      return true;
    case 122:
    case 90:
    case 118:
      return $subParseTimeZoneInGMT(text, start, pos, cal);
    default:return false;
  }
}

function $subParseDayOfWeek(this$static, text, pos, start, cal){
  var value;
  value = $matchString(text, start, $weekdays(this$static.dateTimeConstants), pos);
  value < 0 && (value = $matchString(text, start, $shortWeekdays(this$static.dateTimeConstants), pos));
  if (value < 0) {
    return false;
  }
  cal.dayOfWeek = value;
  return true;
}

function $subParseFractionalSeconds(value, start, end, cal){
  var a, i;
  i = end - start;
  if (i < 3) {
    while (i < 3) {
      value *= 10;
      ++i;
    }
  }
   else {
    a = 1;
    while (i > 3) {
      a *= 10;
      --i;
    }
    value = ~~((value + (a >> 1)) / a);
  }
  cal.milliseconds = value;
  return true;
}

function $subParseMonth(this$static, text, pos, cal, value, start){
  if (value < 0) {
    value = $matchString(text, start, $months(this$static.dateTimeConstants), pos);
    value < 0 && (value = $matchString(text, start, $shortMonths(this$static.dateTimeConstants), pos));
    if (value < 0) {
      return false;
    }
    cal.month = value;
    return true;
  }
   else if (value > 0) {
    cal.month = value - 1;
    return true;
  }
  return false;
}

function $subParseStandaloneDay(this$static, text, pos, start, cal){
  var value;
  value = $matchString(text, start, $standaloneWeekdays(this$static.dateTimeConstants), pos);
  value < 0 && (value = $matchString(text, start, $standaloneShortWeekdays(this$static.dateTimeConstants), pos));
  if (value < 0) {
    return false;
  }
  cal.dayOfWeek = value;
  return true;
}

function $subParseStandaloneMonth(this$static, text, pos, cal, value, start){
  if (value < 0) {
    value = $matchString(text, start, $standaloneMonths(this$static.dateTimeConstants), pos);
    value < 0 && (value = $matchString(text, start, $standaloneShortMonths(this$static.dateTimeConstants), pos));
    if (value < 0) {
      return false;
    }
    cal.month = value;
    return true;
  }
   else if (value > 0) {
    cal.month = value - 1;
    return true;
  }
  return false;
}

function $subParseTimeZoneInGMT(text, start, pos, cal){
  if ($startsWith(text, 'GMT', start)) {
    pos[0] = start + 3;
    return $parseTimeZoneOffset(text, pos, cal);
  }
  return $parseTimeZoneOffset(text, pos, cal);
}

function $subParseYear(text, pos, start, value, part, cal){
  var ambiguousTwoDigitYear, ch, date, defaultCenturyStartYear;
  ch = 32;
  if (value < 0) {
    ch = text.charCodeAt(pos[0]);
    if (ch != 43 && ch != 45) {
      return false;
    }
    ++pos[0];
    value = $parseInt(text, pos);
    if (value < 0) {
      return false;
    }
    ch == 45 && (value = -value);
  }
  if (ch == 32 && pos[0] - start == 2 && part.count == 2) {
    date = $Date(new Date_0);
    defaultCenturyStartYear = (date.checkJsDate() , date.jsdate.getFullYear() - 1900) + 1900 - 80;
    ambiguousTwoDigitYear = defaultCenturyStartYear % 100;
    cal.ambiguousYear = value == ambiguousTwoDigitYear;
    value += ~~(defaultCenturyStartYear / 100) * 100 + (value < ambiguousTwoDigitYear?100:0);
  }
  cal.year = value;
  return true;
}

function $zeroPaddingNumber(buf, value, minWidth){
  var b, i;
  b = 10;
  for (i = 0; i < minWidth - 1; ++i) {
    value < b && $appendNonNull(buf.data, '0');
    b *= 10;
  }
  $append(buf.data, value);
}

function DateTimeFormat(){
}

_ = DateTimeFormat.prototype = new Object_0;
_.typeId$ = 0;
_.dateTimeConstants = null;
_.pattern = null;
function $DateTimeFormat$PatternPart(this$static, txt, cnt){
  this$static.text = txt;
  this$static.count = cnt;
  this$static.abutStart = false;
  return this$static;
}

function DateTimeFormat$PatternPart(){
}

_ = DateTimeFormat$PatternPart.prototype = new Object_0;
_.typeId$ = 30;
_.abutStart = false;
_.count = 0;
_.text = null;
function TersusNumberConstants(){
}

_ = TersusNumberConstants.prototype = new Object_0;
_.typeId$ = 0;
_.decimalSeparator = '.';
_.groupingSeparator = ',';
function $clinit_98(){
  $clinit_98 = nullMethod;
  $clinit_27();
}

function $TersusNumberFormat(this$static, numberConstants, pattern, cdata){
  $clinit_98();
  $NumberFormat(this$static, numberConstants, pattern, cdata, true);
  return this$static;
}

function TersusNumberFormat(){
}

_ = TersusNumberFormat.prototype = new NumberFormat;
_.typeId$ = 31;
function $clinit_99(){
  $clinit_99 = nullMethod;
  numberConstants_0 = new TersusNumberConstants;
  numberFormats = $HashMap(new HashMap);
}

function formatDateAndTime(time, pattern, timeZoneOffset){
  var date, format, tz, timeZone;
  date = $Date_0(new Date_0, fromDouble(time));
  format = $DateTimeFormat(new DateTimeFormat, pattern, $getDateTimeConstants(($clinit_24() , $clinit_24() , instance)));
  if (timeZoneOffset > -10000) {
    tz = createTimeZone(timeZoneOffset);
    return $format_1(format, date, tz);
  }
   else 
    return timeZone = createTimeZone((date.checkJsDate() , date.jsdate.getTimezoneOffset())) , $format_1(format, date, timeZone);
}

function formatNumber(num, pattern){
  var format;
  numberConstants_0.decimalSeparator = $wnd.tersus.DECIMAL_POINT;
  numberConstants_0.groupingSeparator = $wnd.tersus.THOUSANDS_SEPARATOR;
  format = dynamicCast($get_1(numberFormats, pattern), 17);
  if (!format) {
    format = $TersusNumberFormat(new TersusNumberFormat, numberConstants_0, pattern, ['USD', 'US$', 2, 'US$']);
    $put(numberFormats, pattern, format);
  }
  return $format(format, num);
}

function parseDateAndTime(text, pattern, timeZoneOffset){
  var date, format, rc;
  format = $DateTimeFormat(new DateTimeFormat, pattern, $getDateTimeConstants(($clinit_24() , $clinit_24() , instance)));
  date = $Date_0(new Date_0, P0_longLit);
  timeZoneOffset > -10000?(rc = $parse_1(format, text, 0, date, false, timeZoneOffset)):(rc = $parse_1(format, text, 0, date, false, -2147483648));
  if (rc <= 0 || rc != text.length)
    return -1;
  return toDouble(fromDouble((date.checkJsDate() , date.jsdate.getTime())));
}

function parseNumber(text, pattern){
  var format;
  numberConstants_0.decimalSeparator = $wnd.tersus.DECIMAL_POINT;
  numberConstants_0.groupingSeparator = $wnd.tersus.THOUSANDS_SEPARATOR;
  format = dynamicCast($get_1(numberFormats, pattern), 17);
  if (!format) {
    format = $TersusNumberFormat(new TersusNumberFormat, numberConstants_0, pattern, ['USD', 'US$', 2, 'US$']);
    $put(numberFormats, pattern, format);
  }
  return $parse(format, text);
}

var numberConstants_0, numberFormats;
var $entry = entry_0;
function gwtOnLoad(errFn, modName, modBase){
  $moduleName = modName;
  $moduleBase = modBase;
  if (errFn)
    try {
      $entry(init)();
    }
     catch (e) {
      errFn(modName);
    }
   else {
    $entry(init)();
  }
}

var _3I_classLit = new Class, _3Ljava_lang_StackTraceElement_2_classLit = new Class, _3Ljava_lang_String_2_classLit = new Class, _3C_classLit = new Class, _3_3D_classLit = new Class, _3Ljava_lang_Object_2_classLit = new Class;
//$stats && $stats({moduleName:'tersus.gwt.Util',sessionId:$sessionId,subSystem:'startup',evtGroup:'moduleStartup',millis:(new Date()).getTime(),type:'moduleEvalEnd'});
//if ($wnd.tersus_gwt_Util) $wnd.tersus_gwt_Util.onScriptLoad();
init();


// file: 001-1-cordova-3.4.0.js
// Platform: ios
// 3.4.0
/*
 Licensed to the Apache Software Foundation (ASF) under one
 or more contributor license agreements.  See the NOTICE file
 distributed with this work for additional information
 regarding copyright ownership.  The ASF licenses this file
 to you under the Apache License, Version 2.0 (the
 "License"); you may not use this file except in compliance
 with the License.  You may obtain a copy of the License at
 
     http://www.apache.org/licenses/LICENSE-2.0
 
 Unless required by applicable law or agreed to in writing,
 software distributed under the License is distributed on an
 "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 KIND, either express or implied.  See the License for the
 specific language governing permissions and limitations
 under the License.
*/
;(function() {
var CORDOVA_JS_BUILD_LABEL = '3.4.0';
// file: src/scripts/require.js

/*jshint -W079 */
/*jshint -W020 */

var require,
    define;

(function () {
    var modules = {},
    // Stack of moduleIds currently being built.
        requireStack = [],
    // Map of module ID -> index into requireStack of modules currently being built.
        inProgressModules = {},
        SEPARATOR = ".";



    function build(module) {
        var factory = module.factory,
            localRequire = function (id) {
                var resultantId = id;
                //Its a relative path, so lop off the last portion and add the id (minus "./")
                if (id.charAt(0) === ".") {
                    resultantId = module.id.slice(0, module.id.lastIndexOf(SEPARATOR)) + SEPARATOR + id.slice(2);
                }
                return require(resultantId);
            };
        module.exports = {};
        delete module.factory;
        factory(localRequire, module.exports, module);
        return module.exports;
    }

    require = function (id) {
        if (!modules[id]) {
            throw "module " + id + " not found";
        } else if (id in inProgressModules) {
            var cycle = requireStack.slice(inProgressModules[id]).join('->') + '->' + id;
            throw "Cycle in require graph: " + cycle;
        }
        if (modules[id].factory) {
            try {
                inProgressModules[id] = requireStack.length;
                requireStack.push(id);
                return build(modules[id]);
            } finally {
                delete inProgressModules[id];
                requireStack.pop();
            }
        }
        return modules[id].exports;
    };

    define = function (id, factory) {
        if (modules[id]) {
            throw "module " + id + " already defined";
        }

        modules[id] = {
            id: id,
            factory: factory
        };
    };

    define.remove = function (id) {
        delete modules[id];
    };

    define.moduleMap = modules;
})();

//Export for use in node
if (typeof module === "object" && typeof require === "function") {
    module.exports.require = require;
    module.exports.define = define;
}

// file: src/cordova.js
define("cordova", function(require, exports, module) {


var channel = require('cordova/channel');
var platform = require('cordova/platform');

/**
 * Intercept calls to addEventListener + removeEventListener and handle deviceready,
 * resume, and pause events.
 */
var m_document_addEventListener = document.addEventListener;
var m_document_removeEventListener = document.removeEventListener;
var m_window_addEventListener = window.addEventListener;
var m_window_removeEventListener = window.removeEventListener;

/**
 * Houses custom event handlers to intercept on document + window event listeners.
 */
var documentEventHandlers = {},
    windowEventHandlers = {};

document.addEventListener = function(evt, handler, capture) {
    var e = evt.toLowerCase();
    if (typeof documentEventHandlers[e] != 'undefined') {
        documentEventHandlers[e].subscribe(handler);
    } else {
        m_document_addEventListener.call(document, evt, handler, capture);
    }
};

window.addEventListener = function(evt, handler, capture) {
    var e = evt.toLowerCase();
    if (typeof windowEventHandlers[e] != 'undefined') {
        windowEventHandlers[e].subscribe(handler);
    } else {
        m_window_addEventListener.call(window, evt, handler, capture);
    }
};

document.removeEventListener = function(evt, handler, capture) {
    var e = evt.toLowerCase();
    // If unsubscribing from an event that is handled by a plugin
    if (typeof documentEventHandlers[e] != "undefined") {
        documentEventHandlers[e].unsubscribe(handler);
    } else {
        m_document_removeEventListener.call(document, evt, handler, capture);
    }
};

window.removeEventListener = function(evt, handler, capture) {
    var e = evt.toLowerCase();
    // If unsubscribing from an event that is handled by a plugin
    if (typeof windowEventHandlers[e] != "undefined") {
        windowEventHandlers[e].unsubscribe(handler);
    } else {
        m_window_removeEventListener.call(window, evt, handler, capture);
    }
};

function createEvent(type, data) {
    var event = document.createEvent('Events');
    event.initEvent(type, false, false);
    if (data) {
        for (var i in data) {
            if (data.hasOwnProperty(i)) {
                event[i] = data[i];
            }
        }
    }
    return event;
}


var cordova = {
    define:define,
    require:require,
    version:CORDOVA_JS_BUILD_LABEL,
    platformId:platform.id,
    /**
     * Methods to add/remove your own addEventListener hijacking on document + window.
     */
    addWindowEventHandler:function(event) {
        return (windowEventHandlers[event] = channel.create(event));
    },
    addStickyDocumentEventHandler:function(event) {
        return (documentEventHandlers[event] = channel.createSticky(event));
    },
    addDocumentEventHandler:function(event) {
        return (documentEventHandlers[event] = channel.create(event));
    },
    removeWindowEventHandler:function(event) {
        delete windowEventHandlers[event];
    },
    removeDocumentEventHandler:function(event) {
        delete documentEventHandlers[event];
    },
    /**
     * Retrieve original event handlers that were replaced by Cordova
     *
     * @return object
     */
    getOriginalHandlers: function() {
        return {'document': {'addEventListener': m_document_addEventListener, 'removeEventListener': m_document_removeEventListener},
        'window': {'addEventListener': m_window_addEventListener, 'removeEventListener': m_window_removeEventListener}};
    },
    /**
     * Method to fire event from native code
     * bNoDetach is required for events which cause an exception which needs to be caught in native code
     */
    fireDocumentEvent: function(type, data, bNoDetach) {
        var evt = createEvent(type, data);
        if (typeof documentEventHandlers[type] != 'undefined') {
            if( bNoDetach ) {
                documentEventHandlers[type].fire(evt);
            }
            else {
                setTimeout(function() {
                    // Fire deviceready on listeners that were registered before cordova.js was loaded.
                    if (type == 'deviceready') {
                        document.dispatchEvent(evt);
                    }
                    documentEventHandlers[type].fire(evt);
                }, 0);
            }
        } else {
            document.dispatchEvent(evt);
        }
    },
    fireWindowEvent: function(type, data) {
        var evt = createEvent(type,data);
        if (typeof windowEventHandlers[type] != 'undefined') {
            setTimeout(function() {
                windowEventHandlers[type].fire(evt);
            }, 0);
        } else {
            window.dispatchEvent(evt);
        }
    },

    /**
     * Plugin callback mechanism.
     */
    // Randomize the starting callbackId to avoid collisions after refreshing or navigating.
    // This way, it's very unlikely that any new callback would get the same callbackId as an old callback.
    callbackId: Math.floor(Math.random() * 2000000000),
    callbacks:  {},
    callbackStatus: {
        NO_RESULT: 0,
        OK: 1,
        CLASS_NOT_FOUND_EXCEPTION: 2,
        ILLEGAL_ACCESS_EXCEPTION: 3,
        INSTANTIATION_EXCEPTION: 4,
        MALFORMED_URL_EXCEPTION: 5,
        IO_EXCEPTION: 6,
        INVALID_ACTION: 7,
        JSON_EXCEPTION: 8,
        ERROR: 9
    },

    /**
     * Called by native code when returning successful result from an action.
     */
    callbackSuccess: function(callbackId, args) {
        try {
            cordova.callbackFromNative(callbackId, true, args.status, [args.message], args.keepCallback);
        } catch (e) {
            console.log("Error in error callback: " + callbackId + " = "+e);
        }
    },

    /**
     * Called by native code when returning error result from an action.
     */
    callbackError: function(callbackId, args) {
        // TODO: Deprecate callbackSuccess and callbackError in favour of callbackFromNative.
        // Derive success from status.
        try {
            cordova.callbackFromNative(callbackId, false, args.status, [args.message], args.keepCallback);
        } catch (e) {
            console.log("Error in error callback: " + callbackId + " = "+e);
        }
    },

    /**
     * Called by native code when returning the result from an action.
     */
    callbackFromNative: function(callbackId, success, status, args, keepCallback) {
        var callback = cordova.callbacks[callbackId];
        if (callback) {
            if (success && status == cordova.callbackStatus.OK) {
                callback.success && callback.success.apply(null, args);
            } else if (!success) {
                callback.fail && callback.fail.apply(null, args);
            }

            // Clear callback if not expecting any more results
            if (!keepCallback) {
                delete cordova.callbacks[callbackId];
            }
        }
    },
    addConstructor: function(func) {
        channel.onCordovaReady.subscribe(function() {
            try {
                func();
            } catch(e) {
                console.log("Failed to run constructor: " + e);
            }
        });
    }
};


module.exports = cordova;

});

// file: src/common/argscheck.js
define("cordova/argscheck", function(require, exports, module) {

var exec = require('cordova/exec');
var utils = require('cordova/utils');

var moduleExports = module.exports;

var typeMap = {
    'A': 'Array',
    'D': 'Date',
    'N': 'Number',
    'S': 'String',
    'F': 'Function',
    'O': 'Object'
};

function extractParamName(callee, argIndex) {
    return (/.*?\((.*?)\)/).exec(callee)[1].split(', ')[argIndex];
}

function checkArgs(spec, functionName, args, opt_callee) {
    if (!moduleExports.enableChecks) {
        return;
    }
    var errMsg = null;
    var typeName;
    for (var i = 0; i < spec.length; ++i) {
        var c = spec.charAt(i),
            cUpper = c.toUpperCase(),
            arg = args[i];
        // Asterix means allow anything.
        if (c == '*') {
            continue;
        }
        typeName = utils.typeName(arg);
        if ((arg === null || arg === undefined) && c == cUpper) {
            continue;
        }
        if (typeName != typeMap[cUpper]) {
            errMsg = 'Expected ' + typeMap[cUpper];
            break;
        }
    }
    if (errMsg) {
        errMsg += ', but got ' + typeName + '.';
        errMsg = 'Wrong type for parameter "' + extractParamName(opt_callee || args.callee, i) + '" of ' + functionName + ': ' + errMsg;
        // Don't log when running unit tests.
        if (typeof jasmine == 'undefined') {
            console.error(errMsg);
        }
        throw TypeError(errMsg);
    }
}

function getValue(value, defaultValue) {
    return value === undefined ? defaultValue : value;
}

moduleExports.checkArgs = checkArgs;
moduleExports.getValue = getValue;
moduleExports.enableChecks = true;


});

// file: src/common/base64.js
define("cordova/base64", function(require, exports, module) {

var base64 = exports;

base64.fromArrayBuffer = function(arrayBuffer) {
    var array = new Uint8Array(arrayBuffer);
    return uint8ToBase64(array);
};

//------------------------------------------------------------------------------

/* This code is based on the performance tests at http://jsperf.com/b64tests
 * This 12-bit-at-a-time algorithm was the best performing version on all
 * platforms tested.
 */

var b64_6bit = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
var b64_12bit;

var b64_12bitTable = function() {
    b64_12bit = [];
    for (var i=0; i<64; i++) {
        for (var j=0; j<64; j++) {
            b64_12bit[i*64+j] = b64_6bit[i] + b64_6bit[j];
        }
    }
    b64_12bitTable = function() { return b64_12bit; };
    return b64_12bit;
};

function uint8ToBase64(rawData) {
    var numBytes = rawData.byteLength;
    var output="";
    var segment;
    var table = b64_12bitTable();
    for (var i=0;i<numBytes-2;i+=3) {
        segment = (rawData[i] << 16) + (rawData[i+1] << 8) + rawData[i+2];
        output += table[segment >> 12];
        output += table[segment & 0xfff];
    }
    if (numBytes - i == 2) {
        segment = (rawData[i] << 16) + (rawData[i+1] << 8);
        output += table[segment >> 12];
        output += b64_6bit[(segment & 0xfff) >> 6];
        output += '=';
    } else if (numBytes - i == 1) {
        segment = (rawData[i] << 16);
        output += table[segment >> 12];
        output += '==';
    }
    return output;
}

});

// file: src/common/builder.js
define("cordova/builder", function(require, exports, module) {

var utils = require('cordova/utils');

function each(objects, func, context) {
    for (var prop in objects) {
        if (objects.hasOwnProperty(prop)) {
            func.apply(context, [objects[prop], prop]);
        }
    }
}

function clobber(obj, key, value) {
    exports.replaceHookForTesting(obj, key);
    obj[key] = value;
    // Getters can only be overridden by getters.
    if (obj[key] !== value) {
        utils.defineGetter(obj, key, function() {
            return value;
        });
    }
}

function assignOrWrapInDeprecateGetter(obj, key, value, message) {
    if (message) {
        utils.defineGetter(obj, key, function() {
            console.log(message);
            delete obj[key];
            clobber(obj, key, value);
            return value;
        });
    } else {
        clobber(obj, key, value);
    }
}

function include(parent, objects, clobber, merge) {
    each(objects, function (obj, key) {
        try {
            var result = obj.path ? require(obj.path) : {};

            if (clobber) {
                // Clobber if it doesn't exist.
                if (typeof parent[key] === 'undefined') {
                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
                } else if (typeof obj.path !== 'undefined') {
                    // If merging, merge properties onto parent, otherwise, clobber.
                    if (merge) {
                        recursiveMerge(parent[key], result);
                    } else {
                        assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
                    }
                }
                result = parent[key];
            } else {
                // Overwrite if not currently defined.
                if (typeof parent[key] == 'undefined') {
                    assignOrWrapInDeprecateGetter(parent, key, result, obj.deprecated);
                } else {
                    // Set result to what already exists, so we can build children into it if they exist.
                    result = parent[key];
                }
            }

            if (obj.children) {
                include(result, obj.children, clobber, merge);
            }
        } catch(e) {
            utils.alert('Exception building Cordova JS globals: ' + e + ' for key "' + key + '"');
        }
    });
}

/**
 * Merge properties from one object onto another recursively.  Properties from
 * the src object will overwrite existing target property.
 *
 * @param target Object to merge properties into.
 * @param src Object to merge properties from.
 */
function recursiveMerge(target, src) {
    for (var prop in src) {
        if (src.hasOwnProperty(prop)) {
            if (target.prototype && target.prototype.constructor === target) {
                // If the target object is a constructor override off prototype.
                clobber(target.prototype, prop, src[prop]);
            } else {
                if (typeof src[prop] === 'object' && typeof target[prop] === 'object') {
                    recursiveMerge(target[prop], src[prop]);
                } else {
                    clobber(target, prop, src[prop]);
                }
            }
        }
    }
}

exports.buildIntoButDoNotClobber = function(objects, target) {
    include(target, objects, false, false);
};
exports.buildIntoAndClobber = function(objects, target) {
    include(target, objects, true, false);
};
exports.buildIntoAndMerge = function(objects, target) {
    include(target, objects, true, true);
};
exports.recursiveMerge = recursiveMerge;
exports.assignOrWrapInDeprecateGetter = assignOrWrapInDeprecateGetter;
exports.replaceHookForTesting = function() {};

});

// file: src/common/channel.js
define("cordova/channel", function(require, exports, module) {

var utils = require('cordova/utils'),
    nextGuid = 1;

/**
 * Custom pub-sub "channel" that can have functions subscribed to it
 * This object is used to define and control firing of events for
 * cordova initialization, as well as for custom events thereafter.
 *
 * The order of events during page load and Cordova startup is as follows:
 *
 * onDOMContentLoaded*         Internal event that is received when the web page is loaded and parsed.
 * onNativeReady*              Internal event that indicates the Cordova native side is ready.
 * onCordovaReady*             Internal event fired when all Cordova JavaScript objects have been created.
 * onDeviceReady*              User event fired to indicate that Cordova is ready
 * onResume                    User event fired to indicate a start/resume lifecycle event
 * onPause                     User event fired to indicate a pause lifecycle event
 * onDestroy*                  Internal event fired when app is being destroyed (User should use window.onunload event, not this one).
 *
 * The events marked with an * are sticky. Once they have fired, they will stay in the fired state.
 * All listeners that subscribe after the event is fired will be executed right away.
 *
 * The only Cordova events that user code should register for are:
 *      deviceready           Cordova native code is initialized and Cordova APIs can be called from JavaScript
 *      pause                 App has moved to background
 *      resume                App has returned to foreground
 *
 * Listeners can be registered as:
 *      document.addEventListener("deviceready", myDeviceReadyListener, false);
 *      document.addEventListener("resume", myResumeListener, false);
 *      document.addEventListener("pause", myPauseListener, false);
 *
 * The DOM lifecycle events should be used for saving and restoring state
 *      window.onload
 *      window.onunload
 *
 */

/**
 * Channel
 * @constructor
 * @param type  String the channel name
 */
var Channel = function(type, sticky) {
    this.type = type;
    // Map of guid -> function.
    this.handlers = {};
    // 0 = Non-sticky, 1 = Sticky non-fired, 2 = Sticky fired.
    this.state = sticky ? 1 : 0;
    // Used in sticky mode to remember args passed to fire().
    this.fireArgs = null;
    // Used by onHasSubscribersChange to know if there are any listeners.
    this.numHandlers = 0;
    // Function that is called when the first listener is subscribed, or when
    // the last listener is unsubscribed.
    this.onHasSubscribersChange = null;
},
    channel = {
        /**
         * Calls the provided function only after all of the channels specified
         * have been fired. All channels must be sticky channels.
         */
        join: function(h, c) {
            var len = c.length,
                i = len,
                f = function() {
                    if (!(--i)) h();
                };
            for (var j=0; j<len; j++) {
                if (c[j].state === 0) {
                    throw Error('Can only use join with sticky channels.');
                }
                c[j].subscribe(f);
            }
            if (!len) h();
        },
        create: function(type) {
            return channel[type] = new Channel(type, false);
        },
        createSticky: function(type) {
            return channel[type] = new Channel(type, true);
        },

        /**
         * cordova Channels that must fire before "deviceready" is fired.
         */
        deviceReadyChannelsArray: [],
        deviceReadyChannelsMap: {},

        /**
         * Indicate that a feature needs to be initialized before it is ready to be used.
         * This holds up Cordova's "deviceready" event until the feature has been initialized
         * and Cordova.initComplete(feature) is called.
         *
         * @param feature {String}     The unique feature name
         */
        waitForInitialization: function(feature) {
            if (feature) {
                var c = channel[feature] || this.createSticky(feature);
                this.deviceReadyChannelsMap[feature] = c;
                this.deviceReadyChannelsArray.push(c);
            }
        },

        /**
         * Indicate that initialization code has completed and the feature is ready to be used.
         *
         * @param feature {String}     The unique feature name
         */
        initializationComplete: function(feature) {
            var c = this.deviceReadyChannelsMap[feature];
            if (c) {
                c.fire();
            }
        }
    };

function forceFunction(f) {
    if (typeof f != 'function') throw "Function required as first argument!";
}

/**
 * Subscribes the given function to the channel. Any time that
 * Channel.fire is called so too will the function.
 * Optionally specify an execution context for the function
 * and a guid that can be used to stop subscribing to the channel.
 * Returns the guid.
 */
Channel.prototype.subscribe = function(f, c) {
    // need a function to call
    forceFunction(f);
    if (this.state == 2) {
        f.apply(c || this, this.fireArgs);
        return;
    }

    var func = f,
        guid = f.observer_guid;
    if (typeof c == "object") { func = utils.close(c, f); }

    if (!guid) {
        // first time any channel has seen this subscriber
        guid = '' + nextGuid++;
    }
    func.observer_guid = guid;
    f.observer_guid = guid;

    // Don't add the same handler more than once.
    if (!this.handlers[guid]) {
        this.handlers[guid] = func;
        this.numHandlers++;
        if (this.numHandlers == 1) {
            this.onHasSubscribersChange && this.onHasSubscribersChange();
        }
    }
};

/**
 * Unsubscribes the function with the given guid from the channel.
 */
Channel.prototype.unsubscribe = function(f) {
    // need a function to unsubscribe
    forceFunction(f);

    var guid = f.observer_guid,
        handler = this.handlers[guid];
    if (handler) {
        delete this.handlers[guid];
        this.numHandlers--;
        if (this.numHandlers === 0) {
            this.onHasSubscribersChange && this.onHasSubscribersChange();
        }
    }
};

/**
 * Calls all functions subscribed to this channel.
 */
Channel.prototype.fire = function(e) {
    var fail = false,
        fireArgs = Array.prototype.slice.call(arguments);
    // Apply stickiness.
    if (this.state == 1) {
        this.state = 2;
        this.fireArgs = fireArgs;
    }
    if (this.numHandlers) {
        // Copy the values first so that it is safe to modify it from within
        // callbacks.
        var toCall = [];
        for (var item in this.handlers) {
            toCall.push(this.handlers[item]);
        }
        for (var i = 0; i < toCall.length; ++i) {
            toCall[i].apply(this, fireArgs);
        }
        if (this.state == 2 && this.numHandlers) {
            this.numHandlers = 0;
            this.handlers = {};
            this.onHasSubscribersChange && this.onHasSubscribersChange();
        }
    }
};


// defining them here so they are ready super fast!
// DOM event that is received when the web page is loaded and parsed.
channel.createSticky('onDOMContentLoaded');

// Event to indicate the Cordova native side is ready.
channel.createSticky('onNativeReady');

// Event to indicate that all Cordova JavaScript objects have been created
// and it's time to run plugin constructors.
channel.createSticky('onCordovaReady');

// Event to indicate that all automatically loaded JS plugins are loaded and ready.
channel.createSticky('onPluginsReady');

// Event to indicate that Cordova is ready
channel.createSticky('onDeviceReady');

// Event to indicate a resume lifecycle event
channel.create('onResume');

// Event to indicate a pause lifecycle event
channel.create('onPause');

// Event to indicate a destroy lifecycle event
channel.createSticky('onDestroy');

// Channels that must fire before "deviceready" is fired.
channel.waitForInitialization('onCordovaReady');
channel.waitForInitialization('onDOMContentLoaded');

module.exports = channel;

});

// file: src/ios/exec.js
define("cordova/exec", function(require, exports, module) {

/**
 * Creates a gap bridge iframe used to notify the native code about queued
 * commands.
 */
var cordova = require('cordova'),
    channel = require('cordova/channel'),
    utils = require('cordova/utils'),
    base64 = require('cordova/base64'),
    // XHR mode does not work on iOS 4.2.
    // XHR mode's main advantage is working around a bug in -webkit-scroll, which
    // doesn't exist only on iOS 5.x devices.
    // IFRAME_NAV is the fastest.
    // IFRAME_HASH could be made to enable synchronous bridge calls if we wanted this feature.
    jsToNativeModes = {
        IFRAME_NAV: 0,
        XHR_NO_PAYLOAD: 1,
        XHR_WITH_PAYLOAD: 2,
        XHR_OPTIONAL_PAYLOAD: 3,
        IFRAME_HASH_NO_PAYLOAD: 4,
        // Bundling the payload turns out to be slower. Probably since it has to be URI encoded / decoded.
        IFRAME_HASH_WITH_PAYLOAD: 5
    },
    bridgeMode,
    execIframe,
    execHashIframe,
    hashToggle = 1,
    execXhr,
    requestCount = 0,
    vcHeaderValue = null,
    commandQueue = [], // Contains pending JS->Native messages.
    isInContextOfEvalJs = 0;

function createExecIframe() {
    var iframe = document.createElement("iframe");
    iframe.style.display = 'none';
    document.body.appendChild(iframe);
    return iframe;
}

function createHashIframe() {
    var ret = createExecIframe();
    // Hash changes don't work on about:blank, so switch it to file:///.
    ret.contentWindow.history.replaceState(null, null, 'file:///#');
    return ret;
}

function shouldBundleCommandJson() {
    if (bridgeMode === jsToNativeModes.XHR_WITH_PAYLOAD) {
        return true;
    }
    if (bridgeMode === jsToNativeModes.XHR_OPTIONAL_PAYLOAD) {
        var payloadLength = 0;
        for (var i = 0; i < commandQueue.length; ++i) {
            payloadLength += commandQueue[i].length;
        }
        // The value here was determined using the benchmark within CordovaLibApp on an iPad 3.
        return payloadLength < 4500;
    }
    return false;
}

function massageArgsJsToNative(args) {
    if (!args || utils.typeName(args) != 'Array') {
        return args;
    }
    var ret = [];
    args.forEach(function(arg, i) {
        if (utils.typeName(arg) == 'ArrayBuffer') {
            ret.push({
                'CDVType': 'ArrayBuffer',
                'data': base64.fromArrayBuffer(arg)
            });
        } else {
            ret.push(arg);
        }
    });
    return ret;
}

function massageMessageNativeToJs(message) {
    if (message.CDVType == 'ArrayBuffer') {
        var stringToArrayBuffer = function(str) {
            var ret = new Uint8Array(str.length);
            for (var i = 0; i < str.length; i++) {
                ret[i] = str.charCodeAt(i);
            }
            return ret.buffer;
        };
        var base64ToArrayBuffer = function(b64) {
            return stringToArrayBuffer(atob(b64));
        };
        message = base64ToArrayBuffer(message.data);
    }
    return message;
}

function convertMessageToArgsNativeToJs(message) {
    var args = [];
    if (!message || !message.hasOwnProperty('CDVType')) {
        args.push(message);
    } else if (message.CDVType == 'MultiPart') {
        message.messages.forEach(function(e) {
            args.push(massageMessageNativeToJs(e));
        });
    } else {
        args.push(massageMessageNativeToJs(message));
    }
    return args;
}

function iOSExec() {
    // Use XHR for iOS 5 to work around a bug in -webkit-scroll.
    // Use IFRAME_NAV elsewhere since it's faster and XHR bridge
    // seems to have bugs in newer OS's (CB-3900, CB-3359, CB-5457, CB-4970, CB-4998, CB-5134)
    if (bridgeMode === undefined) {
        bridgeMode = navigator.userAgent.indexOf(' 5_') == -1 ? jsToNativeModes.IFRAME_NAV: jsToNativeModes.XHR_NO_PAYLOAD;
    }

    var successCallback, failCallback, service, action, actionArgs, splitCommand;
    var callbackId = null;
    if (typeof arguments[0] !== "string") {
        // FORMAT ONE
        successCallback = arguments[0];
        failCallback = arguments[1];
        service = arguments[2];
        action = arguments[3];
        actionArgs = arguments[4];

        // Since we need to maintain backwards compatibility, we have to pass
        // an invalid callbackId even if no callback was provided since plugins
        // will be expecting it. The Cordova.exec() implementation allocates
        // an invalid callbackId and passes it even if no callbacks were given.
        callbackId = 'INVALID';
    } else {
        // FORMAT TWO, REMOVED
        try {
            splitCommand = arguments[0].split(".");
            action = splitCommand.pop();
            service = splitCommand.join(".");
            actionArgs = Array.prototype.splice.call(arguments, 1);

            console.log('The old format of this exec call has been removed (deprecated since 2.1). Change to: ' +
                       "cordova.exec(null, null, \"" + service + "\", \"" + action + "\"," + JSON.stringify(actionArgs) + ");"
            );
            return;
        } catch (e) {}
    }

    // Register the callbacks and add the callbackId to the positional
    // arguments if given.
    if (successCallback || failCallback) {
        callbackId = service + cordova.callbackId++;
        cordova.callbacks[callbackId] =
            {success:successCallback, fail:failCallback};
    }

    actionArgs = massageArgsJsToNative(actionArgs);

    var command = [callbackId, service, action, actionArgs];

    // Stringify and queue the command. We stringify to command now to
    // effectively clone the command arguments in case they are mutated before
    // the command is executed.
    commandQueue.push(JSON.stringify(command));

    // If we're in the context of a stringByEvaluatingJavaScriptFromString call,
    // then the queue will be flushed when it returns; no need for a poke.
    // Also, if there is already a command in the queue, then we've already
    // poked the native side, so there is no reason to do so again.
    if (!isInContextOfEvalJs && commandQueue.length == 1) {
        switch (bridgeMode) {
        case jsToNativeModes.XHR_NO_PAYLOAD:
        case jsToNativeModes.XHR_WITH_PAYLOAD:
        case jsToNativeModes.XHR_OPTIONAL_PAYLOAD:
            // This prevents sending an XHR when there is already one being sent.
            // This should happen only in rare circumstances (refer to unit tests).
            if (execXhr && execXhr.readyState != 4) {
                execXhr = null;
            }
            // Re-using the XHR improves exec() performance by about 10%.
            execXhr = execXhr || new XMLHttpRequest();
            // Changing this to a GET will make the XHR reach the URIProtocol on 4.2.
            // For some reason it still doesn't work though...
            // Add a timestamp to the query param to prevent caching.
            execXhr.open('HEAD', "/!gap_exec?" + (+new Date()), true);
            if (!vcHeaderValue) {
                vcHeaderValue = /.*\((.*)\)/.exec(navigator.userAgent)[1];
            }
            execXhr.setRequestHeader('vc', vcHeaderValue);
            execXhr.setRequestHeader('rc', ++requestCount);
            if (shouldBundleCommandJson()) {
                execXhr.setRequestHeader('cmds', iOSExec.nativeFetchMessages());
            }
            execXhr.send(null);
            break;
        case jsToNativeModes.IFRAME_HASH_NO_PAYLOAD:
        case jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD:
            execHashIframe = execHashIframe || createHashIframe();
            // Check if they've removed it from the DOM, and put it back if so.
            if (!execHashIframe.contentWindow) {
                execHashIframe = createHashIframe();
            }
            // The delegate method is called only when the hash changes, so toggle it back and forth.
            hashToggle = hashToggle ^ 3;
            var hashValue = '%0' + hashToggle;
            if (bridgeMode === jsToNativeModes.IFRAME_HASH_WITH_PAYLOAD) {
                hashValue += iOSExec.nativeFetchMessages();
            }
            execHashIframe.contentWindow.location.hash = hashValue;
            break;
        default:
            execIframe = execIframe || createExecIframe();
            // Check if they've removed it from the DOM, and put it back if so.
            if (!execIframe.contentWindow) {
                execIframe = createExecIframe();
            }
            execIframe.src = "gap://ready";
        }
    }
}

iOSExec.jsToNativeModes = jsToNativeModes;

iOSExec.setJsToNativeBridgeMode = function(mode) {
    // Remove the iFrame since it may be no longer required, and its existence
    // can trigger browser bugs.
    // https://issues.apache.org/jira/browse/CB-593
    if (execIframe) {
        execIframe.parentNode.removeChild(execIframe);
        execIframe = null;
    }
    bridgeMode = mode;
};

iOSExec.nativeFetchMessages = function() {
    // Each entry in commandQueue is a JSON string already.
    if (!commandQueue.length) {
        return '';
    }
    var json = '[' + commandQueue.join(',') + ']';
    commandQueue.length = 0;
    return json;
};

iOSExec.nativeCallback = function(callbackId, status, message, keepCallback) {
    return iOSExec.nativeEvalAndFetch(function() {
        var success = status === 0 || status === 1;
        var args = convertMessageToArgsNativeToJs(message);
        cordova.callbackFromNative(callbackId, success, status, args, keepCallback);
    });
};

iOSExec.nativeEvalAndFetch = function(func) {
    // This shouldn't be nested, but better to be safe.
    isInContextOfEvalJs++;
    try {
        func();
        return iOSExec.nativeFetchMessages();
    } finally {
        isInContextOfEvalJs--;
    }
};

module.exports = iOSExec;

});

// file: src/common/exec/proxy.js
define("cordova/exec/proxy", function(require, exports, module) {


// internal map of proxy function
var CommandProxyMap = {};

module.exports = {

    // example: cordova.commandProxy.add("Accelerometer",{getCurrentAcceleration: function(successCallback, errorCallback, options) {...},...);
    add:function(id,proxyObj) {
        console.log("adding proxy for " + id);
        CommandProxyMap[id] = proxyObj;
        return proxyObj;
    },

    // cordova.commandProxy.remove("Accelerometer");
    remove:function(id) {
        var proxy = CommandProxyMap[id];
        delete CommandProxyMap[id];
        CommandProxyMap[id] = null;
        return proxy;
    },

    get:function(service,action) {
        return ( CommandProxyMap[service] ? CommandProxyMap[service][action] : null );
    }
};
});

// file: src/common/init.js
define("cordova/init", function(require, exports, module) {

var channel = require('cordova/channel');
var cordova = require('cordova');
var modulemapper = require('cordova/modulemapper');
var platform = require('cordova/platform');
var pluginloader = require('cordova/pluginloader');

var platformInitChannelsArray = [channel.onNativeReady, channel.onPluginsReady];

function logUnfiredChannels(arr) {
    for (var i = 0; i < arr.length; ++i) {
        if (arr[i].state != 2) {
            console.log('Channel not fired: ' + arr[i].type);
        }
    }
}

window.setTimeout(function() {
    if (channel.onDeviceReady.state != 2) {
        console.log('deviceready has not fired after 5 seconds.');
        logUnfiredChannels(platformInitChannelsArray);
        logUnfiredChannels(channel.deviceReadyChannelsArray);
    }
}, 5000);

// Replace navigator before any modules are required(), to ensure it happens as soon as possible.
// We replace it so that properties that can't be clobbered can instead be overridden.
function replaceNavigator(origNavigator) {
    var CordovaNavigator = function() {};
    CordovaNavigator.prototype = origNavigator;
    var newNavigator = new CordovaNavigator();
    // This work-around really only applies to new APIs that are newer than Function.bind.
    // Without it, APIs such as getGamepads() break.
    if (CordovaNavigator.bind) {
        for (var key in origNavigator) {
            if (typeof origNavigator[key] == 'function') {
                newNavigator[key] = origNavigator[key].bind(origNavigator);
            }
        }
    }
    return newNavigator;
}
if (window.navigator) {
    window.navigator = replaceNavigator(window.navigator);
}

if (!window.console) {
    window.console = {
        log: function(){}
    };
}
if (!window.console.warn) {
    window.console.warn = function(msg) {
        this.log("warn: " + msg);
    };
}

// Register pause, resume and deviceready channels as events on document.
channel.onPause = cordova.addDocumentEventHandler('pause');
channel.onResume = cordova.addDocumentEventHandler('resume');
channel.onDeviceReady = cordova.addStickyDocumentEventHandler('deviceready');

// Listen for DOMContentLoaded and notify our channel subscribers.
if (document.readyState == 'complete' || document.readyState == 'interactive') {
    channel.onDOMContentLoaded.fire();
} else {
    document.addEventListener('DOMContentLoaded', function() {
        channel.onDOMContentLoaded.fire();
    }, false);
}

// _nativeReady is global variable that the native side can set
// to signify that the native code is ready. It is a global since
// it may be called before any cordova JS is ready.
if (window._nativeReady) {
    channel.onNativeReady.fire();
}

modulemapper.clobbers('cordova', 'cordova');
modulemapper.clobbers('cordova/exec', 'cordova.exec');
modulemapper.clobbers('cordova/exec', 'Cordova.exec');

// Call the platform-specific initialization.
platform.bootstrap && platform.bootstrap();

pluginloader.load(function() {
    channel.onPluginsReady.fire();
});

/**
 * Create all cordova objects once native side is ready.
 */
channel.join(function() {
    modulemapper.mapModules(window);

    platform.initialize && platform.initialize();

    // Fire event to notify that all objects are created
    channel.onCordovaReady.fire();

    // Fire onDeviceReady event once page has fully loaded, all
    // constructors have run and cordova info has been received from native
    // side.
    channel.join(function() {
        require('cordova').fireDocumentEvent('deviceready');
    }, channel.deviceReadyChannelsArray);

}, platformInitChannelsArray);


});

// file: src/common/modulemapper.js
define("cordova/modulemapper", function(require, exports, module) {

var builder = require('cordova/builder'),
    moduleMap = define.moduleMap,
    symbolList,
    deprecationMap;

exports.reset = function() {
    symbolList = [];
    deprecationMap = {};
};

function addEntry(strategy, moduleName, symbolPath, opt_deprecationMessage) {
    if (!(moduleName in moduleMap)) {
        throw new Error('Module ' + moduleName + ' does not exist.');
    }
    symbolList.push(strategy, moduleName, symbolPath);
    if (opt_deprecationMessage) {
        deprecationMap[symbolPath] = opt_deprecationMessage;
    }
}

// Note: Android 2.3 does have Function.bind().
exports.clobbers = function(moduleName, symbolPath, opt_deprecationMessage) {
    addEntry('c', moduleName, symbolPath, opt_deprecationMessage);
};

exports.merges = function(moduleName, symbolPath, opt_deprecationMessage) {
    addEntry('m', moduleName, symbolPath, opt_deprecationMessage);
};

exports.defaults = function(moduleName, symbolPath, opt_deprecationMessage) {
    addEntry('d', moduleName, symbolPath, opt_deprecationMessage);
};

exports.runs = function(moduleName) {
    addEntry('r', moduleName, null);
};

function prepareNamespace(symbolPath, context) {
    if (!symbolPath) {
        return context;
    }
    var parts = symbolPath.split('.');
    var cur = context;
    for (var i = 0, part; part = parts[i]; ++i) {
        cur = cur[part] = cur[part] || {};
    }
    return cur;
}

exports.mapModules = function(context) {
    var origSymbols = {};
    context.CDV_origSymbols = origSymbols;
    for (var i = 0, len = symbolList.length; i < len; i += 3) {
        var strategy = symbolList[i];
        var moduleName = symbolList[i + 1];
        var module = require(moduleName);
        // <runs/>
        if (strategy == 'r') {
            continue;
        }
        var symbolPath = symbolList[i + 2];
        var lastDot = symbolPath.lastIndexOf('.');
        var namespace = symbolPath.substr(0, lastDot);
        var lastName = symbolPath.substr(lastDot + 1);

        var deprecationMsg = symbolPath in deprecationMap ? 'Access made to deprecated symbol: ' + symbolPath + '. ' + deprecationMsg : null;
        var parentObj = prepareNamespace(namespace, context);
        var target = parentObj[lastName];

        if (strategy == 'm' && target) {
            builder.recursiveMerge(target, module);
        } else if ((strategy == 'd' && !target) || (strategy != 'd')) {
            if (!(symbolPath in origSymbols)) {
                origSymbols[symbolPath] = target;
            }
            builder.assignOrWrapInDeprecateGetter(parentObj, lastName, module, deprecationMsg);
        }
    }
};

exports.getOriginalSymbol = function(context, symbolPath) {
    var origSymbols = context.CDV_origSymbols;
    if (origSymbols && (symbolPath in origSymbols)) {
        return origSymbols[symbolPath];
    }
    var parts = symbolPath.split('.');
    var obj = context;
    for (var i = 0; i < parts.length; ++i) {
        obj = obj && obj[parts[i]];
    }
    return obj;
};

exports.reset();


});

// file: src/ios/platform.js
define("cordova/platform", function(require, exports, module) {

module.exports = {
    id: 'ios',
    bootstrap: function() {
        require('cordova/channel').onNativeReady.fire();
    }
};


});

// file: src/common/pluginloader.js
define("cordova/pluginloader", function(require, exports, module) {

var modulemapper = require('cordova/modulemapper');
var urlutil = require('cordova/urlutil');

// Helper function to inject a <script> tag.
function injectScript(url, onload, onerror) {
    var script = document.createElement("script");
    // onload fires even when script fails loads with an error.
    script.onload = onload;
    script.onerror = onerror || onload;
    script.src = url;
    document.head.appendChild(script);
}

function onScriptLoadingComplete(moduleList, finishPluginLoading) {
    // Loop through all the plugins and then through their clobbers and merges.
    for (var i = 0, module; module = moduleList[i]; i++) {
        if (module) {
            try {
                if (module.clobbers && module.clobbers.length) {
                    for (var j = 0; j < module.clobbers.length; j++) {
                        modulemapper.clobbers(module.id, module.clobbers[j]);
                    }
                }

                if (module.merges && module.merges.length) {
                    for (var k = 0; k < module.merges.length; k++) {
                        modulemapper.merges(module.id, module.merges[k]);
                    }
                }

                // Finally, if runs is truthy we want to simply require() the module.
                // This can be skipped if it had any merges or clobbers, though,
                // since the mapper will already have required the module.
                if (module.runs && !(module.clobbers && module.clobbers.length) && !(module.merges && module.merges.length)) {
                    modulemapper.runs(module.id);
                }
            }
            catch(err) {
                // error with module, most likely clobbers, should we continue?
            }
        }
    }

    finishPluginLoading();
}

// Handler for the cordova_plugins.js content.
// See plugman's plugin_loader.js for the details of this object.
// This function is only called if the really is a plugins array that isn't empty.
// Otherwise the onerror response handler will just call finishPluginLoading().
function handlePluginsObject(path, moduleList, finishPluginLoading) {
    // Now inject the scripts.
    var scriptCounter = moduleList.length;

    if (!scriptCounter) {
        finishPluginLoading();
        return;
    }
    function scriptLoadedCallback() {
        if (!--scriptCounter) {
            onScriptLoadingComplete(moduleList, finishPluginLoading);
        }
    }

    for (var i = 0; i < moduleList.length; i++) {
        injectScript(path + moduleList[i].file, scriptLoadedCallback);
    }
}

function injectPluginScript(pathPrefix, finishPluginLoading) {
    var pluginPath = pathPrefix + 'cordova_plugins.js';

    injectScript(pluginPath, function() {
        try {
            var moduleList = require("cordova/plugin_list");
            handlePluginsObject(pathPrefix, moduleList, finishPluginLoading);
        }
        catch (e) {
            // Error loading cordova_plugins.js, file not found or something
            // this is an acceptable error, pre-3.0.0, so we just move on.
            finishPluginLoading();
        }
    }, finishPluginLoading); // also, add script load error handler for file not found
}

function findCordovaPath() {
    var path = null;
    var scripts = document.getElementsByTagName('script');
    var term = 'cordova.js';
    for (var n = scripts.length-1; n>-1; n--) {
        var src = scripts[n].src;
        if (src.indexOf(term) == (src.length - term.length)) {
            path = src.substring(0, src.length - term.length);
            break;
        }
    }
    return path;
}

// Tries to load all plugins' js-modules.
// This is an async process, but onDeviceReady is blocked on onPluginsReady.
// onPluginsReady is fired when there are no plugins to load, or they are all done.
exports.load = function(callback) {
    var pathPrefix = findCordovaPath();
    if (pathPrefix === null) {
        console.log('Could not find cordova.js script tag. Plugin loading may fail.');
        pathPrefix = '';
    }
    injectPluginScript(pathPrefix, callback);
};


});

// file: src/common/urlutil.js
define("cordova/urlutil", function(require, exports, module) {


/**
 * For already absolute URLs, returns what is passed in.
 * For relative URLs, converts them to absolute ones.
 */
exports.makeAbsolute = function makeAbsolute(url) {
    var anchorEl = document.createElement('a');
    anchorEl.href = url;
    return anchorEl.href;
};


});

// file: src/common/utils.js
define("cordova/utils", function(require, exports, module) {

var utils = exports;

/**
 * Defines a property getter / setter for obj[key].
 */
utils.defineGetterSetter = function(obj, key, getFunc, opt_setFunc) {
    if (Object.defineProperty) {
        var desc = {
            get: getFunc,
            configurable: true
        };
        if (opt_setFunc) {
            desc.set = opt_setFunc;
        }
        Object.defineProperty(obj, key, desc);
    } else {
        obj.__defineGetter__(key, getFunc);
        if (opt_setFunc) {
            obj.__defineSetter__(key, opt_setFunc);
        }
    }
};

/**
 * Defines a property getter for obj[key].
 */
utils.defineGetter = utils.defineGetterSetter;

utils.arrayIndexOf = function(a, item) {
    if (a.indexOf) {
        return a.indexOf(item);
    }
    var len = a.length;
    for (var i = 0; i < len; ++i) {
        if (a[i] == item) {
            return i;
        }
    }
    return -1;
};

/**
 * Returns whether the item was found in the array.
 */
utils.arrayRemove = function(a, item) {
    var index = utils.arrayIndexOf(a, item);
    if (index != -1) {
        a.splice(index, 1);
    }
    return index != -1;
};

utils.typeName = function(val) {
    return Object.prototype.toString.call(val).slice(8, -1);
};

/**
 * Returns an indication of whether the argument is an array or not
 */
utils.isArray = function(a) {
    return utils.typeName(a) == 'Array';
};

/**
 * Returns an indication of whether the argument is a Date or not
 */
utils.isDate = function(d) {
    return utils.typeName(d) == 'Date';
};

/**
 * Does a deep clone of the object.
 */
utils.clone = function(obj) {
    if(!obj || typeof obj == 'function' || utils.isDate(obj) || typeof obj != 'object') {
        return obj;
    }

    var retVal, i;

    if(utils.isArray(obj)){
        retVal = [];
        for(i = 0; i < obj.length; ++i){
            retVal.push(utils.clone(obj[i]));
        }
        return retVal;
    }

    retVal = {};
    for(i in obj){
        if(!(i in retVal) || retVal[i] != obj[i]) {
            retVal[i] = utils.clone(obj[i]);
        }
    }
    return retVal;
};

/**
 * Returns a wrapped version of the function
 */
utils.close = function(context, func, params) {
    if (typeof params == 'undefined') {
        return function() {
            return func.apply(context, arguments);
        };
    } else {
        return function() {
            return func.apply(context, params);
        };
    }
};

/**
 * Create a UUID
 */
utils.createUUID = function() {
    return UUIDcreatePart(4) + '-' +
        UUIDcreatePart(2) + '-' +
        UUIDcreatePart(2) + '-' +
        UUIDcreatePart(2) + '-' +
        UUIDcreatePart(6);
};

/**
 * Extends a child object from a parent object using classical inheritance
 * pattern.
 */
utils.extend = (function() {
    // proxy used to establish prototype chain
    var F = function() {};
    // extend Child from Parent
    return function(Child, Parent) {
        F.prototype = Parent.prototype;
        Child.prototype = new F();
        Child.__super__ = Parent.prototype;
        Child.prototype.constructor = Child;
    };
}());

/**
 * Alerts a message in any available way: alert or console.log.
 */
utils.alert = function(msg) {
    if (window.alert) {
        window.alert(msg);
    } else if (console && console.log) {
        console.log(msg);
    }
};


//------------------------------------------------------------------------------
function UUIDcreatePart(length) {
    var uuidpart = "";
    for (var i=0; i<length; i++) {
        var uuidchar = parseInt((Math.random() * 256), 10).toString(16);
        if (uuidchar.length == 1) {
            uuidchar = "0" + uuidchar;
        }
        uuidpart += uuidchar;
    }
    return uuidpart;
}


});

window.cordova = require('cordova');
// file: src/scripts/bootstrap.js

require('cordova/init');

})();
// file: 001-NumberFormat.js
/**  domain Javascript formatting utility.
Published in http://www.mredkj.com/javascript/nfdocs.html as a public domain work (no Copyright)
9-November-2005 - Modified by Tersus (Youval Bronicki):
	Move properties to the prototype to prevent each instance from being a big object
12-May-2008  - Modified by Tersus (Youval Bronicki):
    Added support for setting decimal point without separators
16-Nov-2008  - Modified by Tersus (Youval Bronicki):
    Changed toPercentage to use same formatting as toFormatted 
*/
/*
 * NumberFormat 1.5.3
 * v1.5.3 - 29-September-2004
 * v1.5.2 - 27-August-2004
 * v1.5.1 - 13-February-2004
 * v1.5.0 - 20-December-2002
 * v1.0.3 - 23-March-2002
 * v1.0.2 - 13-March-2002
 * v1.0.1 - 20-July-2001
 * v1.0.0 - 13-April-2000
 * http://www.mredkj.com
 */
  
/*
 * NumberFormat -The constructor
 * num - The number to be formatted.
 *  Also refer to setNumber
 * inputDecimal - (Optional) The decimal character for the input
 *  Also refer to setInputDecimal
 */
function NumberFormat() {};
	// constants
	NumberFormat.prototype.COMMA = ',';
	NumberFormat.prototype.PERIOD = '.';
	NumberFormat.prototype.DASH = '-'; // v1.5.0 - new - used internally
	NumberFormat.prototype.LEFT_PAREN = '('; // v1.5.0 - new - used internally
	NumberFormat.prototype.RIGHT_PAREN = ')'; // v1.5.0 - new - used internally
	NumberFormat.prototype.LEFT_OUTSIDE = 0; // v1.5.0 - new - currency
	NumberFormat.prototype.LEFT_INSIDE = 1;  // v1.5.0 - new - currency
	NumberFormat.prototype.RIGHT_INSIDE = 2;  // v1.5.0 - new - currency
	NumberFormat.prototype.RIGHT_OUTSIDE = 3;  // v1.5.0 - new - currency
	NumberFormat.prototype.LEFT_DASH = 0; // v1.5.0 - new - negative
	NumberFormat.prototype.RIGHT_DASH = 1; // v1.5.0 - new - negative
	NumberFormat.prototype.PARENTHESIS = 2; // v1.5.0 - new - negative
	NumberFormat.prototype.NO_ROUNDING = -1 // v1.5.1 - new

	// member variables
	NumberFormat.prototype.num = null;
	NumberFormat.prototype.numOriginal = null;
	NumberFormat.prototype.hasSeparators = null;  // v1.5.0 - new
	NumberFormat.prototype.separatorValue = NumberFormat.prototype.COMMA;  // v1.5.0 - new
	NumberFormat.prototype.inputDecimalValue = NumberFormat.prototype.PERIOD; // v1.5.0 - new
	NumberFormat.prototype.decimalValue = NumberFormat.prototype.PERIOD;  // v1.5.0 - new
	NumberFormat.prototype.negativeFormat = NumberFormat.prototype.LEFT_DASH; // v1.5.0 - new
	NumberFormat.prototype.negativeRed = false; // v1.5.0 - new
	NumberFormat.prototype.hasCurrency = false;  // v1.5.0 - modified
	NumberFormat.prototype.currencyPosition = NumberFormat.prototype.LEFT_INSIDE;  // v1.5.0 - new
	NumberFormat.prototype.currencyValue = '$';  // v1.5.0 - modified
	NumberFormat.prototype.places = NumberFormat.prototype.NO_ROUNDING;
	NumberFormat.prototype.roundToPlaces = null; // v1.5.1 - new

	// external methods
	NumberFormat.prototype.setNumber = setNumberNF;
	NumberFormat.prototype.toUnformatted = toUnformattedNF;
	NumberFormat.prototype.setInputDecimal = setInputDecimalNF; // v1.5.0 - new
	NumberFormat.prototype.setSeparators = setSeparatorsNF; // v1.5.0 - new - for separators and decimals
	NumberFormat.prototype.setCommas = setCommasNF;
	NumberFormat.prototype.setNegativeFormat = setNegativeFormatNF; // v1.5.0 - new
	NumberFormat.prototype.setNegativeRed = setNegativeRedNF; // v1.5.0 - new
	NumberFormat.prototype.setCurrency = setCurrencyNF;
	NumberFormat.prototype.setCurrencyPrefix = setCurrencyPrefixNF;
	NumberFormat.prototype.setCurrencyValue = setCurrencyValueNF; // v1.5.0 - new - setCurrencyPrefix uses this
	NumberFormat.prototype.setCurrencyPosition = setCurrencyPositionNF; // v1.5.0 - new - setCurrencyPrefix uses this
	NumberFormat.prototype.setPlaces = setPlacesNF;
	NumberFormat.prototype.toFormatted = toFormattedNF;
	NumberFormat.prototype.toPercentage = toPercentageNF;
	NumberFormat.prototype.getOriginal = getOriginalNF;
	NumberFormat.prototype.moveDecimalRight = moveDecimalRightNF;
	NumberFormat.prototype.moveDecimalLeft = moveDecimalLeftNF;

	// internal methods
	NumberFormat.prototype.getRounded = getRoundedNF;
	NumberFormat.prototype.preserveZeros = preserveZerosNF;
	NumberFormat.prototype.justNumber = justNumberNF;
	NumberFormat.prototype.expandExponential = expandExponentialNF;
	NumberFormat.prototype.getZeros = getZerosNF;
	NumberFormat.prototype.moveDecimalAsString = moveDecimalAsStringNF;
	NumberFormat.prototype.moveDecimal = moveDecimalNF;
	NumberFormat.prototype.addSeparators = addSeparatorsNF;



/*
 * setInputDecimal
 * val - The decimal value for the input.
 *
 * v1.5.0 - new
 */
function setInputDecimalNF(val)
{
	this.inputDecimalValue = val;
}

/*
 * setNumber - Sets the number
 * num - The number to be formatted
 * inputDecimal - (Optional) The decimal character for the input
 *  Also refer to setInputDecimal
 * 
 * If there is a non-period decimal format for the input,
 * setInputDecimal should be called before calling setNumber.
 *
 * v1.5.0 - modified
 */
function setNumberNF(num, inputDecimal)
{
	if (inputDecimal != null) {
		this.setInputDecimal(inputDecimal); // v.1.5.1 - new
	}
	
	this.numOriginal = num;
	this.num = this.justNumber(num);
}

/*
 * toUnformatted - Returns the number as just a number.
 * If the original value was '100,000', then this method will return the number 100000
 * v1.0.2 - Modified comments, because this method no longer returns the original value.
 */
function toUnformattedNF()
{
	return (this.num);
}

/*
 * getOriginal - Returns the number as it was passed in, which may include non-number characters.
 * This function is new in v1.0.2
 */
function getOriginalNF()
{
	return (this.numOriginal);
}

/*
 * setNegativeFormat - How to format a negative number.
 * 
 * format - The format. Use one of the following constants.
 * LEFT_DASH   example: -1000
 * RIGHT_DASH  example: 1000-
 * PARENTHESIS example: (1000)
 *
 * v1.5.0 - new
 */
function setNegativeFormatNF(format)
{
	this.negativeFormat = format;
}

/*
 * setNegativeRed - Format the number red if it's negative.
 * 
 * isRed - true, to format the number red if negative, black if positive;
 *  false, for it to always be black font.
 *
 * v1.5.0 - new
 */
function setNegativeRedNF(isRed)
{
	this.negativeRed = isRed;
}

/*
 * setSeparators - One purpose of this method is to set a
 *  switch that indicates if there should be separators between groups of numbers.
 *  Also, can use it to set the values for the separator and decimal.
 *  For example, in the value 1,000.00
 *   The comma (,) is the separator and the period (.) is the decimal.
 *
 * Both separator or decimal are not required.
 * The separator and decimal cannot be the same value. If they are, decimal with be changed.
 * Can use the following constants (via the instantiated object) for separator or decimal:
 *  COMMA
 *  PERIOD
 * 
 * isC - true, if there should be separators; false, if there should be no separators
 * separator - the value of the separator.
 * decimal - the value of the decimal.
 *
 * v1.5.0 - new
 */
function setSeparatorsNF(isC, separator, decimal)
{
	this.hasSeparators = isC;
	
	// Make sure a separator was passed in
	if (separator == null) separator = this.COMMA;
	
	// Make sure a decimal was passed in
	if (decimal == null) decimal = this.PERIOD;
	
	// Additionally, make sure the values aren't the same.
	//  When the separator and decimal both are periods, make the decimal a comma.
	//  When the separator and decimal both are any other value, make the decimal a period.
	if (separator == decimal) {
		this.decimalValue = (decimal == this.PERIOD) ? this.COMMA : this.PERIOD;
	} else {
		this.decimalValue = decimal;
	}
	
	// Since the decimal value changes if decimal and separator are the same,
	// the separator value can keep its setting.
	this.separatorValue = separator;
}

/*
 * setCommas - Sets a switch that indicates if there should be commas.
 * The separator value is set to a comma and the decimal value is set to a period.
 * isC - true, if the number should be formatted with separators (commas); false, if no separators
 *
 * v1.5.0 - modified
 */
function setCommasNF(isC)
{
	this.setSeparators(isC, this.COMMA, this.PERIOD);
}

/*
 * setCurrency - Sets a switch that indicates if should be displayed as currency
 * isC - true, if should be currency; false, if not currency
 */
function setCurrencyNF(isC)
{
	this.hasCurrency = isC;
}

/*
 * setCurrencyPrefix - Sets the symbol for currency.
 * val - The symbol
 */
function setCurrencyValueNF(val)
{
	this.currencyValue = val;
}

/*
 * setCurrencyPrefix - Sets the symbol for currency.
 * The symbol will show up on the left of the numbers and outside a negative sign.
 * cp - The symbol
 *
 * v1.5.0 - modified - This now calls setCurrencyValue and setCurrencyPosition(this.LEFT_OUTSIDE)
 */
function setCurrencyPrefixNF(cp)
{
	this.setCurrencyValue(cp);
	this.setCurrencyPosition(this.LEFT_OUTSIDE);
}

/*
 * setCurrencyPosition - Sets the position for currency,
 *  which includes position relative to the numbers and negative sign.
 * cp - The position. Use one of the following constants.
 *  This method does not automatically put the negative sign at the left or right.
 *  They are left by default, and would need to be set right with setNegativeFormat.
 *	LEFT_OUTSIDE  example: $-1.00
 *	LEFT_INSIDE   example: -$1.00
 *	RIGHT_INSIDE  example: 1.00$-
 *	RIGHT_OUTSIDE example: 1.00-$
 *
 * v1.5.0 - new
 */
function setCurrencyPositionNF(cp)
{
	this.currencyPosition = cp
}

/*
 * setPlaces - Sets the precision of decimal places
 * p - The number of places.
 *  -1 or the constant NO_ROUNDING turns off rounding to a set number of places.
 *  Any other number of places less than or equal to zero is considered zero.
 *
 * v1.5.1 - modified
 */
function setPlacesNF(p)
{
	this.roundToPlaces = !(p == this.NO_ROUNDING); // v1.5.1
	this.places = (p < 0) ? 0 : p; // v1.5.1 - Don't leave negatives.
}

/*
 * v1.5.2 - new
 *
 * addSeparators
 * The value to be formatted shouldn't have any formatting already.
 *
 * nStr - A number or number as a string
 * inD - Input decimal (string value). Example: '.'
 * outD - Output decimal (string value). Example: '.'
 * sep - Output separator (string value). Example: ','
 */
function addSeparatorsNF(nStr, inD, outD, sep)
{
	nStr += '';
	var dpos = nStr.indexOf(inD);
	var nStrEnd = '';
	if (dpos != -1) {
		nStrEnd = outD + nStr.substring(dpos + 1, nStr.length);
		nStr = nStr.substring(0, dpos);
	}
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(nStr)) {
		nStr = nStr.replace(rgx, '$1' + sep + '$2');
	}
	return nStr + nStrEnd;
}

/*
 * toFormatted - Returns the number formatted according to the settings (a string)
 *
 * v1.5.0 - modified
 * v1.5.1 - modified
 */
function toFormattedNF(v)
{	
	var pos;
	var nNum = v!=null ? v : this.num; // v1.0.1 - number as a number
	var nStr;            // v1.0.1 - number as a string
	var splitString = new Array(2);   // v1.5.0
	
	// round decimal places - modified v1.5.1
	// Note: Take away negative temporarily with Math.abs
	if (this.roundToPlaces) {
		nNum = this.getRounded(nNum);
		nStr = this.preserveZeros(Math.abs(nNum)); // this step makes nNum into a string. v1.0.1 Math.abs
	} else {
		nStr = this.expandExponential(Math.abs(nNum)); // expandExponential is called in preserveZeros, so call it here too
	}
	
	// v1.5.3 - lost the if in 1.5.2, so putting it back
	if (this.hasSeparators) {
		// v1.5.2
		// Note that the argument being passed in for inD is this.PERIOD
		//  That's because the toFormatted method is working with an unformatted number
		nStr = this.addSeparators(nStr, this.PERIOD, this.decimalValue, this.separatorValue);
	}
	else
	{
		// still need to set the decimal period (which could have been overridden)
		nStr = nStr.replace(/\./g,this.decimalValue);
	}
	
	// negative and currency
	// $[c0] -[n0] $[c1] -[n1] #.#[nStr] -[n2] $[c2] -[n3] $[c3]
	var c0 = '';
	var n0 = '';
	var c1 = '';
	var n1 = '';
	var n2 = '';
	var c2 = '';
	var n3 = '';
	var c3 = '';
	var negSignL = (this.negativeFormat == this.PARENTHESIS) ? this.LEFT_PAREN : this.DASH;
	var negSignR = (this.negativeFormat == this.PARENTHESIS) ? this.RIGHT_PAREN : this.DASH;
		
	if (this.currencyPosition == this.LEFT_OUTSIDE) {
		// add currency sign in front, outside of any negative. example: $-1.00	
		if (nNum < 0) {
			if (this.negativeFormat == this.LEFT_DASH || this.negativeFormat == this.PARENTHESIS) n1 = negSignL;
			if (this.negativeFormat == this.RIGHT_DASH || this.negativeFormat == this.PARENTHESIS) n2 = negSignR;
		}
		if (this.hasCurrency) c0 = this.currencyValue;
	} else if (this.currencyPosition == this.LEFT_INSIDE) {
		// add currency sign in front, inside of any negative. example: -$1.00
		if (nNum < 0) {
			if (this.negativeFormat == this.LEFT_DASH || this.negativeFormat == this.PARENTHESIS) n0 = negSignL;
			if (this.negativeFormat == this.RIGHT_DASH || this.negativeFormat == this.PARENTHESIS) n3 = negSignR;
		}
		if (this.hasCurrency) c1 = this.currencyValue;
	}
	else if (this.currencyPosition == this.RIGHT_INSIDE) {
		// add currency sign at the end, inside of any negative. example: 1.00$-
		if (nNum < 0) {
			if (this.negativeFormat == this.LEFT_DASH || this.negativeFormat == this.PARENTHESIS) n0 = negSignL;
			if (this.negativeFormat == this.RIGHT_DASH || this.negativeFormat == this.PARENTHESIS) n3 = negSignR;
		}
		if (this.hasCurrency) c2 = this.currencyValue;
	}
	else if (this.currencyPosition == this.RIGHT_OUTSIDE) {
		// add currency sign at the end, outside of any negative. example: 1.00-$
		if (nNum < 0) {
			if (this.negativeFormat == this.LEFT_DASH || this.negativeFormat == this.PARENTHESIS) n1 = negSignL;
			if (this.negativeFormat == this.RIGHT_DASH || this.negativeFormat == this.PARENTHESIS) n2 = negSignR;
		}
		if (this.hasCurrency) c3 = this.currencyValue;
	}

	nStr = c0 + n0 + c1 + n1 + nStr + n2 + c2 + n3 + c3;
	
	// negative red
	if (this.negativeRed && nNum < 0) {
		nStr = '<font color="red">' + nStr + '</font>';
	}

	return (nStr);
}

/*
 * 2008-11-16 (Tersus - uses same formatting as toFormatted)
 * toPercentage - Format the current number as a percentage.
 * This is separate from most of the regular formatting settings.
 * The exception is the number of decimal places.
 * If a number is 0.123 it will be formatted as 12.3%
 *
 * !! This is an initial version, so it doesn't use many settings.
 * !! should use some of the formatting settings that toFormatted uses.
 * !! probably won't want to use settings like currency.
 *
 * v1.5.0 - new
 */
function toPercentageNF()
{
	nNum = this.num * 100;
	
	// round decimal places
	nNum = this.toFormatted(nNum);
	
	return nNum + '%';
}

/*
 * Return concatenated zeros as a string. Used to pad a number.
 * It might be extra if already have many decimal places
 * but is needed if the number doesn't have enough decimals. 
 */
function getZerosNF(places)
{
		var extraZ = '';
		var i;
		for (i=0; i<places; i++) {
			extraZ += '0';
		}
		return extraZ;
}

/*
 * Takes a number that JavaScript expresses in notational format
 * and makes it the full number (as a string).
 * e.g. Makes -1e-21 into -0.000000000000000000001
 *
 * If the value passed in is not a number (as determined by isNaN),
 * this function just returns the original value.
 *
 * Exponential number formats can include 1e21 1e+21 1e-21
 *  where 1e21 and 1e+21 are the same thing.
 *
 * If an exponential number is evaluated by JavaScript,
 * it will change 12.34e-9 to 1.234e-8,
 * which is a benefit to this method, because
 * it prevents extra zeros that occur for certain numbers
 * when using moveDecimalAsString
 *
 * Returns a string.
 *
 * v1.5.1 - new
 */
function expandExponentialNF(origVal)
{
	if (isNaN(origVal)) return origVal;

	var newVal = parseFloat(origVal) + ''; // parseFloat to let JavaScript evaluate number
	var eLoc = newVal.toLowerCase().indexOf('e');

	if (eLoc != -1) {
		var plusLoc = newVal.toLowerCase().indexOf('+');
		var negLoc = newVal.toLowerCase().indexOf('-', eLoc); // search for - after the e
		var justNumber = newVal.substring(0, eLoc);
		
		if (negLoc != -1) {
			// shift decimal to the left
			var places = newVal.substring(negLoc + 1, newVal.length);
			justNumber = this.moveDecimalAsString(justNumber, true, parseInt(places));
		} else {
			// shift decimal to the right
			// Check if there's a plus sign, and if not refer to where the e is.
			// This is to account for either formatting 1e21 or 1e+21
			if (plusLoc == -1) plusLoc = eLoc;
			var places = newVal.substring(plusLoc + 1, newVal.length);
			justNumber = this.moveDecimalAsString(justNumber, false, parseInt(places));
		}
		
		newVal = justNumber;
	}

	return newVal;
} 

/*
 * Move decimal right.
 * Returns a number.
 *
 * v1.5.1 - new
 */
function moveDecimalRightNF(val, places)
{
	var newVal = '';
	
	if (places == null) {
		newVal = this.moveDecimal(val, false);
	} else {
		newVal = this.moveDecimal(val, false, places);
	}
	
	return newVal;
}

/*
 * Move decimal left.
 * Returns a number.
 *
 * v1.5.1 - new
 */
function moveDecimalLeftNF(val, places)
{
	var newVal = '';
	
	if (places == null) {
		newVal = this.moveDecimal(val, true);
	} else {
		newVal = this.moveDecimal(val, true, places);
	}
	
	return newVal;
}

/*
 * moveDecimalAsString
 * This is used by moveDecimal, and does not run parseFloat on the return value.
 * 
 * Normally a decimal place is moved by multiplying by powers of 10
 * Multiplication and division in JavaScript can result in floating point limitations.
 * So use this method to move a decimal place left or right.
 *
 * Parameters:
 * val - The value to be shifted. Can be a number or a string,
 *  but don't include special characters. It should evaluate to a number.
 * left - If true, then move decimal left. If false, move right.
 * places - (optional) If not included, then use the objects this.places
 *  The purpose is so this method can be used independent of the state of the object.
 *
 * The regular expressions:
 * re1
 * Pad with zeros in case there aren't enough numbers to cover the spaces shift.
 * A left shift pads to the left, and a right shift pads to the right.
 * Can't just concatenate. There might be a negative sign or the value could be an exponential.
 *
 * re2
 * Switch the decimal.
 * Need the first [0-9]+ to force the search to start rightmost.
 * The \.? and [0-9]{} criteria are the pieces that will be switched
 *
 * Other notes:
 * This method works on exponential numbers, e.g. 1.7e-12
 * because the regular expressions only modify the number and decimal parts.
 *
 * Mozilla can't handle [0-9]{0} in the regular expression.
 *  Fix: Since nothing changes when the decimal is shifted zero places, return the original value.
 *
 * IE is incorrect if exponential ends in .
 *  e.g. -8500000000000000000000. should be -8.5e+21
 *  IE counts it as -8.5e+22
 *	Fix: Replace trailing period, if there is one, using replace(/\.$/, '').
 *
 * Netscape 4.74 cannot handle a leading - in the string being searched for the re2 expressions.
 *  e.g. /([0-9]*)(\.?)([0-9]{2})/ should match everything in -100.00 except the -
 *  but it matches nothing using Netscape 4.74.
 *  It might be a combination of the * ? special characters.
 *  Fix: (-?) was added to each of the re2 expressions to look for - one or zero times.
 *
 * Returns a string.
 *
 * v1.5.1 - new
 * v1.5.2 - modified
 */
function moveDecimalAsStringNF(val, left, places)
{
	var spaces = (arguments.length < 3) ? this.places : places;
	if (spaces <= 0) return val; // to avoid Mozilla limitation
			
	var newVal = val + '';
	var extraZ = this.getZeros(spaces);
	var re1 = new RegExp('([0-9.]+)');
	if (left) {
		newVal = newVal.replace(re1, extraZ + '$1');
		var re2 = new RegExp('(-?)([0-9]*)([0-9]{' + spaces + '})(\\.?)');		
		newVal = newVal.replace(re2, '$1$2.$3');
	} else {
		var reArray = re1.exec(newVal); // v1.5.2
		if (reArray != null) {
			newVal = newVal.substring(0,reArray.index) + reArray[1] + extraZ + newVal.substring(reArray.index + reArray[0].length); // v1.5.2
		}
		var re2 = new RegExp('(-?)([0-9]*)(\\.?)([0-9]{' + spaces + '})');
		newVal = newVal.replace(re2, '$1$2$4.');
	}
	newVal = newVal.replace(/\.$/, ''); // to avoid IE flaw
	
	return newVal;
}

/*
 * moveDecimal
 * Refer to notes in moveDecimalAsString
 * parseFloat is called here to clear away the padded zeros.
 *
 * Returns a number.
 *
 * v1.5.1 - new
 */
function moveDecimalNF(val, left, places)
{
	var newVal = '';
	
	if (places == null) {
		newVal = this.moveDecimalAsString(val, left);
	} else {
		newVal = this.moveDecimalAsString(val, left, places);
	}
	
	return parseFloat(newVal);
}

/*
 * getRounded - Used internally to round a value
 * val - The number to be rounded
 * 
 *  To round to a certain decimal precision,
 *  all that should need to be done is
 *  multiply by a power of 10, round, then divide by the same power of 10.
 *  However, occasional numbers don't get exact results in most browsers.
 *  e.g. 0.295 multiplied by 10 yields 2.9499999999999997 instead of 2.95
 *  Instead of adjusting the incorrect multiplication,
 *  this function uses string manipulation to shift the decimal.
 *
 * Returns a number.
 *
 * v1.5.1 - modified
 */
function getRoundedNF(val)
{
	val = this.moveDecimalRight(val);
	val = Math.round(val);
	val = this.moveDecimalLeft(val);
	
	return val;
}

/*
 * preserveZeros - Used internally to make the number a string
 * 	that preserves zeros at the end of the number
 * val - The number
 */
function preserveZerosNF(val)
{
	var i;

	// make a string - to preserve the zeros at the end
	val = this.expandExponential(val);
	
	if (this.places <= 0) return val; // leave now. no zeros are necessary - v1.0.1 less than or equal
	
	var decimalPos = val.indexOf('.');
	if (decimalPos == -1) {
		val += '.';
		for (i=0; i<this.places; i++) {
			val += '0';
		}
	} else {
		var actualDecimals = (val.length - 1) - decimalPos;
		var difference = this.places - actualDecimals;
		for (i=0; i<difference; i++) {
			val += '0';
		}
	}
	
	return val;
}

/*
 * justNumber - Used internally to parse the value into a floating point number.
 * Replace all characters that are not 0-9, a decimal point, or a negative sign.
 *
 *  A number can be entered using special notation.
 *  For example, the following is a valid number: 0.0314E+2
 *
 * v1.0.2 - new
 * v1.5.0 - modified
 * v1.5.1 - modified
 * v1.5.2 - modified
 */
function justNumberNF(val)
{
	newVal = val + '';
	
	var isPercentage = false;
	
	// check for percentage
	// v1.5.0
	if (newVal.indexOf('%') != -1) {
		newVal = newVal.replace(/\%/g, '');
		isPercentage = true; // mark a flag
	}
		
	// Replace everything but digits - + ( ) e E
	var re = new RegExp('[^\\' + this.inputDecimalValue + '\\d\\-\\+\\(\\)eE]', 'g');	// v1.5.2	
	newVal = newVal.replace(re, '');
	// Replace the first decimal with a period and the rest with blank
	// The regular expression will only break if a special character
	//  is used as the inputDecimalValue
	//  e.g. \ but not .
	var tempRe = new RegExp('[' + this.inputDecimalValue + ']', 'g');
	var treArray = tempRe.exec(newVal); // v1.5.2
	if (treArray != null) {
	  var tempRight = newVal.substring(treArray.index + treArray[0].length); // v1.5.2
		newVal = newVal.substring(0,treArray.index) + this.PERIOD + tempRight.replace(tempRe, ''); // v1.5.2
	}
	
	// If negative, get it in -n format
	if (newVal.charAt(newVal.length - 1) == this.DASH ) {
		newVal = newVal.substring(0, newVal.length - 1);
		newVal = '-' + newVal;
	}
	else if (newVal.charAt(0) == this.LEFT_PAREN
	 && newVal.charAt(newVal.length - 1) == this.RIGHT_PAREN) {
		newVal = newVal.substring(1, newVal.length - 1);
		newVal = '-' + newVal;
	}
	
	newVal = parseFloat(newVal);
	
	if (!isFinite(newVal)) {
		newVal = 0;
  }
	
	// now that it's a number, adjust for percentage, if applicable.
  // example. if the number was formatted 24%, then move decimal left to get 0.24
  // v1.5.0 - updated v1.5.1
  if (isPercentage) {
  	newVal = this.moveDecimalLeft(newVal, 2);
  }
		
	return newVal;
}

// file: 002-cookies.js
/* cookies.js */
/*
     Example File From "JavaScript and DHTML Cookbook"
     Published by O'Reilly & Associates
     Copyright 2003 Danny Goodman
*/

// utility function to retrieve a future expiration date in proper format;
// pass three integer parameters for the number of days, hours,
// and minutes from now you want the cookie to expire; all three
// parameters required, so use zeros where appropriate
function getExpDate(days, hours, minutes) {
    var expDate = new Date();
    if (typeof days == "number" && typeof hours == "number" && typeof hours == "number") {
        expDate.setDate(expDate.getDate() + parseInt(days));
        expDate.setHours(expDate.getHours() + parseInt(hours));
        expDate.setMinutes(expDate.getMinutes() + parseInt(minutes));
        return expDate.toGMTString();
    }
}

// utility function called by getCookie()
function getCookieVal(offset) {
    var endstr = document.cookie.indexOf (";", offset);
    if (endstr == -1) {
        endstr = document.cookie.length;
    }
    return unescape(document.cookie.substring(offset, endstr));
}

// primary function to retrieve cookie by name
function getCookie(name) {
    var arg = name + "=";
    var alen = arg.length;
    var cookie = document.cookie;
    var clen = cookie.length;
    var i = 0;
    while (i < clen) {
        var j = i + alen;
        if (cookie.substring(i, j) == arg) {
            return getCookieVal(j);
        }
        i = cookie.indexOf(" ", i) + 1;
        if (i == 0) break; 
    }
    return null;
}

// store cookie value with optional details as needed
function setCookie(name, value, expires, path, domain, secure) {
    document.cookie = name + "=" + escape (value) +
        ((expires) ? "; expires=" + expires : "") +
        ((path) ? "; path=" + path : "") +
        ((domain) ? "; domain=" + domain : "") +
        ((secure) ? "; secure" : "");
}

// remove the cookie by setting ancient expiration date
function deleteCookie(name,path,domain) {
    if (getCookie(name)) {
        document.cookie = name + "=" +
            ((path) ? "; path=" + path : "") +
            ((domain) ? "; domain=" + domain : "") +
            "; expires=Thu, 01-Jan-70 00:00:01 GMT";
    }
}


// file: 003-datagrid.js
(function($) {
    function isResizeLeft(e, $th) {
        return e.pageX <= $th.offset().left + 5;
    };
    function isResizeRight(e, $th) {
        return e.pageX >= $th.offset().left + $th.outerWidth() - 5;
    };
    function isResize(e, $th) {
        return isResizeLeft(e, $th) || isResizeRight(e, $th);
    };
    function scrollbarWidth() {
        var outer = $(
            '<div style="position:absolute;top:-200px;left:-200px;width:100px;height:100px;overflow:hidden;border:1px solid black;"/>')
            .appendTo(document.body);
        var inner = $('<div style="height:300px;border:0px;padding:0px;"/>')
            .appendTo(outer);
        var fullWidth = inner.width();
        outer.css('overflow-y', 'scroll');
        var w = fullWidth - inner.width();
        if (w == 0)
            w = fullWidth - outer[0].clientWidth;
        outer.remove();
        return w;
    };
    function move($list, from, to, nchildren) {
        $list.each(function() {
            var parent = this;
            var children = parent.children;
	    if (children.length != nchildren)
		return true;
            var childFrom = children[from];
            var childTo = null;
            if (to < children.length) {
                childTo = children[to];
            }
            parent.insertBefore(childFrom, childTo);
        });
    };
    function permute(p, from, to)
    {
	var e = p.splice(from,1)[0];
	if (from < to)
	    --to;
	p.splice(to,0,e);
    };


    $.widget(
        'tersus.datagrid',
        {
	    
            options : {
                scrollable : false,
                resizableColumns : true,
                movableColumns : true,
                sortable : null
            }

            ,
            _create : function() {
                this.setWindow();
                this.setHeaderRow();
                if (this.options.scrollable)
                    this.initScrollable();
                else
                    this.initNonScrollable();
// Commented out to enable dynamic column order in the non-movable case, which might affect performance
//		if (this.options.movableColumns)
		    this.trackContent();
            }

            ,
            destroy : function() {
                $.Widget.prototype.destroy.call(this);
            }

            ,
            _setOption : function(key, value) {
                switch (key) {
                case "myoption":
                    // handle changes to option
                    break;
                }
                $.Widget.prototype._setOption
                    .apply(this, arguments);
            }

            ,
            initScrollable : function() {
                var self = this;
//                this.element.css('width', 'auto');
                if (this.element.is('table')) {
                    this.bodyTable = this.element;
                    this.body = this.bodyTable.wrap('<div class="body">').parent();
                    this.body.wrap('<div class="datagrid">');
                    this.top = this.body.parent();
		    this.top.css('height','100%');
                } 
		else
		{
                    this.top = this.element;
		    this.bodyTable = this.top.children('table'); 
		    if (this.bodyTable.length != 1)
			throw ('Data Grid container should contain exactly one table');
                    this.body = this.bodyTable.wrap('<div class="body">').parent();
	        }
		this.top.addClass('scrollable');
		/* create a header DIV */
                this.head = $('<div class="head"/>').prependTo(this.top);
		/* create a header TABLE with same class as original table (this may copy styling attributes, but will not always work ..)*/
                this.headTable = $('<table>').appendTo(this.head).addClass(this.bodyTable.attr('class'));
		this.top.addClass('datagrid');
                this.body.width(this.top.innerWidth());
		self.top[0].offsetTop;
               this.measureDefaultWidths();
                this.bodyTable.children('caption,thead').appendTo(
                    this.headTable);
		this.tables = this.headTable.add(this.bodyTable);
		/* Create a footer DIV and TABLE if TFOOT elements are present */
		var $tfoot = this.bodyTable.children('tfoot');
                var sw = scrollbarWidth();
		if ($tfoot.length > 0)
		{
                    this.footer = $('<div class="footer"/>').css('bottom',sw).appendTo(this.top);
                    this.footerTable = $('<table>').appendTo(this.footer).addClass(this.bodyTable.attr('class'));
		    $tfoot.appendTo(this.footerTable);
		    this.tables=this.tables.add(this.footerTable);
		}
                this.initCols();
                // If needed - move thead to 'head' div
                this.head.width(this.top.innerWidth() - sw);
                if(this.footer)
		    this.footer.width(this.top.innerWidth() - sw);
                this.body.width(this.top.innerWidth());
		self.top[0].offsetTop;
                this.setColWidths(true);
                this.body.on('scroll', function(e) {
                    self.head.scrollLeft(self.body.scrollLeft());
                    if (self.footer) 
			self.footer.scrollLeft(self.body.scrollLeft());
                });
                this.applyLayout();
            },
            applyLayout : function() {
		var self = this;
		if (self.layoutRequested)
		    return;
		self.layoutRequested=true;
                setTimeout(function() {
		    self.layoutRequested=false;
                    self.tables.show();
		    if (self.head && self.body) /*scrollable*/
		    {
			self.top[0].offsetTop;
			self.body.css('top',self.head.outerHeight());
			if (self.footer)
			{
			    self.body.css('padding-bottom',self.footer.outerHeight()-parseInt(self.bodyTable.css('border-bottom-width')));
			}
		    }
                }, 2);
		
            },
	    trackContent: function()
	    {
		var self = this;
		this.top.find('tr').data('tracked',true);
		this.top.on('DOMSubtreeModified.datagrid',function() {
//		    console.log('DOMSubtreeModified');
		    self.top.find('tr').each(function(index,row) {
			setTimeout(function() {
			    if (! $(row).data('tracked'))
			    {
				if (self.applyPermutationAndVisibility(row))
				{
				    $(row).data('tracked',true);
//				    console.log('New row tracked');
				}
			    }
			},0);
			self.applyLayout();
		    });
			
		});
			       
	    },
            setHeaderRow : function() {
                var self = this;

                this.headerRow = this.element.find('thead>tr')
                    .first();

                if (this.options.resizableColumns
                    || this.options.movableColumns) {
                    this.headerRow
                        .children('th')
                        .on(
                            {
                                'mouseover mousemove' : function(
                                    e) {
                                    if (self.options.resizableColumns
                                        && isResize(e,
                                                    $(this))) {
                                        $(this).addClass('resize');
                                    } else
                                        $(this).removeClass('resize');
                                },
                                'mousedown' : function(e) {
                                    self.mouseDown(e,$(this));
                                },
                                'mouseout' : function(e) {
                                    $(this).removeClass('resize');
                                }
                            });
                }

                var sortable = this.options.sortable;
                if (sortable) {
                    this.headerRow
                        .children('th')
                        .on(
                            'click',
                            function(e) {
                                self.clearSelection();
                                var c = $(this).hasClass('up') ? 'down'
                                    : $(this).hasClass('down') ? null : 'up';
//                                console.log('sort:' + c);
                                // 'Default' - reset all cells
                                // 'multi' - reset just this cell
                                (sortable != 'multi' ? self.headerRow.children('th') : $(this)).removeClass('up down');
                                if (c)
                                    $(this).addClass(c);
				self._trigger('sort');
                            });
                }

            },
            measureDefaultWidths : function() {
		this.defaultTableWidth = this.bodyTable.outerWidth();
                this.headerRow.children('th').each(
                    function() {
                        $(this).data('default-width',
                                     $(this).outerWidth());
                    });
            }

            ,
            initCols : function() {
                this.tables.prepend('<colgroup>');
                this.colgroups = this.tables.children('colgroup');
                var self = this;
                this.headerRow.children('th').each(
                    function() {
                        var $th = $(this);
                        self.colgroups.append('<col>');
                        $th.data('col', self.colgroups
                                 .children('col:last-child'));
                    });
            },
            initPerm : function() {
                this.perm=[];
                for (var i=0; i< this.headerRow.children('th').length;i++)
		{
		    this.perm.push(i);
		}
            },
            initNonScrollable : function() {
                // Non-scrollable currently requires not having a
                // wrapper div
		this.top = this.element;
		this.tables = this.element.is('table') ? this.element : this.element.children('table');
		this.top.addClass('datagrid');

                if (this.options.resizableColumns
                    || this.options.movableColumns) {
                    this.initCols();
                    this.setColWidths();
                    this.applyLayout();
                }
            },
            setWindow : function() {
                var d = this.element[0].ownerDocument;
                this.window = d.defaultView || d.parentWindow;
            },
            clearSelection : function() {
                var w = this.window;
                if (w.document.selection
                    && w.document.selection.empty)
                    w.document.selection.empty();
                else if (w.getSelection
                         && w.getSelection().removeAllRanges)
                    w.getSelection().removeAllRanges();
            },
            mouseOver : function(e, $th) {
                if (isResize(e, $th)) {
                    $th.addClass('resize');
                }
            },
            mouseOut : function() {
                $th.removeClass('resize');
            },
            mouseDown : function(e, $th) {
                this.clearSelection();
                var o = $th.offset();
                // console.log('pageX="+e.pageX+ ' pageY='+e.pageY +
                // ' offsetLeft='+o.left+ ' offsetTop='+o.top+ '
                // width='+$th.outerWidth());

                if (this.options.resizableColumns
                    && isResizeLeft(e, $th)) {
                    var $prev = $th.prev();
			    while ($prev.css('display')=='none')
				$prev=$prev.prev();
                if ($prev.length) {
//                        console.log('Resize left');
                        this.beginResize(e, $prev);
                    }
                } else if (this.options.resizableColumns
                           && isResizeRight(e, $th)) {
//                    console.log('Resize right');
                    this.beginResize(e, $th);
                } else if (this.options.movableColumns) {
//                    console.log('move');
                    this.beginMove(e, $th);
                }
            },
            beginMove : function(e, $th) {
                var self = this;
                var doc = $th[0].ownerDocument;

                this.move = {
                    $feedback : $('<div class="drag-feedback">'),
                    $th : $th,
                    $col : $th.data('col'),
                    startX : e.pageX,
                    cancel : function() {
                        $(doc).off('.datagrid');
                        self.move.$feedback.remove();
                        delete self.move;
                    }
                }
                var offset = $th.offset();
                this.move.$feedback.html($th.html()).css({
                    position : 'absolute',
                    top : offset.top,
                    left : offset.left,
                    boxSizing : 'border-box',
                    width : $th.outerWidth(),
                    height : $th.outerHeight()
                });

                $(doc).on('mousemove.datagrid', function(e) {
                    self.moveFeedback(e);
                }).one('mouseup.datagrid', function(e) {
                    self.finishMove(e);
                });
            },
            moveFeedback : function(e) {
                this.clearSelection();
                var $feedback = this.move.$feedback;
                if ($feedback.parent().length == 0)
                    $feedback.appendTo(this.window.document.body);

                var offset = this.top.offset();
                var y = e.pageY, top = offset.top, left = offset.left, w = this.element
                    .outerWidth(), h = this.element
                    .outerHeight(), x = e.pageX
                    - this.move.startX
                    + this.move.$th.offset().left;
/*                console.log('y=' + y + ' top=' + top + ' left='
                            + left + ' w=' + w + ' h=' + h + ' x=' + x);*/
                if (y < top || y > top + h) {
                    this.move.cancel();
                    return;
                }
                $feedback.css('left', x);
            },
	    applyPermutationAndVisibility: function(e)
	    {
		var $e=$(e);
		if (!this.perm && !this.visibilityV)
		    return true; /* Nothing to do*/
		if (this.perm.length != $e.children().length)
		    return false;
		// TODO // Validate number of elements
		var reordered = [];
//		console.log('Permuting row');
		var list = $e.children();
		var p = this.perm;
		var v = this.visibilityV;
		if (this.perm)
		    list.each(function(i) {$e.append(list[p[i]]);});
		if (v)
		{
		    list.each(function(i) { 
			if (!v[i]) // If we need special logic for "nohide" it can be added here
			    $(this).hide();
		    });
		}
		return true;
		
	    },
            finishMove : function(e) {
                if (!this.move)
                    return;

                var $th = this.move.$th, startX = this.move.startX, currentX = e.pageX, x = currentX
                    - startX + $th.offset().left;

                this.move.cancel();

                var fromIndex = -1, toIndex = -1;
                if (currentX != startX) {
                    this.headerRow
                        .children('th')
                        .each(
                            function(i) {
                                if (this === $th[0]) {
                                    fromIndex = i;
                                    return;
                                }
                                var $cell = $(this);
                                if (!$cell.is(':visible'))
                                    return;
                                var left = $cell.offset().left, width = $cell
                                    .outerWidth();
                                if (x >= left && x < left + width) {
                                    if (x > left + width/2) {
                                        toIndex = i + 1;
                                    } else
                                        toIndex = i;
                                }
                            });
                    if (toIndex != -1 && toIndex != fromIndex
                        && toIndex != fromIndex + 1) {
                        // Check original column order and sort
                        // order
                        this.moveCells(fromIndex, toIndex);
			this.updateColGroups();
			this._trigger('movecolumn');
//			console.log('New permutation:'+JSON.stringify(this.perm));
                    }
                }

            },
            moveCells : function(fromIndex, toIndex) {
                // Todo exclude rows with a wrong number of elements
		if (!this.perm)
		    this.initPerm();
		this.reorderColGroups(fromIndex,toIndex);
                move(this.tables.children(
                    'thead,tbody,tfoot').children('tr'), fromIndex,
                     toIndex, this.perm.length);
		permute(this.perm,fromIndex,toIndex);
            },
	    reorderColGroups:function(fromIndex, toIndex)
	    {
		var from = fromIndex;
		var to = toIndex;
		// Since there are no 'col' elements for hidden columns, we need to correct the indices
		var cells=this.headerRow.children();
		for (var i=0; i<cells.length;i++)
		{
		    if (cells[i].style.display == 'none')
		    {
		    if (i<=fromIndex)
			--from;
			if (i<=toIndex)
			    --to;
		    }
		}
		move(this.colgroups,from,to);
	    },
            beginResize : function(e, $th) {
                this.setColWidths();
                this.element.addClass('ter-resize');
                this.resize = {
                    $col : $th.data('col'),
                    startX : e.pageX,
                    initialColWidth : $th.outerWidth(),
                    initialTableWidth : $th.closest('table')
                        .outerWidth()
                };
//		console.log('resizing:'+$th.text());
                var doc = $th[0].ownerDocument;
                var self = this;
                $(doc).on('mousemove.datagrid', function(e) {
                    self.doResize(e);
                });
                $(doc).one('mouseup.datagrid', function(e) {
                    $(doc).off('mousemove.datagrid');
                    self.resize = {};
                    self.element.removeClass('ter-resize');
                });

            },
            setColWidths : function(useDefaultWidths) {
                this.tables.width(useDefaultWidths ? this.defaultTableWidth : this.tables.eq(0).outerWidth());
                this.headerRow.children().each(
                    function() {
                        var $th = $(this);
                        var $col = $th.data('col');
                        if ($th.is(':visible')) {
                            $col.width(useDefaultWidths ? $th
                                       .data('default-width')
                                       : $th.outerWidth());
                        }
                    });

		this.tables.css('tableLayout','fixed');
            },
            doResize : function(e) {
                this.clearSelection();
                var $col = this.resize.$col;
                var deltaX = e.pageX - this.resize.startX;
                var colWidth = this.resize.initialColWidth + deltaX;
                var tableWidth = this.resize.initialTableWidth
                    + deltaX;
                var self = this;
                setTimeout(function() {
                    $col.width(colWidth);
                    self.tables.css({
                        'box-sizing' : 'border-box',
                        'width' : tableWidth
                    });
		    self.applyLayout();
                }, 0);
            },
	    appendRow : function(target,row)
	    {
		this.tables.children(target).eq(0).append(row);
	    },
	    permutation : function (newPerm) /* vector of currently visible columns */
	    {
		if (!this.perm)
		    this.initPerm();
		if (!newPerm)
		{
		    return this.perm.slice(0); // Create a copy of the array
		}
		var n = this.perm.length;
		if (!newPerm || ! (newPerm.length==n))
		    throw 'Invalid permutation (wrong number of elements)';
		var c=[];
		$.each(newPerm, function() {
		    if (this %1 != 0)
			throw 'Invalid permutation (the value '+this+ ' is not an integer)';
		    if (this<0 || this>=n)
			throw 'Invalid permutation (the value '+this+' out of range (0 .. '+(n-1)+')';
		    if (c[this])
			throw 'Invalid permutation (the value '+this+ ' is not unique';
		    c[this]=true;
		});

		for (var i=0;i<n;i++)
		{
		    // Iteratively reorder columns until the this.perm is identical to newPerm
		    if (this.perm[i] == newPerm[i])
			continue;
		    var required = newPerm[i];
		    for (var j=i+1; j<n; j++)
		    {
			if (this.perm[j]==newPerm[i])
			{
			    this.moveCells(j,i);
			    break;
			}
		    }
		}
		this.updateColGroups();
	    },
	    visibility : function (v) /* vector of 0/1 according to original column order */
	    {
		if (!this.visibilityV)
		{
		    this.visibilityV= $.map(this.headerRow.children('th'),function(){return 1;});
		}
		if (!v)
		{
		    // Return current visibility vector
		    return this.visibilityV.slice(0);
		}
		else
		{
		    // Set visibility
		    var n =  this.headerRow.children('th').length;
		    if (!v.length || v.length != n)
			throw 'Invalid argument (visibility should be a vector with length='+n+')';
		    var c = this.visibilityV;
		    for (var i=0;i<v.length;i++)
			this.updateColumnVisibility(i,v[i]);
		}

	    },

	    sort: function(v)
	    {
		var $h =  this.headerRow.children('th');
		var currentSort =  $h.map(function(i,th){
			if ($(th).hasClass('up'))
			    return 'up';
			if ($(th).hasClass('down'))
			    return 'down';
			return '';
		    });

		if (!v)
		{
		    return currentSort;
		}
		else
		{
		    if (!v.length || v.length != $h.length)
			throw 'Invalid argument (sort vector should have length='+$h.length+')';	    
		    $h.each(function(i,th)
		    {
			if ((v[i]||'') != currentSort[i])
			{
			    $(th).removeClass('up down').addClass((v[i]||''));
			}
		    });
		}
	    },
	    invPerm:function(i)
	    {
		if (!this.perm)
		    return i;
		for (var j=0;j<this.perm.length;j++)
		{
		    if (this.perm[j]==i)
		    {
			return j;
		    }
		}
		return -1;
		
	    },
	    updateColumnVisibility:function(colIndex, visible)
	    {
		if (this.visibilityV[colIndex] == visible)
		    return;
		this.visibilityV[colIndex] = visible;
		var n = this.visibilityV.length;
		var curIndex = this.invPerm(colIndex);
		/* increase width of table */
		var cssWidth = this.tables[0].style.width;
		if (cssWidth) /* non-jquery API checks if width is set explicitly */
		{
		    var headerCell = this.headerRow.children().eq(curIndex);
		    var cw;
		    cw = parseInt(headerCell.data('col')[0].style.width);
		    if (cw)
		    {
			var originalWidth = parseInt(cssWidth);
			this.tables.css('width',(visible ? originalWidth+cw : originalWidth-cw)+'px');
		    }
		    else
		    {
			/* clear explicit width on col elements */
			headerCell.data('col').each(function(){
			    this.style.width='';
			});
		    }
		}
		
		this.tables.find('tr').each(function(i){
/*
// Special logic to suppress hiding columns probably not needed
		    if ($(this).data('datagrid.nohide'))
			return;
*/
		    var $c = $(this).children();
		    if ($c.length == n)
		    {
			if (visible)
			    $c.eq(curIndex).show();
			else
			    $c.eq(curIndex).hide();
		    }
		});
		this.updateColGroups();
	    },
	    updateColGroups:function()
	    {
		var self = this;
		this.headerRow.children().each(function() {
		    var visible = $(this).css('display')!='none';
		    $(this).data('col').each(function(i){ /* when scrollable, there are two or three col elements per column */
			$(this).remove();
			if (visible)
			{
			    $(this).appendTo(self.colgroups.eq(i));
			}
		    });
		});
	    },
	    setTableClass:function(c)
	    {
		this.tables.attr('class',c);
	    },
	    adjustSize:function(callback)
	    {
		if (this.head) /* scrollable */
		{
	            var sw = scrollbarWidth();
                    this.head.width(this.top.innerWidth() - sw);
                    if(this.footer)
			this.footer.width(this.top.innerWidth() - sw);
                    this.body.width(this.top.innerWidth());
		}
		callback.call();
	    }
        });
})(jQuery);

// file: 005-tersus.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
     if (!window.tersus) window.tersus  = {};
if (!tersus.settings) tersus.settings = {};
window.tlog = null;
tersus.isLocalHost = function(host)
{
    return host == 'localhost' || host =='127.0.0.1' || host == '0:0:0:0:0:0:0:1%0';
};
tersus.isNative=false;//Overridden in native context

tersus.getTraceBaseURL = function() /* Can be overridden in specific cases to direct client-side trace to another server */
{
    var url = tersus.serverURL || tersus.rootURL;
    if (url.lastIndexOf('/') != url.length -1)
	url = url + '/';
    url = url+'Trace/';
    return url;
};
tersus.useIFrames=true;
tersus.ANYTHING = 'Common/Data Types/Anything';
tersus.loadScript = function loadScript(url,w)
{
    if (!w)
	w = window;
    var loadScript = w.document.createElement("script");
    
    // Add script object attributes
    loadScript.setAttribute("type", "text/javascript");
    loadScript.setAttribute("charset", "utf-8");
    loadScript.setAttribute("src", url);
    var head = w.document.getElementsByTagName("head").item(0);
    head.appendChild(loadScript);

};
tersus.topZindex = 10;
tersus.SERVICE_MAX_RETRIES = 2;
tersus.SERVICE_RETRY_DELAY = 2000;
tersus.alertMode = {interactive:true};
tersus.getEvent = function(elementName)
{
    var eventSpec = null;
    for (var eventKey in Events)
    {
        if (Events[eventKey].elementName == elementName)
            eventSpec = Events[eventKey];
    }
    if (!eventSpec)
        eventSpec = new tersus.Event(elementName); // Ad-hoc event
    return eventSpec;

};
tersus.invokeAction=function(eventName,parameters, domEvent, targetNode, wait)
{
    /* wait - indicates that the event should silently wait until previous events finished processing
     *  - (rather than timeout with "Busy" ).  */
    if (tlog) tlog('invokeAction called ['+eventName+']');
    if (!targetNode)
	targetNode = window.currentRootDisplayNode;
    if (targetNode)
    {
	var eventAttributes = null;
	if (domEvent)
	    eventAttributes = getEventAttributes(domEvent);

	if (tlog)
	    tlog('Queuing Event ..');	
	//window.engine.handleEvent(targetNode,eventSpec,parameters,eventAttributes);
	var eventSpec = tersus.getEvent(eventName);
	targetNode.queueEvent(eventSpec,  parameters, domEvent, null /*callback*/, wait);
    }
};
window.tersus.clearLog = function()
{
    window.tersus._log = [];
    window.tlog  = window.tersus.log;
};
tersus.formatTime = function(time)
{
    var p2 = tersus.DateAndTime.pad2;
    return  p2(time.getHours())+':'+p2(time.getMinutes())+':'+p2(time.getSeconds());
};

tersus.useXMLHTTPRequest = true;
tersus.autoLogout = false;
window.tersus.log = function(msg1, msg2, msg3)
{
    var now=new Date();
    var time = now.getTime();
    if (l = window.tersus._log)
    {
	l.push(time);
	l.push('\t');
	l.push(tersus.escapeHTML(msg1));
	if (msg2 != null)
	{
	    l.push('\t');
	    l.push(msg2);
	}			
	if (msg3 != null)
	{
	    l.push('\t');
	    l.push(msg3);
	}		
	l.push('\n');	
    }
};
window.tersus.showLog = function()
{
    if (window.tersus._log)
    {
	var w = window.open();
	w.document.write('<pre>');
	w.document.write(window.tersus._log.join(''));
	w.document.close();
    }
    window.tersus.clearLog();
};
window.tersus.escapeHTML = function(s)
{
    if (s == null)
	return '';
    if (typeof(s) != 'string')
	s = s.toString();
    s = s.replace(/&/g, '&amp;');
    s = s.replace(/</g, '&lt;');
    s = s.replace(/>/g, '&gt;');
    s = s.replace(/\n/g, '<br/>');
    s = s.replace(/["]/g, '&quot;');
    return s;	
};
window.tersus.escapeHTMLAttribute = function(s)
{
    if (s == null)
        return '';
    if (typeof(s) != 'string')
        s = s.toString();
    s = s.replace(/&/g, '&amp;');
    s = s.replace(/</g, '&lt;');
    s = s.replace(/>/g, '&gt;');
    s = s.replace(/\n/g, '&#013;');
    s = s.replace(/["]/g, '&quot;');
    return s;   
};
tersus.onUnload = function()
{
    if (tersus.Subscribe && tersus.Subscribe.xhr)
    {
	tersus.Subscribe.xhr.abort();
    }
    if (! tersus.reloading) // the onunload event should not be fired when we're reloading
    {
	tersus.isUnloading = true;
	if (window.rootDisplayNode)
	    window.engine.handleEvent(window.rootDisplayNode,Events.ON_UNLOAD);
	// autoLogout default has changed to 'false', since 'true' may create an inconsistent
	// state where user & permissions can still be retrieved, although requiredPermission
	// no longer abides by them.
	// The 'true' option should be deprecated and removed, or moved to a 'backwards
	// compatibility module' we might want to offer in the future
	if (tersus.autoLogout)
	    tersus.logout();
    }
};
tersus._disabled = false;
tersus.createClassNameList = function()
{
    var list = [];
    var sheets = document.styleSheets;
    var count = 0;
    for (var i=0;i<sheets.length;i++)
    {
	var sheet = sheets[i];
	var rules = sheet.cssRules;
	if (rules == undefined)
	    rules = sheet.rules; //IE
	if (rules == undefined)
	    break;
	for (var j=0;j<rules.length;j++)
	{
	    var rule = rules[j];
	    var selectorText = rule.selectorText; 
	    /* Adding ' ' to make sure we have somthing before the .,
	       so we can always ignore the first part after splitting */
	    var classNames = (' '+selectorText).split('.');
	    classNames.shift();
	    list = list.concat(classNames);
	}
    }
    tersus.styleClassNames  = new Set(list);
};
tersus.logout = function logout()
{
    var req = createXMLHTTPRequest();
    
    var url=tersus.rootURL+'Logout';
    req.open('GET', url, false);
    req.send(null);
};
tersus.KEEP_ALIVE_INTERVAL=600000; //10 minutes
tersus.DEV_UPDATE_CHECK_INTERVAL = 2000; // 2 seconds
tersus.PROD_UPDATE_CHECK_INTERVAL = 60000; // 1 minute
tersus.init = function()
{
    tersus.repository = new ConstructorRepository();
    window.onfocus = tersus.checkUpdate;
    tersus.async.timer = setInterval(tersus.async.worker, tersus.async.interval);
    if (tersus.settings.dev_mode)
        tersus.updateCheckInterval = tersus.DEV_UPDATE_CHECK_INTERVAL;
    else
        tersus.updateCheckInterval = tersus.PROD_UPDATE_CHECK_INTERVAL;
    
    // The following are also candidates for removal
    tersus.keepAliveTimer = setInterval(tersus.keepAlive, tersus.KEEP_ALIVE_INTERVAL);
    window.onresize = tersus.onResize;
};
tersus.noop = function()
{
};
tersus.keepAliveReq = null;
tersus.keepAlive = function()
{
    var req = tersus.keepAliveReq;
    if (!req)
	req = tersus.keepAliveReq = createXMLHTTPRequest();
    var url = tersus.rootURL+'blank.html?'+(new Date()).getTime();
    req.open('GET', url, true);
    req.onreadystatechange = tersus.noop;
    req.send(null);
};
tersus.getTimestampReq = null;
tersus.lastCheckUpdateTime = 0;
tersus.checkUpdate = function()
{
    var time = (new Date()).getTime();
    if (time < tersus.lastCheckUpdateTime + tersus.updateCheckInterval)
	return; // We don't want to check too often
    tersus.getTimestamp(tersus.handleCheckUpdateResponse);
}
tersus.getTimestamp = function (callback)
{
    var time = (new Date()).getTime();
    tersus.lastCheckUpdateTime = time;
    var path = 'Timestamp';
    var url = tersus.rootURL+path;
    var req = tersus.getTimestampReq;
    if (!req)
	req = tersus.getTimestampReq = createXMLHTTPRequest();
    req.open('POST',url, true);
    req.onreadystatechange = callback;
    req.send(null);
    
}
tersus.parseTimestampResponse = function (req)
{
    return eval ('x='+req.responseText+';x;');
}
if (tersus.lastTimestamp == undefined)
    tersus.lastTimestamp = 0;
tersus.setLastTimestamp = function(timestamp)
{
    if (timestamp > tersus.lastTimestamp)
	tersus.lastTimestamp = timestamp;
};
tersus.handleCheckUpdateResponse = function(responseText)
{
    if (!window.tersus)
	return; // This can happen, at least in Firefox, when navigating away from the application
    var req = tersus.getTimestampReq;
    if (req.readyState != 4)
	return;
    if (req.status == 200 || req.responseText)
    {
	var r = tersus.parseTimestampResponse(req);
	var currentTimestamp = r.timestamp;
	window.userName = r.userName;
	if (tersus.lastTimestamp && currentTimestamp && currentTimestamp > tersus.lastTimestamp)
	{
	    if (tlog) tlog("Application Updated -> Reloading");
	    tersus.progress.set('Reloading Application ...');
	    //			tersus.progress.show();
		window.onbeforeunload = null;
	    setTimeout(tersus.reloadApplication,1000);
	}
	else
	    if (tlog) tlog("No update");
	tersus.setLastTimestamp(currentTimestamp);
    }
};
tersus.reloadApplication = function()
{
    tersus.reloading = true;
    var windows = tersus.getWindows();
    for (var i=0;i<windows.length;i++)
    {
	if (window != windows[i])
	    windows[i].close();
    }
    location.reload();
};
tersus.initServiceResponseFrames = function ()
{
    tersus.serviceResponseFrames = [];
    for (var i=0; i<10; i++)
    {
	var f = tersus.serviceResponseFrames[i] = createAnIFrame(window,'_service_'+i);
	f.src  = 'blank.html';
    };
    tersus.nextResponseFrameIndex = 0;
};

tersus.nextServiceResponseFrame = function ()
{
    var iframe = tersus.serviceResponseFrames[tersus.nextResponseFrameIndex++];
    if (tersus.nextResponseFrameIndex >= tersus.serviceResponseFrames.length)
	tersus.nextResponseFrameIndex = 0;
    return iframe;
};
tersus.windows = [self];
tersus.getWindows = function()
{
    if (tersus.windows.length > 1)
	tersus.unregisterClosedWindows();
    return tersus.windows;
};
tersus.registerWindow = function (w)
{
    tersus.windows.push(w);
    if (tlog) tlog("registerWindow:"+w.name+" current:"+tersus.windows.length);
};
tersus.unregisterWindow = function (w)
{
    for (var i=0; i <tersus.windows.length; i++)
    {
	if (tersus.windows[i] == w)
	{
	    tersus.windows.splice(i,1); // remove
	    if (tlog) tlog("unregisterWindow:"+w.name+" index:"+i);
	    return;
	}
	if (tlog) tlog("unregisterWindow:"+w.name+" ** not found **");
    }
    
}
tersus.popupNodes = {}; 
tersus.checkWindow = function (w)
{
    try
    {
	return w && !w.closed;
    }
    catch (e)
    {
	return false;
    }
}
tersus.unregisterPopupNodes = function()
{
    for (var id in tersus.popupNodes)
    {
	var node = tersus.popupNodes[id];
	var alive = false;
	try
	{
	    alive = node.currentWindow && ! node.currentWindow.closed && (node.isPopIn || node.isDialog || (id == node.currentWindow.popupId));
	}
	catch (e)
	{
	}
	if (! alive)
	{
	    delete tersus.popupNodes[id];
	}
    };
};
tersus.unregisterClosedWindows = function ()
{
    if (tlog) tlog("unregisterClosedWindows - before:"+tersus.windows.length);
    var temp = [];
    for (var i=0;i<tersus.windows.length;i++)
    {
	var w = tersus.windows[i];
	try
	{
	    if ((! w.closed) && w.document && w.document.body)
		temp.push(w);
	    else
		if (tlog) tlog(w.name + ' closed:'+w.closed + ' body:'+w.document.body);
	}
	catch (e)
	{
	    if (tlog) tlog(e);
	};
    }
    tersus.windows = temp;
    if (tlog) tlog("unregisterClosedWindows - after:"+tersus.windows.length);
};
tersus.progress = {};
tersus.progress.setStatus = function (msg)
{
    var windows = tersus.getWindows();
    for (var i=0;i<windows.length;i++)
	windows[i].status = msg;
};
/** Threshold for forcing the progress bar to open when handling a service response */
tersus.progress.responseLengthThreshold = 10000;
tersus.progress.set = function(msg, cancellationFunc)
{
    tersus.progress.active=true;
    $('body').addClass('ter-progress');
}
tersus.progress.clear = function()
{
    tersus.progress.active=false;
    $('body').removeClass('ter-progress');
    document.body.offsetWidth;//force reflow (makes class change apply immediately, clears "working" indication from cursor)
}
tersus.progress.delay = 1000; // 1000 milliseconds until progress bar appears
tersus.gotoURL = function(url, replace, reload)
{
    if (tlog) tlog("gotoURL: '"+url+"' reload="+reload);
    if (replace)
	window.location.replace(url)
    else
	window.location.href=url;
    if (!reload)
    {
	tersus.history.location = url;
	tersus.loadParams();
    }
    if (tersus.useModernHistory)
	return;
    if (window.browser=='IE' && url.indexOf('mailto:')!=0) // In IE, we add the new URL to the history stack using a special IFRAME
    {
	var historyFrame = document.getElementById('_history');
	if (historyFrame)
	{
	    var src = 'history.html?'+encodeURIComponent(url);
	    if (replace)
		getIFrameWindow(historyFrame).location.replace(src);
	    else
		historyFrame.src =src ;
	}
    }
    else
    {
	// The following code loads a dummy page - this makes firefox "understand" that there is nothing more to wait for
	// (the behavior looks like a Firefox bug, but hasn't been fully analyzed)
	var f= tersus.nextServiceResponseFrame()
	if (f)
	{
	    getIFrameWindow(f).location.replace('blank.html?u='+encodeURIComponent(url));
	}
    } 
};


tersus.history = {};
tersus.history.fixedURL = null;
tersus.history._checkLocation = function()
{
    var current = window.location.href;
    if (current != tersus.history.location)
    {
	if (tlog) tlog("New location:"+current);
	tersus.history.location = current;
	tersus.loadParams();
	tersus.history.locationChanged();
    };
};
tersus.history.checkLocation = function()
{
    if (window.location.href != tersus.history.location)
 	tersus.async.exec(tersus.history._checkLocation, false /* don't wait */);
};


tersus.history.locationChanged = function()
{
    if (tersus.history.fixedURL) /* The 'fixedURL' property is used to disable navigation */
    {
	tersus.gotoURL(tersus.history.fixedURL, false/*replace*/, false/*reload*/);
	return;
    }
    var newPerspectiveName = tersus.searchParams[tersus.PERSPECTIVE];
    if (newPerspectiveName == null && window.perspectives && window.perspectives.length > 0)
	newPerspectiveName = window.perspectives[0].name;
    var newViewName = tersus.searchParams[tersus.VIEW];
    if (newViewName == null && newPerspectiveName)
    {
	var p = getPerspective(newPerspectiveName);
	if (p && p.views && p.views.length>0)
	    newViewName = p.views[0].name;
    }

    var perspectiveChanged = window.perspectives && window.perspectives.length > 1 && window.perspective.name != newPerspectiveName;
    var viewChanged = window.view == null || window.view.name != newViewName;
    if (perspectiveChanged || viewChanged)
    {
	window.engine.handleEvent(window.rootDisplayNode,Events.ON_LEAVE_VIEW);
	queueEvent(tersus, tersus.reloadView, [], null,null, null, -1);
    }
    else
	tersus.updateView();
};

tersus.locationChangeListeners = [];
tersus.updateView = function()
{
    if (tersus.locationChangeListeners.length > 0)
    {
	for (var i =0 ; i< tersus.locationChangeListeners.length; i++)
	{
	    var listenerId = tersus.locationChangeListeners[i];
	    var listenerNode = tersus.findNode(listenerId);
	    if (listenerNode)
		window.engine.handleEvent(listenerNode,Events.ON_LOCATION_CHANGE);
	}
    }
    else
    {
	window.rootDisplayNode.refresh();
	resumeRoot();
    }

}
// Extract search parameters
tersus.loadParams = function()
{
    tersus.searchParams = {};
    var terms = [];
    var search = window.location.search;
    if (search && search.length > 1)
	terms = terms.concat(search.substring(1).split('&'));
    
    // Extract the part that follows the hash ('#').  
    // We can't use window.location.hash because some bad decoding happens there
    var hashIndex = location.href.indexOf('#');
    if (hashIndex >=0)
    {
	var hash = location.href.substring(hashIndex+1);
	terms = terms.concat(hash.split('&'));	
    }
    for (var i=0; i< terms.length; i++)
    {
	var term = terms[i];
	var keyValuePair = term.split('=');
	var key = decodeURIComponent(keyValuePair[0]);
	var value = decodeURIComponent(keyValuePair[1]);
	tersus.searchParams[key]=value;
    }
}

tersus.history.init = function ()
{
    tersus.history.location = window.location.href;
    tersus.loadParams();
    tersus.history.timer = setInterval(tersus.history.checkLocation,100);
}

tersus.getInternalParameters = function()
{
    var params = {};
    for (var p in tersus.searchParams)
	params[p] = tersus.searchParams[p];
    return params;
};

tersus.history.init();	

// tersus.async - a mechanism for preventing concurrency
tersus.async = {};
tersus.async.queue = [];
tersus.async.interval=100;
tersus.async.isBusy = function () { return tersus.async.queue.length > 0;};
tersus.async.nowait = function()
{
    // Returns true if any of the items on queue requires waiting (i.e. is a blocking operation)
    for (var i=0;i<tersus.async.queue.length;i++)
	if (tersus.async.queue[i].wait)
	    return false;
    return true;
};
tersus.async.exec = function(f, waitIfBusy)
{
    var item = {func:f, wait:waitIfBusy?true:false};
    if (item.wait && ! tersus.progress.active)
	tersus.progress.set('..');
    
    tersus.async.queue.push(item);
};

tersus.async.worker = function()
{
    while (tersus.async.queue.length > 0 || window.rootDisplayNode && window.rootDisplayNode.status == FlowStatus.READY_TO_RESUME)
    {
	if (window.rootDisplayNode && window.rootDisplayNode.status == FlowStatus.READY_TO_RESUME)
	    resumeRoot();
	else if (tersus.async.queue.length > 0)
	{
	    var busy = isBusy(); // Root system busy
	    if (! busy)
	    {
		var item = tersus.async.queue.shift();
		try
		{
		    if (tlog) tlog("tersus.async.worker: start");
		    item.func();
		}
		catch (e)
		{
		    if (tlog)
			tlog(e);
		}
		finally
		{
		    if (tlog) tlog("tersus.async.worker: end");
		}
	    }
	    else // if the root system is busy, we search for items on the queue that don't need to wait
	    {
		var found = false;
		for (var i=0;i<tersus.async.queue.length;i++)
		{
		    var item = tersus.async.queue[i];
		    if (!item.wait)
		    {
			tersus.async.queue.splice(i,1);
			try
			{
			    if (tlog) tlog("tersus.async.worker: start");
			    item.func();
			}
			catch (e)
			{
			    if (tlog)
				tlog(e)
			}
			finally
			{
			    if (tlog) tlog("tersus.async.worker: end");
			}
			found = true;
		    }
		}
		if (!found)
		    break; // Try again later
	    }
	}
    }
    //Since we're here - any queue are waiting for the root system to complete. So if the root system is not busy it means that the queue is empty and we can clear progress
    if (tersus.progress.active)
    {
	if ( ! isBusy())
	{
	    debugAssertion(tersus.async.queue.length == 0, 'tersus.async.queue expected to be empty when root system not busy');
	    tersus.progress.clear();
	}
    }
    
};
tersus.unescapeString = function unescape_string(s)
{
    return s.replace(/\\n/g, '\n').replace(/\\t/g,'\t').replace(/\\\\/g,'\\');
};
tersus.setDirection = function tersus_setDirection(direction)
{
    var windows = tersus.getWindows();
    window.textDirection = direction;
    for (var i=0; i< windows.length;i++)
    {
	windows[i].document.body.className=direction;
    }
    
};
tersus.getDirection = function tersus_getDirection()
{
    return window.textDirection == 'rtl'? 'rtl':'ltr';
};
tersus.translateResource = function (s)
{
    if (tersus.resourceMap && tersus.resourceMap[s])
	return tersus.resourceMap[s];
    else
	return s;
};
tersus.Conventions = {};
tersus.Conventions.isEventHandler = function (subflow)
{
    return subflow && (subflow.role.match(/^<On .*>$/) || subflow.role == '<Open>') ;
};
window.engine = {};
FlowStatus = {};
FlowStatus.NOT_READY_TO_START = 'Not Ready to Start';
FlowStatus.READY_TO_START = 'Ready to Start';
FlowStatus.READY_TO_RESUME = 'Ready to Resume';
FlowStatus.WAITING_FOR_INPUT = 'Waiting for Input';
FlowStatus.STARTED = 'Started';
FlowStatus.RESUMED = 'Resumed';
FlowStatus.PAUSED = 'Paused';
FlowStatus.DONE = 'Done';

BuiltinNames = {};
BuiltinNames.DONE_EXIT_NAME = '<Done>';

tersus.Event = function(elementName, jsName, methodName, name)
{
    this.elementName = elementName;
    this.jsName = jsName;
    this.methodName = methodName;
    this.name=name;
};
Events = {};
Events.ON_CLICK = new tersus.Event('<On Click>', 'onclick', 'onClick', 'click');
Events.ON_CONTEXT_MENU = new tersus.Event('<On Context Menu>', 'oncontextmenu' , 'onContextMenu', 'contextmenu');
Events.ON_FOCUS = new tersus.Event('<On Focus>', 'onfocus', 'onFocus', 'focus');
Events.ON_BLUR = new tersus.Event('<On Blur>', 'onblur','onBlur', 'blur');
Events.ON_MOUSEOVER = new tersus.Event('<On Mouse Over>','onmouseover','onMouseOver', 'mouseover');
Events.ON_MOUSEOUT = new tersus.Event('<On Mouse Out>','onmouseout','onMouseOut', 'mouseout');
Events.ON_MOUSEENTER = new tersus.Event('<On Mouse Enter>','onmouseenter','onMouseEnter', 'mouseenter');
Events.ON_MOUSELEAVE = new tersus.Event('<On Mouse Leave>','onmouseleave','onMouseLeave', 'mouseleave');
Events.ON_MOUSEDOWN = new tersus.Event('<On Mouse Down>','onmousedown','onMouseDown', 'mousedown');
Events.ON_MOUSEUP = new tersus.Event('<On Mouse Up>','onmouseup','onMouseUp', 'mouseup');
Events.ON_MOUSEMOVE = new tersus.Event('<On Mouse Move>','onmousemove','onMouseMove', 'mousemove');
Events.ON_KEYPRESS = new tersus.Event('<On Key Press>','onkeypress','onKeyPress', 'keypress');
Events.ON_KEYDOWN = new tersus.Event('<On Key Down>','onkeydown','onKeyDown', 'keydown');
Events.ON_KEYUP = new tersus.Event('<On Key Up>','onkeyup','onKeyUp', 'keyup');
Events.ON_DOUBLE_CLICK = new tersus.Event('<On Double Click>','ondblclick','onDoubleClick', 'doubleclick');
Events.ON_TOUCHSTART = new tersus.Event('<On Touch Start>','ontouchstart','onTouchStart', 'touchstart');
Events.ON_TOUCHMOVE = new tersus.Event('<On Touch Move>','ontouchmove','onTouchMove', 'touchmove');
Events.ON_TOUCHEND = new tersus.Event('<On Touch End>','ontouchend','onTouchEnd', 'touchend');
Events.ON_BROWSE = new tersus.Event('<On Browse>',null,null);
Events.ON_TAP_HOLD = new tersus.Event('<On Tap Hold>','ontaphold','onTouchHold', 'taphold');
Events.ON_SWIPE_LEFT = new tersus.Event('<On Swipe Left>','onswipeleft','onSwipeLeft', 'swipeleft');
Events.ON_SWIPE_RIGHT = new tersus.Event('<On Swipe Right>','onswiperight','onSwipeRight', 'swiperight');
Events.ON_SWIPE_UP = new tersus.Event('<On Swipe Up>','onswipeup','onSwipeUp', 'swipeup');
Events.ON_SWIPE_DOWN = new tersus.Event('<On Swipe Down>','onswipedown','onSwipeDown', 'swipedown');
Events.ON_SWIPE = new tersus.Event('<On Swipe>','onswipe','onSwipe', 'swipe');
Events.ON_CHANGE = new tersus.Event('<On Change>','onchange','onChange', 'change');
Events.ON_EXPAND = new tersus.Event('<On Expand>');
Events.ON_POPSTATE = new tersus.Event('<On Pop State>','onpopstate','onPopState', 'popstate');
Events.ON_COLLAPSE = new tersus.Event('<On Collapse>');
Events.ON_SELECT = new tersus.Event('<On Select>');
Events.ON_LOCATION_CHANGE = new tersus.Event('<On Location Change>');
Events.ON_UNLOAD = new tersus.Event('<On Unload>');
Events.ON_LEAVE_VIEW = new tersus.Event('<On Leave View>');
Events.ON_SORT = new tersus.Event('<On Sort>');
Events.OPEN = new tersus.Event('<Open>');
Events.ON_DELETE = new tersus.Event('<On Delete>');
Events.ON_ELEMENT_CHANGE = new tersus.Event('<On Element Change>');
Events.ON_ORIENTATION_CHANGE = new tersus.Event('<On Orientation Change>');
Events.ON_TAP = new tersus.Event('<On Tap>', 'ontap', 'onTap', 'tap');
Events.ON_SUBMIT = new tersus.Event('<On Submit>', 'onsubmit', 'onSubmit', 'submit');
Events.ON_DRAG = new tersus.Event('<On Drag>', 'ondrag', 'onDrag', 'drag');
Events.ON_DROP = new tersus.Event('<On Drop>', 'ondrop', 'onDrop', 'drop');
Events.ON_ERROR = new tersus.Event('<On Error>', 'onerror', 'onError', 'error');

BuiltinModels = {};
BuiltinModels.TEXT_ID='Common/Data Types/Text';
BuiltinModels.NUMBER_ID='Common/Data Types/Number';
BuiltinModels.NOTHING_ID='Common/Data Types/Nothing';

function compareValues(value1, value2, caseInsensitive, recursionMap)
{
	//recursionMap holds a list all comparisons already made (or in progress) - we don't want to comapre the same objects twice
	if (value1 && value1.isDataNode)
		value1 = value1.value;
	if (value2 && value2.isDataNode)
		value2 = value2.value;

	if( value1==value2)
		return true;
	if (! value1 || ! value2)
		return false;

	if (! value1.isNode || !value2.isNode)
		return false;
	if (value1.constructor != value2.constructor && ! (value1.isLeaf && value2.isLeaf && value1.pluginFunc == value2.pluginFunc))
		return false;
	if (! value1.elementList)
	{
		var l1 = value1.leafValue;
		var l2 = value2.leafValue;
		var c1 = 0;
		var c2 = 0;
		if (value1.isMap && value2.isMap)
		{
			var keys2 = new Set();
			for (var key in l2)
			{
				++c2;
				keys2.add(key);
			}
			for (var key in l1)
			{
				if (! keys2.contains(key))
					return false;
				if (! compareValues(l1[key],l2[key]), caseInsensitive, recursionMap)
					return false;
				++c1;
			}
			if (c1 != c2)
				return false; //Different number of memebers
			return true;
		}
		if (value1.isText && caseInsensitive)
		{
			l1 = l1.toUpperCase();
			l2 = l2.toUpperCase();
		}
		return l1 == l2 || l1 && l1.equals && l1.equals(l2);
	}

	if (!recursionMap && value1.isRecursive())
	{
		recursionMap = {};
	}
	if (recursionMap)
	{
		var id1  = value1.getNodeId();
		var id2 = value2.getNodeId();
		var key = id1+':'+id2;
		if (recursionMap[key])
			return true; // already compared (or comparison in progress) - no need to comapre again
		recursionMap[key]=true;
	}

	for (var i=0; i<value1.elementList.length; i++)
	{
		var e = value1.elementList[i];
		//		if (e.isDisplayElement || e.isDataElement || e.isMethodElement)
		{
			var children1;
			var children2;
			if (e.isRepetitive)
			{
				children1 = e.getChildren(value1);
				children2 = e.getChildren(value2);
			}
			else
			{
				children1 = [e.getChild(value1)];
				children2 = [e.getChild(value2)];
			}
			if (children1.length != children2.length)
				return false;
			for (var j=0; j<children1.length; j++)
			{
				if (! compareValues(children1[j], children2[j], caseInsensitive, recursionMap))
					return false;
			}
		}
	}
	return true;
};
function escapeHTML(value)
{
    return value.replace(/&/g, '&amp;').replace(/>/g,'&gt;').replace(/</g,'&lt;').replace(/\n/g, '<br>');
};
HTMLProperties = {};


// Creates a set

function loadBooleanOption(name)
{
    var value = getCookie(name);
    window[name] = (value == 'true');
};
function loadOptions()
{
    loadBooleanOption('autoReload');
    loadBooleanOption('serverTracing');
    loadBooleanOption('showServiceInvocations');
    loadBooleanOption('clientTracing');
};

tersus.loadFile = function(path, callback, ignoreErrors)
{
    var storageKey = null;
    if (window.localStorage && tersus.useLocalStorage)
    {
	storageKey = "File?"+path;
	var text = localStorage.getItem(storageKey);
	if (text != null)
	{
	    if (callback)
	    {
		setTimeout(function() {callback(text);},0);
		return;
	    }
	    else
		return text;
	}
    }
    return tersus.loadURL(tersus.rootURL+path, callback, ignoreErrors, null/*error callback*/, storageKey);
};
tersus.loadURL = function(url, callback, ignoreErrors, errorCallback, storageKey)
{
    var req = createXMLHTTPRequest();
    
    if (callback)
    {
	req.open('GET',url, true);
	req.onreadystatechange = function()
	{
	    var responseText = null;
	    var status = null;
	    var statusText = null;
	    try
	    {
		if (req.readyState != 4)
		    return;
		var status = req.status;
		var statusText = req.statusText;
		if (status == 200)
		{
		    responseText = req.responseText;
		    if (storageKey && window.localStorage)
		    {
			if (tlog)
			    tlog('Storing '+storageKey+ ' in local storage.');
			localStorage.setItem(storageKey, responseText);
		    }
		}
	    }
	    catch (e)
	    {
		if (ignoreErrors)
		    callback(null);
		else if (errorCallback)
		    errorCallback(status, statusText, e);
		else
		    tersus.error('Failed to load "'+url+'"');
		return;
		
	    }
	    if (status == 200)
		callback(responseText);
	    else if (ignoreErrors)
		callback(null);
	    else if (errorCallback)
		errorCallback(status, statusText, null);
	    else
		tersus.error('Failed to load "'+url+'"');
	};
	req.send(null);
	return req;
    }
    else
    {
	var method = 'GET';
	if (tersus.useLocalStorage && isWebKit && navigator.onLine == true)
	    method = 'POST'; // For some reason 'GET' doesn't work in Safari cached mode (and so offline-enabled applications can't load templates like 'popin.html' even when online)
	req.open(method, url, false); 
	req.send(null);
	if (req.status != 200)
	{
	    tersus.error('Missing resource '+url+ '\nerror code='+req.status+' error message='+req.statusText);
	    if (parent && parent.notLoaded)
		parent.notLoaded();
	    
	    return;
	}
	if (storageKey && window.localStorage)
	{
	    if (tlog)
		tlog('Storing '+storageKey+ ' in local storage.');
	    localStorage.setItem(storageKey, req.responseText);
	}
	return req.responseText;
    }
};
tersus.getUserName = function()
{
    return window.userName;
};
tersus.setUserName = function(name)
{
    window.userName = name;
};
tersus.getCurrentViewURL = function()
{
    if (tersus.firstURL.match('\\?minify=false#?$'))
	return tersus.firstURL;
    else
	return tersus.rootURL;
};
function addHiddenField(form, name, value)
{
    
    var field = form.ownerDocument.createElement('input');
    field.type = 'hidden';
    field.value =value;
    field.name = name;
    form.appendChild(field);
    return field;
}

loadOptions();
function set(list)
{
    var out = {};
    for (var i=0; i< list.length; i++)
    {
	out[list[i]] = list[i];
    }
    return out;
}
function Set(list)
{
    this.members = {};
    if (list) 
    {
	for (var i=0; i< list.length; i++)
	{
	    this.members[list[i]] = true;
	}
    }
};
Set.prototype.contains = function (member) 
{
    return this.members[member];
};
Set.prototype.add = function(obj)
{
    this.members[obj]=true;
};
Set.prototype.toList = function()
{
    var list = [];
    for (var memeber in this.members)
	list.push(memeber);
    return list;
};

Set.prototype.remove = function(member)
{
    delete this.members[member];
};
HTMLProperties['table']=set(['width']);
HTMLProperties['TABLE']=set(['width']);
STYLE_PROPERTIES = set(['width', 'height', 'overflow']);

Operation = {};
Operation.REPLACE = 'Replace';
Operation.ADD = 'Add';
Operation.REMOVE = 'Remove';
function internalError(message)
{
    alert ('Error:\n'+message);
    this.undefined();
};
function modelError(message, model)
{
    if (model && model.modelId)
	message = 'Invalid Model: '+model.modelId+'\n'+message;
    if (tlog)
	tlog(message);
    throw new tersus.Exception(message);
};
function debugAssertion(expression, message)
{
    //Default implemenation is a no-op. Should be overridden in test settings
}
function modelExecutionError(message, node)
{
    if (node)
	message += '\nLocation:'+new tersus.RuntimeLocation(node);
    alert ('Model Execution Error:\n'+message);
};

function makeAssertion(flag, description)
{
    if (! description)
	var description = '';
    if ( !flag)
    {
	alert ('Assertion Failed ' + description);
	this.undefined();
    }
};

tersus.RuntimeLocation = function(node,element, suffix)
{
    var segments = [];
    // Collecting path segments in reverse order
    if (suffix)
	segments.push(suffix);
    if (element)
	segments.push(element.role);
    var current = node;
    while (current)
    {
	if (!current.isBackground)
	{
	    var currentModelId = current.getModelId();
	    if (! current.element  || current.element.modelId != currentModelId)
	    {
		this.baseModelId = currentModelId;
		if (!currentModelId)
		    error("No currentModelId id");
		break;
	    }
	    else
		segments.push(current.element.role);
	}
	current = current.parent;
    }
    segments.reverse();
    this.path = new Path();
    this.path.setSegments(segments);
};
tersus.RuntimeLocation.prototype.toString = function()
{
    return this.baseModelId + '['+this.path.str+']';
};
/*
  Handles a user event (mouse click etc.)
  displayNode: the displayNode on which the event was registered
  eventType: the type of the event (see Events.ON_XXX)
  parameters: parameters that will be passed to the event handler action
*/
window.engine.handleEvent = function handleEvent(displayNode, eventType , parameters, domEventAttributes) 
{
    if (tlog) tlog ('handleEvent '+eventType.elementName + ' on '+displayNode.modelName + ' ( '+displayNode.getPath().str+')');
    tersus.currentEventAttributes = domEventAttributes;

    var subFlow = displayNode.getEventHandler(eventType);
    if (!subFlow)
	return;
    var child = subFlow.createChild(displayNode);
    if (parameters)
    {
	for (var parameterName in parameters)
	{
	    var trigger = child.getElement(parameterName);
	    if (trigger)
	    {
		var value = parameters[parameterName];
		if (value !== undefined)
		{
		    if (trigger.isRepetitive)
		    {
			var v = value.length? value : [value];
			for (var i=0;i<v.length;i++)
			{
			    trigger.addAChild(child,trigger.getValueNode(v[i]));
			}
		    }
		    else
			trigger.replaceChild(child, trigger.getValueNode(value));
		}
	    }
	}
    }
    if (subFlow.isRepetitive)
	subFlow.addAChild(displayNode,child);
    else
	subFlow.replaceChild(displayNode,child);
    child.readyToStart();
    
    var ctx = child.getExecutionContext()
    if (ctx === rootDisplayNode)
	resumeRoot();
    else
    {
	ctx.doResume();
        if (window.trace)
            window.trace.flush();
        if (this == window.rootDisplayNode)
            tersus.progress.clear();
        $(window).trigger('ter-process-end');
    }
};

function isBusy()
{
    return(window.rootDisplayNode && window.rootDisplayNode.status != FlowStatus.WAITING_FOR_INPUT)
};
function checkBusy()
{
    if (isBusy())
    {
	if (window.rootDisplayNode.errorHandler)
	{
	    var $pausedNodes = $(tersus.scanHierarchy(window.rootDisplayNode, tersus.Node.subFlowIterator, function(node){return node.status == FlowStatus.PAUSED;}));
            // To get to active nodes, we exclude from paused nodes the parents of paused nodes 
	    var $activeNodes = $pausedNodes.not($pausedNodes.map(function(i,node){return node.parent;}));
	    // Then concatenate all with new line spearators as the details
	    var details = $activeNodes.map(function(i,node){return node.getPath().str;}).toArray().join('\n'); 
	    window.rootDisplayNode.handleException({message:'Application is busy',details:details});
	}
	else if (tersus.alertMode.interactive)
	    tersus.error('The application is busy, please wait (or refresh)');
	return true;
    }
    else
	return false;
};
function resumeRoot()
{
    var start = new Date();
    if (tlog) tlog('resumeRoot');
    if (! tersus.progress.active)
	tersus.progress.set('Busy...');
    if (tlog) tlog ('resumeRoot: resuming root node');
    window.rootDisplayNode.doResume();
    if (window.trace)
    {
	if (tlog) tlog("resumeRoot: flushing trace");
	window.trace.flush();
    }
    var end = new Date();
    $(window).trigger('ter-process-end');
    if (tlog) tlog("resumeRoot: duration: " + (end - start) + " ms.");
    window.duration = "Action duration: " + (end - start) + " ms.";

};

tersus.queueEventDelay = 5000;
function queueEvent(object, method, args, startTime,description, callback, maxDelay)
{
    if (!maxDelay)
	maxDelay=tersus.queueEventDelay;
    if (isBusy())
    {
	var now = new Date();
	var delay = now - startTime;
	if (tlog) 
	{
	    if (!description)
		description = method.name;
	    tlog('QE: Busy ('+delay+' ms) - '+description);
	}
	if (delay < maxDelay || maxDelay<0)
	{
	    tersus.progress.set('Busy ...');
	    setTimeout(function() {queueEvent(object,method, args, startTime, description, callback, maxDelay);},100);
	    return;
	}
    }
    //TODO - provide a nice visual indication that the system is waiting for something, and 
    // a way for the user to abort the running operation (or refresh the screen).
    // In the meantime, we use 'checkBusy()', that shows a warning message.
    if (checkBusy())
    {
	if (tlog)
	    tlog('QE: Giving up - '+description);
	if (callback)
	    tersus.async.exec(callback,false);
	return;
    }
    if (tlog)
	tlog('QE: Invoking - '+description);
    /* TODO prevent concurrent operation:
       
       -- If we have a single user gesture triggering multiple events, we want them all to run, even if the first one takes a long time
       -- However, we don't want them to run "in parallel" (in simulated parallel)
       -- Therefore, putting them in the async queue is not good enough (they will run "in parallel")
       -- We may need to add a pre-queue (maybe a variant of queueEvent that runs for ever)
       
    */
    tersus.async.exec (function () {method.apply(object,args);if (callback)
	tersus.async.exec(callback,true);}, true /* wait if busy */);
};

tersus.traverseHierarchy = function traverseHierarchy(root, iterator, operation)
{
    var alreadyScanned = {};
    var iteration = function(node)
    {
	var id = node.getNodeId();
	if (alreadyScanned[id])
	    return;
	alreadyScanned[id] = true;
	var stop = operation(node);
	if (stop == true)
	    return true;
	iterator(node,iteration);
    }
    iteration(root);
}
tersus.scanHierarchy = function scanHierarchy(root, iterator, filter)
{
    var alreadyScanned = {};
    var out = [];
    var operation = function(node)
    {
	if (filter(node))
	    out.push(node);
    };
    tersus.traverseHierarchy(root,iterator, operation);
    return out;
}
tersus.sqlize = function(str)
{
    return str.replace(/[^a-zA-Z0-9]/g, "_");
};



function stats()
{
    var packages = {};
    var nModels = 0;
    var nPackages = 0;
    for (var modelId in tersus.repository.constructors)
    {
	++nModels;
	var packageId = tersus.getPackageId(modelId);
	if (packages[packageId])
	    ++packages[packageId];
	else
	{
	    packages[packageId]=1;
	    ++nPackages;
	}
    }
    var message = 'Total models:'+nModels;
    message += 'Total packages:'+nPackages;
    for (var packageId in packages)
    {
	message += '\n'+packageId+':'+packages[packageId];
    }
    var w = window.open();
    w.document.write('<pre>');
    w.document.write(message);
    w.document.write('</pre>');
    w.document.close();

}
tersus.getPackageId = function(modelId)
{
    var i = modelId.lastIndexOf('/');
    return modelId.substring(0,i);
};
Function.prototype.__subclass = function(name, c)
{
    if (!c)
	c = function(){};
    c.name=name;
    c.prototype = new this();
    c.prototype.constructor = c;
    c.prototype.parentPrototype = this.prototype;
    c.prototype.supr = function(name, args)
    {
	if (args === undefined)
	    args = [];
	var p = this.parentPrototype;
	var f = this[name];
	while (p && p[name]===f)
	    p = p.parentPrototype;
	return p[name].apply(this,args);
    };
    return c;
};

tersus.newAction = function(name, startFunc)
{
    var c = ActionNode.__subclass('tersus.'+name);
    c.prototype.start = startFunc;
    tersus[name]=c;
};

tersus.findChildNodesByClassName = function(node, className, out)
{
    if (!out) out = [];
    if (node.className && node.className==className)
	out.push(node);
    var children = node.childNodes;
    for( var i = 0; i<children.length; i++)
    {
	tersus.findChildNodesByClassName(children[i], className, out);
    }
    return out;
};
tersus.adjustHeight = function (domNode, delta)
{
    var currentHeight =  getVisibleSize(domNode).height ;
    if (window.browser != 'IE')
    {
	var paddingBottom = parseInt(getActualStyle(domNode,'padding-bottom'));
	var paddingTop = parseInt(getActualStyle(domNode,'padding-top'));
	currentHeight -= (paddingBottom + paddingTop);
    }
    domNode.style.height = (currentHeight + delta) + 'px';
}

tersus.foreach = function(array, f)
{
    if (array && array.length)
	for (var i=0;i<array.length; i++)
    {
	f(array[i]);
    }
}

tersus.preventDefaultEventHandling = function()
{
    var ev = tersus.currentEvent;
    if (ev)
    {
	if (ev.preventDefault)
	    ev.preventDefault();
	else
	    ev.returnValue=false;
	
	if (ev.stopPropagation)
            ev.stopPropagation();
	else
            ev.cancelBubble = true;
    }		
}
tersus.isIPhone =  navigator.userAgent.toLowerCase().indexOf('iphone') >=0 || tersus.searchParams.UserAgent == 'iPhone';
tersus.isIPhoneSafari =  navigator.userAgent.toLowerCase().indexOf('iphone') >=0 && navigator.userAgent.toLowerCase().indexOf('applewebkit') >=0 ;
if (tersus.isPhone)
    tersus.useIFrames = false;

tersus.foreach = function(a, func, contextObj)
{
    if (a == null)
	return;
    for (var i=0;i<a.length;i++)
    {
	func.call(contextObj, a[i], i);
    };
};
tersus.addAll = function (a1, a2)
{
    tersus.foreach(a2, function(x) {a1.push(x);});
};
// file: 006-errors.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Exception = function(message,cause)
{
	this.message = message;
	this.cause = cause;
};
tersus.Exception.prototype = new tersus.Exception(null,null);
tersus.Exception.prototype.toString = function()
{
	return this.message;
}
tersus.errors = null;

tersus.notify = function(title,msg)
{
	if (window.alert)
		window.alert(msg);
	else if (navigator.notification)
    {
	    navigator.notification.alert(msg, function(){}, title, 'OK');                 
    }

};

tersus.error = function(msg)
{
	if (window.tlog) 
		tlog(msg);
	else if (window.console)
		console.log(msg);
	if (tersus.errors)
		tersus.errors.push(msg);
	else 
		tersus.notify('Error',msg);
};

tersus.getErrors = function()
{	
	if (tersus.errors == null || tersus.errors.length == 0)
		return null;
	else
		return tersus.errors.join('\n');
};

tersus.clearErrors = function()
{
	tersus.errors=[];
};

tersus.serverError = function(msg)
{
	tersus.error(msg);
	if (tersus.pendingServiceCalls)
	{
		var list = tersus.pendingServiceCalls.toList();
		if (list.length == 1)
		{
			var node = tersus.findNode(list[0]);
			if (node && node.handleResponse)
			{
				node.handleResponse({});
			}
		}
		else if (length > 1)
		{
			tersus.error("Can't identify caller.  Please refresh.");
		}
	}
};
// file: 009-Repository.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function ConstructorRepository()
{
	this.constructors = {};
	this.htmlTemplates = {};
	this.preloaded = {};
	this.loadedPackages = [];
	this.packageTexts = {};
	this.parsedPackages = {};
};
ConstructorRepository.prototype.add = function add_prototype(c)
{
	this.constructors[c.prototype.modelId]=c;
};

ConstructorRepository.prototype.get = function get(id)
{
	if (!this.constructors[id])
	{
		this.parsePackage(tersus.getPackageId(id));
	}
	if (! this.constructors[id])
	{
		if (tlog) tlog('Not preloaded:'+id);
		this.loadPackages([tersus.getPackageId(id)]);
		this.parsePackage(tersus.getPackageId(id));
	}
	var c =  this.constructors[id];
	return c;
};
ConstructorRepository.prototype.isLoaded = function(modelId)
{
	this.parsePackage(tersus.getPackageId(modelId));
	// Check again - maybe the package was parsed and now the constructor is there
	return (this.constructors[modelId]!=undefined);
};
ConstructorRepository.prototype.parsePackage = function(packageId)
{
	if (this.packageTexts[packageId] && !this.parsedPackages[packageId])
	{
		var t0 = new Date();
		this.parsedPackages[packageId] = true;
		var text = this.packageTexts[packageId];
		var models = eval(text);
		var t1 = new Date();
		for (var i=0;i<models.length;i++)
		{
			this.loadModel(packageId, models[i]);
		}
		var t2 = new Date();
		if (tlog)
			tlog('LOADER: ' + packageId+ ': '+models.length+' models loaded in '+(t2-t0) + ' ms ( eval time='+(t1-t0) + ' ms)');
	}
	
};

ConstructorRepository.prototype.loadModel = function (packageId, m)
{
	var c = function(){this.init();};
	var p = c.prototype = eval ('new '+m.c + '()');
	p.constructor = c;
	p.modelId = packageId + '/'+m.n;
	p.modelName = m.n;
	p.plugin = m.p;
	if (p.initModel)
		p.initModel();
	if (m.sp != null)
		p.sharedProperties = m.sp;
	if (m.pv != null)
		p.pluginVersion = m.pv;
	if (m.cc != null)
		p.cancellable = m.cc;
	if (m.sc != null)
		p.secure = m.sc;
	if (m.runImmediately != null)
		p.runImmediately=m.runImmediately;
	if (m.eventHandling != null)
		 p.eventHandling=m.eventHandling;
	if (m.serviceTimeout != null)
		 p.serviceTimeout=m.serviceTimeout;
	if (m.pm != null) p.progressMessage = m.pm;
	if (m.xmlNS != null)
		p.xmlNamespace = m.xmlNS;
	if (m.format != null)
		p.format = m.format;
	if (m.formatAsGMT != null)
		p.formatAsGMT = m.formatAsGMT;
	if (m.progressMessage != null) p.progressMessage = m.progressMessage;
	if (m.v != null)
	{
		try
		{
			p.parseString(m.v);
		}
		catch (e)
		{
			throw {message:'Invalid value/format for '+p.modelId + ' details='+e.message};
		}
	}
	if (m.tableName)
		p.tableName=m.tableName;
	if (m.e)
	{
		for (var i=0;i<m.e.length;i++)
		{
			var me = m.e[i];
			var e = null;
			switch (me.t)
			{
				case 'sf':
				  e = p.addSubFlow(me.r,me.ref);
				  break;
				case 'l':
			      e = p.addLink(me.r, me.src, me.tgt);
			      break;
			    case 'ctx':
			      e = p.addAncestorReference(me.r,me.ref);
			      break;
			    case 'const':
			      e = p.addConstant(me.r,me.ref);
			      break;
			    case 'var':
			      e = p.addIntermediateDataElement(me.r,me.ref);
			      break;
			    case 'da':
			      e = p.addDataElement(me.r,me.ref);
			      break;
			    case 'di':
			      e = p.addDisplayElement(me.r,me.ref,me.ep);
			      break;
			    case 'tr':
			      e = p.addTrigger(me.r, me.ref);
			      break;
			    case 'ex':
			      e = p.addExit(me.r,me.ref);
			      break;
			    case 'er':
			      e = p.addErrorExit(me.r,me.ref);
			      break;
			    default:
			      throw new tersus.Exception('Invalid Model ('+p.modelId+'): unknown element type "'+me.t+'"');
			      
			}
			if (e)
			{
				if (me.rep != null)	e.isRepetitive = me.rep;
				if (me.rk != null)	e.dependencyRank = me.rk;
				if (me.m != null)	e.mandatory = me.m;
				if (me.ac != null)	e.alwaysCreate = me.ac;
				if (me.v != null)	e.valueStr = me.v;
				if (me.ct != null)	e.isConstantTrigger = me.ct;
				if (me.op != null)	e.operation = me.op;
				if (me.sr != null)	e.isSelfReady = me.sr;
				if (me.primaryKey != null) e.isPrimaryKey = me.primaryKey;
				if (me.columnName != null) e.columnName = me.columnName;
				if (me.xmlNS != null) e.xmlNamespace = me.xmlNS;
				if (me.format != null) e.format = me.format;
				if (me.formatAsGMT != null) e.formatAsGMT = me.formatAsGMT;
			}
		}
	}
	this.add(c);
	if (p.onload)
		p.onload();
	
	
};
ConstructorRepository.prototype.checkLoaded = function(modelId)
{
	if (this.isLoaded(modelId))
		return true;
	for (var i=0;i<this.loadedPackages.length;i++)
	{
		var packageId = this.loadedPackages[i];
		if (modelId.substring(0,packageId.length) == packageId
			&& modelId.charAt(packageId.length) == '/')
		{
			modelError("Missing model "+modelId + "\n(pakcage "+packageId + " already loaded)");
			break;
		}
	}
	return false;
		
}

var MAX_URL_LENGTH=1024;
tersus.packageLoader = function(){};
tersus.packageLoader.prototype.onload = function(packages)
{
	tersus[this.scriptCallback] = null; //Drop reference to allow garbage collection
	for (var id in packages)
	{
		tersus.repository.packageTexts[id] = packages[id];
	}
	this.runAsync();
};
tersus.packageLoader.error = function(msg)
{
	tersus.error('An error has occurred while loading the application:\n'+msg);
};
tersus.nextPackageLoaderId = 1;
tersus.packageLoader.prototype.runAsync = function runAsync()
{
	var userName = tersus.getUserName();
	var loader=this;
	if (loader.currentIndex == loader.packageIds.length)
	{
		setTimeout(loader.callback,0);
		return;
	}
	if (window.localStorage && tersus.useLocalStorage) // new mechanism - packages stored in local storage 
	{
		var url = tersus.rootURL+'Code';
        var paramString='packages=';
        while (this.currentIndex<this.packageIds.length)
        {
        	paramString += encodeURIComponent(':'+loader.packageIds[this.currentIndex]);
        	++ this.currentIndex;
        }
        var tsKey = tersus.rootURL+':LAST_TIMESTAMP';
        var storedTimestamp = localStorage.getItem(tsKey);
        var timestamp = Math.max(tersus.lastTimestamp, storedTimestamp);
        var storageKey=tersus.rootURL+':Code?timestamp='+timestamp+'&user='+encodeURIComponent(userName)+'&'+paramString;
        if (timestamp == storedTimestamp)
        {
        	var text = localStorage.getItem(storageKey);
        	if (text != null)
        	{
        		var packages = eval(text);
        		loader.onload(packages);
        		if (tlog) tlog('Loaded from local Storage');
       			return; 	
        	}
        }
        else
        {
        	for (var i=localStorage.length -1; i>=0 ;i--)
        	{
        		var key=localStorage.key(i);
        		if (key.search(/^(Code|File)\?/) >= 0)
        		{
	       			localStorage.removeItem(key);
	       			if (tlog) tlog('Removing '+key + ' from local storage');
	       		}
        	}
        	localStorage.removeItem(tsKey);
        	
        }
 		var req = createXMLHTTPRequest();
        req.onreadystatechange= function(){
        	if (req.readyState ==4)
        	{
        		if (req.status==200)
        		{
        			var text = req.responseText;
	        		var packages=eval(text);
	        		try
	        		{
	        			localStorage.setItem(storageKey, text);
	        			localStorage.setItem(tsKey,timestamp);
	        		}
	        		catch (e)
	        		{
	        			if (localStorage.length > 0)
	        			{
	        				localStorage.clear();
	        				tersus.reloadApplication();
	        				return;
	        			}
	        			else 
	        			{
	        				tersus.error("Can't load application - local storage error:\n"+e);
	        				return;
	        			}
	        			
	        		}
	        		loader.onload(packages);
	        		if (tlog) tlog('Loaded from server');
	        	}
	        	else
	        	{
	        		tersus.error("Failed to load models from server");
	        	}
	        }
	        	
        };
        req.open('POST', url, true);
        req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
        req.send(paramString);
		return;
	}
	else // old mode
	{
		loader.scriptCallback = 'loadPackages'+(tersus.nextPackageLoaderId ++);
		tersus[loader.scriptCallback] = function(constructors) { loader.onload(constructors);};
		var url = tersus.rootURL+'Code?timestamp='+tersus.lastTimestamp+'&_js_callback='+'tersus.'+loader.scriptCallback+'&user='+encodeURIComponent(userName)+'&packages=';
			
		// We may need to split the request into multiple requests if the url ends up too long
		for (var nextIndex=loader.currentIndex;nextIndex<loader.packageIds.length;nextIndex++)
		{
			var nextURL = url+encodeURIComponent(':'+loader.packageIds[nextIndex]);
			if (nextURL.length > MAX_URL_LENGTH)
				break;
			else
				url = nextURL;
		}		
		if (nextIndex==loader.currentIndex)
		{
			modelError("Package id "+loader.packageIds[nextIndex] + " is too long to load");
			return;
		}
		if (tersus.progress.active)
			tersus.progress.set("Loading application components");
		loader.currentIndex = nextIndex;
		tersus.loadScript(url);
	}
};
tersus.packageLoader.prototype.runSync = function runSync()
{
	var loader = this;
	var url = tersus.rootURL+'Code?timestamp='+tersus.lastTimestamp+'&user='+encodeURIComponent(tersus.getUserName())+'&packages=';
	
	// We work hard to retrieve packages using 'GET', as this will enable caching
	// This means we sometimes have to split the list into multiple requests
	if (tersus.progress.active)
		tersus.progress.set("Loading application components");
	while (loader.currentIndex < loader.packageIds.length)
	{
		for (var nextIndex=loader.currentIndex;nextIndex<loader.packageIds.length;nextIndex++)
		{
			var nextURL = url+encodeURIComponent(':'+loader.packageIds[nextIndex]);
			if (nextURL.length > MAX_URL_LENGTH)
				break;
			else
				url = nextURL;
		}		
		if (nextIndex==loader.currentIndex)
		{
			modelError("Package id "+loader.packageIds[nextIndex] + " is too long to load");
			return;
		}
		loader.currentIndex = nextIndex;
		var jsText = tersus.loadURL(url);
		if (jsText)
		{
			var packages = eval(jsText);	
			for (var id in packages)
			{
				tersus.repository.packageTexts[id] = packages[id];
			}
		}
	}
};
ConstructorRepository.prototype.loadPackages = function loadPackages(packageIds, callback) 
{
	if (tlog) tlog('Loading packages: '+packageIds.join(';'));
	for (var i=0;i<packageIds.length;i++)
	{
		this.loadedPackages.push(packageIds[i]);
	}

	var loader = new tersus.packageLoader();
	
	loader.packageIds = packageIds;
	loader.callback = callback;
	loader.currentIndex = 0;
	if (loader.callback)
		loader.runAsync();
	else
		loader.runSync();
};


ConstructorRepository.prototype.content = function content()
{
	var content = null;
	for (var id in this.constructors)
	{
		if (! content)
			content = id;
		else
			content = content + '\n'+id;
	}
	return content;
};
ConstructorRepository.prototype.templateNumber = 0;

//TODO - change loading mechanism so that html snippets are loaded with model
tersus.preloadedTemplates = {};
tersus.preloadTemplate = function(name,text)
{
	tersus.preloadedTemplates[name]=text;
};
ConstructorRepository.prototype.extractTemplate = function(path,html)
{
	var $t0=$(html);
	var $t = $t0.filter('#content').add($t0.find('#content')); // content cound be top level or lower level
	if (! $t[0]) // Create a container for all content nodes of the template
	{
		var $t = $('<div>');
		$t.append($t0.filter('*').not('title,script,meta'));//filter('*') excludes text nodes
	}
	this.saveTemplate(path, $t[0]);
	return $t[0];
};
ConstructorRepository.prototype.loadHTMLTemplate = function (path)
{
	if (this.htmlTemplates[path])
		return; //Already loaded
	if (tersus.preloadedTemplates[path] != null)
	{
		var text = tersus.preloadedTemplates[path];
		var template = document.createElement('DIV');
		template.innerHTML = text;
		this.saveTemplate(path, template);
		return;
	}
	if (tersus.progress.active)
	{
		var message;
		if (tersus.progressMessage)
			message = tersus.progressMessage;
		else
			message = 'Loading template '+path + '...';
		tersus.progress.set(message);
	}
	var html = tersus.loadFile(path);
	
	this.extractTemplate(path,html);
	
	/*
	
	// Old mechanism (no jQuery)
	if (tersus.progress.active)
		tersus.progress.set('Template loaded.');
	var name = 'templateFrame_'+ (++this.templateNumber);
	var iframe = window.createAnIFrame(window, name);
	var iframeNode = window.document.getElementById(name);
	var repository=this;
	var count=0;
	var cont1 = function()
	{
		++count;
		var d = iframeNode.contentDocument;
		var w = iframeNode.contentWindow;
		if ( d == null && w == null)
		{
			if (count < 50)
				setTimeout(cont1,50);
			else
				tersus.error('Failed to load template '+path);
			return;
		}
		if (d == null)
		{
			d = iframeNode.contentWindow.document;
		}
		d.write(html);
		d.close();
		var cont2 = function() 
		{
			var templateNode = d.getElementById('content');
			if (!templateNode)
				templateNode = d.body;
			templateNode.id='';
			var template;
			if (templateNode.tagName == 'BODY')
			{
				template = document.createElement('DIV');
				template.innerHTML = templateNode.innerHTML;
			}
			else
			{
			  template =  importNode(window.document,templateNode);
			}
			repository.processTemplate(template);
			iframeNode.parentNode.removeChild(iframeNode);
			repository.htmlTemplates[path]=template;
		};
		setTimeout(cont2,50);
	}
	setTimeout(cont1,50);
	*/
};
ConstructorRepository.prototype.saveTemplate = function saveTemplate(path,template)
{
	this.processTemplate(template);
	this.htmlTemplates[path]=template;
};
//TODO move this mechanism to "Embedded HTML" so that it isn't loaded unnecessarity
ConstructorRepository.prototype.getHTMLTemplate = function (path)
{
	var template = this.htmlTemplates[path];
	if (!template)
	{
		var wasInProgress = tersus.progress.active;
		var progressMessage;
		if (tersus.progressMessage)
			message = tersus.progressMessage;
		else
			message = 'Loading template '+path + '...';
		
		tersus.progress.set(message);
		var html = tersus.loadFile(path);
		if (wasInProgress)
			tersus.progress.set('Template loaded.');
		else
			tersus.progress.clear();
			
		/*
		// Old mechanism
		
		var name = 'templateFrame';
		var iframe = window.createAnIFrame(window, name);
		var iframeNode = window.document.getElementById(name);
		var d = iframeNode.contentWindow.document;
		d.write(html);
		d.close();
		var templateNode = d.getElementById('content');
		if (!templateNode)
			templateNode = d.body;
		var template;
		if (templateNode.tagName == 'BODY')
		{
			template = document.createElement('DIV');
			template.innerHTML = templateNode.innerHTML;
		}
		else
		{
		  template =  importNode(window.document,templateNode);
		}
		this.processTemplate(template);
		iframeNode.parentNode.removeChild(iframeNode);
		this.htmlTemplates[path]=template;
		*/
		
		var template = this.extractTemplate(path,html);
	}
	return template;
};
/**
 * Perform the following processing for a template:
 *
 * 1) Remove sample nodes
 * 2) Hide repetitive template nodes
*/

ConstructorRepository.prototype.processTemplate = function(template)
{
	var $t=$(template);
	$t.attr('id','');
	$t.find("[repetitive=sample]").remove();
	$t.find("[repetitive=true]").css('display','none');

/*
	var elements = template.getElementsByTagName('*');
	for (var i=0; i<elements.length; i++)
	{
		var e = elements[i];
		var repetitive  = e.getAttribute('repetitive');
		if (repetitive == 'sample')
		{
			if (e.parentNode)
				e.parentNode.removeChild(e);
		}
		else if (repetitive == true)
			e.style.display='none';
	}
	*/
};

// file: 011-Path.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
//Path
function Path(pathStr)
{
	if (pathStr !== null && pathStr !== undefined)
	{
		this.str = pathStr;
	 	if (pathStr.length == 0)
			this.segments = [];
		else
			this.segments = pathStr.split('/');
	}
};

Path.prototype.setSegments = function(segments)
{
	this.segments = segments;
	this.str = segments.join('/');
};
Path.prototype.toString = function toString() {return this.str;};
Path.prototype.addSegment = function addSegment(role) 
{
	this.segments.push(role);
	this.str += '/' + role;
};

Path.prototype.getElement = function (parent)
{
	var currentModel = parent;
	var currentElement = null;
	for (var i=0; i<this.segments.length;i++)
	{
		if (currentModel == null)
			return null;
		currentElement = currentModel.getElement(this.segments[i]);
		if (currentElement == null)
			return null;
		if (currentElement.modelId)
			currentModel = tersus.repository.get(currentElement.modelId).prototype;
		else
			currentModel = null;
		
	};
	return currentElement;
};
Path.prototype.clone = function()
{
	var clone = new Path();
	clone.segments = this.segments.concat();
	clone.str = this.str;
	return clone;	
};


// file: 012-Node.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 //Generic Runtime Node
tersus.Node = function tersus_Node() {};
tersus.Node.prototype.type='Node';
tersus.Node.prototype.textTranslation = true;
tersus.Node.prototype.pluginVersion = 0;
tersus.Node.prototype.getPrototype = function()
{
	if (this.modelId)
		return tersus.repository.get(this.modelId).prototype;
}
tersus.Node.prototype.getNodeId = function()
{
	if (!this.nodeId)
	{
		this.nodeId = window.nextNodeId ? window.nextNodeId : 1;
		window.nextNodeId = this.nodeId + 1;
	}
	return this.nodeId;
};
tersus.Node.prototype.getModelId = function()
{
	return this.modelId;
};
tersus.Node.prototype.isInstance = function(value)
{
	return value && value.isNode && value.modelId == this.modelId;
};
tersus.Node.prototype.init = function() {}; // Called when a concrete instance is created
tersus.findNodeOld = function findNodeOld(id)
{
	if (tlog) tlog("Trying to find node "+id);

	var node = window.rootDisplayNode.findById(id);
	if (node)
	{
		if (tlog) tlog("Node "+id + " found.");
		return node;
	}
	tersus.unregisterPopupNodes();
	for (var popupId in tersus.popupNodes)
	{
		node = tersus.popupNodes[popupId].findById(id);
		if (node)
		{
			if (tlog) tlog("Node "+id + " found.");
			return node;
		}
	}
	return null;
		
};
tersus.Node.prototype.findById = function(id, alreadyScanned, depth)
{
	if (!depth)
	   depth=1;
		
	if (this.nodeId == id)
		return this;
	if (! this.elementList)
		return null;
	if (!alreadyScanned)
		alreadyScanned = {};
	var thisNodeId = this.getNodeId();
	if (alreadyScanned[thisNodeId])
		return null;
	alreadyScanned[thisNodeId]=true;
	for (var i=0; i<this.elementList.length; i++)
	{
		var e = this.elementList[i];
		if (e.isRepetitive)
		{
			var children = e.getChildren(this);
			for (var j=0; j<children.length;j++)
			{
				var child = children[j];
				if (child)
				{
					var node = child.findById(id, alreadyScanned, depth+1);
					if (node)
						return node;
				}
			}
		}
		else
		{
			var child = e.getChild(this);
			if (child)
			{
				var node = child.findById(id, alreadyScanned, depth+1);
				if (node)
					return node;
			}
		}
	}
	return null;
};

/* returns true if we the maximum number of results has been reached */

tersus.Node.prototype.scanChildren = function(filter, alreadyScanned, outputList, maxResults)
{
	var id = this.getNodeId();
	if (alreadyScanned[id])
		return false;
        if(maxResults!=null && maxResults <= outputList.length)
	    return true;
	alreadyScanned[id]=true;
	if (this.currentWindow && this.currentWindow.closed)
		return false;
	if (filter.match(this))
		outputList.push(this);
	if (! this.elementList)
		return false;
	for (var i=0; i<this.elementList.length; i++)
	{
		var e = this.elementList[i];
		if (e.isDisplayElement || e.isDataElement || e.isMethodElement)
		{
			if (e.isRepetitive)
			{
				var children = e.getChildren(this);
				for (var j=0; j<children.length;j++)
				{
					var child = children[j];
					if (child)
					{
						var rc = child.scanChildren(filter, alreadyScanned, outputList, maxResults);
					        if (rc)
						    return true;
					}
				}
			}
			else
			{
				var child = e.getChild(this);
				if (child)
				{
					var rc = child.scanChildren(filter, alreadyScanned, outputList, maxResults);
				        if (rc)
					    return true;
				}
			}
		}
	}
	return false;
};
tersus.Node.prototype.countHierarchy = function()
{
	var count = 1
	if (this.elementList)
	{
		for (var i=0; i<this.elementList.length; i++)
		{
			var e = this.elementList[i];
			if (e.isRepetitive)
			{
				var children = e.getChildren(this);
				for (var j=0; j<children.length;j++)
				{
					var child = children[j];
					if (child)
					{
						count += child.countHierarchy();
					}
				}
			}
		
			else
			{
				var child = e.getChild(this);
				if (child)
				{
					count += child.countHierarchy();
				}
			}
		}
	}
	return count;
};

tersus.Node.prototype.invokeLinks = function invokeLinks()
{
	var links = this.element.outgoingLinks;
	if (links)
	{
		for (var i=0; i<links.length; i++)
		{
			var link = links[i];
			link.invoke(this);		
		}
	}
};
tersus.Node.prototype.isNode = true;
tersus.Node.prototype.isReady = function isReady()
{
	return true;
};

tersus.Node.prototype.addElement = function addElement(element)
{
	if (!this.elements)
		this.elements = {};
	this.elements[element.role]=element;
	if (!this.elementList)
		this.elementList = [];
	this.elementList.push(element);
	element.owner = this;
	return element;
};

tersus.Node.prototype.getElement = function getElement(role)
{
	var element = null;
	if (this.elements)
		element = this.elements[role];
	if (element)
		return element;
	else
		return null;
};
tersus.Node.prototype.addGetter = function(role, getter)
{
	this['getter_'+role] = getter;
};
tersus.Node.prototype.addSetter = function(role, setter)
{
	this['setter_'+role] = setter;
};
tersus.Node.prototype.addRemover = function(role, remover)
{
	this['remover_'+role] = remover;
};

tersus.Node.prototype.getGetter = function getGetter(role)
{
	if (this['getter_'+role])
		return this['getter_'+role];
	else if (role.charAt(0)=='<')
		return this['get'+role];// Obsolete mode (still widely used as of June 2009)
	else return null;
};
tersus.Node.prototype.getSetter = function getSetter(role)
{
	if (this['setter_'+role])
		return this['setter_'+role];
	else if (role.charAt(0)=='<') 
		return this['set'+role]; // Obsolete mode (still widely used as of June 2009)
	else
		return null;
};
tersus.Node.prototype.getAdder = function getAdder(role)
{
	return this['add'+role];
};
tersus.Node.prototype.getRemover = function getRemover(role)
{
	if ( this['remover_'+role])
		return this['remover_'+role];
	else if (role.charAt(0)=='<') 
		return this['remove'+role]; // Obsolete mode (still widely used as of June 2009)
	else
		return null;
};

tersus.Node.prototype.getChild = function getChild(role)
{
	var element = this.getElement(role);
	if (element)
		return element.getChild(this);
	else
		return null;
};

tersus.Node.prototype.getChildren = function getChildren(role)
{
	var element = this.getElement(role);
	if (element)
		return element.getChildren(this);
	else
		return [];
};
/*
	Returns an array of all values at given path.
	path - a Path containing the required path
	index - an optional number indicating which segment in the path should be deemed first 
	         (the first 'index' segments are ignored.)
*/
tersus.Node.prototype.getValues = function getValues(path, index)
{
	if (!index)
		var index = 0;
	var values = [];
	this._getValues(path, index, values);
	return values;
};


/*
	Adds all values at a given path to a given array of values
	This method is used internally to implement 'getValues'/
	path - a Path containing the required path
	index - an optional number indicating which segment in the path should be deemed first 
	         (the first 'index' segments are ignored.)
	values - an array to which all values will be added.
	 
*/
tersus.Node.prototype._getValues = function _getValues(path, index, values)
{
	if (path.segments.length < index)
	{
		internalError('Bad path in _getValues');
		return;
	}
	var role = path.segments[index];
	if (path.segments.length == index )
	{ 
		values.push(this);
	}
	else
	{
		var element = this.getElement(role);
		if (!element)
			return; // The path links to a non-existant element (as of Feb 26, this can happen because of the way the permission mechanism works)
		if (element.isRepetitive)
		{
			var children = element.getChildren(this);
			for (var i=0; i<children.length; i++)
			{
				var child = children[i];
				if (child)
					child._getValues(path, index+1, values);
			}
		}
		else
		{
			var child = element.getChild(this);
			if (child)
				child._getValues(path, index+1, values);
			
		}
	}
}
/**
	Sets the value of a descendant, specified by path
	The index specifies a number of initial segments of the path that should be ignored
	(index = 0 means using the whole path, index = 1 means starting from the second segment).
*/
tersus.Node.prototype.setValue = function setValue(path, value, operation, index)
{
	if (! operation)
	{
		internalError('Operation not specified');
	}
	if (! index)
		var index = 0;
	if (path.segments.length <= index)
	{
		internalError('Bad path in setValue');
	}
	var role = path.segments[index];
	if (path.segments.length-1 == index)
	{
		var element = this.getElement(role);
		if (!element)
			return;// The path links to a non-existant element (as of 0.9.49, this can happen because of the way the permission mechanism works)
		element.setChild(this, value, operation);
	}
	else if (path.segments.length > index)
	{
		var element = this.getElement(role);
		if (! element)
			return; // The path links to a non-existant element (as of 0.9.49, this can happen because of the way the permission mechanism works)
		var child = element.getChild(this);
		if (! child)
			child = element.createChild(this); // Creating an intermediate level
		child.setValue(path, value, operation, index+1);
	}
};


tersus.Node.prototype.getPath = function getPath()
{
	if (this.parent)
	{
		var path = this.parent.getPath();
		path.addSegment(this.element.role);
		return path;
	}
	else
		return new Path(tersus.viewPath);
};
tersus.Node.prototype.setAlwaysCreate = function setAlwaysCreate(role, alwaysCreate)
{
	this.elements[role].alwaysCreate = alwaysCreate;
};
// Performs any operation needed when this node is deleted
tersus.Node.prototype.onDelete = function onDelete() 
{
};

// Performs a 'set' operation with a leafValue
// Returns true if the operation is sucessful, false if there is no element with the given role
tersus.Node.prototype.setLeafChild = function setLeafChild(role, leafValue, operation)
{
	if (leafValue == null)
		return;
	var element = this.getElement(role);
	if (!element)
		return false;
	var value = element.createChildInstance();
	value.setLeaf(leafValue);
	element.setChild(this, value, operation);
	return true;
};

tersus.Node.prototype.getLeafChild = function getLeafChild(role)
{
	var child = this.getChild(role);
	if (child)
		return child.leafValue;
	else
		return null;
};
tersus.Node.prototype.setChild = function setChild(role, value, operation)
{
	var element = this.getElement(role);
	if (!element)
		return false;
	element.setChild(this, value, operation);
	return true;
};
tersus.Node.prototype.setLeaf = function setLeaf(value)
{
	this.leafValue = value;
};

tersus.Node.prototype.parseString = function(str)
{
	this.leafValue = str;
};
tersus.Node.prototype.copyObject = function copyObject(value, strict)
{
	if (this.isLeaf)
		this.setLeaf(value);
	else if (this.elements)
	{
	    for (var elementRole in this.elements)
	    {
		var element = this.getElement(elementRole);
		if (element.isRepetitive)
		{
		    var values = value[elementRole];
		    if (values)
		    {
			for (var i=0; i< values.length; i++)
			{
			    var child = element.createChild(this);
			    child.copyObject(values[i], strict);
			}
		    }
		}
		else
		{
		    var childValue = value[elementRole];
		    if (childValue !== null && childValue !== undefined)
		    {
			var child = element.createChild(this);
			child.copyObject(childValue, strict);
		    }
		}
	    }
	    if (strict)
	    {
		var e = this.elements;
		$.each(value, function(key,value) {
		    if (!e[key])
			throw "Unknown element "+key;
		});
	    }
	}
};
tersus.Node.prototype.getTranslation = function(key)
{
	if (tersus.labelMap)
	{
		var v = tersus.labelMap[key];
		if (v && v.leafValue)
			return v.leafValue;
		else
			return v;
	}
};

tersus.Node.prototype.translate = function (s)
{
	if (! this.textTranslation)
		return s;
	return this.forceTranslate(s);
};
tersus.Node.prototype.forceTranslate = function (s)
{
	var t = this.getTranslation(s);
	if (t != undefined)
		return t;
	else
		return s;
};
tersus.Node.prototype.preloadOnStart = true;
tersus.Node.prototype.preload = function(callback)
{
	if (tersus.repository.preloaded[this.modelId])
		return true;
	var packageSet = new Set();
	if (tlog) var startTime = new Date();
	var	alreadyChecked = new Set();
	this.addPreloadPackages(packageSet,alreadyChecked);
	this.addMissingLinkTargets(packageSet,alreadyChecked);
	if (tlog)
	{
		var endTime = new Date();
		if (tlog) tlog("Package scan took "+(endTime-startTime) +" milliseconds");
	}
	var packageList = packageSet.toList();
	if (packageList.length == 0)
	{
		tersus.repository.preloaded[this.modelId] = true;
		return true;
	}
	else
	{
		if (tlog) tlog('Preloading '+this.modelId);
		packageList.sort();
		var mainPackages = [];
		var last = null;
		for (var i=0;i<packageList.length;i++)
		{
			var current = packageList[i];
			if (last && last == current.substring(0,last.length))
				continue;
			mainPackages.push(current);
			last = current;
		}
		this.pause();
		tersus.repository.loadPackages(mainPackages, callback);
		return false;
	}
};
tersus.Node.prototype.addPreloadPackages = function (packageSet, alreadyChecked)
{
	if (tersus.repository.preloaded[this.modelId])
		return;
	if (alreadyChecked.contains(this.modelId))
		return;
	alreadyChecked.add(this.modelId);
	if (this.elementList)
	{
		for (var i=0;i<this.elementList.length;i++)
		{
			var e = this.elementList[i];
			if (e.modelId)
			{
				if (!tersus.repository.checkLoaded(e.modelId))
				{
					var packageId = tersus.getPackageId(e.modelId);
					packageSet.add(packageId);
				}
				else 
				{
					if (e.isDisplayElement || e.isFlowDataElement || ! this.isDisplayNode )
					{
						var childConstructor = tersus.repository.get(e.modelId);
						var childModel = childConstructor.prototype;
//						if (childModel.preloadOnStart)
//							childModel.addPreloadPackages(packageSet, alreadyChecked);
					}
				}
			}
		}
	}
};
tersus.Node.prototype.addMissingLinkTargets = function (packageSet, alreadyChecked)
{
	if (!this.links)
		return;
	for (var i=0;i<this.links.length; i++)
	{
		var link = this.links[i];
		var currentModel = this;
		var segments = link.target.segments;
		for (var j=0; j< segments.length; j++)
		{
			var element = currentModel.getElement(segments[j]);
			if (!element)
				continue; // This can happen if there is no permission
			var id = element.modelId;
			if (!id)
				continue; 
			if (! tersus.repository.checkLoaded(id))
			{
				if (tlog) tlog('Need to preload '+id);
				var packageId = tersus.getPackageId(id);
				packageSet.add(packageId);
				break;
			}
			else
			{
				currentModel = tersus.repository.get(id).prototype;	
				if (currentModel.preloadOnStart)
					currentModel.addPreloadPackages(packageSet,alreadyChecked);
			}
		}
	}
	return true;
};	
tersus.Node.prototype.destroyHierarchy = function()
{
	this.destroyChildren();
        if (this.destroy)
                this.destroy();
};
tersus.Node.prototype.destroyChildren = function()
{
        tersus.Node.subFlowIterator(this,function(node) {node.destroyHierarchy()});
};

tersus.Node.childIterator = function (node,iteration)
{
	if (node && node.elements)
	{
		for (var i=0; i<node.elementList.length; i++)
		{
			var e = node.elementList[i];
			if ( e.isRepetitive)
			{
				var children  = e.getChildren(node);
				for (var j=0;j<children.length;j++)
				{
					var stop = iteration(children[j]);
					if (stop == true)
						return;
				}
			}
			else
			{
				var child = e.getChild(node);
				if (child)
				{
					var stop = iteration(child);
					if (stop == true)
						return;
				}
			}
		}
	}
	
};
tersus.Node.subFlowIterator = function (node,iteration)
{
	if (node && node.subFlowList)
	{
		for (var i=0; i<node.subFlowList.length; i++)
		{
			var e = node.subFlowList[i];
			if ( e.isRepetitive)
			{
				var children  = e.getChildren(node);
				for (var j=0;j<children.length;j++)
				{
					var stop = iteration(children[j]);
					if (stop == true)
						return;
				}
			}
			else
			{
				var child = e.getChild(node);
				if (child)
				{
					var stop = iteration(child);
					if (stop == true)
						return;
				}
			}
		}
	}
	
};

tersus.compare = function (obj1, obj2)
{
	if (obj1 == null)
		return obj2 == null ? 0 : -1;
	return obj1.compare(obj2);
};
tersus.Node.prototype.compare = function (obj2)
{
    /* Note: r3431 contains a generalized implementation of comparison, which has been reverted out of backward and client-server compatibility concerns.  The new implementation remains a good idea, but will significant effort to complete (client+server), review and test */
	if (obj2 == null)
		return 1;
	var obj1 = this;
    if (!this.isInstance(obj2))
        throw "compare: Can't compare "+obj1.modelId + " and "+ obj2.modelId;
        
    if (this.isLeaf)
    	return obj1.leafValue > obj2.leafValue ? 1 : obj1.leafValue == obj2.leafValue ? 0 : -1;

    for (var i = 0; i < this.elementList.length; i++)
    {
        var e = this.elementList[i];
        if (e.isRepetitive)
        {
            var list1 = e.getChildren(obj1);
            var list2 = e.getChildren(obj2);
            var commonSize = Math.min(list1.length, list2.length);
            for (var j=0; j<commonSize;j++)
            {
                var item1 = list1[j]
                var item2 = list2[j];
                
               	var comparison = tersus.compare(item1, item2);
                if (comparison != 0)
                    return comparison;
            }
            return list1.length - list2.length;
        }
        else
        {
            var v1 = e.getChild(obj1);
            var v2 = e.getChild(obj2);
            var comparison = tersus.compare(v1, v2);
            if (comparison != 0)
                return comparison;
        }
    }
    return 0;
};

tersus.Node.prototype.isRecursive = function()
{
    /* Checks if the model represents a potentially recursive structure - used to optimize recursions*/
    var model = this.constructor.prototype;
    if (model.__isRecursive === undefined)
    {
        if (model.__isRecursive || model.__in_recursion_check ||model.modelId == tersus.ANYTHING || model.isMap ||model.constructor === tersus.DynamicDisplay)
        {
            model.__isRecursive = true; 
            return true;
        }
        else
        {
            var recursive = false;
            model.__in_recursion_check=true;
            try
            {
                if (model.elementList)
                {
                    for (var i=0;i<model.elementList.length;i++)
                    {
                        var e = model.elementList[i];
                        var childModel = e.getChildConstructor().prototype;
                        if (childModel.isRecursive())
                        {
                            recursive= true;
                            break;
                        }
                        
                    }
                }
                model.__isRecursive=recursive;
            }
            finally
            {
                delete model.__in_recursion_check;
            }
        }
    }
    return model.__isRecursive;
};


// file: 013-Element.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Element() {};
/**
	createChildInstance - creates an instance of the model refered by this element.
	 
	Note: the instance is not added to the parent node (which is not specified).

	
*/
Element.prototype.dependencyRank = -1;
Element.prototype.isRemovable = true;
Element.prototype.alwaysCreate = true;
Element.prototype.getChildConstructor = function (explicitModelId)
{
	var modelId = explicitModelId ? explicitModelId : this.modelId;
	var childConstructor;
	if (modelId)
		childConstructor = tersus.repository.get(modelId);
	else
		childConstructor = DataValue;
	if (! childConstructor)
	{
		var message ="'"+ this.modelId + "' not found in constructor repository.\n";
		message += "Existing consructors:\n";
		for (var modelId in tersus.repository.constructors)
		{
			message += "'" + modelId + "'\n";
		}
		tersus.error(message);
	}
	return childConstructor;
};
Element.prototype.createChildInstance = function createChildInstance(modelId)
{
	var childConstructor = this.getChildConstructor(modelId);
	var childInstance = new childConstructor();
	childInstance.prototype = childConstructor.prototype;
	return childInstance;
}

/*
	Creates a child instance, and stores it as a child.
	(This implementation is used by DataElements and Exits. Display Elements have a different implementation).
*/
Element.prototype.createChild = function createChild(parent)
{
	var childInstance = this.createChildInstance();
	this.addChild(parent, childInstance);
	return childInstance;
};	
Element.prototype.addChild = function addChild(parent, child)
{
	if (! parent.children)
		parent.children = {};
	if (this.isRepetitive)
	{
		if (! parent.children[this.role])
			parent.children[this.role] = [];
		parent.children[this.role].push(child);
	}
	else
	{
		parent.children[this.role] = child;
	}
};
Element.prototype.isEmpty = function isEmpty(parent)
{
	if (this.isRepetitive)
	{
		var children = this.getChildren(parent);
		return (! children || children.length ==0);
	}
	else
	{
		var child = this.getChild(parent);
		return (! child);
	}
};
Element.prototype.getChild = function getChild(parent)
{
	if ( this.isRepetitive)
		internalError("getChild(parent) called on repetitive element");
	var child = null;
	if (parent.children)
		child = parent.children[this.role];
	return child;
};

/*
	returns a list of children (child instances) of a given parent.
	If there are no such children, an empty list is returned.
	IMPORTANT:  The caller must not modify the returned list 
*/
Element.prototype.getChildren = function getChildren(parent)
{
	if ( ! this.isRepetitive)
		internalError("getChildren(parent) called on non repetitive element");
	var children = null;
	if (parent.children)
		children = parent.children[this.role];
	if (! children)
		children = [];
	return children;
};

Element.prototype.removeChildren = function removeChildren(parent)
{
    if (!this.isRepetitive)
        makeAssertion( this.isRepetitive, "removeChildren called on non-repetitive element "+this.role+" of "+ parent.modelId);
	var children = this.getChildren(parent);
	for (var i=0; i< children.length; i++)
	{
		var child = children[i];
		if (child && child.parent == parent)
			child.onDelete();
	}
	if (parent.children)
		parent.children[this.role] = [];
};

Element.prototype.removeNumberedChild = function removeNumberedChild(parent, index)
{
    if (!this.isRepetitive)
        makeAssertion( this.isRepetitive, "removeNumberedChild called on non-repetitive element "+this.role+" of "+ parent.modelId);
	var children = this.getChildren(parent);
	children.splice(index - 1, 1);
};

Element.prototype.setChildren = function setChildren(parent, values, operation)
{
	if ( ! this.isRepetitive)
		internalError("setChildren(parent, values, operation) called on non repetitive element "+this.role + " of "+parent.modelId);
	if (operation ==  Operation.REPLACE)
		this.removeChildren(parent);
	for (var i=0; i<values.length; i++)
	{
		var value = values[i];
		this.setChild(parent, value, Operation.ADD);
	}
};


Element.prototype.addAChild = function addAChild(parent,value)
{
	if (! parent.children)
		parent.children = {};
	if (!this.isRepetitive)
	    makeAssertion( this.isRepetitive,"addAChild called on non-repetitive element "+this.role+" of "+parent.modelId);
	if (! parent.children[this.role])
		parent.children[this.role] = [];
	parent.children[this.role].push(value);
};
Element.prototype.replaceChild = function replaceChild(parent, value)
{
    if (this.isRepetitive)
        makeAssertion( ! this.isRepetitive, "replaceChild called on repetitive element "+this.role+" of "+parent.modelId);
	if (! parent.children)
		parent.children = {};
	if (this.modelId && tersus.repository.get(this.modelId).prototype.isNothing && ! value.isNothing)
		this.createChild(parent); // Creates a new instance of Nothing
	else
		parent.children[this.role]=value;	
}
Element.prototype.removeChild = function removeChildren(parent)
{
    if (this.isRepetitive)
        makeAssertion( ! this.isRepetitive, "removeChild called on repetitive element "+this.role+" of "+parent.modelId);
	if (! parent.children)
		return;
	var child = this.getChild(parent);
	if (child != null)
	{
		if (parent.hasElementChangeHandler)
		{
			var oldValue = child.isDataNode ? child.value : child;
			parent.handleElementChange(this.role, oldValue, null);
		}
		delete parent.children[this.role];
		if (child && child.parent == parent)
			child.onDelete();
	}
};



Element.prototype.setChild = function setChild(parent, value, operation)
{
	if (! parent.children)
		parent.children = {};
	if (this.isRepetitive)
	{
		if (operation == Operation.ADD)
			this.addAChild(parent, value);
		else if (operation == Operation.REMOVE)
			this.removeChildren(parent);
		else
			internalError('Operation '+operation+' not supported for repetitive elements');
		
	}
	else
	{
		if (operation == Operation.REPLACE)
			this.replaceChild(parent, value,true);
		else if (operation == Operation.REMOVE)
			this.removeChild(parent);
		else
			
			internalError('Operation '+operation+' not supported for non-repetitive elements');
	}
};
Element.prototype.moveChild = function (parent, fromIndex, toIndex)
{
	var children = this.getChildren(parent);
	var child = children.splice(fromIndex, 1)[0];
	children.splice(toIndex,0,child);
	return child;
};
Element.prototype.getValueNode = function(value)
{
	if (value == null)
		return null;
	var valueNode;
	if (value.isNode)
		valueNode=value;
	else
	{
		valueNode=this.createChildInstance();
		valueNode.setLeaf(value);
	}
	return valueNode;
};
// file: 015-DataNode.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
//DataNode (of a Flow)
//A DataNode holds a reference to some value, and participates in the flow
// (it can be invoked).
function DataNode() {};
DataNode.prototype = new tersus.Node();
DataNode.prototype.constructor = DataNode;
DataNode.prototype.isDataNode = true;
DataNode.prototype.invoke = function()
{
	if (window.trace)
		window.trace.activated(this);
	this.invokeLinks();
}
DataNode.prototype.toString = function toString()
{
	return this.leafValue + '['+this.modelId +']';
};
DataNode.prototype.copyObject = function copyObject(obj)
{
	this.value.copyObject(obj);
};
DataNode.prototype._getValues = function _getValues(path, index, values)
{
	if (index == path.segments.length)
		values.push(this.value);
	else
		return this.value._getValues(path, index, values);
}
DataNode.prototype.setValue = function setValue(path, value, operation, index)
{
	this.value.setValue(path, value, operation, index);
	//TODO we probably need a special case for leaf data nodes
};
DataNode.prototype.scanChildren = function(filter, alreadyScanned, outputList)
{
// Do nothing - we don't want to scan variables 
//	this.value.scanChildren(filter, alreadyScanned, outputList);
};
DataNode.prototype.getModelId = function()
{
	return this.value.getModelId();
};
// file: 020-FlowNode.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
//FlowNode - an instance of FlowModel (implements composite behavior)

function FlowNode() {};
FlowNode.prototype = new tersus.Node();
FlowNode.prototype.constructor = FlowNode;
FlowNode.prototype.errorExit = null;
FlowNode.prototype.errorHandler = null;
FlowNode.prototype.addSubFlow = function addSubFlow(role, modelId)
{
	// Adds a representation of the sub-flow both to a list of sub-flows
	// and to a map of sub-flows
	var subFlow = new SubFlow(role, modelId);
	this.registerSubFlow(subFlow);
	return this.addElement(subFlow);
}
FlowNode.prototype.registerSubFlow = function registerSubFlow(subFlow)
{
	if (! this.subFlowMap)
		this.subFlowMap = {};
	this.subFlowMap[subFlow.role] = subFlow;
	if (! this.subFlowList)
		this.subFlowList = [];
	this.subFlowList.push(subFlow);
};
/**
	Returns the sole DisplayElement of this Flow.
	Returns null if there are 0 or multiple DisplayElements.
*/
FlowNode.prototype.addAncestorReference = function addAncestorReference(role, modelId)
{
	var reference = new FlowDataElement(role, modelId);
	reference.isAncestorReference = true;
	if (! this.ancestorReferenceList)
		this.ancestorReferenceList = [];
	
	this.ancestorReferenceList.push(reference);
	return this.addElement(reference);
};

FlowNode.prototype.addIntermediateDataElement = function addIntermediateDataElement(role, modelId)
{
	if (this.getGetter(role))
	{
		var element = new MethodElement(this, role, modelId);
		element.modelId = modelId;
	}
	else
		var element = new FlowDataElement(role, modelId);
	return this.addElement(element);
};

FlowNode.prototype.addConstant = function addConstant(role, modelId)
{
	var constantReference = new FlowDataElement(role, modelId);
	constantReference.type = 'Constant';
	if (!this.constantList)
		this.constantList = [];
	this.constantList.push(constantReference);
	return this.addElement(constantReference);
};

FlowNode.prototype.addLink = function addLink(role, source, target)
{
	if (!this.elements)
		return null; // If there are no elements, there is nothing to link. This can happen because of permission issues  
		
	var link = new Link(role, source,target);
	var sourceElement;
	if (!this.links)
		this.links = [];
	this.links.push(link);
	var sourceElement = this.elements[link.source.segments[0]];
	if (! sourceElement)
		return;
	if (! sourceElement.outgoingLinks)
		sourceElement.outgoingLinks = [];
	sourceElement.outgoingLinks.push(link);
	return link;
};

FlowNode.prototype.getLink = function getLink(role)
{
	if (! this.links)
		return null;
	for (var i=0; i<this.links.length; i++)
	{
		var link = this.links[i];
		if (link.role == role)
			return link;
	}
	return null;
};

/*
	Called before a FlowNode is started
*/
FlowNode.prototype.started = function started()
{
	this.setStatus(FlowStatus.STARTED);
	if (window.trace)
		window.trace.started(this);
};
FlowNode.prototype.resumed = function ()
{
	this.setStatus(FlowStatus.RESUMED);
};

FlowNode.prototype.finished = function ()
{
	/* Because actions can contain pop-up windows, finish() may be called more than once,
	 * but we don't want the <Done> exit to be charged again, or the trace to contain an additional event*/
	
	if (! this.alreadyFinished)
	{
		if (!this.error)
		{
			var doneExit = this.getElement(BuiltinNames.DONE_EXIT_NAME);
			if (doneExit)
				this.chargeEmptyExit(doneExit);
		}
		if (window.trace)
			window.trace.finished(this);
		if (this.whenDone)
			this.whenDone();
	}
	this.setStatus(FlowStatus.DONE);
	this.alreadyFinished = true;
}
FlowNode.prototype.waiting = function ()
{
	this.setStatus(FlowStatus.WAITING_FOR_INPUT);
	if (window.trace)
		window.trace.waiting(this);
}
FlowNode.prototype.continueExecution = function()
{
		var executionContext = this.getExecutionContext();
		this.resumeAfterPause();
		executionContext.doResume();
		if (window.trace)
			window.trace.flush();
		if (this == window.rootDisplayNode)
			tersus.progress.clear();
		$(window).trigger('ter-process-end');
};
FlowNode.prototype.doStart = function()
{
	var node = this;
	var	resume = function()
	{
		if (tlog) tlog(node.modelName,'resumed after preload', node.modelId);
		node.resumeAfterPause();
		node.setStatus(FlowStatus.READY_TO_START);
		var executionContext = node.getExecutionContext();
		executionContext.doResume();
		if (window.trace)
			window.trace.flush();
	};
	if (! this.preloadOnStart || this.preload(resume))
	{
		if (tlog) tlog(node.modelName,'started (already loaded)', node.modelId);
	
		var isAtomic = this.isAction && !this.subFlowMap;
		var isDisplay = this.isDisplayNode;
		var isRoot = !this.getParentContext();
		if (isAtomic || this.errorExit  || this.onerror|| (isRoot&&!tersus.failOnScriptErrors))
		{
			try
			{
				this.started();
				this.start();
				if (tlog) tlog(node.modelName,'started done', node.modelId);
			}
			catch (e)
			{
				if (this.errorExit || this.errorHandler || isRoot || isDisplay)
					this.handleException(e);
				else
					throw this.convertException(e);
			}
		}
		else
		{
			this.started();
			this.start();
			if (tlog) tlog(node.modelName,'started done', node.modelId);
		}
		if (this.status != FlowStatus.PAUSED)
		{
			if (this.isAction)
				this.finished();
			else
				this.waiting();
		}
	}
	else
		if (tlog) tlog(node.modelName,'paused(waiting for models to load)', node.modelId);
};
FlowNode.prototype.convertException = function(e)
{
	if (typeof e === 'object' && 'getMessage' in e) // Java exception
	{
		e = {message: e.getClass().getName() + ' - ' + e.getMessage()};
	}
	else if (typeof e != 'object')
		e = {message:''+e};
	if (!e.errorPath)
		e.errorPath = this.getPath().str;
	return e;
}
FlowNode.prototype.handleException = function (e)
{
	e = this.convertException(e);
	var msg = e.message?e.message:''+e;
	var details = e.details;
	
	if (this.errorHandler)
	{
		var ERROR='<Error>';
		var cc = this.errorHandler.getChildConstructor();
		var errorTrigger = cc.prototype.getElement(ERROR);
		var params = null; 
		if (errorTrigger)
		{
			params = {};
			var eObj = params[ERROR] = new (errorTrigger.getChildConstructor());
			eObj.setLeafChild('Message', msg, Operation.REPLACE);
			eObj.setLeafChild('Location', e.errorPath, Operation.REPLACE);
			if (details)
				eObj.setLeafChild('Details', e.details, Operation.REPLACE);
		}
		var process = new BackgroundProcess(this, this.errorHandler, params);
		//process.whenDone(callback);
		setTimeout(function(){process.start();},0); 
	}
	else if (this.errorExit)
	{
		var error = this.errorExit.createChildInstance();
		error.setLeafChild('Message', msg, Operation.REPLACE);
		error.setLeafChild('Location', e.errorPath, Operation.REPLACE);
		this.chargeExit(this.errorExit,error);
		this.error = error;
	}
	else
	{
		//TODO  - Throw if below event level, Show message box if at event level
	    tersus.lastError=e;
		var m ="An error has occurred: "+e.message;
		if (e.details)
			m+='\n\nDetails: '+e.details;
		if (e.errorPath)
			m+='\n\nPath: '+e.errorPath;
		
		if (this.currentWindow && !tersus.checkWindow(this.currentWindow))
		{
			m += "\n\nThe problem may have been caused by closing a pop-up window while it was being populated."
		}
		tersus.error(m);
	}
};
FlowNode.prototype.doResume = function doResume(message)
{
	this.resumed();
	var isAtomic = this.isAction && !this.subFlowMap;
	var isDisplay = this.isDisplayNode;
	var isRoot = !this.getParentContext();
	try
	{
		if (isAtomic || this.errorExit || this.errorHandler || (isRoot&&!tersus.failOnScriptErrors))
		{
			try
			{
				this.resume();
			}
			catch (e)
			{
				if (this.errorExit || this.errorHandler || isRoot)
					this.handleException(e);
				else
					throw this.convertException(e);
			}
		}
		else
		{
			this.resume();
		}
	}
	finally
	{
		if (this.status != FlowStatus.PAUSED)
		{
			if (this.isAction)
				this.finished();
			else
				this.waiting();
		}
	}
};

FlowNode.prototype.start = function()
{
	var element; //represents a model element
	var child; // represents a child instance (sub-flow instance)
	var role;
	// add trigger values to the ready queue
	if (this.triggers)
		for (var i = 0; i < this.triggers.length; i++)
		{
			var trigger = this.triggers[i];
			
			if (trigger.isRepetitive)
			{
				var values = trigger.getChildren(this);
				trigger.removeChildren(this);
				for (var j=0; j< values.length; j++)
				{
					var value = values[j];
					this.createReference(trigger, value);
				}
			}		
			else
			{
				var value = this.getChild(trigger.role);
				if (value)
					this.createReference(trigger, value);
			}
		}
			
			
		//create instances for constants
		if (this.constantList)
		{
			for (var i=0; i< this.constantList.length; i++)
			{
				element = this.constantList[i];
				if (element.isSelfReady)
					child = element.createChild(this);
			}
		}
		
		if (this.ancestorReferenceList)
		{
			var ancestor;
			var ancestorData;
			var referenceNode;
			for (var i=0; i< this.ancestorReferenceList.length; i++)
			{
				element = this.ancestorReferenceList[i];
				role = element.role;
				ancestor = this.parent;
				var child = null;
				while (ancestor)
				{
					var parentElement = ancestor.getElement(role);
					if ( parentElement && parentElement.modelId == element.modelId) // In the direct ancestor we will find the referring element
					{
						var parentObj = parentElement.getChild(ancestor);
						if (parentObj)
							child = this.createReference(element, parentObj);
						ancestor = null;
					}
					else if (ancestor.modelId == element.modelId)
					{
						child = this.createReference(element, ancestor);
						ancestor = null; //No need to continue searching
					}
					else
					{
						ancestor = ancestor.parent;
					}
				}
				if (! child)
					if (tlog)
						tlog("Missing ancestor reference for "+role + " in "+ this.modelId);

			}
		}
		this.createSubFlows();
		this.runLoop();
	};
FlowNode.prototype.createSubFlows = function()
{
	//initializes sub flows
	if (this.subFlowList)
	{
		for (var i=0;i<this.subFlowList.length; i++)
		{
			var subFlow = this.subFlowList[i];
			subFlow.init(this);
		}
	}
};


FlowNode.prototype.createReference = function createReference(element, value)
{
	var child = new DataNode();
	child.type = element.type;
	child.mainWindow = this.mainWindow;
	child.currentWindow = this.currentWindow;
	child.parent = this;
	child.element = element;
	if (value.isDataNode)
		child.value = value.value;
	else
		child.value = value;
	element.addChild(this, child);
	if (child.isReady())
		this.addReadyElement(child);
	return child;
};




FlowNode.prototype.readyToResume = function readyToResume()
{
		this.setStatus(FlowStatus.READY_TO_RESUME);
		var parent = this.getParentContext();
		if (parent == null)
			return;
		parent.addReadyElement(this);
		if (parent.status == FlowStatus.WAITING_FOR_INPUT || parent.status == FlowStatus.DONE)
			parent.readyToResume();
};

/*
	Marks this FlowNode and its ancestors as ready to resume from the point of pause:
	(The paused processes are added to the beginning of the run-queue)
	
*/
FlowNode.prototype.resumeAfterPause = function resumeAfterPause()
{
	this.setStatus(FlowStatus.READY_TO_RESUME);
	var parent = this.getParentContext();
	if (parent == null)
		return;
	if ( ! parent.readyElements)
		parent.readyElements = [];
	parent.readyElements.splice(0,0, this); // insert at the beginning
	parent.resumeAfterPause();
}	

FlowNode.prototype.pause = function pause()
{
	this.setStatus(FlowStatus.PAUSED);
	if (window.trace)
		window.trace.paused(this);
	var parent = this.getParentContext();
	if (parent)
		parent.pause();
};

FlowNode.prototype.readyToStart = function readyToStart()
{
		this.setStatus(FlowStatus.READY_TO_START);
		var parent = this.getParentContext();
		if (parent == null)
			return;
		parent.addReadyElement(this);
		if (parent.status == FlowStatus.WAITING_FOR_INPUT || parent.status == FlowStatus.DONE)
			parent.readyToResume();
};
FlowNode.prototype.setInitialStatus = function setInitialStatus()
{
	this.setStatus(FlowStatus.NOT_READY_TO_START);
	this.checkReady();
};

FlowNode.prototype.checkReady = function checkReady()
{
	if (this.status == FlowStatus.NOT_READY_TO_START && this.isReady())
	{
		this.readyToStart();
	}
		
};

/*
	Adds 'child' to the run-queue, while preserving the dependency rank order
	('child' is added at the largest index that will result in a non-decreasing 
	dependency rank order)
*/
FlowNode.prototype.addReadyElement = function addReadyElement(child)
{
	
	
	
	var childRank = child.element.dependencyRank;
	
	
	if (!this.readyElements)
		this.readyElements = [];
	var targetIndex = this.readyElements.length;
	if( child.element === this.initElement) // <Init>
	{
		var parent = this;
		// After <Init> is done, we need to create child elements
		child.whenDone = function()
		{
			parent.createChildren();
		};
		// <Init> must be executed first
		targetIndex = 0;
	}
	else
	{
		while (targetIndex > 0)
		{
			var node = this.readyElements[targetIndex-1];
			var nodeRank = node.element.dependencyRank;
			if (nodeRank <= childRank)
			{
				// child should be inserted at targetIndex
				break;
			}
			--targetIndex;
		}
	}
	// Calling splice adds 'child' at targetIndex
	this.readyElements.splice(targetIndex, 0, child);
	
};

FlowNode.prototype.setStatus = function setStatus(status)
{
	if (tlog)
		tlog('STATUS ['+this.getNodeId()+' - '+this.modelName+']: '+this.status+' => '+status);
	this.status = status;
};


FlowNode.prototype.resume = function resume(message)
{

	this.runLoop();

	if (this == window.rootDisplayNode && 	this.status == FlowStatus.WAITING_FOR_INPUT)
		if (tersus.async.nowait())
			tersus.progress.clear();
};
FlowNode.prototype.isReady = function isReady()
{
	if (this.triggers)
	{
		for (var i=0; i<this.triggers.length; i++)
		{
			var trigger = this.triggers[i];
			if (trigger.mandatory)
			{
				if (trigger.isEmpty(this))
				{
					return false;
				}
			}
		}
	}
	return true;
};
FlowNode.prototype.runLoop = function run()
{
	var child;
//		createParentElementReferences(context, flow);
	while (this.status != FlowStatus.PAUSED && this.hasReadyElements())
	{
		child = this.readyElements.shift();
		child.invoke(); //Start or resume
	}

};

FlowNode.prototype.hasReadyElements = function hasReadyElements()
{
	return (this.readyElements && this.readyElements.length > 0);
};

FlowNode.prototype.invoke = function invoke ()
{
	switch(this.status)
	{
		case FlowStatus.READY_TO_START:
			this.doStart();
			break;
		case FlowStatus.READY_TO_RESUME:
			this.doResume();
			break;
		default:
			internalError('Child with invalid status invoked '+ this.status);
	}
	if (this.status != FlowStatus.PAUSED)
		this.invokeLinks();
	//TODO - remove exit values / input values
};

FlowNode.prototype.chargeEmptyExit = function chargeEmptyExit(exit)
{
	if (! exit.isExit)
		exit = this.getExit(exit); // exit given by name
	if (exit)
	{
		exit.createChild(this);
		if (window.trace)
		{
			window.trace.charged(this, exit);
		};
	}
};

FlowNode.prototype.getExit = function (name)
{
	if (!this.exits)
		return null;
	var exit = this.getElement(name);
	if (exit && exit.isExit)
		return exit;
	else if (name.search(/^<.*>$/)>=0) // Distinguished name - allow perfixes
	{
		var l = name.length;
		for (var i=0; i<this.exits.length; i++)
		{
			var current = this.exits[i];
			var r=current.role;
			if (r.substr(-l) == name && r.indexOf('<')==r.length-l)
			{
				if (exit)
					return null; //ambigous
				exit = current;
			}
		}
	}
	return exit;
};

FlowNode.prototype.getTrigger = function (name)
{
	if (!this.triggers)
		return null;
	var trigger = this.getElement(name);
	if (trigger)
		return trigger;
	else if (name.search(/^<.*>$/)>=0) // Distinguished name - allow perfixes
	{
		var l = name.length;
		for (var i=0; i<this.triggers.length; i++)
		{
			var current = this.triggers[i];
			var r=current.role;
			if (r.substr(-l) == name && r.indexOf('<')==r.length-l)
			{
				if (trigger)
					return null; //ambigous
				trigger = current;
			}
		}
	}
	return trigger;
};
FlowNode.prototype.getTriggerLeafValue = function(role)
{
	var trigger = this.getTrigger(role);
	var value = null;
	if (trigger)
	{
		value = trigger.getChild(this);
		if (value != null)
			value = value.leafValue;
	}
	return value;
};
FlowNode.prototype.chargeExit = function (exit, value)
{
	if (! exit.isExit)
		exit = this.getExit(exit);
	if (exit)
	{
		exit.replaceChild(this,value);
		if (window.trace)
			window.trace.charged(this, exit, value);
	}
};
FlowNode.prototype.accumulateExitValue = function(exit, value)
{
	if (! exit.isExit)
		exit = this.getExit(exit);
	if (exit)
	{
		exit.addAChild(this,value);
		if (window.trace)
			window.trace.charged(this, exit, value);
	}
};

FlowNode.prototype.chargeLeafExit = function chargeLeafExit(exit, leafValue)
{

	if (! exit.isExit)
		exit = this.getExit(exit); // exit given by name
	if (exit && (leafValue != null) )
	{
		var child = exit.createChild(this);
		child.setLeaf(leafValue);
		if (window.trace)
			window.trace.charged(this, exit, child);
		
	}
};

FlowNode.prototype.getExecutionContext = function getExecutionContext()
{
	if (this.getParentContext())
		return this.getParentContext().getExecutionContext();
	else
		return this;
};

FlowNode.prototype.getParentContext = function getParentContext()
{
	return this.parent;
};

FlowNode.prototype.addTrigger = function addTrigger(role, modelId)
{
	if (! this.triggers)
		this.triggers = [];
	var trigger = new Trigger(role, modelId);
	this.triggers.push( trigger);
	return this.addElement(trigger);
};

FlowNode.prototype.addExit = function addExit(role, modelId)
{
	if (! this.exits)
		this.exits = [];
	var exit = new Exit(role, modelId);
	this.exits.push( exit);
	return this.addElement(exit);
};
FlowNode.prototype.addErrorExit = function addErrorExit(role, modelId)
{
	var e = this.addExit(role,modelId);
	if (this.errorExit)
		modelError('Multiple Error exits',this);
	this.errorExit = e;
	e.isError=true;
	return e;
};

FlowNode.prototype.getTriggerValues = function getTriggerValues(excludedTriggerName)
{
	var values = [];
	for (var i=0; i<this.triggers.length; i++)
	{
		var trigger = this.triggers[i];
		if (trigger.modelId != BuiltinModels.NOTHING_ID && trigger.role != excludedTriggerName )
		{
			if (trigger.isRepetitive)
			{
				values = values.concat(trigger.getChildren(this));
			}
			else
			{
				var value = trigger.getChild(this);
				if (value !== null && value !== undefined)
					values.push(value);	
			}
			
		}
	}
	return values;
};

FlowNode.prototype.getEventHandler = function(eventType)
{
	if (! this.subFlowMap)
		return null;
	var handler = this.subFlowMap[eventType.elementName];
	if (handler == undefined)
		return null;
	return handler;
};
FlowNode.prototype.hasEventHandler = function(eventType)
{
	return (this.getEventHandler(eventType) != null);
};

FlowNode.prototype.queueEvent = function (eventType, params, domEvent, callback, wait)
{
	var handler = this.getEventHandler(eventType);
	if (handler)
	{
		var eventAttrbutes = domEvent ? getEventAttributes(domEvent) : tersus.currentEventAttributes;
		var description = null;
		if (tlog)
		{
			description = eventType.methodName + ' ['+ this.getPath().str+']';
			tlog('queuing event:'+eventType.jsName ? eventType.jsName: eventType.elementName);
			if (eventAttrbutes)
				tlog('keyCode='+eventAttrbutes.keyCode+' type='+eventAttrbutes.type);
		}
		var c = handler.getChildConstructor();
		var p = c && c.prototype; // prototype or null
		
		var e = domEvent || tersus.currentEvent;
		if ( e &&  p.eventHandling)
		{
			if (p.eventHandling.match('stop_propagation'))
				e.stopPropagation();
			if (p.eventHandling.match('prevent_default'))
				e.preventDefault();
		    if (console) console.log(e.type+' ' + p.eventHandling);
		}
		
		if (p && p.runImmediately)
		{
			// Run a "background process" in current thread
			var process = new BackgroundProcess(this, handler, params);
			process.whenDone(callback);
			process.start(); 
		}
		else if (wait)
		{
		    var self=this;
		    tersus.async.exec(function()
		            {
		                window.engine.handleEvent(self, eventType, params, eventAttrbutes);
		            }, true /* wait */);
        }
		else
			queueEvent(window.engine, window.engine.handleEvent, [this,eventType,  params, eventAttrbutes], new Date(), description, callback);
	}
	else if (callback)
   		tersus.async.exec(callback,true);

};

FlowNode.map = {};
FlowNode.prototype.getNodeId = function()
{
        if (!this.nodeId)
        {
                this.nodeId = window.nextNodeId ? window.nextNodeId : 1;
                FlowNode.map[this.nodeId]=this;
                window.nextNodeId = this.nodeId + 1;
        }
        return this.nodeId;
};
FlowNode.prototype.destroy = function()
{
	if (this.nodeId)
		delete FlowNode.map[this.nodeId]
}
tersus.findNode = function findNode(id)
{
	return FlowNode.map[id];
}

// file: 021-ActionNode.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function ActionNode() {};
ActionNode.prototype = new FlowNode();
ActionNode.prototype.constructor = ActionNode;
ActionNode.prototype.isAction = true;
ActionNode.prototype.type="Action";
ActionNode.prototype.runImmediately=false;
// file: 024-BackgroundProcess.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 

function BackgroundProcess (parent, subflow, params)
{
	if (parent && subflow)
	{
		this.parent = parent;
		this.process = subflow.createChildInstance();
		this.context = new BackgroundProcessContext(parent);
		this.process.mainWindow = parent.mainWindow;
		this.process.currentWindow = parent.currentWindow;
		this.process.parent = this.context;
		this.process.element = subflow;
		if (params)
		{
			for (var key in params)
			{
			    var trigger = this.process.getElement(key);
			    if (trigger)
			    {
				var value  = params[key];
				if (value!=null && !value.isNode)
				    value = trigger.getValueNode(value);
				trigger.setChild(this.process, value, Operation.REPLACE);

			    }
			}
		}
	}
};

BackgroundProcess.prototype.setTriggerValue = function setTriggerValue(role, value)
{
	this.process.setChild(role,value, Operation.REPLACE);
};
BackgroundProcess.prototype.setTriggerLeafValue = function setTriggerValue(role, value)
{
	this.process.setLeafChild(role,value, Operation.REPLACE);
};


BackgroundProcess.prototype.getExitValues = function getExitValues(role)
{
	return this.process.getChildren(role);
};

BackgroundProcess.prototype.start = function()
{
	if (this.process.isReady())
		this.process.doStart();
	if (window.trace)
		window.trace.flush();
	
};
BackgroundProcess.prototype.whenDone = function whenDone(callback)
{
	this.process.whenDone = callback;
};
function BackgroundProcessContext(context)
{
	this.context = context;
	this.parent = context;
	this.setStatus(FlowStatus.WAITING_FOR_INPUT);
};
BackgroundProcessContext.prototype = new FlowNode();
BackgroundProcessContext.prototype.constructor = BackgroundProcessContext;
BackgroundProcessContext.prototype.getPath = function getPath()
{
	return this.context.getPath();
};
BackgroundProcessContext.prototype.getParentContext = function getParentContext()
{
	return null;
};
BackgroundProcessContext.prototype.isBackground = true;

// file: 025-DisplayNode.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at http://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
// DisplayNode (a FlowNode that displays soemthing)
function DisplayNode()
{
};


DisplayNode.prototype = new FlowNode();
DisplayNode.prototype.visible = true;
DisplayNode.prototype.constructor = DisplayNode;
DisplayNode.prototype.type='Display';
DisplayNode.prototype.isDisplayNode=true;
  
DisplayNode.prototype.explicitReadOnly = false;
DisplayNode.prototype.VALIDATION_MESSAGE = '<Validation Message>';

DisplayNode.prototype.setViewNode = function DisplayNode_setViewNode(viewNode)
{
	this.viewNode = viewNode;
};
DisplayNode.prototype.getValidationContext = function DisplayNode_getValidationContext()
{
	if (this.parent && this.parent.getValidationContext)
		return this.parent.getValidationContext();
	else
		return this;
};
DisplayNode.findNodeForDocumentNode = function(viewNode)
{
	var nodeId = null;
	while (viewNode && viewNode.getAttribute && !nodeId)
	{
		nodeId = viewNode.getAttribute("lid"); // logic node id
		if (! nodeId)
			nodeId = viewNode.id;
		if (nodeId)
			return tersus.findNode(nodeId);
		viewNode = viewNode.parentNode;
	}
	return null; 
};
DisplayNode.prototype.escapeHTML = function(s)
{
	if (this.sharedProperties.allowHTMLTags != true && ! this.allowHTMLTags)
		return tersus.escapeHTML(s);
	else
		return s;
};
DisplayNode.prototype._onFocus = function()
{
	var parent = this.parent;
	while (parent)
	{
		if (parent.onChildFocus)
			parent.onChildFocus();
		parent = parent.parent;
	}
};

tersus.createEventHandler = function(eventType)
{
	// Default event handler method on DisplayNode
	if (eventType.methodName)
	{
		DisplayNode.prototype[eventType.methodName] = function(domNode, callback)
		{
			if (window.trace)
			{
				window.trace.event(this, eventType);
			}
			var baseMethodName = '_'+eventType.methodName;
			if (this[baseMethodName])
				this[baseMethodName]();
			this.queueEvent(eventType, null, null, callback);
		
		}
	}
};

for (var key in Events)
{
	tersus.createEventHandler(Events[key]);
};

tersus.createEventDispatcher = function(eventType, w)
{
	// Event dispatching global function
	if (eventType.jsName && eventType.methodName)
	{
		w.tersus_dispatchers[eventType.jsName] = function(e)
		{
			var eName = eventType.name;
			var $this = $(this);
			if ($this.hasClass(eName))
			{
				if (tlog) tlog ('Duplicate ' + eName + ' ignored  on ' + this.tagName);
				return;
			}
			$this.addClass(eName);
			var clear = function()
			{
				$this.removeClass(eName);
			};
			var ev = e;
			if (ev == null)
			{
				var w = getParentWindow(this);
				ev = w.event;
			}
			if (tersus.disabled == true || tersus.disabled && tersus.disabled[eventType.jsName] == true)
				return true;
			if (ev)
				tersus.currentEventAttributes = getEventAttributes(ev);
			tersus.currentEvent = ev;
			try
			{
				var node = DisplayNode.findNodeForDocumentNode(this);
				if (tlog)
				{
					var tagDesc = this.tagName;
					if (this.className)
						tagDesc+='.'+this.className;
					tlog('Captured event: '+ eventType.methodName + ' on '+tagDesc+' ['+ node.getPath().str+']');
				}
				
				if (node)
				{
					return node[eventType.methodName].call(node, this, clear);
				}
				else
					return true;
			}
			finally
			{
				tersus.currentEvent = null;
			}
		};
	}
};


tersus.createEventDispatchers = function t_addEvents(w)
{
	w.tersus_dispatchers = {};
	for (var key in Events)
	{
		tersus.createEventDispatcher(Events[key], w);
	}
};

tersus.createEventDispatchers(window);
// New implementation based on jQuery and jQuery Mobile
DisplayNode.prototype.registerEventHandler = function(eventType,domNode)
{
  	if (!domNode)
    {
            if (this.eventTargets)
                    domNode = this.eventTargets[eventType.jsName];
            if (!domNode)
                    domNode = this.viewNode;
    }
    domNode.setAttribute('lid',this.getNodeId());
    if (!eventType.jsName)
    {
            internalError('No event dispatcher defined for '+eventType.elementName);
            return;
    }
    
    var dispatcher = this.currentWindow.tersus_dispatchers[eventType.jsName];
    if (dispatcher)
    {
    	var jqName = eventType.jsName.substr(2);
    	
    	var doc = domNode.ownerDocument;
		var w = doc.defaultView || doc.parentWindow;
    	if (w == window && jqName == 'click' && $.event.special.vclick) // Virtual events don't work in pop-up
    		jqName = 'vclick';
        $(domNode).unbind(jqName,dispatcher);
        $(domNode).bind(jqName,dispatcher);
    }
    else
            internalError('No event dispatcher defined for '+eventType.jsName);
    
};

/* Old implementation */
/*
DisplayNode.prototype.registerEventHandler = function(eventType, domNode)
{
	if (!domNode)
	{
		if (this.eventTargets)
			domNode = this.eventTargets[eventType.jsName];
		if (!domNode)
			domNode = this.viewNode;
	 }
	domNode.setAttribute('lid',this.getNodeId());
	if (!eventType.jsName)
	{
		internalError('No event dispatcher defined for '+eventType.elementName);
		return;
	}
	
	var dispatcher = this.currentWindow.tersus_dispatchers[eventType.jsName];
	if (dispatcher)
		domNode[eventType.jsName] = dispatcher;
	else
		internalError('No event dispatcher defined for '+eventType.jsName);
	
};
*/
DisplayNode.prototype.checkBooleanProperty = function (name)
{
	return this.sprop(name) == true;
}
DisplayNode.prototype.sprop = function (name) // Can be made redundant if we prevent blanks on loading
{
	if (!this.sharedProperties) 
		return null;
	var p = this.sharedProperties[name];
	return (p !== ' ' ? p :null);
}
DisplayNode.prototype.copyValue = function(value)
{
	this.deepCopy(value);
};
DisplayNode.prototype.create = function DisplayNode_create(value)
{
	if (! (tersus.preferHTMLCreation && this.checkBooleanProperty('optimizeHTML')) )
	{
		this.setTextTranslation();
		this.createViewNode();
		this.attachViewNode();
		this.initViewNode();
		if (!this.initElement)
			this.createChildren();
	}
	if (value != null)
		this.copyValue(value);
	
};
DisplayNode.prototype.createChildren = function DisplayNode_createChildren()
{
	if (this.displayElements)
	{
		for (var i=0; i<this.displayElements.length; i++)
		{
			var e = this.displayElements[i];
			if ( !e.isRepetitive && ! e.isMethodElement && e.alwaysCreate)
			{
				if (!e.getChild(this))
					e.createChild(this);
			}
		}
	}
	
};
DisplayNode.prototype.setDisplayOrder = function setDisplayOrder()
{
	var displayOrder = this.element? this.element.displayOrder:1;
	this.viewNode.setAttribute('display_order',displayOrder);
};
DisplayNode.prototype.attachViewNode = function DisplayNode_attachViewNode()
{
	if (! this.viewNode)
		return;
	if (this.parent)
	{
		this.setDisplayOrder();
		this.parent.appendChildViewNode(this, this.element);
	}
};
DisplayNode.prototype.initViewNode = function DisplayNode_initViewNode()
{
	if (this.defaultStyleClass)
		this.setStyleClass(this.defaultStyleClass);
	this.setProperties();
	this.setEventHandlers();

}
tersus.removeEventHandlers = function(domNode)
{
	var doc = domNode.ownerDocument;
	var w = doc.defaultView || doc.parentWindow;
	for (key in Events)
	{
		var eventType = Events[key];
		if (eventType.jsName)
		{
			var dispatcher = w.tersus_dispatchers[eventType.jsName];
    		if (dispatcher)
		    {
		    	var jqName = eventType.jsName.substr(2);
		    	if (w == window && jqName == 'click' && $.event.special.vclick) // Virtual events don't work in pop-up
		    		jqName = 'vclick';
		        $(domNode).unbind(jqName,dispatcher);
		    }
		}
	}
	
};
DisplayNode.prototype.setEventHandlers = function DisplayNode_setEventHandlers()
{
	for (var key in Events)
	{
		var eventType = Events[key];
		if (this.hasEventHandler(eventType) && eventType.jsName || this['_'+eventType.methodName])
		{
			if (this.element)
				this.registerEventHandler(eventType);
			else
				this.registerEventHandler(eventType,document.body);
		}
	}
	if (this.hasEventHandler(Events.ON_LOCATION_CHANGE))
		tersus.locationChangeListeners.push(this.getNodeId());
}
DisplayNode.prototype.removeChildViewNode = function(child)
{
	if (child)
	{
		var top = child.wrapperNode ? child.wrapperNode : child.viewNode;
		if (top && top.parentNode)
			top.parentNode.removeChild(top);
	}
};
DisplayNode.prototype.appendChildViewNode = function appendChildViewNode(child, childElement)
{
	var childNode;
	if (child.wrapperNode)
	{
		childNode = child.wrapperNode; // Child wrapper already created - no need to wrap again 
	}
	else if (child.sharedProperties && (child.sharedProperties.wrapperTag != null) && (child.sharedProperties.wrapperTag != ' ') )
	{
		childNode = this.createHTMLElement(child.sharedProperties.wrapperTag, child.sharedProperties.wrapperStyleClass);
		childNode.setAttribute('display_order', child.viewNode.getAttribute('display_order'));
		childNode.appendChild(child.viewNode);
		child.wrapperNode = childNode;
	}
	else
		childNode = child.viewNode;
	if (child.placeHolderNode)
	{
		this.viewNode.replaceChild(childNode, child.placeHolderNode);
		child.placeHolderNode = null;
	}
	else	
	{
		DisplayNode.appendChildNode(this.viewNode, childNode);
	}
		
};

DisplayNode.appendChildNode = function(parent, newChild)
{
	var displayOrder = parseFloat(newChild.getAttribute('display_order'));
	var children = parent.childNodes;
	for( var i = 0; i<children.length; i++)
	{
		var child = children[i];
		if (child.getAttribute && parseFloat(child.getAttribute('display_order')) > displayOrder)
		{
			parent.insertBefore(newChild, child);
			return;
		}
	}
	parent.appendChild(newChild);
};
DisplayNode.prototype.forDisplayChildren = function (f)
{
	if (this.displayElements)
	{
		for (var i=0;i<this.displayElements.length;i++)
		{
			var e = this.displayElements[i];
			if (e.isRepetitive)
			{
				var list = e.getChildren(this);
				for (var j=0;j<list.length;j++)
				{
					var child = list[j];
					if (child)
						if (f.call(null,child))
							reutrn;
				}
			}
			else
			{
				child = e.getChild(this);
				if (child)
					if (f.call(null,child))
						return;
			}
		}
	}
}	

DisplayNode.prototype.deleteMe = function()
{
	var element = this.element;
	var parent= this.parent;
	if (! parent)
		return;
	if (element.isRepetitive)
	{
		var siblings = element.getChildren(parent);
		for (var i=0;i<siblings.length;i++)
		{
			if (siblings[i] == this)
			{
				siblings.splice(i,1); // removes element at index i
				this.onDelete();
				return;
			}
		}
	}
	else
		element.removeChild(parent);
};
DisplayNode.prototype.destroy = function()
{
	FlowNode.prototype.destroy.call(this);
	// Remove event listener
	if (this.hasEventHandler(Events.ON_LOCATION_CHANGE))
	{
		// Remove this node's id from the tersus.locationChangeListeners
		var listeners = [];
		for (var i=0;i<tersus.locationChangeListeners.length;i++)
		{
			if (tersus.locationChangeListeners[i] != this.getNodeId())
				listeners.push(tersus.locationChangeListeners[i]);
		}
		tersus.locationChangeListeners = listeners;
	};
	
	if (this.hasEventHandler(Events.ON_DELETE))
	{
		var process = new BackgroundProcess(this, this.getEventHandler(Events.ON_DELETE));
		tersus.async.exec(function(){process.start()}, false /* don't wait */); 
	};
};
DisplayNode.prototype.onDelete = function onDelete()
{
	this.destroyHierarchy();
	if (this.parent)
		this.parent.removeChildViewNode(this);
};

DisplayNode.prototype.createHTMLElement = function createHTMLElement(tag, styleClass)
{
	var element = this.currentWindow.document.createElement(tag);
	if (styleClass && styleClass != ' ')
		element.className=styleClass;
	return element;
};
DisplayNode.prototype.createHTMLChildElement = function createHTMLChildElement(parentNode,tag, styleClass)
{
	var childNode = this.createHTMLElement(tag, styleClass);
	parentNode.appendChild(childNode);
	return childNode;
};
DisplayNode.prototype.getTag = function getTag()
{
	var t = this.sprop('tag');
	if (!t)
		t = this.defaultTag;
	return t;
};
DisplayNode.prototype.createViewNode = function DisplayNode_createViewNode()
{
	var tag = this.getTag();
	this.viewNode = this.createHTMLElement(tag);
	this.viewNode.setAttribute('lid',this.getNodeId());
};
DisplayNode.prototype.setProperties = function setProperties()
{
	var props = this.sharedProperties;
	if (!props)
		return;
	if (props.styleClass && props.styleClass != ' ')
		this.setStyleClass(props.styleClass);
	else if (this.defaultStyleClass)
		this.setStyleClass(this.defaultStyleClass);
	this.setStyle(props.style);
	if (props.label)
		this.viewNode.innerHTML = props.label;
/*	if (props.textTranslation !== null || props.textTranslaton !== undefined)
	{
		if (props.textTranslation == false)
			this.textTranslation = false;
		else
			this.textTranslation = true;
	}
*/	var tag = this.viewNode.tagName;
	for (var p in props)
	{
		var value = props[p];
		if ( value != ' ')
		{
			if ((p == 'width'|| p=='height') && value.search(/^[0-9]+$/)>=0)
				value = value+'px';
				
			if (HTMLProperties[tag] && HTMLProperties[tag][p])
				this.viewNode[p]=value;
			else if (STYLE_PROPERTIES[p])
				this.viewNode.style[STYLE_PROPERTIES[p]]=value;
		}
	}
};
DisplayNode.prototype.setTextTranslation = function setTextTranslation()
{
	var textTranslation = this.sharedProperties.textTranslation;
	if (textTranslation !== null && textTranslation !== undefined)
	{
		if (textTranslation == false)
			this.textTranslation = false;
		else
			this.textTranslation = true;
	}
};
DisplayNode.prototype.removeAll = function DisplayNode_removeAll()
{
	if (this.elements)
	{
		for (var i=0; i<this.elementList.length; i++)
		{
			var e = this.elementList[i];
			if (e.isRemovable)
			{
				if (e.isRepetitive)
				{
					e.removeChildren(this);
				}
				else
				{
					e.removeChild(this);
				}
			}
		}
	}
}
DisplayNode.prototype.sharedProperties = DisplayNode.prototype.NO_PROPERTIES = {};
DisplayNode.prototype.addDisplayElement = function addElement(role, modelId, properties)
{
	if (this.getGetter(role))
	{
		var element = new MethodElement(this, role, modelId);
		element.modelId = modelId;
	}
	else
		var element = new DisplayElement(role, modelId);
	if (! this.displayElements)
		this.displayElements = [element];
	else
		this.displayElements.push(element);
	element.displayOrder = this.displayElements.length;
	this.registerSubFlow(element);
	element.properties = properties ? properties : this.NO_PROPERTIES;
	return this.addElement(element);
};
DisplayNode.prototype.optimizeFormatString = false;
DisplayNode.prototype.onload = function()
{
	this.optimizeFormatString = 
		(this.sprop('decimalPlaces') == null || this.sprop('decimalPlaces') == -1)
		&&
	 	this.sprop('useThousandsSeparator') == null &&
	 	this.sprop('currencySymbol') == null;
	 this.htmlTagSuffix = '</'+this.getTag()+'>';
	 this.hasElementChangeHandler =  this.hasEventHandler(Events.ON_ELEMENT_CHANGE);
	 this.initElement = this.getElement('<Init>');
	 this.errorHandler = this.getElement('<On Error>');
}
DisplayNode.prototype.handleElementChange = function (role, oldValue, newValue)
{
	var parameters = {'<Element Name>':role, '<Previous Value>':oldValue, '<New Value>':newValue};
	this.queueEvent(Events.ON_ELEMENT_CHANGE,parameters,null /* No GUI Attributes */);	
}

DisplayNode.prototype['set<Value>'] = function setValue(value)
{
	this.value = value;
	this.setValueString();
};
DisplayNode.prototype['set<Value>'].requiresNodes = true;
DisplayNode.prototype.setValueString = function()
{
	this.valueStr = '';
	if (this.value != null)
	{
		if (this.optimizeFormatString)
			this.valueStr = this.value.leafValue;
		else if (this.value.formatString)
			this.valueStr = this.value.formatString(this.sharedProperties);
		else
			this.valueStr = this.value.toString();
	}
	if (this.viewNode)
		this.viewNode.innerHTML = this.escapeHTML(this.valueStr);
};
DisplayNode.prototype['remove<Value>'] = function removeVaule()
{
	this.value = null;
	if (this.viewNode)
		this.viewNode.innerHTML='';
};
DisplayNode.prototype['set<Labels>'] = function setLabels(map)
{
	tersus.labelMap = map;
	var op = function(node)
	{
		if (node.captionChanged && node.viewNode)
		{
	        try
	        {
	            node.captionChanged();
	        }
	        catch (e)
	        {
	            if (console && console.log)
	                console.log('Error updating caption: path='+node.getPath().str + '\nError='+(e.message? e.message:e));
	            throw 'Error updating caption';
	        }
		}
		
	};
	tersus.traverseHierarchy(window.rootDisplayNode, tersus.Node.childIterator, op);
};
DisplayNode.prototype['get<Labels>'] = function getLabels()
{
	return tersus.labelMap;
};
DisplayNode.prototype['set<Resources>'] = function setLabels(map)
{
	tersus.resourceMap = map;
};
DisplayNode.prototype['get<Resources>'] = function getLabels()
{
	return tersus.resourceMap;
};
DisplayNode.prototype['set<Direction>'] = function DisplayNode_setDirection(direction)
{
	tersus.setDirection(direction);
};
DisplayNode.prototype['get<Direction>'] = function getDirection()
{
	return tersus.getDirection();
};

DisplayNode.prototype['get<Visible>'] = function ()
{
	return this.visible;
};

DisplayNode.prototype['set<Visible>'] = function (visible)
{
	this.visible = visible;
	this.refreshVisibility();
};
DisplayNode.prototype.isInvisible = function()
{
	var visible = this.visible;
	var parent = this.parent;
	while (visible && parent && parent.isGroup)
	{
		visible = parent.visible;
		parent = parent.parent;
	}
	return !visible;	
}
DisplayNode.prototype.refreshVisibility = function()
{
	var domNode = this.wrapperNode ? this.wrapperNode : this.viewNode;
	if (domNode)
	{
		if (this.isInvisible())
			domNode.style.display='none';
		else
		{
			domNode.style.display='';
			this.onResize();
		}
	}
};

DisplayNode.prototype.styleClass = '';
// baseClassName - the class name defined by the application, not taking into account special conditions like selection
DisplayNode.prototype.baseClassName = ''; 
DisplayNode.prototype.extraClassName = ''; 
DisplayNode.prototype.setStyleClass = function setStyleClass(value)
{
	if (this.viewNode)
	{
		var className = value;
		
		//rtl logic should be moved to a legacy script
		var rtlClassName = value+'_rtl';
		if (window.textDirection == 'rtl' && tersus.styleClassNames && tersus.styleClassNames.contains(rtlClassName))
			className = rtlClassName;
		$(this.viewNode).removeClass(this.baseClassName).addClass(className);
		this.baseClassName = className;
	}
	this.styleClass = value;
};
DisplayNode.prototype.addStyleClass = function addStyleClass(value)
{
	var elementClass = this.getLeafChild('<Style Class>');
	if (!elementClass)
		elementClass = this.viewNode ? this.styleClass : this.sharedProperties.styleClass;
	if (!elementClass)
		elementClass = value;
	else
	{
		var orig = ' ' + elementClass + ' ';
		var classNames = value.split(/\s+/);
		for (var i=0;i<classNames.length;i++)
		{
			var c=classNames[i];
			if (orig.indexOf(' '+c+' ') < 0)
				elementClass += ' '+c;
		}
	}
	this.setLeafChild('<Style Class>',$.trim(elementClass), Operation.REPLACE);
	if (!this.getLeafChild('<Style Class>'))
		this.setStyleClass($.trim(elementClass));

};
DisplayNode.prototype.removeStyleClass = function removeStyleClass(value)
{
	var elementClass = this.getLeafChild('<Style Class>');
	if (!elementClass)
	{
		elementClass = this.viewNode ? this.styleClass : this.sharedProperties.styleClass;
		if (!elementClass)
			return;
	}

	elementClass = ' '+elementClass+' ';
	var classNames = value.split(/\s+/);
	for (var i=0;i<classNames.length;i++)
	{
		elementClass = elementClass.replace(' '+classNames[i]+' ',' ');
	}
	this.setLeafChild('<Style Class>',$.trim(elementClass), Operation.REPLACE);
	if (!this.getLeafChild('<Style Class>'))
		this.setStyleClass($.trim(elementClass));
};
DisplayNode.prototype['set<Style Class>'] = function(value)
{
	this.setStyleClass(value);
};
 DisplayNode.prototype['get<Style Class>'] = function getStyleClass()
{
	return this.styleClass;
};
DisplayNode.prototype.setStyle =  DisplayNode.prototype['set<Style>'] = function(value)
{
	if (this.viewNode && value != null)
	{
		try
		{
			return this.viewNode.style.cssText = value;
		}
		catch (e)
		{
			modelExecutionError('Failed to set style "'+value+'"  (HTML tag='+this.viewNode.tagName+')',this);
		}
	}
};
DisplayNode.prototype['get<Style>'] = function getStyleClass()
{
	if (this.viewNode)
		return this.viewNode.style.cssText;
};
DisplayNode.prototype['get<Value>'] = function getValue()
{
	return this.value;
}
DisplayNode.prototype.getBaseCaption = DisplayNode.prototype['get<Caption>'] = function()
{
	if (this.caption !== null &&  this.caption !== undefined)
		return this.caption;
	var c = this.sprop('caption');
	if (c != null)
		return c;
	else
		return this.element.role;
	
};
DisplayNode.prototype.getCaption = function()
{
	var idTranslation = this.getTranslation(this.modelId);
	if(idTranslation !== null && idTranslation !== undefined)
		return idTranslation; 
	else
		return this.translate(this.getBaseCaption());
};
DisplayNode.prototype.captionChanged = function() {};
DisplayNode.prototype['set<Caption>'] = function(caption)
{
	this.caption = caption;
	this.captionChanged();
};
DisplayNode.prototype['get<Read Only>'] = function ()
{
	return this.explicitReadOnly;
};
DisplayNode.prototype['set<Read Only>'] = function (readOnly)
{
	if (this.explicitReadOnly != readOnly)
	{
		var originalState = this.computedReadOnly();
		this.explicitReadOnly = readOnly;
		var newState = this.computedReadOnly();
		if (this.newState != originalState) 
		{
			this.updateSelfReadOnly(newState);
			this.updateChildrenReadOnly(newState);
		}
		
	}
};
DisplayNode.prototype.updateSelfReadOnly = function ()
{
};
DisplayNode.prototype.updateChildrenReadOnly = function DisplayNode_updateChildrenReadOnly(readOnly)
{
	if (! this.displayElements)
		return;
	for (var i=0; i<this.displayElements.length; i++)
	{
		var element = this.displayElements[i];
		if (element.isRepetitive)
		{
			var children = element.getChildren(this);
			for (var j=0; j<children.length;j++)
			{
				var child = children[j];
				if (! child.explicitReadOnly) // If the child is explicitly read only, its state won't change
					child.parentReadOnlyChanged(readOnly);
			}
		}
		else
		{
			var child = element.getChild(this);
			if (child && ! child.explicitReadOnly) // If the child is explicitly read only, its state won't change
				child.parentReadOnlyChanged(readOnly);
		}
	}
};
DisplayNode.prototype.parentReadOnlyChanged = function(readOnly)
{
	this.updateSelfReadOnly(readOnly);
	this.updateChildrenReadOnly(readOnly)
};
/**
 * Computes the read only state of this node.  A node is in read only mode if it's explicitly
 * marked as read only, or if its ancestor is read only
 */	
DisplayNode.prototype.computedReadOnly = function DisplayNode_computedReadOnly()
{
	if (this.explicitReadOnly)
		return true;
	else if (this.parent && this.parent.computedReadOnly)
		return this.parent.computedReadOnly();
	else
		return false;
};
DisplayNode.prototype.onResizeChildren = function onResizeChildren()
{
	if (this.displayElements)
	{
		for (var i=0; i<this.displayElements.length; i++)
		{
			var element = this.displayElements[i];
			if (element.isRepetitive)
			{
				var children = element.getChildren(this);
				for (var j=0; j<children.length;j++)
				{
					var child = children[j];
					child.onResize();
				}
			}
			else
			{
				var child = element.getChild(this);
				if (child)
					child.onResize();
			}
		}
	}
};
DisplayNode.prototype.updateLayout = function(domNode)
{
	var $this=$(domNode);
	if ($this.hasClass('ter-max-height'))
	{
		if (window.console) window.console.log(this.modelId+ 'before resize -  height:'+$this.height()+' innerHeight:'+$this.innerHeight());
		/* For the top level element (no this.parent), we need to use min-height as the height be too large 
		  (a separate method updates the container's min-height according to the available dimensions) */
		  
		var p = domNode.parentNode;
		var $p = $(p);
		var ps = p.style;
/*		if (window.console)
		    console.log('p.id='+$p.attr('id')+' p.class='+$p.attr('class')+' $p.height()' +$p.height(), ' ps.height:'+ps.height +'  ps.minHeight:'+ps.minHeight +'  $p.css(height):'+ $p.css('height') +' $p.css(minHeight):'+ $p.css('minHeight'));
*/
		var h  = parseInt(ps.height || ps.minHeight || $p.css('height') || $p.css('minHeight')); // Need to give preference to explicitly set height
		if ($p.css('box-sizing')=='border-box')
		    h = h - ($p.outerHeight()-$p.height()); // total height of padding
		var s= 0;
		$this.siblings().each(function(){s+=$(this).outerHeight();});
		var m = 0, $prev=$(), $all=$this.parent().children(), n = $all.size();
		$all.each(function(i){
			var $cur =  $(this);
			m+=Math.max(parseInt($prev.css('margin-bottom'))||0, parseInt($cur.css('margin-top'))||0);
			if (i == n-1)
				m+=parseInt($cur.css('margin-bottom'))||0;
			$prev=$cur;
		});
		if (window.console) console.log(this.modelId+': h='+h+ ' s='+s+' m='+m);
		h = h - s - m;
		$this.css({'height':h+'px','box-sizing':'border-box'});
	}
	else if ($this.hasClass('ter-parent-height'))
	{
//		if (window.console) console.log(this.modelId+ 'before resize -  height:'+$this.height()+' innerHeight:'+$this.innerHeight());
//		if (window.console) console.log(this.modelId+ ' parentHeight:'+$this.parent().height()+' parentInnerHeight:'+$this.parent().innerHeight());
		$this.css({'height':$this.parent().height()+'px','box-sizing':'border-box'});
	}
	
};
DisplayNode.prototype.onResize = function()
{
	if(this.wrapperNode && this.wrapperNode != this.viewNode)
	{
		this.updateLayout(this.wrapperNode);
	}
	else if (this.viewNode)
	{
		this.updateLayout(this.viewNode);
	}
	this.onResizeChildren();
};

DisplayNode.prototype.isDisplayNode = true;
/******************************************************************
 *  reset() is called before replacing a display element, and does not trigger initialization processes
 *  refresh() is called when refreshing a display element, and includes initiailization processes (createSubFlows).
 *
 *  If reset triggered initialization processes, we might end up in strange situations, like double initialization
 *   (e.g. If a chooser initializes itself, and then a different chooser is copied onto it)
 *
 *
 ****************************************************************** */
DisplayNode.prototype.reset = function DisplayNode_reset()
{
	this.removeAll();
	this.initViewNode();
	this.createChildren(); // TODO(x) eliminate redundant creation of children (not sure whether this really is redundant as reset() is overridden in HTMLTag)
};
DisplayNode.prototype.refresh = function DisplayNode_refresh()
{
	this.reset();
	this.createSubFlows();
};


DisplayNode.prototype.deepCopy = function deepCopy(value)
{
	if (tlog) tlog("start deepCopy:"+value.modelId);
	for (var elementRole in value.elements)
	{
		var element = this.getElement(elementRole);
		if (element)
		{
			if (element.isRepetitive)
			{
				var childValues = value.getChildren(elementRole);
				element.setChildren(this, childValues, Operation.REPLACE);
			}
			else
			{
				var childValue = value.getChild(elementRole);
				if (childValue != null)
				{
					element.replaceChild(this, childValue);
				}
			}
		}
	}
	if (tlog) tlog("end deepCopy:"+value.modelId);
};
DisplayNode.prototype.tooltip = null;
DisplayNode.prototype.setTooltip = DisplayNode.prototype['set<Tooltip>'] = function (tooltip)
{
	var tooltipClassName = 'tooltip';
	this.tooltip = tooltip;
	if (this.viewNode && tooltip !== null && tooltip !== undefined)
	{
		this.viewNode.title = this.translate(tooltip);
		if (tooltip != '')
			this.addStyleClass(tooltipClassName);
		else
			this.removeStyleClass(tooltipClassName);
	};
};
DisplayNode.prototype.getTooltip = DisplayNode.prototype['get<Tooltip>'] = function ()
{
	return this.tooltip;
};
DisplayNode.prototype.setValidationMessage = DisplayNode.prototype['set<Validation Message>']= function (message)
{
	var invalidClassName = 'invalid';
	this.validationMessage = message;
	if (this.currentWindow && this.viewNode)
	{
		if (message != null)
		{
			this.addStyleClass(invalidClassName);
			this.viewNode.title = this.forceTranslate(message);
		}
		else
		{
			this.removeStyleClass(invalidClassName);
			this.viewNode.title='';
		}
	}
};
DisplayNode.prototype['remove<Validation Message>']= function ()
{
	this.setValidationMessage(null);
};
DisplayNode.prototype.getValidationMessage = DisplayNode.prototype['get<Validation Message>']= function (message)
{
	return this.validationMessage;
};

DisplayNode.prototype.showValidationMessage = function (message)
{
	if (this.currentWindow.alert) this.currentWindow.alert(message);
};
DisplayNode.prototype.validate = function validate()
{
	var message = this.getValidationMessage();
	if (message != null)
	{
		this.showValidationMessage(this.forceTranslate(message));
		return false;
	}
	if (! this.elementList)
		return true;
	for (var j=0; j<this.elementList.length; j++)
	{
		var element = this.elementList[j];
		if (element.isRepetitive)
		{
			var values = element.getChildren(this);
			for (var i=0; i< values.length; i++)
			{
				var value = values[i];
				if (value && value.validate && ! value.validate())
					return false;
				
					
			}
		}
		else
		{
			var value = element.getChild(this);
			if (value && value.validate && ! value.validate())
				return false;
		}
	}
	return true;
};
DisplayNode.prototype.findDisplayElementIndex = function (role)
{
	for (var i=0; i<this.displayElements.length;i++)
	{
		var e = this.displayElements[i];
		if (e.role ==role)
			return i;
	}
	return null;
};
DisplayNode.prototype.findPreviousSibling = function (child)
{
	var role = child.element.role;
	
	// Find the last child among the preceding display elements
	var index = this.findDisplayElementIndex(role);
	if (index == null)
		return null;
	for (var i=index;i>=0;i--)
	{
		var e = this.displayElements[i];
		if (e.isRepetitive)
		{
			var children = e.getChildren(this);
			for (var j=children.length-1; j>=0; j--)
			{
				var sibling = children[j];
				if (sibling && sibling != child)
					return sibling;
			}
		}
		else
		{
			var sibling = e.getChild(this);
			if (sibling && sibling != child)
				return sibling;
		}
	}
	return null;
};
DisplayNode.prototype.focusOnFirstField = function()
{
	var elements = this.viewNode.getElementsByTagName('*');
	for (var i=0; i<elements.length; i++)
	{
		var e = elements[i];
		if (e.tagName == 'INPUT' || e.tagName == 'TEXTAREA')// || e.tagName == 'SELECT')
		{
			if (isVisible(e) && !e.disabled)
			{
				this.currentWindow.setTimeout(function(){if (isVisible(e) && !e.disabled) e.focus();},0);
				break;
			}
		}
	}
};


DisplayNode.prototype.addGetter('<Screen X>', function()
{
	if (!this.viewNode)
		return null;
	return getScreenPosition(this.viewNode).left;
});
DisplayNode.prototype.addSetter('<Screen X>', function(x)
{
	this.viewNode.style.position='absolute';
	this.viewNode.style.left = (x - getScroll(this.viewNode).left)+'px';
});

DisplayNode.prototype.addGetter('<Screen Y>', function()
{
	if (!this.viewNode)
		return null;
	if (this.viewNode.tagName == 'SPAN')
	{
		if (this.inputField) // This happens in input fields
			return getScreenPosition(this.inputField).top;
		else
			internalError("Getting the vertical position of 'SPAN' elements not supported yet");
	}
	else
	return getScreenPosition(this.viewNode).top;
});
DisplayNode.prototype.addSetter('<Screen Y>', function(y)
{
	this.viewNode.style.position='absolute';
	this.viewNode.style.top = (y - getScroll(this.viewNode).top)+'px';
});

DisplayNode.prototype.addGetter('<URL>', function()
{
	if (this.viewNode)
		return this.viewNode.href;
});
DisplayNode.prototype.addSetter('<URL>', function(url)
{
	if (this.viewNode)
		this.viewNode.href = url;
});
DisplayNode.prototype.addGetter('<Target Window>', function()
{
	if (this.viewNode)
		return this.viewNode.target;
});
DisplayNode.prototype.addSetter('<Target Window>', function(target)
{
	if (this.viewNode)
		this.viewNode.target = target;
});
DisplayNode.prototype.addGetter('<Width>', function()
{
	if (this.viewNode)
		return getVisibleSize(this.viewNode).width;
	else
		return this.width;
});
DisplayNode.prototype.addSetter('<Width>', function(width)
{
	this.width = width;
	if (this.viewNode)
		this.viewNode.style.width = width  + 'px';
});
DisplayNode.prototype.addGetter('<Height>', function()
{
	if (! this.viewNode)
		return this.height;
	if (this.viewNode.tagName == 'SPAN')
	{
		if (this.inputField) // This happens in input fields
			return getVisibleSize(this.inputField).height;
		else
			internalError("Getting the height of 'SPAN' elements not supported yet");
	}
	else
		return getVisibleSize(this.viewNode).height;
});
DisplayNode.prototype.addSetter('<Height>', function(height)
{
	this.height = height;
	if (this.viewNode)
		this.viewNode.style.height = height+'px';
});
DisplayNode.prototype.addGetter('<Col Span>', function()
{
	if (this.viewNode && this.viewNode.parentNode && this.viewNode.parentNode.colSpan)
		return this.viewNode.parentNode.colSpan;
	else
		return this.colSpan;
});
DisplayNode.prototype.addSetter('<Col Span>', function(span)
{
	this.colSpan = span;
	if (this.viewNode && this.viewNode.parentNode && this.viewNode.parentNode.colSpan)
		this.viewNode.parentNode.colSpan = span;
});
DisplayNode.prototype.addGetter('<Row Span>', function()
{
	if (this.viewNode && this.viewNode.parentNode && this.viewNode.parentNode.rowSpan)
		return this.viewNode.parentNode.rowSpan;
	else
		return this.rowSpan;
});
DisplayNode.prototype.addSetter('<Row Span>', function(span)
{
	this.rowSpan = span;
	if (this.viewNode && this.viewNode.parentNode && this.viewNode.parentNode.rowSpan)
		this.viewNode.parentNode.rowSpan = span;
});

DisplayNode.displayChildrenIterator = function (node,iteration)
{
	if (node && node.displayElements)
	{
		for (var i=0; i<node.displayElements.length; i++)
		{
			var e = node.displayElements[i];
			if ( e.isRepetitive)
			{
				var children  = e.getChildren(node);
				for (var j=0;j<children.length;j++)
				{
					var stop = iteration(children[j]);
					if (stop == true)
						return;
				}
			}
			else
			{
				var child = e.getChild(node);
				if (child)
				{
					var stop = iteration(child);
					if (stop == true)
						return;
				}
			}
		}
	}
	
};

DisplayNode.prototype.prop = function(name)
{
    var e = this.element;
    var p = (e && e.props) || this.props;
    if (!p) // Initialize combined element+model property map on first time
    {
        p = {};
        $.extend(p,this.baseProperties);
        p['class'] = this.defaultClass || this.defaultStyleClass;
        p.tag = this.defaultTag;
        for (var n in this.sharedProperties)
        {
            var v = this.sharedProperties[n];
            if (v != null && v !== ' ')
                p[tersus.convertProperty(n)]=v;
        } 
        if (e)
        {
            for (var n in e.properties)
            {
                var v = e.properties[n];
                if (v != null && v !== ' ')
                    p[tersus.convertProperty(n)]=v;
            }
            e.props = p;
        }
        else
            this.constructor.prototype.props = e;
    }
    return p[name];
}

// file: 026-DataValue.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function DataValue() {};
DataValue.prototype = new tersus.Node();
DataValue.prototype.constructor = DataValue;
DataValue.prototype.isDataValue = true;
DataValue.prototype.sqlType = 'NONE';
DataValue.prototype.toString = function toString()
{
	if (this.leafValue)
	{
		return ''+this.leafValue;
	}
	else
		return 'Composite Value: '+this.modelId;
};
DataValue.prototype.formatString = function (props)
{
	return this.toString();
};
DataValue.prototype.formatInput = function (props)
{
	return this.formatString(props);
};
DataValue.prototype.parseInput = function()
{
	internalError("parseInput not implemented for "+this.constructor.name);
};
DataValue.prototype.addDataElement = function addDataElement(role,modelId)
{
	var element;
	var getter = this.getGetter(role);
	if (getter)
		element = new MethodElement(this, role, modelId);
	else
		element = new DataElement(role, modelId);
	return this.addElement(element);
};


// file: 026-ServiceNode.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
 tersus.defaultServiceTimeout = 0;
 tersus.serviceTimeoutOverhead = 1;
 
//Service Node

function ServiceNode() {};
ServiceNode.prototype = new FlowNode();
ServiceNode.prototype.constructor = ServiceNode;
ServiceNode.prototype.type = 'Service';
ServiceNode.prototype.secure = false; // true means service must be invoked under HTTPS
ServiceNode.prototype.excludedTriggers=new Set(['<URL>']);
ServiceNode.prototype.start = function startService()
{	
	if (this.secure && !tersus.rootURL.match(/^https:/))
	{
		tersus.error('The service "'+this.modelName+'" must  be used in a secure context');
		return;
	} 
	this.pause();
	this.retries = 0;
	this.callService();
};
ServiceNode.prototype.started = function serviceStarted()
{
	this.setStatus(FlowStatus.STARTED);
	if (window.trace)
	{
		window.trace.invoked(this);
		window.trace.flush();
	}
};
ServiceNode.prototype.isService = true;
/*
	Invokes a service that contains file arguments.
	This is a special case for the following reasons:
	(1) We must use the orginial "File Input Node" to send the file 
	(2) For this reason, we use the "Form" node that is already part of the document
	(3) We need to use "form/multipart" encoding
	
	
	In this case, we can't create a separate form, 
	because there is no way to copy the FileInput node's content to another
	file input node (it is possible in Mozilla, but not in IE)
	
	Using XMLHTTPRequest is out of the question because JavaScript can't read
	local files.
*/

ServiceNode.prototype.callService = function  callService()
{
	this.explicitURL = this.getLeafChild('<URL>');
	var baseURL = tersus.serverURL ? tersus.serverURL+'/':tersus.rootURL;
	this.url = this.explicitURL ? this.explicitURL : baseURL+'Service';
	
	var host = document.domain;
 	var urlHost = this.url.match(/\/\/([^:/]+)[:/]/)[1];
 	if (urlHost != null)
 		host=urlHost;
    if (host == '')
    	modelError('Missing <URL> for service invocation, or attempt to access server-side database in native application',this);
	if (navigator.onLine == false)
	{
		var host = document.domain;
		if(! tersus.isLocalHost(host))
		{
			this.serviceError = "Offline - can't access server";
			this.handleResponse({});
			return;
		}
	}
	if (tlog)
		tlog("Calling service:"+this.modelName);
	if ( !tersus.useXMLHTTPRequest) // Legacy workaround for HTTP issues
        this.callIFrameService();
	else if (this.findFileTrigger())
	{
	    if (window.FileList)
	    {
	        if (!this.callMultiPartService())
		        this.callIFrameService(); // Workaround for problems with pop-up window on IE10/IE11	
	    }	
	    else
	        this.callIFrameService(); //Legacy browsers - no File API
	}
	else
		this.callRegularService();
};
ServiceNode.prototype.cancellable = true;
ServiceNode.prototype.getCancellationFunc = function getCancellationFunc()
{
	if (this.cancellable == 'false' || !this.cancellable)
		return null;
	var serviceNode = this;
	var cancellation = function () { 
			tersus.progress.set('Request cancelled.');
			serviceNode.cancel();
			};
	return cancellation;
};
ServiceNode.prototype.cancel = function cancel()
{
	if (this.responseReceived)
		return;
	this.abort();
	if (this.responseReceived)
		return;
	this.handleResponse({});
	this.cancelled = true;
};
ServiceNode.prototype.abort = function abort()
{
	var req = createXMLHTTPRequest();
	var serviceNode = this;
	var url = tersus.rootURL+'Abort';
	req.open('POST', url, true);
	req.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
	req.send('_userRequestId='+window.encodeURIComponent(this.getNodeId()));
};
ServiceNode.prototype.setProgressMessage = function()
{
	if (tersus.progress.active)
	{
		var message = null;
		if (this.progressMessage && this.progressMessage != ' ')
			message = this.progressMessage;
		else if (tersus.progressMessage)
			message = tersus.progressMessage;
		else
			message = 'Service: '+this.modelName;
		tersus.progress.set(message, this.getCancellationFunc());
	}
};
ServiceNode.prototype.callRegularService = function getService()
{
	var paramString = this.getParamString();
	this.nodesToRemove = [];
	
	// We wrap the call to XMLHTTPRequest in setTimeout to avoid a firefox bug:
	// see http://www.highdots.com/forums/javascript/xmlhttprequest-firefox-problem-577724.html
	// However, we suppress this behavior if we're inside 'onUnload' (or the service will never be invoked)
	var serviceNode = this;
	var f = function() {
		serviceNode.setProgressMessage();
		serviceNode.callXMLHTTPService(paramString);
	};
	if (tersus.isUnloading)
		f();
	else
		tersus.async.exec(f, false/* don't wait */);
};


ServiceNode.prototype.callXMLHTTPService = function callXMLHTTPService(paramString)
{
	var req = createXMLHTTPRequest();
	var nodeId = this.getNodeId();
	var modelName = this.modelName;
	var url = this.url;
	if (! tersus.isUnloading) // If we're unloading we won't be able to process the response
	{
		req.onreadystatechange= function(){
			ServiceNode.handleXMLHTTPResponse(req, nodeId, url, modelName);
		};
	}

	req.open('POST', this.url, true);
	req.timeout = this.getTimeoutMilliseconds();
	req.setRequestHeader('Content-Type','application/x-www-form-urlencoded; charset=UTF-8');
	req.send(paramString);
};
ServiceNode.prototype.callMultiPartService = function getService()
{
    var data = this.prepareFormData();
    if (!data)
    	return false; /* can't use FormData (popup file in IE)*/
    this.nodesToRemove = [];
    
    // We wrap the call to XMLHTTPRequest in setTimeout to avoid a firefox bug:
    // see http://www.highdots.com/forums/javascript/xmlhttprequest-firefox-problem-577724.html
    // However, we suppress this behavior if we're inside 'onUnload' (or the service will never be invoked)
    var serviceNode = this;
    var f = function() {
        serviceNode.setProgressMessage();
        serviceNode.callXHR2Service(data);
    };
    if (tersus.isUnloading)
        f();
    else
        tersus.async.exec(f, false/* don't wait */);
    return true;
};
ServiceNode.prototype.prepareFormData = function()
{
    var location = new tersus.RuntimeLocation(this);
    var serializer = new Serializer();
    var d = new FormData();
    if (!this.explicitURL)
    {
        d.append("_baseModelId",location.baseModelId);
        d.append("_path",this.getServicePath(location));
	d.append("_id", this.modelId);
        d.append("_userRequestId", ''+this.getNodeId());
    }
    else
    {
        d.append('_output','json');
    }
    if (window.trace)
    {
        d.append('_traceFileName',this.getTraceFileName());
    }   
    if (this.triggers)
    {
        for (var i=0; i< this.triggers.length; i++)
        {
            var trigger = this.triggers[i];
            var paramName = trigger.role;
            if (trigger.isRepetitive)
            {
                var values = trigger.getChildren(this);
                if (values.length > 0)
                {
                    d.append(trigger.role, serializer.serialize(values)); 
                }
            }
            else
            {
                var value = trigger.getChild(this);
                if (value != null)
                {
                    if (value.isFile && value.file)
                    {
                    	if (value.window && value.window !== window)
                    		return null; // Using a file from a file input field in a popup not supported in IE10/IE11.
                    // Note - it is not clear what happens when files are dropped on a pop-up, but the fall-back of IFRAME loading won't work 
                        d.append(trigger.role, value.file);
                    }
                    else if (value.isLeaf)
                        d.append(trigger.role, value.serialize ? value.serialize() : value.leafValue);
                    else
                        d.append(trigger.role, serializer.serialize(value));
                }
            }
        }
    }
    if (!this.explicitURL)
    {
        d.append('_sig','END');
    }
    return d;
};
ServiceNode.prototype.getTimeoutMilliseconds = function()
{
    var timeout = tersus.defaultServiceTimeout*1000;
    if (this.serviceTimeout)
    {
		timeout = this.serviceTimeout*1000 + tersus.serviceTimeoutOverhead*1000;
    }
    return timeout;
    
};

ServiceNode.prototype.callXHR2Service = function callXHR2Service(data)
{
    var req = createXMLHTTPRequest();
    var nodeId = this.getNodeId();
    var modelName = this.modelName;
    var url = this.url;
    if (! tersus.isUnloading) // If we're unloading we won't be able to process the response
    {
        req.onreadystatechange= function(){
            ServiceNode.handleXMLHTTPResponse(req, nodeId, url, modelName);
        };
    }
    req.open('POST', this.url, true);
    req.timeout = this.getTimeoutMilliseconds();
    req.send(data);    
};

ServiceNode.dummy = function () {};
ServiceNode.handleXMLHTTPResponse = function(req, nodeId, url, modelName)
{
	if (req.readyState != 4)
		return;
	req.onreadystatechange = ServiceNode.dummy;
	var status  = 'Error';
	var statusText = 'Unknown';
	try
	{
		status = req.status;
		statusText = req.statusText;
	}
	catch (e)
	{
	}
	var serviceNode = tersus.findNode(nodeId);
	if (!serviceNode)
		return;
	if (serviceNode.cancelled)
		return;
	delete FlowNode.map[nodeId]; 
	if (status == 400 && serviceNode.retries < tersus.SERVICE_MAX_RETRIES)
	{
		serviceNode.retries++;
		setTimeout(function(){serviceNode.callRegularService();}, tersus.SERVICE_RETRY_DELAY);
		return;
	}
	if (status != 200)
	{
		var message;
		if (status == 400)
		{
			message = 'The server has reported "BAD REQUEST".  This is possibly a result of a temporary network problem.';
			if (statusText != 'OK') // Safari bug - reports 'OK' instead of server message
				message += '\n\nOriginal server message: '+statusText;
		}
		else
			message = 'Failed to execute service (url='+url+', modelName='+modelName +',status='+status+',message='+statusText+')';
		serviceNode.serviceError = message;
		setTimeout(function() {serviceNode.handleResponse({});},0);
		return;
	}

	if (tersus.progress.active)
		tersus.progress.set('Processing service response ...');
	var responseText = req.responseText;
	
	/* If there is a sizeable response, we expect processing to take significant time
	   (during which there is no opportunity for the progress bar to appear, so we make
	   force progress bar to be visible  */
//	if (responseText.length > tersus.progress.responseLengthThreshold)
//		tersus.progress.show();
	setTimeout( function()
		{
			if (tlog) tlog('Parsing response ('+responseText.length+' characters)');
			var exitValues = eval("var output = "+responseText+";output;");
			if (tlog) tlog('Done parsing response');
			if (exitValues._ERROR)
			{
				serviceNode.serviceError=exitValues._ERROR;
				serviceNode.handleResponse({});
			}
			else
			{
				if (exitValues['<Done>'] == null)
					exitValues['<Done>']={};
				serviceNode.handleResponse(exitValues);
			}
		},0);
};

tersus.serviceRedirectionMap = {};
ServiceNode.prototype.getServicePath = function(location)
{
    //Typically returns the path (based on location), but may redirect for backward compatibility
    return tersus.serviceRedirectionMap[this.modelId] || location.path.str;
};	
ServiceNode.prototype.getParamString = function()
{
	var location = new tersus.RuntimeLocation(this);
	var serializer = new Serializer();
	if (!this.explicitURL)
	{
		var paramString = "_baseModelId="+encodeURIComponent(location.baseModelId);
		paramString += "&_path="+encodeURIComponent(this.getServicePath(location));
		paramString += "&_id="+encodeURIComponent(this.modelId);
		paramString+='&_userRequestId='+this.getNodeId();
	}
	else
	{
		var paramString = '_output=json';
	}
	if (window.trace)
	{
		paramString+='&_traceFileName='+encodeURIComponent(this.getTraceFileName());
	}	
	if (this.triggers)
	{
		for (var i=0; i< this.triggers.length; i++)
		{
			var trigger = this.triggers[i];
			var paramName = trigger.role;
			var paramValue = null;
			if (trigger.isRepetitive)
			{
				var values = trigger.getChildren(this);
				if (values.length > 0)
				{
					paramValue = serializer.serialize(values); 
				}
			}
			else
			{
				var value = trigger.getChild(this);
				if (value != null)
				{
					if (value.isLeaf)
						paramValue = value.serialize ? value.serialize() : value.leafValue;
					else
						paramValue = serializer.serialize(value);
				}
			}
			if (paramValue != null)
			{	
				if (paramString.length > 0)
					paramString+= '&';
				paramString += encodeURIComponent(paramName);
				paramString += '=';
				paramString += encodeURIComponent(paramValue);
			}
		}
	}
	if (!this.explicitURL)
	{
		paramString += '&_sig=END';
	}
	if (tlog)
		tlog('Done creating paramString');
	return paramString;
};
ServiceNode.prototype.callIFrameService = function callIFrameService()
{
	var form = this.prepareForm();
	if ( ! form)
	{
		this.continueExecution();
		return;
	};
	this.addTersusParameters(form);
	
	var iframe = this.getResponseFrame();
	
	form.action = this.url;
	form.method = 'POST';
	form.target  = iframe.name;
	this.callbackName = iframe.name+"_cb";
	var serviceNode = this;
	this.mainWindow[this.callbackName] = function callback(exitValues)
	{
		serviceNode.mainWindow[serviceNode.callbackName] = null;
		if (serviceNode.cancelled)
			return;
		tersus.progress.set('Processing service response ...');
		setTimeout( function()
		{
			if (exitValues._ERROR)
			{
				serviceNode.serviceError=exitValues._ERROR;
				serviceNode.handleResponse({});
			}
			else
				serviceNode.handleResponse(exitValues);
		},0);
	};
	var callbackField = addHiddenField(form, '_js_callback', 'parent.'+this.callbackName);
	form.appendChild(callbackField);
	this.nodesToRemove.push(callbackField);
	if (tersus.IFRAME_SERVICE_TIMEOUT)
	{
		setTimeout(function (){
			if (!serviceNode.responseReceived)
			{
				tersus.error('Server Error: Timeout');
				serviceNode.cancel();
			}
		}
		,tersus.IFRAME_SERVICE_TIMEOUT);
	};
	var sigField = addHiddenField(form, '_sig', 'END');
	form.appendChild(sigField);
	this.nodesToRemove.push(sigField);
	try
	{
		var nodeId = this.getNodeId();
		if (!tersus.pendingServiceCalls)
			tersus.pendingServiceCalls = new Set([nodeId]);
		else
			tersus.pendingServiceCalls.add(nodeId);
		form.submit();
		this.setProgressMessage();	
	}
	catch (e)
	{
		var msg;
		var fileTrigger = this.findFileTrigger();
		var fileName = this.getChild(fileTrigger.role).getFileName();
		if (e.name=='TypeError') // This happens in IE when a user types an invalid file name
			msg = 'Please check the file name "'+fileName + '"';
		else
			msg = 'An error occurred when invoke the service ('+e.message+').';
		tersus.error(msg);
		this.continueExecution();
	}
	for (var i=0; i< this.nodesToRemove.length; i++)
	{
		var node = this.nodesToRemove[i];
		node.parentNode.removeChild(node);
	}
};
ServiceNode.prototype.prepareForm = function prepareForm()
{
	var serializer = new Serializer();
	var form;
	var fileTrigger = this.findFileTrigger();
	this.nodesToRemove = [];
	
	if (fileTrigger)
	{
		var fileInputDisplayNode = this.getChild(fileTrigger.role).inputFieldDisplayNode;
		if ( fileInputDisplayNode.currentWindow.closed)
		{
			tersus.error('Tersus Application Error: Reference to a file input field in closed popup window.\n');
			return null;
		}
		
		form = fileInputDisplayNode.viewNode;
		setEncType(form,'multipart/form-data'); 
		var fileInputNode = fileInputDisplayNode.fileNode;
		fileInputNode.name = fileTrigger.role;
	}
	else
	{
		form = this.mainWindow.document.createElement('form');
		if (! window.showServiceInvocations)
		{
			this.nodesToRemove.push(form);
		}
		this.mainWindow.document.body.appendChild(form);
	}

	if (this.triggers)
	{
		for (var i=0; i< this.triggers.length; i++)
		{
			var trigger = this.triggers[i];
			if (this.excludedTriggers.contains(trigger.role))
				continue;
			if (trigger != fileTrigger) // If fileTrigger is non-null, it is already part of the form
			{
				if (trigger.isRepetitive)
				{
					var values = trigger.getChildren(this);
					if (values.length > 0)
					{
						var serialization = serializer.serialize(values); 
						var inputField = form.ownerDocument.createElement('input');
						inputField.type = 'hidden';
						inputField.name = trigger.role;
						inputField.value = serialization;
						form.appendChild(inputField);
						if (fileTrigger)
							this.nodesToRemove.push(inputField);
					}
				}
				else
				{
					var value = trigger.getChild(this);
					if (value != null)
					{
						var serialization;
						if (value.isLeaf)
							serialization = value.serialize ? value.serialize() : value.leafValue;
						else
							serialization = serializer.serialize(value);
						var inputField = form.ownerDocument.createElement('input');
						inputField.type = 'hidden';
						inputField.name = trigger.role;
						inputField.value = serialization;
						form.appendChild(inputField);
						if (fileTrigger)
							this.nodesToRemove.push(inputField);
					}
				}	
			}
		}
	}	
	return form;
};

ServiceNode.prototype.addTersusParameters = function(form)
{
	var location = new tersus.RuntimeLocation(this);
	if (this.explicitURL)
	{
		var outputField = addHiddenField(form, '_output', 'json');
		form.appendChild(outputField);
		this.nodesToRemove.push(outputField);
	
	}
	else
	{
		var baseModelIdField = addHiddenField(form, '_baseModelId', location.baseModelId);
		form.appendChild(baseModelIdField);
		this.nodesToRemove.push(baseModelIdField);
		var pathField = addHiddenField(form, '_path', this.getServicePath(location));
		form.appendChild(pathField);
		var idField = addHiddenField(form, '_id', this.modelId);
		form.appendChild(idField);
		this.nodesToRemove.push(pathField);
	}
	if (window.trace)
	{
		window.trace.flush();
		var traceFileField = addHiddenField(form, '_traceFileName', this.getTraceFileName());
		form.appendChild(traceFileField);
		var requestIdField = addHiddenField(form, '_userRequestId', this.getNodeId());
		form.appendChild(traceFileField);
		this.nodesToRemove.push(traceFileField);
		this.nodesToRemove.push(requestIdField);
	}
};
ServiceNode.prototype.getTraceFileName = function()
{
	return window.trace.filename;
};

ServiceNode.prototype.handleResponse = function handleResponse(response)
{
	if (tlog) tlog('Processing response for service: '+	this.modelName);
	if (tersus.pendingServiceCalls)
		tersus.pendingServiceCalls.remove(this.getNodeId());
	var start = new Date();
	this.responseReceived = true;
	if (window.trace)
		window.trace.responded(this);
		
	for (var exitRole in response)
	{
        var exit = this.getElement(exitRole);
        if (!exit)
        	continue; // It's possible that the exit is missing because of permission issues
        if (exit.isRepetitive)
        {
        	var values = response[exitRole];
        	for (var i=0; i< values.length; i++)
        	{
        		var dataValue  = exit.createChild(this);
        	    dataValue.copyObject(values[i]);
        	}
        }
        else
        {
        	var value = response[exitRole];
        	var dataValue  = exit.createChild(this);
       	    dataValue.copyObject(value);
        }
        			
	};
	if (this.status != FlowStatus.PAUSED)
		tersus.error('Unexpected status "'+this.status+'" for ' + this.getPath());
	this.continueExecution();
	var end = new Date();
	window.duration = "Response processed in " + (end - start) + " ms";
	
};

ServiceNode.prototype.resume = function resume()
{
	if (this.serviceError)
		throw this.serviceError;
};
/* Creates an iframe for invoking the service */

ServiceNode.prototype.getResponseFrame = function getResponseFrame()
{
	var iframe = tersus.nextServiceResponseFrame();
	this.iframeId =iframe.id;
	return iframe;
};
/*
	returns the unique trigger that holds a 'File Input' value
	If there is no such trigger, returns null.
	If there is more than one trigger, an error is reported.
*/
ServiceNode.prototype.findFileTrigger = function findFileTrigger()
{
	var fileTrigger = null;
	if (this.triggers)
	{
		for (var i=0; i<this.triggers.length; i++)
		{
			//TODO consider using the modelId of the trigger to identify the file
			var trigger = this.triggers[i];
			if (trigger.isRepetitive)
				continue;
			var child = this.getChild(trigger.role); 
			if (child && child.isFile)
			{
				if (fileTrigger)
				{
					modelError("Too many file input values");
					return null;
				}
				else
					fileTrigger = trigger;
			}
		}
	}
	return fileTrigger;
};

// file: 030-DataElement.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function DataElement(role, modelId)
{
	this.role = role;
	if (modelId)
		this.modelId = modelId;
};
DataElement.prototype = new Element();
DataElement.prototype.constructor = DataElement;
DataElement.prototype.type = 'Data Element';
DataElement.prototype.isDataElement = true;
// file: 031-SubFlow.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function SubFlow(role, modelId)
{
	this.role = role;
	this.modelId = modelId;
};
SubFlow.prototype = new Element();
SubFlow.prototype.constructor = SubFlow;
SubFlow.prototype.isSubFlow = true;
SubFlow.prototype.createChild = function createChild(parent, modelId)
{
	debugAssertion(modelId == null, "Expecting SubFlow.createChild to always receive null modelId");
	var child = this.createChildInstance(modelId);
	child.mainWindow = parent.mainWindow;
	child.currentWindow = parent.currentWindow;
	child.parent = parent;
	child.element = this;
	if (child.initialize)
		child.initialize();
	return child;
};
SubFlow.prototype.init = function SubFlow_init(parent)
{
	if (! this.isRepetitive && ! tersus.Conventions.isEventHandler(this))
	{
		var child = this.createChild(parent);
		this.addChild(parent, child);
		child.setInitialStatus();
	}
};
// file: 032-DisplayElement.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function DisplayElement(role, modelId)
{
	this.role = role;
	this.modelId = modelId;
}
DisplayElement.prototype = new SubFlow();
DisplayElement.prototype.constructor = DisplayElement;
DisplayElement.prototype.isDisplayElement = true;
DisplayElement.prototype.type = 'Display Element';
DisplayElement.prototype.addAChild = function addChild(parent, value)
{
	if (parent.currentWindow)
	{
		this.createChild(parent, value.modelId, value);
	}
	else
	{
		Element.prototype.addAChild.call(this, parent, value);
	}
};

DisplayElement.prototype.replaceChild = function replaceChild(parent, value, reset)
{
	if (parent.currentWindow) // parent is a real display node
	{
		var oldChild = this.getChild(parent);
		if (oldChild)
		{
			if (oldChild.modelId == value.modelId)
			{
				if (reset)
					oldChild.reset();
				child = oldChild;
				child.copyValue(value);
			}
			else
			{
				var oldViewNode = null;
				if (oldChild != null)
				{
					var placeHolder = oldChild.wrapperNode ? oldChild.wrapperNode: oldChild.viewNode;
					oldChild.viewNode = oldChild.wrapperNode = null;
					placeHolder.style.display = 'none';
					this.removeChild(parent);
				}
				child = this.createChild(parent,value.modelId, value, placeHolder);
			}
		}
		else
			child = this.createChild(parent,value.modelId, value);
	}
	else
	{
		Element.prototype.replaceChild.call(this, parent, value);
	}
}
DisplayElement.prototype.moveChild = function (parent, fromIndex, toIndex)
{
	var children = this.getChildren(parent);
	var currentChild = null;
	if (children.length > 0)
		currentChild = children[toIndex];
		
	var child = Element.prototype.moveChild.call(this,parent,fromIndex,toIndex);
	if (child.viewNode && currentChild)
	{
		// Move the new child before the current child
		child.viewNode.parentNode.insertBefore(child.viewNode, currentChild.viewNode);
	}
	return child;
};

DisplayElement.prototype.removeNumberedChild = function removeNumberedChild(parent, index)
{
	makeAssertion( this.isRepetitive);
	var children = this.getChildren(parent);
	children[index - 1].deleteMe();
};


// As opposed to regular SubFlows, DisplayElements are added to the parent node
DisplayElement.prototype.createChildWithoutVisuals = function createChildWithoutVisuals(parent, modelId)
{
	var child = SubFlow.prototype.createChild.call(this, parent, modelId);
	this.addChild(parent, child);
	if (parent.currentWindow && ! child.isPopup)
	{
		child.setInitialStatus();
	}
	return child;
};
DisplayElement.prototype.createChild = function createChild(parent, modelId, value, placeHolderNode)
{
	var child = this.createChildWithoutVisuals(parent,modelId);
	if (parent.currentWindow && ! child.isPopup)
	{
		child.placeHolderNode = placeHolderNode;
		child.create(value);
	}
	return child;
};
DisplayElement.prototype.init = function DisplayElement_init(parent)
{
	// There is no need to initialize display elements, as the whole  hierarchy is created in advance
	// Except for popups (which are more like regular subflows)
	// TODO clean this up (the generic DisplayElement should not know about popups)
	if (tersus.repository.get(this.modelId).prototype.isPopup)
	{
		SubFlow.prototype.init.call(this,parent);
	}
	
};

DisplayElement.prototype.prop = function(name)
{
	
	 var local = this.properties[name];
	 if (local != null)
	 	return local;
	 var childConstructor = this.getChildConstructor();
	 if (!childConstructor)
	 	return null;
	 return childConstructor.prototype.sharedProperties[name];
};

// file: 033-Trigger.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function Trigger(role, modelId)
{
	this.role = role;
	if (modelId)
		this.modelId = modelId;
};
Trigger.prototype = new Element();
Trigger.prototype.constructor = Trigger;
Trigger.prototype.type='Trigger';

Trigger.prototype.replaceChild = function(parent, value)
{
	if (parent.isInputSet) // Special case: trigger of a repetitive sub-process - we accumulate the value
	{
		if (! parent.children[this.role])
			parent.children[this.role] = [];
		parent.children[this.role].push(child);
		
	}
	else
		Element.prototype.replaceChild.call(this, parent, value);
};
Trigger.prototype.removeChildren = function(parent)
{
	makeAssertion( this.isRepetitive);
	if (parent.children)
		parent.children[this.role] = [];
};
// file: 034-Exit.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function Exit(role, modelId)
{
	this.role = role;
	if (modelId)
		this.modelId = modelId;
};
Exit.prototype = new Element();
Exit.prototype.constructor = Exit;
Exit.prototype.isExit=true;
Exit.prototype.isError=false;
Exit.prototype.type='Exit';
// file: 035-FlowDataElement.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function FlowDataElement(role, modelId)
{
	this.role = role;
	if (modelId)
		this.modelId = modelId;
};
FlowDataElement.prototype = new Element();
FlowDataElement.prototype.isFlowDataElement = true;
FlowDataElement.prototype.constructor = FlowDataElement;
FlowDataElement.prototype.type = 'Data Element';
FlowDataElement.prototype.createChild = function createChild(parent, modelId)
{
	var dataValue = this.createChildInstance(modelId);
	return parent.createReference(this, dataValue);
};
	
FlowDataElement.prototype.replaceChild = function replaceChild(parent, value)
{
	var oldValue;
	if (parent.hasElementChangeHandler)
		oldValue = this.getChild(parent);
	parent.createReference(this, value);
	if (parent.hasElementChangeHandler)
	{
		if (oldValue && oldValue.isDataNode)
			oldValue = oldValue.value;
		if (oldValue != value)
		{
			// handle the case of different leaf instances with same leaf value
			if (oldValue == null || value == null || !oldValue.isLeaf || ! value.isLeaf || (oldValue.leafValue != value.leafValue && ! (oldValue.leafValue != null && oldValue.leafValue.equals && oldValue.leafValue.equals(value.leafValue))))
				parent.handleElementChange(this.role, oldValue, value);
		}
	}
};
FlowDataElement.prototype.addAChild = function addAChild(parent, value)
{
	var reference = parent.createReference(this,value);
    if (parent.hasElementChangeHandler)
    {
        parent.handleElementChange(this.role, null, value);
    }
}

// file: 036-InputSet.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function InputSet(parent, subFlow)
{
	this.parent = parent;
	this.subFlow=subFlow;
	this.element=subFlow;
	this.childConstructor = tersus.repository.get(subFlow.modelId);
	this.triggers = this.childConstructor.prototype.triggers;
	this.setStatus(FlowStatus.NOT_READY_TO_START);
	
};
InputSet.prototype = new FlowNode();
InputSet.prototype.constructor = InputSet;
InputSet.prototype.invoke = function ()
{
	this.explode();
};
InputSet.prototype.createInstance = function()
{
	var instance =  this.subFlow.createChild(this.parent);
	instance.setStatus(FlowStatus.NOT_READY_TO_START);
	return instance;
};
InputSet.prototype.explode = function ()
{
	var instances = [];
	instances.push(this.createInstance()); 
	for (var i=0; i<this.triggers.length; i++)
	{
		var trigger = this.triggers[i];
		var values = this.children[trigger.role];
		var nPrototypes = instances.length;
		for (var j=0; j<nPrototypes; j++)
		{
			//TODO handle the case of repetitive triggers (no cartesian product is needed)
			var prototypeInstance = instances[j];
			if (values)
			{
				for (var k=0; k<values.length; k++)
				{
					var value = values[k];
					if (k==0)
					{
						trigger.replaceChild(prototypeInstance, value);
					}
					else
					{
						var newInstance = this.createInstance();
						for (var l=0; l<i; l++)
						{
							// copy values of preceding triggers
							var previousTrigger = this.triggers[l];
							previousTrigger.replaceChild(newInstance, previousTrigger.getChild(prototypeInstance));
						}
						// set current value
						trigger.replaceChild(newInstance, value);
						instances.push(newInstance);
					}
				}
			}	
		}
	}
	for (var i=0; i<instances.length; i++)
		instances[i].checkReady();
};
InputSet.prototype.addValue = function (role, value)
{
	if (! this.children)
		this.children = {};
	if (! this.children[role])
		this.children[role]= [];
	this.children[role].push(value);
};
// file: 037-Link.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function Link(role, source, target)
{	
	this.role = role;
	this.source = new Path(source);
	this.target = new Path(target);
};
Link.prototype.type= 'Flow';
Link.prototype.invoke = function invoke(sourceNode)
{
	var values;
	var parent = sourceNode.parent;
	// get source value
	values = sourceNode.getValues(this.source, 1);
	var targetElement = parent.getElement(this.target.segments[0]);
	if (! targetElement)
		return; // The target element may be null if access control excluded it from the user's application
	if (window.trace && values.length > 0)
			window.trace.flow(this, parent, values.length + " values");
	for (var i=0; i<values.length; i++)
	{
		var value = values[i];
		
		if (this.isConstantTrigger)
		{
			var constantElement = targetElement;
			constantElement.createChild(parent);
		}
		else
		{
			if (window.trace)
			{
				window.trace.flowValue(this, parent, value);
			}
			if (targetElement.isSubFlow && targetElement.isRepetitive)
			{
				var inputSet = parent.children[targetElement.role];
				if (!inputSet)
				{
					inputSet = new InputSet(parent, targetElement);
					parent.children[targetElement.role] = inputSet;
				}
				makeAssertion(this.target.segments.length == 2);
				var triggerRole = this.target.segments[1];
				inputSet.addValue(triggerRole, value);
				inputSet.checkReady();
			}
			else
			{
				// set target value
				sourceNode.parent.setValue(this.target, value, this.operation);
			
				if (! targetElement.isRepetitive)
				{
					var targetNode = targetElement.getChild(parent);
					if (targetNode && targetNode.checkReady)
						targetNode.checkReady();
				}
			}
		}
		
	}
};

// file: 038-MethodElement.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function MethodElement(owner, role, modelId)
{
	this.owner = owner;
	this.role = role;
	debugAssertion(modelId != null, "Expecting MethodElements to always have a model Id");
	if (modelId)
		this.modelId = modelId;
	else
		this.modelId = BuiltinModels.TEXT_ID; //TODO - remove this once we're sure that modelId is always given
	if (owner.getAdder(role)) // TODO - this should be a validation
		this.isRepetitive = true;
	else
		this.isRepetitive = false;
	
	if (! owner.getRemover(this.role))
		this.isRemovable = false;
};
MethodElement.prototype = new Element();
MethodElement.prototype.constructor = MethodElement;
MethodElement.prototype.type = 'Data Element';
MethodElement.prototype.isMethodElement = true;
MethodElement.prototype.replaceChild = function replaceChild(parent, value)
{
	if (parent.currentWindow) // parent is a real display node
	{
		var setter = parent.getSetter(this.role);
		if (setter == null)
			return;
		if (setter.requiresNodes)
			setter.call(parent, value);
		else
		{
			var  leafValue = value.leafValue;
			setter.call(parent, leafValue);
		}
	}
	else
		Element.prototype.replaceChild.call(this, parent,value);
	
};
MethodElement.prototype.addAChild = function addAChild(parent, value)
{
	if (parent.currentWindow) // parent is a real display node
	{
		var adder = parent.getAdder(this.role);
		if (adder.requiresNodes)
			adder.call(parent, value);
		else
		{
			var  leafValue = value.leafValue;
			adder.call(parent, leafValue);
		}
	}
	else
		Element.prototype.addAChild.call(this, parent,value);
	
};
MethodElement.prototype.removeChild = function removeChild(parent)
{
	if (parent.currentWindow) // parent is a real display node
	{
		var remover = parent.getRemover(this.role);
		if (remover)
			remover.call(parent);
	}
	else
		Element.prototype.removeChild.call(this, parent);
};

MethodElement.prototype.getChild = function getChild(parent)
{
	if (parent.currentWindow || parent.isDataValue) // parent is a real display node or a DataValue
	{
		var getter = parent.getGetter(this.role);
		var value = getter.call(parent);
	        if (value !== null && value !== undefined)
		{
		    if (value.isNode)
				return value;
			else
			{
				//This is a primitive value - wrap it as a DataValue
				var dataValue = this.createChildInstance();
				dataValue.setLeaf(value);
				return dataValue;
			}
		}
		else
		return null;
	}
	else // parent is a 'temporary' display-data node
	{
		return Element.prototype.getChild.call(this, parent);
	}
};

MethodElement.prototype.getChildren = function getChildren(parent)
{
	if (parent.currentWindow || parent.isDataValue) // parent is a real display node
	{
		var getter = parent.getGetter(this.role);
		var values = getter.call(parent);
		if (values.length > 0 && ! values[0].isNode) // The getter returned raw(leaf) values, not nodes
		{
			var leafValues = values
			values = [];
			if (leafValues.length)
			{
				for (var i=0; i<leafValues.length; i++)
				{
					var leafValue = leafValues[i];
					if (leafValue !== null && leafValue !== undefined)
					{
						var dataValue = this.createChildInstance();
						dataValue.setLeaf(leafValue);
						values.push(dataValue);
					}
				}
			}
		}
		return values;
	}
	else // parent is a 'temporary' display-data node
	{
		return Element.prototype.getChildren.call(this, parent);
	}
	
};
MethodElement.prototype.removeChildren = function removeChildren(parent)
{
	if (parent.currentWindow) // parent is a real display node
	{
		var remover = parent.getRemover(this.role);
		remover.call(parent);
	}
	else // parent is a 'temporary' display-data node
	{
		Element.prototype.removeChildren.call(this, parent);
	}
		
};


// file: 040-DataTypes.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 DATE_FORMAT='yyyy-MM-dd';
if (! tersus) tersus = {};
tersus.DECIMAL_POINT='.';
tersus.THOUSANDS_SEPARATOR=',';
if (! tersus.Messages) tersus.Messages = {};
tersus.Messages.INVALID_NUMBER = 'Please type a valid number';
tersus.Messages.INVALID_DATE = 'Please type a valid date in format '+DATE_FORMAT;

tersus.Nothing = function tersus_Nothing() {};
tersus.Nothing.prototype = new DataValue();
tersus.Nothing.prototype.constructor = tersus.Nothing;
tersus.Nothing.prototype.pluginFunc = tersus.Nothing;
tersus.Nothing.prototype.isLeaf = true;
tersus.Nothing.prototype.isNothing = true;
tersus.Nothing.prototype.toString = function toString()
{
	return '<Nothing>';
}
tersus.Nothing.prototype.serialize = function() 
{
	return 'Nothing';
};
tersus.Nothing.prototype.isInstance = function(value)
{
	return value != null && value.isNothing;
};

tersus.Text = function tersus_Text() {};
tersus.Text.prototype = new DataValue();
tersus.Text.prototype.constructor = tersus.Text;
tersus.Text.prototype.isLeaf = true;
tersus.Text.prototype.pluginFunc = tersus.Text;
tersus.Text.prototype.isText = true;
tersus.Text.prototype.sqlType = 'TEXT';
tersus.Text.prototype.parseInput = function tersus_Text_parseInput(str)
{
	if (str == '')
		return null;
	
	var constructor = this.constructor;
	var text = new constructor();
	text.leafValue = str.replace (/\r/g,'');
	return text;
};
tersus.Text.prototype.isInstance = function(value)
{
	return value != null && value.isText;
};
tersus.Text.prototype.formatString = function tersus_Text_formatString(properties)
{
	if (this.leafValue == null)
		return '';
	var s = this.leafValue.toString();
	return s;
};
tersus.Text.prototype.formatInput = function tersus_Text_formatInput(properties)
{
	if (this.leafValue == null)
		return '';
	var s = this.leafValue.toString();
	return s;
};
tersus.Text.prototype.setLeaf = function(value)
{
	if (value == null)
		this.leafValue == null;
	else this.leafValue = ''+value;
};
tersus.Text.prototype.parseString = tersus.Text.prototype.setLeaf;
tersus.Text.prototype.toString=tersus.Text.prototype.serialize= function(){return this.leafValue;}
tersus.SecretText = tersus.Text.__subclass('tersus.SecretText');
tersus.SecretText.prototype.isSecret=true;

tersus.notEmpty = function (value)
{
	return value !== null && value !== undefined && value !== ' ';
};
tersus.isNumber = function tersus_isNumber(value)
{
	if (value == null)
		return false;
	var str = value.toString();
	var re = /^\s*[-+]?(\d+(\.\d*)?|(\.\d+))([eE][-+]?\d+)?\s*$/;
	return str.match(re);
};
tersus.isNumberWithSeparators = function tersus_isNumber(value)
{
	if (value == null)
		return false;
	var str = value.toString();
	var reStr = '^[-]?((\\d{1,3}(['+tersus.THOUSANDS_SEPARATOR+']\\d{3})*)|\\d*)(['+tersus.DECIMAL_POINT+']\\d*)?$';
	var re = new RegExp(reStr);
	return str.match(re);
};

tersus.Number = function tersus_Number() {};
tersus.Number.prototype = new DataValue();
tersus.Number.prototype.constructor = tersus.Number;
tersus.Number.prototype.isLeaf = true;
tersus.Number.prototype.sqlType = 'NUMERIC';
tersus.Number.prototype.pluginFunc = tersus.Number;
tersus.Number.prototype.isNumber = true;
tersus.Number.prototype.isInstance = function(value)
{
	return value != null && value.isNumber;
};
tersus.Number.prototype.parseInput = function(s, props) 
{
	if (s == null || s == '')
		return null;
	if (props.currencySymbol)
		s = s.replace(props.currencySymbol, '');
	if (s == '')
		return null;
	var s1 = null;
	if (tersus.permissiveNumberInput)
	{
		var s0 = s.replace(/[,]/,'.');
		if (tersus.isNumber(s0))
			s1 = s0;
	}
	
	if (s1 == null) // Not permissive or permissive format doesn't match
	{
		s1 = s.replace(new RegExp('['+tersus.THOUSANDS_SEPARATOR+']','g'),'');
		s1 = s1.replace(new RegExp('['+tersus.DECIMAL_POINT+']','g'),'.');
	}
	var x = parseFloat(s1);
	if (isNaN(x))
		return null;
	var number = new (this.constructor)();
	number.leafValue = x;
	return number;
};

tersus.Number.prototype.serialize = tersus.Number.prototype.toString = function()
{
	if (this.leafValue === null || this.leafValue === undefined)
		return null;
	else
		return this.leafValue.toString();
}

tersus.Number.prototype.validateInput = function (s, props)
{
	if ( s == null || s == '')
		return null;
	if (props.currencySymbol)
		s = s.replace(props.currencySymbol,'');
	if (tersus.permissiveNumberInput)
	{
		var s0 = s.replace(/[,]/,'.');
		if (tersus.isNumber(s0))
			return null;
	}
	
	if (tersus.isNumberWithSeparators(s))
		return null;
	else
		return tersus.Messages.INVALID_NUMBER;
};
tersus.Number.prototype.formatInput = function tersus_Number_formatInput(props)
{
	return this.formatString(props, true);
};
tersus.Number.prototype.formatString = function tersus_Number_formatString(props, noRounding)
{
    if (props.format)
        return gwtFormatNumber(this.leafValue,props.format);
    // TODO move formatter to legacy script (and use default format when props.format is missing)
//	return ''+this.leafValue;
	var formatter = new NumberFormat();
	if (props)
	{
		if (!noRounding && tersus.isNumber(props.decimalPlaces))
			formatter.setPlaces(props.decimalPlaces);
		var useSeparators =  (true == props.useThousandsSeparator);
		formatter.setSeparators(useSeparators, tersus.THOUSANDS_SEPARATOR, tersus.DECIMAL_POINT);
		if (props.currencySymbol && props.currencySymbol != ' ')
		{
			formatter.setCurrencyValue(props.currencySymbol);
			formatter.setCurrency(true);
		}
		if (props.currencyPosition && NumberFormat.prototype[props.currencyPosition])
			formatter.setCurrencyPosition(NumberFormat.prototype[props.currencyPosition]);
	}
	formatter.setNumber(this.leafValue);
	if (props && props.showPercentage)
		return formatter.toPercentage();
	else
		return formatter.toFormatted();
	
	
};
tersus.Number.prototype.parseString = function tersus_Number_parseString (str, element)
{
	var format;
	if (element) format = element.format;
	if (!format) format = this.format;
	if (format)
	{
		try
		{
		 	this.leafValue = gwtParseNumber(str, format);
		}
		catch (e)
		{
			throw {message:'Invalid number format. Format="'+format+'" text="'+str+'"'};
		}
		
	}
	else
	{
		if (! tersus.isNumber(str))
			throw {message:'Invalid number format: text="'+str+'"'}; 
		this.leafValue = parseFloat(str);
	}
};
tersus.Boolean = function tersus_Boolean() {};
tersus.Boolean.prototype = new DataValue();
tersus.Boolean.prototype.constructor = tersus.Boolean;
tersus.Boolean.prototype.isLeaf = true;
tersus.Boolean.prototype.pluginFunc = tersus.Boolean;
tersus.Boolean.prototype.YES_STR = 'Yes';
tersus.Boolean.prototype.TRUE_STR = 'true';
tersus.Boolean.prototype.NO_STR = 'No';
tersus.Boolean.prototype.leafValue = null;
tersus.Boolean.prototype.sqlType = 'CHAR(1)';
tersus.Boolean.prototype.setLeaf = function (v)
{
	if (v == null)
		this.leafValue = null;
	else if (v == true || v == this.YES_STR || v == this.TRUE_STR)
		this.leafValue = true;
	else
		this.leafValue = false;
};
tersus.Boolean.prototype.parseString = function tersus_Boolean_parseString(str, element)
{
	this.leafValue = (str == this.YES_STR || str == this.TRUE_STR);
};

tersus.Boolean.prototype.serialize = function ()
{
	if (this.leafValue == null)
		return 'null';
	else
		return this.leafValue? this.YES_STR: this.NO_STR;
		
};
tersus.Boolean.prototype.toString = tersus.Boolean.prototype.serialize;
tersus.Boolean.prototype.isBooleanValue = true;
tersus.Boolean.prototype.isInstance = function(value)
{
	return value != null && value.isBooleanValue;
};


tersus.DateValue = function tersus_DateValue(dateStr)
{
	if (dateStr)
	{
		var parts = dateStr.split('-');
		this.year = parseInt(parts[0],10);
		this.month = parseInt(parts[1],10);
		this.day = parseInt(parts[2],10);
	}
};
tersus.DateValue.prototype.formatString = function formatString(format)
{
    if (window.formatDate) //legacy
        return formatDate(this.year, this.month, this.day, DATE_FORMAT);
    else
    {
        format = format || DATE_FORMAT;
        return gwtFormatDateAndTime(this.toLocalDate(), format, -10000);
    }
}
tersus.DateValue.prototype.toString = function toString()
{
	var p2 = tersus.DateAndTime.pad2;
	return this.year+'-'+p2(this.month)+'-'+p2(this.day);
}
tersus.DateValue.prototype.isTersusDate = true;
tersus.DateValue.prototype.toLocalDate = function()
{
	var d= new Date(this.year, this.month-1,this.day);
	return d;
};

tersus.DateValue.prototype.equals = function (other)
{
	return other && other.isTersusDate && other.year == this.year && other.month == this.month && other.day == this.day;
};
function createDate(year, month, day)
{
	var date = new tersus.DateValue();
	date.year = year;
	date.month = month;
	date.day = day;
	return date;
};

tersus.Date = function tersus_Date() {};
tersus.Date.prototype = new DataValue();
tersus.Date.prototype.constructor = tersus.Date;
tersus.Date.prototype.isLeaf = true;
tersus.Date.prototype.sqlType = 'Date';
tersus.Date.prototype.pluginFunc = tersus.Date;
tersus.Date.prototype.isDate = true;
tersus.Date.prototype.isInstance = function(value)
{
	return value != null && value.isDate;
};
tersus.Date.prototype.setLeaf = function tersus_Date_setLeaf(value)
{
	if (value.isTersusDate)
		this.leafValue = value;
	else
		this.leafValue = new tersus.DateValue(value);
};

tersus.Date.prototype.format = 'yyyy-MM-dd';
tersus.Date.prototype.parseString = function tersus_Date_parseString(str, element)
{
	var format;
	if (element)
		format = element.format;
	if (!format)
		format = this.format;	
	this.parseDateString(str, format);
};
tersus.Date.prototype.parseDateString = function tersus_Date_parseString(str, format)
{
    var time =  gwtParseDateAndTime(str, format, -100000); // Using local time zone
    if (time == -1)
        throw {message:'Invalid date format. Format:"'+format+'" text="'+str+'"'};
    var d = new Date(time); // Using 
    var date = new tersus.DateValue();
    date.year=d.getFullYear();
    date.month=d.getMonth()+1;
    date.day=d.getDate();
    this.leafValue=date;    
};

tersus.Date.prototype.parseInput = function (str)
{
    if (str == null || str == '')
        return null;
    var constructor = this.constructor;
    var node = new constructor();
    var date = new tersus.DateValue();
    node.parseDateString(str, DATE_FORMAT);
    return node;
};


tersus.Date.prototype.getYear = function tersus_Date_getYear()
{
	if (this.leafValue)
		return this.leafValue.year;
	else
		return null;
};
tersus.Date.prototype.getMonth = function tersus_Date_getMonth()
{
	if (this.leafValue)
		return this.leafValue.month;
	else
		return null;
};
tersus.Date.prototype.getDay = function tersus_Date_getDay()
{
	if (this.leafValue)
		return this.leafValue.day;
	else
		return null;
};

tersus.Date.prototype.formatString = function(props)
{
	var dateFormat = null;
	if (props)
	{
		var dateFormat = props.format || props.dateFormat; /* props.dateFormat is un un-document legacy that has likely never used, but support is retained*/
	}	
	if (! dateFormat)
		dateFormat = DATE_FORMAT;
	var date = this.leafValue;
	var s;
	if (date == null)
		s =  '';
	else if (date.isTersusDate) 
	    s=date.formatString(dateFormat);
	else
		s = date.toString();
	return s;

};

Date.prototype.equals = function (other)
{
	return other.getTime && this.getTime() == other.getTime();
};

tersus.getDate = function(o)
{
	if (o && o.leafValue)
	{
		if (o.leafValue.isTersusDate)
			return o.leafValue.toLocalDate();
		else 
			return o.leafValue;
	}
		
};

tersus.DateAndTime = function tersus_DateAndTime() {};
tersus.DateAndTime.prototype = new DataValue();
tersus.DateAndTime.prototype.constructor = tersus.DateAndTime;
tersus.DateAndTime.prototype.isLeaf = true;
tersus.DateAndTime.prototype.pluginFunc = tersus.DateAndTime;
tersus.DateAndTime.prototype.isDateAndTime = true;
tersus.DateAndTime.prototype.sqlType = 'Timestamp';
tersus.DateAndTime.prototype.isInstance = function(value)
{
	return value != null && value.isDateAndTime;
};
tersus.DateAndTime.prototype.formatString = function(props)
{
    var date = this.leafValue;
    if (props.format)
        return gwtFormatDateAndTime(date, props.format, -10000);
	var	dateFormat = DATE_FORMAT;
	var s;
	if (date == null)
		s =  '';
	else
	{
	    //TODO clean this up.  The code in this file should not refer to formatDate (from popcalendar) - need some other way to allow for backward compatability
	    if (window.formatDate)
	        s = window.formatDate(date.getFullYear(), date.getMonth()+1, date.getDate(), dateFormat);
	    else
	        s = gwtFormatDateAndTime(date, dateFormat, -10000);
		var p2 = tersus.DateAndTime.pad2;
		s += ' - '+p2(date.getHours())+':'+p2(date.getMinutes())+':'+p2(date.getSeconds());
	}
	return s;
};
tersus.DateAndTime.prototype.re = new RegExp("([0-9]+)-([0-9]+)-([0-9]+) ([0-9]+):([0-9]+)(:([0-9]+)(:([0-9]+))?)?");
tersus.DateAndTime.pad2 = function(value)
{
	if (value < 10)
		return '0'+value;
	else
		return value;
};
tersus.DateAndTime.pad3 = function(value)
{
	if (value < 10)
		return '00' + value;
	else if (value < 100)
		return '0' + value;
	else
		return value;
};
tersus.DateAndTime.prototype.format='yyyy-MM-dd HH:mm:ss:SSS';
tersus.DateAndTime.prototype.formatAsGMT=false;
tersus.DateAndTime.prototype.W3CFORMATS = ["yyyy-MM-dd'T'HH:mm:ss.SSSSSSZ","yyyy-MM-dd'T'HH:mm:ssZ","yyyy-MM-dd'T'HH:mmZ"];
tersus.DateAndTime.prototype.W3CFORMAT="yyyy-MM-dd'T'HH:mm:ss.SSSSSSSTZD";
tersus.DateAndTime.prototype.setLeaf = function tersus_Date_setLeaf(value)
{
	if (value.constructor==Date)
		this.leafValue =value;
	else
	{
		var d = this.re.exec(value);
		if (d == null)
			internalError("Failed to parse date/time string '"+value+"'");
		var date =  this.leafValue = new Date(0);
		date.setUTCFullYear(d[1]);
		date.setUTCMonth(d[2]-1);
		date.setUTCDate(d[3]);
		date.setUTCHours(d[4]);
		date.setUTCMinutes(d[5]);
		if (d[7])
			date.setUTCSeconds(d[7]);
		if (d[9])
		date.setUTCMilliseconds(d[9]);
	};	
};

tersus.parseDateTimeString = function(str, format, tzOffset)
{
	var time;
	if (format == tersus.DateAndTime.prototype.W3CFORMAT)
	{
		var s1=str.replace(/z/i,'+00:00');
		for (var i=0;i<tersus.DateAndTime.prototype.W3CFORMATS.length;i++)
		{
			time =  gwtParseDateAndTime(s1,tersus.DateAndTime.prototype.W3CFORMATS[i], 0);
			if (time != -1)
				break;
		}
	}
	else
	{
		time =  gwtParseDateAndTime(str,format,tzOffset);
	}
	if (time == -1)
			throw {message:'Invalid date/time format. Format:"'+format+'" text="'+str+'"'};
    return time;
};
tersus.DateAndTime.prototype.parseString = function tesus_DateAndTime_parseString(str, element)
{
	var format = this.format;
	var formatAsGMT = this.formatAsGMT;
	if (element)
	{
		if (element.format != null)
			format = element.format;
		if (element.formatAsGMT != null)
			formatAsGMT = element.formatAsGMT;
	}
	
        var time = tersus.parseDateTimeString(str, format,  formatAsGMT?0:-100000);
	this.leafValue = new Date(time);
};

tersus.DateAndTime.prototype.serialize = function(noquote)
{
	var d = this.leafValue;
	var p2 = tersus.DateAndTime.pad2;
	var p3 = tersus.DateAndTime.pad3;
	var q = noquote?'':'"';
	return d.getUTCFullYear()+"-"+p2(d.getUTCMonth()+1)+"-"+p2(d.getUTCDate())+" "+p2(d.getUTCHours())+":"+p2(d.getUTCMinutes())+":"+p2(d.getUTCSeconds())+":"+p3(d.getUTCMilliseconds());
};

File = function File(ownerField)
{
	this.inputFieldDisplayNode = ownerField;
};
File.prototype = new DataValue();
File.prototype.constructor = File;
File.prototype.pluginFunc = File;
// TODO: when IE8.0/IE9.0 support can be dropped, move inputFieldDisplayNode to legacy script
File.prototype.isFile = true;
File.prototype.getFileName = function getFileName()
{
    if (this.file)
        return this.file.name;
	if (! this.inputFieldDisplayNode)
	{
		if (this.children && this.children['File Name'])
			return this.children['File Name'];
		else
			return null;
	}
	if ( this.inputFieldDisplayNode.currentWindow.closed)
	{
		tersus.error('Tersus Application Error: Reference to a file input field in closed popup window.\n');
		return null;
	}
	if (! this.inputFieldDisplayNode.fileNode)
		return null;
	if (this.inputFieldDisplayNode.fileNode.value)
		return this.inputFieldDisplayNode.fileNode.value;
	else if (this.children)
		return this.children['File Name'];
	else
		return null;
	
};

File.prototype.addGetter('File Name',File.prototype.getFileName);
File.prototype.toString = function toString()
{
	return 'Input File '+ this.getFileName();
};

// file: 050-serializer.js
/*********************************************************************************************************
 * Copyright (c) 2003-2010 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Serializer() {};
Serializer.prototype.DEBUG = false;
Serializer.prototype.Tokens = {};
Serializer.prototype.Tokens.START_OBJECT = '{';
Serializer.prototype.Tokens.END_OBJECT = '}';
Serializer.prototype.Tokens.START_ARRAY = '[';
Serializer.prototype.Tokens.END_ARRAY = ']';
Serializer.prototype.Tokens.OBJECT_SEPARATOR = ',';
Serializer.prototype.Tokens.ARRAY_SEPARATOR = ',';
Serializer.prototype.Tokens.ASSIGN = ':';
Serializer.prototype.Tokens.QUOTE = '"';
Serializer.prototype.addWhitespace = true;

Serializer.prototype.serialize = function serialize(value)
{
	var output = [];
	var stack = [];
	if (value.constructor == Array)
		this._serializeList(value, output, stack);
	else
		this._serializeValue(value, output, stack);
	var serialization = output.join('');
	return serialization;
};
Serializer.prototype._serializeList = function _serializeList(values, output, stack)
{
	output.push(this.Tokens.START_ARRAY);
	for (var i=0; i<values.length; i++)
	{
		if (i>0)
		{
			output.push(this.Tokens.ARRAY_SEPARATOR);
			if (this.addWhitespace)
				output.push('\n');
		}
		this._serializeValue(values[i], output, stack);
	};
	output.push(this.Tokens.END_ARRAY);
};
/*
 Serializes a value hierarchy into an output buffer
 value - the value to be serialized
 output - an array of strings/primitive values serving as the output buffer
*/
Serializer.prototype._serializeValue  = function _serializeValue(value, output, stack)
{
	if (value.isDataNode)
	{
		this._serializeValue(value.value, output, stack);
		return;
	};
	if (value.isNode)
	{
		for (var i=0;i<stack.length;i++)
		{
			var n = stack[i];
			if (n == value)
				return;
		}
	}
	stack.push(value);
	if (value.isSecret && this.hideSecretValues)
	{
		output.push('*****');
	}
	else if (value.isNumber || value.isBooleanValue)
	{
		if (value.leafValue != null)
			output.push(value.leafValue); // No need for quoting or escaping
	}
	else if (value.serialize)
	{
		this._quote(value.serialize(),output);
	}
	else if (value.isNothing)
	{
		output.push(this.Tokens.START_OBJECT);
		output.push(this.Tokens.END_OBJECT);
	}
	else if (value.isLeaf)
	{
		if (value.leafValue !== null && value.leafValue !== undefined)
			this._quote(value.leafValue, output);
		else
			output.push('null');
	}
	else
	{
		output.push(this.Tokens.START_OBJECT);
		var childCount = 0;
		if (value.elements)
		{
			for (var role in value.elements)
			{
				var element = value.elements[role];
				if (element.isAncestorReference)
					continue;
				if (element.isSubFlow && ! element.isDisplayElement)
					continue;
				if (element.isRepetitive)
				{
					var childValues = element.getChildren(value);
					if (childValues.length == 0)
						continue;
					if (childCount >0)
						output.push(this.Tokens.OBJECT_SEPARATOR);
					this._quote(element.role, output);
					output.push(this.Tokens.ASSIGN);
					this._serializeList(childValues, output, stack);
				}
				else
				{
					var childValue = element.getChild(value);
					if (! childValue)
						continue;
					if (childValue.isPopup)
						continue; // A pop is realy an action here, and it may be closed.  We don't want to serialize it
					if (childCount >0)
						output.push(this.Tokens.OBJECT_SEPARATOR);
					this._quote(element.role, output);
					output.push(this.Tokens.ASSIGN);
					this._serializeValue(childValue, output, stack);
				}
				childCount++;
			}
		}
		output.push(this.Tokens.END_OBJECT);
	}
	stack.pop();
};

Serializer.prototype._quote= function _quote(value, output)
{
	output.push(this.Tokens.QUOTE);
	var s = value.toString(); 
	var l = s.length;
	var escaped = "";
    for (var i = 0; i < l; i++)
    {
    	c = s.charAt(i);
    	switch (c)
    	{
      		case '\\':
				escaped += '\\\\';
                break;
      		case '\t':
				escaped += '\\t';
                break;
			case '\r':
				escaped += '\\r';
				break;
			case '\n':
				escaped += '\\n';
				break;
			case this.Tokens.QUOTE:
				escaped += "\\"+this.Tokens.QUOTE;
				break;
			default:
				escaped += c;
          }
	}
	//TODO complete escaping (use JSON http://www.crockford.com/JSON)
	
	output.push(escaped);
	output.push(this.Tokens.QUOTE);
};

// file: 051-trace.js
/*********************************************************************************************************
 * Copyright (c) 2003-2010 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function startTrace(silent)
{
	closeTrace();
	
	window.trace = new Trace();
	window.trace.open(silent);
};
function showTrace()
{
	var traceWindow = window.open("","traceWindow");
	traceWindow.document.write('<textarea cols="120" rows="80">' + trace.buffer.join('') + '</textarea>');
	window.trace.window = traceWindow;
	setTimeout(function(){traceWindow.focus();}, 100);
};
function stopTrace(silent)
{
	if (!silent)
	{
		if (! window.trace)
			tersus.notify('Message','Tracing not started');
		else
			tersus.notify('Message',"Trace file '"+window.trace.filename+"' closed.");
	}
	closeTrace();
};
function closeTrace()
{
	if (window.trace)
	{
		window.trace.flush();
		if (window.trace.window) window.trace.window.close();
	}
	deleteCookie(Trace.COOKIE_NAME);
	window.trace = null;
};

function initTrace()
{
	var file = getCookie(Trace.COOKIE_NAME);
	if (file)
	{
		tersus.notify("Message",'Using trace file ' + file);
		window.trace = new Trace();
		window.trace.filename=file;
	}
};
function Trace() 
{

	this.buffer = [];
	this.elementStack = [];
	this.indentation = '';
};

Trace.prototype.serializer = new Serializer();
Trace.prototype.serializer.addWhitespace=false;
Trace.prototype.serializer.hideSecretValues=true;

Trace.COOKIE_NAME='tersus_trace_file';
Trace.prototype.open = function(silent)
{
	this.filename = this.openTraceFile();
	setCookie(Trace.COOKIE_NAME, this.filename);	
	if (!silent)
		tersus.notify('Message',"Tracing started. The trace file is '"+this.filename +"'");
	
};
Trace.prototype.openTraceFile = function()
{
	var req = createXMLHTTPRequest();
	var url = tersus.getTraceBaseURL()+'NewFile';
	req.open('POST', url, false);
	req.send(null);
	if (req.status != 200)
	{
		tersus.notify('Message','Failed to create trace file');
		return null;
	}
	else
	{
		var filename=''+req.responseText;
		return filename;
	}
};
Trace.prototype.flush=function()
{
	if (this.buffer.length == 0)
		return;
	var prefix = "// Client side trace\n";
	var content = prefix + this.buffer.join('');
	this.buffer.splice(0, this.buffer.length); // remove all
	var url = tersus.getTraceBaseURL()+encodeURIComponent(this.filename);
	var req = createXMLHTTPRequest();
	req.open('POST', url, false);
	req.send(content);
	if (req.readyState == 4 && req.status != 200)
	{
		tersus.notify('Message','Failed to write to trace file');
	}
	
};
Trace.prototype.close = function()
{
	this.traceWindow.close();
};
Trace.prototype.STARTED= 'Started';
Trace.prototype.FINISHED= 'Finished';
Trace.prototype.WAITING= 'Waiting';
Trace.prototype.RESUMED= 'Resumed';
Trace.prototype.PAUSED = 'Paused';
Trace.prototype.RESPONDED = 'Responded';
Trace.prototype.INVOKED = 'Invoked';
Trace.prototype.VALUE = 'Value';
Trace.prototype.ACTIVATED = 'Activated';
Trace.prototype.SET = 'Set';
Trace.prototype.ACCUMULATED = 'Accumulated';
Trace.prototype.REMOVED = 'Removed';
Trace.prototype.CREATED = 'Created';
Trace.prototype.CLICKED = 'Clicked';
Trace.prototype.SQL = 'SQL';

Trace.prototype.location = function (node, element, suffix)
{
	return new tersus.RuntimeLocation(node,element, suffix);
};
Trace.prototype.started = function(node) 
{
	if (node.isDisplayNode && ! node.isButton)
		return; // We don't really care about 'start' of display nodes
	this.trace(node.type, this.STARTED, this.location(node), this.getTriggerValues(node));
};
Trace.prototype.getTriggerValues = function(node)
{
	var details=[];
	var count = 0;
	if (node.triggers)
	{
		details.push('{');
		for (var i=0; i<node.triggers.length; i++)
		{
			var trigger = node.triggers[i];
			var serialization = null;
			if (trigger.isRepetitive)
			{
				var values  = trigger.getChildren(node);
				if (values.length > 0)
					serialization = this.serializer.serialize(values);
			}
			else
			{
				var value = trigger.getChild(node);
				if (value != null)
					serialization = this.serializer.serialize(value);
			}
			if (serialization != null)
			{
				
				if (count>0)
				{
					details.push(',');
				}
				++count;
				this.serializer._quote(trigger.role, details);
				details.push(':');
				details.push(serialization);
			}
		}
		details.push('}');
	}
	return details.join('');
};
Trace.prototype.resumed = function(node) 
{
	//No tracing for 'resumed' - nothing interesting here (?)
};
Trace.prototype.finished = function(node)
{
	this.trace(node.type, this.FINISHED, this.location(node));
};
Trace.prototype.waiting = function(node)
{
	//No tracing for 'waiting' - nothing interesting here (?)
};
Trace.prototype.charged = function(node, exit, value)
{
	var details = null;
	if (value != null)
	{
		details = this.serializer.serialize(value);
	}
	var event = this.SET;
	if (exit.isRepetitive)
		event = this.ACCUMULATED;
	this.trace(exit.type, event, this.location(node,exit),details,null);
	
};
Trace.prototype.sql = function(node, sql, values)
{
	var l = [];
	if (values)
	{
		l.push(' values: ');
		for (var i=0;i<values.length;i++)
		{
			if (i>0)
				l.push(',');
			var v = values [i];
			if (v == null)
				l.push('null');
			else if (typeof(v) == 'string')
			{
				this.serializer._quote(v,l);
			}
			else
				l.push(v);
		}
	}
	var valuesStr = l.join('');
	this.trace(null,this.SQL,this.location(node),"Executing statement: '" + sql + "'" + valuesStr, null);
}

Trace.prototype.paused = function(node)
{
	//No tracing for 'pause' - we want the trace to simulate the synchronous behavior
};
Trace.prototype.flow = function(flow,parent, details)
{
	this.trace(flow.type, this.ACTIVATED, this.location(parent,flow), details);
};

Trace.prototype.flowValue = function(flow, parent, value)
{
	var lastElement = flow.target.getElement(parent);
	if (!lastElement)
		return;//This can happen when elements are excluded from the client-side model because of permissions
	var eventType = '?';
	if (flow.operation == Operation.REPLACE)
		eventType = this.SET;
	else if (flow.operation == Operation.REMOVE)
		eventType = this.REMOVED;
	else if (flow.operation == Operation.ADD)
		eventType = this.ACCUMULATED;
	var pp = this.location(parent).path.str;
	var displayPath = pp ? pp + "/"+flow.target : flow.target;
	this.trace(lastElement.type, eventType, this.location(parent,flow,"Value"),this.serializer.serialize(value),null,displayPath);
};
Trace.prototype.link = function(flow, filename, comment)
{
	this.trace(null,this.LINK, this.location(flow), "'"+filename+"' - "+ comment);
};

Trace.prototype.invoked = function(node)
{
	var details = null;
	this.trace(node.type, this.INVOKED, this.location(node), this.getTriggerValues(node));
};

Trace.prototype.activated = function(node)
{
	this.trace(node.type, this.ACTIVATED, this.location(node.parent, node.element), this.serializer.serialize(node.value));
}

Trace.prototype.responded = function(node)
{
	this.trace(node.type, this.RESPONDED, this.location(node));
};

Trace.prototype.trace = function(objectType, event, location, details, comment, displayPath)
{
	if (location && (location.baseModelId != this.lastBaseModelId || this.buffer.length==0) )
	{
		// We need to write out the base model id either if this is the first record or if the base model id changed
		this.buffer.push('@');
		this.buffer.push(location.baseModelId);
		this.buffer.push('\n');
		this.lastBaseModelId = location.baseModelId;
	}
	if (!objectType)
		objectType = "-";
	if (!details)
		details = "-";
	if (! comment)
		comment = "-";
	var path = location.path?location.path.str:null;
	if (! path)
		path = "-";
	if (!displayPath)
		displayPath = "-";
	var now=new Date();
	var time = Date.UTC(now.getUTCFullYear(), now.getUTCMonth(), now.getUTCDate(), now.getUTCHours(), now.getUTCMinutes(), now.getUTCSeconds(), now.getUTCMilliseconds());
	
	this.buffer.push(objectType,"\t",event,"\t",path,"\t");
	this.addEscaped(details);
	this.buffer.push("\t",comment,"\t",displayPath,"\t",time,"\n");
};
Trace.prototype.addEscaped = function (s)
{
	var s1 = s.replace(/\n/g,'\\n').replace(/\r/g,'\\r').replace(/\t/g,'\\t');
	this.buffer.push(s1);
};
Trace.prototype.event = function(node, event)
{
	if (event == Events.ON_CLICK)
	{
		var location = this.location(node);
		var displayPath = location.path.str;
		location.path = null; // We send a location with an empty path to 'force' the event to appear as a top level event
		this.trace(node.type,this.CLICKED,location,null/*details*/,null/*comment*/,displayPath); 
	}
};

initTrace();

// file: 052-loader.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.PERSPECTIVE = 'Perspective';
tersus.VIEW = 'View';
tersus.preloadAll = true;
tersus.onResize = function()
{
	tersus.async.exec(tersus._onResize, false /* don't wait */);
};


tersus.initialResize = function()
{
	tersus.onResize();
	if (rootDisplayNode.status == FlowStatus.WAITING_FOR_INPUT)
		$(window).unbind('ter-process-end',tersus.initialResize);
};
$(window).bind('ter-process-end',tersus.initialResize); 
tersus._onResize = function onResize()
{
    if (window.currentRootDisplayNode)
	window.currentRootDisplayNode.onResize();
    tersus.unregisterPopupNodes();
    for (var popupId in tersus.popupNodes)
    {
        node = tersus.popupNodes[popupId].onResize();
    }

};
function getPerspective(name)
{
	for (var i=0; i<window.perspectives.length; i++)
	{
		if (window.perspectives[i].name == name)
		{
			return window.perspectives[i];
		}
	}
	return null;
};
function getView(name)
{
	for (var i=0; i< window.perspective.views.length; i++)
	{
		var v = perspective.views[i];
		if (v.name == name)
		{
			return  v;
		}
	}
	return null;
};

tersus.selectView=function(targets)
{
    var width = $(window).width();
    var height = $(window).height();
    if (width < 768 || (height < 768 && width < 1024)) // Mobile
        return targets.mobileView || targets.tabletView || targets.desktopView || targets.defaultView;
    else if (width <= 1024) // Tablet
        return targets.tabletView || targets.desktopView || targets.defaultView;
    else //Desktop
        return targets.desktopView || targets.tabletView || targets.defaultView;
};

tersus.setPerspectiveAndView = function()
{
	var perspectiveName = tersus.searchParams[tersus.PERSPECTIVE];
	var viewName = tersus.searchParams[tersus.VIEW];
	window.perspective = getPerspective(perspectiveName);
	if (!window.perspective)
		window.perspective = window.perspectives[0];
	window.view = getView(viewName);
	if (!window.view)
	{
	    var targets = {};
	    var views = window.perspective.views;
	    targets.defaultView=views[0];
	    for (var i=0;i<views.length;i++)
	    {
	        var v = views[i];
	        if (v.name == '<Mobile View>')
	            targets.mobileView=v;
	        else if (v.name == '<Tablet View>')
	            targets.tabletView=v;
            else if (v.name == '<Desktop View>')
                targets.desktopView= v;
	    }
		window.view = tersus.selectView(targets);
	}
};

tersus.load = function load()
{
	var cache = window.applicationCache;
	if (cache) 
	{
		if (tlog) tlog('tersus.load: cacheStatus='+cache.status);
		switch (cache.status)
		{
			case cache.UPDATEREADY:
				tersus.reloadApplication(); 
				return;
			case cache.CHECKING:
			case cache.DOWNLOADING:
			case cache.UPDATING:
			cache.onupdateready = function(){if(tlog) tlog('OnUpdateReady');setTimeout(tersus.reloadApplication,50);};
			cache.oncached=function(){if(tlog) tlog('OnCached');applicationCache.onnoupdate=null;tersus.load();};
			cache.onnoupdate=function(){if(tlog) tlog('OnUpdate');applicationCache.onnoupdate=null;tersus.load();};
			cache.onerror=function(){if(tlog) tlog('OnError');applicationCache.onerror=null;tersus.load();};
			return;	
		}
	}
	if (tlog) tlog('load()');
	tersus.init();
	if (tlog) tlog('init() finished');
	tersus.progress.set('Loading application ...');
	if (tlog) 
		tlog ('tersus.lastTimestamp:'+tersus.lastTimestamp)
	if (!tersus.lastTimestamp)
		tersus.reloadView();
	else if (window.localStorage && tersus.useLocalStorage && navigator.onLine == false && !tersus.isLocalHost(document.domain))
	{
		tersus.reloadView();
	}
	else
	{
		tersus.getTimestamp(tersus.handleLoadTimestampResponse);
	}
	if (tlog) tlog('load() returns');
	
};
tersus.handleLoadTimestampResponse = function()
{
	var req = tersus.getTimestampReq;
	if (tlog) tlog('Ready state:'+req.readyState);
	if (req.readyState != 4)
		return;
	if (tlog) tlog('Status:'+req.status);
		
	if (req.status == 200 || req.responseText)
	{
		var r = tersus.parseTimestampResponse(req);
		var currentTimestamp = r.timestamp;
		window.userName = r.userName;
		tersus.setLastTimestamp(currentTimestamp);
		tersus.reloadView();
	}
	else if(req.status == 0 && window.localStorage && tersus.useLocalStorage)
		tersus.reloadView();
	else if (req.status == 0 && navigator.onLine == false)
		tersus.reloadView();
};
tersus.reloadView = function()
{
	tersus.setPerspectiveAndView();
	tersus.loadView(document.getElementById('tersus.content'),view);
};
tersus.loader = {};
tersus.loadView = function loadView(targetElement, view)
{
	tersus.progress.set('Loading view - '+view.name);
	tersus.async.exec(function(){ tersus._loadView(targetElement, view);},false);
}
tersus._loadView = function loadView(targetElement, view)
{
	tersus.progress.set('Loading view - '+view.name);
	tersus.loader.currentView = view;
	tersus.loader.targetElement = targetElement;
	if (window.rootDisplayNode)
	{
		window.rootDisplayNode.destroyHierarchy();
		window.rootDisplayNode = null;
	    $(targetElement).empty(); // destroyHierarchy doesn't delete DOM Nodes
	}
	if (window.initPopupCalendar && ! tersus.popupCalendarInitialized)
	{
		tersus.popupCalendarInitialized = true;
		initPopupCalendar();
	}
	tersus.viewPath = view.path;
	if (tersus.repository.checkLoaded(view.id))
		tersus.loader.load();
	else
		if (tersus.preloadAll)
			tersus.repository.loadPackages([""],tersus.loader.load);
		else
			tersus.repository.loadPackages([tersus.getPackageId(view.id)],tersus.loader.load);
	tersus.alertMode = {interactive:true};
}
tersus.loader.load = function load()
{
	var view = tersus.loader.currentView;
	var targetElement = tersus.loader.targetElement;
	var root = window.rootDisplayNode;
	try
	{
		targetElement.innerHTML = '';
		if (!tersus.repository.isLoaded(view.id))
		{
			targetElement.innerHTML = 'View '+view.id+' not found';
			tersus.progress.clear();
			return;
		}
		if (! root)
		{
			var constructor = tersus.repository.get(view.id)
			window.currentRootDisplayNode = window.rootDisplayNode = root =  new constructor();
			root.mainWindow = window;
			root.currentWindow = window;
		}
		if (root.preload(tersus.loader.load))
		{
			root.create();
			root.doStart();
			if (window.trace)
				window.trace.flush();
			
			var topNode = root.wrapperNode ? root.wrapperNode : root.viewNode;	
			if (!topNode.parentNode || !topNode.parentNode.tagName)
				targetElement.appendChild(topNode);
			tersus.progress.clear();
			if (!is_touch_device())
				window.setTimeout(function(){window.rootDisplayNode.focusOnFirstField();},0);
			window.setTimeout(function(){$(window).trigger('ter-process-end');},10);
			
		}
	}
	catch (e)
	{
			targetElement.innerHTML = escapeHTML(e.message);
	}
}
tersus.switchView = function(perspective,view,parameters)
{
	if (!perspective && window.perspectives.length > 1)
		perspective = window.perspective.name;
	if (perspective)
		var url = tersus.baseURL+'#Perspective='+encodeURIComponent(perspective)+'&View='+encodeURIComponent(view);
	else
		var url = tersus.baseURL+'#View='+encodeURIComponent(view);
	if (parameters)
		url+='&'+parameters;
	tersus.gotoURL(url, false, true);

};

function openTools()
{
	var w = 250;
	var h = 220;
	var leftPx = window.screenX+window.innerWidth;
	if (leftPx  > screen.availWidth -w -10)
		leftPx = screen.availWidth -w -10;
	if (leftPx<0) leftPx=0;
		
	var topPx = window.screenY;
	var popup = window.open("tools.html","Tools","top="+topPx+",left="+leftPx+"toolbar=no,location=no,status=no,menubar=no,width=" + w + ",height=" + h); 
	popup.focus();
};
function showContent()
{
	var w = window.open("","","");
	w.document.write('<textarea cols="80" rows="50">'+document.getElementById("main.content").innerHTML+"</textarea>");
	setTimeout(function(){w.focus();},0);
};


function removeSuffix(str, separator)
{
	var index = str.indexOf(separator);
	if (index >=0)
		return str.substring(0,index);
	else
		return str;
};
	
// Extract rootURL and baseURL
var fullURL = window.location.href;
tersus.baseURL = removeSuffix(removeSuffix(fullURL,'#'),'?');
tersus.rootURL = tersus.baseURL.substring(0, tersus.baseURL.length-tersus.urlPathSuffix.length+1);
tersus.firstURL = fullURL;


// file: 060-sha256.js
/* A JavaScript implementation of the Secure Hash Algorithm, SHA-256
 * Version 0.3 Copyright Angel Marin 2003-2004 - http://anmar.eu.org/
 * Distributed under the BSD License
 * Some bits taken from Paul Johnston's SHA-1 implementation
 */
var chrsz = 8;  /* bits per input character. 8 - ASCII; 16 - Unicode  */
function safe_add (x, y) {
  var lsw = (x & 0xFFFF) + (y & 0xFFFF);
  var msw = (x >> 16) + (y >> 16) + (lsw >> 16);
  return (msw << 16) | (lsw & 0xFFFF);
}
function S (X, n) {return ( X >>> n ) | (X << (32 - n));}
function R (X, n) {return ( X >>> n );}
function Ch(x, y, z) {return ((x & y) ^ ((~x) & z));}
function Maj(x, y, z) {return ((x & y) ^ (x & z) ^ (y & z));}
function Sigma0256(x) {return (S(x, 2) ^ S(x, 13) ^ S(x, 22));}
function Sigma1256(x) {return (S(x, 6) ^ S(x, 11) ^ S(x, 25));}
function Gamma0256(x) {return (S(x, 7) ^ S(x, 18) ^ R(x, 3));}
function Gamma1256(x) {return (S(x, 17) ^ S(x, 19) ^ R(x, 10));}
function core_sha256 (m, l) {
    var K = new Array(0x428A2F98,0x71374491,0xB5C0FBCF,0xE9B5DBA5,0x3956C25B,0x59F111F1,0x923F82A4,0xAB1C5ED5,0xD807AA98,0x12835B01,0x243185BE,0x550C7DC3,0x72BE5D74,0x80DEB1FE,0x9BDC06A7,0xC19BF174,0xE49B69C1,0xEFBE4786,0xFC19DC6,0x240CA1CC,0x2DE92C6F,0x4A7484AA,0x5CB0A9DC,0x76F988DA,0x983E5152,0xA831C66D,0xB00327C8,0xBF597FC7,0xC6E00BF3,0xD5A79147,0x6CA6351,0x14292967,0x27B70A85,0x2E1B2138,0x4D2C6DFC,0x53380D13,0x650A7354,0x766A0ABB,0x81C2C92E,0x92722C85,0xA2BFE8A1,0xA81A664B,0xC24B8B70,0xC76C51A3,0xD192E819,0xD6990624,0xF40E3585,0x106AA070,0x19A4C116,0x1E376C08,0x2748774C,0x34B0BCB5,0x391C0CB3,0x4ED8AA4A,0x5B9CCA4F,0x682E6FF3,0x748F82EE,0x78A5636F,0x84C87814,0x8CC70208,0x90BEFFFA,0xA4506CEB,0xBEF9A3F7,0xC67178F2);
    var HASH = new Array(0x6A09E667, 0xBB67AE85, 0x3C6EF372, 0xA54FF53A, 0x510E527F, 0x9B05688C, 0x1F83D9AB, 0x5BE0CD19);
    var W = new Array(64);
    var a, b, c, d, e, f, g, h, i, j;
    var T1, T2;
    /* append padding */
    m[l >> 5] |= 0x80 << (24 - l % 32);
    m[((l + 64 >> 9) << 4) + 15] = l;
    for ( var i = 0; i<m.length; i+=16 ) {
        a = HASH[0]; b = HASH[1]; c = HASH[2]; d = HASH[3]; e = HASH[4]; f = HASH[5]; g = HASH[6]; h = HASH[7];
        for ( var j = 0; j<64; j++) {
            if (j < 16) W[j] = m[j + i];
            else W[j] = safe_add(safe_add(safe_add(Gamma1256(W[j - 2]), W[j - 7]), Gamma0256(W[j - 15])), W[j - 16]);
            T1 = safe_add(safe_add(safe_add(safe_add(h, Sigma1256(e)), Ch(e, f, g)), K[j]), W[j]);
            T2 = safe_add(Sigma0256(a), Maj(a, b, c));
            h = g; g = f; f = e; e = safe_add(d, T1); d = c; c = b; b = a; a = safe_add(T1, T2);
        }
        HASH[0] = safe_add(a, HASH[0]); HASH[1] = safe_add(b, HASH[1]); HASH[2] = safe_add(c, HASH[2]); HASH[3] = safe_add(d, HASH[3]); HASH[4] = safe_add(e, HASH[4]); HASH[5] = safe_add(f, HASH[5]); HASH[6] = safe_add(g, HASH[6]); HASH[7] = safe_add(h, HASH[7]);
    }
    return HASH;
}
function str2binb (str) {
  var bin = Array();
  var mask = (1 << chrsz) - 1;
  for(var i = 0; i < str.length * chrsz; i += chrsz)
    bin[i>>5] |= (str.charCodeAt(i / chrsz) & mask) << (24 - i%32);
  return bin;
}
function binb2hex (binarray) {
  var hexcase = 0; /* hex output format. 0 - lowercase; 1 - uppercase */
  var hex_tab = hexcase ? "0123456789ABCDEF" : "0123456789abcdef";
  var str = "";
  for (var i = 0; i < binarray.length * 4; i++) {
    str += hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8+4)) & 0xF) + hex_tab.charAt((binarray[i>>2] >> ((3 - i%4)*8  )) & 0xF);
  }
  return str;
}
function hex_sha256(s){return binb2hex(core_sha256(str2binb(s),s.length * chrsz));}

// file: 062-reload-styles.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.reloadStyles = function()
{
	var linkElement = document.getElementById('main_stylesheet');
	if (linkElement)
	{
		if(window.tersusOriginalStyleURL == null)
			window.tersusOriginalStyleURL = linkElement.href;
		
		linkElement.href=window.tersusOriginalStyleURL+ '&_x=' +(new Date()).getTime();
	}	
}

// file: 073-send-message.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function sendMessage(adapter, message, traceFileName)
{
	var url=tersus.rootURL+'File/'+encodeURIComponent(adapter);
	var req = createXMLHTTPRequest();
	var serviceNode = this;
	req.open('POST', url, true);
	var b = []
	Serializer.prototype._quote(message, b);
	req.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
	var requestBody='Message='+window.encodeURIComponent(b.join(''));
	if (traceFileName)
		requestBody+='&_traceFileName='+window.encodeURIComponent(traceFileName);
	req.send(requestBody);
	
}
// file: 080-transition2.js
tersus.transition2 = function($from, $to, activeClass, fromTransitionClass, toTransitionClass, transitionEndClass,  callback) {
    if ($from && $to && $from[0] == $to[0]) {
        callback();
        return;
    }
    if ($from && $from.length > 0 && $.support.transition) {
        $to.addClass(toTransitionClass).addClass(activeClass);
        $from.addClass(fromTransitionClass);
        $to[0].offsetWidth;// force reflow
        $from[0].offsetWidth;
        $to.one($.support.transition.end, function() {
            $to.removeClass(transitionEndClass+" "+toTransitionClass);
            $from.removeClass(transitionEndClass+" "+fromTransitionClass+" "+activeClass);
            if (callback)
                callback();
        });
        $to.addClass(transitionEndClass);
        $from.addClass(transitionEndClass);
    } else {
        $from.removeClass(activeClass);
        $to.addClass(activeClass);
        if (callback)
            tersus.async.exec(callback);
    }
};
// file: 090-standalone.js
tersus.isNative=true;
tersus.preload = function (packages)
{
	tersus.repository = new ConstructorRepository();
    tersus.repository.packageTexts = packages;
};
tersus.init = function()
{
	window.onunload = tersus.onUnload;
	
	tersus.async.timer = setInterval(tersus.async.worker, tersus.async.interval);
	tersus.keepAliveTimer = setInterval(tersus.keepAlive, tersus.KEEP_ALIVE_INTERVAL);
			
	tersus.createClassNameList();
	window.onresize = tersus.onResize;
	if (tersus.settings.dev_mode)
		tersus.updateCheckInterval = tersus.DEV_UPDATE_CHECK_INTERVAL;
	else
		tersus.updateCheckInterval = tersus.PROD_UPDATE_CHECK_INTERVAL;
};

tersus.checkUpdate = function()
{
};

// file: 100-GenericField.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.GenericField = function tersus_GenericField() {
};
tersus.GenericField.prototype = new DisplayNode();
tersus.GenericField.prototype.constructor = tersus.GenericField;
tersus.GenericField.prototype.currentReadOnly = null;
tersus.GenericField.prototype.value = null;
tersus.GenericField.prototype.isEditable = true;
tersus.GenericField.prototype.inputFieldTag = 'input';
tersus.GenericField.prototype.defaultTag = 'span';
tersus.GenericField.prototype.textTranslation = false;
tersus.GenericField.prototype.emptyOptionText = null;
tersus.GenericField.EMPTY_OPTION_TEXT = '<Empty Option Text>';
tersus.GenericField.prototype.init = function ()
{
	if (this.sharedProperties && tersus.isNumber(this.sharedProperties.maxLength))
    	this.maxLength = this.sharedProperties.maxLength;
};
tersus.GenericField.prototype.addGetter(tersus.GenericField.EMPTY_OPTION_TEXT, function()
{
	return this.emptyOptionText;
});
tersus.GenericField.prototype.updateOptions = function()
{
 	if (this.inputField && this.isChooser)
	{
		this.inputField.innerHTML = '';
		for (var i=0; i<this.options.length; i++)
		{
			var option = this.options[i];
			this.addOptionElement(option, i);
		}		
	}
 }
tersus.GenericField.prototype.addRemover(tersus.GenericField.EMPTY_OPTION_TEXT, function()
{
	if (this.emptyOptionText != null)
	{
		if (this.options)
			this.options.splice(0,1);//remove null from beginning of list
		this.emptyOptionText = null;
		this.updateOptions();
	}
});
tersus.GenericField.prototype.addSetter(tersus.GenericField.EMPTY_OPTION_TEXT,function(text)
{
	if (this.emptyOptionText == null)
	{
		if (this.options)
			this.options.splice(0,0,null); // add null to beginning of list
		else
			this.options = [null];
	}
	this.emptyOptionText = text;
	this.updateOptions();
});
tersus.GenericField.prototype.addGetter('<Max Length>', function()
{
	return this.maxLength;
});
tersus.GenericField.prototype.addSetter('<Max Length>', function(length)
{
	this.maxLength = length;
	if (this.inputField)
		this.inputField.maxLength = this.maxLength;
	// Reset value in order to truncate if needed
	this.setFieldValue(this.getFieldValue());
	
});
tersus.GenericField.prototype.reformat = function()
{
	this.setValueString();
};
tersus.GenericField.prototype.formatProperties = {
	currencySymbol:'<Currency Symbol>',
	currencyPosition:'<Currency Position>',
	useThousandsSeparator:'<Use Thousands Separator>',
	decimalPlaces:'<Decimal Places>'
};
tersus.GenericField.prototype.createFormatProps = function()
{
	this.formatProps = {};
	for (var p in this.formatProperties)
	{
		this.formatProps[p]=this.sprop(p);
	}	
};

tersus.GenericField.addFormatAccessor  = function (pt, prop, elementName)
{
	pt.addSetter(elementName, function(v)
	{
		if (! this.formatProps)
			this.createFormatProps();
		this.formatProps[prop] = v;	
		this.reformat();
	});
	pt.addGetter(elementName, function()
	{
		if (this.formatProps)
			return this.formatProps[prop];
		else
			return this.sprop(prop);
	});
};
for (var p in tersus.GenericField.prototype.formatProperties)
{
	tersus.GenericField.addFormatAccessor(tersus.GenericField.prototype, p,tersus.GenericField.prototype.formatProperties[p] );
};

tersus.GenericField.prototype.onClick  = function (domNode, callback)
{
	if (domNode == this.browseButton)
		this.queueEvent(Events.ON_BROWSE, null, null, callback);
	else if (this.currentReadOnly) 
		DisplayNode.prototype.onClick.call(this,domNode, callback);
	if (this.hyperlink)
		tersus.preventDefaultEventHandling();
};
tersus.GenericField.prototype['remove<Value>'] = function removeValue()
{
	this.value = null;
	if (this.viewNode)
	{
		if (this.inputField)
		{
			if (this.isChooser)
			{
				this.setSelectedIndex(0);
				if (this.options.length>0)
					this.value = this.options[0];
			}
			else
				this.inputField.value = '';
		}
		else if (this.hyperlink)
			this.hyperlink.innerHTML='';
		else
			this.viewNode.innerHTML = '';
		
	}
};

tersus.GenericField.prototype.updateSelfReadOnly = function tersus_GenericField_updateSelfReadOnly(readOnly)
{
	if (this.currentReadOnly == readOnly)
		return; // no change
	this.currentReadOnly = readOnly;
	if (this.inputField)
	{
		/* When we switch to read only mode, we get the current value from the input field, with the exception
		  of a chooser whose value doesn't match the options (selectedIndex<0) */
		var update = true;
		if (this.isChooser)
		{
			if (this.tmpSelectedIndex != null)
				update = this.tmpSelectedIndex != -1; // IE workaround
			else
				update = this.inputField.selectedIndex != -1;
		} 
   		if (update)
       		this.value = this.getFieldValue();
    }
	if (this.viewNode)
	{
		this.viewNode.innerHTML = '';
		if (readOnly)
		{
			if (this.hasEventHandler(Events.ON_CLICK))
				this.initLink()
			else
				this.initDisplay()
		}
		else
			this.initWritable();
	}
	this.setValueString();
};

tersus.GenericField.prototype.createViewNode = function tersus_GenericField_createViewNode()
{
	if (this.setDefaultProperties)
		this.setDefaultProperties();
	
    if (this.sharedProperties.inputFieldTag && this.sharedProperties.inputFieldTag != ' ')
    	this.inputFieldTag = this.sharedProperties.inputFieldTag;
    var optionsElement = this.getElement('<Options>');
    if (optionsElement)
    {
    	this.optionsElement = optionsElement;
    	this.isChooser = true;
    	this.options = [];
    	this.inputFieldTag = 'select';
    }
    DisplayNode.prototype.createViewNode.call(this);
};
tersus.GenericField.prototype.initViewNode = function tersus_GenericField_initViewNode()
{
    DisplayNode.prototype.initViewNode.call(this);
    this.updateSelfReadOnly(this.computedReadOnly());
   	if (this.hasEventHandler(Events.ON_CLICK))
   		this.registerEventHandler(Events.ON_CLICK,this.viewNode);
    
};
tersus.GenericField.prototype.attachHTMLNode = function (e)
{
	this.viewNode = e;
	if (e.firstChild && e.firstChild.tagName == 'INPUT')
		this.inputField = e.firstChild;
   	this.registerEventHandler(Events.ON_CHANGE,this.inputField);
	this.registerEventHandler(Events.ON_FOCUS,this.inputField);
   	if (this.hasEventHandler(Events.ON_BLUR))
	   	this.registerEventHandler(Events.ON_BLUR,this.inputField);
   	if (this.hasEventHandler(Events.ON_KEYPRESS))
	   	this.registerEventHandler(Events.ON_KEYPRESS,this.inputField);
   	if (this.hasEventHandler(Events.ON_KEYDOWN))
	   	this.registerEventHandler(Events.ON_KEYDOWN,this.inputField);
   	if (this.hasEventHandler(Events.ON_KEYUP))
	   	this.registerEventHandler(Events.ON_KEYUP,this.inputField);
   	if (this.hasEventHandler(Events.ON_CLICK))
	   	this.registerEventHandler(Events.ON_CLICK,this.hyperlink);
		
}

tersus.GenericField.prototype.setViewNode = function tersus_GenericField_setViewNode(viewNode)
{
	if (viewNode.tagName == 'INPUT')
	{	
		this.viewNode = this.createHTMLElement(this.getTag());
		viewNode.parentNode.replaceChild(this.viewNode, viewNode);
		this.viewNode.appendChild(viewNode);
		this.inputField = viewNode;
	}
	else
		this.viewNode = viewNode;
};
tersus.GenericField.nodesToAdjust = [];
tersus.GenericField.prototype.disabled = false;
tersus.GenericField.prototype.initWritable = function tersus_GenericField_initWritable()
{
	tersus.removeEventHandlers(this.viewNode);
    this.inputField = this.createHTMLElement(this.inputFieldTag);
    if (!this.isEditable)
    {
    	this.inputField.readOnly = true;
    }
    this.inputField.disabled = this.disabled;
    this.hyperlink = null;
    if (! this.isChooser && tersus.isNumber(this.sharedProperties.size))
    	this.inputField.size = this.sharedProperties.size;
    if (this.maxLength != null)
    	this.inputField.maxLength = this.maxLength;
    if (this.sharedProperties.width != undefined && this.sharedProperties.width != ' ')
    	this.inputField.style.width = this.sharedProperties.width;
    if (this.sharedProperties.styleClass && this.sharedProperties.styleClass != ' ')
	    this.inputField.className = this.sharedProperties.styleClass;
    if (this.sharedProperties.height && this.sharedProperties.height != ' ')
	    this.inputField.style.height = this.sharedProperties.height;
    var rows = this.sharedProperties.numberOfRows;
	if (rows && tersus.isNumber(rows))
		this.inputField.rows = parseInt(rows);
	var cols = this.sharedProperties.numberOfColumns;
	if (cols && tersus.isNumber(cols))
		this.inputField.cols = cols;
	if (this.isChooser)
	{	
		this.inputField.setAttribute('data-role','none');
		for (var i=0; i<this.options.length; i++)
		{
			var option = this.options[i];
			this.addOptionElement(option, i);
		}
		if (this.sharedProperties.size && this.sharedProperties.size != ' ')
			this.inputField.style.width = (2.5+0.57*this.sharedProperties.size) + "em"; // Trying to emulate the 'size' property of text input
		else if (this.sharedProperties.width && this.sharedProperties.width != ' ')
			this.inputField.style.width = this.sharedProperties.width;
			
	};
    	
    this.viewNode.innerHTML = '';
    this.viewNode.appendChild(this.inputField);
    if (this.hasEventHandler(Events.ON_BROWSE))
    {
	    this.viewNode.style.whiteSpace='nowrap';
		this.viewNode.style.position='relative';
    	this.inputField.className = 'pf_txt';

    	this.browseButton = this.createHTMLElement('button','pf_browse');
    	this.browseButton.innerHTML = '<img src="images/spacer.gif"/>';
	    this.browseButton.type='button';
    	this.browseButton.id = this.getNodeId();
    	this.registerEventHandler(Events.ON_CLICK, this.browseButton);
	    this.viewNode.appendChild(this.browseButton);
	    var adjustList = tersus.GenericField.nodesToAdjust;
	    if (adjustList.length == 0)
		    setTimeout(tersus.GenericField.adjustPositions,10);
		adjustList.push(this);
	    //Adjust the position of the button based on the input field
    }
    this.inputField.setAttribute('node_id',this.getNodeId());
   	this.registerEventHandler(Events.ON_CHANGE,this.inputField);
	this.registerEventHandler(Events.ON_FOCUS,this.inputField);
   	if (this.hasEventHandler(Events.ON_BLUR))
	   	this.registerEventHandler(Events.ON_BLUR,this.inputField);
   	if (this.hasEventHandler(Events.ON_KEYPRESS))
	   	this.registerEventHandler(Events.ON_KEYPRESS,this.inputField);
   	if (this.hasEventHandler(Events.ON_KEYDOWN))
	   	this.registerEventHandler(Events.ON_KEYDOWN,this.inputField);
   	if (this.hasEventHandler(Events.ON_KEYUP))
	   	this.registerEventHandler(Events.ON_KEYUP,this.inputField);
};

tersus.GenericField.prototype.onChange = function(domNode, callback)
{
	this.validateFieldValue();
	DisplayNode.prototype.onChange.call(this, domNode, callback);
};
tersus.GenericField.prototype.onResize = function()
{
	if (this.browseButton)
	{
	    var adjustList = tersus.GenericField.nodesToAdjust;
	    this.browseButton.style.top='';
	    this.browseButton.style.left='';
	    if (adjustList.length == 0)
		    setTimeout(tersus.GenericField.adjustPositions,10);
		adjustList.push(this);
	}
};
tersus.GenericField.adjustPositions = function()
{
	var list = tersus.GenericField.nodesToAdjust;
	tersus.GenericField.nodesToAdjust = [];
	for (var i=0; i<list.length; i++)
	{
		var node = list[i];
		node.adjustPosition();
	}
};
/**
 * adjustPosition: align the browse button with the input field
 */
tersus.GenericField.prototype.adjustPosition = function()
{
	if (!this.inputField)
		return; // The field may have become read-only 
	var direction = getActualStyle(this.inputField,'direction');
	var $b = $(this.browseButton);
	var $i= $(this.inputField);
	$b.height($i.innerHeight()).css('left','0px').css('top','0px');
	var inputOffset = getOffsets(this.inputField);
	var inputTop=inputOffset.top;
	var buttonOffset = getOffsets(this.browseButton);
	var buttonTop = buttonOffset.top;
	var deltaTop = inputTop - buttonTop;
	this.browseButton.style.top = deltaTop+'px';
	if (direction == 'rtl')
	{
		var inputLeft = inputOffset.left;
		var buttonRight = buttonOffset.left + this.browseButton.offsetWidth-2; 	
		var deltaLeft = inputLeft - buttonRight;
		this.browseButton.style.borderRightWidth='0';
		this.browseButton.style.borderLeftWidth='2px';
		
	}
	else
	{
		var inputRight=inputOffset.left+this.inputField.offsetWidth -2; //Don't know why, but we need to substract 2
		var buttonLeft = buttonOffset.left;
		var deltaLeft = inputRight - buttonLeft;
		this.browseButton.style.borderRightWidth='2px';
		this.browseButton.style.borderLeftWidth='0px';
	}
	this.browseButton.style.left = deltaLeft+'px';
};
tersus.GenericField.prototype.getDefaultContent = function()
{
	return '';
};
tersus.GenericField.prototype.initLink = function tersus_GenericField_initLink()
{
	if (this.inputField)
		this.value = this.getFieldValue();
    this.inputField = null
    this.browseButton = null;
    this.hyperlink = this.createHTMLElement('a');
    var id = this.getNodeId();
    this.hyperlink.href='';
   	this.hyperlink.innerHTML = this.getDefaultContent();
    this.viewNode.appendChild(this.hyperlink);
};
tersus.GenericField.prototype.initDisplay = function tersus_GenericField_initDisplay()
{
	this.hyperlink = null;
	this.inputField = null;
	this.browseButton = null;
	DisplayNode.prototype.setEventHandlers.call(this);
};
tersus.GenericField.prototype.getFieldValue = tersus.GenericField.prototype['get<Value>'] = function tersus_GenericField_getFieldValue()
{
	if (this.inputField)
	{	
		if (this.isChooser)
			this.value = this.getSelectedOption();
		else
		{
			var valueElement = this.getElement('<Value>');
			var valuePrototype = valueElement.getChildConstructor().prototype;
			this.value = valuePrototype.parseInput(this.inputField.value, this.formatProps ? this.formatProps : this.sharedProperties);
		}
	}
	return this.value;
};
tersus.GenericField.prototype.setFieldValue = tersus.GenericField.prototype['set<Value>'] = function tersus_GenericField_setFieldValue(value)
{
	this.value = value;
	// Truncate to maxLength if needed (only if this is a text field)
	if (this.maxLength && value && value.isText && value.leafValue && value.leafValue.length > this.maxLength)
	{
		this.value = new value.constructor();
		this.value.leafValue =  value.leafValue.substring(0,this.maxLength); 
	}

	if (this.isChooser && ! this.currentReadOnly)
		this.setSelectedIndex(this.findIndex(this.value));
	else
		this.setValueString();
};
tersus.GenericField.prototype.setValueString = function()
{
	this.valueStr = '';
	if (this.value != null)
	{
		if (this.isChooser)
			this.valueStr = this.getOptionText(this.value);
		else if (this.inputField)
			this.valueStr = this.value.formatInput(this.formatProps ? this.formatProps : this.sharedProperties);
		else
			this.valueStr = this.value.formatString(this.formatProps ? this.formatProps : this.sharedProperties);
	}
	if (this.inputField) 
	{
		if (!this.isChooser) // For chooser we've already set the selected index
			this.inputField.value = this.valueStr;
	}
	else if (this.hyperlink)
		this.hyperlink.innerHTML = this.escapeHTML(this.translate(this.valueStr));
	else if (this.viewNode)
		this.viewNode.innerHTML =  this.escapeHTML(this.translate(this.valueStr));
};
tersus.GenericField.prototype.setValueStringOpt = function()
{
	this.valueStr = '';
	if (this.value != null)
	{
		if (this.isChooser)
			this.valueStr = this.getOptionText(this.value);
		else if (this.optimizeFormatString)
			this.valueStr = this.value.leafValue;
		else if (this.inputField && this.valueFormatInput)
			this.valueStr = this.value.formatInput(this.sharedProperties);
		else if (this.value.formatString)
			this.valueStr = this.value.formatString(this.sharedProperties);
		else
			this.valueStr = this.value.toString();
	}
	if (this.inputField)
	{
		this.inputField.value = this.valueStr;
	}
	else if (this.hyperlink)
		this.hyperlink.innerHTML = this.escapeHTML(this.translate(this.valueStr));
	else if (this.viewNode)
		this.viewNode.innerHTML =  this.escapeHTML(this.translate(this.valueStr));
};
tersus.GenericField.prototype.setFieldValue.requiresNodes = true;
tersus.GenericField.prototype.validateFieldValue = function()
{
	var valueElement = this.getElement('<Value>');
	var valuePrototype = valueElement.getChildConstructor().prototype;
	if (valuePrototype.validateInput)
	{
		var errorMessage =  valuePrototype.validateInput(this.inputField.value, this.formatProps ? this.formatProps : this.sharedProperties);
		this.setValidationMessage(errorMessage);
	}
};
tersus.GenericField.prototype.setEventHandlers = function ()
{
};
tersus.GenericField.prototype.showValidationMessage = function (message)
{
	var targetNode = this.viewNode;
	if (this.inputField)
		targetNode = this.inputField;
	this.currentWindow.alert(message);
	if (targetNode.focus && !targetNode.disabled)
		targetNode.focus();
	if (targetNode.select)
		targetNode.select();
};

tersus.GenericField.prototype.tmpSelectedIndex = null;
tersus.GenericField.prototype.getSelectedOption  = function tersus_GenericField_getSelectedOption()
{
	var selectedIndex;
	if (this.tmpSelectedIndex != null) // In IE, the selected index is updated asynchronously, so we use tmpSelectedIndex if it is set
		selectedIndex = this.tmpSelectedIndex;
	else
		selectedIndex = this.inputField.selectedIndex;
	if (selectedIndex < 0)
		return null;
	return this.options[selectedIndex];
};

tersus.GenericField.prototype.setSelectedIndex = function tersus_GenericField_setSelectedIndex(selectedIndex)
{
	if (!this.inputField)
		return;
	if (window.browser == 'IE') // IE needs a delay in order to recognize any newly added option/s
	{
		var inputField = this.inputField;
		var node = this;
		this.tmpSelectedIndex = selectedIndex;
		setTimeout(function(){	
		inputField.selectedIndex = selectedIndex;
		node.tmpSelectedIndex = null;}
		, 10);
	}
	else
		this.inputField.selectedIndex = selectedIndex;
};

tersus.GenericField.prototype.getOptions = tersus.GenericField.prototype['get<Options>'] = function tersus_GenericField_getOptions()
{
	if ( !this.options)
		return [];
	if (this.emptyOptionText != null)
	{
		return this.options.slice(1); // Ignoring the first item in the array, which is the empty option (null)
	}
	return this.options;
};
tersus.GenericField.prototype.reset = function()
{
	/* For choosers, the basic behavior sometimes leaves the value set as follows:
	 * When <Empty Option Text> is removed, the empty option is removed as the first on the list of options
	 * Then, clearing <Value> sets it as the first option
	 */ 
	DisplayNode.prototype.reset.call(this);
	this.value = null;
};
tersus.GenericField.prototype.addOption = tersus.GenericField.prototype['add<Options>'] = function tersus_GenericField_addOption(value)
{
	if (! this.options)
		this.options = [];
	this.options.push(value);
	if (this.inputField)
	{
		this.addOptionElement(value, this.options.length -1 );
	}
};
tersus.GenericField.prototype.addOptionElement = function tersus_GenericField_addOptionElement(value, index)
{
	var optionNode = this.createHTMLElement('option');
	optionNode.innerHTML = this.translate(tersus.escapeHTML(this.getOptionText(value)));
	this.inputField.appendChild(optionNode);
	/* Check if the new option matches the value (which may have been set previously)
	 In case of a match, select the new option */
	if (this.value != null &&  compareValues(this.value, value))
		this.setSelectedIndex(index);
};
tersus.GenericField.prototype.deepCopy = function deepCopy(value)
{
	var selectedIndex = null;
	this.emptyOptionText = value.getLeafChild(tersus.GenericField.EMPTY_OPTION_TEXT);
	this.options = this.emptyOptionText == null ? [] : [null];

	for (var elementRole in value.elements)
	{
		if (elementRole == tersus.GenericField.EMPTY_OPTION_TEXT)
			continue;
		var element = this.getElement(elementRole);
		if (element)
		{
			if (element.isRepetitive)
			{
				var childValues = value.getChildren(elementRole);
				if (elementRole == '<Options>') // Special optimization - setting the options of a large chooser as one chunk of HTML
				{
					var html = [];
					if (this.emptyOptionText != null)
					{
						html.push('<OPTION>');
						html.push(tersus.escapeHTML(this.translate(this.emptyOptionText)));
						html.push('</OPTION>');
					}
					if (childValues.length > 0)
					{
						var optimize_get_text = false;
						var optionText;
						var v0 = childValues[0];
						this.getOptionText(v0);
						var textElement = v0.__textElement;
						if (textElement && textElement.modelId == BuiltinModels.TEXT_ID && ! this.textTranslation)
							optimize_get_text = true;
						for (var i=0; i<childValues.length;i++)
						{
							var v = childValues[i];
							this.options.push(v);
							if (this.inputField)
							{
								var optionText = '';
								html.push('<OPTION>');
								if (optimize_get_text)
								{
									var c = v.children;
									if (c)
									{
										var tr = v.__textElementRole;
										if (tr)
										{
											var tn = c[tr];
											if (tn)
												optionText =this.escapeHTML(tn.leafValue); // Can be further optimized by checking in advance if escapeHTML is required
										}
										else
											optionText = this.escapeHTML(this.getOptionText(v)); // No text element found - reverting to un-optimized
									}
									html.push(optionText);
								}
								else
									html.push(tersus.escapeHTML(this.translate(this.getOptionText(v))));
								html.push('</OPTION>');
								if (this.value != null &&  compareValues(this.value, v))
								{
									selectedIndex = this.options.length-1; // Takes care of emptyOptionText as well
								}
							}
						}
						if (this.inputField)
						{
							var f=this.inputField;
							if (window.browser == 'IE')
							{
								// Don't remember why, but we need to re-recreate the input field in IE
								var oh = f.outerHTML;
								var p = f.parentNode;
								var ps = f.previousSibling;
								var endTag = '</SELECT>';
								f.outerHTML = oh.substring(0,oh.length-endTag.length) + html.join('') + endTag;
								if (ps)
									this.inputField = ps.nextSibling;
								else
									this.inputField = p.firstChild;
								this.attachHTMLNode(this.viewNode); // re-registers event handlers, which are lost when the input field is re-recreated.					

							}
							else
								f.innerHTML = html.join('');
						}
					}
					if (this.inputField && selectedIndex != null)
						this.setSelectedIndex(selectedIndex);
					
				}
				else
					element.setChildren(this, childValues, Operation.REPLACE);
			}
			else
			{
				var childValue = value.getChild(elementRole);
				if (childValue != null)
				{
					element.replaceChild(this, childValue);
				}
			}
		}
	}
	
};

tersus.GenericField.prototype.addOption.requiresNodes = true;
tersus.GenericField.prototype.removeOptions = tersus.GenericField.prototype['remove<Options>'] = function tersus_GenericField_removeOptions()
{
	if (this.emptyOptionText != null)
		this.options=[null];
	else
		this.options = [];
	this.updateOptions();
};

tersus.GenericField.prototype.findIndex = function tersus_GenericField_findIndex(value)
{
	if (this.options)
		for (var i=0; i<this.options.length; i++)
		{
			var option = this.options[i];
			if (compareValues(option, value))
				return i;
		}
	return -1;
};
tersus.GenericField.prototype.getOptionText = function tersus_GenericField_getOptionText(value)
{
	var outputValue = null;
	if (value && value.elementList)
	{
		var textElementRole = value.__textElementRole;
		if (textElementRole == null)
		{
			for (var i=0; i< value.elementList.length; i++)
			{
				var element = value.elementList[i];
				if (i==0)
				{
					textElementRole = element.role; // If no text element is found, the first element is used
					value.constructor.prototype.__textElement = element;
				}
				if (element.modelId == BuiltinModels.TEXT_ID)
				{
					textElementRole = element.role;
					value.constructor.prototype.__textElement = element;
					break;
				}
			}
		value.constructor.prototype.__textElementRole = textElementRole;
		}
		if (textElementRole && value.children)
			outputValue = value.children[textElementRole];
	}
	else
		outputValue = value;
	var text = '';
	if (outputValue != null)
		text =  outputValue.formatString(this.sharedProperties);
	else if (this.emptyOptionText != null)
		text = this.emptyOptionText;
	return text;
};
tersus.GenericField.prototype['get<Disabled>'] = function ()
{
	return this.disabled;
};

tersus.GenericField.prototype['set<Disabled>'] = function (disabled)
{
	this.disabled = disabled?true:false;
	if (this.inputField)
	{
		this.inputField.disabled=this.disabled;
	}
};
tersus.GenericField.prototype.getClickTarget = function()
{
	if (this.inputField)
		return this.inputField;
	else if (this.hyperlink)
		return this.hyperlink;
	else
		return this.viewNode;
};
tersus.GenericField.prototype.focus = function()
{
	if (this.inputField)
		this.inputField.focus();
	else if (this.viewNode.focus)
		this.viewNode.focus();
};
TextInputField = NumberInputField = tersus.GenericField; //backward compatability

// file: 101-DisplayField.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.DisplayField = function tersus_DisplayField() {};
tersus.DisplayField.prototype = new tersus.GenericField();
tersus.DisplayField.prototype.constructor = tersus.DisplayField;
tersus.DisplayField.prototype.explicitReadOnly = true;
TextDisplay = NumberDisplay = DateDisplay = tersus.DisplayField; // backward compatability

// file: 102-HTMLTag.js
/*********************************************************************************************************
 * Copyright (c) 2003-2010 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/

var SPECIAL_HTML_ATTRIBUTES='marquee.direction,marquee.scrollamount,marquee.loop';
var HTML_ATTRIBUTES = 'abbr,accept,accept-charset,accesskey,action,align,alink,alt,archive,autoplay,axis,background,bgcolor,border,cellpadding,cellspacing,char,charoff,charset,checked,cite,class,classid,clear,code,codebase,codetype,color,cols,colspan,compact,content,contenteditable,controls,coords,data,datetime,declare,defer,dir,disabled,enctype,face,for,frame,frameborder,headers,height,href,hreflang,hspace,http-equiv,id,ismap,label,lang,language,link,longdesc,marginheight,marginwidth,maxlength,media,method,multiple,name,nohref,noresize,noshade,nowrap,object,onblur,onchange,onclick,ondblclick,onfocus,onkeydown,onkeypress,onkeyup,onload,onmousedown,onmousemove,onmouseout,onmouseover,onmouseup,onreset,onselect,onsubmit,onunload,profile,prompt,readonly,rel,rev,rows,rowspan,rules,scheme,scope,scrolling,selected,shape,size,span,src,standby,start,style,summary,tabindex,target,text,title,type,usemap,valign,value,valuetype,version,vlink,vspace,width,pattern,required,placeholder,autocorrect,autocapitalize';
var STYLE_ATTRIBUTES = 'azimuth,background,background-attachment,background-color,background-image,background-position,background-repeat,border,border-collapse,border-color,border-spacing,border-style,border-top,border-right,border-bottom,border-left,border-top-color,border-right-color,border-bottom-color,border-left-color,border-top-style,border-right-style,border-bottom-style,border-left-style,border-top-width,border-right-width,border-bottom-width,border-left-width,border-width,bottom,caption-side,clear,clip,color,content,counter-increment,counter-reset,cue,cue-after,cue-before,cursor,direction,display,elevation,empty-cells,float,font,font-family,font-size,font-size-adjust,font-stretch,font-style,font-variant,font-weight,height,left,letter-spacing,line-height,list-style,list-style-image,list-style-position,list-style-type,margin,margin-top,margin-right,margin-bottom,margin-left,marker-offset,marks,max-height,max-width,min-height,min-width,orphans,outline,outline-color,outline-style,outline-width,overflow,padding,padding-top,padding-right,padding-bottom,padding-left,page,page-break-after,page-break-before,page-break-inside,pause,pause-after,pause-before,pitch,pitch-range,play-during,position,quotes,richness,right,size,speak,speak-header,speak-numeral,speak-punctuation,speech-rate,stress,table-layout,text-align,text-decoration,text-indent,text-shadow,text-transform,top,unicode-bidi,vertical-align,visibility,voice-family,volume,white-space,widows,width,word-spacing,z-index';
tersus.HTML_ATTRIBUTES = new Set(HTML_ATTRIBUTES.split(','));
tersus.SPECIAL_HTML_ATTRIBUTES = new Set(SPECIAL_HTML_ATTRIBUTES.split(','));
var BOOLEAN_HTML_ATTRIBUTES = 'readonly,disabled,checked,autoplay,controls,required,selected';
tersus.BOOLEAN_HTML_ATTRIBUTES = new Set(BOOLEAN_HTML_ATTRIBUTES.split(','));
tersus.STYLE_ATTRIBUTES = new Set(STYLE_ATTRIBUTES.split(','));
tersus.HTMLTag = DisplayNode.__subclass('tersus.HTMLTag', function(){});
tersus.HTMLTag.prototype.isHTMLTag = true;
tersus.propertyConversionMap = { 
	styleclass:'class',
	'style class':'class',
	wrappertag:'wrapperTags',
	wrappertags:'wrapperTags',
	wrapper_tags:'wrapperTags',
	wrapperstyleclass:'wrapperStyleClasses',
	wrapperstyleclasses:'wrapperStyleClasses',
	wrapper_classes:'wrapperStyleClasses',
	path:'src',
	icon:'data-icon',
	theme:'data-theme',
	inset:'data-inset'
};


tersus.HTMLTag.prototype.isHTMLTag = true;
tersus.convertProperty = function(p)
{
	var l = p.toLowerCase(); 
	var c = tersus.propertyConversionMap[l];
	return c ? c: l;
};
DisplayElement.prototype.isHTMLPrepared = false;
DisplayElement.prototype.prepareForHTML = function(parent)
{
	if (this.isHTMLPrepared)
		return;
	this.isHTMLPrepared = true;
	var childPrototype = this.getChildConstructor().prototype;
	if (!childPrototype || ! (childPrototype.isHTMLTag || childPrototype.isGroup ))
		return;
	this.prepHTML = childPrototype.prepareForHTML(this,parent);
	childPrototype.prepareChildrenForHTML();
};
DisplayNode.prototype.prepareChildrenForHTML = function()
{
	if (this.displayElements)
	{
		for (var i=0;i<this.displayElements.length;i++)
		{
			var e = this.displayElements[i];
			if (e.prepareForHTML)
				e.prepareForHTML(this);
		}
	}
};
tersus.HTMLTag.prototype.updateVisible = function()
{
	this.visible = !(this.getLeafChild('<Visible>') == false);
};
tersus.template = function(template, data)
{
	if (!tersus.templates)
		tersus.templates = {};
	if (!tersus.templates[template])
		tersus.templates[template]=$.template(template);
	return tersus.templates[template]($,{'data':data}).join('');
};
DisplayNode.prototype.prepareForHTML = function(e,parent)
{
	var props = {};
	var prep = {};
	if (!this.isHTMLTag)
		return prep;
	prep.updateVisible = parent && parent.isGroup || this.getElement('<Visible>'); //No need to update if parent is not a group and no <Visible>
	props.wrapperTags = this.defaultWrapperTags;
	props.wrapperStyleClasses = this.defaultWrapperStyleClasses;
	$.extend(props,this.baseProperties);
	props['class'] = this.defaultClass;
	props['type']=this.inputType; // For input fields
	props.tag = this.defaultTag;
	if (this.contentTag)
	{
		prep.contentPrefix = tersus.template('<${tag}{{if cls}} class="${cls}"{{/if}}>',{tag:this.contentTag,cls:this.contentClass});
		prep.contentSuffix = '</'+this.contentTag+'>';
	}
	for (var p in this.sharedProperties)
	{
		var v = this.sharedProperties[p];
		if (v != null && v != ' ')
			props[tersus.convertProperty(p)]=v;
	} 
	if (e)
	{
		for (var p in e.properties)
		{
			var v = e.properties[p];
			if (v != null && v != ' ')
				props[tersus.convertProperty(p)]=v;
		}
	}
	if (props.wrapperTags == '-')
		props.wrapperTags = null;
	if (props.wrapperStyleClasses == '-')
		props.wrapperStyleClasses = null; 
	prep.staticStyle = '';
	var html = '';
	for (var p in props)
	{
		var v = props[p];
		var dynamicElement =  this.dynamicAttributeElements[p];
		if (dynamicElement)
		{
			//Prepare default value
			if (prep.defaultValues == null)
				prep.defaultValues = {};
			prep.defaultValues[dynamicElement.role]=v;
		}
		else
		{
			//Parepare static value
			if (tersus.SPECIAL_HTML_ATTRIBUTES.contains(props.tag+'.'+p))
				html += ' ' + p + '="' +v+'"';
			else if (tersus.STYLE_ATTRIBUTES.contains(p))
				prep.staticStyle += p + ':' + v+';';
			else if (tersus.BOOLEAN_HTML_ATTRIBUTES.contains(p))
			{
				if (v)
					html+= " " + p;	
			}
			else if (p.match(/^data-/) || tersus.HTML_ATTRIBUTES.contains(p) && v != undefined)
				html += " " + p +'="'+tersus.escapeHTML(v)+'"'; 	
		}
	}
	if (e && e.displayOrder)
	{
		html+= ' display_order="'+e.displayOrder+'"';
	}
	prep.tag = props.tag.toUpperCase();
	prep.isInput = prep.tag == 'INPUT' || prep.tag == 'TEXTAREA';
	prep.HTMLPrefix = '';
	prep.HTMLSuffix = '';
	prep.wrapperTags = null;
	if (props.wrapperTags)
	{
		var tags = prep.wrapperTags = props.wrapperTags.split(',');
		if (tags.length > 0)
			prep.wrapper_tag = tags[0];
		var classes = [];
		if (props.wrapperStyleClasses)
		{
			classes = props.wrapperStyleClasses.split(',');
		}
		
		for (var i=0;i<tags.length;i++)
		{
			var t = tags[i];
			var c = null;
			if (i< classes.length)
				c = classes[i];
			if (c)
				prep.HTMLPrefix += '<'+t+' class="'+c+'">';
			else
				prep.HTMLPrefix += '<'+t+'>';
			prep.HTMLSuffix = '</'+t+'>'+prep.HTMLSuffix;
		}
	}
	prep.HTMLPrefix += '<'+prep.tag + html;
	if (prep.staticStyle.length>0 && this.styleAttributeElements.length ==0)
		prep.HTMLPrefix += ' style="'+prep.staticStyle+'"';
	prep.HTMLPrefix += ' lid="';
	prep.HTMLSuffix = '</'+prep.tag+'>'+prep.HTMLSuffix;
	prep.simpleHTML = this.HTMLAttributeElements.length == 0 && this.styleAttributeElements.length ==0 && !prep.updateVisible;
	return prep;
};
 
tersus.HTMLTag.prototype.reset = function()
{
	this.removeAll();
	this.create();
};
tersus.HTMLTag.prototype.create = tersus.HTMLTag.prototype.copyValue = function(value)
{

	var oldViewNode = this.viewNode; // Shouldn't we care about "old wrapper node"
	this.viewNode = null; // Clear view node so that attribute values are set logically during the copy phase (and not placed on DOM nodes)
	if (this.element && !this.element.isHTMLPrepared)
		this.element.prepareForHTML(this.parent);
	var nodeMap = {};
	var htmlV = [];
	var legacyNodes = []; // nodes that are not instances of HTMLTag and need to be copied the old way
	this.copyValueOpt(value, nodeMap, htmlV, legacyNodes);
	var html = htmlV.join('');
	
	var domNode =$(html, this.currentWindow.document)[0];
	var prev = this.wrapperNode ? this.wrapperNode: oldViewNode; // TODO (x) use placeHolderNode;
	this.viewNode = domNode;
	var wt = this.prep.wrapperTags;
	this.wrapperNode = this.viewNode;
	if (wt)
	{
		for (var i=0;i<wt.length;i++)
			this.viewNode = this.viewNode.firstChild;
	}
	this.textContainer = this.viewNode;
	if (prev)
		this.replaceDomNode(domNode,prev);
	else
		this.attachViewNode();
	this.setEventHandlers();
	this.postAttach();
	this.attachHierarchy(nodeMap);
	for (var i=0;i<legacyNodes.length;i++)
	{
		var n = legacyNodes[i];
		n.create(n.valueToCopy);
		n.valueToCopy = null;
	}
	var t = this;
	tersus.async.exec(function(){t.onResize();},false);
};
tersus.HTMLTag.prototype.replaceDomNode = function(newNode, prevNode)
{
	prevNode.parentNode.replaceChild(newNode, prevNode);
};
tersus.HTMLTag.prototype.initModel = function()
{
	this.dynamicAttributeElements = {};
	this.HTMLAttributeElements = [];
	this.styleAttributeElements = [];
}
tersus.HTMLTag.prototype.onload = function()
{
	DisplayNode.prototype.onload.call(this);
	this.createEventHandlerList();
};
DisplayNode.prototype.copyValueOpt = function(value, nodeMap, htmlV, legacyNodes)
{
	var prep;
	if (this.element && this.element.prepHTML)
	{
		prep = this.prep = this.element.prepHTML;
	}
	else
	{
		if (!this.prepHTML)
		{
			{
				var prototype = this.getPrototype();
				prototype.prepHTML = prototype.prepareForHTML(null);
				prototype.prepareChildrenForHTML();
			}
		}
		prep = this.prep = this.prepHTML;
	}
	// Copy default values into instance
	var def = prep.defaultValues;
	if (def != null)
	{
		for (var role in def)
		{
			this.setLeafChild(role, def[role], Operation.REPLACE);
		}
	}
	if (value != null)
		this.leafValue = value.leafValue;
	else 
		this.leafValue = null;
	if (!this.isGroup)
	{
		htmlV.push(null); // placeHolder for tag opening; we can't create the tag before we copy values
		var openIndex = htmlV.length-1;
	}
	if (prep.contentPrefix)
		htmlV.push(prep.contentPrefix);
	var displayChildren=[];
	if (this.elements)
	{
		for (var elementRole in this.elements)
		{
			var element = this.getElement(elementRole);
			if (element)
			{
				if (element.isRepetitive)
				{
					if (value)
					{
						var childValues = value.getChildren(elementRole);
						for (var i=0;i<childValues.length;i++)
						{
							var oldChild = childValues[i];
							if (element.isDisplayElement)
							{
								var newChild =  element.createChildWithoutVisuals(this, oldChild.modelId);
								if (newChild.isHTMLTag || newChild.isDisplayGroup)
									newChild.copyValueOpt(oldChild, nodeMap,htmlV, legacyNodes);
								else
								{
									newChild.valueToCopy = oldChild;
									legacyNodes.push(newChild);
								}
							}
							else
							{
								var newChild = oldChild; //No need to clone non-display elements
								element.addAChild(this, newChild);
							}
							displayChildren.push(newChild);
						}
					}
				}
				else
				{
					var oldChild = value ? value.getChild(elementRole) : null;
					if (element.isDisplayElement && (element.alwaysCreate && ! this.initElement  || oldChild != null))
					{
						var newChild =  element.createChildWithoutVisuals(this, oldChild? oldChild.modelId:null);
						if (newChild.isHTMLTag || newChild.isDisplayGroup)
							newChild.copyValueOpt(oldChild, nodeMap,htmlV,legacyNodes);
						else
						{
							newChild.valueToCopy = oldChild;
							legacyNodes.push(newChild);
						}
						displayChildren.push(newChild);
						Element.prototype.replaceChild.call(element,this, newChild);
					}
					else if (oldChild != null)
						element.replaceChild(this, oldChild);
					
				}
			}
		}	
	}
	if (prep.contentSuffix)
		htmlV.push(prep.contentSuffix);
	
	if (! this.isGroup)
	{
		var nodeIdS = '' + this.getNodeId();
		nodeMap[nodeIdS] = this;
		var e = this.element;
		if (prep.simpleHTML)
		{
			htmlV[openIndex] = prep.HTMLPrefix + nodeIdS+'">';
		}
		else
		{
			var hv = [];
			hv.push(prep.HTMLPrefix);
			hv.push(nodeIdS);
			hv.push('" ');
			for (var i=0;i<this.HTMLAttributeElements.length; i++)
			{
				var e = this.HTMLAttributeElements[i];
				var v = e.getChild(this);
				if ( v!=null)
				{
					if (tersus.BOOLEAN_HTML_ATTRIBUTES.contains(e.role))
					{
						if (v)
						{
							hv.push(e.attributeName);
							hv.push(' ');
						}
						
					}
					else
					{
						hv.push(e.attributeName);
						hv.push('="');
						hv.push(tersus.escapeHTMLAttribute(v.leafValue));
						hv.push('" ');
					}
				}
			}
			var invisible = false;
			if (prep.updateVisible)
			{
				this.updateVisible();
				invisible = this.isInvisible();
			}
			if (this.styleAttributeElements.length > 0 || e.staticStyle || invisible)
			{
				hv.push(' style="');
				hv.push(prep.staticStyle);
				for (var i=0;i<this.styleAttributeElements.length; i++)
				{
					var e = this.styleAttributeElements[i];
					var v = e.getChild(this);
					if ( v!=null && v.leafValue != null)
					{
						hv.push(e.attributeName);
						hv.push(':');
						hv.push(v.leafValue);
						hv.push(';');
					}
				};
				if (invisible)
					hv.push('display:none;');
				hv.push('"');
			}
			hv.push('>');
			htmlV[openIndex] = hv.join('');
		}
		this.addHTMLTagContent(htmlV, displayChildren, prep);
		htmlV.push(prep.HTMLSuffix);
	}
};
tersus.HTMLTag.prototype.addHTMLTagContent = function(htmlV, displayChildren, prep)
{
	if (!this.displayElements && !prep.isInput)
		htmlV.push(this.escapeHTML(this.translate(this.valueStr)));
};

tersus.HTMLTag.prototype.attachHTMLNode = function(e)
{
	this.viewNode = this.textContainer=e;
	var wt = this.prep.wrapperTags;
	this.wrapperNode = this.viewNode;
	if (wt)
	{
		for (var i=0; i< wt.length;i++)
			this.wrapperNode = this.wrapperNode.parentNode;
	}
	if (this.hasEventHandlers)
		this.setEventHandlers();
	this.postAttach();
}
tersus.HTMLTag.prototype.postAttach = function()
{
	var e = this.viewNode;
	if (e.tagName=='INPUT' || e.tagName=='TEXTAREA')
		this.inputField = e;
	
	var p = e.getAttribute('data-role');
	if (p=='button') p='buttonMarkup';
	var node = this;
	if (p && $.fn[p])
		$.fn[p].apply($(e));
	if (e.tagName=='A')
		$(e).find('span.ui-btn-text').each(function(i,e1){node.textContainer=e1;}); // Should make <Value> work, but not <Disabled>
	
};
tersus.HTMLTag.prototype.attachHierarchy = function (nodeMap) 
{
	var elements = this.viewNode.getElementsByTagName('*');
	for (var i=0;i<elements.length; i++)
	{
		var e = elements[i];
		var lid = e.getAttribute('lid');
		if (lid)
		{
			var n = nodeMap[lid];
			if (n)
				n.attachHTMLNode(e);
		}
	}
};
//Todo (?) - merge HTMLTag and DisplayNode so that optimization is the default
tersus.HTMLTag.prototype.createEventHandlerList = function createEventHandlerList()
{
	this.eventHandlerList = [];
	for (var key in Events)
	{
		var eventType = Events[key];
		if (this.hasEventHandler(eventType) && eventType.jsName)
			this.eventHandlerList.push(eventType);
	}
	this.isLocationChangeListener = this.hasEventHandler(Events.ON_LOCATION_CHANGE);
	
	this.hasEventHandlers = this.eventHandlerList.length > 0 || this.isLocationChangeListener;
};
tersus.HTMLTag.prototype.setEventHandlers = function DisplayNode_setEventHandlers()
{
	for (var i=0; i<this.eventHandlerList.length; i++)
	{
		var eventType = this.eventHandlerList[i];
		this.registerEventHandler(eventType);
	}
	if (this.isLocationChangeListener)
		tersus.locationChangeListeners.push(this.getNodeId());
};

tersus.HTMLTag.prototype.addIntermediateDataElement = function addIntermediateDataElement(role, modelId)
{
	//Interpret "distingushed" elements as CSS/HTML attributes (and throw error if there is no such HTML/CSS attribute)
	var element = null;
	if (this.getGetter(role) && role != '<Style Class>' && role != '<Style>')
	{
		element = new MethodElement(this, role, modelId);
	}
	else if (role == '<Valid Values>')
	{
		//<Valid Values> is used by the Table Wizard mechanism and is actaully a regular data element
		element = new FlowDataElement(role, modelId);
	}
	else if (role.search(/^<.*>$/)>=0) 
	{
		var p = tersus.convertProperty(role.substring(1,role.length-1));
		if (tersus.STYLE_ATTRIBUTES.contains(p))
		{
			element = new tersus.StyleAttributeElement(this,role,modelId);
			this.styleAttributeElements.push(element);
			this.dynamicAttributeElements[p]=element;
		}
		else if (p.match(/^data-/) || tersus.HTML_ATTRIBUTES.contains(p))
		{
			element = new tersus.HTMLAttributeElement(this,role,modelId);
			this.HTMLAttributeElements.push(element);
			this.dynamicAttributeElements[p]=element;
		}
		else
		 	modelError("Unknown CSS/HTML property \""+p+"\" for data element \""+role+"\"",this);
	}
	else
	{
		element = new FlowDataElement(role, modelId);
	}
	return this.addElement(element);
};

tersus.HTMLAttributeElement = DataElement.__subclass('HTMLAttributeElement', function(owner, role, modelId)
{
	this.owner = owner;
	this.role = role;
	this.modelId = modelId;
	this.attributeName = tersus.convertProperty(role.substring(1,role.length-1));
	this.changeHandler=owner['jq'+role];
});
tersus.HTMLAttributeElement.prototype.replaceChild = function replaceChild(parent, value)
{
	DataElement.prototype.replaceChild.call(this, parent,value);
	var v = value != null ? value.leafValue : null;
	if (parent.viewNode)
	{
		if (this.attributeName == 'class')
		{
			if (v == null) v = '';
			parent.viewNode.className = v;
		}
		else if (tersus.BOOLEAN_HTML_ATTRIBUTES.contains(this.attributeName))
		{
			$(parent.viewNode).prop(this.attributeName, v);
		}
		else
			parent.viewNode.setAttribute(this.attributeName, v);
			
		if (this.changeHandler)
			this.changeHandler.call(parent,value);
	}
};
tersus.HTMLAttributeElement.prototype.removeChild = function removeChild(parent)
{
	DataElement.prototype.removeChild.call(this, parent);
	if (parent.viewNode)
	{
		if (this.attributeName == 'class')
			parent.viewNode.className = '';
		else if (tersus.BOOLEAN_HTML_ATTRIBUTES.contains(this.attributeName))
			$(parent.viewNode).prop(this.attributeName, null);
		else
			parent.viewNode.setAttribute(this.attributeName, null);
	}
};

tersus.HTMLAttributeElement.prototype.getChild = function getChild(parent)
{
	if (parent.viewNode)
	{
		var leafValue;
		if (this.attributeName == 'class')
		{
			leafValue = parent.viewNode.className;
			if (leafValue == '') 
				leafValue = null;
		}
		else if (tersus.BOOLEAN_HTML_ATTRIBUTES.contains(this.attributeName))
			leafValue = $(parent.viewNode).prop(this.attributeName);
		else
			leafValue = parent.viewNode.getAttribute(this.attributeName);
		var dataValue = null;
		if (leafValue != null)
		{
			dataValue = this.createChildInstance();
			dataValue.setLeaf(leafValue);
		}
		return dataValue;

	}
	else
		return DataElement.prototype.getChild.call(this, parent);
};
tersus.StyleAttributeElement = DataElement.__subclass('StyleAttributeElement', function(owner, role, modelId)
{
	this.owner = owner;
	this.role = role;
	this.modelId = modelId;
	this.attributeName = tersus.convertProperty(role.substring(1,role.length-1));
	this.jsAttributeName = tersus.getJsAttributeName(this.attributeName);
});
tersus.StyleAttributeElement.prototype.replaceChild = function replaceChild(parent, value)
{
	DataElement.prototype.replaceChild.call(this, parent,value);
	if (parent.viewNode)
	{
		var v = value != null ? value.leafValue : null;
		if (v != null)
			parent.viewNode.style[this.jsAttributeName]= v;
	}
};
tersus.StyleAttributeElement.prototype.removeChild = function removeChild(parent)
{
	DataElement.prototype.removeChild.call(this, parent);
	if (parent.viewNode) // parent is a real display node
		parent.viewNode.style[this.jsAttributeName] = null;
};

tersus.StyleAttributeElement.prototype.getChild = function getChild(parent)
{
	if (parent.viewNode)
	{
		var leafValue = parent.viewNode.style[this.attributeName];
		var dataValue = this.createChildInstance();
		dataValue.setLeaf(leafValue);
		return dataValue;
	}
	else
		return DataElement.prototype.getChild.call(this, parent);
};
tersus.HTMLTag.prototype.formatProperties = tersus.GenericField.prototype.formatProperties;
tersus.HTMLTag.prototype.createFormatProps = tersus.GenericField.prototype.createFormatProps;
tersus.HTMLTag.prototype.reformat = tersus.GenericField.prototype.reformat;
for (var p in tersus.GenericField.prototype.formatProperties)
{
        tersus.GenericField.addFormatAccessor(tersus.HTMLTag.prototype, p,tersus.GenericField.prototype.formatProperties[p] );
};

tersus.HTMLTag.prototype.captionChanged = function()
{
	if(this.textTranslation && this.viewNode && this.textContainer && this.elements && this.elements['<Value>'])
	{
		this.setValueString();
	}
};
tersus.HTMLTag.prototype.setValueString = function()
{
	this.valueStr = '';
	if (this.value != null)
	{
		if (this.optimizeFormatString)
			this.valueStr = this.value.leafValue;
		else if (this.value.formatString)
			this.valueStr = this.value.formatString(this.formatProps ? this.formatProps : this.sharedProperties);
		else
			this.valueStr = this.value.toString();
	}
	if (this.viewNode)
	{
		if (this.inputField)
			this.inputField.value=this.valueStr;
		else
			this.textContainer.innerHTML = this.escapeHTML(this.translate(this.valueStr));
	}
};
tersus.HTMLTag.prototype.getFieldValue = tersus.HTMLTag.prototype['get<Value>'] = function getFieldValue()
{
    if (this.inputField)
    {       
    	var valueElement = this.getElement('<Value>');
        var valuePrototype = valueElement.getChildConstructor().prototype;
        this.value = valuePrototype.parseInput(this.inputField.value, this.formatProps ? this.formatProps : this.sharedProperties);
    }
    else if (this.viewNode && $(this.viewNode).prop('contenteditable') == 'true')
    {
	this.value = this.viewNode.innerHTML;
    }
    return this.value;
};
tersus.HTMLTag.prototype.setFieldValue = tersus.HTMLTag.prototype['set<Value>'] = tersus.HTMLTag.prototype['remove<Value>'] = function setFieldValue(value) 
{
        this.value = value;
        if (this.inputField && this.inputField.tagName =='INPUT')
        {
	        // Truncate to maxLength if needed (only if this is a text field)
	        if (this.maxLength && value && value.isText && value.leafValue && value.leafValue.length > this.maxLength)
	        {
	                this.value = new value.constructor();
	                this.value.leafValue =  value.leafValue.substring(0,this.maxLength); 
	        }
	    }
        this.setValueString();
};
tersus.HTMLTag.prototype.refresh = function()
{
		DisplayNode.prototype.refresh.call(this);
		var $this  = $(this.viewNode);
		if ($this.parents().hasClass('ui-page'))
			$this.pageUpdate();
};
tersus.HTMLTag.prototype.onSubmit = function(domNode, callback)
{
	if (window.trace)
	{
		window.trace.event(this, Events.ON_SUBMIT);
	}
	this.queueEvent(Events.ON_SUBMIT, null, null, callback);
	tersus.currentEvent.preventDefault();
};


tersus.HTMLTag.prototype.setFieldValue.requiresNodes = true;

// file: 103-FullScreen.js
tersus.FullScreen = tersus.HTMLTag.__subclass('FullScreen');
tersus.FullScreen.prototype.onResize = function onResize()
{
	var d = this.currentWindow.document;
	var s = getViewportSize(d);
/*	if (this.lastSize && this.lastSize.height == s.height && this.lastSize.width == s.width)
		return; // no change in size - nothing to do
	this.lastSize = s;*/

	var top = this.viewNode;
	var children = top.childNodes;
	var body;
	for (var i=0;i<children.length;i++)
	{
		var c=children[i];
		var cn = c.className;
		if (cn.indexOf('body')>=0)
			body = c;	
	}
	if (body)
	{
		var delta = top.offsetHeight - body.clientHeight;
		var height = s.height;	 //client height of body

		//Because clientHeight includes padding, but style.height doesn't include padding, we need to add padding to delta
		delta += getMeasure(body,'padding-bottom');
		delta += getMeasure(body,'padding-top');
		
		
		//Similarly, we need to remove body padding from the available height
		height -= parseInt(getActualStyle(d.body,'margin-bottom'));
		height -= parseInt(getActualStyle(d.body,'margin-top'));
		var newHeight = height-delta;
		if (newHeight>0 && newHeight < 3000)
		{
			body.style.height = newHeight+'px';
		}
	}
	this.onResizeChildren();
};

// file: 104-TagPopin.js
tersus.TagPopin = tersus.FullScreen.__subclass('TagPopin');
tersus.TagPopin.prototype.getCurrentRootViewNode = function()
{
	var root;
	var doc = this.currentWindow.document;
	root = doc.getElementById('root');
	if (! root)
		root = doc.getElementById('tersus.content');
	return root;
};
tersus.TagPopin.prototype.attachViewNode = function()
{
	this.originalRoot = this.getCurrentRootViewNode();
	this.rootNode = this.wrapperNode? this.wrapperNode:this.viewNode;
	this.originalRoot.parentNode.appendChild(this.rootNode, this.originalRoot);
};
tersus.TagPopin.prototype.isPopup = true;
tersus.TagPopin.prototype.isPopin = true;
tersus.TagPopin.prototype.start = function()
{
	if (this.element && ! this.element.prepareForHTML)
		this.element.prepareForHTML = DisplayElement.prototype.prepareForHTML;
	var w = this.currentWindow;
	var doc = w.document;
	this.originalRootDisplayNode = w.currentRootDisplayNode;
	tersus.popupNodes[this.getNodeId()]=this;
	clearSelection(w);
	this.create();
	w.currentRootDisplayNode = this;		
	FlowNode.prototype.start.call(this);
	this.isOpen = true;
	if (tersus.isIPhone)
		window.scrollTo(0,1);
	var w =this.rootNode;
	var cn = w.className;
	setTimeout(function() {w.className = cn +' open';},10);
};
tersus.TagPopin.prototype.destroy = function()
{
	if (! this.isDestroyed)
	{
		this.isDestroyed = true;
		DisplayNode.prototype.destroy.call(this);
		this.doClose();
	}
};
tersus.TagPopin.prototype.closeWindow = function() 
{
	this.destroyHierarchy();
};
tersus.TagPopin.prototype.doClose = function()
{
	delete tersus.popupNodes[this.getNodeId()];
	
	if (this.isOpen)
	{
		var doc = this.currentWindow.document;
//		currentRoot.parentNode.replaceChild(this.originalRoot, currentRoot);
		var r = this.rootNode;
		r.className = r.className.replace(/open/,'closed');
		setTimeout(function(){r.parentNode.removeChild(r);},500);
		this.currentWindow.currentRootDisplayNode = this.originalRootDisplayNode;
		this.viewNode = null;
		this.rootNode = null;
	}
	this.isOpen = false;
};

tersus.TagPopin.prototype.findById = function tersus_popIn_FindById(id, alreadyScanned)
{
	//Traverse only if its window is open
	if (this.isOpen)
		return tersus.Node.prototype.findById.call(this,id, alreadyScanned);
	else
		return null;
};
// file: 105-UIWidget.js

(function( $, undefined ) {
var setter = tersus.setter = function(f, requiresNodes)
{
	if (requiresNodes)
		f.requiresNodes = true;
	return f;
	
};

$.fn.tersus = function(options)
{
	return this.map(function(ix, e) {return DisplayNode.findNodeForDocumentNode(e);});
};

tersus.UIWidget = function(name, base, options)
{
	if (tersus[name])
		throw 'Duplicate definition of \'tersus.\''+name;
		
	var c = tersus[base].__subclass('tersus.'+name);
	tersus[name]=c;
	var p = c.prototype;
	$.extend(p,{
        postAttach:function()
        {
            tersus.HTMLTag.prototype.postAttach.call(this);
            if (this.attach)
                this.attach();
        }});

	$.extend(p,options);
};

tersus.UIWidget('UIBase','HTMLTag', {
    defaultTag:'div'
});

})( jQuery);

// file: 105-Widgets.js

(function( $, undefined ) {
var setter = tersus.setter = function(f, requiresNodes)
{
	if (requiresNodes)
		f.requiresNodes = true;
	return f;
	
};

$.fn.tersus = function(options)
{
	return this.map(function(ix, e) {return DisplayNode.findNodeForDocumentNode(e);});
};
//animation/transition end callback



var register = function(eventType, domNode)
		{
			if (eventType===Events.ON_CLICK)
			{
				tersus.HTMLTag.prototype.registerEventHandler.call(this,eventType, domNode);
				return;
			}
			if (!eventType.jsName)
			{
				throw {message:('No event dispatcher defined for '+eventType.elementName)};
				return;
			}
			var dispatcher = this.currentWindow.tersus_dispatchers[eventType.jsName];
			if (!dispatcher)
				throw {message:('No event dispatcher defined for '+eventType.jsName)};

			if (!domNode)
			{
				if (this.eventTargets)
					domNode = this.eventTargets[eventType.jsName];
				if (!domNode)
					domNode = this.viewNode;
			 }
			domNode.setAttribute('lid',this.getNodeId());
			$(domNode).bind(eventType.name,dispatcher);
		};
		
tersus.Widget = function(name, base, options)
{
	if (tersus[name])
		throw 'Duplicate definition of \'tersus.\''+name;
		
	var c = tersus[base].__subclass('tersus.'+name);
	tersus[name]=c;
	var p = c.prototype;
	$.extend(p,{
		
		postAttach:function()
		{
			var e = this.viewNode;
			var p = e.getAttribute('data-role');
			if (p=='button') p='buttonMarkup';
			var node = this;
			var pl = $.fn[this.jQuery];
			if (pl)
				pl.apply($(e));
			if (e.tagName=='A')
				$(e).find('span.ui-btn-text').each(function(i,e1){node.textContainer=e1;}); // Should make <Value> work, but not <Disabled>
			if (this.attach)
				this.attach();
			
		}
		,registerEventHandler:register
		
		,eachDisplay: function(callback)
		{
			if (this.elements)
			{
				var i=0;
				for (var elementRole in this.elements)
				{
					var element = this.getElement(elementRole);
					if (element.isDisplayElement)
					{
						if (element.isRepetitive)
						{
							var cc = element.getChildren(this);
							for (var j=0;j<cc.length;j++)
							{
								var c=cc[j];
								if (callback.call( c, i, c ) === false)
									return;
								++i;
							}
						}
						else
						{
							var c = element.getChild(this);
							if (c)
							{
								if (callback.call( c, i, c ) === false)
									return;
								++i;
							}
						}
					}							
				}
			}
		}		
	});
	
	$.extend(p,options);
	if (typeof options.template === 'string')
		p.template=$.template(null,options.template);
	if (p.template)
	{
		p.addHTMLTagContent = function(htmlV, displayChildren, prep)
		{
			var caption = null;
			if (this.getElement('<Caption>'))
				caption = this.getCaption();
			var data = {'caption':caption, value:this.valueStr, id:this.getNodeId(), readOnly:this.currentReadOnly};
			if (typeof this.templateData === 'function')
				$.extend(data, this.templateData.call(this, displayChildren)); // Add widget-specific data
			else if (typeof this.templateData === 'object')
				$.extend(data, this.templateData);
			var t = this.template($,{'data':data});
			$.merge(htmlV,t);
		};
	};
};

tersus.Widget('Toolbar','HTMLTag',{
	defaultTag:'div'
});
tersus.Widget('Label2','HTMLTag', {
	defaultTag:'h2'
	,template:'${caption}'
	,captionChanged:function(){$(this.viewNode).html(this.getCaption());}
});
tersus.Widget('Button2','HTMLTag', {
	defaultTag:'a'
	//,jQuery:'buttonMarkup'
	//,baseProperties:{'data-role':'button'}
	,template:'${caption}'
	,attach: function(){var node=this;$(this.wrapperNode).not('.ui-btn').buttonMarkup().prev().find('span.ui-btn-text').each(function(i,e1){node.textContainer=e1;;});}
	,onClick:function(domNode, callback){
		if (this.getLeafChild('<Disabled>'))
			return;
		DisplayNode.prototype.onClick.call(this, domNode, callback);
	}
	,captionChanged:function(){$(this.viewNode).find('.ui-btn-text').text(this.getCaption());}
	,'jq<Icon>': function(icon) {$(this.viewNode).data('icon',icon).buttonUpdate();}
});

/*

	// A version of Button2 with more explicit HTML Structure.  Doesn't support icons

tersus.Widget('Button2','HTMLTag', {
	defaultTag:'a'
	,defaultClass:'ui-btn ui-btn-corner-all ui-shadow ui-btn-up-c'
	//,jQuery:'buttonMarkup'
	//,baseProperties:{'data-role':'button'}
	,template:'<span class="ui-btn-inner"><span class="ui-btn-text">${caption}</span></span>'
	,attach: function(){
		this.textContainer=$(this.viewNode).find('.ui-btn-text')[0];
	}
	,onClick:function(domNode, callback){
		if (this.getLeafChild('<Disabled>'))
			return;
		DisplayNode.prototype.onClick.call(this, domNode, callback);
	}
	//,'jq<Icon>': function(icon) {$(this.viewNode).data('icon',icon).buttonUpdate();}
});
 */

tersus.Widget('FieldWidget','HTMLTag',{
	template:'{{if readOnly}}{{if caption}}<label for="${id}" class="ui-input-text" >${caption}</label>{{/if}}<span id="${id}" class="ter-field-readonly">${value}</span>'
			+'{{else}}{{if caption}}<label for="${id}" class="ui-input-text">${caption}</label>{{/if}}<input type="${fieldType}" id="${id}" value="${value}"/>{{/if}}'
	,defaultTag:'div'
	,jQuery:'fieldcontain'
	,setTextNode: function()
	{
		var $this = $(this.viewNode);
		this.textContainer = $this.find('.ter-field-readonly')[0];
		this.inputField = $this.find('input,textarea')[0];
	}

	,attach:function(){
		this.setTextNode();
		this.eventTargets={'onfocus':this.inputField};
		$(this.viewNode).find('input[type="text"]').textinput();
	}
	,updateSelfReadOnly: function(ro) {
		this.currentReadOnly=ro;
		if (!this.viewNode)
			return;
		if (ro)
		{
			var $f = $('<span class="ter-field-readonly"/>');
			$f.text(this.valueStr);
			$f.attr('id',this.getNodeId());
			$(this.viewNode).find('input').replaceWith($f);
		}
		else
		{
			var $f = $('<input type="text" class="ui-input-text ui-body-null ui-corner-all ui-shadow-inset ui-body-c"/>');
			$f.val(this.valueStr);
			$f.attr('id',this.getNodeId());
			$(this.viewNode).find('span.ter-field-readonly').replaceWith($f);
		}
		this.setTextNode();
	}
});
tersus.Widget('TextArea2','FieldWidget',{
	template:'{{if caption}}<label for="${id}">${caption}</label>{{/if}}<textarea id="${id}" value="${value}"/>'
});

tersus.Widget('TextField','FieldWidget',{
	templateData:{fieldType:'text'}
});
tersus.Widget('PasswordField2','FieldWidget',{
	templateData:{fieldType:'password'}
});
tersus.Widget('NumberField','FieldWidget',{
	templateData:{fieldType:'number'}

});

tersus.Widget('DateField2','FieldWidget',{
	templateData:{fieldType:'text'}
//	,attach:function(){tersus.FieldWidget.prototype.attach.call(this);var $f=$(this.inputField); setTimeout(function(){$f.datebox();},0);}

});
tersus.Widget('List','HTMLTag',{
	defaultTag:'ul'
	,attach:function(){if(this.pluginVersion<1) $(this.viewNode).listview();}
});
tersus.Widget('Form','HTMLTag',{
	defaultTag:'form'
});
tersus.Widget('ListItem','HTMLTag',{
	defaultTag:'li'
	,attach:function()
	{
		if (this.pluginVersion<1)
		{
			if (this.sprop('data-role')=='none')
				return;
		 	var lv = $(this.viewNode).parent().data('listview'); if (lv) lv.refresh();
		 }
	}
	,prepareForHTML:function(e,parent)
	{
		if (this.pluginVersion<1 && this.hasEventHandler(Events.ON_CLICK))
		{
			$(this.displayElements)
				.filter(function(i){
					return this.getChildConstructor().prototype.plugin=='Tersus/Widgets/Text Display';
				})
				.first()
				.each(function(){
					this.properties = $.extend({wrapperTags:'a'},this.properties);
				});
		}
		return tersus.HTMLTag.prototype.prepareForHTML.call(this);
	}
});
tersus.Widget('ListDivider','HTMLTag',{
	defaultTag:'li'
	,baseProperties:{'data-role':'list-divider'}
	,template:'${caption}'
});

tersus.Widget('Image2','HTMLTag',{
	defaultTag:'img'
});
tersus.Widget('TextDisplay','HTMLTag',{
	defaultTag:'span'
});
tersus.Widget('NumberDisplay','HTMLTag',{
	defaultTag:'span'
});
tersus.Widget('DateDisplay','HTMLTag',{
	defaultTag:'span'
});

tersus.Widget('Slider', 'HTMLTag', {
	templateData: function(){return {min:13, max:77};}
	,template:'{{if caption}}<label for="${id}">${caption}</label>{{/if}}<input type="number" id="${id}" value="${value}" min=${min} max=${max}/>'
	,defaultTag:'div'
	,jQuery:'fieldcontain'
	,attach:function(){this.inputField=this.viewNode.lastChild; $(this.inputField).slider();}
});

tersus.Widget('RadioButton2','Button2',
{
	onClick:function(domNode, callback){
		var $p = $(this.parent.viewNode); $self = $(this.viewNode);
		$p.find('.ui-btn').removeClass('ui-btn-active');
		$self.addClass('ui-btn-active');
		DisplayNode.prototype.onClick.call(this, domNode, callback);
		this.onChange(domNode, callback);
		this.parent.onChange(domNode, callback);
	}
	,getButtonValue:function()
	{
		if (this.value != undefined)
			return this.value;
		else
		{
			var c = tersus.repository.get(BuiltinModels.TEXT_ID);
			var node = new c();
	        node.prototype = c.prototype;
	        node.setLeaf(this.getBaseCaption());
			return node;
		}
	}
});

tersus.Widget('ButtonGroup','HTMLTag',{
	defaultTag:'fieldset',
	attach:function()
	{
		var $self = $(this.viewNode);
		$self.addClass('ui-corner-all ui-controlgroup ui-controlgroup-horizontal');
		setTimeout(function()
		{
			var rtl= $self.css('direction') == 'rtl';
			var $buttons = $self.find('.ui-btn');
			$self.find('.ui-btn-corner-all').removeClass('ui-btn-corner-all ui-shadow');
			$buttons.first().addClass(rtl ? 'ui-corner-right' : 'ui-corner-left');
			$buttons.last().addClass(rtl ? 'ui-corner-left' : 'ui-corner-right');
			
			if ($buttons.filter('.ui-btn-active').length == 0)
				$buttons.first().addClass('ui-btn-active');
		},0);
	}
	,'get<Value>':function()
	{
		var $active = $(this.viewNode).find('.ui-btn-active').tersus();
		if ($active.length>0)
			return $active[0].getButtonValue();
		 
	}	
	
	,'set<Value>':setter(function(value)
	{
		var $self = $(this.viewNode);
		$self.find('.ui-btn-active').removeClass('ui-btn-active');
		$self.find('.ui-btn').each(function(index){
			var node = $(this).tersus()[0];
			if (node && node.getButtonValue && compareValues(value, node.getButtonValue()))
				$(this).addClass('ui-btn-active');
		});
		
	},true)
});
$.fn.pageUpdate = function(options)
{
	var $elem=$(this);
	// If we're refreshing a direct component of a page - update the whole page
	var $dataEls = $elem.find( "[data-role]" ).andSelf().each(function() {
          				var $this = $( this ),
                        role = $this.data( "role" ),
                        theme = $this.data( "theme" );

                        //apply theming and markup modifications to page,header,content,footer
                        if ( role === "header" || role === "footer" ) {
                        	$this.addClass( "ui-bar-" + (theme || $this.parent('[data-role=page]').data( "theme" ) || "a") );

                            // add ARIA role
                            $this.attr( "role", role === "header" ? "banner" : "contentinfo" );

                            //right,left buttons
                            var $headeranchors = $this.children( "a" ),
                            leftbtn = $headeranchors.hasClass( "ui-btn-left" ),
                            rightbtn = $headeranchors.hasClass( "ui-btn-right" );

                            if ( !leftbtn ) {
                                leftbtn = $headeranchors.eq( 0 ).not( ".ui-btn-right" ).addClass( "ui-btn-left" ).length;
                            }

                            if ( !rightbtn ) {
                                rightbtn = $headeranchors.eq( 1 ).addClass( "ui-btn-right" ).length;
                            }
                            //page title
                            $this.children( "h1, h2, h3, h4, h5, h6" )
                                    .addClass( "ui-title" )
                                        //regardless of h element number in src, it becomes h1 for the enhanced page
                                        .attr({ "tabindex": "0", "role": "heading", "aria-level": "1" });
                        } else if ( role === "content" ) {
                            if ( theme ) {
                                    $this.addClass( "ui-body-" + theme );
                            }

                            // add ARIA role
                            $this.attr( "role", "main" );

                        } else if ( role === "page" ) {
                                $this.addClass( "ui-body-" + (theme || "c") );
                    }

					switch(role) {
                        case "header":
                        case "footer":
                        case "page":
                        case "content":
    	                    $this.addClass( "ui-" + role );
	                        break;
                        case "collapsible":
                        case "fieldcontain":
                        case "navbar":
                        case "listview":
                        case "dialog":
                            $this[ role ]();
                            break;
                    }
                });

                //links in bars, or those with data-role become buttons
                $elem.find( "[data-role='button'], .ui-bar > a, .ui-header > a, .ui-footer > a" )
                        .not( ".ui-btn" )
                        .buttonMarkup();

                $elem
                        .find("[data-role='controlgroup']")
                        .controlgroup();
                        
                                 var o = this.options;

             
                // enchance form controls
               $elem
                        .find( "[type='radio'], [type='checkbox']" )
                        .checkboxradio();

			   $elem
                        .find( "button, [type='button'], [type='submit'], [type='reset'], [type='image']" )
                        .button();

                $elem
                        .find( "input, textarea" )
                        .not( "[type='radio'], [type='checkbox'], button, [type='button'], [type='submit'], [type='reset'], [type='image']" )
                        .textinput();

                $elem
                        .find( "input, select" )
                        .filter( "[data-role='slider'], [data-type='range']" )
                        .slider();

           /*     $elem
                        .find( "select:not([data-role='slider'])" )
                        .selectmenu();*/
                        
		

};
$.fn.buttonUpdate = function( options ){
	return this.each( function() {
		var el = $( this ),
		    o = $.extend( {}, $.fn.buttonMarkup.defaults, el.data(), options),

			// Classes Defined
			buttonClass,
			innerClass = "ui-btn-inner",
			iconClass;


		// if not, try to find closest theme container
		if ( !o.theme ) {
			var themedParent = el.closest("[class*='ui-bar-'],[class*='ui-body-']"); 
			o.theme = themedParent.length ?
				/ui-(bar|body)-([a-z])/.exec( themedParent.attr("class") )[2] :
				"c";
		}

		buttonClass = "ui-btn ui-btn-up-" + o.theme;
		if ( o.inline ) {
			buttonClass += " ui-btn-inline";
		}
		
		if ( o.icon ) {
			o.icon = "ui-icon-" + o.icon;
			o.iconpos = o.iconpos || "left";

			iconClass = "ui-icon " + o.icon;

			if ( o.shadow ) {
				iconClass += " ui-icon-shadow"
			}
		}

		if ( o.iconpos ) {
			buttonClass += " ui-btn-icon-" + o.iconpos;
			
			if ( o.iconpos == "notext" && !el.attr("title") ) {
				el.attr( "title", el.text() );
			}
		}
		
		if ( o.corners ) { 
			buttonClass += " ui-btn-corner-all";
			innerClass += " ui-btn-corner-all";
		}
		
		if ( o.shadow ) {
			buttonClass += " ui-shadow";
		}
		
		el
			.attr( "data-theme", o.theme )
			.addClass( buttonClass );

		el.attr('class',buttonClass);
		el.find('.ui-btn-inner').attr('class',innerClass);
		if (o.icon)
			el.find('.ui-icon').attr('class',iconClass);
	});		
};

})( jQuery );
// file: 106-UILabel.js
(function( $, undefined ) {
    tersus.UIWidget('UILabel','UIBase', {
        defaultTag:'span'
        ,addHTMLTagContent:function(htmlV, displayChildren, prep)
        {
                if (this.getElement('<Caption>'))
                    htmlV.push(this.getCaption());
        }
        ,captionChanged:function()
        {
            if (this.getElement('<Caption>'))
                $(this.viewNode).text(this.getCaption());
        }
    
    });
})(jQuery);
// file: 107-UIField.js
(function( $, undefined ) {
tersus.UIWidget('UIField','UIBase',{
   defaultTag:'input'
    ,readOnlyChanged:function(){}
    ,inputType:'text'
    ,attach: function()
    {
 		this.setValueString();
		this.updateSelfReadOnly(this.computedReadOnly());
    }
    ,updateSelfReadOnly: function(ro) {
       this.currentReadOnly=ro;
        if (!this.viewNode)
            return;
        var $v = $(this.viewNode);
        var roTag=this.prop('readonlytag') || this.defaultTag;
        var rwTag=this.getTag();
	if (this.detachWidget) this.detachWidget();
        if (roTag == rwTag)
        {
            if (ro)
                $v.attr('readonly',true);
            else
                $v.removeAttr('readonly');
	    this.readOnlyChanged();
        }
        else
        {
            if (ro)
            {
                this.getFieldValue(); // Copies input field value into this.value
                $f = $('<'+roTag+'>');
            }
            else
            {
		var type = this.prop('type') || this.inputType;
                var typeAttr = type ?' type="'+type+'"':'';
                var $f=$('<'+rwTag +typeAttr+'>');
            }
            $f.attr('lid',this.getNodeId());
            $f.attr('display_order',$v.attr('display_order'));
            $v.replaceWith($f);
            this.textContainer=this.viewNode=$f[0];
            this.inputField = ro ? undefined: this.viewNode;
            this.setValueString(); //Sets new element content based on this.value
        }
	if (this.attachWidget) this.attachWidget();
    }});
})(jQuery);

// file: 108-UIDialog.js
tersus.UIWidget('UIDialog','UIBase', {
	isDialog:true
	,defaultOptions:'cover backdrop'
	,start: function()
	{
		this.setup();
		this.create();
		FlowNode.prototype.start.call(this);
		this.isOpen = true;
		//this.currentWindow.scrollTo(0,1);
        tersus.popupNodes[this.getNodeId()]=this;
		this.open();
	}
    ,getContainer:function()
    {
        var c= this.getChild('<Container>');
        if (c && c.viewNode)
            return c.viewNode;
        var selector = (c && c.isText) ? c.leafChild : this.defaultContainer;
        var $container;
        if (! selector)
            $container=$('#tersus\\.content');
        else
        {
            var n = this.parent;
            while (n && !n.viewNode)
                n = n.parent;
            var error;
            if ( !n || !n.viewNode)
               throw 'Dialog container not found (n.viewNode is null)';
                
            $container = $(n.viewNode).closest(selector);
        }
        if ($container.length>0)
            return $container[0];
        
        throw 'Dialog container not found (selector: "'+selector+'")';
    }
	,setup:function()
	{
		if (this.element && ! this.element.prepareForHTML)
			this.element.prepareForHTML = DisplayElement.prototype.prepareForHTML; //TODO checkif needed
		clearSelection(window);
	
		this.container = this.getContainer();
		var str = (this.getLeafChild('<Options>') || this.defaultOptions).trim(); 
		var self=this;
		this.options={};
		$.each(str.split(/\s+/), function(i, v) { self.options[v]=true;}); // Set 'true' for all options in the string
		this.transitionClass = this.getLeafChild('<Transition>') || this.transitionClass;
		if (this.options.replace)
		{
		   this.open = this.replace;
		   this.close = this.replaceBack;
		}
	}

	,open:function()
	{
		var self=this;
		var $dlg = $(this.wrapperNode);
		if ($.support.transition)
		{
		    $dlg.addClass(this.transitionClass+' dlg open');
		    $dlg[0].offsetWidth; //reflow
		    $dlg.one($.support.transition.end, function() { $dlg.removeClass(this.transitionClass+' dlg open end');self.onResize();});
		    $dlg.addClass('end');
		}
	}
	,close:function()
	{
	    var self=this;
        var $dlg = $(this.wrapperNode);
        if ($.support.transition)
        {
            $dlg.addClass(this.transitionClass+' dlg close');
            $dlg[0].offsetWidth; //reflow
            $dlg.one($.support.transition.end, function() { $dlg.remove()});
            $dlg.addClass('end');
        }
        else
            $dlg.remove();
        this.removeBackdrop();
	}
    ,addBackdrop:function()
    {
        if (this.options.replace || !this.options.backdrop)
            return;
        var animate=$(this.wrapperNode).hasClass('fade') ? ' fade' : '';
        var $backdrop = this.$backdrop = $('<div class="modal-backdrop'+animate+'">');
        $(this.container).append($backdrop);
        if (animate)
        {
            $backdrop[0].offsetWidth;
            $backdrop.addClass("in");
        }
        if (this.options['backdrop-dismiss'])
        {
            var e= $.event.special.vclick ? 'vclick' : 'click';
            var self=this;
            $backdrop.on(e, function() {self.closeWindow();});
        }
    }
	,removeBackdrop:function()
	{
	    var $backdrop = this.$backdrop;
	    if (!$backdrop)
	        return;
        if ($.support.transition && $backdrop.hasClass('in'))
        {   
           $backdrop.on($.support.transition.end, function() {$backdrop.remove()});
           $backdrop.removeClass('in');
        }
        else
            $backdrop.remove();
	}
	,replace:function()
	{
		this.$rpl = $(this.container).children('.active').first(); /* The element that the dialog is replacing */
        var $dlg = $(this.wrapperNode);
		this.$rpl.data('replaced-by',$dlg);
	    var self=this;
	    self.pause();
		tersus.transition2(this.$rpl, $dlg, 'active', this.transitionClass +' rpl open', this.transitionClass+ ' dlg open','end', function(){self.continueExecution();});
	}
	,replaceBack:function()
	{
		var $dlg = $(this.wrapperNode);
		this.$rpl.data('replaced-by',null);
		tersus.transition2($dlg, this.$rpl, 'active', this.transitionClass+ ' dlg close', this.transitionClass +' rpl close', 'end', function(){$dlg.remove();});
	}
	,attachViewNode:function()
	{
	    this.addBackdrop();
	    $(this.container).append($(this.wrapperNode));

	}

	,destroy: function()
	{
		if (! this.isDestroyed)
		{
			this.isDestroyed = true;
			this.supr('destroy');
			if (this.viewNode)
			    this.doClose();
		}
	}
	,closeWindow: function() 
	{
		this.destroyHierarchy();
	}
	
	,doClose: function()
	{
		this.close();
        delete tersus.popupNodes[this.getNodeId()];
		this.isOpen = false;
	}
        ,refresh: function()
        {
	    var wasActive =$(this.wrapperNode).hasClass('active');
            tersus.UIBase.prototype.refresh.call(this);
	    if (wasActive)
		$(this.wrapperNode).addClass('active');
	}

});

// file: 109-UIHTMLDisplay.js
(function( $, undefined ) {
    tersus.UIWidget('UIHTMLDisplay','UIBase', {
        defaultTag:'div'
	,setValueString:function()
	{
        this.valueStr = '';
        if (this.value != null)
        {
             this.valueStr = this.value.toString();
        }
        if (this.viewNode)
        {
            if (this.textContainer)
                this.textContainer.innerHTML = this.valueStr;
        }
	}
	,addHTMLTagContent: function(htmlV, displayChildren, prep) 
	{
            htmlV.push(this.valueStr);
	}
});
})(jQuery);

// file: 110-MobileView.js
(function( $, undefined ) {
	if (!$.mobile)
		return;
	$.mobile.ajaxLinksEnabled = false; // For jQuery Mobile
	 $.mobile.autoInitializePage = false;

	tersus.isIphoneBrowser = navigator.userAgent.match(/Mobile.*Safari/) && !navigator.userAgent.match(/Android/) &&  !navigator.standalone;
	tersus.availableHeight = function(w)
	{
		if (!w) w = window;
		var h =  w.innerHeight ? w.innerHeight : $(w).height();
		return tersus.isIphoneBrowser & !tersus.safari.scrolled ? h+60 : h;	
		
	};
	var setter=tersus.setter;
	$.mobile.ajaxEnabled = false;
tersus.safari={scrolled:false}; //Keep track of whether we've already scrolled away the browser chrome (iPhone) as it changes the behavior of innerHeight;	
tersus.Widget('MobileView','HTMLTag',{
	defaultTag:'div'
	,hideNavbar:function()
	{
		if (this.navbar)
		{
			$(this.navbar).css('display','none');
		}
	}
	,showNavbar:function()
	{
		if (this.navbar)
		{
			$(this.navbar).css('display','block');
			$.fixedToolbars.show();
		}
	}
	,'set<Selected Page>':setter(function(p)
		{
			if (p.parent != this)
				throw {message:'Invalid element specified as selected page'};
			this.select(p.getNodeId());
		},true)
	,'get<Selected Page>':function(p)
	{
		return this.selectedPage;
	}
	,onload: function()
	{
		tersus.HTMLTag.prototype.onload.call(this);
	}
	,checkBrowser:function()
	{
	    if ( !$.mobile.gradeA() || !$.support.cssTransitions) {
	    	alert('Your browser does not have all features required to run this application. For best results, please use Safari or Chrome');
	    }
	}
	,create:function(value){
		this.checkBrowser();
		tersus.HTMLTag.prototype.create.call(this);
		if (!$.mobile.gradeA())
			return;
        //set up active page
        var p = $.mobile.startPage = $.mobile.activePage = $('[data-role=page]').first();
        //set page container
        $.mobile.pageContainer = p.parent().addClass('ui-mobile-viewport');
        window.tersusMobileInit();
        //initialize page as active page
        p.page({addBackBtn:false}).addClass( $.mobile.activePageClass);
		$(this.navbar).find('a').each(function(i)
			{
				$(this).find('.ui-icon').css('background-image',$(this).data('iconurl'));
			});        
		//remove rendering class
        $('html').removeClass('ui-mobile-rendering');
        $('html').removeClass('ui-loading');
        setTimeout(function(){window.scrollTo(0,1);tersus.safari.scrolled=true;},100);
        
	}
	,template:'${value}' 

	,navSetup:function()
	{
		//Detect mobile safari to know when we can use real fixed positioning
		this.template = $.template(null,'<div data-role="footer" data-position="bottom"><div data-role="navbar"><ul>{{each(i,p) panes}}<li {{if p.tabClass}}class="${p.tabClass}"{{/if}}><a href="javascript:tersus.findNode(${id}).select(${p.paneId})" data-paneid=${p.paneId} {{if icon}}data-icon="${icon}"{{/if}}{{if iconURL}}data-iconurl=url(${iconURL}){{/if}}>{{if p.caption}}${p.caption}{{/if}}</a></li>{{/each}}</ul></div></div>');
			
		
		this.contentTag = 'div';
		this.contentClass = 'ter-tp-content';
		this.sharedProperties = $.extend({'data-role':'page'},this.sharedProperties);
		this.attach = function()
		{
			this.navbar=this.viewNode.lastChild;
			this.content=this.viewNode.firstChild;
//			$(this.selectedPage.wrapperNode).addClass('ter-tp-active');
			$(this.content.firstChild).addClass('ter-tp-active');
			$(this.navbar).find('a[data-paneid='+this.selectedPage.getNodeId()+']').addClass('ui-btn-active');
			if (this.selectedPage.includeInNavbar)
				this.showNavbar();
			else
				this.hideNavbar();
	
		};
		this.onResize = function()
		{
			var height = tersus.availableHeight();
			$('.ui-mobile-viewport').height(height);
			var nh = $(this.navbar).outerHeight();
			var d = this.selectedPage.includeInNavbar ? nh:0;
			$(this.content).css('min-height',height-d);
			$(this.content).css('height',height-d);
			if (tlog) tlog('On Resize: height='+height+' nh='+nh+' d='+d);
			this.eachDisplay(function(i,c){
				var d = c.includeInNavbar ? nh:0;
				 $(c.viewNode).css('min-height',height-d).parent().css('height',height-d);
				 });
			this.onResizeChildren();
			if (this.selectedPage.includeInNavbar)
				this.showNavbar();
			else
				this.hideNavbar();
			
		};
		this.select = function(id)
		{
			$(this.navbar).find('a').removeClass('ui-btn-active').filter('[data-paneid='+id+']').addClass('ui-btn-active');
			var p =tersus.findNode(id);
			if (!p ||  p == this.selectedPage)
				return;
			window.scrollTo(0,0);
			if (this.selectedPage.includeInNavbar)
				this.showNavbar();
			var reverse = p.element.displayOrder>this.selectedPage.element.displayOrder ? '' : ' reverse';
			
			var from=$(this.selectedPage.wrapperNode);
			this.selectedPage = p;
			var to=$(this.selectedPage.wrapperNode);
			to.prependTo(to.parent());
			from.addClass('slide out'+reverse);
			to.addClass('ter-tp-active slide in'+reverse);
			this.onResize();
			var v = this;
			to.animationComplete(function() {
				from.removeClass('ter-tp-active');
				from.add( to ).removeClass("slide out in reverse");
				if (p.includeInNavbar)
					v.showNavbar();
				else
					v.hideNavbar()
				
			});
			tersus.invokeAction('<On Select>',null,null,p);
		};
		this.templateData =  function(displayChildren)
		{
			var panes = [];
			var view = this;
			$.each(displayChildren, function(i,child)
			{
				if (i==0)
					view.selectedPage=child;
				var iconP=child.sprop('icon'), iconJQ=iconP, iconURL=null;
				child.includeInNavbar = child.sprop('includeInNavbar') != false; // Todo: support local property
				if (!child.includeInNavbar)
					return;
				if (iconP && iconP.match(/[.]/))
				{
					iconJQ='custom';
					iconURL=iconP;
				};
				panes.push({caption:child.getElement('<Caption>')?child.getCaption():null,icon:iconJQ,iconURL:iconURL,paneId:child.getNodeId(), tabClass:child.sprop('tabStyleClass')});
			});
			return {'panes':panes};
		}
	}
	,nonavSetup: function()
	{
		var pe = this.displayElements[0];
		pe.properties = $.extend({'data-role':'page'},pe.properties);
  		this.onResize = function()
		{
			var height = tersus.availableHeight();
			$('.ui-mobile-viewport').height(height);
			$(this.viewNode).css('min-height',height);
			this.eachDisplay(function(i,c){
				 $(c.wrapperNode).css('min-height',height);
				 $(c.viewNode).css('min-height',null);
				 });
			this.onResizeChildren();
		};
  	}
	,prepareForHTML:function(e,parent)
	{
		if (this.displayElements && this.displayElements.length >1 )
		{
			this.navSetup();
		}
		else if (this.displayElements)
		{
			this.nonavSetup();
		}

		return tersus.HTMLTag.prototype.prepareForHTML.call(this,e,parent);
		
	}
	,attachViewNode:function()
	{
		$(this.wrapperNode).appendTo( this.parent ? this.parent.viewNode : '#tersus\\.content');
	}
});
})(jQuery);

// file: 110-Table.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 //Table - a simple table
Table = function Table() {this.columnNames={}; };
Table.prototype = new DisplayNode();
Table.prototype.constructor = Table;
Table.prototype.getTag = function()
{
	return 'table';
};
Table.prototype.reset = function reset()
{
	DisplayNode.prototype.reset.call(this);
	this.selectedRow = null;
	this.hiddenColumns = {};
	if (this.headerRow)
	{
		var headerCells=this.headerRow.childNodes;
		for (var i=0;i<headerCells.length;i++)
		{
			headerCells[i].style.display='';
		}
	}
}
Table.prototype.createViewNode = function createViewNode()
{
	this.hiddenColumns = {};
    DisplayNode.prototype.createViewNode.call(this);
    this.sort = (this.sharedProperties.sort == 'multiple' || this.sharedProperties.sort == 'single');
    
	this.setProperties(); // In Mozilla, we have to set the styleclass before creating the body of the table
    this.createCaption();
    this.createHeader();
    this.bodyNode = this.currentWindow.document.createElement('tbody');
    var h = this.sharedProperties.contentHeight;
    if (h && h == ' ')
    	h = null;
    var w = this.sharedProperties.contentWidth;
    if (w && w == ' ')
    	w = null;
 	if (w || h)   
		setScrollableTable(this.bodyNode, w,h); // broswer dependant
    this.viewNode.appendChild(this.bodyNode);
    this.viewNode.id = this.getNodeId();
};
Table.prototype.createCaption = function createCaption()
{
	if ( this.sharedProperties.showCaption == false) // default = true
	{
		return;
	}
	else
		if ( ! this.getRowPrototype())
			return;
	this.captionDOMElement = this.createHTMLElement('caption');
	this.captionDOMElement.innerHTML = '<div>'+tersus.escapeHTML(this.getCaption())+'</div>';
	this.viewNode.appendChild(this.captionDOMElement);
};
Table.prototype.captionChanged = function()
{
	if (this.captionDOMElement)
		this.captionDOMElement.innerHTML = '<div>'+tersus.escapeHTML(this.getCaption())+'</div>';
};

Table.prototype.addHeaderCells = function addHeaderCells(headerRow,node)
/* Adds header cells based on the structure of the given node */
{
	for (var i=0; i< node.displayElements.length; i++)
	{	
		var columnElement = node.displayElements[i];
		var columnNodePrototype = columnElement.getChildConstructor().prototype;
		if (columnNodePrototype.isDisplayGroup)
		{
			this.addHeaderCells(headerRow, columnNodePrototype);
		}
		else
		{
			var labelHTML = columnElement.properties.caption;
			if (!labelHTML || labelHTML == ' ')
				labelHTML = tersus.escapeHTML(columnElement.role)
			labelHTML = this.translate(labelHTML);
			var headerCell = this.createHTMLElement('th');
			headerCell.setAttribute("element_name", columnElement.role);
			var columnName = columnElement.properties.sortColumnName;
			if (!columnName)
				columnName = columnElement.role;
			if (!tersus.useSQLQuotedIdentifiers)
				columnName = tersus.sqlize(columnName);
			headerCell.setAttribute("column_name", columnName);
			this.columnNames[columnElement.role]=tersus.useSQLQuotedIdentifiers ? columnName : columnName.toLowerCase();
			headerCell.innerHTML = labelHTML;
			var col = this.createHTMLChildElement(this.colgroup,'col');
			headerCell.col = col;
			if (this.sort && columnElement.properties.sortable != false)
			{
				headerCell.setAttribute('sort', 'none');
				headerCell.onclick = Table.headerClicked;
			}
			headerCell.onmousedown = Table.mouseDownOnHeader;
			headerCell.onmouseover = Table.updateHeaderCursor;
			headerCell.onmousemove = Table.updateHeaderCursor;
				

			if (headerRow.childNodes.length == 0)
				headerCell.className='first';
			headerRow.appendChild(headerCell);
		}
	}
};
Table.prototype.getRowPrototype = function()
{
	var output = null;
	if (this.subFlowList)
	{
		for (var i=0; i< this.subFlowList.length; i++)
		{
			var subFlow = this.subFlowList[i];
			if (subFlow.isDisplayElement && subFlow.role != '<Header>' && subFlow.role != '<Footer>')
			{
				if (output)
					return null;
				else
					output = subFlow;
			}
		}	
	}
	return output;
};
Table.prototype.createHeader = function createHeader()
{
	if ( this.sharedProperties.showHeadings == false) // default = true
		return;
	var rowElement = this.getRowPrototype();
	if (! rowElement) return;
	var rowPrototype = tersus.repository.get(rowElement.modelId).prototype;
	if (! rowPrototype.subFlowList) return;
	var headerRow = this.createHTMLElement('tr');
	this.colgroup = this.createHTMLChildElement(this.viewNode,'colgroup');
	this.addHeaderCells(headerRow, rowPrototype);
	var tableHeader = this.createHTMLElement('thead');
	tableHeader.appendChild(headerRow);
	this.header = tableHeader;
	this.headerRow = headerRow;
	this.viewNode.appendChild(tableHeader);
};

Table.prototype.removeChildViewNode = function removeChildViewNode(child)
{
	var c = child.viewNode;
	var row = null;
	if (c.tagName == 'TR' )
		row = c;
	else if (c.parentNode && c.parentNode.tagName == 'TR')
		row = c.parentNode;
	else if (c.parentNode && c.parentNode.parentNode && c.parentNode.parentNode.tagName== 'TR')
		row = c.parentNode.parentNode;
	if (row && row.parentNode)
		row.parentNode.removeChild(row);
};
Table.prototype.applyColOrder = function (row)
{
	if (this.colOrder)
	{
		var cells = [];
		for (var i=0;i<row.childNodes.length;i++)
		{
			cells.push(row.childNodes[i]);
		}
		if (cells.length != this.colOrder.length)
		{
			internalError("Failed to apply column order: mismatch between number of cells in row and number of columns in colOrder");
			return;
		}
		for (var i=0;i<cells.length;i++)
		{
			row.removeChild(cells[i]);
		}
		for (var i=0;i<cells.length;i++)
		{
			row.appendChild(cells[this.colOrder[i]]);
		}
	};
};
Table.prototype.getFooter = function()
{
	if (! this.footer)
		this.footer = 	this.header = this.createHTMLChildElement(this.viewNode, 'tfoot');
	return this.footer;
		
};
Table.prototype.appendChildViewNode = function appendChildViewNode(child, childElement)
{
	var element = childElement?childElement:child.element;
	var targetNode = this.bodyNode;
	if (element.role == '<Header>')
		targetNode = this.header;
	if (element.role == '<Footer>')
		targetNode = this.getFooter();
	var row = null;
	if (child.viewNode.tagName == 'TR')
	{
		row = child.viewNode;
	}
	else
	{
		var row = this.createHTMLElement('TR');
		if (child.viewNode.tagName == 'TH' || child.viewNode.tagName == 'TD')
			row.appendChild(child.viewNode);
		else
		{
			var cell = this.createHTMLChildElement(row,'TD');
			cell.appendChild(child.viewNode);
		}
		row.setAttribute('display_order', child.viewNode.getAttribute('display_order'));
	}
	if (this.headerRow && ! element.prop('suppressColumnHiding'))
	{
		var rowCells = row.childNodes;
		var headerCells = this.headerRow.childNodes;
		if (rowCells.length == headerCells.length)
		{
			for (var i=0;i<headerCells.length;i++)
			{
				if (headerCells[i].style.display=='none')
					rowCells[i].style.display= 'none';
			}
		}
	}
		
		 
	if (this.header) // If there is a header, we know we have a single row, so we can directly append the child row and skip display order handling
		targetNode.appendChild(row)
	else
		DisplayNode.appendChildNode(targetNode,row); 
};

Table.prototype['get<Selected Row>'] = function ()
{
	if (this.selectedRow)
		return this.selectedRow;
	else
		return null;
};
Table.prototype['set<Selected Row>'] = Table.prototype.select = function (row)
{
	var selectedClassName = 'selected';
	//TODO(y) - check that row is a row in this table. Report an error if not.
	if (this.selectedRow)
	{
		if (this.pluginVersion>=1)
			this.selectedRow.removeStyleClass(selectedClassName);
		else
			this.selectedRow.viewNode.className = this.selectedRow.baseClassName;
	}
	this.selectedRow = row;
	if (row && row.viewNode)
	{
		if (this.pluginVersion>=1)
			row.addStyleClass(selectedClassName);
		else
			row.viewNode.className = 'selected';
	}
};
Table.prototype['remove<Selected Row>'] = function ()
{
	var selectedClassName = 'selected';
	if (this.selectedRow)
	{
		if (this.pluginVersion>=1)
			this.selectedRow.removeStyleClass(selectedClassName);
		else
			this.selectedRow.viewNode.className = this.selectedRow.baseClassName;
		this.selectedRow = null;
	}
};
Table.prototype.select.requiresNodes = true;
Table.prototype['get<Sort Order>'] = Table.prototype.getSortOrder = function()
{
	var sortOrder = null;
	var headerCells = this.headerRow.childNodes;
	for (var i=0;i<headerCells.length;i++)
	{
		var headerCell = headerCells[i];
		var columnName = headerCell.getAttribute('column_name');
		if (tersus.useSQLQuotedIdentifiers)
			columnName = '"'+columnName+'"';
		var sort = headerCell.getAttribute('sort');
		var sortKey = null;
		if (sort == 'up')
		 	sortKey=' ASC';
		else if (sort == 'down')
			sortKey=' DESC';
		if (sortKey)
		{
			if (sortOrder ==null)
				sortOrder = '';
			else
				sortOrder+=', ';
			sortOrder+=columnName;
			sortOrder+=sortKey;
		}
	}
	return sortOrder;
};
Table.prototype['set<Sort Order>'] = function (sort_order)
{
	//TODO: handle conflicts between column order and sort order
	var headerCells = this.headerRow.childNodes;
	var header_cell_map = {};
	for (var i=0;i<headerCells.length;i++)
	{
		var headerCell = headerCells[i];
		var columnName = headerCell.getAttribute('column_name');
		if (!tersus.useSQLQuotedIdentifers)
			columnName = columnName.toLowerCase();
		this.doSortNoFire(headerCell,'none');
		header_cell_map[columnName]=headerCell;
	}
	var result;
	var re;
	if (sort_order.indexOf('"')>=0)
		re = / *"([^"]+)"( +([a-z]+))? *(,|$)/gi
	else 
		re = / *([^, ]+)( +([a-z]+))? *(,|$)/gi;
	var prevHeaderCell = null;
	while (result = re.exec(sort_order))
	{
		var columnName = result[1];
		if (! tersus.useSQLQuotedIdentifiers)
			columnName = columnName.toLowerCase();
		var dir = result[3];
		dir =  (dir && dir.toLowerCase().charAt(0)=='d') ? 'down' : 'up';
		var headerCell = header_cell_map[columnName];
		this.doSortNoFire(headerCell,dir);
		if (prevHeaderCell)
			this.ensureColumnOrder(prevHeaderCell, headerCell);
		prevHeaderCell = headerCell; 
	};
};
Table.prototype['remove<Sort Order>'] = function ()
{
	var headerCells = this.headerRow.childNodes;
	for (var i=0;i<headerCells.length;i++)
	{
		this.doSortNoFire(headerCells[i],'none');
	}
};
Table.prototype['set<Hidden Columns>'] = function(hidden_cols)
{
	var re;
	if (hidden_cols.indexOf('"')>=0)
		re = / *"([^"]+)" *(,|$)/gi
	else 
		re = / *([^, ]+) *(,|$)/gi;
	var hidden = this.hiddenColumns;
	for (var columnName in hidden)
		hidden[columnName]=0;
	var result;
	while (result = re.exec(hidden_cols))
	{
		var columnName = result[1];
		if (! tersus.useSQLQuotedIdentifiers)
			columnName = columnName.toLowerCase();
		if (hidden[columnName] == null)
		{
			this.hideColumn(columnName);
		}
		else
			hidden[columnName]=1; // Just mark that this column is still hidden
	}
	for (var columnName in hidden)
	{
		if (hidden[columnName] == 0) // was hidden but no longer is
		{
			this.showColumn(columnName);
		}
	}
	this.rebuildColgroup();
};
Table.prototype['remove<Hidden Columns>'] = function()
{
	for (var columnName in this.hiddenColumns)
	{
		this.showColumn(columnName);
	}
	this.rebuildColgroup();

};

Table.prototype['get<Hidden Columns>'] =  function()
{
	var hidden = this.hiddenColumns;
	if (hidden == null)
		hidden = {}; 
	var hiddenCols = null;
	var headerCells = this.headerRow.childNodes;
	for (var i=0;i<headerCells.length;i++)
	{
		var headerCell = headerCells[i];
		var columnName = headerCell.getAttribute('column_name');
		if (hidden[columnName.toLowerCase()])
		{
			if (hiddenCols == null)
				hiddenCols = '';
			else
				hiddenCols+=', ';
			if (tersus.useSQLQuotedIdentifiers)
				columnName = '"'+columnName+'"';	
			hiddenCols+=columnName;
		}
	}
	return hiddenCols;
};
Table.prototype['get<All Columns>'] =  function()
{
	var allCols = null;
	var headerCells = this.headerRow.childNodes;
	for (var i=0;i<headerCells.length;i++)
	{
		var headerCell = headerCells[i];
		var columnName = headerCell.getAttribute('column_name');
		if (tersus.useSQLQuotedIdentifiers)
			columnName = '"'+columnName+'"';
		if (allCols == null)
			allCols = '';
		else
			allCols+=',';
		allCols+=columnName;
	}
	return allCols;
};

Table.prototype.hideColumn = function(columnName)
{
	this.hiddenColumns[columnName] = 1;
	var headerCells = this.headerRow.childNodes;
	for (var i=0;i<headerCells.length;i++)
	{
		var headerCell = headerCells[i];
		var headerColumnName = headerCell.getAttribute('column_name');
		if (!tersus.useSQLQuotedIdentifiers)
			headerColumnName=headerColumnName.toLowerCase();
		if ( columnName == headerColumnName )
		{
			var cw = getVisibleSize(headerCell).width;
			headerCell.col.style.width = cw + 'px';
			if (this.viewNode.style.width)
			{
				var originalWidth = parseInt(this.viewNode.style.width);
				this.viewNode.style.width = (originalWidth-cw) + 'px';
			}

			this.updateColumnVisibility(i,false);
		
			if (this.colgroup == headerCell.col.parentNode)
				this.colgroup.removeChild(headerCell.col);
		}
	}
};
Table.prototype.showColumn = function(columnName)
{
	delete this.hiddenColumns[columnName];
	var headerCells = this.headerRow.childNodes;
	for (var i=0;i<headerCells.length;i++)
	{
		var headerCell = headerCells[i];
		var headerColumnName = headerCell.getAttribute('column_name');
		if (!tersus.useSQLQuotedIdentifiers)
			headerColumnName=headerColumnName.toLowerCase();
		if ( columnName == headerColumnName )
		{
			if (this.viewNode.style.width)
			{
				var cw = parseInt(headerCell.col.style.width);
				if (cw)
				{
					var originalWidth = parseInt(this.viewNode.style.width);
					this.viewNode.style.width = (originalWidth+cw) + 'px';
				}
			}
			else
				headerCell.col.style.width='';

			this.updateColumnVisibility(i,true);
		}
	}
}
Table.prototype.updateColumnVisibility = function(colNum,visible)
{
    var rowElement = this.getRowPrototype();
    var rowId = rowElement && rowElement.modelId;
	var rows = this.viewNode.rows;
	var colStyle = visible ? '' : 'none';

	this.headerRow.childNodes[colNum].style.display=colStyle;
	
	for (var j=0;j<rows.length; j++)
	{
	    var r = rows[j];
	    var n = DisplayNode.findNodeForDocumentNode(r);
	    if (n)
	    {
	    	var hc = null;
    		if (n.modelId === rowId)
    			hc = true;
    		else
    		{
	    		var hc = n.element.properties.enableHiddenColumns;
		    	if (hc == null)
		    		hc = n.sharedProperties.enableHiddenColumns;
		    	if (hc == null)
	    			hc = false;
    		}
		    if (r === this.headerRow || hc)
		    {
				var rowCells = r.childNodes;
				if (rowCells && rowCells[colNum])
					rowCells[colNum].style.display = colStyle;
		    }
	    }
	}

};
Table.prototype.setColWidths = function()
{
	var headerCells = this.headerRow.childNodes;
	for (var i=0;i<headerCells.length;i++)
	{
		var headerCell = headerCells[i];
		var c = headerCell.col;
		if (headerCell.style.display!='none')
		{
		    var w = $(headerCell).outerWidth();
		    
			c.style.width=w;
		}
	}

};
Table.prototype.rebuildColgroup = function()
{
	var headerCells = this.headerRow.childNodes;
	var cg = this.colgroup;
	var w= [];
	var cc = [];
	for (var i=0;i<headerCells.length;i++)
	{
		var headerCell = headerCells[i];
		var c = headerCell.col;
		if (cg == c.parentNode)
			cg.removeChild(c);
		if (headerCell.style.display!='none')
		{
			cg.appendChild(c);
		}
	}
//	this.currentWindow.setTimeout(function(){for (var i=0;i<w.length;i++) cc[i].style.width=w[i];},2000);
};	
Table.prototype.ensureColumnOrder = function (cell1, cell2) // ensures that cell2 is not before cell1
{
	var allSiblings = cell1.parentNode.childNodes;
	var i1=-1;
	var i2=-1;
	for (var i=0;i<allSiblings.length;i++)
	{
		if (allSiblings[i] == cell1)
			i1 = i;
		if (allSiblings[i] == cell2)
			i2 = i;
	}
	if (i2 < i1) // rearrage columns in the table so that cell2 appears right after cell1
	{
		this.moveCells(i2,i1+1);
	};
};
Table.isResizeLeft = function(e,headerCell)
{
	var offsets = getScreenPosition(headerCell);
	var win = getParentWindow(headerCell);
	var p = getEventPosition(win,e);
	return (p.x <= offsets.left +5);
};
Table.isResizeRight = function(e,headerCell)
{
	var offsets = getScreenPosition(headerCell);
	var size = getVisibleSize(headerCell);
	var win = getParentWindow(headerCell);
	var p = getEventPosition(win,e);
	return (p.x >= offsets.left + size.width -5);
};
Table.isResize = function(e, headerCell)
{
	return Table.isResizeRight(e,headerCell)
	 || headerCell.previousSibling && Table.isResizeLeft(e,headerCell);
};
Table.headerClicked = function(e)
{
	if (! Table.isResize(e,this))
	{
		var tableViewNode = this.parentNode.parentNode.parentNode;
		var tableNode = DisplayNode.findNodeForDocumentNode(tableViewNode);
		if (!tableNode)
			return;
		var win = tableNode.currentWindow;
		if (! getEventPosition(win,e).equals(tableNode.mouseDownPosition))
			return; // Ignore click if it's part of a drag operation
		var sort = this.getAttribute('sort');
		if (sort == 'up')
			tableNode.doSort(this,'down');
		else if (sort == 'down')
			tableNode.doSort(this,'none');
		else
			tableNode.doSort(this, 'up');
	}
};
Table.prototype.doSortNoFire = function(headerCell,dir)
{
	headerCell.setAttribute('sort',dir);
	headerCell.className = 'sort_'+dir;
};
Table.prototype.doSort = function(headerCell, dir)
{
	if (this.sharedProperties.sort == 'single')
	{
		var headerCells =headerCell.parentNode.childNodes;
		for (var i=0; i<headerCells.length; i++)
		{
			var other = headerCells[i];
			if (other !== headerCell)
				this.doSortNoFire(other,'none'); 
		}
	}
	
	this.doSortNoFire(headerCell,dir);
	this.fireOnSort();
}
Table.prototype.fireOnSort = function()
{
	this.mainWindow.engine.handleEvent(this, Events.ON_SORT);
};
Table.mouseDownOnHeader = function(e)
{
	var tableViewNode = this.parentNode.parentNode.parentNode;
	var tableNode = DisplayNode.findNodeForDocumentNode(tableViewNode);
	if (!tableNode)
		return;
	var offsets = getScreenPosition(this);
	var size = getVisibleSize(this);
	var win = tableNode.currentWindow;
	clearSelection(win);
	tableNode.mouseDownPosition  = getEventPosition(win,e);
	if (Table.isResizeLeft(e,this))
	{
		var previousCell = this.previousSibling;
		if (previousCell)
			tableNode.beginResize(e,previousCell);
	}
	else if (Table.isResizeRight(e,this))
		tableNode.beginResize(e,this);
	else
		tableNode.beginReorder(e,this);
};
Table.finishDrag = function (e)
{
	var table=tersus.findNode(this.documentElement.getAttribute('tableId'));
	this.documentElement.setAttribute('tableId', null);
	this.onmouseup = null;
	this.onmousemove = null;
	table.viewNode.className=table.baseClassName;
};
Table.updateHeaderCursor = function (e)
{
	var tableId = this.ownerDocument.documentElement.getAttribute('tableId');
	var table = null;
	if (tableId)
		table=tersus.findNode(tableId);
	if (table && table.reorder)
		this.style.cursor='';
	else
	{
		if (Table.isResize(e,this))
		{
			this.style.cursor='e-resize';
		}
		else if (this.getAttribute('sort'))
			this.style.cursor='pointer';
		else
			this.style.cursor='';
	}
};
Table.performResize = function (e)
{
	var table=tersus.findNode(this.documentElement.getAttribute('tableId'));
	var win = table.currentWindow;
	clearSelection(win);
	var currentPosition = getEventPosition(win,e);
	var delta = {};
	delta.x = currentPosition.x - table.lastPosition.x;
	delta.y = currentPosition.y - table.lastPosition.y;
	table.lastPosition = currentPosition;		
	table.resize(delta);
};
Table.prototype.beginResize = function beginResize(e, headerCell)
{
	this.setColWidths();
	var table = this;
	var win = this.currentWindow;
	clearSelection(win);
	var doc = win.document;
	doc.documentElement.setAttribute('tableId', this.getNodeId());
	table.lastPosition = getEventPosition(win, e);
	table.viewNode.className+=' resizing';
	table.resizingHeaderCell = headerCell;
	table.currentColWidth = getVisibleSize(headerCell).width;
	table.currentTableWidth = getVisibleSize(table.viewNode).width;
	doc.onmousemove = Table.performResize;
	doc.onmouseup = Table.finishDrag;
};
Table.prototype.beginReorder = function beginReorder(e, headerCell)
{
	var table = this;
	var win = this.currentWindow;
	clearSelection(win);
	var doc = win.document;
	var feedback = doc.createElement('div');
	feedback.className='drag_feedback';
	doc.documentElement.setAttribute('tableId', this.getNodeId());
	table.reorder = {};
	table.reorder.feedback =feedback;
	table.reorder.headerCell = headerCell;
	table.reorder.startPosition = getEventPosition(win,e);;
	
	doc.onmousemove = Table.feedbackReorder;
	doc.onmouseup = Table.finishReorder;
};

Table.prototype.cancelReorder = function()
{
	if (! this.reorder)
		return;
	if (this.reorder.feedback.parentNode)
		this.reorder.feedback.parentNode.removeChild(this.reorder.feedback);
	this.reorder = null;
	var doc = this.currentWindow.document;
	doc.documentElement.setAttribute('tableId', null);
	doc.onmouseup = null;
	doc.onmousemove = null;
};
Table.finishReorder = function (e)
{
	var table=tersus.findNode(this.documentElement.getAttribute('tableId'));
	if (! table.reorder)
		return;
	var win = table.currentWindow;
	clearSelection(win);
	var headerCell = table.reorder.headerCell;
	var startX = table.reorder.startPosition.x;
	table.cancelReorder();
	var p = getEventPosition(win,e);
	var fromIndex=-1;
	var toIndex =-1;
	if (p.x != startX)
	{
		var headerCells =headerCell.parentNode.childNodes;
		for (var i=0;i<headerCells.length; i++)
		{
			var cell = headerCells[i];
			if (cell.style.display=='none')
				continue;
			if (cell == headerCell)
				fromIndex = i;
			else if (toIndex < 0)
			{
				var left = getScreenPosition(cell).left;
				var width = getVisibleSize(cell).width;
				if (p.x >= left && p.x <left+width)
				{ 
					if (p.x > left+width/2 )
					{
						toIndex = i+1;
					}
					else
						toIndex = i;
				}
			}
		}
		if (toIndex != -1 && toIndex != fromIndex && toIndex != fromIndex+1)
		{
			var originalSortOrder = table.getSortOrder();
			table.moveCells(fromIndex,toIndex);
			var newSortOrder = table.getSortOrder();
			if (originalSortOrder != newSortOrder)
			{
				table.fireOnSort();
			}
		}
	}
};
Table.move = function (parent, from, to)
{
	var children = parent.childNodes;
	var childFrom = children[from];
	var childTo = null;
	if (to < children.length)
	{
		childTo = children[to];
	}
	parent.insertBefore(childFrom,childTo);
};
Array.prototype.moveItem = function(fromIndex,toIndex)
{
	var item=this.splice(fromIndex,1)[0]; 
	var newIndex = (fromIndex<toIndex) ? toIndex-1: toIndex;
	this.splice(newIndex,0, item);
};
Table.prototype.moveCells = function (fromIndex,toIndex)
{
	this.reorderColGroup(fromIndex, toIndex);
	var rows = this.viewNode.rows;
	for (var i=0;i<rows.length; i++)
		Table.move(rows[i],fromIndex, toIndex);

	//Update the 'colOrder' permutation		
	if (!this.colOrder)
	{
		this.colOrder = [];
		for (var i=0;i<this.headerRow.childNodes.length;i++)
		{
			this.colOrder.push(i);
		}
	}
	this.colOrder.moveItem(fromIndex,toIndex);
};
Table.prototype.reorderColGroup = function(fromIndex, toIndex)
{
	// Since there are no 'col' elements for hidden columns, we need to correct the indices
	var headerCells  = this.headerRow.childNodes;
	var from = fromIndex;
	var to = toIndex;
	for (var i=0;i<headerCells.length;i++)
	{
		var c = headerCells[i];
		if (c.style.display == 'none')
		{
			if (i<=fromIndex)
				--from;
			if (i<=toIndex)
				--to;
		}
	}
	Table.move(this.colgroup, from, to);
};
Table.feedbackReorder = function (e)
{
	var table=tersus.findNode(this.documentElement.getAttribute('tableId'));
	var win = table.currentWindow;
	clearSelection(win);
	var headerCell = table.reorder.headerCell;
	var headerCellSize = getVisibleSize(headerCell);
	var p = getEventPosition(win,e);
	var o = getScreenPosition(table.viewNode);
	var w = getVisibleSize(table.viewNode).width;
	var h = getVisibleSize(table.viewNode).height;
	if( p.y<o.top || p.y > o.top+h || p.x<o.left || p.x > o.left + w)
	{
		table.cancelReorder();
		return;
	}
	
	var feedback = table.reorder.feedback;
	var body = win.document.body;
	if (!feedback.parentNode )
	{
		body.appendChild(feedback);
		feedback.innerHTML = headerCell.innerHTML;
		tersus.async.exec(function()
		{
			var d= (window.browser == 'Mozilla')?-2:0; // Probably needs fixing (box-sizing issue on old browsers)
			$(feedback).css({top: getScreenPosition(headerCell).top+d+body.scrollTop
			                    ,left: p.x+body.scrollLeft
			                    ,width: headerCellSize.width
			                    ,height:headerCellSize.height});
		}, false /* don't wait */)
	}
	else
	{
		$(table.reorder.feedback).css('left',p.x+body.scrollLeft);
	}
};
Table.prototype.resize = function(delta)
{
    var MIN_WIDTH=10;
	this.currentColWidth += delta.x;
	this.currentTableWidth += delta.x;
	var table = this;
	if (this.currentColWidth> MIN_WIDTH)
	    setTimeout(function() {table.resizingHeaderCell.col.style.width = table.currentColWidth+'px';table.viewNode.style.width=table.currentTableWidth+'px'},10);
};

// file: 115-Page.js
(function( $, undefined ) {
	var setter=tersus.setter;
	

tersus.Widget('Page','HTMLTag',{
	defaultTag:'div'
	,defaultWrapperTags:'div'
	,isPage:true
	,prepareForHTML:function(e,parent)
	{
		$(this.displayElements).each(
			function(i) {
				var dataRole = {'<Header>':'header','<Footer>':'footer','<Content>':content}[this.role];
				if (dataRole)
					this.properties = $.extend({'data-role':dataRole},this.properties);
				});
		return tersus.HTMLTag.prototype.prepareForHTML.call(this,e,parent);
	}
	,getScrollContainer:function()
	{
		if (!this.scrollContainer)
		{
			var $v=$(this.viewNode);
			var $s=$v.wrapInner('<div class="tersus-scroll-container"><div class="tersus-scroll-content"/></div>').find('.tersus-scroll-container');
			this.scrollContainer  = $s[0];
		}
		return this.scrollContainer;
	}
	,onBeforeScrollStart:function(e) /*iScroll Hook to detect cases where we don't want to scroll*/
	{
		if (   e.target.tagName == "SELECT"
            || e.target.tagName == "INPUT"
            || e.target.tagName == "BUTTON"
            || e.target.tagName == "A"
            || e.target.tagName == "TEXTAREA") {
            return true;
        }
		e.preventDefault();
		
	}
	,attach:function()
	{
		if (window.iScroll && this.sprop('scroll')!=false)
		{
			var sc=this.getScrollContainer();
			if (sc)
			{
				var self = this;
				$(sc).find('input').bind('vclick',function(){self.onResize();});
	//			this.iscroll = new iScroll(sc,{vScrollbar:false});
				this.iscroll = new iScroll(sc,{vScrollbar:false, onBeforeScrollStart:this.onBeforeScrollStart});
				var id=this.getNodeId();
				$(window).bind('ter-process-end', function(){setTimeout(
				function()
				{
					var n = tersus.findNode(id);
					if (n && n.iscroll)
					{
						n.iscroll.refresh();
					}
				}
				,1000)});
			}
		}
		
	}
	,refresh:function()
	{
	    var wasActive = $(this.viewNode).hasClass('ui-page-active');
	    tersus.HTMLTag.prototype.refresh.call(this);
	    $(this.viewNode).pageUpdate();		
	    if (this == this.parent.selectedPage)
		$(this.wrapperNode).addClass('ter-tp-active');
	    if (wasActive)
		$(this.viewNode).addClass('ui-page-active');
		
		
	}
	,destroy:function()
	{
//		if (this.iscroll)
//			this.iscroll.destroy();
		tersus.HTMLTag.prototype.destroy.call(this);
	}
	,onResize:function()
	{	
		//Set min-height on page content, based on explicit min-height on viewNode or wrapperNode
		var $v = $(this.viewNode);
		
		var c = this.wrapperNode || this.viewNode;
		var h;
/*		while (c.style && ! c.style.height)
			c = c.parentNode;
		if (c.style && c.style.height)
			h = parseInt(c.style.height);*/
		while (c && c.style && ! c.style.height)
			c = c.parentNode;
	        if (c && c.style && c.style.height)
		   h = parseInt(c.style.height);

		if (!h)
			h = $v.outerHeight(); // In certain dialogs the relevant height is on viewNode and not wrapperNode	
		var $c = $v.find('.ui-content');
		var bh = $c.outerHeight(true)-$c.height();
		var fh = 0; $v.find('.ui-footer,.ui-header,.ter-footer,.ter-header').each(function(index){ fh+=$(this).outerHeight();});
		$c.css('min-height',h-bh-fh);
		var s = this.iscroll;
		if (s)
		{
			var sc = this.getScrollContainer();
			$(sc).height(h);
			setTimeout(function(){s.refresh();},100);
		}
		this.onResizeChildren();	
	}
});

})(jQuery);

// file: 120-Row.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Row() {};
Row.prototype = new DisplayNode();
Row.prototype.constructor = Row;
Row.prototype.defaultTag = 'tr';
Row.prototype.attachViewNode = function Row_createViewNode()
{
	this.setDisplayOrder();
	if (this.parent.viewNode.tagName != 'TABLE')
	{
		this.tableNode  = this.createHTMLElement('table');
		this.tbodyNode = this.createHTMLElement('tbody');
		this.tableNode.setAttribute('display_order',this.viewNode.getAttribute('display_order'));
		this.tableNode.appendChild(this.tbodyNode);
		this.tbodyNode.appendChild(this.viewNode);
		if(this.sharedProperties.width != undefined && this.sharedProperties.width != ' ')
			this.tableNode.style.width = this.sharedProperties.width;
		if (this.sharedProperties.styleClass != undefined && this.sharedProperties.styleClass != ' ')
			this.tableNode.className = this.sharedProperties.styleClass;
		else if (this.defaultStyleClass)
			this.tableNode.className = this.defaultStyleClass;
			
		var rowNode = this.viewNode;
		
		// We temporarily set the view node to the table node, because this is the node
		// we want to append to the parent
		
		// This is not very clean, and it would have probably have been more elegant
		// if we distinguished between 'contentNode' and 'viewNode', but this refactoring is currently 
		// out of scope, especially because we'll have to decide what to do with
		// things like style class etc. (which currently apply to the content node)
		// We have to be careful with backward compatability.
		
		// We DON'T simply append our table to the parent view node, because the parent node
		// may have special logic in appendChildViewNode - specifically - we want to retain the behavior of DisplayGroup.

		this.viewNode = this.tableNode;
		this.parent.appendChildViewNode(this);
		this.viewNode = rowNode;		
	}
	else
	{
		this.parent.appendChildViewNode(this);
	}
	if (this.parent.sharedProperties.zebraTable == true)
	{
		var v = this.viewNode;
		var parity = v.parentNode.childNodes.length & 1;
		var cn = v.className;
		cn = cn ? cn : '';
		this.extraClassName =  (parity ? ' odd':' even');
		v.className = cn + this.extraClassName; 
	}
}
Row.prototype.setEventHandlers = function Row_setEventHandlers()
{
	DisplayNode.prototype.setEventHandlers.call(this);

	if (this.isSelectable())	
		this.registerEventHandler(Events.ON_CLICK);	
};
Row.prototype.isSelectable = function()
{
	return this.sharedProperties.selectable==true || this.parent.sharedProperties.selectable==true; 
}
Row.prototype.select = function()
{
	if (this.isSelectable())
	{
		var table = this.parent;
		table.select(this);
	}
};
Row.prototype.onClick = function (domNode, callback)
{
	this.select();
	DisplayNode.prototype.onClick.call(this,domNode, callback);
};
Row.prototype.onChildFocus = function (child)
{
	this.select();	
};
Row.prototype.onDelete = function ()
{
	DisplayNode.prototype.onDelete.call(this);
	if (this.parent.selectedRow == this)
		this.parent.selectedRow = null;
};
Row.prototype.removeChildViewNode = function removeChildViewNode(child)
{
	var c = child.viewNode;
	var p = this.viewNode;
	if (c.parentNode == p) // c is a cell (TD or TH)
		p.removeChild(c);
	else if (p == c.parentNode.parentNode) // c is wrapped in a cell
		p.removeChild(c.parentNode);
};

Row.prototype.appendChildViewNode = function appendChildViewNode(child, childElement)
{
	if (!childElement)
		childElement = child.element;
	var cellNode;
	if (child.viewNode.tagName == 'TD' || child.viewNode.tagName == 'TH')
		cellNode = child.viewNode;
	else
	{
		var cellNode = this.createHTMLElement('td');
		cellNode.setAttribute('display_order',child.viewNode.getAttribute('display_order'));
		cellNode.appendChild(child.viewNode);
	}
	if (child.element && child.element.properties)
	{
		var elementProperties = child.element.properties;
		if (tersus.isNumber(elementProperties.colSpan))
			cellNode.colSpan = elementProperties.colSpan;
		if (tersus.isNumber(elementProperties.rowSpan))
			cellNode.rowSpan = elementProperties.rowSpan;
		if (tersus.notEmpty(elementProperties.cellWidth))
			cellNode.style.width=elementProperties.cellWidth;
		if (elementProperties.cellStyleClass && elementProperties.cellStyleClass != ' ')
			cellNode.className=elementProperties.cellStyleClass;
	}
	if (child.colSpan)
		cellNode.colSpan = child.colSpan;
	DisplayNode.appendChildNode(this.viewNode,cellNode);
	if (cellNode.parentNode.childNodes.length == 1)
	{
		var c = cellNode.className;
		c = c + ' first';
		cellNode.className=c;
		if (cellNode == child.viewNode)
		{
			child.baseClassName = cellNode.className;
			child.extraClassName = ' first';
		}
	}
	var p = this.parent;
	if (p.applyColOrder && p.headerRow && this.viewNode.childNodes.length == p.headerRow.childNodes.length)
	{
		p.applyColOrder(this.viewNode);
	}
	if (p.hiddenColumns != null && p.hiddenColumns[p.columnNames[childElement.role]] != null)
		cellNode.style.display='none';
};

Row.prototype.deleteMe = function()
{
	DisplayNode.prototype.deleteMe.call(this);
	if (this.parent && this.parent.selectedRow == this)
		this.parent.selectedRow = null;
};
// file: 130-Popup.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
//Popup - opens a pop-up window

function Popup() {};
Popup.prototype = new DisplayNode();
Popup.prototype.constructor = Popup;
Popup.prototype.create = function create_popup()
{
	alert('Popup '+this.element.role+' ('+this.modelId+') created');
	ikkk();
};
Popup.WAITING_TO_POP_UP = 'Waiting to pop-up';
Popup.POPPED_UP = 'Popped-up';
Popup.prototype.isPopup = true;
Popup.prototype.start = function()
{
	this.popupStatus = Popup.WAITING_TO_POP_UP;
	tersus.popupNodes[this.getNodeId()]=this;
	this.pause(); // Processing will start once the pop up loads
	this.currentWindow = this.createWindow();
	tersus.registerWindow(this.currentWindow);
	if (! this.currentWindow)
	{
		alert('Your browser blocks pop-up windows.\nTo use this application, please configure the browser to allow this site to open pop-up windows.');
		return;
	}
	this.currentWindow.focus();
}
Popup.prototype.findById = function popup_FindById(id, alreadyScanned)
{
	//Traverse the popup only if its window is open
	if (this.currentWindow && ! this.currentWindow.closed)
		return tersus.Node.prototype.findById.call(this,id, alreadyScanned);
	else
		return null;
};

// resume() is overriden to support the initial pause while waiting for the popup to pop)
Popup.prototype.resume = function resumePopup()
{
	if (this.popupStatus == Popup.WAITING_TO_POP_UP)
	{
		this.popupStatus = Popup.POPPED_UP;
		this.currentWindow.currentRootDisplayNode = this;
		this.currentWindow.focus();
		tersus.createEventDispatchers(this.currentWindow);
		this.setViewNode();
		this.createChildren();
		FlowNode.prototype.start.call(this);
		var node = this;
		this.currentWindow.setTimeout(function(){node.focusOnFirstField();}, 100);
	}
	else
	{
		this.runLoop();
	}
};
Popup.prototype.getPopupTitle = function getPopupTitle()
{
	return this.getCaption();
};

Popup.prototype.setTitle = function()
{
	try
	{
		if (this.currentWindow && ! this.currentWindow.closed)
		{
			this.currentWindow.document.title = this.getPopupTitle();
			if (this.header)
				this.header.innerHTML = tersus.escapeHTML(this.getPopupTitle());
		}	
	}
	catch (e)
	{
	}
};
Popup.prototype.captionChanged = Popup.prototype.setTitle;
Popup.prototype.setViewNode = function setViewNode()
{
	this.viewNode = this.currentWindow.document.getElementById('dialogBody');	
	if (this.viewNode)
	{
		this.header = this.currentWindow.document.getElementById('dialogHeader');
		this.footer = this.currentWindow.document.getElementById('dialogFooter');
	}
	else
	{
		this.viewNode = this.currentWindow.document.getElementById('root');	
		if (! this.viewNode)
			this.viewNode = this.currentWindow.document.body;
	}
	this.setTitle();
	var nodeId = this.getNodeId();
	this.isOpen = true;
	this.onResize();
};
Popup.prototype.templateURL = document.compatMode == 'BackCompat' ? 'popup.quirksmode.html' : 'popup.html';
Popup.prototype.createWindow = function Popup_createWindow(){
	if (this.sprop('templateURL'))
		this.templateURL = this.sprop('templateURL');
	
	var options = this.sharedProperties.windowOptions;
	if (! options)
		options = 'toolbar=no,location=no,status=no,menubar=no,scrollbars=yes,resizable=yes';
	var w = this.sharedProperties.windowWidth;
	if ( ! w || w == ' ')
		w = 350;
	var h = this.sharedProperties.windowHeight;
	if (! h || h == ' ')
		h = 265;
	var leftPx = parseInt((screen.availWidth-w-10)/2);
	var topPx = parseInt((screen.availHeight-h-30)/2);
	if (leftPx<0) leftPx=0;
	if (topPx<0) topPx=0;
	var targetWindow = this.getTargetWindow();
	var skeletonURL = tersus.rootURL+this.templateURL+'?nodeId='+this.getNodeId();
	this.currentWindow.mainTersusWindow = this.mainWindow;
	var popup = this.currentWindow.open(skeletonURL,targetWindow,"top="+topPx+",left="+leftPx+",width=" + w + ",height=" + h+","+options); 
	return popup;
};

Popup.prototype.getTargetWindow = function getTargetWindow()
{
	//TODO support mutltipe popup windows
	if (this.sharedProperties.targetWindow && this.sharedProperties.targetWindow!=' ')
		return this.sharedProperties.targetWindow;
	else if (this.currentWindow == this.mainWindow)
		return "popup";
	else
		return this.currentWindow.name+"_popup";
};
Popup.prototype.destroy = function()
{
	if (! this.isDestroyed)
	{
		this.isDestroyed = true;
		DisplayNode.prototype.destroy.call(this);
		this.doClose();
	}
};
Popup.prototype.closeWindow = function() 
{
	this.destroyHierarchy();
};
Popup.prototype.doClose = function ()
{
	delete tersus.popupNodes[this.getNodeId()];
	tersus.unregisterWindow(this.currentWindow);
	if (this.currentWindow && ! this.currentWindow.closed)
		this.currentWindow.close();
	this.isOpen = false;
	this.viewNode = null;
	this.footer = null;
	this.header = null;
};
Popup.prototype.onResize = function()
{
	if (! (this.isOpen && this.currentWindow && ! this.currentWindow.closed))
		return;
	var d = this.viewNode.ownerDocument;
	var s = getViewportSize(d);
	if (this.lastSize && this.lastSize.height == s.height && this.lastSize.width == s.width)
		return; // no change in size - nothing to do
	this.lastSize = s;
	var height = s.height;	 //client height of body
	var delta = d.getElementById('root').offsetHeight - this.viewNode.clientHeight;

	//Because clientHeight includes padding, but style.height doesn't include padding, we need to add padding to delta
	delta += getMeasure(this.viewNode,'padding-bottom');
	delta += getMeasure(this.viewNode,'padding-top');

	
	
	//Similarly, we need to remove body padding from the available height
	height -= parseInt(getActualStyle(d.body,'margin-bottom'));
	height -= parseInt(getActualStyle(d.body,'margin-top'));
//	height-=1;
	//alert(s.height+' ;'+height);
	var newHeight = height-delta;
	if (newHeight>0 && newHeight < 3000)
	{
		this.viewNode.style.height = newHeight+'px';
	}
	this.onResizeChildren();
};
Popup.prototype.getValidationContext = function Popup_getValidationContext()
{
	return this;
};
Popup.prototype.computedReadOnly = function Popup_computedReadOnly()
{
	return this.explicitReadOnly;
};
Popup.prototype.parentReadOnlyChanged = function Popup_parentReadOnlyChanged(readOnly)
{
};

// file: 131-Popin.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.PopIn = function tersus_PopIn(){};
tersus.PopIn.prototype = new Popup();
tersus.PopIn.prototype.constructor = tersus.PopIn;
tersus.PopIn.prototype.isPopIn = true;
tersus.PopIn.prototype.templateURL='popin.html';
tersus.PopIn.prototype.onload = function()
{
	Popup.prototype.onload.call(this);
	if (this.sprop('templateURL'))
		this.templateURL = this.sprop('templateURL');
	tersus.repository.loadHTMLTemplate(this.templateURL);
};

tersus.PopIn.prototype.create = function () {
	alert('Pop-in created');
}
tersus.PopIn.prototype.getCurrentRootViewNode = function()
{
	var root;
	var doc = this.currentWindow.document;
	root = doc.getElementById('root');
	if (! root)
		root = doc.getElementById('tersus.content');
	return root;
};
tersus.PopIn.prototype.setTitle = tersus.PopIn.prototype.captionChanged = function()
{
    if (this.header)
        this.header.innerHTML = tersus.escapeHTML(this.getCaption());
};
tersus.PopIn.prototype.createViewNode = function() 
{
	var w = this.currentWindow;
	var doc = w.document;
	clearSelection(w);
	this.originalRoot = this.getCurrentRootViewNode();
	this.originalRootDisplayNode = w.currentRootDisplayNode;
	w.currentRootDisplayNode = this;
	var template = tersus.repository.getHTMLTemplate(this.templateURL);
	var newRoot = importNode(doc,template);
	newRoot.id = 'root';
	this.originalRoot.parentNode.replaceChild(newRoot, this.originalRoot);
	this.originalBodyStyle = doc.body.className;
	if (this.originalBodyStyle == '')
		doc.body.className = 'popin';
	else if (! this.originalBodyStyle.match(/popin/))
		doc.body.className='popin '+this.originalBodyStyle;
	this.setViewNode();
};
tersus.PopIn.prototype.disableNavigation = function()
{
	this.previousFixedURL  = tersus.history.fixedURL;
	if (this.sharedProperties.disableNavigation != false)
	{
		tersus.history.fixedURL = window.location.href;
	}
	else
		tersus.history.fixedURL = null;
	
	
};

tersus.PopIn.prototype.resumeNavigation = function()
{
	tersus.history.fixedURL = this.previousFixedURL;
};

tersus.PopIn.prototype.doClose = function()
{
	delete tersus.popupNodes[this.getNodeId()];
	
	if (this.isOpen)
	{
		this.resumeNavigation();
		var doc = this.currentWindow.document;
		var currentRoot = doc.getElementById('root');
		currentRoot.parentNode.replaceChild(this.originalRoot, currentRoot);
		doc.body.className=this.originalBodyStyle;
		this.currentWindow.currentRootDisplayNode = this.originalRootDisplayNode;
		this.viewNode = null;
		this.footer = null;
		this.header = null;
		
	}
	this.isOpen = false;
};

tersus.PopIn.prototype.start = function()
{
	tersus.popupNodes[this.getNodeId()]=this;
	this.disableNavigation();
	this.createViewNode();
	this.initViewNode();
	if (!this.initElement)
		this.createChildren();
	this.isOpen = true;
	FlowNode.prototype.start.call(this);
	var node = this;
	if (tersus.isIPhone)
		window.scrollTo(0,1);
	var activeElement = this.currentWindow.document.activeElement;

	// Remove focus to prevent selection from "smearing" into popin.  Do not blur BODY as in IE7 it causes the browser window to be pushed back
	if (activeElement && activeElement.blur && activeElement.tagName != 'BODY')
		activeElement.blur();
	this.currentWindow.setTimeout(function(){node.focusOnFirstField();}, 100);
	
};
tersus.PopIn.prototype.findById = function tersus_popIn_FindById(id, alreadyScanned)
{
	//Traverse the popup only if its window is open
	if (this.isOpen)
		return tersus.Node.prototype.findById.call(this,id, alreadyScanned);
	else
		return null;
};

// file: 140-Pane.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function Pane() {};
Pane.prototype = new DisplayNode();
Pane.prototype.constructor = Pane;
Pane.prototype.defaultTag = 'div';
Pane.prototype.minHeight = 50;
Pane.prototype.setHeight = function(newHeight)
{
	this.viewNode.style.height = newHeight;
};
Pane.prototype.adjustBottom = function()
{
	var d = this.viewNode.ownerDocument;
	var body = this.viewNode.ownerDocument.body;
	var height = getVisibleSize(body).height;
	var margins = parseInt(getActualStyle(body,'margin-top'))+parseInt(getActualStyle(body,'margin-bottom'));
	height-=margins;

	var currentHeight = getVisibleSize(this.viewNode).height;
	var currentBottom = getOffsets(this.viewNode).top + currentHeight;
	if (window.browser != 'IE')
	{
		var paddingBottom = parseInt(getActualStyle(this.viewNode,'padding-bottom'));
		var paddingTop = parseInt(getActualStyle(this.viewNode,'padding-top'));
		currentBottom += paddingBottom + paddingTop;
	}
	
	var bottomMargin = tersus.isNumber(this.sharedProperties.adjustBottomMargin) ? parseInt(this.sharedProperties.adjustBottomMargin) :0;
	var delta = height-currentBottom - bottomMargin;
	
	if (delta+currentHeight >= this.minHeight)
		this.adjustHeight(delta);
};
Pane.prototype.adjustHeight = function(delta)
{
	tersus.adjustHeight(this.viewNode, delta);
};

Pane.prototype.setProperties = function()
{
	DisplayNode.prototype.setProperties.call(this);
	var pane = this;
	if (this.sharedProperties.adjustBottom == true)
		tersus.async.exec(function() {pane.onResize();}, false /* don't wait */);
};
Pane.prototype.onResize = function()
{
	if (this.sharedProperties.adjustBottom == true)
		this.adjustBottom();
	DisplayNode.prototype.onResize.call(this);
};
// file: 150-DisplayGroup.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.DisplayGroup = function () {};
tersus.DisplayGroup.prototype = new DisplayNode();
tersus.DisplayGroup.prototype.constructor = tersus.DisplayGroup;
tersus.DisplayGroup.prototype.isDisplayGroup = true;
tersus.DisplayGroup.prototype.createViewNode = function ()
{
	
};
tersus.DisplayGroup.prototype.initViewNode = function ()
{
	
};
tersus.DisplayGroup.prototype.attachViewNode = function ()
{
	this.viewNode = this.parent.viewNode;
};
tersus.DisplayGroup.prototype.removeChildViewNode = function (child)
{
	if (this.parent)
		this.parent.removeChildViewNode(child);
};
tersus.DisplayGroup.prototype.addChildHTMLPrefix = function (htmlV, child)
{
	if (this.parent)
		this.parent.addChildHTMLPrefix(htmlV,child);
};
tersus.DisplayGroup.prototype.addChildHTMLSuffix = function (htmlV, child)
{
	if (this.parent)
		this.parent.addChildHTMLSuffix(htmlV,child);
}
tersus.DisplayGroup.prototype.appendChildViewNode = function (child)
{
	var displayOrder = this.element.displayOrder + child.viewNode.getAttribute('display_order')*0.01;
	child.viewNode.setAttribute('display_order',displayOrder);
	this.parent.appendChildViewNode(child,this.element);
	child.refreshVisibility();
};
tersus.DisplayGroup.prototype.refreshVisibility = function ()
{
	this.forDisplayChildren( function(child) {child.refreshVisibility();});
};

tersus.DisplayGroup.prototype.isGroup = true;
tersus.DisplayGroup.prototype.onDelete = function()
{
	this.forDisplayChildren( function(child) {child.onDelete();});
};
tersus.DisplayGroup.prototype.applyColOrder = function(row)
{
	if (this.parent.applyColOrder)
		this.parent.applyColOrder(row);
};

// file: 160-PushButton.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.PushButton = function (){};
tersus.PushButton.prototype = new DisplayNode();
tersus.PushButton.prototype.defaultTag = 'span';
tersus.PushButton.prototype.getButtonName = function ()
{
	return null;
};
tersus.PushButton.prototype.initViewNode = function tersus_PushButton_initViewNode()
{
    DisplayNode.prototype.initViewNode.call(this);
    this.updateSelfReadOnly(this.computedReadOnly());
};

tersus.PushButton.prototype.createViewNode = function ()
{
    var name = this.getButtonName();
    var $button=$('<input>',this.currentWindow.document).attr('type',this.buttonType).attr('data-role','none').addClass(this.buttonType);
    if (name != null)
    	$button.attr('name',name);
    this.button = $button[0];
    if (this.getElement('<Caption>'))
    {
    	DisplayNode.prototype.createViewNode.call(this);
    	this.viewNode.appendChild(this.button);
    	this.label = this.createHTMLElement('span',this.buttonType+'Label');
    	this.label.innerHTML = tersus.escapeHTML(this.getCaption());
    	this.viewNode.appendChild(this.label);
    }
    else
    	this.viewNode = this.button;
};
tersus.PushButton.prototype.getChecked = tersus.PushButton.prototype['get<Checked>'] = function ()
{
	if (this.viewNode)
		return this.button.checked;
};
tersus.PushButton.prototype.setChecked = tersus.PushButton.prototype['set<Checked>'] = function (value)
{
	if (this.viewNode)
		this.button.checked = value;
	if (window.browser=='IE')
	{
		// In IE 6.0, setting 'checked' before the button is rendered 
		// has no visual effect
		var button = this.button;
		tersus.async.exec(function(){ button.checked = value;}, false /* don't wait */);
	}
};
tersus.PushButton.prototype['remove<Checked>'] = function ()
{
	if (this.viewNode)
		this.button.checked = false;
};

tersus.PushButton.prototype.getClickTarget = function()
{
	return this.button;
};
tersus.PushButton.prototype.setEventHandlers = function()
{
	this.registerEventHandler(Events.ON_CLICK, this.button);
	if (this.label)
		this.registerEventHandler(Events.ON_CLICK, this.label);
};

tersus.PushButton.prototype.onClick = function(domNode, callback)
{
	if (domNode == this.button)
	{
		DisplayNode.prototype.onClick.call(this, domNode, callback);
		this.onChange(domNode, callback);
	}
	else if (domNode == this.label)
		this.labelClicked(domNode, callback);
};

tersus.PushButton.prototype.captionChanged = function()
{
	if (this.label)
		this.label.innerHTML = tersus.escapeHTML(this.getCaption());
};
tersus.PushButton.prototype.updateSelfReadOnly = function tersus_PushButton_updateSelfOnly(readOnly)
{
	if (this.currentReadOnly == readOnly)
		return; // no change
	this.currentReadOnly = readOnly;
	if (this.button)
	{
		if (readOnly)
		{
			this.button.disabled = true;
		}
		else
			this.button.disabled = false;
	}
};

// file: 170-SplitPane.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function SplitPane() {};
SplitPane.prototype = new Pane();
SplitPane.prototype.constructor = SplitPane;
SplitPane.prototype.defaultTag = 'div';
SplitPane.prototype.defaultStyleClass = 'splitPane';
SplitPane.prototype.height=400;
SplitPane.prototype.minWidth=50;
SplitPane.prototype.leftWidth = 200;
SplitPane.prototype.borderWidth=1;
SplitPane.prototype.paddingWidth=5;
SplitPane.prototype.dividerThickness=5;
SplitPane.prototype.contentPaneStyle = "splitPaneContent";
SplitPane.prototype.dividerStyle = "splitPaneDivider";
SplitPane.prototype.setDimensions = function()
{
	if (this.sharedProperties.height)
		this.height =parseInt(this.sharedProperties.height);
	this.setHeight(this.height);
	this.divider.style.width = this.dividerThickness + 'px';
	if (this.sharedProperties.leftPaneWidth)
	{
		this.leftWidth=parseInt(this.sharedProperties.leftPaneWidth);
	}
	
};
SplitPane.prototype.setHeight = function(height)
{
	this.height = height;
	this.viewNode.style.height = '';
	this.pane1.style.height = '';
	this.pane2.style.height = '';
	this.viewNode.style.height = this.height+ 'px';
	this.setPaneHeight(this.pane1,this.height);
	this.setPaneHeight(this.pane2,this.height);
	this.divider.style.height = this.height+ 'px';
};
SplitPane.prototype.createViewNode = function createViewNode()
{
	DisplayNode.prototype.createViewNode.call(this);
	if (this.sharedProperties.paddingWidth)
		this.paddingWidth =parseInt(this.sharedProperties.paddingWidth);
	if (this.sharedProperties.borderWidth)
		this.borderWidth =parseInt(this.sharedProperties.borderWidth);
	this.viewNode.style.borderWidth = this.borderWidth;
	
	this.pane1 = this.createHTMLElement('div');
	this.pane2 = this.createHTMLElement('div');
	this.divider = this.createHTMLElement('div');
	this.direction = getActualStyle(this.currentWindow.document.body, 'direction');
	this.setPaneProperties(this.pane1);
	this.setPaneProperties(this.pane2);
	this.divider.className = this.dividerStyle;
	if (this.direction == 'rtl')
		this.divider.className+=' rtl';
	
	this.divider.setAttribute('SplitPaneId', this.getNodeId());
	this.setDimensions();
	this.attachContent();
	var splitPane = this;
	this.divider.onmousedown = SplitPane.beginDrag;
	tersus.async.exec( function() {splitPane.onResize();}, false /* don't wait */);
};

SplitPane.prototype.reset = function reset()
{
	DisplayNode.prototype.reset.call(this);
	this.pane1 = null;
	this.pane2 = null;
	this.viewNode.innerHTML='';
};
SplitPane.prototype.appendChildViewNode = function appendChildViewNode(child)
{
	if (! this.leftPaneContent)
	{
		this.leftPaneContent = child.viewNode;
		this.pane1.appendChild(this.leftPaneContent);
	}
	else if (! this.rightPaneConent)
	{
		this.rightPaneContent = child.viewNode;
		this.pane2.appendChild(this.rightPaneContent);
	}
	else
		modelError('More than 2 child nodes in '+this.modelId + ' (path = '+this.getPath()+')');
	
};
SplitPane.prototype.setPaneProperties = function setPaneProperties(pane, width)
{
		pane.className=this.contentPaneStyle;
		if (this.direction == 'rtl')
			pane.className+=' rtl';
		
		pane.style.padding = this.paddingWidth + 'px';

};
SplitPane.prototype.detachContent = function detachContent()
{
	if (this.contentAttached)
	{
		this.contentAttached = false;
		if (this.pane1.parentNode == this.viewNode)
			this.viewNode.removeChild(this.pane1);
		if (this.divider.parentNode == this.viewNode)
			this.viewNode.removeChild(this.divider);
		if (this.pane2.parentNode == this.viewNode)
			this.viewNode.removeChild(this.pane2);
	}
};
SplitPane.prototype.attachContent = function attachContent()
{
	if (! this.contentAttached)
	{
		this.contentAttached = true;
		this.viewNode.appendChild(this.pane1);
		this.viewNode.appendChild(this.divider);
		this.viewNode.appendChild(this.pane2);
	}
};

SplitPane.prototype.onResize = function onResize()
{
	if (this.contentAttached && ! this.resizing && this.viewNode.offsetWidth > 0)
	{
		this.resizing = true;
		if (this.sharedProperties.height)
			this.setHeight(parseInt(this.sharedProperties.height));
		else
		{
			var node = this.viewNode.parentNode;
			while (node && node.style)
			{
				var parentHeight = node.clientHeight;
				if (parentHeight)
				{
					this.setHeight(parentHeight-2*this.borderWidth);
					break;
				}
				node = node.parentNode;
			}
		}
		var parentWidth = 0;
		
		// Detach content so that the parent width is exactly the available width
		this.detachContent();
		// Clear explicit widths - to be recalculated
		this.viewNode.style.width=null;
		this.pane1.style.width=null;
		this.pane2.style.width = null;
		// Calculating the available width is browser specific
			parentWidth=this.viewNode.offsetWidth;
		if (window.browser == 'Mozilla')
		{
			//In mozilla (as of 2005), we need to set the width property of the parent div in order to make the initial rendering correct
			this.viewNode.style.width=(parentWidth-2*this.borderWidth)+'px';
		}
		
		this.availableWidth = parentWidth - 2*this.borderWidth-this.dividerThickness;
		
		if (this.availableWidth <2*this.minWidth)
		{
			this.leftWidth = Math.round(this.availableWidth/2);
		}
		else if (this.leftWidth + this.minWidth > this.availableWidth)
		{
			this.leftWidth = this.availableWidth - this.minWidth;
		}
		//set explicit widths
		this.rightWidth= this.availableWidth - this.leftWidth-4;
		this.setPaneWidth(this.pane1, this.leftWidth);
		this.setPaneWidth(this.pane2, this.rightWidth);
		if (this.sharedProperties.adjustBottom == true)
		{
			this.adjustBottom();
		};
		//re-attach content
		this.attachContent();
		this.onResizeChildren();
		this.resizing = false;
	}
};

SplitPane.prototype.setPaneWidth = function setPaneWidth(pane,width)
{
		if (window.browser == 'IE' && ieLevel<7) // Traditional box model - width includes padding 
		{
			pane.style.width=width+'px';
		}
		else
		{
			pane.style.width=(width-2*this.paddingWidth)+'px';
		}
};

SplitPane.prototype.setPaneHeight = function setPaneHeight(pane,height)
{
		if (window.browser == 'IE' && ieLevel <7 )
		{
			// In IE, the hight include padding
			pane.style.height=height + 'px';
		}
		else
		{
			pane.style.height=(height -2*this.paddingWidth)+'px';
		}
};
SplitPane.beginDrag = function(e)
{
	var splitPane = tersus.findNode(this.getAttribute('SplitPaneId'));
	splitPane.beginDrag(e);
};
SplitPane.finishDrag = function (e)
{
	var splitPane=tersus.findNode(this.documentElement.getAttribute('SplitPaneId'));
	this.onmouseup = null;
	this.onmousemove = null;
	splitPane.viewNode.className=splitPane.baseClassName;
	
};
SplitPane.performDrag = function (e)
{
	var splitPane=tersus.findNode(this.documentElement.getAttribute('SplitPaneId'));
	var win = splitPane.currentWindow;
	var currentPosition = getEventPosition(win,e);
	var delta = {};
	delta.x = currentPosition.x - splitPane.lastPosition.x;
	delta.y = currentPosition.y - splitPane.lastPosition.y;
	splitPane.lastPosition = currentPosition;		
	splitPane.resize(delta);
};
SplitPane.prototype.beginDrag = function beginDrag(e)
{
	var splitPane = this;
	var win = this.currentWindow;
	var doc = win.document;
	doc.documentElement.setAttribute('SplitPaneId', this.getNodeId());
	splitPane.lastPosition = getEventPosition(win, e);
	splitPane.viewNode.className+=' resizing';
	doc.onmousemove =SplitPane.performDrag;
	doc.onmouseup=SplitPane.finishDrag;
};

SplitPane.prototype.resize = function resize(delta)
{
	if (this.leftWidth+delta.x >= this.minWidth && this.rightWidth-delta.x >= this.minWidth)
	{
		if (this.direction == 'ltr')
		{
			this.leftWidth += delta.x;
			this.rightWidth -= delta.x;
		}
		else
		{
			this.leftWidth -= delta.x;
			this.rightWidth += delta.x;
		}
			
		if (delta.x >0)
		{
			this.setPaneWidth(this.pane2, this.rightWidth);
			this.setPaneWidth(this.pane1, this.leftWidth);
		}
		else
		{
			this.setPaneWidth(this.pane1, this.leftWidth);
			this.setPaneWidth(this.pane2, this.rightWidth);
		}
		
		this.onResizeChildren();
		
	}
};

// file: 180-CallJavaApplet.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.appletName = 'tersus.applets.Base';
tersus.appletArchives = 'applets.jar';
tersus.CallJavaApplet = ActionNode.__subclass('CallJavaApplet');
tersus.CallJavaApplet.separateJVM=true;
tersus.CallJavaApplet.prototype.start = function()
{
	var appletName = this.getLeafChild('<Applet Class Name>');
	if (appletName == null)
		appletName = tersus.appletName;
	var archives = this.getLeafChild('<Archives>');
	if (archives == null)
		archives = tersus.appletArchives;
	var methodName = this.getLeafChild('<Method Name>');
	var args = this.prepareArguments();
	this.separateJVM = this.getLeafChild('<Separate JVM>');
	if (this.separateJVM == null)
		this.separateJVM = tersus.CallJavaApplet.separateJVM;
	
	this.waitForApplet(appletName,methodName,args, archives);
};
tersus.CallJavaApplet.prototype.waitForApplet = function waitForApplet(appletName,methodName,args, archives)
{
	if (document.applets[appletName])
	{
		var output =  this.callApplet(appletName,methodName, args);
		if (output == '__ASYNC')
			this.pause();
		else 
		{
			if (output != null)
				this.handleOutput(output);
			delete FlowNode.map[this.nodeId];
		}
			
	}
	else
	{
		this.pause();
		var rootContext = (this.getExecutionContext() == window.rootDisplayNode);
		if (rootContext)
		{
			tersus.progress.set('Loading applet '+appletName);
		}
		var node = this;
		setTimeout(function()
		{
			node.createApplet(appletName,archives);
			node.startTime = new Date();
			node.called=false;
			node.timerId = setInterval(function ()
			{
				var active = false;
				
				try 
				{
					active = document.applets[appletName] && document.applets[appletName].isActive();
				}
				catch ( e)
				{
					active = false;
				}
					
				if (((new Date())-node.startTime) > 60000 || active)
				{
					clearInterval(node.timerId);
					if (! node.called) // Prevent duplicate calling
					{
						node.called=true;
						var output = node.callApplet(appletName,methodName, args);
						if (output != '__ASYNC')
							node.handleResponse(output);
					}
					// Note that sometimes the timer is invoked one extra time to clearing the timer is not enough
				} 
			},100);
		},10);
	}
};
tersus.CallJavaApplet.prototype.createApplet = function(appletName,archives)
{
	if (!archives)
		archives = '';
	var applet = document.createElement('applet');
	applet.codebase='.';
	applet.width=1;
	applet.height=1;
	applet.setAttribute('id',appletName);
	applet.setAttribute('name',appletName);
	applet.setAttribute('mayscript','true');
	applet.setAttribute('separate_jvm',this.separateJVM);
	applet.code=appletName;
	applet.archive=archives;
	var c = document.getElementById('applet_container');
	if (!c)
	{
		c = document.createElement('div');
		c.id='applet_container';
		document.body.appendChild(c);
	}
	c.appendChild(applet);
};

tersus.CallJavaApplet.prototype.prepareArguments = function()
{
	var st = this.triggers.concat([]);
	var args = [];
	st.sort(function(a,b){ if (a.role < b.role) return -1; else if (a.role == b.role) return 0; else return 1;});
	for (var i=0;i<st.length;i++)
	{
		var t = st[i];
		if (t.role.charAt(0) != '<' && t.modelId != BuiltinModels.NOTHING_ID  )
		{
			if (t.isRepetitive)
			{
				var a = [];
				var l =t.getChildren(this);
				if (l)
				{
					for (var j=0;j<l.length; j++)
					{
						var v = l[j];
						if (v!= null &&  v.leafValue != null)
							a.push(v.leafValue);
						 else
						  	a.push(v);
					}
				}
				args.push(a);
			}
			else
			{
				var v = t.getChild(this);
				if (v!= null && v.leafValue != null)
					args.push(v.leafValue);
				else
					args.push(v);
			}
		}
	}	
	return args;
};
tersus.CallJavaApplet.prototype.callApplet = function(appletName,methodName,args)
{
	var rootContext = (this.getExecutionContext() == window.rootDisplayNode);
	if (! document.applets[appletName])
	{
		if (rootContext)
			tersus.progress.clear();
		modelExecutionError('Applet '+appletName + ' not loaded',this);
		return;
	}
	var applet = document.applets[appletName];
	if (rootContext)
		tersus.progress.set("Calling "+methodName);
	window.tersus_CallJavaApplet_caller = this;
	window.tersus_CallJavaApplet_caller_id = this.getNodeId();
	if (window.browser == 'IE')
	{
		var invocation = 'applet.'+methodName+'(';
		for (i=0;i<args.length;i++)
		{
			if (i>0)
				invocation += ',';
			invocation+='args['+i+']';
		}
		invocation += ')';
		var output = eval(invocation);
	}
	else
		var output = applet[methodName].apply(applet,args);
	window.tersus_CallJavaApplet_caller = null;
	window.tersus_CallJavaApplet_caller_id = null;
	
	return output;
	
};
tersus.CallJavaApplet.prototype.isJavaException = function (e)
{
	if ( typeof e === 'object' &&  'getMessage' in e && 'getClass' in e )
	{
		var n = e.getClass().getName()+'';
		return n.match(/Exception|Error/) ? true: false;
	}
	else
		return false;
};
tersus_handle_applet_response = function (nodeId, output, exitName)
{
	if (tlog)
		tlog('tersus_handle_applet_response id='+nodeId);
	var node = tersus.findNode(nodeId);
	if (!node)
	{
		alert('Applet node #'+nodeId+ ' not found');
		return;
	}
	if (tlog)
		tlog('Processing applet response for '+node.modelName+' ['+nodeId+']');
	node.handleResponse(output,exitName);
};
tersus_handle_applet_error = function (nodeId, error)
{
	error = ''+error; //convert to JS string
	if (tlog)
		tlog('tersus_handle_applet_error id='+nodeId);
	var node = tersus.findNode(nodeId);
	if (!node)
	{
		alert('Applet node #'+nodeId+ ' not found');
		return;
	}
	if (tlog)
		tlog('Processing applet response for '+node.modelName+' ['+nodeId+']');
	
	if (error.match(/^{/))
		error = eval('var e='+error+';e;'); //TODO use string JSON parse
	node.appletError = error;
	node.handleResponse(null,null);
};
tersus_charge_applet_leaf_exit = function (nodeId, exitName, value)
{
	var node = tersus.findNode(nodeId);
	if (!node)
	{
		alert('Applet node #'+nodeId+ ' not found');
		return;
	}
	node.chargeLeafExit(exitName, value);
};
tersus.CallJavaApplet.prototype.handleOutput = function(output, exitName)
{
	if (!exitName)
		exitName = '<Output>';
	if (output != null)
		this.chargeLeafExit(exitName,output);	
}
tersus.CallJavaApplet.prototype.handleResponse = function(output,exitName)
{
	var executionContext = this.getExecutionContext();
	if (executionContext == window.rootDisplayNode)
		tersus.progress.set('Processing response');
	if (output)
	{
		try
		{
			if (this.isJavaException(output))
			{
				this.appletError = output;
			}
			else
			{
				this.handleOutput(output,exitName);
			}
		}
		catch (e)
		{
        	if (!this.appletError)
        		this.appletError = e;
        }
	}
	this.continueExecution();

		
	this.destroy(); // Important - removes node from the node map
	this.children=null; //To be on the safe side in case an applet holds a reference to the node
	this.parent = null; //To be on the safe side ..	
};
tersus.CallJavaApplet.prototype.resume = function()
{
	if (this.appletError)
		throw this.appletError;
}

// file: 180-ScrollPane.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function ScrollPane() {};
ScrollPane.prototype = new Pane();
ScrollPane.prototype.constructor = ScrollPane;
ScrollPane.prototype.defaultStyleClass = 'scrollPane';

// file: 181-ScrollPane.iphone.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at http://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
ScrollPane.prototype = 
function Scrollable() {};
ScrollPane.prototype = new tersus.HTMLTag();
ScrollPane.prototype.constructor = ScrollPane;
ScrollPane.prototype.defaultTag = 'div';
ScrollPane.prototype.defaultClass  = 'scrollPane';
ScrollPane.prototype.defaultWrapperTags='div';
ScrollPane.prototype.defaultWrapperStyleClasses='scrollPaneWrapper';


ScrollPane.preventDefaultSet = false;

ScrollPane.prototype.onResize = function()
{
	this.setDefaultHeight();
	if (this.iScroll)
		this.iScroll.refresh();
	this.onResizeChildren();
}
ScrollPane.prototype.initIScroll = function()
{
	var node = this;

	tersus.async.exec(function()
	{
		node.setDefaultHeight();
		node.iScroll = new iScroll(node.wrapperNode);
	});
};
ScrollPane.prototype.destroy = function()
{
	if (this.iScroll && this.iScroll.destory)
	{
		this.iScroll.destory(true);
		this.iScroll=null;
	}
	tersus.HTMLTag.prototype.destroy.call(this);
};
ScrollPane.prototype.setDefaultHeight = function()
{
	var e = $(this.wrapperNode);
	while (e.length>0)
	{
		if (e.css('overflow-y')=='hidden')
		{
			$(this.wrapperNode).height(e.height());
			return;
		}
		e = e.parent();
	}
	this.iScroll.refresh();
};
ScrollPane.prototype.copyValueOpt = function(value, nodeMap, htmlV, legacyNodes)
{
	tersus.HTMLTag.prototype.copyValueOpt.call(this,value, nodeMap, htmlV, legacyNodes)
	var node = this;
	if (window.iScroll)tersus.async.exec(function(){tersus.async.exec(function() {node.initIScroll();});});
};


// file: 181-ShowFile.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.ShowFile = function ShowFile() {};
tersus.ShowFile.useIFrame=true;
tersus.ShowFile.prototype = new ServiceNode();
tersus.ShowFile.prototype.constructor = tersus.ShowFile;
tersus.ShowFile.prototype.start = function startService()
{	
	if (tersus.alertMode.interactive)
	this.callService();
};
tersus.ShowFile.prototype.getTraceFileName = function()
{
	return this.traceFileName;
};
tersus.ShowFile.iframe = null;
tersus.ShowFile.prototype.callService = function callService()
{
	if (window.trace)
	{
		this.traceFileName = window.trace.openTraceFile();
		window.trace.link(this,this.traceFileName, "contains the trace of the server side process");
	}
	var form = this.prepareForm();
	this.addTersusParameters(form);

	form.action = 'File';
	form.method = 'POST';
        var newFrame=false;
	if (tersus.ShowFile.useIFrame)
	{
		if (tersus.ShowFile.iframe == null)
	        {
		    newFrame=true;
		    tersus.ShowFile.iframe = createAnIFrame(window,'_showFile');
		}
		form.target='_showFile';
	}
	
	setEncType(form,'multipart/form-data'); 
	var sigField = addHiddenField(form, '_sig', 'END');
	form.appendChild(sigField);
	this.nodesToRemove.push(sigField);
        var self=this;
    var submit = function()
    {
	form.submit();
	for (var i=0; i< self.nodesToRemove.length; i++)
	{
		var node = self.nodesToRemove[i];
		node.parentNode.removeChild(node);
	};
    };
    if (newFrame)
	setTimeout(submit,100); /* In chrome 33, a newly created IFRAME is not immediately available as a form target */
    else 
	submit();

};

// file: 200-FieldList.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.Field = function Field(element, path)
{
	if (element != null)
	{
		this.name = element.role;
		this.sqlName = element.columnName ? element.columnName : tersus.sqlize(element.role);
		this.path = path;
		this.element = element;
	}
};
tersus.Field.prototype.constructor = tersus.Field;
tersus.Field.prototype.setValue = function (obj, value)
{
	obj.setValue(this.path, value, Operation.REPLACE);
};
tersus.Field.prototype.setLeafValue = function (obj, leafValue)
{
	var value = this.element.createChildInstance();
	value.setLeaf(leafValue);
	obj.setValue(this.path, value, Operation.REPLACE);
};
tersus.Field.prototype.getSQLDef = function()
{
	var childP = this.element.getChildConstructor().prototype;
	return this.sqlName+ ' ' + childP.sqlType;
};
tersus.Field.prototype.getSQLValue = function (obj)
{
	var values = obj.getValues(this.path);
	if (values && values.length == 1)
	{
		var v = values[0];
		if (v == null)
		  	return v;
		return v.isDateAndTime ? v.serialize() : v.leafValue; // SQLite doesn't support date and time - need to serialize
	}
	else 
		return null;
};

tersus.MapField = tersus.Field.__subclass('MapField', function(sqlName)
{
	this.name = this.sqlName=sqlName;
});
tersus.MapField.prototype.getSQLValue = function (obj)
{
	if (obj == null)
		return null;
	var map = obj.leafValue;
	if (map == null)
		return null;
	var v = map[this.sqlName];
	if (v == null)
		  return v;
	return v.isDateAndTime ? v.serialize() : v.leafValue; // SQLite doesn't support date and time - need to serialize
};

tersus.FieldList = function(model)
{
	this.initialize(model);
};
tersus.FieldList.prototype.constructor = tersus.FieldList;
tersus.FieldList.prototype.initialize = function(model)
{
	this.fields = [];
	this.primaryKeyFields=[];
	this.fieldsByName={};
	if (model)
	{
		this.addFields(model);
		for (var i=0; i<this.fields.length;i++)
		{
			var f = this.fields[i];
			if (f.element.isPrimaryKey)
			{
				this.primaryKeyFields.push(f);
				f.isPrimaryKey = true;
			}
		}
		if (this.primaryKeyFields.length == 0 && this.fields.length >0)
		{
			this.primaryKeyFields.push(this.fields[0]); // Todo - remove this sometime in the future?
			this.primaryKeyFields[0].isPrimaryKey=true;
		}
	}
};
tersus.FieldList.prototype.addMapFields = function(obj)
{
	if (obj == null)
		return;
	var map = obj.leafValue;
	if (map == null)
		return;
	for (var name in map)
		this.addMapField(name);
};
tersus.FieldList.prototype.getField = function getField(name)
{
	return this.fieldsByName[tersus.sqlize(name)];
};

tersus.FieldList.prototype.addMapField = function(name)
{
	if (this.getField(name))
		return;
	this.addField(new tersus.MapField(name));
}
tersus.FieldList.prototype.addField = function(f)
{
	this.fields.push(f);
	if (this.fieldsByName[f.sqlName] != null)
			modelError('Ambiguous column name '+f.sqlName, this);	
	this.fieldsByName[f.sqlName] = f;
};
tersus.FieldList.prototype.addFields = function addFields(root,prefixPath)
{	
	if (prefixPath == null)
		prefixPath = new Path('');
	var elements = root.elementList;
	if (!elements)
		return;
	var n=elements.length;
	for (var i=0;i<n;i++)
	{
		var e = elements[i];
		var c = e.getChildConstructor().prototype;
		var p = prefixPath.clone();
		p.addSegment(e.role);
		if (c.isLeaf)
			this.addField(new tersus.Field(e, p));
		else
			this.addFields(c,p);
	} 
};

// file: 201-DatabaseAction.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.databases = {};
tersus.maxDatabaseSize=5000000;
tersus.DatabaseAction = ActionNode.__subclass('tersus.DatabaseAction');
tersus.DatabaseAction.prototype.getDB = function()
{
	var datasource = this.getLeafChild('<Data Source>');
	if (!datasource)
		datasource = 'default';
	if (datasource.charAt(0) != '/')
	{
		var m = tersus.rootURL.match(/^(?:https?:\/\/[^/]+\/|file:\/+)([^/]+)\/$/);
		if (m && m.length > 0)
			datasource=m[1]+'_'+datasource;
	}
	
	var db = tersus.databases[datasource];
	if (! db)
	{
		db = openDatabase(datasource, 1.0, datasource, tersus.maxDatabaseSize);
		if (db == null) // Workaround for phonegap issue with quota update
		{
			for (var i=0;i<=tersus.maxDatabaseSize/1000000;i++)
			{
				db = openDatabase(datasource, 1.0, datasource, tersus.maxDatabaseSize);
				if (db != null)
					break;
			}
		}
		tersus.databases[datasource]=db;
	}
	return db;
};

tersus.DatabaseAction.prototype.getSQLStatememt = function()
{
	var sql = this.getLeafChild('<SQL Statement>');
	if (!sql)
		modelError('Missing <SQL Statement>',this);
	return sql;
};

tersus.DatabaseAction.prototype.analyzeParameterizedSQL = function(str)
{
	var t = str;
	var i=0;
	var l = t.length;
	var out = [];
	var keys = [];
	while (i<l&& i>= 0)
	{
		var n = t.indexOf('${',i);
		if (n == -1)
		{
			out.push(t.substring(i));
			i = n;
		}
		else
		{
			out.push(t.substring(i,n));
			var b = n+ 2;
			var e=t.indexOf('}', b);
			if (e<0)
			{
				modelExecutionError("Invalid template: missing '}' for '${'.  Position="
							+ n
							+ " Text="
							+ t.substring(n, n + 20));
				return null;
			}
			var key=t.substring(b,e);
			out.push('?');
			keys.push(key);
			i = e+1;
		}

	}
	var result = {};
	result.sqlText = out.join('');
	result.parameters = keys;
	return result;
};

tersus.DatabaseAction.prototype.getFieldList = function(model)
{
	if (!model.fieldList)
	{
		model.fieldList = new tersus.FieldList(model);
	}	
	return model.fieldList;
};
tersus.DatabaseAction.prototype.getOutputColumnsExit = function getOutputColumnsExit()
{
	return this.getExit('<Output Columns>');
};
tersus.DatabaseAction.prototype.outputColumns = function outputColumns(colMap)
{
	var exit = this.getOutputColumnsExit();
	if (exit)
	{
		for (var name in colMap)
		{
			var col = exit.createChildInstance();
			col.setLeafChild('Name',name, Operation.REPLACE);
			col.setLeafChild('Type',colMap[name], Operation.REPLACE);
			this.accumulateExitValue(exit, col);		
		}
	}
};
tersus.DatabaseAction.prototype.outputResultAsMap = function outputResultAsMap(exit, row, columns)
{
	var out = exit.createChildInstance();
	var map = {};
	out.leafValue = map;
	for (var key in row)
	{
		var value = row[key];
		if (value == null)
		{
			if (columns[key] == null)
				columns[key] = '?';
			continue;
		}
		var type =	typeof(value);
		var c;
		if (type == 'string')
		{
			c = tersus.repository.get(BuiltinModels.TEXT_ID);
		}
		else if (type == 'number')
		{
			c = tersus.repository.get(BuiltinModels.NUMBER_ID);
		}
		else
			throw {message:'Unexpected database return type '+type};
		var node = new c();
		node.prototype = c.prototype;
		node.setLeaf(value);
		map[key]=node;
		if (columns)
		{
			if (columns[key] == null || columns[key]=='?')
				columns[key] = c.prototype.modelName;
			else if (columns[key] != c.prototype.modelName)
				columns[key] = 'Anything';
		}
				
	}
	if (exit.isRepetitive)		
		this.accumulateExitValue(exit, out);
	else
		this.chargeExit(exit,out);
	
};

tersus.DatabaseAction.prototype.getTableNameOfModel = function(record)
{
	return record.tableName  ? record.tableName : tersus.sqlize(record.modelName);
};
tersus.DatabaseAction.prototype.getTableName = function getTableName(record)
{
	var n = this.getLeafChild('<Table Name>');
	if (n == null)
		n = this.getTableNameOfModel(record);
	return n;
};

tersus.DatabaseAction.prototype.addPrimaryKeyWhereClause = function createPrimaryKeyFilter(record,fieldList,sqla, values)
{
	sqla.push("WHERE");
	var pk = fieldList.primaryKeyFields;
	var npk = pk.length;
	for (var i=0;i<npk;i++)
	{
		if (i>0)
			sqla.push('AND');
		var f = pk[i];
		var v = f.getSQLValue(record);
		sqla.push(f.sqlName);
		if (v == null)
			sqla.push('IS NULL');
		else
		{
			sqla.push('= ?');
			values.push(v);
		}
	}

};
tersus.DatabaseAction.prototype.addSelectFieldsSQL = function addSelectFieldsSQL(sqla, tableName, fieldList, explicitColumns)
{
	sqla.push('SELECT');
	if (explicitColumns)
		sqla.push(explicitColumns)
	else
	{
		var fields = fieldList.fields;
		var n = fields.length;
		for (var i=0;i<n; i++)
		{
			if (i>0)
				sqla.push(',');
			sqla.push(fields[i].sqlName);
		}
	}
	sqla.push('FROM');
	sqla.push(tableName);
};
tersus.DatabaseAction.prototype.outputResults = function(results, exit, maxRows, reverse)
{
	var nRows = 0;
	var rows = results.rows;
	if (rows)
		nRows =  rows.length;
	if (nRows == 0)
	{
		this.chargeEmptyExit('<None>');
		return;
	}
	if (maxRows && nRows > maxRows)
		nRows = maxRows;
	var outputColumnsExit = this.getOutputColumnsExit();
	var outputPrototype = exit.getChildConstructor().prototype;
	if (outputPrototype.isMap)
	{
		var colMap=null;
		if (outputColumnsExit)
			colMap = {};
		for (var i=0;i<nRows; i++)
		{
			this.outputResultAsMap(exit, rows.item(i), colMap);
		}
		if (outputColumnsExit)
		{
			this.outputColumns(colMap);
		}
	}
	else
	{
		var fields = this.getFieldList(outputPrototype).fields;
		var nFields = fields.length;
		if (reverse)
		{
			for (var i=nRows -1; i>=0; i--)
				this.outputResult(rows.item(i), fields, nFields, exit);
		}
		else
		{
			for (var i=0;i<nRows; i++)
				this.outputResult(rows.item(i), fields, nFields, exit);
		}
	}
	
};
tersus.DatabaseAction.prototype.outputResult = function(item, fields, nfields, exit)
{
	var out = exit.createChildInstance();
	if (out.isLeaf)
	{
		for (var k in item)
			out.setLeaf(item[k]);
	}
	else // composite
	{
		for (var j=0;j<nfields;j++)
		{
			var field = fields[j];
			var v = item[field.sqlName];
			if (v != null)
				field.setLeafValue(out,v);
		}
	} 
	if (exit.isRepetitive)		
		this.accumulateExitValue(exit, out);
	else
		this.chargeExit(exit,out);
};

tersus.DatabaseAction.prototype.start = function()
{
	this.pause();
	if (this.tableOK)
	{
		this.run();
		return;
	}
	this.tableOK = true;
	var p = this.getTablePrototype();
	if (!p || p.tableOK || p.isMap)
	{
		this.run();
	}
	else
	{
		p.tableOK = true;
		this.getTableDef(this.getTableNameOfModel(p), this.updateTableAndRun, this);
	}
};
tersus.DatabaseAction.prototype.updateTableAndRun = function (tableDef)
{
	var p = this.getTablePrototype();
	var fieldList = this.getFieldList(p);
	var fields = fieldList.fields;
	var nfields = fields.length;
	var batch = [];
	if (tableDef == null)
	{
		var sql = 'CREATE TABLE '+this.getTableNameOfModel(p) + ' (';
		for (var i=0;i<nfields; i++)
		{
			var field = fields[i];
			if (i>0)
				sql += ', ';
			sql+=field.getSQLDef();
		}
		var pk = fieldList.primaryKeyFields;
		if (pk.length > 0)
		{
			sql += ', PRIMARY KEY (';
			for (var i=0;i<pk.length;i++)
			{
				if (i>0)
					sql += ',';
				sql += pk[i].sqlName;
			}
			sql+=')';
		}
		sql+=')';
		batch.push(sql);
	}
	else
	{
		for (var i=0;i<nfields;i++)
		{
			var field = fields[i];
			if (tableDef.columns[field.sqlName] == null)
				batch.push('ALTER TABLE '+p.tableName+' ADD COLUMN '+field.getSQLDef());
		}
	}
	if (batch.length > 0)
		this.execSqlBatch(batch, function(){this.run();});
	else
		this.run();			
};

tersus.DatabaseAction.prototype.resumeContext = function()
{
	this.continueExecution();
};
tersus.DatabaseAction.prototype.execSql = function (sql, values, callback)
{
	if (window.trace)
	{
		window.trace.sql(this, sql, values);
	}
	//alert(sql);
	var errorHandler = function(transaction,error)
	{
		alert('Error: '+error.message+' ['+error.code+']');
		return true;	
	};
	var node = this;
	var dataHandler = function(transaction, results)
	{
		callback.call(node,transaction, results);
	};
	this.getDB().transaction(function(transaction){ transaction.executeSql(sql, values, dataHandler, errorHandler);});	
};
tersus.DatabaseAction.prototype.execSqlBatch = function (commands, callback, index)
{
	if (index == null)
		index = 0;
	if (commands.length != null && index >= commands.length)
	{
		alert('Invalid index in execSqlBatch');
	}
	this.execSql(commands[index], [], function()
	{ 
		if (index+1==commands.length)
			callback.call(this);
		else
			this.execSqlBatch(commands, callback, index+1);
	});
};
tersus.DatabaseAction.prototype.getTableDef = function(tableName, callback, obj)
{
	var errorHandler = function(transaction,error)
	{
		alert('Error: '+error.message+' ['+error.code+']');
		return true;	
	};
	var dataHandler = function(transaction, results)
	{
		if (!results || !results.rows || results.rows.length == 0)
		{
			callback.call(obj,null);
			return;
		}
		
		var re0 = /create table [^(]*\((.*)\)$/i;
		var re1 = /\s*(?:(?:(\w+)(?:\s+(\w+))?(?:\s*\(\s*(\d+)\s*\)\s*)?)|(?:primary\s*key\s*\(\s*([^)]*)\s*\)))((?:\s|\w)*)(?:,|$)/ig;
		var row = results.rows.item(0);
		var tableName = row.name;
		var sql = row.sql;
		var tableSpec= re0.exec(sql)[1];
		var tableDef = {name:tableName,columns:{}};
		do
		{
			var m = re1.exec(tableSpec);
			if (m!= null)
			{
				if (m[1] != null) // Column definition
				{
					var col = {name:m[1], type:m[2], size:m[3]};
					if (m[5] && /primary\s+key/i.test(m[5]))
						col.isPrimaryKey=true;
					tableDef.columns[col.name]=col;
				}
				else if (m[4] != null) // Primary key definition
				{
					var pk = m[4].split(/\s*,\s*/);
					for (var j=0; j<pk.length;j++)
					{
						var c = pk[j];
						if (c && tableDef.columns[c])
							tableDef.columns[c].isPrimaryKey=true;
					}
				}
					
			}
		} while (m!= null);
		callback.call(obj, tableDef);
	};
	this.getDB().transaction(function(transaction) {
		transaction.executeSql("select name, sql from sqlite_master where type=? and name=?",['table', tableName],  dataHandler, errorHandler);
	});
};
tersus.DatabaseAction.prototype.getSQLValue = function getSQLValue(role)
{
	  var v = this.getChild(role);
	  if (v == null)
	  	return v;
	  return v.isDateAndTime ? v.serialize() : v.leafValue; // SQLite doesn't support date and time - need to serialize

};
// file: 300-touchend-onclick.iphone.non-simulator.non-symbian.js
/*if (tersus.simulateClickByTouch != false)
{
	DisplayNode.prototype.registerEventHandler = function(eventType, domNode)
	{
		if (!domNode)
			domNode = this.viewNode;
		domNode.setAttribute('lid',this.getNodeId());
		if (!eventType.jsName)
		{
			internalError('No event dispatcher defined for '+eventType.elementName);
			return;
		}
		var dispatcher = this.currentWindow.tersus_dispatchers[eventType.jsName];
		if (dispatcher == null)
			internalError('No event dispatcher defined for '+eventType.jsName);
		else
		{
			if (eventType === Events.ON_CLICK)	
			{
				domNode[Events.ON_TOUCHEND.jsName]=dispatcher;
				domNode[Events.ON_TOUCHSTART.jsName]=tersus.noop;
			}
			else
				domNode[eventType.jsName] = dispatcher;
		}	
	};
	function getEventAttributes(e)
	{
		var atts = {};
		atts.type = e.type;
		if (e.type.substring(0,3)=='key')
		{
			if (e.keyCode)
				atts.keyCode = e.keyCode;
			else 
				atts.keyCode = e.which;
		}
		var buttonCode = e.button;
		if (buttonCode == 1)
			atts.button = 'Left';
		else if (buttonCode == 4)
			atts.button = 'Middle';
		else if (buttonCode == 2)
			atts.button = 'Right';
		if (e.changedTouches && e.changedTouches.length>0)
		{
			var t = e.changedTouches[0];
			atts.clientX  = t.clientX;  
			atts.clientY = t.clientY;
		}
		else
		{
			atts.clientX  = e.clientX;  
			atts.clientY = e.clientY;
		}
		
		atts.targetElement = e.target ? e.target : e.srcElement;
		return atts;
	};	
	
}*/

// file: 301-orientation-change.iphone.non-simulator.js
window.onorientationchange = function(ev)
{
	if (ev)
		tersus.currentEventAttributes = getEventAttributes(ev);
	if (window.rootDisplayNode)
		window.rootDisplayNode.queueEvent(Events.ON_ORIENTATION_CHANGE,{});
	
}
// file: 301-orientation-change.js
tersus.currentOrientation=window.orientation;
window.onorientationchange = function(ev)
{
	if (tersus.currentOrientation === window.orientation)
		return;
	tersus.currentOrientation=window.orientation;
	if (ev)
		tersus.currentEventAttributes = getEventAttributes(ev);
	if (window.rootDisplayNode)
		window.rootDisplayNode.queueEvent(Events.ON_ORIENTATION_CHANGE,{});
	
};

tersus.simulateOrientationChange = function()
{
	if (window.orientation==0 || window.orientation==180)
		window.orientation=90;
	else
		window.orientation=0;
	tersus.invokeAction('<On Orientation Change>',null,null,window.rootDisplayNode);
};

// file: AbsoluteNumber.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('AbsoluteNumber', function()
{
	var x = this.getLeafChild('<X>');
	if (x != null)
	{
		var absValue = Math.abs(x);
		this.chargeLeafExit('<Absolute Value>', absValue);
	}
});

// file: ActionDialog.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.isIE6 = navigator.userAgent.indexOf('MSIE 6') >=0;

 //tersus.ActionDialog = function tersus_ActionDialog() {};
	tersus.ActionDialog = tersus.PopIn.__subclass('Dialog');
	tersus.ActionDialog.prototype.templateURL='actiondialog.html';
	tersus.ActionDialog.prototype.createViewNode = function()
	{
		// create mask (this gives modality by blocking UI access to existing content)
		clearSelection(this.currentWindow); // sometimes the original selection is extended to newly created elements
		var d = this.currentWindow.document;
		var r = this.getCurrentRootViewNode();
		//var ml = this.createHTMLChildElement(r,'div');
		
		// create dialog div
		var template = tersus.repository.getHTMLTemplate(this.templateURL);
		var actioDialogHtml = importNode(d,template);
		this.dialogLayer = actioDialogHtml;
		actioDialogHtml.className='confirm_screenopen';
		this.viewNode = tersus.findChildNodesByClassName(actioDialogHtml,'action_dialog_body')[0];
		this.viewNode = actioDialogHtml;
		this.isOpen = true;
		r.appendChild(actioDialogHtml);
		this.header = tersus.findChildNodesByClassName(actioDialogHtml,'action_dialog_title')[0];
		if (this.header)
		  this.header.innerHTML = tersus.escapeHTML(this.getPopupTitle());
		  
		this.onResize();
		
	};
	tersus.ActionDialog.prototype.onResize = function()
	{
		if (! (this.isOpen && this.currentWindow && ! this.currentWindow.closed && this.viewNode))
			return;
				this.onResizeChildren();
	}
	tersus.ActionDialog.prototype.doClose = function() 
	{
		delete tersus.popupNodes[this.getNodeId()];
	
		if (this.isOpen)
		{
			this.resumeNavigation();
			this.viewNode = null;
			this.header = null;
			var dl = this.dialogLayer;
			//var ml = this.maskLayer;
			this.dialogLayer=null;
			//this.maskLayer=null;
			dl.parentNode.removeChild(dl);
			//ml.parentNode.removeChild(ml);
		}
		this.isOpen = false;
	
	};

// file: AddStyleClass.js
/*********************************************************************************************************
 * Copyright (c) 2003-2013 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/

tersus.newAction('AddStyleClass',function()
{	
	var element = this.getChild('<Element>');
	var value = this.getLeafChild('<Style Class>');
	if (!element || !value || !element.isDisplayNode)
		return;
	element.addStyleClass(value);
});

// file: AdvancedFind.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.AdvancedFind =  tersus.DatabaseAction.__subclass('tersus.AdvancedFind');
tersus.AdvancedFind.prototype.NO_N_MATCHES = 'No Number of Matches';
tersus.AdvancedFind.prototype.NO_POSITION = 'No Position';
tersus.AdvancedFind.prototype.getTablePrototype = function()
{
	var e = this.getExit('<Records>');
	if (e == null)
		e = this.getTrigger('<From>');
	if (e == null)
		e = this.getTrigger('<To>');
	if (e == null)
		e = this.getTrigger('<Start From>');
	if (e == null)
		e = this.getTrigger('<Match>');
	if (e == null)
		return null;
	return e.getChildConstructor().prototype;
};
tersus.AdvancedFind.prototype.run = function()
{
	var ctx =
	{
		condition:[],
		values:[],
		from:this.getChild('<From>'),
		to:this.getChild('<To>'),
		match: this.getChild('<Match>'),
		startFrom:this.getChild('<Start From>'),
		numberOfRecords:this.getChild('<Number of Records>'),
		offset:this.getLeafChild('<Offset>'),
		backward:(true == this.getLeafChild('<Backward>')),
		table:this.getLeafChild('<Table>'),
		columns:this.getLeafChild('<Columns>'),
		filter:this.getLeafChild('<Filter>'),
		givenOrderBy:this.getLeafChild('<Order By>'),
		recordsExit:this.getExit('<Records>'),
		columns:this.getLeafChild('<Columns>'),
		moreExit:this.getExit('<More>'),
		positionExit:this.getExit('<Position>'),
		tablePrototype:this.getTablePrototype(),
		numberOfMatchesExit:this.getExit('<Number of Matches>')
	};
	if (!ctx.offset)
		ctx.offset = 0;
	
	this.setOptimization(ctx);
	this.setFieldList(ctx);
	this.addTable(ctx);
	this.addDynamicFilterConditions(ctx);
	this.addRangeConditions(ctx);
    this.addMatchConditions(ctx);	
	this.setOrderBy(ctx, ctx.backward);
	ctx.needsMatches = ctx.numberOfMatchesExit	 && !ctx.noMatches;
	ctx.needsPosition = ctx.positionExit!=null && !ctx.noPosition;

	if (ctx.needsMatches 
	 || ctx.backward && ctx.needsPosition && ctx.startFrom == null)
    {
    	this.countMatches(ctx, function(ctx,count)
    	{
    		ctx.nMatches = count;
    		if (ctx.needsMatches)
    		{
    			this.chargeLeafExit(ctx.numberOfMatchesExit, count);
    		}
    		if (ctx.recordsExit)
    			this.executeQuery(ctx);
    		else
    			this.resumeContext();
    		
    	});
   	}
    else
  		if (ctx.recordsExit)
   			this.executeQuery(ctx);
   		else
   			this.resumeContext();
   		
};
tersus.AdvancedFind.prototype.setOptimization = function(ctx)
{
	ctx.noPosition = false;
	ctx.noMatches = false;
	var trigger = this.getTrigger('<Optimization>');
	if (!trigger)
		return;
	
	var list = trigger.getChildren(this);
    if (list)
    {
    	for (var i=0;i<list.length;i++)
    	{
    		var opt = list[i].leafValue;
    		if (opt == this.NO_POSITION)
    			ctx.noPosition=true;
    		else if (opt == this.NO_N_MATCHES)
    			ctx.noMatches = true;
    	}
    }
};
tersus.AdvancedFind.prototype.countMatches = function countMatches(ctx, callback)
{
	var sqla = ['SELECT COUNT(1) AS count FROM', ctx.tableSql];
	if (ctx.condition.length > 0)
	{
		sqla.push('WHERE');
		tersus.addAll(sqla, ctx.condition);
	}
	this.execSql(sqla.join(' '),ctx.values, function(transaction, results) 
	{
		var count = results.rows.item(0).count;
		callback.call(this, ctx, count);
	});
};
tersus.AdvancedFind.prototype.setFieldList = function setFieldList (ctx)
{
	if (ctx.tablePrototype != null)
	{
		if (ctx.tablePrototype.isMap)
		{
			ctx.fieldList = new tersus.FieldList();
			ctx.fieldList.addMapFields(ctx.from);
			ctx.fieldList.addMapFields(ctx.to);
			ctx.fieldList.addMapFields(ctx.match);
			ctx.fieldList.addMapFields(ctx.startFrom);
			if (ctx.columns != null)
			{
				tersus.foreach(ctx.columns.split(/ *, */),
				function (name)
				{
						ctx.fieldList.addMapField(name);
				});
			}
			if (ctx.givenOrderBy != null)
			{
				tersus.foreach(ctx.givenOrderBy.split(/\s*,\s*/),
				function (clause)
				{
        			var pp = clause.split(/\s+/);
        			if (pp.length >= 1)
        			{
        				var name = pp[0];
        				ctx.fieldList.addMapField(name);
        			}
        		});
        	}			
		}
		else
			ctx.fieldList = this.getFieldList(ctx.tablePrototype);
	}
};
tersus.AdvancedFind.prototype.addTable = function addTable(ctx)
{
	var rawSql = ctx.table? ctx.table : this.getTableName(ctx.tablePrototype);
	var q = this.analyzeParameterizedSQL(rawSql);
	ctx.tableSql = q.sqlText;
	for (var i=0; i<q.parameters.length; i++)
	{
		ctx.values.push(this.getSQLValue(q.parameters[i]));
	}
};
tersus.AdvancedFind.prototype.addDynamicFilterConditions = function(ctx)
{
	if (! ctx.filter)
		return;
	ctx.condition.push('(');
	var q = this.analyzeParameterizedSQL(ctx.filter);
	ctx.condition.push(q.sqlText);
	ctx.condition.push(')');
	for (var i=0; i<q.parameters.length; i++)
	{
		ctx.values.push(this.getSQLValue(q.parameters[i]));
	}
};



tersus.AdvancedFind.prototype.addMatchConditions = function(ctx)
{
  if (ctx.match == null)
        return;
	var columns = ctx.fieldList.fields;
    for (var i = 0; i < columns.length; i++)
    {
		var column = columns[i];
        var matchValue =  column.getSQLValue(ctx.match);
		if (matchValue != null)
        {
			if (matchValue.indexOf && matchValue.indexOf('%') >= 0)
	            this.addCondition(ctx, column, ' like ', matchValue);
	        else
	            this.addCondition(ctx, column, ' = ', matchValue);
	    }
	}
};       
				

tersus.AdvancedFind.prototype.addRangeConditions = function(ctx)
{
  if (ctx.from == null && ctx.to == null)
        return;

	var columns = ctx.fieldList.fields;
    for (var i = 0; i < columns.length; i++)
    {
		var column = columns[i];
        var fromValue = null;
        var toValue = null;
        if (ctx.from != null)
			fromValue = column.getSQLValue(ctx.from);
		if (ctx.to != null)
			toValue = column.getSQLValue(ctx.to);
		if (fromValue == null && toValue != null)
        {
			if (ctx.condition.length > 0)
				ctx.condition.push("AND");
            ctx.condition.push("(");
            this.addCondition(ctx, column, '<=', toValue);
            this.appendOrIsNull(ctx.condition, column.sqlName);
        }
        else
        {
            if (fromValue != null)
                this.addCondition(ctx, column, '>=', fromValue);
            if (toValue != null)
                this.addCondition(ctx, column, '<=', toValue);
        }
    }	

};
tersus.AdvancedFind.prototype.addCondition = function addCondition(ctx, column, operator, value)
{
	var c = ctx.condition;
    if (c.length > 0 && c[c.length - 1] != '(' )
    {
        c.push(" AND ");
    }
    c.push(column.sqlName);
   	c.push(operator);
    c.push('?');
    //types.add(column.getValueHandler());
    ctx.values.push(value);

};

tersus.AdvancedFind.prototype.appendOrIsNull = function(sqla, columnName)
{
    sqla.push('OR');
    sqla.push(columnName);
    sqla.push(' IS NULL )');
};

tersus.AdvancedFind.prototype.setOrderBy = function setOrderBy(ctx, reverse)
{
    ctx.columnOrder = {};
    ctx.orderedColumns = [];
    if (ctx.recordsExit == null)
    	return;

    this.handleExplicitOrderBy(ctx,reverse);
    if (ctx.fieldList != null)
        this.addPrimaryKeyToSortOrder(ctx,reverse);
};

tersus.AdvancedFind.prototype.handleExplicitOrderBy = function handleExplicitOrderBy (ctx, reverse)
{
   	ctx.columnOrder = {};
   	ctx.orderedColumns=[];
   	ctx.orderBy = [];
    if (ctx.givenOrderBy)
    {
    	var p = ctx.givenOrderBy.split(/\s*,\s*/);
		for (var i=0;i<p.length;i++)
        {
        	var clause = p[i];
        	var pp = clause.split(/\s+/);
            if (pp.length == 0 || pp.length > 2)
            {
            	this.modelExecutionError("Invalid <Order By>: '" + ctx.givenOrderBy + "'", this);
            	return;
            }
            var columnName = pp[0];
            var column = ctx.fieldList.getField(columnName);
            if (column == null)
            {
            	if (ctx.tablePrototype && ctx.tablePrototype.isMap)
            	{	
            		column = new tersus.MapField(columnName);
            		ctx.fieldList.addField(column);	
            	}
            	else
            	{
                	modelExecutionError("Invalid <Order By> ('" + ctx.givenOrderBy
                        + "': unknown column '" + columnName + "'");
                	return;
                }
            }
	
			var desc = pp.length > 1 && pp[1].search(/^desc/i) >= 0;
			if (reverse)
				desc = !desc;
			this.addColumnToSortOrder(ctx, column, desc)
        }
    }
};
tersus.AdvancedFind.prototype.addColumnToSortOrder = function addColumnToSortOrder(ctx, column, desc)
{
    var dir = desc ? 'DESC' : 'ASC';
	ctx.columnOrder[column.sqlName]=desc;
    ctx.orderedColumns.push(column);
    if (ctx.orderBy.length > 0)
    	ctx.orderBy.push(',');
    ctx.orderBy.push(column.sqlName);
    if (desc)
		ctx.orderBy.push(dir);
};
tersus.AdvancedFind.prototype.addPrimaryKeyToSortOrder = function addPrimaryKeyToSortOrder(ctx, reverse)
{
    var pkColumns = ctx.fieldList.primaryKeyFields;
    for (var i = 0; i < pkColumns.length; i++)
    {
        var column = pkColumns[i];
        var columnName = column.sqlName;
    	if (ctx.columnOrder[columnName] == null)
        	this.addColumnToSortOrder(ctx, column, reverse);
    }
};
tersus.AdvancedFind.prototype.addStartFromConditions = function addStartFromConditions(ctx)
{
    if (ctx.startFrom == null)
        return;
    var startFromCondition = [];
    var previousTermsValues = [];
    //var  previousTermsTypes = [];
    var nTerms = 0;
    var previousTermsClause = [];
    for (var i = 0; i < ctx.orderedColumns.length; i++)
    {
        var column =  ctx.orderedColumns[i];
        var columnName = column.sqlName;
        var desc = ctx.columnOrder[columnName];
        if (desc == null)
            continue;
        var value = column.getSQLValue(ctx.startFrom);
        var last = (i == ctx.orderedColumns.length - 1);
        if (value == null)
        {
            if (last)
            {
                if (desc) // If the value of the last column is null, we only care about it if it's sorted desc
                {
                    if (previousTermsClause.length > 0)
                    {
                        previousTermsClause.push("AND");
                        previousTermsClause.push(columnName);
                        previousTermsClause.push("IS NULL");
                    }

                }
                if (startFromCondition.length > 0 && previousTermsClause.length > 0)
                {
                    startFromCondition.push("OR (");
                    tersus.addAll(startFromCondition,previousTermsClause);
                    startFromCondition.push(")");
                }
                else if (previousTermsClause.length > 0)
                {
                	
                    tersus.addAll(startFromCondition,previousTermsClause);
                }
                tersus.addAll(ctx.values,previousTermsValues);
//                tersus.addAll(types,previousTermsTypes);
                ++nTerms;
            }
            else
            {
                if (!desc)
                {
                    if (startFromCondition.length == 0)
                    {
                        startFromCondition.push("(");
                    }
                    else
                    {
                        startFromCondition.push('OR (');
                    }
                    if (previousTermsClause.length > 0)
                    {
                        tersus.addAll(startFromCondition,previousTermsClause);
		                tersus.addAll(ctx.values,previousTermsValues);
	//	                tersus.addAll(types,previousTermsTypes);
                        startFromCondition.push("AND");
                    }
                    startFromCondition.push(columnName);
                    startFromCondition.push("IS NOT NULL )");
                    ++nTerms;
                }
                if (previousTermsClause.length > 0)
                {
                    previousTermsClause.push("AND");
                }
                previousTermsClause.push(columnName);
                previousTermsClause.push(" IS NULL");

            }
        }
        else
        {
            if (startFromCondition.length > 0 && previousTermsClause.length > 0)
            {
                startFromCondition.push("OR (");
                tersus.addAll(startFromCondition,previousTermsClause);
                tersus.addAll(ctx.values,previousTermsValues);
//                tersus.addAll(types,previousTermsTypes);
                startFromCondition.push("AND (");
            }
            else if (previousTermsClause.length > 0)
            {
 				tersus.addAll(startFromCondition,previousTermsClause); 
 				startFromCondition.push("AND ((");
 				tersus.addAll(ctx.values,previousTermsValues);
//              tersus.addAll(types,previousTermsTypes);
 			}         	
            else
                startFromCondition.push("((");
            startFromCondition.push(columnName);

            ctx.values.push(value);
            //types.push(column.getValueHandler());
            if (last)
            {
                if (!desc)
                    startFromCondition.push(">= ? ))");
                else
                {
                    startFromCondition.push("<= ?");
                    // we need to explicitly include null values
                    this.appendOrIsNull(startFromCondition, columnName);
                    startFromCondition.push(')');
                }
            }
            else
            {
                if (!desc)
                    startFromCondition.push("> ? ))");
                else
                {
                    startFromCondition.push("< ?");
                    // we need to explicitly include null values
                    this.appendOrIsNull(startFromCondition, columnName);
                    startFromCondition.push(')');
                }

                if (previousTermsClause.length > 0)
                    previousTermsClause.push("AND");
                previousTermsValues.push(value);
                previousTermsClause.push(columnName);
                previousTermsClause.push("= ?");
                //previousTermsTypes.push(column.getValueHandler());
            }
            ++nTerms;
        }
    }
    if (nTerms == 0)
        return;
    if (ctx.condition.length == 0)
        ctx.condition = startFromCondition;
    else
    {
        ctx.condition.push('AND (');
        tersus.addAll(ctx.condition, startFromCondition);
        ctx.condition.push(')');
    }

};
tersus.AdvancedFind.prototype.executeQuery = function(ctx)
{
	this.addStartFromConditions(ctx);
	var sqla = [];
	var explicitColumns = ctx.columns == null && ctx.tablePrototype.isMap ? '*' : ctx.columns;
	this.addSelectFieldsSQL(sqla, ctx.tableSql, ctx.fieldList, explicitColumns);
		
	if (ctx.condition.length > 0)
	{
		sqla.push('WHERE');
		tersus.addAll(sqla, ctx.condition);
	}
	 
	if (ctx.orderBy.length > 0)
	{
		sqla.push('ORDER BY');
		tersus.addAll(sqla,ctx.orderBy);
	}
	var extra = 0; 
	if (ctx.numberOfRecords > 0)
	{
		if (ctx.moreExit != null)
			extra = 1;
		sqla.push('LIMIT');
		sqla.push(extra + parseInt(ctx.numberOfRecords));
		sqla.push('OFFSET')
		sqla.push(ctx.offset);
	}
	var sql = sqla.join(' ');
	this.execSql(sql, ctx.values, function(transaction,results)
	{
		var nrows = results.rows.length;
		var nrecs = (ctx.numberOfRecords > 0 && nrows> ctx.numberOfRecords) ? ctx.numberOfRecords : nrows;
		if (ctx.moreExit && nrows > nrecs)
			this.chargeEmptyExit(ctx.moreExit);
		this.chargeLeafExit('<Number of Records Returned>', nrecs);
		if (ctx.recordsExit != null)
			this.outputResults(results, ctx.recordsExit, nrecs, ctx.backward);
		this.getPosition(ctx);
	});
};
tersus.AdvancedFind.prototype.getPosition = function(ctx)
{
	if (! ctx.needsPosition)
	{
		this.resumeContext();
		return;
	}
	if (ctx.startFrom == null)
	{
		var pos = ctx.backward ? ctx.nMatches - ctx.numberOfRecords-ctx.offset : ctx.offset;
		this.chargeLeafExit(ctx.positionExit,pos);
		this.resumeContext();
		return;
	}

    ctx.condition=[];
    ctx.values=[];
    this.addDynamicFilterConditions(ctx);
    this.addRangeConditions(ctx);
    this.addMatchConditions(ctx);
    this.setOrderBy(ctx, true); // Regardless of <Backward>, we count all records before our own record
    this.addStartFromConditions(ctx);
    this.countMatches(ctx, function(ctx, count)
    {
    	var startFromPosition = count - 1; // If <Start From> is the first record we have count=1 and startFromPosition = 0);
    	var pos = ctx.backward ? 
    						startFromPosition+1-ctx.numberOfRecords-ctx.offset :
    						startFromPosition + ctx.offset;
		this.chargeLeafExit(ctx.positionExit,pos);
		this.resumeContext();
		return;
    });
};


 
// file: Alert.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 //Alert - displays something

Alert = function Alert() {};
Alert.prototype = new ActionNode();
Alert.prototype.constructor = Alert;

Alert.prototype.start = function startAlert()
{
	if (this.children && this.children['<Message>'] && tersus.alertMode.interactive)
	{
		var message =  tersus.unescapeString(''+this.getLeafChild('<Message>'));
		if (navigator.notification)
		{
			//Phonegap implementation
			this.pause();
			var self = this;
			var callback = function()
			{
				self.resume = function(){ this.finished();};
				self.continueExecution();
			};
			navigator.notification.alert(this.translate(message), callback, this.translate('Alert'), this.translate('OK'));			
		}
		else
		{
			//Native browser 'alert'
			this.currentWindow.alert(this.translate(message));
		}
	}
};

// file: Appears.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Appears = function Appears(){};
tersus.Appears.prototype = new ActionNode();
tersus.Appears.prototype.constructor = tersus.Appears;
tersus.Appears.prototype.start = function()
{
	var list = this.getTriggerValues('<Item>');
	var item = this.getChild('<Item>');
	var found = false;
	for (var i=0; i<list.length; i++)
	{
		var v = list[i];
		if (compareValues(v, item))
		{
			found = true;
			break;
		}
	}
	if (found)
		this.chargeExit('<Yes>', item);
	else
		this.chargeExit('<No>', item); 
		
};

// file: Arrow.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
function DisclosureArrow() {};
DisclosureArrow.prototype = new DisplayNode();
DisclosureArrow.prototype.constructor = DisclosureArrow;
DisclosureArrow.prototype.defaultTag = 'span';

// file: Average.js
/*********************************************************************************************************
 * Copyright (c) 2003-2010 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('Average', function()
{
	var numbers = this.getTriggerValues();
	
	if (numbers&& numbers.length > 0)
	{
		var sum = 0;
		for (var i=0; i<numbers.length; i++)
		{
			var value = numbers[i];
			if (value.leafValue != null)
			{
				sum += parseFloat(value.leafValue);
			}
		}
		this.chargeLeafExit('<Mean>', sum/numbers.length);
	}
});
// file: Back.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Back = function tersus_GetElmentName() {};
tersus.Back.prototype = new ActionNode();
tersus.Back.prototype.constructor = tersus.Back;
tersus.Back.prototype.start = function ()
{
	setTimeout(function () {window.history.back();},0);
};

// file: BackgroundAction.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.BackgroundAction = function tersus_BackgroundAction() {};
tersus.BackgroundAction.prototype = new ActionNode();
tersus.BackgroundAction.prototype.constructor = tersus.BackgroundAction;
tersus.BackgroundAction.prototype.start = function tersus_BackgroundAction_start()
{
	if (this.parent.isBackground)
	{
		// This is the "final" invocation (in the background)
		ActionNode.prototype.start.call(this);
	}
	else
	{
		// This is the "original" invocation that should start a background process
		var process = new BackgroundProcess(this.parent, this.element);
		if (this.triggers)
			for (var i = 0; i < this.triggers.length; i++)
			{
				var trigger = this.triggers[i];
			
				if (trigger.isRepetitive)
				{
					internalError("Repetitive triggers not supported in Background Action");
				}
				else
				{
					var value = this.getChild(trigger.role);
					if (value)
						process.setTriggerValue(trigger.role, value);
				}
			}
		setTimeout (function(){
		tersus.async.exec(function (){process.start()}, false /* don't wait */);},0);// Using setTimeout to ensure we're not continuing in same 'burst' of Javascript
	}
};

// file: Branch.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Branch() {};
Branch.prototype = new ActionNode();
Branch.prototype.constructor = Branch;
Branch.prototype.start = function ()
{
	var dataTrigger = this.getElement('<Data>');
	var selectorTrigger = this.getElement('<Selector>');
	if (! selectorTrigger) // For backward compatability
		selectorTrigger = this.getElement('<Value>');
	var selectorValue = selectorTrigger.getChild(this);
	var dataValue;
	if (dataTrigger)
		dataValue = dataTrigger.getChild(this);
	else
		dataValue = selectorValue;
	var defaultExit = this.getElement('<Other>');
	for (var i=0; i<this.exits.length; i++)
	{
		var exit = this.exits[i];
		if (exit != defaultExit)
		{
			var valueStr = exit.valueStr;
			if (valueStr == undefined)
				valueStr = exit.role;
			valueStr = valueStr.replace(/\\t/g, '\t');
			valueStr = valueStr.replace(/\\n/g, '\n');
			valueStr = valueStr.replace(/\\r/g, '\r');
			valueStr = valueStr.replace(/\\\\/g, '\\');

			if (selectorValue.toString() == valueStr)
			{
				this.chargeExit(exit, dataValue);
				return;
			}
			
		}
	}
	if (defaultExit)
		this.chargeExit(defaultExit, dataValue);
};
// file: BranchByType.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.BranchByType = function BranchByType(){};
tersus.BranchByType.prototype = new ActionNode();
tersus.BranchByType.prototype.constructor = tersus.BranchByType;
tersus.BranchByType.prototype.start = function()
{
	var input = this.getChild('<Input>');
	var otherExit = null;
	if (input)
	{
		for (var i=0; i<this.exits.length; i++)
		{
			var exit = this.exits[i];
			if (exit.role == '<Other>')
				otherExit = exit;
			else
			{
				var c = exit.getChildConstructor();
				if (c && c.prototype.isInstance(input))
				{
					this.chargeExit(exit, input);
					return;
				}
			}
		}
		if (otherExit)
			this.chargeExit(otherExit, input);
	}
};
// file: Button.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function Button(){};
Button.prototype = new DisplayNode();
Button.prototype.constructor = Button;
Button.prototype.type = 'Button';
Button.prototype.defaultTag = 'button';
Button.prototype.isButton = true;
Button.prototype.destroy = function()
{
	this.isDestroyed = true;
	DisplayNode.prototype.destroy.call(this);
};
Button.prototype.createChildren = function Button_createChildren()
{
	// we don't create the sub-hierarchy for a button.
};
Button.prototype.createViewNode = function Button_createViewNode()
{
    var tag = this.getTag();
    if (tag=='button')
    {
        var type=this.prop('type') || 'button';
        this.viewNode=$('<button type='+type+'/>',this.currentWindow.document)[0]; // Work-around for IE8 limitation on setting button type
    }
    else
        this.viewNode = this.createHTMLElement(tag);
    this.viewNode.setAttribute('lid',this.getNodeId());
	this.viewNode.innerHTML = tersus.escapeHTML(this.getCaption());
};
Button.prototype.captionChanged = function()
{
	if (this.viewNode)
		this.viewNode.innerHTML = tersus.escapeHTML(this.getCaption());
};
Button.prototype.setEventHandlers = function Button_setEventHandlers()
{
	DisplayNode.prototype.setEventHandlers.call(this);
	this.registerEventHandler(Events.ON_CLICK);
}
Button.prototype.doStart = function Button_start() 
{
	// We override doStart and not start because we don't want to trace 'Started' events for buttons
	this.waiting();
};
Button.prototype.onClick = function(domNode, callback)
{
	queueEvent(this, this.handleClick, [], new Date(), "Button clicked ["+this.getPath().str+"]", callback);
}; 
Button.prototype.handleClick = function tersus_Button_handleClick() 
{
	if (this.isDestroyed || !this.currentWindow || this.currentWindow.closed || this.disabled || this.status != FlowStatus.WAITING_FOR_INPUT)
	{
		return;
	}
	
	var validate = this.sharedProperties.validate != false; // null considered true
	var validationContext = this.getValidationContext();
	var valid = true;
	if (validate)
	{
		if (tlog) tlog('button.onclick:validating');
		valid = validationContext.validate();
	}
	if (valid)
	{
		if (tlog) tlog('button.onclick: starting handler');
		this.children = null;
		this.clicked = true;
		this.continueExecution();
		if (tlog) tlog('button.onclick: handler done');
	}
	else
		if (tlog) tlog('button.onclick: not valid');
	
};

Button.prototype.validate = function validate()
{
	return true; // Do not traverse children
};
Button.prototype.resume = function resumeButton()
{
	if (this.clicked)
	{
		this.clicked = false;
		this.started();
		FlowNode.prototype.start.call(this);
	}
	else 
		FlowNode.prototype.resume.call(this);
};
Button.prototype['get<Disabled>'] = function ()
{
	return this.disabled;
};

Button.prototype['set<Disabled>'] = function (disabled)
{
	this.disabled = disabled?true:false;
	if (this.viewNode)
	{
		this.viewNode.disabled=this.disabled;
		if (window.browser == 'IE') // IE 6.0 doesn't support the :disable CSS pseudoclass, so we use an explicit style as a workaround
		{
			if (disabled && !this.viewNode.className)
				this.viewNode.className = 'disabled';
			if (!disabled && this.viewNode.className=='disabled')
				this.viewNode.className = '';
		}
	}
};

// file: CancelTimer.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.CancelTimer = function tersus_CancelTimer() {};
tersus.CancelTimer.prototype = new ActionNode();
tersus.CancelTimer.prototype.constructor = tersus.CancelTimer;
tersus.CancelTimer.prototype.start = function()
{
	var timerId = this.getLeafChild("<Timer Id>");
	if (! timerId)
	{
		modelError("Missing <Timer Id> in \"Cancel Timer\" "+this.modelId);
		return;
	}
	if (tlog) tlog("Cancelled timer "+timerId);
	clearInterval(timerId);
};

// file: Checkbox.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Checkbox = function tersus_Checkbox () {};
tersus.Checkbox.prototype = new tersus.PushButton();
tersus.Checkbox.prototype.constructor = tersus.Checkbox;
tersus.Checkbox.prototype.buttonType='checkbox';
// <Value> property: for backwards compatability
tersus.Checkbox.prototype['get<Value>'] = tersus.PushButton.prototype['get<Checked>'];
tersus.Checkbox.prototype['set<Value>'] = tersus.PushButton.prototype['set<Checked>'];
tersus.Checkbox.prototype['remove<Value>'] = tersus.PushButton.prototype['remove<Checked>'];
tersus.Checkbox.prototype.labelClicked = function(domNode, callback)
{
	if (this.button && ! this.button.disabled)
	{
		this.button.checked = ! this.button.checked;
		this.onChange(domNode, callback);
	}
}

// file: Click.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Click = function Click() {};
tersus.Click.prototype = new ActionNode();
tersus.Click.prototype.constructor = tersus.Click;
tersus.Click.prototype.start = function ()
{
	var element = this.getChild('<Element>');
	var queue = this.getLeafChild('<Queue>');
	var action = this;
	var targetNode;
	if (element && element.getClickTarget)
		targetNode = element.getClickTarget();
	else if (element & element.eventTargets && element.eventTargers.onClick)
		targetNode= element.eventTargets.onClick;
	else if (element && element.viewNode)
	{
		targetNode = element.viewNode;
	}
	else 
	{
		targetNode = this.getLeafChild('<View Node>');
	}
	if (targetNode)
	{
		this.pause();
		var resume = function()
		{
		  	action.continueExecution();
		}
		var click = function() {
			if (is_touch_device())
				$(targetNode).trigger('vclick');
			else
				$(targetNode).click();
		 	tersus.async.exec(resume, false /* don't wait */);
		};
		tersus.async.exec(click, false /* don't wait  */); // not sure this behavior is correct
		/*
		 * Proposed improvement:
		 *  - If 'Click' runs in main thread it exits immediately and target is clicked later.
		    - If 'Click' runs in background, it pauses, and target is clicked when root contet is not busy ('wait=true') 
		  */
	}
}
tersus.Click.prototype.resume = function()
{
};

// file: CloseWindow.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 

//CloseWindow - closes the currentWindow

function CloseWindow(){};
CloseWindow.prototype = new ActionNode();
CloseWindow.prototype.constructor = CloseWindow();
CloseWindow.prototype.start = function()
{
	// Find the containing node that has a closeWindow method
	var node = this.getChild('<Dialog>');
	if (!node)
		node = this;
	while (node && !node.closeWindow) 
		node = node.parent;
	if (node && node.closeWindow)
		node.closeWindow();
};

// file: Collapse.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Collapse() {};
Collapse.prototype = new ActionNode();
Collapse.prototype.constructor = Collapse;
Collapse.prototype.start = function ()
{
	var item = this.getChild('<Item>');
	if (item.collapse)
		item.collapse();
};

// file: Compare.js
/*********************************************************************************************************
 * Copyright (c) 2003-2010 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('Compare', function()
{
	var x = this.getLeafChild('<X>');
	var y = this.getLeafChild('<Y>');
	
	if (x<y)
		this.chargeLeafExit('<X<Y>',x);
	if (x>y)
		this.chargeLeafExit('<X>Y>',x);
	if (x==y)
		this.chargeLeafExit('<X=Y>',x);
});
// file: Concatenate.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('Concatenate', function()
{
	var st = this.triggers.concat([]);
	var values = [];
	st.sort(function(a,b){ if (a.role < b.role) return -1; else if (a.role == b.role) return 0; else return 1;});
	var sep = this.getLeafChild('<Separator>');
	if (sep == null)
		sep = '';
	for (var i=0;i<st.length;i++)
	{
		var t = st[i];
		if (t.role != '<Separator>' && t.modelId != BuiltinModels.NOTHING_ID  )
		{
			if (t.isRepetitive)
			{
				var l =t.getChildren(this);
				if (l)
				{
					for (var j=0;j<l.length; j++)
					{
						var v = l[j];
						if (v!= null && v.leafValue != null)
							values.push(v.leafValue);
					}
				}
						
			}
			else
			{
				var v = t.getChild(this);
				if (v!= null && v.leafValue != null)
					values.push(v.leafValue);
			}
			
		}
	}
	var out = values.join(sep);
	this.chargeLeafExit('<Concatenation>',out);	
});


// file: Confirm.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
//Confirm - displays a confirmation message and retrieves user input
function Confirm() {};
Confirm.prototype = new ActionNode();
Confirm.prototype.constructor = Confirm;

Confirm.prototype.start = function startConfirm()
{
	var message =  tersus.unescapeString('' +this.getLeafChild('<Message>'));
	var response;
	if (tersus.alertMode.interactive)
		response = this.currentWindow.confirm(this.translate(message));
	else
		response = tersus.alertMode.confirm;
	if (response)
		this.chargeLeafExit('<OK>', message);
	else
		this.chargeLeafExit('<Cancel>', message);
};
// file: ConstructDate.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('ConstructDate', function()
{
	var d = new tersus.DateValue();
	d.year = this.getLeafChild('<Year>');
	d.month = this.getLeafChild('<Month>');
	d.day = this.getLeafChild('<Day>');
	this.chargeLeafExit('<Date>',d);	
});


// file: ConstructDateAndTime.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('ConstructDateAndTime', function()
{
	var y = this.getLeafChild('<Year>');
	var m = this.getLeafChild('<Month>');
	var d = this.getLeafChild('<Day>');
	var h = this.getLeafChild('<Hour>');
	var mi = this.getLeafChild('<Minute>');
	var s =  this.getLeafChild('<Second>');
	var ms =  this.getLeafChild('<Millisecond>');
	
	var dt = new Date(y,m-1, d, h, mi, s, ms);
	this.chargeLeafExit('<Date and Time>',dt);
});


// file: Convert.js
tersus.newAction('Convert',function() {
    var input = this.getChild('<Input>');
    var strict = this.getLeafChild('<Strict>');
    var exit = this.getExit('<Output>');

    if (input.isMap)
    {
	var output = exit.createChild(this);
	output.copyObject(input.leafValue,strict);
    }
    else
	throw "Convert currently only supports map as input";
});

// file: ConvertNumberToText.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.numberFormats = {};
tersus.newAction('ConvertNumberToText', function()
{
	var number = this.getLeafChild('<Number>');
	if (number == null)
		return;
	var formatStr = this.getLeafChild('<Format>');
	if (formatStr == null)
		this.chargeLeafExit ('<Text>',new String(number));
	else
		this.chargeLeafExit ('<Text>',gwtFormatNumber(number,formatStr));
});


// file: ConvertTextToNumber.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('ConvertTextToNumber', function()
{
	var text = this.getLeafChild('<Text>');
    if (text != null)
    {
    	if (tersus.isNumber(text))
    	{
    		var f = parseFloat(text);
    		if (! isNaN(f))
    		{
    			this.chargeLeafExit('<Number>',f);
    			return;
    		}
    	}
    	var nanExit = this.getExit('<Not a Number>');
    	if (nanExit != null)
    		this.chargeLeafExit(nanExit.role,text);
    	else
    		throw new tersus.Exception('Invalid number format '+text);
    }
});


// file: Count.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Count = function tersus_Count(){};
tersus.Count.prototype = new ActionNode();
tersus.Count.prototype.constructor = tersus.Count;
tersus.Count.prototype.start = function ()
{
	var values = this.getTriggerValues();
	this.chargeLeafExit('<Occurrences>',values.length);
};

// file: Create.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Create = function tersus_Create() {};
tersus.Create.prototype = new ActionNode();
tersus.Create.prototype.constructor = tersus.Create;
tersus.Create.prototype.start = function ()
{
	var modelId = this.getLeafChild('<Model Id>');
	var exit = this.getElement("<Object>");
	if (exit == null)
		return; // This can happen if user doesn't have permission for target type
	var modelNotFoundExit = this.getElement("<Model Not Found>");

	if (modelId != null)
	{
		var	constructor = tersus.repository.get(modelId);
		if (constructor!=null)
		{
			var value = new constructor();
			this.chargeExit(exit, value);
		}
		else
		{
			if (modelNotFoundExit!=null)
				this.chargeLeafExit(modelNotFoundExit.role,modelId);
			else
				modelExecutionError("Model not found:"+modelId,this);
				
		}
	}
	else
	{
		var value = exit.createChildInstance();
		this.chargeExit(exit, value);
	}
};

// file: CreateFromTemplate.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.CreateFromTemplate = function() {};
tersus.CreateFromTemplate.prototype = new ActionNode();
tersus.CreateFromTemplate.prototype.constructor = tersus.CreateFromTemplate;
tersus.CreateFromTemplate.prototype.start = function()
{
	var t = this.getLeafChild('<Template>');
	var i=0;
	var l = t.length;
	var out = [];
	while (i<l&& i>= 0)
	{
		var n = t.indexOf('${',i);
		if (n == -1)
		{
			out.push(t.substring(i));
			i = n;
		}
		else
		{
			out.push(t.substring(i,n));
			var b = n+ 2;
			var e=t.indexOf('}', b);
			if (e<0)
			{
				modelExecutionError("Invalid template: missing '}' for '${'.  Position="
							+ n
							+ " Text="
							+ t.substring(n, n + 20));
				return null;
			}
			var key=t.substring(b,e);
			out.push(this.getLeafChild(key));
			i = e+1;
		}

	}
	this.chargeLeafExit('<Text>',out.join(''));
}


// file: CreateJSON.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('CreateJSON', function()
{
	var value = this.getChild('<Value>');
	var serializer = new Serializer();
	var text = serializer.serialize(value); 
	this.chargeLeafExit('<JSON Text>', text);
});
// file: CreateLocation.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.CreateLocation = function tersus_CreateLocation() {};
tersus.CreateLocation.prototype = new ActionNode();
tersus.CreateLocation.prototype.RELATIVE='<Relative>';
tersus.CreateLocation.prototype.BASE_URL='<Base URL>';
tersus.CreateLocation.prototype.constructor = tersus.CreateLocation;
tersus.CreateLocation.prototype.start = function ()
{
	var relative = this.getTriggerLeafValue(this.RELATIVE);
	var baseURL = this.getTriggerLeafValue(this.BASE_URL);
	if (relative && baseURL)
	{
		modelExecutionError(this.RELATIVE + ' and '+ this.BASE_URL+'should not be used together in Create Location',this);
		relative = false;
	}
	var params;
	if (relative)
		params = tersus.getInternalParameters();
	else
		params = {};
	if (this.triggers)
	{
		for (var i=0; i< this.triggers.length; i++)
		{
			var trigger = this.triggers[i];
			if (trigger.role != this.RELATIVE && trigger.modelId != BuiltinModels.NOTHING_ID)
			{
				var value = trigger.getChild(this);
				if (value != null)
				{
					if (value.serialize)
						value = value.serialize();
					else
						value = value.leafValue;
				}
				params[trigger.role]= value;
			}
		}
	}
	
	var URL;
	if (baseURL)
	{
		URL = baseURL;
		if (URL.indexOf('#') < 0 && URL.indexOf('?')<0)
			URL+='?';
	}
	else
	{
		URL = tersus.getCurrentViewURL();
		if (URL.indexOf('#') <0)
			URL += '#';
	}
	
	var lastChar = URL.charAt(URL.length-1);
	var first =  lastChar == '#' || lastChar == '?';
	for (var p in params)
	{
		var v = params[p];
		if (v !== null && v !== undefined)
		{
			if (! first)
				URL +='&';
			URL += encodeURIComponent(p)+'='+encodeURIComponent(v);
			first = false;
		}
	}
	this.chargeLeafExit('<URL>',URL);		
};

// file: DatabaseQuery.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.DatabaseQuery = tersus.DatabaseAction.__subclass('tersus.DatabaseQuery');
tersus.DatabaseQuery.prototype.start = function()
{
	var sql = this.getSQLStatememt();
	var q = this.analyzeParameterizedSQL(sql);
	var values = [];
	for (var i=0; i<q.parameters.length; i++)
	{
		values.push(this.getSQLValue(q.parameters[i]));
	}
	this.pause();
	this.execSql(q.sqlText, values, function(transaction,results)
	{
		this.outputResults(results, this.getExit('<Results>'));
		this.resumeContext();
	});
};

// file: DatabaseUpdate.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.DatabaseUpdate = tersus.DatabaseAction.__subclass('tersus.DatabaseUpdate');
tersus.DatabaseUpdate.prototype.start = function()
{
	var sql = this.getSQLStatememt();
	var q = this.analyzeParameterizedSQL(sql);
	var values = [];
	for (var i=0; i<q.parameters.length; i++)
	{
		values.push(this.getSQLValue(q.parameters[i]));
	}
	this.pause();
	this.execSql(q.sqlText, values, function(transaction,results)
	{
		this.handleResults(results);
		this.resumeContext();
	});
};
tersus.DatabaseUpdate.prototype.handleResults = function(results)
{
	if (results)
	{
		if (results.rowsAffected != null)
			this.chargeLeafExit('<Number of Records Affected>',results.rowsAffected);
//		if (results.insertId != null)
//			this.chargeLeafExit('<Insert Id>', results.insertId);
		}
};
// file: DateField.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.DateField = function tersus_DateField() {};
tersus.DateField.prototype = new tersus.GenericField();
tersus.DateField.prototype.constructor = tersus.DateField;
tersus.DateField.prototype.isEditable = true;
tersus.DateField.popCalendar = function()
{
	var documentNode = this;
	var node = DisplayNode.findNodeForDocumentNode(documentNode);
	if (!node)
		return;
	var valueHandler = function valueHandler(year, month, day)
	{
		$(node.inputField).trigger('change');
	};
	node.currentWindow.popUpCalendar(this, this, valueHandler, DATE_FORMAT);
};
tersus.DateField.prototype.initWritable = function ()
{
	tersus.GenericField.prototype.initWritable.call(this);
	this.inputField.id = this.getNodeId();
	this.inputField.onclick = tersus.DateField.popCalendar;
	if (!tersus.isNumber(this.sharedProperties.size))
		this.inputField.size = 10;
};

tersus.DateField.prototype.onChange = function(domNode, callback)
{
	tersus.GenericField.prototype.onChange.call(this, domNode, callback);
	hideCalendar();
};
tersus.DateInputField = DateInputField = tersus.DateField; // Backward compatability


// file: Delete.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Delete = tersus.DatabaseAction.__subclass('tersus.Delete');
tersus.Delete.prototype.getTablePrototype = function()
{
	return this.getTrigger('<Record>').getChildConstructor().prototype;
};
tersus.Delete.prototype.run = function()
{
	var record = this.getChild('<Record>');
	var tableName = this.getTableName(record);
	var fieldList = this.getFieldList(record.constructor.prototype);
	var sqla = []; // 'buffer' for creating the sql
	var values = []; // values
	sqla.push('DELETE FROM ');
	sqla.push(tableName);
	this.addPrimaryKeyWhereClause(record,fieldList,sqla, values);
	var sql = sqla.join(' ');
	this.execSql(sql, values, function(transaction,results)
	{
		this.handleResults(results,record,tableName);
		this.resumeContext();
	});
			
};
tersus.Delete.prototype.handleResults = function(results, record, tableName)
{
	var count = results.rowsAffected;
	if (count == 1)
		this.chargeExit('<Deleted>',record);
	else if (count == 0)
		this.chargeExit('<Not Found>',record);
	else
		modelExecutionError("Delete resulted in deleting multiple records in table "
                                    + tableName
                                    + ". Check primary key settings", this);
                                    
};
// file: DeleteElement.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.DeleteElement = function DeleteElement(){};
tersus.DeleteElement.prototype = new ActionNode();
tersus.DeleteElement.prototype.constructor = tersus.DeleteElement;
tersus.DeleteElement.prototype.start = function()
{
	var e = this.getChild('<Element>');
	if (e && e.deleteMe)
		e.deleteMe();
	else
		internalError("Failed to delete child in "+this.getPath());
};

// file: Dialog.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.isIE6 = navigator.userAgent.indexOf('MSIE 6') >=0;
if ( tersus.isIPhone)
{
	tersus.Dialog = tersus.PopIn; // On iPhone (and iPhone simulation) we use a full pop-in for instead of a Dialog
}
else
{
	tersus.Dialog = tersus.PopIn.__subclass('Dialog');
	tersus.Dialog.prototype.setStyleClass = function(value)
	{
		if (this.pluginVersion>0)
			DisplayNode.prototype.setStyleClass.call(this,value);
	};
	
	tersus.Dialog.prototype.createViewNode = function()
	{
		// create mask (this gives modality by blocking UI access to existing content)
		clearSelection(this.currentWindow); // sometimes the original selection is extended to newly created elements
		var d = this.currentWindow.document;
		var r = this.getCurrentRootViewNode();
		var ml = this.createHTMLChildElement(r,'div');
		ml.className='dialog_mask';
		$(ml).css('z-index',++ tersus.topZindex);
		this.maskLayer = ml;
		// create dialog div
		var template = tersus.repository.getHTMLTemplate(this.templateURL);
		var dialog = importNode(d,template);
		var pStyle=this.sharedProperties.dialogPosition;
		if (pStyle)
		{
			$(dialog).attr('style',pStyle);
		}
		this.dialogLayer = dialog;
		dialog.style.position='absolute';
		var c = this.sprop('styleClass');
		dialog.className='dialog';
		
		this.viewNode = tersus.findChildNodesByClassName(dialog,'dialogBody')[0];
		if (this.viewNode)
		{
			this.header = tersus.findChildNodesByClassName(dialog,'dialogHeader')[0];
			this.footer = tersus.findChildNodesByClassName(dialog,'dialogFooter')[0];
		}
		else
			this.viewNode = dialog;
		this.isOpen = true;
		r.appendChild(dialog);
		$(dialog).css('z-index',++ tersus.topZindex);
		if (this.header)
		  this.header.innerHTML = tersus.escapeHTML(this.getPopupTitle());
		var w = this.sharedProperties.windowWidth;
		var h = this.sharedProperties.windowHeight;
		if ( ! w || w == ' ' || w == 'auto' ||  ! h || h == ' ' || h == 'auto' )
		{
		    /* Created "hiding" div in which dialog initialization will take place (to be removed on first resize)
		     * 
		     * Using a 0px X 0px div rather than a hidden (display:none) one because size calculations don't work on hidden elements
		     * 
		     */
		    var $c = $('<div style="position:absolute;overflow:hidden;top:0px;left:0px;height:0px;width:0px">', this.currentWindow.document);
		    $c.append($(dialog));
		    $(r).append($c);
		    var self=this;
		    tersus.async.exec(function(){self.onResize();$(r).append($(dialog));$c.remove()},true);
		}
		else
		      this.onResize();

		this.hideSelectNodes();
	};
	tersus.Dialog.prototype.onResize = function()
	{
		if (! (this.isOpen && this.currentWindow && ! this.currentWindow.closed && this.viewNode))
			return;
		var d = this.viewNode.ownerDocument;
	
		var s = getViewportSize(d);
		// Prevent infinite loop in Internet Explorer ...
		if (this.lastSize && this.lastSize.height == s.height && this.lastSize.width == s.width)
			return; // no change in size - nothing to do
		this.lastSize = s;
		var th = s.height - 8;
		var tw = s.width - 8;
	
        var dl = this.dialogLayer;
		var w = this.sharedProperties.windowWidth;
		if ( ! w || w == ' ' || w == 'auto')
		    w = $(dl).outerWidth(false);
		var h = this.sharedProperties.windowHeight;
		var hAuto = false;
		if ( ! h || h == ' ' || h == 'auto')
		{
		    h = $(this.viewNode).height();
		    th -= 82;
		    hAuto = true;
		}
		w = Math.min(w,tw);
		h = Math.min(h,th);
		$(dl).css('box-sizing','border-box').width(w);
		var pStyle=this.sharedProperties.dialogPosition;
		if (!pStyle)
		{
			var leftPx = parseInt((tw-w)/2);
			var topPx = parseInt((th-h)/2);
			var scroll = getWindowScroll(this.currentWindow);
			dl.style.top = (topPx + scroll.top )+'px';
			dl.style.left = (leftPx + scroll.left)+'px';
		}
		var ml = this.maskLayer;
		ml.style.height = s.height + 'px';
		ml.style.width = '100%';
		ml.style.position = 'absolute';
		ml.style.top = '0px';
		ml.style.left = '0px';

		var delta = 0;
		if (this.header)
			delta += getHeight(this.header);
		if (this.footer)
			delta += getHeight(this.footer);
		if (hAuto)
			delta += getHeight(this.viewNode);
		if (h-delta>20)
		{
		    $(this.viewNode).css('box-sizing','border-box').height(h-delta);
		}
		this.onResizeChildren();
	}
	tersus.Dialog.prototype.doClose = function() 
	{
		delete tersus.popupNodes[this.getNodeId()];
	
		if (this.isOpen)
		{
			this.resumeNavigation();
			this.viewNode = null;
			this.header = null;
			var dl = this.dialogLayer;
			var ml = this.maskLayer;
			this.dialogLayer=null;
			this.maskLayer=null;
			dl.parentNode.removeChild(dl);
			ml.parentNode.removeChild(ml);
		}
		this.isOpen = false;
		this.restoreSelectNodes();
	};
	tersus.Dialog.prototype.hideSelectNodes = function()
	{
	   	if (!tersus.isIE6)
	   		return;
		var l = this.currentWindow.document.body.getElementsByTagName('select');
		this.selectNodes = [];
		for (var i=0;i<l.length;i++)
			this.selectNodes.push(l[i]);
		for (var i=0;i<this.selectNodes.length;i++)
		{
			var n = this.selectNodes[i];
			var placeHolder = this.createHTMLElement('span');
			n.placeHolder=placeHolder;
			n.parentNode.replaceChild(placeHolder,n);			
		}
	
	};
 	tersus.Dialog.prototype.restoreSelectNodes = function()
	{
		if (this.selectNodes)
		{
			for (var i =0; i<this.selectNodes.length; i++)
			{
				var n =	this.selectNodes[i];
				var placeHolder = n.placeHolder;
				placeHolder.parentNode.replaceChild(n, placeHolder);
				n.placeHolder = null;
			}
		};
	};
	tersus.Dialog.prototype.setEventHandlers = function()
	{
		DisplayNode.prototype.setEventHandlers.call(this);
		this.dragNode = this.header ? this.header : this.viewNode;
	
		this.registerEventHandler(Events.ON_MOUSEDOWN, this.dragNode);
	};
	tersus.Dialog.prototype.onMouseDown = function(domNode, callback)
	{
		var atts = tersus.currentEventAttributes;
		if (!atts) return;
		callback();
		if (this.checkTargetElement(atts.targetElement))
		{
			var p = getScreenPosition(this.dialogLayer);
			this.dialogLayer.style.position='absolute';
			this.dialogLayer.style.top  = (p.top - getScroll(this.dialogLayer).top)+'px';
			this.dialogLayer.style.left = (p.left  - getScroll(this.dialogLayer).left)+'px';
			this.baseP = p;
			this.baseMouseP = {x:atts.clientX,y:atts.clientY};
			var node = this;
			var b = this.viewNode.ownerDocument.body;
			b.style.cursor = 'pointer';
			b.onmouseup = function(e)
			{
				node.onDrag(e);
				node.endDrag();
				return false; // disable default action (image drag) 
			};
			b.onmousemove = function(e)
			{
				node.onDrag(e);
				return false; //disable default action (image drag)
			}
			return false; //disable default action (image drag)
		}
		return true;// Don't disable default action
	};

	// Checks whether an element is a "good" drag source (doesn't have its own event handling logic)
	tersus.Dialog.prototype.checkTargetElement = function (targetElement)
	{
		if (targetElement == this.dragNode)
			return true;
		var n = targetElement;
		while (n && n != this.dragNode)
		{
			if (n.onclick || n.onmousedown || n.onmouseup || n.onmousemove || n.ondoubleclick)
				return false;
			if (n.tagName == 'INPUT' || n.tagName == 'TEXTAREA' || n.tagName == 'SELECT' || n.tagName == 'OPTION')
				return false;
			n = n.parentNode;
		}
		return true;
	};
	tersus.Dialog.prototype.endDrag = function()
	{
		var b = this.viewNode.ownerDocument.body;
		b.onmousemove = null;
		b.onmouseup = null;
		b.style.cursor = 'default';
	
	
	};
	tersus.Dialog.prototype.onDrag = function(e)
	{
		var atts;
		if (e)
			atts = getEventAttributes(e);
		else
			atts = getEventAttributes(this.currentWindow.event);
		if (!atts) return;
		this.dialogLayer.style.top = (this.baseP.top + atts.clientY - this.baseMouseP.y - getScroll(this.dialogLayer).top)+'px';
		this.dialogLayer.style.left = (this.baseP.left + atts.clientX - this.baseMouseP.x - getScroll(this.dialogLayer).left)+'px';
	
	}
}

// file: Dialog2.js
(function( $, undefined ) {
	if (!$.mobile)
		return;
tersus.Widget('Dialog2','Page', {
	baseProperties:{'data-role':'page'}
	,isDialog:true
	,attachViewNode:function()
	{
		this.mode = 'View';
		if (this.scope && this.scope.isText)
		{
			this.mode = this.scope.leafValue;
			if (this.mode == 'Page')
			{
				this.scope=this.parent;
				//Find containing page 
				while (this.scope && this.scope.plugin != 'Tersus/Widgets/Page')
					this.scope = this.scope.parent;
			}
		}
		else if (this.scope == window.rootDisplayNode)
			this.mode = 'View';
		else if (this.scope != null)
			this.mode = 'Embedded';

		if (this.mode == 'View')
		{
			$.mobile.pageContainer.add('#tersus\\.content').last().append(this.wrapperNode);
			this.previousPage = $.mobile.activePage;
		}
		else
		{
			var $self=$(this.wrapperNode);
			if (this.mode == 'Floating')
			{
				var theme = null;
				$.mobile.pageContainer.add('#tersus\\.content').last().append($self.addClass('ter-dialog ter-overlay'));
			}
			else
			{
				$(this.scope.wrapperNode).addClass('ter-dialog-container').append($(this.wrapperNode).addClass('ter-dialog'));;
			}
			var $h=$self.find('[data-role=header]');
			if ($h.length>0)
				$h.addClass( "ui-header ui-bar-" + (theme || $self.parent('[data-role=page]').data( "theme" ) || "a") ).find('h1').addClass('ui-title');
			else
				$self.addClass('ter-noheader');
			$self.find('[data-role=content]').addClass( 'ui-content');;
		}
		
	}
	,getScrollContainer:function()
	{
		if (! this.scrollContainer)
		{
			if (this.mode == 'View')
			{
				$(this.viewNode).wrapInner('<div>');
				this.scrollContainer =  this.viewNode;
			}
			else
				this.scrollContainer  = this.wrapperNode;
		}
		return this.scrollContainer;		
	}
	,isPopup:true
	,isPopin:true
	,start: function()
	{
		this.scope = this.getChild('<Scope>');
		if (this.element && ! this.element.prepareForHTML)
			this.element.prepareForHTML = DisplayElement.prototype.prepareForHTML;
		var w = this.currentWindow;
		var doc = w.document;
		clearSelection(w);
		this.create();
		FlowNode.prototype.start.call(this);
		this.isOpen = true;
		w.scrollTo(0,1);
		var transition;
		
		if (this.mode === 'View' )
		{
			$(this.viewNode).page({addBackBtn:false});
			transition = this.replacePage;
		}
		else
		{
			if (this.mode == 'Page')
			{
				$(this.viewNode).find('[data-role=header]').addClass('ui-header ui-bar ui-bar-a').find('h1').addClass('ui-title');
				$(this.viewNode).find('[data-role=content]').addClass('ui-content');
			}
			transition = this.mode == 'Floating' ?this.popDialog : this.slideIn ;
		}	
		var self = this;
		tersus.popupNodes[this.getNodeId()]=this;
		setTimeout(function(){transition.call(self);},200);
		
		// Make scope the DOM Parent
		// Set style on scope and self
	}
	,enhanceForms:function()
	{
		var $self = $(this.wrapperNode);
		$self
			.find( "input, textarea" )
            .not( "[type='radio'], [type='checkbox'], button, [type='button'], [type='submit'], [type='reset'], [type='image']" )
            .textinput();
	    $self
            .find( "input, select" )
            .filter( "[data-role='slider'], [data-type='range']" )
            .slider();

  		/*$self
            .find( "select:not([data-role='slider'])" )
            .selectmenu();*/
        $self
            .find( "[type='radio'], [type='checkbox']" )
            .checkboxradio();
        $self
	        .find( "button, [type='button'], [type='submit'], [type='reset'], [type='image']" ).not("[data-role='none']")
            .button();
	}
	,popDialog:function()
	{
		var $self = $(this.wrapperNode);
		this.enhanceForms();
           // enchance form controls
		$self.wrapInner('<div>');
		$self.addClass('ter-dialog-active pop in');


        
		this.onResize();
		$self.animationEnd(function() {
			$self.removeClass("pop out in reverse");
		});
	}
	,onResize: function()
	{
		var $self = $(this.wrapperNode);
		var $inner =$(this.viewNode);
		var th = tersus.availableHeight();
		if (this.mode == 'Floating')
		{
			var dh = $self.outerHeight();
			$self.css('top',(th-dh)/2);
			this.onResizeChildren();
		}
		else
		{
			if (this.mode=='View')
			{
//				$inner.css('height',th);
			    $inner.css('min-height',th);
			}
			else
			{
				$self.css('height',$(this.scope.wrapperNode).outerHeight());
				if (this.mode != 'Page')
					$self.css('width',$(this.scope.viewNode).innerWidth());
			}
			tersus.Page.prototype.onResize.call(this);
		}		
	}
	,slideIn:function()
	{
		var self=this;
		var $self = $(this.wrapperNode);
		this.enhanceForms();
		$self.addClass('ter-dialog-active ter-slide right');
		setTimeout(function()
		{
			$self.addClass('in');
			$self.animationEnd(function() {
			self.onResize();
			//Todo: at the end of the animation we probably want to clear these styles 
				//$self.removeClass("slide out in reverse");
			});
		},10);
	
	}
	,changePage: function(from, to, transition, back)
	{
		from.addClass( transition + " out " + ( back ? "reverse" : "" ) );
		to.addClass( $.mobile.activePageClass + " " + transition +
			" in " + ( back ? "reverse" : "" ) );
					// callback - remove classes, etc
		to.animationEnd(function() {
			from.add( to ).removeClass("out in reverse " + transition );
			from.removeClass( $.mobile.activePageClass );
			loadComplete();
			removeContainerClasses();
		});
	
	}
	
	,replacePage:function()
	{
		var self = this;
		var $self  = $(this.viewNode).page();
		$.mobile.activePage = $self;
		var $prev = this.previousPage;
		$self.addClass('ter-slide right ui-page-active');
		if ($prev != null)
			$prev.addClass('ter-slide left ui-page-active in');
		setTimeout(function()
		{
			$self.addClass('in');
			self.onResize();
			if ($prev)
			{
				$self.animationEnd(function()
				{
					$prev.removeClass('ui-page-active').add($self).removeClass('ter-slide right left in');
				});
				$prev.removeClass('in');
			}
		},10);
	}
	,destroy: function()
	{
		if (! this.isDestroyed)
		{
			this.isDestroyed = true;
			this.supr('destroy');
			this.doClose();
		}
	}
	,closeWindow: function() 
	{
		this.destroyHierarchy();
	}
	,refresh: function()
	{
		var wasactive = $(this.viewNode).hasClass('ui-page-active');
		tersus.Page.prototype.refresh.call(this);
		if (wasactive)
			$(this.viewNode).addClass('ui-page-active');
		
	}
	,doClose: function()
	{
		delete tersus.popupNodes[this.getNodeId()];
		var self=this;
		var $self = $(this.viewNode);
		var $wrapper = $(this.wrapperNode);
		if (this.isOpen)
		{
			if (this.mode == 'View')
			{
				var doc = this.currentWindow.document;
				var $prev=this.previousPage;
				$.mobile.activePage = $prev;
				
				if ($prev)
					$prev.addClass('ui-page-active ter-slide left');
				$self.addClass('ui-page-active ter-slide right in');
				setTimeout(function()
				{
					$self.animationEnd(function(){
							$wrapper.remove();
							$.fixedToolbars.show(true);
						});
					$self.removeClass('in');
					if ($prev)
						$prev.addClass('in');
					
				},0);
				

			}
			else if (this.mode == 'Floating')
			{
				$(this.wrapperNode).addClass('pop out reverse').animationEnd(function()
				{
					$wrapper.remove();
				});
			
			}
			else
			{
				var $scope = $(this.scope.viewNode);
				$wrapper.addClass('ter-slide right in');
				setTimeout(function()
				{
					$wrapper.removeClass('in').animationEnd(function()
					{
						$wrapper.remove();
						$scope.removeClass('ter-dialog-container');		
					});
				},0);
			}
			this.viewNode = null;
			this.rootNode = null;
		}
		this.isOpen = false;
	}
});
})(jQuery);

// file: Dialog3.js
tersus.Widget('Dialog3','HTMLTag', {
	isDialog:true
	

	,start: function()
	{
		this.setup();
		tersus.popupNodes[this.getNodeId()]=this;
		this.create();
		FlowNode.prototype.start.call(this);
		this.isOpen = true;
		this.currentWindow.scrollTo(0,1); // Shouldn't this be dependent on scope?
		var self = this;
		tersus.popupNodes[this.getNodeId()]=this;
		setTimeout(function(){self[self.placement].call(self);},0);
	}
	,defaultOptions: { 'Floating':'pop,float','View':'slide,replace','Embedded':'slide,cover','Page':'slide,replace'}
	,setup:function()
	{
		if (this.element && ! this.element.prepareForHTML)
			this.element.prepareForHTML = DisplayElement.prototype.prepareForHTML;
		var w = this.currentWindow;
		var doc = w.document;
		
		clearSelection(w);
	
		this.scope = this.getChild('<Scope>');
		if (this.scope && this.scope.isText)
		{
			this.mode = this.scope.leafValue;
			if (this.mode == 'Page')
			{
				//Find containing page 
				this.scope=this.parent;
				while (this.scope && this.scope.isPage)
					this.scope = this.scope.parent;
			}
			else
				this.scope = w.currentRootDisplayNode; // Not sure this is correct
		}
		else if (this.scope)
			this.mode = 'Embedded';
		else
		{
			this.mode = 'Floating';
			this.scope = w.currentRootDisplayNode;
		}
		
		var options = this.getLeafChild('<Options>') || this.defaultOptions[this.mode];
		var p = options.split(/,/);
		if (p.length != 2)
			throw 'Dialog <Options> must be of the form "[transition],[placement]" - e.g "slide,replace" or "pop,over"';
		this.animationName = p[0];
		/*if (this.animationName == 'slide')
			this.animationName='ter-slide right';*/
		this.placement = p[1];
		
		this.previousNode = this.scope.currentDialog ||  this.scope;
		this.container = this.previousNode.wrapperNode || this.previousNode.viewNode;
		this.replacedNode = null;
		if (this.placement == 'replace')
		{
			this.replacedNode = this.container;
			this.container = this.container.parentNode;
		}
	}
	,float:function()
	{
		var $self = $(this.wrapperNode);
		this.$mask=$('<div>').addClass('ter-dialog-mask').css('zindex',++tersus.topZindex);
		$self.before(this.$mask);
		$self.css('zindex',++tersus.topZindex);
		$self.addClass(this.animationName + ' ter-active in');
		this.onResize = function()
		{
			var th = tersus.availableHeight();
			var dh = $self.outerHeight();
			$self.css('top',(th-dh)/2);
			this.$mask.css('height',th);
			this.onResizeChildren();
		}
		this.onResize();
		$self.animationEnd(function() {
			$self.removeClass("ter-slide slide pop out in reverse right left");
		});
	}
	,unfloat:function()
	{
		var $self = $(this.wrapperNode);
		var self = this;
		$self.addClass(this.animationName + ' out');
		$self.animationEnd(function() {
			$self.remove();
			self.$mask.remove();
			self.$mask = null;
		});
	}
	,cover:function()
	{
		this.onResize = function()
		{
			var $self  = $(this.wrapperNode);
			var $inner = $(this.viewNode);
			$self.css('height',$(this.container).outerHeight());
			this.onResizeChildren();					
		}
		var self=this;
		var $self = $(this.wrapperNode);
		$self.addClass('ter-active '+this.animationName);
		setTimeout(function()
		{
			$self.addClass('in');
			$self.animationEnd(function() {
			self.onResize();
			//Todo: at the end of the animation we probably want to clear these styles 
				//$self.removeClass("slide out in reverse");
			});
		},10);
	}
	,uncover:function()
	{
		var $self = $(this.wrapperNode);
		$self.addClass(this.animationName + ' out');
		$self.animationEnd(function() {
			$self.remove();
		});
	}
	,replace:function()
	{
		var $prev = $(this.previousNode.wrapperNode || this.previousNode.viewNode);
		var $self = $(this.wrapperNode);
		this.scope.currentDialog=this;
		tersus.transition($prev, $self, 'ter-active', this.animationName, null);
	}
	,unreplace:function()
	{
		var $prev = $(this.previousNode.wrapperNode || this.previousNode.viewNode);
		var $self = $(this.wrapperNode);
		this.scope.currentDialog=this.previousNode;
		tersus.transition($self, $prev, 'ter-active', this.animationName + ' reverse', function(){$self.remove();});
	}

	,attachViewNode:function()
	{
		$(this.container).addClass('ter-dialog-container').append($(this.wrapperNode).addClass('ter-dialog'));
	}

	,destroy: function()
	{
		if (! this.isDestroyed)
		{
			this.isDestroyed = true;
			this.supr('destroy');
			this.doClose();
		}
	}
	,closeWindow: function() 
	{
		this.destroyHierarchy();
	}
	
	,doClose: function()
	{
		delete tersus.popupNodes[this.getNodeId()];
		var self=this;
		self['un'+self.placement].call(self);
		this.isOpen = false;
	}
});

// file: DialogFooter.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.DialogFooter = function tersus_DialogFooter() {};
tersus.DialogFooter.prototype = new Row();
tersus.DialogFooter.prototype.constructor = tersus.DialogFooter;
tersus.DialogFooter.prototype.attachViewNode = function DialogFooter_attachViewNode()
{
	this.tableNode  = this.createHTMLElement('table');
	this.tbodyNode = this.createHTMLElement('tbody');
	this.tableNode.appendChild(this.tbodyNode);
	this.tbodyNode.appendChild(this.viewNode);
	if (this.parent&& this.parent.footer)
		this.parent.footer.appendChild(this.tableNode);

}
PopupFooter=tersus.DialogFooter; // For backward compatability
// file: Divide.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Divide = function tersus_Divide() {};
tersus.Divide.prototype = new ActionNode();
tersus.Divide.prototype.constructor = tersus.Divide;
tersus.Divide.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	var y = this.getLeafChild('<Y>');
	if (this.getElement('<Ratio>'))
		this.chargeLeafExit('<Ratio>', x/y);
	if (this.getElement('<Quotient>'))
		this.chargeLeafExit('<Quotient>',parseInt(x/y));
	if (this.getElement('<Remainder>'))
		this.chargeLeafExit('<Remainder>',x%y);
};

// file: DualDisplay.js
// This is not really a plugin - just a set of functions that implement flipping
tersus.DualDisplay = {

flip:function flip_dual_display(node)
{
	var parent = node.parent.parent.viewNode;

	parent.mode = 3 - parent.mode;
	tersus.DualDisplay.set(parent);
},
init: function init_dual_display(node)
{
	var parent = node.parent.parent.viewNode;
	parent.mode = 1;
	var s = parent.lastChild.style;
	s.display='none';
	setTimeout(function(){tersus.DualDisplay.set(parent);s.display='';},10);
},

set: function set_dual_display(parent)
{
	var option1 = parent.firstChild;
	var option2 = option1.nextSibling;
	var h = getVisibleSize(parent).height;
	if (parent.mode == 1)
	{
		option1.style['-webkit-transform']='none';
		option2.style['-webkit-transform']='translateY('+h+'px)';
		$(option1).css('-moz-transform','none');
		$(option2).css('-moz-transform','translate(0px,'+h+'px)');
	}
	else
	{
		option1.style['-webkit-transform']='translateY(-'+h+'px)';
		option2.style['-webkit-transform']='none';
		$(option1).css('-moz-transform','translate(0px,-'+h+'px)');
		$(option2).css('-moz-transform','none');
	}
}
};

// file: DynamicDisplay.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.DynamicDisplay = function tersus_DynamicDisplay() {};
tersus.DynamicDisplay.prototype = new DisplayNode();
tersus.DynamicDisplay.prototype.constructor = tersus.DynamicDisplay;
tersus.DynamicDisplay.prototype.defaultTag = 'span';
tersus.DynamicDisplay.prototype.content = null;
tersus.DynamicDisplay.prototype.initViewNode = function()
{
	this.viewNode.style.display='none';
};

// file: DynamicInvocation.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.DynamicInvocation = function tersus_DynamicInvocation() {};
tersus.DynamicInvocation.prototype = new FlowNode();
tersus.DynamicInvocation.prototype.constructor = tersus.DynamicInvocation;
tersus.DynamicInvocation.prototype.doStart = function ()
{
	this.started();
	var modelId = null;
	modelId = this.getLeafChild('<Model Id>');
	if (! modelId)
	{
		modelExecutionError('<Model Id> is missing',this);
		return;
	}
	/* We create a process of the given model, copy trigger values on to it, and then invoke it
	 * (including outgoing links).
	 *
	 */
	
	var	constructor = tersus.repository.get(modelId);
	if (! constructor)
	{
		modelExecutionError('Model \''+modelId+'\' is missing',this);
		return;
	}
	var process = new constructor();
	process.element = this.element;
	process.parent = this.parent;
	process.mainWindow = this.mainWindow;
	process.currentWindow = this.currentWindow;
	if (process.triggers)
	{
		for (var i = 0; i < process.triggers.length; i++)
		{
			var trigger = process.triggers[i];
			var dTrigger = this.getElement(trigger.role);
			if (dTrigger)
			{
				if (trigger.isRepetitive)
				{
					var values = dTrigger.getChildren(this);
					dTrigger.removeChildren(this);
					for (var j=0; j< values.length; j++)
					{
						var value = values[j];
						trigger.addAChild(process,value)
					}
				}		
				else
				{
					var value = dTrigger.getChild(this);
					if (value)
						trigger.replaceChild(process,value);
				}
			}
		}
	}
	var node = this;
	process.whenDone = function()
	{
		node.finished();
	};
	process.setStatus(FlowStatus.READY_TO_START);
	process.invoke();
};

// file: Earlier.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Earlier = function tersus_Earlier() {};
tersus.Earlier.prototype = new ActionNode();
tersus.Earlier.prototype.constructor = tersus.Earlier;
tersus.Earlier.prototype.start = function ()
{
	var time1 = this.getChild('<Time 1>');
	var time2 = this.getChild('<Time 2>');
	if (tersus.getDate(time1) < tersus.getDate(time2))
		this.chargeExit('<Yes>', time1);
	else
		this.chargeExit('<No>', time1);
};


// file: EarlierOrEqual.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.EarlierOrEqual = function tersus_EarlierOrEqual() {};
tersus.EarlierOrEqual.prototype = new ActionNode();
tersus.EarlierOrEqual.prototype.constructor = tersus.EarlierOrEqual;
tersus.EarlierOrEqual.prototype.start = function ()
{
	var time1 = this.getChild('<Time 1>');
	var time2 = this.getChild('<Time 2>');
	if (tersus.getDate(time1) <= tersus.getDate(time2))
		this.chargeExit('<Yes>', time1);
	else
		this.chargeExit('<No>', time1);

};


// file: Earliest.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Earliest = function tersus_Earliest() {};
tersus.Earliest.prototype = new ActionNode();
tersus.Earliest.prototype.constructor = tersus.Earliest;
tersus.Earliest.prototype.start = function ()
{
	var trigger = this.getElement('<Times>');
	var list = trigger.getChildren(this);
	if (list&& list.length > 0)
	{
		var earliest = list[0];
		for (var i=1;i<list.length;i++)
		{
			var next = list[i];
			if (tersus.getDate(next) < tersus.getDate(earliest))
				earliest = next;
		}
		this.chargeExit('<Earliest>', earliest);
	}
};


// file: EmbeddedHTML.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.EmbeddedHTML = function tersus_EmbeddedHTML(){};
tersus.EmbeddedHTML.prototype = new DisplayNode();
tersus.EmbeddedHTML.prototype.constructor = tersus.EmbeddedHTML;
tersus.EmbeddedHTML.prototype.defaultTag = 'div';
tersus.EmbeddedHTML.prototype.onload = function()
{
	tersus.repository.loadHTMLTemplate(tersus.translateResource(this.sharedProperties.templatePath));
};
tersus.EmbeddedHTML.prototype.createViewNode = function()
{
	var template = tersus.repository.getHTMLTemplate(tersus.translateResource(this.sharedProperties.templatePath));
	this.viewNode = importNode(this.currentWindow.document,template);
};
tersus.EmbeddedHTML.prototype.createChildren = function EmbeddedHTML_createChildren()
{
	if (this.displayElements)
	{
		/* Prepare a hash table with the nodes that correspond to different elements*/
		this.childNodeMap = {};
		tersus.EmbeddedHTML.addChildrenToMap(this.viewNode, this.childNodeMap);
		for (var i=0; i<this.displayElements.length; i++)
		{
			var e = this.displayElements[i];
			if ( !e.isRepetitive && ! e.isMethodElement)
			{
				var child = e.createChildWithoutVisuals(this);
				var childViewNode = this.childNodeMap[e.role];
				if (childViewNode)
				{
					child.setViewNode(childViewNode);
					childViewNode.setAttribute('element_name',null);
					child.setEventHandlers();
					child.createChildren();
				}
				else
					alert('Missing element '+e.role+ " in template (path="+this.getPath()+")");
				
			}
		}
	}
	
};
tersus.EmbeddedHTML.addChildrenToMap = function(scope, map)
{
	//Not reusing createNodeMap because in this case we don't traverse the whole hierarchy
	var children = scope.childNodes;
	for (var i=0; i< children.length; i++)
	{
		var childNode = children[i];
		if (childNode.nodeType == 1 /*Node.ELEMENT_NODE*/ )
		{
			var childName = childNode.getAttribute('element_name');
			if (childName != null)
				map[childName]=childNode;
			else					
				tersus.EmbeddedHTML.addChildrenToMap(childNode, map);
		}
	}
};tersus.EmbeddedElement = function EmbeddedElement(){};
tersus.EmbeddedElement.prototype = new tersus.EmbeddedHTML();
tersus.EmbeddedElement.prototype.constructor = tersus.EmbeddedElement;
tersus.EmbeddedElement.prototype.onload = function()
{
};

tersus.EmbeddedElement.prototype.createViewNode = function tersus_EmbeddedElement_createViewNode()
{
	var parentViewNode = this.parent.viewNode;
	this.templateNode = this.parent.childNodeMap[this.element.role];
	if (!this.templateNode)
		modelError("Failed to locate template node for "+this.getPath());
	this.viewNode = this.templateNode.cloneNode(this.templateNode,true);
	this.viewNode.setAttribute('element_name',null);
	this.viewNode.style.display='';
};
tersus.EmbeddedElement.prototype.attachViewNode = function tersus_EmbeddedElement_attachViewNode()
{
	this.templateNode.parentNode.insertBefore(this.viewNode,this.templateNode);
};

// file: EndsWith.js
/*********************************************************************************************************
 * Copyright (c) 2003-2012 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('EndsWith', function()
{
	var text = this.getLeafChild('<Text>');
	var suffix = this.getLeafChild('<Suffix>');
	if (text != null && suffix != null)
	{
		if (text.length >= suffix.length && text.substring(text.length-suffix.length) == suffix)
			this.chargeLeafExit('<Yes>',text);
		else
			this.chargeLeafExit('<No>',text);
	}
});
 
 
// file: Equals.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Equal() {};
Equal.prototype = new ActionNode();
Equal.prototype.constructor = Equal;
Equal.prototype.YES='<Yes>';
Equal.prototype.NO='<No>';
Equal.prototype.start = function ()
{
	var values = this.getTriggerValues();
	var lastValue = null;
	var allEqual = true;
	for (var j=0; j<values.length && allEqual; j++)
	{
		var value = values[j];
		if (lastValue == null)
			lastValue = value;
		else if (! compareValues(lastValue, value))
		{
			allEqual = false;
		}
	}
	if (allEqual)
	{
		if (this.getElement(this.YES))
			this.chargeExit(this.YES, lastValue);
	}
	else
	{
		if (this.getElement(this.NO) != null)
		{
			this.chargeEmptyExit(this.NO);
		}
	}	
};

// file: EqualsWithTolerance.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.EqualWithTolerance = function tersus_EqualWithTolerance() {};
tersus.EqualWithTolerance.prototype = new ActionNode();
tersus.EqualWithTolerance.prototype.constructor = tersus.EqualWithTolerance;
tersus.EqualWithTolerance.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	var y = this.getLeafChild('<Y>');
	var tolerance = this.getLeafChild('<Tolerance>');
	if (x == null)
		modelExecutionError('Missng value for <X>', this);
	if (y == null)
		modelExecutionError('Missng value for <Y>', this);
	if (tolerance == null)
		modelExecutionError('Missng value for <Tolerance>', this);
	if (Math.abs(x-y) < tolerance)
		this.chargeLeafExit('<Yes>',x)
	else
		this.chargeLeafExit('<No>',x);
};

// file: EscapeRegex.js
/*********************************************************************************************************
 * Copyright (c) 2003-2012 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('EscapeRegex', function()
{
	var text = this.getLeafChild('<Text>');
	if (text != null)
		this.chargeLeafExit('<Escaped Text>',text.replace(/([.?*+^$[\]\\(){}|-])/g, "\\$1"));
});
 
 
// file: ExcludeFromList.js
/*********************************************************************************************************
 * Copyright (c) 2003-2010 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('ExcludeFromList', function()
{
	var listTrigger = this.getElement('<List>');
	if (!listTrigger)
	{
		modelError("Missing trigger <List>");
		return;
	}
	
	var list = listTrigger.getChildren(this);
	var excludeTrigger = this.getElement('<Exclude>');
	
	if (list)
	{
		var excludeList;
		if (excludeTrigger.isRepetitive)
			excludeList = excludeTrigger.getChildren(this); 
		else
			excludeList = [excludeTrigger.getChild(this)];
		
		
		for (var i = 0; i < list.length; i++)
		{
			var toExclude = false;
			for (var j = 0; j< excludeList.length; j++)
			{	
				if (compareValues(excludeList[j], list[i]))
				{
					toExclude = true;
					break;
				}
			}
			
			if (!toExclude)
				this.accumulateExitValue('<Remaining>', list[i]);
		}
	}
});

// file: Exists.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 //Exits - checks if a trigger value was received

Exists = function Exists() {};
Exists.prototype = new ActionNode();
Exists.prototype.constructor = Exists;
Exists.prototype.start = function startExists()
{
	var value = null;
	if (this.triggers)
	{
		for (var i=0; i< this.triggers.length; i++)
		{
			var trigger = this.triggers[i];
			if (trigger.isRepetitive)
			{
				var values = trigger.getChildren(this);
				if (values && values.length>0)
				{
					value = values[0];
					break;
				}
			}
			else
			{
				value = trigger.getChild(this);
				if (value != null)
					break;
			}
		}
	}
	if (value != null)
	{
		this.chargeExit('<Yes>', value);
		
	}
	else
	{
		this.chargeEmptyExit('<No>');
	}
};
// file: Expand.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Expand() {};
Expand.prototype = new ActionNode();
Expand.prototype.constructor = Expand;
Expand.prototype.start = function ()
{
	var item = this.getChild('<Item>');
	var node = this;
	item.onExpand = function()
	{
		node.continueAfterExpand();
		item.onExpand = null;
	};
	node.pause();
	item.expand();
};
Expand.prototype.continueAfterExpand = function()
{
		this.continueExecution();
};
// file: Extract.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('Extract', function()
{
	var text = this.getLeafChild('<Text>');
    if (text != null)
    {
        var beginIndex = this.getLeafChild('<Position>');
        if (beginIndex <0)
        {
	        modelExecutionError('Negative <Position>',this);
    	    return;
    	}
        var length = this.getLeafChild('<Length>');
        var endIndex = text.length;
        if (length != null)
        {
            if (length < 0)
		        modelExecutionError('Negative <Length>',this);
            endIndex = beginIndex + length;
            if (endIndex > text.length)
            {
               modelExecutionError("<Text> ('" + text
                            + "') too short to extract a segment of length "
                            + length + " at position " + beginIndex + ".");
               return;
            }
        }
        var segment = text.substring(beginIndex, endIndex);
        this.chargeLeafExit('<Segment>', segment);
	}
});


// file: FileInputField.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
FileInputField = function FileInputField() {
};
FileInputField.prototype = new DisplayNode();
FileInputField.prototype.constructor = FileInputField;

FileInputField.prototype.isFileInputField = true;

FileInputField.prototype.createViewNode = function createViewNode()
{
    this.fileNode = this.currentWindow.document.createElement('input');
    this.fileNode.type = 'file';
    if (this.sharedProperties.accept)
    	this.fileNode.accept=this.sharedProperties.accept;
    this.viewNode = this.currentWindow.document.createElement('form');
    this.viewNode.className='inline';
    this.viewNode.appendChild(this.fileNode);
    if (this.sharedProperties.size)
    	this.viewNode.size = this.sharedProperties.size;
};

FileInputField.prototype._onChange = function()
{
    this.inputFile = null;
};
FileInputField.prototype['get<Value>'] = function getFieldValue()
{
	if (!this.fileNode || this.fileNode.value == "")
		if (this.children && this.children['<Value>'])
			return this.children['<Value>'];
		else
			return null;
	if (! this.inputFile)
	{
		var element = this.getElement('<Value>');
		if (element)
		{
			this.inputFile = element.createChildInstance();
			this.inputFile.inputFieldDisplayNode = this;
		        this.inputFile.window=this.currentWindow;
			var files = this.fileNode.files;
			if (files && files.length == 1)
			    this.inputFile.file = files.item(0);
		}
	}
	return this.inputFile;
};

FileInputField.prototype.registerEventHandler = function(event, domNode)
{
	if (!domNode)
		domNode = this.fileNode;
	DisplayNode.prototype.registerEventHandler.call(this,event,domNode);
};


// file: FilterNumbers.js
/*********************************************************************************************************
 * Copyright (c) 2003-2010 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('FilterNumbers', function()
{
	var numbersTrigger = this.getElement('<Numbers>');
	var numbers = numbersTrigger.getChildren(this);
	var filter = this.getChild('<Filter>');
	
	var filteringNumber = null;
	if (this.triggers)
	{
		for (var i=0; i< this.triggers.length; i++)
		{
			var trigger = this.triggers[i];
			var triggerRole = trigger.role;
			if (!('<Numbers>' == triggerRole) && !('<Filter>' == triggerRole))
			{
				filteringNumber = trigger.getChild(this);
				break;
			}
		};
	}
	
	if (numbers)
	{
		var filterValue = filter.leafValue;
		for (var i=0; i< numbers.length; i++)
		{
			var number = numbers[i].leafValue;
				
			if (filterValue.substring(0,2) == "<=" && number <= filteringNumber)
				this.accumulateExitValue('<Matching>', numbers[i]);
			else if (filterValue.substring(0,1) == "<" && number < filteringNumber)
				this.accumulateExitValue('<Matching>', numbers[i]);
			else if (filterValue.substring(0,1) == "=" && number == filteringNumber)
				this.accumulateExitValue('<Matching>', numbers[i]);
			else if (filterValue.substring(0,2) == ">=" && number >= filteringNumber)
				this.accumulateExitValue('<Matching>', numbers[i]);
			else if (filterValue.substring(0,1) == ">" && number > filteringNumber)
				this.accumulateExitValue('<Matching>', numbers[i]);
		};
	}
});

// file: Find.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Find =  tersus.DatabaseAction.__subclass('tersus.Find');
tersus.Find.prototype.getTablePrototype = function()
{
	return this.getExit('<Records>').getChildConstructor().prototype;
};
tersus.Find.prototype.run = function()
{
	var exit = this.getExit('<Records>');
	if (!exit)
	{
		modelError('Missing exit <Records>',this);
		return;
	}
	var  p = exit.getChildConstructor().prototype;
	var fl = this.getFieldList(p);
	var triggers  = this.triggers;
	if (triggers == null)
		triggers = [];
	var tableName = this.getTableName(p);
	var sqla = [];
	var explicitColumns = fl == null ? '*' : null;
	this.addSelectFieldsSQL(sqla, tableName, fl, explicitColumns);
	
	var first = true;
	var values = [];
	for (var i=0;i<triggers.length; i++)
	{
		var trigger = triggers[i];
		if (trigger.modelId == BuiltinModels.NOTHING_ID) // Control trigger
			continue;
		if (trigger.role.search(/<.*>$/)>=0) // Distinguished trigger (e.g. <Data Source>)
			continue;
		var field = fl.getField(trigger.role);
		if (first)
		{
			sqla.push('WHERE');
			first = false;
		}
		else
			sqla.push('AND');
		sqla.push(field.sqlName);
		var v = this.getSQLValue(trigger.role);
		if ( v == null)
			sqla.push ('IS NULL');
		else
		{
			sqla.push('= ?');
			values.push(v);
		}
	}
	var orderBy = this.getLeafChild('<Order By>');
	if (orderBy != null)
	{
		sqla.push('ORDER BY');
		sqla.push(orderBy);
	}
	var sql = sqla.join(' ');
	this.execSql(sql, values, function(transaction,results)
	{
		this.outputResults(results, exit);
		this.resumeContext();
	});
};

// file: FindElements.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function FindElements() {};
FindElements.prototype = new ActionNode();
FindElements.prototype.SCOPE_TRIGGER_ROLE='<Scope>';
FindElements.prototype.OPTIONS_TRIGGER_ROLE='<Options>';
FindElements.prototype.MAX_RESULTS='<Max Results>';
FindElements.prototype.constructor = FindElements;

FindElements.prototype.start = function ()
{
	var filter = this.createFilter();
	var items = [];
        var maxResults = this.getLeafChild(this.MAX_RESULTS);
	var scope = this.getChild(this.SCOPE_TRIGGER_ROLE);
	if (scope)	
		scope.scanChildren(filter, {}, items, maxResults);
	else
	{
		// NO scope specified - scan everywhere
		window.rootDisplayNode.scanChildren(filter, {}, items);
		tersus.unregisterPopupNodes();
		for (var popupId in tersus.popupNodes)
		{
			node = tersus.popupNodes[popupId].scanChildren(filter, {}, items);
		}
	}
	if (items.length == 0)
	{
		var exit = this.getElement('<None>');
		if (exit)
			this.chargeEmptyExit(exit);
	}
	else
	{
		for (var i=0; i<items.length; i++)
		{
			var item = items[i];
			this.accumulateExitValue('<Elements>',item);
		}
	};
};

FindElements.prototype.createFilter = function()
{
	var filter = {};
	filter.components = [];
	var exit = this.getElement('<Elements>');
	var options = this.getChildren(this.OPTIONS_TRIGGER_ROLE);
	var ignoreCase=false;
	var useRegex=false;
	var allowPartial=false;
	for (var i=0;i<options.length;i++)
	{
		var v = options[i].leafValue;
		if (v.match(/ignore case/i))
			ignoreCase=true;
		if (v.match(/regular expressions/i))
			useRegex=true;
		if (v.match(/allow partial/i))
			allowPartial=true;
	}
	filter.modelId = exit.modelId;
	if (this.triggers)
		for (var i=0; i< this.triggers.length; i++)
		{
			var trigger = this.triggers[i];
			if (trigger.role != this.SCOPE_TRIGGER_ROLE && trigger.modelId != BuiltinModels.NOTHING_ID && trigger.role != this.OPTIONS_TRIGGER_ROLE && trigger.role != this.MAX_RESULTS)
			{
				var value = trigger.getChild(this);
				
				if (useRegex && value.isText)
				{
					var modifier = ignoreCase?'i':'';
					var pattern=value.leafValue;
					if (!allowPartial)
						pattern='^'+pattern+'$';
					var r = new RegExp(pattern, modifier);
					filter.components.push ({role:trigger.role,value:null,regex:r});
					
				}
				else
					filter.components.push ({role:trigger.role,value:value,regex:null});
			};
		};
	filter.match = function(item)
	{
		if (filter.modelId != tersus.ANYTHING && item.modelId != this.modelId)
			return false;
		for (var i =0; i<this.components.length;i++)
		{
			var component = this.components[i];
			if (component.role == '<Element Name>')
			{
				if (!item.element)
					return false;
				var role = item.element.role;
				if (component.regex)
				{
					if (!component.regex.test(role))
						return false;
				}
				else
				{	
					var testValue = component.value.leafValue;
					if (ignoreCase)
					{
						if (role.toUpperCase() != testValue.toUpperCase())
							return false;
					}
					else
					{
						if (role != component.value.leafValue)
							return false;
					}
				}
			}
			else
			{
				var element = item.getElement(component.role)
				if (element)
				{
					var value = element.getChild(item);
					if (value && value.isDataNode)
						value = value.value;  // Get the underlying value (not the wrapper)
					if (component.regex)
					{
						if (value == null || !component.regex.test(value.leafValue))
							return false;
					}
					else
					{
						if (!compareValues(value, component.value, ignoreCase))
							return false;
					}
						
				}
				else
				{ 
					return false;
				}
			}
		}
		return true;
	};
	return filter;
};

// file: FireEvent.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.FireEvent = function FireEvent() {};
tersus.FireEvent.prototype = new ActionNode();
tersus.FireEvent.prototype.constructor = tersus.FireEvent;
tersus.FireEvent.prototype.start = function ()
{
	var element = this.getChild('<Element>');
	var eventName = this.getLeafChild('<Event Name>');
	var parameters = {};
	for (var i = 0; i < this.triggers.length; i++)
	{
		var t = this.triggers[i];
		if (t.role.search('<') < 0)
		{
			var v;
			if ( t.isRepetitive)
				v =  t.getChildren(this);
			else
				v = t.getChild(this);
			if (v != null)
				parameters[t.role]=v;
		}
	}
	tersus.invokeAction(eventName, parameters, null, element, true);
};


// file: First.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.First = function tesrsus_First(){};
tersus.First.prototype = new ActionNode();
tersus.First.prototype.constructor = tersus.First;
tersus.First.prototype.start = function ()
{
	var trigger = this.getElement('<List>');
	var list = trigger.getChildren(this);
	if (list&& list.length > 0)
	{
		var first = list[0];
		this.chargeExit('<First>', first);
		
	}
};

// file: FloatClose.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.FloatingClose = function tersus_DialogFooter() {};
tersus.FloatingClose.prototype = new Row();
tersus.FloatingClose.prototype.constructor = tersus.FloatingClose;
tersus.FloatingClose.prototype.attachViewNode = function DialogFooter_attachViewNode()
{
	
	//this.divNode = this.createHTMLElement('div');
	
	//this.divNode.appendChild(this.viewNode);
	if (this.parent&& this.parent.close)
	{
		this.parent.close.appendChild(this.viewNode);
	}

}
//PopupFooter=tersus.FloatingClose; // For backward compatability
// file: Focus.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('Focus', function()
{
	var e = this.getChild('<Element>');
	if (e.focus)
		e.focus();
	else if (e.viewNode.focus)
		e.viewNode.focus();
});


// file: FormatDateAndTime.js
/*********************************************************************************************************
 * Copyright (c) 2003-2010 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at http://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('FormatDateAndTime', function()
{
	var dt0 = this.getChild('<Date and Time>');
	var dt = tersus.getDate(dt0);
	var t = dt.getTime();
	var tz = this.getLeafChild('<Time Zone>');
	if (tz != null)
	{
		modelExecutionError('<Time Zone> not supported in client side version of Format Date and Time (consider using <Time Zone Offset>)',this);
		return;
	}
	var tzOffset = this.getLeafChild('<Time Zone Offset>');
	if (tzOffset == null)
		tzOffset=-10000;
	else
		tzOffset=-tzOffset; // GWT timezone offset is reverse from intuitive.
	var format = this.getLeafChild('<Format>');
	var text  = gwtFormatDateAndTime(t, format, tzOffset);
	this.chargeLeafExit('<Text>',text);
});

// file: Forward.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Forward = function tersus_GetElmentName() {};
tersus.Forward.prototype = new ActionNode();
tersus.Forward.prototype.constructor = tersus.Forward;
tersus.Forward.prototype.start = function ()
{
	setTimeout(function () {window.history.forward();},0);
};

// file: GetCookie.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function GetCookie() {};
GetCookie.prototype = new ActionNode();
GetCookie.prototype.constructor = GetCookie;
GetCookie.prototype.start = function ()
{
	var name = this.getLeafChild('<Name>');
	if (name)
	{
		name=tersus.sqlize(name);
		var value;
		if (tersus.isNative && window.localStorage)
			value = localStorage.getItem('Cookie.'+name,value);
		else
			value = getCookie(name);
			
		if (value != null && value.length>0)
			this.chargeLeafExit('<Value>',value);
	}
};

// file: GetElement.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.GetElement = function tersus_GetElement() {};
tersus.GetElement.prototype = new ActionNode();
tersus.GetElement.prototype.constructor = tersus.GetElement;
tersus.GetElement.prototype.start = function ()
{
	var elementName = this.getLeafChild('<Element Name>');
	var exit = this.getExit('<Element>');
	var parent = this.getChild('<Parent>');
	if (parent && parent.leafValue && parent.leafValue.tagName) // Special handling of html node attributes
	{
		var attributeValue = parent.leafValue.getAttribute(elementName);
		this.chargeLeafExit('<Element>',attributeValue);
	}
	else if (parent != null && parent.getChild)
	{
		
		var element = parent.getElement(elementName);
		var values = null;
		if (element)
		{
			if (element.isRepetitive)
			{
				values = element.getChildren(parent);
				if (values)
				{
					if (!exit.isRepetitive)
						for (var i=0;i<values.length;i++)
							this.chargeExit(exit, values[i]);
					else
						for (var i=0;i<values.length;i++)
							this.accumulateExitValue(exit, values[i]);
											 
				}
			}
			else
			{
				var value = element.getChild(parent);
				if (value != null)
				{
					if (!exit.isRepetitive)
						this.chargeExit(exit, value);
					else
						this.accumulateExitValue(exit, value);
				}
			}
		}
	}
};

// file: GetElementName.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.GetElementName = function tersus_GetElementName() {};
tersus.GetElementName.prototype = new ActionNode();
tersus.GetElementName.prototype.constructor = tersus.GetElementName;
tersus.GetElementName.prototype.start = function ()
{
	var displayElement = this.getChild('<Element>');
	if (displayElement && displayElement.element)
	{
		var name = displayElement.element.role;
		this.chargeLeafExit('<Name>',name);
	}
};

// file: GetEventAttributes.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.GetEventAttributes = function tersus_GetEventAttributes() {};
tersus.GetEventAttributes.prototype = new ActionNode();
tersus.GetEventAttributes.prototype.constructor = tersus.GetEventAttributes;
tersus.GetEventAttributes.prototype.start = function()
{
	var atts = tersus.currentEventAttributes;
	if (atts)
	{
		this.chargeLeafExit('<Event Type>', atts.type);
		this.chargeLeafExit('<Key Code>', atts.keyCode);
		this.chargeLeafExit('<Mouse Button>',atts.button);
		this.chargeLeafExit('<Mouse X>',atts.clientX);
		this.chargeLeafExit('<Mouse Y>',atts.clientY);
		this.chargeLeafExit('<Control Key>', atts.ctrlKey==true);
        this.chargeLeafExit('<Shift Key>', atts.shiftKey==true);
        this.chargeLeafExit('<Alt Key>', atts.altKey==true);
        this.chargeLeafExit('<Meta Key>', atts.metaKey==true);
		var e = this.getExit('<Target Element>');
		if (e)
			this.chargeExit(e, DisplayNode.findNodeForDocumentNode(atts.targetElement));
	    var e = this.getExit('<Files>');
	    if (e && atts.files)
	    {
            for (var i=0;i<atts.files.length;i++)
            {
                var file = e.createChildInstance();
                file.file = atts.files[i]
                file.setLeafChild('Content Type', file.file.type, Operation.REPLACE);
                this.accumulateExitValue(e, file);
            }
	    }
	}
};

// file: GetGeolocation.js
tersus.newAction('GetGeolocation',function()
{
	var position = null;
	var enableHighAccuracy = this.getLeafChild('<Enable High Accuracy>') || false;
	var timeout = this.getLeafChild('<Timeout>');
	var maxAge = this.getLeafChild('<Maximum Age>');
	
	var options = {enableHighAccuracy:enableHighAccuracy, maximumAge:maxAge, timeout:timeout};
	var gl = navigator.geolocation;
	if (gl && gl.getCurrentPosition)
	{
		this.pause();
		this.errorMessage=null;
		var nodeId = this.getNodeId();
		gl.getCurrentPosition(function(p){tersus.GetGeolocation.handleResponse(p,null,nodeId);}
		, function(error){tersus.GetGeolocation.handleResponse(null, error,nodeId);}
		,options);
	}
  	else
		this.chargeEmptyExit('<None>');	
});

tersus.GetGeolocation.prototype.resume = function()
{
	if (this.errorMessage)
		throw this.errorMessage;
};
tersus.GetGeolocation.handleResponse = function (p,error, nodeId)
{
	var node = tersus.findNode(nodeId);
	if (!node && node.status != FlowStatus.PAUSED)
		return;
	if (error)
	{
	    if (error.code == error.TIMEOUT && node.elements && node.elements['<Timed Out>'] )
	        node.chargeEmptyExit('<Timed Out>');
	    else if (error.code == error.PERMISSION_DENIED && node.elements && node.elements['<Permission Denied>'])
            node.chargeEmptyExit('<Permission Denied>');
	    else
	        node.errorMessage=error.message;
	}
	else 
	{
		if (p)
		{
			var exit = node.getExit('<Geolocation>');
   	     	if (exit)
   	     	{   	     		
  				var loc = exit.createChildInstance();
  				var cElement = loc.getElement('Coordinates');
  				var cStruct = cElement.createChild(loc);
  				var c = p.coords;
  				cStruct.setLeafChild('Latitude',c.latitude, Operation.REPLACE);
  				cStruct.setLeafChild('Longitude',c.longitude, Operation.REPLACE);
  				cStruct.setLeafChild('Accuracy',c.accuracy, Operation.REPLACE);
  				cStruct.setLeafChild('Altitude',c.altitude, Operation.REPLACE);
  				cStruct.setLeafChild('Altitude Accuracy',c.altitude_accuracy, Operation.REPLACE);
  				cStruct.setLeafChild('Heading',c.heading, Operation.REPLACE);
  				cStruct.setLeafChild('Speed',c.speed, Operation.REPLACE);
  				
  				
  				var ts = p.timestamp;
  				if (ts)
  				{
  					var dt = new Date();
  					dt.setTime(ts);
  					loc.setLeafChild('Timestamp',dt,  Operation.REPLACE);
  				}
  				node.chargeExit(exit,loc);
  			}
  		}
  		else
			node.chargeEmptyExit('<None>');
	}	
	node.continueExecution();
};
// file: GetIndex.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('GetIndex', function()
{
	var e = this.getChild('<Element>');
	if (e.element && e.element.isRepetitive)
	{
		var siblings = e.element.getChildren(e.parent);
		for (var i=0;i<siblings.length;i++)
		{
			if (siblings[i] == e)
				this.chargeLeafExit('<Index>',this.pluginVersion>0 ? i+1 : i);
		}
	}
	
});


// file: GetMapEntry.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('GetMapEntry', function()
{
	var map = this.getChild("<Map>");
	if (map && map.leafValue)
		map = map.leafValue;
	
	var key = this.getChild("<Key>");
	if (key && key.leafValue != null)
		key = key.leafValue;
		
	var value = map[key];
	if (value)
	{
		if (value.isNode)
		    this.chargeExit('<Value>',value);
	        else
		    this.chargeLeafExit('<Value>',value);
	}
	else
	    this.chargeEmptyExit('<None>',value);	
});

// file: GetModel.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.GetModel = function tersus_GetModel() {};
tersus.GetModel.prototype = new ActionNode();
tersus.GetModel.prototype.constructor = tersus.GetModel;
tersus.GetModel.prototype.start = function ()
{
	var modelId = null;
	if (this.getElement('<Model Id>') && this.getElement('<Instance>'))
		modelError("'<Model Id>' and '<Instance>' shouldn't both be specified");
	if (this.getElement('<Model Id>'))
	{
		modelId = this.getLeafChild('<Model Id>');
	}
	else
	{
		instance = this.getChild('<Instance>');
		if (instance)
			modelId = instance.modelId;
	}
	var model = null;
	if (modelId)
		model = tersus.repository.get(modelId).prototype;
	if (model)
	{
		if (! model.wrapper)
		{
			var exit =  this.getExit('<Model>');
			model.wrapper = exit.createChildInstance();
			model.wrapper.model = model;
		}
		this.chargeExit('<Model>',model.wrapper);
	}
};

// file: GetNumberedItem.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.GetNumberedItem = function tersus_GetNumberedItem() {};
tersus.GetNumberedItem.prototype = new ActionNode();
tersus.GetNumberedItem.prototype.constructor = tersus.GetNumberedItem;
tersus.GetNumberedItem.prototype.start = function ()
{
	var listTrigger = this.getElement('<List>');
	if (!listTrigger)
	{
		modelError("Missing trigger <List>");
		return;
	}
	var list = listTrigger.getChildren(this);
	if (list)
	{
		var index = this.getLeafChild('<Index>');
		if (index == null)
		{
			modelExecutionError('No <Index> specified',this);
			return;
		}
		if (index>=1 && index <= list.length)
			this.chargeExit('<Item>', list[index-1]);
			
		else if (this.getElement('<Invalid Index>'))
			this.chargeLeafExit('<Invalid Index>',index);
		else
		{
			modelExecutionError('Invalid trigger '+index+' (list size is '+list.length + ')', this)
			return;
		}
	}
};

// file: GetPageParamters.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function GetPageParameters() {};
GetPageParameters.prototype = new FlowNode();
GetPageParameters.prototype.constructor = GetPageParameters();

GetPageParameters.prototype.start = function()
{
	for (var i=0; i< this.exits.length; i++)
	{
		var exit = this.exits[i];
		var paramValue = tersus.searchParams[exit.role];
		if (paramValue)
		{
			this.setLeafChild(exit.role, paramValue, Operation.REPLACE);
		}
	}
};
// file: GetParent.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.GetParent = function GetParent(){};
tersus.GetParent.prototype = new ActionNode();
tersus.GetParent.prototype.constructor = tersus.GetParent;
tersus.GetParent.prototype.start = function()
{
	var trigger = this.getTrigger('<Element>');
	var parent = null;
	if (trigger != null) // Get the parent of the specified element
	{
		var element = trigger.getChild(this);
		if (element)
		{
			parent = element.parent;
		}
	}
	else // Get the DisplayNode that contains this action
	{
		parent = this;
		while (parent && !parent.isDisplayNode)
			parent = parent.parent;
	}
	if (parent)
		this.chargeExit('<Parent>',parent);	
};

// file: GetPosition.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('GetPosition', function()
{
	var text = this.getLeafChild('<Text>');
	var segment = this.getLeafChild('<Segment>');
	if (text != null && segment != null)
	{
		var position = text.indexOf(segment);
			if (position >= 0)
				this.chargeLeafExit('<Position>',position);
			else
			{
				if (this.getExit('<Not Found>') != null)
					this.chargeLeafExit('<Not Found>', segment);
				else
					modelExecutionError("Segment '" + segment + "' is not contained in '" + 
						text + "' but " + NOT_FOUND + " exit is missing", this);
			}	
	}
});
// file: GetStyleAttribute.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('GetStyleAttribute', function()
{
	var e = this.getChild('<Element>');
	var n = this.getLeafChild('<Attribute>');
	var a = tersus.getJsAttributeName(n);
	if (e && e.viewNode && a)
	var v = e.viewNode.style[a];
	this.chargeLeafExit('<Value>',v);
});


// file: GetTableSelection.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function GetTableSelection() {};
GetTableSelection.prototype = new FlowNode();
GetTableSelection.prototype.constructor = GetTableSelection;
GetTableSelection.prototype.start = function getTableSelection()
{
	var table = this.getChild('<Table>');
	var selection = table.selectedRow;
	if (selection)
		this.setChild('<Selected Row>', selection, Operation.REPLACE);
	else
		this.setLeafChild('<None Selected>', 'none', Operation.REPLACE);
};

// file: GetWeek.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function GetWeek() {};
GetWeek.prototype = new FlowNode();
GetWeek.prototype.constructor = GetWeek;
GetWeek.prototype.start = function getWeek()
{
	var date = this.getChild('<Date>');
	if (!date)
		return;
	var year = date.getYear();
	var month = date.getMonth();
	var day = date.getDay();
	// Algorithm from http://www.tondering.dk/claus/calendar.html

	var a = Math.floor((14-month) / 12);
	var y = year + 4800 - a;
	var m = month + 12 * a - 3;
	var b = Math.floor(y/4) - Math.floor(y/100) + Math.floor(y/400);
	var J = day + Math.floor((153 * m + 2) / 5) + 365 * y + b - 32045;
	var d4 = (((J + 31741 - (J % 7)) % 146097) % 36524) % 1461;
	var L = Math.floor(d4 / 1460);
	var d1 = ((d4 - L) % 365) + L;
	var week = Math.floor(d1/7) + 1;
	var weekYear = year;
	if (week == 1 && month == 12)
		weekYear = year+1;
	if (week >= 52 && month == 1)
		weekYear = year-1;
		
	this.setLeafChild('<Year>', weekYear, Operation.REPLACE);
	this.setLeafChild('<Week Number>', week, Operation.REPLACE);		
};

// file: GotoURL.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.GotoURL = ServiceNode.__subclass('tersus.GotoURL');
tersus.GotoURL.prototype.excludedTriggers=new Set(['<URL>','<Method>', '<Replace>','<Reload>', '<Target Window>']);
tersus.GotoURL.prototype.isAction=true;
tersus.GotoURL.prototype.start = function ()
{
	var url = this.getLeafChild('<URL>');
	if (url == null)
		url = tersus.rootURL;
	var replace = this.getLeafChild('<Replace>');
	var reload = this.getLeafChild('<Reload>');
	if (reload != false)
		reload = true;
	var targetWindow = this.getLeafChild('<Target Window>');
	if (targetWindow != null)
		if (this.pluginVersion && this.pluginVersion >= 1)
			targetWindow=tersus.sqlize(targetWindow);
	var method = this.getLeafChild('<Method>');
	
	if (method && method.search('^post$','i') >=0)
	{
		var form = this.prepareForm();
		if (targetWindow)
			form.target  = targetWindow;
		if (url.indexOf('?')>=0)
		{
			modelExecutionError('POST parameters are not part of the URL and should be provided using separate triggers');
			return;
		}
		form.action = url;
		form.method='POST';
		form.submit();
		for (var i=0; i< this.nodesToRemove.length; i++)
		{
			var node = this.nodesToRemove[i];
			node.parentNode.removeChild(node);
		}
	}
	else
	{
		var serializer;
		if (this.triggers)
		{
			var n = this.triggers.length;
			for (var i=0;i<n;i++)
			{
				var t = this.triggers[i];
				if (this.excludedTriggers.contains(t.role) || t.modelId == BuiltinModels.NOTHING_ID)
					continue;
				var value = t.getChild(this);
				if (value == null)
					continue;
				if (url.indexOf('#') < 0 && url.indexOf('?')<0)
					url+='?';
				else
					url += '&';
				url += encodeURIComponent(t.role)+'='+encodeURIComponent(value.leafValue);				
			}
		}
		if (targetWindow)
		{
			var w = window.open(url,targetWindow);
			if (w && w.focus)
				tersus.async.exec(function() {w.focus();}, false /* don't wait */); // Needed in Firefox
			else
				alert('Your browser blocks pop-up windows.\nTo use this application, please configure the browser to allow this site to open pop-up windows.');
		}				
		else
			tersus.async.exec(function () {tersus.gotoURL(url, replace, reload);}, false /* don't wait */);
	}
};

// file: Greater.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Greater = function tersus_Greater() {};
tersus.Greater.prototype = new ActionNode();
tersus.Greater.prototype.constructor = tersus.Greater;
tersus.Greater.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	var y = this.getLeafChild('<Y>');
	if (x > y)
		this.chargeLeafExit('<Yes>',x);
	else
		this.chargeLeafExit('<No>',x);
};

// file: GreaterOrEqual.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.GreaterOrEqual = function tersus_GreaterOrEqual() {};
tersus.GreaterOrEqual.prototype = new ActionNode();
tersus.GreaterOrEqual.prototype.constructor = tersus.GreaterOrEqual;
tersus.GreaterOrEqual.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	var y = this.getLeafChild('<Y>');
	if (x >= y)
		this.chargeLeafExit('<Yes>',x);
	else
		this.chargeLeafExit('<No>',x);
};

// file: Grid.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Grid = function tersus_Grid() {};
tersus.Grid.prototype = new Table();
tersus.Grid.prototype.constructor = tersus.Grid;
tersus.Grid.prototype.createCaption = tersus.Grid.prototype.createHeader = function() {};

// file: HTMLDisplay.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.HTMLDisplay = function tersus_HTMLDisplay(){};
tersus.HTMLDisplay.prototype = new tersus.DisplayField();
tersus.HTMLDisplay.prototype.constructor = tersus.HTMLDisplay;
tersus.HTMLDisplay.prototype.defaultTag = 'div';
tersus.HTMLDisplay.prototype.allowHTMLTags = true;

// file: HTMLEditor.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.HTMLEditor = function tersus_HTMLEditor(){};
tersus.HTMLEditor.prototype = new DisplayNode();
tersus.HTMLEditor.prototype.constructor = tersus.HTMLEditor;
tersus.HTMLEditor.prototype.defaultTag = 'textarea';
tersus.HTMLEditor.prototype.createViewNode = function()
{
	DisplayNode.prototype.createViewNode.call(this);
	this.open();
};
tersus.HTMLEditor.commandMap = { 'mceImage':'<Insert Image>'}
tersus.HTMLEditor.execCommandHandler = function tersus_html_editor_command_handler(editor_id, elm, command, user_interface, value)
{
	if (!elm)
		return false;
	if ( ! tersus.HTMLEditor.commandMap[command])
		return false;
	var w = getParentWindow(elm).parent;
	var tMCE = tersus.HTMLEditor.getTinyMCE(w);
	if (tMCE)
	{
		var editorInstance = tMCE.getInstanceById(editor_id);
		var nodeId = editor_id.match(/mce_(\d+)/)[1];
		var node = tersus.findNode(nodeId);
		
		var element = node.getElement(tersus.HTMLEditor.commandMap[command]);
		if (element)
		{
			var child = element.createChild(node);
			resumeRoot(); // child will be executerd
			if (child.isButton) // we need to simulate pushing the button
				child.onClick();

			
			return true;
		}

	}

	return false;
	
};
tersus.HTMLEditor.defaultSettings = 
{
	mode : "none"
	,theme : "advanced" 
	,content_css : "Styles?timestamp="+tersus.lastStyleModification
	,execcommand_callback : tersus.HTMLEditor.execCommandHandler
};
tersus.HTMLEditor.prototype.createChildren = function()
{ // supressing child creation - child elements represent components of the externally defined editor 
  // in the future we may support adding elements to the display
};
tersus.HTMLEditor.loaded = false;
tersus.HTMLEditor.loading = false;
window.tinyMCE_onload =  function tinyMCE_onload()
{
	var w = window;
	if (tersus.HTMLEditor.customizeTinyMCE)
		tersus.HTMLEditor.customizeTinyMCE(w);	
	w.tinymce.dom.Event.domLoaded=true;
	var s = {}; // settings for tinyMCE
	var d = tersus.HTMLEditor.defaultSettings;
	for (p in d)
		s[p]= d[p];
	var u = tersus.HTMLEditor.settings; // user settings
	if (u)
	{
		for (p in u)
			s[p]=u[p];
	}
	w.tinyMCE.init(s);
	w.tinyMCE_loaded = true;
	w.tinyMCE_loading = false;
	tersus.foreach(w.tinyMCE_openQueue, function(node)
	{
		node.showEditor();
	});
}
tersus.HTMLEditor.prototype.open = function()
{
	var node = this;
	var w = this.currentWindow;
	if (!w.tinyMCE_loaded && !w.tinyMCE_loading)
	{
		w.tinyMCE_loading = true;
		w.tinyMCE_openQueue = [];
		tersus.loadScript('tiny_mce/tiny_mce_src.js',w);
	}
 	if (w.tinyMCE_loaded)
		tersus.async.exec( function () {node.showEditor();}, false /* don't wait */);
 	else
	 	w.tinyMCE_openQueue.push(node);
	this.open = true;
};
tersus.HTMLEditor.prototype.showEditor = function()
{
	var tMCE = this.getTinyMCE();
	if (tMCE)
	{
		var id = 'mce_'+this.getNodeId();
		this.editorId = this.viewNode.id = this.viewNode.name = id;
        tMCE.execCommand('mceAddControl', false, id);
//		tinyMCE.execCommand('mceFocus',false,this.getEditorId());
//		editorInstance.select();
	}
		
	else
		modelExecutionError("HTML Editor not available",this);
};
tersus.HTMLEditor.prototype.getEditor = function()
{
	var tMCE = this.getTinyMCE();
	if (tMCE && this.open)
		return tMCE.get(this.editorId);
	else
		return null;
};
tersus.HTMLEditor.prototype.invokeAction  = function(action, caller)
{
	//Todo - some actions (e.g. focus) may need to be invoked as global command
	//     - some actions may be implemented in the model 
	var editor = this.getEditor();
	if (editor)
	{
		var value = caller.getLeafChild('Value');
		editor.execCommand(action, false, value);
		editor.execCommand('mceRepaint');
	}
};
tersus.HTMLEditor.prototype.destroy = function()
{
	if (this.open)
	{
		var tMCE = this.getTinyMCE();
		var node = this;
		if (tMCE)
		{
			// Because of timing issues it is possible that tinyMCE still doesn't know about our editor.
			// In such cases we don't remove it (and there's a danger of memory leak - probably mainly on older browsers)
			if (this.editorId && tMCE.get(this.editorId))
				tMCE.execCommand('mceRemoveControl', false, node.editorId);
		}
		this.open = false;
	}
	
	DisplayNode.prototype.destroy.call(this);
};
tersus.HTMLEditor.getTinyMCE = function (w)
{
	var tMCE = null;
	try
	{
		if (w && ! w.closed)
			tMCE = w.tinyMCE;
	}
	catch (e)
	{
	}
	return tMCE;
};
tersus.HTMLEditor.prototype.getTinyMCE = function()
{
	return tersus.HTMLEditor.getTinyMCE(this.currentWindow);
};
tersus.HTMLEditor.prototype['get<HTML Text>'] = function()
{
	var editor = this.getEditor();
	if (editor)
		return editor.getContent();
};
tersus.HTMLEditor.prototype['get<Selected HTML Text>'] = function()
{
	var editor = this.getEditor();
	if (editor)
	{
		var sel = new TinyMCE_Selection(editor);
		return sel.getSelectedHTML();
	}
};
tersus.HTMLEditor.prototype['get<Selected HTML Element>'] = function()
{
	var editor = this.getEditor();
	if (editor)
	{
		var sel = editor.selection;
		if (sel)
			return sel.getNode();
	}
};
tersus.HTMLEditor.setHTML = tersus.HTMLEditor.prototype['set<HTML Text>'] = function(text)
{
	if (!this.open)
	{
		alert('Editor Not Open');
		return;
	}
	var node = this;
	var f = function()
	{
		var editor = node.getEditor();
		if (editor)
			setTimeout(function(){editor.setContent(text);},100);
		else
			setTimeout(f, 100);
	}
	setTimeout(f, 100);
};


// file: Hyperlink.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function Hyperlink() {};
Hyperlink.prototype = new DisplayNode();
Hyperlink.prototype.constructor = Hyperlink;
Hyperlink.prototype.defaultTag = 'span';

// file: Identical.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('Identical', function()
{
	var values = this.getTriggerValues();
	var lastValue = null;
	var allEqual = true;
        var firstValue = values[0];
        if (values.length>1)
        {
	    for (var j=1; j<values.length && allEqual; j++)
	    {
		var value = values[j];
	        allEqual = (firstValue === value);
	    }
	}
	if (allEqual)
	{
	    this.chargeExit("<Identical>", firstValue);
	}
	else
	{
	    this.chargeEmptyExit("<Not Identical>");
	}	
});

// file: Image.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Image = function TersusImage(){};
tersus.Image.prototype = new DisplayNode();
tersus.Image.prototype.constructor = tersus.Image;
tersus.Image.prototype.getTag = function()
{
	return "img";
};
tersus.Image.prototype['set<Path>'] = function( path)
{
	this.srcPath = path;
	this.viewNode.src = tersus.translateResource(path);
};
tersus.Image.prototype['get<Path>'] = function()
{
	if (this.srcPath)
		return this.srcPath;
	else
		return null;
};

// file: Insert.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Insert = tersus.DatabaseAction.__subclass('tersus.Insert');
tersus.Insert.prototype.getTablePrototype = function()
{
	return this.getTrigger('<Record>').getChildConstructor().prototype;
};
tersus.Insert.prototype.run = function()
{
	var record = this.getChild('<Record>');
	var tableName = this.getTableName(record);
	var fieldList = this.getFieldList(record.constructor.prototype);
	var dupExit = this.getExit('<Duplicate>');
	if (dupExit)
		this.checkDup(record,tableName,fieldList);
	else
		this.insert(record,tableName,fieldList);
};
tersus.Insert.prototype.checkDup = function(record,tableName, fieldList)
{
	var sqla = [];
	var values = [];
	sqla.push("SELECT COUNT(1) as count FROM ");
	sqla.push(tableName);
	this.addPrimaryKeyWhereClause(record,fieldList,sqla, values);
	var sql = sqla.join(' ');
	this.execSql(sql, values, function(transaction,results)
	{
		var count = results.rows.item(0)['count'];
		if (count > 0)
		{
			this.chargeExit('<Duplicate>', record);
			this.resumeContext();			
		}
		else
			this.insert(record,tableName,fieldList);
	});
	
};
tersus.Insert.prototype.insert = function(record, tableName, fieldList)
{
	
	var sqla = []; // 'buffer' for creating the sql
	sqla.push('INSERT INTO');
	sqla.push(tableName);
	sqla.push('(');
	var values = []; // values
	var fields = fieldList.fields;
	var nfields = fields.length;
	var n = 0;
	for (var j=0;j<nfields;j++)
	{
		var field = fields[j];
		var v = field.getSQLValue(record);
		if (v != null)
		{
			if (n>0)
				sqla.push(',');
			sqla.push(field.sqlName);
			n++;
			values.push(v);
		}
	}
	sqla.push(')');
	sqla.push('VALUES (?');
	for (var i=1;i<n;i++)
		sqla.push(', ?');
	sqla.push(')');
	var sql = sqla.join(' ');
	this.execSql(sql, values, function(transaction,results)
	{
		this.chargeExit('<Inserted>',record);
		this.resumeContext();
	});
			
};
// file: InsertNumberedItem.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.InsertNumberedItem = function InsertNumberedItem(){};
tersus.InsertNumberedItem.prototype = new ActionNode();
tersus.InsertNumberedItem.prototype.constructor = tersus.InsertNumberedItem;
tersus.InsertNumberedItem.prototype.start = function()
{
	var item = this.getChild('<Item>');
	var parent = this.getChild('<Parent>');
	if (!parent.elementList)
	{
		if (this.getElement('<Invalid Parent>'))
			this.chargeExit('<Invalid Parent>', parent);
		else
			modelExecutionError("Invalid parent "+parent.modelId,this);
		return;
	}
	var index = this.getLeafChild('<Index>');
	
	indexDelta = 0;
	if (this.pluginVersion && this.pluginVersion >= 1)
	{
		indexDelta = -1;
		index = index + indexDelta;
	}
		
	var e = this.getTargetElement(parent,item);
	if (!e)
	{
			if (this.getElement('<Invalid Item>'))
				this.chargeExit('<Invalid Item>', item);
			else
				modelExecutionError("Invalid item "+item.modelId,this);
			return;
	}
	if (index < 0 || index > e.getChildren(parent).length)
	{
		if (this.getElement('<Invalid Index>'))
			this.chargeLeafExit('<Invalid Index>', index-indexDelta);
		else
			modelExecutionError("Invalid index "+(index-indexDelta),this);
		return;
	}
	e.addAChild(parent, item);
	var children = e.getChildren(parent);
	var child = e.moveChild(parent,children.length-1, index);
	this.chargeExit('<Inserted>',child);
	
};
tersus.InsertNumberedItem.prototype.getTargetElement = function(parent,item)
{
	var triggerId = this.getElement('<Item>').modelId;
	if (parent && parent.elementList)
	{
		var elements = parent.elementList;
		for (var i=0;i<elements.length;i++)
		{
			if (elements[i].isRepetitive && (elements[i].modelId == item.modelId || elements[i].modelId == triggerId))
			{
				return elements[i];
			}
		}
	}
	return null;
};


// file: InvokeElementAction.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.InvokeElementAction = function() {};
tersus.InvokeElementAction.prototype = new ActionNode();
tersus.InvokeElementAction.prototype.constructor = tersus.InvokeElementAction;
tersus.InvokeElementAction.prototype.start = function()
{
	var targetElement = this.getChild('<Element>');
	var action = this.getLeafChild('<Action>');
	if (targetElement.invokeAction)
	{
		var output = targetElement.invokeAction(action, this);
		// Here we would need to pause the current process, run the target action, and when that action is completed, resume the current action
	}
};


// file: IsEmpty.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('IsEmpty', function()
{
	var text = this.getLeafChild('<Text>');
	
	if (text == null)
	{
		this.chargeEmptyExit('<Missing>');
		return;
	}
		
	var length = text.length;
	if (length > 0)
		this.chargeLeafExit('<No>',text);
	else
		this.chargeLeafExit('<Yes>',text);
});
// file: IsZero.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.IsZero = function tersus_IsZero() {};
tersus.IsZero.prototype = new ActionNode();
tersus.IsZero.prototype.constructor = tersus.IsZero;
tersus.IsZero.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	if (x==0)
		this.chargeLeafExit('<Yes>',x)
	else
		this.chargeLeafExit('<No>',x);
};

// file: Label.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Label() {};
Label.prototype = new tersus.DisplayField();
Label.prototype.constructor = Label;
Label.prototype.defaultStyleClass='label';
Label.prototype.textTranslation=true;

Label.prototype.initialize = function ()
{
	this.value = new tersus.Text();
	this.value.leafValue = this.getBaseCaption();
};
/*
//TODO(x) delete this
Label.prototype.initViewNode = function()
{
	this.value = new tersus.Text();
	this.value.leafValue = this.getCaption();
	tersus.GenericField.prototype.initViewNode.call(this);
}*/
Label.prototype.captionChanged = function()
{
	if (this.viewNode)
	{
		var caption = this.getBaseCaption();
		if (! caption.isNode)
		{
			var text = new tersus.Text();
			text.leafValue = caption;
			caption = text;
		}
		this.setFieldValue(caption);
	}
};

// file: Last.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Last = function tesrsus_Last(){};
tersus.Last.prototype = new ActionNode();
tersus.Last.prototype.constructor = tersus.Last;
tersus.Last.prototype.start = function ()
{
	var trigger = this.getElement('<List>');
	var list = trigger.getChildren(this);
	if (list&& list.length > 0)
	{
		var last = list[list.length-1];
		this.chargeExit('<Last>', last);
		
	}
};

// file: Later.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Later = function tersus_Later() {};
tersus.Later.prototype = new ActionNode();
tersus.Later.prototype.constructor = tersus.Later;
tersus.Later.prototype.start = function ()
{
	var time1 = this.getChild('<Time 1>');
	var time2 = this.getChild('<Time 2>');
	if (tersus.getDate(time1) > tersus.getDate(time2))
		this.chargeExit('<Yes>', time1);
	else
		this.chargeExit('<No>', time1);
};


// file: LaterOrEqual.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.LaterOrEqual = function tersus_LaterOrEqual() {};
tersus.LaterOrEqual.prototype = new ActionNode();
tersus.LaterOrEqual.prototype.constructor = tersus.LaterOrEqual;
tersus.LaterOrEqual.prototype.start = function ()
{
	var time1 = this.getChild('<Time 1>');
	var time2 = this.getChild('<Time 2>');
	if (tersus.getDate(time1) >= tersus.getDate(time2))
		this.chargeExit('<Yes>', time1);
	else
		this.chargeExit('<No>', time1);
};


// file: Latest.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Latest = function tersus_Latest() {};
tersus.Latest.prototype = new ActionNode();
tersus.Latest.prototype.constructor = tersus.Latest;
tersus.Latest.prototype.start = function ()
{
	var trigger = this.getElement('<Times>');
	var list = trigger.getChildren(this);
	if (list&& list.length > 0)
	{
		var latest = list[0];
		for (var i=1;i<list.length;i++)
		{
			var next = list[i];
			if (tersus.getDate(next) > tersus.getDate(latest))
				latest = next;
		}
		this.chargeExit('<Latest>', latest);
	}
};

// file: Layer.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Layer = function tersus_Layer() {};
tersus.Layer.prototype = new Pane();
tersus.Layer.prototype.constructor = tersus.Layer;
tersus.Layer.prototype.attachViewNode = function()
{
	this.currentWindow.currentRootDisplayNode.viewNode.appendChild(this.viewNode);
	this.viewNode.style.position='absolute';
	$(this.viewNode).css('z-index',  ++ tersus.topZindex);
};
tersus.Layer.prototype.onDelete = function onDelete()
{
	this.destroyHierarchy();
	if (this.viewNode && this.viewNode.parentNode)
		this.viewNode.parentNode.removeChild(this.viewNode);
};

// file: Length.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('Length', function()
{
	var text = this.getLeafChild('<Text>');
	if (text == null)
		this.chargeEmptyExit('<Missing>');
	else if (text.length != null)
		this.chargeLeafExit('<Length>',text.length);
});


// file: List Holder.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function List_Holder() {};
List_Holder.prototype = new tersus.HTMLTag();
List_Holder.prototype.constructor = List_Holder;
List_Holder.prototype.defaultTag = 'ul';
// file: List Item.js

/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function List_Item() {};
List_Item.prototype = new DisplayNode();
List_Item.prototype.constructor = List_Item;
List_Item.prototype.defaultTag = 'li';
// file: Logout.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Logout = function() {};
tersus.Logout.prototype = new ActionNode();
tersus.Logout.prototype.constructor = tersus.Logout;
tersus.Logout.prototype.start = function ()
{
	
	tersus.logout();
	tersus.async.exec(tersus.reloadApplication, false /* don't wait */);
};

// file: LowerCase.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('LowerCase', function()
{
	var text = this.getLeafChild('<Text>');
	if (text != null)
		this.chargeLeafExit('<Lower Case>',text.toLowerCase());
});


// file: Map.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Map = function tersus_Map() {};
tersus.Map.prototype = new DataValue();
tersus.Map.prototype.constructor = tersus.Map;
tersus.Map.prototype.isMap = true;
tersus.Map.prototype.isLeaf = true;
tersus.Map.prototype.init = function initMap()
{
	this.leafValue = {};
};

// file: Match.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('Match', function()
{
	var pattern = this.getLeafChild('<Pattern>');
	var text = this.getLeafChild('<Text>');
	var ignoreCase = this.getLeafChild('<Ignore Case>');
	var allowPartial = this.getLeafChild('<Allow Partial Match>');
	
	var matchesExit = this.getExit('<Matches>');
	
	if (text == null)
		this.chargeEmptyExit('<Missing>');
	else
	{	
		if (allowPartial != true)
		{
			if (pattern.charAt(0) != '^')
				pattern = '^' + pattern;
		
			if (pattern.charAt(pattern.length -1) != '$')
				pattern = pattern + '$';
		}
				
		var modifier = ignoreCase?'i':'';
		var matches = text.match(new RegExp(pattern, modifier)); 
		
		if (matches != null)
		{
			this.chargeLeafExit('<Yes>',text);
			if (matchesExit)
			{
				var l = matches.length;
				for (var i=0;i<l;i++)
					this.chargeLeafExit(matchesExit, matches[i]);
			}
		}
    	else
    		this.chargeLeafExit('<No>',text);
    		
    }
});
// file: Maximum.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Maximum = function tersus_Maximum() {};
tersus.Maximum.prototype = new ActionNode();
tersus.Maximum.prototype.constructor = tersus.Maximum;
tersus.Maximum.prototype.start = function ()
{
	var values = this.getTriggerValues();
	if (values.length == 0)
	{
		modelExecutionError("No values specified - can't compute maximum",this);
		return;
	}
	var maximum = values[0].leafValue;
	for (var j=1; j<values.length; j++)
	{
		var value = values[j];
		if (value && value.leafValue > maximum)
			maximum = value.leafValue;
	}
	this.chargeLeafExit('<Maximum>',maximum);
};

// file: MenuBar.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.MenuBar = Row.__subclass('tersus.MenuBar');
tersus.MenuBar.prototype.defaultStyleClass='menu_bar';

// file: MenuButton.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
tersus.MenuButton = function tersus_MenuButton() {};
tersus.MenuButton.prototype = new DisplayNode();
tersus.MenuButton.prototype.constructor = tersus.MenuButton;
tersus.MenuButton.prototype.defaultTag = 'button';
tersus.MenuButton.prototype.defaultStyleClass='menuButton';
tersus.MenuButton.prototype['set<Value>'] = function (value)
{
	this.value = value;
};
tersus.MenuButton.prototype['set<Value>'].requiresNodes = true;
tersus.MenuButton.prototype.createViewNode = function Button_createViewNode()
{
	DisplayNode.prototype.createViewNode.call(this);
	this.viewNode.innerHTML = tersus.escapeHTML(this.getCaption());
};
tersus.MenuButton.prototype.captionChanged = function()
{
	if (this.viewNode)
		this.viewNode.innerHTML = tersus.escapeHTML(this.getCaption());
};
tersus.MenuButton.prototype.setEventHandlers = function Button_setEventHandlers()
{
	this.viewNode.setAttribute('lid', this.getNodeId());
	this.viewNode.onclick = tersus.MenuButton.onclick;
	this.viewNode.onmousedown = tersus.MenuButton.mousedown;
	this.viewNode.onblur = tersus.MenuButton.blur;
	this.viewNode.onkeydown = tersus.MenuButton.keydown;
	this.viewNode.onkeyup = tersus.MenuButton.keyup;
};
tersus.MenuButton.prototype.getOptionText = tersus.GenericField.prototype.getOptionText;
tersus.MenuButton.onclick = function()
{
	var node = DisplayNode.findNodeForDocumentNode(this);
	if (node && ! node.isActive)
	{
		node.activate();
	}
};
tersus.MenuButton.keydown = function(evt)
{
	var node = DisplayNode.findNodeForDocumentNode(this);
	if (!node || ! node.isActive)
		return true;
	if (!evt) evt = window.event;
	if (!evt) return;
	var k=evt.keyCode;
	var option = node.highlightedOption;
	switch(k)
	{
		case 27: //Escape
		case 9: //Tab
			node.deactivate();break;
		case 37: case 38: // Left/Up
			node.highlight(option == null? -1:option-1);
			break; // prevent scrolling
		case 39: case 40: // Right/Down
			node.highlight(option == null?0:option+1);
			break;
		default:
	}
};
tersus.MenuButton.keyup = function(evt)
{
	var node = DisplayNode.findNodeForDocumentNode(this);
	if (!node || ! node.isActive)
	{
		return true;
	}
	if (!evt) evt = window.event;
	if (!evt) 
	{
		return;
	}
	var k=evt.keyCode;
	if (k == 13 && node.highlightedOption != null)
		node.select();
/*	if( k ==38 || k ==40) // Up|Down
	{
		var button = node.viewNode;
		node.dontDeactivate = true;
		button.blur();
		setTimeout(function(){button.focus();node.dontDeactivate=false;},10);
	}*/
};
tersus.MenuButton.highlight = function()
{
	var nodeId = this.getAttribute('nodeId');
	if (!nodeId)
		return;
	var node = tersus.findNode(nodeId);
	if (! node)
		return;
	node.mouseIn = true;
	node.highlight(this.getAttribute('optionIndex'));
};
tersus.MenuButton.unhighlight = function()
{
	this.className = '';
	var nodeId = this.getAttribute('nodeId');
	if (!nodeId)
		return;
	var node = tersus.findNode(nodeId);
	if (! node)
		return;
	node.mouseIn = false;
	node.clearHighlight();
};
tersus.MenuButton.select = function()
{
	var nodeId = this.getAttribute('nodeId');
	if (!nodeId)
		return;
	var node = tersus.findNode(nodeId);
	if (node)
	    node.select();
};
tersus.MenuButton.prototype.highlight = function(index)
{
	if (index <0)
		index = this.options.length -1;
	if (index >=this.options.length)
		index = 0;
	this.clearHighlight();
	this.highlightedOption = index;
	this.optionRows[this.highlightedOption].className = 'highlight';
};
tersus.MenuButton.prototype.clearHighlight = function()
{
	if (this.highlightedOption != null)
	{
		this.optionRows[this.highlightedOption].className = '';
		this.highlightedOption = null;
	}
};
tersus.MenuButton.prototype.select = function ()
{
	if (checkBusy())
		return;
	this.deactivate();
	this.value = this.options[this.highlightedOption];
	this.queueEvent(Events.ON_SELECT);
};
tersus.MenuButton.mousedown = function()
{
	var node = DisplayNode.findNodeForDocumentNode(this);
	if (node && node.activate)
		node.activate();
};
tersus.MenuButton.blur = function()
{
	var node = DisplayNode.findNodeForDocumentNode(this);
	if (node && node.isActive && !node.mouseIn)
		setTimeout(function(){	node.deactivate();},50);
};
tersus.MenuButton.prototype.deactivate = function ()
{
	var t = this.optionsTable;
	if (t && t.parentNode)
		t.parentNode.removeChild(t);
	this.optionsTable = null;
	this.isActive = false;
	if (window.isWebKit)
	{
		tersus.MenuButton.currentNodeId = null;
		var w=this.currentWindow;
		w.document.removeEventListener('click',tersus.MenuButton.deactivator, false);
	}
};
tersus.MenuButton.deactivator = function()
{
	var node = tersus.findNode(tersus.MenuButton.currentNodeId);
	if (!node)
		return;
	if (node && ! node.mouseId)
		node.deactivate();
};
tersus.MenuButton.prototype.activate = function ()
{
	if (this.isActive)
		return;
	if (checkBusy())
		return;
	this.isActive = true;
	if (window.isWebKit)
	{
		var current = tersus.findNode(tersus.MenuButton.currentNodeId);
		if (current)
			current.deactivate();
		var w = this.currentWindow;
		tersus.MenuButton.currentNodeId = this.getNodeId();
		setTimeout(function()
		{
			w.document.addEventListener('mouseup',  tersus.MenuButton.deactivator,false);
		},50);
	}
	this.highlightedOption = null;
	this.mouseIn = false;
	var t = this.optionsTable = this.createHTMLElement('table');
	t.className='options';
	var tb = this.optionsTbody = this.createHTMLChildElement(t,'tbody');
	this.optionRows = [];
	for (var i=0; i<this.options.length ;i++)
	{
		var row = this.createHTMLChildElement(tb,'tr');
		row.onmouseOver = tersus.MenuButton.highlight;
		row.onmouseOut = tersus.MenuButton.unhighligh;
		row.setAttribute('optionIndex', i);
		row.onmouseover = tersus.MenuButton.highlight;
		row.onmouseout = tersus.MenuButton.unhighlight;
		row.onmouseup =  tersus.MenuButton.select;
		row.setAttribute('nodeId',this.getNodeId());
		var cell = this.createHTMLChildElement(row,'td');
		cell.innerHTML = this.translate(tersus.escapeHTML(this.getOptionText(this.options[i])));
		this.optionRows[i] = row;
		
	}
	var backgroundColor = getActualBackground(this.viewNode);
	if (backgroundColor == null) backgroundColor = 'white';
	t.style.backgroundColor=backgroundColor;
	
	t.style.position='absolute';
	$(t).css('z-index',++ tersus.topZindex)
	var d = this.viewNode.ownerDocument;
	d.body.appendChild(t);
	d.body.appendChild(t);
	var buttonPosition=getScreenPosition(this.viewNode);
	var x = buttonPosition.left;
	var y = (buttonPosition.top+this.viewNode.offsetHeight-1);
    t.style.top= (y - getScroll(t).top)+'px';
    t.style.left = (x - getScroll(t).left)+'px';
};

tersus.MenuButton.prototype.addOption = tersus.MenuButton.prototype['add<Options>'] = function tersus_MenuButton_addOption(value)
{
	if (!this.options) this.options=[];
	this.options.push(value);
};
tersus.MenuButton.prototype.addOption.requiresNodes = true;

tersus.MenuButton.prototype.getOptions = tersus.MenuButton.prototype['get<Options>'] = function tersus_MenuButton_getOptions()
{
	if (!this.options) this.options=[];
	return this.options;
};
tersus.MenuButton.prototype.removeOptions = tersus.MenuButton.prototype['remove<Options>'] = function tersus_MenuButton_removeOptions()
{
	this.options = [];
};
tersus.MenuButton.prototype['get<Disabled>'] = function ()
{
	return this.disabled;
};

tersus.MenuButton.prototype['set<Disabled>'] = function (disabled)
{
	this.disabled = disabled?true:false;
	if (this.viewNode)
	{
		this.viewNode.disabled=this.disabled;
		if (window.browser == 'IE') // IE 6.0 doesn't support the :disable CSS pseudoclass, so we use an explicit style as a workaround
		{
			if (disabled && !this.viewNode.className)
				this.viewNode.className = 'disabled';
			if (!disabled && this.viewNode.className=='disabled')
				this.viewNode.className = '';
		}
	}
};

// file: MenuItem.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.MenuItem = DisplayNode.__subclass('tersus.MenuItem');
tersus.MenuItem.prototype.onload = function () {
 this.imagePath = this.sprop('imagePath');
 };
tersus.MenuItem.prototype.defaultTag = 'span';
tersus.MenuItem.prototype.defaultStyleClass='menu_item';
tersus.MenuItem['set<Image Path>'] = function(path)
{
	this.imagePath = path;
	if (this.image)
		this.image.src = path;
};
function menuOption()
{
};
tersus.MenuItem.prototype.createViewNode = function()
{
	DisplayNode.prototype.createViewNode.call(this);
	if (this.imagePath)
	{	
		this.image = this.createHTMLChildElement(this.viewNode,'img');
		this.image.src = this.imagePath;
	}
	this.link = this.createHTMLChildElement(this.viewNode,'a');
    this.link.href='javascript:menuOption("'+this.getCaption()+'")';
    this.link.onfocus = function(){this.className='focus';};
    this.link.onblur = function(){this.className='';};
		
	this.captionChanged();
};
tersus.MenuItem.prototype.captionChanged = function()
{
	if (this.link)
		this.link.innerHTML = this.escapeHTML(this.getCaption());
};

// file: Minimum.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Minimum = function tersus_Minimum() {};
tersus.Minimum.prototype = new ActionNode();
tersus.Minimum.prototype.constructor = tersus.Minimum;
tersus.Minimum.prototype.start = function ()
{
	var values = this.getTriggerValues();
	if (values.length == 0)
	{
		modelExecutionError("No values specified - can't compute minimum",this);
		return;
	}
	var minimum = values[0].leafValue;
	for (var j=1; j<values.length; j++)
	{
		var value = values[j];
		if (value && value.leafValue < minimum)
			minimum = value.leafValue;
	}
	this.chargeLeafExit('<Minimum>',minimum);
};

// file: Model.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Model = function tersus_Model() {};
tersus.Model.prototype = new DataValue();
tersus.Model.prototype.constructor = tersus.Model;
tersus.Model.prototype.pluginFunc = tersus.Model;
tersus.Model.prototype.toString = function()
{
	return 'Model[id='+this.model.modelId+']';
};
tersus.Model.prototype.addGetter('Plugin',function()
{
	if (! this.model)
	{
		modelError("Invalid instnace of "+this.modelId+"  Use 'Get Model' to obtain models and model elements");
		return null;
	}
	return this.model.plugin;
});
tersus.Model.prototype.addGetter('Model Id', function()
{
	if (! this.model)
	{
		modelError("Invalid instnace of "+this.modelId+"  Use 'Get Model' to obtain models and model elements");
		return null;
	}
	return this.model.modelId;
});
tersus.Model.prototype.addGetter('Model Name', function()
{
	if (! this.model)
	{
		modelError("Invalid instnace of "+this.modelId+"  Use 'Get Model' to obtain models and model elements");
		return null;
	}
	return this.model.modelName;
});
tersus.Model.prototype.addGetter('Elements',function()
{
	if (! this.model)
	{
		modelError("Invalid instnace of "+this.modelId+"  Use 'Get Model' to obtain models and model elements");
		return [];
	}
	if (! this.elementsWrappers)
	{
		var elementsElement = this.getElement('Elements');
		this.elementWrappers = [];
		if (this.model.elementList)
		{
			for (var i=0;i<this.model.elementList.length;i++)
			{
				var element = this.model.elementList[i];
				if (!element.wrapper)
				{
					element.wrapper = elementsElement.createChildInstance();
					element.wrapper.element = element;
				}
				this.elementWrappers.push(element.wrapper);
			}
		}
	}
	return this.elementWrappers;
});

// file: ModelElement.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.ModelElement = function tersus_ModelElement() {};
tersus.ModelElement.prototype = new DataValue();
tersus.ModelElement.prototype.constructor = tersus.ModelElement;
tersus.ModelElement.prototype.pluginFunc = tersus.ModelElement;
tersus.ModelElement.prototype.toString = function()
{
	return 'ModelElement[name='+this.element.role+',owner='+this.owner.modelId + ",modelId="+this.element.modelId+']';
};
tersus.ModelElement.prototype.addGetter('Model Id',function()
{
	if (! this.element)
	{
		modelError("Invalid instnace of "+this.modelId+"  Use 'Get Model' to obtain models and model elements");
		return null;
	}
	return this.element.modelId;
});
tersus.ModelElement.prototype.addGetter('Element Name',function()
{
	if (! this.element)
	{
		modelError("Invalid instnace of "+this.modelId+"  Use 'Get Model' to obtain models and model elements");
		return null;
	}
	return this.element.role;
});

tersus.ModelElement.prototype.addGetter('Repetitive',function()
{
	if (! this.element)
	{
		modelError("Invalid instnace of "+this.modelId+"  Use 'Get Model' to obtain models and model elements");
		return null;
	}
	return this.element.isRepetitive;
});
tersus.ModelElement.prototype.addGetter('Type',function()
{
	if (! this.element)
	{
		modelError("Invalid instnace of "+this.modelId+"  Use 'Get Model' to obtain models and model elements");
		return null;
	}
	if (this.element.isDisplayElement)
		return "Display";
	else if (this.element.isSubFlow)
		return "SubProcess";
});

// file: Multiply.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Multiply = function tersus_Multiply() {};
tersus.Multiply.prototype = new ActionNode();
tersus.Multiply.prototype.constructor = tersus.Multiply;
tersus.Multiply.prototype.start = function ()
{
	var values = this.getTriggerValues();
	var product = 1;
	for (var j=0; j<values.length; j++)
	{
		var value = values[j];
		if (value.leafValue != null)
			product *= parseFloat(value.leafValue);
	}
	this.chargeLeafExit('<Product>',product);
};

// file: Negative.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Negative = function tersus_Negative() {};
tersus.Negative.prototype = new ActionNode();
tersus.Negative.prototype.constructor = tersus.Negative;
tersus.Negative.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	if (x<0)
		this.chargeLeafExit('<Yes>',x)
	else
		this.chargeLeafExit('<No>',x);
};

// file: NegativeOrZero.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.NegativeOrZero = function tersus_NegativeOrZero() {};
tersus.NegativeOrZero.prototype = new ActionNode();
tersus.NegativeOrZero.prototype.constructor = tersus.NegativeOrZero;
tersus.NegativeOrZero.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	if (x<=0)
		this.chargeLeafExit('<Yes>',x)
	else
		this.chargeLeafExit('<No>',x);
};

// file: NewTree.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.NewTree = function NewTree(){};
tersus.NewTree.prototype = new DisplayNode();
tersus.NewTree.prototype.constructor = tersus.NewTree;
tersus.NewTree.prototype.defaultTag = 'div';
tersus.NewTree.prototype.defaultStyleClass = 'ntree';
tersus.NewTree.prototype.isNewTree = true;
tersus.NewTree.prototype['get<Selected Item>'] = function()
{
	return this.selectedItem;
};
tersus.NewTree.prototype['set<Selected Item>'] = function (item)
{
    if (item)
    {
        this.selectedItem = item;
        this.selectedItem.select();
    }
};
tersus.NewTree.prototype['set<Selected Item>'] .requiresNodes = true;

tersus.NewTree.prototype['remove<Selected Item>'] = function()
{
	if (this.selectedItem)
	{
		this.selectedItem.deselect();
		this.selectedItem = null;
	}
};
tersus.NewTreeItem = function NewTreeItem(){};
tersus.NewTreeItem.prototype = new DisplayNode();
tersus.NewTreeItem.prototype.constructor = tersus.NewTreeItem;
tersus.NewTreeItem.prototype.defaultTag = 'div';
tersus.NewTreeItem.prototype.defaultStyleClass = 'ntree_item';
tersus.NewTreeItem.TREE_ITEM_ID="tree_item_id";
tersus.NewTreeItem.prototype.COLLAPSED = 'Collapsed';
tersus.NewTreeItem.prototype.EXPANDED = 'Expanded';
tersus.NewTreeItem.prototype.ATOMIC = 'Atomic';
tersus.NewTreeItem.prototype.isNewTreeItem = true;
tersus.NewTreeItem.prototype.getTree = function()
{
	var parent = this.parent;
	while (parent.isNewTreeItem)
	{
		parent = parent.parent;
	};
	if (parent && parent.isNewTree)
	{
		return parent;
	}
	else
		return null;
};
tersus.NewTreeItem.select = function()
{
	var itemId = this.getAttribute(tersus.NewTreeItem.TREE_ITEM_ID);
	var item = tersus.findNode(itemId);
	item.select();
};

tersus.NewTreeItem.prototype.select = function()
{
	var tree = this.getTree();
	if (tree)
	{
		if (tree.selectedItem)
			tree.selectedItem.deselect();
		tree.selectedItem = this;
		if (this.innerHeader)
//			this.innerHeader.viewNode.className = "ntree_item_inner_header_selected";
			this.innerHeader.addStyleClass("ntree_item_inner_header_selected");
	};
};
tersus.NewTreeItem.prototype.deselect = function()
{
		if (this.innerHeader)
//			this.innerHeader.viewNode.className = "ntree_item_inner_header";
			this.innerHeader.removeStyleClass("ntree_item_inner_header_selected");
};
tersus.NewTreeItem.prototype.deleteMe = function()
{
	DisplayNode.prototype.deleteMe.call(this);
	var tree = this.getTree();
	if (tree && tree.selectedItem == this)
		tree.selectedItem = null;
};
tersus.NewTreeItem.prototype.createViewNode = function()
{
	DisplayNode.prototype.createViewNode.call(this);
	this.header = this.createHTMLChildElement(this.viewNode,'span','ntree_item_header');
	this.toggleImage = this.createHTMLChildElement(this.header, 'img', 'ntree_toggle_collapsed');
	this.body = this.createHTMLChildElement(this.viewNode, 'div', 'ntree_item_body');
};
tersus.NewTreeItem.prototype.initViewNode = function()
{
	if (this.defaultStyleClass)
		this.viewNode.className = this.defaultStyleClass;
	this.setProperties();
	this.toggleImage.src = 'images/spacer.gif';
	this.setEventHandlers();
	this.setState(this.COLLAPSED);
};
tersus.NewTreeItem.prototype.onClick = function(domNode, callback)
{
	if (domNode == this.toggleImage)
		this.toggle(callback);
	else
		DisplayNode.prototype.onClick.call(this, callback);
};
tersus.NewTreeItem.prototype.toggle = function(callback)
{
	if (this.state == this.COLLAPSED)
		this.expand(callback);
	else if (this.state == this.EXPANDED)
		this.collapse(callback);
};
tersus.NewTreeItem.prototype.collapse = function(callback)
{
	queueEvent(window.engine, window.engine.handleEvent, [this,Events.ON_COLLAPSE], new Date(), "Tree Item Collapsed", callback);
};
tersus.NewTreeItem.prototype.expand = function(callback)
{
	queueEvent(window.engine, window.engine.handleEvent, [this,Events.ON_EXPAND], new Date(), "Tree Item Expanded", callback);
};
tersus.NewTreeItem.prototype.setEventHandlers = function ()
{
	this.registerEventHandler(Events.ON_CLICK, this.toggleImage);
};
tersus.NewTreeItem.prototype.appendChildViewNode = function (child, childElement)
{
	if (child.element.role == '<Header>')
	{
		this.header.appendChild(child.viewNode);
		child.viewNode.className='ntree_item_inner_header';
		this.innerHeader = child;
		child.viewNode.setAttribute(tersus.NewTreeItem.TREE_ITEM_ID, this.getNodeId());
		child.registerEventHandler(Events.ON_CLICK);
		var item = this;
		var originalClickHandler = child.onClick;
		child.onClick = function(domNode, callback)
		{
			item.select();
			originalClickHandler.call(child, domNode, callback);
		};
		
	}
	else
		DisplayNode.appendChildNode(this.body,child.viewNode);
};

tersus.NewTreeItem.prototype['get<Expanded>'] = function()
{
	return (this.expanded);
};

tersus.NewTreeItem.prototype.setState = function(state)
{
	this.state = state;
	if (state == this.EXPANDED)
	{
		this.expanded = true;
		this.expandable = true;
		this.toggleImage.className = 'ntree_toggle_expanded';
		this.body.style.display='';
	}
	else if (state == this.COLLAPSED)
	{
		this.expanded = false;
		this.expandable = true;
		this.toggleImage.className = 'ntree_toggle_collapsed';
		this.body.style.display='none';
	}
	else if (state == this.ATOMIC)
	{
		this.expandable = false;
		this.toggleImage.className = 'ntree_toggle_atomic';
		this.body.style.display='none';
	}
};
tersus.NewTreeItem.prototype['set<Expanded>'] = function(expanded)
{
	if (expanded == this.expanded)
		return;
	if (this.expandable)
	{
	
		if (expanded)
			this.setState(this.EXPANDED);
		else 
			this.setState(this.COLLAPSED);
	}
	else 
	{
		this.expanded = expanded;
		this.setState(this.ATOMIC);
	}
	
};
tersus.NewTreeItem.prototype['get<Expandable>'] = function ()
{
	return (this.expandable);
};

tersus.NewTreeItem.prototype['set<Expandable>'] = function (expandable)
{
	if (expandable == this.expandable)
		return;
	if (expandable)
	{
		if (this.expanded)
			this.setState(this.EXPANDED);
		else
			this.setState(this.COLLAPSED);
	}
	else
	{
		this.setState(this.ATOMIC);
	};
};

// file: NotifyError.js
tersus.newAction('NotifyError', function()
{
    var message = this.getLeafChild('<Message>');
    var details = this.getLeafChild('<Details>');
    if (!message)
    {
        var error = this.getChild('<Error>');
        if (error)
        {
            if (error.isText)
                message = error.leafValue;
            else
            {
                message == error.getLeafChild('Message');
                details = error.getLeafChild('Details');
            }
        }
    }
    if (!message) message = 'Unknown Error';
    throw ({message:message, details:details});
            
});

// file: Now.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('Now', function()
{
	
	this.chargeLeafExit('<Now>',new Date());
});

// file: ParseDateAndTime.js
/*********************************************************************************************************
 * Copyright (c) 2003-2010 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at http://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('ParseDateAndTime', function()
{
	var str = this.getLeafChild('<Text>');
	var tz = this.getLeafChild('<Time Zone>');
	if (tz != null)
	{
		modelExecutionError('<Time Zone> not supported in client side version of Parse Date and Time (consider using <Time Zone Offset>)',this);
		return;
	}
	var tzOffset = this.getLeafChild('<Time Zone Offset>');
	if (tzOffset == null)
		tzOffset=-10000;
	else
		tzOffset=-tzOffset; // GWT timezone offset is reverse from intuitive.

	var format = this.getLeafChild('<Format>');
        var time = tersus.parseDateTimeString(str, format, tzOffset)
	this.chargeLeafExit('<Date and Time>',new Date(time));
});

// file: ParseJSON.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('ParseJSON', function() {
    var text = this.getLeafChild('<JSON Text>');
    var exit = this.getExit('<Value>');
    
    
    var obj;
    try
    {
	if (exit.getChildConstructor().isMap)
	    obj = JSON.parse(text);
	else // Legacy - more lenient parser
	    obj = eval('var x='+text+';x;');
    }
    catch (e)
    {
	throw new tersus.Exception("Error parsing JSON Text ("+e+") text:\n"+text,e);
    }
    if (exit.isRepetitive)
    {
	var values = obj;
    	for (var i=0; i< values.length; i++)
    	{
    	    var dataValue  = exit.createChild(this);
    	    dataValue.copyObject(values[i]);
    	}
    }
    else
    {
	var dataValue = exit.createChild(this);
	dataValue.copyObject(obj);
    }
    
});

// file: ParseXML.js
tersus.newAction('ParseXML', function()
{
	var xml = this.getLeafChild('<XML Document>');
	var exit = this.getExit('<Parsed Tree>');
	var allowUnknownElements = false; // When adding trigger, make sure to add equivalent in server side
	
	var doc;
	if (window.DOMParser)
	{
		var parser = new DOMParser();
		doc = parser.parseFromString (xml, "text/xml");
	} 
	else if (window.ActiveXObject)
	{
	    doc = new ActiveXObject ("Microsoft.XMLDOM");
	    doc.async = false;
	    doc.loadXML(xml);
    }
 	
 	var node = this.convert(doc.documentElement,exit, allowUnknownElements);
 	if (!node.isLeaf || node.leafValue != null)
 		this.chargeExit(exit,node);	
});
tersus.ParseXML.prototype.convert = function (domElement, element, allowUnknownElements)
{
	var text;
	var nodeConstructor = element.getChildConstructor();
	var prototype = nodeConstructor.prototype;
	var node = null;
	if (prototype.isLeaf)
		text = [];
	else
	{
		node = new nodeConstructor(); // Composite is always created
		for (var i=0;i<domElement.attributes.length;i++)
		{
			var attribute = domElement.attributes[i];
			if (attribute.value)
			{
				var localName = attribute.localName ? attribute.localName : attribute.baseName; // baseName is used in IE
				var elementHandler = this.getElementHandler(node,attribute.nodeName, attribute.localName, attribute.namespaceURI, true);
				if (elementHandler != null)
				{
			 		try
					{
						elementHandler.createChild(node).parseString(attribute.value, elementHandler);
					}
					catch (e)
					{
						throw {message:'Error parsing XML attribute: tagName='+domElement.tagName+' attribute:'+attribute.nodeName+ ' modelId='+elementHandler.modelId+'\nmessage='+e.message};
					}
				}
				else if (!allowUnknownElements && attribute.name.indexOf('xmlns')!=0)
			 		throw {message:'Error parsing XML: Unrecognized attribute ' + attribute.name + ' in '+prototype.modelId};
				
			}
		}		
	}
	for (var i=0;i<domElement.childNodes.length;i++)
	{
		var cn = domElement.childNodes[i];
		if (cn.nodeType == 1 || cn.nodeType == 2)
		{
			var localName = cn.localName ? cn.localName : cn.baseName; //naseName in IE
			var elementHandler = this.getElementHandler(node,cn.nodeName, localName, cn.namespaceURI, cn.nodeType==2);
			if (elementHandler)
			{
				if (cn.nodeType == 1)
				{
					var childNode = this.convert(cn, elementHandler, allowUnknownElements);
					if (childNode != null)
						elementHandler.addChild(node, childNode); 
				}
			}
			else if (!allowUnknownElements)//TODO support permissive parsing
			 	throw {message:'Error parsing XML: Unrecognized element ' + cn.nodeName + ' in '+prototype.modelId};
		}
		else if (text && cn.nodeType == 3) // Text Node
		{
			if (cn.nodeValue)
				text.push(cn.nodeValue);
		}
	}
	if (text && text.length>0) // Leaf node with actual text
	{
		node = new nodeConstructor();
		try
		{
			node.parseString(text.join(''), element);
		}
		catch (e)
		{
			throw {message:'Error parsing XML content: tagName='+domElement.tagName+' modelId='+node.modelId+'\nmessage='+e.message};
		}
	}
	return node;
};

tersus.ParseXML.prototype.getElementHandler = function(parent, name, localName, namespaceURI, isAttribute)
{
	if (!parent.elements)
		return;
	if (namespaceURI != null)
	{
		var elementName = isAttribute ?  '#'+localName : localName;
		for (var elementRole in parent.elements)
		{
			var e = parent.elements[elementRole];
			if (! e.xmlNamespace)
			{
				e.xmlNamespace = e.getChildConstructor().prototype.xmlNamespace;
			}
			if (e.xmlNamespace == namespaceURI)
			{
				if (! e.xmlName)
					e.xmlName = elementRole.substr(elementRole.lastIndexOf(':')+1);
				if (e.xmlName == elementName)
					return e;
			} 
		}
	};
	// Not found with explicit namespaceURI - search by raw name
	var elementName = isAttribute ?  '#'+name : name;
	return parent.elements[elementName];
};

// file: PasswordField.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.PasswordField = function tersus_PasswordField() {};
tersus.PasswordField.prototype = new tersus.GenericField();
tersus.PasswordField.prototype.constructor = tersus.PasswordField();
tersus.PasswordField.prototype.defaultTag = 'input';
tersus.PasswordField.prototype.updateSelfReadOnly = function tersus_GenericField_updateSelfOnly(readOnly)
{
	if (this.currentReadOnly == readOnly)
		return; // no change
	this.currentReadOnly = readOnly;
   	if (this.inputField)
       	this.value = this.getFieldValue();
	if (this.viewNode)
	{
		if (readOnly)
		{
			this.viewNode.disabled = true;
		}
		else
			this.viewNode.disabled = false;
	}
	this.setValueString();
};

tersus.PasswordField.prototype.createViewNode = function tersus_GenericField_createViewNode()
{
    DisplayNode.prototype.createViewNode.call(this);
    this.viewNode.type = 'password';
    this.inputField = this.viewNode;
};
tersus.PasswordField.prototype.setViewNode = function tersus_PasswordField_createViewNode(viewNode)
{
	this.viewNode = this.inputField = viewNode;
}

tersus.PasswordField.prototype.setEventHandlers =DisplayNode.prototype.setEventHandlers;

// file: PercentDisplay.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.PercentDisplay = function tersus_PercentField(){};
tersus.PercentDisplay.prototype = new tersus.DisplayField();
tersus.PercentDisplay.prototype.constructor = tersus.PercentDisplay;
tersus.PercentDisplay.prototype.setDefaultProperties = function()
{
	this.sharedProperties.showPercentage = true;
};

// file: PlaySound.webkit.js
tersus.newAction('PlaySound',function()
{
	var url=this.getLeafChild('<URL>');
	var audio = new Audio(url);
	audio.play();
});

// file: PopupCalendar.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 

function PopupCalendar(){};
PopupCalendar.prototype = new FlowNode();
PopupCalendar.prototype.constructor = PopupCalendar;

PopupCalendar.prototype.start = function()
{
	//Find the containing view node - to get the location
	var visualParent = this.parent;
	while (! visualParent.viewNode)
		visualParent = visualParent.parent;
	
	// Create a hidden field to hold the value and 'intercept' value change
 	var date = this.getChild('<Base Date>');
	var node = this;
	if ($.fn.datepicker && tersus.UIDateField)
	{
	    var $f = $('<input type="hidden">').insertBefore($(visualParent.viewNode)); // May need to insert after for RTL
	    if (date != null)
	        $f[0].value = date.formatString();
	    $f.datepicker(
	    {
	        dateFormat:tersus.UIDateField.prototype.convertFormat(DATE_FORMAT)
	        ,onSelect:function(text, dp)
	        {
	            var date=createDate(dp.currentYear, dp.currentMonth+1, parseInt(dp.currentDay));
	            node.chargeLeafExit('<Date>', date);
	            node.continueExecution();
	        }
	        ,onClose:function()
	        {
	            if (node.status === FlowStatus.PAUSED)
	            {
	                node.continueExecution();
	            };
	        }
	    });
	    node.pause();
	    $f.datepicker("show");
	}
	else
	{
	    var hiddenField = visualParent.hiddenDateFieldForPopupCalendar;
	    if ( ! hiddenField)
	    {
	        hiddenField = visualParent.createHTMLElement('input');
	        hiddenField.type = 'hidden';
	        this.currentWindow.document.body.appendChild(hiddenField);
	        visualParent.hiddenDateFieldForPopupCalendar = hiddenField;
	    }
	    if (date != null)
	        hiddenField.value = date.formatString();
    	var valueHandler = function handleDate(year, month, day)
    	{
    		var date = createDate(year, month, day);
    		node.chargeLeafExit('<Date>', date);
    		node.readyToResume();
    		resumeRoot();
    	};
	    var posElement  = visualParent.viewNode;
	    while (posElement && $(posElement).css('display')=='inline')
		posElement = posElement.parentElement;
	    visualParent.currentWindow.popUpCalendar(posElement, hiddenField, valueHandler, DATE_FORMAT);
    }
};

// file: PopupCalendarWheels.webkit.mobile.non-simulator.js
PopupCalendar.prototype.start = function()
{
    var node = this;
    var callback = function datePickerCallback(year, month, day)
    {
        if (year != null && month != null && day != null)
        {
            var date = createDate(year, month, day);
            node.chargeLeafExit('<Date>', date);
        }
        node.readyToResume();
        resumeRoot();
    };
    
    var date = this.getLeafChild('<Base Date>');
    
    this.openDatePicker(date,callback);
};

PopupCalendar.prototype.openDatePicker = function(date, callback)
{
    if (date == null)
    {
	var now = new Date();
	date = createDate(now.getFullYear(),now.getMonth()+1,now.getDate());
    }
    var days = { };
    var years = { };
    var months = { 1: 'Jan', 2: 'Feb', 3: 'Mar', 4: 'Apr', 5: 'May', 6: 'Jun', 7: 'Jul', 8: 'Aug', 9: 'Sep', 10: 'Oct', 11: 'Nov', 12: 'Dec' };
    for (var key in months)
    {
	var t = tersus.labelMap['Calendar.'+months[key]];
	if (t) months[key]=t;
    }
    
    for( var i = 1; i < 32; i += 1 ) {
	days[i] = i;
    }

    for(var i = date.year-20; i < date.year+10; i += 1 ) {
	years[i] = i;
    }

    var prevDisabled = tersus.disabled;
    SpinningWheel.addSlot(years, 'right', date.year);
    SpinningWheel.addSlot(months, '', date.month);
    SpinningWheel.addSlot(days, 'right', date.day);
    
    /* Block click and touch event from outside the date selector */
    var blocker  = function(e)
    {
        if (!self.wrapper.contains(e.target))
            e.stopPropagation();
    };
    var self = this;
    var unblock = function()
    {
        document.removeEventListener("click", blocker, true);
        document.removeEventListener("touchstart", blocker, true);
        document.removeEventListener("touchmove", blocker, true);
        document.removeEventListener("touchend", blocker, true);
    }
    SpinningWheel.setCancelAction(function(){unblock();callback();});   
    SpinningWheel.setDoneAction(function()
				{
				    try
				    {
					var keys = SpinningWheel.getSelectedValues().keys;
					var year = parseInt(keys[0]);
					var month = parseInt(keys[1]);
					var day = parseInt(keys[2]);
					unblock();
					callback(year, month, day);
				    }
				    catch (e)
				    {
					alert (e);
				    }
				});
    SpinningWheel.open();
    this.wrapper = SpinningWheel.swWrapper;
    document.addEventListener("click", blocker, true);
    document.addEventListener("touchstart", blocker, true);
    document.addEventListener("touchmove", blocker, true);
    document.addEventListener("touchend", blocker, true);
};

// file: Positive.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Positive = function tersus_Positive() {};
tersus.Positive.prototype = new ActionNode();
tersus.Positive.prototype.constructor = tersus.Positive;
tersus.Positive.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	if (x>0)
		this.chargeLeafExit('<Yes>',x)
	else
		this.chargeLeafExit('<No>',x);
};

// file: PositiveOrZero.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.PositiveOrZero = function tersus_PositiveOrZero() {};
tersus.PositiveOrZero.prototype = new ActionNode();
tersus.PositiveOrZero.prototype.constructor = tersus.PositiveOrZero;
tersus.PositiveOrZero.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	if (x>=0)
		this.chargeLeafExit('<Yes>',x)
	else
		this.chargeLeafExit('<No>',x);
};

// file: Print.js
tersus.newAction('Print',function()
{
	var title = this.getLeafChild('<Title>');
	var heading = this.getLeafChild('<Heading>');
	var content = this.getChild('<Content>');
	var style = this.currentWindow.document.getElementById('main_stylesheet');
	var domNode = content.wrapperNode ? content.wrapperNode : content.viewNode;
	if (domNode == null)
		throw {message:'<Content> must be a reference to a rendered display element. Data-only display elements cannot be printed.'};
	
	var values = {Title:title?tersus.escapeHTML(title):'', Heading: heading? '<h1>'+tersus.escapeHTML(heading)+'</h1>' : '', Content:tersus.outerHTML(domNode), Style: tersus.outerHTML(style) };
	var template='<html><head><title>${Title}</title>${Style}</head><body>${Heading}${Content}<script type="text/javascript">window.popupTest="OK";</script></body></html>';
	var html = template.replace(/[$]{([^{}]+)}/g,
        function (all, token) {
          return values[token];
        });
    var w = window.open();
    if (w == null || w.innerHeight == 0)
    {
    	throw {message:"Cannot print because pop-up windows are blocked by the browser. Please enable pop-up windows for this application."};
    }
    w.document.write(html);
    w.document.close();
    w.print();
    setTimeout(function(){w.close()},50);
});


tersus.outerHTML = function(node)
{
	var html;
	if (window.XMLSerializer)
	{
		return (new XMLSerializer()).serializeToString(node);
	}
	else if (node.outerHTML)
		return node.outerHTML;
	else
		throw {message:"Cannot print: no outerHTML or XMLSerializer"};
};
// file: Put.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Put = function tersus_Put() {};
tersus.Put.prototype = new ActionNode();
tersus.Put.prototype.constructor = tersus.Put;
tersus.Put.prototype.start = function ()
{
	var map = this.getChild("<Map>");
	if (map && map.leafValue)
		map = map.leafValue;
	
	var key = this.getChild("<Key>");
	if (key !== null && key !== undefined && key.leafValue !== undefined)
		key = key.leafValue;
	var value = this.getChild("<Value>");
	if (value !== null && value.leafValue !== undefined)
		value = value.leafValue;
	if (map && (key !== null && key !== undefined))
	{
		if (value === null || value === undefined)
			delete map[key];
		else
			map[key]=value;
	}
};

// file: PutMapEntry.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('PutMapEntry', function()
{
	var map = this.getChild("<Map>");
	if (map && map.leafValue)
		map = map.leafValue;
	var key = this.getChild("<Key>");
	if (key && key.leafValue != undefined)
		key = key.leafValue;
	var value = this.getChild("<Value>");
	if (map && key != null)
	{
		if (value == null)
			delete map[key];
		else
			map[key]=value;
	}
});

// file: RadioButton.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.RadioButton = function tersus_RadioButton(){};
tersus.RadioButton.prototype = new tersus.PushButton();
tersus.RadioButton.prototype.constructor = tersus.RadioButton;
tersus.RadioButton.prototype.isRadioButton = true;
tersus.RadioButton.prototype.buttonType='radio';

tersus.RadioButton.prototype.getGroup = function()
{
	if (! this.group)
	{
		this.group = this.parent;
		while (this.group && ! this.group.isRadioButtonGroup)
		{
			this.group = this.group.parent;
		}
	}
	return this.group;
};
tersus.RadioButton.prototype.getButtonName = function()
{
	var group = this.getGroup();
	if (group)
		return group.getNodeId();
	else
		return this.getNodeId();
};
tersus.RadioButton.prototype.getButtonValue = tersus.RadioButton.prototype['get<Value>'] = function()
{
	if (this.value != undefined)
		return this.value;
	else
	{
		var c = tersus.repository.get(BuiltinModels.TEXT_ID);
		var node = new c();
        node.prototype = c.prototype;
        node.setLeaf(this.getCaption());
		return node;
	}
};
tersus.RadioButton.prototype['set<Value>'] = function (value)
{
	this.value = value;
};
tersus.RadioButton.prototype.labelClicked = function (domNode, callback)
{
	if (this.button && ! this.button.disabled)
	{
		if ( ! this.button.checked)
		{
			this.button.checked = true;
			this.onChange(domNode, callback);
		}
	}
};

tersus.RadioButton.prototype['set<Value>'].requiresNodes = true;
tersus.RadioButton.prototype.hasOnChange = true;
tersus.RadioButton.prototype.onChange = function(domNode, callback)
{
	if (this.button && this.button.checked)
	{
		var group = this.getGroup();
		if (group)
		{
			if (group && group.selectedButton == this)
				return; // was already checked
			group.selectedButton = this;
		}
		DisplayNode.prototype.onChange.call(this, domNode, callback);
		if (group)
			group.onChange(domNode, callback);
	}
	else
		DisplayNode.prototype.onChange.call(this);
	
};
tersus.RadioButton.prototype.setChecked =tersus.RadioButton.prototype['set<Checked>'] = function(checked)
{
	if (this.currentWindow)
	{
		var wasChecked = this.getChecked();
	}
	tersus.PushButton.prototype.setChecked.call(this,checked);
	if (checked && !wasChecked)
	{
		var group = this.getGroup();
		if (group)
			group.selectedButton = this;
	}
	else if (!checked && wasChecked)
	{
		var group = this.getGroup();
		if (group && group.selectedButton == this)
			group.selectedButton = null;
		
	}
};


// file: RadioButtonGroup.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.RadioButtonGroup = function tersus_RadioButtonGroup(){};
tersus.RadioButtonGroup.prototype = new tersus.DisplayGroup();
tersus.RadioButtonGroup.prototype.constructor = tersus.DisplayGroup;
tersus.RadioButtonGroup.prototype.isRadioButtonGroup = true;
tersus.RadioButtonGroup.prototype['get<Value>'] = function()
{
	if (! this.selectedButton)
		return null;
	else
		return this.selectedButton.getButtonValue();
};
tersus.RadioButtonGroup.prototype.setSelectedValue = tersus.RadioButtonGroup.prototype['set<Value>'] = function(value)
{
	var found = false;
	var op = function(node)
	{
		if (node.isRadioButton &&  compareValues(node.getButtonValue(), value)	)
		{	
			node.setChecked(true);
			found = true;
			return true; // stop traversal
		}
	};
	tersus.traverseHierarchy(this, DisplayNode.displayChildrenIterator, op);
	if ( ! found && tersus.settings.debug)
		modelExecutionError("Tried to set radio button group <Value> as '"+value+"', but the group contains no radio button with this value",this);
};
tersus.RadioButtonGroup.prototype['remove<Value>']= function()
{
	tersus.traverseHierarchy(this, DisplayNode.displayChildrenIterator, function (node){if (node.isRadioButton) node.setChecked(false);return true;});
};
tersus.RadioButtonGroup.prototype.setSelectedValue.requiresNodes = true;

// file: Range.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Range() {};
Range.prototype = new ActionNode();
Range.prototype.constructor = Range;
Range.prototype.start = function ()
{
	var limit1 = parseInt(this.getLeafChild('<Limit 1>'));
	var limit2 = parseInt(this.getLeafChild('<Limit 2>'));
	
	var min = Math.min(limit1, limit2);
	var max = Math.max(limit1, limit2);
	for (var i = min; i<=max; i++)
	{
		this.setLeafChild('<Numbers>', i, Operation.ADD);
	}	
};

// file: ReadResource.js
tersus.newAction('ReadResource', function tersus_ReadResource_Start()
{
	var url = this.getLeafChild('<URL>');
	var exit = this.getExit('<Content>');
	if (exit.modelId != BuiltinModels.TEXT_ID)
		modelError('<Content> must be of type Text in client side',this);
	var notFoundExit = this.getExit('<Not Found>');
	var notAuthorizedExit = this.getExit('<Not Authorized>');
	var node = this;
	var errorCallback = null;
	var callback = function(text)
	{
		if (text != null)
			node.chargeLeafExit(exit,text);
		node.continueExecution();
	};
	var errorCallback = function (status, statusText, e)
	{
		if (notFoundExit && ( this.pluginVersion==0 || status == 404 ))
			node.chargeEmptyExit(notFoundExit);
		else if (status == 403 && notAuthorizedExit)
			node.chargeEmptyExit(notAuthorizedExit);
		else
			node.resume = function()
			{
			  throw 'Failed to load "'+url+'" - status='+status+' message='+statusText+' ex='+e;
			 };
			
		node.continueExecution();
			
	}
	this.pause();
	tersus.loadURL(url, callback, false, errorCallback, null); 
});
// file: Refresh.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Refresh() {};
Refresh.prototype = new ActionNode();
Refresh.prototype.constructor = Refresh;
Refresh.prototype.start = function ()
{
	var element = this.getChild('<Element>');
	if (element && element.refresh)
	{
		element.refresh();
		rootDisplayNode.onResize(); // Added for mobile widgets. Can probably be removed once we get rid of jQuery Mobile scripting
	}
		
};

// file: RelativeDate.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('RelativeDate', function()
{
	var date = tersus.getDate(this.getChild('<Base Date>')); // Using local timezone
	if (date == null)
		date = new Date();
        else
		date = new Date(date.getTime());
	var y = this.getLeafChild('<Years>');
	var m = this.getLeafChild('<Months>');
	var d = this.getLeafChild('<Days>');
	
	var oy = date.getFullYear();
	var om = date.getMonth();
	var od = date.getDate();
	if (y)
	{
		date.setFullYear(date.getFullYear()+y);
		if (om != date.getMonth()) // overflow because date was Feb 29th.  SetDate(0) brings us back to Feb 28th 
			date.setDate(0);
	}
	if (m)
	{
		date.setMonth(date.getMonth()+m);
		if (date.getDate() != od) // Month overflow - go back to last day of previous month
			date.setDate(0);
	}
	if (d)
		date.setDate(date.getDate()+d);
			
	this.chargeLeafExit('<Date>', createDate(date.getFullYear(), date.getMonth()+1, date.getDate())); //Using local timezone
	
});

// file: RelativeTime.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.RelativeTime = function tersus_Relative_Time() {};
tersus.RelativeTime.prototype = new ActionNode();
tersus.RelativeTime.prototype.constructor = tersus.RelativeTime;
tersus.RelativeTime.prototype.start = function ()
{
	var baseTime = this.getLeafChild('<Base Time>');
	if (baseTime == null)
		baseTime = new Date();
	else
		baseTime = new Date(baseTime.getTime());
	var seconds = this.getLeafChild('<Seconds>');
	var time = baseTime.getTime() +  seconds*1000;
	var newTime = new Date(time);
	this.chargeLeafExit('<Time>',newTime);
}

// file: ReloadApplication.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.ReloadApplication = function() {};
tersus.ReloadApplication.prototype = new ActionNode();
tersus.ReloadApplication.prototype.constructor = tersus.ReloadApplication;
tersus.ReloadApplication.prototype.start = function ()
{
	tersus.async.exec(tersus.reloadApplication, false /* don't wait */);
};

// file: RemoveNumberedItem.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.RemoveNumberedItem = function RemoveNumberedItem(){};
tersus.RemoveNumberedItem.prototype = new ActionNode();
tersus.RemoveNumberedItem.prototype.constructor = tersus.RemoveNumberedItem;
tersus.RemoveNumberedItem.prototype.start = function()
{
	var parent = this.getChild('<Parent>');
	if (!parent.elementList)
	{
		if (this.getElement('<Invalid Parent>'))
			this.chargeExit('<Invalid Parent>', parent);
		else
			modelExecutionError("Invalid parent "+parent.modelId,this);
		return;
	}
	
	var e = this.getTargetList(parent);
	if (!e)
	{
		if (this.getElement('<Invalid Parent>'))
			this.chargeExit('<Invalid Parent>', parent);
		else
			modelExecutionError("Invalid parent "+parent.modelId,this);
			
		return;
	}
	
	var index = this.getLeafChild('<Index>');
	if (index < 0 || index > e.getChildren(parent).length)
	{
		if (this.getElement('<Invalid Index>'))
			this.chargeLeafExit('<Invalid Index>', index);
		else
			modelExecutionError("Invalid index "+index,this);
		return;
	}
	
	if (this.getElement('<Removed Item>'))
	{
		var children = e.getChildren(parent);
		this.chargeLeafExit('<Removed Item>', children[index-1]);
	}
	
	e.removeNumberedChild(parent, index);
};

tersus.RemoveNumberedItem.prototype.getTargetList = function(parent)
{
	var elementName = this.getLeafChild('<Element Name>');
	if (parent && parent.elementList)
	{
		var elements = parent.elementList;
		for (var i=0;i<elements.length;i++)
		{
			if (elementName != null)
			{
				if (elements[i].isRepetitive && elementName == elements[i].role)
					return elements[i];
			}
			else if (elements[i].isRepetitive)
					return elements[i];
		}
	}
	return null;
};


// file: RemoveStyleClass.js
/*********************************************************************************************************
 * Copyright (c) 2003-2013 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/

tersus.newAction('RemoveStyleClass',function()
{	
	var element = this.getChild('<Element>');
	var value = this.getLeafChild('<Style Class>');
	if (!element || !value || !element.isDisplayNode)
		return;
	element.removeStyleClass(value);
});

// file: Replace.js
/*********************************************************************************************************
 * Copyright (c) 2003-2011 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at http://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('Replace', function()
{
	var text = this.getLeafChild('<Text>');
	var replace = this.getLeafChild('<Replace>');
	var by = this.getLeafChild('<By>');
	
	if (by == null)
		by = "";
	
	var i = 0;
	var b = []; //Buffer to collect result fragments
	while (i < text.length)
    {
    	var j = text.indexOf(replace,i);
    	if (j < 0)
    	{
    		b.push(text.substr(i));
    		break;
    	}
    	b.push(text.substr(i,j-i));
    	b.push(by);
    	i = j + replace.length;
    }
 
	this.chargeLeafExit('<Updated Text>',b.join(''));
});
// file: Retrieve.js
/*********************************************************************************************************
 * Copyright (c) 2003-2011 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/

var m = tersus.baseURL.match('^(http|https)://[^/]+(:[0-9]+)?/([^/]*/)');
tersus.appScopePrefix =  (m && m.length>3)? m[3] : '';
tersus.newAction('Retrieve',function()
{	
	var key = this.getLeafChild('<Key>');
	var prefix = '';
	if (key)
	{
        if (tersus.useFilesystemForStorage)
        {
            this.retrieveFromFileSystem(key);
            return;
        }
		var type = this.getLeafChild('<Storage Type>') || 'LOCAL';
		var s;
		if (type == 'LOCAL')
		{
			s = window.localStorage;
			if (s == null)
				throw 'No local storage available';
			key = tersus.appScopePrefix+key;
		}
		else if (type == 'SESSION')
		{
			s = window.sessionStorage;
			if (s == null)
				throw 'No session storage available';
		}
		if (tlog) tlog('Retrieving :'+key + ' from '+type + ' storage');
		
		var value = s.getItem(key,value);
		if (tlog) tlog('Value :'+ (value == null ? 'null' : (value.length + 'characters')));
		
		if (value != null && value.length>0)
			this.chargeLeafExit('<Value>',value);
		else
		{
			this.chargeEmptyExit('<None>');
		}
	}
});

$.extend(tersus.Retrieve.prototype, {
    getErrorMessage: function(code)
    {
        switch(error.code)
        {
            case FileError.NOT_FOUND_ERR: return 'Not found'; 
            case FileError.SECURITY_ERR: return 'Security error';
            case FileError.ABORT_ERR: return 'Aborted';
            case FileError.NOT_READABLE_ERR: return 'Not redable';
            case FileError.ENCODING_ERR: return 'Encoding error';
            case FileError.NO_MODIFICATION_ALLOWED_ERR: return 'No modification allowed';
            case FileError.INVALID_STATE_ERR: return'Invalid state';
            case FileError.SYNTAX_ERR: return 'Syntax error';
            case FileError.INVALID_MODIFICATION_ERR: return 'Invalid modification';
            case FileError.QUOTA_EXCEEDED_ERR: return 'Quota exceeded';
            case FileError.TYPE_MISMATCH_ERR: return 'Type mismatch';
            case FileError.PATH_EXISTS_ERR: return 'Path exists';
            default: return 'Unknown error';
        }   
    }
    ,retrieveFromFileSystem:function(key)
    {
        var self = this;
        var fail = function(error)
        {
          self.resume = function()
          { 
              throw 'Error retrieving file:'+self.getErrorMessage(error.code)+' (code='+error.code+')';
          };
          self.continueExecution();
       
        };
        var done = function(value)
        {
            self.resume = function()
            {
                if (value)
                    this.chargeLeafExit('<Value>', value);
                else
                    this.chargeEmptyExit('<None>');
                self.finished();
            }
            self.continueExecution();
        };
        var fsSuccess = function(fileSystem)
        {
            console.log("Got filesystem");
            var fileEntrySuccess = function(fileEntry)
            {
                console.log("Got file Entry");
                var fileSuccess = function(file)
                {
                    console.log("Got file");
                    var reader = new FileReader();
                    reader.onloadend = function (evt)
                    {
                        
                        if (reader.error)
                            fail(reader.error);
                        else
                        {
                            console.log("Read file. Content="+reader.result);
                            done(reader.result);
                        }
                    };
                    reader.readAsText(file);
                };
                fileEntry.file(fileSuccess, fail);
            };
            var fileEntryError = function(error)
            {
                if (error.code == FileError.NOT_FOUND_ERR)
                   done(null);
                else
                    fail(error);
            }
            fileSystem.root.getFile(key, {create:false}, fileEntrySuccess, fileEntryError);
        };
        window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, fsSuccess, function(evt)
                {
                    fail(evt.target.error);
                });
        self.pause();
    }
});
// file: Round.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Round = function tersus_Round() {};
tersus.Round.prototype = new ActionNode();
tersus.Round.prototype.constructor = tersus.Round;
tersus.Round.prototype.start = function ()
{
	var number = this.getLeafChild('<Number>');
	if (number == null)
		modelExecutionError('Missng value for <Number>', this);
	var precision = this.getLeafChild('<Precision>');
	if (!precision)
		precision =0;
	if (precision!=Math.round(precision))
		modelExecutionError('<Precision> must be an integer', this);
	var factor = Math.pow(10, precision);
	var rounded = Math.round(number * factor)/factor;
	this.chargeLeafExit('<Rounded>',rounded);
};

// file: RunJavascript.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('RunJavascript', function()
{
	var scriptText = this.getLeafChild('<Script Text>');
	var triggerList = [];
	var valueList = [];
	var output;
	var exitList = [];
	var exitMap = {};
	triggerList.push('_node');
	valueList.push(this);
	for (var i=0; i<this.triggers.length; i++)
	{
		var trigger = this.triggers[i];
		if (trigger.role.charAt(0) != '<' ) // ignore 'special' triggers
		{
			triggerList.push(tersus.sqlize(trigger.role));
			//currently handling only leaf data types
			if (trigger.isRepetitive)
			{
				var array = [];
				var values = trigger.getChildren(this);
				var l = values.length;
				for (var j=0;j<l;j++)
				{
					var v = values[j];
					if (v != null)
						array.push(v.leafValue);
				}
				valueList.push(array);
			}
			else
			{
				var value = this.getLeafChild(trigger.role);
				valueList.push(value);
			}
		}
	}
	var functionText = 'var func = function('+triggerList.join(',')+'){';
	var packingText = '';
	functionText += '\nvar _out={};';
	if ( this.exits)
	{
		for (var i=0; i<this.exits.length; i++)
		{
			var exit = this.exits[i];
			if (exit.role.charAt(0) != '<') // ignore 'special' exits
			{
				var varName= tersus.sqlize(exit.role)
				functionText+='var '+varName+';'
				packingText+='_out["'+exit.role+'"]='+varName+';'
			}
		}
	}
	functionText += scriptText;
	functionText += ';'
	functionText += packingText;
	functionText+='return _out;};\nfunc;';
	var f  = eval(functionText);
	var out = f.apply(this,valueList);
	for (var exitName in out)
	{
		var v=out[exitName];
		if(v!=null)
		{
			var exit = this.getExit(exitName);
			if (exit.isRepetitive)
			{
				var l = v.length;
				for (var j=0;j<l;j++)
				{
					this.chargeLeafExit(exit, v[j]);
				}
			}
			else
			{
				this.chargeLeafExit(exitName, v);
			}
		}
	};
});		


// file: ScrollPane2.js

tersus.Widget('ScrollPane2','HTMLTag', {
	defaultTag:'div'
	,defaultWrapperTags:'div'
	,attach:function()
	{
        var zoomable = this.prop('zoomable');
		var useTouchScroll = !zoomable && is_touch_device() && 
			$('<div style="overflow:scroll;-webkit-overflow-scrolling:auto;">').css('-webkit-overflow-scrolling') =='auto';
		var $w = $(this.wrapperNode);
		if (useTouchScroll)
		{
			$w.css('overflow','scroll');
		}
		else if (window.iScroll) // Scrolling using iScroll where supported
		{
			$(this.wrapperNode).css('overflow:hidden');
			this.iScroll = new iScroll(this.wrapperNode,{ hScrollbar: false, vScrollbar: false, onBeforeScrollStart:this.onBeforeScrollStart, zoom:zoomable, zoomMax:this.prop('zoommax') });
			var node=this;
			node.iScrollRefresh = function()
			{
				setTimeout(function(){if (node.iScroll) node.iScroll.refresh();},100);
			};	
			$(window).bind('ter-process-end', node.iScrollRefresh);
		}
		else // Overflow:hidden with no scrolling support other than the
                // browser's default
		{
			$(this.wrapperNode).css('overflow:hidden');
		}
	
	}
    ,'get<Double Tap Zoom>':function()
    {
        return this.iScroll && this.iScroll.options.doubleTapZoom;
    }

    ,'set<Double Tap Zoom>':function(value)
            {
                if (this.iScroll)
                    this.iScroll.options.doubleTapZoom = value;
             }
    ,'get<Max Zoom>':function()
    {
        return this.iScroll && this.iScroll.options.maxZoom;
    }

    ,'set<Max Zoom>':function(value)
            {
                if (this.iScroll)
                    this.iScroll.options.maxZoom = value;
             }
	,onResize: function()
	{
		tersus.HTMLTag.prototype.onResize.call(this);
		if (this.iScroll)
		{
			this.iScroll.refresh();
		}
	}
	,destroy:function()
	{
		if (this.iScroll && this.iScroll.destory)
		{
			this.iScroll.destory(true);
			this.iScroll=null;
		}
		if (this.iScrollRefresh)
			$(window).unbind('ter-process-end', this.iScrollRefresh);
		
		tersus.HTMLTag.prototype.destroy.call(this);
	}
	
	,onBeforeScrollStart:function(e) /*
                                         * iScroll Hook to detect cases where we
                                         * don't want to scroll
                                         */
	{
		if (   e.target.tagName == "SELECT"
            || e.target.tagName == "INPUT"
            || e.target.tagName == "BUTTON"
            || e.target.tagName == "A"
            || e.target.tagName == "TEXTAREA") {
            return true;
        }
		e.preventDefault();
	}
});
// file: Scrollable.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 
function Scrollable() {};
Scrollable.prototype = new tersus.HTMLTag();
Scrollable.prototype.constructor = Scrollable;
Scrollable.prototype.defaultTag = 'div';
Scrollable.prototype.defaultStyleClass  = 'Scrollable';

//Scrollable.prototype.create = function()
Scrollable.prototype.copyValueOpt = function(value, nodeMap, htmlV, legacyNodes)
{
	
	tersus.HTMLTag.prototype.copyValueOpt.call(this,value, nodeMap, htmlV, legacyNodes)
	var scrollable = this;
	tersus.async.exec(function() {scrollable.calliScroll();} , false /* don't wait */);
};

Scrollable.prototype.calliScroll = function()
{
	if ( iScroll)
	{
		new iScroll(this.viewNode.firstChild);
	
	}
}

// file: SelectionField.js
var setter = tersus.setter;

tersus.Widget('SelectionField','HTMLTag',{
	defaultTag:'div'
	,jQuery:'fieldcontain'
	,templateData: function()
	{
		var n=this;
		var options=$(this.options).map(function(i,o){
													return {val:(o==null ? null:i), text:n.translate(n.getOptionText(o))};
													 });
		var btnIconSide = $(document.body).css('direction')=='rtl' ? 'left':'right';
		return {options:options, text:this.translate(this.getOptionText(this.value)), btnIconSide:btnIconSide};
	}
	,reset: function()
	{
		this.$select = null;
		this.supr('reset');
	}

	,template: '{{if caption}}<label for="${id}">${caption}</label>{{/if}}<div class="ui-select">'+
	'<div class="ui-btn ui-btn-icon-${btnIconSide} ui-btn-corner-all ui-shadow ui-btn-down-c ui-btn-up-c">'+
	'<span class="ui-btn-inner ui-btn-corner-all"><span class="ui-btn-text">${text}</span><span class="ui-icon ui-icon-arrow-d ui-icon-shadow"></span></span>'+
	'<select id="${id}">{{each(i,opt) options}}<option {{if (opt.val != null)}}value="${opt.val}"{{/if}}>${opt.text}</option>{{/each}}</select>'+
	'</div></div>'
	,attach:function()
	{
		 var self = this;
		 this.$select = $(this.viewNode).find('select');
		 this.$select.blur(function(){$.mobile.silentScroll(0);});
		 this.$buttonText = $(this.viewNode).find('.ui-btn-text');
		 this.$select.change(function(){
		 	self.jqRefresh();
		 	});
		 this.setSelectedIndex(this.findIndex(this.value));
		 self.jqRefresh();
	}
	,jqRefresh: function()
	{
		this.$buttonText.html(this.translate(this.getOptionText(this.getValue())));
/*		var s = this.$select.data('selectmenu');
		if (s && s.refresh)
			s.refresh(true);*/
			
	}
	,'set<Value>': setter(function(value)
	{
		this.value = value;
		if (this.$select)
		{
			this.setSelectedIndex(this.findIndex(this.value));
			this.jqRefresh();
		}
	},true)
	,'remove<Value>': function()
	{
		if (this.options && this.options.length>0)
			this.value = this.options[0];
		if (this.$select)
		{
			this.setSelectedIndex(0);
			this.jqRefresh();
		}
	}
	,getValue:function()
	{
		var selectedIndex;
//		if (this.tmpSelectedIndex != null) // In IE, the selected index is updated asynchronously, so we use tmpSelectedIndex if it is set
//			selectedIndex = this.tmpSelectedIndex;
//		else
		var selectedIndex = this.$select[0].selectedIndex;
		if (selectedIndex < 0)
			return null;
		return this.options[selectedIndex];
	}
	,'get<Value>':function()
	{
		return this.getValue();
	}	
	,findIndex: function(value)
	{
		if (this.options)
			for (var i=0; i<this.options.length; i++)
			{
				var option = this.options[i];
				if (compareValues(option, value))
					return i;
			}
		return -1;
	}
	,setSelectedIndex: function(index)
	{
		this.$select[0].selectedIndex = Math.max(index,0);
	}
	,'get<Placeholder Text>': function(){return this.emptyOptionText;}
	,'set<Placeholder Text>': function(text)
	{
		var isNew = this.emptyOptionText == null;
		this.emptyOptionText = text;
		if (isNew)
		{
			if (this.options)
				this.options.splice(0,0,null); // add null to beginning of list
			else
				this.options = [null];
		}
		if (this.$select)
		{
			if (isNew)
				this.$select.prepend($("<option>").text(this.translate(this.getOptionText(null))));
			else
				this.$select.find('option').first().text(this.translate(this.getOptionText(null)));
			if (this.value == null)
				this.setSelectedIndex(0);
			this.jqRefresh();
		}
	}
	,'remove<Placeholder Text>': function()
	{
		if (this.emptyOptionText != null)
		{
			this.emptyOptionText = null;
			this.options.splice(0,1); //remove first
			if (this.$select)
			{
				this.$select.first().remove();
				this.jqRefresh();
			}
		}
		
	}
	,'remove<Options>': function()
	{ 
		this.options = this.emptyOptionText == null ? [] : [null];
		if (this.$select)
		{
			var self = this;
			this.$select.children().filter(function(i){return i>0 || null == self.emptyOptionText;}).remove();
			this.jqRefresh();
		}
	}
	,'add<Options>':setter(function(option)
	 {
	 	if (!this.options)
	 		 this.options = [];
	 	this.options.push(option);
	 	if (this.$select)
	 	{
			this.$select.append($("<option>").text(this.translate(this.getOptionText(option))).val(this.options.length));
			if (this.value != null &&  compareValues(this.value, option) || this.options.length==1)
			{
				this.setSelectedIndex(this.options.length-1);
				this.jqRefresh();
			}
		}
	 },true)
    ,'get<Options>':function()
    {
    	if ( !this.options)
			return [];
			if (this.emptyOptionText != null)
			{
				return this.options.slice(1); // Ignoring the first item in the array, which is the empty option (null)
			}
		return this.options;
	}
	,getOptionText: function(value)
	{
        var outputValue = null;
        if (value && value.elementList)
        {
			var textElementRole = value.__textElementRole;
			if (textElementRole == null)
			{
				for (var i=0; i< value.elementList.length; i++)
				{
					var element = value.elementList[i];
					if (i==0)
					{
				        textElementRole = element.role; // If no text element is found, the first element is used
				        value.constructor.prototype.__textElement = element;
					}
					if (element.modelId == BuiltinModels.TEXT_ID)
					{
				        textElementRole = element.role;
				        value.constructor.prototype.__textElement = element;
				        break;
					}
				}
				value.constructor.prototype.__textElementRole = textElementRole;
			}
			if (textElementRole && value.children)
			        outputValue = value.children[textElementRole];
        }
        else
                outputValue = value;
        var text = '';
        if (outputValue != null)
                text =  outputValue.formatString(this.sharedProperties);
        else if (this.emptyOptionText != null)
                text = this.emptyOptionText;
        return text;
	}
});

// file: Separator.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Separator(){};
Separator.prototype = new DisplayNode();
Separator.prototype.constructor = Separator;
Separator.prototype.defaultTag = 'hr';

// file: SequenceNumber.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.SequenceNumber = tersus.DatabaseAction.__subclass('tersus.SequenceNumber');
tersus.SequenceNumber.prototype.getTableName = function()
{
	var tableName = this.getLeafChild('<Table Name>');
	if (tableName == null)
		tableName = 'Sequence_Numbers';
	return tableName;
};
tersus.SequenceNumber.prototype.start = function()
{
	this.pause();
	if (this.tableOK)
	{
		this.run();
		return;
	}
	this.tableOK = true;
	this.getTableDef(this.getTableName(),function(tableDef)
	{
		if (tableDef != null)
			this.run();
		else
			this.execSql('CREATE TABLE '+this.getTableName()+' (Name TEXT PRIMARY Key, Value Integer)',[], this.run);
	},this);
};
tersus.SequenceNumber.prototype.run = function()
{
	var sql = 'SELECT Value from '+this.getTableName()+' WHERE Name=?';
	var key = this.getLeafChild('<Key>');
	if (key == null)
		key = this.modelName;
	
	var values = [key];
	this.execSql(sql, values, function(transaction,results)
	{
		var rows = results.rows;
		if (rows.length == 0)
		{
			this.chargeLeafExit('<Next>',1);
			this.execSql('INSERT INTO '+this.getTableName() +' (Name, Value) VALUES (?,?)', [key, 1], this.resumeContext);
		}
		else
		{
			var seq = rows.item(0).Value + 1;
			this.chargeLeafExit('<Next>',seq);
			this.execSql('UPDATE '+this.getTableName() + ' SET Value= ? Where Name = ?', [seq, key], this.resumeContext); 
		}
	});
};

// file: SetAlertMode.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.SetAlertMode = function tersus_SetAlertMode() {};
tersus.SetAlertMode.prototype = new ActionNode();
tersus.SetAlertMode.prototype.constructor = tersus.SetAlertMode;
tersus.SetAlertMode.prototype.start = function ()
{
	tersus.alertMode.interactive = this.getLeafChild('<Interactive>');
	var errors = this.getLeafChild('<Errors>');
    if (errors || (errors == null))
    	tersus.errors = null;
    else
    	tersus.errors = [];
	tersus.alertMode.confirm = this.getLeafChild('<Confirm>');
}


// file: SetCookie.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function SetCookie() {};
SetCookie.prototype = new ActionNode();
SetCookie.prototype.constructor = SetCookie;
SetCookie.prototype.start = function ()
{
	var name = tersus.sqlize(this.getLeafChild('<Name>'));
	var value = this.getLeafChild('<Value>');
	var expires = this.getLeafChild('<Expires>');
	var domain = this.getLeafChild('<Domain>');
	var path = this.getLeafChild('<Path>');
	var secure = this.getLeafChild('<Secure>');
	
	if (tersus.isNative && window.localStorage)
	{
		localStorage.setItem('Cookie.'+name,value);
		return;
	}
	if (!expires)
		expires = new Date(2100,0,0);
	if (expires && expires.toGMTString)
		expires = expires.toGMTString();
	if (value == null)
		deleteCookie(name);
	else
		setCookie(name,value, expires, path, domain, secure);
};

// file: SetElement.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.SetElement = function tersus_SetElement() {};
tersus.SetElement.prototype = new ActionNode();
tersus.SetElement.prototype.constructor = tersus.SetElement;
tersus.SetElement.prototype.start = function ()
{
	var elementName = this.getLeafChild('<Element Name>');
	var parent = this.getChild('<Parent>');
	var value = this.getChild('<Value>');
	
	if (!parent)
	{
		modelExecutionError("Missing <Parent>",this);
		return;
	}
	if (!elementName)
	{
		modelExecutionError("Missing <Element Name>",this);
		return;
	}		
	var element = parent.getElement(elementName);
	if (element == null)
	{
		modelExecutionError("No element called "+elementName + " in "+ parent.modelId,this);
		return;
	}
	if (element.isRepetitive)
	{
		if (value != null)
			element.addAChild(parent,value);
		else
			element.removeChildren(parent);
	}
	else
	{
		if (value != null)
			element.replaceChild(parent,value, true /* reset display elements before copying new */);
		else
			element.removeChild(parent);
	}	
};

// file: SetStyleAttribute.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('SetStyleAttribute', function()
{
	var e = this.getChild('<Element>');
	var n = this.getLeafChild('<Attribute>');
	var a = tersus.getJsAttributeName(n);
	var v = this.getLeafChild('<Value>');
	if (e && e.viewNode && a)
	{
		 e.viewNode.style[a] = v;
	}
});


// file: SetUnloadConfirmation.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('SetUnloadConfirmation',function()
{
	var message = this.getLeafChild('<Message>');
	if (message)
		window.onbeforeunload = function(event) {
			event.returnValue = message; 
		};
	else
		window.onbeforeunload = null;
});


// file: Show.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Show() {};
Show.prototype = new ActionNode();
Show.prototype.constructor = Show;
Show.prototype.start = function ()
{
	var item = this.getChild('<Item>');
	if (item.select)
		item.select();
	var scrollableNode = item.viewNode;
	while (scrollableNode)
	{
		if (scrollableNode == this.mainWindow.rootDisplayNode.viewNode)
		{
			scrollableNode = this.mainWindow.document.body; // workaround for a bug in detecting the scrollable node in IE
			break;
		}
		if (isScrollable(scrollableNode))
			break;
		else
			scrollableNode = scrollableNode.parentNode;
	}
	if (scrollableNode)
	{
		var s = scrollableNode;
		var sSize = getVisibleSize(s);
		var v = item.viewNode;
		/*
			offsetTop = position of top relative to containing 
		*/
		
		var visible = (getOffsets(v).top >= getOffsets(s).top + s.scrollTop)
					&& (getOffsets(v).top+v.offsetHeight <= getOffsets(s).top + s.scrollTop +sSize.height);
		if (! visible)
		{
			var scrollTarget;
			var scrollToTop = v.offsetTop - s.offsetTop;
			var scrollToMiddle = scrollToTop - sSize.height/2;
			var scrollToBottom = scrollToTop  + (sSize.height-v.offsetHeight);
			if (v.offsetHeight >= sSize.height)
				scrollTarget = scrollToTop;
			else if (v.offsetHeight >= sSize.height/2)
				scrollTarget =scrollToBottom;
			else
				scrollTarget = scrollToMiddle;
			var scrollTo = Math.max(0, scrollTarget);
			var scrollTo = Math.min(scrollTo, s.scrollHeight - sSize.height);
			s.scrollTop = scrollTo;
		}
		var u = function ()
		{
			var message = "";
			message += "viewNode.scrollTop="+v.scrollTop+"\n";
			message += "viewNode.scrollHeight="+v.scrollHeight+"\n";
			message += "viewNode.offsetTop="+v.offsetTop+"\n";
			message += "viewNode.offsetHeight="+v.offsetHeight+"\n";
			message += "scrollableNode.scrollTop="+scrollableNode.scrollTop+"\n";
			message += "scrollableNode.scrollHeight="+scrollableNode.scrollHeight+"\n";
			message += "scrollableNode.offsetTop="+scrollableNode.offsetTop+"\n";
			message += "scrollableNode.offsetHeight="+scrollableNode.offsetHeight+"\n";
			alert(message);
		};
		this.mainWindow.showInfo = u;
		this.mainWindow.scrollableNode = scrollableNode;
	}
};
// file: SimpleTable.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 //Simple Table - A Table whos rows are based on a repetitive Data Element
function SimpleTable() {};
SimpleTable.prototype = new Table();
SimpleTable.prototype.constructor = SimpleTable;

SimpleTable.prototype.createHeader = function createHeader()
{
	if (! this.rowElement) return;
	var rowPrototype = tersus.repository.get(this.rowElement.modelId).prototype;
	if (! rowPrototype.elementList) return;
	var headerRow = this.createHTMLElement('tr');
	for (var i=0; i< rowPrototype.elementList.length; i++)
	{	
		var columnElement = rowPrototype.elementList[i];
		var label = this.translate(columnElement.role);
		var headerCell = this.createHTMLElement('th');
		headerCell.innerHTML = tersus.escapeHTML(label);
		if (i==0)
			headerCell.className='first';
		headerRow.appendChild(headerCell);
	}
	this.header = this.createHTMLElement('thead');
	var caption = this.createHTMLElement('caption');
	caption.innerHTML = tersus.escapeHTML(this.getCaption());
	this.header.appendChild(headerRow);
	this.viewNode.appendChild(caption);
	this.viewNode.appendChild(this.header);

		
};

// Overload addIntermediateDataElement - and create a SimpleTableRowElement instead
SimpleTable.prototype.addIntermediateDataElement = function addIntermediateDataElement(role, modelId)
{
	if (role.charAt(0) == '<' && this.getGetter(role))
	{
		element = new MethodElement(this, role, modelId);
		return this.addElement(element);
	}
	else
	{
		if (this.rowElement)
			modelError('A SimpleTable can only have one intemediate data element. '+this.modelId + ' has both "'+this.rowElement.role+'" and "'+role+'"');
		this.rowElement = new SimpleTableRowElement(role, modelId);
		return this.addElement(this.rowElement);
	}
};
SimpleTable.ROW_NODE_ID='rowNodeId';
SimpleTable.TABLE_NODE_ID='tableNodeId';

SimpleTable.prototype.isSimpleTable = true;
SimpleTable.handleRowClick = function()
{
	var htmlRow = this;
	var tableNode = tersus.findNode(htmlRow.getAttribute(SimpleTable.TABLE_NODE_ID));
	makeAssertion(tableNode != null,"Simple Table node not found");
	var rowId=htmlRow.getAttribute(SimpleTable.ROW_NODE_ID);
	var rowRecord = null;
	if (tableNode.rowElement)
	{
		var rowNodes=tableNode.rowElement.getChildren(tableNode);
		for (var i=0;i<rowNodes.length;i++)
		{
			if (rowNodes[i].getNodeId() == rowId)
			{
				rowRecord = rowNodes[i];
				break;
			}
		}
	}
	makeAssertion(rowRecord != null,"Simple Table row node not found");
	if (tableNode.selectedRow && tableNode.selectedHTMLRow)
		tableNode.selectedHTMLRow.className = null;
	tableNode.selectedHTMLRow = htmlRow;
	htmlRow.className = 'selected';
	tableNode.selectedRow = rowRecord;
};
//SimpleTableRowElement - An Element of SimpleTable that represents the row content.
//This is a special element for which the 'Add' operation creates rows to the table
function SimpleTableRowElement(role, modelId)
{
	this.role = role;
	this.modelId = modelId;
};
SimpleTableRowElement.prototype = new Element();
SimpleTableRowElement.prototype.constructor = SimpleTableRowElement;
SimpleTableRowElement.prototype.addAChild = function addAChild(parent, value)
{
	if (parent.currentWindow) // if parent is a real display node, add a row to the table
	{
		makeAssertion(parent.isSimpleTable, 'SimpleTableRowElement must be a child of SimpleTable');
		makeAssertion(this.isRepetitive, 'Row element of SimpleTable must be repetitive');
		//Create a body row 
		var row = parent.createHTMLElement('tr');
		var rowPrototype = tersus.repository.get(this.modelId).prototype;
		if (rowPrototype.elementList)
		{
			for (var i=0; i< rowPrototype.elementList.length;i++)
			{
				var cell = parent.createHTMLElement('td');
				var cellElement = rowPrototype.elementList[i];
				var cellValue = cellElement.getChild(value);
				if (cellValue && (cellValue.leafValue !== null && cellValue.leafValue !== undefined))
					cell.innerHTML = tersus.escapeHTML(''+cellValue.leafValue); // convert to String
				row.appendChild(cell);				
			}
		}
		parent.bodyNode.appendChild(row);
		var selectable = parent.sharedProperties.selectable == true; 
		if (selectable)
		{
			row.setAttribute(SimpleTable.ROW_NODE_ID,value.getNodeId());
			row.setAttribute(SimpleTable.TABLE_NODE_ID,parent.getNodeId());
			row.onclick = SimpleTable.handleRowClick;
		}
	}
	Element.prototype.addAChild.call(this, parent, value);

};
SimpleTableRowElement.prototype.removeChildren = function removeChildren(parent)
{
	Element.prototype.removeChildren.call(this, parent);
	if (parent.currentWindow && parent.viewNode) // if parent is a real display node, add a row to the table
	{
		var table=parent.viewNode;
		parent.selectedRow = null;
		if (table && table.tBodies.length)
		{
			var body = table.tBodies[0];
			while (body.rows.length > 0)
			{
				body.removeChild(body.rows[0]);
			}
		}
	}
};
Table.prototype['remove<Selected Row>'] = function ()
{
    if (this.selectedHTMLRow)
        $(this.selectedHTMLRow).removeClass('selected');
    this.selectedRow = null;
    this.selectedHTMLRow = null;
    
        
};

// file: Smaller.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Smaller = function tersus_Smaller() {};
tersus.Smaller.prototype = new ActionNode();
tersus.Smaller.prototype.constructor = tersus.Smaller;
tersus.Smaller.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	var y = this.getLeafChild('<Y>');
	if (x < y)
		this.chargeLeafExit('<Yes>',x);
	else
		this.chargeLeafExit('<No>',x);
};

// file: SmallerOrEqual.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.SmallerOrEqual = function tersus_SmallerOrEqual() {};
tersus.SmallerOrEqual.prototype = new ActionNode();
tersus.SmallerOrEqual.prototype.constructor = tersus.SmallerOrEqual;
tersus.SmallerOrEqual.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	var y = this.getLeafChild('<Y>');
	if (x <= y)
		this.chargeLeafExit('<Yes>',x);
	else
		this.chargeLeafExit('<No>',x);

};

// file: Sort.js
tersus.newAction('Sort', function()
{
	var ORDER_BY='<Order By>';
	var items = this.getTriggerValues(ORDER_BY);
	var orderBy = this.getLeafChild(ORDER_BY);
	
	
	var comparator;
	if (orderBy == null || orderBy.match(/^asc(ending)?$/i))
	{
		comparator = function(o1,o2)
		{
			return tersus.compare(o1, o2);
		};
	}
	else if (orderBy.match(/^desc(ending)?$/i))
	{
		comparator = function(o1, o2)
		{
			return tersus.compare(o2, o1);
		};
	}
	else
	{
		var clauses = orderBy.split(/\s*,\s*/);
		var sortComponents = [];	
		for (var i=0; i< clauses.length; i++)
		{
			var clause = clauses[i];
			var path = clause;
			var desc  = false;
			var parts = clause.split(" ");
			if (parts.length>1)
			{
				var suffix = parts[parts.length-1];
				if (suffix.match(/^asc(ending)?$/i))
				{
					path = $.trim(clause.substring(0, clause.length-suffix.length));
				}
				else if (suffix.match(/^desc(ending)?$/i))
				{
					path = $.trim(clause.substring(0, clause.length-suffix.length));
					desc = true;
				}
			}			
			sortComponents.push(new tersus.Sort.Component(path, desc));
		}
		comparator = function(o1, o2)
		{
			for (var i=0;i<sortComponents.length;i++)
			{
				var cc = sortComponents[i].compare(o1,o2);
				if (cc !=0)
					return cc;
			}
			return 0;
		};

	}
	
	tersus.quicksort(items, comparator);
	
	var e = this.getExit('<Sorted Items>');
	for (var i=0;i<items.length;i++)
	{
		this.accumulateExitValue(e, items[i]);
	};
});
tersus.Sort.Component = function(pathStr, desc)
{
	this.path= new Path(pathStr);
	this.desc=desc;
};
tersus.Sort.Component.prototype.compare = function(o1, o2)
{
	if (this.desc)
	{
		var t = o1;
		o1 = o2;
		o2 = t;
	}
	if (o1 == null && o2 == null)
		return 0;
	if (o1 == null)
		return -1;
	if (o2 == null)
		return 1;
		
	var l1 = o1.getValues(this.path);
	var l2 = o2.getValues(this.path);
	if (l1.length > 1 || l2.length>1)
		throw "Can't compare repetitive elements";
	var obj1 = l1[0] || null;
	var obj2 = l2[0] || null;
	return tersus.compare(obj1, obj2);
};



tersus.swap=function(a, i, j) {	var t=a[i];a[i]=a[j];a[j]=t;};
tersus.partition = function(a, left, right, piv, comp)
{
	var pv=a[piv];
	tersus.swap(a, piv, right-1); // Put pivot value at the end
	var pos=left;
	for(var i=left; i<right-1; i++) {
		if(comp(a[i],pv)<=0) {
			tersus.swap(a, pos, i);
			++pos;
		}
	}
	tersus.swap(a, right-1, pos);

	return pos;
};
tersus._quicksort = function(a, left, right, comp)
{
	if(right-1>left) {
		var piv=left+Math.floor(Math.random()*(right-left));

		piv=tersus.partition(a, left, right, piv, comp); // position is updated in 'partition'

		tersus._quicksort(a, left, piv, comp);
		tersus._quicksort(a, piv+1, right, comp);
	}
};
tersus.quicksort = function(array, comparator)
{
	tersus._quicksort(array, 0, array.length, comparator);
};

// file: Split.js
/*********************************************************************************************************
 * Copyright (c) 2003-2010 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('Split', function()
{
	var sep = this.getLeafChild('<Separators>');
	var text = this.getLeafChild('<Text>');
	var allowEmpty = this.getLeafChild('<Return Empty Strings>');


	var start = 0;
	var pos = 0;
	while (pos < text.length)
	{
		var c = text.charAt(pos);
		if (sep.indexOf(c) >= 0) // Found a separator
		{
			if (allowEmpty || pos > start)
				this.chargeLeafExit('<Segments>',text.substring(start, pos));
			++pos;
			start = pos;
		}
		else
			++pos;
	}
	if (allowEmpty || pos > start)
		this.chargeLeafExit('<Segments>',text.substring(start, pos));
});

// file: SplitDate.js
// See SplitDateAndTime
// file: SplitDateAndTime.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('SplitDateAndTime', function()
{
	var d = this.getLeafChild('<Date and Time>');
	if (d==null)
		d = this.getLeafChild('<Date>');
	if (d==null)
		return;	
	if (d.isTersusDate)
	{
		var date=d;
		this.chargeLeafExit('<Year>',date.year);	
		this.chargeLeafExit('<Month>',date.month);
		this.chargeLeafExit('<Day>',date.day);
		if (this.elements['<Day of Week>'])
		{
			var d = new Date(date.year, date.month-1, date.day);
			this.chargeLeafExit('<Day of Week>',d.getDay()+1);
		} 
		this.chargeLeafExit('<Hour>',0);
		this.chargeLeafExit('<Minute>',0);
		this.chargeLeafExit('<Second>',0);
		this.chargeLeafExit('<Millisecond>',0);
	}
	else
	{
		this.chargeLeafExit('<Year>',d.getFullYear());	
		this.chargeLeafExit('<Month>',d.getMonth()+1);
		this.chargeLeafExit('<Day>',d.getDate());
		this.chargeLeafExit('<Day of Week>',d.getDay()+1);
		this.chargeLeafExit('<Hour>',d.getHours());
		this.chargeLeafExit('<Minute>',d.getMinutes());
		this.chargeLeafExit('<Second>',d.getSeconds());
		this.chargeLeafExit('<Millisecond>',d.getMilliseconds());
	}
});
tersus.SplitDate = tersus.SplitDateAndTime;


// file: SquareRoot.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.SquareRoot = function tersus_SquareRoot() {};
tersus.SquareRoot.prototype = new ActionNode();
tersus.SquareRoot.prototype.constructor = tersus.SquareRoot;
tersus.SquareRoot.prototype.start = function ()
{
	var x = this.getLeafChild('<X>');
	if (x != 0)
		this.chargeLeafExit('<Square Root>',Math.sqrt(x))
};
// file: StartsWith.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('StartsWith', function()
{
	var text = this.getLeafChild('<Text>');
	var prefix = this.getLeafChild('<Prefix>');
	if (text != null && prefix != null)
	{
		if (text.length >= prefix.length && text.substring(0,prefix.length) == prefix)
			this.chargeLeafExit('<Yes>',text);
		else
			this.chargeLeafExit('<No>',text);
	}
});


// file: Store.js
/*******************************************************************************
 * Copyright (c) 2003-2011 Tersus Software Ltd. , All rights reserved.
 * 
 * This program is made available under the terms of the GNU Lesser General
 * Public License, version 2.1, which is part of this distribution and is
 * available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 ******************************************************************************/


/* Patch to avoid local storage on iOS 5 */
tersus.useFilesystemForStorage = tersus.isNative && window.requestFileSystem &&
    (/(iPhone|iPod|iPad)/i.test(navigator.userAgent)) &&
    (/OS 5_\d(_\d)? like Mac OS X/i.test(navigator.userAgent));

tersus.newAction('Store',function()
{	
	var key = this.getLeafChild('<Key>');
	var value = this.getLeafChild('<Value>');
	var prefix = '';
	if (key)
	{
        if (tersus.useFilesystemForStorage)
        {
            if (value == null)
                this.removeFromFileSystem(key,value);
            else
                this.storeInFileSystem(key, value);
            return;
        }
        var type = this.getLeafChild('<Storage Type>') || 'LOCAL';
		var s;
		if (type == 'LOCAL')
		{
			s = window.localStorage;
			if (s == null)
				throw 'No local storage available';
			key = tersus.appScopePrefix+key;
		}
		else if (type == 'SESSION')
		{
			s = window.sessionStorage;
			if (s == null)
				throw 'No session storage available';
		}
		if (value == null)
			s.removeItem(key)
		else
			s.setItem(key,value);
	}
});
$.extend(tersus.Store.prototype, {
        getErrorMessage: function(code)
        {
            switch(error.code)
            {
                case FileError.NOT_FOUND_ERR: return 'Not found'; 
                case FileError.SECURITY_ERR: return 'Security error';
                case FileError.ABORT_ERR: return 'Aborted';
                case FileError.NOT_READABLE_ERR: return 'Not redable';
                case FileError.ENCODING_ERR: return 'Encoding error';
                case FileError.NO_MODIFICATION_ALLOWED_ERR: return 'No modification allowed';
                case FileError.INVALID_STATE_ERR: return'Invalid state';
                case FileError.SYNTAX_ERR: return 'Syntax error';
                case FileError.INVALID_MODIFICATION_ERR: return 'Invalid modification';
                case FileError.QUOTA_EXCEEDED_ERR: return 'Quota exceeded';
                case FileError.TYPE_MISMATCH_ERR: return 'Type mismatch';
                case FileError.PATH_EXISTS_ERR: return 'Path exists';
                default: return 'Unknown error';
            }   
        }
        ,storeInFileSystem:function(key, value)
        {
            var self = this;
            var fail = function(error)
            {
              self.resume = function()
              { 
                  throw 'Error writing file:'+self.getErrorMessage(error.code)+' (code='+error.code+')';
              };
              self.continueExecution();
           
            };
            var fsSuccess = function(fileSystem)
            {
                console.log("Got filesystem");
                var fileEntrySuccess = function(fileEntry)
                {
                    console.log("Got file");
                    var writerSuccess = function (writer)
                    {
                        console.log("Got writer");
                        console.log("writer:"+writer);
                        
                        writer.onwrite = function(evt)
                        {
                            console.log("Write done");
                            self.resume = function()
                            {
                                self.finished();
                            };          
                            self.continueExecution();
                         };
                         writer.onerror = function()
                         {
                             console.log("Write failed");
                             fail(writer.error);
                         }
                         writer.write(value);
                    };
                    
                    fileEntry.createWriter(writerSuccess, fail);
                };
                fileSystem.root.getFile(key, {create:true}, fileEntrySuccess, fail);
            };
            window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, fsSuccess, function(evt)
                    {
                        fail(evt.target.error);
                    });
            self.pause();
        }
        ,removeFromFileSystem:function(key)
        {
            var self = this;
            var fail = function(error)
            {
              self.resume = function()
              { 
                  throw 'Error removing file:'+self.getErrorMessage(error.code)+' (code='+error.code+')';
              };
              self.continueExecution();
           
            };
            var done = function()
            {
                self.resume = function()
                {
                    self.finished();
                }
                self.continueExecution();
            };
            var fsSuccess = function(fileSystem)
            {
                console.log("Got filesystem");
                var fileEntrySuccess = function(fileEntry)
                {
                    console.log("Got file");
                    var removeSuccess = function ()
                    {
                        console.log("File removed");
                        done();
                    };
                    fileEntry.remove(removeSuccess, fail);
                };
                var fileEntryError = function(error)
                {
                    if (error.code == FileError.NOT_FOUND_ERR)
                       done();
                    else
                        fail(error);
                }
                fileSystem.root.getFile(key, {create:false}, fileEntrySuccess, fileEntryError);
            };
            window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, fsSuccess, function(evt)
                    {
                        fail(evt.target.error);
                    });
            self.pause();
        }

        
});

// file: Subscribe.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Subscribe = ActionNode.__subclass('Subscribe');
tersus.Subscribe.loadURL = tersus.loadURL; // overridden when notification server is on another host
tersus.Subscribe.prototype.ON_MESSAGE =  '<On Message>';
tersus.Subscribe.prototype.MESSAGE =  '<Message>';
tersus.Subscribe.prototype.CHANNEL_T =  '<Channel>';
tersus.Subscribe.prototype.CHANNEL_D =  'Channel';
tersus.Subscribe.prototype.SOURCE =  'Source';
tersus.Subscribe.prototype.TIMESTAMP =  'Timestamp';
tersus.Subscribe.prototype.TYPE =  'Type';
tersus.Subscribe.prototype.CONTENT =  'Content';
tersus.Subscribe.pendingSubscriptions = null;
tersus.Subscribe.subscriptions = {};
tersus.Subscribe.clientId = null;

tersus.Subscribe.updateSubscriptions = function()
{
	if (!tersus.Subscribe.pendingSubscriptions)
		return;
	var a = [];
	var p = tersus.Subscribe.pendingSubscriptions;
	for (var channel in p)
	{
		if (p[channel]='ADD')
			a.push('+'+channel);
		else
			a.push('-'+channel);
	}
	tersus.Subscribe.pendingSubscriptions = null;
	if (a.length > 0)
	{
		var channels= encodeURIComponent(a.join(','));
		var url = tersus.notificationServer+'?action=subscribe&clientId='+tersus.Subscribe.clientId+'&channels='+channels+'&timestamp='+(new Date()).getTime();
		if (tersus.notificationServerAppId)
			url+='&appId='+tersus.notificationServerAppId;
		
		tersus.Subscribe.loadURL(url, false); //TODO better error handling?
	}
};
tersus.Subscribe.reconnect = function(timeout)
{
		tersus.Subscribe.clientId = null;
		tersus.Subscribe.pendingSubscriptions = {};
		for (var channel in tersus.Subscribe.subscriptions)
			tersus.Subscribe.pendingSubscriptions[channel]='ADD';
		setTimeout(tersus.Subscribe.connect,timeout);
};

tersus.Subscribe.handleResponse = function(responseText)
{
	var p = null;var l = null;
	if(responseText)
	{
		// we expect the second line to contain the response: first line is for "keep-alive" dots
		var ll = responseText.split(/[\n]/);
		if (ll.length >=2)
			l = ll[1];
		else if (ll.length>=1)
			l = ll[0];
		if (l!= null)
			p = l.split(/[\t]/);
	}
	if (!p || p.length == 0 || ! p[0])
	{
		tersus.Subscribe.reconnect(10000);
	}
	else if (p[0] == 'CONNECTED')
	{
		tersus.Subscribe.clientId = p[1];
		tersus.Subscribe.poll();
		tersus.Subscribe.updateSubscriptions();
	}
	else if (p[0] == 'RECONNECT')
	{
		tersus.Subscribe.reconnect(500);
	}
	else if (p[0] == 'MESSAGE')
	{
		//Not using p because split doesn't work consistently across browsers
		pp = l.match(/MESSAGE\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)\t([^\t]*)/);
		var timestamp = new Date(); // TODO parse pp[1] for timestamp
		var channel = tersus.Subscribe.unescapeJava(pp[2]);
		var source = tersus.Subscribe.unescapeJava(pp[3]);
		var type = tersus.Subscribe.unescapeJava(pp[4]);
		var message = tersus.Subscribe.unescapeJava(pp[5]);
		var nodeIds = tersus.Subscribe.subscriptions[channel];
		if (nodeIds)
		{
			for (var i=0; i<nodeIds.length; i++)
			{
				var node = tersus.findNode(nodeIds[i]);
				if (node)
					node.onMessage(timestamp, channel, source, type, message);
			}
		}
		tersus.Subscribe.poll();
	}
	else if (p[0] == 'OK')
	{
		// alert('Subscribed');
	}
	else
	{
		tersus.Subscribe.reconnect(10000);
	}
};
tersus.Subscribe.repoll = function(status, statusText, e)
{
	setTimeout(tersus.Subscribe.poll,1000);
};
tersus.Subscribe.handleError = function(status, statusText, e)
{
	setTimeout(tersus.Subscribe.poll,10000);
};
tersus.Subscribe.poll = function()
{
	var url = tersus.notificationServer+'?action=connect&clientId='+tersus.Subscribe.clientId+'&timestamp='+(new Date()).getTime();
	tersus.Subscribe.xhr = tersus.Subscribe.loadURL(url, true);	
}
tersus.Subscribe.disconnected = true; // indicates that client is neither connected nor connecting to notification server
tersus.Subscribe.unescapeJava = function(str)
{
	if (str.search(/[^\\]["]/) >= 0)
		throw new tersus.Exception('Invalid string literal ['+str+']');
	var s = '"'+str+'"';
	return eval (s);
	
};
tersus.Subscribe.prototype.start = function()
{
	if (!tersus.notificationServer)
		tersus.notificationServer = tersus.rootURL+'Notifier';
	var channel = this.channel = this.getLeafChild(this.CHANNEL_T);
	var list = tersus.Subscribe.subscriptions[channel];
	if (!list)
	{
		list = [];
		tersus.Subscribe.subscriptions[channel] = list;
		if (!tersus.Subscribe.pendingSubscriptions)
		{
			tersus.Subscribe.pendingSubscriptions = {};
		}				
		tersus.Subscribe.pendingSubscriptions[channel]='ADD';
	}
	list.push(this.getNodeId());
	if (tersus.Subscribe.disconnected)
	{
		tersus.Subscribe.connect();
	}
	else
	{
		setTimeout(tersus.Subscribe.updateSubscriptions,1000);
	}
	this.chargeLeafExit('<Subscription Id>',this.getNodeId());
};
tersus.Subscribe.connect = function()
{
	if (!tersus.Subscribe.connectRetries)
		tersus.Subscribe.connectRetries = 0;
	if (tersus.Subscribe.loadURL == null)
	{
		if (tersus.Subscribe.connectRetries < 20)
		{
			setTimeout(tersus.Subscribe.connect,2000);
			return;
		}
		else
		{
			alert('Failed to connect to notification server: COMMFrame not loaded');
			return;
		}
	}
	tersus.Subscribe.disconnected = false;
	var url = tersus.notificationServer+'?action=connect&timestamp='+(new Date()).getTime();
	tersus.Subscribe.loadURL(url, false);
};

tersus.Subscribe.prototype.onMessage = function(timestamp,channel,source, type,content)
{
	var eventElement = this.getElement(this.ON_MESSAGE);
	if (!eventElement)
	{
		modelError('Missing sub-process "'+this.ON_MESSAGE+'"',this);
		return;
	}
	var messageTrigger = eventElement.getChildConstructor().prototype.getTrigger(this.MESSAGE);
	var message = messageTrigger.createChildInstance();
	timestamp = new Date(timestamp.getTime());
	message.setLeafChild(this.TIMESTAMP,timestamp,Operation.REPLACE);
	message.setLeafChild(this.CHANNEL_D,channel,Operation.REPLACE);
	message.setLeafChild(this.SOURCE,source,Operation.REPLACE);
	message.setLeafChild(this.TYPE,type,Operation.REPLACE);
	message.setLeafChild(this.CONTENT,content,Operation.REPLACE);
	var p = {};
	p[this.MESSAGE]=message;
	this.queueEvent(new tersus.Event(this.ON_MESSAGE), p);
};
tersus.NOTIFICATIONS_FRAME = 'notifications';
tersus.Subscribe.loadURL = function(url, useErrorHandler)
{
	return tersus.loadURL(url, tersus.Subscribe.handleResponse, false, useErrorHandler? tersus.Subscribe.handleError : tersus.Subscribe.commError);
}
tersus.Subscribe.loadURLSafari =  function(url, useErrorHandler)
{
	document.domain=tersus.Subscribe.parentDomain;
	var f = document.getElementById(tersus.NOTIFICATIONS_FRAME);
	var fw = getIFrameWindow(f);
	fw.loadURLSafari(url,useErrorHandler);
	document.domain=tersus.Subscribe.mainHost;
};
tersus.Subscribe.prototype.onload = function()
{
	if (tersus.notificationServer)
	{
   		tersus.Subscribe.mainHost = document.domain;
   		var nsHost = tersus.notificationServer.match(/\/\/([^:/]+)[:/]/)[1];
 		tersus.Subscribe.parentDomain = commonSuffix(nsHost,tersus.Subscribe.mainHost).match(/[^.]*.(.*)/)[1];
   		tersus.Subscribe.loadURL = null;
        var iframe = window.createAnIFrame(window, tersus.NOTIFICATIONS_FRAME,'notification.html');
	}
};
tersus.Subscribe.commError = function()
{
   			parent.alert('An error occurred when communicating with notification server');
};

function commonSuffix(s1,s2)
{
	var l1=s1.length;
	var l2=s2.length;
	for (var l = Math.min(l1,l2); l>=0; l--)
	{
		var suf1 = s1.substr(l1-l,l);
		var suf2 = s2.substr(l2-l,l);
		if (suf1 == suf2)
			return suf1;
	}
	return null;
}

// file: Substract.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Substract = function tersus_Substract() {};
tersus.Substract.prototype = new ActionNode();
tersus.Substract.prototype.constructor = tersus.Substract;
tersus.Substract.prototype.start = function ()
{
	var x = parseFloat(this.getLeafChild('<X>'));
	var y = parseFloat(this.getLeafChild('<Y>'));
	this.chargeLeafExit('<Difference>',x-y);
};

// file: Sum.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Sum = function tersus_Add() {};
tersus.Sum.prototype = new ActionNode();
tersus.Sum.prototype.constructor = tersus.Sum;
tersus.Sum.prototype.start = function ()
{
	var values = this.getTriggerValues();
	var sum = 0;
	for (var j=0; j<values.length; j++)
	{
		var value = values[j];
		if (value.leafValue != null)
			sum += parseFloat(value.leafValue);
	}
	this.chargeLeafExit('<Sum>',sum);
};

// file: SwitchView.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function SwitchView() {};
SwitchView.prototype = new FlowNode();
SwitchView.prototype.constructor = SwitchView();

SwitchView.prototype.start = function()
{
	var view = this.getLeafChild('<View>');
	var perspective = this.getLeafChild('<Perspective>');
	var parameters = ''
	for (var i=0; i<this.triggers.length; i++)
	{
		var trigger = this.triggers[i];
		if (trigger.role.charAt(0) != '<') // ignore 'special' triggers
		{
			var value = this.getLeafChild(trigger.role);
			if (value)
			{
				if (parameters)
					parameters += '&';
				parameters+=encodeURIComponent(trigger.role)+'='+encodeURIComponent(value);
			}
		}
	}
	
	tersus.switchView(perspective,view,parameters);
};

// file: TabbedPane.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function TabbedPane() {};
TabbedPane.prototype = new Pane();
TabbedPane.prototype.constructor = TabbedPane;
TabbedPane.prototype.reset = function()
{
	this.selectedTab = this.selectedTabRole = null;
	DisplayNode.prototype.reset.call(this);
};
TabbedPane.prototype.createSpacerDiv = function TabbedPane_createSpacerDiv()
{
	var div = this.createHTMLElement('div');
	div.style.clear='both';
	var img = this.createHTMLElement('img');
	img.src="images/spacer.gif";
	if (document.compatMode != 'BackCompat')
		img.className='spacer_image';
	div.className='spacer_div';
	div.appendChild(img);
	return div;
};
TabbedPane.prototype.createViewNode = function TabbedPane_crateViewNode()
{
	var direction = getActualStyle(this.currentWindow.document.body, 'direction');
	var rtlSuffix = (direction == 'rtl') ? '_rtl':''; // Support for right-to-left languages
	DisplayNode.prototype.createViewNode.call(this);
	var header = this.createHTMLChildElement(this.viewNode,'div', 'tabbedPaneHeader'+rtlSuffix);
	header.appendChild(this.createSpacerDiv());
	this.tabList = this.createHTMLChildElement(header,'ul');
	this.defaultElement = this.displayElements[0];
	this.tabs = {};
	this.links = {};
	var footer = this.createSpacerDiv();
	footer.className="footer";
	header.appendChild(footer);
	var contentTR = this.createHTMLChildElement(this.viewNode, 'div', 'tabbedPaneContentTR'+rtlSuffix);
	var contentBR = this.createHTMLChildElement(contentTR, 'div', 'tabbedPaneContentBR'+rtlSuffix);
	var contentTL = this.createHTMLChildElement(contentBR, 'div', 'tabbedPaneContentTL'+rtlSuffix);
	var contentBL = this.createHTMLChildElement(contentTL, 'div', 'tabbedPaneContentBL'+rtlSuffix);
	contentBL.appendChild(this.createSpacerDiv());
	this.contentNode = this.createHTMLChildElement(contentBL,'div','tabbedPaneContent'+rtlSuffix);
	var width = this.sharedProperties.width
	if ( width !== null && width !== undefined && width != ' ')
	{
		if (window.browser == 'IE')
			this.contentNode.style.width='100%';
		if (width != '100%' || window.browser != 'Mozilla')
			this.viewNode.style.width = this.sharedProperties.width;
	}
	var cHeight = this.sharedProperties.contentHeight;
	if ( cHeight !== null && cHeight !== undefined && cHeight != ' ')
	{
		this.cHeight = cHeight;
		this.contentNode.style.height=cHeight;
	}
	contentBL.appendChild(this.createSpacerDiv());
};

TabbedPane.prototype.addTab = function (tabCaption, childNode, previousTab)
{
	var childId = childNode.getNodeId();
	var item = this.createHTMLElement('li');
	var nextTab = null;
	if (previousTab)
		nextTab = previousTab.nextSibling;
	else
		nextTab = this.tabList.firstChild;
	item.childId=childId;
	this.tabList.insertBefore(item, nextTab);
	var div = this.createHTMLChildElement(item,'div');
	var link = this.createHTMLChildElement(div,'a');
	this.tabs[childId]=item;
	this.links[childId]=link;
	link.href="javascript:tersus.findNode("+this.getNodeId()+").selectTab("+childId+")";
	link.innerHTML=tersus.escapeHTML(tabCaption);
	if ((! this.selectedTab) && (childNode.element == this.defaultElement) )
	{
		item.className='selected';
		this.selectedTab = item;
		this.selectedChild = childNode;
	}
	var pane = this;
	if (this.sharedProperties.adjustBottom == true)
		tersus.async.exec(function() {pane.onResize();}, false /* don't wait */);
	
};

TabbedPane.prototype.fireOnSelect = function (childNode)
{
	window.engine.handleEvent(childNode, Events.ON_SELECT);
};
TabbedPane.prototype.selectTab = function (nodeId)
{
    this.select(nodeId);
    $(window).trigger('ter-process-end');
};

TabbedPane.prototype.select = function (nodeId)
{
	var childNode = tersus.findNode(nodeId);
	if (!childNode)
		return;
	this.links[nodeId].blur();
	this.setSelectedTab(childNode);
	if (childNode.hasEventHandler(Events.ON_SELECT))
	{
		this.fireOnSelect(childNode);
	}
};

TabbedPane.prototype['get<Selected Pane>'] = function()
{
	return this.selectedChild;
};
TabbedPane.prototype.setSelectedTab  = TabbedPane.prototype['set<Selected Pane>'] = function (childNode)
{
	var nodeId = childNode.getNodeId();
	var tab = this.tabs[nodeId];
	if (tab === null || tab === undefined)
		modelError('Error in TabbedPane.setSelectedTab: no tab called '+tab+' in '+ this.modelId);
	if (this.selectedTab == tab)
	{
		return;
	}
	this.selecting = true;
	if (this.selectedTab)
	{
		this.selectedTab.className = 'normal';
		this.selectedChild.viewNode.style.display='none';
	}
	tab.className='selected';
	if (childNode)
	{
		childNode.viewNode.style.display = '';
		//reattach the child node to reset the parent height
		var pane = childNode.viewNode;
		var parent = pane.parentNode;
	}
	
	this.selectedChild = childNode;
	this.selectedTab = tab;
	
	if (this.selectedChild)
		this.selectedChild.onResize();

};

TabbedPane.prototype.setSelectedTab.requiresNodes = true;

TabbedPane.prototype.removeChildViewNode = function (child)
{
	DisplayNode.prototype.removeChildViewNode.call(this,child);
	var tabItem = this.tabs[child.getNodeId()];
	if (tabItem && this.tabList)
		this.tabList.removeChild(tabItem);
	if (this.selectedTab == tabItem)
	{
		this.selectedTab == null;
		this.selectedChild = null;
	}
};
TabbedPane.prototype.appendChildViewNode = function (child)
{
	this.contentNode.appendChild(child.viewNode);
	var previous = this.findPreviousSibling(child);
	var previousTab = null;
	if (previous)
		previousTab = this.tabs[previous.getNodeId()];
	this.addTab(child.getCaption(), child, previousTab);
	if (child == this.selectedChild)
	{
		child.viewNode.style.display='';
		this.selectedChild = child;
	}
	else
		child.viewNode.style.display='none';

	var tabbedPane = this;
	child.captionChanged = function()
	{
		tabbedPane.links[child.getNodeId()].innerHTML = tersus.escapeHTML(this.getCaption());
	};
		
};
TabbedPane.prototype.onResize = function()
{
	if (this.sharedProperties.adjustBottom == true)
	{
		this.adjustBottom();
	};
	if (this.selectedChild)
		this.selectedChild.onResize();
};

TabbedPane.prototype.adjustHeight = function (delta)
{
	tersus.adjustHeight(this.contentNode, delta);
};

// file: Table2.js
/*********************************************************************************************************
 * Copyright (c) 2003-2014 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
//Table - a simple table
tersus.Table2 = function Table2() {};
tersus.Table2.prototype = new DisplayNode();
tersus.Table2.prototype.constructor = tersus.Table2;
tersus.Table2.prototype.getTag = function()
{
	return 'table';
};
tersus.Table2.prototype.reset = function reset()
{
	DisplayNode.prototype.reset.call(this);
	this.selectedRow = null;
	this.visibleColumns = {};
	if (this.headerRow)
	{
		var headerCells=this.headerRow.childNodes;
		for (var i=0;i<headerCells.length;i++)
		{
			headerCells[i].style.display='';
		}
	}
}
tersus.Table2.prototype.createViewNode = function createViewNode()
{
	this.gridPending=true;
	this.columnNames = [];
	this.sortOrder = null;
	this.visibleColumns = null;
	this.hiddenColumns = {};
	DisplayNode.prototype.createViewNode.call(this);

	this.setProperties(); // In Mozilla, we have to set the styleclass before creating the body of the table
	this.createCaption();
	this.createHeader();
	this.createFooter();
	this.bodyNode = this.currentWindow.document.createElement('tbody');
	this.viewNode.appendChild(this.bodyNode);
	this.viewNode.id = this.getNodeId();
};
tersus.Table2.prototype.createCaption = function createCaption()
{
	if ( this.sharedProperties.showCaption == false) // default = true
	{
		return;
	}
	else
		if ( ! this.getRowPrototype())
			return;
	this.captionDOMElement = this.createHTMLElement('caption');
	this.captionDOMElement.innerHTML = '<div>'+tersus.escapeHTML(this.getCaption())+'</div>';
	this.viewNode.appendChild(this.captionDOMElement);
};
tersus.Table2.prototype.captionChanged = function()
{
	if (this.captionDOMElement)
		this.captionDOMElement.innerHTML = '<div>'+tersus.escapeHTML(this.getCaption())+'</div>';
};

tersus.Table2.prototype.baseProperties = {sortable:null,scrollable:null,resizablecolumns:true, moveablecolumns:true};

tersus.Table2.prototype.initGrid = function()
{
	this.gridNode =  this.wrapperNode || this.viewNode;

	// backwards compatibility for html.sort property
	var sortable = this.prop('sortable');
	if (sortable == null)
	{
		switch (this.prop('sort'))
		{
		case 'single':
			sortable = true;
			break;
		case 'multiple':
			sortable = 'multi';
			break;
		default:
			sortable = false;
		}
	}
	var self=this;
	$(this.gridNode).datagrid(
			{
				scrollable:this.prop('scrollable'),
				resizableColumns : this.prop('resizablecolumns'),
				movableColumns:this.prop('movablecolumns'),
				sortable :  sortable,
				movecolumn:function(e){self.handleColChange();},
				sort:function(e){self.handleColChange();}
			});
	this.updateColumnState();
	if (this.pending_hidden_cols !== undefined)
	{
		this.setHiddenColumns(this.pending_hidden_cols);
		delete this.pending_hidden_cols;
	}
	if (this.pendingVisibleColumns !== undefined)
	{
		this.setVisibleColumns(this.pendingVisibleColumns)
		delete this.pendingVisibleColumns;
	}
	if (this.pendingSortOrder !== undefined)
	{
		this.setSortOrder(this.pendingSortOrder);
		delete this.pendingSortOrder;
	}
	this.gridPending=false;
};
tersus.Table2.hiddenTables = [];
tersus.Table2.prototype.createChildren = function()
{
	DisplayNode.prototype.createChildren.call(this);
	var self=this;
	$(this.viewNode).css('width','100%');
	if ($(this.viewNode).is(':visible'))
	{
		setTimeout(function() {
			self.initGrid();
		},0);
	}
	else
	{
		tersus.Table2.hiddenTables.push(this);
	}

};
$(function() {
	$(window).on('ter-process-end', function() {
		var newList = [];
		$.each(tersus.Table2.hiddenTables, function()
				{
			if ($(this.viewNode).is(':visible'))
			{
				this.initGrid();
			}
			else
				newList.push(this);
				});
		tersus.Table2.hiddenTables = newList;
	});

});
tersus.Table2.prototype.addHeaderCells = function addHeaderCells(headerRow,node)
/* Adds header cells based on the structure of the given node */
{
	for (var i=0; i< node.displayElements.length; i++)
	{	
		var columnElement = node.displayElements[i];
		var columnNodePrototype = columnElement.getChildConstructor().prototype;
		if (columnNodePrototype.isDisplayGroup)
		{
			this.addHeaderCells(headerRow, columnNodePrototype);
		}
		else
		{
			var labelHTML = columnElement.properties.caption;
			if (!labelHTML || labelHTML == ' ')
				labelHTML = tersus.escapeHTML(columnElement.role)
				labelHTML = this.translate(labelHTML);
			var headerCell = this.createHTMLElement('th');
			headerCell.setAttribute("element_name", columnElement.role);
			var columnName = columnElement.properties.sortColumnName;
			if (!columnName)
				columnName = columnElement.role;
			if (!tersus.useSQLQuotedIdentifiers)
				columnName = tersus.sqlize(columnName);
			headerCell.setAttribute("column_name", columnName);
			this.columnNames.push(tersus.useSQLQuotedIdentifiers ? columnName : columnName.toLowerCase());
			headerCell.innerHTML = labelHTML;

			if (headerRow.childNodes.length == 0)
				headerCell.className='first';
			headerRow.appendChild(headerCell);
		}
	}
};
tersus.Table2.prototype.getRowPrototype = function()
{
	var output = null;
	if (this.subFlowList)
	{
		for (var i=0; i< this.subFlowList.length; i++)
		{
			var subFlow = this.subFlowList[i];
			if (subFlow.isDisplayElement && subFlow.role != '<Header>' && subFlow.role != '<Footer>')
			{
				if (output)
					return null;
				else
					output = subFlow;
			}
		}	
	}
	return output;
};
tersus.Table2.prototype.createHeader = function createHeader()
{
	if ( this.sharedProperties.showHeadings == false) // default = true
		return;
	var rowElement = this.getRowPrototype();
	if (! rowElement) return;
	var rowPrototype = tersus.repository.get(rowElement.modelId).prototype;
	if (! rowPrototype.subFlowList) return;
	var headerRow = this.createHTMLElement('tr');
	this.columnList = [];
	this.addHeaderCells(headerRow, rowPrototype);
	var tableHeader = this.createHTMLElement('thead');
	tableHeader.appendChild(headerRow);
	this.header = tableHeader;
	this.headerRow = headerRow;
	this.viewNode.appendChild(tableHeader);
};
tersus.Table2.prototype.createFooter = function createHeader()
{
	if ( this.getElement('<Footer>') == null) 
		return;
	this.viewNode.appendChild(this.createHTMLElement('tfoot'));
};

tersus.Table2.prototype.removeChildViewNode = function removeChildViewNode(child)
{
	var c = child.viewNode;
	var row = null;
	if (c.tagName == 'TR' )
		row = c;
	else if (c.parentNode && c.parentNode.tagName == 'TR')
		row = c.parentNode;
	else if (c.parentNode && c.parentNode.parentNode && c.parentNode.parentNode.tagName== 'TR')
		row = c.parentNode.parentNode;
	if (row && row.parentNode)
		row.parentNode.removeChild(row);
};

tersus.Table2.prototype.applyColOrder = function (row)
{
	$(row).data('tracked',false);
};

tersus.Table2.prototype.appendChildViewNode = function appendChildViewNode(child, childElement)
{
	var element = childElement?childElement:child.element;
	var target = 'tbody';
	if (element.role == '<Header>')
		target='thead';
	if (element.role == '<Footer>')
		target='tfoot';
	var row = null;
	if (child.viewNode.tagName == 'TR')
	{
		row = child.viewNode;
	}
	else
	{
		var row = this.createHTMLElement('TR');
		if (child.viewNode.tagName == 'TH' || child.viewNode.tagName == 'TD')
			row.appendChild(child.viewNode);
		else
		{
			var cell = this.createHTMLChildElement(row,'TD');
			cell.appendChild(child.viewNode);
		}
		row.setAttribute('display_order', child.viewNode.getAttribute('display_order'));
	}
	/*
// Special logic for suppressing column hiding.  Probably not needed because columns are hidden only when number of cells match header cells
    if (element.prop('suppressColumnHiding'))
    {
	$(row).data('datagrid.nohide',true);
    }
	 */

	/* There may be a bug in handling display order in the case of a table with multiple row elements. This may or many not be an important use case and may or may not be a new bug */
	if (this.gridNode)
		$(this.gridNode).datagrid('appendRow',target,row);
	else
	{
		// Before datagrid is initialized - add via regular API
		var targetNode = $(this.viewNode).children(target)[0];
		if (targetNode)
			DisplayNode.appendChildNode(targetNode,row); 
	}

};

tersus.Table2.prototype['get<Selected Row>'] = function ()
{
	if (this.selectedRow)
		return this.selectedRow;
	else
		return null;
};
tersus.Table2.prototype['set<Selected Row>'] = tersus.Table2.prototype.select = function (row)
{
	var selectedClassName = 'selected';
	if (this.selectedRow)
	{
		this.selectedRow.removeStyleClass(selectedClassName);
	}
	this.selectedRow = row;
	if (row && row.viewNode)
	{
		row.addStyleClass(selectedClassName);
	}
};
tersus.Table2.prototype['remove<Selected Row>'] = function ()
{
	var selectedClassName = 'selected';
	if (this.selectedRow)
	{
		this.selectedRow.removeStyleClass(selectedClassName);
		this.selectedRow = null;
	}
};
tersus.Table2.prototype.select.requiresNodes = true;
tersus.Table2.prototype.outputColList = function(v, s)
{
	var self=this;
	var colList = $.map(v,function(a,i){
		var suffix = s && s[i];
		var columnName = self.columnNames[a];
		if (tersus.useSQLQuotedIdentifiers)
			columnName = '"'+columnName+'"'; 
		return suffix ? columnName+ ' ' + suffix  : columnName;}).join(',');
	return (colList ? colList : null);
};
tersus.Table2.prototype.parseColList = function(str)
{
	if (str.indexOf('"')>=0)
		re = / *"([^"]+)"( +([a-z]+))? *(,|$)/gi
			else 
				re = / *([^, ]+)( +([a-z]+))? *(,|$)/gi;
			var out=[];
			while (result = re.exec(str))
			{
				var columnName = result[1];
				if (! tersus.useSQLQuotedIdentifiers)
					columnName = columnName.toLowerCase();
				var found=false;
				for (var j=0;j<this.columnNames.length;j++)
				{
					if (this.columnNames[j] == columnName)
					{
						out.push({colIndex:j,suffix:result[3]});
						found = true;
					}
				}
				if (!found)
					throw 'Unknown column:'+result[1];
			}
			return out;
};

tersus.Table2.prototype.updateSortOrder = function()
{
	/* Convert a vector of 'up'/'down'/'' in visual order to an SQL-compatible "order-by" clause using column names */
	var sort =  $(this.gridNode).datagrid('sort');
	var v=[]; /* column indexes */
	var s=[]; /* suffixes */
	var p =  $(this.gridNode).datagrid('permutation');
	$.each(sort, function(i,dir) {
		if (dir)
		{
			v.push(p[i]);
			s.push(dir == 'up' ?  'ASC': 'DESC');
		}
	});
	this.sortOrder = this.outputColList(v,s);
};
tersus.Table2.prototype.updateVisibleColumns = function()
{
	var visible =  $(this.gridNode).datagrid('visibility');
	/* Output current permutation after filtering out hidden columns */
	this.visibleColumns =  this.outputColList( $.map($(this.gridNode).datagrid('permutation'),function(a,i) {
		if (visible[a])
			return a;
	}));
};
tersus.Table2.prototype.updateColumnState = function()
{
	this.updateSortOrder();
	this.updateVisibleColumns();
};
tersus.Table2.prototype['get<Sort Order>'] = tersus.Table2.prototype.getSortOrder = function()
{
	return this.pendingSortOrder || this.sortOrder;
};
tersus.Table2.prototype['set<Sort Order>'] = function (sort_order)
{
	if (this.gridPending)
		this.pendingSortOrder = sort_order;
	else
		this.setSortOrder(sort_order);
};
tersus.Table2.prototype.setSortOrder = function (sort_order)
{
	var l = this.parseColList(sort_order);
	/* step one: ensure compatibility with permutation */
	var p =  $(this.gridNode).datagrid('permutation');
	var prev;
	var sortLogical = $.map(p, function(){return ''});
	var permChanged = false;
	$.each(l, function(i,spec)
			{
		sortLogical[spec.colIndex] = (spec.suffix && spec.suffix.toLowerCase().charAt(0)=='d') ? 'down' : 'up';
		if (prev)
		{
			var iprev, icurr;
			$.each(p, function(i,a) {
				if (a==spec.colIndex)
					icurr=i;
				if (a==prev.colIndex)
					iprev=i;
			});
			if (icurr < iprev)
			{
				p.splice(icurr,1);/* Remove from current position  */
				p.splice(iprev,0,spec.colIndex); /* Add after  previous element's position */
				permChanged=true;
			}

		}
		prev = spec;
			});
	var sortVisible = $.map(p,function(col,i){
		return sortLogical[col];});

	if (permChanged)
		$(this.gridNode).datagrid('permutation',p);
	$(this.gridNode).datagrid('sort',sortVisible);
	this.updateColumnState();
};
tersus.Table2.prototype['remove<Sort Order>'] = function ()
{
	this['set<Sort Order>']('');
};
tersus.Table2.prototype['set<Hidden Columns>'] = function(hidden_cols)
{
	if (this.gridPending)
		this.pending_hidden_cols = hidden_cols;
	else
		this.setHiddenColumns(hidden_cols);
};
tersus.Table2.prototype.setHiddenColumns = function(hidden_cols)
{
	var hidden = this.parseColList(hidden_cols);
	var v = $.map(this.columnNames,function(){return 1;}); // vector of ones
	$.each(hidden, function(i,a) {
		v[a.colIndex]=0;
	});
	$(this.gridNode).datagrid('visibility',v);
	this.updateColumnState();
};

tersus.Table2.prototype['remove<Hidden Columns>'] = function()
{
	this['set<Hidden Columns>']('');
};

tersus.Table2.prototype['get<Hidden Columns>'] =  function()
{
	if (this.pending_hidden_cols)
		return this.pending_hidden_cols;
	var visibility =  $(this.gridNode).datagrid('visibility');
	var v = $.map(visibility, function(a,i) { if (a==0) return i;});
	return this.outputColList(v);
};
tersus.Table2.prototype['get<All Columns>'] =  function()
{
	return this.columnNames.join(',');
};


tersus.Table2.prototype['get<Visible Columns>'] =  function()
{
	return this.pendingVisibleColumns || this.visibleColumns;
};
tersus.Table2.prototype['set<Visible Columns>'] = function(visible_cols)
{
	if (this.gridPending)
		this.pendingVisibleColumns = visible_cols;
	else
		this.setVisibleColumns(visible_cols);
};
tersus.Table2.prototype.setVisibleColumns = function(visible_cols)
{
	var cols = this.parseColList(visible_cols).map(function(a,i){return a.colIndex;});
	var v = $.map(this.columnNames,function(){return 0;}); // vector of zeros
	$.each(cols, function(i,a) {
		v[a]=1;
	});
	var p = cols.slice(0);
	var s = new Set(cols);
	for (var i=0;i<v.length;i++)
	{
		if (! s.contains(i))
			p.push(i);
	}
	$(this.gridNode).datagrid('visibility',v);
	$(this.gridNode).datagrid('permutation',p);
	this.updateColumnState();
};
tersus.Table2.prototype['remove<Visible Columns>'] = function()
{
	/* Resets <Visible Columns> - clears visibility and resets permutation */
	var v = $.map(this.columnNames,function(){return 1;}); // vector of ones
	var p = $.map(this.columnNames, function(a,i) {return i;}); // Identity permutation

	$(this.gridNode).datagrid('visibility',v);
	$(this.gridNode).datagrid('permutation',p);
	this.updateColumnState();
};
tersus.Table2.prototype.handleColChange = function()
{
	var prevSortOrder = this.sortOrder;
	var prevVisibleColumns = this.visibleColumns;
	this.updateColumnState();
	if (prevVisibleColumns != this.visibleColumns)
		tersus.invokeAction('<On Move Column>',null, null,this,true);
	if (prevSortOrder != this.sortOrder)
		tersus.invokeAction('<On Sort>', null, null, this, true);
};
tersus.Table2.prototype.setStyleClass = function(c)
{
	DisplayNode.prototype.setStyleClass.call(this,c);
	if (this.gridNode)
		$(this.gridNode).datagrid('setTableClass',this.styleClass);
};
tersus.Table2.prototype.onResize = function()
{
	if (this.gridNode)
	{
		var self = this;
		$(this.gridNode).datagrid('adjustSize',function(){self.onResizeChildren();});
	}
};

// file: TakePicture.js
tersus.SAMPLE_IMAGE='data:image/png;base64,\niVBORw0KGgoAAAANSUhEUgAAAGQAAABkCAIAAAD/gAIDAAAAAXNSR0IArs4c6QAAANNJREFUeNrt\n3NEJgDAMQEErruGgOoAO6iB1hUoJsfTevx8eERpBS611UVsrAliwYMGCBQsBLFiwYMGChQAWLFiw\nYMFC0N7Wc/G5HyPe8/XcJstjCAsWLMGCBQvWjCf4oINyZ3F7hcmCBQsWLFiCBQsWLOtO8FKStUiZ\nLFiwYMGCJViwYMGCBUuwYMGCBQuWYH0o7R181nt0kwULFixYggUL1lSH0kG/czVZsGDBggVLsGDB\n+nPF/+BNFixYsGDBQgALFixYsGAhgAULFixYsBDACukFZWESy0+VwUsAAAAASUVORK5CYII=\n';
tersus.newAction('TakePicture', function()
{
	var dataURLExit = this.getExit('<Data URL>');
	var fileURIExit = this.getExit('<File URI>');
	var imgQuality=70;
	var q=this.getLeafChild('<Quality>');
	if (q)
	{
		q = Math.round(q);
		
		if (q>0 && q<=100)
			imgQuality = q;
	}
	
	var w = this.getLeafChild('<Width>');
	var h = this.getLeafChild('<Height>');
	
	var dest = dataURLExit ?  Camera.DestinationType.DATA_URL : Camera.DestinationType.FILE_URI;
	
	/*if (tersus.simulateCamera != false)
	{
		if(window.confirm('No camera available.  Would you like to use a sample image?'))
			this.chargeLeafExit('<Data URL>',tersus.SAMPLE_IMAGE);
	}
	else */if (navigator.camera && navigator.camera.getPicture)
	{
		var node = this;
		this.pause();
		var success = function(data)
		{
			console.log('Got Image '+data);			
			if (dataURLExit)
				node.chargeLeafExit(dataURLExit,"data:image/jpeg;base64," + data.replace(/\n/g,''));
			else
			{
				node.chargeLeafExit(fileURIExit, data);
			}
			node.continueExecution();
			console.log('Got Image (done)');			
			
		}
		var error = function(message)
		{
			if (message == 'no image selected' || message == 'Camera cancelled.')
			{
				node.chargeEmptyExit('<None>');
			}
			else
			{
				console.log('Get Picture: Error: '+message);			
				modelExecutionError("Failed to take picture: "+message,node);
			}
			node.continueExecution();
		};
		
		var p = {quality:imgQuality, destinationType:dest};
		
		if (w)
			p.targetWidth=w+0;
		if (h)
			p.targetHeight=h+0;

		console.log('Calling getPicture w='+p.targetWidth+' h='+p.targetHeight +" quality="+p.quality);			
		navigator.camera.getPicture(success, error, p); 
		
	}
	else
		modelExecutionError('No camera available.');		
});

// file: TestCase.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.TestCase = ActionNode;
// file: TestSuite.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.TestSuite = ActionNode;

// file: TextArea.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.TextArea = function tersus_TextArea() {};
tersus.TextArea.prototype = new tersus.GenericField();
tersus.TextArea.prototype.constructor = tersus.TextArea;
tersus.TextArea.prototype.inputFieldTag = 'textarea';
TextArea=tersus.TextArea; // compatibility with very old models


// file: TimeDifference.js
/*********************************************************************************************************
 * Copyright (c) 2003-2010 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
tersus.newAction('TimeDifference', function()
{
	var from = this.getChild('<From>');
	var fromDate = tersus.getDate(from);
	var to = this.getChild('<To>');
	var toDate = tersus.getDate(to);
	
	var differenceMilliseconds = toDate - fromDate;
	var differenceSeconds = differenceMilliseconds/1000.0;
    var differneceMinutes = differenceSeconds/60.0;
    var differenceHours = differneceMinutes/60.0;
    var differenceDays = differenceHours/24.0;
    
    this.chargeLeafExit('<Days>', differenceDays);	
	this.chargeLeafExit('<Hours>', differenceHours);
	this.chargeLeafExit('<Minutes>', differneceMinutes);
	this.chargeLeafExit('<Seconds>', differenceSeconds);
	this.chargeLeafExit('<Milliseconds>', differenceMilliseconds);
});
// file: Timer.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Timer = function tersus_Timer() {};
tersus.Timer.prototype = new ActionNode();
tersus.Timer.prototype.constructor = tersus.Timer;
tersus.Timer.prototype.start = function()
{
	if (!this.subFlowList || this.subFlowList.length == 0)
	{
		modelError("Missing activity in Timer "+this.modelId);
		return;
	}
	if (this.subFlowList.length > 1)
	{
		modelError("Ambiguous activity in Timer "+this.modelId + " (more than one sub-process)");
		return;
	}
	var activityElement = this.subFlowList[0];
	var interval = this.getLeafChild('<Interval>');
	if (!interval)
		modelError("Missing <Interval> for Timer "+this.modelId);
	var timer = this;
	var invoker = function()
	{
		if (timer.busy)
			return;
		timer.busy = true;
		var process = new BackgroundProcess(timer, activityElement);
		if (timer.links)
		{
			for (var i = 0; i < timer.links.length; i++)
			{
				var link = timer.links[i];
				if (link.source.segments.length != 1 || link.target.segments.length != 2)
				{
					modelError("Invalid link "+link.role + " in Timer " + this.modelId);
					return;
				}	
				var outerTriggerName = link.source.segments[0];
				var innerTriggerName = link.target.segments[1];
				var value = timer.getChild(outerTriggerName);
				if (value)
					process.setTriggerValue(innerTriggerName, value);
			}
		}
		process.whenDone(function()
		{
			timer.busy = false;
		});
		process.start();
		
	};
	var timerId = window.setInterval(invoker, interval);
	if (tlog) tlog("Set timer "+timerId + " [" + this.modelId+"]");
	this.chargeLeafExit('<Timer Id>', timerId);
};

// file: Today.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Today() {};
Today.prototype = new ActionNode();
Today.prototype.constructor = Today();

Today.prototype.start = function()
{
	var now = new Date();
	var d  = now.getDate();
	var m = now.getMonth()+1;
	var y  = now.getFullYear();
	var today = createDate(y,m,d);
	this.chargeLeafExit('<Today>',today);
};

// file: Transition.js
/*********************************************************************************************************
 * Copyright (c) 2003-2011 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/

tersus.newAction('Transition',function()
{	
	var element = this.getChild('<Element>');
	element = element.currentDialog || element;
	var animationClass = this.getLeafChild('<Animation Class>');
	var activeClass='ter-active';
	var $element =  $(element.wrapperNode || element.viewNode);
	var $prev = $element.parent().children('.'+activeClass);
	
	this.pause();
	var self=this;
	tersus.transition($prev, $element, activeClass, animationClass, function(){
		self.continueExecution();
	});
	/*
		onResize must be called after the transition is invoked, because size calculations don't work for hidden elements
	*/
	
	element.onResize(); 
	
});

// file: Transition2.js
/*******************************************************************************
 * Copyright (c) 2003-2011 Tersus Software Ltd. , All rights reserved.
 * 
 * This program is made available under the terms of the GNU Lesser General
 * Public License, version 2.1, which is part of this distribution and is
 * available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 ******************************************************************************/

tersus.newAction('Transition2', function() {
    var element = this.getChild('<Element>');
    element = element.currentDialog || element;
    var transitionClass = this.getLeafChild('<Transition>');
    var activeClass = 'active';
    var $element = $(element.wrapperNode || element.viewNode);
    var $element = $element.data('replaced-by')|| $element;
    var $prev = $element.parent().children('.' + activeClass);

    this.pause();
    var self = this;
    tersus.transition2($prev, $element, activeClass, transitionClass+' out', transitionClass+' in', 'end',
            function() {
                self.continueExecution();
            });
    /*
     * onResize must be called after the transition is invoked, because size
     * calculations don't work for hidden elements
     */

    element.onResize();

});
// file: Tree.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function Tree() { this.selectedItem = null};
Tree.prototype = new DisplayNode();
Tree.prototype.constructor = Tree;
Tree.prototype.defaultTag = 'div';
Tree.prototype.start = function startTree()
{
	this.root = new TreeItem();
	this.root.attach(this,null);
	this.setStatus(FlowStatus.WAITING_FOR_INPUT);
};
Tree.prototype.refresh = function()
{
	if (this.root.childItems)
	{
		for (var i=0; i< this.root.childItems.length; i++)
			this.root.childItems[i].onDelete();
	}
	this.childItems = null;
	this.root.loadChildren();
};
Tree.prototype.findById = function (id)
{
	if (this.nodeId == id)
		return this;
	else if (this.root)
		return this.root.findById(id);
	else
		return null;
};
Tree.prototype['get<Selected Item>'] = function()
{
 	if (this.selectedItem)
 		return this.selectedItem;
 	else
 		return null;
};
Tree.prototype.scanChildren = function(filter, alreadyScanned, outputList)
{
	if (filter.match(this))
		outputList.push(this);
	if (this.root)
		this.root.scanChildren(filter, alreadyScanned,outputList);		
};
// file: TreeItem.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function TreeItem() {};
TreeItem.prototype = new DataValue();
TreeItem.prototype.constructor = TreeItem;
TreeItem.prototype.getText = function getText() 
{
	var textNode = this.getChild('<Text>');
	if (textNode)
		return textNode.leafValue;
	else
		return '';
};
TreeItem.prototype.getNodeId = DisplayNode.prototype.getNodeId;
TreeItem.prototype.getImage = function getImage()
{
	var imageNode = this.getChild('<Image Path>');
	if (imageNode)
		return imageNode.leafValue;
	else
		return null;
};

TreeItem.prototype.isExpandable = function()
{
	if (this.childItems)
		return this.childItems.length > 0;
	var element = this.getElement('<Expandable>');
	if (! element)
		return true; // backward compatability
	var expandable = element.getChild(this); 
	return (expandable && expandable.leafValue);
}


TreeItem.COLLAPSED = 'Collapsed';
TreeItem.EXPANDED = 'Expanded';
TreeItem.ATOMIC = 'Atomic';
TreeItem.select = function()
{
	var item = DisplayNode.findNodeForDocumentNode(this);
	if (item)
		item.select();
};
TreeItem.toggle = function()
{
	var item = DisplayNode.findNodeForDocumentNode(this);
	if (item)
		item.toggle();
};
TreeItem.openItem = function()
{
	var treeItem = DisplayNode.findNodeForDocumentNode(this);
	if (treeItem)
		treeItem.openItem();
};
TreeItem.prototype.attach = function attach(tree,parentItem)
{
	this.tree = tree;
	var doc = tree.currentWindow.document;
	this.isRoot = ! parentItem;	
	if (parentItem)
	{
		this.parentItem = parentItem;
		this.viewNode = this.tree.createHTMLElement('div','tree_item');
		this.headerNode = this.tree.createHTMLChildElement(this.viewNode,'span','tree_item_header');
		var thisItem = this;
		this.image = this.tree.createHTMLChildElement(this.headerNode, 'img', 'tree_item_collapsed');
		this.image.src = 'images/spacer.gif';
		this.icon = this.tree.createHTMLChildElement(this.headerNode, 'img', 'tree_item_icon');
		this.icon.style.backgroundImage = 'url('+encodeURI(this.getImage())+')';
		this.icon.src = 'images/spacer.gif';
		this.headerText = this.tree.createHTMLChildElement(this.headerNode, 'span', 'tree_item_header_text');
		this.headerText.innerHTML = tersus.escapeHTML(this.getText());
		var id = this.getNodeId();
		this.icon.id = id;
		this.headerText.id = id;
		this.icon.onclick = TreeItem.select;
		this.headerText.onclick= TreeItem.select;
		this.icon.ondblclick = TreeItem.openItem;
		this.headerText.ondblclick = TreeItem.openItem;
		this.resetExpandable();
		parentItem.getOrCreateContentNode().appendChild(this.viewNode);
	}
	else
	{
		this.viewNode = this.contentNode = doc.createElement('div');
		this.expand();
		
		tree.appendChildViewNode(this);
	}
};
TreeItem.prototype.getOrCreateContentNode = function()
{
	if (!this.contentNode)
		this.contentNode = this.tree.createHTMLChildElement(this.viewNode,'div', 'tree_item_content');
	return this.contentNode;
		
};
TreeItem.prototype.resetExpandable = function()
{
	this.image.onclick = null;
	if (this.isExpandable())
	{
		this.image.id = this.getNodeId();
		this.collapse();
		this.image.onclick = TreeItem.toggle;
	}
	else
		this.atomic();
};
TreeItem.prototype.findById = function (id)
{
	if (this.nodeId == id)
		return this;
	if (this.childItems)
	{
		for (var i=0; i<this.childItems.length; i++)
		{
			var child = this.childItems[i];
			if (child)
			{
				var node = child.findById(id);
				if (node)
					return node;
			}
		}
	}
	return null;
};
TreeItem.prototype.loadChildren = function ()
{
	var item = this;
	var loaderElement = this.tree.getElement('<Get Children>');
	var process = new BackgroundProcess(this.tree, loaderElement);
	if (! this.isRoot) // The root item is not a 'real' item (as defined in the model)
		process.setTriggerValue('<Parent>', this);
	process.whenDone(function()
	{
		item.childItems = process.getExitValues('<Children>');
		if (item.childItems.length >0)
		{
			for (var i=0; i<item.childItems.length; i++)
			{
				var child = item.childItems[i];
				child.attach(item.tree,item);
			}
			item.state = TreeItem.EXPANDED;
		
			if (item.headerNode)
			{
				item.getOrCreateContentNode().style.display = 'block';
			}
			if (item.image)
				item.image.className='tree_item_expanded';
		}
		else
		{
			item.atomic();
		}
		
		if (item.onExpand)
			item.onExpand();
	});
	process.start();

};
TreeItem.prototype.expand  = function expand()
{
		if (! this.childItems)
		{
			this.loadChildren();
		}
		else
		{
			this.state = TreeItem.EXPANDED;
			if (this.headerNode)
			{
				this.getOrCreateContentNode().style.display = 'block';
			}
			if (this.image)
				this.image.className='tree_item_expanded';
			if (this.onExpand)
				this.onExpand();
		}
};
TreeItem.prototype.atomic = function()
{
		this.state = TreeItem.ATOMIC;
		if (this.image)
			this.image.className='tree_item_atomic';

};

TreeItem.prototype.collapse = function collapse()
{
		this.state = TreeItem.COLLAPSED;
		if (this.image)
			this.image.className='tree_item_collapsed';
		if (this.contentNode)
			this.contentNode.style.display='none';
		if (this.childItems)
		{
			for (var i=0; i< this.childItems.length; i++)
				this.childItems[i].onDelete();
		}
		this.childItems = null;

};
TreeItem.prototype.toggle = function toggle()
{
	if (this.state == TreeItem.COLLAPSED)
		this.expand();
	else
		this.collapse();
};

TreeItem.prototype.select = function select()
{
	if (!this.selected)
	{
		if (this.tree.selectedItem)
			this.tree.selectedItem.deselect();
		this.tree.selectedItem = this;
		this.headerText.className = 'tree_item_header_text_selected';
		this.selected = true;
	};
};
TreeItem.prototype.deselect = function deselect()
{
	this.headerText.className = 'tree_item_header_text';
	this.selected = false;
};
TreeItem.prototype.openItem = function openItem()
{
	var openSubFlow = this.tree.getEventHandler(Events.OPEN);
	if (openSubFlow)
	{
		var child = openSubFlow.createChild(this.tree);
		child.setChild('<Selected Item>', this, Operation.REPLACE);
		child.readyToStart();
		window.rootDisplayNode.doResume();
	};
		
};
TreeItem.prototype.scanChildren = function(filter, alreadyScanned,outputList)
{
	var id = this.getNodeId();
	if (alreadyScanned[id])
		return;
	alreadyScanned[id]=true;
	if (filter.match(this))
		outputList.push(this);
	if (this.childItems)
	{
		for (var i=0; i< this.childItems.length; i++)
			this.childItems[i].scanChildren(filter, alreadyScanned,outputList);		
	}
};

TreeItem.prototype.refresh = function()
{
	this.collapse();
	this.loadChildren();
	this.resetExpandable();
	
};
/* Returns true if this item and its ancestors are all expanded */
TreeItem.prototype.isExpandedAndVisible = function()
{
	if (this.state != TreeItem.EXPANDED)
		return false;
	else if (! this.parentItem)
		return true;
	else
		return this.parentItem.isExpandedAndVisible();
}
TreeItem.prototype.onDelete = function ()
{
	if (this.parentItem)
	{
		this.parentItem.contentNode.removeChild(this.viewNode);
	}
};

// file: Trim.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('Trim', function()
{
	var text = this.getLeafChild('<Text>');
    if (text != null)
    {
    	var m = text.replace(/^\s*([\S\s]*?)\s*$/, '$1');
    	if (m && m.length >= 1)
    		this.chargeLeafExit('<Trimmed Text>', m);
	}
});


// file: UIButton.js
(function( $, undefined ) {
    tersus.UIWidget('UIButton','UILabel', {
        defaultTag:'button'
        ,inputType:'button'
        /* Should the whole <Disable> mechanism go to the base class? */
        ,onClick:function(domNode, callback){
            if (this.disabled) // Used to allow disabling other elements
                return;
            DisplayNode.prototype.onClick.call(this, domNode, callback);
        }
        ,'get<Disabled>':function () {return this.disabled;}
        ,'set<Disabled>':function (disabled)
        {
                this.disabled = disabled;
                $(this.viewNode).attr('disabled',disabled);
        }
    });
})(jQuery);
// file: UIButtonGroup.js
tersus.UIWidget('UITextDisplay','UIBase',{
    defaultTag:'span'
});

// file: UICheckBox.js
tersus.UIWidget('UICheckBox','UIBase',{
    defaultTag:'input'
    ,inputType:'checkbox'
});

// file: UIDateAndTimeDisplay.js
tersus.UIWidget('UIDateAndTimeDisplay','UIBase',{
    defaultTag:'span'
    ,onload:function()
    {
        tersus.HTMLTag.prototype.onload.call(this);
        this.optimizeFormatString = false;
    }
});

// file: UIDateDisplay.js
tersus.UIWidget('UIDateDisplay','UIBase',{
    defaultTag:'span'
    ,onload:function()
    {
        tersus.HTMLTag.prototype.onload.call(this);
        this.optimizeFormatString = false;
    }
});

// file: UIDateField.js
(function( $, undefined ) {
    tersus.UIWidget('UIDateField','UIField',{
	convertFormat:function(format)
	{
            //Year: yyyy->yy, yy->y
            format = format.replace(/yyyy/g,"YY").replace(/yy/g,'Y').replace(/Y/g,'y');
            //Month: MMMM -> MM (Full Name), MMM -> M (short Name), MM->mm (padded number), M->m number
            format=format.replace(/MMMM/g,"&&&&").replace(/MMM/g,"&&&").replace(/M/g,"m").replace(/[&]/g,"M");
            //Day of month: EEEE->DD, EEE/EE/E->D
            format=format.replace(/EEEE/g,"DD").replace(/E+/g,"D");
            return format;
	}
	
	,attachWidget:function()
	{
            //TODO clean this up
            var $v = $(this.viewNode);
            var self=this;
	    if (this.inputField)
	    {
		if (window.SpinningWheel)
		{
		    $v.on('focus', function(event)
			  {
			      if (self.computedReadOnly())
				  return;
                              var date = self.getFieldValue() && self.getFieldValue().leafValue;
                              var callback = function(year, month, day)
                              {
				  var date = createDate(year, month, day);                            
				  self.setLeafChild('<Value>',date, Operation.REPLACE);
                              };
                              this.blur();
                              PopupCalendar.prototype.openDatePicker(date, callback);
			  });
		}
		else // use jQuery UI Datepicker
		{
		    $v.datepicker({
			dateFormat:this.convertFormat(DATE_FORMAT),
			onSelect:function(text, inst) 
			{
			    if (self.inputField) 
			    {
				var $input = $(self.inputField);
				$input.trigger('change');
				$input.focus();
				/*
				  // focus on next focusable element
				var $a = $(':focusable');
				setTimeout(function(){$a.eq($a.index($input)+1).focus()},50);
				*/
				
			    }
			}
		    });
		    if (this.computedReadOnly())
			$v.datepicker('disable');
		}
	    }
	}
	,detachWidget:function()
	{
	    
	    if (this.inputField && window.SpinningWheel)
		$(this.viewNode).datepicker('destroy');
	    
	}
	,readOnlyChanged:function(ro)
	{
	    if (!window.SpinningWheel)
	    {
		if (this.computedReadOnly())
		    $(this.viewNode).datepicker('disable');
		else
		    $(this.viewNode).datepicker('enable');
	    }

	}

    });})(jQuery);

// file: UIFileField.js
(function( $, undefined ) {
    function getFile()
    {
        if (!this.fileValue && this.inputField)
        {
            //Create a File instance based on the input field's selection
            var element = this.getElement('<Value>');
            if (element)
            {
                    this.fileValue = element.createChildInstance();
                    this.fileValue.inputFieldDisplayNode = this; //Legacy API needed for IE8.0, IE9.0
                    var files = this.inputField.files;
                    if (files && files.length == 1)
                        this.fileValue.file = files[0];
            }
        }
        return this.fileValue;
    };
tersus.UIWidget('UIFileField','UIField',{
    inputType:'file'
    ,fileValue:null
    ,'get<Value>':getFile
    ,getFieldValue:getFile
    ,_onChange:function(){this.fileValue=null;}
});
})(jQuery);
// file: UIImage.js
tersus.UIWidget('UIImage','UIBase',{
    defaultTag:'img'
});
// file: UIModalDialog.js
tersus.UIWidget('UIModalDialog','UIDialog', {
    defaultOptions:'cover backdrop backdrop-dismiss'
    ,open:function()
    {
        var $dlg=$(this.wrapperNode);
        $dlg[0].offsetWidth;
        $dlg.addClass('in');
    }
    ,close:function()
    {
        var $dlg=$(this.wrapperNode);
        if ($.support.transition)
        {
            $dlg.one($.support.transition.end, function(){$dlg.remove();});
            $dlg.removeClass('in');
        }
        else
            $dlg.remove();
        this.removeBackdrop();
    }
    ,refresh:function()
    {
	var wasActive = $(this.wrapperNode).hasClass('in');
	tersus.UIDialog.prototype.refresh.call(this);
	if (wasActive)
	    $(this.wrapperNode).addClass('in');

    }
});

// file: UINumberDisplay.js
tersus.UIWidget('UINumberDisplay','UIBase',{
    defaultTag:'span'
   ,onload:function()
    {
        tersus.HTMLTag.prototype.onload.call(this);
        this.optimizeFormatString = false;
    }

});

// file: UINumberField.js
(function( $, undefined ) {
tersus.UIWidget('UINumberField','UIField',{
    //Initially no special behavior for number field
    });
})(jQuery);
// file: UIPageDialog.js
tersus.UIWidget('UIPageDialog','UIDialog', {
    defaultOptions:'replace'
    ,defaultContainer:'.mobile-view,.tablet-view,.desktop-view'
    ,transitionClass:'slide left'
});

// file: UIPasswordField.js
(function( $, undefined ) {
tersus.UIWidget('UIPasswordField','UIField',{
    inputType:'password'
    });
})(jQuery);
// file: UIRadioButton.js
(function($, undefined) {
    tersus.UIWidget('UIRadioButton', 'UIBase', {
        defaultTag : 'input',
        inputType : 'radio',
        isRadioButton : true,
        value : null,
        group : null,
        setGroup : function() {
            var n = this.parent;
            while (n && !n.isRadioButtonGroup)
                n = n.parent;
            this.group = n;
        },
        setChecked : function(bool) {
            $(this.viewNode).attr('checked', bool);
        },
        attach : function() {
            this.setGroup();
            if (this.group)
                $(this.viewNode).attr('name', this.group.getGroupName());
            var self = this;
            $(this.viewNode).on('change', function() {
                if (self.group && $(self.viewNode).attr('checked'))
                    self.group.selectedButton = self;
            });
        },
        'set<Value>' : setter(function(value) {
            this.value = value;
        }, true),
        getValue : function() {
            return this.value;
        },
        'get<Value>' : function() {
            return this.getValue();
        }

    });
})(jQuery);

// file: UIRadioButtonGroup.js
(function($, undefined) {
    tersus.UIWidget('UIRadioButtonGroup', 'UIBase', {
        defaultTag : 'div',
        isRadioButtonGroup : true,
        groupName : null,
        selectedButton : null,
        getGroupName : function() {
            if (!this.groupName)
                this.groupName = '' + this.getNodeId();
            return this.groupName;
        },
        
        setSelectedValue: function(value)
        {
                var found = false;
                var self = this;
                var op = function(node)
                {
                        if (node.isRadioButton &&  compareValues(node.getValue(), value)  )
                        {       
                                node.setChecked(true);
                                self.selectedButton=node;
                                found = true;
                                return true; // stop traversal
                        }
                };
                tersus.traverseHierarchy(this, DisplayNode.displayChildrenIterator, op);
        },

        'get<Value>':function()
        {
                if (! this.selectedButton)
                        return null;
                else
                        return this.selectedButton.getValue();
        },
        
        'set<Value>' : setter(function(value){
            this.setSelectedValue(value);
        },true),
        
        'remove<Value>': function()
        {
            if (this.selectedButton)
            {
                this.selectedButton.setChecked(false);
                this.selectedButton = null;
            }
        }

    });
})(jQuery);
// file: UISelectionField.js
(function($, undefined) {

    var setter = tersus.setter;

    tersus.UIWidget('UISelectionField', 'UIBase', {
        defaultTag : 'select',
        attach : function() {
            this.setSelectedIndex(this.findIndex(this.value));
        },
        'set<Value>' : setter(function(value) {
            this.value = value;
            this.setSelectedIndex(this.findIndex(this.value));
        }, true),
        'remove<Value>' : function() {
            if (this.options && this.options.length > 0)
                this.value = this.options[0];
            this.setSelectedIndex(0);
        },
        getValue : function() {
            var selectedIndex;
            // TODO: check behavior on IE. The scenario is probably getting the value immediately after setting it
            /*
             * Old code: if (this.tmpSelectedIndex != null) // In IE, the selected index is updated asynchronously, so we use tmpSelectedIndex if it is set
             * selectedIndex = this.tmpSelectedIndex; else
             */
            var selectedIndex = this.getSelectedIndex();
            if (selectedIndex < 0)
                return null;
            return this.options[selectedIndex];
        },
        'get<Value>' : function() {
            return this.getValue();
        },
        findIndex : function(value) {
            if (this.options)
                for ( var i = 0; i < this.options.length; i++) {
                    var option = this.options[i];
                    if (compareValues(option, value))
                        return i;
                }
            return -1;
        },
        getSelectedIndex : function() {
            var index = this.viewNode && this.viewNode.selectedIndex;
            return index >= 0 ? index : -1; // Converts null to -1
        },
        setSelectedIndex : function(index) {
            if (this.viewNode)
                this.viewNode.selectedIndex = Math.max(index, 0);
        },
        'get<Placeholder Text>' : function() {
            return this.emptyOptionText;
        },
        'set<Placeholder Text>' : function(text) {
            var isNew = this.emptyOptionText == null;
            this.emptyOptionText = text;
            if (isNew) {
                if (this.options)
                    this.options.splice(0, 0, null); // add null to beginning of list
                else
                    this.options = [ null ];
            }
            if (this.viewNode) {
                if (isNew)
                    $(this.viewNode).prepend($("<option>").text(this.translate(this.getOptionText(null))));
                else
                    $(this.viewNode).find('option').first().text(this.translate(this.getOptionText(null)));
                if (this.value == null)
                    this.setSelectedIndex(0);
            }
        },
        'remove<Placeholder Text>' : function() {
            if (this.emptyOptionText != null) {
                this.emptyOptionText = null;
                this.options.splice(0, 1); // remove first
                if (this.viewNode) {
                    $(this.viewNode).find('option').first().remove();
                }
            }

        },
        'remove<Options>' : function() {
            this.options = this.emptyOptionText == null ? [] : [ null ];
            if (this.viewNode) {
                var self = this;
                $(this.viewNode).find('option').filter(function(i) {
                    return i > 0 || null == self.emptyOptionText;
                }).remove();
            }
        },
        'add<Options>' : setter(function(option) {
            if (!this.options)
                this.options = [];
            this.options.push(option);
            if (this.viewNode) {
                $(this.viewNode).append($("<option>").text(this.translate(this.getOptionText(option))).val(this.options.length));
                if (this.value != null && compareValues(this.value, option) || this.options.length == 1) {
                    this.setSelectedIndex(this.options.length - 1);
                }
            }
        }, true),

        addHTMLTagContent : function(htmlV, displayChildren, prep) // Need to add <option> elements, which are not part of the Tersus display hierarchy
        {
            if (this.options) {
                for ( var i = 0; i < this.options.length; i++) {
                    htmlV.push("<option>");
                    htmlV.push(this.escapeHTML(this.translate(this.getOptionText(this.options[i]))));
                    htmlV.push("</option>");
                }
            }
        },
        'get<Options>' : function() {
            if (!this.options)
                return [];
            if (this.emptyOptionText != null) {
                return this.options.slice(1); // Ignoring the first item in the array, which is the empty option (null)
            }
            return this.options;
        },
        getOptionText : function(value) { /* Logic for selecting the text to display for (potentially) a data structure */
            var outputValue = null;
            if (value && value.elementList) {
                var textElementRole = value.__textElementRole;
                if (textElementRole == null) {
                    for ( var i = 0; i < value.elementList.length; i++) {
                        var element = value.elementList[i];
                        if (i == 0) {
                            textElementRole = element.role; // If no text element is found, the first element is used
                            value.constructor.prototype.__textElement = element;
                        }
                        if (element.modelId == BuiltinModels.TEXT_ID) {
                            textElementRole = element.role;
                            value.constructor.prototype.__textElement = element;
                            break;
                        }
                    }
                    value.constructor.prototype.__textElementRole = textElementRole;
                }
                if (textElementRole && value.children)
                    outputValue = value.children[textElementRole];
            } else
                outputValue = value;
            var text = '';
            if (outputValue != null)
                text = outputValue.formatString(this.sharedProperties);
            else if (this.emptyOptionText != null)
                text = this.emptyOptionText;
            return text;
        }
	,updateSelfReadOnly: function(ro) {
       this.currentReadOnly=ro;
        if (!this.viewNode)
            return;
        var $v = $(this.viewNode);
        var roTag=this.prop('readonlytag') || this.defaultTag;
        var rwTag=this.getTag();
        if (roTag == rwTag)
        {
            if (ro)
                $v.prop('disabled',true);
            else
                $v.prop('disabled',false);
        }
        else
        {
            if (ro)
            {
                this.value = this.getValue();
                $f = $('<'+roTag+'>');
		this.textContainer=this.viewNode=$f[0];
		this.setValueString(); //Sets new element content based on this.value
		$f.attr('lid',this.getNodeId());
		$f.attr('display_order',$v.attr('display_order'));
		$v.replaceWith($f);
            }
            else
            {
                var $f=$('<'+rwTag+'>');
		var options = this.options;
		delete this.options;
		delete this.textContainer;
		$v.replaceWith($f);
		this.viewNode=$f[0];
		for (var i=0;i<options.length;i++)
		    this['add<Options>'].call(this,options[i]);
            }
        }
    }});

})(jQuery);

// file: UISplitPane.js
(function($, undefined) {
    tersus.UIWidget('UISplitPane', 'UIBase', {
        defaultTag : 'div'
    });
})(jQuery);
// file: UITextArea.js
(function( $, undefined ) {
tersus.UIWidget('UITextArea','UIField',{
    defaultTag:'textarea'
    ,inputType:null
    });
})(jQuery);
// file: UITextDisplay.js
tersus.UIWidget('UIButtonGroup','UIBase',{
    defaultTag:'div'
});

// file: UITextField.js
(function( $, undefined ) {
tersus.UIWidget('UITextField','UIField',{
    //Initially no special behavior for text field
    });
})(jQuery);
// file: UniqueItems.js
tersus.newAction('UniqueItems', function()
{
	var items = this.getTriggerValues();
	var output = [];
	
	for (var i=0;i<items.length;i++)
	{
		var item = items[i];
		var alreadyListed = false;
		for (var j=0;j<output.length;j++)
		{
			if (compareValues(item, output[j]))
			{
				alreadyListed = true;
				break;
			}
		}
		if (!alreadyListed)
			output.push(item);
	}
	var e = this.getExit('<Unique Items>');
	for (var i=0;i<output.length;i++)
	{
		this.accumulateExitValue(e, output[i]);
	};
});


// file: Unsubscribe.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Unsubscribe = tersus.CallJavaApplet.__subclass('Unsubscribe');

tersus.Unsubscribe.prototype.start = function()
{
	var id = this.getLeafChild('<Subscription Id>');
	var node = tersus.findNode(id);
	if (node)
	{
		var channel = node.channel;
		if (channel)
		{
			var list = tersus.Subscribe.subscriptions[channel];
			if (list)
			{
				for (var i=0;i<list; i++)
				{
					if (list[i] == id)
					{
						list.splice(id,1);
						if (list.length == 0)
						{
							delete tersus.Subscribe.subscriptions[id];
							tersus.Subscribe.pendingSubscriptions[channel] = 'REMOVE';
							setTimeout(tersus.updateSubscriptions,1000); // we're delaying updating of subscriptions in order to use one server request for numerous subscriptions
						}
						break;
					}
				}
			}
		}
		
	}

};

// file: Update.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Update = tersus.DatabaseAction.__subclass('tersus.Update');
tersus.Update.prototype.getTablePrototype = function()
{
	return this.getTrigger('<Record>').getChildConstructor().prototype;
};
tersus.Update.prototype.run = function()
{
	var record = this.getChild('<Record>');
	var tableName = this.getTableName(record);
	var fieldList = this.getFieldList(record.constructor.prototype);
	var sqla = []; // 'buffer' for creating the sql
	var values = []; // values
	sqla.push('UPDATE '+tableName + " SET ");
	var fields = fieldList.fields;
	var nfields = fields.length;
	var n = 0;
	var first = false;
	for (var j=0;j<nfields;j++)
	{
		var field = fields[j];
		if (!field.isPrimaryKey)
		{
			if (n++>0)
				sqla.push(',');
			sqla.push(field.sqlName);
			var v = field.getSQLValue(record);
			if (v != null)
			{
				sqla.push('= ?');
				values.push(v);
			}
			else
				sqla.push (' = NULL');
		}
	}
	this.addPrimaryKeyWhereClause(record,fieldList,sqla, values);
	var sql = sqla.join(' ');
	this.execSql(sql, values, function(transaction,results)
	{
		this.handleResults(results,record,tableName);
		this.resumeContext();
	});
			
};
tersus.Update.prototype.handleResults = function(results, record, tableName)
{
	var count = results.rowsAffected;
	if (count == 1)
		this.chargeExit('<Updated>',record);
	else if (count == 0)
		this.chargeExit('<Not Found>',record);
	else
		modelExecutionError("Update resulted in updating multiple records in table "
                                    + tableName
                                    + ". Check primary key settings", this);
                                    
};
// file: UpperCase.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.newAction('UpperCase', function()
{
	var text = this.getLeafChild('<Text>');
	if (text != null)
		this.chargeLeafExit('<Upper Case>',text.toUpperCase());
});


// file: VSplitPane.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.VSplitPane = function tersus_VSplitPane(){};
tersus.VSplitPane.prototype = new SplitPane();
tersus.VSplitPane.prototype.constructor = tersus.VSplitPane;
tersus.VSplitPane.prototype.bottomPaneHeight = 150;
tersus.VSplitPane.prototype.minHeight=20;
tersus.VSplitPane.prototype.contentPaneStyle = "vSplitPaneContent";
tersus.VSplitPane.prototype.dividerStyle = "vSplitPaneDivider";
tersus.VSplitPane.prototype.onResize = function ()
{
	if (this.sharedProperties.height)
		this.setDimensions();
	else
	{
		var d = this.viewNode.ownerDocument;
		var body = this.viewNode.ownerDocument.body;
		var height = getVisibleSize(body).height;
	
		var currentBottom = getOffsets(this.viewNode).top + this.viewNode.offsetHeight;
		if (window.browser != 'IE')
			currentBottom += 0;
		
		var delta = height-currentBottom;
		var currentHeight = this.bottomPaneHeight + this.topPaneHeight;
		if (delta+currentHeight >= 2*this.minHeight)
		{
			this.topPaneHeight = Math.max(this.minHeight, this.topPaneHeight+delta);
			this.bottomPaneHeight = currentHeight+delta-this.topPaneHeight;
			this.setPaneHeight(this.pane1,this.topPaneHeight);
			this.setPaneHeight(this.pane2,this.bottomPaneHeight);
		}
		var pane = this;
		var resizeChildren = function(){pane.onResizeChildren()};
		this.currentWindow.setTimeout(resizeChildren,10);
	}
};
tersus.VSplitPane.prototype.setDimensions = function()
{
	if (this.sharedProperties.height)
		this.height =parseInt(this.sharedProperties.height);
	
	this.divider.style.height = this.dividerThickness+ 'px';
	if (this.sharedProperties.bottomPaneHeight)
	{
		this.bottomPaneHeight=parseInt(this.sharedProperties.bottomPaneHeight);
	}
	this.topPaneHeight = this.height - this.bottomPaneHeight;
	this.setPaneHeight(this.pane1, this.topPaneHeight);
	this.setPaneHeight(this.pane2,this.bottomPaneHeight);
};
tersus.VSplitPane.prototype.resize = function(delta)
{
	if (this.topPaneHeight+delta.y >= this.minHeight && this.bottomPaneHeight-delta.y >= this.minHeight)
	{
		this.topPaneHeight += delta.y;
		this.bottomPaneHeight -= delta.y;
		this.setPaneHeight(this.pane1, this.topPaneHeight);
		this.setPaneHeight(this.pane2,this.bottomPaneHeight);
		this.onResizeChildren();
	}
};

// file: VariablePane.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function VariablePane(){};
VariablePane.prototype = new DisplayNode();
VariablePane.prototype.constructor = VariablePane;
VariablePane.prototype.defaultTag='div';
VariablePane.prototype.preloadOnStart=false;

VariablePane.prototype.createChildren = function()
{
};
VariablePane.prototype.createSubFlows = function()
{
	//initializes sub flows
	if (this.subFlowList)
	{
		for (var i=0;i<this.subFlowList.length; i++)
		{
			var subFlow = this.subFlowList[i];
			if (!subFlow.isDisplayElement)
				subFlow.init(this);
		}
	}
};

VariablePane.prototype.addDisplayElement = function addElement(role, modelId, properties)
{
	if (role.charAt(0) == '<' && this.getGetter(role))
	{
		var element = new MethodElement(this, role, modelId);
	}
	else
		var element = new VariableNodeDisplayElement(role, modelId);
	if (! this.displayElements)
		this.displayElements = [element];
	else
		this.displayElements.push(element);
	this.registerSubFlow(element);
	element.properties = properties;
	return this.addElement(element);
};
VariablePane.prototype['get<Current Content>'] = function()
{
	if (this.children)
	{
		for (var i=0; i<this.displayElements.length; i++)
		{
			var e = this.displayElements[i];
			var c = e.getChild(this);
			if (c != null)
				return c;
		}
	}
	return null;
}

function VariableNodeDisplayElement(role, modelId)
{
	this.role = role;
	this.modelId = modelId;
}

VariableNodeDisplayElement.prototype = new DisplayElement();
VariableNodeDisplayElement.prototype.constructor = VariableNodeDisplayElement;
VariableNodeDisplayElement.prototype.createChild = function createChild(parent, modelId, value)
{
	if (parent.currentWindow) // parent is a real display node
	{
		//TODO fix this so that 'onDelete()' is called for all children
		// (currently, some cleanup may be skipped)
		parent.children = [];
		parent.viewNode.innerHTML = '';
	}
	var child = DisplayElement.prototype.createChild.call(this,parent, modelId, value);
	return child;
};
VariableNodeDisplayElement.prototype.replaceChild = function replaceChild(parent, value)
{
	//TODO(x) complete the refactoring - replace deepCopy with copyValue. Compare with base implementation to see if it's needed at all
	if (parent.currentWindow) // parent is a real display node
	{
		var child = this.getChild(parent);
		if (child)
			child.deepCopy(value);
		else
			child = this.createChild(parent, this.modelId, value);		
	}
	else
	{
		Element.prototype.replaceChild.call(this, parent, value);
	}
};
// file: Wait.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 tersus.Wait = function tersus_Wait() {};
tersus.Wait.prototype = new ActionNode();
tersus.Wait.prototype.constructor = tersus.Wait;
tersus.Wait.prototype.done = function ()
{
	this.continueExecution();
};
tersus.Wait.prototype.resume = function()
{
};
tersus.Wait.DELAY=50;
tersus.Wait.prototype.start = function ()
{
	var time = this.getLeafChild('<Milliseconds>');
	var action = this;
	/* Not sure timing here is always correct.  We should probably always wait until the execution context is not busy
	   But there is no mechanism to do it and the required behavior is not fully defined */
	var done = function()
	{
		tersus.async.exec(function(){action.done();}, false /* don't wait */); // already waiting in checkResume  
	};
	if (time != null)
		setTimeout(done,time);  
	else
	{
		var checkResume = function()
		{
			if (tlog) tlog('browser location='+window.location.href+' tersus location='+tersus.history.location);
			tersus.history.checkLocation();
			if (isBusy() || tersus.async.isBusy())
				setTimeout(checkResume,tersus.Wait.DELAY);
			else
				tersus.async.exec(done, false /* don't wait */ ); // Looks like a redundant call to 'async' - not sure.  
		};
		tersus.async.exec(checkResume, false /* don't wait */);
	}
	if (window.trace)
		window.trace.flush();
	this.pause();
};

// file: WatchAccelerometer.js
tersus.newAction('WatchAccelerometer', function()
{
	tersus.WatchAccelerometer.watcherId = this.getNodeId();
	var threshold = this.getLeafChild('<Threshold>');
	if (threshold == null)
		threshold = 0.5;
	document.location='tersus://WatchAccelerometer/'+threshold;
});

tersus.WatchAccelerometer.busy = false;
var count = 0;
tersus.WatchAccelerometer.handleResponse = function(x, y, z, timestamp)
{
	++count;
	if (tersus.WatchAccelerometer.busy)
		return;
	tersus.WatchAccelerometer.busy = true;	
	var node = window.rootDisplayNode;
	var actionElement = node.getElement('<On Acceleration>');
	if (!actionElement)
		modelError('Missing element <On Acceleration>');
	var process = new BackgroundProcess(node, actionElement);
	process.setTriggerLeafValue('<X>',x);
	process.setTriggerLeafValue('<Y>',y);
	process.setTriggerLeafValue('<Z>',z);
	process.setTriggerLeafValue('<Timestamp>',timestamp);
			
	process.whenDone(function()
	{
		tersus.WatchAccelerometer.busy = false;
	});
	process.start();
};

// file: bootstrap-transition.js
/* ========================================================================
 * Bootstrap: transition.js v3.0.3
 * http://getbootstrap.com/javascript/#transitions
 * ========================================================================
 * Copyright 2011-2014 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // CSS TRANSITION SUPPORT (Shoutout: http://www.modernizr.com/)
  // ============================================================

  function transitionEnd() {
    var el = document.createElement('bootstrap')

    var transEndEventNames = {
      'WebkitTransition' : 'webkitTransitionEnd',
      'MozTransition'    : 'transitionend',
      'OTransition'      : 'oTransitionEnd otransitionend',
      'transition'       : 'transitionend'
    }

    for (var name in transEndEventNames) {
      if (el.style[name] !== undefined) {
        return { end: transEndEventNames[name] }
      }
    }

    return false // explicit for ie8 (  ._.)
  }

  // http://blog.alexmaccaw.com/css-transitions
  $.fn.emulateTransitionEnd = function (duration) {
    var called = false, $el = this
    $(this).one($.support.transition.end, function () { called = true })
    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
    setTimeout(callback, duration)
    return this
  }

  $(function () {
    $.support.transition = transitionEnd()
  })

}(jQuery);

// file: editor.js
tersus.HTMLEditor2 = {
	keyMap:{
		8:'BS'
		,9:'TAB'
		,27:'ESC'
		,32:'SPC'
		,38:'UP'
		,37:'LEFT'
		,39:'RIGHT'
		,40:'DOWN'
		,46:'DEL'
	},
	convertKeyCode:function(code)
	{
		if (code>=48 && code<=90)
			return String.fromCharCode(code);
		return tersus.HTMLEditor2.keyMap[code];
	},
	
	saveSelection: function() {
	    if (window.getSelection) {
	        sel = window.getSelection();
	        if (sel.getRangeAt && sel.rangeCount) {
	            var ranges = [];
	            for (var i = 0, len = sel.rangeCount; i < len; ++i) {
	                ranges.push(sel.getRangeAt(i));
	            }
	            tersus.HTMLEditor2.savedSelection=ranges;
	        }
	    } else if (document.selection && document.selection.createRange) {
	    	tersus.HTMLEditor2.savedSelection=document.selection.createRange();
	    }
	},

	restoreSelection:function () {
	    if (tersus.HTMLEditor2.savedSelection) {
	        if (window.getSelection) {
	            sel = window.getSelection();
	            sel.removeAllRanges();
	            for (var i = 0, len = tersus.HTMLEditor2.savedSelection.length; i < len; ++i) {
	                sel.addRange(tersus.HTMLEditor2.savedSelection[i]);
	            }
	        } else if (document.selection && tersus.HTMLEditor2.savedSelection.select) {
	        	tersus.HTMLEditor2.savedSelection.select();
	        }
	       // tersus.HTMLEditor2.savedSelection = null;
	    }
	},

	getSelectionElements:function()
	{
	    var elements = [];
	    var range, containerEl, links, linkRange;
	    if (window.getSelection) {
	        sel = window.getSelection();
	        if (sel.getRangeAt && sel.rangeCount) {
	            linkRange = document.createRange();
	            for (var r = 0; r < sel.rangeCount; ++r) {
	                range = sel.getRangeAt(r);
	                containerEl = range.commonAncestorContainer;
	                if (containerEl.nodeType != 1) {
	                    containerEl = containerEl.parentNode;
	                }
	                elements.push(containerEl);
	            }
	            linkRange.detach();
	        }
	    } else if (document.selection && document.selection.type != "Control") {
	        range = document.selection.createRange();
	        containerEl = range.parentElement();
	        elements.push(containerEl);
	    }
	    return elements;
	},
	setSelectionLinkTarget:function(target)
	{
		tersus.HTMLEditor2.getSelectionElement('a').attr('target', target);
	},

	getSelectionElement:function(tagName, w)
	{
		w = w || window;
		tagName=tagName.toUpperCase();
		var n;
		if (w.getSelection)
		{
			var sel = window.getSelection();
			if (sel.rangeCount==1)
			{
				var r = sel.getRangeAt(0);
				if(r.startContainer !== r.endContainer || r.startOffset != r.endOffset)
				{
					var n = r.endContainer;
					if (n.hasChildNodes() && r.endOffset >0)
						n = n.childNodes[r.endOffset-1];
	
					while (n && n.tagName != tagName)
					{
						n = n.parentNode;
					}
				}
			}
		}
		return $(n);
	},


	getSelectionStartNode:function(w)
	{
		w = w || window;
		if (w.getSelection)
		{
			var sel= window.getSelection();
			if (sel.rangeCount>0)
			{
				var range = sel.getRangeAt(0);
				var node = range.startContainer;
				if (node.hasChildNodes() && range.startOffset >0)
					node = node.childNodes[range.startOffset-1];
				return node;
			}
		}
	},
	
	setImageAttributes:function(alt, width, height)
	{
		var node = tersus.HTMLEditor2.getSelectionStartNode();
		if (node && node.tagName=='IMG')
		{
			width = width>=0 ? width: '';
			height= height>=0 ? height : '';
			$(node).attr('alt',alt).width(width).height(height);
		}
	},

	getImageAttributes:function(_node)
	{
		var $img = tersus.HTMLEditor2.getSelectionElement('img');
		_node.setLeafChild('alt', $img.attr('alt'), Operation.REPLACE);
		_node.setLeafChild('src', $img.attr('src'), Operation.REPLACE);
		_node.setLeafChild('width', $img.width(), Operation.REPLACE);
		_node.setLeafChild('height', $img.height(), Operation.REPLACE);
	},
	commands: {
		bold:{style:'bold', description:'Bold', keyBinding:'Ctrl-B'},
		italic:{style:'italic', description:'Italic', keyBinding:'Ctrl-I'},
		underline:{style:'underline', description:'Underline', keyBinding:'Ctrl-U'},
		justifyLeft:{style:'align-left', description:'Align Left', keyBinding:'Ctrl-Shift-L'},
		justifyCenter:{style:'align-center', description:'Align Center', keyBinding:'Ctrl-Shift-E'},
		justifyRight:{style:'align-right', description:'Align RIght', keyBinding:'Ctrl-Shift-R'},
		insertOrderedList:{style:'ordered-list', description:'Bulleted List', keyBinding:'Ctrl-Shift-8'},
		insertUnorderedList:{style:'unordered-list', description:'Numbered List', keyBinding:'Ctrl-Shift-7'},
		outdent:{style:'outdent', description:'Indent Less'},
		indent:{style:'indent', description:'Indent More'},
		removeFormat:{style:'clean', description:'Remove Formatting'}
	},
	defaultCommands:['bold','italic','underline','justifyLeft','justifyCenter','justifyRight','insertOrderedList','insertUnorderedList','outdent','indent','removeFormat']
};

// file: iPhoneVariablePane.js
/*********************************************************************************************************
 * Copyright (c) 2003-2009 Tersus Software Ltd. , All rights reserved.
 *
 * This program is made available under the terms of the GNU Lesser General Public License, version 2.1,
 * which is part of this distribution and is available at hhttp://www.gnu.org/licenses/lgpl-2.1.txt
 **********************************************************************************************************/
 function iPhoneVariablePane(){};
iPhoneVariablePane.prototype = new DisplayNode();
iPhoneVariablePane.prototype.constructor = iPhoneVariablePane;
iPhoneVariablePane.prototype.defaultTag='div';
iPhoneVariablePane.prototype.preloadOnStart=false;

iPhoneVariablePane.prototype.createChildren = function()
{
};
iPhoneVariablePane.prototype.createSubFlows = function()
{
	//initializes sub flows
	if (this.subFlowList)
	{
		for (var i=0;i<this.subFlowList.length; i++)
		{
			var subFlow = this.subFlowList[i];
			if (!subFlow.isDisplayElement)
				subFlow.init(this);
		}
	}
};

iPhoneVariablePane.prototype.addDisplayElement = function addElement(role, modelId, properties)
{
	if (role.charAt(0) == '<' && this.getGetter(role))
	{
		var element = new MethodElement(this, role, modelId);
	}
	else
		var element = new VariableNodeDisplayElement(role, modelId);
	if (! this.displayElements)
		this.displayElements = [element];
	else
		this.displayElements.push(element);
	this.registerSubFlow(element);
	element.properties = properties;
	return this.addElement(element);
};
iPhoneVariablePane.prototype['get<Current Content>'] = function()
{
	if (this.children)
	{
		for (var i=0; i<this.displayElements.length; i++)
		{
			var e = this.displayElements[i];
			var c = e.getChild(this);
			if (c != null)
				return c;
		}
	}
	return null;
}

function VariableNodeDisplayElement(role, modelId)
{
	this.role = role;
	this.modelId = modelId;
}

iPhoneVariablePane.prototype.setProperties = function()
{
	DisplayNode.prototype.setProperties.call(this);
	var vari = this;
	tersus.async.exec(function() {vari.onResize();}, false /* don't wait */);
};
iPhoneVariablePane.prototype.onResize = function()
{
	this.adjustHeightMiddle();
	
	this.onResizeChildren();

};
iPhoneVariablePane.prototype.setHeight = function(newHeight)
{
	this.viewNode.style.height = newHeight;
};
iPhoneVariablePane.prototype.adjustHeightMiddle = function()
{
	var par = this.viewNode.parentNode;
	var pheight = getVisibleSize(par).height;
	
	var kidsHeight = 0;
	var kids = par.childNodes;   // Get the list of children
    
    for(var i = 0; i < kids.length; i++)  // calc sibilings height
     {
 		if (kids[i].className != 'Variable')
 		{
 			kidsHeight += getVisibleSize(kids[i]).height;
 		}
 	} 	
	var delta = pheight - kidsHeight;
	this.setHeight(delta);
}
VariableNodeDisplayElement.prototype = new DisplayElement();
VariableNodeDisplayElement.prototype.constructor = VariableNodeDisplayElement;
VariableNodeDisplayElement.prototype.createChild = function createChild(parent, modelId, value)
{
	if (parent.currentWindow) // parent is a real display node
	{
		//TODO fix this so that 'onDelete()' is called for all children
		// (currently, some cleanup may be skipped)
		parent.children = [];
		parent.viewNode.innerHTML = '';
	}
	var child = DisplayElement.prototype.createChild.call(this,parent, modelId, value);
	return child;
};
VariableNodeDisplayElement.prototype.replaceChild = function replaceChild(parent, value)
{
	//TODO(x) complete the refactoring - replace deepCopy with copyValue. Compare with base implementation to see if it's needed at all
	if (parent.currentWindow) // parent is a real display node
	{
		var child = this.getChild(parent);
		if (child)
			child.deepCopy(value);
		else
			child = this.createChild(parent, this.modelId, value);		
	}
	else
	{
		Element.prototype.replaceChild.call(this, parent, value);
	}
};

// file: iscroll.non-msie.js
/*!
 * iScroll v4.1.9 ~ Copyright (c) 2011 Matteo Spinelli, http://cubiq.org
 * Released under MIT license, http://cubiq.org/license
 */
(function(){
var m = Math,
	mround = function (r) { return r >> 0; },
	vendor = (/webkit/i).test(navigator.appVersion) ? 'webkit' :
		(/firefox/i).test(navigator.userAgent) ? 'Moz' :
		'opera' in window ? 'O' : '',

	// Browser capabilities
	has3d = 'WebKitCSSMatrix' in window && 'm11' in new WebKitCSSMatrix(),
	hasTouch = 'ontouchstart' in window,
	hasTransform = vendor + 'Transform' in document.documentElement.style,
	isAndroid = (/android/gi).test(navigator.appVersion),
	isIDevice = (/iphone|ipad/gi).test(navigator.appVersion),
	isPlaybook = (/playbook/gi).test(navigator.appVersion),
	hasTransitionEnd = isIDevice || isPlaybook,
	nextFrame = (function() {
	    return window.requestAnimationFrame
			|| window.webkitRequestAnimationFrame
			|| window.mozRequestAnimationFrame
			|| window.oRequestAnimationFrame
			|| window.msRequestAnimationFrame
			|| function(callback) { return setTimeout(callback, 1); }
	})(),
	cancelFrame = (function () {
	    return window.cancelRequestAnimationFrame
			|| window.webkitCancelRequestAnimationFrame
			|| window.mozCancelRequestAnimationFrame
			|| window.oCancelRequestAnimationFrame
			|| window.msCancelRequestAnimationFrame
			|| clearTimeout
	})(),

	// Events
	RESIZE_EV = 'onorientationchange' in window ? 'orientationchange' : 'resize',
	START_EV = hasTouch ? 'touchstart' : 'mousedown',
	MOVE_EV = hasTouch ? 'touchmove' : 'mousemove',
	END_EV = hasTouch ? 'touchend' : 'mouseup',
	CANCEL_EV = hasTouch ? 'touchcancel' : 'mouseup',
	WHEEL_EV = vendor == 'Moz' ? 'DOMMouseScroll' : 'mousewheel',

	// Helpers
	trnOpen = 'translate' + (has3d ? '3d(' : '('),
	trnClose = has3d ? ',0)' : ')',

	// Constructor
	iScroll = function (el, options) {
		var that = this,
			doc = document,
			i;

		that.wrapper = typeof el == 'object' ? el : doc.getElementById(el);
		that.wrapper.style.overflow = 'hidden';
		that.scroller = that.wrapper.children[0];

		// Default options
		that.options = {
			hScroll: true,
			vScroll: true,
			x: 0,
			y: 0,
			bounce: true,
			bounceLock: false,
			momentum: true,
			lockDirection: true,
			useTransform: true,
			useTransition: false,
			topOffset: 0,
			checkDOMChanges: false,		// Experimental

			// Scrollbar
			hScrollbar: true,
			vScrollbar: true,
			fixedScrollbar: isAndroid,
			hideScrollbar: isIDevice,
			fadeScrollbar: isIDevice && has3d,
			scrollbarClass: '',

			// Zoom
			zoom: false,
			zoomMin: 1,
			zoomMax: 4,
			doubleTapZoom: 2,
			wheelAction: 'scroll',

			// Snap
			snap: false,
			snapThreshold: 1,

			// Events
			onRefresh: null,
			onBeforeScrollStart: function (e) { e.preventDefault(); },
			onScrollStart: null,
			onBeforeScrollMove: null,
			onScrollMove: null,
			onBeforeScrollEnd: null,
			onScrollEnd: null,
			onTouchEnd: null,
			onDestroy: null,
			onZoomStart: null,
			onZoom: null,
			onZoomEnd: null
		};
		// Helpers FIX ANDROID BUG!
		// translate3d and scale doesn't work together! 
		// Ignoring 3d ONLY WHEN YOU SET that.zoom
		if ( that.zoom && isAndroid ){
			trnOpen = 'translate(';
			trnClose = ')';
		}
		// User defined options
		for (i in options) that.options[i] = options[i];
		
		// Set starting position
		that.x = that.options.x;
		that.y = that.options.y;

		// Normalize options
		that.options.useTransform = hasTransform ? that.options.useTransform : false;
		that.options.hScrollbar = that.options.hScroll && that.options.hScrollbar;
		that.options.vScrollbar = that.options.vScroll && that.options.vScrollbar;
		that.options.zoom = that.options.useTransform && that.options.zoom;
		that.options.useTransition = hasTransitionEnd && that.options.useTransition;
		
		// Set some default styles
		that.scroller.style[vendor + 'TransitionProperty'] = that.options.useTransform ? '-' + vendor.toLowerCase() + '-transform' : 'top left';
		that.scroller.style[vendor + 'TransitionDuration'] = '0';
		that.scroller.style[vendor + 'TransformOrigin'] = '0 0';
		if (that.options.useTransition) that.scroller.style[vendor + 'TransitionTimingFunction'] = 'cubic-bezier(0.33,0.66,0.66,1)';
		
		if (that.options.useTransform) that.scroller.style[vendor + 'Transform'] = trnOpen + that.x + 'px,' + that.y + 'px' + trnClose;
		else that.scroller.style.cssText += ';position:absolute;top:' + that.y + 'px;left:' + that.x + 'px';

		if (that.options.useTransition) that.options.fixedScrollbar = true;

		that.refresh();

		that._bind(RESIZE_EV, window);
		that._bind(START_EV);
		if (!hasTouch) {
			that._bind('mouseout', that.wrapper);
			that._bind(WHEEL_EV);
		}

		if (that.options.checkDOMChanges) that.checkDOMTime = setInterval(function () {
			that._checkDOMChanges();
		}, 500);
	};

// Prototype
iScroll.prototype = {
	enabled: true,
	x: 0,
	y: 0,
	steps: [],
	scale: 1,
	currPageX: 0, currPageY: 0,
	pagesX: [], pagesY: [],
	aniTime: null,
	wheelZoomCount: 0,
	
	handleEvent: function (e) {
		var that = this;
		switch(e.type) {
			case START_EV:
				if (!hasTouch && e.button !== 0) return;
				that._start(e);
				break;
			case MOVE_EV: that._move(e); break;
			case END_EV:
			case CANCEL_EV: that._end(e); break;
			case RESIZE_EV: that._resize(); break;
			case WHEEL_EV: that._wheel(e); break;
			case 'mouseout': that._mouseout(e); break;
			case 'webkitTransitionEnd': that._transitionEnd(e); break;
		}
	},
	
	_checkDOMChanges: function () {
		if (this.moved || this.zoomed || this.animating ||
			(this.scrollerW == this.scroller.offsetWidth * this.scale && this.scrollerH == this.scroller.offsetHeight * this.scale)) return;

		this.refresh();
	},
	
	_scrollbar: function (dir) {
		var that = this,
			doc = document,
			bar;

		if (!that[dir + 'Scrollbar']) {
			if (that[dir + 'ScrollbarWrapper']) {
				if (hasTransform) that[dir + 'ScrollbarIndicator'].style[vendor + 'Transform'] = '';
				that[dir + 'ScrollbarWrapper'].parentNode.removeChild(that[dir + 'ScrollbarWrapper']);
				that[dir + 'ScrollbarWrapper'] = null;
				that[dir + 'ScrollbarIndicator'] = null;
			}

			return;
		}

		if (!that[dir + 'ScrollbarWrapper']) {
			// Create the scrollbar wrapper
			bar = doc.createElement('div');

			if (that.options.scrollbarClass) bar.className = that.options.scrollbarClass + dir.toUpperCase();
			else bar.style.cssText = 'position:absolute;z-index:100;' + (dir == 'h' ? 'height:7px;bottom:1px;left:2px;right:' + (that.vScrollbar ? '7' : '2') + 'px' : 'width:7px;bottom:' + (that.hScrollbar ? '7' : '2') + 'px;top:2px;right:1px');

			bar.style.cssText += ';pointer-events:none;-' + vendor + '-transition-property:opacity;-' + vendor + '-transition-duration:' + (that.options.fadeScrollbar ? '350ms' : '0') + ';overflow:hidden;opacity:' + (that.options.hideScrollbar ? '0' : '1');

			that.wrapper.appendChild(bar);
			that[dir + 'ScrollbarWrapper'] = bar;

			// Create the scrollbar indicator
			bar = doc.createElement('div');
			if (!that.options.scrollbarClass) {
				bar.style.cssText = 'position:absolute;z-index:100;background:rgba(0,0,0,0.5);border:1px solid rgba(255,255,255,0.9);-' + vendor + '-background-clip:padding-box;-' + vendor + '-box-sizing:border-box;' + (dir == 'h' ? 'height:100%' : 'width:100%') + ';-' + vendor + '-border-radius:3px;border-radius:3px';
			}
			bar.style.cssText += ';pointer-events:none;-' + vendor + '-transition-property:-' + vendor + '-transform;-' + vendor + '-transition-timing-function:cubic-bezier(0.33,0.66,0.66,1);-' + vendor + '-transition-duration:0;-' + vendor + '-transform:' + trnOpen + '0,0' + trnClose;
			if (that.options.useTransition) bar.style.cssText += ';-' + vendor + '-transition-timing-function:cubic-bezier(0.33,0.66,0.66,1)';

			that[dir + 'ScrollbarWrapper'].appendChild(bar);
			that[dir + 'ScrollbarIndicator'] = bar;
		}

		if (dir == 'h') {
			that.hScrollbarSize = that.hScrollbarWrapper.clientWidth;
			that.hScrollbarIndicatorSize = m.max(mround(that.hScrollbarSize * that.hScrollbarSize / that.scrollerW), 8);
			that.hScrollbarIndicator.style.width = that.hScrollbarIndicatorSize + 'px';
			that.hScrollbarMaxScroll = that.hScrollbarSize - that.hScrollbarIndicatorSize;
			that.hScrollbarProp = that.hScrollbarMaxScroll / that.maxScrollX;
		} else {
			that.vScrollbarSize = that.vScrollbarWrapper.clientHeight;
			that.vScrollbarIndicatorSize = m.max(mround(that.vScrollbarSize * that.vScrollbarSize / that.scrollerH), 8);
			that.vScrollbarIndicator.style.height = that.vScrollbarIndicatorSize + 'px';
			that.vScrollbarMaxScroll = that.vScrollbarSize - that.vScrollbarIndicatorSize;
			that.vScrollbarProp = that.vScrollbarMaxScroll / that.maxScrollY;
		}

		// Reset position
		that._scrollbarPos(dir, true);
	},
	
	_resize: function () {
		var that = this;
		setTimeout(function () { that.refresh(); }, isAndroid ? 200 : 0);
	},
	
	_pos: function (x, y) {
		x = this.hScroll ? x : 0;
		y = this.vScroll ? y : 0;

		if (this.options.useTransform) {
			this.scroller.style[vendor + 'Transform'] = trnOpen + x + 'px,' + y + 'px' + trnClose + ' scale(' + this.scale + ')';
		} else {
			x = mround(x);
			y = mround(y);
			this.scroller.style.left = x + 'px';
			this.scroller.style.top = y + 'px';
		}

		this.x = x;
		this.y = y;

		this._scrollbarPos('h');
		this._scrollbarPos('v');
	},

	_scrollbarPos: function (dir, hidden) {
		var that = this,
			pos = dir == 'h' ? that.x : that.y,
			size;

		if (!that[dir + 'Scrollbar']) return;

		pos = that[dir + 'ScrollbarProp'] * pos;

		if (pos < 0) {
			if (!that.options.fixedScrollbar) {
				size = that[dir + 'ScrollbarIndicatorSize'] + mround(pos * 3);
				if (size < 8) size = 8;
				that[dir + 'ScrollbarIndicator'].style[dir == 'h' ? 'width' : 'height'] = size + 'px';
			}
			pos = 0;
		} else if (pos > that[dir + 'ScrollbarMaxScroll']) {
			if (!that.options.fixedScrollbar) {
				size = that[dir + 'ScrollbarIndicatorSize'] - mround((pos - that[dir + 'ScrollbarMaxScroll']) * 3);
				if (size < 8) size = 8;
				that[dir + 'ScrollbarIndicator'].style[dir == 'h' ? 'width' : 'height'] = size + 'px';
				pos = that[dir + 'ScrollbarMaxScroll'] + (that[dir + 'ScrollbarIndicatorSize'] - size);
			} else {
				pos = that[dir + 'ScrollbarMaxScroll'];
			}
		}

		that[dir + 'ScrollbarWrapper'].style[vendor + 'TransitionDelay'] = '0';
		that[dir + 'ScrollbarWrapper'].style.opacity = hidden && that.options.hideScrollbar ? '0' : '1';
		that[dir + 'ScrollbarIndicator'].style[vendor + 'Transform'] = trnOpen + (dir == 'h' ? pos + 'px,0' : '0,' + pos + 'px') + trnClose;
	},
	
	_start: function (e) {
		var that = this,
			point = hasTouch ? e.touches[0] : e,
			matrix, x, y,
			c1, c2;

		if (!that.enabled) return;

		if (that.options.onBeforeScrollStart) that.options.onBeforeScrollStart.call(that, e);

		if (that.options.useTransition || that.options.zoom) that._transitionTime(0);

		that.moved = false;
		that.animating = false;
		that.zoomed = false;
		that.distX = 0;
		that.distY = 0;
		that.absDistX = 0;
		that.absDistY = 0;
		that.dirX = 0;
		that.dirY = 0;

		// Gesture start
		if (that.options.zoom && hasTouch && e.touches.length > 1) {
			c1 = m.abs(e.touches[0].pageX-e.touches[1].pageX);
			c2 = m.abs(e.touches[0].pageY-e.touches[1].pageY);
			that.touchesDistStart = m.sqrt(c1 * c1 + c2 * c2);

			that.originX = m.abs(e.touches[0].pageX + e.touches[1].pageX - that.wrapperOffsetLeft * 2) / 2 - that.x;
			that.originY = m.abs(e.touches[0].pageY + e.touches[1].pageY - that.wrapperOffsetTop * 2) / 2 - that.y;

			if (that.options.onZoomStart) that.options.onZoomStart.call(that, e);
		}

		if (that.options.momentum) {
			if (that.options.useTransform) {
				// Very lame general purpose alternative to CSSMatrix
				matrix = getComputedStyle(that.scroller, null)[vendor + 'Transform'].replace(/[^0-9-.,]/g, '').split(',');
				x = matrix[4] * 1;
				y = matrix[5] * 1;
			} else {
				x = getComputedStyle(that.scroller, null).left.replace(/[^0-9-]/g, '') * 1;
				y = getComputedStyle(that.scroller, null).top.replace(/[^0-9-]/g, '') * 1;
			}
			
			if (x != that.x || y != that.y) {
				if (that.options.useTransition) that._unbind('webkitTransitionEnd');
				else cancelFrame(that.aniTime);
				that.steps = [];
				that._pos(x, y);
			}
		}

		that.absStartX = that.x;	// Needed by snap threshold
		that.absStartY = that.y;

		that.startX = that.x;
		that.startY = that.y;
		that.pointX = point.pageX;
		that.pointY = point.pageY;

		that.startTime = e.timeStamp || Date.now();

		if (that.options.onScrollStart) that.options.onScrollStart.call(that, e);

		that._bind(MOVE_EV);
		that._bind(END_EV);
		that._bind(CANCEL_EV);
	},
	
	_move: function (e) {
		var that = this,
			point = hasTouch ? e.touches[0] : e,
			deltaX = point.pageX - that.pointX,
			deltaY = point.pageY - that.pointY,
			newX = that.x + deltaX,
			newY = that.y + deltaY,
			c1, c2, scale,
			timestamp = e.timeStamp || Date.now();

		if (that.options.onBeforeScrollMove) that.options.onBeforeScrollMove.call(that, e);

		// Zoom
		if (that.options.zoom && hasTouch && e.touches.length > 1) {
			c1 = m.abs(e.touches[0].pageX - e.touches[1].pageX);
			c2 = m.abs(e.touches[0].pageY - e.touches[1].pageY);
			that.touchesDist = m.sqrt(c1*c1+c2*c2);

			that.zoomed = true;

			scale = 1 / that.touchesDistStart * that.touchesDist * this.scale;

			if (scale < that.options.zoomMin) scale = 0.5 * that.options.zoomMin * Math.pow(2.0, scale / that.options.zoomMin);
			else if (scale > that.options.zoomMax) scale = 2.0 * that.options.zoomMax * Math.pow(0.5, that.options.zoomMax / scale);

			that.lastScale = scale / this.scale;

			newX = this.originX - this.originX * that.lastScale + this.x,
			newY = this.originY - this.originY * that.lastScale + this.y;

			this.scroller.style[vendor + 'Transform'] = trnOpen + newX + 'px,' + newY + 'px' + trnClose + ' scale(' + scale + ')';

			if (that.options.onZoom) that.options.onZoom.call(that, e);
			return;
		}

		that.pointX = point.pageX;
		that.pointY = point.pageY;

		// Slow down if outside of the boundaries
		if (newX > 0 || newX < that.maxScrollX) {
			newX = that.options.bounce ? that.x + (deltaX / 2) : newX >= 0 || that.maxScrollX >= 0 ? 0 : that.maxScrollX;
		}
		if (newY > that.minScrollY || newY < that.maxScrollY) { 
			newY = that.options.bounce ? that.y + (deltaY / 2) : newY >= that.minScrollY || that.maxScrollY >= 0 ? that.minScrollY : that.maxScrollY;
		}

		if (that.absDistX < 6 && that.absDistY < 6) {
			that.distX += deltaX;
			that.distY += deltaY;
			that.absDistX = m.abs(that.distX);
			that.absDistY = m.abs(that.distY);

			return;
		}

		// Lock direction
		if (that.options.lockDirection) {
			if (that.absDistX > that.absDistY + 5) {
				newY = that.y;
				deltaY = 0;
			} else if (that.absDistY > that.absDistX + 5) {
				newX = that.x;
				deltaX = 0;
			}
		}

		that.moved = true;
		that._pos(newX, newY);
		that.dirX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
		that.dirY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;

		if (timestamp - that.startTime > 300) {
			that.startTime = timestamp;
			that.startX = that.x;
			that.startY = that.y;
		}
		
		if (that.options.onScrollMove) that.options.onScrollMove.call(that, e);
	},
	
	_end: function (e) {
		if (hasTouch && e.touches.length != 0) return;

		var that = this,
			point = hasTouch ? e.changedTouches[0] : e,
			target, ev,
			momentumX = { dist:0, time:0 },
			momentumY = { dist:0, time:0 },
			duration = (e.timeStamp || Date.now()) - that.startTime,
			newPosX = that.x,
			newPosY = that.y,
			distX, distY,
			newDuration,
			snap,
			scale;

		that._unbind(MOVE_EV);
		that._unbind(END_EV);
		that._unbind(CANCEL_EV);

		if (that.options.onBeforeScrollEnd) that.options.onBeforeScrollEnd.call(that, e);

		if (that.zoomed) {
			scale = that.scale * that.lastScale;
			scale = Math.max(that.options.zoomMin, scale);
			scale = Math.min(that.options.zoomMax, scale);
			that.lastScale = scale / that.scale;
			that.scale = scale;

			that.x = that.originX - that.originX * that.lastScale + that.x;
			that.y = that.originY - that.originY * that.lastScale + that.y;
			
			that.scroller.style[vendor + 'TransitionDuration'] = '200ms';
			that.scroller.style[vendor + 'Transform'] = trnOpen + that.x + 'px,' + that.y + 'px' + trnClose + ' scale(' + that.scale + ')';
			
			that.zoomed = false;
			that.refresh();

			if (that.options.onZoomEnd) that.options.onZoomEnd.call(that, e);
			return;
		}

		if (!that.moved) {
			if (hasTouch) {
				if (that.doubleTapTimer && that.options.zoom) {
					// Double tapped
					clearTimeout(that.doubleTapTimer);
					that.doubleTapTimer = null;
					if (that.options.onZoomStart) that.options.onZoomStart.call(that, e);
					that.zoom(that.pointX, that.pointY, that.scale == 1 ? that.options.doubleTapZoom : 1);
					if (that.options.onZoomEnd) {
						setTimeout(function() {
							that.options.onZoomEnd.call(that, e);
						}, 200); // 200 is default zoom duration
					}
				} else {
					that.doubleTapTimer = setTimeout(function () {
						that.doubleTapTimer = null;

						// Find the last touched element
						target = point.target;
						while (target.nodeType != 1) target = target.parentNode;

						if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') {
							ev = document.createEvent('MouseEvents');
							ev.initMouseEvent('click', true, true, e.view, 1,
								point.screenX, point.screenY, point.clientX, point.clientY,
								e.ctrlKey, e.altKey, e.shiftKey, e.metaKey,
								0, null);
							ev._fake = true;
							target.dispatchEvent(ev);
						}
					}, that.options.zoom ? 250 : 0);
				}
			}

			that._resetPos(200);

			if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
			return;
		}

		if (duration < 300 && that.options.momentum) {
			momentumX = newPosX ? that._momentum(newPosX - that.startX, duration, -that.x, that.scrollerW - that.wrapperW + that.x, that.options.bounce ? that.wrapperW : 0) : momentumX;
			momentumY = newPosY ? that._momentum(newPosY - that.startY, duration, -that.y, (that.maxScrollY < 0 ? that.scrollerH - that.wrapperH + that.y - that.minScrollY : 0), that.options.bounce ? that.wrapperH : 0) : momentumY;

			newPosX = that.x + momentumX.dist;
			newPosY = that.y + momentumY.dist;

 			if ((that.x > 0 && newPosX > 0) || (that.x < that.maxScrollX && newPosX < that.maxScrollX)) momentumX = { dist:0, time:0 };
 			if ((that.y > that.minScrollY && newPosY > that.minScrollY) || (that.y < that.maxScrollY && newPosY < that.maxScrollY)) momentumY = { dist:0, time:0 };
		}

		if (momentumX.dist || momentumY.dist) {
			newDuration = m.max(m.max(momentumX.time, momentumY.time), 10);

			// Do we need to snap?
			if (that.options.snap) {
				distX = newPosX - that.absStartX;
				distY = newPosY - that.absStartY;
				if (m.abs(distX) < that.options.snapThreshold && m.abs(distY) < that.options.snapThreshold) { that.scrollTo(that.absStartX, that.absStartY, 200); }
				else {
					snap = that._snap(newPosX, newPosY);
					newPosX = snap.x;
					newPosY = snap.y;
					newDuration = m.max(snap.time, newDuration);
				}
			}

			that.scrollTo(mround(newPosX), mround(newPosY), newDuration);

			if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
			return;
		}

		// Do we need to snap?
		if (that.options.snap) {
			distX = newPosX - that.absStartX;
			distY = newPosY - that.absStartY;
			if (m.abs(distX) < that.options.snapThreshold && m.abs(distY) < that.options.snapThreshold) that.scrollTo(that.absStartX, that.absStartY, 200);
			else {
				snap = that._snap(that.x, that.y);
				if (snap.x != that.x || snap.y != that.y) that.scrollTo(snap.x, snap.y, snap.time);
			}

			if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
			return;
		}

		that._resetPos(200);
		if (that.options.onTouchEnd) that.options.onTouchEnd.call(that, e);
	},
	
	_resetPos: function (time) {
		var that = this,
			resetX = that.x >= 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x,
			resetY = that.y >= that.minScrollY || that.maxScrollY > 0 ? that.minScrollY : that.y < that.maxScrollY ? that.maxScrollY : that.y;

		if (resetX == that.x && resetY == that.y) {
			if (that.moved) {
				that.moved = false;
				if (that.options.onScrollEnd) that.options.onScrollEnd.call(that);		// Execute custom code on scroll end
			}

			if (that.hScrollbar && that.options.hideScrollbar) {
				if (vendor == 'webkit') that.hScrollbarWrapper.style[vendor + 'TransitionDelay'] = '300ms';
				that.hScrollbarWrapper.style.opacity = '0';
			}
			if (that.vScrollbar && that.options.hideScrollbar) {
				if (vendor == 'webkit') that.vScrollbarWrapper.style[vendor + 'TransitionDelay'] = '300ms';
				that.vScrollbarWrapper.style.opacity = '0';
			}

			return;
		}

		that.scrollTo(resetX, resetY, time || 0);
	},

	_wheel: function (e) {
		var that = this,
			wheelDeltaX, wheelDeltaY,
			deltaX, deltaY,
			deltaScale;

		if ('wheelDeltaX' in e) {
			wheelDeltaX = e.wheelDeltaX / 12;
			wheelDeltaY = e.wheelDeltaY / 12;
		} else if ('detail' in e) {
			wheelDeltaX = wheelDeltaY = -e.detail * 3;
		} else {
			wheelDeltaX = wheelDeltaY = -e.wheelDelta;
		}
		
		if (that.options.wheelAction == 'zoom') {
			deltaScale = that.scale * Math.pow(2, 1/3 * (wheelDeltaY ? wheelDeltaY / Math.abs(wheelDeltaY) : 0));
			if (deltaScale < that.options.zoomMin) deltaScale = that.options.zoomMin;
			if (deltaScale > that.options.zoomMax) deltaScale = that.options.zoomMax;
			
			if (deltaScale != that.scale) {
				if (!that.wheelZoomCount && that.options.onZoomStart) that.options.onZoomStart.call(that, e);
				that.wheelZoomCount++;
				
				that.zoom(e.pageX, e.pageY, deltaScale, 400);
				
				setTimeout(function() {
					that.wheelZoomCount--;
					if (!that.wheelZoomCount && that.options.onZoomEnd) that.options.onZoomEnd.call(that, e);
				}, 400);
			}
			
			return;
		}
		
		deltaX = that.x + wheelDeltaX;
		deltaY = that.y + wheelDeltaY;

		if (deltaX > 0) deltaX = 0;
		else if (deltaX < that.maxScrollX) deltaX = that.maxScrollX;

		if (deltaY > that.minScrollY) deltaY = that.minScrollY;
		else if (deltaY < that.maxScrollY) deltaY = that.maxScrollY;

		that.scrollTo(deltaX, deltaY, 0);
	},
	
	_mouseout: function (e) {
		var t = e.relatedTarget;

		if (!t) {
			this._end(e);
			return;
		}

		while (t = t.parentNode) if (t == this.wrapper) return;
		
		this._end(e);
	},

	_transitionEnd: function (e) {
		var that = this;

		if (e.target != that.scroller) return;

		that._unbind('webkitTransitionEnd');
		
		that._startAni();
	},


	/**
	 *
	 * Utilities
	 *
	 */
	_startAni: function () {
		var that = this,
			startX = that.x, startY = that.y,
			startTime = Date.now(),
			step, easeOut,
			animate;

		if (that.animating) return;
		
		if (!that.steps.length) {
			that._resetPos(400);
			return;
		}
		
		step = that.steps.shift();
		
		if (step.x == startX && step.y == startY) step.time = 0;

		that.animating = true;
		that.moved = true;
		
		if (that.options.useTransition) {
			that._transitionTime(step.time);
			that._pos(step.x, step.y);
			that.animating = false;
			if (step.time) that._bind('webkitTransitionEnd');
			else that._resetPos(0);
			return;
		}

		animate = function () {
			var now = Date.now(),
				newX, newY;

			if (now >= startTime + step.time) {
				that._pos(step.x, step.y);
				that.animating = false;
				if (that.options.onAnimationEnd) that.options.onAnimationEnd.call(that);			// Execute custom code on animation end
				that._startAni();
				return;
			}

			now = (now - startTime) / step.time - 1;
			easeOut = m.sqrt(1 - now * now);
			newX = (step.x - startX) * easeOut + startX;
			newY = (step.y - startY) * easeOut + startY;
			that._pos(newX, newY);
			if (that.animating) that.aniTime = nextFrame(animate);
		};

		animate();
	},

	_transitionTime: function (time) {
		time += 'ms';
		this.scroller.style[vendor + 'TransitionDuration'] = time;
		if (this.hScrollbar) this.hScrollbarIndicator.style[vendor + 'TransitionDuration'] = time;
		if (this.vScrollbar) this.vScrollbarIndicator.style[vendor + 'TransitionDuration'] = time;
	},

	_momentum: function (dist, time, maxDistUpper, maxDistLower, size) {
		var deceleration = 0.0006,
			speed = m.abs(dist) / time,
			newDist = (speed * speed) / (2 * deceleration),
			newTime = 0, outsideDist = 0;

		// Proportinally reduce speed if we are outside of the boundaries 
		if (dist > 0 && newDist > maxDistUpper) {
			outsideDist = size / (6 / (newDist / speed * deceleration));
			maxDistUpper = maxDistUpper + outsideDist;
			speed = speed * maxDistUpper / newDist;
			newDist = maxDistUpper;
		} else if (dist < 0 && newDist > maxDistLower) {
			outsideDist = size / (6 / (newDist / speed * deceleration));
			maxDistLower = maxDistLower + outsideDist;
			speed = speed * maxDistLower / newDist;
			newDist = maxDistLower;
		}

		newDist = newDist * (dist < 0 ? -1 : 1);
		newTime = speed / deceleration;

		return { dist: newDist, time: mround(newTime) };
	},

	_offset: function (el) {
		var left = -el.offsetLeft,
			top = -el.offsetTop;
			
		while (el = el.offsetParent) {
			left -= el.offsetLeft;
			top -= el.offsetTop;
		}
		
		if (el != this.wrapper) {
			left *= this.scale;
			top *= this.scale;
		}

		return { left: left, top: top };
	},

	_snap: function (x, y) {
		var that = this,
			i, l,
			page, time,
			sizeX, sizeY;

		// Check page X
		page = that.pagesX.length - 1;
		for (i=0, l=that.pagesX.length; i<l; i++) {
			if (x >= that.pagesX[i]) {
				page = i;
				break;
			}
		}
		if (page == that.currPageX && page > 0 && that.dirX < 0) page--;
		x = that.pagesX[page];
		sizeX = m.abs(x - that.pagesX[that.currPageX]);
		sizeX = sizeX ? m.abs(that.x - x) / sizeX * 500 : 0;
		that.currPageX = page;

		// Check page Y
		page = that.pagesY.length-1;
		for (i=0; i<page; i++) {
			if (y >= that.pagesY[i]) {
				page = i;
				break;
			}
		}
		if (page == that.currPageY && page > 0 && that.dirY < 0) page--;
		y = that.pagesY[page];
		sizeY = m.abs(y - that.pagesY[that.currPageY]);
		sizeY = sizeY ? m.abs(that.y - y) / sizeY * 500 : 0;
		that.currPageY = page;

		// Snap with constant speed (proportional duration)
		time = mround(m.max(sizeX, sizeY)) || 200;

		return { x: x, y: y, time: time };
	},

	_bind: function (type, el, bubble) {
		(el || this.scroller).addEventListener(type, this, !!bubble);
	},

	_unbind: function (type, el, bubble) {
		(el || this.scroller).removeEventListener(type, this, !!bubble);
	},


	/**
	 *
	 * Public methods
	 *
	 */
	destroy: function () {
		var that = this;

		that.scroller.style[vendor + 'Transform'] = '';

		// Remove the scrollbars
		that.hScrollbar = false;
		that.vScrollbar = false;
		that._scrollbar('h');
		that._scrollbar('v');

		// Remove the event listeners
		that._unbind(RESIZE_EV, window);
		that._unbind(START_EV);
		that._unbind(MOVE_EV);
		that._unbind(END_EV);
		that._unbind(CANCEL_EV);
		
		if (that.options.hasTouch) {
			that._unbind('mouseout', that.wrapper);
			that._unbind(WHEEL_EV);
		}
		
		if (that.options.useTransition) that._unbind('webkitTransitionEnd');
		
		if (that.options.checkDOMChanges) clearInterval(that.checkDOMTime);
		
		if (that.options.onDestroy) that.options.onDestroy.call(that);
	},

	refresh: function () {
		var that = this,
			offset,
			i, l,
			els,
			pos = 0,
			page = 0;

		if (that.scale < that.options.zoomMin) that.scale = that.options.zoomMin;
		that.wrapperW = that.wrapper.clientWidth || 1;
		that.wrapperH = that.wrapper.clientHeight || 1;

		that.minScrollY = -that.options.topOffset || 0;
		that.scrollerW = mround(that.scroller.offsetWidth * that.scale);
		that.scrollerH = mround((that.scroller.offsetHeight + that.minScrollY) * that.scale);
		that.maxScrollX = that.wrapperW - that.scrollerW;
		that.maxScrollY = that.wrapperH - that.scrollerH + that.minScrollY;
		that.dirX = 0;
		that.dirY = 0;

		if (that.options.onRefresh) that.options.onRefresh.call(that);

		that.hScroll = that.options.hScroll && that.maxScrollX < 0;
		that.vScroll = that.options.vScroll && (!that.options.bounceLock && !that.hScroll || that.scrollerH > that.wrapperH);

		that.hScrollbar = that.hScroll && that.options.hScrollbar;
		that.vScrollbar = that.vScroll && that.options.vScrollbar && that.scrollerH > that.wrapperH;

		offset = that._offset(that.wrapper);
		that.wrapperOffsetLeft = -offset.left;
		that.wrapperOffsetTop = -offset.top;

		// Prepare snap
		if (typeof that.options.snap == 'string') {
			that.pagesX = [];
			that.pagesY = [];
			els = that.scroller.querySelectorAll(that.options.snap);
			for (i=0, l=els.length; i<l; i++) {
				pos = that._offset(els[i]);
				pos.left += that.wrapperOffsetLeft;
				pos.top += that.wrapperOffsetTop;
				that.pagesX[i] = pos.left < that.maxScrollX ? that.maxScrollX : pos.left * that.scale;
				that.pagesY[i] = pos.top < that.maxScrollY ? that.maxScrollY : pos.top * that.scale;
			}
		} else if (that.options.snap) {
			that.pagesX = [];
			while (pos >= that.maxScrollX) {
				that.pagesX[page] = pos;
				pos = pos - that.wrapperW;
				page++;
			}
			if (that.maxScrollX%that.wrapperW) that.pagesX[that.pagesX.length] = that.maxScrollX - that.pagesX[that.pagesX.length-1] + that.pagesX[that.pagesX.length-1];

			pos = 0;
			page = 0;
			that.pagesY = [];
			while (pos >= that.maxScrollY) {
				that.pagesY[page] = pos;
				pos = pos - that.wrapperH;
				page++;
			}
			if (that.maxScrollY%that.wrapperH) that.pagesY[that.pagesY.length] = that.maxScrollY - that.pagesY[that.pagesY.length-1] + that.pagesY[that.pagesY.length-1];
		}

		// Prepare the scrollbars
		that._scrollbar('h');
		that._scrollbar('v');

		if (!that.zoomed) {
			that.scroller.style[vendor + 'TransitionDuration'] = '0';
			that._resetPos(200);
		}
	},

	scrollTo: function (x, y, time, relative) {
		var that = this,
			step = x,
			i, l;

		that.stop();

		if (!step.length) step = [{ x: x, y: y, time: time, relative: relative }];
		
		for (i=0, l=step.length; i<l; i++) {
			if (step[i].relative) { step[i].x = that.x - step[i].x; step[i].y = that.y - step[i].y; }
			that.steps.push({ x: step[i].x, y: step[i].y, time: step[i].time || 0 });
		}

		that._startAni();
	},

	scrollToElement: function (el, time) {
		var that = this, pos;
		el = el.nodeType ? el : that.scroller.querySelector(el);
		if (!el) return;

		pos = that._offset(el);
		pos.left += that.wrapperOffsetLeft;
		pos.top += that.wrapperOffsetTop;

		pos.left = pos.left > 0 ? 0 : pos.left < that.maxScrollX ? that.maxScrollX : pos.left;
		pos.top = pos.top > that.minScrollY ? that.minScrollY : pos.top < that.maxScrollY ? that.maxScrollY : pos.top;
		time = time === undefined ? m.max(m.abs(pos.left)*2, m.abs(pos.top)*2) : time;

		that.scrollTo(pos.left, pos.top, time);
	},

	scrollToPage: function (pageX, pageY, time) {
		var that = this, x, y;

		if (that.options.onScrollStart) that.options.onScrollStart.call(that);

		if (that.options.snap) {
			pageX = pageX == 'next' ? that.currPageX+1 : pageX == 'prev' ? that.currPageX-1 : pageX;
			pageY = pageY == 'next' ? that.currPageY+1 : pageY == 'prev' ? that.currPageY-1 : pageY;

			pageX = pageX < 0 ? 0 : pageX > that.pagesX.length-1 ? that.pagesX.length-1 : pageX;
			pageY = pageY < 0 ? 0 : pageY > that.pagesY.length-1 ? that.pagesY.length-1 : pageY;

			that.currPageX = pageX;
			that.currPageY = pageY;
			x = that.pagesX[pageX];
			y = that.pagesY[pageY];
		} else {
			x = -that.wrapperW * pageX;
			y = -that.wrapperH * pageY;
			if (x < that.maxScrollX) x = that.maxScrollX;
			if (y < that.maxScrollY) y = that.maxScrollY;
		}

		that.scrollTo(x, y, time || 400);
	},

	disable: function () {
		this.stop();
		this._resetPos(0);
		this.enabled = false;

		// If disabled after touchstart we make sure that there are no left over events
		this._unbind(MOVE_EV);
		this._unbind(END_EV);
		this._unbind(CANCEL_EV);
	},
	
	enable: function () {
		this.enabled = true;
	},
	
	stop: function () {
		if (this.options.useTransition) this._unbind('webkitTransitionEnd');
		else cancelFrame(this.aniTime);
		this.steps = [];
		this.moved = false;
		this.animating = false;
	},
	
	zoom: function (x, y, scale, time) {
		var that = this,
			relScale = scale / that.scale;

		if (!that.options.useTransform) return;

		that.zoomed = true;
		time = time === undefined ? 200 : time;
		x = x - that.wrapperOffsetLeft - that.x;
		y = y - that.wrapperOffsetTop - that.y;
		that.x = x - x * relScale + that.x;
		that.y = y - y * relScale + that.y;

		that.scale = scale;
		that.refresh();

		that.x = that.x > 0 ? 0 : that.x < that.maxScrollX ? that.maxScrollX : that.x;
		that.y = that.y > that.minScrollY ? that.minScrollY : that.y < that.maxScrollY ? that.maxScrollY : that.y;

		that.scroller.style[vendor + 'TransitionDuration'] = time + 'ms';
		that.scroller.style[vendor + 'Transform'] = trnOpen + that.x + 'px,' + that.y + 'px' + trnClose + ' scale(' + scale + ')';
		that.zoomed = false;
	},
	
	isReady: function () {
		return !this.moved && !this.zoomed && !this.animating;
	}
};

if (typeof exports !== 'undefined') exports.iScroll = iScroll;
else window.iScroll = iScroll;

})();

// file: jquery-mobile-10-define.js
// creates the define method on window, only used where async loading
// is not desired in the docs and experiments
window.define = function() {
	Array.prototype.slice.call( arguments ).pop()( window.jQuery );
};

// file: jquery-mobile-20-ns.js
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: The mobile namespace on the jQuery object
//>>label: Namespace
//>>group: Core
define([ "jquery" ], function( jQuery ) {
(function( $ ) {
	$.mobile = {};
}( jQuery ));
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");
// file: jquery-mobile-30-support-touch.js
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Touch feature test
//>>label: Touch support test
//>>group: Core

define( [ "jquery", "./jquery.mobile.ns" ], function( jQuery ) {
//>>excludeEnd("jqmBuildExclude");
	(function( $, undefined ) {
		var support = {
			touch: "ontouchend" in document
		};

		$.mobile.support = $.mobile.support || {};
		$.extend( $.support, support );
		$.extend( $.mobile.support, support );
	}( jQuery ));
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");

// file: jquery-mobile-40-vmouse.js

// This plugin is an experiment for abstracting away the touch and mouse
// events so that developers don't have to worry about which method of input
// the device their document is loaded on supports.
//
// The idea here is to allow the developer to register listeners for the
// basic mouse events, such as mousedown, mousemove, mouseup, and click,
// and the plugin will take care of registering the correct listeners
// behind the scenes to invoke the listener at the fastest possible time
// for that device, while still retaining the order of event firing in
// the traditional mouse environment, should multiple handlers be registered
// on the same element for different events.
//
// The current version exposes the following virtual events to jQuery bind methods:
// "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel"

//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Normalizes touch/mouse events.
//>>label: Virtual Mouse (vmouse) Bindings
//>>group: Core

define( [ "jquery" ], function( jQuery ) {
//>>excludeEnd("jqmBuildExclude");
(function( $, window, document, undefined ) {

var lastTouchTime=0;
var dataPropertyName = "virtualMouseBindings",
	touchTargetPropertyName = "virtualTouchID",
	virtualEventNames = "vmouseover vmousedown vmousemove vmouseup vclick vmouseout vmousecancel".split( " " ),
	touchEventProps = "clientX clientY pageX pageY screenX screenY".split( " " ),
	mouseHookProps = $.event.mouseHooks ? $.event.mouseHooks.props : [],
	mouseEventProps = $.event.props.concat( mouseHookProps ),
	activeDocHandlers = {},
	resetTimerID = 0,
	startX = 0,
	startY = 0,
	didScroll = false,
	clickBlockList = [],
	blockMouseTriggers = false,
	blockTouchTriggers = false,
	eventCaptureSupported = "addEventListener" in document,
	$document = $( document ),
	nextTouchID = 1,
	lastTouchID = 0, threshold;

$.vmouse = {
	moveDistanceThreshold: 10,
	clickDistanceThreshold: 10,
	resetTimerDuration: 1500
};

function getNativeEvent( event ) {

	while ( event && typeof event.originalEvent !== "undefined" ) {
		event = event.originalEvent;
	}
	return event;
}

function createVirtualEvent( event, eventType ) {

	var t = event.type,
		oe, props, ne, prop, ct, touch, i, j, len;

	event = $.Event( event );
	event.type = eventType;

	oe = event.originalEvent;
	props = $.event.props;

	// addresses separation of $.event.props in to $.event.mouseHook.props and Issue 3280
	// https://github.com/jquery/jquery-mobile/issues/3280
	if ( t.search( /^(mouse|click)/ ) > -1 ) {
		props = mouseEventProps;
	}

	// copy original event properties over to the new event
	// this would happen if we could call $.event.fix instead of $.Event
	// but we don't have a way to force an event to be fixed multiple times
	if ( oe ) {
		for ( i = props.length, prop; i; ) {
			prop = props[ --i ];
			event[ prop ] = oe[ prop ];
		}
	}

	// make sure that if the mouse and click virtual events are generated
	// without a .which one is defined
	if ( t.search(/mouse(down|up)|click/) > -1 && !event.which ) {
		event.which = 1;
	}

	if ( t.search(/^touch/) !== -1 ) {
		ne = getNativeEvent( oe );
		t = ne.touches;
		ct = ne.changedTouches;
		touch = ( t && t.length ) ? t[0] : ( ( ct && ct.length ) ? ct[ 0 ] : undefined );

		if ( touch ) {
			for ( j = 0, len = touchEventProps.length; j < len; j++) {
				prop = touchEventProps[ j ];
				event[ prop ] = touch[ prop ];
			}
		}
	}

	return event;
}

function getVirtualBindingFlags( element ) {

	var flags = {},
		b, k;

	while ( element ) {

		b = $.data( element, dataPropertyName );

		for (  k in b ) {
			if ( b[ k ] ) {
				flags[ k ] = flags.hasVirtualBinding = true;
			}
		}
		element = element.parentNode;
	}
	return flags;
}

function getClosestElementWithVirtualBinding( element, eventType ) {
	var b;
	while ( element ) {

		b = $.data( element, dataPropertyName );

		if ( b && ( !eventType || b[ eventType ] ) ) {
			return element;
		}
		element = element.parentNode;
	}
	return null;
}

function enableTouchBindings() {
	blockTouchTriggers = false;
}

function disableTouchBindings() {
	blockTouchTriggers = true;
}

function enableMouseBindings() {
	lastTouchID = 0;
	clickBlockList.length = 0;
	blockMouseTriggers = false;

	// When mouse bindings are enabled, our
	// touch bindings are disabled.
	disableTouchBindings();
}

function disableMouseBindings() {
	// When mouse bindings are disabled, our
	// touch bindings are enabled.
	enableTouchBindings();
}

function startResetTimer() {
	clearResetTimer();
	resetTimerID = setTimeout( function() {
		resetTimerID = 0;
		enableMouseBindings();
	}, $.vmouse.resetTimerDuration );
}

function clearResetTimer() {
	if ( resetTimerID ) {
		clearTimeout( resetTimerID );
		resetTimerID = 0;
	}
}

function triggerVirtualEvent( eventType, event, flags ) {
    var ve;
    //TERSUS:
    // Workaround for problem where 'click' events are fired on right-click (moz only)
    if ($.browser.mozilla && event.type == 'click' && event.button == 2)
	    return;
    // Workaround for duplicate triggering of 'vclick' when DOM changes (jQuery mobile fails to ignore the 'click' event when the element on which the touch was started is different from the on which it ends)
    // Our work-around: if the original evant is a click, and we've seen a touch event in the past second, we assume the click event is a virtual generated by the browser based on a touch gestrure
    // and so we ignore it
    if (eventType=='vclick' && event.type=='click' && ((new Date()).getTime() - lastTouchTime < 1000) )
	return;
    //END TERSUS
    
    //Workaround for 'vclick' firing on disabled buttons
    if (eventType =='vclick' && event.target.disabled)
	return;
    
    if ( ( flags && flags[ eventType ] ) ||
	 ( !flags && getClosestElementWithVirtualBinding( event.target, eventType ) ) ) {
	
	ve = createVirtualEvent( event, eventType );
	
	$( event.target).trigger( ve );
    }

    return ve;
}

function mouseEventCallback( event ) {
	var touchID = $.data( event.target, touchTargetPropertyName );

	if ( !blockMouseTriggers && ( !lastTouchID || lastTouchID !== touchID ) ) {
		var ve = triggerVirtualEvent( "v" + event.type, event );
		if ( ve ) {
			if ( ve.isDefaultPrevented() ) {
				event.preventDefault();
			}
			if ( ve.isPropagationStopped() ) {
				event.stopPropagation();
			}
			if ( ve.isImmediatePropagationStopped() ) {
				event.stopImmediatePropagation();
			}
		}
	}
}

function handleTouchStart( event ) {

	var touches = getNativeEvent( event ).touches,
		target, flags;

	if ( touches && touches.length === 1 ) {

		target = event.target;
		flags = getVirtualBindingFlags( target );

		if ( flags.hasVirtualBinding ) {

			lastTouchID = nextTouchID++;
			$.data( target, touchTargetPropertyName, lastTouchID );

			clearResetTimer();

			disableMouseBindings();
			didScroll = false;

			var t = getNativeEvent( event ).touches[ 0 ];
			startX = t.pageX;
			startY = t.pageY;

			triggerVirtualEvent( "vmouseover", event, flags );
			triggerVirtualEvent( "vmousedown", event, flags );
		}
	}
}

function handleScroll( event ) {
	if ( blockTouchTriggers ) {
		return;
	}

	if ( !didScroll ) {
		triggerVirtualEvent( "vmousecancel", event, getVirtualBindingFlags( event.target ) );
	}

	didScroll = true;
	startResetTimer();
}

function handleTouchMove( event ) {
	if ( blockTouchTriggers ) {
		return;
	}

	var t = getNativeEvent( event ).touches[ 0 ],
		didCancel = didScroll,
		moveThreshold = $.vmouse.moveDistanceThreshold,
		flags = getVirtualBindingFlags( event.target );

		didScroll = didScroll ||
			( Math.abs( t.pageX - startX ) > moveThreshold ||
				Math.abs( t.pageY - startY ) > moveThreshold );


	if ( didScroll && !didCancel ) {
		triggerVirtualEvent( "vmousecancel", event, flags );
	}

	triggerVirtualEvent( "vmousemove", event, flags );
	startResetTimer();
}

function handleTouchEnd( event ) {
	if ( blockTouchTriggers ) {
		return;
	}
        lastTouchTime = (new Date()).getTime();

	disableTouchBindings();

	var flags = getVirtualBindingFlags( event.target ),
		t;
	triggerVirtualEvent( "vmouseup", event, flags );

	if ( !didScroll ) {
		var ve = triggerVirtualEvent( "vclick", event, flags );
		if ( ve && ve.isDefaultPrevented() ) {
			// The target of the mouse events that follow the touchend
			// event don't necessarily match the target used during the
			// touch. This means we need to rely on coordinates for blocking
			// any click that is generated.
			t = getNativeEvent( event ).changedTouches[ 0 ];
			clickBlockList.push({
				touchID: lastTouchID,
				x: t.clientX,
				y: t.clientY
			});

			// Prevent any mouse events that follow from triggering
			// virtual event notifications.
			blockMouseTriggers = true;
		}
	}
	triggerVirtualEvent( "vmouseout", event, flags);
	didScroll = false;

	startResetTimer();
}

function hasVirtualBindings( ele ) {
	var bindings = $.data( ele, dataPropertyName ),
		k;

	if ( bindings ) {
		for ( k in bindings ) {
			if ( bindings[ k ] ) {
				return true;
			}
		}
	}
	return false;
}

function dummyMouseHandler() {}

function getSpecialEventObject( eventType ) {
	var realType = eventType.substr( 1 );

	return {
		setup: function( data, namespace ) {
			// If this is the first virtual mouse binding for this element,
			// add a bindings object to its data.

			if ( !hasVirtualBindings( this ) ) {
				$.data( this, dataPropertyName, {} );
			}

			// If setup is called, we know it is the first binding for this
			// eventType, so initialize the count for the eventType to zero.
			var bindings = $.data( this, dataPropertyName );
			bindings[ eventType ] = true;

			// If this is the first virtual mouse event for this type,
			// register a global handler on the document.

			activeDocHandlers[ eventType ] = ( activeDocHandlers[ eventType ] || 0 ) + 1;

			if ( activeDocHandlers[ eventType ] === 1 ) {
				$document.bind( realType, mouseEventCallback );
			}

			// Some browsers, like Opera Mini, won't dispatch mouse/click events
			// for elements unless they actually have handlers registered on them.
			// To get around this, we register dummy handlers on the elements.

			$( this ).bind( realType, dummyMouseHandler );

			// For now, if event capture is not supported, we rely on mouse handlers.
			if ( eventCaptureSupported ) {
				// If this is the first virtual mouse binding for the document,
				// register our touchstart handler on the document.

				activeDocHandlers[ "touchstart" ] = ( activeDocHandlers[ "touchstart" ] || 0) + 1;

				if ( activeDocHandlers[ "touchstart" ] === 1 ) {
					$document.bind( "touchstart", handleTouchStart )
						.bind( "touchend", handleTouchEnd )

						// On touch platforms, touching the screen and then dragging your finger
						// causes the window content to scroll after some distance threshold is
						// exceeded. On these platforms, a scroll prevents a click event from being
						// dispatched, and on some platforms, even the touchend is suppressed. To
						// mimic the suppression of the click event, we need to watch for a scroll
						// event. Unfortunately, some platforms like iOS don't dispatch scroll
						// events until *AFTER* the user lifts their finger (touchend). This means
						// we need to watch both scroll and touchmove events to figure out whether
						// or not a scroll happenens before the touchend event is fired.

						.bind( "touchmove", handleTouchMove )
						.bind( "scroll", handleScroll );
				}
			}
		},

		teardown: function( data, namespace ) {
			// If this is the last virtual binding for this eventType,
			// remove its global handler from the document.

			--activeDocHandlers[ eventType ];

			if ( !activeDocHandlers[ eventType ] ) {
				$document.unbind( realType, mouseEventCallback );
			}

			if ( eventCaptureSupported ) {
				// If this is the last virtual mouse binding in existence,
				// remove our document touchstart listener.

				--activeDocHandlers[ "touchstart" ];

				if ( !activeDocHandlers[ "touchstart" ] ) {
					$document.unbind( "touchstart", handleTouchStart )
						.unbind( "touchmove", handleTouchMove )
						.unbind( "touchend", handleTouchEnd )
						.unbind( "scroll", handleScroll );
				}
			}

			var $this = $( this ),
				bindings = $.data( this, dataPropertyName );

			// teardown may be called when an element was
			// removed from the DOM. If this is the case,
			// jQuery core may have already stripped the element
			// of any data bindings so we need to check it before
			// using it.
			if ( bindings ) {
				bindings[ eventType ] = false;
			}

			// Unregister the dummy event handler.

			$this.unbind( realType, dummyMouseHandler );

			// If this is the last virtual mouse binding on the
			// element, remove the binding data from the element.

			if ( !hasVirtualBindings( this ) ) {
				$this.removeData( dataPropertyName );
			}
		}
	};
}

// Expose our custom events to the jQuery bind/unbind mechanism.

for ( var i = 0; i < virtualEventNames.length; i++ ) {
	$.event.special[ virtualEventNames[ i ] ] = getSpecialEventObject( virtualEventNames[ i ] );
}

// Add a capture click handler to block clicks.
// Note that we require event capture support for this so if the device
// doesn't support it, we punt for now and rely solely on mouse events.
if ( eventCaptureSupported ) {
	document.addEventListener( "click", function( e ) {
		var cnt = clickBlockList.length,
			target = e.target,
			x, y, ele, i, o, touchID;

		if ( cnt ) {
			x = e.clientX;
			y = e.clientY;
			threshold = $.vmouse.clickDistanceThreshold;

			// The idea here is to run through the clickBlockList to see if
			// the current click event is in the proximity of one of our
			// vclick events that had preventDefault() called on it. If we find
			// one, then we block the click.
			//
			// Why do we have to rely on proximity?
			//
			// Because the target of the touch event that triggered the vclick
			// can be different from the target of the click event synthesized
			// by the browser. The target of a mouse/click event that is syntehsized
			// from a touch event seems to be implementation specific. For example,
			// some browsers will fire mouse/click events for a link that is near
			// a touch event, even though the target of the touchstart/touchend event
			// says the user touched outside the link. Also, it seems that with most
			// browsers, the target of the mouse/click event is not calculated until the
			// time it is dispatched, so if you replace an element that you touched
			// with another element, the target of the mouse/click will be the new
			// element underneath that point.
			//
			// Aside from proximity, we also check to see if the target and any
			// of its ancestors were the ones that blocked a click. This is necessary
			// because of the strange mouse/click target calculation done in the
			// Android 2.1 browser, where if you click on an element, and there is a
			// mouse/click handler on one of its ancestors, the target will be the
			// innermost child of the touched element, even if that child is no where
			// near the point of touch.

			ele = target;

			while ( ele ) {
				for ( i = 0; i < cnt; i++ ) {
					o = clickBlockList[ i ];
					touchID = 0;

					if ( ( ele === target && Math.abs( o.x - x ) < threshold && Math.abs( o.y - y ) < threshold ) ||
								$.data( ele, touchTargetPropertyName ) === o.touchID ) {
						// XXX: We may want to consider removing matches from the block list
						//      instead of waiting for the reset timer to fire.
						e.preventDefault();
						e.stopPropagation();
						return;
					}
				}
				ele = ele.parentNode;
			}
		}
	}, true);
}
})( jQuery, window, document );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");

// file: jquery-mobile-50-touch.js
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
//>>description: Touch events including: touchstart, touchmove, touchend, tap, taphold, swipe, swipeleft, swiperight, swipeup, swipedown, scrollstart, scrollstop
//>>label: Touch
//>>group: Events

define( [ "jquery", "../jquery.mobile.vmouse", "../jquery.mobile.support.touch" ], function( jQuery ) {
//>>excludeEnd("jqmBuildExclude");

(function( $, window, undefined ) {
	var $document = $( document );

	// add new event shortcuts
	$.each( ( "touchstart touchmove touchend " +
		"tap taphold " +
		"swipe swipeleft swiperight swipeup swipedown" +
		"scrollstart scrollstop" ).split( " " ), function( i, name ) {

		$.fn[ name ] = function( fn ) {
			return fn ? this.bind( name, fn ) : this.trigger( name );
		};

		// jQuery < 1.8
		if ( $.attrFn ) {
			$.attrFn[ name ] = true;
		}
	});

	var supportTouch = $.mobile.support.touch,
		scrollEvent = "touchmove scroll",
		touchStartEvent = supportTouch ? "touchstart" : "mousedown",
		touchStopEvent = supportTouch ? "touchend" : "mouseup",
		touchMoveEvent = supportTouch ? "touchmove" : "mousemove";

	function triggerCustomEvent( obj, eventType, event ) {
		var originalType = event.type;
		event.type = eventType;
		$.event.dispatch.call( obj, event );
		event.type = originalType;
	}

	// also handles scrollstop
	$.event.special.scrollstart = {

		enabled: true,

		setup: function() {

			var thisObject = this,
				$this = $( thisObject ),
				scrolling,
				timer;

			function trigger( event, state ) {
				scrolling = state;
				triggerCustomEvent( thisObject, scrolling ? "scrollstart" : "scrollstop", event );
			}

			// iPhone triggers scroll after a small delay; use touchmove instead
			$this.bind( scrollEvent, function( event ) {

				if ( !$.event.special.scrollstart.enabled ) {
					return;
				}

				if ( !scrolling ) {
					trigger( event, true );
				}

				clearTimeout( timer );
				timer = setTimeout( function() {
					trigger( event, false );
				}, 50 );
			});
		}
	};

	// also handles taphold
	$.event.special.tap = {
		tapholdThreshold: 750,

		setup: function() {
			var thisObject = this,
				$this = $( thisObject );

			$this.bind( "vmousedown", function( event ) {

				if ( event.which && event.which !== 1 ) {
					return false;
				}

				var origTarget = event.target,
					origEvent = event.originalEvent,
					timer;

				function clearTapTimer() {
					clearTimeout( timer );
				}

				function clearTapHandlers() {
					clearTapTimer();

					$this.unbind( "vclick", clickHandler )
						.unbind( "vmouseup", clearTapTimer );
					$document.unbind( "vmousecancel", clearTapHandlers );
                    $document.unbind( "vmousemove", clearTapHandlers );
                    $this.find('*').add($this).add($this.parents()).unbind("scroll",clearTapHandlers);
				}
				

				function clickHandler( event ) {
					clearTapHandlers();

					// ONLY trigger a 'tap' event if the start target is
					// the same as the stop target.
					if ( origTarget === event.target ) {
						triggerCustomEvent( thisObject, "tap", event );
					}
				}

				$this.bind( "vmouseup", clearTapTimer )
					.bind( "vclick", clickHandler );
				$document.bind( "vmousecancel", clearTapHandlers );
				$document.bind("vmousemove", clearTapHandlers);
				$this.find('*').add($this).add($this.parents()).bind("scroll",clearTapHandlers);
                

				timer = setTimeout( function() {
					triggerCustomEvent( thisObject, "taphold", $.Event( "taphold", { target: origTarget } ) );
				}, $.event.special.tap.tapholdThreshold );
			});
		}
	};

	// also handles swipeleft, swiperight, swipeup, swipedown
	$.event.special.swipe = {
		scrollSupressionThreshold: 30, // More than this horizontal displacement, and we will suppress scrolling.

		durationThreshold: 1000, // More time than this, and it isn't a swipe.

		primaryAxisDistanceThreshold: 30,  // Swipe horizontal displacement must be more than this.

		secondaryAxisDistanceThreshold: 75,  // Swipe vertical displacement must be less than this.

		start: function( event ) {
			var data = event.originalEvent.touches ?
					event.originalEvent.touches[ 0 ] : event;
			return {
						time: ( new Date() ).getTime(),
						coords: [ data.pageX, data.pageY ],
						origin: $( event.target )
					};
		},

		stop: function( event ) {
			var data = event.originalEvent.touches ?
					event.originalEvent.touches[ 0 ] : event;
			return {
						time: ( new Date() ).getTime(),
						coords: [ data.pageX, data.pageY ]
					};
		},

		handleSwipe: function( start, stop ) {
			if ( stop.time - start.time < $.event.special.swipe.durationThreshold)
			{
				var horizontalDistance = Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] );
				var verticalDistance = Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] )
				if ( horizontalDistance > $.event.special.swipe.primaryAxisDistanceThreshold &&
						verticalDistance < $.event.special.swipe.secondaryAxisDistanceThreshold )
					start.origin.trigger( "swipe" )
						.trigger( start.coords[0] > stop.coords[0] ? "swipeleft" : "swiperight" )
				else
					if ( verticalDistance > $.event.special.swipe.primaryAxisDistanceThreshold &&
							horizontalDistance < $.event.special.swipe.secondaryAxisDistanceThreshold )
						start.origin.trigger( "swipe" )
							.trigger( start.coords[1] > stop.coords[1] ? "swipeup" : "swipedown" )
					else
						start.origin.trigger( "swipe" );										
			}
		},

		setup: function() {
			var thisObject = this,
				$this = $( thisObject );

			$this.bind( touchStartEvent, function( event ) {
				var start = $.event.special.swipe.start( event ),
					stop;

				function moveHandler( event ) {
					if ( !start ) {
						return;
					}

					stop = $.event.special.swipe.stop( event );

					// prevent scrolling
					if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) {
						event.preventDefault();
					}
				}

				$this.bind( touchMoveEvent, moveHandler )
					.one( touchStopEvent, function() {
						$this.unbind( touchMoveEvent, moveHandler );

						if ( start && stop ) {
							$.event.special.swipe.handleSwipe( start, stop );
						}
						start = stop = undefined;
					});
			});
		}
	};
	$.each({
		scrollstop: "scrollstart",
		taphold: "tap",
		swipeleft: "swipe",
		swiperight: "swipe",
		swipeup: "swipe",
		swipedown: "swipe"
	}, function( event, sourceEvent ) {

		$.event.special[ event ] = {
			setup: function() {
				$( this ).bind( sourceEvent, $.noop );
			}
		};
	});

})( jQuery, this );
//>>excludeStart("jqmBuildExclude", pragmas.jqmBuildExclude);
});
//>>excludeEnd("jqmBuildExclude");

// file: json2.js
/*
    http://www.JSON.org/json2.js
    2011-02-23

    Public Domain.

    NO WARRANTY EXPRESSED OR IMPLIED. USE AT YOUR OWN RISK.

    See http://www.JSON.org/js.html


    This code should be minified before deployment.
    See http://javascript.crockford.com/jsmin.html

    USE YOUR OWN COPY. IT IS EXTREMELY UNWISE TO LOAD CODE FROM SERVERS YOU DO
    NOT CONTROL.


    This file creates a global JSON object containing two methods: stringify
    and parse.

        JSON.stringify(value, replacer, space)
            value       any JavaScript value, usually an object or array.

            replacer    an optional parameter that determines how object
                        values are stringified for objects. It can be a
                        function or an array of strings.

            space       an optional parameter that specifies the indentation
                        of nested structures. If it is omitted, the text will
                        be packed without extra whitespace. If it is a number,
                        it will specify the number of spaces to indent at each
                        level. If it is a string (such as '\t' or '&nbsp;'),
                        it contains the characters used to indent at each level.

            This method produces a JSON text from a JavaScript value.

            When an object value is found, if the object contains a toJSON
            method, its toJSON method will be called and the result will be
            stringified. A toJSON method does not serialize: it returns the
            value represented by the name/value pair that should be serialized,
            or undefined if nothing should be serialized. The toJSON method
            will be passed the key associated with the value, and this will be
            bound to the value

            For example, this would serialize Dates as ISO strings.

                Date.prototype.toJSON = function (key) {
                    function f(n) {
                        // Format integers to have at least two digits.
                        return n < 10 ? '0' + n : n;
                    }

                    return this.getUTCFullYear()   + '-' +
                         f(this.getUTCMonth() + 1) + '-' +
                         f(this.getUTCDate())      + 'T' +
                         f(this.getUTCHours())     + ':' +
                         f(this.getUTCMinutes())   + ':' +
                         f(this.getUTCSeconds())   + 'Z';
                };

            You can provide an optional replacer method. It will be passed the
            key and value of each member, with this bound to the containing
            object. The value that is returned from your method will be
            serialized. If your method returns undefined, then the member will
            be excluded from the serialization.

            If the replacer parameter is an array of strings, then it will be
            used to select the members to be serialized. It filters the results
            such that only members with keys listed in the replacer array are
            stringified.

            Values that do not have JSON representations, such as undefined or
            functions, will not be serialized. Such values in objects will be
            dropped; in arrays they will be replaced with null. You can use
            a replacer function to replace those with JSON values.
            JSON.stringify(undefined) returns undefined.

            The optional space parameter produces a stringification of the
            value that is filled with line breaks and indentation to make it
            easier to read.

            If the space parameter is a non-empty string, then that string will
            be used for indentation. If the space parameter is a number, then
            the indentation will be that many spaces.

            Example:

            text = JSON.stringify(['e', {pluribus: 'unum'}]);
            // text is '["e",{"pluribus":"unum"}]'


            text = JSON.stringify(['e', {pluribus: 'unum'}], null, '\t');
            // text is '[\n\t"e",\n\t{\n\t\t"pluribus": "unum"\n\t}\n]'

            text = JSON.stringify([new Date()], function (key, value) {
                return this[key] instanceof Date ?
                    'Date(' + this[key] + ')' : value;
            });
            // text is '["Date(---current time---)"]'


        JSON.parse(text, reviver)
            This method parses a JSON text to produce an object or array.
            It can throw a SyntaxError exception.

            The optional reviver parameter is a function that can filter and
            transform the results. It receives each of the keys and values,
            and its return value is used instead of the original value.
            If it returns what it received, then the structure is not modified.
            If it returns undefined then the member is deleted.

            Example:

            // Parse the text. Values that look like ISO date strings will
            // be converted to Date objects.

            myData = JSON.parse(text, function (key, value) {
                var a;
                if (typeof value === 'string') {
                    a =
/^(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2}(?:\.\d*)?)Z$/.exec(value);
                    if (a) {
                        return new Date(Date.UTC(+a[1], +a[2] - 1, +a[3], +a[4],
                            +a[5], +a[6]));
                    }
                }
                return value;
            });

            myData = JSON.parse('["Date(09/09/2001)"]', function (key, value) {
                var d;
                if (typeof value === 'string' &&
                        value.slice(0, 5) === 'Date(' &&
                        value.slice(-1) === ')') {
                    d = new Date(value.slice(5, -1));
                    if (d) {
                        return d;
                    }
                }
                return value;
            });


    This is a reference implementation. You are free to copy, modify, or
    redistribute.
*/

/*jslint evil: true, strict: false, regexp: false */

/*members "", "\b", "\t", "\n", "\f", "\r", "\"", JSON, "\\", apply,
    call, charCodeAt, getUTCDate, getUTCFullYear, getUTCHours,
    getUTCMinutes, getUTCMonth, getUTCSeconds, hasOwnProperty, join,
    lastIndex, length, parse, prototype, push, replace, slice, stringify,
    test, toJSON, toString, valueOf
*/


// Create a JSON object only if one does not already exist. We create the
// methods in a closure to avoid creating global variables.

var JSON;
if (!JSON) {
    JSON = {};
}

(function () {
    "use strict";

    function f(n) {
        // Format integers to have at least two digits.
        return n < 10 ? '0' + n : n;
    }

    if (typeof Date.prototype.toJSON !== 'function') {

        Date.prototype.toJSON = function (key) {

            return isFinite(this.valueOf()) ?
                this.getUTCFullYear()     + '-' +
                f(this.getUTCMonth() + 1) + '-' +
                f(this.getUTCDate())      + 'T' +
                f(this.getUTCHours())     + ':' +
                f(this.getUTCMinutes())   + ':' +
                f(this.getUTCSeconds())   + 'Z' : null;
        };

        String.prototype.toJSON      =
            Number.prototype.toJSON  =
            Boolean.prototype.toJSON = function (key) {
                return this.valueOf();
            };
    }

    var cx = /[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        escapable = /[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,
        gap,
        indent,
        meta = {    // table of character substitutions
            '\b': '\\b',
            '\t': '\\t',
            '\n': '\\n',
            '\f': '\\f',
            '\r': '\\r',
            '"' : '\\"',
            '\\': '\\\\'
        },
        rep;


    function quote(string) {

// If the string contains no control characters, no quote characters, and no
// backslash characters, then we can safely slap some quotes around it.
// Otherwise we must also replace the offending characters with safe escape
// sequences.

        escapable.lastIndex = 0;
        return escapable.test(string) ? '"' + string.replace(escapable, function (a) {
            var c = meta[a];
            return typeof c === 'string' ? c :
                '\\u' + ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
        }) + '"' : '"' + string + '"';
    }


    function str(key, holder) {

// Produce a string from holder[key].

        var i,          // The loop counter.
            k,          // The member key.
            v,          // The member value.
            length,
            mind = gap,
            partial,
            value = holder[key];

// If the value has a toJSON method, call it to obtain a replacement value.

        if (value && typeof value === 'object' &&
                typeof value.toJSON === 'function') {
            value = value.toJSON(key);
        }

// If we were called with a replacer function, then call the replacer to
// obtain a replacement value.

        if (typeof rep === 'function') {
            value = rep.call(holder, key, value);
        }

// What happens next depends on the value's type.

        switch (typeof value) {
        case 'string':
            return quote(value);

        case 'number':

// JSON numbers must be finite. Encode non-finite numbers as null.

            return isFinite(value) ? String(value) : 'null';

        case 'boolean':
        case 'null':

// If the value is a boolean or null, convert it to a string. Note:
// typeof null does not produce 'null'. The case is included here in
// the remote chance that this gets fixed someday.

            return String(value);

// If the type is 'object', we might be dealing with an object or an array or
// null.

        case 'object':

// Due to a specification blunder in ECMAScript, typeof null is 'object',
// so watch out for that case.

            if (!value) {
                return 'null';
            }

// Make an array to hold the partial results of stringifying this object value.

            gap += indent;
            partial = [];

// Is the value an array?

            if (Object.prototype.toString.apply(value) === '[object Array]') {

// The value is an array. Stringify every element. Use null as a placeholder
// for non-JSON values.

                length = value.length;
                for (i = 0; i < length; i += 1) {
                    partial[i] = str(i, value) || 'null';
                }

// Join all of the elements together, separated with commas, and wrap them in
// brackets.

                v = partial.length === 0 ? '[]' : gap ?
                    '[\n' + gap + partial.join(',\n' + gap) + '\n' + mind + ']' :
                    '[' + partial.join(',') + ']';
                gap = mind;
                return v;
            }

// If the replacer is an array, use it to select the members to be stringified.

            if (rep && typeof rep === 'object') {
                length = rep.length;
                for (i = 0; i < length; i += 1) {
                    if (typeof rep[i] === 'string') {
                        k = rep[i];
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            } else {

// Otherwise, iterate through all of the keys in the object.

                for (k in value) {
                    if (Object.prototype.hasOwnProperty.call(value, k)) {
                        v = str(k, value);
                        if (v) {
                            partial.push(quote(k) + (gap ? ': ' : ':') + v);
                        }
                    }
                }
            }

// Join all of the member texts together, separated with commas,
// and wrap them in braces.

            v = partial.length === 0 ? '{}' : gap ?
                '{\n' + gap + partial.join(',\n' + gap) + '\n' + mind + '}' :
                '{' + partial.join(',') + '}';
            gap = mind;
            return v;
        }
    }

// If the JSON object does not yet have a stringify method, give it one.

    if (typeof JSON.stringify !== 'function') {
        JSON.stringify = function (value, replacer, space) {

// The stringify method takes a value and an optional replacer, and an optional
// space parameter, and returns a JSON text. The replacer can be a function
// that can replace values, or an array of strings that will select the keys.
// A default replacer method can be provided. Use of the space parameter can
// produce text that is more easily readable.

            var i;
            gap = '';
            indent = '';

// If the space parameter is a number, make an indent string containing that
// many spaces.

            if (typeof space === 'number') {
                for (i = 0; i < space; i += 1) {
                    indent += ' ';
                }

// If the space parameter is a string, it will be used as the indent string.

            } else if (typeof space === 'string') {
                indent = space;
            }

// If there is a replacer, it must be a function or an array.
// Otherwise, throw an error.

            rep = replacer;
            if (replacer && typeof replacer !== 'function' &&
                    (typeof replacer !== 'object' ||
                    typeof replacer.length !== 'number')) {
                throw new Error('JSON.stringify');
            }

// Make a fake root object containing our value under the key of ''.
// Return the result of stringifying the value.

            return str('', {'': value});
        };
    }


// If the JSON object does not yet have a parse method, give it one.

    if (typeof JSON.parse !== 'function') {
        JSON.parse = function (text, reviver) {

// The parse method takes a text and an optional reviver function, and returns
// a JavaScript value if the text is a valid JSON text.

            var j;

            function walk(holder, key) {

// The walk method is used to recursively walk the resulting structure so
// that modifications can be made.

                var k, v, value = holder[key];
                if (value && typeof value === 'object') {
                    for (k in value) {
                        if (Object.prototype.hasOwnProperty.call(value, k)) {
                            v = walk(value, k);
                            if (v !== undefined) {
                                value[k] = v;
                            } else {
                                delete value[k];
                            }
                        }
                    }
                }
                return reviver.call(holder, key, value);
            }


// Parsing happens in four stages. In the first stage, we replace certain
// Unicode characters with escape sequences. JavaScript handles many characters
// incorrectly, either silently deleting them, or treating them as line endings.

            text = String(text);
            cx.lastIndex = 0;
            if (cx.test(text)) {
                text = text.replace(cx, function (a) {
                    return '\\u' +
                        ('0000' + a.charCodeAt(0).toString(16)).slice(-4);
                });
            }

// In the second stage, we run the text against regular expressions that look
// for non-JSON patterns. We are especially concerned with '()' and 'new'
// because they can cause invocation, and '=' because it can cause mutation.
// But just to be safe, we want to reject all unexpected forms.

// We split the second stage into 4 regexp operations in order to work around
// crippling inefficiencies in IE's and Safari's regexp engines. First we
// replace the JSON backslash pairs with '@' (a non-JSON character). Second, we
// replace all simple value tokens with ']' characters. Third, we delete all
// open brackets that follow a colon or comma or that begin the text. Finally,
// we look to see that the remaining characters are only whitespace or ']' or
// ',' or ':' or '{' or '}'. If that is so, then the text is safe for eval.

            if (/^[\],:{}\s]*$/
                    .test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g, '@')
                        .replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g, ']')
                        .replace(/(?:^|:|,)(?:\s*\[)+/g, ''))) {

// In the third stage we use the eval function to compile the text into a
// JavaScript structure. The '{' operator is subject to a syntactic ambiguity
// in JavaScript: it can begin a block or an object literal. We wrap the text
// in parens to eliminate the ambiguity.

                j = eval('(' + text + ')');

// In the optional fourth stage, we recursively walk the new structure, passing
// each name/value pair to a reviver function for possible transformation.

                return typeof reviver === 'function' ?
                    walk({'': j}, '') : j;
            }

// If the text is not JSON parseable, then a SyntaxError is thrown.

            throw new SyntaxError('JSON.parse');
        };
    }
}());

// file: onshake.iphone.js
tersus.handleShake = function()
{
	tersus.invokeAction('<On Shake>');
}

// file: remote-debugging.js
tersus.weinre = function(promptForPort, userid, host)
{
	userid = userid || 'anonymous';

	if (!host)
	{
	    var host = document.domain;
    	var serverHost = tersus.serverURL ? tersus.serverURL.match(/\/\/([^:/]+)[:/]/)[1] : null;
    	if (serverHost != null)
            host=serverHost;
    }
    var port = 8999;
    if (promptForPort)
    	port = prompt("Weinre port number",port);
//    alert('Remote debugging with host:'+host + ' port:'+port+ ' user:'+userid);
    tersus.loadScript("http://"+host+":"+port+"/target/target-script-min.js#"+userid);
};

// file: scroll.js
$(function(){setTimeout(function() {window.scrollTo(0, 1)}, 100);})
// file: settings.js
// Overload 
// file: spinning_wheels.webkit.mobile.non-simulator.js
/**
 * 
 * Find more about the Spinning Wheel function at
 * http://cubiq.org/spinning-wheel-on-webkit-for-iphone-ipod-touch/11
 *
 * Copyright (c) 2009 Matteo Spinelli, http://cubiq.org/
 * Released under MIT license
 * http://cubiq.org/dropbox/mit-license.txt
 * 
 * Version 1.4 - Last updated: 2009.07.09
 * 
 */

var SpinningWheel = {
	cellHeight: 44,
	friction: 0.003,
	slotData: [],


	/**
	 *
	 * Event handler
	 *
	 */

	handleEvent: function (e) {
		if (e.type == 'touchstart') {
			this.lockScreen(e);
			if (e.currentTarget.id == 'sw-cancel' || e.currentTarget.id == 'sw-done') {
				this.tapDown(e);
			} else if (e.currentTarget.id == 'sw-frame') {
				this.scrollStart(e);
			}
		} else if (e.type == 'touchmove') {
			this.lockScreen(e);
			
			if (e.currentTarget.id == 'sw-cancel' || e.currentTarget.id == 'sw-done') {
				this.tapCancel(e);
			} else if (e.currentTarget.id == 'sw-frame') {
				this.scrollMove(e);
			}
		} else if (e.type == 'touchend' || e.type == 'click') {
			if (e.currentTarget.id == 'sw-cancel' || e.currentTarget.id == 'sw-done') {
				this.tapUp(e);
			} else if (e.currentTarget.id == 'sw-frame') {
				this.scrollEnd(e);
			}
		} else if (e.type == 'webkitTransitionEnd') {
			if (e.target.id == 'sw-wrapper') {
				this.destroy();
			} else {
				this.backWithinBoundaries(e);
			}
		} else if (e.type == 'orientationchange') {
			this.onOrientationChange(e);
		} else if (e.type == 'scroll') {
			this.onScroll(e);
		}
	},


	/**
	 *
	 * Global events
	 *
	 */

	onOrientationChange: function (e) {
		window.scrollTo(0, 0);
		this.swWrapper.style.top = window.innerHeight + window.pageYOffset + 'px';
		this.calculateSlotsWidth();
	},
	
	onScroll: function (e) {
		this.swWrapper.style.top = window.innerHeight + window.pageYOffset + 'px';
	},

	lockScreen: function (e) {
		e.preventDefault();
		e.stopPropagation();
	},


	/**
	 *
	 * Initialization
	 *
	 */

	reset: function () {
		this.slotEl = [];

		this.activeSlot = null;
		
		this.swWrapper = undefined;
		this.swSlotWrapper = undefined;
		this.swSlots = undefined;
		this.swFrame = undefined;
	},

	calculateSlotsWidth: function () {
		var div = this.swSlots.getElementsByTagName('div');
		for (var i = 0; i < div.length; i += 1) {
			this.slotEl[i].slotWidth = div[i].offsetWidth;
		}
	},

	create: function () {
		var i, l, out, ul, div;

		this.reset();	// Initialize object variables

		// Create the Spinning Wheel main wrapper
		div = document.createElement('div');
		div.id = 'sw-wrapper';
		div.style.top = window.innerHeight + window.pageYOffset + 'px';		// Place the SW down the actual viewing screen
		div.style.webkitTransitionProperty = '-webkit-transform';
		div.innerHTML = '<div id="sw-header"><div id="sw-cancel">Cancel</' + 'div><div id="sw-done">Done</' + 'div></' + 'div><div id="sw-slots-wrapper"><div id="sw-slots"></' + 'div></' + 'div><div id="sw-frame"></' + 'div>';

		document.body.appendChild(div);

		this.swWrapper = div;													// The SW wrapper
		this.swSlotWrapper = document.getElementById('sw-slots-wrapper');		// Slots visible area
		this.swSlots = document.getElementById('sw-slots');						// Pseudo table element (inner wrapper)
		this.swFrame = document.getElementById('sw-frame');						// The scrolling controller

		// Create HTML slot elements
		for (l = 0; l < this.slotData.length; l += 1) {
			// Create the slot
			ul = document.createElement('ul');
			out = '';
			for (i in this.slotData[l].values) {
				out += '<li>' + this.slotData[l].values[i] + '<' + '/li>';
			}
			ul.innerHTML = out;

			div = document.createElement('div');		// Create slot container
			div.className = this.slotData[l].style;		// Add styles to the container
			div.appendChild(ul);
	
			// Append the slot to the wrapper
			this.swSlots.appendChild(div);
			
			ul.slotPosition = l;			// Save the slot position inside the wrapper
			ul.slotYPosition = 0;
			ul.slotWidth = 0;
			ul.slotMaxScroll = this.swSlotWrapper.clientHeight - ul.clientHeight - 86;
			ul.style.webkitTransitionTimingFunction = 'cubic-bezier(0, 0, 0.2, 1)';		// Add default transition
			
			this.slotEl.push(ul);			// Save the slot for later use
			
			// Place the slot to its default position (if other than 0)
			if (this.slotData[l].defaultValue) {
				this.scrollToValue(l, this.slotData[l].defaultValue);	
			}
		}
		
		this.calculateSlotsWidth();
		
		// Global events
		document.addEventListener('touchstart', this, false);			// Prevent page scrolling
		document.addEventListener('touchmove', this, false);			// Prevent page scrolling
		window.addEventListener('orientationchange', this, true);		// Optimize SW on orientation change
		window.addEventListener('scroll', this, true);				// Reposition SW on page scroll

		// Cancel/Done buttons events
		document.getElementById('sw-cancel').addEventListener('click', this, false);
		document.getElementById('sw-done').addEventListener('click', this, false);
		document.getElementById('sw-cancel').addEventListener('touchstart', this, false);
		document.getElementById('sw-done').addEventListener('touchstart', this, false);

		// Add scrolling to the slots
		this.swFrame.addEventListener('touchstart', this, false);
	},

	open: function () {
		this.create();

		this.swWrapper.style.webkitTransitionTimingFunction = 'ease-out';
		this.swWrapper.style.webkitTransitionDuration = '400ms';
		this.swWrapper.style.webkitTransform = 'translate3d(0, -260px, 0)';
	},
	
	
	/**
	 *
	 * Unload
	 *
	 */

	destroy: function () {
		this.swWrapper.removeEventListener('webkitTransitionEnd', this, false);

		this.swFrame.removeEventListener('touchstart', this, false);

		document.getElementById('sw-cancel').removeEventListener('touchstart', this, false);
		document.getElementById('sw-done').removeEventListener('touchstart', this, false);

		document.removeEventListener('touchstart', this, false);
		document.removeEventListener('touchmove', this, false);
		window.removeEventListener('orientationchange', this, true);
		window.removeEventListener('scroll', this, true);
		
		this.slotData = [];
		this.cancelAction = function () {
			return false;
		};
		
		this.cancelDone = function () {
			return true;
		};
		
		this.reset();
		
		document.body.removeChild(document.getElementById('sw-wrapper'));
	},
	
	close: function () {
		this.swWrapper.style.webkitTransitionTimingFunction = 'ease-in';
		this.swWrapper.style.webkitTransitionDuration = '400ms';
		this.swWrapper.style.webkitTransform = 'translate3d(0, 0, 0)';
		
		this.swWrapper.addEventListener('webkitTransitionEnd', this, false);
	},


	/**
	 *
	 * Generic methods
	 *
	 */

	addSlot: function (values, style, defaultValue) {
		if (!style) {
			style = '';
		}
		
		style = style.split(' ');

		for (var i = 0; i < style.length; i += 1) {
			style[i] = 'sw-' + style[i];
		}
		
		style = style.join(' ');

		var obj = { 'values': values, 'style': style, 'defaultValue': defaultValue };
		this.slotData.push(obj);
	},

	getSelectedValues: function () {
		var index, count,
		    i, l,
			keys = [], values = [];
		for (var i = 0; i < this.slotEl.length; i += 1) {
			// Remove any residual animation
			this.slotEl[i].removeEventListener('webkitTransitionEnd', this, false);
			this.slotEl[i].style.webkitTransitionDuration = '0';

			if (this.slotEl[i].slotYPosition > 0) {
				this.setPosition(i, 0);
			} else if (this.slotEl[i].slotYPosition < this.slotEl[i].slotMaxScroll) {
				this.setPosition(i, this.slotEl[i].slotMaxScroll);
			}

			index = -Math.round(this.slotEl[i].slotYPosition / this.cellHeight);

			count = 0;
			for (l in this.slotData[i].values) {
				if (count == index) {
					keys.push(l);
					values.push(this.slotData[i].values[l]);
					break;
				}
				
				count += 1;
			}
		}

		return { 'keys': keys, 'values': values };
	},


	/**
	 *
	 * Rolling slots
	 *
	 */

	setPosition: function (slot, pos) {
		this.slotEl[slot].slotYPosition = pos;
		this.slotEl[slot].style.webkitTransform = 'translate3d(0, ' + pos + 'px, 0)';
	},
	
	scrollStart: function (e) {
		// Find the clicked slot
		var xPos = e.targetTouches[0].clientX - this.swSlots.offsetLeft;	// Clicked position minus left offset (should be 11px)

		// Find tapped slot
		var slot = 0;
		for (var i = 0; i < this.slotEl.length; i += 1) {
			slot += this.slotEl[i].slotWidth;
			
			if (xPos < slot) {
				this.activeSlot = i;
				break;
			}
		}

		// If slot is readonly do nothing
		if (this.slotData[this.activeSlot].style.match('readonly')) {
			this.swFrame.removeEventListener('touchmove', this, false);
			this.swFrame.removeEventListener('touchend', this, false);
			return false;
		}

		this.slotEl[this.activeSlot].removeEventListener('webkitTransitionEnd', this, false);	// Remove transition event (if any)
		this.slotEl[this.activeSlot].style.webkitTransitionDuration = '0';		// Remove any residual transition
		
		// Stop and hold slot position
		var theTransform = window.getComputedStyle(this.slotEl[this.activeSlot]).webkitTransform;
		theTransform = new WebKitCSSMatrix(theTransform).m42;
		if (theTransform != this.slotEl[this.activeSlot].slotYPosition) {
			this.setPosition(this.activeSlot, theTransform);
		}
		
		this.startY = e.targetTouches[0].clientY;
		this.scrollStartY = this.slotEl[this.activeSlot].slotYPosition;
		this.scrollStartTime = e.timeStamp;

		this.swFrame.addEventListener('touchmove', this, false);
		this.swFrame.addEventListener('touchend', this, false);
		
		return true;
	},

	scrollMove: function (e) {
		var topDelta = e.targetTouches[0].clientY - this.startY;

		if (this.slotEl[this.activeSlot].slotYPosition > 0 || this.slotEl[this.activeSlot].slotYPosition < this.slotEl[this.activeSlot].slotMaxScroll) {
			topDelta /= 2;
		}
		
		this.setPosition(this.activeSlot, this.slotEl[this.activeSlot].slotYPosition + topDelta);
		this.startY = e.targetTouches[0].clientY;

		// Prevent slingshot effect
		if (e.timeStamp - this.scrollStartTime > 80) {
			this.scrollStartY = this.slotEl[this.activeSlot].slotYPosition;
			this.scrollStartTime = e.timeStamp;
		}
	},
	
	scrollEnd: function (e) {
		this.swFrame.removeEventListener('touchmove', this, false);
		this.swFrame.removeEventListener('touchend', this, false);

		// If we are outside of the boundaries, let's go back to the sheepfold
		if (this.slotEl[this.activeSlot].slotYPosition > 0 || this.slotEl[this.activeSlot].slotYPosition < this.slotEl[this.activeSlot].slotMaxScroll) {
			this.scrollTo(this.activeSlot, this.slotEl[this.activeSlot].slotYPosition > 0 ? 0 : this.slotEl[this.activeSlot].slotMaxScroll);
			return false;
		}

		// Lame formula to calculate a fake deceleration
		var scrollDistance = this.slotEl[this.activeSlot].slotYPosition - this.scrollStartY;

		// The drag session was too short
		if (scrollDistance < this.cellHeight / 1.5 && scrollDistance > -this.cellHeight / 1.5) {
			if (this.slotEl[this.activeSlot].slotYPosition % this.cellHeight) {
				this.scrollTo(this.activeSlot, Math.round(this.slotEl[this.activeSlot].slotYPosition / this.cellHeight) * this.cellHeight, '100ms');
			}

			return false;
		}

		var scrollDuration = e.timeStamp - this.scrollStartTime;

		var newDuration = (2 * scrollDistance / scrollDuration) / this.friction;
		var newScrollDistance = (this.friction / 2) * (newDuration * newDuration);
		
		if (newDuration < 0) {
			newDuration = -newDuration;
			newScrollDistance = -newScrollDistance;
		}

		var newPosition = this.slotEl[this.activeSlot].slotYPosition + newScrollDistance;

		if (newPosition > 0) {
			// Prevent the slot to be dragged outside the visible area (top margin)
			newPosition /= 2;
			newDuration /= 3;

			if (newPosition > this.swSlotWrapper.clientHeight / 4) {
				newPosition = this.swSlotWrapper.clientHeight / 4;
			}
		} else if (newPosition < this.slotEl[this.activeSlot].slotMaxScroll) {
			// Prevent the slot to be dragged outside the visible area (bottom margin)
			newPosition = (newPosition - this.slotEl[this.activeSlot].slotMaxScroll) / 2 + this.slotEl[this.activeSlot].slotMaxScroll;
			newDuration /= 3;
			
			if (newPosition < this.slotEl[this.activeSlot].slotMaxScroll - this.swSlotWrapper.clientHeight / 4) {
				newPosition = this.slotEl[this.activeSlot].slotMaxScroll - this.swSlotWrapper.clientHeight / 4;
			}
		} else {
			newPosition = Math.round(newPosition / this.cellHeight) * this.cellHeight;
		}

		this.scrollTo(this.activeSlot, Math.round(newPosition), Math.round(newDuration) + 'ms');
 
		return true;
	},

	scrollTo: function (slotNum, dest, runtime) {
		this.slotEl[slotNum].style.webkitTransitionDuration = runtime ? runtime : '100ms';
		this.setPosition(slotNum, dest ? dest : 0);

		// If we are outside of the boundaries go back to the sheepfold
		if (this.slotEl[slotNum].slotYPosition > 0 || this.slotEl[slotNum].slotYPosition < this.slotEl[slotNum].slotMaxScroll) {
			this.slotEl[slotNum].addEventListener('webkitTransitionEnd', this, false);
		}
	},
	
	scrollToValue: function (slot, value) {
		var yPos, count, i;

		this.slotEl[slot].removeEventListener('webkitTransitionEnd', this, false);
		this.slotEl[slot].style.webkitTransitionDuration = '0';
		
		count = 0;
		for (i in this.slotData[slot].values) {
			if (i == value) {
				yPos = count * this.cellHeight;
				this.setPosition(slot, yPos);
				break;
			}
			
			count -= 1;
		}
	},
	
	backWithinBoundaries: function (e) {
		e.target.removeEventListener('webkitTransitionEnd', this, false);

		this.scrollTo(e.target.slotPosition, e.target.slotYPosition > 0 ? 0 : e.target.slotMaxScroll, '150ms');
		return false;
	},


	/**
	 *
	 * Buttons
	 *
	 */

	tapDown: function (e) {
		e.currentTarget.addEventListener('touchmove', this, false);
		e.currentTarget.addEventListener('touchend', this, false);
		e.currentTarget.className = 'sw-pressed';
	},

	tapCancel: function (e) {
		e.currentTarget.removeEventListener('touchmove', this, false);
		e.currentTarget.removeEventListener('touchend', this, false);
		e.currentTarget.className = '';
	},
	
	tapUp: function (e) {
		this.tapCancel(e);

		if (e.currentTarget.id == 'sw-cancel') {
			this.cancelAction();
		} else {
			this.doneAction();
		}
		
		this.close();
	},

	setCancelAction: function (action) {
		this.cancelAction = action;
	},

	setDoneAction: function (action) {
		this.doneAction = action;
	},
	
	cancelAction: function () {
		return false;
	},

	cancelDone: function () {
		return true;
	}
};

// file: statusbar.js
document.addEventListener('deviceready', function() 
	{
		if (window.StatusBar)
		{
			StatusBar.overlaysWebView(false);
		}
	},false);

