/* Minification failed. Returning unminified contents.
(14541,37-38): run-time error JS1195: Expected expression: )
(14541,40-41): run-time error JS1195: Expected expression: >
(14541,82-83): run-time error JS1004: Expected ';': )
(14542,23-27): run-time error JS1004: Expected ';': else
(14583,9-10): run-time error JS1002: Syntax error: }
(14585,49-50): run-time error JS1195: Expected expression: )
(14585,51-52): run-time error JS1004: Expected ';': {
(14661,5-6): run-time error JS1002: Syntax error: }
(14665,5-6): run-time error JS1002: Syntax error: }
(14669,25-26): run-time error JS1004: Expected ';': {
(27250,37-38): run-time error JS1195: Expected expression: )
(27250,40-41): run-time error JS1195: Expected expression: >
(27250,84-85): run-time error JS1004: Expected ';': )
(27252,21-22): run-time error JS1002: Syntax error: }
(27253,37-38): run-time error JS1195: Expected expression: )
(27253,40-41): run-time error JS1195: Expected expression: >
(27253,63-64): run-time error JS1004: Expected ';': )
(27259,116-117): run-time error JS1004: Expected ';': {
(27556,5-6): run-time error JS1002: Syntax error: }
(27558,47-50): run-time error JS1197: Too many errors. The file might not be a JavaScript file: new
(14590,21-27): run-time error JS1018: 'return' statement outside of function: return
 */
/* Minification failed. Returning unminified contents.
(14518,37-38): run-time error JS1195: Expected expression: )
(14518,40-41): run-time error JS1195: Expected expression: >
(14518,82-83): run-time error JS1004: Expected ';': )
(14519,23-27): run-time error JS1004: Expected ';': else
(14560,9-10): run-time error JS1002: Syntax error: }
(14562,49-50): run-time error JS1195: Expected expression: )
(14562,51-52): run-time error JS1004: Expected ';': {
(14638,5-6): run-time error JS1002: Syntax error: }
(14642,5-6): run-time error JS1002: Syntax error: }
(14646,25-26): run-time error JS1004: Expected ';': {
(27227,37-38): run-time error JS1195: Expected expression: )
(27227,40-41): run-time error JS1195: Expected expression: >
(27227,84-85): run-time error JS1004: Expected ';': )
(27229,21-22): run-time error JS1002: Syntax error: }
(27230,37-38): run-time error JS1195: Expected expression: )
(27230,40-41): run-time error JS1195: Expected expression: >
(27230,63-64): run-time error JS1004: Expected ';': )
(27236,116-117): run-time error JS1004: Expected ';': {
(27533,5-6): run-time error JS1002: Syntax error: }
(27535,47-50): run-time error JS1197: Too many errors. The file might not be a JavaScript file: new
(14567,21-27): run-time error JS1018: 'return' statement outside of function: return
 */
/*! jQuery UI - v1.10.1 - 2013-02-26
* http://jqueryui.com
* Includes: jquery.ui.core.js, jquery.ui.widget.js, jquery.ui.position.js, jquery.ui.autocomplete.js, jquery.ui.menu.js
* Copyright (c) 2013 jQuery Foundation and other contributors Licensed MIT */

(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.1",

	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 );
(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 );
(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+(\.[\d]+)?%?/,
	rposition = /^\w+/,
	rpercent = /%$/,
	_position = $.fn.position;

function getOffsets( offsets, width, height ) {
	return [
		parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
		parseFloat( offsets[ 1 ] ) * ( 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: (!isWindow && 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 ) );
(function( $, undefined ) {

// used to prevent race conditions with remote data sources
var requestIndex = 0;

$.widget( "ui.autocomplete", {
	version: "1.10.1",
	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
	},

	isOpen: false,
	checkCollapseFlag: false,
	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,
			nodeName = this.element[0].nodeName.toLowerCase(),
			isTextarea = nodeName === "textarea",
			isInput = nodeName === "input";

		this.isMultiLine =
			// Textareas are always multi-line
			isTextarea ? true :
			// Inputs are always single-line, even if inside a contentEditable element
			// IE also treats inputs as contentEditable
			isInput ? false :
			// All other element types are determined by whether or not they're contentEditable
			this.element.prop( "isContentEditable" );

		this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
		this.isNewMenu = true;

		this.element
			.addClass( "ui-autocomplete-input" )
			.attr( "autocomplete", "off" )
			.attr('aria-expanded', false);

		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 ui-front" )
			.appendTo( this._appendTo() )
			.menu({
				// custom key handling for now
				input: $(),
				// disable ARIA support, the live region takes care of that
				role: null
			})
			.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;
	},

	_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 );
			this.liveRegion.text("").text("collapsed");
			this.element.attr('aria-expanded', false);
			this.isOpen = false;
			this.checkCollapseFlag = false;
		}
	},

	_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();
		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>")
            .attr({ "data-item-id": item.itemId ? item.itemId : 0, "data-item-code": item.classCode ? item.classCode:'' })
			.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 suggestions found for the keyword, press enter to search for jobs.",
			results: function( amount ) {
			    return amount + (amount > 1 ? " suggestions are" : " suggestion 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.isOpen) ? this.options.messages.results( content.length ) : this.options.messages.results( content.length ) + " expanded";
			this.element.attr('aria-expanded', true);
			this.checkCollapseFlag = true;
			this.isOpen = true;
		} else {
			message =  this.options.messages.noResults;
			this.element.attr('aria-expanded', false);
			if(this.checkCollapseFlag) {
				message =  this.options.messages.noResults + " collapsed";
				this.checkCollapseFlag = false;
				this.isOpen = false;
			}
		}
		this.liveRegion.text( message );
	}
});

}( jQuery ));
(function( $, undefined ) {

$.widget( "ui.menu", {
	version: "1.10.1",
	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 ( !/[^\-\u2014\u2013\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 ));
;
/**
 * This work is licensed under the MIT License
 *
 * Configurable idle (no activity) timer and logout redirect for jQuery.
 * Works across multiple windows and tabs from the same domain.
 *
 * Dependencies: JQuery v1.7+, JQuery UI, store.js from https://github.com/marcuswestin/store.js - v1.3.4+
 * version 1.0.8
 **/

/*global jQuery: false, document: false, store: false, clearInterval: false, setInterval: false, setTimeout: false, window: false, alert: false*/
/*jslint indent: 2, sloppy: true*/

(function ($) {

    $.fn.idleTimeout = function (options) {
        // Chrome poorly supports 508c standards, especially aria-live attribute.
        // So we need to know if it's Chrome to implement some features in another way.
        var isChrome = !!window.chrome;


        //##############################
        //## Configuration Variables
        //##############################
        var defaults = {
            idleTimeLimit: 1200,       // 'No activity' time limit in seconds. 1200 = 20 Minutes
            redirectUrl: '/logout',    // redirect to this url on timeout logout. Set to "redirectUrl: false" to disable redirect

            // optional custom callback to perform before logout
            customCallback: false,     // set to false for no customCallback
            // customCallback:    function () {    // define optional custom js function
            // perform custom action before logout
            // },

            // configure which activity events to detect
            // http://www.quirksmode.org/dom/events/
            // https://developer.mozilla.org/en-US/docs/Web/Reference/Events
            activityEvents: 'click keypress scroll wheel mousewheel mousemove', // separate each event with a space

            // warning dialog box configuration
            enableDialog: true,        // set to false for logout without warning dialog
            dialogDisplayLimit: 180,   // time to display the warning dialog before logout (and optional callback) in seconds. 180 = 3 Minutes
            dialogTitle: 'Session Expiration Warning',
            dialogText: 'Because you have been inactive, your session is about to expire.',
            dialogTimeRemaining: 'Time remaining',
            dialogStayLoggedInButton: 'Stay Logged In',
            dialogLogOutNowButton: 'Log Out Now',

            pronounceWarningInterval: 15, // in seconds

            // error message
            errorAlertMessage: 'Please disable "Private Mode", or upgrade to a modern browser. Or perhaps a dependent file missing. Please see: https://github.com/marcuswestin/store.js',

            // server-side session keep-alive timer
            sessionKeepAliveTimer: 600, // Ping the server at this interval in seconds. 600 = 10 Minutes
            // sessionKeepAliveTimer: false, // Set to false to disable pings
            sessionKeepAliveUrl: window.location.href, // set URL to ping - does not apply if sessionKeepAliveTimer: false
            stopTrackingEvent: ''
        },

        //##############################
        //## Private Variables
        //##############################
          opts = $.extend(defaults, options),
          checkHeartbeat = 2, // frequency to check for timeouts in seconds
          origTitle = document.title, // save original browser title
          startKeepSessionAlive, stopKeepSessionAlive, keepSession, keepAlivePing, activityDetector,
          idleTimer, remainingTimer, checkIdleTimeout, idleTimerLastActivity, startIdleTimer, stopIdleTimer,
          $warningContainer, $warningContainerParent, $warningResumeLink, initializeWarningDialog, openWarningDialog,
          dialogTimer, checkDialogTimeout, startDialogTimer, stopDialogTimer, isDialogOpen, closeWarningDialog,
          countdownDisplay, triggerResume, logoutUser;

        //##############################
        //## Private Functions
        //##############################
        startKeepSessionAlive = function () {

            keepSession = function () {
                if (idleTimerLastActivity === store.get('idleTimerLastActivity')) {
                    $.get(opts.sessionKeepAliveUrl);
                }
            };

            keepAlivePing = setInterval(keepSession, (opts.sessionKeepAliveTimer * 1000));
        };

        stopKeepSessionAlive = function () {
            clearInterval(keepAlivePing);
        };

        activityDetector = function () {

            $('body').on(opts.activityEvents, function () {

                if (!opts.enableDialog || (opts.enableDialog && isDialogOpen() !== true)) {
                    startIdleTimer();
                }
            });
        };

        checkIdleTimeout = function () {
            var timeNow = $.now(), timeIdleTimeout = (store.get('idleTimerLastActivity') + (opts.idleTimeLimit * 1000));

            if (timeNow > timeIdleTimeout) {

                if (!opts.enableDialog) {
                    logoutUser();
                } else if (opts.enableDialog && isDialogOpen() !== true) {
                    openWarningDialog();
                    startDialogTimer();
                    triggerResume();
                }
            } else if (store.get('idleTimerLoggedOut') === true) { //a 'manual' user logout?
                logoutUser();
            } else {
                if (isDialogOpen() === true) {
                    closeWarningDialog();
                    stopDialogTimer();
                }
            }
        };

        startIdleTimer = function () {
            stopIdleTimer();
            idleTimerLastActivity = $.now();
            store.set('idleTimerLastActivity', idleTimerLastActivity);
            idleTimer = setInterval(checkIdleTimeout, (checkHeartbeat * 1000));
        };

        stopIdleTimer = function () {
            clearInterval(idleTimer);
        };

        initializeWarningDialog = function() {
            $warningContainer = $('#idletimeout-container');
            var $countdownPlaceholder = $('.countdown-place-holder', $warningContainer);
            $countdownPlaceholder.before(opts.dialogText);

            $warningResumeLink = $('#idletimeout-resume-link', $warningContainer);
            $warningResumeLink.text(opts.dialogStayLoggedInButton);

            if (isChrome) {
                // Chrome doesn't like changing of aria-live attribute, so
                // it should be permanently here.
                $warningContainer.attr('aria-live', 'assertive');
            }

            $($warningResumeLink).on('click', function() {
                closeWarningDialog();
                stopDialogTimer();
                startIdleTimer();
            });
        };

        openWarningDialog = function () {
            $warningContainerParent = $warningContainer.parent();
            $warningContainer.prependTo('body');
            $warningContainer.slideDown();

            countdownDisplay();

            document.title = opts.dialogTitle;

            if (opts.sessionKeepAliveTimer) {
                stopKeepSessionAlive();
            }
        };

        checkDialogTimeout = function () {
            var timeNow = $.now(), timeDialogTimeout = (store.get('idleTimerLastActivity') + (opts.idleTimeLimit * 1000) + (opts.dialogDisplayLimit * 1000));

            if ((timeNow > timeDialogTimeout) || (store.get('idleTimerLoggedOut') === true)) {
                logoutUser();
            }
        };

        startDialogTimer = function () {
            dialogTimer = setInterval(checkDialogTimeout, (checkHeartbeat * 1000));
        };

        stopDialogTimer = function () {
            clearInterval(dialogTimer);
            clearInterval(remainingTimer);
        };

        isDialogOpen = function () {
            var dialogOpen = $($warningContainer).is(":visible");

            if (dialogOpen === true) {
                return true;
            }
            return false;
        };

        closeWarningDialog = function () {
            if (!isChrome) {
                $warningContainer.removeAttr('aria-live');
            }

            $warningContainer.slideUp({
                complete: function () {
                    $warningContainer.appendTo($warningContainerParent);
                }
            });

            document.title = origTitle;

            if (opts.sessionKeepAliveTimer) {
                startKeepSessionAlive();
            }
        };

        // display remaining time on warning dialog
        countdownDisplay = function () {
            var dialogDisplaySeconds = opts.dialogDisplayLimit, mins, secs;
            var timeUntilPronounce = 1; // Skip first value because of NVDA issue.
            var $countdownPlaceholder = $('span', $warningContainer);

            function updateTimer() {
                if (!isChrome) {
                    if (timeUntilPronounce === 0) {
                        $warningContainer.attr('aria-live', 'assertive');
                        timeUntilPronounce = opts.pronounceWarningInterval;
                    } else if (timeUntilPronounce === opts.pronounceWarningInterval - 1) {
                        // Time was pronounced last time, we need to remove aria-live
                        $warningContainer.removeAttr('aria-live');
                    }
                }

                mins = Math.floor(dialogDisplaySeconds / 60); // minutes
                if (mins < 10) { mins = '0' + mins; }
                secs = dialogDisplaySeconds - (mins * 60); // seconds
                if (secs < 10) { secs = '0' + secs; }
                $countdownPlaceholder.html(mins + ':' + secs);
                dialogDisplaySeconds -= 1;
                timeUntilPronounce -= 1;
            }

            updateTimer();
            remainingTimer = setInterval(updateTimer, 1000);
        };

        triggerResume = function() {
            var isFired = false;

            $('body').one(opts.activityEvents, function (event) {
                if (isFired) { return; }

                isFired = true;

                var $target = $(event.target);

                if (!$target.is($warningResumeLink)) {
                    $warningResumeLink.trigger('click');
                }
            });
        };

        logoutUser = function () {
            store.set('idleTimerLoggedOut', true);

            if (opts.sessionKeepAliveTimer) {
                stopKeepSessionAlive();
            }

            if (opts.customCallback) {
                if (opts.customCallback()) {
                    stopDialogTimer();
                    stopIdleTimer();
                }
            }

            if (opts.redirectUrl) {
                window.location.href = opts.redirectUrl;
            }
        };

        //###############################
        // Build & Return the instance of the item as a plugin
        // This is your construct.
        //###############################
        return this.each(function () {

            if (store.enabled) {
                idleTimerLastActivity = $.now();
                store.set('idleTimerLastActivity', idleTimerLastActivity);
                store.set('idleTimerLoggedOut', false);
            } else {
                alert(opts.errorAlertMessage);
            }

            initializeWarningDialog();

            activityDetector();

            if (opts.sessionKeepAliveTimer) {
                startKeepSessionAlive();
            }

            startIdleTimer();

            if (opts.stopTrackingEvent) {
                $(document).one(opts.stopTrackingEvent, function() {
                    $('body').off(opts.activityEvents);
                    closeWarningDialog();
                    stopKeepSessionAlive();
                    stopDialogTimer();
                    stopIdleTimer();
                });
            }
        });
    };
}(jQuery));;
/*
 * jQuery.bind-first library v0.2.3
 * Copyright (c) 2013 Vladimir Zhuravlev
 *
 * Released under MIT License
 * @license
 *
 * Date: Thu Feb  6 10:13:59 ICT 2014
 **/
(function(t){function e(e){return u?e.data("events"):t._data(e[0]).events}function n(t,n,r){var i=e(t),a=i[n];if(!u){var s=r?a.splice(a.delegateCount-1,1)[0]:a.pop();return a.splice(r?0:a.delegateCount||0,0,s),void 0}r?i.live.unshift(i.live.pop()):a.unshift(a.pop())}function r(e,r,i){var a=r.split(/\s+/);e.each(function(){for(var e=0;a.length>e;++e){var r=t.trim(a[e]).match(/[^\.]+/i)[0];n(t(this),r,i)}})}function i(e){t.fn[e+"First"]=function(){var n=t.makeArray(arguments),i=n.shift();return i&&(t.fn[e].apply(this,arguments),r(this,i)),this}}var a=t.fn.jquery.split("."),s=parseInt(a[0]),f=parseInt(a[1]),u=1>s||1==s&&7>f;i("bind"),i("one"),t.fn.delegateFirst=function(){var e=t.makeArray(arguments),n=e[1];return n&&(e.splice(0,2),t.fn.delegate.apply(this,arguments),r(this,n,!0)),this},t.fn.liveFirst=function(){var e=t.makeArray(arguments);return e.unshift(this.selector),t.fn.delegateFirst.apply(t(document),e),this},u||(t.fn.onFirst=function(e,n){var i=t(this),a="string"==typeof n;if(t.fn.on.apply(i,arguments),"object"==typeof e)for(type in e)e.hasOwnProperty(type)&&r(i,type,a);else"string"==typeof e&&r(i,e,a);return i})})(jQuery);;
/*
 * jQuery File Upload Plugin 5.26
 * https://github.com/blueimp/jQuery-File-Upload
 *
 * Copyright 2010, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */

/*jslint nomen: true, unparam: true, regexp: true */
/*global define, window, document, File, Blob, FormData, location */

(function (factory) {
    'use strict';
    if (typeof define === 'function' && define.amd) {
        // Register as an anonymous AMD module:
        define([
            'jquery',
            'jquery.ui.widget'
        ], factory);
    } else {
        // Browser globals:
        factory(window.jQuery);
    }
}(function ($) {
    'use strict';

    // The FileReader API is not actually used, but works as feature detection,
    // as e.g. Safari supports XHR file uploads via the FormData API,
    // but not non-multipart XHR file uploads:
    $.support.xhrFileUpload = !!(window.XMLHttpRequestUpload && window.FileReader);
    $.support.xhrFormDataFileUpload = !!window.FormData;

    // The fileupload widget listens for change events on file input fields defined
    // via fileInput setting and paste or drop events of the given dropZone.
    // In addition to the default jQuery Widget methods, the fileupload widget
    // exposes the "add" and "send" methods, to add or directly send files using
    // the fileupload API.
    // By default, files added via file input selection, paste, drag & drop or
    // "add" method are uploaded immediately, but it is possible to override
    // the "add" callback option to queue file uploads.
    $.widget('blueimp.fileupload', {

        options: {
            // The drop target element(s), by the default the complete document.
            // Set to null to disable drag & drop support:
            dropZone: $(document),
            // The paste target element(s), by the default the complete document.
            // Set to null to disable paste support:
            pasteZone: $(document),
            // The file input field(s), that are listened to for change events.
            // If undefined, it is set to the file input fields inside
            // of the widget element on plugin initialization.
            // Set to null to disable the change listener.
            fileInput: undefined,
            // By default, the file input field is replaced with a clone after
            // each input field change event. This is required for iframe transport
            // queues and allows change events to be fired for the same file
            // selection, but can be disabled by setting the following option to false:
            replaceFileInput: true,
            // The parameter name for the file form data (the request argument name).
            // If undefined or empty, the name property of the file input field is
            // used, or "files[]" if the file input name property is also empty,
            // can be a string or an array of strings:
            paramName: undefined,
            // By default, each file of a selection is uploaded using an individual
            // request for XHR type uploads. Set to false to upload file
            // selections in one request each:
            singleFileUploads: true,
            // To limit the number of files uploaded with one XHR request,
            // set the following option to an integer greater than 0:
            limitMultiFileUploads: undefined,
            // Set the following option to true to issue all file upload requests
            // in a sequential order:
            sequentialUploads: false,
            // To limit the number of concurrent uploads,
            // set the following option to an integer greater than 0:
            limitConcurrentUploads: undefined,
            // Set the following option to true to force iframe transport uploads:
            forceIframeTransport: false,
            // Set the following option to the location of a redirect url on the
            // origin server, for cross-domain iframe transport uploads:
            redirect: undefined,
            // The parameter name for the redirect url, sent as part of the form
            // data and set to 'redirect' if this option is empty:
            redirectParamName: undefined,
            // Set the following option to the location of a postMessage window,
            // to enable postMessage transport uploads:
            postMessage: undefined,
            // By default, XHR file uploads are sent as multipart/form-data.
            // The iframe transport is always using multipart/form-data.
            // Set to false to enable non-multipart XHR uploads:
            multipart: true,
            // To upload large files in smaller chunks, set the following option
            // to a preferred maximum chunk size. If set to 0, null or undefined,
            // or the browser does not support the required Blob API, files will
            // be uploaded as a whole.
            maxChunkSize: undefined,
            // When a non-multipart upload or a chunked multipart upload has been
            // aborted, this option can be used to resume the upload by setting
            // it to the size of the already uploaded bytes. This option is most
            // useful when modifying the options object inside of the "add" or
            // "send" callbacks, as the options are cloned for each file upload.
            uploadedBytes: undefined,
            // By default, failed (abort or error) file uploads are removed from the
            // global progress calculation. Set the following option to false to
            // prevent recalculating the global progress data:
            recalculateProgress: true,
            // Interval in milliseconds to calculate and trigger progress events:
            progressInterval: 100,
            // Interval in milliseconds to calculate progress bitrate:
            bitrateInterval: 500,
            // By default, uploads are started automatically when adding files:
            autoUpload: true,

            // Additional form data to be sent along with the file uploads can be set
            // using this option, which accepts an array of objects with name and
            // value properties, a function returning such an array, a FormData
            // object (for XHR file uploads), or a simple object.
            // The form of the first fileInput is given as parameter to the function:
            formData: function (form) {
                return form.serializeArray();
            },

            // The add callback is invoked as soon as files are added to the fileupload
            // widget (via file input selection, drag & drop, paste or add API call).
            // If the singleFileUploads option is enabled, this callback will be
            // called once for each file in the selection for XHR file uplaods, else
            // once for each file selection.
            // The upload starts when the submit method is invoked on the data parameter.
            // The data object contains a files property holding the added files
            // and allows to override plugin options as well as define ajax settings.
            // Listeners for this callback can also be bound the following way:
            // .bind('fileuploadadd', func);
            // data.submit() returns a Promise object and allows to attach additional
            // handlers using jQuery's Deferred callbacks:
            // data.submit().done(func).fail(func).always(func);
            add: function (e, data) {
                if (data.autoUpload || (data.autoUpload !== false &&
                        ($(this).data('blueimp-fileupload') ||
                        $(this).data('fileupload')).options.autoUpload)) {
                    data.submit();
                }
            },

            // Other callbacks:

            // Callback for the submit event of each file upload:
            // submit: function (e, data) {}, // .bind('fileuploadsubmit', func);

            // Callback for the start of each file upload request:
            // send: function (e, data) {}, // .bind('fileuploadsend', func);

            // Callback for successful uploads:
            // done: function (e, data) {}, // .bind('fileuploaddone', func);

            // Callback for failed (abort or error) uploads:
            // fail: function (e, data) {}, // .bind('fileuploadfail', func);

            // Callback for completed (success, abort or error) requests:
            // always: function (e, data) {}, // .bind('fileuploadalways', func);

            // Callback for upload progress events:
            // progress: function (e, data) {}, // .bind('fileuploadprogress', func);

            // Callback for global upload progress events:
            // progressall: function (e, data) {}, // .bind('fileuploadprogressall', func);

            // Callback for uploads start, equivalent to the global ajaxStart event:
            // start: function (e) {}, // .bind('fileuploadstart', func);

            // Callback for uploads stop, equivalent to the global ajaxStop event:
            // stop: function (e) {}, // .bind('fileuploadstop', func);

            // Callback for change events of the fileInput(s):
            // change: function (e, data) {}, // .bind('fileuploadchange', func);

            // Callback for paste events to the pasteZone(s):
            // paste: function (e, data) {}, // .bind('fileuploadpaste', func);

            // Callback for drop events of the dropZone(s):
            // drop: function (e, data) {}, // .bind('fileuploaddrop', func);

            // Callback for dragover events of the dropZone(s):
            // dragover: function (e) {}, // .bind('fileuploaddragover', func);

            // Callback for the start of each chunk upload request:
            // chunksend: function (e, data) {}, // .bind('fileuploadchunksend', func);

            // Callback for successful chunk uploads:
            // chunkdone: function (e, data) {}, // .bind('fileuploadchunkdone', func);

            // Callback for failed (abort or error) chunk uploads:
            // chunkfail: function (e, data) {}, // .bind('fileuploadchunkfail', func);

            // Callback for completed (success, abort or error) chunk upload requests:
            // chunkalways: function (e, data) {}, // .bind('fileuploadchunkalways', func);

            // The plugin options are used as settings object for the ajax calls.
            // The following are jQuery ajax settings required for the file uploads:
            processData: false,
            contentType: false,
            cache: false
        },

        // A list of options that require a refresh after assigning a new value:
        _refreshOptionsList: [
            'fileInput',
            'dropZone',
            'pasteZone',
            'multipart',
            'forceIframeTransport'
        ],

        _BitrateTimer: function () {
            this.timestamp = +(new Date());
            this.loaded = 0;
            this.bitrate = 0;
            this.getBitrate = function (now, loaded, interval) {
                var timeDiff = now - this.timestamp;
                if (!this.bitrate || !interval || timeDiff > interval) {
                    this.bitrate = (loaded - this.loaded) * (1000 / timeDiff) * 8;
                    this.loaded = loaded;
                    this.timestamp = now;
                }
                return this.bitrate;
            };
        },

        _isXHRUpload: function (options) {
            return !options.forceIframeTransport &&
                ((!options.multipart && $.support.xhrFileUpload) ||
                $.support.xhrFormDataFileUpload);
        },

        _getFormData: function (options) {
            var formData;
            if (typeof options.formData === 'function') {
                return options.formData(options.form);
            }
            if ($.isArray(options.formData)) {
                return options.formData;
            }
            if (options.formData) {
                formData = [];
                $.each(options.formData, function (name, value) {
                    formData.push({name: name, value: value});
                });
                return formData;
            }
            return [];
        },

        _getTotal: function (files) {
            var total = 0;
            $.each(files, function (index, file) {
                total += file.size || 1;
            });
            return total;
        },

        _initProgressObject: function (obj) {
            obj._progress = {
                loaded: 0,
                total: 0,
                bitrate: 0
            };
        },

        _onProgress: function (e, data) {
            if (e.lengthComputable) {
                var now = +(new Date()),
                    loaded;
                if (data._time && data.progressInterval &&
                        (now - data._time < data.progressInterval) &&
                        e.loaded !== e.total) {
                    return;
                }
                data._time = now;
                loaded = Math.floor(
                    e.loaded / e.total * (data.chunkSize || data._progress.total)
                ) + (data.uploadedBytes || 0);
                // Add the difference from the previously loaded state
                // to the global loaded counter:
                this._progress.loaded += (loaded - data._progress.loaded);
                this._progress.bitrate = this._bitrateTimer.getBitrate(
                    now,
                    this._progress.loaded,
                    data.bitrateInterval
                );
                data._progress.loaded = data.loaded = loaded;
                data._progress.bitrate = data.bitrate = data._bitrateTimer.getBitrate(
                    now,
                    loaded,
                    data.bitrateInterval
                );
                // Trigger a custom progress event with a total data property set
                // to the file size(s) of the current upload and a loaded data
                // property calculated accordingly:
                this._trigger('progress', e, data);
                // Trigger a global progress event for all current file uploads,
                // including ajax calls queued for sequential file uploads:
                this._trigger('progressall', e, this._progress);
            }
        },

        _initProgressListener: function (options) {
            var that = this,
                xhr = options.xhr ? options.xhr() : $.ajaxSettings.xhr();
            // Accesss to the native XHR object is required to add event listeners
            // for the upload progress event:
            if (xhr.upload) {
                $(xhr.upload).bind('progress', function (e) {
                    var oe = e.originalEvent;
                    // Make sure the progress event properties get copied over:
                    e.lengthComputable = oe.lengthComputable;
                    e.loaded = oe.loaded;
                    e.total = oe.total;
                    that._onProgress(e, options);
                });
                options.xhr = function () {
                    return xhr;
                };
            }
        },

        _initXHRData: function (options) {
            var formData,
                file = options.files[0],
                // Ignore non-multipart setting if not supported:
                multipart = options.multipart || !$.support.xhrFileUpload,
                paramName = options.paramName[0];
            options.headers = options.headers || {};
            if (options.contentRange) {
                options.headers['Content-Range'] = options.contentRange;
            }
            if (!multipart) {
                options.headers['Content-Disposition'] = 'attachment; filename="' +
                    encodeURI(file.name) + '"';
                options.contentType = file.type;
                options.data = options.blob || file;
            } else if ($.support.xhrFormDataFileUpload) {
                if (options.postMessage) {
                    // window.postMessage does not allow sending FormData
                    // objects, so we just add the File/Blob objects to
                    // the formData array and let the postMessage window
                    // create the FormData object out of this array:
                    formData = this._getFormData(options);
                    if (options.blob) {
                        formData.push({
                            name: paramName,
                            value: options.blob
                        });
                    } else {
                        $.each(options.files, function (index, file) {
                            formData.push({
                                name: options.paramName[index] || paramName,
                                value: file
                            });
                        });
                    }
                } else {
                    if (options.formData instanceof FormData) {
                        formData = options.formData;
                    } else {
                        formData = new FormData();
                        $.each(this._getFormData(options), function (index, field) {
                            formData.append(field.name, field.value);
                        });
                    }
                    if (options.blob) {
                        options.headers['Content-Disposition'] = 'attachment; filename="' +
                            encodeURI(file.name) + '"';
                        formData.append(paramName, options.blob, file.name);
                    } else {
                        $.each(options.files, function (index, file) {
                            // Files are also Blob instances, but some browsers
                            // (Firefox 3.6) support the File API but not Blobs.
                            // This check allows the tests to run with
                            // dummy objects:
                            if ((window.Blob && file instanceof Blob) ||
                                    (window.File && file instanceof File)) {
                                formData.append(
                                    options.paramName[index] || paramName,
                                    file,
                                    file.name
                                );
                            }
                        });
                    }
                }
                options.data = formData;
            }
            // Blob reference is not needed anymore, free memory:
            options.blob = null;
        },

        _initIframeSettings: function (options) {
            // Setting the dataType to iframe enables the iframe transport:
            options.dataType = 'iframe ' + (options.dataType || '');
            // The iframe transport accepts a serialized array as form data:
            options.formData = this._getFormData(options);
            // Add redirect url to form data on cross-domain uploads:
            if (options.redirect && $('<a></a>').prop('href', options.url)
                    .prop('host') !== location.host) {
                options.formData.push({
                    name: options.redirectParamName || 'redirect',
                    value: options.redirect
                });
            }
        },

        _initDataSettings: function (options) {
            if (this._isXHRUpload(options)) {
                if (!this._chunkedUpload(options, true)) {
                    if (!options.data) {
                        this._initXHRData(options);
                    }
                    this._initProgressListener(options);
                }
                if (options.postMessage) {
                    // Setting the dataType to postmessage enables the
                    // postMessage transport:
                    options.dataType = 'postmessage ' + (options.dataType || '');
                }
            } else {
                this._initIframeSettings(options, 'iframe');
            }
        },

        _getParamName: function (options) {
            var fileInput = $(options.fileInput),
                paramName = options.paramName;
            if (!paramName) {
                paramName = [];
                fileInput.each(function () {
                    var input = $(this),
                        name = input.prop('name') || 'files[]',
                        i = (input.prop('files') || [1]).length;
                    while (i) {
                        paramName.push(name);
                        i -= 1;
                    }
                });
                if (!paramName.length) {
                    paramName = [fileInput.prop('name') || 'files[]'];
                }
            } else if (!$.isArray(paramName)) {
                paramName = [paramName];
            }
            return paramName;
        },

        _initFormSettings: function (options) {
            // Retrieve missing options from the input field and the
            // associated form, if available:
            if (!options.form || !options.form.length) {
                options.form = $(options.fileInput.prop('form'));
                // If the given file input doesn't have an associated form,
                // use the default widget file input's form:
                if (!options.form.length) {
                    options.form = $(this.options.fileInput.prop('form'));
                }
            }
            options.paramName = this._getParamName(options);
            if (!options.url) {
                options.url = options.form.prop('action') || location.href;
            }
            // The HTTP request method must be "POST" or "PUT":
            options.type = (options.type || options.form.prop('method') || '')
                .toUpperCase();
            if (options.type !== 'POST' && options.type !== 'PUT' &&
                    options.type !== 'PATCH') {
                options.type = 'POST';
            }
            if (!options.formAcceptCharset) {
                options.formAcceptCharset = options.form.attr('accept-charset');
            }
        },

        _getAJAXSettings: function (data) {
            var options = $.extend({}, this.options, data);
            this._initFormSettings(options);
            this._initDataSettings(options);
            return options;
        },

        // jQuery 1.6 doesn't provide .state(),
        // while jQuery 1.8+ removed .isRejected() and .isResolved():
        _getDeferredState: function (deferred) {
            if (deferred.state) {
                return deferred.state();
            }
            if (deferred.isResolved()) {
                return 'resolved';
            }
            if (deferred.isRejected()) {
                return 'rejected';
            }
            return 'pending';
        },

        // Maps jqXHR callbacks to the equivalent
        // methods of the given Promise object:
        _enhancePromise: function (promise) {
            promise.success = promise.done;
            promise.error = promise.fail;
            promise.complete = promise.always;
            return promise;
        },

        // Creates and returns a Promise object enhanced with
        // the jqXHR methods abort, success, error and complete:
        _getXHRPromise: function (resolveOrReject, context, args) {
            var dfd = $.Deferred(),
                promise = dfd.promise();
            context = context || this.options.context || promise;
            if (resolveOrReject === true) {
                dfd.resolveWith(context, args);
            } else if (resolveOrReject === false) {
                dfd.rejectWith(context, args);
            }
            promise.abort = dfd.promise;
            return this._enhancePromise(promise);
        },

        // Adds convenience methods to the callback arguments:
        _addConvenienceMethods: function (e, data) {
            var that = this;
            data.submit = function () {
                if (this.state() !== 'pending') {
                    data.jqXHR = this.jqXHR =
                        (that._trigger('submit', e, this) !== false) &&
                        that._onSend(e, this);
                }
                return this.jqXHR || that._getXHRPromise();
            };
            data.abort = function () {
                if (this.jqXHR) {
                    return this.jqXHR.abort();
                }
                return this._getXHRPromise();
            };
            data.state = function () {
                if (this.jqXHR) {
                    return that._getDeferredState(this.jqXHR);
                }
            };
            data.progress = function () {
                return this._progress;
            };
        },

        // Parses the Range header from the server response
        // and returns the uploaded bytes:
        _getUploadedBytes: function (jqXHR) {
            var range = jqXHR.getResponseHeader('Range'),
                parts = range && range.split('-'),
                upperBytesPos = parts && parts.length > 1 &&
                    parseInt(parts[1], 10);
            return upperBytesPos && upperBytesPos + 1;
        },

        // Uploads a file in multiple, sequential requests
        // by splitting the file up in multiple blob chunks.
        // If the second parameter is true, only tests if the file
        // should be uploaded in chunks, but does not invoke any
        // upload requests:
        _chunkedUpload: function (options, testOnly) {
            var that = this,
                file = options.files[0],
                fs = file.size,
                ub = options.uploadedBytes = options.uploadedBytes || 0,
                mcs = options.maxChunkSize || fs,
                slice = file.slice || file.webkitSlice || file.mozSlice,
                dfd = $.Deferred(),
                promise = dfd.promise(),
                jqXHR,
                upload;
            if (!(this._isXHRUpload(options) && slice && (ub || mcs < fs)) ||
                    options.data) {
                return false;
            }
            if (testOnly) {
                return true;
            }
            if (ub >= fs) {
                file.error = 'Uploaded bytes exceed file size';
                return this._getXHRPromise(
                    false,
                    options.context,
                    [null, 'error', file.error]
                );
            }
            // The chunk upload method:
            upload = function () {
                // Clone the options object for each chunk upload:
                var o = $.extend({}, options),
                    currentLoaded = o._progress.loaded;
                o.blob = slice.call(
                    file,
                    ub,
                    ub + mcs,
                    file.type
                );
                // Store the current chunk size, as the blob itself
                // will be dereferenced after data processing:
                o.chunkSize = o.blob.size;
                // Expose the chunk bytes position range:
                o.contentRange = 'bytes ' + ub + '-' +
                    (ub + o.chunkSize - 1) + '/' + fs;
                // Process the upload data (the blob and potential form data):
                that._initXHRData(o);
                // Add progress listeners for this chunk upload:
                that._initProgressListener(o);
                jqXHR = ((that._trigger('chunksend', null, o) !== false && $.ajax(o)) ||
                        that._getXHRPromise(false, o.context))
                    .done(function (result, textStatus, jqXHR) {
                        ub = that._getUploadedBytes(jqXHR) ||
                            (ub + o.chunkSize);
                        // Create a progress event if no final progress event
                        // with loaded equaling total has been triggered
                        // for this chunk:
                        if (o._progress.loaded === currentLoaded) {
                            that._onProgress($.Event('progress', {
                                lengthComputable: true,
                                loaded: ub - o.uploadedBytes,
                                total: ub - o.uploadedBytes
                            }), o);
                        }
                        options.uploadedBytes = o.uploadedBytes = ub;
                        o.result = result;
                        o.textStatus = textStatus;
                        o.jqXHR = jqXHR;
                        that._trigger('chunkdone', null, o);
                        that._trigger('chunkalways', null, o);
                        if (ub < fs) {
                            // File upload not yet complete,
                            // continue with the next chunk:
                            upload();
                        } else {
                            dfd.resolveWith(
                                o.context,
                                [result, textStatus, jqXHR]
                            );
                        }
                    })
                    .fail(function (jqXHR, textStatus, errorThrown) {
                        o.jqXHR = jqXHR;
                        o.textStatus = textStatus;
                        o.errorThrown = errorThrown;
                        that._trigger('chunkfail', null, o);
                        that._trigger('chunkalways', null, o);
                        dfd.rejectWith(
                            o.context,
                            [jqXHR, textStatus, errorThrown]
                        );
                    });
            };
            this._enhancePromise(promise);
            promise.abort = function () {
                return jqXHR.abort();
            };
            upload();
            return promise;
        },

        _beforeSend: function (e, data) {
            if (this._active === 0) {
                // the start callback is triggered when an upload starts
                // and no other uploads are currently running,
                // equivalent to the global ajaxStart event:
                this._trigger('start');
                // Set timer for global bitrate progress calculation:
                this._bitrateTimer = new this._BitrateTimer();
                // Reset the global progress values:
                this._progress.loaded = this._progress.total = 0;
                this._progress.bitrate = 0;
            }
            if (!data._progress) {
                data._progress = {};
            }
            data._progress.loaded = data.loaded = data.uploadedBytes || 0;
            data._progress.total = data.total = this._getTotal(data.files) || 1;
            data._progress.bitrate = data.bitrate = 0;
            this._active += 1;
            // Initialize the global progress values:
            this._progress.loaded += data.loaded;
            this._progress.total += data.total;
        },

        _onDone: function (result, textStatus, jqXHR, options) {
            var total = options._progress.total;
            if (options._progress.loaded < total) {
                // Create a progress event if no final progress event
                // with loaded equaling total has been triggered:
                this._onProgress($.Event('progress', {
                    lengthComputable: true,
                    loaded: total,
                    total: total
                }), options);
            }
            options.result = result;
            options.textStatus = textStatus;
            options.jqXHR = jqXHR;
            this._trigger('done', null, options);
        },

        _onFail: function (jqXHR, textStatus, errorThrown, options) {
            options.jqXHR = jqXHR;
            options.textStatus = textStatus;
            options.errorThrown = errorThrown;
            this._trigger('fail', null, options);
            if (options.recalculateProgress) {
                // Remove the failed (error or abort) file upload from
                // the global progress calculation:
                this._progress.loaded -= options._progress.loaded;
                this._progress.total -= options._progress.total;
            }
        },

        _onAlways: function (jqXHRorResult, textStatus, jqXHRorError, options) {
            // jqXHRorResult, textStatus and jqXHRorError are added to the
            // options object via done and fail callbacks
            this._active -= 1;
            this._trigger('always', null, options);
            if (this._active === 0) {
                // The stop callback is triggered when all uploads have
                // been completed, equivalent to the global ajaxStop event:
                this._trigger('stop');
            }
        },

        _onSend: function (e, data) {
            if (!data.submit) {
                this._addConvenienceMethods(e, data);
            }
            var that = this,
                jqXHR,
                aborted,
                slot,
                pipe,
                options = that._getAJAXSettings(data),
                send = function () {
                    that._sending += 1;
                    // Set timer for bitrate progress calculation:
                    options._bitrateTimer = new that._BitrateTimer();
                    jqXHR = jqXHR || (
                        ((aborted || that._trigger('send', e, options) === false) &&
                        that._getXHRPromise(false, options.context, aborted)) ||
                        that._chunkedUpload(options) || $.ajax(options)
                    ).done(function (result, textStatus, jqXHR) {
                        that._onDone(result, textStatus, jqXHR, options);
                    }).fail(function (jqXHR, textStatus, errorThrown) {
                        that._onFail(jqXHR, textStatus, errorThrown, options);
                    }).always(function (jqXHRorResult, textStatus, jqXHRorError) {
                        that._sending -= 1;
                        that._onAlways(
                            jqXHRorResult,
                            textStatus,
                            jqXHRorError,
                            options
                        );
                        if (options.limitConcurrentUploads &&
                                options.limitConcurrentUploads > that._sending) {
                            // Start the next queued upload,
                            // that has not been aborted:
                            var nextSlot = that._slots.shift();
                            while (nextSlot) {
                                if (that._getDeferredState(nextSlot) === 'pending') {
                                    nextSlot.resolve();
                                    break;
                                }
                                nextSlot = that._slots.shift();
                            }
                        }
                    });
                    return jqXHR;
                };
            this._beforeSend(e, options);
            if (this.options.sequentialUploads ||
                    (this.options.limitConcurrentUploads &&
                    this.options.limitConcurrentUploads <= this._sending)) {
                if (this.options.limitConcurrentUploads > 1) {
                    slot = $.Deferred();
                    this._slots.push(slot);
                    pipe = slot.pipe(send);
                } else {
                    pipe = (this._sequence = this._sequence.pipe(send, send));
                }
                // Return the piped Promise object, enhanced with an abort method,
                // which is delegated to the jqXHR object of the current upload,
                // and jqXHR callbacks mapped to the equivalent Promise methods:
                pipe.abort = function () {
                    aborted = [undefined, 'abort', 'abort'];
                    if (!jqXHR) {
                        if (slot) {
                            slot.rejectWith(options.context, aborted);
                        }
                        return send();
                    }
                    return jqXHR.abort();
                };
                return this._enhancePromise(pipe);
            }
            return send();
        },

        _onAdd: function (e, data) {
            var that = this,
                result = true,
                options = $.extend({}, this.options, data),
                limit = options.limitMultiFileUploads,
                paramName = this._getParamName(options),
                paramNameSet,
                paramNameSlice,
                fileSet,
                i;
            if (!(options.singleFileUploads || limit) ||
                    !this._isXHRUpload(options)) {
                fileSet = [data.files];
                paramNameSet = [paramName];
            } else if (!options.singleFileUploads && limit) {
                fileSet = [];
                paramNameSet = [];
                for (i = 0; i < data.files.length; i += limit) {
                    fileSet.push(data.files.slice(i, i + limit));
                    paramNameSlice = paramName.slice(i, i + limit);
                    if (!paramNameSlice.length) {
                        paramNameSlice = paramName;
                    }
                    paramNameSet.push(paramNameSlice);
                }
            } else {
                paramNameSet = paramName;
            }
            data.originalFiles = data.files;
            $.each(fileSet || data.files, function (index, element) {
                var newData = $.extend({}, data);
                newData.files = fileSet ? element : [element];
                newData.paramName = paramNameSet[index];
                that._initProgressObject(newData);
                that._addConvenienceMethods(e, newData);
                result = that._trigger('add', e, newData);
                return result;
            });
            return result;
        },

        _replaceFileInput: function (input) {
            var inputClone = input.clone(true);
            $('<form></form>').append(inputClone)[0].reset();
            // Detaching allows to insert the fileInput on another form
            // without loosing the file input value:
            input.after(inputClone).detach();
            // Avoid memory leaks with the detached file input:
            $.cleanData(input.unbind('remove'));
            // Replace the original file input element in the fileInput
            // elements set with the clone, which has been copied including
            // event handlers:
            this.options.fileInput = this.options.fileInput.map(function (i, el) {
                if (el === input[0]) {
                    return inputClone[0];
                }
                return el;
            });
            // If the widget has been initialized on the file input itself,
            // override this.element with the file input clone:
            if (input[0] === this.element[0]) {
                this.element = inputClone;
            }
        },

        _handleFileTreeEntry: function (entry, path) {
            var that = this,
                dfd = $.Deferred(),
                errorHandler = function (e) {
                    if (e && !e.entry) {
                        e.entry = entry;
                    }
                    // Since $.when returns immediately if one
                    // Deferred is rejected, we use resolve instead.
                    // This allows valid files and invalid items
                    // to be returned together in one set:
                    dfd.resolve([e]);
                },
                dirReader;
            path = path || '';
            if (entry.isFile) {
                if (entry._file) {
                    // Workaround for Chrome bug #149735
                    entry._file.relativePath = path;
                    dfd.resolve(entry._file);
                } else {
                    entry.file(function (file) {
                        file.relativePath = path;
                        dfd.resolve(file);
                    }, errorHandler);
                }
            } else if (entry.isDirectory) {
                dirReader = entry.createReader();
                dirReader.readEntries(function (entries) {
                    that._handleFileTreeEntries(
                        entries,
                        path + entry.name + '/'
                    ).done(function (files) {
                        dfd.resolve(files);
                    }).fail(errorHandler);
                }, errorHandler);
            } else {
                // Return an empy list for file system items
                // other than files or directories:
                dfd.resolve([]);
            }
            return dfd.promise();
        },

        _handleFileTreeEntries: function (entries, path) {
            var that = this;
            return $.when.apply(
                $,
                $.map(entries, function (entry) {
                    return that._handleFileTreeEntry(entry, path);
                })
            ).pipe(function () {
                return Array.prototype.concat.apply(
                    [],
                    arguments
                );
            });
        },

        _getDroppedFiles: function (dataTransfer) {
            dataTransfer = dataTransfer || {};
            var items = dataTransfer.items;
            if (items && items.length && (items[0].webkitGetAsEntry ||
                    items[0].getAsEntry)) {
                return this._handleFileTreeEntries(
                    $.map(items, function (item) {
                        var entry;
                        if (item.webkitGetAsEntry) {
                            entry = item.webkitGetAsEntry();
                            if (entry) {
                                // Workaround for Chrome bug #149735:
                                entry._file = item.getAsFile();
                            }
                            return entry;
                        }
                        return item.getAsEntry();
                    })
                );
            }
            return $.Deferred().resolve(
                $.makeArray(dataTransfer.files)
            ).promise();
        },

        _getSingleFileInputFiles: function (fileInput) {
            fileInput = $(fileInput);
            var entries = fileInput.prop('webkitEntries') ||
                    fileInput.prop('entries'),
                files,
                value;
            if (entries && entries.length) {
                return this._handleFileTreeEntries(entries);
            }
            files = $.makeArray(fileInput.prop('files'));
            if (!files.length) {
                value = fileInput.prop('value');
                if (!value) {
                    return $.Deferred().resolve([]).promise();
                }
                // If the files property is not available, the browser does not
                // support the File API and we add a pseudo File object with
                // the input value as name with path information removed:
                files = [{name: value.replace(/^.*\\/, '')}];
            } else if (files[0].name === undefined && files[0].fileName) {
                // File normalization for Safari 4 and Firefox 3:
                $.each(files, function (index, file) {
                    file.name = file.fileName;
                    file.size = file.fileSize;
                });
            }
            return $.Deferred().resolve(files).promise();
        },

        _getFileInputFiles: function (fileInput) {
            if (!(fileInput instanceof $) || fileInput.length === 1) {
                return this._getSingleFileInputFiles(fileInput);
            }
            return $.when.apply(
                $,
                $.map(fileInput, this._getSingleFileInputFiles)
            ).pipe(function () {
                return Array.prototype.concat.apply(
                    [],
                    arguments
                );
            });
        },

        _onChange: function (e) {
            var that = this,
                data = {
                    fileInput: $(e.target),
                    form: $(e.target.form)
                };
            this._getFileInputFiles(data.fileInput).always(function (files) {
                data.files = files;
                if (that.options.replaceFileInput) {
                    that._replaceFileInput(data.fileInput);
                }
                if (that._trigger('change', e, data) !== false) {
                    that._onAdd(e, data);
                }
            });
        },

        _onPaste: function (e) {
            var cbd = e.originalEvent.clipboardData,
                items = (cbd && cbd.items) || [],
                data = {files: []};
            $.each(items, function (index, item) {
                var file = item.getAsFile && item.getAsFile();
                if (file) {
                    data.files.push(file);
                }
            });
            if (this._trigger('paste', e, data) === false ||
                    this._onAdd(e, data) === false) {
                return false;
            }
        },

        _onDrop: function (e) {
            var that = this,
                dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer,
                data = {};
            if (dataTransfer && dataTransfer.files && dataTransfer.files.length) {
                e.preventDefault();
            }
            this._getDroppedFiles(dataTransfer).always(function (files) {
                data.files = files;
                if (that._trigger('drop', e, data) !== false) {
                    that._onAdd(e, data);
                }
            });
        },

        _onDragOver: function (e) {
            var dataTransfer = e.dataTransfer = e.originalEvent.dataTransfer;
            if (this._trigger('dragover', e) === false) {
                return false;
            }
            if (dataTransfer && $.inArray('Files', dataTransfer.types) !== -1) {
                dataTransfer.dropEffect = 'copy';
                e.preventDefault();
            }
        },

        _initEventHandlers: function () {
            if (this._isXHRUpload(this.options)) {
                this._on(this.options.dropZone, {
                    dragover: this._onDragOver,
                    drop: this._onDrop
                });
                this._on(this.options.pasteZone, {
                    paste: this._onPaste
                });
            }
            this._on(this.options.fileInput, {
                change: this._onChange
            });
        },

        _destroyEventHandlers: function () {
            this._off(this.options.dropZone, 'dragover drop');
            this._off(this.options.pasteZone, 'paste');
            this._off(this.options.fileInput, 'change');
        },

        _setOption: function (key, value) {
            var refresh = $.inArray(key, this._refreshOptionsList) !== -1;
            if (refresh) {
                this._destroyEventHandlers();
            }
            this._super(key, value);
            if (refresh) {
                this._initSpecialOptions();
                this._initEventHandlers();
            }
        },

        _initSpecialOptions: function () {
            var options = this.options;
            if (options.fileInput === undefined) {
                options.fileInput = this.element.is('input[type="file"]') ?
                        this.element : this.element.find('input[type="file"]');
            } else if (!(options.fileInput instanceof $)) {
                options.fileInput = $(options.fileInput);
            }
            if (!(options.dropZone instanceof $)) {
                options.dropZone = $(options.dropZone);
            }
            if (!(options.pasteZone instanceof $)) {
                options.pasteZone = $(options.pasteZone);
            }
        },

        _create: function () {
            var options = this.options;
            // Initialize options set via HTML5 data-attributes:
            $.extend(options, $(this.element[0].cloneNode(false)).data());
            this._initSpecialOptions();
            this._slots = [];
            this._sequence = this._getXHRPromise(true);
            this._sending = this._active = 0;
            this._initProgressObject(this);
            this._initEventHandlers();
        },

        // This method is exposed to the widget API and allows to query
        // the widget upload progress.
        // It returns an object with loaded, total and bitrate properties
        // for the running uploads:
        progress: function () {
            return this._progress;
        },

        // This method is exposed to the widget API and allows adding files
        // using the fileupload API. The data parameter accepts an object which
        // must have a files property and can contain additional options:
        // .fileupload('add', {files: filesList});
        add: function (data) {
            var that = this;
            if (!data || this.options.disabled) {
                return;
            }
            if (data.fileInput && !data.files) {
                this._getFileInputFiles(data.fileInput).always(function (files) {
                    data.files = files;
                    that._onAdd(null, data);
                });
            } else {
                data.files = $.makeArray(data.files);
                this._onAdd(null, data);
            }
        },

        // This method is exposed to the widget API and allows sending files
        // using the fileupload API. The data parameter accepts an object which
        // must have a files or fileInput property and can contain additional options:
        // .fileupload('send', {files: filesList});
        // The method returns a Promise object for the file upload call.
        send: function (data) {
            if (data && !this.options.disabled) {
                if (data.fileInput && !data.files) {
                    var that = this,
                        dfd = $.Deferred(),
                        promise = dfd.promise(),
                        jqXHR,
                        aborted;
                    promise.abort = function () {
                        aborted = true;
                        if (jqXHR) {
                            return jqXHR.abort();
                        }
                        dfd.reject(null, 'abort', 'abort');
                        return promise;
                    };
                    this._getFileInputFiles(data.fileInput).always(
                        function (files) {
                            if (aborted) {
                                return;
                            }
                            data.files = files;
                            jqXHR = that._onSend(null, data).then(
                                function (result, textStatus, jqXHR) {
                                    dfd.resolve(result, textStatus, jqXHR);
                                },
                                function (jqXHR, textStatus, errorThrown) {
                                    dfd.reject(jqXHR, textStatus, errorThrown);
                                }
                            );
                        }
                    );
                    return this._enhancePromise(promise);
                }
                data.files = $.makeArray(data.files);
                if (data.files.length) {
                    return this._onSend(null, data);
                }
            }
            return this._getXHRPromise(false, data && data.context);
        }

    });

}));
;
/*
 * jQuery Iframe Transport Plugin 1.6.1
 * https://github.com/blueimp/jQuery-File-Upload
 *
 * Copyright 2011, Sebastian Tschan
 * https://blueimp.net
 *
 * Licensed under the MIT license:
 * http://www.opensource.org/licenses/MIT
 */

/*jslint unparam: true, nomen: true */
/*global define, window, document */

(function (factory) {
    'use strict';
    if (typeof define === 'function' && define.amd) {
        // Register as an anonymous AMD module:
        define(['jquery'], factory);
    } else {
        // Browser globals:
        factory(window.jQuery);
    }
}(function ($) {
    'use strict';

    // Helper variable to create unique names for the transport iframes:
    var counter = 0;

    // The iframe transport accepts three additional options:
    // options.fileInput: a jQuery collection of file input fields
    // options.paramName: the parameter name for the file form data,
    //  overrides the name property of the file input field(s),
    //  can be a string or an array of strings.
    // options.formData: an array of objects with name and value properties,
    //  equivalent to the return data of .serializeArray(), e.g.:
    //  [{name: 'a', value: 1}, {name: 'b', value: 2}]
    $.ajaxTransport('iframe', function (options) {
        if (options.async) {
            var form,
                iframe,
                addParamChar;
            return {
                send: function (_, completeCallback) {
                    form = $('<form style="display:none;"></form>');
                    form.attr('accept-charset', options.formAcceptCharset);
                    addParamChar = /\?/.test(options.url) ? '&' : '?';
                    // XDomainRequest only supports GET and POST:
                    if (options.type === 'DELETE') {
                        options.url = options.url + addParamChar + '_method=DELETE';
                        options.type = 'POST';
                    } else if (options.type === 'PUT') {
                        options.url = options.url + addParamChar + '_method=PUT';
                        options.type = 'POST';
                    } else if (options.type === 'PATCH') {
                        options.url = options.url + addParamChar + '_method=PATCH';
                        options.type = 'POST';
                    }
                    // javascript:false as initial iframe src
                    // prevents warning popups on HTTPS in IE6.
                    // IE versions below IE8 cannot set the name property of
                    // elements that have already been added to the DOM,
                    // so we set the name along with the iframe HTML markup:
                    iframe = $(
                        '<iframe src="javascript:false;" name="iframe-transport-' +
                            (counter += 1) + '"></iframe>'
                    ).bind('load', function () {
                        var fileInputClones,
                            paramNames = $.isArray(options.paramName) ?
                                    options.paramName : [options.paramName];
                        iframe
                            .unbind('load')
                            .bind('load', function () {
                                var response;
                                // Wrap in a try/catch block to catch exceptions thrown
                                // when trying to access cross-domain iframe contents:
                                try {
                                    response = iframe.contents();
                                    // Google Chrome and Firefox do not throw an
                                    // exception when calling iframe.contents() on
                                    // cross-domain requests, so we unify the response:
                                    if (!response.length || !response[0].firstChild) {
                                        throw new Error();
                                    }
                                } catch (e) {
                                    response = undefined;
                                }
                                // The complete callback returns the
                                // iframe content document as response object:
                                completeCallback(
                                    200,
                                    'success',
                                    {'iframe': response}
                                );
                                // Fix for IE endless progress bar activity bug
                                // (happens on form submits to iframe targets):
                                $('<iframe src="javascript:false;"></iframe>')
                                    .appendTo(form);
                                form.remove();
                            });
                        form
                            .prop('target', iframe.prop('name'))
                            .prop('action', options.url)
                            .prop('method', options.type);
                        if (options.formData) {
                            $.each(options.formData, function (index, field) {
                                $('<input type="hidden"/>')
                                    .prop('name', field.name)
                                    .val(field.value)
                                    .appendTo(form);
                            });
                        }
                        if (options.fileInput && options.fileInput.length &&
                                options.type === 'POST') {
                            fileInputClones = options.fileInput.clone();
                            // Insert a clone for each file input field:
                            options.fileInput.after(function (index) {
                                return fileInputClones[index];
                            });
                            if (options.paramName) {
                                options.fileInput.each(function (index) {
                                    $(this).prop(
                                        'name',
                                        paramNames[index] || options.paramName
                                    );
                                });
                            }
                            // Appending the file input fields to the hidden form
                            // removes them from their original location:
                            form
                                .append(options.fileInput)
                                .prop('enctype', 'multipart/form-data')
                                // enctype must be set as encoding for IE:
                                .prop('encoding', 'multipart/form-data');
                        }
                        form.submit();
                        // Insert the file input fields at their original location
                        // by replacing the clones with the originals:
                        if (fileInputClones && fileInputClones.length) {
                            options.fileInput.each(function (index, input) {
                                var clone = $(fileInputClones[index]);
                                $(input).prop('name', clone.prop('name'));
                                clone.replaceWith(input);
                            });
                        }
                    });
                    form.append(iframe).appendTo(document.body);
                },
                abort: function () {
                    if (iframe) {
                        // javascript:false as iframe src aborts the request
                        // and prevents warning popups on HTTPS in IE6.
                        // concat is used to avoid the "Script URL" JSLint error:
                        iframe
                            .unbind('load')
                            .prop('src', 'javascript'.concat(':false;'));
                    }
                    if (form) {
                        form.remove();
                    }
                }
            };
        }
    });

    // The iframe transport returns the iframe content document as response.
    // The following adds converters from iframe to text, json, html, and script:
    $.ajaxSetup({
        converters: {
            'iframe text': function (iframe) {
                return iframe && $(iframe[0].body).text();
            },
            'iframe json': function (iframe) {
                return iframe && $.parseJSON($(iframe[0].body).text());
            },
            'iframe html': function (iframe) {
                return iframe && $(iframe[0].body).html();
            },
            'iframe script': function (iframe) {
                return iframe && $.globalEval($(iframe[0].body).text());
            }
        }
    });

}));
;
/*mousewheel*/
(function(a){function d(b){var c=b||window.event,d=[].slice.call(arguments,1),e=0,f=!0,g=0,h=0;return b=a.event.fix(c),b.type="mousewheel",c.wheelDelta&&(e=c.wheelDelta/120),c.detail&&(e=-c.detail/3),h=e,c.axis!==undefined&&c.axis===c.HORIZONTAL_AXIS&&(h=0,g=-1*e),c.wheelDeltaY!==undefined&&(h=c.wheelDeltaY/120),c.wheelDeltaX!==undefined&&(g=-1*c.wheelDeltaX/120),d.unshift(b,e,g,h),(a.event.dispatch||a.event.handle).apply(this,d)}var b=["DOMMouseScroll","mousewheel"];if(a.event.fixHooks)for(var c=b.length;c;)a.event.fixHooks[b[--c]]=a.event.mouseHooks;a.event.special.mousewheel={setup:function(){if(this.addEventListener)for(var a=b.length;a;)this.addEventListener(b[--a],d,!1);else this.onmousewheel=d},teardown:function(){if(this.removeEventListener)for(var a=b.length;a;)this.removeEventListener(b[--a],d,!1);else this.onmousewheel=null}},a.fn.extend({mousewheel:function(a){return a?this.bind("mousewheel",a):this.trigger("mousewheel")},unmousewheel:function(a){return this.unbind("mousewheel",a)}})})(jQuery);
/*custom scrollbar*/
(function(c){var b={init:function(e){var f={set_width:false,set_height:false,horizontalScroll:false,scrollInertia:950,mouseWheel:true,mouseWheelPixels:"auto",autoDraggerLength:true,autoHideScrollbar:false,snapAmount:null,snapOffset:0,scrollButtons:{enable:false,scrollType:"continuous",scrollSpeed:"auto",scrollAmount:40},advanced:{updateOnBrowserResize:true,updateOnContentResize:false,autoExpandHorizontalScroll:false,autoScrollOnFocus:true,normalizeMouseWheelDelta:false},contentTouchScroll:true,callbacks:{onScrollStart:function(){},onScroll:function(){},onTotalScroll:function(){},onTotalScrollBack:function(){},onTotalScrollOffset:0,onTotalScrollBackOffset:0,whileScrolling:function(){}},theme:"light"},e=c.extend(true,f,e);return this.each(function(){var m=c(this);if(e.set_width){m.css("width",e.set_width)}if(e.set_height){m.css("height",e.set_height)}if(!c(document).data("mCustomScrollbar-index")){c(document).data("mCustomScrollbar-index","1")}else{var t=parseInt(c(document).data("mCustomScrollbar-index"));c(document).data("mCustomScrollbar-index",t+1)}m.wrapInner("<div class='mCustomScrollBox mCS-"+e.theme+"' id='mCSB_"+c(document).data("mCustomScrollbar-index")+"' style='position:relative; height:100%; overflow:hidden; max-width:100%;' />").addClass("mCustomScrollbar _mCS_"+c(document).data("mCustomScrollbar-index"));var g=m.children(".mCustomScrollBox");if(e.horizontalScroll){g.addClass("mCSB_horizontal").wrapInner("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />");var k=g.children(".mCSB_h_wrapper");k.wrapInner("<div class='mCSB_container' style='position:absolute; left:0;' />").children(".mCSB_container").css({width:k.children().outerWidth(),position:"relative"}).unwrap()}else{g.wrapInner("<div class='mCSB_container' style='position:relative; top:0;' />")}var o=g.children(".mCSB_container");if(c.support.touch){o.addClass("mCS_touch")}o.after("<div class='mCSB_scrollTools' style='position:absolute;'><div class='mCSB_draggerContainer'><div class='mCSB_dragger' style='position:absolute;' oncontextmenu='return false;'><div class='mCSB_dragger_bar' style='position:relative;'></div></div><div class='mCSB_draggerRail'></div></div></div>");var l=g.children(".mCSB_scrollTools"),h=l.children(".mCSB_draggerContainer"),q=h.children(".mCSB_dragger");if(e.horizontalScroll){q.data("minDraggerWidth",q.width())}else{q.data("minDraggerHeight",q.height())}if(e.scrollButtons.enable){if(e.horizontalScroll){l.prepend("<a class='mCSB_buttonLeft' oncontextmenu='return false;'></a>").append("<a class='mCSB_buttonRight' oncontextmenu='return false;'></a>")}else{l.prepend("<a class='mCSB_buttonUp' oncontextmenu='return false;'></a>").append("<a class='mCSB_buttonDown' oncontextmenu='return false;'></a>")}}g.bind("scroll",function(){if(!m.is(".mCS_disabled")){g.scrollTop(0).scrollLeft(0)}});m.data({mCS_Init:true,mCustomScrollbarIndex:c(document).data("mCustomScrollbar-index"),horizontalScroll:e.horizontalScroll,scrollInertia:e.scrollInertia,scrollEasing:"mcsEaseOut",mouseWheel:e.mouseWheel,mouseWheelPixels:e.mouseWheelPixels,autoDraggerLength:e.autoDraggerLength,autoHideScrollbar:e.autoHideScrollbar,snapAmount:e.snapAmount,snapOffset:e.snapOffset,scrollButtons_enable:e.scrollButtons.enable,scrollButtons_scrollType:e.scrollButtons.scrollType,scrollButtons_scrollSpeed:e.scrollButtons.scrollSpeed,scrollButtons_scrollAmount:e.scrollButtons.scrollAmount,autoExpandHorizontalScroll:e.advanced.autoExpandHorizontalScroll,autoScrollOnFocus:e.advanced.autoScrollOnFocus,normalizeMouseWheelDelta:e.advanced.normalizeMouseWheelDelta,contentTouchScroll:e.contentTouchScroll,onScrollStart_Callback:e.callbacks.onScrollStart,onScroll_Callback:e.callbacks.onScroll,onTotalScroll_Callback:e.callbacks.onTotalScroll,onTotalScrollBack_Callback:e.callbacks.onTotalScrollBack,onTotalScroll_Offset:e.callbacks.onTotalScrollOffset,onTotalScrollBack_Offset:e.callbacks.onTotalScrollBackOffset,whileScrolling_Callback:e.callbacks.whileScrolling,bindEvent_scrollbar_drag:false,bindEvent_content_touch:false,bindEvent_scrollbar_click:false,bindEvent_mousewheel:false,bindEvent_buttonsContinuous_y:false,bindEvent_buttonsContinuous_x:false,bindEvent_buttonsPixels_y:false,bindEvent_buttonsPixels_x:false,bindEvent_focusin:false,bindEvent_autoHideScrollbar:false,mCSB_buttonScrollRight:false,mCSB_buttonScrollLeft:false,mCSB_buttonScrollDown:false,mCSB_buttonScrollUp:false});if(e.horizontalScroll){if(m.css("max-width")!=="none"){if(!e.advanced.updateOnContentResize){e.advanced.updateOnContentResize=true}}}else{if(m.css("max-height")!=="none"){var s=false,r=parseInt(m.css("max-height"));if(m.css("max-height").indexOf("%")>=0){s=r,r=m.parent().height()*s/100}m.css("overflow","hidden");g.css("max-height",r)}}m.mCustomScrollbar("update");if(e.advanced.updateOnBrowserResize){var i,j=c(window).width(),u=c(window).height();c(window).bind("resize."+m.data("mCustomScrollbarIndex"),function(){if(i){clearTimeout(i)}i=setTimeout(function(){if(!m.is(".mCS_disabled")&&!m.is(".mCS_destroyed")){var w=c(window).width(),v=c(window).height();if(j!==w||u!==v){if(m.css("max-height")!=="none"&&s){g.css("max-height",m.parent().height()*s/100)}m.mCustomScrollbar("update");j=w;u=v}}},150)})}if(e.advanced.updateOnContentResize){var p;if(e.horizontalScroll){var n=o.outerWidth()}else{var n=o.outerHeight()}p=setInterval(function(){if(e.horizontalScroll){if(e.advanced.autoExpandHorizontalScroll){o.css({position:"absolute",width:"auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({width:o.outerWidth(),position:"relative"}).unwrap()}var v=o.outerWidth()}else{var v=o.outerHeight()}if(v!=n){m.mCustomScrollbar("update");n=v}},300)}})},update:function(){var n=c(this),k=n.children(".mCustomScrollBox"),q=k.children(".mCSB_container");q.removeClass("mCS_no_scrollbar");n.removeClass("mCS_disabled mCS_destroyed");k.scrollTop(0).scrollLeft(0);var y=k.children(".mCSB_scrollTools"),o=y.children(".mCSB_draggerContainer"),m=o.children(".mCSB_dragger");if(n.data("horizontalScroll")){var A=y.children(".mCSB_buttonLeft"),t=y.children(".mCSB_buttonRight"),f=k.width();if(n.data("autoExpandHorizontalScroll")){q.css({position:"absolute",width:"auto"}).wrap("<div class='mCSB_h_wrapper' style='position:relative; left:0; width:999999px;' />").css({width:q.outerWidth(),position:"relative"}).unwrap()}var z=q.outerWidth()}else{var w=y.children(".mCSB_buttonUp"),g=y.children(".mCSB_buttonDown"),r=k.height(),i=q.outerHeight()}if(i>r&&!n.data("horizontalScroll")){y.css("display","block");var s=o.height();if(n.data("autoDraggerLength")){var u=Math.round(r/i*s),l=m.data("minDraggerHeight");if(u<=l){m.css({height:l})}else{if(u>=s-10){var p=s-10;m.css({height:p})}else{m.css({height:u})}}m.children(".mCSB_dragger_bar").css({"line-height":m.height()+"px"})}var B=m.height(),x=(i-r)/(s-B);n.data("scrollAmount",x).mCustomScrollbar("scrolling",k,q,o,m,w,g,A,t);var D=Math.abs(q.position().top);n.mCustomScrollbar("scrollTo",D,{scrollInertia:0,trigger:"internal"})}else{if(z>f&&n.data("horizontalScroll")){y.css("display","block");var h=o.width();if(n.data("autoDraggerLength")){var j=Math.round(f/z*h),C=m.data("minDraggerWidth");if(j<=C){m.css({width:C})}else{if(j>=h-10){var e=h-10;m.css({width:e})}else{m.css({width:j})}}}var v=m.width(),x=(z-f)/(h-v);n.data("scrollAmount",x).mCustomScrollbar("scrolling",k,q,o,m,w,g,A,t);var D=Math.abs(q.position().left);n.mCustomScrollbar("scrollTo",D,{scrollInertia:0,trigger:"internal"})}else{k.unbind("mousewheel focusin");if(n.data("horizontalScroll")){m.add(q).css("left",0)}else{m.add(q).css("top",0)}y.css("display","none");q.addClass("mCS_no_scrollbar");n.data({bindEvent_mousewheel:false,bindEvent_focusin:false})}}},scrolling:function(h,p,m,j,w,e,A,v){var k=c(this);if(!k.data("bindEvent_scrollbar_drag")){var n,o;if(c.support.msPointer){j.bind("MSPointerDown",function(H){H.preventDefault();k.data({on_drag:true});j.addClass("mCSB_dragger_onDrag");var G=c(this),J=G.offset(),F=H.originalEvent.pageX-J.left,I=H.originalEvent.pageY-J.top;if(F<G.width()&&F>0&&I<G.height()&&I>0){n=I;o=F}});c(document).bind("MSPointerMove."+k.data("mCustomScrollbarIndex"),function(H){H.preventDefault();if(k.data("on_drag")){var G=j,J=G.offset(),F=H.originalEvent.pageX-J.left,I=H.originalEvent.pageY-J.top;D(n,o,I,F)}}).bind("MSPointerUp."+k.data("mCustomScrollbarIndex"),function(x){k.data({on_drag:false});j.removeClass("mCSB_dragger_onDrag")})}else{j.bind("mousedown touchstart",function(H){H.preventDefault();H.stopImmediatePropagation();var G=c(this),K=G.offset(),F,J;if(H.type==="touchstart"){var I=H.originalEvent.touches[0]||H.originalEvent.changedTouches[0];F=I.pageX-K.left;J=I.pageY-K.top}else{k.data({on_drag:true});j.addClass("mCSB_dragger_onDrag");F=H.pageX-K.left;J=H.pageY-K.top}if(F<G.width()&&F>0&&J<G.height()&&J>0){n=J;o=F}}).bind("touchmove",function(H){H.preventDefault();H.stopImmediatePropagation();var K=H.originalEvent.touches[0]||H.originalEvent.changedTouches[0],G=c(this),J=G.offset(),F=K.pageX-J.left,I=K.pageY-J.top;D(n,o,I,F)});c(document).bind("mousemove."+k.data("mCustomScrollbarIndex"),function(H){if(k.data("on_drag")){var G=j,J=G.offset(),F=H.pageX-J.left,I=H.pageY-J.top;D(n,o,I,F)}}).bind("mouseup."+k.data("mCustomScrollbarIndex"),function(x){k.data({on_drag:false});j.removeClass("mCSB_dragger_onDrag")})}k.data({bindEvent_scrollbar_drag:true})}function D(G,H,I,F){if(k.data("horizontalScroll")){k.mCustomScrollbar("scrollTo",(j.position().left-(H))+F,{moveDragger:true,trigger:"internal"})}else{k.mCustomScrollbar("scrollTo",(j.position().top-(G))+I,{moveDragger:true,trigger:"internal"})}}if(c.support.touch&&k.data("contentTouchScroll")){if(!k.data("bindEvent_content_touch")){var l,B,r,s,u,C,E;p.bind("touchstart",function(x){x.stopImmediatePropagation();l=x.originalEvent.touches[0]||x.originalEvent.changedTouches[0];B=c(this);r=B.offset();u=l.pageX-r.left;s=l.pageY-r.top;C=s;E=u});p.bind("touchmove",function(x){x.preventDefault();x.stopImmediatePropagation();l=x.originalEvent.touches[0]||x.originalEvent.changedTouches[0];B=c(this).parent();r=B.offset();u=l.pageX-r.left;s=l.pageY-r.top;if(k.data("horizontalScroll")){k.mCustomScrollbar("scrollTo",E-u,{trigger:"internal"})}else{k.mCustomScrollbar("scrollTo",C-s,{trigger:"internal"})}})}}if(!k.data("bindEvent_scrollbar_click")){m.bind("click",function(F){var x=(F.pageY-m.offset().top)*k.data("scrollAmount"),y=c(F.target);if(k.data("horizontalScroll")){x=(F.pageX-m.offset().left)*k.data("scrollAmount")}if(y.hasClass("mCSB_draggerContainer")||y.hasClass("mCSB_draggerRail")){k.mCustomScrollbar("scrollTo",x,{trigger:"internal",scrollEasing:"draggerRailEase"})}});k.data({bindEvent_scrollbar_click:true})}if(k.data("mouseWheel")){if(!k.data("bindEvent_mousewheel")){h.bind("mousewheel",function(H,J){var G,F=k.data("mouseWheelPixels"),x=Math.abs(p.position().top),I=j.position().top,y=m.height()-j.height();if(k.data("normalizeMouseWheelDelta")){if(J<0){J=-1}else{J=1}}if(F==="auto"){F=100+Math.round(k.data("scrollAmount")/2)}if(k.data("horizontalScroll")){I=j.position().left;y=m.width()-j.width();x=Math.abs(p.position().left)}if((J>0&&I!==0)||(J<0&&I!==y)){H.preventDefault();H.stopImmediatePropagation()}G=x-(J*F);k.mCustomScrollbar("scrollTo",G,{trigger:"internal"})});k.data({bindEvent_mousewheel:true})}}if(k.data("scrollButtons_enable")){if(k.data("scrollButtons_scrollType")==="pixels"){if(k.data("horizontalScroll")){v.add(A).unbind("mousedown touchstart MSPointerDown mouseup MSPointerUp mouseout MSPointerOut touchend",i,g);k.data({bindEvent_buttonsContinuous_x:false});if(!k.data("bindEvent_buttonsPixels_x")){v.bind("click",function(x){x.preventDefault();q(Math.abs(p.position().left)+k.data("scrollButtons_scrollAmount"))});A.bind("click",function(x){x.preventDefault();q(Math.abs(p.position().left)-k.data("scrollButtons_scrollAmount"))});k.data({bindEvent_buttonsPixels_x:true})}}else{e.add(w).unbind("mousedown touchstart MSPointerDown mouseup MSPointerUp mouseout MSPointerOut touchend",i,g);k.data({bindEvent_buttonsContinuous_y:false});if(!k.data("bindEvent_buttonsPixels_y")){e.bind("click",function(x){x.preventDefault();q(Math.abs(p.position().top)+k.data("scrollButtons_scrollAmount"))});w.bind("click",function(x){x.preventDefault();q(Math.abs(p.position().top)-k.data("scrollButtons_scrollAmount"))});k.data({bindEvent_buttonsPixels_y:true})}}function q(x){if(!j.data("preventAction")){j.data("preventAction",true);k.mCustomScrollbar("scrollTo",x,{trigger:"internal"})}}}else{if(k.data("horizontalScroll")){v.add(A).unbind("click");k.data({bindEvent_buttonsPixels_x:false});if(!k.data("bindEvent_buttonsContinuous_x")){v.bind("mousedown touchstart MSPointerDown",function(y){y.preventDefault();var x=z();k.data({mCSB_buttonScrollRight:setInterval(function(){k.mCustomScrollbar("scrollTo",Math.abs(p.position().left)+x,{trigger:"internal",scrollEasing:"easeOutCirc"})},17)})});var i=function(x){x.preventDefault();clearInterval(k.data("mCSB_buttonScrollRight"))};v.bind("mouseup touchend MSPointerUp mouseout MSPointerOut",i);A.bind("mousedown touchstart MSPointerDown",function(y){y.preventDefault();var x=z();k.data({mCSB_buttonScrollLeft:setInterval(function(){k.mCustomScrollbar("scrollTo",Math.abs(p.position().left)-x,{trigger:"internal",scrollEasing:"easeOutCirc"})},17)})});var g=function(x){x.preventDefault();clearInterval(k.data("mCSB_buttonScrollLeft"))};A.bind("mouseup touchend MSPointerUp mouseout MSPointerOut",g);k.data({bindEvent_buttonsContinuous_x:true})}}else{e.add(w).unbind("click");k.data({bindEvent_buttonsPixels_y:false});if(!k.data("bindEvent_buttonsContinuous_y")){e.bind("mousedown touchstart MSPointerDown",function(y){y.preventDefault();var x=z();k.data({mCSB_buttonScrollDown:setInterval(function(){k.mCustomScrollbar("scrollTo",Math.abs(p.position().top)+x,{trigger:"internal",scrollEasing:"easeOutCirc"})},17)})});var t=function(x){x.preventDefault();clearInterval(k.data("mCSB_buttonScrollDown"))};e.bind("mouseup touchend MSPointerUp mouseout MSPointerOut",t);w.bind("mousedown touchstart MSPointerDown",function(y){y.preventDefault();var x=z();k.data({mCSB_buttonScrollUp:setInterval(function(){k.mCustomScrollbar("scrollTo",Math.abs(p.position().top)-x,{trigger:"internal",scrollEasing:"easeOutCirc"})},17)})});var f=function(x){x.preventDefault();clearInterval(k.data("mCSB_buttonScrollUp"))};w.bind("mouseup touchend MSPointerUp mouseout MSPointerOut",f);k.data({bindEvent_buttonsContinuous_y:true})}}function z(){var x=k.data("scrollButtons_scrollSpeed");if(k.data("scrollButtons_scrollSpeed")==="auto"){x=Math.round((k.data("scrollInertia")+100)/40)}return x}}}if(k.data("autoScrollOnFocus")){if(!k.data("bindEvent_focusin")){h.bind("focusin",function(){h.scrollTop(0).scrollLeft(0);var x=c(document.activeElement);if(x.is("input,textarea,select,button,a[tabindex],area,object")){var G=p.position().top,y=x.position().top,F=h.height()-x.outerHeight();if(k.data("horizontalScroll")){G=p.position().left;y=x.position().left;F=h.width()-x.outerWidth()}if(G+y<0||G+y>F){k.mCustomScrollbar("scrollTo",y,{trigger:"internal"})}}});k.data({bindEvent_focusin:true})}}if(k.data("autoHideScrollbar")){if(!k.data("bindEvent_autoHideScrollbar")){h.bind("mouseenter",function(x){h.addClass("mCS-mouse-over");d.showScrollbar.call(h.children(".mCSB_scrollTools"))}).bind("mouseleave touchend",function(x){h.removeClass("mCS-mouse-over");if(x.type==="mouseleave"){d.hideScrollbar.call(h.children(".mCSB_scrollTools"))}});k.data({bindEvent_autoHideScrollbar:true})}}},scrollTo:function(e,f){var i=c(this),o={moveDragger:false,trigger:"external",callbacks:true,scrollInertia:i.data("scrollInertia"),scrollEasing:i.data("scrollEasing")},f=c.extend(o,f),p,g=i.children(".mCustomScrollBox"),k=g.children(".mCSB_container"),r=g.children(".mCSB_scrollTools"),j=r.children(".mCSB_draggerContainer"),h=j.children(".mCSB_dragger"),t=draggerSpeed=f.scrollInertia,q,s,m,l;if(!k.hasClass("mCS_no_scrollbar")){i.data({mCS_trigger:f.trigger});if(i.data("mCS_Init")){f.callbacks=false}if(e||e===0){if(typeof(e)==="number"){if(f.moveDragger){p=e;if(i.data("horizontalScroll")){e=h.position().left*i.data("scrollAmount")}else{e=h.position().top*i.data("scrollAmount")}draggerSpeed=0}else{p=e/i.data("scrollAmount")}}else{if(typeof(e)==="string"){var v;if(e==="top"){v=0}else{if(e==="bottom"&&!i.data("horizontalScroll")){v=k.outerHeight()-g.height()}else{if(e==="left"){v=0}else{if(e==="right"&&i.data("horizontalScroll")){v=k.outerWidth()-g.width()}else{if(e==="first"){v=i.find(".mCSB_container").find(":first")}else{if(e==="last"){v=i.find(".mCSB_container").find(":last")}else{v=i.find(e)}}}}}}if(v.length===1){if(i.data("horizontalScroll")){e=v.position().left}else{e=v.position().top}p=e/i.data("scrollAmount")}else{p=e=v}}}if(i.data("horizontalScroll")){if(i.data("onTotalScrollBack_Offset")){s=-i.data("onTotalScrollBack_Offset")}if(i.data("onTotalScroll_Offset")){l=g.width()-k.outerWidth()+i.data("onTotalScroll_Offset")}if(p<0){p=e=0;clearInterval(i.data("mCSB_buttonScrollLeft"));if(!s){q=true}}else{if(p>=j.width()-h.width()){p=j.width()-h.width();e=g.width()-k.outerWidth();clearInterval(i.data("mCSB_buttonScrollRight"));if(!l){m=true}}else{e=-e}}var n=i.data("snapAmount");if(n){e=Math.round(e/n)*n-i.data("snapOffset")}d.mTweenAxis.call(this,h[0],"left",Math.round(p),draggerSpeed,f.scrollEasing);d.mTweenAxis.call(this,k[0],"left",Math.round(e),t,f.scrollEasing,{onStart:function(){if(f.callbacks&&!i.data("mCS_tweenRunning")){u("onScrollStart")}if(i.data("autoHideScrollbar")){d.showScrollbar.call(r)}},onUpdate:function(){if(f.callbacks){u("whileScrolling")}},onComplete:function(){if(f.callbacks){u("onScroll");if(q||(s&&k.position().left>=s)){u("onTotalScrollBack")}if(m||(l&&k.position().left<=l)){u("onTotalScroll")}}h.data("preventAction",false);i.data("mCS_tweenRunning",false);if(i.data("autoHideScrollbar")){if(!g.hasClass("mCS-mouse-over")){d.hideScrollbar.call(r)}}}})}else{if(i.data("onTotalScrollBack_Offset")){s=-i.data("onTotalScrollBack_Offset")}if(i.data("onTotalScroll_Offset")){l=g.height()-k.outerHeight()+i.data("onTotalScroll_Offset")}if(p<0){p=e=0;clearInterval(i.data("mCSB_buttonScrollUp"));if(!s){q=true}}else{if(p>=j.height()-h.height()){p=j.height()-h.height();e=g.height()-k.outerHeight();clearInterval(i.data("mCSB_buttonScrollDown"));if(!l){m=true}}else{e=-e}}var n=i.data("snapAmount");if(n){e=Math.round(e/n)*n-i.data("snapOffset")}d.mTweenAxis.call(this,h[0],"top",Math.round(p),draggerSpeed,f.scrollEasing);d.mTweenAxis.call(this,k[0],"top",Math.round(e),t,f.scrollEasing,{onStart:function(){if(f.callbacks&&!i.data("mCS_tweenRunning")){u("onScrollStart")}if(i.data("autoHideScrollbar")){d.showScrollbar.call(r)}},onUpdate:function(){if(f.callbacks){u("whileScrolling")}},onComplete:function(){if(f.callbacks){u("onScroll");if(q||(s&&k.position().top>=s)){u("onTotalScrollBack")}if(m||(l&&k.position().top<=l)){u("onTotalScroll")}}h.data("preventAction",false);i.data("mCS_tweenRunning",false);if(i.data("autoHideScrollbar")){if(!g.hasClass("mCS-mouse-over")){d.hideScrollbar.call(r)}}}})}if(i.data("mCS_Init")){i.data({mCS_Init:false})}}}function u(w){this.mcs={top:k.position().top,left:k.position().left,draggerTop:h.position().top,draggerLeft:h.position().left,topPct:Math.round((100*Math.abs(k.position().top))/Math.abs(k.outerHeight()-g.height())),leftPct:Math.round((100*Math.abs(k.position().left))/Math.abs(k.outerWidth()-g.width()))};switch(w){case"onScrollStart":i.data("mCS_tweenRunning",true).data("onScrollStart_Callback").call(i,this.mcs);break;case"whileScrolling":i.data("whileScrolling_Callback").call(i,this.mcs);break;case"onScroll":i.data("onScroll_Callback").call(i,this.mcs);break;case"onTotalScrollBack":i.data("onTotalScrollBack_Callback").call(i,this.mcs);break;case"onTotalScroll":i.data("onTotalScroll_Callback").call(i,this.mcs);break}}},stop:function(){var g=c(this),e=g.children().children(".mCSB_container"),f=g.children().children().children().children(".mCSB_dragger");d.mTweenAxisStop.call(this,e[0]);d.mTweenAxisStop.call(this,f[0])},disable:function(e){var j=c(this),f=j.children(".mCustomScrollBox"),h=f.children(".mCSB_container"),g=f.children(".mCSB_scrollTools"),i=g.children().children(".mCSB_dragger");f.unbind("mousewheel focusin mouseenter mouseleave touchend");h.unbind("touchstart touchmove");if(e){if(j.data("horizontalScroll")){i.add(h).css("left",0)}else{i.add(h).css("top",0)}}g.css("display","none");h.addClass("mCS_no_scrollbar");j.data({bindEvent_mousewheel:false,bindEvent_focusin:false,bindEvent_content_touch:false,bindEvent_autoHideScrollbar:false}).addClass("mCS_disabled")},destroy:function(){var e=c(this);e.removeClass("mCustomScrollbar _mCS_"+e.data("mCustomScrollbarIndex")).addClass("mCS_destroyed").children().children(".mCSB_container").unwrap().children().unwrap().siblings(".mCSB_scrollTools").remove();c(document).unbind("mousemove."+e.data("mCustomScrollbarIndex")+" mouseup."+e.data("mCustomScrollbarIndex")+" MSPointerMove."+e.data("mCustomScrollbarIndex")+" MSPointerUp."+e.data("mCustomScrollbarIndex"));c(window).unbind("resize."+e.data("mCustomScrollbarIndex"))}},d={showScrollbar:function(){this.stop().animate({opacity:1},"fast")},hideScrollbar:function(){this.stop().animate({opacity:0},"fast")},mTweenAxis:function(g,i,h,f,o,y){var y=y||{},v=y.onStart||function(){},p=y.onUpdate||function(){},w=y.onComplete||function(){};var n=t(),l,j=0,r=g.offsetTop,s=g.style;if(i==="left"){r=g.offsetLeft}var m=h-r;q();e();function t(){if(window.performance&&window.performance.now){return window.performance.now()}else{if(window.performance&&window.performance.webkitNow){return window.performance.webkitNow()}else{if(Date.now){return Date.now()}else{return new Date().getTime()}}}}function x(){if(!j){v.call()}j=t()-n;u();if(j>=g._time){g._time=(j>g._time)?j+l-(j-g._time):j+l-1;if(g._time<j+1){g._time=j+1}}if(g._time<f){g._id=_request(x)}else{w.call()}}function u(){if(f>0){g.currVal=k(g._time,r,m,f,o);s[i]=Math.round(g.currVal)+"px"}else{s[i]=h+"px"}p.call()}function e(){l=1000/60;g._time=j+l;_request=(!window.requestAnimationFrame)?function(z){u();return setTimeout(z,0.01)}:window.requestAnimationFrame;g._id=_request(x)}function q(){if(g._id==null){return}if(!window.requestAnimationFrame){clearTimeout(g._id)}else{window.cancelAnimationFrame(g._id)}g._id=null}function k(B,A,F,E,C){switch(C){case"linear":return F*B/E+A;break;case"easeOutQuad":B/=E;return -F*B*(B-2)+A;break;case"easeInOutQuad":B/=E/2;if(B<1){return F/2*B*B+A}B--;return -F/2*(B*(B-2)-1)+A;break;case"easeOutCubic":B/=E;B--;return F*(B*B*B+1)+A;break;case"easeOutQuart":B/=E;B--;return -F*(B*B*B*B-1)+A;break;case"easeOutQuint":B/=E;B--;return F*(B*B*B*B*B+1)+A;break;case"easeOutCirc":B/=E;B--;return F*Math.sqrt(1-B*B)+A;break;case"easeOutSine":return F*Math.sin(B/E*(Math.PI/2))+A;break;case"easeOutExpo":return F*(-Math.pow(2,-10*B/E)+1)+A;break;case"mcsEaseOut":var D=(B/=E)*B,z=D*B;return A+F*(0.499999999999997*z*D+-2.5*D*D+5.5*z+-6.5*D+4*B);break;case"draggerRailEase":B/=E/2;if(B<1){return F/2*B*B*B+A}B-=2;return F/2*(B*B*B+2)+A;break}}},mTweenAxisStop:function(e){if(e._id==null){return}if(!window.requestAnimationFrame){clearTimeout(e._id)}else{window.cancelAnimationFrame(e._id)}e._id=null},rafPolyfill:function(){var f=["ms","moz","webkit","o"],e=f.length;while(--e>-1&&!window.requestAnimationFrame){window.requestAnimationFrame=window[f[e]+"RequestAnimationFrame"];window.cancelAnimationFrame=window[f[e]+"CancelAnimationFrame"]||window[f[e]+"CancelRequestAnimationFrame"]}}};d.rafPolyfill.call();c.support.touch=!!("ontouchstart" in window);c.support.msPointer=window.navigator.msPointerEnabled;var a=("https:"==document.location.protocol)?"https:":"http:";c.event.special.mousewheel||document.write('<script src="'+a+'//cdnjs.cloudflare.com/ajax/libs/jquery-mousewheel/3.0.6/jquery.mousewheel.min.js"><\/script>');c.fn.mCustomScrollbar=function(e){if(b[e]){return b[e].apply(this,Array.prototype.slice.call(arguments,1))}else{if(typeof e==="object"||!e){return b.init.apply(this,arguments)}else{c.error("Method "+e+" does not exist")}}}})(jQuery);;
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):e.moment=t()}(this,function(){"use strict";var H;function f(){return H.apply(null,arguments)}function a(e){return e instanceof Array||"[object Array]"===Object.prototype.toString.call(e)}function F(e){return null!=e&&"[object Object]"===Object.prototype.toString.call(e)}function c(e,t){return Object.prototype.hasOwnProperty.call(e,t)}function L(e){if(Object.getOwnPropertyNames)return 0===Object.getOwnPropertyNames(e).length;for(var t in e)if(c(e,t))return;return 1}function o(e){return void 0===e}function u(e){return"number"==typeof e||"[object Number]"===Object.prototype.toString.call(e)}function V(e){return e instanceof Date||"[object Date]"===Object.prototype.toString.call(e)}function G(e,t){for(var n=[],s=e.length,i=0;i<s;++i)n.push(t(e[i],i));return n}function E(e,t){for(var n in t)c(t,n)&&(e[n]=t[n]);return c(t,"toString")&&(e.toString=t.toString),c(t,"valueOf")&&(e.valueOf=t.valueOf),e}function l(e,t,n,s){return Pt(e,t,n,s,!0).utc()}function m(e){return null==e._pf&&(e._pf={empty:!1,unusedTokens:[],unusedInput:[],overflow:-2,charsLeftOver:0,nullInput:!1,invalidEra:null,invalidMonth:null,invalidFormat:!1,userInvalidated:!1,iso:!1,parsedDateParts:[],era:null,meridiem:null,rfc2822:!1,weekdayMismatch:!1}),e._pf}function A(e){if(null==e._isValid){var t=m(e),n=j.call(t.parsedDateParts,function(e){return null!=e}),n=!isNaN(e._d.getTime())&&t.overflow<0&&!t.empty&&!t.invalidEra&&!t.invalidMonth&&!t.invalidWeekday&&!t.weekdayMismatch&&!t.nullInput&&!t.invalidFormat&&!t.userInvalidated&&(!t.meridiem||t.meridiem&&n);if(e._strict&&(n=n&&0===t.charsLeftOver&&0===t.unusedTokens.length&&void 0===t.bigHour),null!=Object.isFrozen&&Object.isFrozen(e))return n;e._isValid=n}return e._isValid}function I(e){var t=l(NaN);return null!=e?E(m(t),e):m(t).userInvalidated=!0,t}var j=Array.prototype.some||function(e){for(var t=Object(this),n=t.length>>>0,s=0;s<n;s++)if(s in t&&e.call(this,t[s],s,t))return!0;return!1},Z=f.momentProperties=[],z=!1;function $(e,t){var n,s,i,r=Z.length;if(o(t._isAMomentObject)||(e._isAMomentObject=t._isAMomentObject),o(t._i)||(e._i=t._i),o(t._f)||(e._f=t._f),o(t._l)||(e._l=t._l),o(t._strict)||(e._strict=t._strict),o(t._tzm)||(e._tzm=t._tzm),o(t._isUTC)||(e._isUTC=t._isUTC),o(t._offset)||(e._offset=t._offset),o(t._pf)||(e._pf=m(t)),o(t._locale)||(e._locale=t._locale),0<r)for(n=0;n<r;n++)o(i=t[s=Z[n]])||(e[s]=i);return e}function q(e){$(this,e),this._d=new Date(null!=e._d?e._d.getTime():NaN),this.isValid()||(this._d=new Date(NaN)),!1===z&&(z=!0,f.updateOffset(this),z=!1)}function h(e){return e instanceof q||null!=e&&null!=e._isAMomentObject}function B(e){!1===f.suppressDeprecationWarnings&&"undefined"!=typeof console&&console.warn&&console.warn("Deprecation warning: "+e)}function e(r,a){var o=!0;return E(function(){if(null!=f.deprecationHandler&&f.deprecationHandler(null,r),o){for(var e,t,n=[],s=arguments.length,i=0;i<s;i++){if(e="","object"==typeof arguments[i]){for(t in e+="\n["+i+"] ",arguments[0])c(arguments[0],t)&&(e+=t+": "+arguments[0][t]+", ");e=e.slice(0,-2)}else e=arguments[i];n.push(e)}B(r+"\nArguments: "+Array.prototype.slice.call(n).join("")+"\n"+(new Error).stack),o=!1}return a.apply(this,arguments)},a)}var J={};function Q(e,t){null!=f.deprecationHandler&&f.deprecationHandler(e,t),J[e]||(B(t),J[e]=!0)}function d(e){return"undefined"!=typeof Function&&e instanceof Function||"[object Function]"===Object.prototype.toString.call(e)}function X(e,t){var n,s=E({},e);for(n in t)c(t,n)&&(F(e[n])&&F(t[n])?(s[n]={},E(s[n],e[n]),E(s[n],t[n])):null!=t[n]?s[n]=t[n]:delete s[n]);for(n in e)c(e,n)&&!c(t,n)&&F(e[n])&&(s[n]=E({},s[n]));return s}function K(e){null!=e&&this.set(e)}f.suppressDeprecationWarnings=!1,f.deprecationHandler=null;var ee=Object.keys||function(e){var t,n=[];for(t in e)c(e,t)&&n.push(t);return n};function r(e,t,n){var s=""+Math.abs(e);return(0<=e?n?"+":"":"-")+Math.pow(10,Math.max(0,t-s.length)).toString().substr(1)+s}var te=/(\[[^\[]*\])|(\\)?([Hh]mm(ss)?|Mo|MM?M?M?|Do|DDDo|DD?D?D?|ddd?d?|do?|w[o|w]?|W[o|W]?|Qo?|N{1,5}|YYYYYY|YYYYY|YYYY|YY|y{2,4}|yo?|gg(ggg?)?|GG(GGG?)?|e|E|a|A|hh?|HH?|kk?|mm?|ss?|S{1,9}|x|X|zz?|ZZ?|.)/g,ne=/(\[[^\[]*\])|(\\)?(LTS|LT|LL?L?L?|l{1,4})/g,se={},ie={};function s(e,t,n,s){var i="string"==typeof s?function(){return this[s]()}:s;e&&(ie[e]=i),t&&(ie[t[0]]=function(){return r(i.apply(this,arguments),t[1],t[2])}),n&&(ie[n]=function(){return this.localeData().ordinal(i.apply(this,arguments),e)})}function re(e,t){return e.isValid()?(t=ae(t,e.localeData()),se[t]=se[t]||function(s){for(var e,i=s.match(te),t=0,r=i.length;t<r;t++)ie[i[t]]?i[t]=ie[i[t]]:i[t]=(e=i[t]).match(/\[[\s\S]/)?e.replace(/^\[|\]$/g,""):e.replace(/\\/g,"");return function(e){for(var t="",n=0;n<r;n++)t+=d(i[n])?i[n].call(e,s):i[n];return t}}(t),se[t](e)):e.localeData().invalidDate()}function ae(e,t){var n=5;function s(e){return t.longDateFormat(e)||e}for(ne.lastIndex=0;0<=n&&ne.test(e);)e=e.replace(ne,s),ne.lastIndex=0,--n;return e}var oe={};function t(e,t){var n=e.toLowerCase();oe[n]=oe[n+"s"]=oe[t]=e}function _(e){return"string"==typeof e?oe[e]||oe[e.toLowerCase()]:void 0}function ue(e){var t,n,s={};for(n in e)c(e,n)&&(t=_(n))&&(s[t]=e[n]);return s}var le={};function n(e,t){le[e]=t}function he(e){return e%4==0&&e%100!=0||e%400==0}function y(e){return e<0?Math.ceil(e)||0:Math.floor(e)}function g(e){var e=+e,t=0;return t=0!=e&&isFinite(e)?y(e):t}function de(t,n){return function(e){return null!=e?(fe(this,t,e),f.updateOffset(this,n),this):ce(this,t)}}function ce(e,t){return e.isValid()?e._d["get"+(e._isUTC?"UTC":"")+t]():NaN}function fe(e,t,n){e.isValid()&&!isNaN(n)&&("FullYear"===t&&he(e.year())&&1===e.month()&&29===e.date()?(n=g(n),e._d["set"+(e._isUTC?"UTC":"")+t](n,e.month(),We(n,e.month()))):e._d["set"+(e._isUTC?"UTC":"")+t](n))}var i=/\d/,w=/\d\d/,me=/\d{3}/,_e=/\d{4}/,ye=/[+-]?\d{6}/,p=/\d\d?/,ge=/\d\d\d\d?/,we=/\d\d\d\d\d\d?/,pe=/\d{1,3}/,ke=/\d{1,4}/,ve=/[+-]?\d{1,6}/,Me=/\d+/,De=/[+-]?\d+/,Se=/Z|[+-]\d\d:?\d\d/gi,Ye=/Z|[+-]\d\d(?::?\d\d)?/gi,k=/[0-9]{0,256}['a-z\u00A0-\u05FF\u0700-\uD7FF\uF900-\uFDCF\uFDF0-\uFF07\uFF10-\uFFEF]{1,256}|[\u0600-\u06FF\/]{1,256}(\s*?[\u0600-\u06FF]{1,256}){1,2}/i;function v(e,n,s){be[e]=d(n)?n:function(e,t){return e&&s?s:n}}function Oe(e,t){return c(be,e)?be[e](t._strict,t._locale):new RegExp(M(e.replace("\\","").replace(/\\(\[)|\\(\])|\[([^\]\[]*)\]|\\(.)/g,function(e,t,n,s,i){return t||n||s||i})))}function M(e){return e.replace(/[-\/\\^$*+?.()|[\]{}]/g,"\\$&")}var be={},xe={};function D(e,n){var t,s,i=n;for("string"==typeof e&&(e=[e]),u(n)&&(i=function(e,t){t[n]=g(e)}),s=e.length,t=0;t<s;t++)xe[e[t]]=i}function Te(e,i){D(e,function(e,t,n,s){n._w=n._w||{},i(e,n._w,n,s)})}var S,Y=0,O=1,b=2,x=3,T=4,N=5,Ne=6,Pe=7,Re=8;function We(e,t){if(isNaN(e)||isNaN(t))return NaN;var n=(t%(n=12)+n)%n;return e+=(t-n)/12,1==n?he(e)?29:28:31-n%7%2}S=Array.prototype.indexOf||function(e){for(var t=0;t<this.length;++t)if(this[t]===e)return t;return-1},s("M",["MM",2],"Mo",function(){return this.month()+1}),s("MMM",0,0,function(e){return this.localeData().monthsShort(this,e)}),s("MMMM",0,0,function(e){return this.localeData().months(this,e)}),t("month","M"),n("month",8),v("M",p),v("MM",p,w),v("MMM",function(e,t){return t.monthsShortRegex(e)}),v("MMMM",function(e,t){return t.monthsRegex(e)}),D(["M","MM"],function(e,t){t[O]=g(e)-1}),D(["MMM","MMMM"],function(e,t,n,s){s=n._locale.monthsParse(e,s,n._strict);null!=s?t[O]=s:m(n).invalidMonth=e});var Ce="January_February_March_April_May_June_July_August_September_October_November_December".split("_"),Ue="Jan_Feb_Mar_Apr_May_Jun_Jul_Aug_Sep_Oct_Nov_Dec".split("_"),He=/D[oD]?(\[[^\[\]]*\]|\s)+MMMM?/,Fe=k,Le=k;function Ve(e,t){var n;if(e.isValid()){if("string"==typeof t)if(/^\d+$/.test(t))t=g(t);else if(!u(t=e.localeData().monthsParse(t)))return;n=Math.min(e.date(),We(e.year(),t)),e._d["set"+(e._isUTC?"UTC":"")+"Month"](t,n)}}function Ge(e){return null!=e?(Ve(this,e),f.updateOffset(this,!0),this):ce(this,"Month")}function Ee(){function e(e,t){return t.length-e.length}for(var t,n=[],s=[],i=[],r=0;r<12;r++)t=l([2e3,r]),n.push(this.monthsShort(t,"")),s.push(this.months(t,"")),i.push(this.months(t,"")),i.push(this.monthsShort(t,""));for(n.sort(e),s.sort(e),i.sort(e),r=0;r<12;r++)n[r]=M(n[r]),s[r]=M(s[r]);for(r=0;r<24;r++)i[r]=M(i[r]);this._monthsRegex=new RegExp("^("+i.join("|")+")","i"),this._monthsShortRegex=this._monthsRegex,this._monthsStrictRegex=new RegExp("^("+s.join("|")+")","i"),this._monthsShortStrictRegex=new RegExp("^("+n.join("|")+")","i")}function Ae(e){return he(e)?366:365}s("Y",0,0,function(){var e=this.year();return e<=9999?r(e,4):"+"+e}),s(0,["YY",2],0,function(){return this.year()%100}),s(0,["YYYY",4],0,"year"),s(0,["YYYYY",5],0,"year"),s(0,["YYYYYY",6,!0],0,"year"),t("year","y"),n("year",1),v("Y",De),v("YY",p,w),v("YYYY",ke,_e),v("YYYYY",ve,ye),v("YYYYYY",ve,ye),D(["YYYYY","YYYYYY"],Y),D("YYYY",function(e,t){t[Y]=2===e.length?f.parseTwoDigitYear(e):g(e)}),D("YY",function(e,t){t[Y]=f.parseTwoDigitYear(e)}),D("Y",function(e,t){t[Y]=parseInt(e,10)}),f.parseTwoDigitYear=function(e){return g(e)+(68<g(e)?1900:2e3)};var Ie=de("FullYear",!0);function je(e,t,n,s,i,r,a){var o;return e<100&&0<=e?(o=new Date(e+400,t,n,s,i,r,a),isFinite(o.getFullYear())&&o.setFullYear(e)):o=new Date(e,t,n,s,i,r,a),o}function Ze(e){var t;return e<100&&0<=e?((t=Array.prototype.slice.call(arguments))[0]=e+400,t=new Date(Date.UTC.apply(null,t)),isFinite(t.getUTCFullYear())&&t.setUTCFullYear(e)):t=new Date(Date.UTC.apply(null,arguments)),t}function ze(e,t,n){n=7+t-n;return n-(7+Ze(e,0,n).getUTCDay()-t)%7-1}function $e(e,t,n,s,i){var r,t=1+7*(t-1)+(7+n-s)%7+ze(e,s,i),n=t<=0?Ae(r=e-1)+t:t>Ae(e)?(r=e+1,t-Ae(e)):(r=e,t);return{year:r,dayOfYear:n}}function qe(e,t,n){var s,i,r=ze(e.year(),t,n),r=Math.floor((e.dayOfYear()-r-1)/7)+1;return r<1?s=r+P(i=e.year()-1,t,n):r>P(e.year(),t,n)?(s=r-P(e.year(),t,n),i=e.year()+1):(i=e.year(),s=r),{week:s,year:i}}function P(e,t,n){var s=ze(e,t,n),t=ze(e+1,t,n);return(Ae(e)-s+t)/7}s("w",["ww",2],"wo","week"),s("W",["WW",2],"Wo","isoWeek"),t("week","w"),t("isoWeek","W"),n("week",5),n("isoWeek",5),v("w",p),v("ww",p,w),v("W",p),v("WW",p,w),Te(["w","ww","W","WW"],function(e,t,n,s){t[s.substr(0,1)]=g(e)});function Be(e,t){return e.slice(t,7).concat(e.slice(0,t))}s("d",0,"do","day"),s("dd",0,0,function(e){return this.localeData().weekdaysMin(this,e)}),s("ddd",0,0,function(e){return this.localeData().weekdaysShort(this,e)}),s("dddd",0,0,function(e){return this.localeData().weekdays(this,e)}),s("e",0,0,"weekday"),s("E",0,0,"isoWeekday"),t("day","d"),t("weekday","e"),t("isoWeekday","E"),n("day",11),n("weekday",11),n("isoWeekday",11),v("d",p),v("e",p),v("E",p),v("dd",function(e,t){return t.weekdaysMinRegex(e)}),v("ddd",function(e,t){return t.weekdaysShortRegex(e)}),v("dddd",function(e,t){return t.weekdaysRegex(e)}),Te(["dd","ddd","dddd"],function(e,t,n,s){s=n._locale.weekdaysParse(e,s,n._strict);null!=s?t.d=s:m(n).invalidWeekday=e}),Te(["d","e","E"],function(e,t,n,s){t[s]=g(e)});var Je="Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday".split("_"),Qe="Sun_Mon_Tue_Wed_Thu_Fri_Sat".split("_"),Xe="Su_Mo_Tu_We_Th_Fr_Sa".split("_"),Ke=k,et=k,tt=k;function nt(){function e(e,t){return t.length-e.length}for(var t,n,s,i=[],r=[],a=[],o=[],u=0;u<7;u++)s=l([2e3,1]).day(u),t=M(this.weekdaysMin(s,"")),n=M(this.weekdaysShort(s,"")),s=M(this.weekdays(s,"")),i.push(t),r.push(n),a.push(s),o.push(t),o.push(n),o.push(s);i.sort(e),r.sort(e),a.sort(e),o.sort(e),this._weekdaysRegex=new RegExp("^("+o.join("|")+")","i"),this._weekdaysShortRegex=this._weekdaysRegex,this._weekdaysMinRegex=this._weekdaysRegex,this._weekdaysStrictRegex=new RegExp("^("+a.join("|")+")","i"),this._weekdaysShortStrictRegex=new RegExp("^("+r.join("|")+")","i"),this._weekdaysMinStrictRegex=new RegExp("^("+i.join("|")+")","i")}function st(){return this.hours()%12||12}function it(e,t){s(e,0,0,function(){return this.localeData().meridiem(this.hours(),this.minutes(),t)})}function rt(e,t){return t._meridiemParse}s("H",["HH",2],0,"hour"),s("h",["hh",2],0,st),s("k",["kk",2],0,function(){return this.hours()||24}),s("hmm",0,0,function(){return""+st.apply(this)+r(this.minutes(),2)}),s("hmmss",0,0,function(){return""+st.apply(this)+r(this.minutes(),2)+r(this.seconds(),2)}),s("Hmm",0,0,function(){return""+this.hours()+r(this.minutes(),2)}),s("Hmmss",0,0,function(){return""+this.hours()+r(this.minutes(),2)+r(this.seconds(),2)}),it("a",!0),it("A",!1),t("hour","h"),n("hour",13),v("a",rt),v("A",rt),v("H",p),v("h",p),v("k",p),v("HH",p,w),v("hh",p,w),v("kk",p,w),v("hmm",ge),v("hmmss",we),v("Hmm",ge),v("Hmmss",we),D(["H","HH"],x),D(["k","kk"],function(e,t,n){e=g(e);t[x]=24===e?0:e}),D(["a","A"],function(e,t,n){n._isPm=n._locale.isPM(e),n._meridiem=e}),D(["h","hh"],function(e,t,n){t[x]=g(e),m(n).bigHour=!0}),D("hmm",function(e,t,n){var s=e.length-2;t[x]=g(e.substr(0,s)),t[T]=g(e.substr(s)),m(n).bigHour=!0}),D("hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[x]=g(e.substr(0,s)),t[T]=g(e.substr(s,2)),t[N]=g(e.substr(i)),m(n).bigHour=!0}),D("Hmm",function(e,t,n){var s=e.length-2;t[x]=g(e.substr(0,s)),t[T]=g(e.substr(s))}),D("Hmmss",function(e,t,n){var s=e.length-4,i=e.length-2;t[x]=g(e.substr(0,s)),t[T]=g(e.substr(s,2)),t[N]=g(e.substr(i))});k=de("Hours",!0);var at,ot={calendar:{sameDay:"[Today at] LT",nextDay:"[Tomorrow at] LT",nextWeek:"dddd [at] LT",lastDay:"[Yesterday at] LT",lastWeek:"[Last] dddd [at] LT",sameElse:"L"},longDateFormat:{LTS:"h:mm:ss A",LT:"h:mm A",L:"MM/DD/YYYY",LL:"MMMM D, YYYY",LLL:"MMMM D, YYYY h:mm A",LLLL:"dddd, MMMM D, YYYY h:mm A"},invalidDate:"Invalid date",ordinal:"%d",dayOfMonthOrdinalParse:/\d{1,2}/,relativeTime:{future:"in %s",past:"%s ago",s:"a few seconds",ss:"%d seconds",m:"a minute",mm:"%d minutes",h:"an hour",hh:"%d hours",d:"a day",dd:"%d days",w:"a week",ww:"%d weeks",M:"a month",MM:"%d months",y:"a year",yy:"%d years"},months:Ce,monthsShort:Ue,week:{dow:0,doy:6},weekdays:Je,weekdaysMin:Xe,weekdaysShort:Qe,meridiemParse:/[ap]\.?m?\.?/i},R={},ut={};function lt(e){return e&&e.toLowerCase().replace("_","-")}function ht(e){for(var t,n,s,i,r=0;r<e.length;){for(t=(i=lt(e[r]).split("-")).length,n=(n=lt(e[r+1]))?n.split("-"):null;0<t;){if(s=dt(i.slice(0,t).join("-")))return s;if(n&&n.length>=t&&function(e,t){for(var n=Math.min(e.length,t.length),s=0;s<n;s+=1)if(e[s]!==t[s])return s;return n}(i,n)>=t-1)break;t--}r++}return at}function dt(t){var e;if(void 0===R[t]&&"undefined"!=typeof module&&module&&module.exports&&null!=t.match("^[^/\\\\]*$"))try{e=at._abbr,require("./locale/"+t),ct(e)}catch(e){R[t]=null}return R[t]}function ct(e,t){return e&&((t=o(t)?mt(e):ft(e,t))?at=t:"undefined"!=typeof console&&console.warn&&console.warn("Locale "+e+" not found. Did you forget to load it?")),at._abbr}function ft(e,t){if(null===t)return delete R[e],null;var n,s=ot;if(t.abbr=e,null!=R[e])Q("defineLocaleOverride","use moment.updateLocale(localeName, config) to change an existing locale. moment.defineLocale(localeName, config) should only be used for creating a new locale See http://momentjs.com/guides/#/warnings/define-locale/ for more info."),s=R[e]._config;else if(null!=t.parentLocale)if(null!=R[t.parentLocale])s=R[t.parentLocale]._config;else{if(null==(n=dt(t.parentLocale)))return ut[t.parentLocale]||(ut[t.parentLocale]=[]),ut[t.parentLocale].push({name:e,config:t}),null;s=n._config}return R[e]=new K(X(s,t)),ut[e]&&ut[e].forEach(function(e){ft(e.name,e.config)}),ct(e),R[e]}function mt(e){var t;if(!(e=e&&e._locale&&e._locale._abbr?e._locale._abbr:e))return at;if(!a(e)){if(t=dt(e))return t;e=[e]}return ht(e)}function _t(e){var t=e._a;return t&&-2===m(e).overflow&&(t=t[O]<0||11<t[O]?O:t[b]<1||t[b]>We(t[Y],t[O])?b:t[x]<0||24<t[x]||24===t[x]&&(0!==t[T]||0!==t[N]||0!==t[Ne])?x:t[T]<0||59<t[T]?T:t[N]<0||59<t[N]?N:t[Ne]<0||999<t[Ne]?Ne:-1,m(e)._overflowDayOfYear&&(t<Y||b<t)&&(t=b),m(e)._overflowWeeks&&-1===t&&(t=Pe),m(e)._overflowWeekday&&-1===t&&(t=Re),m(e).overflow=t),e}var yt=/^\s*((?:[+-]\d{6}|\d{4})-(?:\d\d-\d\d|W\d\d-\d|W\d\d|\d\d\d|\d\d))(?:(T| )(\d\d(?::\d\d(?::\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,gt=/^\s*((?:[+-]\d{6}|\d{4})(?:\d\d\d\d|W\d\d\d|W\d\d|\d\d\d|\d\d|))(?:(T| )(\d\d(?:\d\d(?:\d\d(?:[.,]\d+)?)?)?)([+-]\d\d(?::?\d\d)?|\s*Z)?)?$/,wt=/Z|[+-]\d\d(?::?\d\d)?/,pt=[["YYYYYY-MM-DD",/[+-]\d{6}-\d\d-\d\d/],["YYYY-MM-DD",/\d{4}-\d\d-\d\d/],["GGGG-[W]WW-E",/\d{4}-W\d\d-\d/],["GGGG-[W]WW",/\d{4}-W\d\d/,!1],["YYYY-DDD",/\d{4}-\d{3}/],["YYYY-MM",/\d{4}-\d\d/,!1],["YYYYYYMMDD",/[+-]\d{10}/],["YYYYMMDD",/\d{8}/],["GGGG[W]WWE",/\d{4}W\d{3}/],["GGGG[W]WW",/\d{4}W\d{2}/,!1],["YYYYDDD",/\d{7}/],["YYYYMM",/\d{6}/,!1],["YYYY",/\d{4}/,!1]],kt=[["HH:mm:ss.SSSS",/\d\d:\d\d:\d\d\.\d+/],["HH:mm:ss,SSSS",/\d\d:\d\d:\d\d,\d+/],["HH:mm:ss",/\d\d:\d\d:\d\d/],["HH:mm",/\d\d:\d\d/],["HHmmss.SSSS",/\d\d\d\d\d\d\.\d+/],["HHmmss,SSSS",/\d\d\d\d\d\d,\d+/],["HHmmss",/\d\d\d\d\d\d/],["HHmm",/\d\d\d\d/],["HH",/\d\d/]],vt=/^\/?Date\((-?\d+)/i,Mt=/^(?:(Mon|Tue|Wed|Thu|Fri|Sat|Sun),?\s)?(\d{1,2})\s(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)\s(\d{2,4})\s(\d\d):(\d\d)(?::(\d\d))?\s(?:(UT|GMT|[ECMP][SD]T)|([Zz])|([+-]\d{4}))$/,Dt={UT:0,GMT:0,EDT:-240,EST:-300,CDT:-300,CST:-360,MDT:-360,MST:-420,PDT:-420,PST:-480};function St(e){var t,n,s,i,r,a,o=e._i,u=yt.exec(o)||gt.exec(o),o=pt.length,l=kt.length;if(u){for(m(e).iso=!0,t=0,n=o;t<n;t++)if(pt[t][1].exec(u[1])){i=pt[t][0],s=!1!==pt[t][2];break}if(null==i)e._isValid=!1;else{if(u[3]){for(t=0,n=l;t<n;t++)if(kt[t][1].exec(u[3])){r=(u[2]||" ")+kt[t][0];break}if(null==r)return void(e._isValid=!1)}if(s||null==r){if(u[4]){if(!wt.exec(u[4]))return void(e._isValid=!1);a="Z"}e._f=i+(r||"")+(a||""),Tt(e)}else e._isValid=!1}}else e._isValid=!1}function Yt(e,t,n,s,i,r){e=[function(e){e=parseInt(e,10);{if(e<=49)return 2e3+e;if(e<=999)return 1900+e}return e}(e),Ue.indexOf(t),parseInt(n,10),parseInt(s,10),parseInt(i,10)];return r&&e.push(parseInt(r,10)),e}function Ot(e){var t,n,s,i,r=Mt.exec(e._i.replace(/\([^()]*\)|[\n\t]/g," ").replace(/(\s\s+)/g," ").replace(/^\s\s*/,"").replace(/\s\s*$/,""));r?(t=Yt(r[4],r[3],r[2],r[5],r[6],r[7]),n=r[1],s=t,i=e,n&&Qe.indexOf(n)!==new Date(s[0],s[1],s[2]).getDay()?(m(i).weekdayMismatch=!0,i._isValid=!1):(e._a=t,e._tzm=(n=r[8],s=r[9],i=r[10],n?Dt[n]:s?0:60*(((n=parseInt(i,10))-(s=n%100))/100)+s),e._d=Ze.apply(null,e._a),e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),m(e).rfc2822=!0)):e._isValid=!1}function bt(e,t,n){return null!=e?e:null!=t?t:n}function xt(e){var t,n,s,i,r,a,o,u,l,h,d,c=[];if(!e._d){for(s=e,i=new Date(f.now()),n=s._useUTC?[i.getUTCFullYear(),i.getUTCMonth(),i.getUTCDate()]:[i.getFullYear(),i.getMonth(),i.getDate()],e._w&&null==e._a[b]&&null==e._a[O]&&(null!=(i=(s=e)._w).GG||null!=i.W||null!=i.E?(u=1,l=4,r=bt(i.GG,s._a[Y],qe(W(),1,4).year),a=bt(i.W,1),((o=bt(i.E,1))<1||7<o)&&(h=!0)):(u=s._locale._week.dow,l=s._locale._week.doy,d=qe(W(),u,l),r=bt(i.gg,s._a[Y],d.year),a=bt(i.w,d.week),null!=i.d?((o=i.d)<0||6<o)&&(h=!0):null!=i.e?(o=i.e+u,(i.e<0||6<i.e)&&(h=!0)):o=u),a<1||a>P(r,u,l)?m(s)._overflowWeeks=!0:null!=h?m(s)._overflowWeekday=!0:(d=$e(r,a,o,u,l),s._a[Y]=d.year,s._dayOfYear=d.dayOfYear)),null!=e._dayOfYear&&(i=bt(e._a[Y],n[Y]),(e._dayOfYear>Ae(i)||0===e._dayOfYear)&&(m(e)._overflowDayOfYear=!0),h=Ze(i,0,e._dayOfYear),e._a[O]=h.getUTCMonth(),e._a[b]=h.getUTCDate()),t=0;t<3&&null==e._a[t];++t)e._a[t]=c[t]=n[t];for(;t<7;t++)e._a[t]=c[t]=null==e._a[t]?2===t?1:0:e._a[t];24===e._a[x]&&0===e._a[T]&&0===e._a[N]&&0===e._a[Ne]&&(e._nextDay=!0,e._a[x]=0),e._d=(e._useUTC?Ze:je).apply(null,c),r=e._useUTC?e._d.getUTCDay():e._d.getDay(),null!=e._tzm&&e._d.setUTCMinutes(e._d.getUTCMinutes()-e._tzm),e._nextDay&&(e._a[x]=24),e._w&&void 0!==e._w.d&&e._w.d!==r&&(m(e).weekdayMismatch=!0)}}function Tt(e){if(e._f===f.ISO_8601)St(e);else if(e._f===f.RFC_2822)Ot(e);else{e._a=[],m(e).empty=!0;for(var t,n,s,i,r,a=""+e._i,o=a.length,u=0,l=ae(e._f,e._locale).match(te)||[],h=l.length,d=0;d<h;d++)n=l[d],(t=(a.match(Oe(n,e))||[])[0])&&(0<(s=a.substr(0,a.indexOf(t))).length&&m(e).unusedInput.push(s),a=a.slice(a.indexOf(t)+t.length),u+=t.length),ie[n]?(t?m(e).empty=!1:m(e).unusedTokens.push(n),s=n,r=e,null!=(i=t)&&c(xe,s)&&xe[s](i,r._a,r,s)):e._strict&&!t&&m(e).unusedTokens.push(n);m(e).charsLeftOver=o-u,0<a.length&&m(e).unusedInput.push(a),e._a[x]<=12&&!0===m(e).bigHour&&0<e._a[x]&&(m(e).bigHour=void 0),m(e).parsedDateParts=e._a.slice(0),m(e).meridiem=e._meridiem,e._a[x]=function(e,t,n){if(null==n)return t;return null!=e.meridiemHour?e.meridiemHour(t,n):null!=e.isPM?((e=e.isPM(n))&&t<12&&(t+=12),t=e||12!==t?t:0):t}(e._locale,e._a[x],e._meridiem),null!==(o=m(e).era)&&(e._a[Y]=e._locale.erasConvertYear(o,e._a[Y])),xt(e),_t(e)}}function Nt(e){var t,n,s,i=e._i,r=e._f;if(e._locale=e._locale||mt(e._l),null===i||void 0===r&&""===i)return I({nullInput:!0});if("string"==typeof i&&(e._i=i=e._locale.preparse(i)),h(i))return new q(_t(i));if(V(i))e._d=i;else if(a(r))!function(e){var t,n,s,i,r,a,o=!1,u=e._f.length;if(0===u)return m(e).invalidFormat=!0,e._d=new Date(NaN);for(i=0;i<u;i++)r=0,a=!1,t=$({},e),null!=e._useUTC&&(t._useUTC=e._useUTC),t._f=e._f[i],Tt(t),A(t)&&(a=!0),r=(r+=m(t).charsLeftOver)+10*m(t).unusedTokens.length,m(t).score=r,o?r<s&&(s=r,n=t):(null==s||r<s||a)&&(s=r,n=t,a&&(o=!0));E(e,n||t)}(e);else if(r)Tt(e);else if(o(r=(i=e)._i))i._d=new Date(f.now());else V(r)?i._d=new Date(r.valueOf()):"string"==typeof r?(n=i,null!==(t=vt.exec(n._i))?n._d=new Date(+t[1]):(St(n),!1===n._isValid&&(delete n._isValid,Ot(n),!1===n._isValid&&(delete n._isValid,n._strict?n._isValid=!1:f.createFromInputFallback(n))))):a(r)?(i._a=G(r.slice(0),function(e){return parseInt(e,10)}),xt(i)):F(r)?(t=i)._d||(s=void 0===(n=ue(t._i)).day?n.date:n.day,t._a=G([n.year,n.month,s,n.hour,n.minute,n.second,n.millisecond],function(e){return e&&parseInt(e,10)}),xt(t)):u(r)?i._d=new Date(r):f.createFromInputFallback(i);return A(e)||(e._d=null),e}function Pt(e,t,n,s,i){var r={};return!0!==t&&!1!==t||(s=t,t=void 0),!0!==n&&!1!==n||(s=n,n=void 0),(F(e)&&L(e)||a(e)&&0===e.length)&&(e=void 0),r._isAMomentObject=!0,r._useUTC=r._isUTC=i,r._l=n,r._i=e,r._f=t,r._strict=s,(i=new q(_t(Nt(i=r))))._nextDay&&(i.add(1,"d"),i._nextDay=void 0),i}function W(e,t,n,s){return Pt(e,t,n,s,!1)}f.createFromInputFallback=e("value provided is not in a recognized RFC2822 or ISO format. moment construction falls back to js Date(), which is not reliable across all browsers and versions. Non RFC2822/ISO date formats are discouraged. Please refer to http://momentjs.com/guides/#/warnings/js-date/ for more info.",function(e){e._d=new Date(e._i+(e._useUTC?" UTC":""))}),f.ISO_8601=function(){},f.RFC_2822=function(){};ge=e("moment().min is deprecated, use moment.max instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=W.apply(null,arguments);return this.isValid()&&e.isValid()?e<this?this:e:I()}),we=e("moment().max is deprecated, use moment.min instead. http://momentjs.com/guides/#/warnings/min-max/",function(){var e=W.apply(null,arguments);return this.isValid()&&e.isValid()?this<e?this:e:I()});function Rt(e,t){var n,s;if(!(t=1===t.length&&a(t[0])?t[0]:t).length)return W();for(n=t[0],s=1;s<t.length;++s)t[s].isValid()&&!t[s][e](n)||(n=t[s]);return n}var Wt=["year","quarter","month","week","day","hour","minute","second","millisecond"];function Ct(e){var e=ue(e),t=e.year||0,n=e.quarter||0,s=e.month||0,i=e.week||e.isoWeek||0,r=e.day||0,a=e.hour||0,o=e.minute||0,u=e.second||0,l=e.millisecond||0;this._isValid=function(e){var t,n,s=!1,i=Wt.length;for(t in e)if(c(e,t)&&(-1===S.call(Wt,t)||null!=e[t]&&isNaN(e[t])))return!1;for(n=0;n<i;++n)if(e[Wt[n]]){if(s)return!1;parseFloat(e[Wt[n]])!==g(e[Wt[n]])&&(s=!0)}return!0}(e),this._milliseconds=+l+1e3*u+6e4*o+1e3*a*60*60,this._days=+r+7*i,this._months=+s+3*n+12*t,this._data={},this._locale=mt(),this._bubble()}function Ut(e){return e instanceof Ct}function Ht(e){return e<0?-1*Math.round(-1*e):Math.round(e)}function Ft(e,n){s(e,0,0,function(){var e=this.utcOffset(),t="+";return e<0&&(e=-e,t="-"),t+r(~~(e/60),2)+n+r(~~e%60,2)})}Ft("Z",":"),Ft("ZZ",""),v("Z",Ye),v("ZZ",Ye),D(["Z","ZZ"],function(e,t,n){n._useUTC=!0,n._tzm=Vt(Ye,e)});var Lt=/([\+\-]|\d\d)/gi;function Vt(e,t){var t=(t||"").match(e);return null===t?null:0===(t=60*(e=((t[t.length-1]||[])+"").match(Lt)||["-",0,0])[1]+g(e[2]))?0:"+"===e[0]?t:-t}function Gt(e,t){var n;return t._isUTC?(t=t.clone(),n=(h(e)||V(e)?e:W(e)).valueOf()-t.valueOf(),t._d.setTime(t._d.valueOf()+n),f.updateOffset(t,!1),t):W(e).local()}function Et(e){return-Math.round(e._d.getTimezoneOffset())}function At(){return!!this.isValid()&&(this._isUTC&&0===this._offset)}f.updateOffset=function(){};var It=/^(-|\+)?(?:(\d*)[. ])?(\d+):(\d+)(?::(\d+)(\.\d*)?)?$/,jt=/^(-|\+)?P(?:([-+]?[0-9,.]*)Y)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)W)?(?:([-+]?[0-9,.]*)D)?(?:T(?:([-+]?[0-9,.]*)H)?(?:([-+]?[0-9,.]*)M)?(?:([-+]?[0-9,.]*)S)?)?$/;function C(e,t){var n,s=e,i=null;return Ut(e)?s={ms:e._milliseconds,d:e._days,M:e._months}:u(e)||!isNaN(+e)?(s={},t?s[t]=+e:s.milliseconds=+e):(i=It.exec(e))?(n="-"===i[1]?-1:1,s={y:0,d:g(i[b])*n,h:g(i[x])*n,m:g(i[T])*n,s:g(i[N])*n,ms:g(Ht(1e3*i[Ne]))*n}):(i=jt.exec(e))?(n="-"===i[1]?-1:1,s={y:Zt(i[2],n),M:Zt(i[3],n),w:Zt(i[4],n),d:Zt(i[5],n),h:Zt(i[6],n),m:Zt(i[7],n),s:Zt(i[8],n)}):null==s?s={}:"object"==typeof s&&("from"in s||"to"in s)&&(t=function(e,t){var n;if(!e.isValid()||!t.isValid())return{milliseconds:0,months:0};t=Gt(t,e),e.isBefore(t)?n=zt(e,t):((n=zt(t,e)).milliseconds=-n.milliseconds,n.months=-n.months);return n}(W(s.from),W(s.to)),(s={}).ms=t.milliseconds,s.M=t.months),i=new Ct(s),Ut(e)&&c(e,"_locale")&&(i._locale=e._locale),Ut(e)&&c(e,"_isValid")&&(i._isValid=e._isValid),i}function Zt(e,t){e=e&&parseFloat(e.replace(",","."));return(isNaN(e)?0:e)*t}function zt(e,t){var n={};return n.months=t.month()-e.month()+12*(t.year()-e.year()),e.clone().add(n.months,"M").isAfter(t)&&--n.months,n.milliseconds=+t-+e.clone().add(n.months,"M"),n}function $t(s,i){return function(e,t){var n;return null===t||isNaN(+t)||(Q(i,"moment()."+i+"(period, number) is deprecated. Please use moment()."+i+"(number, period). See http://momentjs.com/guides/#/warnings/add-inverted-param/ for more info."),n=e,e=t,t=n),qt(this,C(e,t),s),this}}function qt(e,t,n,s){var i=t._milliseconds,r=Ht(t._days),t=Ht(t._months);e.isValid()&&(s=null==s||s,t&&Ve(e,ce(e,"Month")+t*n),r&&fe(e,"Date",ce(e,"Date")+r*n),i&&e._d.setTime(e._d.valueOf()+i*n),s&&f.updateOffset(e,r||t))}C.fn=Ct.prototype,C.invalid=function(){return C(NaN)};Ce=$t(1,"add"),Je=$t(-1,"subtract");function Bt(e){return"string"==typeof e||e instanceof String}function Jt(e){return h(e)||V(e)||Bt(e)||u(e)||function(t){var e=a(t),n=!1;e&&(n=0===t.filter(function(e){return!u(e)&&Bt(t)}).length);return e&&n}(e)||function(e){var t,n,s=F(e)&&!L(e),i=!1,r=["years","year","y","months","month","M","days","day","d","dates","date","D","hours","hour","h","minutes","minute","m","seconds","second","s","milliseconds","millisecond","ms"],a=r.length;for(t=0;t<a;t+=1)n=r[t],i=i||c(e,n);return s&&i}(e)||null==e}function Qt(e,t){if(e.date()<t.date())return-Qt(t,e);var n=12*(t.year()-e.year())+(t.month()-e.month()),s=e.clone().add(n,"months"),t=t-s<0?(t-s)/(s-e.clone().add(n-1,"months")):(t-s)/(e.clone().add(1+n,"months")-s);return-(n+t)||0}function Xt(e){return void 0===e?this._locale._abbr:(null!=(e=mt(e))&&(this._locale=e),this)}f.defaultFormat="YYYY-MM-DDTHH:mm:ssZ",f.defaultFormatUtc="YYYY-MM-DDTHH:mm:ss[Z]";Xe=e("moment().lang() is deprecated. Instead, use moment().localeData() to get the language configuration. Use moment().locale() to change languages.",function(e){return void 0===e?this.localeData():this.locale(e)});function Kt(){return this._locale}var en=126227808e5;function tn(e,t){return(e%t+t)%t}function nn(e,t,n){return e<100&&0<=e?new Date(e+400,t,n)-en:new Date(e,t,n).valueOf()}function sn(e,t,n){return e<100&&0<=e?Date.UTC(e+400,t,n)-en:Date.UTC(e,t,n)}function rn(e,t){return t.erasAbbrRegex(e)}function an(){for(var e=[],t=[],n=[],s=[],i=this.eras(),r=0,a=i.length;r<a;++r)t.push(M(i[r].name)),e.push(M(i[r].abbr)),n.push(M(i[r].narrow)),s.push(M(i[r].name)),s.push(M(i[r].abbr)),s.push(M(i[r].narrow));this._erasRegex=new RegExp("^("+s.join("|")+")","i"),this._erasNameRegex=new RegExp("^("+t.join("|")+")","i"),this._erasAbbrRegex=new RegExp("^("+e.join("|")+")","i"),this._erasNarrowRegex=new RegExp("^("+n.join("|")+")","i")}function on(e,t){s(0,[e,e.length],0,t)}function un(e,t,n,s,i){var r;return null==e?qe(this,s,i).year:(r=P(e,s,i),function(e,t,n,s,i){e=$e(e,t,n,s,i),t=Ze(e.year,0,e.dayOfYear);return this.year(t.getUTCFullYear()),this.month(t.getUTCMonth()),this.date(t.getUTCDate()),this}.call(this,e,t=r<t?r:t,n,s,i))}s("N",0,0,"eraAbbr"),s("NN",0,0,"eraAbbr"),s("NNN",0,0,"eraAbbr"),s("NNNN",0,0,"eraName"),s("NNNNN",0,0,"eraNarrow"),s("y",["y",1],"yo","eraYear"),s("y",["yy",2],0,"eraYear"),s("y",["yyy",3],0,"eraYear"),s("y",["yyyy",4],0,"eraYear"),v("N",rn),v("NN",rn),v("NNN",rn),v("NNNN",function(e,t){return t.erasNameRegex(e)}),v("NNNNN",function(e,t){return t.erasNarrowRegex(e)}),D(["N","NN","NNN","NNNN","NNNNN"],function(e,t,n,s){s=n._locale.erasParse(e,s,n._strict);s?m(n).era=s:m(n).invalidEra=e}),v("y",Me),v("yy",Me),v("yyy",Me),v("yyyy",Me),v("yo",function(e,t){return t._eraYearOrdinalRegex||Me}),D(["y","yy","yyy","yyyy"],Y),D(["yo"],function(e,t,n,s){var i;n._locale._eraYearOrdinalRegex&&(i=e.match(n._locale._eraYearOrdinalRegex)),n._locale.eraYearOrdinalParse?t[Y]=n._locale.eraYearOrdinalParse(e,i):t[Y]=parseInt(e,10)}),s(0,["gg",2],0,function(){return this.weekYear()%100}),s(0,["GG",2],0,function(){return this.isoWeekYear()%100}),on("gggg","weekYear"),on("ggggg","weekYear"),on("GGGG","isoWeekYear"),on("GGGGG","isoWeekYear"),t("weekYear","gg"),t("isoWeekYear","GG"),n("weekYear",1),n("isoWeekYear",1),v("G",De),v("g",De),v("GG",p,w),v("gg",p,w),v("GGGG",ke,_e),v("gggg",ke,_e),v("GGGGG",ve,ye),v("ggggg",ve,ye),Te(["gggg","ggggg","GGGG","GGGGG"],function(e,t,n,s){t[s.substr(0,2)]=g(e)}),Te(["gg","GG"],function(e,t,n,s){t[s]=f.parseTwoDigitYear(e)}),s("Q",0,"Qo","quarter"),t("quarter","Q"),n("quarter",7),v("Q",i),D("Q",function(e,t){t[O]=3*(g(e)-1)}),s("D",["DD",2],"Do","date"),t("date","D"),n("date",9),v("D",p),v("DD",p,w),v("Do",function(e,t){return e?t._dayOfMonthOrdinalParse||t._ordinalParse:t._dayOfMonthOrdinalParseLenient}),D(["D","DD"],b),D("Do",function(e,t){t[b]=g(e.match(p)[0])});ke=de("Date",!0);s("DDD",["DDDD",3],"DDDo","dayOfYear"),t("dayOfYear","DDD"),n("dayOfYear",4),v("DDD",pe),v("DDDD",me),D(["DDD","DDDD"],function(e,t,n){n._dayOfYear=g(e)}),s("m",["mm",2],0,"minute"),t("minute","m"),n("minute",14),v("m",p),v("mm",p,w),D(["m","mm"],T);var ln,_e=de("Minutes",!1),ve=(s("s",["ss",2],0,"second"),t("second","s"),n("second",15),v("s",p),v("ss",p,w),D(["s","ss"],N),de("Seconds",!1));for(s("S",0,0,function(){return~~(this.millisecond()/100)}),s(0,["SS",2],0,function(){return~~(this.millisecond()/10)}),s(0,["SSS",3],0,"millisecond"),s(0,["SSSS",4],0,function(){return 10*this.millisecond()}),s(0,["SSSSS",5],0,function(){return 100*this.millisecond()}),s(0,["SSSSSS",6],0,function(){return 1e3*this.millisecond()}),s(0,["SSSSSSS",7],0,function(){return 1e4*this.millisecond()}),s(0,["SSSSSSSS",8],0,function(){return 1e5*this.millisecond()}),s(0,["SSSSSSSSS",9],0,function(){return 1e6*this.millisecond()}),t("millisecond","ms"),n("millisecond",16),v("S",pe,i),v("SS",pe,w),v("SSS",pe,me),ln="SSSS";ln.length<=9;ln+="S")v(ln,Me);function hn(e,t){t[Ne]=g(1e3*("0."+e))}for(ln="S";ln.length<=9;ln+="S")D(ln,hn);ye=de("Milliseconds",!1),s("z",0,0,"zoneAbbr"),s("zz",0,0,"zoneName");i=q.prototype;function dn(e){return e}i.add=Ce,i.calendar=function(e,t){1===arguments.length&&(arguments[0]?Jt(arguments[0])?(e=arguments[0],t=void 0):function(e){for(var t=F(e)&&!L(e),n=!1,s=["sameDay","nextDay","lastDay","nextWeek","lastWeek","sameElse"],i=0;i<s.length;i+=1)n=n||c(e,s[i]);return t&&n}(arguments[0])&&(t=arguments[0],e=void 0):t=e=void 0);var e=e||W(),n=Gt(e,this).startOf("day"),n=f.calendarFormat(this,n)||"sameElse",t=t&&(d(t[n])?t[n].call(this,e):t[n]);return this.format(t||this.localeData().calendar(n,this,W(e)))},i.clone=function(){return new q(this)},i.diff=function(e,t,n){var s,i,r;if(!this.isValid())return NaN;if(!(s=Gt(e,this)).isValid())return NaN;switch(i=6e4*(s.utcOffset()-this.utcOffset()),t=_(t)){case"year":r=Qt(this,s)/12;break;case"month":r=Qt(this,s);break;case"quarter":r=Qt(this,s)/3;break;case"second":r=(this-s)/1e3;break;case"minute":r=(this-s)/6e4;break;case"hour":r=(this-s)/36e5;break;case"day":r=(this-s-i)/864e5;break;case"week":r=(this-s-i)/6048e5;break;default:r=this-s}return n?r:y(r)},i.endOf=function(e){var t,n;if(void 0===(e=_(e))||"millisecond"===e||!this.isValid())return this;switch(n=this._isUTC?sn:nn,e){case"year":t=n(this.year()+1,0,1)-1;break;case"quarter":t=n(this.year(),this.month()-this.month()%3+3,1)-1;break;case"month":t=n(this.year(),this.month()+1,1)-1;break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday()+7)-1;break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1)+7)-1;break;case"day":case"date":t=n(this.year(),this.month(),this.date()+1)-1;break;case"hour":t=this._d.valueOf(),t+=36e5-tn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5)-1;break;case"minute":t=this._d.valueOf(),t+=6e4-tn(t,6e4)-1;break;case"second":t=this._d.valueOf(),t+=1e3-tn(t,1e3)-1;break}return this._d.setTime(t),f.updateOffset(this,!0),this},i.format=function(e){return e=e||(this.isUtc()?f.defaultFormatUtc:f.defaultFormat),e=re(this,e),this.localeData().postformat(e)},i.from=function(e,t){return this.isValid()&&(h(e)&&e.isValid()||W(e).isValid())?C({to:this,from:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},i.fromNow=function(e){return this.from(W(),e)},i.to=function(e,t){return this.isValid()&&(h(e)&&e.isValid()||W(e).isValid())?C({from:this,to:e}).locale(this.locale()).humanize(!t):this.localeData().invalidDate()},i.toNow=function(e){return this.to(W(),e)},i.get=function(e){return d(this[e=_(e)])?this[e]():this},i.invalidAt=function(){return m(this).overflow},i.isAfter=function(e,t){return e=h(e)?e:W(e),!(!this.isValid()||!e.isValid())&&("millisecond"===(t=_(t)||"millisecond")?this.valueOf()>e.valueOf():e.valueOf()<this.clone().startOf(t).valueOf())},i.isBefore=function(e,t){return e=h(e)?e:W(e),!(!this.isValid()||!e.isValid())&&("millisecond"===(t=_(t)||"millisecond")?this.valueOf()<e.valueOf():this.clone().endOf(t).valueOf()<e.valueOf())},i.isBetween=function(e,t,n,s){return e=h(e)?e:W(e),t=h(t)?t:W(t),!!(this.isValid()&&e.isValid()&&t.isValid())&&(("("===(s=s||"()")[0]?this.isAfter(e,n):!this.isBefore(e,n))&&(")"===s[1]?this.isBefore(t,n):!this.isAfter(t,n)))},i.isSame=function(e,t){var e=h(e)?e:W(e);return!(!this.isValid()||!e.isValid())&&("millisecond"===(t=_(t)||"millisecond")?this.valueOf()===e.valueOf():(e=e.valueOf(),this.clone().startOf(t).valueOf()<=e&&e<=this.clone().endOf(t).valueOf()))},i.isSameOrAfter=function(e,t){return this.isSame(e,t)||this.isAfter(e,t)},i.isSameOrBefore=function(e,t){return this.isSame(e,t)||this.isBefore(e,t)},i.isValid=function(){return A(this)},i.lang=Xe,i.locale=Xt,i.localeData=Kt,i.max=we,i.min=ge,i.parsingFlags=function(){return E({},m(this))},i.set=function(e,t){if("object"==typeof e)for(var n=function(e){var t,n=[];for(t in e)c(e,t)&&n.push({unit:t,priority:le[t]});return n.sort(function(e,t){return e.priority-t.priority}),n}(e=ue(e)),s=n.length,i=0;i<s;i++)this[n[i].unit](e[n[i].unit]);else if(d(this[e=_(e)]))return this[e](t);return this},i.startOf=function(e){var t,n;if(void 0===(e=_(e))||"millisecond"===e||!this.isValid())return this;switch(n=this._isUTC?sn:nn,e){case"year":t=n(this.year(),0,1);break;case"quarter":t=n(this.year(),this.month()-this.month()%3,1);break;case"month":t=n(this.year(),this.month(),1);break;case"week":t=n(this.year(),this.month(),this.date()-this.weekday());break;case"isoWeek":t=n(this.year(),this.month(),this.date()-(this.isoWeekday()-1));break;case"day":case"date":t=n(this.year(),this.month(),this.date());break;case"hour":t=this._d.valueOf(),t-=tn(t+(this._isUTC?0:6e4*this.utcOffset()),36e5);break;case"minute":t=this._d.valueOf(),t-=tn(t,6e4);break;case"second":t=this._d.valueOf(),t-=tn(t,1e3);break}return this._d.setTime(t),f.updateOffset(this,!0),this},i.subtract=Je,i.toArray=function(){var e=this;return[e.year(),e.month(),e.date(),e.hour(),e.minute(),e.second(),e.millisecond()]},i.toObject=function(){var e=this;return{years:e.year(),months:e.month(),date:e.date(),hours:e.hours(),minutes:e.minutes(),seconds:e.seconds(),milliseconds:e.milliseconds()}},i.toDate=function(){return new Date(this.valueOf())},i.toISOString=function(e){if(!this.isValid())return null;var t=(e=!0!==e)?this.clone().utc():this;return t.year()<0||9999<t.year()?re(t,e?"YYYYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYYYY-MM-DD[T]HH:mm:ss.SSSZ"):d(Date.prototype.toISOString)?e?this.toDate().toISOString():new Date(this.valueOf()+60*this.utcOffset()*1e3).toISOString().replace("Z",re(t,"Z")):re(t,e?"YYYY-MM-DD[T]HH:mm:ss.SSS[Z]":"YYYY-MM-DD[T]HH:mm:ss.SSSZ")},i.inspect=function(){if(!this.isValid())return"moment.invalid(/* "+this._i+" */)";var e,t="moment",n="";return this.isLocal()||(t=0===this.utcOffset()?"moment.utc":"moment.parseZone",n="Z"),t="["+t+'("]',e=0<=this.year()&&this.year()<=9999?"YYYY":"YYYYYY",this.format(t+e+"-MM-DD[T]HH:mm:ss.SSS"+(n+'[")]'))},"undefined"!=typeof Symbol&&null!=Symbol.for&&(i[Symbol.for("nodejs.util.inspect.custom")]=function(){return"Moment<"+this.format()+">"}),i.toJSON=function(){return this.isValid()?this.toISOString():null},i.toString=function(){return this.clone().locale("en").format("ddd MMM DD YYYY HH:mm:ss [GMT]ZZ")},i.unix=function(){return Math.floor(this.valueOf()/1e3)},i.valueOf=function(){return this._d.valueOf()-6e4*(this._offset||0)},i.creationData=function(){return{input:this._i,format:this._f,locale:this._locale,isUTC:this._isUTC,strict:this._strict}},i.eraName=function(){for(var e,t=this.localeData().eras(),n=0,s=t.length;n<s;++n){if(e=this.clone().startOf("day").valueOf(),t[n].since<=e&&e<=t[n].until)return t[n].name;if(t[n].until<=e&&e<=t[n].since)return t[n].name}return""},i.eraNarrow=function(){for(var e,t=this.localeData().eras(),n=0,s=t.length;n<s;++n){if(e=this.clone().startOf("day").valueOf(),t[n].since<=e&&e<=t[n].until)return t[n].narrow;if(t[n].until<=e&&e<=t[n].since)return t[n].narrow}return""},i.eraAbbr=function(){for(var e,t=this.localeData().eras(),n=0,s=t.length;n<s;++n){if(e=this.clone().startOf("day").valueOf(),t[n].since<=e&&e<=t[n].until)return t[n].abbr;if(t[n].until<=e&&e<=t[n].since)return t[n].abbr}return""},i.eraYear=function(){for(var e,t,n=this.localeData().eras(),s=0,i=n.length;s<i;++s)if(e=n[s].since<=n[s].until?1:-1,t=this.clone().startOf("day").valueOf(),n[s].since<=t&&t<=n[s].until||n[s].until<=t&&t<=n[s].since)return(this.year()-f(n[s].since).year())*e+n[s].offset;return this.year()},i.year=Ie,i.isLeapYear=function(){return he(this.year())},i.weekYear=function(e){return un.call(this,e,this.week(),this.weekday(),this.localeData()._week.dow,this.localeData()._week.doy)},i.isoWeekYear=function(e){return un.call(this,e,this.isoWeek(),this.isoWeekday(),1,4)},i.quarter=i.quarters=function(e){return null==e?Math.ceil((this.month()+1)/3):this.month(3*(e-1)+this.month()%3)},i.month=Ge,i.daysInMonth=function(){return We(this.year(),this.month())},i.week=i.weeks=function(e){var t=this.localeData().week(this);return null==e?t:this.add(7*(e-t),"d")},i.isoWeek=i.isoWeeks=function(e){var t=qe(this,1,4).week;return null==e?t:this.add(7*(e-t),"d")},i.weeksInYear=function(){var e=this.localeData()._week;return P(this.year(),e.dow,e.doy)},i.weeksInWeekYear=function(){var e=this.localeData()._week;return P(this.weekYear(),e.dow,e.doy)},i.isoWeeksInYear=function(){return P(this.year(),1,4)},i.isoWeeksInISOWeekYear=function(){return P(this.isoWeekYear(),1,4)},i.date=ke,i.day=i.days=function(e){if(!this.isValid())return null!=e?this:NaN;var t,n,s=this._isUTC?this._d.getUTCDay():this._d.getDay();return null!=e?(t=e,n=this.localeData(),e="string"!=typeof t?t:isNaN(t)?"number"==typeof(t=n.weekdaysParse(t))?t:null:parseInt(t,10),this.add(e-s,"d")):s},i.weekday=function(e){if(!this.isValid())return null!=e?this:NaN;var t=(this.day()+7-this.localeData()._week.dow)%7;return null==e?t:this.add(e-t,"d")},i.isoWeekday=function(e){return this.isValid()?null!=e?(t=e,n=this.localeData(),n="string"==typeof t?n.weekdaysParse(t)%7||7:isNaN(t)?null:t,this.day(this.day()%7?n:n-7)):this.day()||7:null!=e?this:NaN;var t,n},i.dayOfYear=function(e){var t=Math.round((this.clone().startOf("day")-this.clone().startOf("year"))/864e5)+1;return null==e?t:this.add(e-t,"d")},i.hour=i.hours=k,i.minute=i.minutes=_e,i.second=i.seconds=ve,i.millisecond=i.milliseconds=ye,i.utcOffset=function(e,t,n){var s,i=this._offset||0;if(!this.isValid())return null!=e?this:NaN;if(null==e)return this._isUTC?i:Et(this);if("string"==typeof e){if(null===(e=Vt(Ye,e)))return this}else Math.abs(e)<16&&!n&&(e*=60);return!this._isUTC&&t&&(s=Et(this)),this._offset=e,this._isUTC=!0,null!=s&&this.add(s,"m"),i!==e&&(!t||this._changeInProgress?qt(this,C(e-i,"m"),1,!1):this._changeInProgress||(this._changeInProgress=!0,f.updateOffset(this,!0),this._changeInProgress=null)),this},i.utc=function(e){return this.utcOffset(0,e)},i.local=function(e){return this._isUTC&&(this.utcOffset(0,e),this._isUTC=!1,e&&this.subtract(Et(this),"m")),this},i.parseZone=function(){var e;return null!=this._tzm?this.utcOffset(this._tzm,!1,!0):"string"==typeof this._i&&(null!=(e=Vt(Se,this._i))?this.utcOffset(e):this.utcOffset(0,!0)),this},i.hasAlignedHourOffset=function(e){return!!this.isValid()&&(e=e?W(e).utcOffset():0,(this.utcOffset()-e)%60==0)},i.isDST=function(){return this.utcOffset()>this.clone().month(0).utcOffset()||this.utcOffset()>this.clone().month(5).utcOffset()},i.isLocal=function(){return!!this.isValid()&&!this._isUTC},i.isUtcOffset=function(){return!!this.isValid()&&this._isUTC},i.isUtc=At,i.isUTC=At,i.zoneAbbr=function(){return this._isUTC?"UTC":""},i.zoneName=function(){return this._isUTC?"Coordinated Universal Time":""},i.dates=e("dates accessor is deprecated. Use date instead.",ke),i.months=e("months accessor is deprecated. Use month instead",Ge),i.years=e("years accessor is deprecated. Use year instead",Ie),i.zone=e("moment().zone is deprecated, use moment().utcOffset instead. http://momentjs.com/guides/#/warnings/zone/",function(e,t){return null!=e?(this.utcOffset(e="string"!=typeof e?-e:e,t),this):-this.utcOffset()}),i.isDSTShifted=e("isDSTShifted is deprecated. See http://momentjs.com/guides/#/warnings/dst-shifted/ for more information",function(){if(!o(this._isDSTShifted))return this._isDSTShifted;var e,t={};return $(t,this),(t=Nt(t))._a?(e=(t._isUTC?l:W)(t._a),this._isDSTShifted=this.isValid()&&0<function(e,t,n){for(var s=Math.min(e.length,t.length),i=Math.abs(e.length-t.length),r=0,a=0;a<s;a++)(n&&e[a]!==t[a]||!n&&g(e[a])!==g(t[a]))&&r++;return r+i}(t._a,e.toArray())):this._isDSTShifted=!1,this._isDSTShifted});w=K.prototype;function cn(e,t,n,s){var i=mt(),s=l().set(s,t);return i[n](s,e)}function fn(e,t,n){if(u(e)&&(t=e,e=void 0),e=e||"",null!=t)return cn(e,t,n,"month");for(var s=[],i=0;i<12;i++)s[i]=cn(e,i,n,"month");return s}function mn(e,t,n,s){t=("boolean"==typeof e?u(t)&&(n=t,t=void 0):(t=e,e=!1,u(n=t)&&(n=t,t=void 0)),t||"");var i,r=mt(),a=e?r._week.dow:0,o=[];if(null!=n)return cn(t,(n+a)%7,s,"day");for(i=0;i<7;i++)o[i]=cn(t,(i+a)%7,s,"day");return o}w.calendar=function(e,t,n){return d(e=this._calendar[e]||this._calendar.sameElse)?e.call(t,n):e},w.longDateFormat=function(e){var t=this._longDateFormat[e],n=this._longDateFormat[e.toUpperCase()];return t||!n?t:(this._longDateFormat[e]=n.match(te).map(function(e){return"MMMM"===e||"MM"===e||"DD"===e||"dddd"===e?e.slice(1):e}).join(""),this._longDateFormat[e])},w.invalidDate=function(){return this._invalidDate},w.ordinal=function(e){return this._ordinal.replace("%d",e)},w.preparse=dn,w.postformat=dn,w.relativeTime=function(e,t,n,s){var i=this._relativeTime[n];return d(i)?i(e,t,n,s):i.replace(/%d/i,e)},w.pastFuture=function(e,t){return d(e=this._relativeTime[0<e?"future":"past"])?e(t):e.replace(/%s/i,t)},w.set=function(e){var t,n;for(n in e)c(e,n)&&(d(t=e[n])?this[n]=t:this["_"+n]=t);this._config=e,this._dayOfMonthOrdinalParseLenient=new RegExp((this._dayOfMonthOrdinalParse.source||this._ordinalParse.source)+"|"+/\d{1,2}/.source)},w.eras=function(e,t){for(var n,s=this._eras||mt("en")._eras,i=0,r=s.length;i<r;++i){switch(typeof s[i].since){case"string":n=f(s[i].since).startOf("day"),s[i].since=n.valueOf();break}switch(typeof s[i].until){case"undefined":s[i].until=1/0;break;case"string":n=f(s[i].until).startOf("day").valueOf(),s[i].until=n.valueOf();break}}return s},w.erasParse=function(e,t,n){var s,i,r,a,o,u=this.eras();for(e=e.toUpperCase(),s=0,i=u.length;s<i;++s)if(r=u[s].name.toUpperCase(),a=u[s].abbr.toUpperCase(),o=u[s].narrow.toUpperCase(),n)switch(t){case"N":case"NN":case"NNN":if(a===e)return u[s];break;case"NNNN":if(r===e)return u[s];break;case"NNNNN":if(o===e)return u[s];break}else if(0<=[r,a,o].indexOf(e))return u[s]},w.erasConvertYear=function(e,t){var n=e.since<=e.until?1:-1;return void 0===t?f(e.since).year():f(e.since).year()+(t-e.offset)*n},w.erasAbbrRegex=function(e){return c(this,"_erasAbbrRegex")||an.call(this),e?this._erasAbbrRegex:this._erasRegex},w.erasNameRegex=function(e){return c(this,"_erasNameRegex")||an.call(this),e?this._erasNameRegex:this._erasRegex},w.erasNarrowRegex=function(e){return c(this,"_erasNarrowRegex")||an.call(this),e?this._erasNarrowRegex:this._erasRegex},w.months=function(e,t){return e?(a(this._months)?this._months:this._months[(this._months.isFormat||He).test(t)?"format":"standalone"])[e.month()]:a(this._months)?this._months:this._months.standalone},w.monthsShort=function(e,t){return e?(a(this._monthsShort)?this._monthsShort:this._monthsShort[He.test(t)?"format":"standalone"])[e.month()]:a(this._monthsShort)?this._monthsShort:this._monthsShort.standalone},w.monthsParse=function(e,t,n){var s,i;if(this._monthsParseExact)return function(e,t,n){var s,i,r,e=e.toLocaleLowerCase();if(!this._monthsParse)for(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[],s=0;s<12;++s)r=l([2e3,s]),this._shortMonthsParse[s]=this.monthsShort(r,"").toLocaleLowerCase(),this._longMonthsParse[s]=this.months(r,"").toLocaleLowerCase();return n?"MMM"===t?-1!==(i=S.call(this._shortMonthsParse,e))?i:null:-1!==(i=S.call(this._longMonthsParse,e))?i:null:"MMM"===t?-1!==(i=S.call(this._shortMonthsParse,e))||-1!==(i=S.call(this._longMonthsParse,e))?i:null:-1!==(i=S.call(this._longMonthsParse,e))||-1!==(i=S.call(this._shortMonthsParse,e))?i:null}.call(this,e,t,n);for(this._monthsParse||(this._monthsParse=[],this._longMonthsParse=[],this._shortMonthsParse=[]),s=0;s<12;s++){if(i=l([2e3,s]),n&&!this._longMonthsParse[s]&&(this._longMonthsParse[s]=new RegExp("^"+this.months(i,"").replace(".","")+"$","i"),this._shortMonthsParse[s]=new RegExp("^"+this.monthsShort(i,"").replace(".","")+"$","i")),n||this._monthsParse[s]||(i="^"+this.months(i,"")+"|^"+this.monthsShort(i,""),this._monthsParse[s]=new RegExp(i.replace(".",""),"i")),n&&"MMMM"===t&&this._longMonthsParse[s].test(e))return s;if(n&&"MMM"===t&&this._shortMonthsParse[s].test(e))return s;if(!n&&this._monthsParse[s].test(e))return s}},w.monthsRegex=function(e){return this._monthsParseExact?(c(this,"_monthsRegex")||Ee.call(this),e?this._monthsStrictRegex:this._monthsRegex):(c(this,"_monthsRegex")||(this._monthsRegex=Le),this._monthsStrictRegex&&e?this._monthsStrictRegex:this._monthsRegex)},w.monthsShortRegex=function(e){return this._monthsParseExact?(c(this,"_monthsRegex")||Ee.call(this),e?this._monthsShortStrictRegex:this._monthsShortRegex):(c(this,"_monthsShortRegex")||(this._monthsShortRegex=Fe),this._monthsShortStrictRegex&&e?this._monthsShortStrictRegex:this._monthsShortRegex)},w.week=function(e){return qe(e,this._week.dow,this._week.doy).week},w.firstDayOfYear=function(){return this._week.doy},w.firstDayOfWeek=function(){return this._week.dow},w.weekdays=function(e,t){return t=a(this._weekdays)?this._weekdays:this._weekdays[e&&!0!==e&&this._weekdays.isFormat.test(t)?"format":"standalone"],!0===e?Be(t,this._week.dow):e?t[e.day()]:t},w.weekdaysMin=function(e){return!0===e?Be(this._weekdaysMin,this._week.dow):e?this._weekdaysMin[e.day()]:this._weekdaysMin},w.weekdaysShort=function(e){return!0===e?Be(this._weekdaysShort,this._week.dow):e?this._weekdaysShort[e.day()]:this._weekdaysShort},w.weekdaysParse=function(e,t,n){var s,i;if(this._weekdaysParseExact)return function(e,t,n){var s,i,r,e=e.toLocaleLowerCase();if(!this._weekdaysParse)for(this._weekdaysParse=[],this._shortWeekdaysParse=[],this._minWeekdaysParse=[],s=0;s<7;++s)r=l([2e3,1]).day(s),this._minWeekdaysParse[s]=this.weekdaysMin(r,"").toLocaleLowerCase(),this._shortWeekdaysParse[s]=this.weekdaysShort(r,"").toLocaleLowerCase(),this._weekdaysParse[s]=this.weekdays(r,"").toLocaleLowerCase();return n?"dddd"===t?-1!==(i=S.call(this._weekdaysParse,e))?i:null:"ddd"===t?-1!==(i=S.call(this._shortWeekdaysParse,e))?i:null:-1!==(i=S.call(this._minWeekdaysParse,e))?i:null:"dddd"===t?-1!==(i=S.call(this._weekdaysParse,e))||-1!==(i=S.call(this._shortWeekdaysParse,e))||-1!==(i=S.call(this._minWeekdaysParse,e))?i:null:"ddd"===t?-1!==(i=S.call(this._shortWeekdaysParse,e))||-1!==(i=S.call(this._weekdaysParse,e))||-1!==(i=S.call(this._minWeekdaysParse,e))?i:null:-1!==(i=S.call(this._minWeekdaysParse,e))||-1!==(i=S.call(this._weekdaysParse,e))||-1!==(i=S.call(this._shortWeekdaysParse,e))?i:null}.call(this,e,t,n);for(this._weekdaysParse||(this._weekdaysParse=[],this._minWeekdaysParse=[],this._shortWeekdaysParse=[],this._fullWeekdaysParse=[]),s=0;s<7;s++){if(i=l([2e3,1]).day(s),n&&!this._fullWeekdaysParse[s]&&(this._fullWeekdaysParse[s]=new RegExp("^"+this.weekdays(i,"").replace(".","\\.?")+"$","i"),this._shortWeekdaysParse[s]=new RegExp("^"+this.weekdaysShort(i,"").replace(".","\\.?")+"$","i"),this._minWeekdaysParse[s]=new RegExp("^"+this.weekdaysMin(i,"").replace(".","\\.?")+"$","i")),this._weekdaysParse[s]||(i="^"+this.weekdays(i,"")+"|^"+this.weekdaysShort(i,"")+"|^"+this.weekdaysMin(i,""),this._weekdaysParse[s]=new RegExp(i.replace(".",""),"i")),n&&"dddd"===t&&this._fullWeekdaysParse[s].test(e))return s;if(n&&"ddd"===t&&this._shortWeekdaysParse[s].test(e))return s;if(n&&"dd"===t&&this._minWeekdaysParse[s].test(e))return s;if(!n&&this._weekdaysParse[s].test(e))return s}},w.weekdaysRegex=function(e){return this._weekdaysParseExact?(c(this,"_weekdaysRegex")||nt.call(this),e?this._weekdaysStrictRegex:this._weekdaysRegex):(c(this,"_weekdaysRegex")||(this._weekdaysRegex=Ke),this._weekdaysStrictRegex&&e?this._weekdaysStrictRegex:this._weekdaysRegex)},w.weekdaysShortRegex=function(e){return this._weekdaysParseExact?(c(this,"_weekdaysRegex")||nt.call(this),e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex):(c(this,"_weekdaysShortRegex")||(this._weekdaysShortRegex=et),this._weekdaysShortStrictRegex&&e?this._weekdaysShortStrictRegex:this._weekdaysShortRegex)},w.weekdaysMinRegex=function(e){return this._weekdaysParseExact?(c(this,"_weekdaysRegex")||nt.call(this),e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex):(c(this,"_weekdaysMinRegex")||(this._weekdaysMinRegex=tt),this._weekdaysMinStrictRegex&&e?this._weekdaysMinStrictRegex:this._weekdaysMinRegex)},w.isPM=function(e){return"p"===(e+"").toLowerCase().charAt(0)},w.meridiem=function(e,t,n){return 11<e?n?"pm":"PM":n?"am":"AM"},ct("en",{eras:[{since:"0001-01-01",until:1/0,offset:1,name:"Anno Domini",narrow:"AD",abbr:"AD"},{since:"0000-12-31",until:-1/0,offset:1,name:"Before Christ",narrow:"BC",abbr:"BC"}],dayOfMonthOrdinalParse:/\d{1,2}(th|st|nd|rd)/,ordinal:function(e){var t=e%10;return e+(1===g(e%100/10)?"th":1==t?"st":2==t?"nd":3==t?"rd":"th")}}),f.lang=e("moment.lang is deprecated. Use moment.locale instead.",ct),f.langData=e("moment.langData is deprecated. Use moment.localeData instead.",mt);var _n=Math.abs;function yn(e,t,n,s){t=C(t,n);return e._milliseconds+=s*t._milliseconds,e._days+=s*t._days,e._months+=s*t._months,e._bubble()}function gn(e){return e<0?Math.floor(e):Math.ceil(e)}function wn(e){return 4800*e/146097}function pn(e){return 146097*e/4800}function kn(e){return function(){return this.as(e)}}pe=kn("ms"),me=kn("s"),Ce=kn("m"),we=kn("h"),ge=kn("d"),Je=kn("w"),k=kn("M"),_e=kn("Q"),ve=kn("y");function vn(e){return function(){return this.isValid()?this._data[e]:NaN}}var ye=vn("milliseconds"),ke=vn("seconds"),Ie=vn("minutes"),w=vn("hours"),Mn=vn("days"),Dn=vn("months"),Sn=vn("years");var Yn=Math.round,On={ss:44,s:45,m:45,h:22,d:26,w:null,M:11};function bn(e,t,n,s){var i=C(e).abs(),r=Yn(i.as("s")),a=Yn(i.as("m")),o=Yn(i.as("h")),u=Yn(i.as("d")),l=Yn(i.as("M")),h=Yn(i.as("w")),i=Yn(i.as("y")),r=(r<=n.ss?["s",r]:r<n.s&&["ss",r])||a<=1&&["m"]||a<n.m&&["mm",a]||o<=1&&["h"]||o<n.h&&["hh",o]||u<=1&&["d"]||u<n.d&&["dd",u];return(r=(r=null!=n.w?r||h<=1&&["w"]||h<n.w&&["ww",h]:r)||l<=1&&["M"]||l<n.M&&["MM",l]||i<=1&&["y"]||["yy",i])[2]=t,r[3]=0<+e,r[4]=s,function(e,t,n,s,i){return i.relativeTime(t||1,!!n,e,s)}.apply(null,r)}var xn=Math.abs;function Tn(e){return(0<e)-(e<0)||+e}function Nn(){if(!this.isValid())return this.localeData().invalidDate();var e,t,n,s,i,r,a,o=xn(this._milliseconds)/1e3,u=xn(this._days),l=xn(this._months),h=this.asSeconds();return h?(e=y(o/60),t=y(e/60),o%=60,e%=60,n=y(l/12),l%=12,s=o?o.toFixed(3).replace(/\.?0+$/,""):"",i=Tn(this._months)!==Tn(h)?"-":"",r=Tn(this._days)!==Tn(h)?"-":"",a=Tn(this._milliseconds)!==Tn(h)?"-":"",(h<0?"-":"")+"P"+(n?i+n+"Y":"")+(l?i+l+"M":"")+(u?r+u+"D":"")+(t||e||o?"T":"")+(t?a+t+"H":"")+(e?a+e+"M":"")+(o?a+s+"S":"")):"P0D"}var U=Ct.prototype;return U.isValid=function(){return this._isValid},U.abs=function(){var e=this._data;return this._milliseconds=_n(this._milliseconds),this._days=_n(this._days),this._months=_n(this._months),e.milliseconds=_n(e.milliseconds),e.seconds=_n(e.seconds),e.minutes=_n(e.minutes),e.hours=_n(e.hours),e.months=_n(e.months),e.years=_n(e.years),this},U.add=function(e,t){return yn(this,e,t,1)},U.subtract=function(e,t){return yn(this,e,t,-1)},U.as=function(e){if(!this.isValid())return NaN;var t,n,s=this._milliseconds;if("month"===(e=_(e))||"quarter"===e||"year"===e)switch(t=this._days+s/864e5,n=this._months+wn(t),e){case"month":return n;case"quarter":return n/3;case"year":return n/12}else switch(t=this._days+Math.round(pn(this._months)),e){case"week":return t/7+s/6048e5;case"day":return t+s/864e5;case"hour":return 24*t+s/36e5;case"minute":return 1440*t+s/6e4;case"second":return 86400*t+s/1e3;case"millisecond":return Math.floor(864e5*t)+s;default:throw new Error("Unknown unit "+e)}},U.asMilliseconds=pe,U.asSeconds=me,U.asMinutes=Ce,U.asHours=we,U.asDays=ge,U.asWeeks=Je,U.asMonths=k,U.asQuarters=_e,U.asYears=ve,U.valueOf=function(){return this.isValid()?this._milliseconds+864e5*this._days+this._months%12*2592e6+31536e6*g(this._months/12):NaN},U._bubble=function(){var e=this._milliseconds,t=this._days,n=this._months,s=this._data;return 0<=e&&0<=t&&0<=n||e<=0&&t<=0&&n<=0||(e+=864e5*gn(pn(n)+t),n=t=0),s.milliseconds=e%1e3,e=y(e/1e3),s.seconds=e%60,e=y(e/60),s.minutes=e%60,e=y(e/60),s.hours=e%24,t+=y(e/24),n+=e=y(wn(t)),t-=gn(pn(e)),e=y(n/12),n%=12,s.days=t,s.months=n,s.years=e,this},U.clone=function(){return C(this)},U.get=function(e){return e=_(e),this.isValid()?this[e+"s"]():NaN},U.milliseconds=ye,U.seconds=ke,U.minutes=Ie,U.hours=w,U.days=Mn,U.weeks=function(){return y(this.days()/7)},U.months=Dn,U.years=Sn,U.humanize=function(e,t){if(!this.isValid())return this.localeData().invalidDate();var n=!1,s=On;return"object"==typeof e&&(t=e,e=!1),"boolean"==typeof e&&(n=e),"object"==typeof t&&(s=Object.assign({},On,t),null!=t.s&&null==t.ss&&(s.ss=t.s-1)),e=this.localeData(),t=bn(this,!n,s,e),n&&(t=e.pastFuture(+this,t)),e.postformat(t)},U.toISOString=Nn,U.toString=Nn,U.toJSON=Nn,U.locale=Xt,U.localeData=Kt,U.toIsoString=e("toIsoString() is deprecated. Please use toISOString() instead (notice the capitals)",Nn),U.lang=Xe,s("X",0,0,"unix"),s("x",0,0,"valueOf"),v("x",De),v("X",/[+-]?\d+(\.\d{1,3})?/),D("X",function(e,t,n){n._d=new Date(1e3*parseFloat(e))}),D("x",function(e,t,n){n._d=new Date(g(e))}),f.version="2.29.4",H=W,f.fn=i,f.min=function(){return Rt("isBefore",[].slice.call(arguments,0))},f.max=function(){return Rt("isAfter",[].slice.call(arguments,0))},f.now=function(){return Date.now?Date.now():+new Date},f.utc=l,f.unix=function(e){return W(1e3*e)},f.months=function(e,t){return fn(e,t,"months")},f.isDate=V,f.locale=ct,f.invalid=I,f.duration=C,f.isMoment=h,f.weekdays=function(e,t,n){return mn(e,t,n,"weekdays")},f.parseZone=function(){return W.apply(null,arguments).parseZone()},f.localeData=mt,f.isDuration=Ut,f.monthsShort=function(e,t){return fn(e,t,"monthsShort")},f.weekdaysMin=function(e,t,n){return mn(e,t,n,"weekdaysMin")},f.defineLocale=ft,f.updateLocale=function(e,t){var n,s;return null!=t?(s=ot,null!=R[e]&&null!=R[e].parentLocale?R[e].set(X(R[e]._config,t)):(t=X(s=null!=(n=dt(e))?n._config:s,t),null==n&&(t.abbr=e),(s=new K(t)).parentLocale=R[e],R[e]=s),ct(e)):null!=R[e]&&(null!=R[e].parentLocale?(R[e]=R[e].parentLocale,e===ct()&&ct(e)):null!=R[e]&&delete R[e]),R[e]},f.locales=function(){return ee(R)},f.weekdaysShort=function(e,t,n){return mn(e,t,n,"weekdaysShort")},f.normalizeUnits=_,f.relativeTimeRounding=function(e){return void 0===e?Yn:"function"==typeof e&&(Yn=e,!0)},f.relativeTimeThreshold=function(e,t){return void 0!==On[e]&&(void 0===t?On[e]:(On[e]=t,"s"===e&&(On.ss=t-1),!0))},f.calendarFormat=function(e,t){return(e=e.diff(t,"days",!0))<-6?"sameElse":e<-1?"lastWeek":e<0?"lastDay":e<1?"sameDay":e<2?"nextDay":e<7?"nextWeek":"sameElse"},f.prototype=i,f.HTML5_FMT={DATETIME_LOCAL:"YYYY-MM-DDTHH:mm",DATETIME_LOCAL_SECONDS:"YYYY-MM-DDTHH:mm:ss",DATETIME_LOCAL_MS:"YYYY-MM-DDTHH:mm:ss.SSS",DATE:"YYYY-MM-DD",TIME:"HH:mm",TIME_SECONDS:"HH:mm:ss",TIME_MS:"HH:mm:ss.SSS",WEEK:"GGGG-[W]WW",MONTH:"YYYY-MM"},f});
//# sourceMappingURL=moment.min.js.map;
!function(t,e){"object"==typeof exports&&"undefined"!=typeof module?module.exports=e():"function"==typeof define&&define.amd?define(e):t.SignaturePad=e()}(this,function(){"use strict";function t(t,e,i){this.x=t,this.y=e,this.time=i||(new Date).getTime()}function e(t,e,i,o){this.startPoint=t,this.control1=e,this.control2=i,this.endPoint=o}function i(t,e,i){var o,n,s,r=null,h=0;i||(i={});var a=function(){h=!1===i.leading?0:Date.now(),r=null,s=t.apply(o,n),r||(o=n=null)};return function(){var c=Date.now();h||!1!==i.leading||(h=c);var d=e-(c-h);return o=this,n=arguments,d<=0||d>e?(r&&(clearTimeout(r),r=null),h=c,s=t.apply(o,n),r||(o=n=null)):r||!1===i.trailing||(r=setTimeout(a,d)),s}}function o(t,e){var n=this,s=e||{};this.velocityFilterWeight=s.velocityFilterWeight||.7,this.minWidth=s.minWidth||.5,this.maxWidth=s.maxWidth||2.5,this.throttle="throttle"in s?s.throttle:16,this.minDistance="minDistance"in s?s.minDistance:5,this.throttle?this._strokeMoveUpdate=i(o.prototype._strokeUpdate,this.throttle):this._strokeMoveUpdate=o.prototype._strokeUpdate,this.dotSize=s.dotSize||function(){return(this.minWidth+this.maxWidth)/2},this.penColor=s.penColor||"black",this.backgroundColor=s.backgroundColor||"rgba(0,0,0,0)",this.onBegin=s.onBegin,this.onEnd=s.onEnd,this._canvas=t,this._ctx=t.getContext("2d"),this.clear(),this._handleMouseDown=function(t){1===t.which&&(n._mouseButtonDown=!0,n._strokeBegin(t))},this._handleMouseMove=function(t){n._mouseButtonDown&&n._strokeMoveUpdate(t)},this._handleMouseUp=function(t){1===t.which&&n._mouseButtonDown&&(n._mouseButtonDown=!1,n._strokeEnd(t))},this._handleTouchStart=function(t){if(1===t.targetTouches.length){var e=t.changedTouches[0];n._strokeBegin(e)}},this._handleTouchMove=function(t){t.preventDefault();var e=t.targetTouches[0];n._strokeMoveUpdate(e)},this._handleTouchEnd=function(t){t.target===n._canvas&&(t.preventDefault(),n._strokeEnd(t))},this.on()}return t.prototype.velocityFrom=function(t){return this.time!==t.time?this.distanceTo(t)/(this.time-t.time):1},t.prototype.distanceTo=function(t){return Math.sqrt(Math.pow(this.x-t.x,2)+Math.pow(this.y-t.y,2))},t.prototype.equals=function(t){return this.x===t.x&&this.y===t.y&&this.time===t.time},e.prototype.length=function(){for(var t=0,e=void 0,i=void 0,o=0;o<=10;o+=1){var n=o/10,s=this._point(n,this.startPoint.x,this.control1.x,this.control2.x,this.endPoint.x),r=this._point(n,this.startPoint.y,this.control1.y,this.control2.y,this.endPoint.y);if(o>0){var h=s-e,a=r-i;t+=Math.sqrt(h*h+a*a)}e=s,i=r}return t},e.prototype._point=function(t,e,i,o,n){return e*(1-t)*(1-t)*(1-t)+3*i*(1-t)*(1-t)*t+3*o*(1-t)*t*t+n*t*t*t},o.prototype.clear=function(){var t=this._ctx,e=this._canvas;t.fillStyle=this.backgroundColor,t.clearRect(0,0,e.width,e.height),t.fillRect(0,0,e.width,e.height),this._data=[],this._reset(),this._isEmpty=!0},o.prototype.fromDataURL=function(t){var e=this,i=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{},o=new Image,n=i.ratio||window.devicePixelRatio||1,s=i.width||this._canvas.width/n,r=i.height||this._canvas.height/n;this._reset(),o.src=t,o.onload=function(){e._ctx.drawImage(o,0,0,s,r)},this._isEmpty=!1},o.prototype.toDataURL=function(t){var e;switch(t){case"image/svg+xml":return this._toSVG();default:for(var i=arguments.length,o=Array(i>1?i-1:0),n=1;n<i;n++)o[n-1]=arguments[n];return(e=this._canvas).toDataURL.apply(e,[t].concat(o))}},o.prototype.on=function(){this._handleMouseEvents(),this._handleTouchEvents()},o.prototype.off=function(){this._canvas.removeEventListener("mousedown",this._handleMouseDown),this._canvas.removeEventListener("mousemove",this._handleMouseMove),document.removeEventListener("mouseup",this._handleMouseUp),this._canvas.removeEventListener("touchstart",this._handleTouchStart),this._canvas.removeEventListener("touchmove",this._handleTouchMove),this._canvas.removeEventListener("touchend",this._handleTouchEnd)},o.prototype.isEmpty=function(){return this._isEmpty},o.prototype._strokeBegin=function(t){this._data.push([]),this._reset(),this._strokeUpdate(t),"function"==typeof this.onBegin&&this.onBegin(t)},o.prototype._strokeUpdate=function(t){var e=t.clientX,i=t.clientY,o=this._createPoint(e,i),n=this._data[this._data.length-1],s=n&&n[n.length-1],r=s&&o.distanceTo(s)<this.minDistance;if(!s||!r){var h=this._addPoint(o),a=h.curve,c=h.widths;a&&c&&this._drawCurve(a,c.start,c.end),this._data[this._data.length-1].push({x:o.x,y:o.y,time:o.time,color:this.penColor})}},o.prototype._strokeEnd=function(t){var e=this.points.length>2,i=this.points[0];if(!e&&i&&this._drawDot(i),i){var o=this._data[this._data.length-1],n=o[o.length-1];i.equals(n)||o.push({x:i.x,y:i.y,time:i.time,color:this.penColor})}"function"==typeof this.onEnd&&this.onEnd(t)},o.prototype._handleMouseEvents=function(){this._mouseButtonDown=!1,this._canvas.addEventListener("mousedown",this._handleMouseDown),this._canvas.addEventListener("mousemove",this._handleMouseMove),document.addEventListener("mouseup",this._handleMouseUp)},o.prototype._handleTouchEvents=function(){this._canvas.style.msTouchAction="none",this._canvas.style.touchAction="none",this._canvas.addEventListener("touchstart",this._handleTouchStart),this._canvas.addEventListener("touchmove",this._handleTouchMove),this._canvas.addEventListener("touchend",this._handleTouchEnd)},o.prototype._reset=function(){this.points=[],this._lastVelocity=0,this._lastWidth=(this.minWidth+this.maxWidth)/2,this._ctx.fillStyle=this.penColor},o.prototype._createPoint=function(e,i,o){var n=this._canvas.getBoundingClientRect();return new t(e-n.left,i-n.top,o||(new Date).getTime())},o.prototype._addPoint=function(t){var i=this.points,o=void 0;if(i.push(t),i.length>2){3===i.length&&i.unshift(i[0]),o=this._calculateCurveControlPoints(i[0],i[1],i[2]);var n=o.c2;o=this._calculateCurveControlPoints(i[1],i[2],i[3]);var s=o.c1,r=new e(i[1],n,s,i[2]),h=this._calculateCurveWidths(r);return i.shift(),{curve:r,widths:h}}return{}},o.prototype._calculateCurveControlPoints=function(e,i,o){var n=e.x-i.x,s=e.y-i.y,r=i.x-o.x,h=i.y-o.y,a={x:(e.x+i.x)/2,y:(e.y+i.y)/2},c={x:(i.x+o.x)/2,y:(i.y+o.y)/2},d=Math.sqrt(n*n+s*s),l=Math.sqrt(r*r+h*h),u=a.x-c.x,v=a.y-c.y,p=l/(d+l),_={x:c.x+u*p,y:c.y+v*p},y=i.x-_.x,f=i.y-_.y;return{c1:new t(a.x+y,a.y+f),c2:new t(c.x+y,c.y+f)}},o.prototype._calculateCurveWidths=function(t){var e=t.startPoint,i=t.endPoint,o={start:null,end:null},n=this.velocityFilterWeight*i.velocityFrom(e)+(1-this.velocityFilterWeight)*this._lastVelocity,s=this._strokeWidth(n);return o.start=this._lastWidth,o.end=s,this._lastVelocity=n,this._lastWidth=s,o},o.prototype._strokeWidth=function(t){return Math.max(this.maxWidth/(t+1),this.minWidth)},o.prototype._drawPoint=function(t,e,i){var o=this._ctx;o.moveTo(t,e),o.arc(t,e,i,0,2*Math.PI,!1),this._isEmpty=!1},o.prototype._drawCurve=function(t,e,i){var o=this._ctx,n=i-e,s=Math.floor(t.length());o.beginPath();for(var r=0;r<s;r+=1){var h=r/s,a=h*h,c=a*h,d=1-h,l=d*d,u=l*d,v=u*t.startPoint.x;v+=3*l*h*t.control1.x,v+=3*d*a*t.control2.x,v+=c*t.endPoint.x;var p=u*t.startPoint.y;p+=3*l*h*t.control1.y,p+=3*d*a*t.control2.y,p+=c*t.endPoint.y;var _=e+c*n;this._drawPoint(v,p,_)}o.closePath(),o.fill()},o.prototype._drawDot=function(t){var e=this._ctx,i="function"==typeof this.dotSize?this.dotSize():this.dotSize;e.beginPath(),this._drawPoint(t.x,t.y,i),e.closePath(),e.fill()},o.prototype._fromData=function(e,i,o){for(var n=0;n<e.length;n+=1){var s=e[n];if(s.length>1)for(var r=0;r<s.length;r+=1){var h=s[r],a=new t(h.x,h.y,h.time),c=h.color;if(0===r)this.penColor=c,this._reset(),this._addPoint(a);else if(r!==s.length-1){var d=this._addPoint(a),l=d.curve,u=d.widths;l&&u&&i(l,u,c)}}else{this._reset();o(s[0])}}},o.prototype._toSVG=function(){var t=this,e=this._data,i=this._canvas,o=Math.max(window.devicePixelRatio||1,1),n=i.width/o,s=i.height/o,r=document.createElementNS("http://www.w3.org/2000/svg","svg");r.setAttributeNS(null,"width",i.width),r.setAttributeNS(null,"height",i.height),this._fromData(e,function(t,e,i){var o=document.createElement("path");if(!(isNaN(t.control1.x)||isNaN(t.control1.y)||isNaN(t.control2.x)||isNaN(t.control2.y))){var n="M "+t.startPoint.x.toFixed(3)+","+t.startPoint.y.toFixed(3)+" C "+t.control1.x.toFixed(3)+","+t.control1.y.toFixed(3)+" "+t.control2.x.toFixed(3)+","+t.control2.y.toFixed(3)+" "+t.endPoint.x.toFixed(3)+","+t.endPoint.y.toFixed(3);o.setAttribute("d",n),o.setAttribute("stroke-width",(2.25*e.end).toFixed(3)),o.setAttribute("stroke",i),o.setAttribute("fill","none"),o.setAttribute("stroke-linecap","round"),r.appendChild(o)}},function(e){var i=document.createElement("circle"),o="function"==typeof t.dotSize?t.dotSize():t.dotSize;i.setAttribute("r",o),i.setAttribute("cx",e.x),i.setAttribute("cy",e.y),i.setAttribute("fill",e.color),r.appendChild(i)});var h='<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" viewBox="0 0 '+n+" "+s+'" width="'+n+'" height="'+s+'">',a=r.innerHTML;if(void 0===a){var c=document.createElement("dummy"),d=r.childNodes;c.innerHTML="";for(var l=0;l<d.length;l+=1)c.appendChild(d[l].cloneNode(!0));a=c.innerHTML}var u=h+a+"</svg>";return"data:image/svg+xml;base64,"+btoa(u)},o.prototype.fromData=function(t){var e=this;this.clear(),this._fromData(t,function(t,i){return e._drawCurve(t,i.start,i.end)},function(t){return e._drawDot(t)}),this._data=t},o.prototype.toData=function(){return this._data},o});;
/* ========================================================================
 * Bootstrap: tab.js v3.4.1
 * https://getbootstrap.com/docs/3.4/javascript/#tabs
 * ========================================================================
 * Copyright 2011-2019 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


!function ($) {
  'use strict';

  // TAB CLASS DEFINITION
  // ====================

  var Tab = function (element) {
    // jscs:disable requireDollarBeforejQueryAssignment
    this.element = $(element)
    // jscs:enable requireDollarBeforejQueryAssignment
  }

  Tab.VERSION = '3.4.1'

  Tab.TRANSITION_DURATION = 150

  Tab.prototype.show = function () {
    var $this    = this.element
    var $ul      = $this.closest('ul:not(.dropdown-menu)')
    var selector = $this.data('target')

    if (!selector) {
      selector = $this.attr('href')
      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
    }

    if ($this.parent('li').hasClass('active')) return

    var $previous = $ul.find('.active:last a')
    var hideEvent = $.Event('hide.bs.tab', {
      relatedTarget: $this[0]
    })
    var showEvent = $.Event('show', {
      relatedTarget: $previous[0]
    })

    $previous.trigger(hideEvent)
    $this.trigger(showEvent)

    if (showEvent.isDefaultPrevented() || hideEvent.isDefaultPrevented()) return

    var $target = $(document).find(selector)

    this.activate($this.closest('li'), $ul)
    this.activate($target, $target.parent(), function () {
      $previous.trigger({
        type: 'hidden.bs.tab',
        relatedTarget: $this[0]
      })
      $this.trigger({
        type: 'shown',
        relatedTarget: $previous[0]
      })
    })
  }

  Tab.prototype.activate = function (element, container, callback) {
    var $active    = container.find('> .active')
    var transition = callback
      && $.support.transition
      && ($active.length && $active.hasClass('fade') || !!container.find('> .fade').length)

    function next() {
      $active
        .removeClass('active')
        .find('> .dropdown-menu > .active')
        .removeClass('active')
        .end()
        //.find('[data-toggle="tab"]') //Commented for ONLINE-13390 finding
        //.attr('aria-expanded', false)

      element
        .addClass('active')
        //.find('[data-toggle="tab"]')//Commented for ONLINE-13390 finding
        //.attr('aria-expanded', true)

      if (transition) {
        element[0].offsetWidth // reflow for transition
        element.addClass('in')
      } else {
        element.removeClass('fade')
      }

      if (element.parent('.dropdown-menu').length) {
        element
          .closest('li.dropdown')
          .addClass('active')
          .end()
          .find('[data-toggle="tab"]')
          .attr('aria-expanded', true)
      }

      callback && callback()
    }

    $active.length && transition ?
      $active
        .one('bsTransitionEnd', next)
        .emulateTransitionEnd(Tab.TRANSITION_DURATION) :
      next()

    $active.removeClass('in')
  }


  // TAB PLUGIN DEFINITION
  // =====================

  function Plugin(option) {
    return this.each(function () {
      var $this = $(this)
      var data  = $this.data('bs.tab')

      if (!data) $this.data('bs.tab', (data = new Tab(this)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.tab

  $.fn.tab             = Plugin
  $.fn.tab.Constructor = Tab


  // TAB NO CONFLICT
  // ===============

  $.fn.tab.noConflict = function () {
    $.fn.tab = old
    return this
  }


  // TAB DATA-API
  // ============

  var clickHandler = function (e) {
    e.preventDefault()
    Plugin.call($(this), 'show')
  }

  $(document)
    .on('click.bs.tab.data-api', '[data-toggle="tab"]', clickHandler)
    .on('click.bs.tab.data-api', '[data-toggle="pill"]', clickHandler)

}(jQuery);
;
/* ========================================================================
 * Bootstrap: collapse.js v3.4.1
 * https://getbootstrap.com/docs/3.4/javascript/#collapse
 * ========================================================================
 * Copyright 2011-2019 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */

/* jshint latedef: false */

+function ($) {
  'use strict';

  // COLLAPSE PUBLIC CLASS DEFINITION
  // ================================

  var Collapse = function (element, options) {
    this.$element      = $(element)
    this.options       = $.extend({}, Collapse.DEFAULTS, options)
    this.$trigger      = $('[data-toggle="collapse"][href="#' + element.id + '"],' +
                           '[data-toggle="collapse"][data-target="#' + element.id + '"]')
    this.transitioning = null

    if (this.options.parent) {
      this.$parent = this.getParent()
    } else {
      this.addAriaAndCollapsedClass(this.$element, this.$trigger)
    }

    if (this.options.toggle) this.toggle()
  }

  Collapse.VERSION  = '3.4.1'

  Collapse.TRANSITION_DURATION = 350

  Collapse.DEFAULTS = {
    toggle: true
  }

  Collapse.prototype.dimension = function () {
    var hasWidth = this.$element.hasClass('width')
    return hasWidth ? 'width' : 'height'
  }

  Collapse.prototype.show = function () {
    if (this.transitioning || this.$element.hasClass('in')) return

    var activesData
    var actives = this.$parent && this.$parent.children('.panel').children('.in, .collapsing')

    if (actives && actives.length) {
      activesData = actives.data('bs.collapse')
      if (activesData && activesData.transitioning) return
    }

    var startEvent = $.Event('show.bs.collapse')
    this.$element.trigger(startEvent)
    if (startEvent.isDefaultPrevented()) return

    if (actives && actives.length) {
      Plugin.call(actives, 'hide')
      activesData || actives.data('bs.collapse', null)
    }

    var dimension = this.dimension()

    this.$element
      .removeClass('collapse')
      .addClass('collapsing')[dimension](0)
      .attr('aria-expanded', true)

    this.$trigger
      .removeClass('collapsed')
      .attr('aria-expanded', true)

    this.transitioning = 1

    var complete = function () {
      this.$element
        .removeClass('collapsing')
        .addClass('collapse in')[dimension]('')
      this.transitioning = 0
      this.$element
        .trigger('shown.bs.collapse')
    }

    if (!$.support.transition) return complete.call(this)

    var scrollSize = $.camelCase(['scroll', dimension].join('-'))

    this.$element
      .one('bsTransitionEnd', $.proxy(complete, this))
      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)[dimension](this.$element[0][scrollSize])
  }

  Collapse.prototype.hide = function () {
    if (this.transitioning || !this.$element.hasClass('in')) return

    var startEvent = $.Event('hide.bs.collapse')
    this.$element.trigger(startEvent)
    if (startEvent.isDefaultPrevented()) return

    var dimension = this.dimension()

    this.$element[dimension](this.$element[dimension]())[0].offsetHeight

    this.$element
      .addClass('collapsing')
      .removeClass('collapse in')
      .attr('aria-expanded', false)

    this.$trigger
      .addClass('collapsed')
      .attr('aria-expanded', false)

    this.transitioning = 1

    var complete = function () {
      this.transitioning = 0
      this.$element
        .removeClass('collapsing')
        .addClass('collapse')
        .trigger('hidden.bs.collapse')
    }

    if (!$.support.transition) return complete.call(this)

    this.$element
      [dimension](0)
      .one('bsTransitionEnd', $.proxy(complete, this))
      .emulateTransitionEnd(Collapse.TRANSITION_DURATION)
  }

  Collapse.prototype.toggle = function () {
    this[this.$element.hasClass('in') ? 'hide' : 'show']()
  }

  Collapse.prototype.getParent = function () {
    return $(document).find(this.options.parent)
      .find('[data-toggle="collapse"][data-parent="' + this.options.parent + '"]')
      .each($.proxy(function (i, element) {
        var $element = $(element)
        this.addAriaAndCollapsedClass(getTargetFromTrigger($element), $element)
      }, this))
      .end()
  }

  Collapse.prototype.addAriaAndCollapsedClass = function ($element, $trigger) {
    var isOpen = $element.hasClass('in')

    $element.attr('aria-expanded', isOpen)
    $trigger
      .toggleClass('collapsed', !isOpen)
      .attr('aria-expanded', isOpen)
  }

  function getTargetFromTrigger($trigger) {
    var href
    var target = $trigger.attr('data-target')
      || (href = $trigger.attr('href')) && href.replace(/.*(?=#[^\s]+$)/, '') // strip for ie7

    return $(document).find(target)
  }


  // COLLAPSE PLUGIN DEFINITION
  // ==========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.collapse')
      var options = $.extend({}, Collapse.DEFAULTS, $this.data(), typeof option == 'object' && option)

      if (!data && options.toggle && /show|hide/.test(option)) options.toggle = false
      if (!data) $this.data('bs.collapse', (data = new Collapse(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.collapse

  $.fn.collapse             = Plugin
  $.fn.collapse.Constructor = Collapse


  // COLLAPSE NO CONFLICT
  // ====================

  $.fn.collapse.noConflict = function () {
    $.fn.collapse = old
    return this
  }


  // COLLAPSE DATA-API
  // =================

  $(document).on('click.bs.collapse.data-api', '[data-toggle="collapse"]', function (e) {
    var $this   = $(this)

    if (!$this.attr('data-target')) e.preventDefault()

    var $target = getTargetFromTrigger($this)
    var data    = $target.data('bs.collapse')
    var option  = data ? 'toggle' : $this.data()

    Plugin.call($target, option)
  })

}(jQuery);
;
/* ========================================================================
 * Bootstrap: transition.js v3.4.1
 * https://getbootstrap.com/docs/3.4/javascript/#transitions
 * ========================================================================
 * Copyright 2011-2019 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // CSS TRANSITION SUPPORT (Shoutout: https://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 (  ._.)
  }

  // https://blog.alexmaccaw.com/css-transitions
  $.fn.emulateTransitionEnd = function (duration) {
    var called = false
    var $el = this
    $(this).one('bsTransitionEnd', function () { called = true })
    var callback = function () { if (!called) $($el).trigger($.support.transition.end) }
    setTimeout(callback, duration)
    return this
  }

  $(function () {
    $.support.transition = transitionEnd()

    if (!$.support.transition) return

    $.event.special.bsTransitionEnd = {
      bindType: $.support.transition.end,
      delegateType: $.support.transition.end,
      handle: function (e) {
        if ($(e.target).is(this)) return e.handleObj.handler.apply(this, arguments)
      }
    }
  })

}(jQuery);
;
/* ========================================================================
 * Bootstrap: tooltip.js v3.4.1
 * https://getbootstrap.com/docs/3.4/javascript/#tooltip
 * Inspired by the original jQuery.tipsy by Jason Frame
 * ========================================================================
 * Copyright 2011-2019 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */

+function ($) {
  'use strict';

  var DISALLOWED_ATTRIBUTES = ['sanitize', 'whiteList', 'sanitizeFn']

  var uriAttrs = [
    'background',
    'cite',
    'href',
    'itemtype',
    'longdesc',
    'poster',
    'src',
    'xlink:href'
  ]

  var ARIA_ATTRIBUTE_PATTERN = /^aria-[\w-]*$/i

  var DefaultWhitelist = {
    // Global attributes allowed on any supplied element below.
    '*': ['class', 'dir', 'id', 'lang', 'role', ARIA_ATTRIBUTE_PATTERN],
    a: ['target', 'href', 'title', 'rel'],
    area: [],
    b: [],
    br: [],
    col: [],
    code: [],
    div: [],
    em: [],
    hr: [],
    h1: [],
    h2: [],
    h3: [],
    h4: [],
    h5: [],
    h6: [],
    i: [],
    img: ['src', 'alt', 'title', 'width', 'height'],
    li: [],
    ol: [],
    p: [],
    pre: [],
    s: [],
    small: [],
    span: [],
    sub: [],
    sup: [],
    strong: [],
    u: [],
    ul: []
  }

  /**
   * A pattern that recognizes a commonly useful subset of URLs that are safe.
   *
   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
   */
  var SAFE_URL_PATTERN = /^(?:(?:https?|mailto|ftp|tel|file):|[^&:/?#]*(?:[/?#]|$))/gi

  /**
   * A pattern that matches safe data URLs. Only matches image, video and audio types.
   *
   * Shoutout to Angular 7 https://github.com/angular/angular/blob/7.2.4/packages/core/src/sanitization/url_sanitizer.ts
   */
  var DATA_URL_PATTERN = /^data:(?:image\/(?:bmp|gif|jpeg|jpg|png|tiff|webp)|video\/(?:mpeg|mp4|ogg|webm)|audio\/(?:mp3|oga|ogg|opus));base64,[a-z0-9+/]+=*$/i

  function allowedAttribute(attr, allowedAttributeList) {
    var attrName = attr.nodeName.toLowerCase()

    if ($.inArray(attrName, allowedAttributeList) !== -1) {
      if ($.inArray(attrName, uriAttrs) !== -1) {
        return Boolean(attr.nodeValue.match(SAFE_URL_PATTERN) || attr.nodeValue.match(DATA_URL_PATTERN))
      }

      return true
    }

    var regExp = $(allowedAttributeList).filter(function (index, value) {
      return value instanceof RegExp
    })

    // Check if a regular expression validates the attribute.
    for (var i = 0, l = regExp.length; i < l; i++) {
      if (attrName.match(regExp[i])) {
        return true
      }
    }

    return false
  }

  function sanitizeHtml(unsafeHtml, whiteList, sanitizeFn) {
    if (unsafeHtml.length === 0) {
      return unsafeHtml
    }

    if (sanitizeFn && typeof sanitizeFn === 'function') {
      return sanitizeFn(unsafeHtml)
    }

    // IE 8 and below don't support createHTMLDocument
    if (!document.implementation || !document.implementation.createHTMLDocument) {
      return unsafeHtml
    }

    var createdDocument = document.implementation.createHTMLDocument('sanitization')
    createdDocument.body.innerHTML = unsafeHtml

    var whitelistKeys = $.map(whiteList, function (el, i) { return i })
    var elements = $(createdDocument.body).find('*')

    for (var i = 0, len = elements.length; i < len; i++) {
      var el = elements[i]
      var elName = el.nodeName.toLowerCase()

      if ($.inArray(elName, whitelistKeys) === -1) {
        el.parentNode.removeChild(el)

        continue
      }

      var attributeList = $.map(el.attributes, function (el) { return el })
      var whitelistedAttributes = [].concat(whiteList['*'] || [], whiteList[elName] || [])

      for (var j = 0, len2 = attributeList.length; j < len2; j++) {
        if (!allowedAttribute(attributeList[j], whitelistedAttributes)) {
          el.removeAttribute(attributeList[j].nodeName)
        }
      }
    }

    return createdDocument.body.innerHTML
  }

  // TOOLTIP PUBLIC CLASS DEFINITION
  // ===============================

  var Tooltip = function (element, options) {
    this.type       = null
    this.options    = null
    this.enabled    = null
    this.timeout    = null
    this.hoverState = null
    this.$element   = null
    this.inState    = null

    this.init('tooltip', element, options)
  }

  Tooltip.VERSION  = '3.4.1'

  Tooltip.TRANSITION_DURATION = 150

  Tooltip.DEFAULTS = {
    animation: true,
    placement: 'top',
    selector: false,
    template: '<div class="tooltip" role="tooltip"><div class="tooltip-arrow"></div><div class="tooltip-inner"></div></div>',
    trigger: 'hover focus',
    title: '',
    delay: 0,
    html: false,
    container: false,
    viewport: {
      selector: 'body',
      padding: 0
    },
    sanitize : true,
    sanitizeFn : null,
    whiteList : DefaultWhitelist
  }

  Tooltip.prototype.init = function (type, element, options) {
    this.enabled   = true
    this.type      = type
    this.$element  = $(element)
    this.options   = this.getOptions(options)
    this.$viewport = this.options.viewport && $(document).find($.isFunction(this.options.viewport) ? this.options.viewport.call(this, this.$element) : (this.options.viewport.selector || this.options.viewport))
    this.inState   = { click: false, hover: false, focus: false }

    if (this.$element[0] instanceof document.constructor && !this.options.selector) {
      throw new Error('`selector` option must be specified when initializing ' + this.type + ' on the window.document object!')
    }

    var triggers = this.options.trigger.split(' ')

    for (var i = triggers.length; i--;) {
      var trigger = triggers[i]

      if (trigger == 'click') {
        this.$element.on('click.' + this.type, this.options.selector, $.proxy(this.toggle, this))
      } else if (trigger != 'manual') {
        var eventIn  = trigger == 'hover' ? 'mouseenter' : 'focusin'
        var eventOut = trigger == 'hover' ? 'mouseleave' : 'focusout'

        this.$element.on(eventIn  + '.' + this.type, this.options.selector, $.proxy(this.enter, this))
        this.$element.on(eventOut + '.' + this.type, this.options.selector, $.proxy(this.leave, this))
      }
    }

    this.options.selector ?
      (this._options = $.extend({}, this.options, { trigger: 'manual', selector: '' })) :
      this.fixTitle()
  }

  Tooltip.prototype.getDefaults = function () {
    return Tooltip.DEFAULTS
  }

  Tooltip.prototype.getOptions = function (options) {
    var dataAttributes = this.$element.data()

    for (var dataAttr in dataAttributes) {
      if (dataAttributes.hasOwnProperty(dataAttr) && $.inArray(dataAttr, DISALLOWED_ATTRIBUTES) !== -1) {
        delete dataAttributes[dataAttr]
      }
    }

    options = $.extend({}, this.getDefaults(), dataAttributes, options)

    if (options.delay && typeof options.delay == 'number') {
      options.delay = {
        show: options.delay,
        hide: options.delay
      }
    }

    if (options.sanitize) {
      options.template = sanitizeHtml(options.template, options.whiteList, options.sanitizeFn)
    }

    return options
  }

  Tooltip.prototype.getDelegateOptions = function () {
    var options  = {}
    var defaults = this.getDefaults()

    this._options && $.each(this._options, function (key, value) {
      if (defaults[key] != value) options[key] = value
    })

    return options
  }

  Tooltip.prototype.enter = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget).data('bs.' + this.type)

    if (!self) {
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
      $(obj.currentTarget).data('bs.' + this.type, self)
    }

    if (obj instanceof $.Event) {
      self.inState[obj.type == 'focusin' ? 'focus' : 'hover'] = true
    }

    if (self.tip().hasClass('in') || self.hoverState == 'in') {
      self.hoverState = 'in'
      return
    }

    clearTimeout(self.timeout)

    self.hoverState = 'in'

    if (!self.options.delay || !self.options.delay.show) return self.show()

    self.timeout = setTimeout(function () {
      if (self.hoverState == 'in') self.show()
    }, self.options.delay.show)
  }

  Tooltip.prototype.isInStateTrue = function () {
    for (var key in this.inState) {
      if (this.inState[key]) return true
    }

    return false
  }

  Tooltip.prototype.leave = function (obj) {
    var self = obj instanceof this.constructor ?
      obj : $(obj.currentTarget).data('bs.' + this.type)

    if (!self) {
      self = new this.constructor(obj.currentTarget, this.getDelegateOptions())
      $(obj.currentTarget).data('bs.' + this.type, self)
    }

    if (obj instanceof $.Event) {
      self.inState[obj.type == 'focusout' ? 'focus' : 'hover'] = false
    }

    if (self.isInStateTrue()) return

    clearTimeout(self.timeout)

    self.hoverState = 'out'

    if (!self.options.delay || !self.options.delay.hide) return self.hide()

    self.timeout = setTimeout(function () {
      if (self.hoverState == 'out') self.hide()
    }, self.options.delay.hide)
  }

  Tooltip.prototype.show = function () {
    var e = $.Event('show.bs.' + this.type)

    if (this.hasContent() && this.enabled) {
      this.$element.trigger(e)

      var inDom = $.contains(this.$element[0].ownerDocument.documentElement, this.$element[0])
      if (e.isDefaultPrevented() || !inDom) return
      var that = this

      var $tip = this.tip()

      var tipId = this.getUID(this.type)

      this.setContent()
      $tip.attr('id', tipId)
      this.$element.not('.hide-aria-label').attr('aria-describedby', tipId)

      if (this.options.animation) $tip.addClass('fade')

      var placement = typeof this.options.placement == 'function' ?
        this.options.placement.call(this, $tip[0], this.$element[0]) :
        this.options.placement

      var autoToken = /\s?auto?\s?/i
      var autoPlace = autoToken.test(placement)
      if (autoPlace) placement = placement.replace(autoToken, '') || 'top'

      $tip
        .detach()
        .css({ top: 0, left: 0, display: 'block' })
        .addClass(placement)
        .data('bs.' + this.type, this)

      this.options.container ? $tip.appendTo($(document).find(this.options.container)) : $tip.insertAfter(this.$element)
      this.$element.trigger('inserted.bs.' + this.type)

      var pos          = this.getPosition()
      var actualWidth  = $tip[0].offsetWidth
      var actualHeight = $tip[0].offsetHeight

      if (autoPlace) {
        var orgPlacement = placement
        var viewportDim = this.getPosition(this.$viewport)

        placement = placement == 'bottom' && pos.bottom + actualHeight > viewportDim.bottom ? 'top'    :
                    placement == 'top'    && pos.top    - actualHeight < viewportDim.top    ? 'bottom' :
                    placement == 'right'  && pos.right  + actualWidth  > viewportDim.width  ? 'left'   :
                    placement == 'left'   && pos.left   - actualWidth  < viewportDim.left   ? 'right'  :
                    placement

        $tip
          .removeClass(orgPlacement)
          .addClass(placement)
      }

      var calculatedOffset = this.getCalculatedOffset(placement, pos, actualWidth, actualHeight)

      this.applyPlacement(calculatedOffset, placement)

      var complete = function () {
        var prevHoverState = that.hoverState
        that.$element.trigger('shown.bs.' + that.type)
        that.hoverState = null

        if (prevHoverState == 'out') that.leave(that)
      }

      $.support.transition && this.$tip.hasClass('fade') ?
        $tip
          .one('bsTransitionEnd', complete)
          .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
        complete()
    }
  }

    $.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
    };

  Tooltip.prototype.applyPlacement = function (offset, placement) {
    var $tip   = this.tip()
    var width  = $tip[0].offsetWidth
    var height = $tip[0].offsetHeight

    // manually read margins because getBoundingClientRect includes difference
    var marginTop = parseInt($tip.css('margin-top'), 10)
    var marginLeft = parseInt($tip.css('margin-left'), 10)

    // we must check for NaN for ie 8/9
    if (isNaN(marginTop))  marginTop  = 0
    if (isNaN(marginLeft)) marginLeft = 0

    offset.top  += marginTop
    offset.left += marginLeft

    // $.fn.offset doesn't round pixel values
    // so we use setOffset directly with our own function B-0
    $.offset.setOffset($tip[0], $.extend({
      using: function (props) {
        $tip.css({
          top: Math.round(props.top),
          left: Math.round(props.left)
        })
      }
    }, offset), 0)

    $tip.addClass('in')

    // check to see if placing tip in new offset caused the tip to resize itself
    var actualWidth  = $tip[0].offsetWidth
    var actualHeight = $tip[0].offsetHeight

    if (placement == 'top' && actualHeight != height) {
      offset.top = offset.top + height - actualHeight
    }

    var delta = this.getViewportAdjustedDelta(placement, offset, actualWidth, actualHeight)

    if (delta.left) offset.left += delta.left
    else offset.top += delta.top

    var isVertical          = /top|bottom/.test(placement)
    var arrowDelta          = isVertical ? delta.left * 2 - width + actualWidth : delta.top * 2 - height + actualHeight
    var arrowOffsetPosition = isVertical ? 'offsetWidth' : 'offsetHeight'

    $tip.offset(offset)
    this.replaceArrow(arrowDelta, $tip[0][arrowOffsetPosition], isVertical)
  }

  Tooltip.prototype.replaceArrow = function (delta, dimension, isVertical) {
    this.arrow()
      .css(isVertical ? 'left' : 'top', 50 * (1 - delta / dimension) + '%')
      .css(isVertical ? 'top' : 'left', '')
  }

  Tooltip.prototype.setContent = function () {
    var $tip  = this.tip()
    var title = this.getTitle()

    if (this.options.html) {
      if (this.options.sanitize) {
        title = sanitizeHtml(title, this.options.whiteList, this.options.sanitizeFn)
      }

      $tip.find('.tooltip-inner').html(title)
    } else {
      $tip.find('.tooltip-inner').text(title)
    }

    $tip.removeClass('fade in top bottom left right')
  }

  Tooltip.prototype.hide = function (callback) {
    var that = this
    var $tip = $(this.$tip)
    var e    = $.Event('hide.bs.' + this.type)

    function complete() {
      if (that.hoverState != 'in') $tip.detach()
      if (that.$element) { // TODO: Check whether guarding this code with this `if` is really necessary.
        that.$element
          .removeAttr('aria-describedby')
          .trigger('hidden.bs.' + that.type)
      }
      callback && callback()
    }

    this.$element.trigger(e)

    if (e.isDefaultPrevented()) return

    $tip.removeClass('in')

    $.support.transition && $tip.hasClass('fade') ?
      $tip
        .one('bsTransitionEnd', complete)
        .emulateTransitionEnd(Tooltip.TRANSITION_DURATION) :
      complete()

    this.hoverState = null

    return this
  }

  Tooltip.prototype.fixTitle = function () {
    var $e = this.$element
    if ($e.attr('title') || typeof $e.attr('data-original-title') != 'string') {
      $e.attr('data-original-title', $e.attr('title') || '').attr('title', '')
    }
  }

  Tooltip.prototype.hasContent = function () {
    return this.getTitle()
  }

  Tooltip.prototype.getPosition = function ($element) {
    $element   = $element || this.$element

    var el     = $element[0]
    var isBody = el.tagName == 'BODY'

    var elRect    = el.getBoundingClientRect()
    if (elRect.width == null) {
      // width and height are missing in IE8, so compute them manually; see https://github.com/twbs/bootstrap/issues/14093
      elRect = $.extend({}, elRect, { width: elRect.right - elRect.left, height: elRect.bottom - elRect.top })
    }
    var isSvg = window.SVGElement && el instanceof window.SVGElement
    // Avoid using $.offset() on SVGs since it gives incorrect results in jQuery 3.
    // See https://github.com/twbs/bootstrap/issues/20280
    var elOffset  = isBody ? { top: 0, left: 0 } : (isSvg ? null : $element.offset())
    var scroll    = { scroll: isBody ? document.documentElement.scrollTop || document.body.scrollTop : $element.scrollTop() }
    var outerDims = isBody ? { width: $(window).width(), height: $(window).height() } : null

    return $.extend({}, elRect, scroll, outerDims, elOffset)
  }

  Tooltip.prototype.getCalculatedOffset = function (placement, pos, actualWidth, actualHeight) {
    return placement == 'bottom' ? { top: pos.top + pos.height,   left: pos.left + pos.width / 2 - actualWidth / 2 } :
           placement == 'top'    ? { top: pos.top - actualHeight, left: pos.left + pos.width / 2 - actualWidth / 2 } :
           placement == 'left'   ? { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left - actualWidth } :
        /* placement == 'right' */ { top: pos.top + pos.height / 2 - actualHeight / 2, left: pos.left + pos.width }

  }

  Tooltip.prototype.getViewportAdjustedDelta = function (placement, pos, actualWidth, actualHeight) {
    var delta = { top: 0, left: 0 }
    if (!this.$viewport) return delta

    var viewportPadding = this.options.viewport && this.options.viewport.padding || 0
    var viewportDimensions = this.getPosition(this.$viewport)

    if (/right|left/.test(placement)) {
      var topEdgeOffset    = pos.top - viewportPadding - viewportDimensions.scroll
      var bottomEdgeOffset = pos.top + viewportPadding - viewportDimensions.scroll + actualHeight
      if (topEdgeOffset < viewportDimensions.top) { // top overflow
        delta.top = viewportDimensions.top - topEdgeOffset
      } else if (bottomEdgeOffset > viewportDimensions.top + viewportDimensions.height) { // bottom overflow
        delta.top = viewportDimensions.top + viewportDimensions.height - bottomEdgeOffset
      }
    } else {
      var leftEdgeOffset  = pos.left - viewportPadding
      var rightEdgeOffset = pos.left + viewportPadding + actualWidth
      if (leftEdgeOffset < viewportDimensions.left) { // left overflow
        delta.left = viewportDimensions.left - leftEdgeOffset
      } else if (rightEdgeOffset > viewportDimensions.right) { // right overflow
        delta.left = viewportDimensions.left + viewportDimensions.width - rightEdgeOffset
      }
    }

    return delta
  }

  Tooltip.prototype.getTitle = function () {
    var title
    var $e = this.$element
    var o  = this.options

    title = $e.attr('data-original-title')
      || (typeof o.title == 'function' ? o.title.call($e[0]) :  o.title)

    return title
  }

  Tooltip.prototype.getUID = function (prefix) {
    do prefix += ~~(Math.random() * 1000000)
    while (document.getElementById(prefix))
    return prefix
  }

  Tooltip.prototype.tip = function () {
    if (!this.$tip) {
      this.$tip = $(this.options.template)
      if (this.$tip.length != 1) {
        throw new Error(this.type + ' `template` option must consist of exactly 1 top-level element!')
      }
    }
    return this.$tip
  }

  Tooltip.prototype.arrow = function () {
    return (this.$arrow = this.$arrow || this.tip().find('.tooltip-arrow'))
  }

  Tooltip.prototype.enable = function () {
    this.enabled = true
  }

  Tooltip.prototype.disable = function () {
    this.enabled = false
  }

  Tooltip.prototype.toggleEnabled = function () {
    this.enabled = !this.enabled
  }

  Tooltip.prototype.toggle = function (e) {
    var self = this
    if (e) {
      self = $(e.currentTarget).data('bs.' + this.type)
      if (!self) {
        self = new this.constructor(e.currentTarget, this.getDelegateOptions())
        $(e.currentTarget).data('bs.' + this.type, self)
      }
    }

    if (e) {
      self.inState.click = !self.inState.click
      if (self.isInStateTrue()) self.enter(self)
      else self.leave(self)
    } else {
      self.tip().hasClass('in') ? self.leave(self) : self.enter(self)
    }
  }

  Tooltip.prototype.destroy = function () {
    var that = this
    clearTimeout(this.timeout)
    this.hide(function () {
      that.$element.off('.' + that.type).removeData('bs.' + that.type)
      if (that.$tip) {
        that.$tip.detach()
      }
      that.$tip = null
      that.$arrow = null
      that.$viewport = null
      that.$element = null
    })
  }

  Tooltip.prototype.sanitizeHtml = function (unsafeHtml) {
    return sanitizeHtml(unsafeHtml, this.options.whiteList, this.options.sanitizeFn)
  }

  // TOOLTIP PLUGIN DEFINITION
  // =========================

  function Plugin(option) {
    return this.each(function () {
      var $this   = $(this)
      var data    = $this.data('bs.tooltip')
      var options = typeof option == 'object' && option

      if (!data && /destroy|hide/.test(option)) return
      if (!data) $this.data('bs.tooltip', (data = new Tooltip(this, options)))
      if (typeof option == 'string') data[option]()
    })
  }

  var old = $.fn.tooltip

  $.fn.tooltip             = Plugin
  $.fn.tooltip.Constructor = Tooltip


  // TOOLTIP NO CONFLICT
  // ===================

  $.fn.tooltip.noConflict = function () {
    $.fn.tooltip = old
    return this
  }

}(jQuery);
;
(function () {

    $(document).on('focus mouseenter', '[data-toggle="popover"]', function () {
        this._title = this.title;
        this.title = '';
        var isPopoverVisible = $('.popover-content').length > 0;
        if ($(this)[0].id != "redirectLink" && isPopoverVisible) {
            $('#redirectLink').popover('hide');
            $('.click-popover').removeClass('visible-desktop');
            $('.click-popover').hide();
        }
    });
    

    $(document).on('mouseleave','[data-toggle="popover"]', function() {
        this.title = this._title;        
    });

    $.fn.tooltip.Constructor.prototype.fixTitle = function () {
        var $e = this.$element
        if ($e.attr('title') || typeof ($e.attr('data-original-title')) != 'string') {
            $e.attr('data-original-title', $e.attr('title') || '');
        }
    }
})();;
/* ========================================================================
 * Bootstrap: popover.js v3.4.1
 * https://getbootstrap.com/docs/3.4/javascript/#popovers
 * ========================================================================
 * Copyright 2011-2019 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
    'use strict';

    // POPOVER PUBLIC CLASS DEFINITION
    // ===============================

    var Popover = function (element, options) {
        this.init('popover', element, options)
    }

    if (!$.fn.tooltip) throw new Error('Popover requires tooltip.js')

    Popover.VERSION = '3.4.1'

    Popover.DEFAULTS = $.extend({}, $.fn.tooltip.Constructor.DEFAULTS, {
        placement: 'right',
        trigger: 'click',
        content: '',
        template: '<div class="popover" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
    })


    // NOTE: POPOVER EXTENDS tooltip.js
    // ================================

    Popover.prototype = $.extend({}, $.fn.tooltip.Constructor.prototype)

    Popover.prototype.constructor = Popover

    Popover.prototype.getDefaults = function () {
        return Popover.DEFAULTS
    }

    Popover.prototype.setContent = function () {
        var $tip = this.tip()
        var title = this.getTitle()
        var content = this.getContent()

        if (this.options.html) {
            var typeContent = typeof content

            if (this.options.sanitize) {
                title = this.sanitizeHtml(title)

                if (typeContent === 'string') {
                    content = this.sanitizeHtml(content)
                }
            }

            $tip.find('.popover-title').html(title)
            $tip.find('.popover-content').children().detach().end()[
                typeContent === 'string' ? 'html' : 'append'
            ](content)
        } else {
            $tip.find('.popover-title').text(title)
            $tip.find('.popover-content').children().detach().end().text(content)
        }

        $tip.removeClass('fade top bottom left right in')

        // IE8 doesn't accept hiding via the `:empty` pseudo selector, we have to do
        // this manually by checking the contents.
        if (!$tip.find('.popover-title').html()) $tip.find('.popover-title').hide()
    }

    Popover.prototype.hasContent = function () {
        return this.getTitle() || this.getContent()
    }

    Popover.prototype.getContent = function () {
        var $e = this.$element
        var o = this.options

        return $e.attr('data-content')
            || (typeof o.content == 'function' ?
                o.content.call($e[0]) :
                o.content)
    }

    Popover.prototype.arrow = function () {
        return (this.$arrow = this.$arrow || this.tip().find('.arrow'))
    }


    // POPOVER PLUGIN DEFINITION
    // =========================

    function Plugin(option) {
        return this.each(function () {
            var $this = $(this)
            var data = $this.data('bs.popover')
            var options = typeof option == 'object' && option

            if (!data && /destroy|hide/.test(option)) return
            if (!data) $this.data('bs.popover', (data = new Popover(this, options)))
            if (typeof option == 'string') data[option]()
        })
    }

    var old = $.fn.popover

    $.fn.popover = Plugin
    $.fn.popover.Constructor = Popover


    // POPOVER NO CONFLICT
    // ===================

    $.fn.popover.noConflict = function () {
        $.fn.popover = old
        return this
    }

}(jQuery);
;
/* ========================================================================
 * Bootstrap: alert.js v3.4.1
 * https://getbootstrap.com/docs/3.4/javascript/#alerts
 * ========================================================================
 * Copyright 2011-2019 Twitter, Inc.
 * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE)
 * ======================================================================== */


+function ($) {
  'use strict';

  // ALERT CLASS DEFINITION
  // ======================

  var dismiss = '[data-dismiss="alert"]'
  var Alert   = function (el) {
    $(el).on('click', dismiss, this.close)
  }

  Alert.VERSION = '3.4.1'

  Alert.TRANSITION_DURATION = 150

  Alert.prototype.close = function (e) {
    var $this    = $(this)
    var selector = $this.attr('data-target')

    if (!selector) {
      selector = $this.attr('href')
      selector = selector && selector.replace(/.*(?=#[^\s]*$)/, '') // strip for ie7
    }

    selector    = selector === '#' ? [] : selector
    var $parent = $(document).find(selector)

    if (e) e.preventDefault()

    if (!$parent.length) {
      $parent = $this.closest('.alert')
    }

    $parent.trigger(e = $.Event('close.bs.alert'))

    if (e.isDefaultPrevented()) return

    $parent.removeClass('in')

    function removeElement() {
      // detach from parent, fire event then clean up data
      $parent.detach().trigger('closed.bs.alert').remove()
    }

    $.support.transition && $parent.hasClass('fade') ?
      $parent
        .one('bsTransitionEnd', removeElement)
        .emulateTransitionEnd(Alert.TRANSITION_DURATION) :
      removeElement()
  }


  // ALERT PLUGIN DEFINITION
  // =======================

  function Plugin(option) {
    return this.each(function () {
      var $this = $(this)
      var data  = $this.data('bs.alert')

      if (!data) $this.data('bs.alert', (data = new Alert(this)))
      if (typeof option == 'string') data[option].call($this)
    })
  }

  var old = $.fn.alert

  $.fn.alert             = Plugin
  $.fn.alert.Constructor = Alert


  // ALERT NO CONFLICT
  // =================

  $.fn.alert.noConflict = function () {
    $.fn.alert = old
    return this
  }


  // ALERT DATA-API
  // ==============

  $(document).on('click.bs.alert.data-api', dismiss, Alert.prototype.close)

}(jQuery);
;
/* ============================================================
 * bootstrap-dropdown.js v2.3.1
 * http://twitter.github.com/bootstrap/javascript.html#dropdowns
 * ============================================================
 * Copyright 2012 Twitter, Inc.
 *
 * Licensed 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 ($) {

  "use strict"; // jshint ;_;


 /* DROPDOWN CLASS DEFINITION
  * ========================= */

  var toggle = '[data-toggle=dropdown]'
    , Dropdown = function (element) {
        var $el = $(element).on('click.dropdown.data-api', this.toggle)
        $('html').on('click.dropdown.data-api', function () {
          $el.parent().removeClass('open')
        })
      }

  Dropdown.prototype = {

    constructor: Dropdown

  , toggle: function (e) {
      var $this = $(this)
        , $parent
        , isActive

      if ($this.is('.disabled, :disabled')) return

      $parent = getParent($this)

      isActive = $parent.hasClass('open')

      clearMenus()

      if (!isActive) {
        $parent.toggleClass('open')
      }

      $this.trigger('focus');

      return false
    }

  , keydown: function (e) {
      var $this
        , $items
        , $active
        , $parent
        , isActive
        , index

      if (!/(38|40|27)/.test(e.keyCode)) return

      $this = $(this)

      e.preventDefault()
      e.stopPropagation()

      if ($this.is('.disabled, :disabled')) return

      $parent = getParent($this)

      isActive = $parent.hasClass('open')

      if (!isActive || (isActive && e.keyCode == 27)) {
        if (e.which == 27) $parent.find(toggle).trigger('focus')
        return $this.click()
      }

      $items = $('[role=menu] li:not(.divider):visible a', $parent)

      if (!$items.length) return

      index = $items.index($items.filter(':focus'))

      if (e.keyCode == 38 && index > 0) index--                                        // up
      if (e.keyCode == 40 && index < $items.length - 1) index++                        // down
      if (!~index) index = 0

      $items
        .eq(index)
        .trigger('focus')
    }

  }

  function clearMenus() {
    $(toggle).each(function () {
      getParent($(this)).removeClass('open')
    })
  }

  function getParent($this) {
    var selector = $this.attr('data-target')
      , $parent

    if (!selector) {
      selector = $this.attr('href')
      selector = selector && /#[A-Za-z]/.test(selector) && selector.replace(/.*(?=#[^\s]*$)/, '') //strip for ie7
    }

    $parent = selector && $(selector)

    if (!$parent || !$parent.length) $parent = $this.parent()

    return $parent
  }


  /* DROPDOWN PLUGIN DEFINITION
   * ========================== */

  var old = $.fn.dropdown

  $.fn.dropdown = function (option) {
    return this.each(function () {
      var $this = $(this)
        , data = $this.data('dropdown')
      if (!data) $this.data('dropdown', (data = new Dropdown(this)))
      if (typeof option == 'string') data[option].call($this)
    })
  }

  $.fn.dropdown.Constructor = Dropdown


 /* DROPDOWN NO CONFLICT
  * ==================== */

  $.fn.dropdown.noConflict = function () {
    $.fn.dropdown = old
    return this
  }


  /* APPLY TO STANDARD DROPDOWN ELEMENTS
   * =================================== */

  $(document)
    .on('click.dropdown.data-api', clearMenus)
    .on('click.dropdown.data-api', '.dropdown form', function (e) { e.stopPropagation() })
    .on('click.dropdown-menu', function (e) { e.stopPropagation() })
    .on('click.dropdown.data-api'  , toggle, Dropdown.prototype.toggle)
    .on('keydown.dropdown.data-api', toggle + ', [role=menu]' , Dropdown.prototype.keydown)

}(window.jQuery);
;
/*
    json2.js
    2013-05-26

    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, regexp: true */

/*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.

if (typeof JSON !== 'object') {
    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 () {

            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 () {
                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');
        };
    }
}());
;
/*
 * Toastr
 * Copyright 2012-2015
 * Authors: John Papa, Hans Fjällemark, and Tim Ferrell.
 * All Rights Reserved.
 * Use, reproduction, distribution, and modification of this code is subject to the terms and
 * conditions of the MIT license, available at http://www.opensource.org/licenses/mit-license.php
 *
 * ARIA Support: Greta Krafsig
 *
 * Project: https://github.com/CodeSeven/toastr
 */
/* global define */
(function (define) {
    define(['jquery'], function ($) {
        return (function () {
            var $container;
            var listener;
            var toastId = 0;
            var toastType = {
                error: 'error',
                info: 'info',
                success: 'success',
                warning: 'warning'
            };

            var toastr = {
                clear: clear,
                remove: remove,
                error: error,
                getContainer: getContainer,
                info: info,
                options: {},
                subscribe: subscribe,
                success: success,
                version: '2.1.4',
                warning: warning
            };

            var previousToast;

            return toastr;

            ////////////////

            function error(message, title, optionsOverride) {
                return notify({
                    type: toastType.error,
                    iconClass: getOptions().iconClasses.error,
                    message: message,
                    optionsOverride: optionsOverride,
                    title: title
                });
            }

            function getContainer(options, create) {
                if (!options) { options = getOptions(); }
                $container = $('#' + options.containerId);
                if ($container.length) {
                    return $container;
                }
                if (create) {
                    $container = createContainer(options);
                }
                return $container;
            }

            function info(message, title, optionsOverride) {
                return notify({
                    type: toastType.info,
                    iconClass: getOptions().iconClasses.info,
                    message: message,
                    optionsOverride: optionsOverride,
                    title: title
                });
            }

            function subscribe(callback) {
                listener = callback;
            }

            function success(message, title, optionsOverride) {
                return notify({
                    type: toastType.success,
                    iconClass: getOptions().iconClasses.success,
                    message: message,
                    optionsOverride: optionsOverride,
                    title: title
                });
            }

            function warning(message, title, optionsOverride) {
                return notify({
                    type: toastType.warning,
                    iconClass: getOptions().iconClasses.warning,
                    message: message,
                    optionsOverride: optionsOverride,
                    title: title
                });
            }

            function clear($toastElement, clearOptions) {
                var options = getOptions();
                if (!$container) { getContainer(options); }
                if (!clearToast($toastElement, options, clearOptions)) {
                    clearContainer(options);
                }
            }

            function remove($toastElement) {
                var options = getOptions();
                if (!$container) { getContainer(options); }
                if ($toastElement && $(':focus', $toastElement).length === 0) {
                    removeToast($toastElement);
                    return;
                }
                if ($container.children().length) {
                    $container.remove();
                }
            }

            // internal functions

            function clearContainer (options) {
                var toastsToClear = $container.children();
                for (var i = toastsToClear.length - 1; i >= 0; i--) {
                    clearToast($(toastsToClear[i]), options);
                }
            }

            function clearToast ($toastElement, options, clearOptions) {
                var force = clearOptions && clearOptions.force ? clearOptions.force : false;
                if ($toastElement && (force || $(':focus', $toastElement).length === 0)) {
                    $toastElement[options.hideMethod]({
                        duration: options.hideDuration,
                        easing: options.hideEasing,
                        complete: function () { removeToast($toastElement); }
                    });
                    return true;
                }
                return false;
            }

            function createContainer(options) {
                $container = $('<div/>')
                    .attr('id', options.containerId)
                    .addClass(options.positionClass);

                $container.appendTo($(options.target));
                return $container;
            }

            function getDefaults() {
                return {
                    tapToDismiss: true,
                    toastClass: 'toast',
                    containerId: 'toast-container',
                    debug: false,

                    showMethod: 'fadeIn', //fadeIn, slideDown, and show are built into jQuery
                    showDuration: 300,
                    showEasing: 'swing', //swing and linear are built into jQuery
                    onShown: undefined,
                    hideMethod: 'fadeOut',
                    hideDuration: 1000,
                    hideEasing: 'swing',
                    onHidden: undefined,
                    closeMethod: false,
                    closeDuration: false,
                    closeEasing: false,
                    closeOnHover: true,

                    extendedTimeOut: 1000,
                    iconClasses: {
                        error: 'toast-error',
                        info: 'toast-info',
                        success: 'toast-success',
                        warning: 'toast-warning'
                    },
                    iconClass: 'toast-info',
                    positionClass: 'toast-top-right',
                    timeOut: 5000, // Set timeOut and extendedTimeOut to 0 to make it sticky
                    titleClass: 'toast-title',
                    messageClass: 'toast-message',
                    escapeHtml: false,
                    target: 'body',
                    closeHtml: '<button type="button">&times;</button>',
                    closeClass: 'toast-close-button',
                    newestOnTop: true,
                    preventDuplicates: false,
                    progressBar: false,
                    progressClass: 'toast-progress',
                    rtl: false
                };
            }

            function publish(args) {
                if (!listener) { return; }
                listener(args);
            }

            function notify(map) {
                var options = getOptions();
                var iconClass = map.iconClass || options.iconClass;

                if (typeof (map.optionsOverride) !== 'undefined') {
                    options = $.extend(options, map.optionsOverride);
                    iconClass = map.optionsOverride.iconClass || iconClass;
                }

                if (shouldExit(options, map)) { return; }

                toastId++;

                $container = getContainer(options, true);

                var intervalId = null;
                var $toastElement = $('<div/>');
                var $titleElement = $('<div/>');
                var $messageElement = $('<div/>');
                var $progressElement = $('<div/>');
                var $closeElement = $(options.closeHtml);
                var progressBar = {
                    intervalId: null,
                    hideEta: null,
                    maxHideTime: null
                };
                var response = {
                    toastId: toastId,
                    state: 'visible',
                    startTime: new Date(),
                    options: options,
                    map: map
                };

                personalizeToast();

                displayToast();

                handleEvents();

                publish(response);

                if (options.debug && console) {
                    console.log(response);
                }

                return $toastElement;

                function escapeHtml(source) {
                    if (source == null) {
                        source = '';
                    }

                    return source
                        .replace(/&/g, '&amp;')
                        .replace(/"/g, '&quot;')
                        .replace(/'/g, '&#39;')
                        .replace(/</g, '&lt;')
                        .replace(/>/g, '&gt;');
                }

                function personalizeToast() {
                    setIcon();
                    setTitle();
                    setMessage();
                    setCloseButton();
                    setProgressBar();
                    setRTL();
                    setSequence();
                    setAria();
                }

                function setAria() {
                    var ariaValue = '';
                    switch (map.iconClass) {
                        case 'toast-success':
                        case 'toast-info':
                            ariaValue =  'polite';
                            break;
                        default:
                            ariaValue = 'assertive';
                    }
                    $toastElement.attr('aria-live', ariaValue);
                }

                function handleEvents() {
                    if (options.closeOnHover) {
                        $toastElement.hover(stickAround, delayedHideToast);
                    }

                    if (!options.onclick && options.tapToDismiss) {
                        $toastElement.click(hideToast);
                    }

                    if (options.closeButton && $closeElement) {
                        $closeElement.click(function (event) {
                            if (event.stopPropagation) {
                                event.stopPropagation();
                            } else if (event.cancelBubble !== undefined && event.cancelBubble !== true) {
                                event.cancelBubble = true;
                            }

                            if (options.onCloseClick) {
                                options.onCloseClick(event);
                            }

                            hideToast(true);
                        });
                    }

                    if (options.onclick) {
                        $toastElement.click(function (event) {
                            options.onclick(event);
                            hideToast();
                        });
                    }
                }

                function displayToast() {
                    $toastElement.hide();

                    $toastElement[options.showMethod](
                        {duration: options.showDuration, easing: options.showEasing, complete: options.onShown}
                    );

                    if (options.timeOut > 0) {
                        intervalId = setTimeout(hideToast, options.timeOut);
                        progressBar.maxHideTime = parseFloat(options.timeOut);
                        progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
                        if (options.progressBar) {
                            progressBar.intervalId = setInterval(updateProgress, 10);
                        }
                    }
                }

                function setIcon() {
                    if (map.iconClass) {
                        $toastElement.addClass(options.toastClass).addClass(iconClass);
                    }
                }

                function setSequence() {
                    if (options.newestOnTop) {
                        $container.prepend($toastElement);
                    } else {
                        $container.append($toastElement);
                    }
                }

                function setTitle() {
                    if (map.title) {
                        var suffix = map.title;
                        if (options.escapeHtml) {
                            suffix = escapeHtml(map.title);
                        }
                        $titleElement.append(suffix).addClass(options.titleClass);
                        $toastElement.append($titleElement);
                    }
                }

                function setMessage() {
                    if (map.message) {
                        var suffix = map.message;
                        if (options.escapeHtml) {
                            suffix = escapeHtml(map.message);
                        }
                        $messageElement.append(suffix).addClass(options.messageClass);
                        $toastElement.append($messageElement);
                    }
                }

                function setCloseButton() {
                    if (options.closeButton) {
                        $closeElement.addClass(options.closeClass).attr('role', 'button');
                        $toastElement.prepend($closeElement);
                    }
                }

                function setProgressBar() {
                    if (options.progressBar) {
                        $progressElement.addClass(options.progressClass);
                        $toastElement.prepend($progressElement);
                    }
                }

                function setRTL() {
                    if (options.rtl) {
                        $toastElement.addClass('rtl');
                    }
                }

                function shouldExit(options, map) {
                    if (options.preventDuplicates) {
                        if (map.message === previousToast) {
                            return true;
                        } else {
                            previousToast = map.message;
                        }
                    }
                    return false;
                }

                function hideToast(override) {
                    var method = override && options.closeMethod !== false ? options.closeMethod : options.hideMethod;
                    var duration = override && options.closeDuration !== false ?
                        options.closeDuration : options.hideDuration;
                    var easing = override && options.closeEasing !== false ? options.closeEasing : options.hideEasing;
                    if ($(':focus', $toastElement).length && !override) {
                        return;
                    }
                    clearTimeout(progressBar.intervalId);
                    return $toastElement[method]({
                        duration: duration,
                        easing: easing,
                        complete: function () {
                            removeToast($toastElement);
                            clearTimeout(intervalId);
                            if (options.onHidden && response.state !== 'hidden') {
                                options.onHidden();
                            }
                            response.state = 'hidden';
                            response.endTime = new Date();
                            publish(response);
                        }
                    });
                }

                function delayedHideToast() {
                    if (options.timeOut > 0 || options.extendedTimeOut > 0) {
                        intervalId = setTimeout(hideToast, options.extendedTimeOut);
                        progressBar.maxHideTime = parseFloat(options.extendedTimeOut);
                        progressBar.hideEta = new Date().getTime() + progressBar.maxHideTime;
                    }
                }

                function stickAround() {
                    clearTimeout(intervalId);
                    progressBar.hideEta = 0;
                    $toastElement.stop(true, true)[options.showMethod](
                        {duration: options.showDuration, easing: options.showEasing}
                    );
                }

                function updateProgress() {
                    var percentage = ((progressBar.hideEta - (new Date().getTime())) / progressBar.maxHideTime) * 100;
                    $progressElement.width(percentage + '%');
                }
            }

            function getOptions() {
                return $.extend({}, getDefaults(), toastr.options);
            }

            function removeToast($toastElement) {
                if (!$container) { $container = getContainer(); }
                if ($toastElement.is(':visible')) {
                    return;
                }
                $toastElement.remove();
                $toastElement = null;
                if ($container.children().length === 0) {
                    $container.remove();
                    previousToast = undefined;
                }
            }

        })();
    });
}(typeof define === 'function' && define.amd ? define : function (deps, factory) {
    if (typeof module !== 'undefined' && module.exports) { //Node
        module.exports = factory(require('jquery'));
    } else {
        window.toastr = factory(window.jQuery);
    }
}));
;
"use strict"
// Module export pattern from
// https://github.com/umdjs/umd/blob/master/returnExports.js
;(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        // AMD. Register as an anonymous module.
        define([], factory);
    } else if (typeof exports === 'object') {
        // Node. Does not work with strict CommonJS, but
        // only CommonJS-like environments that support module.exports,
        // like Node.
        module.exports = factory();
    } else {
        // Browser globals (root is window)
        root.store = factory();
  }
}(this, function () {
	
	// Store.js
	var store = {},
		win = window,
		doc = win.document,
		localStorageName = 'localStorage',
		scriptTag = 'script',
		storage

	store.disabled = false
	store.version = '1.3.17'
	store.set = function(key, value) {}
	store.get = function(key, defaultVal) {}
	store.has = function(key) { return store.get(key) !== undefined }
	store.remove = function(key) {}
	store.clear = function() {}
	store.transact = function(key, defaultVal, transactionFn) {
		if (transactionFn == null) {
			transactionFn = defaultVal
			defaultVal = null
		}
		if (defaultVal == null) {
			defaultVal = {}
		}
		var val = store.get(key, defaultVal)
		transactionFn(val)
		store.set(key, val)
	}
	store.getAll = function() {}
	store.forEach = function() {}

	store.serialize = function(value) {
		return JSON.stringify(value)
	}
	store.deserialize = function(value) {
		if (typeof value != 'string') { return undefined }
		try { return JSON.parse(value) }
		catch(e) { return value || undefined }
	}

	// Functions to encapsulate questionable FireFox 3.6.13 behavior
	// when about.config::dom.storage.enabled === false
	// See https://github.com/marcuswestin/store.js/issues#issue/13
	function isLocalStorageNameSupported() {
		try { return (localStorageName in win && win[localStorageName]) }
		catch(err) { return false }
	}

	if (isLocalStorageNameSupported()) {
		storage = win[localStorageName]
		store.set = function(key, val) {
			if (val === undefined) { return store.remove(key) }
			storage.setItem(key, store.serialize(val))
			return val
		}
		store.get = function(key, defaultVal) {
			var val = store.deserialize(storage.getItem(key))
			return (val === undefined ? defaultVal : val)
		}
		store.remove = function(key) { storage.removeItem(key) }
		store.clear = function() { storage.clear() }
		store.getAll = function() {
			var ret = {}
			store.forEach(function(key, val) {
				ret[key] = val
			})
			return ret
		}
		store.forEach = function(callback) {
			for (var i=0; i<storage.length; i++) {
				var key = storage.key(i)
				callback(key, store.get(key))
			}
		}
	} else if (doc.documentElement.addBehavior) {
		var storageOwner,
			storageContainer
		// Since #userData storage applies only to specific paths, we need to
		// somehow link our data to a specific path.  We choose /favicon.ico
		// as a pretty safe option, since all browsers already make a request to
		// this URL anyway and being a 404 will not hurt us here.  We wrap an
		// iframe pointing to the favicon in an ActiveXObject(htmlfile) object
		// (see: http://msdn.microsoft.com/en-us/library/aa752574(v=VS.85).aspx)
		// since the iframe access rules appear to allow direct access and
		// manipulation of the document element, even for a 404 page.  This
		// document can be used instead of the current document (which would
		// have been limited to the current path) to perform #userData storage.
		try {
			storageContainer = new ActiveXObject('htmlfile')
			storageContainer.open()
			storageContainer.write('<'+scriptTag+'>document.w=window</'+scriptTag+'><iframe src="/favicon.ico"></iframe>')
			storageContainer.close()
			storageOwner = storageContainer.w.frames[0].document
			storage = storageOwner.createElement('div')
		} catch(e) {
			// somehow ActiveXObject instantiation failed (perhaps some special
			// security settings or otherwse), fall back to per-path storage
			storage = doc.createElement('div')
			storageOwner = doc.body
		}
		var withIEStorage = function(storeFunction) {
			return function() {
				var args = Array.prototype.slice.call(arguments, 0)
				args.unshift(storage)
				// See http://msdn.microsoft.com/en-us/library/ms531081(v=VS.85).aspx
				// and http://msdn.microsoft.com/en-us/library/ms531424(v=VS.85).aspx
				storageOwner.appendChild(storage)
				storage.addBehavior('#default#userData')
				storage.load(localStorageName)
				var result = storeFunction.apply(store, args)
				storageOwner.removeChild(storage)
				return result
			}
		}

		// In IE7, keys cannot start with a digit or contain certain chars.
		// See https://github.com/marcuswestin/store.js/issues/40
		// See https://github.com/marcuswestin/store.js/issues/83
		var forbiddenCharsRegex = new RegExp("[!\"#$%&'()*+,/\\\\:;<=>?@[\\]^`{|}~]", "g")
		var ieKeyFix = function(key) {
			return key.replace(/^d/, '___$&').replace(forbiddenCharsRegex, '___')
		}
		store.set = withIEStorage(function(storage, key, val) {
			key = ieKeyFix(key)
			if (val === undefined) { return store.remove(key) }
			storage.setAttribute(key, store.serialize(val))
			storage.save(localStorageName)
			return val
		})
		store.get = withIEStorage(function(storage, key, defaultVal) {
			key = ieKeyFix(key)
			var val = store.deserialize(storage.getAttribute(key))
			return (val === undefined ? defaultVal : val)
		})
		store.remove = withIEStorage(function(storage, key) {
			key = ieKeyFix(key)
			storage.removeAttribute(key)
			storage.save(localStorageName)
		})
		store.clear = withIEStorage(function(storage) {
			var attributes = storage.XMLDocument.documentElement.attributes
			storage.load(localStorageName)
			while (attributes.length) {
				storage.removeAttribute(attributes[0].name)
			}
			storage.save(localStorageName)
		})
		store.getAll = function(storage) {
			var ret = {}
			store.forEach(function(key, val) {
				ret[key] = val
			})
			return ret
		}
		store.forEach = withIEStorage(function(storage, callback) {
			var attributes = storage.XMLDocument.documentElement.attributes
			for (var i=0, attr; attr=attributes[i]; ++i) {
				callback(attr.name, store.deserialize(storage.getAttribute(attr.name)))
			}
		})
	}

	try {
		var testKey = '__storejs__'
		store.set(testKey, testKey)
		if (store.get(testKey) != testKey) { store.disabled = true }
		store.remove(testKey)
	} catch(e) {
		store.disabled = true
	}
	store.enabled = !store.disabled
	
	return store
}));
;
/*!jQuery Knob*/
/**
 * Downward compatible, touchable dial
 *
 * Version: 1.2.0 (15/07/2012)
 * Requires: jQuery v1.7+
 *
 * Copyright (c) 2012 Anthony Terrien
 * Under MIT and GPL licenses:
 *  http://www.opensource.org/licenses/mit-license.php
 *  http://www.gnu.org/licenses/gpl.html
 *
 * Thanks to vor, eskimoblood, spiffistan, FabrizioC
 */
(function($) {

    /**
     * Kontrol library
     */
    "use strict";

    /**
     * Definition of globals and core
     */
    var k = {}, // kontrol
        max = Math.max,
        min = Math.min;

    k.c = {};
    k.c.d = $(document);
    k.c.t = function (e) {
        return e.originalEvent.touches.length - 1;
    };

    /**
     * Kontrol Object
     *
     * Definition of an abstract UI control
     *
     * Each concrete component must call this one.
     * <code>
     * k.o.call(this);
     * </code>
     */
    k.o = function () {
        var s = this;

        this.o = null; // array of options
        this.$ = null; // jQuery wrapped element
        this.i = null; // mixed HTMLInputElement or array of HTMLInputElement
        this.g = null; // 2D graphics context for 'pre-rendering'
        this.v = null; // value ; mixed array or integer
        this.cv = null; // change value ; not commited value
        this.x = 0; // canvas x position
        this.y = 0; // canvas y position
        this.$c = null; // jQuery canvas element
        this.c = null; // rendered canvas context
        this.t = 0; // touches index
        this.isInit = false;
        this.fgColor = null; // main color
        this.pColor = null; // previous color
        this.dH = null; // draw hook
        this.cH = null; // change hook
        this.eH = null; // cancel hook
        this.rH = null; // release hook

        this.run = function () {
            var cf = function (e, conf) {
                var k;
                for (k in conf) {
                    s.o[k] = conf[k];
                }
                s.init();
                s._configure()
                 ._draw();
            };

            if(this.$.data('kontroled')) return;
            this.$.data('kontroled', true);

            this.extend();
            this.o = $.extend(
                {
                    // Config
                    min : this.$.data('min') || 0,
                    max : this.$.data('max') || 100,
                    stopper : true,
                    readOnly : this.$.data('readonly'),

                    // UI
                    cursor : (this.$.data('cursor') === true && 30)
                                || this.$.data('cursor')
                                || 0,
                    thickness : this.$.data('thickness') || 0.35,
                    lineCap : this.$.data('linecap') || 'butt',
                    width : this.$.data('width') || 200,
                    height : this.$.data('height') || 200,
                    displayInput : this.$.data('displayinput') == null || this.$.data('displayinput'),
                    displayPrevious : this.$.data('displayprevious'),
                    fgColor : this.$.data('fgcolor') || '#87CEEB',
                    inputColor: this.$.data('inputcolor') || this.$.data('fgcolor') || '#87CEEB',
                    inline : false,
                    step : this.$.data('step') || 1,

                    // Hooks
                    draw : null, // function () {}
                    change : null, // function (value) {}
                    cancel : null, // function () {}
                    release : null // function (value) {}
                }, this.o
            );

            // routing value
            if(this.$.is('fieldset')) {

                // fieldset = array of integer
                this.v = {};
                this.i = this.$.find('input')
                this.i.each(function(k) {
                    var $this = $(this);
                    s.i[k] = $this;
                    s.v[k] = $this.val();

                    $this.bind(
                        'change'
                        , function () {
                            var val = {};
                            val[k] = $this.val();
                            s.val(val);
                        }
                    );
                });
                this.$.find('legend').remove();

            } else {
                // input = integer
                this.i = this.$;
                this.v = this.$.val();
                (this.v == '') && (this.v = this.o.min);

                this.$.bind(
                    'change'
                    , function () {
                        s.val(s._validate(s.$.val()));
                    }
                );
            }

            (!this.o.displayInput) && this.$.hide();

            this.$c = $('<canvas width="' +
                            this.o.width + 'px" height="' +
                            this.o.height + 'px"></canvas>');
            this.c = this.$c[0].getContext("2d");

            this.$
                .wrap($('<div style="' + (this.o.inline ? 'display:inline;' : '') +
                        'width:' + this.o.width + 'px;height:' +
                        this.o.height + 'px;"></div>'))
                .before(this.$c);

            if (this.v instanceof Object) {
                this.cv = {};
                this.copy(this.v, this.cv);
            } else {
                this.cv = this.v;
            }

            this.$
                .bind("configure", cf)
                .parent()
                .bind("configure", cf);

            this._listen()
                ._configure()
                ._xy()
                .init();

            this.isInit = true;

            this._draw();

            return this;
        };

        this._draw = function () {

            // canvas pre-rendering
            var d = true,
                c = document.createElement('canvas');

            c.width = s.o.width;
            c.height = s.o.height;
            s.g = c.getContext('2d');

            s.clear();

            s.dH
            && (d = s.dH());

            (d !== false) && s.draw();

            s.c.drawImage(c, 0, 0);
            c = null;
        };

        this._touch = function (e) {

            var touchMove = function (e) {

                var v = s.xy2val(
                            e.originalEvent.touches[s.t].pageX,
                            e.originalEvent.touches[s.t].pageY
                            );

                if (v == s.cv) return;

                if (
                    s.cH
                    && (s.cH(v) === false)
                ) return;


                s.change(s._validate(v));
                s._draw();
            };

            // get touches index
            this.t = k.c.t(e);

            // First touch
            touchMove(e);

            // Touch events listeners
            k.c.d
                .bind("touchmove.k", touchMove)
                .bind(
                    "touchend.k"
                    , function () {
                        k.c.d.unbind('touchmove.k touchend.k');

                        if (
                            s.rH
                            && (s.rH(s.cv) === false)
                        ) return;

                        s.val(s.cv);
                    }
                );

            return this;
        };

        this._mouse = function (e) {

            var mouseMove = function (e) {
                var v = s.xy2val(e.pageX, e.pageY);
                if (v == s.cv) return;

                if (
                    s.cH
                    && (s.cH(v) === false)
                ) return;

                s.change(s._validate(v));
                s._draw();
            };

            // First click
            mouseMove(e);

            // Mouse events listeners
            k.c.d
                .bind("mousemove.k", mouseMove)
                .bind(
                    // Escape key cancel current change
                    "keyup.k"
                    , function (e) {
                        if (e.keyCode === 27) {
                            k.c.d.unbind("mouseup.k mousemove.k keyup.k");

                            if (
                                s.eH
                                && (s.eH() === false)
                            ) return;

                            s.cancel();
                        }
                    }
                )
                .bind(
                    "mouseup.k"
                    , function (e) {
                        k.c.d.unbind('mousemove.k mouseup.k keyup.k');

                        if (
                            s.rH
                            && (s.rH(s.cv) === false)
                        ) return;

                        s.val(s.cv);
                    }
                );

            return this;
        };

        this._xy = function () {
            var o = this.$c.offset();
            this.x = o.left;
            this.y = o.top;
            return this;
        };

        this._listen = function () {

            if (!this.o.readOnly) {
                this.$c
                    .bind(
                        "mousedown"
                        , function (e) {
                            e.preventDefault();
                            s._xy()._mouse(e);
                         }
                    )
                    .bind(
                        "touchstart"
                        , function (e) {
                            e.preventDefault();
                            s._xy()._touch(e);
                         }
                    );
                this.listen();
            } else {
                this.$.attr('readonly', 'readonly');
            }

            return this;
        };

        this._configure = function () {

            // Hooks
            if (this.o.draw) this.dH = this.o.draw;
            if (this.o.change) this.cH = this.o.change;
            if (this.o.cancel) this.eH = this.o.cancel;
            if (this.o.release) this.rH = this.o.release;

            if (this.o.displayPrevious) {
                this.pColor = this.h2rgba(this.o.fgColor, "0.4");
                this.fgColor = this.h2rgba(this.o.fgColor, "0.6");
            } else {
                this.fgColor = this.o.fgColor;
            }

            return this;
        };

        this._clear = function () {
            this.$c[0].width = this.$c[0].width;
        };

        this._validate = function(v) {
            return (~~ (((v < 0) ? -0.5 : 0.5) + (v/this.o.step))) * this.o.step;
        };

        // Abstract methods
        this.listen = function () {}; // on start, one time
        this.extend = function () {}; // each time configure triggered
        this.init = function () {}; // each time configure triggered
        this.change = function (v) {}; // on change
        this.val = function (v) {}; // on release
        this.xy2val = function (x, y) {}; //
        this.draw = function () {}; // on change / on release
        this.clear = function () { this._clear(); };

        // Utils
        this.h2rgba = function (h, a) {
            var rgb;
            h = h.substring(1,7)
            rgb = [parseInt(h.substring(0,2),16)
                   ,parseInt(h.substring(2,4),16)
                   ,parseInt(h.substring(4,6),16)];
            return "rgba(" + rgb[0] + "," + rgb[1] + "," + rgb[2] + "," + a + ")";
        };

        this.copy = function (f, t) {
            for (var i in f) { t[i] = f[i]; }
        };
    };


    /**
     * k.Dial
     */
    k.Dial = function () {
        k.o.call(this);

        this.startAngle = null;
        this.xy = null;
        this.radius = null;
        this.lineWidth = null;
        this.cursorExt = null;
        this.w2 = null;
        this.PI2 = 2*Math.PI;

        this.extend = function () {
            this.o = $.extend(
                {
                    bgColor : this.$.data('bgcolor') || '#EEEEEE',
                    angleOffset : this.$.data('angleoffset') || 0,
                    angleArc : this.$.data('anglearc') || 360,
                    inline : true
                }, this.o
            );
        };

        this.val = function (v) {
            if (null != v) {
                this.cv = this.o.stopper ? max(min(v, this.o.max), this.o.min) : v;
                this.v = this.cv;
                this.$.val(this.v);
                this._draw();
            } else {
                return this.v;
            }
        };

        this.xy2val = function (x, y) {
            var a, ret;

            a = Math.atan2(
                        x - (this.x + this.w2)
                        , - (y - this.y - this.w2)
                    ) - this.angleOffset;

            if(this.angleArc != this.PI2 && (a < 0) && (a > -0.5)) {
                // if isset angleArc option, set to min if .5 under min
                a = 0;
            } else if (a < 0) {
                a += this.PI2;
            }

            ret = ~~ (0.5 + (a * (this.o.max - this.o.min) / this.angleArc))
                    + this.o.min;

            this.o.stopper
            && (ret = max(min(ret, this.o.max), this.o.min));

            return ret;
        };

        this.listen = function () {
            // bind MouseWheel
            var s = this,
                mw = function (e) {
                            e.preventDefault();
                            var ori = e.originalEvent
                                ,deltaX = ori.detail || ori.wheelDeltaX
                                ,deltaY = ori.detail || ori.wheelDeltaY
                                ,v = parseInt(s.$.val()) + (deltaX>0 || deltaY>0 ? s.o.step : deltaX<0 || deltaY<0 ? -s.o.step : 0);

                            if (
                                s.cH
                                && (s.cH(v) === false)
                            ) return;

                            s.val(v);
                        }
                , kval, to, m = 1, kv = {37:-s.o.step, 38:s.o.step, 39:s.o.step, 40:-s.o.step};

            this.$
                .bind(
                    "keydown"
                    ,function (e) {
                        var kc = e.keyCode;

                        // numpad support
                        if(kc >= 96 && kc <= 105) {
                            kc = e.keyCode = kc - 48;
                        }

                        kval = parseInt(String.fromCharCode(kc));

                        if (isNaN(kval)) {

                            (kc !== 13)         // enter
                            && (kc !== 8)       // bs
                            && (kc !== 9)       // tab
                            && (kc !== 189)     // -
                            && e.preventDefault();

                            // arrows
                            if ($.inArray(kc,[37,38,39,40]) > -1) {
                                e.preventDefault();

                                var v = parseInt(s.$.val()) + kv[kc] * m;

                                s.o.stopper
                                && (v = max(min(v, s.o.max), s.o.min));

                                s.change(v);
                                s._draw();

                                // long time keydown speed-up
                                to = window.setTimeout(
                                    function () { m*=2; }
                                    ,30
                                );
                            }
                        }
                    }
                )
                .bind(
                    "keyup"
                    ,function (e) {
                        if (isNaN(kval)) {
                            if (to) {
                                window.clearTimeout(to);
                                to = null;
                                m = 1;
                                s.val(s.$.val());
                            }
                        } else {
                            // kval postcond
                            (s.$.val() > s.o.max && s.$.val(s.o.max))
                            || (s.$.val() < s.o.min && s.$.val(s.o.min));
                        }

                    }
                );

            this.$c.bind("mousewheel DOMMouseScroll", mw);
            this.$.bind("mousewheel DOMMouseScroll", mw)
        };

        this.init = function () {

            if (
                this.v < this.o.min
                || this.v > this.o.max
            ) this.v = this.o.min;

            this.$.val(this.v);
            this.w2 = this.o.width / 2;
            this.cursorExt = this.o.cursor / 100;
            this.xy = this.w2;
            this.lineWidth = this.xy * this.o.thickness;
            this.lineCap = this.o.lineCap;
            this.radius = this.xy - this.lineWidth / 2;

            this.o.angleOffset
            && (this.o.angleOffset = isNaN(this.o.angleOffset) ? 0 : this.o.angleOffset);

            this.o.angleArc
            && (this.o.angleArc = isNaN(this.o.angleArc) ? this.PI2 : this.o.angleArc);

            // deg to rad
            this.angleOffset = this.o.angleOffset * Math.PI / 180;
            this.angleArc = this.o.angleArc * Math.PI / 180;

            // compute start and end angles
            this.startAngle = 1.5 * Math.PI + this.angleOffset;
            this.endAngle = 1.5 * Math.PI + this.angleOffset + this.angleArc;

            var s = max(
                            String(Math.abs(this.o.max)).length
                            , String(Math.abs(this.o.min)).length
                            , 2
                            ) + 2;

            this.o.displayInput
                && this.i.css({
                        'width' : ((this.o.width / 2 + 4) >> 0) + 'px'
                        ,'height' : ((this.o.width / 3) >> 0) + 'px'
                        ,'position' : 'absolute'
                        ,'vertical-align' : 'middle'
                        ,'margin-top' : ((this.o.width / 3) >> 0) + 'px'
                        ,'margin-left' : '-' + ((this.o.width * 3 / 4 + 2) >> 0) + 'px'
                        ,'border' : 0
                        ,'background' : 'none'
                        ,'font' : 'bold ' + ((this.o.width / s) >> 0) + 'px Arial'
                        ,'text-align' : 'center'
                        ,'color' : this.o.inputColor || this.o.fgColor
                        ,'padding' : '0px'
                        ,'-webkit-appearance': 'none'
                        })
                || this.i.css({
                        'width' : '0px'
                        ,'visibility' : 'hidden'
                        });
        };

        this.change = function (v) {
            this.cv = v;
            this.$.val(v);
        };

        this.angle = function (v) {
            return (v - this.o.min) * this.angleArc / (this.o.max - this.o.min);
        };

        this.draw = function () {

            var c = this.g,                 // context
                a = this.angle(this.cv)    // Angle
                , sat = this.startAngle     // Start angle
                , eat = sat + a             // End angle
                , sa, ea                    // Previous angles
                , r = 1;

            c.lineWidth = this.lineWidth;

            c.lineCap = this.lineCap;

            this.o.cursor
                && (sat = eat - this.cursorExt)
                && (eat = eat + this.cursorExt);

            c.beginPath();
                c.strokeStyle = this.o.bgColor;
                c.arc(this.xy, this.xy, this.radius, this.endAngle, this.startAngle, true);
            c.stroke();

            if (this.o.displayPrevious) {
                ea = this.startAngle + this.angle(this.v);
                sa = this.startAngle;
                this.o.cursor
                    && (sa = ea - this.cursorExt)
                    && (ea = ea + this.cursorExt);

                c.beginPath();
                    c.strokeStyle = this.pColor;
                    c.arc(this.xy, this.xy, this.radius, sa, ea, false);
                c.stroke();
                r = (this.cv == this.v);
            }

            c.beginPath();
                c.strokeStyle = r ? this.o.fgColor : this.fgColor ;
                c.arc(this.xy, this.xy, this.radius, sat, eat, false);
            c.stroke();
        };

        this.cancel = function () {
            this.val(this.v);
        };
    };

    $.fn.dial = $.fn.knob = function (o) {
        return this.each(
            function () {
                var d = new k.Dial();
                d.o = o;
                d.$ = $(this);
                d.run();
            }
        ).parent();
    };

})(jQuery);;
(function($) {
    "use strict";

    $.fn.htmlClean = function() {
        this.contents().filter(function() {
            if (this.nodeType != 3) {
                $(this).htmlClean();
                return false;
            } else {
                //var $that = $(this);
                //var textContent = $that.text();
                //textContent = $.trim(textContent);
                //$that.text(textContent);

                return !/\S/.test(this.nodeValue);
            }
        }).remove();
        return this;
    };

})(jQuery);;
// Chosen, a Select Box Enhancer for jQuery and Prototype
// by Patrick Filler for Harvest, http://getharvest.com
//
// Version 0.9.15
// Full source at https://github.com/harvesthq/chosen
// Copyright (c) 2011 Harvest http://getharvest.com

// MIT License, https://github.com/harvesthq/chosen/blob/master/LICENSE.md
// This file is generated by `cake build`, do not edit it by hand.
(function() {
  var SelectParser;

  SelectParser = (function() {
    function SelectParser() {
      this.options_index = 0;
      this.parsed = [];
    }

    SelectParser.prototype.add_node = function(child) {
      if (child.nodeName.toUpperCase() === "OPTGROUP") {
        return this.add_group(child);
      } else {
        return this.add_option(child);
      }
    };

    SelectParser.prototype.add_group = function(group) {
      var group_position, option, _i, _len, _ref, _results;
      group_position = this.parsed.length;
      this.parsed.push({
        array_index: group_position,
        group: true,
        label: group.label,
        children: 0,
        disabled: group.disabled
      });
      _ref = group.childNodes;
      _results = [];
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        option = _ref[_i];
        _results.push(this.add_option(option, group_position, group.disabled));
      }
      return _results;
    };

    SelectParser.prototype.add_option = function(option, group_position, group_disabled) {
      if (option.nodeName.toUpperCase() === "OPTION") {
        if (option.text !== "") {
          if (group_position != null) {
            this.parsed[group_position].children += 1;
          }
          this.parsed.push({
            array_index: this.parsed.length,
            options_index: this.options_index,
            value: option.value,
            text: option.text,
            html: option.innerHTML,
            selected: option.selected,
            disabled: group_disabled === true ? group_disabled : option.disabled,
            group_array_index: group_position,
            classes: option.className,
            style: option.style.cssText
          });
        } else {
          this.parsed.push({
            array_index: this.parsed.length,
            options_index: this.options_index,
            empty: true
          });
        }
        return this.options_index += 1;
      }
    };

    return SelectParser;

  })();

  SelectParser.select_to_array = function(select) {
    var child, parser, _i, _len, _ref;
    parser = new SelectParser();
    _ref = select.childNodes;
    for (_i = 0, _len = _ref.length; _i < _len; _i++) {
      child = _ref[_i];
      parser.add_node(child);
    }
    return parser.parsed;
  };

  this.SelectParser = SelectParser;

}).call(this);
/*
Chosen source: generate output using 'cake build'
Copyright (c) 2011 by Harvest
*/


(function() {
  var AbstractChosen, root;

  root = this;

  AbstractChosen = (function() {
    function AbstractChosen(form_field, options) {
      this.form_field = form_field;
      this.options = options != null ? options : {};
      if (!AbstractChosen.browser_is_supported()) {
        return;
      }
      this.is_multiple = this.form_field.multiple;
      this.set_default_text();
      this.set_default_values();
      this.setup();
      this.set_up_html();
      this.register_observers();
      this.finish_setup();
    }

    AbstractChosen.prototype.set_default_values = function() {
      var _this = this;
      this.click_test_action = function(evt) {
        return _this.test_active_click(evt);
      };
      this.activate_action = function(evt) {
        return _this.activate_field(evt);
      };
      this.active_field = false;
      this.mouse_on_container = false;
      this.results_showing = false;
      this.result_highlighted = null;
      this.result_single_selected = null;
      this.allow_single_deselect = (this.options.allow_single_deselect != null) && (this.form_field.options[0] != null) && this.form_field.options[0].text === "" ? this.options.allow_single_deselect : false;
      this.disable_search_threshold = this.options.disable_search_threshold || 0;
      this.disable_search = this.options.disable_search || false;
      this.enable_split_word_search = this.options.enable_split_word_search != null ? this.options.enable_split_word_search : true;
      this.search_contains = this.options.search_contains || false;
      this.single_backstroke_delete = this.options.single_backstroke_delete || false;
      this.max_selected_options = this.options.max_selected_options || Infinity;
      return this.inherit_select_classes = this.options.inherit_select_classes || false;
    };

    AbstractChosen.prototype.set_default_text = function() {
      if (this.form_field.getAttribute("data-placeholder")) {
        this.default_text = this.form_field.getAttribute("data-placeholder");
      } else if (this.is_multiple) {
        this.default_text = this.options.placeholder_text_multiple || this.options.placeholder_text || AbstractChosen.default_multiple_text;
      } else {
        this.default_text = this.options.placeholder_text_single || this.options.placeholder_text || AbstractChosen.default_single_text;
      }
      return this.results_none_found = this.form_field.getAttribute("data-no_results_text") || this.options.no_results_text || AbstractChosen.default_no_result_text;
    };

    AbstractChosen.prototype.mouse_enter = function() {
      return this.mouse_on_container = true;
    };

    AbstractChosen.prototype.mouse_leave = function() {
      return this.mouse_on_container = false;
    };

    AbstractChosen.prototype.input_focus = function(evt) {
      var _this = this;
      if (this.is_multiple) {
        if (!this.active_field) {
          return setTimeout((function() {
            return _this.container_mousedown();
          }), 50);
        }
      } else {
        if (!this.active_field) {
          return this.activate_field();
        }
      }
    };

    AbstractChosen.prototype.input_blur = function(evt) {
      var _this = this;
      if (!this.mouse_on_container) {
        this.active_field = false;
        return setTimeout((function() {
          return _this.blur_test();
        }), 100);
      }
    };

    AbstractChosen.prototype.result_add_option = function(option) {
      var classes, style;
      if (!option.disabled) {
        option.dom_id = this.container_id + "_o_" + option.array_index;
        classes = option.selected && this.is_multiple ? [] : ["active-result"];
        if (option.selected) {
          classes.push("result-selected");
        }
        if (option.group_array_index != null) {
          classes.push("group-option");
        }
        if (option.classes !== "") {
          classes.push(option.classes);
        }
        style = option.style.cssText !== "" ? " style=\"" + option.style + "\"" : "";
        return '<li id="' + option.dom_id + '" class="' + classes.join(' ') + '"' + style + '>' + option.html + '</li>';
      } else {
        return "";
      }
    };

    AbstractChosen.prototype.results_update_field = function() {
      this.set_default_text();
      if (!this.is_multiple) {
        this.results_reset_cleanup();
      }
      this.result_clear_highlight();
      this.result_single_selected = null;
      return this.results_build();
    };

    AbstractChosen.prototype.results_toggle = function() {
      if (this.results_showing) {
        return this.results_hide();
      } else {
        return this.results_show();
      }
    };

    AbstractChosen.prototype.results_search = function(evt) {
      if (this.results_showing) {
        return this.winnow_results();
      } else {
        return this.results_show();
      }
    };

    AbstractChosen.prototype.choices_count = function() {
      var option, _i, _len, _ref;
      if (this.selected_option_count != null) {
        return this.selected_option_count;
      }
      this.selected_option_count = 0;
      _ref = this.form_field.options;
      for (_i = 0, _len = _ref.length; _i < _len; _i++) {
        option = _ref[_i];
        if (option.selected) {
          this.selected_option_count += 1;
        }
      }
      return this.selected_option_count;
    };

    AbstractChosen.prototype.choices_click = function(evt) {
      evt.preventDefault();
      if (!this.results_showing) {
        return this.results_show();
      }
    };

    AbstractChosen.prototype.keyup_checker = function(evt) {
      var stroke, _ref;
      stroke = (_ref = evt.which) != null ? _ref : evt.keyCode;
      this.search_field_scale();
      switch (stroke) {
        case 8:
          if (this.is_multiple && this.backstroke_length < 1 && this.choices_count() > 0) {
            return this.keydown_backstroke();
          } else if (!this.pending_backstroke) {
            this.result_clear_highlight();
            return this.results_search();
          }
          break;
        case 13:
          evt.preventDefault();
          if (this.results_showing) {
            return this.result_select(evt);
          }
          break;
        case 27:
          if (this.results_showing) {
            this.results_hide();
          }
          return true;
        case 9:
        case 38:
        case 40:
        case 16:
        case 91:
        case 17:
          break;
        default:
          return this.results_search();
      }
    };

    AbstractChosen.prototype.generate_field_id = function() {
      var new_id;
      new_id = this.generate_random_id();
      this.form_field.id = new_id;
      return new_id;
    };

    AbstractChosen.prototype.generate_random_char = function() {
      var chars, newchar, rand;
      chars = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
      rand = Math.floor(Math.random() * chars.length);
      return newchar = chars.substring(rand, rand + 1);
    };

    AbstractChosen.prototype.container_width = function() {
      if (this.options.width != null) {
        return this.options.width;
      } else {
        return "" + this.form_field.offsetWidth + "px";
      }
    };

    AbstractChosen.browser_is_supported = function() {
      var _ref;
      if (window.navigator.appName === "Microsoft Internet Explorer") {
        return (null !== (_ref = document.documentMode) && _ref >= 8);
      }
      return true;
    };

    AbstractChosen.default_multiple_text = "Select Some Options";

    AbstractChosen.default_single_text = "Select an Option";

    AbstractChosen.default_no_result_text = "No results match";

    return AbstractChosen;

  })();

  root.AbstractChosen = AbstractChosen;

}).call(this);
/*
Chosen source: generate output using 'cake build'
Copyright (c) 2011 by Harvest
*/


/*
Please note - this is a customized version of May 2013 build.
Modifications need to be merged into current version.
All changes are marked with "Customization" comment
*/


(function() {
  var $, Chosen, root, _ref,
    __hasProp = {}.hasOwnProperty,
    __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; };

  root = this;

  $ = jQuery;

  $.fn.extend({
    chosen: function(options) {
      if (!AbstractChosen.browser_is_supported()) {
        return this;
      }
      return this.each(function(input_field) {
        var $this;
        $this = $(this);
        if (!$this.hasClass("chzn-done")) {
          return $this.data('chosen', new Chosen(this, options));
        }
      });
    }
  });

  Chosen = (function(_super) {
    __extends(Chosen, _super);

    function Chosen() {
      _ref = Chosen.__super__.constructor.apply(this, arguments);
      return _ref;
    }

    Chosen.prototype.setup = function() {
      this.form_field_jq = $(this.form_field);
      this.current_selectedIndex = this.form_field.selectedIndex;
      return this.is_rtl = this.form_field_jq.hasClass("chzn-rtl");
    };

    Chosen.prototype.finish_setup = function() {
      return this.form_field_jq.addClass("chzn-done");
    };

    Chosen.prototype.set_up_html = function() {
      var container_classes, container_props;
      this.container_id = this.form_field.id.length ? this.form_field.id.replace(/[^\w]/g, '_') : this.generate_field_id();
      this.container_id += "_chzn";
      container_classes = ["chzn-container"];
      container_classes.push("chzn-container-" + (this.is_multiple ? "multi" : "single"));
      if (this.inherit_select_classes && this.form_field.className) {
        container_classes.push(this.form_field.className);
      }
      if (this.is_rtl) {
        container_classes.push("chzn-rtl");
      }
      container_props = {
        'id': this.container_id,
        'class': container_classes.join(' '),
        'style': "width: " + (this.container_width()) + ";",
        'title': this.form_field.title
      };
      this.container = $("<div />", container_props);
      if (this.is_multiple) {
        this.container.html('<ul class="chzn-choices"><li class="search-field"><input type="text" value="' + this.default_text + '" class="default" autocomplete="off" style="width:25px;" /></li></ul><div class="chzn-drop"><ul class="chzn-results"></ul></div>');
      } else {
        this.container.html('<a href="javascript:void(0)" class="chzn-single chzn-default" aria-label="' + this.default_text + '"><span>' + this.default_text + '</span><div class="chzn-search"><input type="text" autocomplete="off" /></div><div><b></b></div></a><div class="chzn-drop"><ul class="chzn-results"></ul></div>');
      }
      this.form_field_jq.hide().after(this.container);
      this.dropdown = this.container.find('div.chzn-drop').first();
      this.search_field = this.container.find('input').first();
      this.search_results = this.container.find('ul.chzn-results').first();
      this.search_field_scale();
      this.search_no_results = this.container.find('li.no-results').first();
      if (this.is_multiple) {
        this.search_choices = this.container.find('ul.chzn-choices').first();
        this.search_container = this.container.find('li.search-field').first();
      } else {
        this.search_container = this.container.find('div.chzn-search').first();
        this.selected_item = this.container.find('.chzn-single').first();
      }
      this.results_build();
      this.set_tab_index_initial();
      this.set_label_behavior();
      return this.form_field_jq.trigger("liszt:ready", {
        chosen: this
      });
    };

    Chosen.prototype.register_observers = function() {
      var _this = this;
      this.container.mousedown(function(evt) {
        _this.container_mousedown(evt);
      });
      this.container.mouseup(function(evt) {
        _this.container_mouseup(evt);
      });
      this.container.mouseenter(function(evt) {
        _this.mouse_enter(evt);
      });
      this.container.mouseleave(function(evt) {
        _this.mouse_leave(evt);
      });
      this.search_results.mouseup(function(evt) {
        _this.search_results_mouseup(evt);
      });
      this.search_results.mouseover(function(evt) {
        _this.search_results_mouseover(evt);
      });
      this.search_results.mouseout(function(evt) {
        _this.search_results_mouseout(evt);
      });
      this.search_results.bind('mousewheel DOMMouseScroll', function(evt) {
        _this.search_results_mousewheel(evt);
      });
      this.form_field_jq.bind("liszt:updated", function(evt) {
        _this.results_update_field(evt);
      });
      this.form_field_jq.bind("liszt:activate", function(evt) {
        _this.activate_field(evt);
      });
      this.form_field_jq.bind("liszt:open", function(evt) {
        _this.container_mousedown(evt);
      });
      this.search_field.blur(function(evt) {
        _this.input_blur(evt);
      });
      this.search_field.keyup(function(evt) {
        _this.keyup_checker(evt);
      });
      this.search_field.keydown(function(evt) {
        _this.keydown_checker(evt);
      });
      this.search_field.focus(function(evt) {
        _this.input_focus(evt);
      });
      if (!this.is_multiple) {
        this.selected_item.focus(function(evt) {
          _this.selected_item_focus(evt);
        });
      }
      if (this.is_multiple) {
        return this.search_choices.click(function(evt) {
          _this.choices_click(evt);
        });
      } else {
        return this.container.click(function(evt) {
          evt.preventDefault();
        });
      }
    };

    Chosen.prototype.search_field_disabled = function() {
      this.is_disabled = this.form_field_jq[0].disabled;
      if (this.is_disabled) {
        this.container.addClass('chzn-disabled');
        this.search_field[0].disabled = true;
        if (!this.is_multiple) {
          this.selected_item.unbind("focus", this.activate_action);
        }
        return this.close_field();
      } else {
        this.container.removeClass('chzn-disabled');
        this.search_field[0].disabled = false;
        if (!this.is_multiple) {
          return this.selected_item.bind("focus", this.activate_action);
        }
      }
    };

    Chosen.prototype.container_mousedown = function(evt) {
      if (!this.is_disabled) {
        if (evt && evt.type === "mousedown" && !this.results_showing) {
          evt.preventDefault();
        }
        if (!((evt != null) && ($(evt.target)).hasClass("search-choice-close"))) {
          if (!this.active_field) {
            if (this.is_multiple) {
              this.search_field.val("");
            }
            $(document).click(this.click_test_action);
            this.results_show();
          } else if (!this.is_multiple && evt && (($(evt.target)[0] === this.selected_item[0]) || $(evt.target).parents("a.chzn-single").length)) {
            evt.preventDefault();
            this.results_toggle();
          }
          return this.activate_field();
        }
      }
    };

    Chosen.prototype.container_mouseup = function(evt) {
      if (evt.target.nodeName === "ABBR" && !this.is_disabled) {
        return this.results_reset(evt);
      }
    };

    Chosen.prototype.search_results_mousewheel = function(evt) {
      var delta, _ref1, _ref2;
      delta = -((_ref1 = evt.originalEvent) != null ? _ref1.wheelDelta : void 0) || ((_ref2 = evt.originialEvent) != null ? _ref2.detail : void 0);
      if (delta != null) {
        evt.preventDefault();
        if (evt.type === 'DOMMouseScroll') {
          delta = delta * 40;
        }
        return this.search_results.scrollTop(delta + this.search_results.scrollTop());
      }
    };

    Chosen.prototype.blur_test = function(evt) {
      if (!this.active_field && this.container.hasClass("chzn-container-active")) {
        return this.close_field();
      }
    };

    Chosen.prototype.close_field = function() {
      $(document).unbind("click", this.click_test_action);
      this.active_field = false;
      this.results_hide();
      this.container.removeClass("chzn-container-active");
      this.winnow_results_clear();
      this.clear_backstroke();
      this.show_search_field_default();
      return this.search_field_scale();
    };

    Chosen.prototype.activate_field = function() {
      this.container.addClass("chzn-container-active");
      this.active_field = true;
      this.search_field.val(this.search_field.val());
      return this.search_field.focus();
    };

    Chosen.prototype.test_active_click = function(evt) {
      if ($(evt.target).parents('#' + this.container_id).length) {
        return this.active_field = true;
      } else {
        return this.close_field();
      }
    };

    Chosen.prototype.results_build = function() {
      var content, data, _i, _len, _ref1;
      this.parsing = true;
      this.selected_option_count = null;
      this.results_data = root.SelectParser.select_to_array(this.form_field);
      if (this.is_multiple && this.choices_count() > 0) {
        this.search_choices.find("li.search-choice").remove();
      } else if (!this.is_multiple) {
        this.selected_item.addClass("chzn-default").find("span").text(this.default_text);
        if (this.disable_search || this.form_field.options.length <= this.disable_search_threshold) {
          this.container.addClass("chzn-container-single-nosearch");
        } else {
          this.container.removeClass("chzn-container-single-nosearch");
        }
      }
      content = '';
      _ref1 = this.results_data;
      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
        data = _ref1[_i];
        if (data.group) {
          content += this.result_add_group(data);
        } else if (!data.empty) {
          content += this.result_add_option(data);
          if (data.selected && this.is_multiple) {
            this.choice_build(data);
          } else if (data.selected && !this.is_multiple) {
            this.selected_item.removeClass("chzn-default").find("span").text(data.text);
            if (this.allow_single_deselect) {
              this.single_deselect_control_build();
            }
          }
        }
      }
      this.search_field_disabled();
      this.show_search_field_default();
      this.search_field_scale();
      this.search_results.html(content);
      return this.parsing = false;
    };

    Chosen.prototype.result_add_group = function(group) {
      if (!group.disabled) {
        group.dom_id = this.container_id + "_g_" + group.array_index;
        return '<li id="' + group.dom_id + '" class="group-result">' + $("<div />").text(group.label).html() + '</li>';
      } else {
        return "";
      }
    };

    Chosen.prototype.result_do_highlight = function(el) {
      var high_bottom, high_top, maxHeight, visible_bottom, visible_top;
      if (el.length) {
        this.result_clear_highlight();
        this.result_highlight = el;
        this.result_highlight.addClass("highlighted");
        maxHeight = parseInt(this.search_results.css("maxHeight"), 10);
        visible_top = this.search_results.scrollTop();
        visible_bottom = maxHeight + visible_top;
        high_top = this.result_highlight.position().top + this.search_results.scrollTop();
        high_bottom = high_top + this.result_highlight.outerHeight();
        if (high_bottom >= visible_bottom) {
          return this.search_results.scrollTop((high_bottom - maxHeight) > 0 ? high_bottom - maxHeight : 0);
        } else if (high_top < visible_top) {
          return this.search_results.scrollTop(high_top);
        }
      }
    };

    Chosen.prototype.result_clear_highlight = function() {
      if (this.result_highlight) {
        this.result_highlight.removeClass("highlighted");
      }
      return this.result_highlight = null;
    };

    Chosen.prototype.results_show = function() {
      if (this.result_single_selected != null) {
        this.result_do_highlight(this.result_single_selected);
      } else if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
        this.form_field_jq.trigger("liszt:maxselected", {
          chosen: this
        });
        return false;
      }
      this.container.addClass("chzn-with-drop");
      this.form_field_jq.trigger("liszt:showing_dropdown", {
        chosen: this
      });
      this.results_showing = true;
      this.search_field.focus();
      this.search_field.val(this.search_field.val());
      this.winnow_results();
      return this.set_tab_index_on_show();
    };

    Chosen.prototype.results_hide = function() {
      var callback, context;
      this.result_clear_highlight();
      this.container.removeClass("chzn-with-drop");
      this.form_field_jq.trigger("liszt:hiding_dropdown", {
        chosen: this
      });
      this.results_showing = false;
      context = this;
      callback = function() {
        return context.set_tab_index_on_hide();
      };
      return setTimeout(callback, 0);
    };

    Chosen.prototype.set_tab_index_initial = function(el) {
      var ti;
      if (this.form_field_jq.attr("tabindex")) {
        ti = this.form_field_jq.attr("tabindex");
        this.form_field_jq.attr("tabindex", -1);
        return this.selected_item.attr("tabindex", ti);
      }
    };

    Chosen.prototype.set_tab_index_on_show = function(el) {
      var ti;
      if (!this.is_multiple) {
        ti = this.selected_item.attr("tabindex");
        if (ti !== "-1") {
          this.selected_item.attr("tabindex", -1);
          return this.search_field.attr("tabindex", ti);
        }
      }
    };

    Chosen.prototype.set_tab_index_on_hide = function(el) {
      var ti;
      if (!this.is_multiple) {
        ti = this.search_field.attr("tabindex");
        if (ti !== "-1") {
          this.selected_item.attr("tabindex", ti);
          return this.search_field.attr("tabindex", -1);
        }
      }
    };

    Chosen.prototype.set_label_behavior = function() {
      var _this = this;
      this.form_field_label = this.form_field_jq.parents("label");
      if (!this.form_field_label.length && this.form_field.id.length) {
        this.form_field_label = $("label[for='" + this.form_field.id + "']");
      }
      if (this.form_field_label.length > 0) {
        return this.form_field_label.click(function(evt) {
          if (_this.is_multiple) {
            return _this.container_mousedown(evt);
          } else {
            return _this.activate_field();
          }
        });
      }
    };

    Chosen.prototype.show_search_field_default = function() {
      if (this.is_multiple && this.choices_count() < 1 && !this.active_field) {
        this.search_field.val(this.default_text);
        return this.search_field.addClass("default");
      } else {
        this.search_field.val("");
        return this.search_field.removeClass("default");
      }
    };

    Chosen.prototype.search_results_mouseup = function(evt) {
      var target;
      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
      if (target.length) {
        this.result_highlight = target;
        this.result_select(evt);
        return this.search_field.focus();
      }
    };

    Chosen.prototype.search_results_mouseover = function(evt) {
      var target;
      target = $(evt.target).hasClass("active-result") ? $(evt.target) : $(evt.target).parents(".active-result").first();
      if (target) {
        return this.result_do_highlight(target);
      }
    };

    Chosen.prototype.search_results_mouseout = function(evt) {
      if ($(evt.target).hasClass("active-result" || $(evt.target).parents('.active-result').first())) {
        return this.result_clear_highlight();
      }
    };

    Chosen.prototype.choice_build = function(item) {
      var choice, close_link,
        _this = this;
      choice = $('<li />', {
        "class": "search-choice"
      }).html("<span>" + item.html + "</span>");
      if (item.disabled) {
        choice.addClass('search-choice-disabled');
      } else {
        close_link = $('<a />', {
          href: '#',
          "class": 'search-choice-close',
          rel: item.array_index
        });
        close_link.click(function(evt) {
          return _this.choice_destroy_link_click(evt);
        });
        choice.append(close_link);
      }
      return this.search_container.before(choice);
    };

    Chosen.prototype.choice_destroy_link_click = function(evt) {
      evt.preventDefault();
      evt.stopPropagation();
      if (!this.is_disabled) {
        return this.choice_destroy($(evt.target));
      }
    };

    Chosen.prototype.choice_destroy = function(link) {
      if (this.result_deselect(link.attr("rel"))) {
        this.show_search_field_default();
        if (this.is_multiple && this.choices_count() > 0 && this.search_field.val().length < 1) {
          this.results_hide();
        }
        link.parents('li').first().remove();
        return this.search_field_scale();
      }
    };

    Chosen.prototype.results_reset = function() {
      this.form_field.options[0].selected = true;
      this.selected_option_count = null;
      this.selected_item.find("span").text(this.default_text);
      if (!this.is_multiple) {
        this.selected_item.addClass("chzn-default");
      }
      this.show_search_field_default();
      this.results_reset_cleanup();
      this.form_field_jq.trigger("change");
      if (this.active_field) {
        return this.results_hide();
      }
    };

    Chosen.prototype.results_reset_cleanup = function() {
      this.current_selectedIndex = this.form_field.selectedIndex;
      return this.selected_item.find("abbr").remove();
    };

    Chosen.prototype.result_select = function(evt) {
      var high, high_id, item, position;
      if (this.result_highlight) {
        high = this.result_highlight;
        high_id = high.attr("id");
        this.result_clear_highlight();
        if (this.is_multiple && this.max_selected_options <= this.choices_count()) {
          this.form_field_jq.trigger("liszt:maxselected", {
            chosen: this
          });
          return false;
        }
        if (this.is_multiple) {
          this.result_deactivate(high);
        } else {
          this.search_results.find(".result-selected").removeClass("result-selected");
          this.result_single_selected = high;
          this.selected_item.removeClass("chzn-default");
        }
        high.addClass("result-selected");
        position = high_id.substr(high_id.lastIndexOf("_") + 1);
        item = this.results_data[position];
        item.selected = true;
        this.form_field.options[item.options_index].selected = true;
        this.selected_option_count = null;
        if (this.is_multiple) {
          this.choice_build(item);
        } else {
          this.selected_item.find("span").first().text(item.text);
          if (this.allow_single_deselect) {
            this.single_deselect_control_build();
          }
        }
        if (!((evt.metaKey || evt.ctrlKey) && this.is_multiple)) {
          this.results_hide();
        }
        this.search_field.val("");
        if (this.is_multiple || this.form_field.selectedIndex !== this.current_selectedIndex) {
          this.form_field_jq.trigger("change", {
            'selected': this.form_field.options[item.options_index].value
          });
        }
        this.current_selectedIndex = this.form_field.selectedIndex;
        return this.search_field_scale();
      }
    };

    Chosen.prototype.result_activate = function(el) {
      return el.addClass("active-result");
    };

    Chosen.prototype.result_deactivate = function(el) {
      return el.removeClass("active-result");
    };

    Chosen.prototype.result_deselect = function(pos) {
      var result, result_data;
      result_data = this.results_data[pos];
      if (!this.form_field.options[result_data.options_index].disabled) {
        result_data.selected = false;
        this.form_field.options[result_data.options_index].selected = false;
        this.selected_option_count = null;
        result = $("#" + this.container_id + "_o_" + pos);
        result.removeClass("result-selected").addClass("active-result").show();
        this.result_clear_highlight();
        this.winnow_results();
        this.form_field_jq.trigger("change", {
          deselected: this.form_field.options[result_data.options_index].value
        });
        this.search_field_scale();
        return true;
      } else {
        return false;
      }
    };

    Chosen.prototype.single_deselect_control_build = function() {
      if (!this.allow_single_deselect) {
        return;
      }
      if (!this.selected_item.find("abbr").length) {
        this.selected_item.find("span").first().after("<abbr class=\"search-choice-close\"></abbr>");
      }
      return this.selected_item.addClass("chzn-single-with-deselect");
    };

    Chosen.prototype.winnow_results = function() {
      var found, option, part, parts, regex, regexAnchor, result, result_id, results, searchText, startpos, text, zregex, _i, _j, _len, _len1, _ref1;
      this.no_results_clear();
      results = 0;
      searchText = this.search_field.val() === this.default_text ? "" : $('<div/>').text($.trim(this.search_field.val())).html();
      regexAnchor = this.search_contains ? "" : "^";
      regex = new RegExp(regexAnchor + searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
      zregex = new RegExp(searchText.replace(/[-[\]{}()*+?.,\\^$|#\s]/g, "\\$&"), 'i');
      _ref1 = this.results_data;
      for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
        option = _ref1[_i];
        if (!option.disabled && !option.empty) {
          if (option.group) {
            $('#' + option.dom_id).css('display', 'none');
          } else if (!(this.is_multiple && option.selected)) {
            found = false;
            result_id = option.dom_id;
            result = $("#" + result_id);
            if (regex.test(option.html)) {
              found = true;
              results += 1;
            } else if (this.enable_split_word_search && (option.html.indexOf(" ") >= 0 || option.html.indexOf("[") === 0)) {
              parts = option.html.replace(/\[|\]/g, "").split(" ");
              if (parts.length) {
                for (_j = 0, _len1 = parts.length; _j < _len1; _j++) {
                  part = parts[_j];
                  if (regex.test(part)) {
                    found = true;
                    results += 1;
                  }
                }
              }
            }
            if (found) {
              if (searchText.length) {
                startpos = option.html.search(zregex);
                text = option.html.substr(0, startpos + searchText.length) + '</em>' + option.html.substr(startpos + searchText.length);
                text = text.substr(0, startpos) + '<em>' + text.substr(startpos);
              } else {
                text = option.html;
              }
              result.html(text);
              this.result_activate(result);
              if (option.group_array_index != null) {
                $("#" + this.results_data[option.group_array_index].dom_id).css('display', 'list-item');
              }
            } else {
              if (this.result_highlight && result_id === this.result_highlight.attr('id')) {
                this.result_clear_highlight();
              }
              this.result_deactivate(result);
            }
          }
        }
      }
      if (results < 1 && searchText.length) {
        return this.no_results(searchText);
      } else {
        return this.winnow_results_set_highlight();
      }
    };

    Chosen.prototype.winnow_results_clear = function() {
      var li, lis, _i, _len, _results;
      this.search_field.val("");
      lis = this.search_results.find("li");
      _results = [];
      for (_i = 0, _len = lis.length; _i < _len; _i++) {
        li = lis[_i];
        li = $(li);
        if (li.hasClass("group-result")) {
          _results.push(li.css('display', 'auto'));
        } else if (!this.is_multiple || !li.hasClass("result-selected")) {
          _results.push(this.result_activate(li));
        } else {
          _results.push(void 0);
        }
      }
      return _results;
    };

    Chosen.prototype.winnow_results_set_highlight = function() {
      var do_high, selected_results;
      if (!this.result_highlight) {
        selected_results = !this.is_multiple ? this.search_results.find(".result-selected.active-result") : [];
        do_high = selected_results.length ? selected_results.first() : this.search_results.find(".active-result").first();
        if (do_high != null) {
          return this.result_do_highlight(do_high);
        }
      }
    };

    Chosen.prototype.no_results = function(terms) {
      var no_results_html;
      no_results_html = $('<li class="no-results">' + this.results_none_found + ' "<span></span>"</li>');
      no_results_html.find("span").first().html(terms);
      return this.search_results.append(no_results_html);
    };

    Chosen.prototype.no_results_clear = function() {
      return this.search_results.find(".no-results").remove();
    };

    Chosen.prototype.keydown_arrow = function() {
      var first_active, next_sib;
      if (!this.result_highlight) {
        first_active = this.search_results.find("li.active-result").first();
        if (first_active) {
          this.result_do_highlight($(first_active));
        }
      } else if (this.results_showing) {
        next_sib = this.result_highlight.nextAll("li.active-result").first();
        if (next_sib) {
          this.result_do_highlight(next_sib);
        }
      }
      if (!this.results_showing) {
        return this.results_show();
      }
    };

    Chosen.prototype.keyup_arrow = function() {
      var prev_sibs;
      if (!this.results_showing && !this.is_multiple) {
        return this.results_show();
      } else if (this.result_highlight) {
        prev_sibs = this.result_highlight.prevAll("li.active-result");
        if (prev_sibs.length) {
          return this.result_do_highlight(prev_sibs.first());
        } else {
          if (this.choices_count() > 0) {
            this.results_hide();
          }
          return this.result_clear_highlight();
        }
      }
    };

    Chosen.prototype.keydown_backstroke = function() {
      var next_available_destroy;
      if (this.pending_backstroke) {
        this.choice_destroy(this.pending_backstroke.find("a").first());
        return this.clear_backstroke();
      } else {
        next_available_destroy = this.search_container.siblings("li.search-choice").last();
        if (next_available_destroy.length && !next_available_destroy.hasClass("search-choice-disabled")) {
          this.pending_backstroke = next_available_destroy;
          if (this.single_backstroke_delete) {
            return this.keydown_backstroke();
          } else {
            return this.pending_backstroke.addClass("search-choice-focus");
          }
        }
      }
    };

    Chosen.prototype.clear_backstroke = function() {
      if (this.pending_backstroke) {
        this.pending_backstroke.removeClass("search-choice-focus");
      }
      return this.pending_backstroke = null;
    };

    Chosen.prototype.keydown_checker = function(evt) {
      var stroke, _ref1;
      stroke = (_ref1 = evt.which) != null ? _ref1 : evt.keyCode;
      this.search_field_scale();
      if (stroke !== 8 && this.pending_backstroke) {
        this.clear_backstroke();
      }
      switch (stroke) {
        case 8:
          this.backstroke_length = this.search_field.val().length;
          break;
        case 9:
          if (this.results_showing && !this.is_multiple) {
            this.result_select(evt);
          }
          this.mouse_on_container = false;
          break;
        case 13:
          evt.preventDefault();
          break;
        case 38:
          evt.preventDefault();
          this.keyup_arrow();
          break;
        case 40:
          this.keydown_arrow();
          break;
      }
    };

    Chosen.prototype.search_field_scale = function() {
      var div, h, style, style_block, styles, w, _i, _len;
      if (this.is_multiple) {
        h = 0;
        w = 0;
        style_block = "position:absolute; left: -1000px; top: -1000px; display:none;";
        styles = ['font-size', 'font-style', 'font-weight', 'font-family', 'line-height', 'text-transform', 'letter-spacing'];
        for (_i = 0, _len = styles.length; _i < _len; _i++) {
          style = styles[_i];
          style_block += style + ":" + this.search_field.css(style) + ";";
        }
        div = $('<div />', {
          'style': style_block
        });
        div.text(this.search_field.val());
        $('body').append(div);
        w = div.width() + 25;
        div.remove();
        if (!this.f_width) {
          this.f_width = this.container.outerWidth();
        }
        if (w > this.f_width - 10) {
          w = this.f_width - 10;
        }
        return this.search_field.css({
          'width': w + 'px'
        });
      }
    };

    Chosen.prototype.selected_item_focus = function(evt) {
      return this.results_show();
    };

    Chosen.prototype.generate_random_id = function() {
      var string;
      string = "sel" + this.generate_random_char() + this.generate_random_char() + this.generate_random_char();
      while ($("#" + string).length > 0) {
        string += this.generate_random_char();
      }
      return string;
    };

    return Chosen;

  })(AbstractChosen);

  root.Chosen = Chosen;

}).call(this);
;
(function (window, $, undefined) {

    // WAVE reports empty links as errors - add hidden span to prevent this behavior
    $(document).ready(function () {
        var addThisTimer = setInterval(function () {
            if (window.addthis && window.addthis.addEventListener) {
                clearInterval(addThisTimer);
                $('.share-button-group svg')
                    .each(function() {
                        $(this).attr('focusable', 'false');
                    });
            }
        }, 100);
    });

})(window, jQuery);;
/* MediaMatch v.2.0.2 - Testing css media queries in Javascript. Authors & copyright (c) 2013: WebLinc, David Knight. */

window.matchMedia || (window.matchMedia = function (win) {
    'use strict';

    // Internal globals
    var _doc        = win.document,
        _viewport   = _doc.documentElement,
        _queries    = [],
        _queryID    = 0,
        _type       = '',
        _features   = {},
                    // only screen
                    // only screen and
                    // not screen
                    // not screen and
                    // screen
                    // screen and
        _typeExpr   = /\s*(only|not)?\s*(screen|print|[a-z\-]+)\s*(and)?\s*/i,
                    // (-vendor-min-width: 300px)
                    // (min-width: 300px)
                    // (width: 300px)
                    // (width)
                    // (orientation: portrait|landscape)
        _mediaExpr  = /^\s*\(\s*(-[a-z]+-)?(min-|max-)?([a-z\-]+)\s*(:?\s*([0-9]+(\.[0-9]+)?|portrait|landscape)(px|em|dppx|dpcm|rem|%|in|cm|mm|ex|pt|pc|\/([0-9]+(\.[0-9]+)?))?)?\s*\)\s*$/,
        _timer      = 0,

        // Helper methods

        /*
            _matches
         */
        _matches = function (media) {
            // screen and (min-width: 400px), screen and (max-width: 500px)
            var mql         = (media.indexOf(',') !== -1 && media.split(',')) || [media],
                mqIndex     = mql.length - 1,
                mqLength    = mqIndex,
                mq          = null,

                // not screen, screen
                negateType      = null,
                negateTypeFound = '',
                negateTypeIndex = 0,
                negate          = false,
                type            = '',

                // (min-width: 400px), (min-width)
                exprListStr = '',
                exprList    = null,
                exprIndex   = 0,
                exprLength  = 0,
                expr        = null,

                prefix      = '',
                length      = '',
                unit        = '',
                value       = '',
                feature     = '',

                match       = false;

            if (media === '') {
                return true;
            }

            do {
                mq          = mql[mqLength - mqIndex];
                negate      = false;
                negateType  = mq.match(_typeExpr);

                if (negateType) {
                    negateTypeFound = negateType[0];
                    negateTypeIndex = negateType.index;
                }

                if (!negateType || ((mq.substring(0, negateTypeIndex).indexOf('(') === -1) && (negateTypeIndex || (!negateType[3] && negateTypeFound !== negateType.input)))) {
                    match = false;
                    continue;
                }

                exprListStr = mq;

                negate = negateType[1] === 'not';

                if (!negateTypeIndex) {
                    type        =  negateType[2];
                    exprListStr = mq.substring(negateTypeFound.length);
                }

                // Test media type
                // Test type against this device or if 'all' or empty ''
                match       = type === _type || type === 'all' || type === '';

                exprList    = (exprListStr.indexOf(' and ') !== -1 && exprListStr.split(' and ')) || [exprListStr];
                exprIndex   = exprList.length - 1;
                exprLength  = exprIndex;

                if (match && exprIndex >= 0 && exprListStr !== '') {
                    do {
                        expr = exprList[exprIndex].match(_mediaExpr);

                        if (!expr || !_features[expr[3]]) {
                            match = false;
                            break;
                        }

                        prefix  = expr[2];
                        length  = expr[5];
                        value   = length;
                        unit    = expr[7];
                        feature = _features[expr[3]];

                        // Convert unit types
                        if (unit) {
                            if (unit === 'px') {
                                // If unit is px
                                value = Number(length);
                            } else if (unit === 'em' || unit === 'rem') {
                                // Convert relative length unit to pixels
                                // Assumed base font size is 16px
                                value = 16 * length;
                            } else if (expr[8]) {
                                // Convert aspect ratio to decimal
                                value = (length / expr[8]).toFixed(2);
                            } else if (unit === 'dppx') {
                                // Convert resolution dppx unit to pixels
                                value = length * 96;
                            } else if (unit === 'dpcm') {
                                // Convert resolution dpcm unit to pixels
                                value = length * 0.3937;
                            } else {
                                // default
                                value = Number(length);
                            }
                        }

                        // Test for prefix min or max
                        // Test value against feature
                        if (prefix === 'min-' && value) {
                            match = feature >= value;
                        } else if (prefix === 'max-' && value) {
                            match = feature <= value;
                        } else if (value) {
                            match = feature === value;
                        } else {
                            match = !!feature;
                        }

                        // If 'match' is false, break loop
                        // Continue main loop through query list
                        if (!match) {
                            break;
                        }
                    } while (exprIndex--);
                }

                // If match is true, break loop
                // Once matched, no need to check other queries
                if (match) {
                    break;
                }
            } while (mqIndex--);

            return negate ? !match : match;
        },

        /*
            _setFeature
         */
        _setFeature = function () {
            // Sets properties of '_features' that change on resize and/or orientation.
            var w   = win.innerWidth || _viewport.clientWidth,
                h   = win.innerHeight || _viewport.clientHeight,
                dw  = win.screen.width,
                dh  = win.screen.height,
                c   = win.screen.colorDepth,
                x   = win.devicePixelRatio;

            _features.width                     = w;
            _features.height                    = h;
            _features['aspect-ratio']           = (w / h).toFixed(2);
            _features['device-width']           = dw;
            _features['device-height']          = dh;
            _features['device-aspect-ratio']    = (dw / dh).toFixed(2);
            _features.color                     = c;
            _features['color-index']            = Math.pow(2, c);
            _features.orientation               = (h >= w ? 'portrait' : 'landscape');
            _features.resolution                = (x && x * 96) || win.screen.deviceXDPI || 96;
            _features['device-pixel-ratio']     = x || 1;
        },

        /*
            _watch
         */
        _watch = function () {
            clearTimeout(_timer);

            _timer = setTimeout(function () {
                var query   = null,
                    qIndex  = _queryID - 1,
                    qLength = qIndex,
                    match   = false;

                if (qIndex >= 0) {
                    _setFeature();

                    do {
                        query = _queries[qLength - qIndex];

                        if (query) {
                            match = _matches(query.mql.media);

                            if ((match && !query.mql.matches) || (!match && query.mql.matches)) {
                                query.mql.matches = match;

                                if (query.listeners) {
                                    for (var i = 0, il = query.listeners.length; i < il; i++) {
                                        if (query.listeners[i]) {
                                            query.listeners[i].call(win, query.mql);
                                        }
                                    }
                                }
                            }
                        }
                    } while(qIndex--);
                }

                
            }, 10);
        },

        /*
            _init
         */
        _init = function () {
            var head        = _doc.getElementsByTagName('head')[0],
                style       = _doc.createElement('style'),
                info        = null,
                typeList    = ['screen', 'print', 'speech', 'projection', 'handheld', 'tv', 'braille', 'embossed', 'tty'],
                typeIndex   = 0,
                typeLength  = typeList.length,
                cssText     = '#mediamatchjs { position: relative; z-index: 0; }',
                eventPrefix = '',
                addEvent    = win.addEventListener || (eventPrefix = 'on') && win.attachEvent;

            style.type  = 'text/css';
            style.id    = 'mediamatchjs';

            head.appendChild(style);

            // Must be placed after style is inserted into the DOM for IE
            info = (win.getComputedStyle && win.getComputedStyle(style)) || style.currentStyle;

            // Create media blocks to test for media type
            for ( ; typeIndex < typeLength; typeIndex++) {
                cssText += '@media ' + typeList[typeIndex] + ' { #mediamatchjs { position: relative; z-index: ' + typeIndex + ' } }';
            }

            // Add rules to style element
            if (style.styleSheet) {
                style.styleSheet.cssText = cssText;
            } else {
                style.textContent = cssText;
            }

            // Get media type
            _type = typeList[(info.zIndex * 1) || 0];

            head.removeChild(style);

            _setFeature();

            // Set up listeners
            addEvent(eventPrefix + 'resize', _watch);
            addEvent(eventPrefix + 'orientationchange', _watch);
        };

    _init();

    /*
        A list of parsed media queries, ex. screen and (max-width: 400px), screen and (max-width: 800px)
    */
    return function (media) {
        var id  = _queryID,
            mql = {
                matches         : false,
                media           : media,
                addListener     : function addListener(listener) {
                    _queries[id].listeners || (_queries[id].listeners = []);
                    listener && _queries[id].listeners.push(listener);
                },
                removeListener  : function removeListener(listener) {
                    var query   = _queries[id],
                        i       = 0,
                        il      = 0;

                    if (!query) {
                        return;
                    }

                    il = query.listeners.length;

                    for ( ; i < il; i++) {
                        if (query.listeners[i] === listener) {
                            query.listeners.splice(i, 1);
                        }
                    }
                }
            };

        if (media === '') {
            mql.matches = true;
            return mql;
        }

        mql.matches = _matches(media);

        _queryID = _queries.push({
            mql         : mql,
            listeners   : null
        });

        return mql;
    };
}(window));;
// enquire.js v2.0.2 - Awesome Media Queries in JavaScript
// Copyright (c) 2013 Nick Williams - http://wicky.nillia.ms/enquire.js
// License: MIT (http://www.opensource.org/licenses/mit-license.php)

;(function(global) {

'use strict';

var matchMedia = global.matchMedia;

    /*jshint -W098 */
    /**
     * Helper function for iterating over a collection
     *
     * @param collection
     * @param fn
     */
    function each(collection, fn) {
        var i      = 0,
            length = collection.length,
            cont;

        for(i; i < length; i++) {
            cont = fn(collection[i], i);
            if(cont === false) {
                break; //allow early exit
            }
        }
    }

    /**
     * Helper function for determining whether target object is an array
     *
     * @param target the object under test
     * @return {Boolean} true if array, false otherwise
     */
    function isArray(target) {
        return Object.prototype.toString.apply(target) === '[object Array]';
    }

    /**
     * Helper function for determining whether target object is a function
     *
     * @param target the object under test
     * @return {Boolean} true if function, false otherwise
     */
    function isFunction(target) {
        return typeof target === 'function';
    }

/**
 * Delegate to handle a media query being matched and unmatched.
 *
 * @param {object} options
 * @param {function} options.match callback for when the media query is matched
 * @param {function} [options.unmatch] callback for when the media query is unmatched
 * @param {function} [options.setup] one-time callback triggered the first time a query is matched
 * @param {boolean} [options.deferSetup=false] should the setup callback be run immediately, rather than first time query is matched?
 * @constructor
 */
function QueryHandler(options) {
    this.options = options;
    !options.deferSetup && this.setup();
}
QueryHandler.prototype = {

    /**
     * coordinates setup of the handler
     *
     * @function
     */
    setup : function() {
        if(this.options.setup) {
            this.options.setup();
        }
        this.initialised = true;
    },

    /**
     * coordinates setup and triggering of the handler
     *
     * @function
     */
    on : function() {
        !this.initialised && this.setup();
        this.options.match && this.options.match();
    },

    /**
     * coordinates the unmatch event for the handler
     *
     * @function
     */
    off : function() {
        this.options.unmatch && this.options.unmatch();
    },

    /**
     * called when a handler is to be destroyed.
     * delegates to the destroy or unmatch callbacks, depending on availability.
     *
     * @function
     */
    destroy : function() {
        this.options.destroy ? this.options.destroy() : this.off();
    },

    /**
     * determines equality by reference.
     * if object is supplied compare options, if function, compare match callback
     *
     * @function
     * @param {object || function} [target] the target for comparison
     */
    equals : function(target) {
        return this.options === target || this.options.match === target;
    }

};
/**
 * Represents a single media query, manages it's state and registered handlers for this query
 *
 * @constructor
 * @param {string} query the media query string
 * @param {boolean} [isUnconditional=false] whether the media query should run regardless of whether the conditions are met. Primarily for helping older browsers deal with mobile-first design
 */
function MediaQuery(query, isUnconditional) {
    this.query = query;
    this.isUnconditional = isUnconditional;
    this.handlers = [];
    this.mql = matchMedia(query);

    var self = this;
    this.listener = function(mql) {
        self.mql = mql;
        self.assess();
    };
    this.mql.addListener(this.listener);
}
MediaQuery.prototype = {

    /**
     * add a handler for this query, triggering if already active
     *
     * @param {object} handler
     * @param {function} handler.match callback for when query is activated
     * @param {function} [handler.unmatch] callback for when query is deactivated
     * @param {function} [handler.setup] callback for immediate execution when a query handler is registered
     * @param {boolean} [handler.deferSetup=false] should the setup callback be deferred until the first time the handler is matched?
     */
    addHandler : function(handler) {
        var qh = new QueryHandler(handler);
        this.handlers.push(qh);

        this.matches() && qh.on();
    },

    /**
     * removes the given handler from the collection, and calls it's destroy methods
     * 
     * @param {object || function} handler the handler to remove
     */
    removeHandler : function(handler) {
        var handlers = this.handlers;
        each(handlers, function(h, i) {
            if(h.equals(handler)) {
                h.destroy();
                return !handlers.splice(i,1); //remove from array and exit each early
            }
        });
    },

    /**
     * Determine whether the media query should be considered a match
     * 
     * @return {Boolean} true if media query can be considered a match, false otherwise
     */
    matches : function() {
        return this.mql.matches || this.isUnconditional;
    },

    /**
     * Clears all handlers and unbinds events
     */
    clear : function() {
        each(this.handlers, function(handler) {
            handler.destroy();
        });
        this.mql.removeListener(this.listener);
        this.handlers.length = 0; //clear array
    },

    /*
     * Assesses the query, turning on all handlers if it matches, turning them off if it doesn't match
     */
    assess : function() {
        var action = this.matches() ? 'on' : 'off';

        each(this.handlers, function(handler) {
            handler[action]();
        });
    }
};
/**
 * Allows for registration of query handlers.
 * Manages the query handler's state and is responsible for wiring up browser events
 *
 * @constructor
 */
function MediaQueryDispatch () {
    if(!matchMedia) {
        throw new Error('matchMedia not present, legacy browsers require a polyfill');
    }

    this.queries = {};
    this.browserIsIncapable = !matchMedia('only all').matches;
}

MediaQueryDispatch.prototype = {

    /**
     * Registers a handler for the given media query
     *
     * @param {string} q the media query
     * @param {object || Array || Function} options either a single query handler object, a function, or an array of query handlers
     * @param {function} options.match fired when query matched
     * @param {function} [options.unmatch] fired when a query is no longer matched
     * @param {function} [options.setup] fired when handler first triggered
     * @param {boolean} [options.deferSetup=false] whether setup should be run immediately or deferred until query is first matched
     * @param {boolean} [shouldDegrade=false] whether this particular media query should always run on incapable browsers
     */
    register : function(q, options, shouldDegrade) {
        var queries         = this.queries,
            isUnconditional = shouldDegrade && this.browserIsIncapable;

        if(!queries[q]) {
            queries[q] = new MediaQuery(q, isUnconditional);
        }

        //normalise to object in an array
        if(isFunction(options)) {
            options = { match : options };
        }
        if(!isArray(options)) {
            options = [options];
        }
        each(options, function(handler) {
            queries[q].addHandler(handler);
        });

        return this;
    },

    /**
     * unregisters a query and all it's handlers, or a specific handler for a query
     *
     * @param {string} q the media query to target
     * @param {object || function} [handler] specific handler to unregister
     */
    unregister : function(q, handler) {
        var query = this.queries[q];

        if(query) {
            if(handler) {
                query.removeHandler(handler);
            }
            else {
                query.clear();
                delete this.queries[q];
            }
        }

        return this;
    }
};

global.enquire = global.enquire || new MediaQueryDispatch();

}(this));;
/*! LAB.js (LABjs :: Loading And Blocking JavaScript)
    v2.0.3 (c) Kyle Simpson
    MIT License
*/

(function(global){
	var _$LAB = global.$LAB,
	
		// constants for the valid keys of the options object
		_UseLocalXHR = "UseLocalXHR",
		_AlwaysPreserveOrder = "AlwaysPreserveOrder",
		_AllowDuplicates = "AllowDuplicates",
		_CacheBust = "CacheBust",
		/*!START_DEBUG*/_Debug = "Debug",/*!END_DEBUG*/
		_BasePath = "BasePath",
		
		// stateless variables used across all $LAB instances
		root_page = /^[^?#]*\//.exec(location.href)[0],
		root_domain = /^\w+\:\/\/\/?[^\/]+/.exec(root_page)[0],
		append_to = document.head || document.getElementsByTagName("head"),
		
		// inferences... ick, but still necessary
		opera_or_gecko = (global.opera && Object.prototype.toString.call(global.opera) == "[object Opera]") || ("MozAppearance" in document.documentElement.style),

/*!START_DEBUG*/
		// console.log() and console.error() wrappers
		log_msg = function(){}, 
		log_error = log_msg,
/*!END_DEBUG*/
		
		// feature sniffs (yay!)
		test_script_elem = document.createElement("script"),
		explicit_preloading = typeof test_script_elem.preload == "boolean", // http://wiki.whatwg.org/wiki/Script_Execution_Control#Proposal_1_.28Nicholas_Zakas.29
		real_preloading = explicit_preloading || (test_script_elem.readyState && test_script_elem.readyState == "uninitialized"), // will a script preload with `src` set before DOM append?
		script_ordered_async = !real_preloading && test_script_elem.async === true, // http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
		
		// XHR preloading (same-domain) and cache-preloading (remote-domain) are the fallbacks (for some browsers)
		xhr_or_cache_preloading = !real_preloading && !script_ordered_async && !opera_or_gecko
	;

/*!START_DEBUG*/
	// define console wrapper functions if applicable
	if (global.console && global.console.log) {
		if (!global.console.error) global.console.error = global.console.log;
		log_msg = function(msg) { global.console.log(msg); };
		log_error = function(msg,err) { global.console.error(msg,err); };
	}
/*!END_DEBUG*/

	// test for function
	function is_func(func) { return Object.prototype.toString.call(func) == "[object Function]"; }

	// test for array
	function is_array(arr) { return Object.prototype.toString.call(arr) == "[object Array]"; }

	// make script URL absolute/canonical
	function canonical_uri(src,base_path) {
		var absolute_regex = /^\w+\:\/\//;
		
		// is `src` is protocol-relative (begins with // or ///), prepend protocol
		if (/^\/\/\/?/.test(src)) {
			src = location.protocol + src;
		}
		// is `src` page-relative? (not an absolute URL, and not a domain-relative path, beginning with /)
		else if (!absolute_regex.test(src) && src.charAt(0) != "/") {
			// prepend `base_path`, if any
			src = (base_path || "") + src;
		}
		// make sure to return `src` as absolute
		return absolute_regex.test(src) ? src : ((src.charAt(0) == "/" ? root_domain : root_page) + src);
	}

	// merge `source` into `target`
	function merge_objs(source,target) {
		for (var k in source) { if (source.hasOwnProperty(k)) {
			target[k] = source[k]; // TODO: does this need to be recursive for our purposes?
		}}
		return target;
	}

	// does the chain group have any ready-to-execute scripts?
	function check_chain_group_scripts_ready(chain_group) {
		var any_scripts_ready = false;
		for (var i=0; i<chain_group.scripts.length; i++) {
			if (chain_group.scripts[i].ready && chain_group.scripts[i].exec_trigger) {
				any_scripts_ready = true;
				chain_group.scripts[i].exec_trigger();
				chain_group.scripts[i].exec_trigger = null;
			}
		}
		return any_scripts_ready;
	}

	// creates a script load listener
	function create_script_load_listener(elem,registry_item,flag,onload) {
		elem.onload = elem.onreadystatechange = function() {
			if ((elem.readyState && elem.readyState != "complete" && elem.readyState != "loaded") || registry_item[flag]) return;
			elem.onload = elem.onreadystatechange = null;
			onload();
		};
	}

	// script executed handler
	function script_executed(registry_item) {
		registry_item.ready = registry_item.finished = true;
		for (var i=0; i<registry_item.finished_listeners.length; i++) {
			registry_item.finished_listeners[i]();
		}
		registry_item.ready_listeners = [];
		registry_item.finished_listeners = [];
	}

	// make the request for a scriptha
	function request_script(chain_opts,script_obj,registry_item,onload,preload_this_script) {
		// setTimeout() "yielding" prevents some weird race/crash conditions in older browsers
		setTimeout(function(){
			var script, src = script_obj.real_src, xhr;
			
			// don't proceed until `append_to` is ready to append to
			if ("item" in append_to) { // check if `append_to` ref is still a live node list
				if (!append_to[0]) { // `append_to` node not yet ready
					// try again in a little bit -- note: will re-call the anonymous function in the outer setTimeout, not the parent `request_script()`
					setTimeout(arguments.callee,25);
					return;
				}
				// reassign from live node list ref to pure node ref -- avoids nasty IE bug where changes to DOM invalidate live node lists
				append_to = append_to[0];
			}
			script = document.createElement("script");
			if (script_obj.type) script.type = script_obj.type;
			if (script_obj.charset) script.charset = script_obj.charset;
			
			// should preloading be used for this script?
			if (preload_this_script) {
				// real script preloading?
				if (real_preloading) {
					/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload: "+src);/*!END_DEBUG*/
					registry_item.elem = script;
					if (explicit_preloading) { // explicit preloading (aka, Zakas' proposal)
						script.preload = true;
						script.onpreload = onload;
					}
					else {
						script.onreadystatechange = function(){
							if (script.readyState == "loaded") onload();
						};
					}
					script.src = src;
					// NOTE: no append to DOM yet, appending will happen when ready to execute
				}
				// same-domain and XHR allowed? use XHR preloading
				else if (preload_this_script && src.indexOf(root_domain) == 0 && chain_opts[_UseLocalXHR]) {
					xhr = new XMLHttpRequest(); // note: IE never uses XHR (it supports true preloading), so no more need for ActiveXObject fallback for IE <= 7
					/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload (xhr): "+src);/*!END_DEBUG*/
					xhr.onreadystatechange = function() {
						if (xhr.readyState == 4) {
							xhr.onreadystatechange = function(){}; // fix a memory leak in IE
							registry_item.text = xhr.responseText + "\n//@ sourceURL=" + src; // http://blog.getfirebug.com/2009/08/11/give-your-eval-a-name-with-sourceurl/
							onload();
						}
					};
					xhr.open("GET",src);
					xhr.send();
				}
				// as a last resort, use cache-preloading
				else {
					/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script preload (cache): "+src);/*!END_DEBUG*/
					script.type = "text/cache-script";
					create_script_load_listener(script,registry_item,"ready",function() {
						append_to.removeChild(script);
						onload();
					});
					script.src = src;
					append_to.insertBefore(script,append_to.firstChild);
				}
			}
			// use async=false for ordered async? parallel-load-serial-execute http://wiki.whatwg.org/wiki/Dynamic_Script_Execution_Order
			else if (script_ordered_async) {
				/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script load (ordered async): "+src);/*!END_DEBUG*/
				script.async = false;
				create_script_load_listener(script,registry_item,"finished",onload);
				script.src = src;
				append_to.insertBefore(script,append_to.firstChild);
			}
			// otherwise, just a normal script element
			else {
				/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("start script load: "+src);/*!END_DEBUG*/
				create_script_load_listener(script,registry_item,"finished",onload);
				script.src = src;
				append_to.insertBefore(script,append_to.firstChild);
			}
		},0);
	}
		
	// create a clean instance of $LAB
	function create_sandbox() {
		var global_defaults = {},
			can_use_preloading = real_preloading || xhr_or_cache_preloading,
			queue = [],
			registry = {},
			instanceAPI
		;
		
		// global defaults
		global_defaults[_UseLocalXHR] = true;
		global_defaults[_AlwaysPreserveOrder] = false;
		global_defaults[_AllowDuplicates] = false;
		global_defaults[_CacheBust] = false;
		/*!START_DEBUG*/global_defaults[_Debug] = false;/*!END_DEBUG*/
		global_defaults[_BasePath] = "";

		// execute a script that has been preloaded already
		function execute_preloaded_script(chain_opts,script_obj,registry_item) {
			var script;
			
			function preload_execute_finished() {
				if (script != null) { // make sure this only ever fires once
					script = null;
					script_executed(registry_item);
				}
			}
			
			if (registry[script_obj.src].finished) return;
			if (!chain_opts[_AllowDuplicates]) registry[script_obj.src].finished = true;
			
			script = registry_item.elem || document.createElement("script");
			if (script_obj.type) script.type = script_obj.type;
			if (script_obj.charset) script.charset = script_obj.charset;
			create_script_load_listener(script,registry_item,"finished",preload_execute_finished);
			
			// script elem was real-preloaded
			if (registry_item.elem) {
				registry_item.elem = null;
			}
			// script was XHR preloaded
			else if (registry_item.text) {
				script.onload = script.onreadystatechange = null;	// script injection doesn't fire these events
				script.text = registry_item.text;
			}
			// script was cache-preloaded
			else {
				script.src = script_obj.real_src;
			}
			append_to.insertBefore(script,append_to.firstChild);

			// manually fire execution callback for injected scripts, since events don't fire
			if (registry_item.text) {
				preload_execute_finished();
			}
		}
	
		// process the script request setup
		function do_script(chain_opts,script_obj,chain_group,preload_this_script) {
			var registry_item,
				registry_items,
				ready_cb = function(){ script_obj.ready_cb(script_obj,function(){ execute_preloaded_script(chain_opts,script_obj,registry_item); }); },
				finished_cb = function(){ script_obj.finished_cb(script_obj,chain_group); }
			;
			
			script_obj.src = canonical_uri(script_obj.src,chain_opts[_BasePath]);
			script_obj.real_src = script_obj.src + 
				// append cache-bust param to URL?
				(chain_opts[_CacheBust] ? ((/\?.*$/.test(script_obj.src) ? "&_" : "?_") + ~~(Math.random()*1E9) + "=") : "")
			;
			
			if (!registry[script_obj.src]) registry[script_obj.src] = {items:[],finished:false};
			registry_items = registry[script_obj.src].items;

			// allowing duplicates, or is this the first recorded load of this script?
			if (chain_opts[_AllowDuplicates] || registry_items.length == 0) {
				registry_item = registry_items[registry_items.length] = {
					ready:false,
					finished:false,
					ready_listeners:[ready_cb],
					finished_listeners:[finished_cb]
				};

				request_script(chain_opts,script_obj,registry_item,
					// which callback type to pass?
					(
					 	(preload_this_script) ? // depends on script-preloading
						function(){
							registry_item.ready = true;
							for (var i=0; i<registry_item.ready_listeners.length; i++) {
								registry_item.ready_listeners[i]();
							}
							registry_item.ready_listeners = [];
						} :
						function(){ script_executed(registry_item); }
					),
					// signal if script-preloading should be used or not
					preload_this_script
				);
			}
			else {
				registry_item = registry_items[0];
				if (registry_item.finished) {
					finished_cb();
				}
				else {
					registry_item.finished_listeners.push(finished_cb);
				}
			}
		}

		// creates a closure for each separate chain spawned from this $LAB instance, to keep state cleanly separated between chains
		function create_chain() {
			var chainedAPI,
				chain_opts = merge_objs(global_defaults,{}),
				chain = [],
				exec_cursor = 0,
				scripts_currently_loading = false,
				group
			;
			
			// called when a script has finished preloading
			function chain_script_ready(script_obj,exec_trigger) {
				/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("script preload finished: "+script_obj.real_src);/*!END_DEBUG*/
				script_obj.ready = true;
				script_obj.exec_trigger = exec_trigger;
				advance_exec_cursor(); // will only check for 'ready' scripts to be executed
			}

			// called when a script has finished executing
			function chain_script_executed(script_obj,chain_group) {
				/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("script execution finished: "+script_obj.real_src);/*!END_DEBUG*/
				script_obj.ready = script_obj.finished = true;
				script_obj.exec_trigger = null;
				// check if chain group is all finished
				for (var i=0; i<chain_group.scripts.length; i++) {
					if (!chain_group.scripts[i].finished) return;
				}
				// chain_group is all finished if we get this far
				chain_group.finished = true;
				advance_exec_cursor();
			}

			// main driver for executing each part of the chain
			function advance_exec_cursor() {
				while (exec_cursor < chain.length) {
					if (is_func(chain[exec_cursor])) {
						/*!START_DEBUG*/if (chain_opts[_Debug]) log_msg("$LAB.wait() executing: "+chain[exec_cursor]);/*!END_DEBUG*/
						try { chain[exec_cursor++](); } catch (err) {
							/*!START_DEBUG*/if (chain_opts[_Debug]) log_error("$LAB.wait() error caught: ",err);/*!END_DEBUG*/
						}
						continue;
					}
					else if (!chain[exec_cursor].finished) {
						if (check_chain_group_scripts_ready(chain[exec_cursor])) continue;
						break;
					}
					exec_cursor++;
				}
				// we've reached the end of the chain (so far)
				if (exec_cursor == chain.length) {
					scripts_currently_loading = false;
					group = false;
				}
			}
			
			// setup next chain script group
			function init_script_chain_group() {
				if (!group || !group.scripts) {
					chain.push(group = {scripts:[],finished:true});
				}
			}

			// API for $LAB chains
			chainedAPI = {
				// start loading one or more scripts
				script:function(){
					for (var i=0; i<arguments.length; i++) {
						(function(script_obj,script_list){
							var splice_args;
							
							if (!is_array(script_obj)) {
								script_list = [script_obj];
							}
							for (var j=0; j<script_list.length; j++) {
								init_script_chain_group();
								script_obj = script_list[j];
								
								if (is_func(script_obj)) script_obj = script_obj();
								if (!script_obj) continue;
								if (is_array(script_obj)) {
									// set up an array of arguments to pass to splice()
									splice_args = [].slice.call(script_obj); // first include the actual array elements we want to splice in
									splice_args.unshift(j,1); // next, put the `index` and `howMany` parameters onto the beginning of the splice-arguments array
									[].splice.apply(script_list,splice_args); // use the splice-arguments array as arguments for splice()
									j--; // adjust `j` to account for the loop's subsequent `j++`, so that the next loop iteration uses the same `j` index value
									continue;
								}
								if (typeof script_obj == "string") script_obj = {src:script_obj};
								script_obj = merge_objs(script_obj,{
									ready:false,
									ready_cb:chain_script_ready,
									finished:false,
									finished_cb:chain_script_executed
								});
								group.finished = false;
								group.scripts.push(script_obj);
								
								do_script(chain_opts,script_obj,group,(can_use_preloading && scripts_currently_loading));
								scripts_currently_loading = true;
								
								if (chain_opts[_AlwaysPreserveOrder]) chainedAPI.wait();
							}
						})(arguments[i],arguments[i]);
					}
					return chainedAPI;
				},
				// force LABjs to pause in execution at this point in the chain, until the execution thus far finishes, before proceeding
				wait:function(){
					if (arguments.length > 0) {
						for (var i=0; i<arguments.length; i++) {
							chain.push(arguments[i]);
						}
						group = chain[chain.length-1];
					}
					else group = false;
					
					advance_exec_cursor();
					
					return chainedAPI;
				}
			};

			// the first chain link API (includes `setOptions` only this first time)
			return {
				script:chainedAPI.script, 
				wait:chainedAPI.wait, 
				setOptions:function(opts){
					merge_objs(opts,chain_opts);
					return chainedAPI;
				}
			};
		}

		// API for each initial $LAB instance (before chaining starts)
		instanceAPI = {
			// main API functions
			setGlobalDefaults:function(opts){
				merge_objs(opts,global_defaults);
				return instanceAPI;
			},
			setOptions:function(){
				return create_chain().setOptions.apply(null,arguments);
			},
			script:function(){
				return create_chain().script.apply(null,arguments);
			},
			wait:function(){
				return create_chain().wait.apply(null,arguments);
			},

			// built-in queuing for $LAB `script()` and `wait()` calls
			// useful for building up a chain programmatically across various script locations, and simulating
			// execution of the chain
			queueScript:function(){
				queue[queue.length] = {type:"script", args:[].slice.call(arguments)};
				return instanceAPI;
			},
			queueWait:function(){
				queue[queue.length] = {type:"wait", args:[].slice.call(arguments)};
				return instanceAPI;
			},
			runQueue:function(){
				var $L = instanceAPI, len=queue.length, i=len, val;
				for (;--i>=0;) {
					val = queue.shift();
					$L = $L[val.type].apply(null,val.args);
				}
				return $L;
			},

			// rollback `[global].$LAB` to what it was before this file was loaded, the return this current instance of $LAB
			noConflict:function(){
				global.$LAB = _$LAB;
				return instanceAPI;
			},

			// create another clean instance of $LAB
			sandbox:function(){
				return create_sandbox();
			}
		};

		return instanceAPI;
	}

	// create the main instance of $LAB
	global.$LAB = create_sandbox();


	/* The following "hack" was suggested by Andrea Giammarchi and adapted from: http://webreflection.blogspot.com/2009/11/195-chars-to-help-lazy-loading.html
	   NOTE: this hack only operates in FF and then only in versions where document.readyState is not present (FF < 3.6?).
	   
	   The hack essentially "patches" the **page** that LABjs is loaded onto so that it has a proper conforming document.readyState, so that if a script which does 
	   proper and safe dom-ready detection is loaded onto a page, after dom-ready has passed, it will still be able to detect this state, by inspecting the now hacked 
	   document.readyState property. The loaded script in question can then immediately trigger any queued code executions that were waiting for the DOM to be ready. 
	   For instance, jQuery 1.4+ has been patched to take advantage of document.readyState, which is enabled by this hack. But 1.3.2 and before are **not** safe or 
	   fixed by this hack, and should therefore **not** be lazy-loaded by script loader tools such as LABjs.
	*/ 
	(function(addEvent,domLoaded,handler){
		if (document.readyState == null && document[addEvent]){
			document.readyState = "loading";
			document[addEvent](domLoaded,handler = function(){
				document.removeEventListener(domLoaded,handler,false);
				document.readyState = "complete";
			},false);
		}
	})("addEventListener","DOMContentLoaded");

})(this);;
// Copyright 2013-2014 Kevin Cox

/*******************************************************************************
*                                                                              *
*  This software is provided 'as-is', without any express or implied           *
*  warranty. In no event will the authors be held liable for any damages       *
*  arising from the use of this software.                                      *
*                                                                              *
*  Permission is granted to anyone to use this software for any purpose,       *
*  including commercial applications, and to alter it and redistribute it      *
*  freely, subject to the following restrictions:                              *
*                                                                              *
*  1. The origin of this software must not be misrepresented; you must not     *
*     claim that you wrote the original software. If you use this software in  *
*     a product, an acknowledgment in the product documentation would be       *
*     appreciated but is not required.                                         *
*                                                                              *
*  2. Altered source versions must be plainly marked as such, and must not be  *
*     misrepresented as being the original software.                           *
*                                                                              *
*  3. This notice may not be removed or altered from any source distribution.  *
*                                                                              *
*******************************************************************************/

+function(){
"use strict";

var array = /\[([^\[]*)\]$/;

/// URL Regex.
/**
 * This regex splits the URL into parts.  The capture groups catch the important
 * bits.
 * 
 * Each section is optional, so to work on any part find the correct top level
 * `(...)?` and mess around with it.
 */
var regex = /^(?:([a-z]*):)?(?:\/\/)?(?:([^:@]*)(?::([^@]*))?@)?([0-9a-z-._]+)?(?::([0-9]*))?(\/[^?#]*)?(?:\?([^#]*))?(?:#(.*))?$/i;
//               1 - scheme              2 - user    3 = pass    4 - host           5 - port  6 - path        7 - query    8 - hash

var noslash = ["mailto","bitcoin"];

var self = {
	/** Parse a query string.
	 *
	 * This function parses a query string (sometimes called the search
	 * string).  It takes a query string and returns a map of the results.
	 *
	 * Keys are considered to be everything up to the first '=' and values are
	 * everything afterwords.  Since URL-decoding is done after parsing, keys
	 * and values can have any values, however, '=' have to be encoded in keys
	 * while '?' and '&' have to be encoded anywhere (as they delimit the
	 * kv-pairs).
	 *
	 * Keys and values will always be strings, except if there is a key with no
	 * '=' in which case it will be considered a flag and will be set to true.
	 * Later values will override earlier values.
	 *
	 * Array keys are also supported.  By default keys in the form of `name[i]`
	 * will be returned like that as strings.  However, if you set the `array`
	 * flag in the options object they will be parsed into arrays.  Note that
	 * although the object returned is an `Array` object all keys will be
	 * written to it.  This means that if you have a key such as `k[forEach]`
	 * it will overwrite the `forEach` function on that array.  Also note that
	 * string properties always take precedence over array properties,
	 * irrespective of where they are in the query string.
	 *
	 *   url.get("array[1]=test&array[foo]=bar",{array:true}).array[1]  === "test"
	 *   url.get("array[1]=test&array[foo]=bar",{array:true}).array.foo === "bar"
	 *   url.get("array=notanarray&array[0]=1",{array:true}).array      === "notanarray"
	 *
	 * If array parsing is enabled keys in the form of `name[]` will
	 * automatically be given the next available index.  Note that this can be
	 * overwritten with later values in the query string.  For this reason is
	 * is best not to mix the two formats, although it is safe (and often
	 * useful) to add an automatic index argument to the end of a query string.
	 *
	 *   url.get("a[]=0&a[]=1&a[0]=2", {array:true})  -> {a:["2","1"]};
	 *   url.get("a[0]=0&a[1]=1&a[]=2", {array:true}) -> {a:["0","1","2"]};
	 *
	 * @param{string} q The query string (the part after the '?').
	 * @param{{full:boolean,array:boolean}=} opt Options.
	 *
	 * - full: If set `q` will be treated as a full url and `q` will be built.
	 *   by calling #parse to retrieve the query portion.
	 * - array: If set keys in the form of `key[i]` will be treated
	 *   as arrays/maps.
	 *
	 * @return{!Object.<string, string|Array>} The parsed result.
	 */
	"get": function(q, opt){
		q = q || "";
		if ( typeof opt          == "undefined" ) opt = {};
		if ( typeof opt["full"]  == "undefined" ) opt["full"] = false;
		if ( typeof opt["array"] == "undefined" ) opt["array"] = false;
		
		if ( opt["full"] === true )
		{
			q = self["parse"](q, {"get":false})["query"] || "";
		}
		
		var o = {};
		
		var c = q.split("&");
		for (var i = 0; i < c.length; i++)
		{
			if (!c[i].length) continue;
			
			var d = c[i].indexOf("=");
			var k = c[i], v = true;
			if ( d >= 0 )
			{
				k = c[i].substr(0, d);
				v = c[i].substr(d+1);
				
				v = decodeURIComponent(v);
			}
			
			if (opt["array"])
			{
				var inds = [];
				var ind;
				var curo = o;
				var curk = k;
				while (ind = curk.match(array)) // Array!
				{
					curk = curk.substr(0, ind.index);
					inds.unshift(decodeURIComponent(ind[1]));
				}
				curk = decodeURIComponent(curk);
				if (inds.some(function(i)
				{
					if ( typeof curo[curk] == "undefined" ) curo[curk] = [];
					if (!Array.isArray(curo[curk]))
					{
						//console.log("url.get: Array property "+curk+" already exists as string!");
						return true;
					}
					
					curo = curo[curk];
					
					if ( i === "" ) i = curo.length;
					
					curk = i;
				})) continue;
				curo[curk] = v;
				continue;
			}
			
			k = decodeURIComponent(k);
			
			//typeof o[k] == "undefined" || console.log("Property "+k+" already exists!");
			o[k] = v;
		}
		
		return o;
	},
	
	/** Build a get query from an object.
	 *
	 * This constructs a query string from the kv pairs in `data`.  Calling
	 * #get on the string returned should return an object identical to the one
	 * passed in except all non-boolean scalar types become strings and all
	 * object types become arrays (non-integer keys are still present, see
	 * #get's documentation for more details).
	 *
	 * This always uses array syntax for describing arrays.  If you want to
	 * serialize them differently (like having the value be a JSON array and
	 * have a plain key) you will need to do that before passing it in.
	 *
	 * All keys and values are supported (binary data anyone?) as they are
	 * properly URL-encoded and #get properly decodes.
	 *
	 * @param{Object} data The kv pairs.
	 * @param{string} prefix The properly encoded array key to put the
	 *   properties.  Mainly intended for internal use.
	 * @return{string} A URL-safe string.
	 */
	"buildget": function(data, prefix){
		var itms = [];
		for ( var k in data )
		{
			var ek = encodeURIComponent(k);
			if ( typeof prefix != "undefined" )
				ek = prefix+"["+ek+"]";
			
			var v = data[k];
			
			switch (typeof v)
			{
				case 'boolean':
					if(v) itms.push(ek);
					break;
				case 'number':
					v = v.toString();
				case 'string':
					itms.push(ek+"="+encodeURIComponent(v));
					break;
				case 'object':
					itms.push(self["buildget"](v, ek));
					break;
			}
		}
		return itms.join("&");
	},
	
	/** Parse a URL
	 * 
	 * This breaks up a URL into components.  It attempts to be very liberal
	 * and returns the best result in most cases.  This means that you can
	 * often pass in part of a URL and get correct categories back.  Notably,
	 * this works for emails and Jabber IDs, as well as adding a '?' to the
	 * beginning of a string will parse the whole thing as a query string.  If
	 * an item is not found the property will be undefined.  In some cases an
	 * empty string will be returned if the surrounding syntax but the actual
	 * value is empty (example: "://example.com" will give a empty string for
	 * scheme.)  Notably the host name will always be set to something.
	 * 
	 * Returned properties.
	 * 
	 * - **scheme:** The url scheme. (ex: "mailto" or "https")
	 * - **user:** The username.
	 * - **pass:** The password.
	 * - **host:** The hostname. (ex: "localhost", "123.456.7.8" or "example.com")
	 * - **port:** The port, as a number. (ex: 1337)
	 * - **path:** The path. (ex: "/" or "/about.html")
	 * - **query:** "The query string. (ex: "foo=bar&v=17&format=json")
	 * - **get:** The query string parsed with get.  If `opt.get` is `false` this
	 *   will be absent
	 * - **hash:** The value after the hash. (ex: "myanchor")
	 *   be undefined even if `query` is set.
	 *
	 * @param{string} url The URL to parse.
	 * @param{{get:Object}=} opt Options:
	 *
	 * - get: An options argument to be passed to #get or false to not call #get.
	 *    **DO NOT** set `full`.
	 *
	 * @return{!Object} An object with the parsed values.
	 */
	"parse": function(url, opt) {
		
		if ( typeof opt == "undefined" ) opt = {};
		
		var md = url.match(regex) || [];
		
		var r = {
			"url":    url,
			
			"scheme": md[1],
			"user":   md[2],
			"pass":   md[3],
			"host":   md[4],
			"port":   md[5] && +md[5],
			"path":   md[6],
			"query":  md[7],
			"hash":   md[8],
		};
		
		if ( opt.get !== false )
			r["get"] = r["query"] && self["get"](r["query"], opt.get);
		
		return r;
	},
	
	/** Build a URL from components.
	 * 
	 * This pieces together a url from the properties of the passed in object.
	 * In general passing the result of `parse()` should return the URL.  There
	 * may differences in the get string as the keys and values might be more
	 * encoded then they were originally were.  However, calling `get()` on the
	 * two values should yield the same result.
	 * 
	 * Here is how the parameters are used.
	 * 
	 *  - url: Used only if no other values are provided.  If that is the case
	 *     `url` will be returned verbatim.
	 *  - scheme: Used if defined.
	 *  - user: Used if defined.
	 *  - pass: Used if defined.
	 *  - host: Used if defined.
	 *  - path: Used if defined.
	 *  - query: Used only if `get` is not provided and non-empty.
	 *  - get: Used if non-empty.  Passed to #buildget and the result is used
	 *    as the query string.
	 *  - hash: Used if defined.
	 * 
	 * These are the options that are valid on the options object.
	 * 
	 *  - useemptyget: If truthy, a question mark will be appended for empty get
	 *    strings.  This notably makes `build()` and `parse()` fully symmetric.
	 *
	 * @param{Object} data The pieces of the URL.
	 * @param{Object} opt Options for building the url.
	 * @return{string} The URL.
	 */
	"build": function(data, opt){
		opt = opt || {};
		
		var r = "";
		
		if ( typeof data["scheme"] != "undefined" )
		{
			r += data["scheme"];
			r += (noslash.indexOf(data["scheme"])>=0)?":":"://";
		}
		if ( typeof data["user"] != "undefined" )
		{
			r += data["user"];
			if ( typeof data["pass"] == "undefined" )
			{
				r += "@";
			}
		}
		if ( typeof data["pass"] != "undefined" ) r += ":" + data["pass"] + "@";
		if ( typeof data["host"] != "undefined" ) r += data["host"];
		if ( typeof data["port"] != "undefined" ) r += ":" + data["port"];
		if ( typeof data["path"] != "undefined" ) r += data["path"];
		
		if (opt["useemptyget"])
		{
			if      ( typeof data["get"]   != "undefined" ) r += "?" + self["buildget"](data["get"]);
			else if ( typeof data["query"] != "undefined" ) r += "?" + data["query"];
		}
		else
		{
			// If .get use it.  If .get leads to empty, use .query.
			var q = data["get"] && self["buildget"](data["get"]) || data["query"];
			if (q) r += "?" + q;
		}
		
		if ( typeof data["hash"] != "undefined" ) r += "#" + data["hash"];
		
		return r || data["url"] || "";
	},
};

if ( typeof define != "undefined" && define["amd"] ) define(self);
else if ( typeof module != "undefined" ) module['exports'] = self;
else window["url"] = self;

}();
;
/*!
* inputmask.min.js
* https://github.com/RobinHerbots/Inputmask
* Copyright (c) 2010 - 2019 Robin Herbots
* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
* Version: 4.0.7
*/

(function(factory){if(typeof define==="function"&&define.amd){define(["./dependencyLibs/inputmask.dependencyLib","./global/window"],factory)}else if(typeof exports==="object"){module.exports=factory(require("./dependencyLibs/inputmask.dependencyLib"),require("./global/window"))}else{window.Inputmask=factory(window.dependencyLib||jQuery,window)}})(function($,window,undefined){var document=window.document,ua=navigator.userAgent,ie=ua.indexOf("MSIE ")>0||ua.indexOf("Trident/")>0,mobile=isInputEventSupported("touchstart"),iemobile=/iemobile/i.test(ua),iphone=/iphone/i.test(ua)&&!iemobile;function Inputmask(alias,options,internal){if(!(this instanceof Inputmask)){return new Inputmask(alias,options,internal)}this.el=undefined;this.events={};this.maskset=undefined;this.refreshValue=false;if(internal!==true){if($.isPlainObject(alias)){options=alias}else{options=options||{};if(alias)options.alias=alias}this.opts=$.extend(true,{},this.defaults,options);this.noMasksCache=options&&options.definitions!==undefined;this.userOptions=options||{};this.isRTL=this.opts.numericInput;resolveAlias(this.opts.alias,options,this.opts)}}Inputmask.prototype={dataAttribute:"data-inputmask",defaults:{placeholder:"_",optionalmarker:["[","]"],quantifiermarker:["{","}"],groupmarker:["(",")"],alternatormarker:"|",escapeChar:"\\",mask:null,regex:null,oncomplete:$.noop,onincomplete:$.noop,oncleared:$.noop,repeat:0,greedy:false,autoUnmask:false,removeMaskOnSubmit:false,clearMaskOnLostFocus:true,insertMode:true,clearIncomplete:false,alias:null,onKeyDown:$.noop,onBeforeMask:null,onBeforePaste:function(pastedValue,opts){return $.isFunction(opts.onBeforeMask)?opts.onBeforeMask.call(this,pastedValue,opts):pastedValue},onBeforeWrite:null,onUnMask:null,showMaskOnFocus:true,showMaskOnHover:true,onKeyValidation:$.noop,skipOptionalPartCharacter:" ",numericInput:false,rightAlign:false,undoOnEscape:true,radixPoint:"",_radixDance:false,groupSeparator:"",keepStatic:null,positionCaretOnTab:true,tabThrough:false,supportsInputType:["text","tel","url","password","search"],ignorables:[8,9,13,19,27,33,34,35,36,37,38,39,40,45,46,93,112,113,114,115,116,117,118,119,120,121,122,123,0,229],isComplete:null,preValidation:null,postValidation:null,staticDefinitionSymbol:undefined,jitMasking:false,nullable:true,inputEventOnly:false,noValuePatching:false,positionCaretOnClick:"lvp",casing:null,inputmode:"verbatim",colorMask:false,disablePredictiveText:false,importDataAttributes:true,shiftPositions:true},definitions:{9:{validator:"[0-9\uff11-\uff19]",definitionSymbol:"*"},a:{validator:"[A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",definitionSymbol:"*"},"*":{validator:"[0-9\uff11-\uff19A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]"}},aliases:{},masksCache:{},mask:function(elems){var that=this;function importAttributeOptions(npt,opts,userOptions,dataAttribute){if(opts.importDataAttributes===true){var attrOptions=npt.getAttribute(dataAttribute),option,dataoptions,optionData,p;function importOption(option,optionData){optionData=optionData!==undefined?optionData:npt.getAttribute(dataAttribute+"-"+option);if(optionData!==null){if(typeof optionData==="string"){if(option.indexOf("on")===0)optionData=window[optionData];else if(optionData==="false")optionData=false;else if(optionData==="true")optionData=true}userOptions[option]=optionData}}if(attrOptions&&attrOptions!==""){attrOptions=attrOptions.replace(/'/g,'"');dataoptions=JSON.parse("{"+attrOptions+"}")}if(dataoptions){optionData=undefined;for(p in dataoptions){if(p.toLowerCase()==="alias"){optionData=dataoptions[p];break}}}importOption("alias",optionData);if(userOptions.alias){resolveAlias(userOptions.alias,userOptions,opts)}for(option in opts){if(dataoptions){optionData=undefined;for(p in dataoptions){if(p.toLowerCase()===option.toLowerCase()){optionData=dataoptions[p];break}}}importOption(option,optionData)}}$.extend(true,opts,userOptions);if(npt.dir==="rtl"||opts.rightAlign){npt.style.textAlign="right"}if(npt.dir==="rtl"||opts.numericInput){npt.dir="ltr";npt.removeAttribute("dir");opts.isRTL=true}return Object.keys(userOptions).length}if(typeof elems==="string"){elems=document.getElementById(elems)||document.querySelectorAll(elems)}elems=elems.nodeName?[elems]:elems;$.each(elems,function(ndx,el){var scopedOpts=$.extend(true,{},that.opts);if(importAttributeOptions(el,scopedOpts,$.extend(true,{},that.userOptions),that.dataAttribute)){var maskset=generateMaskSet(scopedOpts,that.noMasksCache);if(maskset!==undefined){if(el.inputmask!==undefined){el.inputmask.opts.autoUnmask=true;el.inputmask.remove()}el.inputmask=new Inputmask(undefined,undefined,true);el.inputmask.opts=scopedOpts;el.inputmask.noMasksCache=that.noMasksCache;el.inputmask.userOptions=$.extend(true,{},that.userOptions);el.inputmask.isRTL=scopedOpts.isRTL||scopedOpts.numericInput;el.inputmask.el=el;el.inputmask.maskset=maskset;$.data(el,"_inputmask_opts",scopedOpts);maskScope.call(el.inputmask,{action:"mask"})}}});return elems&&elems[0]?elems[0].inputmask||this:this},option:function(options,noremask){if(typeof options==="string"){return this.opts[options]}else if(typeof options==="object"){$.extend(this.userOptions,options);if(this.el&&noremask!==true){this.mask(this.el)}return this}},unmaskedvalue:function(value){this.maskset=this.maskset||generateMaskSet(this.opts,this.noMasksCache);return maskScope.call(this,{action:"unmaskedvalue",value:value})},remove:function(){return maskScope.call(this,{action:"remove"})},getemptymask:function(){this.maskset=this.maskset||generateMaskSet(this.opts,this.noMasksCache);return maskScope.call(this,{action:"getemptymask"})},hasMaskedValue:function(){return!this.opts.autoUnmask},isComplete:function(){this.maskset=this.maskset||generateMaskSet(this.opts,this.noMasksCache);return maskScope.call(this,{action:"isComplete"})},getmetadata:function(){this.maskset=this.maskset||generateMaskSet(this.opts,this.noMasksCache);return maskScope.call(this,{action:"getmetadata"})},isValid:function(value){this.maskset=this.maskset||generateMaskSet(this.opts,this.noMasksCache);return maskScope.call(this,{action:"isValid",value:value})},format:function(value,metadata){this.maskset=this.maskset||generateMaskSet(this.opts,this.noMasksCache);return maskScope.call(this,{action:"format",value:value,metadata:metadata})},setValue:function(value){if(this.el){$(this.el).trigger("setvalue",[value])}},analyseMask:function(mask,regexMask,opts){var tokenizer=/(?:[?*+]|\{[0-9\+\*]+(?:,[0-9\+\*]*)?(?:\|[0-9\+\*]*)?\})|[^.?*+^${[]()|\\]+|./g,regexTokenizer=/\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g,escaped=false,currentToken=new MaskToken,match,m,openenings=[],maskTokens=[],openingToken,currentOpeningToken,alternator,lastMatch,groupToken;function MaskToken(isGroup,isOptional,isQuantifier,isAlternator){this.matches=[];this.openGroup=isGroup||false;this.alternatorGroup=false;this.isGroup=isGroup||false;this.isOptional=isOptional||false;this.isQuantifier=isQuantifier||false;this.isAlternator=isAlternator||false;this.quantifier={min:1,max:1}}function insertTestDefinition(mtoken,element,position){position=position!==undefined?position:mtoken.matches.length;var prevMatch=mtoken.matches[position-1];if(regexMask){if(element.indexOf("[")===0||escaped&&/\\d|\\s|\\w]/i.test(element)||element==="."){mtoken.matches.splice(position++,0,{fn:new RegExp(element,opts.casing?"i":""),optionality:false,newBlockMarker:prevMatch===undefined?"master":prevMatch.def!==element,casing:null,def:element,placeholder:undefined,nativeDef:element})}else{if(escaped)element=element[element.length-1];$.each(element.split(""),function(ndx,lmnt){prevMatch=mtoken.matches[position-1];mtoken.matches.splice(position++,0,{fn:null,optionality:false,newBlockMarker:prevMatch===undefined?"master":prevMatch.def!==lmnt&&prevMatch.fn!==null,casing:null,def:opts.staticDefinitionSymbol||lmnt,placeholder:opts.staticDefinitionSymbol!==undefined?lmnt:undefined,nativeDef:(escaped?"'":"")+lmnt})})}escaped=false}else{var maskdef=(opts.definitions?opts.definitions[element]:undefined)||Inputmask.prototype.definitions[element];if(maskdef&&!escaped){mtoken.matches.splice(position++,0,{fn:maskdef.validator?typeof maskdef.validator=="string"?new RegExp(maskdef.validator,opts.casing?"i":""):new function(){this.test=maskdef.validator}:new RegExp("."),optionality:false,newBlockMarker:prevMatch===undefined?"master":prevMatch.def!==(maskdef.definitionSymbol||element),casing:maskdef.casing,def:maskdef.definitionSymbol||element,placeholder:maskdef.placeholder,nativeDef:element})}else{mtoken.matches.splice(position++,0,{fn:null,optionality:false,newBlockMarker:prevMatch===undefined?"master":prevMatch.def!==element&&prevMatch.fn!==null,casing:null,def:opts.staticDefinitionSymbol||element,placeholder:opts.staticDefinitionSymbol!==undefined?element:undefined,nativeDef:(escaped?"'":"")+element});escaped=false}}}function verifyGroupMarker(maskToken){if(maskToken&&maskToken.matches){$.each(maskToken.matches,function(ndx,token){var nextToken=maskToken.matches[ndx+1];if((nextToken===undefined||(nextToken.matches===undefined||nextToken.isQuantifier===false))&&token&&token.isGroup){token.isGroup=false;if(!regexMask){insertTestDefinition(token,opts.groupmarker[0],0);if(token.openGroup!==true){insertTestDefinition(token,opts.groupmarker[1])}}}verifyGroupMarker(token)})}}function defaultCase(){if(openenings.length>0){currentOpeningToken=openenings[openenings.length-1];insertTestDefinition(currentOpeningToken,m);if(currentOpeningToken.isAlternator){alternator=openenings.pop();for(var mndx=0;mndx<alternator.matches.length;mndx++){if(alternator.matches[mndx].isGroup)alternator.matches[mndx].isGroup=false}if(openenings.length>0){currentOpeningToken=openenings[openenings.length-1];currentOpeningToken.matches.push(alternator)}else{currentToken.matches.push(alternator)}}}else{insertTestDefinition(currentToken,m)}}function reverseTokens(maskToken){function reverseStatic(st){if(st===opts.optionalmarker[0])st=opts.optionalmarker[1];else if(st===opts.optionalmarker[1])st=opts.optionalmarker[0];else if(st===opts.groupmarker[0])st=opts.groupmarker[1];else if(st===opts.groupmarker[1])st=opts.groupmarker[0];return st}maskToken.matches=maskToken.matches.reverse();for(var match in maskToken.matches){if(maskToken.matches.hasOwnProperty(match)){var intMatch=parseInt(match);if(maskToken.matches[match].isQuantifier&&maskToken.matches[intMatch+1]&&maskToken.matches[intMatch+1].isGroup){var qt=maskToken.matches[match];maskToken.matches.splice(match,1);maskToken.matches.splice(intMatch+1,0,qt)}if(maskToken.matches[match].matches!==undefined){maskToken.matches[match]=reverseTokens(maskToken.matches[match])}else{maskToken.matches[match]=reverseStatic(maskToken.matches[match])}}}return maskToken}function groupify(matches){var groupToken=new MaskToken(true);groupToken.openGroup=false;groupToken.matches=matches;return groupToken}if(regexMask){opts.optionalmarker[0]=undefined;opts.optionalmarker[1]=undefined}while(match=regexMask?regexTokenizer.exec(mask):tokenizer.exec(mask)){m=match[0];if(regexMask){switch(m.charAt(0)){case"?":m="{0,1}";break;case"+":case"*":m="{"+m+"}";break}}if(escaped){defaultCase();continue}switch(m.charAt(0)){case"(?=":break;case"(?!":break;case"(?<=":break;case"(?<!":break;case opts.escapeChar:escaped=true;if(regexMask){defaultCase()}break;case opts.optionalmarker[1]:case opts.groupmarker[1]:openingToken=openenings.pop();openingToken.openGroup=false;if(openingToken!==undefined){if(openenings.length>0){currentOpeningToken=openenings[openenings.length-1];currentOpeningToken.matches.push(openingToken);if(currentOpeningToken.isAlternator){alternator=openenings.pop();for(var mndx=0;mndx<alternator.matches.length;mndx++){alternator.matches[mndx].isGroup=false;alternator.matches[mndx].alternatorGroup=false}if(openenings.length>0){currentOpeningToken=openenings[openenings.length-1];currentOpeningToken.matches.push(alternator)}else{currentToken.matches.push(alternator)}}}else{currentToken.matches.push(openingToken)}}else defaultCase();break;case opts.optionalmarker[0]:openenings.push(new MaskToken(false,true));break;case opts.groupmarker[0]:openenings.push(new MaskToken(true));break;case opts.quantifiermarker[0]:var quantifier=new MaskToken(false,false,true);m=m.replace(/[{}]/g,"");var mqj=m.split("|"),mq=mqj[0].split(","),mq0=isNaN(mq[0])?mq[0]:parseInt(mq[0]),mq1=mq.length===1?mq0:isNaN(mq[1])?mq[1]:parseInt(mq[1]);if(mq0==="*"||mq0==="+"){mq0=mq1==="*"?0:1}quantifier.quantifier={min:mq0,max:mq1,jit:mqj[1]};var matches=openenings.length>0?openenings[openenings.length-1].matches:currentToken.matches;match=matches.pop();if(match.isAlternator){matches.push(match);matches=match.matches;var groupToken=new MaskToken(true);var tmpMatch=matches.pop();matches.push(groupToken);matches=groupToken.matches;match=tmpMatch}if(!match.isGroup){match=groupify([match])}matches.push(match);matches.push(quantifier);break;case opts.alternatormarker:function groupQuantifier(matches){var lastMatch=matches.pop();if(lastMatch.isQuantifier){lastMatch=groupify([matches.pop(),lastMatch])}return lastMatch}if(openenings.length>0){currentOpeningToken=openenings[openenings.length-1];var subToken=currentOpeningToken.matches[currentOpeningToken.matches.length-1];if(currentOpeningToken.openGroup&&(subToken.matches===undefined||subToken.isGroup===false&&subToken.isAlternator===false)){lastMatch=openenings.pop()}else{lastMatch=groupQuantifier(currentOpeningToken.matches)}}else{lastMatch=groupQuantifier(currentToken.matches)}if(lastMatch.isAlternator){openenings.push(lastMatch)}else{if(lastMatch.alternatorGroup){alternator=openenings.pop();lastMatch.alternatorGroup=false}else{alternator=new MaskToken(false,false,false,true)}alternator.matches.push(lastMatch);openenings.push(alternator);if(lastMatch.openGroup){lastMatch.openGroup=false;var alternatorGroup=new MaskToken(true);alternatorGroup.alternatorGroup=true;openenings.push(alternatorGroup)}}break;default:defaultCase()}}while(openenings.length>0){openingToken=openenings.pop();currentToken.matches.push(openingToken)}if(currentToken.matches.length>0){verifyGroupMarker(currentToken);maskTokens.push(currentToken)}if(opts.numericInput||opts.isRTL){reverseTokens(maskTokens[0])}return maskTokens},positionColorMask:function(input,template){input.style.left=template.offsetLeft+"px"}};Inputmask.extendDefaults=function(options){$.extend(true,Inputmask.prototype.defaults,options)};Inputmask.extendDefinitions=function(definition){$.extend(true,Inputmask.prototype.definitions,definition)};Inputmask.extendAliases=function(alias){$.extend(true,Inputmask.prototype.aliases,alias)};Inputmask.format=function(value,options,metadata){return Inputmask(options).format(value,metadata)};Inputmask.unmask=function(value,options){return Inputmask(options).unmaskedvalue(value)};Inputmask.isValid=function(value,options){return Inputmask(options).isValid(value)};Inputmask.remove=function(elems){if(typeof elems==="string"){elems=document.getElementById(elems)||document.querySelectorAll(elems)}elems=elems.nodeName?[elems]:elems;$.each(elems,function(ndx,el){if(el.inputmask)el.inputmask.remove()})};Inputmask.setValue=function(elems,value){if(typeof elems==="string"){elems=document.getElementById(elems)||document.querySelectorAll(elems)}elems=elems.nodeName?[elems]:elems;$.each(elems,function(ndx,el){if(el.inputmask)el.inputmask.setValue(value);else $(el).trigger("setvalue",[value])})};Inputmask.escapeRegex=function(str){var specials=["/",".","*","+","?","|","(",")","[","]","{","}","\\","$","^"];return str.replace(new RegExp("(\\"+specials.join("|\\")+")","gim"),"\\$1")};Inputmask.keyCode={BACKSPACE:8,BACKSPACE_SAFARI:127,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,PAGE_DOWN:34,PAGE_UP:33,RIGHT:39,SPACE:32,TAB:9,UP:38,X:88,CONTROL:17};Inputmask.dependencyLib=$;function resolveAlias(aliasStr,options,opts){var aliasDefinition=Inputmask.prototype.aliases[aliasStr];if(aliasDefinition){if(aliasDefinition.alias)resolveAlias(aliasDefinition.alias,undefined,opts);$.extend(true,opts,aliasDefinition);$.extend(true,opts,options);return true}else if(opts.mask===null){opts.mask=aliasStr}return false}function generateMaskSet(opts,nocache){function generateMask(mask,metadata,opts){var regexMask=false;if(mask===null||mask===""){regexMask=opts.regex!==null;if(regexMask){mask=opts.regex;mask=mask.replace(/^(\^)(.*)(\$)$/,"$2")}else{regexMask=true;mask=".*"}}if(mask.length===1&&opts.greedy===false&&opts.repeat!==0){opts.placeholder=""}if(opts.repeat>0||opts.repeat==="*"||opts.repeat==="+"){var repeatStart=opts.repeat==="*"?0:opts.repeat==="+"?1:opts.repeat;mask=opts.groupmarker[0]+mask+opts.groupmarker[1]+opts.quantifiermarker[0]+repeatStart+","+opts.repeat+opts.quantifiermarker[1]}var masksetDefinition,maskdefKey=regexMask?"regex_"+opts.regex:opts.numericInput?mask.split("").reverse().join(""):mask;if(Inputmask.prototype.masksCache[maskdefKey]===undefined||nocache===true){masksetDefinition={mask:mask,maskToken:Inputmask.prototype.analyseMask(mask,regexMask,opts),validPositions:{},_buffer:undefined,buffer:undefined,tests:{},excludes:{},metadata:metadata,maskLength:undefined,jitOffset:{}};if(nocache!==true){Inputmask.prototype.masksCache[maskdefKey]=masksetDefinition;masksetDefinition=$.extend(true,{},Inputmask.prototype.masksCache[maskdefKey])}}else masksetDefinition=$.extend(true,{},Inputmask.prototype.masksCache[maskdefKey]);return masksetDefinition}var ms;if($.isFunction(opts.mask)){opts.mask=opts.mask(opts)}if($.isArray(opts.mask)){if(opts.mask.length>1){if(opts.keepStatic===null){opts.keepStatic="auto";for(var i=0;i<opts.mask.length;i++){if(opts.mask[i].charAt(0)!==opts.mask[0].charAt(0)){opts.keepStatic=true;break}}}var altMask=opts.groupmarker[0];$.each(opts.isRTL?opts.mask.reverse():opts.mask,function(ndx,msk){if(altMask.length>1){altMask+=opts.groupmarker[1]+opts.alternatormarker+opts.groupmarker[0]}if(msk.mask!==undefined&&!$.isFunction(msk.mask)){altMask+=msk.mask}else{altMask+=msk}});altMask+=opts.groupmarker[1];return generateMask(altMask,opts.mask,opts)}else opts.mask=opts.mask.pop()}if(opts.mask&&opts.mask.mask!==undefined&&!$.isFunction(opts.mask.mask)){ms=generateMask(opts.mask.mask,opts.mask,opts)}else{ms=generateMask(opts.mask,opts.mask,opts)}return ms}function isInputEventSupported(eventName){var el=document.createElement("input"),evName="on"+eventName,isSupported=evName in el;if(!isSupported){el.setAttribute(evName,"return;");isSupported=typeof el[evName]==="function"}el=null;return isSupported}function maskScope(actionObj,maskset,opts){maskset=maskset||this.maskset;opts=opts||this.opts;var inputmask=this,el=this.el,isRTL=this.isRTL,undoValue,$el,skipKeyPressEvent=false,skipInputEvent=false,ignorable=false,maxLength,mouseEnter=false,colorMask,originalPlaceholder;function getMaskTemplate(baseOnInput,minimalPos,includeMode,noJit,clearOptionalTail){var greedy=opts.greedy;if(clearOptionalTail)opts.greedy=false;minimalPos=minimalPos||0;var maskTemplate=[],ndxIntlzr,pos=0,test,testPos,lvp=getLastValidPosition();do{if(baseOnInput===true&&getMaskSet().validPositions[pos]){testPos=clearOptionalTail&&getMaskSet().validPositions[pos].match.optionality===true&&getMaskSet().validPositions[pos+1]===undefined&&(getMaskSet().validPositions[pos].generatedInput===true||getMaskSet().validPositions[pos].input==opts.skipOptionalPartCharacter&&pos>0)?determineTestTemplate(pos,getTests(pos,ndxIntlzr,pos-1)):getMaskSet().validPositions[pos];test=testPos.match;ndxIntlzr=testPos.locator.slice();maskTemplate.push(includeMode===true?testPos.input:includeMode===false?test.nativeDef:getPlaceholder(pos,test))}else{testPos=getTestTemplate(pos,ndxIntlzr,pos-1);test=testPos.match;ndxIntlzr=testPos.locator.slice();var jitMasking=noJit===true?false:opts.jitMasking!==false?opts.jitMasking:test.jit;if(jitMasking===false||jitMasking===undefined||typeof jitMasking==="number"&&isFinite(jitMasking)&&jitMasking>pos){maskTemplate.push(includeMode===false?test.nativeDef:getPlaceholder(pos,test))}}if(opts.keepStatic==="auto"){if(test.newBlockMarker&&test.fn!==null){opts.keepStatic=pos-1}}pos++}while((maxLength===undefined||pos<maxLength)&&(test.fn!==null||test.def!=="")||minimalPos>pos);if(maskTemplate[maskTemplate.length-1]===""){maskTemplate.pop()}if(includeMode!==false||getMaskSet().maskLength===undefined)getMaskSet().maskLength=pos-1;opts.greedy=greedy;return maskTemplate}function getMaskSet(){return maskset}function resetMaskSet(soft){var maskset=getMaskSet();maskset.buffer=undefined;if(soft!==true){maskset.validPositions={};maskset.p=0}}function getLastValidPosition(closestTo,strict,validPositions){var before=-1,after=-1,valids=validPositions||getMaskSet().validPositions;if(closestTo===undefined)closestTo=-1;for(var posNdx in valids){var psNdx=parseInt(posNdx);if(valids[psNdx]&&(strict||valids[psNdx].generatedInput!==true)){if(psNdx<=closestTo)before=psNdx;if(psNdx>=closestTo)after=psNdx}}return before===-1||before==closestTo?after:after==-1?before:closestTo-before<after-closestTo?before:after}function getDecisionTaker(tst){var decisionTaker=tst.locator[tst.alternation];if(typeof decisionTaker=="string"&&decisionTaker.length>0){decisionTaker=decisionTaker.split(",")[0]}return decisionTaker!==undefined?decisionTaker.toString():""}function getLocator(tst,align){var locator=(tst.alternation!=undefined?tst.mloc[getDecisionTaker(tst)]:tst.locator).join("");if(locator!=="")while(locator.length<align)locator+="0";return locator}function determineTestTemplate(pos,tests){pos=pos>0?pos-1:0;var altTest=getTest(pos),targetLocator=getLocator(altTest),tstLocator,closest,bestMatch;for(var ndx=0;ndx<tests.length;ndx++){var tst=tests[ndx];tstLocator=getLocator(tst,targetLocator.length);var distance=Math.abs(tstLocator-targetLocator);if(closest===undefined||tstLocator!==""&&distance<closest||bestMatch&&!opts.greedy&&bestMatch.match.optionality&&bestMatch.match.newBlockMarker==="master"&&(!tst.match.optionality||!tst.match.newBlockMarker)||bestMatch&&bestMatch.match.optionalQuantifier&&!tst.match.optionalQuantifier){closest=distance;bestMatch=tst}}return bestMatch}function getTestTemplate(pos,ndxIntlzr,tstPs){return getMaskSet().validPositions[pos]||determineTestTemplate(pos,getTests(pos,ndxIntlzr?ndxIntlzr.slice():ndxIntlzr,tstPs))}function getTest(pos,tests){if(getMaskSet().validPositions[pos]){return getMaskSet().validPositions[pos]}return(tests||getTests(pos))[0]}function positionCanMatchDefinition(pos,def){var valid=false,tests=getTests(pos);for(var tndx=0;tndx<tests.length;tndx++){if(tests[tndx].match&&tests[tndx].match.def===def){valid=true;break}}return valid}function getTests(pos,ndxIntlzr,tstPs){var maskTokens=getMaskSet().maskToken,testPos=ndxIntlzr?tstPs:0,ndxInitializer=ndxIntlzr?ndxIntlzr.slice():[0],matches=[],insertStop=false,latestMatch,cacheDependency=ndxIntlzr?ndxIntlzr.join(""):"";function resolveTestFromToken(maskToken,ndxInitializer,loopNdx,quantifierRecurse){function handleMatch(match,loopNdx,quantifierRecurse){function isFirstMatch(latestMatch,tokenGroup){var firstMatch=$.inArray(latestMatch,tokenGroup.matches)===0;if(!firstMatch){$.each(tokenGroup.matches,function(ndx,match){if(match.isQuantifier===true)firstMatch=isFirstMatch(latestMatch,tokenGroup.matches[ndx-1]);else if(match.hasOwnProperty("matches"))firstMatch=isFirstMatch(latestMatch,match);if(firstMatch)return false})}return firstMatch}function resolveNdxInitializer(pos,alternateNdx,targetAlternation){var bestMatch,indexPos;if(getMaskSet().tests[pos]||getMaskSet().validPositions[pos]){$.each(getMaskSet().tests[pos]||[getMaskSet().validPositions[pos]],function(ndx,lmnt){if(lmnt.mloc[alternateNdx]){bestMatch=lmnt;return false}var alternation=targetAlternation!==undefined?targetAlternation:lmnt.alternation,ndxPos=lmnt.locator[alternation]!==undefined?lmnt.locator[alternation].toString().indexOf(alternateNdx):-1;if((indexPos===undefined||ndxPos<indexPos)&&ndxPos!==-1){bestMatch=lmnt;indexPos=ndxPos}})}if(bestMatch){var bestMatchAltIndex=bestMatch.locator[bestMatch.alternation];var locator=bestMatch.mloc[alternateNdx]||bestMatch.mloc[bestMatchAltIndex]||bestMatch.locator;return locator.slice((targetAlternation!==undefined?targetAlternation:bestMatch.alternation)+1)}else{return targetAlternation!==undefined?resolveNdxInitializer(pos,alternateNdx):undefined}}function isSubsetOf(source,target){function expand(pattern){var expanded=[],start,end;for(var i=0,l=pattern.length;i<l;i++){if(pattern.charAt(i)==="-"){end=pattern.charCodeAt(i+1);while(++start<end)expanded.push(String.fromCharCode(start))}else{start=pattern.charCodeAt(i);expanded.push(pattern.charAt(i))}}return expanded.join("")}if(opts.regex&&source.match.fn!==null&&target.match.fn!==null){return expand(target.match.def.replace(/[\[\]]/g,"")).indexOf(expand(source.match.def.replace(/[\[\]]/g,"")))!==-1}return source.match.def===target.match.nativeDef}function staticCanMatchDefinition(source,target){var sloc=source.locator.slice(source.alternation).join(""),tloc=target.locator.slice(target.alternation).join(""),canMatch=sloc==tloc;canMatch=canMatch&&source.match.fn===null&&target.match.fn!==null?target.match.fn.test(source.match.def,getMaskSet(),pos,false,opts,false):false;return canMatch}function setMergeLocators(targetMatch,altMatch){if(altMatch===undefined||targetMatch.alternation===altMatch.alternation&&targetMatch.locator[targetMatch.alternation].toString().indexOf(altMatch.locator[altMatch.alternation])===-1){targetMatch.mloc=targetMatch.mloc||{};var locNdx=targetMatch.locator[targetMatch.alternation];if(locNdx===undefined)targetMatch.alternation=undefined;else{if(typeof locNdx==="string")locNdx=locNdx.split(",")[0];if(targetMatch.mloc[locNdx]===undefined)targetMatch.mloc[locNdx]=targetMatch.locator.slice();if(altMatch!==undefined){for(var ndx in altMatch.mloc){if(typeof ndx==="string")ndx=ndx.split(",")[0];if(targetMatch.mloc[ndx]===undefined)targetMatch.mloc[ndx]=altMatch.mloc[ndx]}targetMatch.locator[targetMatch.alternation]=Object.keys(targetMatch.mloc).join(",")}return true}}return false}if(testPos>500&&quantifierRecurse!==undefined){throw"Inputmask: There is probably an error in your mask definition or in the code. Create an issue on github with an example of the mask you are using. "+getMaskSet().mask}if(testPos===pos&&match.matches===undefined){matches.push({match:match,locator:loopNdx.reverse(),cd:cacheDependency,mloc:{}});return true}else if(match.matches!==undefined){if(match.isGroup&&quantifierRecurse!==match){match=handleMatch(maskToken.matches[$.inArray(match,maskToken.matches)+1],loopNdx,quantifierRecurse);if(match)return true}else if(match.isOptional){var optionalToken=match;match=resolveTestFromToken(match,ndxInitializer,loopNdx,quantifierRecurse);if(match){$.each(matches,function(ndx,mtch){mtch.match.optionality=true});latestMatch=matches[matches.length-1].match;if(quantifierRecurse===undefined&&isFirstMatch(latestMatch,optionalToken)){insertStop=true;testPos=pos}else return true}}else if(match.isAlternator){var alternateToken=match,malternateMatches=[],maltMatches,currentMatches=matches.slice(),loopNdxCnt=loopNdx.length;var altIndex=ndxInitializer.length>0?ndxInitializer.shift():-1;if(altIndex===-1||typeof altIndex==="string"){var currentPos=testPos,ndxInitializerClone=ndxInitializer.slice(),altIndexArr=[],amndx;if(typeof altIndex=="string"){altIndexArr=altIndex.split(",")}else{for(amndx=0;amndx<alternateToken.matches.length;amndx++){altIndexArr.push(amndx.toString())}}if(getMaskSet().excludes[pos]){var altIndexArrClone=altIndexArr.slice();for(var i=0,el=getMaskSet().excludes[pos].length;i<el;i++){altIndexArr.splice(altIndexArr.indexOf(getMaskSet().excludes[pos][i].toString()),1)}if(altIndexArr.length===0){getMaskSet().excludes[pos]=undefined;altIndexArr=altIndexArrClone}}if(opts.keepStatic===true||isFinite(parseInt(opts.keepStatic))&&currentPos>=opts.keepStatic)altIndexArr=altIndexArr.slice(0,1);var unMatchedAlternation=false;for(var ndx=0;ndx<altIndexArr.length;ndx++){amndx=parseInt(altIndexArr[ndx]);matches=[];ndxInitializer=typeof altIndex==="string"?resolveNdxInitializer(testPos,amndx,loopNdxCnt)||ndxInitializerClone.slice():ndxInitializerClone.slice();if(alternateToken.matches[amndx]&&handleMatch(alternateToken.matches[amndx],[amndx].concat(loopNdx),quantifierRecurse))match=true;else if(ndx===0){unMatchedAlternation=true}maltMatches=matches.slice();testPos=currentPos;matches=[];for(var ndx1=0;ndx1<maltMatches.length;ndx1++){var altMatch=maltMatches[ndx1],dropMatch=false;altMatch.match.jit=altMatch.match.jit||unMatchedAlternation;altMatch.alternation=altMatch.alternation||loopNdxCnt;setMergeLocators(altMatch);for(var ndx2=0;ndx2<malternateMatches.length;ndx2++){var altMatch2=malternateMatches[ndx2];if(typeof altIndex!=="string"||altMatch.alternation!==undefined&&$.inArray(altMatch.locator[altMatch.alternation].toString(),altIndexArr)!==-1){if(altMatch.match.nativeDef===altMatch2.match.nativeDef){dropMatch=true;setMergeLocators(altMatch2,altMatch);break}else if(isSubsetOf(altMatch,altMatch2)){if(setMergeLocators(altMatch,altMatch2)){dropMatch=true;malternateMatches.splice(malternateMatches.indexOf(altMatch2),0,altMatch)}break}else if(isSubsetOf(altMatch2,altMatch)){setMergeLocators(altMatch2,altMatch);break}else if(staticCanMatchDefinition(altMatch,altMatch2)){if(setMergeLocators(altMatch,altMatch2)){dropMatch=true;malternateMatches.splice(malternateMatches.indexOf(altMatch2),0,altMatch)}break}}}if(!dropMatch){malternateMatches.push(altMatch)}}}matches=currentMatches.concat(malternateMatches);testPos=pos;insertStop=matches.length>0;match=malternateMatches.length>0;ndxInitializer=ndxInitializerClone.slice()}else match=handleMatch(alternateToken.matches[altIndex]||maskToken.matches[altIndex],[altIndex].concat(loopNdx),quantifierRecurse);if(match)return true}else if(match.isQuantifier&&quantifierRecurse!==maskToken.matches[$.inArray(match,maskToken.matches)-1]){var qt=match;for(var qndx=ndxInitializer.length>0?ndxInitializer.shift():0;qndx<(isNaN(qt.quantifier.max)?qndx+1:qt.quantifier.max)&&testPos<=pos;qndx++){var tokenGroup=maskToken.matches[$.inArray(qt,maskToken.matches)-1];match=handleMatch(tokenGroup,[qndx].concat(loopNdx),tokenGroup);if(match){latestMatch=matches[matches.length-1].match;latestMatch.optionalQuantifier=qndx>=qt.quantifier.min;latestMatch.jit=(qndx||1)*tokenGroup.matches.indexOf(latestMatch)>=qt.quantifier.jit;if(latestMatch.optionalQuantifier&&isFirstMatch(latestMatch,tokenGroup)){insertStop=true;testPos=pos;break}if(latestMatch.jit){getMaskSet().jitOffset[pos]=tokenGroup.matches.indexOf(latestMatch)}return true}}}else{match=resolveTestFromToken(match,ndxInitializer,loopNdx,quantifierRecurse);if(match)return true}}else{testPos++}}for(var tndx=ndxInitializer.length>0?ndxInitializer.shift():0;tndx<maskToken.matches.length;tndx++){if(maskToken.matches[tndx].isQuantifier!==true){var match=handleMatch(maskToken.matches[tndx],[tndx].concat(loopNdx),quantifierRecurse);if(match&&testPos===pos){return match}else if(testPos>pos){break}}}}function mergeLocators(pos,tests){var locator=[];if(!$.isArray(tests))tests=[tests];if(tests.length>0){if(tests[0].alternation===undefined){locator=determineTestTemplate(pos,tests.slice()).locator.slice();if(locator.length===0)locator=tests[0].locator.slice()}else{$.each(tests,function(ndx,tst){if(tst.def!==""){if(locator.length===0)locator=tst.locator.slice();else{for(var i=0;i<locator.length;i++){if(tst.locator[i]&&locator[i].toString().indexOf(tst.locator[i])===-1){locator[i]+=","+tst.locator[i]}}}}})}}return locator}if(pos>-1){if(ndxIntlzr===undefined){var previousPos=pos-1,test;while((test=getMaskSet().validPositions[previousPos]||getMaskSet().tests[previousPos])===undefined&&previousPos>-1){previousPos--}if(test!==undefined&&previousPos>-1){ndxInitializer=mergeLocators(previousPos,test);cacheDependency=ndxInitializer.join("");testPos=previousPos}}if(getMaskSet().tests[pos]&&getMaskSet().tests[pos][0].cd===cacheDependency){return getMaskSet().tests[pos]}for(var mtndx=ndxInitializer.shift();mtndx<maskTokens.length;mtndx++){var match=resolveTestFromToken(maskTokens[mtndx],ndxInitializer,[mtndx]);if(match&&testPos===pos||testPos>pos){break}}}if(matches.length===0||insertStop){matches.push({match:{fn:null,optionality:false,casing:null,def:"",placeholder:""},locator:[],mloc:{},cd:cacheDependency})}if(ndxIntlzr!==undefined&&getMaskSet().tests[pos]){return $.extend(true,[],matches)}getMaskSet().tests[pos]=$.extend(true,[],matches);return getMaskSet().tests[pos]}function getBufferTemplate(){if(getMaskSet()._buffer===undefined){getMaskSet()._buffer=getMaskTemplate(false,1);if(getMaskSet().buffer===undefined)getMaskSet().buffer=getMaskSet()._buffer.slice()}return getMaskSet()._buffer}function getBuffer(noCache){if(getMaskSet().buffer===undefined||noCache===true){getMaskSet().buffer=getMaskTemplate(true,getLastValidPosition(),true);if(getMaskSet()._buffer===undefined)getMaskSet()._buffer=getMaskSet().buffer.slice()}return getMaskSet().buffer}function refreshFromBuffer(start,end,buffer){var i,p;if(start===true){resetMaskSet();start=0;end=buffer.length}else{for(i=start;i<end;i++){delete getMaskSet().validPositions[i]}}p=start;for(i=start;i<end;i++){resetMaskSet(true);if(buffer[i]!==opts.skipOptionalPartCharacter){var valResult=isValid(p,buffer[i],true,true);if(valResult!==false){resetMaskSet(true);p=valResult.caret!==undefined?valResult.caret:valResult.pos+1}}}}function casing(elem,test,pos){switch(opts.casing||test.casing){case"upper":elem=elem.toUpperCase();break;case"lower":elem=elem.toLowerCase();break;case"title":var posBefore=getMaskSet().validPositions[pos-1];if(pos===0||posBefore&&posBefore.input===String.fromCharCode(Inputmask.keyCode.SPACE)){elem=elem.toUpperCase()}else{elem=elem.toLowerCase()}break;default:if($.isFunction(opts.casing)){var args=Array.prototype.slice.call(arguments);args.push(getMaskSet().validPositions);elem=opts.casing.apply(this,args)}}return elem}function checkAlternationMatch(altArr1,altArr2,na){var altArrC=opts.greedy?altArr2:altArr2.slice(0,1),isMatch=false,naArr=na!==undefined?na.split(","):[],naNdx;for(var i=0;i<naArr.length;i++){if((naNdx=altArr1.indexOf(naArr[i]))!==-1){altArr1.splice(naNdx,1)}}for(var alndx=0;alndx<altArr1.length;alndx++){if($.inArray(altArr1[alndx],altArrC)!==-1){isMatch=true;break}}return isMatch}function alternate(pos,c,strict,fromSetValid,rAltPos){var validPsClone=$.extend(true,{},getMaskSet().validPositions),lastAlt,alternation,isValidRslt=false,altPos,prevAltPos,i,validPos,decisionPos,lAltPos=rAltPos!==undefined?rAltPos:getLastValidPosition();if(lAltPos===-1&&rAltPos===undefined){lastAlt=0;prevAltPos=getTest(lastAlt);alternation=prevAltPos.alternation}else{for(;lAltPos>=0;lAltPos--){altPos=getMaskSet().validPositions[lAltPos];if(altPos&&altPos.alternation!==undefined){if(prevAltPos&&prevAltPos.locator[altPos.alternation]!==altPos.locator[altPos.alternation]){break}lastAlt=lAltPos;alternation=getMaskSet().validPositions[lastAlt].alternation;prevAltPos=altPos}}}if(alternation!==undefined){decisionPos=parseInt(lastAlt);getMaskSet().excludes[decisionPos]=getMaskSet().excludes[decisionPos]||[];if(pos!==true){getMaskSet().excludes[decisionPos].push(getDecisionTaker(prevAltPos))}var validInputsClone=[],staticInputsBeforePos=0;for(i=decisionPos;i<getLastValidPosition(undefined,true)+1;i++){validPos=getMaskSet().validPositions[i];if(validPos&&validPos.generatedInput!==true){validInputsClone.push(validPos.input)}else if(i<pos)staticInputsBeforePos++;delete getMaskSet().validPositions[i]}while(getMaskSet().excludes[decisionPos]&&getMaskSet().excludes[decisionPos].length<10){var posOffset=staticInputsBeforePos*-1,validInputs=validInputsClone.slice();getMaskSet().tests[decisionPos]=undefined;resetMaskSet(true);isValidRslt=true;while(validInputs.length>0){var input=validInputs.shift();if(!(isValidRslt=isValid(getLastValidPosition(undefined,true)+1,input,false,fromSetValid,true))){break}}if(isValidRslt&&c!==undefined){var targetLvp=getLastValidPosition(pos)+1;for(i=decisionPos;i<getLastValidPosition()+1;i++){validPos=getMaskSet().validPositions[i];if((validPos===undefined||validPos.match.fn==null)&&i<pos+posOffset){posOffset++}}pos=pos+posOffset;isValidRslt=isValid(pos>targetLvp?targetLvp:pos,c,strict,fromSetValid,true)}if(!isValidRslt){resetMaskSet();prevAltPos=getTest(decisionPos);getMaskSet().validPositions=$.extend(true,{},validPsClone);if(getMaskSet().excludes[decisionPos]){var decisionTaker=getDecisionTaker(prevAltPos);if(getMaskSet().excludes[decisionPos].indexOf(decisionTaker)!==-1){isValidRslt=alternate(pos,c,strict,fromSetValid,decisionPos-1);break}getMaskSet().excludes[decisionPos].push(decisionTaker);for(i=decisionPos;i<getLastValidPosition(undefined,true)+1;i++)delete getMaskSet().validPositions[i]}else{isValidRslt=alternate(pos,c,strict,fromSetValid,decisionPos-1);break}}else break}}getMaskSet().excludes[decisionPos]=undefined;return isValidRslt}function isValid(pos,c,strict,fromSetValid,fromAlternate,validateOnly){function isSelection(posObj){return isRTL?posObj.begin-posObj.end>1||posObj.begin-posObj.end===1:posObj.end-posObj.begin>1||posObj.end-posObj.begin===1}strict=strict===true;var maskPos=pos;if(pos.begin!==undefined){maskPos=isRTL?pos.end:pos.begin}function _isValid(position,c,strict){var rslt=false;$.each(getTests(position),function(ndx,tst){var test=tst.match;getBuffer(true);rslt=test.fn!=null?test.fn.test(c,getMaskSet(),position,strict,opts,isSelection(pos)):(c===test.def||c===opts.skipOptionalPartCharacter)&&test.def!==""?{c:getPlaceholder(position,test,true)||test.def,pos:position}:false;if(rslt!==false){var elem=rslt.c!==undefined?rslt.c:c,validatedPos=position;elem=elem===opts.skipOptionalPartCharacter&&test.fn===null?getPlaceholder(position,test,true)||test.def:elem;if(rslt.remove!==undefined){if(!$.isArray(rslt.remove))rslt.remove=[rslt.remove];$.each(rslt.remove.sort(function(a,b){return b-a}),function(ndx,lmnt){revalidateMask({begin:lmnt,end:lmnt+1})})}if(rslt.insert!==undefined){if(!$.isArray(rslt.insert))rslt.insert=[rslt.insert];$.each(rslt.insert.sort(function(a,b){return a-b}),function(ndx,lmnt){isValid(lmnt.pos,lmnt.c,true,fromSetValid)})}if(rslt!==true&&rslt.pos!==undefined&&rslt.pos!==position){validatedPos=rslt.pos}if(rslt!==true&&rslt.pos===undefined&&rslt.c===undefined){return false}if(!revalidateMask(pos,$.extend({},tst,{input:casing(elem,test,validatedPos)}),fromSetValid,validatedPos)){rslt=false}return false}});return rslt}var result=true,positionsClone=$.extend(true,{},getMaskSet().validPositions);if($.isFunction(opts.preValidation)&&!strict&&fromSetValid!==true&&validateOnly!==true){result=opts.preValidation(getBuffer(),maskPos,c,isSelection(pos),opts,getMaskSet())}if(result===true){trackbackPositions(undefined,maskPos,true);if(maxLength===undefined||maskPos<maxLength){result=_isValid(maskPos,c,strict);if((!strict||fromSetValid===true)&&result===false&&validateOnly!==true){var currentPosValid=getMaskSet().validPositions[maskPos];if(currentPosValid&&currentPosValid.match.fn===null&&(currentPosValid.match.def===c||c===opts.skipOptionalPartCharacter)){result={caret:seekNext(maskPos)}}else{if((opts.insertMode||getMaskSet().validPositions[seekNext(maskPos)]===undefined)&&(!isMask(maskPos,true)||getMaskSet().jitOffset[maskPos])){if(getMaskSet().jitOffset[maskPos]&&getMaskSet().validPositions[seekNext(maskPos)]===undefined){result=isValid(maskPos+getMaskSet().jitOffset[maskPos],c,strict);if(result!==false)result.caret=maskPos}else for(var nPos=maskPos+1,snPos=seekNext(maskPos);nPos<=snPos;nPos++){result=_isValid(nPos,c,strict);if(result!==false){result=trackbackPositions(maskPos,result.pos!==undefined?result.pos:nPos)||result;maskPos=nPos;break}}}}}}if(result===false&&opts.keepStatic!==false&&(opts.regex==null||isComplete(getBuffer()))&&!strict&&fromAlternate!==true){result=alternate(maskPos,c,strict,fromSetValid)}if(result===true){result={pos:maskPos}}}if($.isFunction(opts.postValidation)&&result!==false&&!strict&&fromSetValid!==true&&validateOnly!==true){var postResult=opts.postValidation(getBuffer(true),pos.begin!==undefined?isRTL?pos.end:pos.begin:pos,result,opts);if(postResult!==undefined){if(postResult.refreshFromBuffer&&postResult.buffer){var refresh=postResult.refreshFromBuffer;refreshFromBuffer(refresh===true?refresh:refresh.start,refresh.end,postResult.buffer)}result=postResult===true?result:postResult}}if(result&&result.pos===undefined){result.pos=maskPos}if(result===false||validateOnly===true){resetMaskSet(true);getMaskSet().validPositions=$.extend(true,{},positionsClone)}return result}function trackbackPositions(originalPos,newPos,fillOnly){var result;if(originalPos===undefined){for(originalPos=newPos-1;originalPos>0;originalPos--){if(getMaskSet().validPositions[originalPos])break}}for(var ps=originalPos;ps<newPos;ps++){if(getMaskSet().validPositions[ps]===undefined&&!isMask(ps,true)){var vp=ps==0?getTest(ps):getMaskSet().validPositions[ps-1];if(vp){var tests=getTests(ps).slice();if(tests[tests.length-1].match.def==="")tests.pop();var bestMatch=determineTestTemplate(ps,tests);bestMatch=$.extend({},bestMatch,{input:getPlaceholder(ps,bestMatch.match,true)||bestMatch.match.def});bestMatch.generatedInput=true;revalidateMask(ps,bestMatch,true);if(fillOnly!==true){var cvpInput=getMaskSet().validPositions[newPos].input;getMaskSet().validPositions[newPos]=undefined;result=isValid(newPos,cvpInput,true,true)}}}}return result}function revalidateMask(pos,validTest,fromSetValid,validatedPos){function IsEnclosedStatic(pos,valids,selection){var posMatch=valids[pos];if(posMatch!==undefined&&(posMatch.match.fn===null&&posMatch.match.optionality!==true||posMatch.input===opts.radixPoint)){var prevMatch=selection.begin<=pos-1?valids[pos-1]&&valids[pos-1].match.fn===null&&valids[pos-1]:valids[pos-1],nextMatch=selection.end>pos+1?valids[pos+1]&&valids[pos+1].match.fn===null&&valids[pos+1]:valids[pos+1];return prevMatch&&nextMatch}return false}var begin=pos.begin!==undefined?pos.begin:pos,end=pos.end!==undefined?pos.end:pos;if(pos.begin>pos.end){begin=pos.end;end=pos.begin}validatedPos=validatedPos!==undefined?validatedPos:begin;if(begin!==end||opts.insertMode&&getMaskSet().validPositions[validatedPos]!==undefined&&fromSetValid===undefined){var positionsClone=$.extend(true,{},getMaskSet().validPositions),lvp=getLastValidPosition(undefined,true),i;getMaskSet().p=begin;for(i=lvp;i>=begin;i--){if(getMaskSet().validPositions[i]&&getMaskSet().validPositions[i].match.nativeDef==="+"){opts.isNegative=false}delete getMaskSet().validPositions[i]}var valid=true,j=validatedPos,vps=getMaskSet().validPositions,needsValidation=false,posMatch=j,i=j;if(validTest){getMaskSet().validPositions[validatedPos]=$.extend(true,{},validTest);posMatch++;j++;if(begin<end)i++}for(;i<=lvp;i++){var t=positionsClone[i];if(t!==undefined&&(i>=end||i>=begin&&t.generatedInput!==true&&IsEnclosedStatic(i,positionsClone,{begin:begin,end:end}))){while(getTest(posMatch).match.def!==""){if(needsValidation===false&&positionsClone[posMatch]&&positionsClone[posMatch].match.nativeDef===t.match.nativeDef){getMaskSet().validPositions[posMatch]=$.extend(true,{},positionsClone[posMatch]);getMaskSet().validPositions[posMatch].input=t.input;trackbackPositions(undefined,posMatch,true);j=posMatch+1;valid=true}else if(opts.shiftPositions&&positionCanMatchDefinition(posMatch,t.match.def)){var result=isValid(posMatch,t.input,true,true);valid=result!==false;j=result.caret||result.insert?getLastValidPosition():posMatch+1;needsValidation=true}else{valid=t.generatedInput===true||t.input===opts.radixPoint&&opts.numericInput===true}if(valid)break;if(!valid&&posMatch>end&&isMask(posMatch,true)&&(t.match.fn!==null||posMatch>getMaskSet().maskLength)){break}posMatch++}if(getTest(posMatch).match.def=="")valid=false;posMatch=j}if(!valid)break}if(!valid){getMaskSet().validPositions=$.extend(true,{},positionsClone);resetMaskSet(true);return false}}else if(validTest){getMaskSet().validPositions[validatedPos]=$.extend(true,{},validTest)}resetMaskSet(true);return true}function isMask(pos,strict){var test=getTestTemplate(pos).match;if(test.def==="")test=getTest(pos).match;if(test.fn!=null){return test.fn}if(strict!==true&&pos>-1){var tests=getTests(pos);return tests.length>1+(tests[tests.length-1].match.def===""?1:0)}return false}function seekNext(pos,newBlock){var position=pos+1;while(getTest(position).match.def!==""&&(newBlock===true&&(getTest(position).match.newBlockMarker!==true||!isMask(position))||newBlock!==true&&!isMask(position))){position++}return position}function seekPrevious(pos,newBlock){var position=pos,tests;if(position<=0)return 0;while(--position>0&&(newBlock===true&&getTest(position).match.newBlockMarker!==true||newBlock!==true&&!isMask(position)&&(tests=getTests(position),tests.length<2||tests.length===2&&tests[1].match.def===""))){}return position}function writeBuffer(input,buffer,caretPos,event,triggerEvents){if(event&&$.isFunction(opts.onBeforeWrite)){var result=opts.onBeforeWrite.call(inputmask,event,buffer,caretPos,opts);if(result){if(result.refreshFromBuffer){var refresh=result.refreshFromBuffer;refreshFromBuffer(refresh===true?refresh:refresh.start,refresh.end,result.buffer||buffer);buffer=getBuffer(true)}if(caretPos!==undefined)caretPos=result.caret!==undefined?result.caret:caretPos}}if(input!==undefined){input.inputmask._valueSet(buffer.join(""));if(caretPos!==undefined&&(event===undefined||event.type!=="blur")){caret(input,caretPos)}else renderColorMask(input,caretPos,buffer.length===0);if(triggerEvents===true){var $input=$(input),nptVal=input.inputmask._valueGet();skipInputEvent=true;$input.trigger("input");setTimeout(function(){if(nptVal===getBufferTemplate().join("")){$input.trigger("cleared")}else if(isComplete(buffer)===true){$input.trigger("complete")}},0)}}}function getPlaceholder(pos,test,returnPL){test=test||getTest(pos).match;if(test.placeholder!==undefined||returnPL===true){return $.isFunction(test.placeholder)?test.placeholder(opts):test.placeholder}else if(test.fn===null){if(pos>-1&&getMaskSet().validPositions[pos]===undefined){var tests=getTests(pos),staticAlternations=[],prevTest;if(tests.length>1+(tests[tests.length-1].match.def===""?1:0)){for(var i=0;i<tests.length;i++){if(tests[i].match.optionality!==true&&tests[i].match.optionalQuantifier!==true&&(tests[i].match.fn===null||(prevTest===undefined||tests[i].match.fn.test(prevTest.match.def,getMaskSet(),pos,true,opts)!==false))){staticAlternations.push(tests[i]);if(tests[i].match.fn===null)prevTest=tests[i];if(staticAlternations.length>1){if(/[0-9a-bA-Z]/.test(staticAlternations[0].match.def)){return opts.placeholder.charAt(pos%opts.placeholder.length)}}}}}}return test.def}return opts.placeholder.charAt(pos%opts.placeholder.length)}function HandleNativePlaceholder(npt,value){if(ie){if(npt.inputmask._valueGet()!==value&&(npt.placeholder!==value||npt.placeholder==="")){var buffer=getBuffer().slice(),nptValue=npt.inputmask._valueGet();if(nptValue!==value){var lvp=getLastValidPosition();if(lvp===-1&&nptValue===getBufferTemplate().join("")){buffer=[]}else if(lvp!==-1){clearOptionalTail(buffer)}writeBuffer(npt,buffer)}}}else if(npt.placeholder!==value){npt.placeholder=value;if(npt.placeholder==="")npt.removeAttribute("placeholder")}}var EventRuler={on:function(input,eventName,eventHandler){var ev=function(e){var that=this;if(that.inputmask===undefined&&this.nodeName!=="FORM"){var imOpts=$.data(that,"_inputmask_opts");if(imOpts)new Inputmask(imOpts).mask(that);else EventRuler.off(that)}else if(e.type!=="setvalue"&&this.nodeName!=="FORM"&&(that.disabled||that.readOnly&&!(e.type==="keydown"&&(e.ctrlKey&&e.keyCode===67)||opts.tabThrough===false&&e.keyCode===Inputmask.keyCode.TAB))){e.preventDefault()}else{switch(e.type){case"input":if(skipInputEvent===true){skipInputEvent=false;return e.preventDefault()}if(mobile){var args=arguments;setTimeout(function(){eventHandler.apply(that,args);caret(that,that.inputmask.caretPos,undefined,true)},0);return false}break;case"keydown":skipKeyPressEvent=false;skipInputEvent=false;break;case"keypress":if(skipKeyPressEvent===true){return e.preventDefault()}skipKeyPressEvent=true;break;case"click":if(iemobile||iphone){var args=arguments;setTimeout(function(){eventHandler.apply(that,args)},0);return false}break}var returnVal=eventHandler.apply(that,arguments);if(returnVal===false){e.preventDefault();e.stopPropagation()}return returnVal}};input.inputmask.events[eventName]=input.inputmask.events[eventName]||[];input.inputmask.events[eventName].push(ev);if($.inArray(eventName,["submit","reset"])!==-1){if(input.form!==null)$(input.form).on(eventName,ev)}else{$(input).on(eventName,ev)}},off:function(input,event){if(input.inputmask&&input.inputmask.events){var events;if(event){events=[];events[event]=input.inputmask.events[event]}else{events=input.inputmask.events}$.each(events,function(eventName,evArr){while(evArr.length>0){var ev=evArr.pop();if($.inArray(eventName,["submit","reset"])!==-1){if(input.form!==null)$(input.form).off(eventName,ev)}else{$(input).off(eventName,ev)}}delete input.inputmask.events[eventName]})}}};var EventHandlers={keydownEvent:function(e){var input=this,$input=$(input),k=e.keyCode,pos=caret(input);if(k===Inputmask.keyCode.BACKSPACE||k===Inputmask.keyCode.DELETE||iphone&&k===Inputmask.keyCode.BACKSPACE_SAFARI||e.ctrlKey&&k===Inputmask.keyCode.X&&!isInputEventSupported("cut")){e.preventDefault();handleRemove(input,k,pos);writeBuffer(input,getBuffer(true),getMaskSet().p,e,input.inputmask._valueGet()!==getBuffer().join(""))}else if(k===Inputmask.keyCode.END||k===Inputmask.keyCode.PAGE_DOWN){e.preventDefault();var caretPos=seekNext(getLastValidPosition());caret(input,e.shiftKey?pos.begin:caretPos,caretPos,true)}else if(k===Inputmask.keyCode.HOME&&!e.shiftKey||k===Inputmask.keyCode.PAGE_UP){e.preventDefault();caret(input,0,e.shiftKey?pos.begin:0,true)}else if((opts.undoOnEscape&&k===Inputmask.keyCode.ESCAPE||k===90&&e.ctrlKey)&&e.altKey!==true){checkVal(input,true,false,undoValue.split(""));$input.trigger("click")}else if(k===Inputmask.keyCode.INSERT&&!(e.shiftKey||e.ctrlKey)){opts.insertMode=!opts.insertMode;input.setAttribute("im-insert",opts.insertMode)}else if(opts.tabThrough===true&&k===Inputmask.keyCode.TAB){if(e.shiftKey===true){if(getTest(pos.begin).match.fn===null){pos.begin=seekNext(pos.begin)}pos.end=seekPrevious(pos.begin,true);pos.begin=seekPrevious(pos.end,true)}else{pos.begin=seekNext(pos.begin,true);pos.end=seekNext(pos.begin,true);if(pos.end<getMaskSet().maskLength)pos.end--}if(pos.begin<getMaskSet().maskLength){e.preventDefault();caret(input,pos.begin,pos.end)}}opts.onKeyDown.call(this,e,getBuffer(),caret(input).begin,opts);ignorable=$.inArray(k,opts.ignorables)!==-1},keypressEvent:function(e,checkval,writeOut,strict,ndx){var input=this,$input=$(input),k=e.which||e.charCode||e.keyCode;if(checkval!==true&&(!(e.ctrlKey&&e.altKey)&&(e.ctrlKey||e.metaKey||ignorable))){if(k===Inputmask.keyCode.ENTER&&undoValue!==getBuffer().join("")){undoValue=getBuffer().join("");setTimeout(function(){$input.trigger("change")},0)}return true}else{if(k){if(k===46&&e.shiftKey===false&&opts.radixPoint!=="")k=opts.radixPoint.charCodeAt(0);var pos=checkval?{begin:ndx,end:ndx}:caret(input),forwardPosition,c=String.fromCharCode(k),offset=0;if(opts._radixDance&&opts.numericInput){var caretPos=getBuffer().indexOf(opts.radixPoint.charAt(0))+1;if(pos.begin<=caretPos){if(k===opts.radixPoint.charCodeAt(0))offset=1;pos.begin-=1;pos.end-=1}}getMaskSet().writeOutBuffer=true;var valResult=isValid(pos,c,strict);if(valResult!==false){resetMaskSet(true);forwardPosition=valResult.caret!==undefined?valResult.caret:seekNext(valResult.pos.begin?valResult.pos.begin:valResult.pos);getMaskSet().p=forwardPosition}forwardPosition=(opts.numericInput&&valResult.caret===undefined?seekPrevious(forwardPosition):forwardPosition)+offset;if(writeOut!==false){setTimeout(function(){opts.onKeyValidation.call(input,k,valResult,opts)},0);if(getMaskSet().writeOutBuffer&&valResult!==false){var buffer=getBuffer();writeBuffer(input,buffer,forwardPosition,e,checkval!==true)}}e.preventDefault();if(checkval){if(valResult!==false)valResult.forwardPosition=forwardPosition;return valResult}}}},pasteEvent:function(e){var input=this,ev=e.originalEvent||e,$input=$(input),inputValue=input.inputmask._valueGet(true),caretPos=caret(input),tempValue;if(isRTL){tempValue=caretPos.end;caretPos.end=caretPos.begin;caretPos.begin=tempValue}var valueBeforeCaret=inputValue.substr(0,caretPos.begin),valueAfterCaret=inputValue.substr(caretPos.end,inputValue.length);if(valueBeforeCaret===(isRTL?getBufferTemplate().reverse():getBufferTemplate()).slice(0,caretPos.begin).join(""))valueBeforeCaret="";if(valueAfterCaret===(isRTL?getBufferTemplate().reverse():getBufferTemplate()).slice(caretPos.end).join(""))valueAfterCaret="";if(window.clipboardData&&window.clipboardData.getData){inputValue=valueBeforeCaret+window.clipboardData.getData("Text")+valueAfterCaret}else if(ev.clipboardData&&ev.clipboardData.getData){inputValue=valueBeforeCaret+ev.clipboardData.getData("text/plain")+valueAfterCaret}else return true;var pasteValue=inputValue;if($.isFunction(opts.onBeforePaste)){pasteValue=opts.onBeforePaste.call(inputmask,inputValue,opts);if(pasteValue===false){return e.preventDefault()}if(!pasteValue){pasteValue=inputValue}}checkVal(input,false,false,pasteValue.toString().split(""));writeBuffer(input,getBuffer(),seekNext(getLastValidPosition()),e,undoValue!==getBuffer().join(""));return e.preventDefault()},inputFallBackEvent:function(e){function radixPointHandler(input,inputValue,caretPos){if(inputValue.charAt(caretPos.begin-1)==="."&&opts.radixPoint!==""){inputValue=inputValue.split("");inputValue[caretPos.begin-1]=opts.radixPoint.charAt(0);inputValue=inputValue.join("")}return inputValue}function ieMobileHandler(input,inputValue,caretPos){if(iemobile){var inputChar=inputValue.replace(getBuffer().join(""),"");if(inputChar.length===1){var iv=inputValue.split("");iv.splice(caretPos.begin,0,inputChar);inputValue=iv.join("")}}return inputValue}var input=this,inputValue=input.inputmask._valueGet();if(getBuffer().join("")!==inputValue){var caretPos=caret(input);inputValue=radixPointHandler(input,inputValue,caretPos);inputValue=ieMobileHandler(input,inputValue,caretPos);if(getBuffer().join("")!==inputValue){var buffer=getBuffer().join(""),offset=!opts.numericInput&&inputValue.length>buffer.length?-1:0,frontPart=inputValue.substr(0,caretPos.begin),backPart=inputValue.substr(caretPos.begin),frontBufferPart=buffer.substr(0,caretPos.begin+offset),backBufferPart=buffer.substr(caretPos.begin+offset);var selection=caretPos,entries="",isEntry=false;if(frontPart!==frontBufferPart){var fpl=(isEntry=frontPart.length>=frontBufferPart.length)?frontPart.length:frontBufferPart.length,i;for(i=0;frontPart.charAt(i)===frontBufferPart.charAt(i)&&i<fpl;i++);if(isEntry){selection.begin=i-offset;entries+=frontPart.slice(i,selection.end)}}if(backPart!==backBufferPart){if(backPart.length>backBufferPart.length){entries+=backPart.slice(0,1)}else{if(backPart.length<backBufferPart.length){selection.end+=backBufferPart.length-backPart.length;if(!isEntry&&opts.radixPoint!==""&&backPart===""&&frontPart.charAt(selection.begin+offset-1)===opts.radixPoint){selection.begin--;entries=opts.radixPoint}}}}writeBuffer(input,getBuffer(),{begin:selection.begin+offset,end:selection.end+offset});if(entries.length>0){$.each(entries.split(""),function(ndx,entry){var keypress=new $.Event("keypress");keypress.which=entry.charCodeAt(0);ignorable=false;EventHandlers.keypressEvent.call(input,keypress)})}else{if(selection.begin===selection.end-1){selection.begin=seekPrevious(selection.begin+1);if(selection.begin===selection.end-1){caret(input,selection.begin)}else{caret(input,selection.begin,selection.end)}}var keydown=new $.Event("keydown");keydown.keyCode=opts.numericInput?Inputmask.keyCode.BACKSPACE:Inputmask.keyCode.DELETE;EventHandlers.keydownEvent.call(input,keydown)}e.preventDefault()}}},beforeInputEvent:function(e){if(e.cancelable){var input=this;switch(e.inputType){case"insertText":$.each(e.data.split(""),function(ndx,entry){var keypress=new $.Event("keypress");keypress.which=entry.charCodeAt(0);ignorable=false;EventHandlers.keypressEvent.call(input,keypress)});return e.preventDefault();case"deleteContentBackward":var keydown=new $.Event("keydown");keydown.keyCode=Inputmask.keyCode.BACKSPACE;EventHandlers.keydownEvent.call(input,keydown);return e.preventDefault();case"deleteContentForward":var keydown=new $.Event("keydown");keydown.keyCode=Inputmask.keyCode.DELETE;EventHandlers.keydownEvent.call(input,keydown);return e.preventDefault()}}},setValueEvent:function(e){this.inputmask.refreshValue=false;var input=this,value=e&&e.detail?e.detail[0]:arguments[1],value=value||input.inputmask._valueGet(true);if($.isFunction(opts.onBeforeMask))value=opts.onBeforeMask.call(inputmask,value,opts)||value;value=value.toString().split("");checkVal(input,true,false,value);undoValue=getBuffer().join("");if((opts.clearMaskOnLostFocus||opts.clearIncomplete)&&input.inputmask._valueGet()===getBufferTemplate().join("")){input.inputmask._valueSet("")}},focusEvent:function(e){var input=this,nptValue=input.inputmask._valueGet();if(opts.showMaskOnFocus){if(nptValue!==getBuffer().join("")){writeBuffer(input,getBuffer(),seekNext(getLastValidPosition()))}else if(mouseEnter===false){caret(input,seekNext(getLastValidPosition()))}}if(opts.positionCaretOnTab===true&&mouseEnter===false){EventHandlers.clickEvent.apply(input,[e,true])}undoValue=getBuffer().join("")},mouseleaveEvent:function(e){var input=this;mouseEnter=false;if(opts.clearMaskOnLostFocus&&document.activeElement!==input){HandleNativePlaceholder(input,originalPlaceholder)}},clickEvent:function(e,tabbed){function doRadixFocus(clickPos){if(opts.radixPoint!==""){var vps=getMaskSet().validPositions;if(vps[clickPos]===undefined||vps[clickPos].input===getPlaceholder(clickPos)){if(clickPos<seekNext(-1))return true;var radixPos=$.inArray(opts.radixPoint,getBuffer());if(radixPos!==-1){for(var vp in vps){if(radixPos<vp&&vps[vp].input!==getPlaceholder(vp)){return false}}return true}}}return false}var input=this;setTimeout(function(){if(document.activeElement===input){var selectedCaret=caret(input);if(tabbed){if(isRTL){selectedCaret.end=selectedCaret.begin}else{selectedCaret.begin=selectedCaret.end}}if(selectedCaret.begin===selectedCaret.end){switch(opts.positionCaretOnClick){case"none":break;case"select":caret(input,0,getBuffer().length);break;case"ignore":caret(input,seekNext(getLastValidPosition()));break;case"radixFocus":if(doRadixFocus(selectedCaret.begin)){var radixPos=getBuffer().join("").indexOf(opts.radixPoint);caret(input,opts.numericInput?seekNext(radixPos):radixPos);break}default:var clickPosition=selectedCaret.begin,lvclickPosition=getLastValidPosition(clickPosition,true),lastPosition=seekNext(lvclickPosition);if(clickPosition<lastPosition){caret(input,!isMask(clickPosition,true)&&!isMask(clickPosition-1,true)?seekNext(clickPosition):clickPosition)}else{var lvp=getMaskSet().validPositions[lvclickPosition],tt=getTestTemplate(lastPosition,lvp?lvp.match.locator:undefined,lvp),placeholder=getPlaceholder(lastPosition,tt.match);if(placeholder!==""&&getBuffer()[lastPosition]!==placeholder&&tt.match.optionalQuantifier!==true&&tt.match.newBlockMarker!==true||!isMask(lastPosition,opts.keepStatic)&&tt.match.def===placeholder){var newPos=seekNext(lastPosition);if(clickPosition>=newPos||clickPosition===lastPosition){lastPosition=newPos}}caret(input,lastPosition)}break}}}},0)},cutEvent:function(e){var input=this,$input=$(input),pos=caret(input),ev=e.originalEvent||e;var clipboardData=window.clipboardData||ev.clipboardData,clipData=isRTL?getBuffer().slice(pos.end,pos.begin):getBuffer().slice(pos.begin,pos.end);clipboardData.setData("text",isRTL?clipData.reverse().join(""):clipData.join(""));if(document.execCommand)document.execCommand("copy");handleRemove(input,Inputmask.keyCode.DELETE,pos);writeBuffer(input,getBuffer(),getMaskSet().p,e,undoValue!==getBuffer().join(""))},blurEvent:function(e){var $input=$(this),input=this;if(input.inputmask){HandleNativePlaceholder(input,originalPlaceholder);var nptValue=input.inputmask._valueGet(),buffer=getBuffer().slice();if(nptValue!==""||colorMask!==undefined){if(opts.clearMaskOnLostFocus){if(getLastValidPosition()===-1&&nptValue===getBufferTemplate().join("")){buffer=[]}else{clearOptionalTail(buffer)}}if(isComplete(buffer)===false){setTimeout(function(){$input.trigger("incomplete")},0);if(opts.clearIncomplete){resetMaskSet();if(opts.clearMaskOnLostFocus){buffer=[]}else{buffer=getBufferTemplate().slice()}}}writeBuffer(input,buffer,undefined,e)}if(undoValue!==getBuffer().join("")){undoValue=buffer.join("");$input.trigger("change")}}},mouseenterEvent:function(e){var input=this;mouseEnter=true;if(document.activeElement!==input&&opts.showMaskOnHover){HandleNativePlaceholder(input,(isRTL?getBuffer().slice().reverse():getBuffer()).join(""))}},submitEvent:function(e){if(undoValue!==getBuffer().join("")){$el.trigger("change")}if(opts.clearMaskOnLostFocus&&getLastValidPosition()===-1&&el.inputmask._valueGet&&el.inputmask._valueGet()===getBufferTemplate().join("")){el.inputmask._valueSet("")}if(opts.clearIncomplete&&isComplete(getBuffer())===false){el.inputmask._valueSet("")}if(opts.removeMaskOnSubmit){el.inputmask._valueSet(el.inputmask.unmaskedvalue(),true);setTimeout(function(){writeBuffer(el,getBuffer())},0)}},resetEvent:function(e){el.inputmask.refreshValue=true;setTimeout(function(){$el.trigger("setvalue")},0)}};function checkVal(input,writeOut,strict,nptvl,initiatingEvent){var inputmask=this||input.inputmask,inputValue=nptvl.slice(),charCodes="",initialNdx=-1,result=undefined;function isTemplateMatch(ndx,charCodes){var charCodeNdx=getMaskTemplate(true,0,false).slice(ndx,seekNext(ndx)).join("").replace(/'/g,"").indexOf(charCodes);return charCodeNdx!==-1&&!isMask(ndx)&&(getTest(ndx).match.nativeDef===charCodes.charAt(0)||getTest(ndx).match.fn===null&&getTest(ndx).match.nativeDef==="'"+charCodes.charAt(0)||getTest(ndx).match.nativeDef===" "&&(getTest(ndx+1).match.nativeDef===charCodes.charAt(0)||getTest(ndx+1).match.fn===null&&getTest(ndx+1).match.nativeDef==="'"+charCodes.charAt(0)))}resetMaskSet();if(!strict&&opts.autoUnmask!==true){var staticInput=getBufferTemplate().slice(0,seekNext(-1)).join(""),matches=inputValue.join("").match(new RegExp("^"+Inputmask.escapeRegex(staticInput),"g"));if(matches&&matches.length>0){inputValue.splice(0,matches.length*staticInput.length);initialNdx=seekNext(initialNdx)}}else{initialNdx=seekNext(initialNdx)}if(initialNdx===-1){getMaskSet().p=seekNext(initialNdx);initialNdx=0}else getMaskSet().p=initialNdx;inputmask.caretPos={begin:initialNdx};$.each(inputValue,function(ndx,charCode){if(charCode!==undefined){if(getMaskSet().validPositions[ndx]===undefined&&inputValue[ndx]===getPlaceholder(ndx)&&isMask(ndx,true)&&isValid(ndx,inputValue[ndx],true,undefined,undefined,true)===false){getMaskSet().p++}else{var keypress=new $.Event("_checkval");keypress.which=charCode.charCodeAt(0);charCodes+=charCode;var lvp=getLastValidPosition(undefined,true);if(!isTemplateMatch(initialNdx,charCodes)){result=EventHandlers.keypressEvent.call(input,keypress,true,false,strict,inputmask.caretPos.begin);if(result){initialNdx=inputmask.caretPos.begin+1;charCodes=""}}else{result=EventHandlers.keypressEvent.call(input,keypress,true,false,strict,lvp+1)}if(result){writeBuffer(undefined,getBuffer(),result.forwardPosition,keypress,false);inputmask.caretPos={begin:result.forwardPosition,end:result.forwardPosition}}}}});if(writeOut)writeBuffer(input,getBuffer(),result?result.forwardPosition:undefined,initiatingEvent||new $.Event("checkval"),initiatingEvent&&initiatingEvent.type==="input")}function unmaskedvalue(input){if(input){if(input.inputmask===undefined){return input.value}if(input.inputmask&&input.inputmask.refreshValue){EventHandlers.setValueEvent.call(input)}}var umValue=[],vps=getMaskSet().validPositions;for(var pndx in vps){if(vps[pndx].match&&vps[pndx].match.fn!=null){umValue.push(vps[pndx].input)}}var unmaskedValue=umValue.length===0?"":(isRTL?umValue.reverse():umValue).join("");if($.isFunction(opts.onUnMask)){var bufferValue=(isRTL?getBuffer().slice().reverse():getBuffer()).join("");unmaskedValue=opts.onUnMask.call(inputmask,bufferValue,unmaskedValue,opts)}return unmaskedValue}function caret(input,begin,end,notranslate){function translatePosition(pos){if(isRTL&&typeof pos==="number"&&(!opts.greedy||opts.placeholder!=="")&&el){pos=el.inputmask._valueGet().length-pos}return pos}var range;if(begin!==undefined){if($.isArray(begin)){end=isRTL?begin[0]:begin[1];begin=isRTL?begin[1]:begin[0]}if(begin.begin!==undefined){end=isRTL?begin.begin:begin.end;begin=isRTL?begin.end:begin.begin}if(typeof begin==="number"){begin=notranslate?begin:translatePosition(begin);end=notranslate?end:translatePosition(end);end=typeof end=="number"?end:begin;var scrollCalc=parseInt(((input.ownerDocument.defaultView||window).getComputedStyle?(input.ownerDocument.defaultView||window).getComputedStyle(input,null):input.currentStyle).fontSize)*end;input.scrollLeft=scrollCalc>input.scrollWidth?scrollCalc:0;input.inputmask.caretPos={begin:begin,end:end};if(input===document.activeElement){if("selectionStart"in input){input.selectionStart=begin;input.selectionEnd=end}else if(window.getSelection){range=document.createRange();if(input.firstChild===undefined||input.firstChild===null){var textNode=document.createTextNode("");input.appendChild(textNode)}range.setStart(input.firstChild,begin<input.inputmask._valueGet().length?begin:input.inputmask._valueGet().length);range.setEnd(input.firstChild,end<input.inputmask._valueGet().length?end:input.inputmask._valueGet().length);range.collapse(true);var sel=window.getSelection();sel.removeAllRanges();sel.addRange(range)}else if(input.createTextRange){range=input.createTextRange();range.collapse(true);range.moveEnd("character",end);range.moveStart("character",begin);range.select()}renderColorMask(input,{begin:begin,end:end})}}}else{if("selectionStart"in input){begin=input.selectionStart;end=input.selectionEnd}else if(window.getSelection){range=window.getSelection().getRangeAt(0);if(range.commonAncestorContainer.parentNode===input||range.commonAncestorContainer===input){begin=range.startOffset;end=range.endOffset}}else if(document.selection&&document.selection.createRange){range=document.selection.createRange();begin=0-range.duplicate().moveStart("character",-input.inputmask._valueGet().length);end=begin+range.text.length}return{begin:notranslate?begin:translatePosition(begin),end:notranslate?end:translatePosition(end)}}}function determineLastRequiredPosition(returnDefinition){var buffer=getMaskTemplate(true,getLastValidPosition(),true,true),bl=buffer.length,pos,lvp=getLastValidPosition(),positions={},lvTest=getMaskSet().validPositions[lvp],ndxIntlzr=lvTest!==undefined?lvTest.locator.slice():undefined,testPos;for(pos=lvp+1;pos<buffer.length;pos++){testPos=getTestTemplate(pos,ndxIntlzr,pos-1);ndxIntlzr=testPos.locator.slice();positions[pos]=$.extend(true,{},testPos)}var lvTestAlt=lvTest&&lvTest.alternation!==undefined?lvTest.locator[lvTest.alternation]:undefined;for(pos=bl-1;pos>lvp;pos--){testPos=positions[pos];if((testPos.match.optionality||testPos.match.optionalQuantifier&&testPos.match.newBlockMarker||lvTestAlt&&(lvTestAlt!==positions[pos].locator[lvTest.alternation]&&testPos.match.fn!=null||testPos.match.fn===null&&testPos.locator[lvTest.alternation]&&checkAlternationMatch(testPos.locator[lvTest.alternation].toString().split(","),lvTestAlt.toString().split(","))&&getTests(pos)[0].def!==""))&&buffer[pos]===getPlaceholder(pos,testPos.match)){bl--}else break}return returnDefinition?{l:bl,def:positions[bl]?positions[bl].match:undefined}:bl}function clearOptionalTail(buffer){buffer.length=0;var template=getMaskTemplate(true,0,true,undefined,true),lmnt,validPos;while(lmnt=template.shift(),lmnt!==undefined)buffer.push(lmnt);return buffer}function isComplete(buffer){if($.isFunction(opts.isComplete))return opts.isComplete(buffer,opts);if(opts.repeat==="*")return undefined;var complete=false,lrp=determineLastRequiredPosition(true),aml=seekPrevious(lrp.l);if(lrp.def===undefined||lrp.def.newBlockMarker||lrp.def.optionality||lrp.def.optionalQuantifier){complete=true;for(var i=0;i<=aml;i++){var test=getTestTemplate(i).match;if(test.fn!==null&&getMaskSet().validPositions[i]===undefined&&test.optionality!==true&&test.optionalQuantifier!==true||test.fn===null&&buffer[i]!==getPlaceholder(i,test)){complete=false;break}}}return complete}function handleRemove(input,k,pos,strict,fromIsValid){if(opts.numericInput||isRTL){if(k===Inputmask.keyCode.BACKSPACE){k=Inputmask.keyCode.DELETE}else if(k===Inputmask.keyCode.DELETE){k=Inputmask.keyCode.BACKSPACE}if(isRTL){var pend=pos.end;pos.end=pos.begin;pos.begin=pend}}if(k===Inputmask.keyCode.BACKSPACE&&pos.end-pos.begin<1){pos.begin=seekPrevious(pos.begin);if(getMaskSet().validPositions[pos.begin]!==undefined&&getMaskSet().validPositions[pos.begin].input===opts.groupSeparator){pos.begin--}}else if(k===Inputmask.keyCode.DELETE&&pos.begin===pos.end){pos.end=isMask(pos.end,true)&&(getMaskSet().validPositions[pos.end]&&getMaskSet().validPositions[pos.end].input!==opts.radixPoint)?pos.end+1:seekNext(pos.end)+1;if(getMaskSet().validPositions[pos.begin]!==undefined&&getMaskSet().validPositions[pos.begin].input===opts.groupSeparator){pos.end++}}revalidateMask(pos);if(strict!==true&&opts.keepStatic!==false||opts.regex!==null){var result=alternate(true);if(result){var newPos=result.caret!==undefined?result.caret:result.pos?seekNext(result.pos.begin?result.pos.begin:result.pos):getLastValidPosition(-1,true);if(k!==Inputmask.keyCode.DELETE||pos.begin>newPos){pos.begin==newPos}}}var lvp=getLastValidPosition(pos.begin,true);if(lvp<pos.begin||pos.begin===-1){getMaskSet().p=seekNext(lvp)}else if(strict!==true){getMaskSet().p=pos.begin;if(fromIsValid!==true){while(getMaskSet().p<lvp&&getMaskSet().validPositions[getMaskSet().p]===undefined){getMaskSet().p++}}}}function initializeColorMask(input){var computedStyle=(input.ownerDocument.defaultView||window).getComputedStyle(input,null);function findCaretPos(clientx){var e=document.createElement("span"),caretPos;for(var style in computedStyle){if(isNaN(style)&&style.indexOf("font")!==-1){e.style[style]=computedStyle[style]}}e.style.textTransform=computedStyle.textTransform;e.style.letterSpacing=computedStyle.letterSpacing;e.style.position="absolute";e.style.height="auto";e.style.width="auto";e.style.visibility="hidden";e.style.whiteSpace="nowrap";document.body.appendChild(e);var inputText=input.inputmask._valueGet(),previousWidth=0,itl;for(caretPos=0,itl=inputText.length;caretPos<=itl;caretPos++){e.innerHTML+=inputText.charAt(caretPos)||"_";if(e.offsetWidth>=clientx){var offset1=clientx-previousWidth;var offset2=e.offsetWidth-clientx;e.innerHTML=inputText.charAt(caretPos);offset1-=e.offsetWidth/3;caretPos=offset1<offset2?caretPos-1:caretPos;break}previousWidth=e.offsetWidth}document.body.removeChild(e);return caretPos}var template=document.createElement("div");template.style.width=computedStyle.width;template.style.textAlign=computedStyle.textAlign;colorMask=document.createElement("div");input.inputmask.colorMask=colorMask;colorMask.className="im-colormask";input.parentNode.insertBefore(colorMask,input);input.parentNode.removeChild(input);colorMask.appendChild(input);colorMask.appendChild(template);input.style.left=template.offsetLeft+"px";$(colorMask).on("mouseleave",function(e){return EventHandlers.mouseleaveEvent.call(input,[e])});$(colorMask).on("mouseenter",function(e){return EventHandlers.mouseenterEvent.call(input,[e])});$(colorMask).on("click",function(e){caret(input,findCaretPos(e.clientX));return EventHandlers.clickEvent.call(input,[e])})}function renderColorMask(input,caretPos,clear){var maskTemplate=[],isStatic=false,test,testPos,ndxIntlzr,pos=0;function setEntry(entry){if(entry===undefined)entry="";if(!isStatic&&(test.fn===null||testPos.input===undefined)){isStatic=true;maskTemplate.push("<span class='im-static'>"+entry)}else if(isStatic&&(test.fn!==null&&testPos.input!==undefined||test.def==="")){isStatic=false;var mtl=maskTemplate.length;maskTemplate[mtl-1]=maskTemplate[mtl-1]+"</span>";maskTemplate.push(entry)}else maskTemplate.push(entry)}function setCaret(){if(document.activeElement===input){maskTemplate.splice(caretPos.begin,0,caretPos.begin===caretPos.end||caretPos.end>getMaskSet().maskLength?'<mark class="im-caret" style="border-right-width: 1px;border-right-style: solid;">':'<mark class="im-caret-select">');maskTemplate.splice(caretPos.end+1,0,"</mark>")}}if(colorMask!==undefined){var buffer=getBuffer();if(caretPos===undefined){caretPos=caret(input)}else if(caretPos.begin===undefined){caretPos={begin:caretPos,end:caretPos}}if(clear!==true){var lvp=getLastValidPosition();do{if(getMaskSet().validPositions[pos]){testPos=getMaskSet().validPositions[pos];test=testPos.match;ndxIntlzr=testPos.locator.slice();setEntry(buffer[pos])}else{testPos=getTestTemplate(pos,ndxIntlzr,pos-1);test=testPos.match;ndxIntlzr=testPos.locator.slice();if(opts.jitMasking===false||pos<lvp||typeof opts.jitMasking==="number"&&isFinite(opts.jitMasking)&&opts.jitMasking>pos){setEntry(getPlaceholder(pos,test))}else isStatic=false}pos++}while((maxLength===undefined||pos<maxLength)&&(test.fn!==null||test.def!=="")||lvp>pos||isStatic);if(isStatic)setEntry();setCaret()}var template=colorMask.getElementsByTagName("div")[0];template.innerHTML=maskTemplate.join("");input.inputmask.positionColorMask(input,template)}}function mask(elem){function isElementTypeSupported(input,opts){function patchValueProperty(npt){var valueGet;var valueSet;function patchValhook(type){if($.valHooks&&($.valHooks[type]===undefined||$.valHooks[type].inputmaskpatch!==true)){var valhookGet=$.valHooks[type]&&$.valHooks[type].get?$.valHooks[type].get:function(elem){return elem.value};var valhookSet=$.valHooks[type]&&$.valHooks[type].set?$.valHooks[type].set:function(elem,value){elem.value=value;return elem};$.valHooks[type]={get:function(elem){if(elem.inputmask){if(elem.inputmask.opts.autoUnmask){return elem.inputmask.unmaskedvalue()}else{var result=valhookGet(elem);return getLastValidPosition(undefined,undefined,elem.inputmask.maskset.validPositions)!==-1||opts.nullable!==true?result:""}}else return valhookGet(elem)},set:function(elem,value){var $elem=$(elem),result;result=valhookSet(elem,value);if(elem.inputmask){$elem.trigger("setvalue",[value])}return result},inputmaskpatch:true}}}function getter(){if(this.inputmask){return this.inputmask.opts.autoUnmask?this.inputmask.unmaskedvalue():getLastValidPosition()!==-1||opts.nullable!==true?document.activeElement===this&&opts.clearMaskOnLostFocus?(isRTL?clearOptionalTail(getBuffer().slice()).reverse():clearOptionalTail(getBuffer().slice())).join(""):valueGet.call(this):""}else return valueGet.call(this)}function setter(value){valueSet.call(this,value);if(this.inputmask){$(this).trigger("setvalue",[value])}}function installNativeValueSetFallback(npt){EventRuler.on(npt,"mouseenter",function(event){var $input=$(this),input=this,value=input.inputmask._valueGet();if(value!==getBuffer().join("")){$input.trigger("setvalue")}})}if(!npt.inputmask.__valueGet){if(opts.noValuePatching!==true){if(Object.getOwnPropertyDescriptor){if(typeof Object.getPrototypeOf!=="function"){Object.getPrototypeOf=typeof"test".__proto__==="object"?function(object){return object.__proto__}:function(object){return object.constructor.prototype}}var valueProperty=Object.getPrototypeOf?Object.getOwnPropertyDescriptor(Object.getPrototypeOf(npt),"value"):undefined;if(valueProperty&&valueProperty.get&&valueProperty.set){valueGet=valueProperty.get;valueSet=valueProperty.set;Object.defineProperty(npt,"value",{get:getter,set:setter,configurable:true})}else if(npt.tagName!=="INPUT"){valueGet=function(){return this.textContent};valueSet=function(value){this.textContent=value};Object.defineProperty(npt,"value",{get:getter,set:setter,configurable:true})}}else if(document.__lookupGetter__&&npt.__lookupGetter__("value")){valueGet=npt.__lookupGetter__("value");valueSet=npt.__lookupSetter__("value");npt.__defineGetter__("value",getter);npt.__defineSetter__("value",setter)}npt.inputmask.__valueGet=valueGet;npt.inputmask.__valueSet=valueSet}npt.inputmask._valueGet=function(overruleRTL){return isRTL&&overruleRTL!==true?valueGet.call(this.el).split("").reverse().join(""):valueGet.call(this.el)};npt.inputmask._valueSet=function(value,overruleRTL){valueSet.call(this.el,value===null||value===undefined?"":overruleRTL!==true&&isRTL?value.split("").reverse().join(""):value)};if(valueGet===undefined){valueGet=function(){return this.value};valueSet=function(value){this.value=value};patchValhook(npt.type);installNativeValueSetFallback(npt)}}}var elementType=input.getAttribute("type");var isSupported=input.tagName==="INPUT"&&$.inArray(elementType,opts.supportsInputType)!==-1||input.isContentEditable||input.tagName==="TEXTAREA";if(!isSupported){if(input.tagName==="INPUT"){var el=document.createElement("input");el.setAttribute("type",elementType);isSupported=el.type==="text";el=null}else isSupported="partial"}if(isSupported!==false){patchValueProperty(input)}else input.inputmask=undefined;return isSupported}EventRuler.off(elem);var isSupported=isElementTypeSupported(elem,opts);if(isSupported!==false){el=elem;$el=$(el);originalPlaceholder=el.placeholder;maxLength=el!==undefined?el.maxLength:undefined;if(maxLength===-1)maxLength=undefined;if(opts.colorMask===true){initializeColorMask(el)}if(mobile){if("inputmode"in el){el.inputmode=opts.inputmode;el.setAttribute("inputmode",opts.inputmode)}if(opts.disablePredictiveText===true){if("autocorrect"in el){el.autocorrect=false}else{if(opts.colorMask!==true){initializeColorMask(el)}el.type="password"}}}if(isSupported===true){el.setAttribute("im-insert",opts.insertMode);EventRuler.on(el,"submit",EventHandlers.submitEvent);EventRuler.on(el,"reset",EventHandlers.resetEvent);EventRuler.on(el,"blur",EventHandlers.blurEvent);EventRuler.on(el,"focus",EventHandlers.focusEvent);if(opts.colorMask!==true){EventRuler.on(el,"click",EventHandlers.clickEvent);EventRuler.on(el,"mouseleave",EventHandlers.mouseleaveEvent);EventRuler.on(el,"mouseenter",EventHandlers.mouseenterEvent)}EventRuler.on(el,"paste",EventHandlers.pasteEvent);EventRuler.on(el,"cut",EventHandlers.cutEvent);EventRuler.on(el,"complete",opts.oncomplete);EventRuler.on(el,"incomplete",opts.onincomplete);EventRuler.on(el,"cleared",opts.oncleared);if(!mobile&&opts.inputEventOnly!==true){EventRuler.on(el,"keydown",EventHandlers.keydownEvent);EventRuler.on(el,"keypress",EventHandlers.keypressEvent)}else{el.removeAttribute("maxLength")}EventRuler.on(el,"input",EventHandlers.inputFallBackEvent);EventRuler.on(el,"beforeinput",EventHandlers.beforeInputEvent)}EventRuler.on(el,"setvalue",EventHandlers.setValueEvent);undoValue=getBufferTemplate().join("");if(el.inputmask._valueGet(true)!==""||opts.clearMaskOnLostFocus===false||document.activeElement===el){var initialValue=$.isFunction(opts.onBeforeMask)?opts.onBeforeMask.call(inputmask,el.inputmask._valueGet(true),opts)||el.inputmask._valueGet(true):el.inputmask._valueGet(true);if(initialValue!=="")checkVal(el,true,false,initialValue.split(""));var buffer=getBuffer().slice();undoValue=buffer.join("");if(isComplete(buffer)===false){if(opts.clearIncomplete){resetMaskSet()}}if(opts.clearMaskOnLostFocus&&document.activeElement!==el){if(getLastValidPosition()===-1){buffer=[]}else{clearOptionalTail(buffer)}}if(opts.clearMaskOnLostFocus===false||opts.showMaskOnFocus&&document.activeElement===el||el.inputmask._valueGet(true)!=="")writeBuffer(el,buffer);if(document.activeElement===el){caret(el,seekNext(getLastValidPosition()))}}}}var valueBuffer;if(actionObj!==undefined){switch(actionObj.action){case"isComplete":el=actionObj.el;return isComplete(getBuffer());case"unmaskedvalue":if(el===undefined||actionObj.value!==undefined){valueBuffer=actionObj.value;valueBuffer=($.isFunction(opts.onBeforeMask)?opts.onBeforeMask.call(inputmask,valueBuffer,opts)||valueBuffer:valueBuffer).split("");checkVal.call(this,undefined,false,false,valueBuffer);if($.isFunction(opts.onBeforeWrite))opts.onBeforeWrite.call(inputmask,undefined,getBuffer(),0,opts)}return unmaskedvalue(el);case"mask":mask(el);break;case"format":valueBuffer=($.isFunction(opts.onBeforeMask)?opts.onBeforeMask.call(inputmask,actionObj.value,opts)||actionObj.value:actionObj.value).split("");checkVal.call(this,undefined,true,false,valueBuffer);if(actionObj.metadata){return{value:isRTL?getBuffer().slice().reverse().join(""):getBuffer().join(""),metadata:maskScope.call(this,{action:"getmetadata"},maskset,opts)}}return isRTL?getBuffer().slice().reverse().join(""):getBuffer().join("");case"isValid":if(actionObj.value){valueBuffer=actionObj.value.split("");checkVal.call(this,undefined,true,true,valueBuffer)}else{actionObj.value=getBuffer().join("")}var buffer=getBuffer();var rl=determineLastRequiredPosition(),lmib=buffer.length-1;for(;lmib>rl;lmib--){if(isMask(lmib))break}buffer.splice(rl,lmib+1-rl);return isComplete(buffer)&&actionObj.value===getBuffer().join("");case"getemptymask":return getBufferTemplate().join("");case"remove":if(el&&el.inputmask){$.data(el,"_inputmask_opts",null);$el=$(el);el.inputmask._valueSet(opts.autoUnmask?unmaskedvalue(el):el.inputmask._valueGet(true));EventRuler.off(el);if(el.inputmask.colorMask){colorMask=el.inputmask.colorMask;colorMask.removeChild(el);colorMask.parentNode.insertBefore(el,colorMask);colorMask.parentNode.removeChild(colorMask)}var valueProperty;if(Object.getOwnPropertyDescriptor&&Object.getPrototypeOf){valueProperty=Object.getOwnPropertyDescriptor(Object.getPrototypeOf(el),"value");if(valueProperty){if(el.inputmask.__valueGet){Object.defineProperty(el,"value",{get:el.inputmask.__valueGet,set:el.inputmask.__valueSet,configurable:true})}}}else if(document.__lookupGetter__&&el.__lookupGetter__("value")){if(el.inputmask.__valueGet){el.__defineGetter__("value",el.inputmask.__valueGet);el.__defineSetter__("value",el.inputmask.__valueSet)}}el.inputmask=undefined}return el;break;case"getmetadata":if($.isArray(maskset.metadata)){var maskTarget=getMaskTemplate(true,0,false).join("");$.each(maskset.metadata,function(ndx,mtdt){if(mtdt.mask===maskTarget){maskTarget=mtdt;return false}});return maskTarget}return maskset.metadata}}}return Inputmask});;
/*!
* jquery.inputmask.js
* https://github.com/RobinHerbots/Inputmask
* Copyright (c) 2010 - 2019 Robin Herbots
* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
* Version: 4.0.7
*/

(function(factory) {
    if (typeof define === "function" && define.amd) {
        define([ "jquery", "./inputmask" ], factory);
    } else if (typeof exports === "object") {
        module.exports = factory(require("jquery"), require("./inputmask"));
    } else {
        factory(jQuery, window.Inputmask);
    }
})(function($, Inputmask) {
    if ($.fn.inputmask === undefined) {
        $.fn.inputmask = function(fn, options) {
            var nptmask, input = this[0];
            if (options === undefined) options = {};
            if (typeof fn === "string") {
                switch (fn) {
                  case "unmaskedvalue":
                    return input && input.inputmask ? input.inputmask.unmaskedvalue() : $(input).val();

                  case "remove":
                    return this.each(function() {
                        if (this.inputmask) this.inputmask.remove();
                    });

                  case "getemptymask":
                    return input && input.inputmask ? input.inputmask.getemptymask() : "";

                  case "hasMaskedValue":
                    return input && input.inputmask ? input.inputmask.hasMaskedValue() : false;

                  case "isComplete":
                    return input && input.inputmask ? input.inputmask.isComplete() : true;

                  case "getmetadata":
                    return input && input.inputmask ? input.inputmask.getmetadata() : undefined;

                  case "setvalue":
                    Inputmask.setValue(input, options);
                    break;

                  case "option":
                    if (typeof options === "string") {
                        if (input && input.inputmask !== undefined) {
                            return input.inputmask.option(options);
                        }
                    } else {
                        return this.each(function() {
                            if (this.inputmask !== undefined) {
                                return this.inputmask.option(options);
                            }
                        });
                    }
                    break;

                  default:
                    options.alias = fn;
                    nptmask = new Inputmask(options);
                    return this.each(function() {
                        nptmask.mask(this);
                    });
                }
            } else if (Array.isArray(fn)) {
                options.alias = fn;
                nptmask = new Inputmask(options);
                return this.each(function() {
                    nptmask.mask(this);
                });
            } else if (typeof fn == "object") {
                nptmask = new Inputmask(fn);
                if (fn.mask === undefined && fn.alias === undefined) {
                    return this.each(function() {
                        if (this.inputmask !== undefined) {
                            return this.inputmask.option(fn);
                        } else nptmask.mask(this);
                    });
                } else {
                    return this.each(function() {
                        nptmask.mask(this);
                    });
                }
            } else if (fn === undefined) {
                return this.each(function() {
                    nptmask = new Inputmask(options);
                    nptmask.mask(this);
                });
            }
        };
    }
    return $.fn.inputmask;
});;
/**
 * Autotab - jQuery plugin 1.9.2
 * https://github.com/Mathachew/jquery-autotab
 * 
 * Copyright (c) 2008, 2015 Matthew Miller
 * 
 * Licensed under the MIT licensing:
 *   http://www.opensource.org/licenses/mit-license.php
 */

(function ($) {
    var platform = navigator.platform,
        settings = {
            tabPause: 800,
            focusChange: null,
            iOS: (platform === 'iPad' || platform === 'iPhone' || platform === 'iPod'),
            firefox: (typeof InstallTrigger !== 'undefined'),
            ie11: !(window.ActiveXObject) && "ActiveXObject" in window
        };

    var setSettings = function (e, settings) {
        if (settings === null || typeof settings === 'undefined') {
            return;
        }

        for (var key in settings) {
            $(e).data('autotab-' + key, settings[key]);
        }
    };

    var getSettings = function (e) {
        var settings = {
            arrowKey: false,
            format: 'all',
            loaded: false,
            disabled: false,
            pattern: null,
            uppercase: false,
            lowercase: false,
            nospace: false,
            maxlength: 2147483647,
            target: null,
            previous: null,
            trigger: null,
            originalValue: '',
            changed: false,
            editable: (e.type === 'text' || e.type === 'password' || e.type === 'textarea' || e.type === 'tel' || e.type === 'number' || e.type === 'email' || e.type === 'search' || e.type === 'url'),
            filterable: (e.type === 'text' || e.type === 'password' || e.type === 'textarea'),
            tabOnSelect: false
        };

        // If $.autotab.selectFilterByClas is true and the format not specified, automatically select an element's format based on a matching class name.
        // The first matched element becomes the selected format for the filter.
        if ($.autotab.selectFilterByClass === true && typeof $(e).data('autotab-format') === 'undefined') {
            var classes = ['all', 'text', 'alpha', 'number', 'numeric', 'alphanumeric', 'hex', 'hexadecimal', 'custom'];

            for (var key in classes) {
                if ($(e).hasClass(classes[key])) {
                    settings.format = classes[key];
                    break;
                }
            }
        }

        for (var key in settings) {
            if (typeof $(e).data('autotab-' + key) !== 'undefined') {
                settings[key] = $(e).data('autotab-' + key);
            }
        }

        // Save settings on first run
        if (!settings.loaded) {
            if (settings.trigger !== null && typeof settings.trigger === 'string') {
                settings.trigger = settings.trigger.toString();
            }

            setSettings(e, settings);
        }

        return settings;
    };

    var queryObject = function (e) {
        return (typeof e !== 'undefined' && (typeof e === 'string' || !(e instanceof jQuery)));
    };

    var getSelection = function (e) {
        var start = 0,
            end = 0,
            selectionType = 0;

        if (e.type === 'text' || e.type === 'password' || e.type === 'textarea') {
            if (typeof e.selectionStart === 'number' && typeof e.selectionEnd === 'number') {
                // Non-IE browsers and IE 9+
                start = e.selectionStart;
                end = e.selectionEnd;
                selectionType = 1;
            }
            else if (document.selection && document.selection.createRange) {
                // For IE up to version 8
                var selectionRange = document.selection.createRange(),
                    textInputRange = e.createTextRange(),
                    precedingRange = e.createTextRange(),
                    bookmark = selectionRange.getBookmark();
                textInputRange.moveToBookmark(bookmark);
                precedingRange.setEndPoint("EndToStart", textInputRange);
                start = precedingRange.text.length;
                end = start + selectionRange.text.length;
                selectionType = 2;
            }
        }

        return {
            start: start,
            end: end,
            selectionType: selectionType
        };
    };

    $.autotab = function (options) {
        if (typeof options !== 'object') {
            options = {};
        }

        $(':input').autotab(options);
    };

    $.autotab.selectFilterByClass = false;

    $.autotab.next = function () {
        var e = $(document.activeElement);

        if (e.length) {
            e.trigger('autotab-next');
        }
    };

    $.autotab.previous = function () {
        var e = $(document.activeElement);

        if (e.length) {
            e.trigger('autotab-previous');
        }
    };

    $.autotab.remove = function (e) {
        queryObject(e) ? $(e).autotab('remove') : $(':input').autotab('remove');
    };

    $.autotab.restore = function (e) {
        queryObject(e) ? $(e).autotab('restore') : $(':input').autotab('restore');
    };

    $.autotab.refresh = function (e) {
        queryObject(e) ? $(e).autotab('refresh') : $(':input').autotab('refresh');
    };

    $.fn.autotab = function (method, options) {
        if (!this.length) {
            return this;
        }

        // Remove hidden fields since tabbing backwards is supported on different form elements
        var filtered = $.grep(this, function (e, i) {
            return e.type != 'hidden';
        });

        // Apply filter options
        if (method == 'filter') {
            if (typeof options === 'string' || typeof options === 'function') {
                options = { format: options };
            }

            for (var i = 0, length = filtered.length; i < length; i++) {
                var defaults = getSettings(filtered[i]),
                    newOptions = options;

                // Retain the established target/previous values as this area is for filtering only
                newOptions.target = defaults.target;
                newOptions.previous = defaults.previous;

                $.extend(defaults, newOptions);

                if (!defaults.loaded) {
                    defaults.disabled = true;
                    autotabBind(filtered[i], newOptions);
                }
                else {
                    setSettings(filtered[i], defaults);
                }
            }
        }
        // Disable auto tab and filtering
        else if (method == 'remove' || method == 'destroy' || method == 'disable') {
            for (var i = 0, length = filtered.length; i < length; i++) {
                var defaults = getSettings(filtered[i]);

                defaults.disabled = true;

                setSettings(filtered[i], defaults);
            }
        }
        // Re-enable auto tab and filtering
        else if (method == 'restore' || method == 'enable') {
            for (var i = 0, length = filtered.length; i < length; i++) {
                var defaults = getSettings(filtered[i]);

                defaults.disabled = false;

                setSettings(filtered[i], defaults);
            }
        }
        // Refresh target/previous elements
        else if (method == 'refresh') {
            for (var i = 0, length = filtered.length; i < length; i++) {
                var defaults = getSettings(filtered[i]),
                    n = i + 1,
                    p = i - 1,
                    selectTarget = function () {
                        if (i > 0 && n < length) {
                            defaults.target = filtered[n];
                        }
                        else if (i > 0) {
                            defaults.target = null;
                        }
                        else {
                            defaults.target = filtered[n];
                        }   
                    },
                    selectPrevious = function () {
                        if (i > 0 && n < length) {
                            defaults.previous = filtered[p];
                        }
                        else if (i > 0) {
                            defaults.previous = filtered[p];
                        }
                        else {
                            defaults.previous = null;
                        }
                    };

                // Nothing was specified for the target element, so automatically set it
                if (defaults.target === null || defaults.target.selector === '') {
                    selectTarget();
                }
                else if (typeof defaults.target === 'string' || defaults.target.selector) {
                    defaults.target = $(typeof defaults.target === 'string' ? defaults.target : defaults.target.selector);

                    if (defaults.target.length === 0) {
                        selectTarget();
                    }
                }

                // Nothing was specified for the previous element, so automatically set it
                if (defaults.previous === null || defaults.previous.selector === '') {
                    selectPrevious();
                }
                else if (typeof defaults.previous === 'string' || defaults.previous.selector) {
                    defaults.previous = $(typeof defaults.previous === 'string' ? defaults.previous : defaults.previous.selector);

                    if (defaults.previous.length === 0) {
                        selectPrevious();
                    }
                }

                if (!defaults.loaded) {
                    autotabBind(filtered[i], defaults);
                }
                else {
                    if (queryObject(defaults.target)) {
                        defaults.target = $(defaults.target);
                    }

                    if (queryObject(defaults.previous)) {
                        defaults.previous = $(defaults.previous);
                    }

                    setSettings(filtered[i], defaults);
                }
            }
        }
        else {
            if (method === null || typeof method === 'undefined') {
                options = {};
            }
            else if (typeof method === 'string' || typeof method === 'function') {
                options = { format: method };
            }
            else if (typeof method === 'object') {
                options = method;
            }

            // Bind key events to element(s) passed
            if (filtered.length > 1) {
                for (var i = 0, length = filtered.length; i < length; i++) {
                    var n = i + 1,
                        p = i - 1,
                        newOptions = options;

                    if (i > 0 && n < length) {
                        newOptions.target = filtered[n];
                        newOptions.previous = filtered[p];
                    }
                    else if (i > 0) {
                        newOptions.target = null;
                        newOptions.previous = filtered[p];
                    }
                    else {
                        newOptions.target = filtered[n];
                        newOptions.previous = null;
                    }

                    autotabBind(filtered[i], newOptions);
                }
            }
            else {
                autotabBind(filtered[0], options);
            }
        }

        return this;
    };

    var filterValue = function (e, value, defaults) {
        if (typeof defaults.format === 'function') {
            return defaults.format(value, e);
        }

        var pattern = null;

        switch (defaults.format) {
            case 'text':
                pattern = new RegExp('[0-9]+', 'g');
                break;

            case 'alpha':
                pattern = new RegExp('[^a-zA-Z]+', 'g');
                break;

            case 'number':
            case 'numeric':
                pattern = new RegExp('[^0-9]+', 'g');
                break;

            case 'alphanumeric':
                pattern = new RegExp('[^0-9a-zA-Z]+', 'g');
                break;

            case 'hex':
            case 'hexadecimal':
                pattern = new RegExp('[^0-9A-Fa-f]+', 'g');
                break;

            case 'custom':
                pattern = new RegExp(defaults.pattern, 'g');
                break;

            case 'all':
            default:
                break;
        }

        if (pattern !== null) {
            value = value.replace(pattern, '');
        }

        if (defaults.nospace) {
            pattern = new RegExp('[ ]+', 'g');
            value = value.replace(pattern, '');
        }

        if (defaults.uppercase) {
            value = value.toUpperCase();
        }

        if (defaults.lowercase) {
            value = value.toLowerCase();
        }

        return value;
    };

    var autotabBind = function (element, options) {
        var defaults = getSettings(element);

        if (defaults.disabled) {
            defaults.disabled = false;
            defaults.target = null;
            defaults.previous = null;
        }

        $.extend(defaults, options);

        // Sets targets to element based on the name or ID passed if they are not currently objects
        if (queryObject(defaults.target)) {
            defaults.target = $(defaults.target);
        }

        if (queryObject(defaults.previous)) {
            defaults.previous = $(defaults.previous);
        }

        var oldMaxlength = element.maxLength;

        if (typeof element.maxLength === 'undefined' && element.type == 'textarea') {
            oldMaxlength = element.maxLength = element.getAttribute('maxlength');
        }

        // defaults.maxlength has not changed and maxlength was specified
        if (defaults.maxlength == 2147483647 && oldMaxlength != 2147483647 && oldMaxlength != -1) {
            defaults.maxlength = oldMaxlength;
        }
        // defaults.maxlength overrides maxlength
        else if (defaults.maxlength > 0) {
            element.maxLength = defaults.maxlength;
        }
        // defaults.maxlength and maxlength have not been specified
        // A target cannot be used since there is no defined maxlength
        else {
            defaults.target = null;
        }

        if (!defaults.loaded) {
            defaults.loaded = true;
            setSettings(element, defaults);
        }
        else {
            setSettings(element, defaults);
            return;
        }

        // Add a change event to select lists only so that we can auto tab when a value is selected
        if (element.type == 'select-one') {
            $(element).on('change', function (e) {
                var defaults = getSettings(this);

                if (defaults.tabOnSelect) {
                    $(this).trigger('autotab-next');
                }
            });
        }

        // The 1ms timeouts allow for keypress events to complete in case a
        // custom function or exterior method calls for a manual auto tab
        $(element).on('autotab-next', function (event, defaults) {
            var self = this;
            setTimeout(function () {
                if (!defaults) {
                    defaults = getSettings(self);
                }

                var target = defaults.target;

                if (!defaults.disabled && target.length) {
                    // Using focus on iOS devices is a pain, so use the browser's next/previous buttons to proceed
                    if (!settings.iOS) {

                        // Field is disabled/readonly, so tab to next element
                        if (target.prop('disabled') || target.prop('readonly')) {
                            target.trigger('autotab-next');
                        }
                        else {
                            // Allows the user to navigate between each charater with arrow keys
                            if (defaults.arrowKey) {
                                target.focus();
                            }
                            else {
                                target.focus().select();
                            }
                        }

                        settings.focusChange = new Date();
                    }
                }
            }, 1);
        }).on('autotab-previous', function (event, defaults) {
            var self = this;
            setTimeout(function () {
                if (!defaults) {
                    defaults = getSettings(self);
                }

                var previous = defaults.previous;

                if (!defaults.disabled && previous.length) {
                    var value = previous.val();

                    // Field is disabled/readonly, so tab to previous element
                    if (previous.prop('disabled') || previous.prop('readonly')) {
                        previous.trigger('autotab-previous');
                    }
                    else if (value.length && previous.data('autotab-editable') && !defaults.arrowKey) {
                        if (settings.ie11) {
                            previous.val(value.substring(0, value.length - 1)).focus();
                        }
                        else {
                            previous.focus().val(value.substring(0, value.length - 1));
                        }

                        setSettings(previous, { changed: true });
                    }
                    else {
                        if (defaults.arrowKey) {
                            setSettings(this, { arrowKey: false });
                        }

                        if (settings.ie11) {
                            previous.val(value).focus();
                        }
                        else {
                            previous.focus().val(value);
                        }
                    }

                    settings.focusChange = null;
                }
            }, 1);
        }).on('focus', function () {
            setSettings(this, { originalValue: this.value });
        }).on('blur', function () {
            var defaults = getSettings(this);

            if (defaults.changed && this.value != defaults.originalValue) {
                setSettings(this, { changed: false });
                $(this).change();
            }
        }).on('keydown.autotab', function (e) {
            var defaults = getSettings(this);

            if (!defaults || defaults.disabled) {
                return true;
            }

            var selection = getSelection(this),
                keyCode = e.which || e.charCode;

            // Go to the previous element when backspace
            // is pressed in an empty input field
            if (keyCode == 8) {
                defaults.arrowKey = false;

                // Prevent the browser from of navigating to the previous page
                if (!defaults.editable) {
                    $(this).trigger('autotab-previous', defaults);
                    return false;
                }

                setSettings(this, { changed: (this.value !== defaults.originalValue) });

                if (this.value.length === 0) {
                    $(this).trigger('autotab-previous', defaults);
                    return;
                }
            }
            else if (keyCode == 9 && settings.focusChange !== null) {
                // Tab backwards
                if (e.shiftKey) {
                    settings.focusChange = null;
                    return;
                }

                if ((new Date().getTime() - settings.focusChange.getTime()) < settings.tabPause) {
                    settings.focusChange = null;
                    return false;
                }
            }
            else if (this.type !== 'range' && this.type !== 'select-one' && this.type !== 'select-multiple') {
                if ((this.type !== 'tel' && this.type !== 'number') || ((this.type === 'tel' || this.type === 'number') && this.value.length == 0)) {
                    if (keyCode == 37 && (!defaults.editable || selection.start == 0)) {
                        defaults.arrowKey = true;
                        $(this).trigger('autotab-previous', defaults);
                    }
                    else if (keyCode == 39 && (!defaults.editable || !defaults.filterable || selection.end == this.value.length || this.value.length == 0)) {
                        defaults.arrowKey = true;
                        $(this).trigger('autotab-next', defaults);
                    }
                }
            }
        }).on('keypress.autotab', function (e) {
            var defaults = getSettings(this),
                keyCode = e.which || e.keyCode;

            // e.charCode == 0 indicates a special key has been pressed, which only Firefox triggers
            if (!defaults || defaults.disabled || (settings.firefox && e.charCode === 0) || e.ctrlKey || e.altKey || keyCode == 13 || this.disabled) {
                return true;
            }

            var keyChar = String.fromCharCode(keyCode);

            if (this.type != 'text' && this.type != 'password' && this.type != 'textarea') {
                // this.value.length is the length before the keypress event was trigged
                if ((this.value.length + 1) >= defaults.maxlength) {
                    defaults.arrowKey = false;
                    $(this).trigger('autotab-next', defaults);
                }

                return !(this.value.length == defaults.maxlength);
            }

            // Prevents auto tabbing when defaults.trigger is pressed
            if (defaults.trigger !== null && defaults.trigger.indexOf(keyChar) >= 0) {
                if (settings.focusChange !== null && (new Date().getTime() - settings.focusChange.getTime()) < settings.tabPause) {
                    settings.focusChange = null;
                }
                else {
                    defaults.arrowKey = false;
                    $(this).trigger('autotab-next', defaults);
                }

                return false;
            }

            settings.focusChange = null;

            var hasValue = document.selection && document.selection.createRange ? true : (keyCode > 0);

            keyChar = filterValue(this, keyChar, defaults);

            if (hasValue && (keyChar === null || keyChar === '')) {
                return false;
            }

            // Many, many thanks to Tim Down for this solution: http://stackoverflow.com/a/3923320/94656
            if (hasValue && (this.value.length <= this.maxLength)) {
                var selection = getSelection(this);

                // Text is fully selected, so it needs to be replaced
                if (selection.start === 0 && selection.end == this.value.length) {
                    this.value = keyChar;
                    setSettings(this, { changed: (this.value != defaults.originalValue) });
                }
                else {
                    if (this.value.length == this.maxLength && selection.start === selection.end) {
                        defaults.arrowKey = false;
                        $(this).trigger('autotab-next', defaults);
                        return false;
                    }

                    this.value = this.value.slice(0, selection.start) + keyChar + this.value.slice(selection.end);
                    setSettings(this, { changed: (this.value != defaults.originalValue) });
                }

                // Prevents the cursor position from being set to the end of the text box
                // This is called even if the text is fully selected and replaced due to an unexpected behavior in IE6 and up (#32)
                if (this.value.length != defaults.maxlength) {
                    selection.start++;

                    if (selection.selectionType == 1) {
                        this.selectionStart = this.selectionEnd = selection.start;
                    }
                    else if (selection.selectionType == 2) {
                        var range = this.createTextRange();
                        range.collapse(true);
                        range.moveEnd('character', selection.start);
                        range.moveStart('character', selection.start);
                        range.select();
                    }
                }
            }


            if (this.value.length == defaults.maxlength) {
                defaults.arrowKey = false;
                $(this).trigger('autotab-next', defaults);
            }

            return false;
        }).on('drop paste', function (e) {
            var defaults = getSettings(this);

            if (!defaults) {
                return true;
            }

            this.maxLength = 2147483647;

            (function (e, originDefaults) {
                setTimeout(function () {
                    var lastIndex = -1,
                        hiddenInput = document.createElement('input');
                    hiddenInput.type = 'hidden';
                    hiddenInput.value = e.value.toLowerCase();
                    hiddenInput.originalValue = e.value;

                    e.value = filterValue(e, e.value, originDefaults).substr(0, originDefaults.maxlength);

                    var handlePaste = function (e, previousValue) {
                        if (!e) {
                            return;
                        }

                        var defaults = getSettings(e);

                        if ($(e).prop('disabled') || $(e).prop('readonly') || !defaults.editable) {
                            $(e).trigger('autotab-next');

                            if (!settings.iOS) {
                                handlePaste(defaults.target[0], previousValue);
                            }
                            return;
                        }

                        for (var i = 0, count = previousValue.length; i < count; i++) {
                            lastIndex = hiddenInput.value.indexOf(previousValue.charAt(i).toLowerCase(), lastIndex) + 1;
                        }

                        var trimmedValue = hiddenInput.originalValue.substr(lastIndex),
                            filteredValue = filterValue(e, trimmedValue, defaults).substr(0, defaults.maxlength);

                        if (!filteredValue) {
                            return;
                        }

                        e.value = filteredValue;

                        if (filteredValue.length == defaults.maxlength) {
                            defaults.arrowKey = false;
                            $(e).trigger('autotab-next', defaults);

                            // Firefox causes all but the first and last elements to retain a select all state, so in order to
                            // effectively support arrow keys, the starting point of the selection is to the last possible cursor
                            if (settings.firefox) {
                                setTimeout(function () {
                                    e.selectionStart = e.value.length;
                                }, 1);
                            }

                            if (!settings.iOS) {
                                handlePaste(defaults.target[0], filteredValue);
                            }
                        }

                    };

                    if (e.value.length == originDefaults.maxlength) {
                        defaults.arrowKey = false;
                        $(e).trigger('autotab-next', defaults);

                        if (!settings.iOS) {
                            handlePaste(originDefaults.target[0], e.value.toLowerCase());
                        }
                    }

                    e.maxLength = originDefaults.maxlength;
                }, 1);
            })(this, defaults);
        });
    };

    // Deprecated, here for backwards compatibility
    $.fn.autotab_magic = function (focus) {
        return $(this).autotab();
    };
    $.fn.autotab_filter = function (options) {
        var defaults = {};

        if (typeof options === 'string' || typeof options === 'function') {
            defaults.format = options;
        }
        else {
            $.extend(defaults, options);
        }

        return $(this).autotab('filter', defaults);
    };

})(jQuery);
;
/*!
* inputmask.extensions.min.js
* https://github.com/RobinHerbots/Inputmask
* Copyright (c) 2010 - 2019 Robin Herbots
* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
* Version: 4.0.7
*/

(function(factory){if(typeof define==="function"&&define.amd){define(["./inputmask"],factory)}else if(typeof exports==="object"){module.exports=factory(require("./inputmask"))}else{factory(window.Inputmask)}})(function(Inputmask){Inputmask.extendDefinitions({A:{validator:"[A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",casing:"upper"},"&":{validator:"[0-9A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5]",casing:"upper"},"#":{validator:"[0-9A-Fa-f]",casing:"upper"}});Inputmask.extendAliases({cssunit:{regex:"[+-]?[0-9]+\\.?([0-9]+)?(px|em|rem|ex|%|in|cm|mm|pt|pc)"},url:{regex:"(https?|ftp)//.*",autoUnmask:false},ip:{mask:"i[i[i]].i[i[i]].i[i[i]].i[i[i]]",definitions:{i:{validator:function(chrs,maskset,pos,strict,opts){if(pos-1>-1&&maskset.buffer[pos-1]!=="."){chrs=maskset.buffer[pos-1]+chrs;if(pos-2>-1&&maskset.buffer[pos-2]!=="."){chrs=maskset.buffer[pos-2]+chrs}else chrs="0"+chrs}else chrs="00"+chrs;return new RegExp("25[0-5]|2[0-4][0-9]|[01][0-9][0-9]").test(chrs)}}},onUnMask:function(maskedValue,unmaskedValue,opts){return maskedValue},inputmode:"numeric"},email:{mask:"*{1,64}[.*{1,64}][.*{1,64}][.*{1,63}]@-{1,63}.-{1,63}[.-{1,63}][.-{1,63}]",greedy:false,casing:"lower",onBeforePaste:function(pastedValue,opts){pastedValue=pastedValue.toLowerCase();return pastedValue.replace("mailto:","")},definitions:{"*":{validator:"[0-9\uff11-\uff19A-Za-z\u0410-\u044f\u0401\u0451\xc0-\xff\xb5!#$%&'*+/=?^_`{|}~-]"},"-":{validator:"[0-9A-Za-z-]"}},onUnMask:function(maskedValue,unmaskedValue,opts){return maskedValue},inputmode:"email"},mac:{mask:"##:##:##:##:##:##"},vin:{mask:"V{13}9{4}",definitions:{V:{validator:"[A-HJ-NPR-Za-hj-npr-z\\d]",casing:"upper"}},clearIncomplete:true,autoUnmask:true}});return Inputmask});;
(function (window, undefined) {
    'use strict';

    var stylingTagsToStrip = ['STRONG', 'B', 'I', 'BASEFONT', 'BIG', 'FONT', 'IFRAME', 'IMG', 'U', 'SCRIPT', 'PRE', 'SMALL'];

    window.utils = {
        //for usage examples check Utils.Test

        getUrlParameter: function (parameterName, url) {
            if (!url) {
                url = location.search;
            }
            return decodeURI((RegExp(parameterName + '=' + '(.+?)(&|$)').exec(url) || [, ""])[1]);
        },

        formatDateTimeAMPM: function(date) {
            var hours = date.getHours();
            var minutes = date.getMinutes();

            var ampm = hours >= 12 ? 'PM' : 'AM';

            hours = hours % 12;
            hours = hours ? hours : 12; // the hour '0' should be '12'

            minutes = minutes < 10 ? '0' + minutes : minutes;

            var strTime = hours + ':' + minutes + ampm;
            return strTime;
        },

        stringEndsWith: function (str, suffix) {
            return str.indexOf(suffix, str.length - suffix.length) !== -1;
        },

        removeFromStringEnd: function(str, charactersToRemove) {
            return str.substring(0, str.length - charactersToRemove);
        },

        toTitleCase: function (str) {
            return str.replace(/\w+/g, function (txt) {
                return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
            });
        },

        compareYearAndMonth: function (year1, month1, year2, month2) {
            function isNull(value) {
                return !value;
            }

            if (isNull(year1) && isNull(year2))
                return 0;
            if (isNull(year1) && !isNull(year2))
                return -1;
            if (!isNull(year1) && isNull(year2))
                return 1;

            if (year1 < year2)
                return 1;
            if (year1 > year2)
                return -1;

            if (isNull(month1))
                month1 = 0;
            if (isNull(month2))
                month2 = 0;

            return month2 - month1;
        },

        containsDuplicates: function(array) {
            array.sort();
            var containsDuplicates = false;

            var last = array[0];
            for (var i = 1; i < array.length; i++) {
                if (array[i] == last) {
                    containsDuplicates = true;
                }

                last = array[i];
            }

            return containsDuplicates;
        },

        findDuplicates: function (array, resultElementTransition) {
            var elementsWithCountDictionary = {};

            for (var i = 0; i < array.length; i++) {
                var element = array[i];

                if (elementsWithCountDictionary[element] === undefined) {
                    elementsWithCountDictionary[element] = 1;
                } else {
                    elementsWithCountDictionary[element] += 1;
                }
            }

            var duplicates = [];
            for (var p in elementsWithCountDictionary) {
                var count = elementsWithCountDictionary[p];
                if (count > 1) {
                    if (resultElementTransition) {
                        p = resultElementTransition(p);
                    }

                    duplicates.push(p);
                }
            }

            return duplicates;
        },

        firstOrDefault: function(array, condition) {
            var matchingElements = $.grep(array, condition);
            if (matchingElements.length === 0)
                return null;

            return matchingElements[0];
        },

        exists: function(array, condition) {
            return $.grep(array, condition).length > 0;
        },

        jQueryObjectToString: function(object) {
            return $('<div>').append(object.clone()).html();
        },

        replaceLinebreaksWithBrs: function(text) {
            return text.replace(/\n/g, "<br>");
        },
        
        normalizeNewlines: function(text) {
            return String(text).replace(/(\r\n|\n|\r)/gm, "\n");
        },

        stripHtmlStyling: function (text) {
            if (!text) {
                return '';
            }

            text = window.utils.replaceLinebreaksWithBrs(text);

            if (text.indexOf("<") === -1) {
                return text;
            }

            try {
                var stripped = [],
                    allContents = $('<div>').append(text).contents();

                allContents.each(function () {

                    var $this = $(this),
                        node;

                    if ($.inArray(this.tagName, stylingTagsToStrip) > -1) {
                        node = $this.contents();
                    }
                    else {
                        node = $this
                            .removeAttr("style")
                            .removeAttr("class");
                    }

                    stripped.push(
                        window.utils.jQueryObjectToString(node)
                    );
                });

                return stripped.join('');
            }
            catch (e) {
                // error in formatting
                return text;
            }
        },

        stripHtmlTags: function (content) {
            var text = $("<div/>").html(content).text();
            return text;
        },

        //Returns a new function which calls 'wrapper' function before or after the original function.
        wrapFunction: function (fn, wrapper, after) {
            return function () {
                if (!after) {
                    wrapper.apply(this, arguments);
                }
                fn.apply(this, arguments);
                if (after) {
                    wrapper.apply(this, arguments);
                }
            };
        }
    };
})(window);;
(function (window, undefined) {
    'use strict';

    var namespace = function (name) {
        return (window[name] || (window[name] = {}));
    };

    window.namespace = namespace;

})(window);;
(function (window, undefined) {
    'use strict';

    namespace('Areas').AreaNames = {
        gJobs: 'gJobs',
        careerPages: 'careerPages'
    };

})(window);
;
(function (window, undefined) {
    'use strict';

    var application = {
        templateEngine: {
            setBaseUrl: function (url) {
                infuser.defaults.templateUrl = url;
            }
        }
    };


    window.OnlineApp = application;

})(window);;
(function (window, undefined) {

    function iterateThroughNamespace(parentNamespaceObject, namespaces) {
        for (var namespaceIndex = 0; namespaceIndex < namespaces.length; namespaceIndex++) {

            var childNamespace = namespaces[namespaceIndex];
            var childNamespaceObject = parentNamespaceObject[childNamespace];

            if (typeof (childNamespaceObject) === 'undefined') {
                childNamespaceObject = {};
                parentNamespaceObject[childNamespace] = childNamespaceObject;
            }

            parentNamespaceObject = childNamespaceObject;
        }

        return parentNamespaceObject;
    }

    OnlineApp.Namespace = {

        open: function (parentNamespace) {

            var namespaces = parentNamespace
                .split('.')
                .concat(Array.prototype.slice.call(arguments, 1));

            var parentNamespaceObject = window[namespaces[0]];

            namespaces = namespaces.slice(1);

            return iterateThroughNamespace(parentNamespaceObject, namespaces);
        },

        //TODO : Merge with open method!
        openRelative: function (base, parentNamespace) {

            var namespaces = parentNamespace
                .split('.');

            var parentNamespaceObject = base;

            return iterateThroughNamespace(parentNamespaceObject, namespaces);
        },

        extend: function (parentNamespace, object) {
            var namespace = this.open(parentNamespace);
            return $.extend(namespace, object);
        }
    };

})(window);;
(function (window, undefined) {
    // Note: we do not use strict mode here to allow access callee in function body

    // FROM: http://helephant.com/2007/05/diy-javascript-stack-trace
    // AND: http://joel.net/logging-errors-with-elmah-in-asp.net-mvc-3--part-5--javascript


    //Note: all the special cases when the javascript error logging is not needed should be described in this method
    function isLoggingRequired() {

        var result = true;

        //avoid error handling for GoogleBot requests as GoogleBot cannot execute all the javascript correctly
        if (navigator.userAgent && navigator.userAgent.indexOf('Googlebot') !== -1) {
            result = false;
        }

        return result;
    }

    function getTrace() {
        var trace = [];
        var current = this;
        while (current) {
            trace.push(getSignature.apply(current));
            current = current.caller;
        }
        return trace;
    }

    function getSignature() {
        var signature = {
            name: getName.apply(this),
            params: [],
            toString: function () {

                var params = (this.params || []).length > 0
                    ? "'" + this.params.join("', '") + "'"
                    : "";

                return this.name + "(" + params + ")";
            }
        };

        if (this.arguments) {
            for (var x = 0; x < this.arguments.length; x++)
                signature.params.push(this.arguments[x]);
        }

        return signature;
    }

    function getName() {
        if (this.name) return this.name;

        var definition = this.toString().split("\n")[0];
        var exp = /^function ([^\s(]+).+/;
        if (exp.test(definition))
            return definition.split("\n")[0].replace(exp, "$1") || "anonymous";

        return "anonymous";
    }

    function createLogMessage(err, stack) {
        if (err == null) return undefined;

        var url = err.fileName != null
            ? err.fileName
            : document.location;

        if (stack == null && err.stack != null) {
            stack = err.stack;
        }

        // format output
        var out = err.message != null
            ? err.name + ": " + err.message
            : err;

        out += ": at document path '" + url + "'.";

        if (stack != null) {
            out += "\n  at " + stack.join("\n  at ");
        }

        return out;
    }
    
    function handleError(message, filename, lineNo, columnNo, error) {
        //api url
        var apiUrl = '/api/errorlog';

        var stack;

        if (arguments != null && arguments.callee != null) {
            stack = getTrace.apply(arguments.callee);
        }

        var elmahTrace = '';
        // for blink browsers
        if (error) {
            elmahTrace = error.stack;
        }
            // a guess for other browsers
        else if (stack) {
            for (var i = 0; i < stack.length; ++i) {
                if (!stack[i]) continue;

                var params = stack[i].params;
                for (var j = 0; j < params.length; ++j) {
                    if (!params[j]) continue;

                    if (params[j].stack) {
                        elmahTrace += params[j].stack + "\n\n";
                    }
                }
            }
        }

        var data = {
            errorMsg: message,
            errorLine: lineNo,
            filePath: filename,
            url: document.location.href,
            referrer: document.referrer,
            userAgent: navigator.userAgent,
            elmahLog: createLogMessage(message, stack),
            elmahTrace: elmahTrace
        };

        $.ajax({
            url: apiUrl,
            type: 'POST',
            data: data
        });

        //suppress browser error messages for non-dev environments
        var suppressErrors = $.inArray(window.location.hostname, ['localhost', 'gjobs.local.neogov.net', 'schooljobs.local.neogov.net']) == -1;

        return suppressErrors;
    };

    if (isLoggingRequired()) {
        try {
            window.onerror = handleError;
        } catch(e) {
        }
    }
    
})(window);;
(function (window, undefined) {
    'use strict';

    function ExternalFileLoader() {
        var self = this;

        self.load = function (url) {
            var script = document.createElement('script');

            script.type = 'text/javascript';
            script.src = url + '?v=' + Date.now();

            $('head').append(script);
        }
    };

    namespace('gJobs').externalFileLoader = new ExternalFileLoader();

})(window);
;
(function (window) {

    namespace('gJobs').ariaAttributes = {
        role: 'role',
        autocomplete: 'aria-autocomplete',
        owns: 'aria-owns',
        controls: 'aria-controls',
        haspopup: 'aria-haspopup',
        disabled: 'aria-disabled',
        invalid: 'aria-invalid',
        expanded: 'aria-expanded',
        hidden: 'aria-hidden',
        activeDescendant: 'aria-activedescendant',
        labelledBy: 'aria-labelledby',
        describedBy: 'aria-describedby',
        multiselectable: 'aria-multiselectable',
        label: 'aria-label',
        selected: 'aria-selected',
        notification: 'data-notification',
        required: 'aria-required',
        tabindex: 'tabindex'
    };

})(window);;
(function (window, undefined) {

    namespace('gJobs').nonFlickeringPopover = function ($elements, className) {   
       
        $('body').on('click', function (e) {
            if ($('#applications').length == 0) {//Part of fix for ONLINE-13390, eventhandler added for maps and not required for application submission page
                var isPopoverVisible = $('.popover-content').length > 0;

                if (e.target.id == 'redirectLink') {

                    if (isPopoverVisible) {
                        gJobs.screenReadersService.setNotification($("#aria-live-message-container"), 'Popover opened', '', true);
                    }
                }
                if (e.target.id != 'redirectLink' && isPopoverVisible) {
                    $('[data-toggle=popover]').each(function () {
                        // hide any open popovers when the anywhere else in the body is clicked
                        if (!$(this).is(e.target) && $(this).has(e.target).length === 0) {
                            $(this).popover('hide');
                            closePopover();
                            var elementsToExclude = getListOfElmentsToBeExcluded();
                            if (e.target && e.target.id && e.target.id != "" && elementsToExclude.indexOf(e.target.id) == -1) {
                                gJobs.screenReadersService.setNotification($("#aria-live-message-container"), 'Popover closed', '', true);
                            }
                            $("#redirectLink").focus();
                        }
                    });
                }
            }
        });

        $('body').on('keydown', function (e) {
            if (e.keyCode == 27) {
                var isPopoverVisible = $('.popover-content').length > 0;
                if (e.target.id == 'redirectLink') {

                    if (isPopoverVisible) {
                        gJobs.screenReadersService.setNotification($("#aria-live-message-container"), 'Popover opened', '', true);
                    }
                }
                if (e.target.id != 'redirectLink' && isPopoverVisible) {
                    $('[data-toggle=popover]').each(function () {
                        // hide any open popovers when the anywhere else in the body is clicked
                        if (!$(this).is(e.target) && $(this).has(e.target).length === 0) {
                            $(this).popover('hide');
                            closePopover();
                            var elementsToExclude = getListOfElmentsToBeExcluded();
                            if (e.target && e.target.id && e.target.id != "" && elementsToExclude.indexOf(e.target.id) == -1) {
                                gJobs.screenReadersService.setNotification($("#aria-live-message-container"), 'Popover closed', '', true);
                            }
                            $("#redirectLink").focus();
                        }
                    });
                }
            }
        });

        $('#redirectLink').on('click', function () {
            
            $(this).popover({
                template: '<div class="popover click-popover role="tooltip"><h3 class="popover-title"></h3><div class="popover-content"></div></div>',

                animation: false,
                html: true
            });
            $(this).popover('show');
            $('.popover').css('background','black')
            $('a#gmapLink').css('color', 'white');
            $('a#gmapLink').css('font-weight', 600);
            $('#gmapLink').focus();
        })

        $('#redirectLink').on('keydown', function (e) {
            if (e.keyCode == 13) {
                $(this).popover({
                    template: '<div class="popover click-popover role="tooltip"><h3 class="popover-title"></h3><div class="popover-content"></div></div>',

                    animation: false,
                    html: true
                });
                $(this).popover('show');
                $('a#gmapLink').css('color', 'white');
                $('#gmapLink').focus();
            }
        })

        $elements.popover({
            template: '<div class="popover ' + className + '" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>',
            
            animation: false,
            html:true
        }).click(function () {
            $(this).popover({
                template: '<div class="popover click-popover role="tooltip"><h3 class="popover-title"></h3><div class="popover-content"></div></div>',

                animation: false,
                html: true
            });
            $(this).popover('show');

            $('a#gmapLink').css('color', 'white');
            $('#gmapLink').focus();
        })           
        .mouseenter(function () {
            var $this = $(this);
            if ($this[0].id != "redirectLink") {
                if ($this.data('bs.popover') && !$this.data('bs.popover').tip().hasClass('in') && !$this.data('bs.closing')) {
                    showPopover($this);                    
                }
                closeLocationPopover();
            }
        })
        .mouseleave(closePopover)
            .focus(function () {
                if ($(this)[0].id != "redirectLink") {
                    showPopover($(this));
                    closeLocationPopover();
                }
        })
        .blur(closePopover);

        function showPopover($element) {
            var id = getUniqueId();
            
            $element
                .popover('show')
                .not('.hide-aria-label')
                .attr('aria-describedby', id);
            if ($element
                .data('bs.popover')) {
                $element
                    .data('bs.popover').tip()
                    .attr('id', id);
            }
            $('a#gmapLink').css('color', 'white');
            $('#redirectLink').attr('tabindex', 0);
        }

        function closePopover() {
            
            var $this = $(this);
            if ($(this)[0].id != "redirectLink") {
                $this.data('bs.closing', true);
                if ($this && $this.data('bs.popover')) {
                    $this.data('bs.popover').tip().fadeOut(150, function () {
                        $this.data('bs.closing', false);
                        $this
                            .removeClass('in')
                            .removeAttr('aria-describedby')
                            .popover('hide');

                    });
                }
            }
        }

        function closeLocationPopover() {
            $('#redirectLink').popover('hide');
            $('.click-popover').removeClass('visible-desktop');
            $('.click-popover').hide();
        }
       
        function getUniqueId() {
            var timestamp = +(new Date());
            return 'popover-' + timestamp;
        }
    };

})();;
(function(window, undefined) {

    var applicationSettingCodes =
    {
        '1': 'MandatoryEducationHistoryDates',
        '2': 'WorkHistoryDutiesBreakdown',
        '3': 'WorkHistoryCustomMessage',
        '4': 'LicenseHistoryCustomMessage',
        '5': 'AdditionalInfoTypeFilter',
        '6': 'ReferenceCustomMessage',
        '7': 'ShowExtraColumnApplicationStatus',
        '8': 'ShowExtraInformationPrintApplication',
        '9': 'MandatoryEducationHistoryUnits',
        '10': 'PersonalProfileCustomMessage',
        '11': 'ShowApplicationsForThisEmployerOnly'
    };

    function populateFieldSettings(settings) {
        var fieldSettings = {};
        for (var i = 0, length = settings.length; i < length; ++i) {
            var code = settings[i].code;
            var state = settings[i].state;
            fieldSettings[code] = {
                visible: (state < 3),
                required: (state < 2)
            };
        }

        // Note: moved from preferences.html
        // TODO: investigate whether null check required/possible
        var showPreferences =
            fieldSettings.salaryMinYr.visible
                || fieldSettings.salaryMinHr.visible
                || fieldSettings.relocateID.visible
                || fieldSettings.relocateComments.visible
                || fieldSettings.shiftType.visible
                || fieldSettings.positionType.visible
                || fieldSettings.workType.visible
                || fieldSettings.objective.visible;

        fieldSettings['preferences'] = {
            visible: showPreferences
        };

        return fieldSettings;
    }

    function populateApplicationSettings(settings) {
        var applicationSettings = {};
        for (var i = 0, length = settings.length; i < length; ++i) {
            var code = settings[i].code;
            var setting = settings[i].setting;
            var settingName = applicationSettingCodes[code];

            if (settingName) {
                applicationSettings[settingName] = setting;
            }
        }

        return applicationSettings;
    }
    
    function populateCustomFields(settings) {
        var customFields = {};
        
        for (var i = 0, length = settings.length; i < length; ++i) {
            var label = settings[i].fieldLabel;
            var fieldValues = settings[i].fieldValues;
            var data = settings[i].data;
            
            customFields[label] = {
                values: fieldValues,
                data: data
            };
        }
        return customFields;
    }

    function TabSettings() {
        var self = OnlineApp.ViewModels.Base.DataViewModel.apply(this, arguments) || this;

        self.showAdditionalMenu = ko.observable(false);
        self.acceptAdditionalInfo = ko.observable(false);
        self.acceptAttachResume = ko.observable(false);
        self.acceptEducationHistory = ko.observable(false);
        self.acceptLicense = ko.observable(false);
        self.acceptReference = ko.observable(false);
        self.acceptEReferences = ko.observable(false);
        self.eRefRequiredReferences = ko.observable(null);
        self.acceptSkill = ko.observable(false);
        self.acceptTextResume = ko.observable(false);
        self.acceptWorkHistory = ko.observable(false);

        self.fromDataModel = function (data) {
            if (!data) {
                return;
            }

            self.showAdditionalMenu(data.showAdditionalMenu);
            self.acceptAdditionalInfo(data.acceptAdditionalInfo);
            self.acceptAttachResume(data.acceptAttachResume);
            self.acceptEducationHistory(data.acceptEducationHistory);
            self.acceptLicense(data.acceptLicense);
            self.acceptReference(data.acceptReference);
            self.acceptEReferences(data.acceptEReferences);
            self.eRefRequiredReferences(data.eRefRequiredReferences);
            self.acceptSkill(data.acceptSkill);
            self.acceptTextResume(data.acceptTextResume);
            self.acceptWorkHistory(data.acceptWorkHistory);
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Settings', {
        populateFieldSettings: populateFieldSettings,
        populateApplicationSettings: populateApplicationSettings,
        populateCustomFields: populateCustomFields
    });

    OnlineApp.Namespace.extend('OnlineApp.Settings', {
        TabSettings: TabSettings
    });

    $(document).ready(function () {
        // Configure toastr.js settings
        toastr.options.target = '#aria-live-toastr-container';
    });

})(window);;
(function (window, undefined) {
    'use strict';

    OnlineApp.Namespace.extend('OnlineApp.FieldSettings', {   
        //Contact info
        firstName: {
            required: true
        },
        middleName: {
            visible: true,
            required: false
        },
        lastName: {
            required: true
        },
        formerLastName: {
            visible: false,
            required: false
        },
        address1: {
            required: true
        },
        address2: {
            visible: true,
            required: false
        },
        city: {
            required: true
        },
        stateID: {
            required: true
        },
        zip: {
            required: true
        },
        homePhone: {
            visible: true,
            required: false
        },
        alternatePhone: {
            visible: true,
            required: false
        },
        notificationType_cd: {
            visible: true,
            required: false
        },
        countryID: {
            visible: true,
            required: true
        },
        email: {
            required: true
        },

        //Personal info
        driverLicense: {
            visible: true,
            required: false
        },
        driverLicenseStateID: {
            visible: true,
            required: false
        },
        driverLicenseNumber: {
            visible: true,
            required: false
        },
        driverLicenseClassID: {
            visible: true,
            required: false
        },
        monthDayBirth: {
            visible: false,
            required: false
        },
        ssn: {
            visible: false,
            required: false
        },
        legalWork: {
            visible: true,
            required: true
        },
        highestEducationLevelID: {
            visible: true,
            required: true
        },

        //Preferences
        preferences: {
            visible: true,
            required: false
        },
        salaryMinYr: {
            visible: true,
            required: false
        },
        salaryMinHr: {
            visible: true,
            required: false
        },
        relocateID: {
            visible: true,
            required: false
        },
        relocateComments: {
            visible: true,
            required: false
        },
        shiftType: {
            visible: true,
            required: false
        },
        positionType: {
            visible: true,
            required: false
        },
        workType: {
            visible: true,
            required: false
        },
        objective: {
            visible: true,
            required: false
        },

        // WorkExperience
        workExperienceCompanyName: {
            visible: true,
            required: true
        },
        workExperienceAddress: {
            visible: true,
            required: false
        },
        workExperienceCity: {
            visible: true,
            required: true
        },
        workExperienceState: {
            visible: true,
            required: true
        },
        workExperienceZipCode: {
            visible: true,
            required: false
        },
        workExperienceCountry: {
            visible: true,
            required: false
        },
        workExperiencePhone: {
            visible: true,
            required: false
        },
        workExperienceWebsite: {
            visible: true,
            required: false
        },
        workExperienceMayWeContactEmployer: {
            visible: true,
            required: false
        },
        workExperiencePositionTitle: {
            visible: true,
            required: true
        },
        workExperienceHoursPerWeek: {
            visible: true,
            required: true
        },
        workExperienceMonthlySalary: {
            visible: true,
            required: false
        },
        workExperienceEmployeesSupervised: {
            visible: true,
            required: false
        },
        workExperienceStartDate: {
            visible: true,
            required: true
        },
        workExperienceEndDate: {
            visible: true,
            required: true
        },
        workExperienceReasonForLeaving: {
            visible: true
        },
        workExperienceSupervisorName: {
            visible: true
        },
        workExperienceSupervisorTitle: {
            visible: true
        },
        workExperienceDutiesSummary: {
            visible: true,
            required: true
        },

        // Education
        educationSchoolType: {
            visible: true,
            required: true
        },
        educationSchoolName: {
            visible: true,
            required: true
        },
        educationCity: {
            visible: true,
            required: true
        },
        educationState: {
            visible: true,
            required: true
        },
        educationCountry: {
            visible: true,
            required: true
        },
        educationWebsite: {
            visible: true,
            required: false
        },
        educationMajorMinor: {
            visible: true,
            required: false
        },
        educationDegree: {
            visible: true,
            required: true
        },
        educationUnitsCompleted: {
            visible: true,
            required: false
        },
        educationUnitType: {
            visible: true,
            required: false
        },
        educationStartDate: {
            visible: true,
            required: false
        },
        educationEndDate: {
            visible: true,
            required: false
        },
        educationDidYouGraduate: {
            visible: true,
            required: false
        }
    });

})(window);;
(function (window, undefined) {
    'use strict';

    namespace('Events').CommonEventsNames = {
        CloseFlyout: 'closeFlyout',
        TryCloseFlyout: 'tryCloseFlyout',
        FlyoutClosing: 'flyoutClosing',
        HistoryFlyoutOpened: 'historyFlyoutOpened',
        HistoryFlyoutClosed: 'historyFlyoutClosed',
        ScheduleFlyoutOpened: 'scheduleFlyoutOpened',
        ScheduleFlyoutClosed: 'scheduleFlyoutClosed',
        ShowNext: 'showNext',
        ShowPrevious: 'showPrevious',
        ShowJobDetails: 'showJobDetails',
        HideApply: 'hideApply',
        ShowApply: 'showApply',
        ShowMessage: 'showMessage',
        ApplicationSubmitted: 'applicationSubmitted',
        ApplicationLoaded: 'applicationLoaded',
        ShowOnlineApp: 'showOnlineApp',
        Login: 'loginEvent',
        LoginFailed: 'loginFailed',
        Register: 'registerEvent',
        JobsListLoaded: 'jobsListLoaded',
        JobDetailsLoaded: 'jobDetailsLoaded',
        ShowFlyout: 'showFlyout',
        ClassSpecsListLoaded: 'classSpecsListLoaded',
        ShowValidationMessage: 'showValidationMessage',
        AppointmentFlyoutStateChanged: 'appointmentFlyoutStateChanged',
        DecreaseNumberOfUnreadMessages: 'decreaseNumberOfUnreadMessages',
        ShowTermsAndPrivacyPolicyAnnouncement: 'showTermsAndPrivacyPolicyAnnouncement',
        TermsAndPrivacyAccepted: 'termsAndPrivacyAccepted',
        GoogleAnalyticsTrackersInjected: 'googleAnalyticsTrackersInjected',
        ShowAccessMembershipDialog: 'showAccessMembershipDialog',
        CloseAccessMembershipDialog: 'closeAccessMembershipDialog',
        ShowConfirmDialog: 'showConfirmDialog',
        ToTopButtonTopPropertyChanged: 'toTopButtonTopPropertyChanged',
        Angular: {
            Login: 'angularLoginEvent',
            Register: 'angularRegisterEvent'
        },
        ShowStickyHeader: 'showStickyHeader',
        HideStickyHeader: 'hideStickyHeader',
        AccessMembershipEnabled: 'accessMembershipEnabled',
        AccessMembershipDisabled: 'accessMembershipDisabled',
        JobAlertCreated: 'JobAlertCreated',
        JobAlertUpdated: 'JobAlertUpdated',
        ChatbotClosed: 'chatPanelClosed',
        ChatPanelMinimized: 'chatPanelMinimized',
        ChatbotConversationFeedbackTextGiven: 'conversationFeedbackTextGiven',
        ChatBotConversationDeleted: 'conversationDeleted',
        ChatbotPositiveMessageFeedbackGiven: 'positiveMessageFeedbackGiven',
        ChatbotNegativeMessageFeedbackGiven: 'negativeMessageFeedbackGiven',
        HelpAndSupportPageOpened: 'helpAndSupportPageOpened',
        SupplementalAttachmentDocAttached: 'supplementalAttachmentDocAttached',
        SupplementalAttachmentDocDeleted: 'supplementalAttachmentDocDeleted',
        OpenAccessMembershipDialog: 'openAccessMembershipDialog'
    };

})(window);;
(function (window, undefined) {
    'use strict';

    OnlineApp.Namespace.extend('OnlineApp.Events.CommonEventsNames', {
        EditableItemBeginEdit: 'editableItemBeginEdit',
        EditItemComplete: 'editItemComplete',
        EditableCollectionItemDiscarded: 'editableCollectionItemDiscarded',
        TryRemoveItem: 'tryRemoveItem',
        RemoveItemComplete: 'removeItemComplete',
        ItemRemoved: 'itemRemoved',
        ResumeImportComplete: 'resumeImportComplete',
        PreSaveValidationFailed: 'preSaveValidationFailed',
        ApplicationSubmit: 'applicationSubmit',
        Login: 'loginEvent',
        Register: 'registerEvent',
        QuestionsSaved: 'questionsSaved',
        DocumentAttached: 'documentAttached',
        PasswordReset: 'passwordReset',
        ResetPasswordClicked: 'resetPasswordClicked',
        ContactInfomationAvailable: 'contactInformationAvailable',
        RegisterAccountLinkClicked: 'registerAccountLinkClicked',
        RegisterAccountFormOpened: 'registerAccountFormOpened',
        LoginFormOpened: 'loginFormOpened',
        ApplicationRendered: 'applicationRendered',
        TabActivated: 'tabActivated',
        ApplicationClosed: 'applicationClosed',
        ApplyTabOpened: 'applyTabOpened',
        ResourcesLinkClicked: 'resourcesLinkClicked',
        CertifySubmitTabOpened: 'certifySubmitTabOpened',
        EmailVerified: "emailVerified",
        EmailWasChanged: "emailWasChanged",
        ContactInfoEmailVerificationFormClosed: "contactInfoEmailVerificationFormClosed",
        ShowCancelVerificationRequestDialog: 'ShowCancelVerificationRequestDialog',
        InitSearchFieldsWithAutocomplete: "initSearchFieldsWithAutocomplete",
        AutocompleteMenuItemSelect: "menuselect",
        ConfirmEditEmailAddress: "confirmEditEmailAddress",
        CancelEditEmailAddress: "cancelEditEmailAddress",
        OjrMasterJicSubscribe: "ojrMasterJicSubscribe"
    });

})(window);;
(function (window, undefined) {
    'use strict';

    var SessionKeys = {
        EmailWasChangedAndNewVerificationCodeSent: 'emailWasChangedAndNewVerificationCodeSent',
        IsBannerWasClosedInCurrentSession: 'isBannerWasClosedInCurrentSession',
        PostBackUrl: 'postBackUrl',
        IsVerifyIdentityVerificationCodeVerified: 'isVerifyIdentityVerificationCodeVerified',
        ApplicationProcessUrl: 'applicationProcessUrl'
    };

    OnlineApp.Namespace.extend('OnlineApp', {
        SessionKeys: SessionKeys
    });

})(window);
;
(function (window, undefined) {
    'use strict';

    var LocalStorageKeys = {
        EmailWasChanged: 'emailWasChanged',
        EmailWasChangedAndNewVerificationCodeSent: 'emailWasChangedAndNewVerificationCodeSent',
        EmailWasVerified: 'emailWasVerified',
        ShowJobAlertPopup: 'showJobAlertPopup',
        RedirectToShowJobAlertPopup: 'redirectToShowJobAlertPopup'
    };

    OnlineApp.Namespace.extend('OnlineApp', {
        LocalStorageKeys: LocalStorageKeys
    });

})(window);
;
(function (window, undefined) {

    $(document).ready(function() {
        var areaInfoService = gJobs.areaInfoService;

        var $body = $('body');
        var disableScrollClasses = 'scroll-disable inner-scrollbar';
        var initialBodyClasses = '';

        var $termsAndPrivacyPolicyDialogContainer = $('#terms-and-privacy-policy-update-confirmation');

        var isCareerPages = areaInfoService.getCurrentArea() === areaInfoService.areaNames.Career;

        var TermsAndPrivacyAnnouncementViewModel = function (options) {
            var self = OnlineApp.ViewModels.Base.ValidatableViewModel.call(this) || this;

            self.visible = ko.observable(false);
            self.isBusy = ko.observable(false);
            
            self.hasAcceptedTerms = ko.observable(false).extend({ required: {} });

            self.options = options || {};

            self.hasError = function () {
                self.hasAcceptedTerms.validate();
                return self.hasAcceptedTerms.hasError();
            };

            self.visible.subscribe(function(value) {
                showHideElementsOnDialog(value);
            })

            self.acceptTermsAndPrivacyPolicy = function() {
                self.isBusy(true);

                if (!self.hasError()) {
                    $.post('/user/acceptTermsAndPrivacyPolicy')
                    .done(function(data) {
                        if (!data.isSuccess) {
                           toastr.warning(Resources.NotificationMessages.EncounteredProblem);
                        } else {
                            showHideElementsOnDialog(false);
                            
                            $(document).trigger(Events.CommonEventsNames.TermsAndPrivacyAccepted);
                            gJobs.screenReadersService.setAriaLiveNotification(
                                'You have successfully accepted the changes to the terms of service and privacy policy. Term & use Modal Dialog has been closed.'
                            );
                            $("#skip-to-content-button").focus();
                            sessionStorage.setItem("isTermsDeclined", "1");
                            $('body').removeClass('scroll-disable inner-scrollbar');
                            $('body').css("overflow-y", "auto");
                            $('#body-shadow').addClass('hidden');
                        }
                    })
                    .always(function() {
                        self.isBusy(false);
                        self.visible(false);
                        $termsAndPrivacyPolicyDialogContainer.removeClass('active');
                        $termsAndPrivacyPolicyDialogContainer.css("display", "none");
                        localStorage.setItem("istermsAndPrivacyPolicyDialogContainer", "0");
                        $("#skip-to-content-button").focus();
                        if (isCareerPages) {
                            AgencyPages.bodyScrollingAdjustmentService.enableBodyScrolling();
                        } else {
                            $body.attr('class', initialBodyClasses);
                        }
                        if (options.closeCallback && typeof options.closeCallback === "function") {
                            options.closeCallback();
                        }
                    });
                } else {
                    self.isBusy(false);
                    OnlineApp.Helpers.layoutHelper.tabbing.activateFirstElement(
                        $termsAndPrivacyPolicyDialogContainer.find('form')
                    );
                }
            }

            self.declineTermsAndPrivacyPolicy = function () {     
                var redirectUrl = '/applications/accountsettings?declined=true#delete';
                if (isCareerPages) {
                    redirectUrl = AgencyPages.pageInfoService.getCurrentAgencyHomePageUrl() + redirectUrl;
                }
                sessionStorage.setItem("isTermsDeclined", "1");
                localStorage.setItem("istermsAndPrivacyPolicyDialogContainer", "1");

                var popup = document.getElementById("terms-and-privacy-policy-update-confirmation");
                if (popup) {
                    popup.style.display = "none";
                }

                window.location.replace(redirectUrl);                
            }

            function showHideElementsOnDialog(hide) {
                gJobs.dialogHelper.showHideElementsOnDialog(
                    {
                        selector: '#body-container, #main-container,'
                                  + '#footer, .new-job-flyout, #skip-to-content-button,'
                                  + '#last-focusable-element, #cookie-consent',
                        shouldDisableRestoreTabIndex: true,
                        hide: hide
                    }
                );
            }
        }

        $(document).on(Events.CommonEventsNames.ShowTermsAndPrivacyPolicyAnnouncement, function(e, data) {
            var currentQueryParams = url.get(window.location.search.slice(1), { array: true });
            if (currentQueryParams.declined !== 'true' && !$('html').hasClass('error-page')) {
                $element = $termsAndPrivacyPolicyDialogContainer.get(0);
                termsAndPrivacyAnnouncementViewModel = new TermsAndPrivacyAnnouncementViewModel(data);

                if (!ko.dataFor($element)) {
                    ko.applyBindings(termsAndPrivacyAnnouncementViewModel, $element);
                }

                if (isCareerPages) {
                    AgencyPages.bodyScrollingAdjustmentService.disableBodyScrolling();
                } else {
                    if (!$termsAndPrivacyPolicyDialogContainer.hasClass('active')) {
                        initialBodyClasses = $body.attr('class') || '';
                        $body.addClass(disableScrollClasses);
                    }
                }
                localStorage.setItem("istermsAndPrivacyPolicyDialogContainer", "1");
                $termsAndPrivacyPolicyDialogContainer.addClass('active');
                termsAndPrivacyAnnouncementViewModel.visible(true);
                gJobs.focusService.setFocus($('.terms-of-use-modal'));
            }
        });
    });

})(window);;
(function (window, undefined) {
    'use strict';

    namespace('Resources').NotificationMessages = {
        EncounteredProblem: "Sorry, we've encountered a problem! Please try again.",
        LoadTemplateFail: "Application could not load settings for selected job.",
        ServiceUnavailable: "Service unavailable.",
        SessionTimeoutExpires: "Your session is going to expire in ",
        SessionTimeoutResume: "Click here or press any key to continue.",
        LoginFail: "Could not log in to system. Please contact administrator for support.",
        RegistrationFail: "Registration failed. Please contact administrator for support.",
        ServerConnectionFailed: "Could not connect to server.",
        LoginSuccess: "You are logged in.",
        RegistrationSuccess: "Account successfully created. You are logged in."
    };

})(window);;
(function (window, undefined) {
    'use strict';

    namespace('Resources').EndpointUrls = {
        KeepAlive: '/Application/KeepAlive'
    };

})(window);;
(function (window, undefined) {
    'use strict';

    OnlineApp.Namespace.extend('OnlineApp.FlyoutWrapperClasses', {
        convictionQuestionnaire: {
            className: 'conviction-questionnaire-flyout',
            selector: '.conviction-questionnaire-flyout'
        }
    });

})(window);;
(function (window, undefined) {
    'use strict';

    namespace('Resources').FileUploadMessages = {
        invalidFile: "The file you're trying to upload is invalid or empty.",
        unsupportedExtension: "The file you are trying to upload has an extension that is not allowed.",
        unsupportedExtensionWithAllowed: function (supportedFileTypes) {
            return "The file you are trying to upload has an extension that is not allowed. You can only upload " + supportedFileTypes + " files.";
        },
        fileTooLarge: function() {
            return "The file you're trying to upload is too large. Maximum file size is " + Math.round(maximumFileUploadSizeInKB / 1024) + " MB."
        }
    };

})(window);;
(function (window, undefined) {

    function LayoutHelper() {

        var lockCounter = 0;

        var self = this;

        self.$loadingSpinner = null;

        self.showOnlineAppSpinner = function() {
            self.getOnlineAppLoadingSpinner().show();
        };

        self.hideOnlineAppSpinner = function () {
            if (lockCounter == 0) {
                self.getOnlineAppLoadingSpinner().hide();
            }
        };

        self.forceHideOnlineAppSpinner = function () {
            lockCounter = 0;
            self.getOnlineAppLoadingSpinner().hide();
        };

        self.showOnlineAppInnerSpinner = function (lock) {
            self.getOnlineAppLoadingSpinner().addClass('inline').show();

            if (lock) {
                lockCounter++;
            }
        };

        self.hideOnlineAppInnerSpinner = function (unlock) {
            if (unlock) {
                lockCounter--;
            }

            if (lockCounter == 0) {
                self.getOnlineAppLoadingSpinner().removeClass('inline').hide();
            }
        };

        self.getOnlineAppLoadingSpinner = function() {

            self.$loadingSpinner = $('#onlineapp-loading-spinner, .loading-spinner');

            return self.$loadingSpinner;
        };

        self.getOnlineAppContainer = function() {
            return $('.onlineapp-wrapper');
        };

        self.updateSchoolDegreeCustomSelect = function () {
            $(".edit-dialog select[name='school-degree']").trigger("liszt:updated");
        };

        self.isOnlineAppInsideFlyout = function () {
            if ($(".flyout-window,#job-details-flyout").length > 0) {
                return true;
            }

            return false;
        };

        self.isCareerPagesApp = function () {
            return $(".career-pages-header") && $(".career-pages-header").length > 0;
        }

        self.tabbing = {

            // todo: implement caching for getting tabbable elements

            getTabbableElements: function (parentContainer) {
                var elements,
                    tabbableElementsSelector = '.box a,' + 
                        'input[type=text],input[type=radio],input[type=checkbox],' +
                        'input[type=checkbox],input[type=tel],input[type=email],input[type=password],' +
                        'textarea,button,div.chzn-container,' +
                        '.instruction,' +
                        '.screenreader-link-required,label[aria-label],' + '.nav a,' +
                        '.floating-header a,' + '#title-bar a,' + '.terms-and-privacy-policy a,';
                
                var additionalTabbableElementsSelector = '.left-menu-nav a,' +
                        '.flyout-header-tabs a, .btn, .item-edit-button,' +
                        '.share a,' + '.entity-details-buttons.tab-buttons a,' +
                        '.form-signin a,' + '.job-details-agency-info a,' +
                        '.job-details-content a,' + '.job-details-summary .popover-trigger,' +
                        '.profiles .profile-item,' + '.disability-form a,' + '.apply-tab-header-content a,' +
                        '#skip-to-content-button,' + '.invisible-chosen-input,' + '.note.popover-trigger,' + '.content.dialog-content' + ',.dynamic-tabindex' +
                        ', .flyout-content span[data-toggle="popover"]:not(.tab-aux-icon)' +
                        ', .profiles > li.profile-item' + 
                        ', .submitted a.application-advertisement-link' +
                        ', .top-resume-result' +
                        ', .description a' + ', .note';

                var jobApplyTab = $('.job-apply-tab');

                if (self.isOnlineAppInsideFlyout() && !(parentContainer && parentContainer.length)) {
                    if (self.isCareerPagesApp()) {
                        parentContainer = $(".flyout-window,#job-details-flyout");
                    }
                    else {
                        parentContainer = $("#header,.flyout-window,#job-details-flyout");
                    }
                } else {
                    parentContainer = $(parentContainer || (jobApplyTab.length ? jobApplyTab : $(document)));
                }
                elements = parentContainer.find(tabbableElementsSelector + additionalTabbableElementsSelector);

                elements = elements
                    .filter(":visible")
                    .filter(function() {
                        return ($(this).css("visibility") !== "hidden");
                    });

                return elements;
            },

            updateIndices: function (parentContainer, avoidSetTabOrder) {
                var tabbableElements = this.getTabbableElements(parentContainer);

                tabbableElements = $('#skip-to-content-button').add(tabbableElements);
                var $lastFocusableElement = $('#last-focusable-element');
                if ($lastFocusableElement.length !== 0) {
                    tabbableElements.add($lastFocusableElement);
                }

                function ariaSelectedAllowed(element) {
                    var allowedRoles = ['gridcell', 'option', 'row', 'tab', 'columnheader', 'menuitemradio', 'radio', 'rowheader', 'treeitem'];
                    return allowedRoles.indexOf(element.getAttribute('role')) > -1
                }

                tabbableElements = tabbableElements.each(function() {
                    var $this = $(this);
                    if (!$this.hasClass('ignore-tabindex-update')) {
                        $this.attr('tabindex', 0);
                    }
                    if (ariaSelectedAllowed($this.get(0))) {
                        if ($this.parent().hasClass('active')) {
                            $this.attr('aria-selected', 'true');
                        }
                        else {
                            $this.attr('aria-selected', 'false');
                        }
                    }
                });
                ko.bindingHandlers.tabIndex.setCheckAndRadioBehavior(tabbableElements);

                if ($('.onlineapp-tabs').is(':visible') && !avoidSetTabOrder) {
                    OnlineApp.Helpers.applicationTabOrderHelper.setTabOrder();
                }
            },

            resetOrder: function (parentContainer) {
                var tabbing = this;
                $(document).one("keydown", function(e) {
                    var keyCode = e.keyCode || e.which;

                    if (keyCode == 9) {
                        e.preventDefault();

                        tabbing.getTabbableElements(parentContainer)
                            .filter(":visible:first")
                            .focus();
                    }
                });
            },

            shouldForceDropdownOpening: function($element) {
                return $element.closest('.select-validation-error').length !== 0;
            },

            getFirstElement: function(parentContainer) {
                parentContainer = parentContainer || $('.box-container.edit-dialog:visible, .login-tab form:visible');

                var $tabbableElements = this.getTabbableElements(parentContainer).filter(':visible');
                var $uploadButton = $tabbableElements.filter('.attachment-upload-button:first');
                var $first = $tabbableElements.filter(':first');
                var hasError = false;
                var length = $tabbableElements.length;

                if ($uploadButton.length) {
                    return $uploadButton;
                }
                
                for (var i = 0; i < length; i++) {
                    var $element = $($tabbableElements[i]);
                    
                        hasError = $element.hasClass('validation-error');
                        if (!hasError) {
                            isElementDropdown = hasError = $element.closest('.select-validation-error').length !== 0;
                        }

                        if (!hasError) { // case for radiogroup or checkboxes group
                            var inputSet = $element.closest('.radio-set, .checkbox-set');
                            hasError = inputSet.hasClass('validation-error') || inputSet.parent().hasClass('validation-error');
                        }

                        if (hasError) {
                            $first = $element;
                            break;
                        }
                }

                var $inputSet = $first.closest('.radio-set');
                
                if ($inputSet.length) {
                    var $checkedRadio = $inputSet.find('input[type=\'radio\']:checked');
                    if ($checkedRadio.length) {
                        $first = $checkedRadio;
                    }
                }

                return $first;
            },

            activateFirstElement: function (parentContainer, callback) {
                var $first = this.getFirstElement(parentContainer);

                // If the validation was caused by pressing some button, we need 
                // to wait for all events, otherwise we can immediately lose focus.
                setTimeout(function () {
                    $first.focus();

                    if (callback !== undefined)
                        callback($first);
                });
            }
        };

        self.updateFloatingMenu = function () {
            if ($('html').is('.job-page')) return;

            var $wrapper = self.getOnlineAppContainer(),
                $navTabs = $wrapper.find('.nav-tabs');

            $wrapper = $wrapper.has($navTabs[0]);

            if (!$navTabs.is(":visible")) return;

            var firstItem = $navTabs.children('li:visible:first'),
                menuItemsCount = $navTabs.children('li:visible').length;

            var menuHeight = firstItem.outerHeight(true) * menuItemsCount;
            var navTabsPaddingTop = parseInt($navTabs.css('padding-top'), 10);
            var scrollContainerRect = $wrapper.scrollParent()[0].getBoundingClientRect();
            var fullHeight = menuHeight + scrollContainerRect.top + navTabsPaddingTop;

            if (fullHeight < $(window).height()) {
                $navTabs.addClass('fixed');

                var positionStyleValue = $navTabs.css('position');

                if (positionStyleValue === 'fixed') {
                    $navTabs.css('top', 'auto');
                } else {
                    $navTabs.css('top', 0);
                }
            } else {
                $navTabs.removeClass('fixed');
                $navTabs.css('top', 0);
            }
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Helpers', {
        layoutHelper: new LayoutHelper()
    });

})(window);;
(function (window, undefined) {
    'use strict';


    function DateTimeFormatter() {

        var self = this;


        self.getMilitaryTime = function (dateTime) {

            function pad(number, length) {

                var str = '' + number;

                while (str.length < length) {
                    str = '0' + str;
                }

                return str;

            }
            
            var militaryHours = dateTime.getHours();
            var isAfterNoon = (militaryHours >= 12);

            var hours = (militaryHours % 12);
            hours = hours ? hours : 12;

            var minutes = dateTime.getMinutes();

            return pad(hours, 2) + ':' + pad(minutes, 2) + ' ' + (isAfterNoon ? 'PM' : 'AM');
        },

        self.getFullDate = function (dateTime) {

            var months = [
                'January', 'February', 'March', 'April', 'May',
                'June', 'July', 'August', 'September', 'October',
                'November', 'December'
            ];

            var weekDays = [
                'Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'
            ];


            var formattedDate =
                weekDays[dateTime.getDay()] + ', ' +
                months[dateTime.getMonth()] + ' ' +
                dateTime.getDate();

            return formattedDate;
        },

        self.getFullDateNoDay = function (dateTime) {

            var months = [
                'January', 'February', 'March', 'April', 'May',
                'June', 'July', 'August', 'September', 'October',
                'November', 'December'
            ];
            
            var formattedDate =
                months[dateTime.getMonth()] + ' ' +
                dateTime.getDate();

            return formattedDate;
        },

        self.getShortDate = function (dateTime) {
            var day = dateTime.getDate();
            var month = dateTime.getMonth() + 1;
            var year = dateTime.getFullYear();

            var dateComponents = [month, day, year];
            var dateOutput = dateComponents.join('/');

            return dateOutput;
        },

        self.getShortDateTime = function (dateTime) {
            var date = self.getShortDate(dateTime);
            var time = self.getMilitaryTime(dateTime);

            var formattedDateTime = (date + ' ' + time);

            return formattedDateTime;
        }
    }



    OnlineApp.Namespace.extend('OnlineApp.Helpers', {
        DateTimeFormatter: new DateTimeFormatter()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function Notifications() {
        var self = this;

        self.showResponseMessages = function (response) {
            var messagesToShow = [];
            
            if (typeof response == 'string' || response instanceof String) {
                messagesToShow = [response];
            } else if ($.isArray(response)) {
                for (var i = 0; i < response.length; i++) {
                    var error = response[i];
                    if (error && error.errorMessage) {
                        messagesToShow.push(error.errorMessage);
                    }
                }
            }
            if (messagesToShow.length === 0) {
                messagesToShow = [Resources.NotificationMessages.EncounteredProblem];
            }
            
            for (var i = 0; i < messagesToShow.length; i++) {
                toastr.warning(messagesToShow[i]);
            }
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Helpers', {
        Notifications: new Notifications()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    var debounce = function (func, wait) {
        var timeout,
            args,
            context,
            timestamp,
            result,
            later = function () {
                var last = getNowDate() - timestamp;
                if (last < wait) {
                    timeout = setTimeout(later, wait - last);
                } else {
                    timeout = null;
                    result = func.apply(context, args);
                    context = args = null;
                }
            },
            getNowDate = Date.now || function () {
                return new Date().getTime();
            };

        return function () {
            context = this;
            args = arguments;
            timestamp = getNowDate();
            if (!timeout) {
                timeout = setTimeout(later, wait);
            }

            return result;
        };
    };

    OnlineApp.Namespace.extend('OnlineApp.Helpers', {
        FunctionUtilities: {
            debounce: debounce
        }
    });

})(window);;
(function (window, undefined) {

    function CaptchaHelper(container) {

        var self = this;
        var captchaContainerSelector = 'captcha-container';
        var captchaContainerClassSelector = '.' + captchaContainerSelector;
        var captchaContainerIdSelector = '#' + captchaContainerSelector;
        var currentCaptchaIndices = [];

        self.isCaptchaSubmitted = false;
        self.container = container || 'document';

        function enableLoginButtonForSubmitedRecaptcha() {
            var recaptchaContainers = $(self.container).find(captchaContainerClassSelector);
            for (var captchaIndex = 0; captchaIndex < recaptchaContainers.length; captchaIndex++) {
                if (grecaptcha.getResponse(currentCaptchaIndices[captchaIndex]).length > 0) {
                    var captchaContainer = $(captchaContainerIdSelector + captchaIndex);
                    captchaContainer.parent().next('button').prop('disabled', false);
                    captchaContainer.attr('aria-label', 'Recaptcha challenge solved');
                }
            }
        }

        self.setCaptchaResponse = function(response) {
            self.captchaResponse = response;
            self.isCaptchaSubmitted = true;

            enableLoginButtonForSubmitedRecaptcha();
        }

        self.expiredResponseCallback = function() {
            self.isCaptchaSubmitted = false;
        }

        self.resetCaptcha = function () {
            var recaptchaContainers = $(self.container).find(captchaContainerClassSelector);
            for (var captchaIndex = 0; captchaIndex < recaptchaContainers.length; captchaIndex++) {
                var captchaContainer = $(captchaContainerIdSelector + captchaIndex);
                captchaContainer.parent().next('button').prop('disabled', true);
                captchaContainer.attr('aria-label', 'Plеase, solve captcha challenge');
                self.captchaResponse = null;
                self.isCaptchaSubmitted = false;
                grecaptcha.reset(currentCaptchaIndices[captchaIndex]);
            }
        }

        self.renderCaptcha = function () {
            grecaptcha.ready(function() {
                currentCaptchaIndices = [];
                var recaptchaContainers = $(self.container).find(captchaContainerClassSelector);
                for (var i = 0; i < recaptchaContainers.length; ++i) {
                    if ($(recaptchaContainers[i]).is(':empty')) {
                        $(recaptchaContainers[i]).attr('id', captchaContainerSelector + i);
                        var captchaIndex = grecaptcha.render($(recaptchaContainers[i]).attr('id'),
                            {
                                'sitekey': window.recaptchaPublicKey,
                                'callback': self.setCaptchaResponse,
                                'expired-callback': self.expiredResponseCallback
                            });
                        $(recaptchaContainers[i]).find('iframe').attr('title', 'Captcha Challenge');
                        $(recaptchaContainers[i]).parent().next('button').prop('disabled', true);
                        currentCaptchaIndices.push(captchaIndex);
                    }
                }
            });
        }
    }

    OnlineApp.Namespace.extend('OnlineApp.Helpers', {
        CaptchaHelper: CaptchaHelper,
        loginCaptchaHelper: new CaptchaHelper('.login-tab')
    });

})(window);;
(function(window, undefined) {
    'use strict';

    function TextSearchWithAutocompleteLabelsComponentHelper() {
        var self = this;

        var fullWidthClassName = 'full-width';

        function createSelectedAutocompleteLabel(labelText,originalLabel,name) {
            var labelMarkup = '<div class="selected-search-label-container">' +
                                '<span class="selected-search-label-text" ' +
                                      'data-toggle="popover" ' +
                                      'data-trigger="hover focus" ' +
                                      'data-placement="bottom" ' +
                                      'data-container="body" ' +
                                      'data-selector="true" ' +
                'data-original-title=" ">' +
                                    labelText +
                                '</span>' +
                '<button class="selected-search-label-remove-button ss-delete" aria-label="Remove ' + name + ' &quot;' + originalLabel + '&quot;" data-trigger="hover focus" data-toggle="popover" data-placement="bottom" title="Remove ' + name + ' &quot;' + originalLabel +'&quot;"></button>' +
                              '</div>';

            return $(labelMarkup);
        }

        function removeSelectedAutocompleteLabelFromLabelsContainer(event) {
            var $removeButton = $(event.target);

            $removeButton.parent('.selected-search-label-container').remove();
        }

        function recalculateSearchFieldWidthAfterRemovingSelectedLabel(searchComponentContainerSelector) {
            var $searchFieldContainer = $(searchComponentContainerSelector + ' .search-field-container');
            var $searchField = $searchFieldContainer.find('.search-field');

            $searchFieldContainer.removeClass(fullWidthClassName);

            if ($searchField[0].clientHeight < $searchField[0].scrollHeight) {
                $searchFieldContainer.addClass(fullWidthClassName);
            }
        }

        self.addSelectedAutocompleteLabelToSearchComponent = function(labelText, searchComponentContainerSelector, removeSelectedAutocompleteLabelCallback,name,fieldSelector) {
            var truncatedLabelText = labelText;

            if (labelText.length > window.selectedLabelTextLengthForAdvancedJobInterestCard) {
                truncatedLabelText = labelText.substring(0, window.selectedLabelTextLengthForAdvancedJobInterestCard) + '...';
            }
            $(fieldSelector).removeAttr("aria-label");
            var $selectedLabel = createSelectedAutocompleteLabel(truncatedLabelText, labelText, name);
            $(fieldSelector).attr("aria-label", name + " " + labelText + " " + 'selected');           
            var buttonToolTipText = "Remove " + name + ' "' + labelText+'"';

            $selectedLabel.find('button[data-toggle="popover"]').attr('data-content', buttonToolTipText);
            $selectedLabel.find('button[data-toggle="popover"]').delayedPopover();

            $selectedLabel.find('span[data-toggle="popover"]').attr('data-content', labelText);
            $selectedLabel.find('span[data-toggle="popover"]').delayedPopover();

            $selectedLabel.find('.selected-search-label-remove-button').click(function(event) {
                if (removeSelectedAutocompleteLabelCallback) removeSelectedAutocompleteLabelCallback();

                removeSelectedAutocompleteLabelFromLabelsContainer(event);
                recalculateSearchFieldWidthAfterRemovingSelectedLabel(searchComponentContainerSelector);
            });

            var $containerForSelectedLabel = $(searchComponentContainerSelector + ' .search-labels-container');

            if ($containerForSelectedLabel && $containerForSelectedLabel.length)
                $containerForSelectedLabel.append($selectedLabel);
        };

        self.initScrollHandlersForSearchField = function(searchComponentContainerSelector) {
            var $searchFieldContainer = $(searchComponentContainerSelector + ' .search-field-container');
            var $searchField = $searchFieldContainer.find('.search-field');

            if ($searchField && $searchField.length) {
                $searchField.on('input', function(event) {
                    if ($searchField[0].clientHeight < $searchField[0].scrollHeight) {
                        if ($searchFieldContainer.hasClass(fullWidthClassName)) {
                            $searchField.height($searchField[0].scrollHeight);
                        }

                        $searchFieldContainer.addClass(fullWidthClassName);
                    }
                });

                $searchField.on('keydown', function(event) {
                    if ($searchField[0].clientHeight >= $searchField[0].scrollHeight) {
                        var key = event.keyCode || event.charCode;

                        if (key === $.ui.keyCode.BACKSPACE || key === $.ui.keyCode.DELETE) {
                            $searchFieldContainer.removeClass(fullWidthClassName);
                        }
                    }
                });
            }
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Helpers', {
        textSearchWithAutocompleteLabelsComponentHelper: new TextSearchWithAutocompleteLabelsComponentHelper()
    });

})(window);
;
(function (window, undefined) {
    'use strict';
    /*
        Sometimes when server is misconfigured, it may respond with HTTP 302 status code instead of HTTP 401 when user session is expired.
        As Ajax requests automatically follow these redirects, the response may end up being 200 OK, so we need to perform validation
        of the response body to be sure it is really a valid success response from the API.
    */

    var isValidSuccessResponse = function (responseData) {
        return (responseData &&
            (responseData.isSuccess === true || !!responseData.dateSubmittedText));
    };

    var ensurePromiseFailsOnInvalidData = function (promise, customSuccessResponseValidator) {
        var deferred = $.Deferred();

        var validate = customSuccessResponseValidator || isValidSuccessResponse;

        promise.done(function (data) {
            if (validate(data)) {
                deferred.resolveWith(this, arguments);
            } else {
                deferred.rejectWith(this);
            }
        }).fail(function () {
            deferred.rejectWith(this, arguments);
        });

        var resultPromise = deferred.promise();

        //If the original promise is a jQuery XHR object, then legacy subscribers may expect it to have
        //'success' and 'error' methods which are actually the same as 'done' and 'fail'
        if (typeof promise.error === 'function') {
            resultPromise.error = resultPromise.fail;
        }
        if (typeof promise.success === 'function') {
            resultPromise.success = resultPromise.done;
        }

        return resultPromise;
    };

    OnlineApp.Namespace.extend('OnlineApp.Helpers', {
        ajaxResponseValidator: {
            ensurePromiseFailsOnInvalidData: ensurePromiseFailsOnInvalidData
        }
    });

})(window);;
(function (window, undefined) {

    function PopoverHelper() {

        var self = this;

        self.initializePopover = function (container, button) {
            $(container).on('click',function (event) {
                var $button = $(button);
                var $target = $(event.target);
                var isTheSameElement = $target.closest($button).length != 0;
                var $popover = $button.siblings('.popover');

                if (isTheSameElement) {
                    if (!$popover.is(':visible')) {
                        $button.popover('show');
                    }
                } else {
                    $button.popover('hide');
                }
            });
        };

        self.accountInitializePopover = function (container, button) {
            $(container).mouseover(function (event) {
                var $button = $(button);
                var $target = $(event.target);
                var isTheSameElement = $target.closest($button).length != 0;
                var $popover = $button.siblings('.popover');

                if (isTheSameElement) {
                    if (!$popover.is(':visible')) {
                        $button.popover('show');
                    }
                } else {
                    $button.popover('hide');
                }
            });
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Helpers', {
        popoverHelper: new PopoverHelper()
    });

})(window);;
(function (window, undefined) {
    'use strict';
    
    function renderTemplateToString(templateName, viewModel, shouldStripHtmlTags) {
        var $virtualElement = $('<div>');
        var bindingContext = viewModel;

        ko.renderTemplate(templateName,
                         bindingContext,
                         { templateEngine: ko.KoExternalTemplateEngine() },
                         $virtualElement.get(0),
                         'replaceChildren');

        var templateString = $virtualElement.html();
        if (shouldStripHtmlTags) {
            templateString = $(templateString).text();
        }

        $virtualElement.remove();
        return templateString;
    }

    OnlineApp.Namespace.extend('OnlineApp.Helpers.Templates', {
        renderTemplateToString: renderTemplateToString
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function getJsonFromUrl(url) {
        var query = url.substr(1);
        query = query.replace(/%5B0/g, '').replace(/%5D/g, '');
        var result = {};
        query.split("&").forEach(function (part) {
            var item = part.split("=");
            result[item[0]] = decodeURIComponent(item[1]);
        });

        return result;
    }

    OnlineApp.Namespace.extend('OnlineApp.Helpers.Url', {
        getJsonFromUrl: getJsonFromUrl
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function CachedAjaxRequest(options) {
        var self = this;

        var request = null;
        var data = null;

        self.send = function() {

            if (data === null) {
                if (request === null) {
                    request = $.ajax(options)
                        .then(function (data) {
                            data = data;
                            return data;
                        })
                        .always(function () {
                            request = null;
                        });
                    return request;
                } else {
                    return request;
                }
            }

            return $.when(data);
        }

        self.resetCache = function() {
            data = null;
        }
    }

    namespace('gJobs').CachedAjaxRequest = CachedAjaxRequest;

})(window);;
(function(window, undefined) {
    function ApplicationTabOrderHelper() {
        var self = this;

        var $lastActiveMenuItem = null,
            $currentFirstTabbableElement = null,
            $currentLastTabbableElement = null,
            $currentTabLink = null,
            $previousTab = null;

        var containerSelector = '.onlineapp-app-container';

        self.setLastMenuItemFocusBehaviour = function() {
            var $container = $(containerSelector);
            var $lastMenuItem =
                $container.find('ul.left-menu-nav li a:not(.disabled)').last();
            var $nextFocusableElement = $('#last-focusable-element');

            if (!$nextFocusableElement.length) {
                var footerSelector = window.revampedDesign
                    ? '#footer,footer,#footer-new,#sjobs-footer-new'
                    : '#footer,footer';
                var $footer = $(footerSelector);
                $nextFocusableElement = $($footer.find(':tabbable').first());

                gJobs.focusService.setFocusOnKeydown({
                    $element: $nextFocusableElement,
                    $targetElement: $lastMenuItem,
                    $previousElement: $lastActiveMenuItem,
                    shift: true
                });
            } else {
                gJobs.focusService.setFocusOnKeydown({
                    $element: $nextFocusableElement,
                    $targetElement: $lastMenuItem,
                    shift: true
                });
            }

            gJobs.focusService.setFocusOnKeydown({
                $element: $lastMenuItem,
                $targetElement: $nextFocusableElement,
                $previousElement: $lastActiveMenuItem
            });

            $lastActiveMenuItem = $lastMenuItem;
        };

        self.setTabOrder = function () {

            self.setLastMenuItemFocusBehaviour();

            var activeTab = OnlineApp.Controllers.navigationMenuController.getActiveTab();

            if (!activeTab.tab.length) return;

            var $activeTabLink = $('ul.left-menu-nav [href="#' + activeTab.tabId + '"]');
            var $tabbableElements = activeTab.tab.find(':tabbable');
            var $lastTabbableElement = $($tabbableElements.last());
            var $firstTabbableElement = $($tabbableElements.first());
            var $nextTab = $activeTabLink.parent().next().find('a:not(.disabled)');

            gJobs.focusService.setFocusOnKeydown({
                $element: $activeTabLink,
                $targetElement: $firstTabbableElement,
                $previousElement: $currentTabLink
            });

            gJobs.focusService.setFocusOnKeydown({
                $element: $firstTabbableElement,
                $targetElement: $activeTabLink,
                $previousElement: $currentFirstTabbableElement,
                shift: true
            });

            gJobs.focusService.setFocusOnKeydown({
                $element: $lastTabbableElement,
                $targetElement: $nextTab,
                $previousElement: $currentLastTabbableElement
            });

            if ($nextTab.length) {
                gJobs.focusService.setFocusOnKeydown({
                    $element: $nextTab,
                    $targetElement: $lastTabbableElement,
                    $previousElement: $previousTab,
                    shift: true
                });
            } else {
                gJobs.focusService.removeFocusOnKeydownHandler($previousTab, true);
            }

            $currentFirstTabbableElement = $firstTabbableElement;
            $currentLastTabbableElement = $lastTabbableElement;
            $currentTabLink = $activeTabLink;
            $previousTab = $nextTab;
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Helpers',
    {
        applicationTabOrderHelper: new ApplicationTabOrderHelper()
    });
})(window);
;
(function (window, undefined) {
    'use strict';

    function LocalStorageHelper() {
        var self = this;

        self.updateItemForMultipleTabs = function (key, value) {
            localStorage.removeItem(key);
            localStorage.setItem(key, value);
        }
    }

    namespace('gJobs').LocalStorageHelper = LocalStorageHelper;
    namespace('gJobs').localStorageHelper = new LocalStorageHelper();

})(window);
;
 function getListOfElmentsToBeExcluded() {
        var elementsToExclude = ['showNewResetPassword', 'hideNewResetPassword', 'showResetPassword', 'hideResetPassword',
            'showPassword', 'hidePassword', 'showCurrentPassword', 'hideCurrentPassword',
            'showNewPassword', 'hideNewPassword', 'showConfirmPassword', 'hideConfirmPassword',
            'showCurrentEditEmailPassword', 'hideCurrentEditEmailPassword', 'showSignUpPassword', 'hideSignUpPassword',
            'showSignUpConfirmPassword', 'hideSignUpConfirmPassword', 'search-button', 'clear-field-button', 'closeMap', 'openMap','top-resume-upload','att-send-to-top-resume',];
        return elementsToExclude;
    }
    
;
(function (window, undefined) {
    'use strict';

    function AccountSettingsHelper() {
        var self = this;

        self.getLinkForAccountSettings = function () {
            var abstractAreaInfoService = new gJobs.AbstractAreaInfoService();

            var ACCOUNT_SETTINGS_URL = "/Applications/AccountSettings";
            
            var linkForAccountSettings = "";
            var currentArea = gJobs.areaInfoService.getCurrentArea();

            if (currentArea === abstractAreaInfoService.areaNames.GJobs) {
                linkForAccountSettings = ACCOUNT_SETTINGS_URL;
            } else {
                if (currentArea === abstractAreaInfoService.areaNames.Career) {
                    linkForAccountSettings = AgencyPages.pageInfoService.getCurrentAgencyHomePath() + ACCOUNT_SETTINGS_URL;
                } else if (currentArea === abstractAreaInfoService.areaNames.Agency) {
                    var agencyFolderName = AgencyPages.pageInfoService ?
                        AgencyPages.pageInfoService.getCurrentAgencyFolderName() :
                        gJobs.pageInfoService.getCurrentAgencyPageFolderName();

                    linkForAccountSettings = ACCOUNT_SETTINGS_URL + "/" + agencyFolderName;
                }
            }

            return linkForAccountSettings;
        }
    }

    namespace('gJobs').AccountSettingsHelper = AccountSettingsHelper;
    namespace('gJobs').accountSettingsHelper = new AccountSettingsHelper();

})(window);
;
(function (window, undefined) {
    'use strict';

    function EmailVerificationHelper() {
        if (window.enableEmailVerification && !window.enableEmailVerificationRefinements) {
            var EMAIL_VERIFICATION_BANNER_WRAPPER_ID = "email-verification-banner-wrapper";
            var EMAIL_VERIFICATION_BANNER_ID = "email-verification-banner";
            var CAREERS_FOOTER_SELECTOR = "#main-container footer";
            var GJOBS_FOOTER_SELECTOR = "#footer-new";
            var ACCOUNT_SETTINGS_LINK_SELECTOR = ".account-settings-link";
            var TO_TOP_BUTTON_SELECTOR = "#to-top-panel";

            var mainScrollableElement = document;
            var emailVerificationWrapper = $("#" + EMAIL_VERIFICATION_BANNER_WRAPPER_ID);
            var emailVerificationBanner = emailVerificationWrapper.children("#" + EMAIL_VERIFICATION_BANNER_ID);
            var accountSettingsLink = emailVerificationBanner.find(ACCOUNT_SETTINGS_LINK_SELECTOR);
            var toTopButton = $(TO_TOP_BUTTON_SELECTOR);
            var footer;

            var isEmailVerified = false;
            var isCareersPage = false;
            var isInitiated = false;
            var isBannerWasClosedInCurrentSession = (sessionStorage.getItem(OnlineApp.SessionKeys.IsBannerWasClosedInCurrentSession) === 'true');
            var isInboxPage = false;
            var isAgencyPages;
            var isFlyoutOpen = false;
            var isScheduleFlyoutOpen = false;

            var areaNames;
            var pageTypes;
            var currentPageType;
            var currentArea;
            var pageInfoService;
            var documentHeight = $(document).height();
            var mainScrollableElementHeight;

            function isJobPage() {
                return Boolean(($('.job-page').length || $('.standalone-job-page').length) && !$('.job-page-access-membership').length);
            }

            function isAgencyPagesApplicationProcess() {
                return isAgencyPages && pageInfoService.isOnApplyPage();
            }

            function isEmailVerificationBannerEnabled () {
                return !isEmailVerified && !isBannerWasClosedInCurrentSession;
            }

            function updateStylesForEmailVerificationBanner () {
                if (isEmailVerificationBannerEnabled()) {
                    if (isCareersPage) {
                        footer.css('margin-top', '');
                        emailVerificationWrapper.css('margin-top', footer.css('margin-top'));
                        emailVerificationWrapper.css('height', emailVerificationBanner.outerHeight() + "px");
                        footer.css('margin-top', '0');
                    } else {
                        emailVerificationWrapper.css('height', emailVerificationBanner.outerHeight() + "px");
                    }
                }
            }

            function closeEmailVerificationBanner () {
                sessionStorage.setItem(OnlineApp.SessionKeys.IsBannerWasClosedInCurrentSession, 'true');
                isBannerWasClosedInCurrentSession = true;

                emailVerificationWrapper.css('display', 'none');

                if (isCareersPage) {
                    footer.css('margin-top', '');
                }
            }

            function recalculateEmailVerificationBannerPosition () {
                if (isEmailVerificationBannerEnabled() && !isScheduleFlyoutOpen) {
                    if (isScrolledIntoView(footer)) {
                       emailVerificationBanner.css('position', 'absolute');
                       updateStylesForEmailVerificationBanner();
                    } else {
                       emailVerificationBanner.css('position', 'fixed');
                    }
                }
            }

            function showEmailVerificationBanner (fromLoginEvent) {
                if (fromLoginEvent || !isBannerWasClosedInCurrentSession) {
                    emailVerificationWrapper.css('display', 'block');
                    updateStylesForEmailVerificationBanner();
                }
            }

            function tryMakeEmailVerificationBannerAbsoluteBeforeShow () {
                var isProfileSettingsPage = currentPageType === pageTypes.profileSettings.type;

                if (currentPageType && (isProfileSettingsPage || documentHeight === $(window).height())) {
                    if (!isCareersPage && isProfileSettingsPage) {
                        /*
                            It's needed because on Gjobs "Profile Settings" page "onlineapp-loading-spinner"
                            will overlap email verification banner
                        */
                        emailVerificationBanner.css('z-index', 8);
                    }

                    emailVerificationBanner.css('position', 'absolute');

                    return true;
                }

                return false;
            }

            function isScrolledIntoView(el) {
                var rect = el[0].getBoundingClientRect();
                var elemTop = rect.top;
                var elemBottom = rect.bottom;
            
                var isVisible = elemTop < window.innerHeight && elemBottom >= 0;
                
                return isVisible;
            }

            function initEmailVerificationBanner () {
                if (!isEmailVerified && !isInitiated) {
                    var accountSettingsLinkHref = gJobs.accountSettingsHelper.getLinkForAccountSettings();

                    accountSettingsLink.attr('href', accountSettingsLinkHref);
                                
                    if (isInboxPage) {
                        (function startCheckingScrollableElementHeightChange () {
                            setInterval(function() {
                                var currentMainScrollableElementHeight = $(mainScrollableElement)[0].scrollHeight;
                                if (mainScrollableElementHeight !== currentMainScrollableElementHeight) {
                                    recalculateEmailVerificationBannerPosition();
                                    mainScrollableElementHeight = currentMainScrollableElementHeight;
                                }
                            }, 600);  
                        })();
                    } else if ((isCareersPage && currentPageType && currentPageType !== pageTypes.jobOpportunitiesJobs.type)
                                || (!isCareersPage && currentPageType && currentPageType !== pageTypes.homePage.type && currentPageType !== pageTypes.searchPage.type)
                    ) {
                        (function startCheckingDocumentHeightChange () {
                            setInterval(function() {
                                var currentDocumentHeight = $(mainScrollableElement).height();
                                if (!isFlyoutOpen && !isScheduleFlyoutOpen && documentHeight !== currentDocumentHeight) {
                                    recalculateEmailVerificationBannerPosition();
                                    documentHeight = currentDocumentHeight;
                                }
                            }, 600);    
                        })();
                    }
            
                    $(document).delegate('.close-email-verification-banner', 'click', closeEmailVerificationBanner);
                    $(document).on('resize', updateStylesForEmailVerificationBanner);
                    $(mainScrollableElement).scroll(recalculateEmailVerificationBannerPosition);

                    $(document).on(Events.CommonEventsNames.ToTopButtonTopPropertyChanged, function () {
                        if (isEmailVerificationBannerEnabled()) {
                            if (!toTopButton.length) {
                                toTopButton = $(TO_TOP_BUTTON_SELECTOR);
                            }

                            /* 
                                It's needed because email verification banner 
                                will overlap "to-top-panel" button
                            */
                           toTopButton.css('top',  (parseFloat(toTopButton.css('top')) - emailVerificationBanner.outerHeight()) + 'px');
                        }
                    });

                    $(document).on(Events.CommonEventsNames.ShowFlyout, function () {
                        isFlyoutOpen = true;
                        accountSettingsLink.attr('aria-hidden', 'true');
                        accountSettingsLink.attr('tabindex', -1);
                    });

                    $(document).on(Events.CommonEventsNames.FlyoutClosing, function () {
                        isFlyoutOpen = false;
                        accountSettingsLink.removeAttr('aria-hidden tabindex');
                    });

                    $(document).on(Events.CommonEventsNames.HistoryFlyoutOpened + " " + Events.CommonEventsNames.ScheduleFlyoutOpened, function () {
                        if (!isCareersPage) {
                            isFlyoutOpen = true;
                            emailVerificationBanner.css('position', 'fixed');
                        }
                    });

                    $(document).on(Events.CommonEventsNames.HistoryFlyoutClosed, function () {
                        if (!isCareersPage) {
                            isFlyoutOpen = false;
                            recalculateEmailVerificationBannerPosition();
                        }
                    });

                    $(document).on(Events.CommonEventsNames.ScheduleFlyoutOpened, function () {
                        if (!isCareersPage) {
                            isScheduleFlyoutOpen = true;
                        }
                    });

                    $(document).on(Events.CommonEventsNames.ScheduleFlyoutClosed, function () {
                        if (!isCareersPage) {
                            isFlyoutOpen = false;
                            isScheduleFlyoutOpen = false;
                        }
                    });

                    isInitiated = true;

                    if (!tryMakeEmailVerificationBannerAbsoluteBeforeShow()) {
                        emailVerificationBanner.css('position', 'fixed');
                    }
                }
            }

            function tryShowEmailVerificationBanner (fromLoginEvent) {
                var abstractAreaInfoService = new gJobs.AbstractAreaInfoService();

                pageInfoService = gJobs.pageInfoService ? gJobs.pageInfoService : AgencyPages.pageInfoService;
                pageTypes = pageInfoService.getPageTypes();
                var currentPage = pageInfoService.getCurrentPageType();
                areaNames = abstractAreaInfoService.areaNames;
                currentArea = gJobs.areaInfoService.getCurrentArea();
                isAgencyPages = currentArea === areaNames.Agency;

                if (currentArea === areaNames.Career) {
                    isCareersPage = true;
                    footer = $(CAREERS_FOOTER_SELECTOR);
                    emailVerificationWrapper.css('position', 'relative');
                } else {
                    footer = $(GJOBS_FOOTER_SELECTOR);
                }

                if (currentPage) {
                    currentPageType = currentPage.type;
                }

                if (currentPageType === pageTypes.inbox.type || (isAgencyPages && currentPageType === pageTypes.agencyInbox.type)) {
                    isInboxPage = true;

                    if (isCareersPage) {
                        mainScrollableElement = $('#sizer');
                    } else {
                        mainScrollableElement = $('#body-container');
                    }

                    mainScrollableElementHeight = mainScrollableElement[0].scrollHeight;
                }

                if ((!currentPageType || currentPageType !== pageTypes.accountSettings.type) && !isAgencyPagesApplicationProcess() && !isJobPage()) {
                    OnlineApp.Services.authenticationService.isLoggedIn()
                        .done(function (isLoggedIn) {
                            if (isLoggedIn) {
                                OnlineApp.Services.emailVerificationService.isEmailVerified()
                                .then(function(response) {
                                    var data = response.data;
            
                                    if (data.isEmailVerified !== true) {
                                        initEmailVerificationBanner();
                                        showEmailVerificationBanner(fromLoginEvent);
                                    } else {
                                        isEmailVerified = true;
                                    }
                                });
                            }
                        });
                }
            }


            $(document).ready(function () {
                tryShowEmailVerificationBanner();
            });

            $(document).on(Events.CommonEventsNames.Login + " " + Events.CommonEventsNames.Register, function () {
                isEmailVerified = false;

                isBannerWasClosedInCurrentSession = false;
                sessionStorage.setItem(OnlineApp.SessionKeys.IsBannerWasClosedInCurrentSession, "false");
                
                tryShowEmailVerificationBanner(true);
            });
            $(document).on(OnlineApp.Events.CommonEventsNames.EmailVerified, function () {
                emailVerificationWrapper.css('display', 'none');

                if (isCareersPage) {
                    footer.css('margin-top', '');
                }
                
                isEmailVerified = true;
            });
        }
    }

    namespace('gJobs').emailVerificationHelper = new EmailVerificationHelper();

})(window);
;
(function (window, undefined) {
    'use strict';

    function AccountVerificationHelper() {
        var self = this,
            showBannerAfterSuccessfulVerificationQueryParameter = "showBannerAfterSuccessfulVerification",
            showBannerAfterFailedVerificationQueryParameter = "showBannerAfterFailedVerification",
            emailAddressQueryParameter = "emailAddress",
            failVerificationLinkNotificationClassName = "fail-verification-link-notification";
        
        self.showNotification = function(htmlContent, options) {
            var successEmailNotificationEventName = "successEmailNotification";
            var successEmailNotificationSelector = "success-email-notification";
            var successEmailNotification = $('#' + successEmailNotificationSelector);

            if (successEmailNotification.length !== 0) {
                successEmailNotification.html(htmlContent);
                if (options && options.additionalCssClassNames) {
                    successEmailNotification.addClass(options.additionalCssClassNames);
                }
                successEmailNotification.css("display", "flex");
            } else {
                $('body').append(
                    "<div class='uses-gjobs-styles'><div id='" + successEmailNotificationSelector + "'>" + htmlContent + "</div></div>"
                );

                successEmailNotification = $('#' + successEmailNotificationSelector);

                if (options && options.additionalCssClassNames) {
                    successEmailNotification.addClass(options.additionalCssClassNames);
                }
            }

            gJobs.screenReadersService.setAriaLiveNotification(successEmailNotification.text());

            $(document).on('click.' + successEmailNotificationEventName, function () {
                successEmailNotification.css("display", "none");
                if (options && options.additionalCssClassNames) {
                    successEmailNotification.removeClass(options.additionalCssClassNames);
                }
            });

            setTimeout(function () {
                successEmailNotification.css("display", "none");
                if (options && options.additionalCssClassNames) {
                    successEmailNotification.removeClass(options.additionalCssClassNames);
                }
                $(document).off('click.' + successEmailNotificationEventName);
            }, 20000)
        };

        //Mimic to serve Banner for Resend Link
        self.showNotificationMimic = function (htmlContent, options, isSuccess) {
            var successEmailNotificationEventName = "successEmailNotification";
            var emailNotificationSelector = isSuccess ? "success-email-notification" : "fail-email-notification";
            var successEmailNotification = $('#' + emailNotificationSelector);

            if (successEmailNotification.length !== 0) {
                successEmailNotification.html(htmlContent);
                if (options && options.additionalCssClassNames) {
                    successEmailNotification.addClass(options.additionalCssClassNames);
                }
                successEmailNotification.css("display", "flex");
            } else {
                $('body').append(
                    "<div class='uses-gjobs-styles'><div id='" + emailNotificationSelector + "'>" + htmlContent + "</div></div>"
                );

                successEmailNotification = $('#' + emailNotificationSelector);

                if (options && options.additionalCssClassNames) {
                    successEmailNotification.addClass(options.additionalCssClassNames);
                }
            }

            gJobs.screenReadersService.silenceScreenreaderForBanner(successEmailNotification.text());
            gJobs.screenReadersService.setAriaLiveNotification("Successfully changed email id");
            $(document).on('click.' + successEmailNotificationEventName, function () {
                successEmailNotification.css("display", "none");
                if (options && options.additionalCssClassNames) {
                    successEmailNotification.removeClass(options.additionalCssClassNames);
                }
            });

            setTimeout(function () {
                successEmailNotification.css("display", "none");
                if (options && options.additionalCssClassNames) {
                    successEmailNotification.removeClass(options.additionalCssClassNames);
                }
                $(document).off('click.' + successEmailNotificationEventName);
            }, 20000)
        };

        self.showAccountVerificationNotification = function (userEmail, verificationResult) {
            var isSuccess = verificationResult == "true";
            var htmlContentSuccess = "<div class='success-email-notification-holder'><img class='email-verification-success-icon' src='/Content/Images/email-verification-success-notification-icon-white.svg' /><span role='alert'>Your account (" + userEmail + ") is verified</span></div>";
            var htmlContentFail = "<div class='fail-verification-link-notification'><img class='email-verification-success-icon' src='/Content/Images/email-verification-success-notification-icon-white.svg' /><span role='alert'>Sorry, your request is invalid. This email address is already in use</span></div>";

            self.showNotificationMimic(isSuccess ? htmlContentSuccess : htmlContentFail, null, isSuccess);
        }

        self.showResendCodeSuccessNotification = function () {
            var htmlContent = "<div class='success-email-notification-holder'><span>A new verification code has been sent to your email address</span></div>";

            self.showNotification(htmlContent);
        }

        self.showVerificationLinkFailNotification = function() {
            var htmlContent = "<div class='success-email-notification-holder'><span>Your verification link is expired</span></div>";

            var options = {
                additionalCssClassNames: failVerificationLinkNotificationClassName
            };

            self.showNotification(htmlContent, options);
        };

        self.showVerificationLinkSendSuccessNotification = function() {
            var htmlContent = "<div class='success-email-notification-holder'><span>Confirmation link sent!</span></div>";

            self.showNotificationMimic(htmlContent, null, true);
        };

        self.showVerificationLinkSendFailNotification = function() {
            var htmlContent = "<div class='success-email-notification-holder'><span>Confirmation link wasn't sent. Please try again</span></div>";

            var options = {
                additionalCssClassNames: failVerificationLinkNotificationClassName
            };

            self.showNotification(htmlContent, options);
        };

        function removeEmailVerificationParametersFromUrl() {
            var currentUrl = window.location.href.replace(/&?(showBannerAfterSuccessfulVerification|showBannerAfterFailedVerification)=([^&]$|[^&]*)/ig, "");

            return currentUrl;
        }

        $(document).ready(function() {
            if (window.enableEmailVerificationRefinements) {
                var currentUrl = removeEmailVerificationParametersFromUrl();
                var verificationResult = window.utils.getUrlParameter(showBannerAfterSuccessfulVerificationQueryParameter);

                if (verificationResult) {
                    var userEmail = decodeURIComponent(window.utils.getUrlParameter(emailAddressQueryParameter));

                    self.showAccountVerificationNotification(userEmail, verificationResult);

                    history.pushState(null, "", currentUrl);
                }

                if (window.utils.getUrlParameter(showBannerAfterFailedVerificationQueryParameter)) {
                    self.showVerificationLinkFailNotification();
                    history.pushState(null, "", currentUrl);
                }
            }
        });
    }

    OnlineApp.Namespace.extend('gJobs.Helpers', {
        accountVerificationHelper: new AccountVerificationHelper()
    });

})(window);
;
(function (window, undefined) {
    'use strict';

    var $verifyIdentityEl = $('#verify-identity');

    //
    // Initializer
    //
    $(function () {
        if ($verifyIdentityEl.get(0)) {

            var verifyIdentityViewModel = new gJobs.ViewModels.VerifyIdentityViewModel();

            ko.applyBindings(verifyIdentityViewModel, $verifyIdentityEl.get(0));
        }
    });

})(window);
;
(function(window, undefined) {
    'use strict';

    var $verifyAccountEl = $('#verify-account');

    //
    // Initializer
    //
    $(function() {
        if ($verifyAccountEl.get(0)) {
            gJobs.screenReadersService.setAriaLiveNotification('Verify your account page has loaded', null, true);

            var verifyAccountViewModel = new gJobs.ViewModels.VerifyAccountViewModel();

            ko.applyBindings(verifyAccountViewModel, $verifyAccountEl.get(0));
        }
    });

})(window);;
(function(window, undefined) {
    'use strict';

    var expiredVerificationLinkContainer = $('#expired-verification-link-container');

    //
    // Initializer
    //
    $(function() {
        if (expiredVerificationLinkContainer.get(0)) {

            var expiredVerificationLinkViewModel = new gJobs.ViewModels.ExpiredVerificationLinkViewModel();

            ko.applyBindings(expiredVerificationLinkViewModel, expiredVerificationLinkContainer.get(0));
        }
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function EditEmailAddressViewModel() {
        var self = this,
            editEmailLinkSelector = "#editEmailLink",
            verifyAccountDataContainerSelector = "#verify-account-data-container",
            dataVerifyAccountExternalLoginAttribute = "data-verify-account-external-login";


        self.emailAddress = ko.observable('').extend({ required: {}, email: {} });
        self.isEmailAddressNotAvailable = ko.observable(false);
        self.hasEmailChangedAfterError = ko.observable(true);
        self.emailAddressCopy = ko.observable('').extend({ required: {}, email: {} });
        self.isEmailAddressCopyNotAvailable = ko.observable(false);
        self.isEmailIdNotMatch = ko.observable(false);
        self.isEditEmailAddressSubmitButtonEnabled = ko.observable(false);
        self.isEditEmailAddressSubmitButtonBusy = ko.observable(false);
        self.credential = ko.observable(null);
        self.currentPassword = ko.observable().extend({ required: {} });
        self.isEmailAddressValidated = ko.observable(false);
        self.isExternalLogin = ko.observable(false);
        self.emailAddress.subscribe(function (value) {
            self.isEmailAddressNotAvailable(false);
            self.isEmailAddressValidated(self.validateEmailAddresses());
            if (!self.isExternalLogin()) {
                self.isEditEmailAddressSubmitButtonEnabled(self.validateEmailAddresses() && (self.currentPassword() != undefined && self.currentPassword() != '' && self.currentPassword() != null));
            }
            else {
                self.isEditEmailAddressSubmitButtonEnabled(self.validateEmailAddresses())
            }
        });

        self.emailAddressCopy.subscribe(function (value) {
            self.isEmailAddressCopyNotAvailable(false);
            self.isEmailAddressValidated(self.validateEmailAddresses());
            if (!self.isExternalLogin()) {
                self.isEditEmailAddressSubmitButtonEnabled(self.validateEmailAddresses() && (self.currentPassword() != undefined && self.currentPassword() != '' && self.currentPassword() != null));
            }
            else {
                self.isEditEmailAddressSubmitButtonEnabled(self.validateEmailAddresses())
            }
        });
        self.currentPassword.subscribe(function (value) {
            if (!self.isExternalLogin()) {
                self.isEmailAddressValidated(self.validateEmailAddresses());
                self.isEditEmailAddressSubmitButtonEnabled(self.validateEmailAddresses() && self.validateCurrentPassword());
            }
        });

        self.isEditEmailAddressSubmitButtonEnabled.subscribe(function (value) {
            self.isEditEmailAddressSubmitButtonBusy(false);
        });
        self.outOfEmailBlock = function () {
            setTimeout(function () {
                self.emailAddress.validate();
            }, 0);
            if (self.emailAddress() == "") {
                self.emailAddress.validationMessage('Error: This field is required');
                self.emailAddress.hasError(true);
                self.emailAddress.isValidationMessageVisible(true);
            }
        };
        var validationAnnounced = false;

        self.checkEmailCopyFocus = function () {
            validationAnnounced = false;
            if (self.emailAddressCopy() != "" && self.emailAddress() != self.emailAddressCopy()) {
                $("#aria-live-message-container").text('');
                setTimeout(function () { gJobs.screenReadersService.setAriaLiveNotification('Email ID does not match', $("#aria-live-message-container"), false); }, 300);
                self.isEmailIdNotMatch(true);
            }
        }
        self.checkEmailCopy = function () {
            setTimeout(function () {
                self.emailAddressCopy.validate();
            }, 0);
            if (self.emailAddressCopy() != "" && self.emailAddress() != self.emailAddressCopy()) {
                if (!validationAnnounced) {
                    gJobs.screenReadersService.setAriaLiveNotification('Email ID does not match');
                    validationAnnounced = true;
                }
                self.emailAddressCopy.validationMessage('Email ID does not match');
                self.emailAddressCopy.hasError(true);
                self.emailAddressCopy.isValidationMessageVisible(true);
                self.isEmailIdNotMatch(true);
            }
            return true;
        }
        self.checkEmailCopyFocusOut = function () {
            validationAnnounced = false;
            self.isEmailIdNotMatch(false);
            setTimeout(function () {
                self.emailAddressCopy.validate();
            }, 0);
            if (self.emailAddressCopy() == "") {
                self.emailAddressCopy.validationMessage('Error: This field is required');
                self.emailAddressCopy.hasError(true);
                self.emailAddressCopy.isValidationMessageVisible(true);
            }
            else if (self.emailAddressCopy() != "" && self.emailAddress() != self.emailAddressCopy()) {
                var emailRegEx = /^['_a-zA-Z0-9-+]+(\.['_a-zA-Z0-9-+]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.(([a-zA-Z]+))$/;
                if (emailRegEx.test(self.emailAddressCopy())) {
                    self.isEmailIdNotMatch(true);
                    //self.emailAddressCopy.validationMessage('Email ID does not match');
                    //self.emailAddressCopy.hasError(true);
                    //self.emailAddressCopy.isValidationMessageVisible(true);
                }
            }
        }

        //Commenting this code temporarily For ONLINE-13234
        self.confirmEmailAddress = function () {
            self.isEditEmailAddressSubmitButtonBusy(true);

            if (!self.validateEmailAddresses()) {
                if (self.emailAddress() !== self.emailAddressCopy()) {
                    self.isEmailAddressCopyNotAvailable(true);
                }

                self.isEditEmailAddressSubmitButtonEnabled(false);
            } else {
                var isEmailAllowedRequestData = {
                    email: self.emailAddress(),
                    credential: self.credential(),
                    captchaAnswer: null,
                    password: self.currentPassword()
                };

                OnlineApp.Services.authenticationService
                    .isEmailAllowed(isEmailAllowedRequestData)
                    .then(
                        function (data) {
                            if (data.success) {
                                self.emailAddress.hasError(!data.isEmailAllowed);
                                self.isEmailAddressNotAvailable(!data.isEmailAllowed);
                                self.isEditEmailAddressSubmitButtonEnabled(data.isEmailAllowed);

                                if (data.isEmailAllowed) {
                                    OnlineApp.Services.emailVerificationService
                                        .updateEmailAddressByCredential(self.credential(), self.emailAddress())
                                        .then(
                                            function (response) {
                                                var options = { emailAddress: self.emailAddress() };

                                                self.resetEmailAddressElements();

                                                $(document).trigger(OnlineApp.Events.CommonEventsNames.ConfirmEditEmailAddress, options);

                                                $(editEmailLinkSelector).focus();
                                                gJobs.screenReadersService.setAriaLiveNotification('Edited email successfully ');

                                            },
                                            function () {
                                                toastr.warning(Resources.NotificationMessages.ServiceUnavailable);
                                            }
                                        );
                                }
                                else {
                                    self.emailAddress.validationMessage('Email address not available!');
                                    self.emailAddress.hasError(true);
                                    self.emailAddress.isValidationMessageVisible(true);
                                    $('#edit-email-address-input-field').focus();
                                }
                            } else {
                                if (data.errorPropertyName == 'Password') {
                                    self.currentPassword.validationMessage(data.errorMessage);
                                    self.currentPassword.hasError(true);
                                    self.currentPassword.isValidationMessageVisible(true);
                                    self.isEditEmailAddressSubmitButtonBusy(false);
                                    $('#currentPassword').focus();
                                }
                                else {
                                    toastr.warning(Resources.NotificationMessages.ServiceUnavailable);
                                }
                            }
                        },
                        function () {
                            toastr.warning(Resources.NotificationMessages.ServiceUnavailable);
                        }
                    );
            }
        };

        self.cancelEditEmailAddress = function () {

            self.resetEmailAddressElements();

            $(document).trigger(OnlineApp.Events.CommonEventsNames.CancelEditEmailAddress);
            $(editEmailLinkSelector).focus();
            gJobs.screenReadersService.setAriaLiveNotification('Current email is not changed');
        };

        self.validateEmailAddresses = function () {
            return self.emailAddress.validate() && self.emailAddress() === self.emailAddressCopy();
        };

        self.validateCurrentPassword = function () {
            return self.currentPassword.validate();
        }

        self.resetEmailAddressElements = function () {
            self.emailAddress('');
            self.emailAddressCopy('');
            self.currentPassword('');
            self.isEmailAddressNotAvailable(false);
            self.isEmailAddressCopyNotAvailable(false);
            self.isEmailIdNotMatch(false);
            self.isEditEmailAddressSubmitButtonEnabled(false);
            updateFieldErrorState(self.emailAddress);
            updateFieldErrorState(self.currentPassword);
        };

        function updateFieldErrorState(field, hasError, errorMessage) {
            field.hasError(hasError);
            field.isValidationMessageVisible(hasError);

            if (hasError && errorMessage) {
                field.validationMessage(errorMessage);
            }
        }

        $(document).ready(function () {
            var isExternal = $(verifyAccountDataContainerSelector).attr(dataVerifyAccountExternalLoginAttribute) == 'true' ? true : false
            self.isExternalLogin(isExternal);
        })
    }

    OnlineApp.Namespace.extend('gJobs.ViewModels', {
        EditEmailAddressViewModel: EditEmailAddressViewModel
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function VerifyIdentityViewModel() {
        var RESEND_VERIFICATION_CODE_ATTEMPTS_COUNT_WITHOUT_CAPTCHA = window.twoStepVerificationResendAttempts;
        var VERIFICATION_ATTEMPTS_COUNT_WITHOUT_CAPTCHA = window.twoStepVerificationVerifyAttempts;
        var KEY_FOR_TEXT_VERIFICATION_CODE_CAPTHA_ANSWER = "VerifyTwoStepVerificationCodeAnswer";
        var KEY_FOR_TEXT_RESEND_VERIFICATION_CODE_CAPTCHA_ANSWER = "ResendTwoStepVerificationCodeAnswer";
        var CAPTCHA_USER_ANSWER_INPUT_ID_FOR_VERIFICATION_CODE = "captcha-user-answer-for-verify-code";
        var CAPTCHA_USER_ANSWER_INPUT_ID_FOR_RESEND_CODE = "captcha-user-answer-for-resend-code";
        var CAPTCHA_LABEL_HTML_CONTENT_FOR_VERIFICATION_CODE = "<span>Please answer the question to <strong>verify</strong> a code again</span>";
        var CAPTCHA_LABEL_HTML_CONTENT_FOR_RESEND_CODE = "<span>Please answer the question to <b>resend</b> a code again</span>";

        var wasVerificationCodeValueInitiaded = false;

        var verificationCodeContainerId = "verify-identity-code-container";
        var verificationCodeContainerSelector = "#" + verificationCodeContainerId;
        var rememberThisDeviceCheckboxSelector = "#remember-this-device-checkbox";
        var rememberThisDeviceLabelContainerSelector = "#remember-this-device-label-container";
        var rememberThisDeviceCheckableItemSelector = ".checkable-item";
        var verificationCodeCaptchaSelector = "#" + CAPTCHA_USER_ANSWER_INPUT_ID_FOR_VERIFICATION_CODE;
        var credentialSelector = "#verify-identity-credential";

        var $verificationCodeContainer;
        var $rememberThisDeviceCheckbox;
        var $rememberThisDeviceCheckableItem;
        var $rememberThisDeviceLabelContainer;
        var $lastFocusableElement;
        var $verificationCodeInputs;

        var credential;

        var accountVerificationHelper = gJobs.Helpers.accountVerificationHelper;

        var self = this;

        function unsetField (field, hasError) {
            field("");
            
            self.accountVerificationViewModel.updateFieldErrorState(
                field,
                hasError,
                field.validationMessage()
            );
        }

        function onVerificationCodeValuesChange (newValue, index) {
                var digits = newValue.replace(/[^A-Za-z0-9]/g,'').split(""); // replace all non-alphanumeric characters with nothing

                if (digits.length) {
                    var lastIndexForIterate = index + digits.length > 6 ? 6 : index + digits.length;
                    
                    for (var i = index; i < lastIndexForIterate; i++) {
                        self.verificationCodeValues[i](digits.shift());
                    }

                    wasVerificationCodeValueInitiaded = true;
                } else {
                    unsetField(
                        self.verificationCodeValues[index], 
                        wasVerificationCodeValueInitiaded
                    );
                }

            if (newValue == '') {
                var textid = 'txt' + (index + 1 - 1).toString();
                if (document.getElementById(textid)) {
                    document.getElementById(textid).focus();
                }
            }
            else {
                if (newValue.length == 1) {
                    var textid = 'txt' + (index + 1 + 1).toString();
                    if (document.getElementById(textid)) {
                        document.getElementById(textid).focus()
                    }
                }
            }
           


            self.isNeedToDisplayErrorMessage(false);
        }
       
        function initVerificationCodeValues () {
            var verificationCodeValues = [];

            for (var i = 0; i < 6; i++) {
                verificationCodeValues.push(
                    ko.observable('').extend({required: {}, number: {}})
                );
            }

            return verificationCodeValues;
        }

        function subscribeVerificationCodeValues(verificationCodeValues) {
            verificationCodeValues.forEach(function(observableItem, index) {
                observableItem.subscribe(function (newValue) { onVerificationCodeValuesChange(newValue, index) });
            });
        }

        self.accountVerificationViewModel = new gJobs.ViewModels.AccountVerificationViewModel(
            {
                keyForTextCaptchaAnswer: KEY_FOR_TEXT_VERIFICATION_CODE_CAPTHA_ANSWER,
                captchaUserAnswerInputId: CAPTCHA_USER_ANSWER_INPUT_ID_FOR_VERIFICATION_CODE,
                captchaLabelHtmlContent: CAPTCHA_LABEL_HTML_CONTENT_FOR_VERIFICATION_CODE,
                attemptsCountWithoutCaptcha: VERIFICATION_ATTEMPTS_COUNT_WITHOUT_CAPTCHA


            },
            {
                keyForTextCaptchaAnswer: KEY_FOR_TEXT_RESEND_VERIFICATION_CODE_CAPTCHA_ANSWER,
                captchaUserAnswerInputId: CAPTCHA_USER_ANSWER_INPUT_ID_FOR_RESEND_CODE,
                captchaLabelHtmlContent: CAPTCHA_LABEL_HTML_CONTENT_FOR_RESEND_CODE,
                attemptsCountWithoutCaptcha: RESEND_VERIFICATION_CODE_ATTEMPTS_COUNT_WITHOUT_CAPTCHA
            }
        );

        self.textCaptchaEnabled = window.textCaptcha;
        self.verificationCodeAttemptsCount = ko.observable(0);
        self.resendVerificationCodeAttemptsCount = ko.observable(0);
        self.isNeedToDisplayErrorMessage = ko.observable(false);
        self.errorMessage = ko.observable("");
        self.verificationCodeValues = initVerificationCodeValues();
        self.shouldRememberThisDevice = ko.observable(false);
        self.userEmailAddress = ko.observable("");
        self.isVerificationCodeInProcess = ko.observable(false);
        self.isUserInfoLoaded = ko.observable(false);
        self.verificationCodeServerErrorMessage = ko.observable("");

        subscribeVerificationCodeValues(self.verificationCodeValues);

        self.verificationCode = ko.computed({
            read: function () {
                var verificationCode = "";

                self.verificationCodeValues.forEach(function (value) {
                    verificationCode += value();
                });

                return verificationCode;
            }
        }).extend({
            verificationCode: { 
                validationMessage: OnlineApp.Validation.validationMessages.invalidTwoStepVerificationCode
            } 
        });

        self.init = function () {
            return gJobs.Services.verifyIdentityService.getUserData(credential);
        };

        

        $(document).ready(function () {
            self.onReady();
            
        });

        self.onReady = function () {
            credential = $(credentialSelector).attr("data-verify-identity-credential");

            $("#content").css('position', 'static');

            $verificationCodeContainer = $(verificationCodeContainerSelector);
            $verificationCodeInputs = $verificationCodeContainer.find("input");
            $rememberThisDeviceCheckbox = $(rememberThisDeviceCheckboxSelector);
            $rememberThisDeviceLabelContainer = $(rememberThisDeviceLabelContainerSelector);
            $rememberThisDeviceCheckableItem = $rememberThisDeviceLabelContainer.find(rememberThisDeviceCheckableItemSelector);

            $($verificationCodeInputs).on('blur', function (e) {
                if ($(e.relatedTarget).parents(verificationCodeContainerSelector).length === 0) {
                    if (wasVerificationCodeValueInitiaded && !self.verificationCode.validate()) {
                        self.isNeedToDisplayErrorMessage(true);
                    }
                }
            });

            $rememberThisDeviceLabelContainer.on('mousedown', function () {
                setTimeout(function () {
                    $rememberThisDeviceCheckbox.focus();
                });
            });

            $rememberThisDeviceCheckbox.on('focus', function () {
                $rememberThisDeviceCheckableItem.addClass('focus');
            });

            $rememberThisDeviceCheckbox.on('focusout', function () {
                $rememberThisDeviceCheckableItem.removeClass('focus');
            });

            $verificationCodeInputs.autotab('alphanumeric');

            self.init().then(function (data) {
                if (data) {
                    self.verificationCodeAttemptsCount(data.verificationAttempts);
                    self.resendVerificationCodeAttemptsCount(data.resendAttempts);
                    self.userEmailAddress(data.email);

                    if (self.isNeedToShowVerificationCodeCaptcha()) {
                        self.accountVerificationViewModel.resetVerificationCodeCaptcha();
                    }

                    if (self.isNeedToShowResendVerificationCodeCaptcha()) {
                        self.accountVerificationViewModel.resetResendVerificationCodeCaptcha();
                    }

                    self.isUserInfoLoaded(true);

                    $verificationCodeInputs.first().focus();
                    
                }
            });
            
        };

        self.isNeedToMarkVerificationCodeDigitWithError = function (verificationCodeDigitIndex) {
            return self.verificationCodeValues[verificationCodeDigitIndex].hasError()
                || self.isNeedToDisplayErrorMessage();
        };

        self.isNeedToShowCaptchasContainer = function () {
            return self.isNeedToShowVerificationCodeCaptcha() 
                || self.isNeedToShowResendVerificationCodeCaptcha();
        }

        self.isNeedToShowVerificationCodeCaptcha = function () {
            return self.textCaptchaEnabled 
                && self.accountVerificationViewModel.isNeedToShowVerificationCodeCaptcha(self.verificationCodeAttemptsCount());
        };

        self.isNeedToShowResendVerificationCodeCaptcha = function () {
            return self.textCaptchaEnabled
                && self.accountVerificationViewModel.isNeedToShowResendVerificationCodeCaptcha(self.resendVerificationCodeAttemptsCount());
        };

        self.getHomePageUrl = function() {
            var homePageUrl = "/";

            if (AgencyPages && AgencyPages.pageInfoService) {
                homePageUrl = AgencyPages.pageInfoService.getCurrentAgencyHomePath();
            }

            return homePageUrl;
        };

        self.verifyCode = function () {
            $('#colr').attr('style', ' background-color:#267a90');
            self.isVerificationCodeInProcess(true);

            if (self.isNeedToShowVerificationCodeCaptcha()) {
                if (!self.accountVerificationViewModel.textCaptchaViewModelForVerificationCode.validate()) {
                    var captchaSelector = self.accountVerificationViewModel.getVerificationCodeCaptchaSelector();
                    $(captchaSelector).focus();
                    self.isVerificationCodeInProcess(false);
                    return;
                };
            }  

            gJobs.Services.verifyIdentityService.verifyCode(
                self.verificationCode(),
                self.shouldRememberThisDevice(),
                self.accountVerificationViewModel.textCaptchaViewModelForVerificationCode.userAnswer(),
                credential
            ).then(function (data) {
                if (data) {
                    if (data.isVerificationSucceeded) {
                        var $announcementContainer = $(".verify-identity-form-container");
                        OnlineApp.Helpers.layoutHelper.tabbing.updateIndices($announcementContainer);

                        gJobs.screenReadersService.setNotification($announcementContainer.find('.sr-notification'), 'Identity verified, redirecting to home page', null, true);

                        var postBackUrl = sessionStorage.getItem(OnlineApp.SessionKeys.PostBackUrl);
                        sessionStorage.removeItem(OnlineApp.SessionKeys.PostBackUrl);

                        var postBackUrlLower = postBackUrl.toLowerCase();

                        if (!postBackUrl || postBackUrlLower.includes("verifyidentity", postBackUrlLower)) {
                            postBackUrl = self.getHomePageUrl();
                        }

                        sessionStorage.setItem(OnlineApp.SessionKeys.IsVerifyIdentityVerificationCodeVerified, "true");

                        if (sessionStorage.getItem(OnlineApp.LocalStorageKeys.RedirectToShowJobAlertPopup) === "true") {
                            sessionStorage.setItem(OnlineApp.LocalStorageKeys.ShowJobAlertPopup, "true");
                        }
                        setTimeout(() => window.location.href = postBackUrl, 1000);
                    } else {
                        var isCaptchaInvalid = false;

                        var newVerificationAttemptsCount = self.verificationCodeAttemptsCount() + 1;
                        self.verificationCodeAttemptsCount(newVerificationAttemptsCount);

                        if (data.errorFieldName === "captcha") {
                            isCaptchaInvalid = true;

                            self.accountVerificationViewModel.updateFieldErrorState(
                                self.accountVerificationViewModel.textCaptchaViewModelForVerificationCode.userAnswer,
                                true
                            );

                            self.isVerificationCodeInProcess(false);
                        } else {
                            self.isNeedToDisplayErrorMessage(true);
                            self.verificationCodeServerErrorMessage(data.errorMessage);

                            self.accountVerificationViewModel.updateFieldErrorState(
                                self.verificationCode,
                                true,
                                data.errorMessage
                            );

                            self.isVerificationCodeInProcess(false);
                            $verificationCodeInputs.first().focus();
                        }

                        if (self.isNeedToShowVerificationCodeCaptcha()) {
                            self.accountVerificationViewModel.resetVerificationCodeCaptchaWithTryingFocusing(
                                null,
                                true,
                                isCaptchaInvalid,
                                data.updatedCaptcha
                            );
                        }
                        
                    }
                }
            });
        };

        self.resendVerificationCode = function () {
            if (self.isNeedToShowResendVerificationCodeCaptcha()) {
                if (!self.accountVerificationViewModel.textCaptchaViewModelForResendCode.validate()) {
                    var captchaSelector = self.accountVerificationViewModel.getResendVerificationCodeCaptchaSelector();
                    $(captchaSelector).focus();
                    return;
                }
            }

            gJobs.Services.verifyIdentityService.resendVerificationCode(
                credential,
                self.accountVerificationViewModel.textCaptchaViewModelForResendCode.userAnswer()
            ).then(function(data) {
                var isCaptchaInvalid = false;

                var newResendVerificationCount = data.resendAttempts;
                self.resendVerificationCodeAttemptsCount(newResendVerificationCount);

                if (data.isResendSucceeded === false) {
                    if (data.isCaptchaInvalid === true) {
                        isCaptchaInvalid = true;
                        self.accountVerificationViewModel.updateFieldErrorState(
                            self.accountVerificationViewModel.textCaptchaViewModelForResendCode.userAnswer,
                            true, 
                            OnlineApp.Validation.validationMessages.captchaInvalidMessage
                        );
                    }
                } else {
                    accountVerificationHelper.showResendCodeSuccessNotification();
                }

                if (self.isNeedToShowResendVerificationCodeCaptcha()) {
                    self.accountVerificationViewModel.resetResendVerificationCodeCaptchaWithTryingFocusing(
                        null,
                        true,
                        isCaptchaInvalid,
                        data.updatedCaptcha
                    );
                }
            });
        };

        OnlineApp.Services.authenticationService.isLoggedIn().done(function(isLoggedIn) {
            if (isLoggedIn) {
                window.location.href = self.getHomePageUrl();
            }
        });

        $(window).focus(function () {
            if (self.isNeedToShowVerificationCodeCaptcha()) {
                
                    self.accountVerificationViewModel.resetVerificationCodeCaptchaWithTryingFocusing(
                        $lastFocusableElement,
                        true
                    );
                
            };
            // commenting this one - not sure why we need to refresh this on focus as it is triggered by action - self.resendVerificationCode
            //if (self.isNeedToShowResendVerificationCodeCaptcha()) {
            //    self.accountVerificationViewModel.resetResendVerificationCodeCaptchaWithTryingFocusing(
            //        $lastFocusableElement,
            //        true
            //    );
            //}
        });

        $(window).blur(function () {
            $lastFocusableElement = $(document.activeElement);
        });

        var loginEvents = OnlineApp.Events.CommonEventsNames.Login + ' ' + Events.CommonEventsNames.Register;

        $(document)
            .on(loginEvents, function(event) {
                window.location.href = self.getHomePageUrl();
            });
    }

    OnlineApp.Namespace.extend('gJobs.ViewModels', {
        VerifyIdentityViewModel: VerifyIdentityViewModel
    });

})(window);

function keydown(event) {
    if (event.keyCode == $.ui.keyCode.BACKSPACE) {

        $('#colr').removeAttr('style');
        
        var id = event.target.id;
        if (id == 'txt2') {
            if (document.getElementById('txt2').value == '') {
                document.getElementById('txt1').focus();
                document.getElementById('txt1').value = '';
            }
            
        }
         else if (id == 'txt3') {
            if (document.getElementById('txt3').value == '') {
                document.getElementById('txt2').focus();
                document.getElementById('txt2').value = '';
            }
            
        }
         else if (id == 'txt4') {
            if (document.getElementById('txt4').value == '') {
                document.getElementById('txt3').focus();
                document.getElementById('txt3').value = '';
            }
           
        }

        else if (id == 'txt5') {
            if (document.getElementById('txt5').value == '') {
                document.getElementById('txt4').focus();
                document.getElementById('txt4').value = '';
            }
            
        }
        else if (id == 'txt6') {
            if (document.getElementById('txt6').value == '') {
                document.getElementById('txt5').focus();
                document.getElementById('txt5').value = '';
            }
            
        }
    }
}
;
(function (window, undefined) {
    'use strict';

    function AccountVerificationViewModel(verificationCodeInfo, resendVerificationCodeInfo) {
        verificationCodeInfo = verificationCodeInfo ? verificationCodeInfo : {};
        resendVerificationCodeInfo = resendVerificationCodeInfo ? resendVerificationCodeInfo : {};
        
        var CAPTCHA_INVALID_MESSAGE = "Captcha is invalid";
        var captchaUserAnswerInputIdForVerifyCode = verificationCodeInfo.captchaUserAnswerInputId;
        var captchaUserAnswerInptutIdForResendCode = resendVerificationCodeInfo.captchaUserAnswerInputId;
        var captchaLabelHtmlContentForResendCode = resendVerificationCodeInfo.captchaLabelHtmlContent;
        var captchaLabelHtmlContentForVerificationCode = verificationCodeInfo.captchaLabelHtmlContent;
        var resendVerificationAttemptsCountWithoutCaptcha = resendVerificationCodeInfo.attemptsCountWithoutCaptcha;
        var verificationAttemptsCountWithoutCaptcha = verificationCodeInfo.attemptsCountWithoutCaptcha;
        var verificationCodeCaptchaSelector = "#" + captchaUserAnswerInputIdForVerifyCode;
        var resendVerificationCodeCaptchaSelector = "#" + captchaUserAnswerInptutIdForResendCode;

        var self = this;

        self.textCaptchaViewModelForVerificationCode = new OnlineApp.ViewModels.TextCaptchaViewModel(
            verificationCodeInfo.keyForTextCaptchaAnswer
        );
        self.textCaptchaViewModelForResendCode = new OnlineApp.ViewModels.TextCaptchaViewModel(
            resendVerificationCodeInfo.keyForTextCaptchaAnswer
        );

        self.getVerificationCodeCaptchaSelector = function () {
            return verificationCodeCaptchaSelector;
        }

        self.getResendVerificationCodeCaptchaSelector = function () {
            return resendVerificationCodeCaptchaSelector;
        }

        self.showSuccessNotification = function (htmlContent) {
            var successEmailNotificationEventName = "successEmailNotification";
            var successEmailNotificationSelector = "success-email-notification";
            var successEmailNotification = $('#' + successEmailNotificationSelector);

            if (successEmailNotification.length !== 0) {
                successEmailNotification.html(htmlContent);
                successEmailNotification.css("display", "flex");
            } else {
                $('body').append(
                    "<div class='uses-gjobs-styles'><div id='" + successEmailNotificationSelector + "'>" + htmlContent + "</div></div>"
                );

                successEmailNotification = $('#' + successEmailNotificationSelector);
            }

            gJobs.screenReadersService.setAriaLiveNotification(successEmailNotification.text());

            $(document).on('click.' + successEmailNotificationEventName, function () {
                if (successEmailNotification.is(":visible")) {
                    successEmailNotification.css("display", "none");
                }
            });

            setTimeout(function () {
                if (successEmailNotification.is(":visible")) {
                    successEmailNotification.css("display", "none");
                }

                $(document).off('click.' + successEmailNotificationEventName);
            }, 10000)
        };

        self.updateFieldErrorState = function (field, hasError, errorMessage) {
            field.hasError(hasError);
            field.isValidationMessageVisible(hasError);

            if (hasError && errorMessage) {
                field.validationMessage(errorMessage);
            }
        };

        self.resetCaptcha = function (textCaptchaViewModel, htmlContentForLabel, captchaUserAnswerId, updatedCaptchaQuestion) {
            textCaptchaViewModel.setCustomLabelHtmlContent(htmlContentForLabel);
            textCaptchaViewModel.setCustomUserAnswerInputId(captchaUserAnswerId);

            return textCaptchaViewModel.resetCaptcha(
                textCaptchaViewModel.userAnswer.hasError(),
                CAPTCHA_INVALID_MESSAGE,
                '',
                updatedCaptchaQuestion
            );
        };

        self.resetVerificationCodeCaptcha = function () {
            self.resetCaptcha(
                self.textCaptchaViewModelForVerificationCode, 
                captchaLabelHtmlContentForVerificationCode, 
                captchaUserAnswerInputIdForVerifyCode
            ); 
        };

        self.resetResendVerificationCodeCaptcha = function () {
            self.resetCaptcha(
                self.textCaptchaViewModelForResendCode, 
                captchaLabelHtmlContentForResendCode, 
                captchaUserAnswerInptutIdForResendCode
            );
        };

        self.isRefreshCaptchaQuestionLinkWasFocusedLast = function (lastFocusableElement, captchaUserAnswerInputId) {
            return lastFocusableElement
                && lastFocusableElement.hasClass('reset-captcha') 
                && lastFocusableElement.parents('.text-captcha-container').find("#" + captchaUserAnswerInputId).length;
        };

        self.resetCaptchaWithTryingFocusing = function (
            captchaViewModel, 
            captchaLabelHtmlContent, 
            captchaUserAnswerInputId, 
            lastFocusableElement,
            isVerificationContainerVisible,
            shouldFocusOnCaptcha,
            updatedCaptchaQuestion
        ) {
            if (self.resetCaptcha(
                captchaViewModel,
                captchaLabelHtmlContent,
                captchaUserAnswerInputId,
                updatedCaptchaQuestion
            )) {
                self.resetCaptcha(
                    captchaViewModel,
                    captchaLabelHtmlContent,
                    captchaUserAnswerInputId,
                    updatedCaptchaQuestion
                ).always(function () {
                    if (isVerificationContainerVisible) {
                        if (
                            shouldFocusOnCaptcha
                            || (lastFocusableElement && lastFocusableElement.attr('id') === captchaUserAnswerInputId)) {
                            $(verificationCodeCaptchaSelector).focus();
                        } else if (
                            self.isRefreshCaptchaQuestionLinkWasFocusedLast(lastFocusableElement, captchaUserAnswerInputId)
                        ) {
                            lastFocusableElement.focus();
                        }
                    }
                });
            }
        };

        self.resetVerificationCodeCaptchaWithTryingFocusing = function (
            lastFocusableElement, 
            isVerificationContainerVisible,
            shouldFocusOnCaptcha,
            updatedCaptchaQuestion
        ) {
            self.resetCaptchaWithTryingFocusing(
                self.textCaptchaViewModelForVerificationCode, 
                captchaLabelHtmlContentForVerificationCode, 
                captchaUserAnswerInputIdForVerifyCode, 
                lastFocusableElement,
                isVerificationContainerVisible,
                shouldFocusOnCaptcha,
                updatedCaptchaQuestion
            ); 
        };

        self.resetResendVerificationCodeCaptchaWithTryingFocusing = function (
            lastFocusableElement, 
            isVerificationContainerVisible,
            shouldFocusOnCaptcha,
            updatedCaptchaQuestion
        ) {
            self.resetCaptchaWithTryingFocusing(
                self.textCaptchaViewModelForResendCode, 
                captchaLabelHtmlContentForResendCode, 
                captchaUserAnswerInptutIdForResendCode, 
                lastFocusableElement,
                isVerificationContainerVisible,
                shouldFocusOnCaptcha,
                updatedCaptchaQuestion
            );
        };

        self.isNeedToShowVerificationCodeCaptcha = function (currentAttemptsCount) {
            return currentAttemptsCount > verificationAttemptsCountWithoutCaptcha;
        };

        self.isNeedToShowResendVerificationCodeCaptcha = function (currentAttemptsCount) {
            return currentAttemptsCount >= resendVerificationAttemptsCountWithoutCaptcha;
        };

    }

    OnlineApp.Namespace.extend('gJobs.ViewModels', {
        AccountVerificationViewModel: AccountVerificationViewModel
    });

})(window);
;
(function(window, undefined) {
    'use strict';
  


    function VerifyAccountViewModel() {

        var self = this,
            resendEmailVerificationAttemptsCountWithoutCaptcha = window.emailVerificationResendAttempts,
            keyForTextResendEmailVerificationCaptchaAnswer = "ResendEmailVerificationCodeAnswer",
            captchaUserAnswerInputIdForResendEmailVerification = "captcha-user-answer-for-resend-code",
            captchaLabelHtmlContentForResendEmailVerification = "<span>Please answer the question to <b>resend</b> a link again</span>",
            verifyAccountDataContainerSelector = "#verify-account-data-container",
            dataVerifyAccountCredentialAttribute = "data-verify-account-credential",
            dataVerifyAccountEmailAttribute = "data-verify-account-email",
            dataVerifyAccountResendAttemptsAttribute = "data-verify-account-resend-attempts",
            dataVerifyAccountChangedEmailAddressWasAdded = "data-verify-account-changed-email-address-was-added",
            dataVerifyAccountIsOjrMasterAttribute = "data-verify-account-is-ojr-master",
            $lastFocusableElement,
            credential;

        var accountVerificationHelper = gJobs.Helpers.accountVerificationHelper;

        self.accountVerificationViewModel = new gJobs.ViewModels.AccountVerificationViewModel(
            null,
            {
                keyForTextCaptchaAnswer: keyForTextResendEmailVerificationCaptchaAnswer,
                captchaUserAnswerInputId: captchaUserAnswerInputIdForResendEmailVerification,
                captchaLabelHtmlContent: captchaLabelHtmlContentForResendEmailVerification,
                attemptsCountWithoutCaptcha: resendEmailVerificationAttemptsCountWithoutCaptcha
            }
        );

        self.textCaptchaEnabled = window.textCaptcha;
        self.resendVerificationEmailAttemptsCount = ko.observable(0);
        
        self.userEmailAddress = ko.observable("");
        self.isUserInfoLoaded = ko.observable(false);
        self.isCareerPageHeadingStyle = ko.observable(false);
        self.changedEmailAddressWasAdded = ko.observable(false);
        self.isOjrMaster = ko.observable(false);

        self.isEditEmailAddressModeActive = ko.observable(false);
        self.editEmailAddressViewModel = new gJobs.ViewModels.EditEmailAddressViewModel();

        $(document).ready(function () {
            self.onReady();
        });

        self.onReady = function() {
            if (self.isUserInfoLoaded()) return;

            var link = window.location.href;
            if (link.indexOf("/careers/") !== -1) {
                self.isCareerPageHeadingStyle = ko.observable(true);
            }

            credential = $(verifyAccountDataContainerSelector).attr(dataVerifyAccountCredentialAttribute);
            self.editEmailAddressViewModel.credential(credential);
           
            self.userEmailAddress($(verifyAccountDataContainerSelector).attr(dataVerifyAccountEmailAttribute));
            self.resendVerificationEmailAttemptsCount($(verifyAccountDataContainerSelector).attr(dataVerifyAccountResendAttemptsAttribute));
            self.changedEmailAddressWasAdded($(verifyAccountDataContainerSelector).attr(dataVerifyAccountChangedEmailAddressWasAdded));
            self.isOjrMaster($(verifyAccountDataContainerSelector).attr(dataVerifyAccountIsOjrMasterAttribute));

            if (self.isNeedToShowResendVerificationEmailCaptcha()) {
                self.accountVerificationViewModel.resetResendVerificationCodeCaptcha();
            }

            self.isUserInfoLoaded(true);
        };

        self.shouldHideEditEmailAddressLink = function() {
            return self.isOjrMaster() === true || self.isOjrMaster() === 'true';
        };

        self.isNeedToShowCaptchasContainer = function() {
            return self.isNeedToShowResendVerificationEmailCaptcha();
        };

        self.isNeedToShowResendVerificationEmailCaptcha = function() {
            return self.textCaptchaEnabled
                && self.accountVerificationViewModel.isNeedToShowResendVerificationCodeCaptcha(self.resendVerificationEmailAttemptsCount());
        };

        self.getHomePageUrl = function() {
            var homePageUrl = "/";

            if (AgencyPages && AgencyPages.pageInfoService) {
                homePageUrl = AgencyPages.pageInfoService.getCurrentAgencyHomePath();
            }

            return homePageUrl;
        };

        self.resendVerificationLink = function() {
            if (self.isNeedToShowResendVerificationEmailCaptcha()) {
                if (!self.accountVerificationViewModel.textCaptchaViewModelForResendCode.validate()) {
                    var captchaSelector = self.accountVerificationViewModel.getResendVerificationCodeCaptchaSelector();
                    $(captchaSelector).focus();
                    return;
                }
            }

            gJobs.Services.verifyAccountService.resendVerificationLink(
                credential,
                self.accountVerificationViewModel.textCaptchaViewModelForResendCode.userAnswer(),
                self.changedEmailAddressWasAdded(),
                self.isOjrMaster()
            ).then(function(response) {
                var data = response.data;

                if (!data) {
                    accountVerificationHelper.showVerificationLinkSendFailNotification();
                    return;
                }

                var isCaptchaInvalid = false;

                self.resendVerificationEmailAttemptsCount(data.resendAttempts);

                if (data.isResendSucceeded === false) {
                    if (data.isCaptchaInvalid === true) {
                        isCaptchaInvalid = true;
                        self.accountVerificationViewModel.updateFieldErrorState(
                            self.accountVerificationViewModel.textCaptchaViewModelForResendCode.userAnswer,
                            true,
                            OnlineApp.Validation.validationMessages.captchaInvalidMessage
                        );
                    }
                } else {
                    accountVerificationHelper.showVerificationLinkSendSuccessNotification();
                }

                if (self.isNeedToShowResendVerificationEmailCaptcha()) {
                    self.accountVerificationViewModel.resetResendVerificationCodeCaptchaWithTryingFocusing(
                        null,
                        true,
                        isCaptchaInvalid,
                        data.updatedCaptcha
                    );
                }
            });
        };

        self.showEditEmailAddressPage = function () {
            $("#skip-to-content-button").focus();
            self.isEditEmailAddressModeActive(true);
        };

        $(window).blur(function() {
            $lastFocusableElement = $(document.activeElement);
        });

        
        var loginEvents = OnlineApp.Events.CommonEventsNames.Login + ' ' + Events.CommonEventsNames.Register;
        
        var editEmailAddressEvents = OnlineApp.Events.CommonEventsNames.CancelEditEmailAddress + ' ' + OnlineApp.Events.CommonEventsNames.ConfirmEditEmailAddress;

        $(document)
            .on(loginEvents, function (event) {
            
                window.location.href = self.getHomePageUrl();
            })
            .on(editEmailAddressEvents, function (event, data) {
                
                if (data && data.emailAddress) {
                   var emailAddress= getMsakedEmail(data.emailAddress)
                    self.userEmailAddress(emailAddress);
                    self.changedEmailAddressWasAdded(true);
                }

                self.isEditEmailAddressModeActive(false);
            });

        function getMsakedEmail(myemailId) {

            
            var index = myemailId.lastIndexOf("@");
            var prefix = myemailId.substring(0, index);
            var postfix = myemailId.substring(index);

            var mask = prefix.split('').map(function (o, i) {
                if (i == 0 || i == (index - 1)) {
                    return o;
                } else {
                    return '*';
                }
            }).join('');

            var maskedid = mask + postfix;
            return maskedid;
        }

    }


    OnlineApp.Namespace.extend('gJobs.ViewModels', {
        VerifyAccountViewModel: VerifyAccountViewModel
    });

})(window);
;
(function(window, undefined) {
    'use strict';

    function ExpiredVerificationLinkViewModel() {

        var self = this,
            resendEmailVerificationAttemptsCountWithoutCaptcha = window.emailVerificationResendAttempts,
            keyForTextResendEmailVerificationCaptchaAnswer = "ResendEmailVerificationCodeAnswer",
            captchaUserAnswerInputIdForResendEmailVerification = "captcha-user-answer-for-resend-code",
            captchaLabelHtmlContentForResendEmailVerification = "<span>Please answer the question to <b>resend</b> a link again</span>",
            expiredVerificationLinkDataContainerSelector = "#expired-verification-link-data-container",
            dataExpiredVerificationLinkCredentialAttribute = "data-expired-verification-link-credential",
            dataExpiredVerificationLinkResendAttemptsAttribute = "data-expired-verification-link-resend-attempts",
            dataExpiredVerificationLinkIsOjrMasterAttribute = "data-expired-verification-link-is-ojr-master",
            $lastFocusableElement,
            credential;

        var accountVerificationHelper = gJobs.Helpers.accountVerificationHelper;

        self.accountVerificationViewModel = new gJobs.ViewModels.AccountVerificationViewModel(
            null,
            {
                keyForTextCaptchaAnswer: keyForTextResendEmailVerificationCaptchaAnswer,
                captchaUserAnswerInputId: captchaUserAnswerInputIdForResendEmailVerification,
                captchaLabelHtmlContent: captchaLabelHtmlContentForResendEmailVerification,
                attemptsCountWithoutCaptcha: resendEmailVerificationAttemptsCountWithoutCaptcha
            }
        );

        self.textCaptchaEnabled = window.textCaptcha;
        self.resendVerificationEmailAttemptsCount = ko.observable(0);
        self.isUserInfoLoaded = ko.observable(false);
        self.isCareerPageHeadingStyle = ko.observable(false);
        self.isOjrMaster = ko.observable(false);

        $(document).ready(function () {
            self.onReady();
        });

        self.onReady = function() {
            if (self.isUserInfoLoaded()) return;

            var link = window.location.href;
            if (link.indexOf("/careers/") !== -1) {
                self.isCareerPageHeadingStyle = ko.observable(true);
            }

            credential = $(expiredVerificationLinkDataContainerSelector).attr(dataExpiredVerificationLinkCredentialAttribute);
            self.resendVerificationEmailAttemptsCount($(expiredVerificationLinkDataContainerSelector).attr(dataExpiredVerificationLinkResendAttemptsAttribute));
            self.isOjrMaster($(expiredVerificationLinkDataContainerSelector).attr(dataExpiredVerificationLinkIsOjrMasterAttribute));

            if (self.isNeedToShowResendVerificationEmailCaptcha()) {
                self.accountVerificationViewModel.resetResendVerificationCodeCaptcha();
            }

            self.isUserInfoLoaded(true);
        };

        self.isNeedToShowCaptchasContainer = function() {
            return self.isNeedToShowResendVerificationEmailCaptcha();
        };

        self.isNeedToShowResendVerificationEmailCaptcha = function() {
            return self.textCaptchaEnabled
                && self.accountVerificationViewModel.isNeedToShowResendVerificationCodeCaptcha(self.resendVerificationEmailAttemptsCount());
        };

        self.getHomePageUrl = function() {
            var homePageUrl = "/";

            if (AgencyPages && AgencyPages.pageInfoService) {
                homePageUrl = AgencyPages.pageInfoService.getCurrentAgencyHomePath();
            }

            return homePageUrl;
        };

        self.resendVerificationLink = function() {
            if (self.isNeedToShowResendVerificationEmailCaptcha()) {
                if (!self.accountVerificationViewModel.textCaptchaViewModelForResendCode.validate()) {
                    var captchaSelector = self.accountVerificationViewModel.getResendVerificationCodeCaptchaSelector();
                    $(captchaSelector).focus();
                    return;
                }
            }

            gJobs.Services.verifyAccountService.resendVerificationLink(
                credential,
                self.accountVerificationViewModel.textCaptchaViewModelForResendCode.userAnswer(),
                true,
                self.isOjrMaster()
            ).then(function(response) {
                var data = response.data;

                if (!data) {
                    accountVerificationHelper.showVerificationLinkSendFailNotification();
                    return;
                }

                var isCaptchaInvalid = false;

                self.resendVerificationEmailAttemptsCount(data.resendAttempts);

                if (data.isResendSucceeded === false) {
                    if (data.isCaptchaInvalid === true) {
                        isCaptchaInvalid = true;
                        self.accountVerificationViewModel.updateFieldErrorState(
                            self.accountVerificationViewModel.textCaptchaViewModelForResendCode.userAnswer,
                            true,
                            OnlineApp.Validation.validationMessages.captchaInvalidMessage
                        );
                    }
                } else {
                    window.location.href = data.forceRedirectUrl ? data.forceRedirectUrl : "/";
                }

                if (self.isNeedToShowResendVerificationEmailCaptcha()) {
                    self.accountVerificationViewModel.resetResendVerificationCodeCaptchaWithTryingFocusing(
                        null,
                        true,
                        isCaptchaInvalid
                    );
                }
            });
        };

        $(window).blur(function() {
            $lastFocusableElement = $(document.activeElement);
        });

        var loginEvents = OnlineApp.Events.CommonEventsNames.Login + ' ' + Events.CommonEventsNames.Register;

        $(document)
            .on(loginEvents, function(event) {
                window.location.href = self.getHomePageUrl();
            });
    }

    OnlineApp.Namespace.extend('gJobs.ViewModels', {
        ExpiredVerificationLinkViewModel: ExpiredVerificationLinkViewModel
    });

})(window);
;
ko.extenders.ignoreOnSerialization = function(target, value) {
    target.ignoreOnSerialization = value;
    return target;
};;
function canHaveProperties(unwrappedObservable) {
    return (typeof unwrappedObservable == "object") && (unwrappedObservable !== null) &&
        (unwrappedObservable !== undefined) && (!(unwrappedObservable instanceof Date)) &&
        (!(unwrappedObservable instanceof String)) && (!(unwrappedObservable instanceof Number)) &&
        (!(unwrappedObservable instanceof Boolean));
}

var visitModel = function (rootObject, isArrayElement) {
    if (!isArrayElement && ko.isObservable(rootObject) && rootObject.ignoreOnSerialization === true) {
        return undefined;
    }

    var unwrappedRootObject = ko.utils.unwrapObservable(rootObject);

    if (!canHaveProperties(unwrappedRootObject)) {
        return unwrappedRootObject;
    } else if (unwrappedRootObject.constructor === Array) {
        return unwrappedRootObject.map(function (o) { return visitModel(o, true); });
    } else {
        var result = {};
        for (var property in unwrappedRootObject) {
            if (ko.utils.unwrapObservable(unwrappedRootObject[property]) !== unwrappedRootObject) {
                var mappedValue = visitModel(unwrappedRootObject[property]);
                if (mappedValue !== undefined) {
                    result[property] = mappedValue;
                }
            }
        }
        return result;
    }
}


ko.toCleanJSON = function (rootObject) {
    // visit each view model property to ignore unnecessary properties
    var cleanRootObject = visitModel(rootObject);

    return ko.toJSON(cleanRootObject);
};;
// source: http://www.knockmeout.net/2011/05/creating-smart-dirty-flag-in-knockoutjs.html

function toJSON(useCleanJSON, root) {
    return useCleanJSON ? ko.toCleanJSON(root) : ko.toJSON(root)
}

ko.dirtyFlag = function (root, isInitiallyDirty, useCleanJSON, deferEvaluation) {
    var initialState = toJSON(useCleanJSON, root),
        deferEvaluationValue = deferEvaluation === undefined ? true : deferEvaluation;

    var result = function () { },
        _initialState = ko.observable(initialState),
        _isInitiallyDirty = ko.observable(isInitiallyDirty);

    result.isDirty = ko.computed({
        read: function () {
            return _isInitiallyDirty() || _initialState() !== toJSON(useCleanJSON, root);
        },
        deferEvaluation: deferEvaluationValue
    });

    result.reset = function () {
        _initialState(toJSON(useCleanJSON, root));
        _isInitiallyDirty(false);
    };

    return result;
};;
// source: https://stackoverflow.com/a/18184016

ko.subscribable.fn.subscribeChanged = function (callback) {
    var oldValue;
    this.subscribe(function (_oldValue) {
        oldValue = _oldValue;
    }, this, 'beforeChange');

    this.subscribe(function (newValue) {
        callback(newValue, oldValue);
    });
};;
(function (window, undefined) {
    'use strict';
    
    var maxMobileScreenWidth = 767;

    ko.bindingHandlers.adjustSignInFormHeight = {
        init: function (element) {
            var $element = $(element);
            var $formSignIn = $(element).closest('.form-signin');

            //protect from incorrect using of the binding
            if ($formSignIn.length == 0) {
                return;
            }

            $element.onFirst('focusin', function (event) {
                if ($(window).width() < maxMobileScreenWidth) {
                    $formSignIn.css('margin-bottom', $(window).height() + 'px');
                }
            });

            $element.onFirst('focusout', function (event) {
                $formSignIn.css('margin-bottom', 'auto');
            });
        }
    };
})(window);;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.selectedOption = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            var $element = $(element);
            var hasChanged = false;

            $element.change(function () {
                hasChanged = true;

                var allBindings = allBindingsAccessor();
                var valueId = $element.val();
                var options = ko.unwrap(allBindings.options || allBindings.isolatedOptions);
                var optionsValue = ko.unwrap(allBindings.optionsValue);

                var selectedOption = ko.utils.arrayFirst(options, function(item) {
                    return (ko.unwrap(item[optionsValue]) == valueId);
                });

                if (selectedOption === null) {
                    selectedOption = {};
                    selectedOption[optionsValue] = valueId;
                }

                var value = valueAccessor();

                if (typeof value.fromDataModel === 'function') {
                    value.fromDataModel(selectedOption);
                }
                else if (ko.isObservable(value)) {
                    var unwrappedValue = ko.unwrap(value),
                        isObject = jQuery.isPlainObject(unwrappedValue);

                    if (isObject) {
                        // Not implemented
                    }
                    else {
                        if (selectedOption != null && selectedOption != undefined) {
                            value(selectedOption[optionsValue]);
                        }
                    }
                }
                else {
                    $.extend(true, value, selectedOption);
                }
            });

            $element.parent().on('keydown', 'input', function (e) {
                var isEnter = e.keyCode === $.ui.keyCode.ENTER;
                var isTab = e.keyCode === $.ui.keyCode.TAB;
                if ((!e.shiftKey && isTab) || isEnter) {
                    var value = valueAccessor();

                    var allBindings = allBindingsAccessor();
                    var optionsValue = ko.unwrap(allBindings.optionsValue);
                    var optionsText = ko.unwrap(allBindings.optionsText);
                    var validators = value.validators || value[optionsValue].validators || [];

                    var selectedValue;
                    if (isEnter) {
                        // Chozen dropdown hasn't been closed yet. We should search actual value in the search results.
                        var options = ko.unwrap(allBindings.options || allBindings.isolatedOptions);
                        var selectedTextValue = $element.parent().find('.active-result.highlighted').text();

                        for (var i = 0; i < options.length; ++i) {
                            if (options[i][optionsText].toString() === selectedTextValue) {
                                selectedValue = options[i][optionsValue];
                                break;
                            }
                        }
                    } else {
                        // Chozen dropdown has been closed, so actual value is in the select element.
                        selectedValue = $element.val();
                    }
                }

                return true;
            });
        }
    };
})();;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.checkedOption = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            var $element = $(element);

            $element.change(function () {
                var allBindings = allBindingsAccessor();
                var valueId = $(':radio[name=' + $element.attr('name') + ']:checked').val();
                var options = ko.utils.unwrapObservable(allBindings.radioOptions);
                var optionsValue = ko.utils.unwrapObservable(allBindings.radioOptionsValue);

                var selectedOption = ko.utils.arrayFirst(options, function (item) {
                    return (ko.utils.unwrapObservable(item[optionsValue]) == valueId);
                });

                if (selectedOption === null) {
                    selectedOption = {};
                    selectedOption[optionsValue] = valueId;
                }

                var value = valueAccessor();

                if (typeof value.fromDataModel === 'function') {
                    value.fromDataModel(selectedOption);
                } else {
                    $.extend(true, value, selectedOption);
                }

            });
        },

        update: function (element, valueAccessor, allBindingsAccessor) {
            var value = valueAccessor();
            var allBindings = allBindingsAccessor();
            var optionsValue = ko.utils.unwrapObservable(allBindings.radioOptionsValue);

            var valueId = ko.utils.unwrapObservable(value[optionsValue]);

            var $element = $(element);
            var isChecked = ($element.val() == valueId);

            $element.prop('checked', isChecked);
        }
    };
})();;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.optionValueId = {
        init: function (element, valueAccessor) {
            var $element = $(element);
            
            $element.change(function() {
                var valueId = $element.val();
                
                if (valueId === "")
                    valueId = null;

                valueAccessor()(valueId);
            });
        },

        update: function (element, valueAccessor) {
            var valueId = valueAccessor()();
            if (!valueId)
                valueId = "";

            $(element).val(valueId);
        }
    };
})();;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.disableClick = {
        init: function (element, valueAccessor) {
            $(element).one('click', function (event) {
                var value = ko.utils.unwrapObservable(valueAccessor());
                if (value) {
                    event.preventDefault();
                    event.stopPropagation();
                    event.stopImmediatePropagation();
                }
            });
        },

        update: function (element, valueAccessor) {
            // apply disabled style if necessary
            var value = ko.utils.unwrapObservable(valueAccessor());
            ko.bindingHandlers.css.update(element, function() {
                 return { "disabled": value };
            });
            
            //added disabled attribute for IE
            if (value) {
                $(element).attr('disabled', 'disabled');
            } else {
                $(element).removeAttr('disabled');
            }
        }
    };
})();;
(function (window, undefined) {
    'use strict';
    
    ko.bindingHandlers.initialize = {
        init: function (element, valueAccessor) {
            valueAccessor()(element);
        },

        update: function (element, valueAccessor) {
        }
    };
})();;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.placeholder = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            var $element = $(element);

            var placeholderValue = valueAccessor();

            var placeholder = ko.utils.unwrapObservable(placeholderValue.text);

            $element.attr('placeholder', placeholder);

            if (placeholderValue.removeOnFocus) {
                $element.on('focus', function () {
                    $element.attr('placeholder', '');
                });
                $element.on('blur', function () {
                    setTimeout(function () { // Prevent reading placeholder by screenreaders
                        $element.attr('placeholder', placeholder);
                    });
                });
            }

            if ($.fn.placeholder) {
                $element.placeholder();
            }

            var excludeEdge = true;
            if (gJobs.browserDetector.isIE(excludeEdge)) {
                initFakePlaceholder($element, placeholder);
            }
        },

        update: function (element, valueAccessor, allBindingsAccessor) {
            var $element = $(element);
            if (!$element.is(':focus'))
                $element.triggerHandler('blur.placeholder');
        }
    };

    function initFakePlaceholder($element, placeholder) {

        var $placeholderFake = $('<span class="placeholder-ie"></span>');
        $placeholderFake.html(placeholder);

        $placeholderFake.hide();
        $element.closest('.field-container').append($placeholderFake);

        var isFocused = false;

        var addPlaceholder = function () {
            if ($placeholderFake !== undefined) {
                $placeholderFake.css({
                    'display': 'inline-block',
                    'left': 0
                });

                $placeholderFake.closest('.field-container').css({
                    'position': 'relative'
                });
            }
        };

        var removePlaceholder = function () {
            if ($placeholderFake !== undefined) {
                $placeholderFake.hide();
            }
        };

        $element.focus(function () {
            if ($element.val()) {
                return;
            }

            addPlaceholder();

            isFocused = true;
        });

        $element.blur(function () {
            removePlaceholder();

            isFocused = false;
        });

        $element.on('input', function () {

            if (isFocused) {
                if ($element.val()) {
                    removePlaceholder();
                } else {
                    addPlaceholder();
                }
            }
        });

        // Specially for IE 8
        $element.on('propertychange', function () {

            if (isFocused) {
                if ($element.val()) {
                    removePlaceholder();
                } else {
                    addPlaceholder();
                }
            }
        });
    }

})(window);;
(function(window, undefined) {
    'use strict';

    // solution of perfomance issues with options binding was taken from
    // http://www.knockmeout.net/2012/06/knockoutjs-performance-gotcha-3-all-bindings.html
    ko.bindingHandlers.isolatedOptions = {
        init: function (element, valueAccessor) {
            var args = arguments;
            ko.computed({
                read: function () {
                    ko.utils.unwrapObservable(valueAccessor());
                    ko.bindingHandlers.options.update.apply(this, args);
                },
                owner: this,
                disposeWhenNodeIsRemoved: element
            });
        }
    };
})();

;
(function (window, undefined) {
    'use strict';

    var invisibleChosenInputForMobilesafari = '<input class="invisible-chosen-input"></input>';
    var aria = gJobs.ariaAttributes;

    ko.bindingHandlers.chosen = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            var $element = $(element);

            var options = valueAccessor();
            $element.chosen(options);

            var allBindings = allBindingsAccessor();

            var isOpenedAfterInit = ko.unwrap(allBindings.isOpenedAfterInit);
            if (isOpenedAfterInit) {
                $element.one('liszt:updated', function () {
                    $element.siblings('.chzn-container').find('a').attr("aria-label", "");
                    $element.siblings('.chzn-container').find('a').trigger('focus');
                });
            }
            $element.on('change', function (e, params) {
                if (params.selected) {
                    $element.siblings('.chzn-container').find('a').last().focus();
                }
            });

            var $chosenContainer = $element.siblings('.chzn-container.chzn-container-single');
            var $chosenSearchInput = $chosenContainer.find('.chzn-search > input');
            var $chosenLink = $chosenContainer.find('.chzn-single');

            if ($('.chzn-results').length > 0) {
                $chosenContainer.find('.chzn-results').attr('role', 'listbox');
            }
            $chosenLink.attr('role', 'option');

            if (gJobs.browserDetector.isMobileSafari()) {

                var onInvisibleElementFocus = function (e) {
                    $chosenLink.trigger('focus');
                    $invisibleElement.remove();
                }

                var $invisibleElement = $(invisibleChosenInputForMobilesafari);

                $chosenContainer.prepend($invisibleElement);

                $invisibleElement.focus(onInvisibleElementFocus);

                $chosenSearchInput.blur(function () {
                    $chosenContainer.prepend($invisibleElement);
                    $invisibleElement.focus(onInvisibleElementFocus);
                });
            }
        },

        update: function (element, valueAccessor, allBindingsAccessor) {

            var validatableValue = valueAccessor().validatableValue;

            /*
                Registering dependency tracking engine with dropdown options updates.
                    This is crucial for deferred async loading or conditional loading of options.
            */
            ko.unwrap(
                allBindingsAccessor().isolatedOptions ||
                allBindingsAccessor().options
            );

            var allBindings = allBindingsAccessor(),
                optionsValue = ko.unwrap(allBindings.optionsValue),
                selectedOption = ko.unwrap(allBindings.selectedOption),
                selectedOptions = ko.unwrap(allBindings.selectedOptions);

            var $chznContainer = $(element).parent().find('.chzn-container');

            var validatableValue = valueAccessor().validatableValue;
            if (validatableValue) {
                var hasError = ko.utils.unwrapObservable(validatableValue.hasError);
                $chznContainer.setAttributes([
                    [aria.invalid, hasError]
                ]);
            }

            if (selectedOption) {
                if (typeof (selectedOption) === 'object') {
                    selectedOption = ko.unwrap(selectedOption[optionsValue]);
                }

                $(element)
                    .val(selectedOption)
                    .trigger("liszt:updated");
            }
            // case for multiselects
            else if (selectedOptions) {
                $(element).trigger("liszt:updated");
                OnlineApp.Helpers.layoutHelper.tabbing.updateIndices();
            }

            if (selectedOption || selectedOptions) {
                $chznContainer.removeClass('chzn-options-caption-set');
            } else {
                $chznContainer.addClass('chzn-options-caption-set');
            }
        }
    };
})();;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.popover = {
        init: function (element, valueAccessor) {
            var $element = $(element);

            var value = valueAccessor();

            if (value.content) {
                $element.popover({
                    content: ko.unwrap(value.content),
                    template: '<div class="popover ' + (value.className || '') + '" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
                });
            } else {
                $element.popover();
            }

            if (value.containerStyle != undefined) {
                var $container = $element.closest('.' + value.containerStyle);

                var topPlacement = false;
                var placement = $element.attr('data-placement');
                if (placement === 'top') {
                    topPlacement = true;
                }

                $element.on('mouseenter', function (e) {

                    $element.popover('show');

                    var $popover = $('.popover.fade.in');

                    var adjustmentFinished = false;

                    while (!adjustmentFinished) {
                        var elementOffset = $container.outerWidth()
                            - (($popover.offset().left - $container.offset().left)
                                + $popover.outerWidth() + parseInt($popover.css('margin-left')));

                        var oldTop = parseInt($popover.css('top'));
                        var oldLeft = parseInt($popover.css('left'));
                        var oldHeight = $popover.height();
                        var oldWidth = $popover.width();

                        $popover.css('width', oldWidth + elementOffset + 'px');

                        var newHeight = $popover.height();
                        var newWidth = $popover.width();

                        var heightOffset = (newHeight - oldHeight) / 2;
                        var widthOffset = (newWidth - oldWidth) / 2;

                        $popover.css('top', oldTop - heightOffset);

                        if (topPlacement) {
                            $popover.css('left', oldLeft - widthOffset);
                        }

                        var newTop = parseInt($popover.css('top'));
                        var newLeft = parseInt($popover.css('left'));

                        if (oldTop == newTop && oldLeft == newLeft) {
                            adjustmentFinished = true;
                        }
                    }
                });

                $element.on('mouseleave', function (e) {

                    $element.popover('hide');
                });
            }
        },
        update: function (element, valueAccessor) {
            var $element = $(element);
            var value = valueAccessor();
            if (value.content) {
                var newValue = ko.unwrap(value.content);
                if (newValue !== $element.data('content')) {
                    $element.popover('destroy');
                    $element.popover({
                        content: newValue,
                        template: '<div class="popover ' + (value.className || '') + '" role="tooltip"><div class="arrow"></div><h3 class="popover-title"></h3><div class="popover-content"></div></div>'
                    });
                }
            }
        }
    };
})(window);;
(function (window, undefined) {
    'use strict';


    var stickElementToBottomOnce = function ($element, $scrollableContainer) {

        /*
            Following properties may vary at runtime, so its not safe to cache them. 
        */
        var scrollOffset = $scrollableContainer.scrollTop();
        var containerHeight = $scrollableContainer.height();
        var elementHeight = $element.height();

        var elementTop = (containerHeight + scrollOffset - elementHeight);

        if (scrollOffset) {
            $element.css({
                'top': elementTop,
                'height': elementHeight
            });
        } else {
            $element.css({
                'top': '',
            });
        }
    };

    var stickElementToBottomOnScroll = function ($element, $scrollableContainer) {

        var stickFunction = function () {
            /*
                Ignore invisible elements.
            */
            if (!$element.is(':visible')) {
                return;
            }

            stickElementToBottomOnce($element, $scrollableContainer);
        };

        $scrollableContainer.scroll(stickFunction);
    };

    var stickElementToBottomOnResize = function ($element, $scrollableContainer) {

        var stickFunction = function () {
            // set handling to the end of event queue (for IE9)
            setTimeout(function () {
                stickElementToBottomOnce($element, $scrollableContainer);
            }, 0);
        };
        $(window).resize(stickFunction);
    };


    ko.bindingHandlers.stickyElement = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            var options = valueAccessor();

            var $element = $(element);
            var $scrollableContainer = $element.closest(options.container);

            stickElementToBottomOnScroll($element, $scrollableContainer);
            stickElementToBottomOnResize($element, $scrollableContainer);
        }
    };
})(window);;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.slideVisible = {
        init: function (element, valueAccessor, allBindings, viewModel) {
            var value = valueAccessor();
            if (!gJobs.browserDetector.isIE() || !viewModel || !viewModel.disableSlideVisibleBinding) {
                $(element).toggle(ko.utils.unwrapObservable(value));
            }
        },

        update: function (element, valueAccessor, allBindings, viewModel) {
            var value = valueAccessor();
            var duration = 600;
            if (!gJobs.browserDetector.isIE() || !viewModel || !viewModel.disableSlideVisibleBinding) {
                ko.utils.unwrapObservable(value) ? $(element).slideDown(duration) : $(element).slideUp(duration);
            }
        }
    };
})();
;
/*
    Custom binding that joins three bindings inside:
        1 - common value binding
        2 - validation binding on hasError observable
        3 - behavioral binding to hide validation message when element is in focus

    Use cases:
         data-bind="validatableValue: observable"
         data-bind="validatableValue: { value: observable, errorClass: 'validation-error' }"
         data-bind="validatableValue: { value: observable, errorClass: false }"
*/

(function (window, undefined) {
    'use strict';


    var normazileBinding = function (valueAccessor) {

        var binding = valueAccessor();

        var normalizedBinding = {
            value: null,
            errorValue: null,
            errorClass: 'validation-error'
        };


        if (typeof binding === 'object') {
            $.extend(normalizedBinding, binding);

            if (!('errorValue' in binding)) {
                binding.errorValue = binding.value.hasError;
            }
        }
        else {
            normalizedBinding.value = binding;
            normalizedBinding.errorValue = binding.hasError;
        }

        return normalizedBinding;
    };

    var preventIeFlickering = function ($element) {
        var disableFlickeringClass = 'disable-flickering-on-focus';

        if (!$element.hasClass('btn')) {
            return;
        }

        $element.addClass(disableFlickeringClass);
        setTimeout(function() {
            $element.removeClass(disableFlickeringClass);
        });
    };

    var initFocusBehavior = function (normalizedBinding, enclosingBindingArguments) {

        var value = normalizedBinding.value;
        var errorClass = normalizedBinding.errorClass;
        var keypressEvent = null;

        $(enclosingBindingArguments.element)
            .keydown(function (e) {
                keypressEvent = e;
            })
            .focusout(function (e) {
                if (value.isValidationMessageVisible && value.hasError && value.hasError()) {
                    value.isValidationMessageVisible(true);
                    if (keypressEvent && !keypressEvent.shiftKey && (keypressEvent.keyCode === $.ui.keyCode.TAB)) {
                        preventIeFlickering($(e.relatedTarget));
                        if (!errorClass) {
                            var $target = $(e.relatedTarget);
                            var $element = $(enclosingBindingArguments.element);
                            if ($element.find($target).length !== 0) {
                                return;
                            }
                        }
                        $(document).trigger(Events.CommonEventsNames.ShowValidationMessage, enclosingBindingArguments.element);
                        keypressEvent = null;
                    }
                }
            });
    };

    var initValueBehavior = function (normalizedBinding, enclosingBindingArguments) {

        var valueAccessor = function () {
            return normalizedBinding.value;
        };

        ko.bindingHandlers.value.init(
            enclosingBindingArguments.element,
            valueAccessor,
            enclosingBindingArguments.allBindingsAccessor,
            enclosingBindingArguments.viewModel,
            enclosingBindingArguments.bindingContext);
    };

    var initMaxLengthBehavior = function(normalizedBinding, enclosingBindingArguments) {
        if (normalizedBinding.value && normalizedBinding.value.validators) {
            for (var i = 0; i < normalizedBinding.value.validators.length; i++) {
                var validator = normalizedBinding.value.validators[i];
                if (validator.name === "length" && validator.options.max) {
                    $(enclosingBindingArguments.element).attr('maxlength', validator.options.max);
                }
            }
        }
    };


    var updateCssBehavior = function (normalizedBinding, enclosingBindingArguments) {

        if (!normalizedBinding.errorClass) {
            return;
        }


        var cssAccessor = function () {
            var css = {};
            css[normalizedBinding.errorClass] = normalizedBinding.errorValue;

            return css;
        };

        // Some binding do not have init functionality, so simply subscribe and update them

        ko.bindingHandlers.css.update(
            enclosingBindingArguments.element,
            cssAccessor,
            enclosingBindingArguments.allBindingsAccessor,
            enclosingBindingArguments.viewModel,
            enclosingBindingArguments.bindingContext);
    };

    var updateValueBehavior = function (normalizedBinding, enclosingBindingArguments) {

        var valueAccessor = function () {
            return normalizedBinding.value;
        };

        // Simple wrapper binding update
        ko.bindingHandlers.value.update(
            enclosingBindingArguments.element,
            valueAccessor,
            enclosingBindingArguments.allBindingsAccessor,
            enclosingBindingArguments.viewModel,
            enclosingBindingArguments.bindingContext);
    };


    
    ko.bindingHandlers.validatableValue = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

            var binding = normazileBinding(valueAccessor);

            var enclosingBindingArgumens = {
                element: element,
                valueAccessor: valueAccessor,
                allBindingsAccessor: allBindingsAccessor,
                viewModel: viewModel,
                bindingContext: bindingContext
            };


            initFocusBehavior(binding, enclosingBindingArgumens);
            initValueBehavior(binding, enclosingBindingArgumens);
            initMaxLengthBehavior(binding, enclosingBindingArgumens);
        },

        update: function (element, valueAccessor, allBindingsAccessor, viewModel, bindingContext) {

            var binding = normazileBinding(valueAccessor);

            var enclosingBindingArgumens = {
                element: element,
                valueAccessor: valueAccessor,
                allBindingsAccessor: allBindingsAccessor,
                viewModel: viewModel,
                bindingContext: bindingContext
            };


            updateCssBehavior(binding, enclosingBindingArgumens);
            updateValueBehavior(binding, enclosingBindingArgumens);
        }
    };
})();



;
(function (ko, $) {
    'use strict';

    var ARIA_DESCRIBEDBY = 'aria-describedby',
        ARIA_LABELLEDBY = 'aria-labelledby';

    ko.bindingHandlers.validationMessage = {
        init: function (element, valueAccessor) {
            var options = valueAccessor();
            var $element = $(element);
            var isDropdown = $element.is('select');

            if (isDropdown) {
                $element = $element.parent().find('div.chzn-container');
            }

            if (options.field && options.field.hasError) {
                var savedFieldLabelledby = null;
                options.field.hasError.subscribe(function (newValue) {
                    if (isDropdown) {
                        savedFieldLabelledby = $element.attr(ARIA_LABELLEDBY) || '';
                        if (newValue && options.field.validationMessage()) {
                            $element.attr(
                                ARIA_LABELLEDBY, savedFieldLabelledby + ' ' + options.validationMessageId
                            );
                        }

                        if (!newValue) {
                            $element.attr(ARIA_LABELLEDBY, savedFieldLabelledby);
                        }
                    } else {
                        if (newValue) {
                            $element.attr(ARIA_DESCRIBEDBY, options.validationMessageId);
                        } else {
                            $element.removeAttr(ARIA_DESCRIBEDBY);
                        }
                    }
                });
            }

            if (options.additionalValidationValue && options.additionalValidationValue.hasError) {
                var savedAdditionalValueLabelledby = null;
                var latestValue = null;
                
                options.additionalValidationValue.hasError.subscribe(function (newValue) {
                    if (newValue === latestValue) {
                        return;
                    }
                    if (newValue) {
                        savedAdditionalValueLabelledby = $element.attr(ARIA_LABELLEDBY);
                        $element.attr(
                            ARIA_LABELLEDBY,
                            savedAdditionalValueLabelledby + ' ' + options.additionalValidationValueId
                        );
                    } else {
                        $element.attr(ARIA_LABELLEDBY, savedAdditionalValueLabelledby);
                    }
                });

                options.additionalValidationValue.hasError.subscribe(function (oldValue) {
                    latestValue = oldValue;
                }, null, "beforeChange");
            }
        }
    };
})(ko, jQuery);;
(function (window, undefined) {
    'use strict';


    var equalizeSize = function (element, valueAccessor, allBindingsAccessor) {

        var options = valueAccessor();

        ko.unwrap(options.enabled);

        var $contentElement = $(element);
        var $element = $contentElement.closest(options.parentElement);

        if (gJobs.browserDetector.isIE()  == 8) {
            $element.css('width', '100%');
        }

        if ($element.width() < $contentElement.width()) {
            $element.width($contentElement.width());
        }
    };


    ko.bindingHandlers.sizeToContent = {

        init: function (element, valueAccessor, allBindingsAccessor) {
            equalizeSize(element, valueAccessor, allBindingsAccessor);
        },

        update: function (element, valueAccessor, allBindingsAccessor) {
            equalizeSize(element, valueAccessor, allBindingsAccessor);
        }
    };
})();;
(function (window, undefined) {
    'use strict';

    var getTemplateName = function () {
        var currentArea = gJobs.areaInfoService && gJobs.areaInfoService.getCurrentArea();

        if (currentArea === gJobs.areaInfoService.areaNames.Career) {
            return 'Templates/DottedSpinner';
        } else {
            return 'Templates/RoundSpinner';
        }
    };

    var getOrCreateLoadingElement = function (element) {

        var $loadingElement = $('.loading-element', element);

        if ($loadingElement.length === 0) {

            $loadingElement = $('<div></div>')
                .addClass('loading-element')
                .appendTo(element);

            var templateName = getTemplateName();

            ko.applyBindingsToNode($loadingElement.get(0), { template: { name: templateName } });
        }

        return $loadingElement[0];
    };

    var getOrCreateTextElement = function (element) {

        var $element = $(element);
        var $textElement = $('.text-element', element);

        if ($textElement.length === 0) {
            var buttonText = $element.html();

            $textElement =
                $('<span>')
                    .addClass('text-element')
                    .html(buttonText);

            $element
                .empty()
                .append($textElement);
        }

        return $textElement[0];
    };


    var negateObservable = function (observable) {
        return ko.computed(function () {
            return !ko.utils.unwrapObservable(observable);
        });
    };



    ko.bindingHandlers.busy = {

        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            
            var value = valueAccessor();


            var textElement =
                getOrCreateTextElement(element);

            ko.applyBindingsToNode(textElement, {
                visible: negateObservable(value)
            });


            var loadingElement =
                getOrCreateLoadingElement(element);

            ko.applyBindingsToNode(loadingElement, {
                visible: value
            });


            return { controlsDescendantBindings: true };
        },

        update: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var value = valueAccessor();
            
            if (ko.utils.unwrapObservable(value)) {
                var $emptyFocusableSpan = $('<span class="hide-notification no-restrict-focus" tabindex="-1">&nbsp;</span>');
                $(element).append($emptyFocusableSpan);
                $emptyFocusableSpan.focus();
                $emptyFocusableSpan.one('focusout', function () {
                    $emptyFocusableSpan.remove();
                });
            }

            ko.bindingHandlers.disable.update(
                element,
                valueAccessor,
                allBindingsAccessor,
                viewModel);
        }
    };
})(window);;
(function (window, undefined) {
    'use strict';


    var applyTextBinding = function (element, valueAccessor) {
        var binding = valueAccessor();

        var isPropertyRequired = checkIsPropertyRequired(binding.field);


        var text;

        if (isPropertyRequired) {
            text = ko.utils.unwrapObservable(binding.text);
        }

        $(element)
            .text(text)
            .toggleClass('required', isPropertyRequired);

        if (isPropertyRequired) {
            $(element).show();
        } else {
            $(element).hide();
        }
    };


    var findRequiredValidator = function (observableProperty) {

        var requiredValidator =
            ko.utils.arrayFirst(observableProperty.validators, function (validator) {
                return (validator.name === 'required');
            });

        return requiredValidator;
    };

    var checkIsPropertyRequired = function (observableProperty) {

        var requiredValidator = findRequiredValidator(observableProperty);

        if (!requiredValidator) {
            return false;
        }

        return requiredValidator.enabled();
    };


    ko.bindingHandlers.requiredText = {
        init: function (element, valueAccessor, allBindingsAccessor) {
            applyTextBinding(element, valueAccessor);
        },

        update: function (element, valueAccessor, allBindingsAccessor) {
            applyTextBinding(element, valueAccessor);
        }
    };


})(window);;
(function (window, undefined) {
    'use strict';

    var tabIndexApplicants;

    function parentContainerIsTheSame(el1, el2, containerSelector) {
        if (!el1 || !el2) {
            return false;
        }

        var parent1 = $(el1).closest(containerSelector),
            parent2 = $(el2).closest(containerSelector);

        return parent1.get(0) === parent2.get(0);
    }

    function setCheckAndRadioBehavior($elements) {
        $elements
            .filter("input[type=radio],input[type=checkbox]")
            .off("focus blur")
            .focus(function (event) {
                if(!event.target ||
                   !event.originalEvent)

                if (parentContainerIsTheSame(
                        event.target,
                        !!event.originalEvent ? event.originalEvent.explicitOriginalTarget : undefined,
                        "label")) {
                    return false;
                }

                var $this = $(this);
                $this.closest('.labelled-input').addClass('focus');

                // check box on pressing "Space" (default browser behavior)
                // and "Enter"
                if ($this.attr("type") === "checkbox") {
                    $this.on("keypress", function (e) {
                        var code = (e.keyCode ? e.keyCode : e.which);
                        if (code == 13) {
                            // here we'd need to manually update ko "checked" binding
                            //var checked = $this.is(":checked");
                            //$this.prop('checked', !checked);

                            // click makes "checked" binding to update
                            $this.click();
                        }
                    });
                }
            })
            .blur(function () {
                var $this = $(this);
                $this.closest('.labelled-input').removeClass('focus');

                if ($this.attr("type") === "checkbox") {
                    $this.off("keypress");
                }
            });
    }

    function setTabIndex(element) {
        var index = tabIndexApplicants ? tabIndexApplicants.index(element) : -1;

        if (index === -1) {
            tabIndexApplicants = $("input[type=text],input[type=radio],input[type=checkbox],textarea,button")
                .filter(":visible")
                .add("select");

            index = tabIndexApplicants.index(element);

            // if element is still not fount (might be invisible)
            if (index === -1) {
                return;
            }

            // iterate over sequence and assign everyone proper tabindex
            tabIndexApplicants.each(function(i) {
                var $this = $(this);
                // tabindex can't be 0
                $this.attr("tabindex", ++i);
            });
            setCheckAndRadioBehavior(tabIndexApplicants);
        }

        // tabindex can't be 0
        // $(element).attr("tabindex", ++index);

        // more robust would be iterate over sequence and assign everyone proper tabindex
    }

    ko.bindingHandlers.tabIndex = {

        init: function (element, valueAccessor) {

            // postpone is used for elements that should be evaluated at later point
            // e.g. we have "save/cancel buttons" html template which loads prior to any other controls
            // but should have last tabindex
            // EDIT: more robust solution is to iterate over sequence and assign everyone proper tabindex
            /*
            var postpone = valueAccessor().postpone;
            if (postpone) {
                window.setTimeout(function () {
                    setTabIndex(element);
                }, 0);

                return;
            }
            */

            setTabIndex(element);
        },

        setCheckAndRadioBehavior: setCheckAndRadioBehavior
    };
})(window);;
(function (window, undefined) {
    'use strict';


    ko.bindingHandlers.autoFill = {

        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

            var autoFillTargetsSelector = ':input';
            var submitControlSelector = 'button[type="submit"]';


            var $element = $(element);

            $element.on('blur', autoFillTargetsSelector, function (e) {
                $(e.target).change();
            });

            $element.on('click', submitControlSelector, function (e) {
                $(e.delegateTarget).find(autoFillTargetsSelector).change();
            });
        }
    };
})();;
(function(window, undefined) {
    'use strict';

    function KnockoutValidationExtender() {
        var self = this;

        /*
            Constants.
        */
        var DEFAULT_VALIDATION_OPTIONS = {
            validationMessage: '',
            isValidationMessageVisible: true
        };


        /*
            Private members.
        */

        /*
            Ensures that observable property has necessary validation properties.
        */
        var ensureStructure = function (observableProperty) {
            observableProperty.hasError = observableProperty.hasError || ko.observable(false);
            observableProperty.validationMessage = observableProperty.validationMessage || ko.observable('');
            observableProperty.validators = observableProperty.validators || [];
            observableProperty.isValidationMessageVisible = (observableProperty.isValidationMessageVisible || ko.observable(false)).extend({ throttle: 1 });
        };

        /*
            Registers validator with observable property. 
        */
        var registerValidator = function (observableProperty, validatorName, validatorObject, options) {
            ensureStructure(observableProperty);

            options = $.extend({},
                DEFAULT_VALIDATION_OPTIONS,
                options);

            var validator = {
                name: validatorName,
                action: validatorObject.validate,
                options: options,
                observableProperty: observableProperty,
                enabled: function () {
                    if (typeof validatorObject.isEnabled !== 'function') {
                        return true;
                    }

                    return validatorObject.isEnabled(options);
                }
            };

            observableProperty.validators.push(validator);

            applyValidatorBehavior(validator);
        };

        /*
            Applies runtime validation behavior.
        */
        var applyValidatorBehavior = function (validator) {

            /*
                Apply on property change behavior.
                    Due to performance reasons all validator actions will be fired at once.
            */
            if (validator.observableProperty.validators.length === 1) {
                validator.observableProperty.subscribe(function () {
                    validate(validator);
                });
            }

            /*
                Apply on demand validation method.
            */
            validator.observableProperty.validate = function (supressValidationError) {
                return validate(validator, supressValidationError);
            };
        };


        /*
            Core method that triggers validation and related validation property changes.
        */
        var validate = function (validator, supressValidationError) {
            var isValid = true;
            var failedValidator;

            var value = validator.observableProperty();
            var validators = validator.observableProperty.validators;


            for (var i = 0; i < validators.length; i++) {
                isValid = isValid && validators[i].action(value, validators[i].options);

                if (!isValid) {
                    failedValidator = validators[i];
                    break;
                }
            }

            if (!supressValidationError) {
                if (isValid) {
                    validator.observableProperty.validationMessage(null);
                    validator.observableProperty.hasError(false);
                    validator.observableProperty.isValidationMessageVisible(false);
                }
                else {
                    validator.observableProperty.validationMessage(failedValidator.options.validationMessage);
                    validator.observableProperty.hasError(true);
                    validator.observableProperty.isValidationMessageVisible(failedValidator.options.isValidationMessageVisible);
                }
            }

            return isValid;
        };


        /*
            Public members.
        */
        self.registerExtension = function (extenderName, extender) {

            ko.extenders[extenderName] = function(target, options) {
                options = $.extend({},
                    extender.defaultOptions,
                    options);

                registerValidator(target, extenderName, extender.validator, options);

                return target;
            };
        };

        self.registerExtensions = function (extenders) {
            $.each(extenders, function (extenderName, extender) {
                self.registerExtension(extenderName, extender);
            });
        };
    };



    OnlineApp.Namespace.extend('OnlineApp.Extensions.Knockout', {
        KnockoutValidationExtender: KnockoutValidationExtender
    });

})(window);;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.directDropdown = {

        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

            var options = valueAccessor() || {};

            if (options.container == undefined) {
                return;
            }

            var $element = $(element);

            if (!options.topMargin) {
                var $label = $element.siblings('label.inline-text, span.inline-text');
                if (!$label.length) {
                    $label = $element.parents('.question-item').find('.question-text');
                }
                if ($label.length) {
                    var labelMargin = parseInt($label.css('margin-top')) || parseInt($label.css('margin-bottom'));
                    options.topMargin = $label.height() + labelMargin;
                }
            }

            var containerClass = "." + options.container;

            var wrapper = $element.siblings('.chzn-container');
            var dropDown = wrapper.find(".chzn-drop");
            var input = wrapper.find("input");

            var container = wrapper.closest(containerClass);

            var choices = dropDown.find("li");

            var isContainerHeightChanged = false;

            input.on("focus", function () {
                // That means if drop down is visible due to chosen.jquery.js plugin.
                if (parseInt(dropDown.css("left")) >= 0) {
                    // Calculate position of the drop down to decide
                    // what should be the direction (up or down).
                    var scrollTop = $(window).scrollTop();
                    var wrapperOffset = $(wrapper).offset().top;
                    var windowHeight = $(window).height();

                    // windowTopOffset - offset between wrapper top and current window top
                    var windowTopOffset = wrapperOffset - scrollTop;
                    var windowCenter = windowHeight / 2 - wrapper.height();

                    if (windowTopOffset > windowCenter) {
                        dropDown.addClass("chzn-drop-up");
                    } else {
                        dropDown.removeClass("chzn-drop-up");
                    }

                    // Check, if drop down is lower height than container.
                    // If not, then make container bigger.
                    var dropDownOffset = dropDown.offset().top;
                    var containerOffset = container.offset().top;

                    // dropDownOffsetBottom - offset of dropdown top from container bottom
                    var dropDownOffsetBottom = container.height() - (dropDownOffset - containerOffset);
                    var dropDownOverflowHeight = dropDown.outerHeight() - dropDownOffsetBottom;

                    if (dropDownOverflowHeight > 0) {
                        var newHeight = container.height() + dropDownOverflowHeight;
                        container.css("height", newHeight + "px");
                        isContainerHeightChanged = true;
                    }

                    // If window height is smaller than 650px, scroll to the input to make whole selection visible
                    if(windowHeight < 650) {
                        scrollToView(wrapper, options.topMargin);
                        dropDown.removeClass("chzn-drop-up");
                    }
                    
                } else {
                    input.trigger("blur");
                }
            });

            var isOver = false;
            dropDown.mouseover(function () {
                isOver = true;
            }).mouseleave(function () {
                isOver = false;
            });

            choices.on("click", function () {
                isOver = false;

                input.trigger("blur");
            });

            input.on("blur", function () {
                if (!isOver && isContainerHeightChanged) {
                    container.css("height", "");
                    isContainerHeightChanged = false;
                }
            });
        }
    };

    function scrollToView(view, topMargin) {
        var $flyoutBody = $(".flyout-scroll-view");
        var isFlyout = $flyoutBody.length > 0;
        var container = isFlyout ? $flyoutBody : $("html, body");

        var newScrollPosition = isFlyout 
            ? view.position().top
            : view.offset().top - $('.floating-header, .navbar').height();

        if (!isNaN(topMargin)) {
            newScrollPosition -= topMargin;
        }

        container.animate({ scrollTop: newScrollPosition }, 500);
    }

})(window);;
(function (window, undefined) {
    'use strict';

    function getRadioButtonsExceptCurrent(radioElement) {

        var radioGroupName = radioElement.attr('name');
        // TODO: refactoring anf optimization required
        var otherRadios = $('input[name="' + radioGroupName + '"]').not(radioElement);

        return otherRadios;
    }

    ko.bindingHandlers.checkRadio = {

        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

            var radioElement = $(element);
            var checkValue = valueAccessor();

            var otherRadios = getRadioButtonsExceptCurrent(radioElement);

            radioElement.on('click', function () {

                // TODO: FIND A BETTER EXPRESSION
                checkValue(radioElement.is(':checked'));

                if (radioElement.is(':checked')) {
                    checkValue(true);
                } else {
                    checkValue(false);
                }

                // Trigger other radios to change their observables to false.
                otherRadios.trigger('changeToFalse');
            });

            radioElement.on('changeToFalse', function () {

                checkValue(false);
            });
        },

        update: function (element, valueAccessor, allBindingsAccessor, viewModel) {

            var radioElement = $(element);
            var checkValue = valueAccessor();
            var value = ko.unwrap(checkValue);

            var otherRadios = getRadioButtonsExceptCurrent(radioElement);

            if (value) {
                otherRadios.trigger('changeToFalse');
                radioElement.prop('checked', true);
                
            } else {

                radioElement.prop('checked', false);
            }
        }
    };
})(window);
;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.updateTabIndex = {
        update: function (element, valueAccessor) {
            OnlineApp.Helpers.layoutHelper.tabbing.updateIndices();
        }
    };
})();;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.hasFocusOneWay = {

        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {

            var options = valueAccessor() || {};

            if (options.observable == undefined) {
                return;
            }

            var observable = options.observable;

            if (options.readOrWrite === 'write') {
                var writeObservable = function (isFocus) {
                    if (ko.isObservable(observable)) {
                        observable(isFocus);
                    }
                };

                ko.applyBindingsToNode(element, {
                    event: {
                        focus: function () {
                            writeObservable(true);
                        },
                        blur: function () {
                            writeObservable(false);
                        }
                    }
                });
            } else if (options.readOrWrite === 'read') {
                observable.subscribe(function(newValue) {
                    if (newValue) {
                        var $element = $(element);
                        $element.focus();
                    }
                });
            }
        }
    };
})();;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.ieFixKeyboardNavigation = {
        init: function (element, valueAccessor) {
            if (!gJobs.browserDetector.isIE()) {
                return;
            }

            var $element = $(element);

            $element.on('keydown', function (e) {
                if (e.which == $.ui.keyCode.TAB) {
                    e.preventDefault();

                    var offset = e.shiftKey ? -1 : 1;
                    var tabindex = parseInt($element.attr('tabindex'), 10);
                    var targetTabindex = tabindex + offset;

                    $('[tabindex="' + targetTabindex + '"]').focus();
                } else if (e.which == $.ui.keyCode.ENTER) {
                    e.preventDefault();
                    $element.trigger('click');
                }
            });
        }
    };
})();
;
(function (window, undefined) {
    'use strict';

    var cache = {};
    var instanceCount = 1;
    var doesLastFocusableElementExist = false;

    ko.bindingHandlers.modalRestrictFocus = {
        init: function (element) {
            var $element = $(element);
            $element.data('unrestrict-index', instanceCount);
            instanceCount++;
        },
        update: function (element, valueAccessor) {
            var value = valueAccessor();
            var $element = $(element);
            var $modalDialogWrapper = $element.parent();
            var unrestrictFunction;
            var index;

            if (value()) {
                gJobs.focusService.setFocus($element);

                unrestrictFunction = gJobs.focusService.restrictFocus($modalDialogWrapper, null, true);

                index = $element.data('unrestrict-index');
                cache[index] = unrestrictFunction;
            } else {
                index = $element.data('unrestrict-index');

                if (index && cache.hasOwnProperty(index)) {
                    $modalDialogWrapper.find('[tabindex]').attr('tabindex', -1);

                    if (!doesLastFocusableElementExist) {
                        gJobs.focusService.restoreBrowserControlsFocusBehavior();
                    }

                    unrestrictFunction = cache[index];
                    unrestrictFunction();
                    $.removeData($element, 'unrestrict-index');
                    gJobs.focusService.restoreFocus();
                }
            }
        }
    };
})();
;
(function (window, undefined) {
    'use strict';

    function isElementFullyInViewport(element, viewport) {
        var rect = element.getBoundingClientRect();

        return rect.top >= viewport.top &&
            rect.left >= viewport.left &&
            rect.right <= viewport.left + viewport.width &&
            rect.bottom <= viewport.top + viewport.height;
    }

    function shouldScrollOnInit($element) {
        if (!$element.is(':visible')) {
            return false;
        }

        var $searchArea = $element.parent();

        var $firstElementWithScrollBinding = $searchArea
            .children('[data-bind]')
            .filter(function (index, element) {
                return $(element).attr('data-bind').indexOf('scrollIntoView') + 1;
            });

        return $element[0] == $firstElementWithScrollBinding[0];
    }

    ko.bindingHandlers.scrollIntoView = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var $element = $(element);

            var options = valueAccessor();
            var shouldScrollToChildElement = options.hasOwnProperty('fieldContainerSelector');

            var alignFunction = function ($target) {
                var isElementInsideFixedElement = $element
                    .parents()
                    .toArray()
                    .some(function (item) {
                        return $(item).css('position') == 'fixed';
                    }
                    );

                var $container = $element.scrollParent();
                if ($container[0] == $('body')[0] && gJobs.browserDetector.isFirefox()) {
                    $container = $('html');
                }

                var elementRect = $element[0].getBoundingClientRect();
                var elementOffset = elementRect.top;
                var elementHeight = elementRect.height;
                var currentScrollPosition = $container.scrollTop();

                var viewport = {
                    height: 0,
                    width: 0,
                    top: 0,
                    left: 0
                };

                if (isElementInsideFixedElement) {
                    var containerRect = $container[0].getBoundingClientRect();
                    elementOffset -= containerRect.top;

                    viewport.top = containerRect.top;
                    viewport.left = containerRect.left;
                    viewport.width = containerRect.width;
                    viewport.height = containerRect.height;

                } else {
                    viewport.width = $(window).width();
                    viewport.height = $(window).height();
                }

                if (isElementFullyInViewport($element[0], viewport)) {
                    return;
                }

                var offset;
                if (elementHeight <= viewport.height) {
                    offset = elementOffset - ((viewport.height / 2) - (elementHeight / 2));
                }
                else {
                    $target = shouldScrollToChildElement ?
                        $target.closest(options.fieldContainerSelector) :
                        $target;

                    var target = $target[0];

                    if (target) {
                        var targetRect = target.getBoundingClientRect();
                        if (!isElementFullyInViewport(target, viewport)) {
                            offset = targetRect.height < viewport.height ?
                                targetRect.top - viewport.top - ((viewport.height / 2) - (targetRect.height / 2)) :
                                targetRect.top - viewport.top;
                        } else {
                            return;
                        }
                    }
                }

                $container.scrollTop(currentScrollPosition + offset);
            }

            if (shouldScrollOnInit($element)) {
                alignFunction($(element).find(":tabbable").first());
            }

            $element.on('keyup', ':tabbable', function (event) {
                if (event.which === $.ui.keyCode.TAB) {
                    alignFunction($(event.target));
                }
            });
        }
    };
})(window);;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.checkMark = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            var $element = $(element);
            var options = valueAccessor();

            var $triggerElement = $element.closest(options.container).find(options.triggerElementSelector);

            $element.on('click', function () {
                if (options.type === 'radio') {
                    $triggerElement.prop('checked', true);
                }

                $triggerElement.trigger('click').focus();
            });
        }
    };
})(window);
;
(function (window, undefined) {
    'use strict';

    ko.bindingHandlers.hideForScreenReader = {

        init: function (element, valueAccessor) {
            var $element = $(element);
            var options = valueAccessor();

            var target = options.eventTarget === 'document' ? document : options.eventTarget;

            $(target)
                .on(options.hideEvent, function(e) {
                    $element.attr('aria-hidden', 'true');
                })
                .on(options.showEvent, function(e) {
                    $element.attr('aria-hidden', 'false');
                });
        }
    };
})();
;
(function (window, undefined) {
    'use strict';
    var layoutHelper = OnlineApp.Helpers.layoutHelper,
        commonEventsNames = OnlineApp.Events.CommonEventsNames;

    function getTargetEditableElement(editableItemContainer) {
        var $nextEditableItem;
        var $nextEditableItemContainer = $('.box-container.edit-dialog:visible:first');
        if ($nextEditableItemContainer.length) {
            $nextEditableItem =
                layoutHelper.tabbing.getFirstElement($nextEditableItemContainer);
        } else {
            var $editableItemContainer = $(editableItemContainer);
            $nextEditableItem = $editableItemContainer.find('.item-edit-button:visible');
        }
        return $nextEditableItem;
    }

    function successSaveSectionNotification (e) {
        var $nextEditableItem = getTargetEditableElement(e.editableItemContainer);

        var notificationMessage = e.data.sectionName + ' section has been saved.';
        gJobs.screenReadersService.setAriaLiveNotification(notificationMessage);
        $nextEditableItem.focus();
    }

    function validationFailedOnSaveSectionNotification (e) {
        var $nextEditableItem = getTargetEditableElement(e.editableItemContainer); 

        var notificationMessage = 'Unable to save ' + e.data.sectionName +
            ' section.';

        gJobs.screenReadersService.setNotificationOnElement({
            text: notificationMessage,
            $element: $nextEditableItem
        });
    }

    function formOpeningNotification(e, data) {
        if (!data.isQuestionsItem && !data.editModeOnly) {
            var $firstFocusableElement = layoutHelper.tabbing.getFirstElement();

            var notificationMessage =
                (data.editEvent ? 'Edit ' : 'Add ') +
                e.data.sectionName +
                ' form has been opened.';
            
            gJobs.screenReadersService.setNotificationOnElement({
                text: notificationMessage,
                $element: $firstFocusableElement
            });
        }
    }

    function successRemoveEditableItemComplete(e, data) {
        var notificationMessage = e.data.sectionName + ' section item has been removed.';

        var $section = $('.onlineapp-app-container .tab-pane.active:visible');
        if (e.data.sectionId)
            $section = $section.find('#' + e.data.sectionId);
        var $focusableElement;

        var $sectionListItems = $section.find('ul li');
        if ($sectionListItems.length) {
            var index = e.index == $sectionListItems.length ? e.index - 1 : e.index;
            $focusableElement = $sectionListItems.eq(index).find('.item-edit-button');
        } else {
            $focusableElement = $section.find('.btn-add-resume-item');
        }

        gJobs.screenReadersService.setNotificationOnElement({
            text: notificationMessage,
            $element: $focusableElement
        });
    }

    ko.bindingHandlers.sectionNotification = {
        init: function (element, valueAccessor) {
            var sectionName = valueAccessor();
            var sectionId = $(element).closest('ul').parent().attr('id');
            $(document)
                .off(commonEventsNames.EditItemComplete, successSaveSectionNotification)
                .off(commonEventsNames.PreSaveValidationFailed, validationFailedOnSaveSectionNotification)
                .off(commonEventsNames.EditableItemBeginEdit, formOpeningNotification)
                .off(commonEventsNames.ItemRemoved, successRemoveEditableItemComplete)
                .on(commonEventsNames.EditItemComplete,
                    { sectionName: sectionName },
                    successSaveSectionNotification)
                .on(commonEventsNames.PreSaveValidationFailed,
                    { sectionName: sectionName },
                    validationFailedOnSaveSectionNotification)
                .on(commonEventsNames.EditableItemBeginEdit,
                    { sectionName: sectionName },
                    formOpeningNotification)
                .on(commonEventsNames.ItemRemoved,
                    { 
                        sectionName: sectionName,
                        sectionId: sectionId
                    },
                    successRemoveEditableItemComplete);
        }
    }

})(window);;
(function (window, undefined) {
    'use strict';

    var commonEventTypes = OnlineApp.Events.CommonEventsNames;

    var eventTypes = {
        edit: 'edit',
        add: 'add',
        cancel: 'cancel',
        save: 'save'
    }

    var eventOptions = {
        save: {
            metric4: 1,
            metric6: 1
        },
        add: {
            metric4: 1,
            metric5: 1
        },
        edit: {
            metric4: 1
        },
        cancel: {
            metric4: 1
        }
    }

    function sendGoogleAnalyticsEvent (e) {
        var options = e.data;

        var data = $.extend({ }, eventOptions[options.eventType]);

        if (options.data) {
            var optionsData = options.data;

            if (optionsData.schoolType) {
                data.dimension16 = optionsData.schoolType();
            }

            if (optionsData.licenceType) {
                data.dimension16 = optionsData.licenceType();
            }

            if (optionsData.positionTitle) {
                data.dimension15 = optionsData.positionTitle();
            }
        }

        gJobs.common.analytics.trackApplicationEvent({
            action: options.eventType,
            eventLabel: options.sectionCode,
            sendToAllTrackers: true,
            data: data
        });
    }

    function attachGoogleAnalyticsEventHandler (element, options) {
        $(element)
            .off('click', sendGoogleAnalyticsEvent)
            .on('click', options, sendGoogleAnalyticsEvent);
    } 

    ko.bindingHandlers.googleAnalyticsEvent = {
        init: function (element, valueAccessor) {
            var options = valueAccessor();
            if (options.sectionCode) {
                if (options.eventType == eventTypes.save) {
                    $(document)
                        .off(commonEventTypes.EditItemComplete, sendGoogleAnalyticsEvent)
                        .on(commonEventTypes.EditItemComplete, options, sendGoogleAnalyticsEvent);
                } else {
                    attachGoogleAnalyticsEventHandler(element, options);
                }
            }
        }
    }

})(window);;
(function(window, undefined) {
    'use strict';

    function BaseValidator() {
        var self = this;

        var defaultValidationOptions = {
            enabled: true
        };

        var checkEnabled = function(conditions) {
            var enabled = true;

            for (var i = 0; i < conditions.length; i++) {
                if ($.isFunction(conditions[i])) {
                    enabled = enabled && conditions[i]();
                } else {
                    enabled = enabled && ko.utils.unwrapObservable(conditions[i]);
                }
            }

            return enabled;
        };

        var normalizeValidationOptions = function(validationOptions) {
            var normalizedValidationOptions =
                $.extend({}, defaultValidationOptions, validationOptions);

            if (!$.isArray(normalizedValidationOptions.enabled)) {
                normalizedValidationOptions.enabled = [normalizedValidationOptions.enabled];
            }

            return normalizedValidationOptions;
        };


        self.isEnabled = function (validationOptions) {
            validationOptions = normalizeValidationOptions(validationOptions);
            return checkEnabled(
                validationOptions.enabled
            );
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        BaseValidator: BaseValidator
    });


})(window);;
(function (window, undefined) {
    'use strict';

    function RegularExpressionValidator() {
        
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        self.validate = function(value, validationOptions) {
            var isValid = true;
            
            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            if (value != undefined && value !== "") {
                if (validationOptions && validationOptions.pattern) {
                    isValid = validationOptions.pattern.test(value);
                }
            }

            return isValid;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        regularExpressionValidator: new RegularExpressionValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function EmailValidator() {
        var self = this;

        var emailRegExp = /^['_a-zA-Z0-9-+]+(\.['_a-zA-Z0-9-+]+)*@[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+)*\.(([a-zA-Z]+))$/;
        
        self.validate = function(value, validationOptions) {
            validationOptions.pattern = emailRegExp;
            return OnlineApp.Validation.regularExpressionValidator.validate(value, validationOptions);
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        emailValidator: new EmailValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function ConfirmFieldValidator() {
        var self = this;

        self.validate = function (value, validationOptions) {
            return value === validationOptions.fieldToConfirm();
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        confirmFieldValidator: new ConfirmFieldValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function timespanStartIsNotAfterEndValidator() {
        var self = this;

        self.validate = function (value, validationOptions) {
            var startMonth = parseInt(validationOptions.startMonth());
            var startYear = parseInt(validationOptions.startYear());
            var endMonth = parseInt(validationOptions.endMonth());
            var endYear = parseInt(validationOptions.endYear());

            startMonth = startMonth || 1;       //startMonth and endMonth can be not selected, so
            endMonth = endMonth || 12;          //startMonth default value is the first month of the year
                                                //and endMonth default value is the last month of the year

            var yearFieldsAreNonZeroNumbers = startYear && endYear;
            if (!yearFieldsAreNonZeroNumbers) {
                return true;
            }

            var endMonthIsNotSpecialCase = endMonth >= 1 && endMonth <= 12;     //don't validate if endMonth is special case (e.g. Present, No expiration)
            if (!endMonthIsNotSpecialCase) {
                return true;
            }

            var isStartDateBeforeOrEqualEndDate = new Date(startYear, startMonth - 1) <= new Date(endYear, endMonth - 1);

            return isStartDateBeforeOrEqualEndDate;
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        timespanStartIsNotAfterEndValidator: new timespanStartIsNotAfterEndValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function isNotFutureDateValidator() {
        var self = this;

        self.validate = function (value, validationOptions) {
            var month = parseInt(validationOptions.month());
            var year = parseInt(validationOptions.year());

            if (!year) { return true; }

            month = month || 1;       //startMonth can be not selected, so default value is the first month of the year

            var isFutureDate = new Date(year, month - 1) > Date.now();

            return !isFutureDate;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        isNotFutureDateValidator: new isNotFutureDateValidator()
    });

})(window);
;
(function (window, undefined) {
    'use strict';

    function validate(value) {
        //all changes must be  applied on server side PasswordValidator.cs
        var isLongEnough = value.length >= 12;
        var hasLetter = (/[a-z]+/.test(value));
        var hasDigit = (/[0-9]+/.test(value));
        var hasUpperCaseLetter = (/[A-Z]+/.test(value));
        var hasNonAlphaNumericChars = (/[\W]+/.test(value));
        return isLongEnough && hasLetter && hasDigit && hasUpperCaseLetter && hasNonAlphaNumericChars;
    }

    //exposed solely for unit testing purposes (PasswordValidatorTests.js)
    window.UnitTestsPasswordValidatorValidate = validate;

    function passwordValidator() {
        var self = this;

        self.validate = function (value) {
            return validate(value);
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        passwordValidator: new passwordValidator()
    });
})(window);;
(function (window, undefined) {
    'use strict';

    function RequiredValidator() {
        
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;


        var defaultValidationOptions = {
            onlyIf: function () { return true; }
        };

        var normalizeValidationOptions = function (validationOptions) {
            var normalizedValidationOptions =
                $.extend({}, defaultValidationOptions, validationOptions);

            return normalizedValidationOptions;
        };


        self.validate = function (value, validationOptions) {

            validationOptions = normalizeValidationOptions(validationOptions);


            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            if (!validationOptions.onlyIf()) {
                return true;
            }

            if (typeof value === 'number') {
                return true;
            }

            if ($.isArray(value) && value.length === 0) {
                return false;
            }

            if (typeof value === 'string' && $.trim(value).length === 0) {
                return false;
            }

            return (!!value);
        };

    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        requiredValidator: new RequiredValidator()
    });

})(window);;
(function(window, undefined) {
    'use strict';

    function RequiredFieldValidator() {
        
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        self.validate = function (value, validationOptions) {
            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            var objectValue = ko.unwrap(validationOptions.objectField),
                subjectValue = ko.unwrap(validationOptions.subjectField);

            if (objectValue) {
                return OnlineApp.Validation.requiredValidator.validate(
                    subjectValue,
                    validationOptions);
            }

            return true;
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        requiredFieldValidator: new RequiredFieldValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function NumericValidator() {
        
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        var integerRegExp = /^\d+$/;
        var floatRegExp = /^(\d*[.])?\d+$/;

        self.validate = function (value, validationOptions) {

            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            if (typeof value !== 'number' && !value) {
                return true;
            }


            validationOptions.pattern = validationOptions.allowFloat === true ? floatRegExp : integerRegExp;

            var isValid = OnlineApp.Validation.regularExpressionValidator.validate(value, validationOptions);

            var numericValue = Number(value);

            if (validationOptions.min != null) {
                isValid = isValid && (numericValue >= validationOptions.min);
            }

            if (validationOptions.max != null) {
                isValid = isValid && (numericValue <= validationOptions.max);
            }

            return isValid;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        numericValidator: new NumericValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function YearValidator() {
        var self = this;

        var yearRegExp = /^[1-9][0-9]{3}$/;


        self.validate = function (value, validationOptions) {
            validationOptions.pattern = yearRegExp;
            return OnlineApp.Validation.regularExpressionValidator.validate(value, validationOptions);
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        yearValidator: new YearValidator()
    });

})(window);
;
(function (window, undefined) {
    'use strict';

    function MonthValidator() {
        var self = this;

        self.validate = function (value, validationOptions) {
            if (value) {
                if (OnlineApp.ViewModels.applicationViewModel.definitionsViewModel) {
                    return OnlineApp.ViewModels.applicationViewModel.definitionsViewModel
                        .month.findItemById(value).hasOwnProperty('id');
                }

                //use server validation if definitions vm is unavailable
                return true;
            }
            
            return true;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        monthValidator: new MonthValidator()
    });

})(window);
;
(function (window, undefined) {
    'use strict';

    function ExtendedMonthValidator() {
        var self = this;

        self.validate = function (value, validationOptions) {
            if (value) {
                if (OnlineApp.ViewModels.applicationViewModel.definitionsViewModel) {
                    return OnlineApp.ViewModels.applicationViewModel.definitionsViewModel
                        .extendedMonth.findItemById(value).hasOwnProperty('id');
                }

                //use server validation if definitions vm is unavailable
                return true;
            }
            
            return true;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        extendedMonthValidator: new ExtendedMonthValidator()
    });

})(window);
;
(function (window, undefined) {
    'use strict';

    function VerificationCodeValidator() {
        var VERIFICATION_CODE_LENGTH = 6;
        
        var self = this;

        self.validate = function (value, validationOptions) {
            var validatableValue = value;

            if (validationOptions.regExpForValueTransform) {
                var charsForReplace = "";

                if (validationOptions.charsForReplace) {
                    charsForReplace = validationOptions.charsForReplace;
                }

                validatableValue = validatableValue.replace(validationOptions.regExpForValueTransform, charsForReplace);
            }

            return validatableValue.length === VERIFICATION_CODE_LENGTH ? true : false;
        }
    }

    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        verificationCodeValidator: new VerificationCodeValidator()
    });

})(window);
;
(function (window, undefined) {
    'use strict';

    function MonthWithNoExpirationValidator() {
        var self = this;

        self.validate = function (value, validationOptions) {
            if (value) {
                if (OnlineApp.ViewModels.applicationViewModel.definitionsViewModel) {
                    return OnlineApp.ViewModels.applicationViewModel.definitionsViewModel
                        .monthWithNoExpiration.findItemById(value).hasOwnProperty('id');
                }

                //use server validation if definitions vm is unavailable
                return true;
            }
            
            return true;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        monthWithNoExpirationValidator: new MonthWithNoExpirationValidator()
    });

})(window);
;
(function (window, undefined) {
    'use strict';

    function MaxValueValidator() {
        var self = this;

        self.validate = function (value, validationOptions) {
            if (!value)
                return true;
            
            if (isNaN(value))
                return false;
            
            validationOptions = validationOptions || {};
            var numericValue = parseInt(value);
            return numericValue <= validationOptions.maxValue;
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        maxValueValidator: new MaxValueValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function LengthValidator() {

        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        self.validate = function (value, validationOptions) {
            
            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            if (typeof value === 'number') {
                value = String(value);
            }
            else if (value == null) {
                value = "";
            }


            var valueLength = value.length;
            var isValid = true;

            validationOptions = validationOptions || {};

            if (validationOptions.min != null) {
                isValid = isValid && (valueLength >= validationOptions.min);
            }

            if (validationOptions.max != null) {
                isValid = isValid && (valueLength <= validationOptions.max);
            }

            return isValid;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        lengthValidator: new LengthValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function AlphaNumericWithUnderscoreValidator() {
        var self = this;

        var alphaNumericWithUnderscoreRegex = /^[a-z0-9_]*$/i;


        self.validate = function(value, validationOptions) {
            validationOptions.pattern = alphaNumericWithUnderscoreRegex;
            return OnlineApp.Validation.regularExpressionValidator.validate(value, validationOptions);
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        alphaNumericWithUnderscoreValidator: new AlphaNumericWithUnderscoreValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function UrlValidator() {
        var self = this;

        var urlRegExp = /^(http(s)?:\/\/)?([\w-]+\.)+[\w-]+(\/[\w- ;,./?%&=]*)?$/;


        self.validate = function (value, validationOptions) {
            if (!value) {
                return true;
            }

            validationOptions.pattern = urlRegExp;
            return OnlineApp.Validation.regularExpressionValidator.validate(value, validationOptions);
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        urlValidator: new UrlValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function ZipValidator() {
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        var zipRegExpUs = /^\d{5}(-\d{4})?$/;
        var zipRegExpCanada =
            /^([ABCEGHJKLMNPRSTVXY][0-9][ABCEGHJKLMNPRSTVWXYZ])\ ?([0-9][ABCEGHJKLMNPRSTVWXYZ][0-9])$/;

        var usCode = 1;
        var canadaCode = 39;

        var defaultValidationOptions = {
            onlyIf: function () { return true; }
        };

        var normalizeValidationOptions = function (validationOptions) {
            var normalizedValidationOptions =
                $.extend({}, defaultValidationOptions, validationOptions);

            return normalizedValidationOptions;
        };

        self.validate = function (value, validationOptions) {
            if (!value) {
                return true;
            }

            validationOptions = normalizeValidationOptions(validationOptions);

            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            if (!validationOptions.onlyIf()) {
                return true;
            }

            if (validationOptions && validationOptions.countryId && validationOptions.countryId()) {
                var isUs = validationOptions.countryId() === usCode;
                var isCanada = validationOptions.countryId() === canadaCode;

                if (!isUs && !isCanada) {
                    return true;
                }

                validationOptions.pattern = isUs ? zipRegExpUs : zipRegExpCanada;
                return OnlineApp.Validation.regularExpressionValidator.validate(value, validationOptions);
            }

            return true;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        zipValidator: new ZipValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function PhoneValidator() {
        
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        var phoneRegExp = /^[01]?[- .]?(\([2-9]\d{2}\)|[2-9]\d{2})[- .]?\d{3}[- .]?\d{4}$/i;

        self.validate = function (value, validationOptions) {
            
            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            validationOptions.pattern = phoneRegExp;
            if (validationOptions && validationOptions.countryID && validationOptions.countryID() == 1) {
                return OnlineApp.Validation.regularExpressionValidator.validate(value, validationOptions);
            }
            return true;
        };
    }
    
    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        phoneValidator: new PhoneValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function StateValidator() {
        
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        self.validate = function (value, validationOptions) {
            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            if (!validationOptions.onlyIf()) {
                return true;
            }

            if (validationOptions && validationOptions.countryId && validationOptions.countryId()) {
                var state = validationOptions.states.filter(function(s) { return s.id === value })[0];

                return state && 
                    ((state.countryId === 0 && validationOptions.countryId() !== 1 && validationOptions.countryId() !== 39) ||
                        state.countryId === validationOptions.countryId());
            }
            return true;
        };
    }
    
    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        stateValidator: new StateValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function SsnValidator() {
        
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        // ONLINE-4287: https://stackoverflow.com/a/1517044

        var ssnRegex =
            /^(?!(000|666))[0-8]{1}[0-9]{2}-(?!00)[0-9]{2}-(?!0000)[0-9]{4}$/;
        var ssnLength = {
            max: 11
        };
        
        self.validate = function (value, validationOptions) {
            
            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            validationOptions.length = ssnLength;
            validationOptions.pattern = ssnRegex;

            var isValid = true;
            isValid = isValid
                && OnlineApp.Validation.regularExpressionValidator.validate(value, validationOptions)
                && OnlineApp.Validation.lengthValidator.validate(value, validationOptions);

            if (OnlineApp.ViewModels.applicationViewModel.definitionsViewModel &&
                OnlineApp.ViewModels.applicationViewModel.definitionsViewModel.invalidSsnValues) {                
                isValid = isValid
                    && OnlineApp.ViewModels.applicationViewModel.definitionsViewModel.invalidSsnValues.indexOf(value) === -1;
            }
            return isValid;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        ssnValidator: new SsnValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function ServerSsnValidator() {
        
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        self.validate = function (value, validationOptions) {
            
            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            var isSsnValid = ko.utils.unwrapObservable(validationOptions.isSsnValid);

            var isValid = true;

            isValid = isValid && isSsnValid;

            return isValid;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        serverSsnValidator: new ServerSsnValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function SalaryValidator() {
        
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        var salaryRegex = /^\$?\d{1,15}(,?\d{1,3})*(\.\d{1,2})?\$?$/;
        var salaryLength = {
            max: 22
        };
        var MAX_SALARY_VALUE = 100000000000000;

        self.validate = function (value, validationOptions) {
            
            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            validationOptions.pattern = salaryRegex;
            validationOptions.length = salaryLength;

            var isValid = true;
            isValid = isValid && OnlineApp.Validation.regularExpressionValidator.validate(value, validationOptions);
            isValid = isValid && OnlineApp.Validation.lengthValidator.validate(value, validationOptions.length);

            if (value != undefined && value !== "") 
            {
                isValid = isValid && MAX_SALARY_VALUE > +(value.replace(/,/g, '').replace('$', ''));
            }

            return isValid;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        salaryValidator: new SalaryValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function DefinitionAwareValueValidator() {
        var self = this;

        self.validate = function (value, validationOptions) {
            if (!value) {
                return true;
            }

            var items = ko.unwrap(validationOptions.definitionItems) || [];
            var fieldName = ko.unwrap(validationOptions.definitionFieldName) || 'id';

            var matchingItems = $.grep(items, function (item) {
                return item[fieldName] == value;
            });

            return matchingItems.length;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        definitionAwareValueValidator: new DefinitionAwareValueValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function DeferredDefinitionAwareValueValidator() {
        var self = this;

        self.validate = function (value, validationOptions) {
            var deferredDefinitionViewModel = validationOptions.deferredDefinitionViewModel;
            var items = ko.unwrap(deferredDefinitionViewModel.items);
            var fieldName = ko.unwrap(validationOptions.definitionFieldName) || 'id';

            if (!value || deferredDefinitionViewModel.get().state() === 'pending') {
                return true;
            }

            var matchingItems = $.grep(items, function (item) {
                return item[fieldName] == value;
            });

            return matchingItems.length;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        deferredDefinitionAwareValueValidator: new DeferredDefinitionAwareValueValidator()
    });

})(window);
;
(function (window, undefined) {
    'use strict';

    // Thanks to author of : https://github.com/iHwy/jQuery-Validation-Extension
    function mod10Check(number){
        var checksum = 0,
            j = 1, i;

        var calc;
        for (i = number.length - 1; i >= 0; i--) {
            calc = Number(number.charAt(i)) * j;
            if (calc > 9) {
                checksum = checksum + 1;
                calc = calc - 10;
            }

            checksum = checksum + calc;

            if (j == 1) {
                j = 2;
            } else {
                j = 1;
            };
        }

        if (checksum % 10 != 0) {
            // not mod-10
            return false;
        } else
            return true;
    }

    function CreditCardNumberValidator() {
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        //dictionary of regular expresisons for credit card types
        var creditCardNumbersRegularExpressions = [];
        //add American Express Credit Card Number regular expression
        creditCardNumbersRegularExpressions[1] = /^(?:3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11})$/;
        //add Discover Credit Card Number regular expression
        creditCardNumbersRegularExpressions[2] = /^(?:6(?:011|5[0-9][0-9])[0-9]{12})$/;
        //add MasterCard Credit Card Number regular expression
        creditCardNumbersRegularExpressions[3] = /^(?:5[1-5][0-9]{14})$/;
        //add Visa Credit Card Number regular expression
        creditCardNumbersRegularExpressions[4] = /^(?:4[0-9]{15})$/;

        self.validate = function (value, validationOptions) {
            var isValid = true;

            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            var currentCardType = ko.unwrap(validationOptions.cardType),
                filteredNumber = value.replace(/[\s-]/g, ""); // removing spaces and dashes

            if (currentCardType != null && creditCardNumbersRegularExpressions[currentCardType] != null) {
                validationOptions.pattern = creditCardNumbersRegularExpressions[currentCardType];
                isValid = OnlineApp.Validation.regularExpressionValidator.validate(filteredNumber, validationOptions);
            }

            if (isValid) {
                isValid = mod10Check(filteredNumber);
            }

            return isValid;
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        creditCardNumberValidator: new CreditCardNumberValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function CsvValidator() {
        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        var americanExpressCsvRegularExpression = /^(?:[0-9]{4})$/,
            threeCharsCsvRegularExpression = /^(?:[0-9]{3})$/;

        self.validate = function (value, validationOptions) {
            var isValid = true;

            if (!self.isEnabled(validationOptions)) {
                return true;
            }

            var currentCardType = ko.unwrap(validationOptions.cardType);

            if (currentCardType != null) {
                if (currentCardType == 1) {
                    validationOptions.pattern = americanExpressCsvRegularExpression;
                } else {
                    validationOptions.pattern = threeCharsCsvRegularExpression;
                }

                isValid = isValid && OnlineApp.Validation.regularExpressionValidator.validate(value, validationOptions);
            }

            return isValid;
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        csvValidator: new CsvValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function DisallowHtmlValidator() {

        var self = OnlineApp.Validation.BaseValidator.apply(this, arguments) || this;

        var xssRegex = /<[a-zA-Z]+/;

        self.validate = function (value, validationOptions) {
            validationOptions.pattern = xssRegex;
            
            if (!value){
                return true;
            }

            return !OnlineApp.Validation.regularExpressionValidator.validate(value, validationOptions);
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        disallowHtmlValidator: new DisallowHtmlValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function CompositeValidator() {
        var self = this;

        self.validate = function(value, validationOptions) {

            var validatorDefinition = validationOptions.validators;
            var validators = Object.keys(validatorDefinition).map(function(validatorDefinition) {
                var validatorExtension = OnlineApp.Validation.validationExtensions[validatorDefinition];
                var validatorOptions = $.extend({}, validatorExtension.defaultOptions, validatorDefinition.validatorOptions);
                return {
                    validate: validatorExtension.validator.validate, 
                    validatorOptions: validatorOptions 
                };
            });

            var isValid = false;

            if (validationOptions.operator === 'and'){
                isValid = validators.every(function(validator) {
                    return validator.validate(value, validator.validatorOptions);
                });
            }
            else {
                isValid = validators.some(function(validator) {
                    return validator.validate(value, validator.validatorOptions);
                });
            }

            return isValid;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        compositeValidator: new CompositeValidator()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    /*
        Registration of actual extensions.
    */
    var VALIDATION_MESSAGES = {
        required: "Error: This field is required",
        invalidEmail: "Email is invalid",
        invalidTwoStepVerificationCode: "Invalid code",
        invalidEmailVerificationCode: "Invalid verification code",
        invalidPassword: "Invalid password",
        invalidUrl: "Invalid url address",
        invalidNumeric: "Value is not a valid number",
        invalidZip: "Invalid Zip/Postal Code",
        invalidLength: "The text is too long",
        invalidSsn: "Invalid Social Security Number",
        invalidSalary: 'Invalid Salary',
        invalidConfirmation: 'Fields do not match',
        invalidPhone: 'Invalid phone number',
        invalidYear: 'Invalid year',
        invalidMonth: 'Invalid month',
        invalidCreditCardNumber: 'Invalid Credit Card Number',
        invalidCsv: 'Invalid CVV',
        invalidDefinitionValue: 'Value is invalid',
        containHtml: 'Field can\'t contain html tags',
        state: 'State is invalid',
        captchaInvalidMessage: "Captcha is invalid",
        invalidClassSpecificationsSearchString: "Please select a "
    };


    var extensions = {
        required: {
            validator: OnlineApp.Validation.requiredValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.required
            }
        },
        regexp: {
            validator: OnlineApp.Validation.regularExpressionValidator
        },
        email: {
            validator: OnlineApp.Validation.emailValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidEmail
            }
        },
        verificationCode: {
            validator: OnlineApp.Validation.verificationCodeValidator,
            defaultOptions: {
                isValidationMessageVisible: false
            }
        },
        confirmField: {
            validator: OnlineApp.Validation.confirmFieldValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidConfirmation
            }
        },
        requiredField: {
            validator: OnlineApp.Validation.requiredFieldValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.required
            }
        },
        timespanStartIsNotAfterEnd: {
            validator: OnlineApp.Validation.timespanStartIsNotAfterEndValidator,
            defaultOptions: {
                isValidationMessageVisible: false
            }
        },
        isNotFutureDate: {
            validator: OnlineApp.Validation.isNotFutureDateValidator,
            defaultOptions: {
                isValidationMessageVisible: false
            }
        },
        password: {
            validator: OnlineApp.Validation.passwordValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidPassword
            }
        },
        url: {
            validator: OnlineApp.Validation.urlValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidUrl
            }
        },
        zip: {
            validator: OnlineApp.Validation.zipValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidZip
            }
        },
        numeric: {
            validator: OnlineApp.Validation.numericValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidNumeric
            }
        },
        length: {
            validator: OnlineApp.Validation.lengthValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidLength
            }
        },
        year: {
            validator: OnlineApp.Validation.yearValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidYear
            }
        },
        month: {
            validator: OnlineApp.Validation.monthValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidMonth
            }
        },
        extendedMonth: {
            validator: OnlineApp.Validation.extendedMonthValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidMonth
            }
        },
        monthWithNoExpiration: {
            validator: OnlineApp.Validation.monthWithNoExpirationValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidMonth
            }
        },
        alphaNumericWithUnderscore: {
            validator: OnlineApp.Validation.alphaNumericWithUnderscoreValidator
        },
        ssn: {
            validator: OnlineApp.Validation.ssnValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidSsn
            }
        },
        serverSsn: {
            validator: OnlineApp.Validation.serverSsnValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidSsn
            }
        },
        salary: {
            validator: OnlineApp.Validation.salaryValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidSalary
            }
        },
        maxValue: {
            validator: OnlineApp.Validation.maxValueValidator,
            defaultOptions: {}
        },
        phone: {
            validator: OnlineApp.Validation.phoneValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidPhone
            }
        },
        creditCardNumber: {
            validator: OnlineApp.Validation.creditCardNumberValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidCreditCardNumber
            }
        },
        csv: {
            validator: OnlineApp.Validation.csvValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidCsv
            }
        },
        definitionAwareValue: {
            validator: OnlineApp.Validation.definitionAwareValueValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidDefinitionValue
            }
        },
        deferredDefinitionAwareValue: {
            validator: OnlineApp.Validation.deferredDefinitionAwareValueValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.invalidDefinitionValue
            }
        },
        disallowHtml: {
            validator: OnlineApp.Validation.disallowHtmlValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.containHtml
            }
        },
        composite: {
            validator: OnlineApp.Validation.compositeValidator,
            defaultOptions: {}
        },
        state: {
            validator: OnlineApp.Validation.stateValidator,
            defaultOptions: {
                validationMessage: VALIDATION_MESSAGES.state
            }
        }
    };


    var validationExtender = new OnlineApp.Extensions.Knockout.KnockoutValidationExtender();
    validationExtender.registerExtensions(extensions);

    OnlineApp.Namespace.extend('OnlineApp.Validation', {
        validationExtensions: extensions,
        validationMessages: VALIDATION_MESSAGES
    });

})();
;
(function (window, undefined) {
    'use strict';

    function TabIndexService() {

        var self = this;

        var dataSaveTabIndex = 'save-tab-index',
            $skipToContentButton = $('#skip-to-content-button');

        var getSettings = function(settings) {
            settings = settings || {};

            if (settings.containerSelector) {
                settings.containerSelector = settings.containerSelector;
            } else {
                settings.containerSelector = gJobs.areaInfoService && gJobs.areaInfoService.getCurrentArea() === gJobs.areaInfoService.areaNames.Career 
                    ? "#main-container" 
                    : '#body-container, #main-container,'
                    + '#footer, #footer-new, #sjobs-footer-new, .new-job-flyout, #skip-to-content-button,'
                        + '#last-focusable-element, #cookie-consent';
            }

            settings.tabIndexElementsSelector = settings.tabIndexElementsSelector || ':focusable, iframe';
            settings.useVisibilityFilter = settings.useVisibilityFilter || true;
            settings.hideSkipButton = settings.hideSkipButton || false; 

            return settings;
        };

        self.disableTabIndex = function (settings) {
            settings = getSettings(settings);

            var tabIndexElements = $(settings.containerSelector).find(settings.tabIndexElementsSelector);

            if (settings.useVisibilityFilter) {
                tabIndexElements = tabIndexElements.filter(':visible');
            }

            if (settings.hideSkipButton) {
                tabIndexElements = $skipToContentButton.add(tabIndexElements);
            }

            tabIndexElements.each(function () {
                var element = $(this);

                var savedTabIndex = element.data(dataSaveTabIndex);
                if (savedTabIndex) {
                    return;
                }

                var tabIndex = element.attr('tabindex');

                if (tabIndex) {
                    element.data(dataSaveTabIndex, tabIndex);
                }

                element.attr("tabindex", -1);
            });
        };

        self.restoreTabIndex = function (settings) {
            settings = getSettings(settings);

            var tabIndexElements = $(settings.containerSelector).find(settings.tabIndexElementsSelector);

            if (settings.useVisibilityFilter) {
                tabIndexElements = tabIndexElements.filter(':visible');
            }

             var firstElement = tabIndexElements.get(0);

            tabIndexElements = $skipToContentButton.add(tabIndexElements);

            tabIndexElements.each(function () {
                var element = $(this);

                var tabIndex = element.data(dataSaveTabIndex);

                if (tabIndex) {
                    element.attr("tabindex", tabIndex);
                    element.removeData(dataSaveTabIndex);
                } else if (!element.is($skipToContentButton)) {
                    element.removeAttr("tabindex");
                }
            });

            if (firstElement) {
                firstElement.focus();
            }
        };

    }

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        tabIndexService: new TabIndexService()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    var ANTIFORGERY_ID = '__RequestVerificationToken';
    var API_URL_PREFIXES = ['/api/', '/user/'];

    var inputSelector = 'input[name="' + ANTIFORGERY_ID + '"]';

    function AntiForgeryService() {
        var self = this;

        self.updateToken = function () {
            return $.ajax({
                type: 'GET',
                url: '/antiForgery/updateToken',
                cache: false,
                success: function (data) {
                    var newToken = $(data).val();
                    $(inputSelector).val(newToken);
                }
            });
        };
    };

    AntiForgeryService.setupAjax = function () {
        var isMethodCsrfSafe = function (method) {
            return (/^(GET|HEAD|OPTIONS|TRACE)$/.test(method));
        };
        var isUrlSafe = function (url) {
            for (var i = 0; i < API_URL_PREFIXES.length; ++i) {
                if (url.indexOf(API_URL_PREFIXES[i]) === 0) {
                    return false;
                }
            }
            return true;
        };
        var extractAntiForgeryToken = function () {
            return $(inputSelector).val();
        };
        $.ajaxSetup({
            beforeSend: function (jqXhr, settings) {
                if (!isMethodCsrfSafe(settings.type) && settings.url && !isUrlSafe(settings.url)) {
                    var antiForgeryToken = extractAntiForgeryToken();
                    jqXhr.setRequestHeader(ANTIFORGERY_ID, antiForgeryToken);
                }
            }
        });
    };

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        antiForgeryService: new AntiForgeryService()
    });

    AntiForgeryService.setupAjax();

})(window);;
(function (window, undefined) {


    function AuthenticationService() {
        var self = this;

        /* private urls */
        var isLoggedInUrl = '/api/authenticate/isLoggedIn',
            loginUrl = '/api/authenticate/login',
            logoutUrl = '/api/authenticate/logout',
            registerUrl = '/api/authenticate/register',
            confirmExternalLoginUrl = '/oauth/confirmCredentials',
            isEmailAllowedUrl = '/api/authenticate/isEmailAllowed',
            getUserDataUrl = '/api/authenticate/getUserData',
            getAppSettingsUrl = '/api/applicationTemplate/GetAppSettings',
            getAllResumeTemplatesForJobSeekerUrl = '/api/applicationTemplate/GetAllResumeTemplatesForJobSeeker',
            canApplyForJobUrl = '/api/applicationTemplate/CanApplyForJob',
            checkEmployeeIdUrl = '/api/applicationTemplate/CheckEmployeeId';

        /* urls to be overridden from outer script */
        self.getHtmlTemplatesUrl = '/api/htmlTemplates/GetApplicationTemplates';
        self.getAccountSettingsPageHtmlTemplatesUrl = '/api/accountSettings/GetAccountSettingsPageTemplates';

        var isLoggedInCachedRequest = new gJobs.CachedAjaxRequest({
            type: 'GET',
            cache: false,
            url: isLoggedInUrl
        });

        var getUserDataCachedRequest = new gJobs.CachedAjaxRequest({
            type: 'GET',
            cache: false,
            url: getUserDataUrl
        });

        /* public methods */

        self.getUserData = function () {
            return getUserDataCachedRequest.send();
        }

        self.isLoggedIn = function () {
            return isLoggedInCachedRequest.send();
        };

        //Accepts either username or email address for login.
        self.login = function (username, password, captchaAnswer, options) {
            $(".form-signin").find("button[type=submit]").attr("aria-hidden", true);
            return $.ajax({
                type: 'POST',
                url: loginUrl,
                data: $.extend({
                    username: username,
                    password: password,
                    captchaAnswer: captchaAnswer,
                    returnUrl: self.getCurrentUrl()
                }, options)
            }).then(function (data) {
                isLoggedInCachedRequest.resetCache();
                return OnlineApp.Services.antiForgeryService.updateToken().then(function () {
                    return data;
                });
            });
        };

        self.logout = function (options) {
            var deffered = $.Deferred();
            sessionStorage.removeItem("isTermsDeclined");
            localStorage.removeItem("isPopupOpen");
            localStorage.removeItem("istermsAndPrivacyPolicyDialogContainer");
            $.ajax({
                type: 'POST',
                url: logoutUrl,
                success: function (response) {
                    var data = response.data;

                    var isExternalLogin,
                        providerName;

                    if (data.isUserDeleted) {
                        isExternalLogin = options.isExternalLogin;
                        providerName = options.providerName;
                    }
                    else {
                        isExternalLogin = data.isExternalLogin;
                        providerName = data.providerName;
                    }

                    if (!isExternalLogin) {
                        deffered.resolve();

                        return;
                    }

                    switch (providerName) {
                        case 'Facebook':
                            FB.getLoginStatus(function facebookLogoutCallback(facebookResponse) {
                                if (facebookResponse.status !== 'connected') {
                                    deffered.resolve();

                                    return;
                                }

                                FB.logout(facebookLogoutCallback);
                            });

                            break;
                        default:
                            deffered.resolve();
                            break;
                    }
                }
            });

            removeItemFromLocalStorage("updatedEmail");
            removeItemFromLocalStorage(OnlineApp.LocalStorageKeys.EmailWasChanged);
            removeItemFromLocalStorage(OnlineApp.LocalStorageKeys.EmailWasChangedAndNewVerificationCodeSent);
            removeItemFromLocalStorage(OnlineApp.LocalStorageKeys.EmailWasVerified);
            removeItemFromSessionStorage(OnlineApp.SessionKeys.IsBannerWasClosedInCurrentSession);
            removeItemFromSessionStorage(OnlineApp.SessionKeys.ApplicationProcessUrl);
            isLoggedInCachedRequest.resetCache();
            return deffered;
        };

        self.register = function (username, password, email, captchaAnswer, options) {
            return $.ajax({
                type: 'POST',
                url: registerUrl,
                data: $.extend({
                    username: username,
                    password: password,
                    email: email,
                    captchaAnswer: captchaAnswer,
                    registrationLimitKey: localStorage.getItem("registrationLimitKey"),
                    returnUrl: self.getCurrentUrl()
                }, options)
            }).then(function (data) {
                return OnlineApp.Services.antiForgeryService.updateToken().then(function () {
                    return data;
                });
            });
        };

        self.confirmExternalLogin = function (username, password) {
            return $.ajax({
                type: 'POST',
                url: confirmExternalLoginUrl,
                data: {
                    username: username,
                    password: password
                }
            }).then(function (data) {
                return OnlineApp.Services.antiForgeryService.updateToken().then(function () {
                    return data;
                });
            });
        };

        self.isEmailAllowed = function (data) {
            return $.ajax({
                type: 'POST',
                url: isEmailAllowedUrl,
                data: data
            });
        };

        self.getUserData = function (resetCache) {
            if (resetCache) {
                getUserDataCachedRequest.resetCache();
            }
            return getUserDataCachedRequest
                .send()
                .then(function (response) {

                    var showAccessMembershipDialog = function () {
                        $(document).trigger(
                            Events.CommonEventsNames.ShowAccessMembershipDialog
                        );
                    }

                    var showTermsAndPrivacyPolicyDialog = function (closeCallBack) {
                        $(document).trigger(
                            Events.CommonEventsNames.ShowTermsAndPrivacyPolicyAnnouncement,
                            { closeCallback: closeCallBack }
                        );
                    }

                    var pageInfoService = AgencyPages.pageInfoService ? AgencyPages.pageInfoService : gJobs.pageInfoService;
                    var currentPage = pageInfoService.getCurrentPageType();
                    var isOnAccessMembershipLandingPage = currentPage === pageInfoService.getPageTypes().accessMembershipLandingPage;

                    if (isOnAccessMembershipLandingPage &&
                        response.data.showAccessMembership &&
                        !response.data.showTermsAndPrivacyPolicyAnnouncement) {
                        return response.data;
                    }
                    else if (response.data.showTermsAndPrivacyPolicyAnnouncement && response.data.showAccessMembership) {
                        showTermsAndPrivacyPolicyDialog(showAccessMembershipDialog);
                    } else if (response.data.showTermsAndPrivacyPolicyAnnouncement) {
                        showTermsAndPrivacyPolicyDialog();
                    } else if (response.data.showAccessMembership) {
                        showAccessMembershipDialog();
                    }

                    return response.data;
                });
        }

        self.getAppSettings = function (id) {
            return $.ajax({
                type: 'GET',
                url: getAppSettingsUrl,
                cache: false,
                data: { jobId: id }
            });
        };

        self.getAllResumeTemplatesForJobSeeker = function () {
            return $.ajax({
                type: 'GET',
                url: getAllResumeTemplatesForJobSeekerUrl,
                cache: false
            });
        };

        self.canApplyForJob = function (id) {
            return $.ajax({
                type: 'GET',
                url: canApplyForJobUrl,
                cache: false,
                data: { jobId: id }
            });
        };

        self.checkEmployeeId = function (id, employerFolderName) {
            return $.ajax({
                type: 'GET',
                url: checkEmployeeIdUrl,
                cache: false,
                data: {
                    employeeId: id,
                    employerFolderName: employerFolderName
                }
            });
        };

        self.getHtmlTemplates = function () {
            return $.ajax({
                type: 'GET',
                url: self.getHtmlTemplatesUrl,
                cache: true
            });
        };

        self.getAccountSettingsPageHtmlTemplates = function () {
            return $.ajax({
                type: 'GET',
                url: self.getHtmlTemplatesUrl,
                cache: true
            });
        };

        self.getCurrentUrl = function () {
            var currentUrl = encodeURIComponent(window.location.href);

            if (window.location.hash) {
                currentUrl = encodeURIComponent(window.location.href.split('#')[0]);
            }

            return currentUrl;
        };
    };

    function removeItemFromLocalStorage(key) {
        localStorage.removeItem(key);
    }

    function removeItemFromSessionStorage(key) {
        sessionStorage.removeItem(key);
    }

    OnlineApp.Namespace.extend('OnlineApp.Services.Test', {
        AuthenticationService: AuthenticationService
    });

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        authenticationService: new AuthenticationService()
    });

})(window);;
(function (window, undefined) {    
    'use strict';
    function EmailVerificationService() {
        var self = this;
                 
        var emailVerificationUrl = '/api/emailverification/verify',
            resendEmailVerificationCodeUrl = '/api/emailverification/resendEmail',
            getUserDataUrl = '/api/emailverification/getUserData',
            getRedirectLinkForSuccessfullEmailVerificationUrl = '/api/emailVerification/getRedirectLinkForSuccessfullEmailVerification',
            isEmailVerifiedUrl = '/api/emailVerification/isEmailVerified',
            trySendEmailVerificationCodeUrl = '/api/emailVerification/TrySendEmail',
            deactivateEmailVerificationCodeUrl = '/api/emailVerification/deactivateEmailVerificationCode',           
            updateEmailAddressByCredentialUrl = '/api/emailVerification/updateEmailAddressByCredential';

        function getAgencyFolderName() {
            var abstractAreaInfoService = new gJobs.AbstractAreaInfoService();
            var currentArea = gJobs.areaInfoService.getCurrentArea();

            var agencyFolderName = "";

            if (currentArea !== abstractAreaInfoService.areaNames.GJobs) {
                agencyFolderName = AgencyPages.pageInfoService ?
                    AgencyPages.pageInfoService.getCurrentAgencyFolderName() :
                    gJobs.pageInfoService.getCurrentAgencyPageFolderName();
            }

            return agencyFolderName;
        }

        self.verifyEmail = function (jobSeekerVerificationCode, captchaAnswer, changedEmailAddressWasAdded) {
            return $.ajax({
                type: 'POST',
                url: emailVerificationUrl,
                data: {
                    jobSeekerVerificationCode: jobSeekerVerificationCode,
                    captchaAnswer: captchaAnswer,
                    changedEmailAddressWasAdded: changedEmailAddressWasAdded
                }
            });
        }

        self.resendEmailVerificationCode = function (captchaAnswer, changedEmailAddressWasAdded) {
            var agencyFolderName = getAgencyFolderName();

            return $.ajax({
                type: 'POST',
                url: resendEmailVerificationCodeUrl,
                data: {
                    captchaAnswer: captchaAnswer,
                    agencyFolderName: agencyFolderName,
                    changedEmailAddressWasAdded: changedEmailAddressWasAdded
                }
            });
        }

        self.getUserData = function () {
            return $.ajax({
                type: 'GET',
                url: getUserDataUrl
            });
        }

        self.trySendEmailVerificationCode = function () {
            var agencyFolderName = getAgencyFolderName();

            return $.ajax({
                type: 'GET',
                url: trySendEmailVerificationCodeUrl + "?agencyFolderName=" + agencyFolderName
            });
        }

        self.getRedirectLinkForSuccessfullEmailVerification = function () {
            return $.ajax({
                type: 'GET',
                url: getRedirectLinkForSuccessfullEmailVerificationUrl
            });
        }

        self.isEmailVerified = function () {
            return $.ajax({
                type: 'GET',
                url: isEmailVerifiedUrl
            });
        }

        self.deactivateEmailVerificationCode = function() {
            return $.ajax({
                type: 'POST',
                url: deactivateEmailVerificationCodeUrl
            });
        };

        
        self.updateEmailAddressByCredential = function(credential, emailAddress) {
            return $.ajax({
                type: 'POST',
                url: updateEmailAddressByCredentialUrl,
                data: {
                    credential: credential,
                    emailAddress: emailAddress
                }
                
            });
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        emailVerificationService: new EmailVerificationService()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function AttachmentsService() {
        var self = this;

        self.setAttachmentFromHistory = function (jobId, attachmentTypeId, attachmentHistoryId) {
            return $.ajax({
                type: "POST",
                url: "/api/attachments/setAttachmentFromHistory",
                data: { jobId: jobId, attachmentTypeId: attachmentTypeId, attachmentHistoryId: attachmentHistoryId }
            });
        };

        self.deleteAttachment = function(jobId, attachmentId) {
            return $.ajax({
                type: "POST",
                url: "/api/attachments/deleteAttachment",
                data: { jobId: jobId, attachmentId: attachmentId }
            });
        };

        self.deleteSupplementalAttachment = function (jobApplicationId, attachmentId, jobId) {
            return $.ajax({
                type: "POST",
                url: "/api/attachments/deleteRequestedSupplementalAttachment",
                data: { jobId: jobId, attachmentId: attachmentId, jobApplicationId: jobApplicationId }
            });
        };
    };


    OnlineApp.Namespace.extend('OnlineApp.Services.Test', {
        AttachmentsService: AttachmentsService
    });

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        attachmentsService: new AttachmentsService()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function AuditService() {
        var self = this,
            endpoint = '/api/audit/';

        self.setCurrentStep = function (jobId, menuStep) {
            return $.ajax({
                type: 'POST',
                url: endpoint + 'setCurrentStep',
                data: {
                    jobId: jobId,
                    menuStep: menuStep
                }
            });
        };

        self.setAction = function (jobId, menuStep) {
            return $.ajax({
                type: 'POST',
                url: endpoint + 'setAction',
                data: {
                    jobId: jobId,
                    menuStep: menuStep
                }
            });
        };
    };

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        auditService: new AuditService()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function JobApplicationService() {
        var self = this,
            endpoint = '/api/jobapplication';

        self.addResumeTemplateToDraft = function (jobId, resumeTemplateId) {
            return $.ajax({
                type: 'POST',
                url: endpoint + '/addResumeTemplateToDraft',
                data: {
                    jobId: jobId,
                    resumeTemplateId: resumeTemplateId
                }
            });
        }

        self.getJobApplication = function (jobApplicationId) {
            if (!jobApplicationId) {
                toastr.warning("Parameter 'jobApplicationId' is required");
            }

            return $.ajax({
                type: 'GET',
                url: endpoint + '/getJobApplication',
                data: {
                    jobApplicationId: jobApplicationId
                }
            });
        };

        self.getActiveJobApplication = function (jobId) {
            return $.ajax({
                type: 'GET',
                url: endpoint + '/getActiveJobApplication',
                data: {
                    jobId: jobId
                }
            });
        };

        self.getActiveOrNewJobApplication = function (resumeTemplateId, jobId, employeeId, jobReferrer, departmentFolder) {
            var path = window.location.search;
            var searchPageRegex = /pagetype=searchPage/i;
            var isSearchPage = searchPageRegex.test(path);
            return $.ajax({
                type: 'GET',
                url: endpoint + '/getActiveOrNewJobApplication',
                data: {
                    resumeTemplateId: resumeTemplateId,
                    jobId: jobId,
                    employeeId: employeeId,
                    jobReferrer: jobReferrer,
                    pagetype: isSearchPage ? 'searchPage' : null,
                    departmentFolder: departmentFolder ? departmentFolder : null
                }
            });
        };

        self.startNewResumeTemplate = function () {
            return $.ajax({
                type: 'GET',
                url: endpoint + '/startNewResumeTemplate'
            });
        };
    };

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        jobApplicationService: new JobApplicationService()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function InboxService() {
        var self = this,
            endpoint = '/api/inbox';
        //self.siteFilterType = siteFilterType;

        self.getMessages = function(criteria) {
            return $.ajax({
                url: endpoint + "/GetMessagesByCriteria",
                type: "GET",
                data: criteria
            });
        }

        self.inboxMessagesSetArchived = function(selectedMessages, areArchived) {
            return $.ajax({
                url: endpoint + "/InboxMessagesSetArchived",
                type: "POST",
                data: JSON.stringify({ selectedMessages: selectedMessages, areArchived: areArchived }),
                contentType: "application/json; charset=utf-8"
            });
        }

        self.getNumberOfMessagesInCategories = function(siteFilterType,employerFolderName) {
            return $.ajax({
                url: endpoint + "/GetNumberOfMessagesInCategories",
                type: "GET",
                data: { siteFilterType: siteFilterType,employerFolderName: employerFolderName}
            });
        }

        self.inboxMessageSetRead = function (messageId, messageSource) {
            return $.ajax({
                url: endpoint + "/InboxMessageSetRead",
                type: "POST",
                data: { messageId: messageId, messageSource: messageSource }
            });
        }

        self.inboxMessageSetFlagged = function (messageId, messageSource, isFlagged) {
            return $.ajax({
                url: endpoint + "/InboxMessageSetFlagged",
                type: "POST",
                data: { messageId: messageId, messageSource: messageSource, isFlagged: isFlagged}
            });
        }
    };

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        inboxService: new InboxService()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function DataServiceEndpoint(controller, settings) {

        // todo: discuss this approach of enabling-disabling endpoints
        var controllerSettings = {
            GET: settings && settings.GET !== undefined ? settings.GET : true,
            POST: settings && settings.POST !== undefined ? settings.POST : true,
            DELETE: settings && settings.DELETE !== undefined ? settings.DELETE : true,
            skipResumeTemplateId: settings && settings.skipResumeTemplateId !== undefined ? settings.skipResumeTemplateId : false
        };

        var self = this,
            endpointBase = ('/api/' + controller);

        self.pathname = controller;

        var toQueryString = function (object) {
            var queryStringSections = [],
                e = encodeURIComponent;

            for (var propertyName in object) {
                queryStringSections.push(e(propertyName) + "=" + e(object[propertyName]));
            }

            return queryStringSections.join("&");
        };

        if (controllerSettings.GET) {
            self.get = function (routeData, queryStringData, useCache) {
                var methodUrl = endpointBase;

                if (routeData != null) {
                    methodUrl += ('/' + routeData);
                }

                if (queryStringData != null) {
                    methodUrl += '?' + toQueryString(queryStringData);
                }

                return $.ajax({
                    url: methodUrl,
                    type: 'GET',
                    cache: useCache !== undefined ? useCache : true
                });
            };
        }

        if (controllerSettings.POST) {
            self.post = function (data, queryStringData) {
                var queryString = "";

                if (queryStringData) {
                    queryString = '?' + toQueryString(queryStringData);
                }

                return $.post(endpointBase + queryString, data);
            };
        }

        if (controllerSettings.DELETE) {
            self['delete'] = function (id, queryStringData) {
                var methodUrl = endpointBase + '/delete';

                if (id != null) {
                    methodUrl += "?id=" + id;
                }

                if (!controllerSettings.skipResumeTemplateId && OnlineApp.ViewModels.applicationViewModel.resumeTemplateViewModel) {
                    var resumeTemplateId = OnlineApp.ViewModels.applicationViewModel.resumeTemplateViewModel.resumeTemplateId();

                    if (resumeTemplateId != null) {
                        methodUrl += "&resumeTemplateID=" + resumeTemplateId;
                    }
                }

                if (queryStringData != null) {
                    var delimiter = (methodUrl.lastIndexOf('?') === -1) ? '?' : '&';
                    methodUrl += delimiter + toQueryString(queryStringData);
                }


                return $.ajax({
                    type: "DELETE",
                    url: methodUrl
                });
            };
        }

        self.action = function (actionName, data) {
            var methodUrl =
                (endpointBase + '/' + actionName);

            return $.post(methodUrl, data);
        };
    }

    function DataService() {
        var self = this;
        self.applicationData = new DataServiceEndpoint("applicationData/all");
        self.applicationDataForProfileSettings = new DataServiceEndpoint("applicationData/forProfileSettings");
        self.dataStorage = {};

        self.loadApplicationData = function (jobId, resumeTemplateId) {
            var promise = self.applicationData
                .get(undefined, { jobId: jobId, resumeTemplateId: resumeTemplateId })
                .done(function (data) {
                    self.dataStorage = data;
                })
                .fail(function () {
                    toastr.warning(Resources.NotificationMessages.EncounteredProblem);
                });

            return promise;
        };

        self.loadApplicationDataForProfileSettings = function (resumeTemplateId) {
            var promise = self.applicationDataForProfileSettings
                .get(undefined, { resumeTemplateId: resumeTemplateId })
                .done(function (data) {
                    // todo: use separate storage
                    self.dataStorage = data;
                })
                .fail(function () {
                    toastr.warning(Resources.NotificationMessages.EncounteredProblem);
                });

            return promise;
        };

        self.educations = new DataServiceEndpoint("education");
        self.workExperience = new DataServiceEndpoint("workExperience");

        /* Note: generalInfo endpoint is not linked to service directly */
        self.generalInfo = new DataServiceEndpoint("generalInfo");
        self.generalInfoAll = new DataServiceEndpoint("generalInfo/all");
        self.contactInfo = new DataServiceEndpoint("generalInfo/contactInfo");
        self.personalInfo = new DataServiceEndpoint("generalInfo/personalInfo");
        self.preferences = new DataServiceEndpoint("generalInfo/preferences");
        self.externalLoginInfo = new DataServiceEndpoint("generalInfo/externalLoginInfo");
        self.emailPreferences = new DataServiceEndpoint("generalInfo/emailPreferences", { cache: false });
        self.disability = new DataServiceEndpoint("disability");
        self.twoFactorAuthenticationPreferences = new DataServiceEndpoint("generalInfo/twoFactorAuthenticationPreferences");


        self.textMessagingPreferences = new DataServiceEndpoint("textMessagingPreferences");

        self.agencyWideQuestions = new DataServiceEndpoint("questions/agencyWide");
        self.supplementaryQuestions = new DataServiceEndpoint("questions/supplementary");
        self.convictionQuestions = new DataServiceEndpoint("questions/conviction");

        self.licenses = new DataServiceEndpoint("licenses");
        self.skills = new DataServiceEndpoint("skills");
        self.officeskill = new DataServiceEndpoint("additionalInfo/officeSkill");
        self.supplementalInfo = new DataServiceEndpoint("supplementalInfo");
        self.languages = new DataServiceEndpoint("languages");

        self.references = new DataServiceEndpoint("references");

        self.submit = new DataServiceEndpoint("submit");

        // Check before submission for payment
        self.checkBeforeSubmit = new DataServiceEndpoint("submitcheck/CheckAppForSubmission");
        self.checkPaymentType = new DataServiceEndpoint("payment/CheckPaymentType");

        self.setInitials = new DataServiceEndpoint("payment/UpsertUserInitialsOnSubmit");
        self.checkCaptcha = new DataServiceEndpoint("submitcheck/IsCaptchaRequiredForApplicationSubmission");
        self.validateCaptcha = new DataServiceEndpoint("submitcheck/ValidateCaptcha");

        self.changePassword = new DataServiceEndpoint("user/changePassword");

        self.compositeDefinitions = new DataServiceEndpoint("definitions/composite");
        self.PastFutureRange = new DataServiceEndpoint("definitions/PastFutureRange");
        self.InvalidSsnValues = new DataServiceEndpoint("definitions/InvalidSsnValues");
        self.sessionExpirationData = new DataServiceEndpoint("definitions/sessionExpirationData");

        self.updateAdSenseDisplayInfo = new DataServiceEndpoint("adsense/updateAdSenseDisplayInfo");

        self.accountSettingsData = new DataServiceEndpoint("accountSettingsData/getAccountSettingsData");

        // talent search
        self.talentSearchPreferences = new DataServiceEndpoint("talentSearchPreferences/talentSearchPreferences");

        self.definitions = {
            states: new DataServiceEndpoint("definitions/states"),
            countries: new DataServiceEndpoint("definitions/countries"),
            educationLevels: new DataServiceEndpoint("definitions/educationLevels"),
            schoolDegrees: new DataServiceEndpoint("definitions/schoolDegrees"),
            schoolTypes: new DataServiceEndpoint("definitions/schoolTypes"),
            languageSkills: new DataServiceEndpoint("definitions/languageSkills"),
            driversLicenseClasses: new DataServiceEndpoint("definitions/driversLicenseClasses"),
            highSchoolHighestLevels: new DataServiceEndpoint("definitions/highschoolhighestlevels"),
            supplementalInfoTypes: new DataServiceEndpoint("definitions/supplementalinfotypes")
        };

        self.attachments = new DataServiceEndpoint("attachments");

        self.exam = new DataServiceEndpoint("exam", {
            GET: true,
            POST: true,
            DELETE: true,
            skipResumeTemplateId: true
        });

        self.offer = new DataServiceEndpoint("offer");

        self.canvassForm = new DataServiceEndpoint("canvass");

        self.paymentInfo = new DataServiceEndpoint("paymentInfo");

        self.testData = new DataServiceEndpoint("testData");

        self.paymentType = new DataServiceEndpoint("payment/setPaymentType");
        self.creditCardPayment = new DataServiceEndpoint("payment/InitiatePaymentSessionTransfer");
        self.waiverForm = new DataServiceEndpoint("payment/deleteForm");

        self.paymentCategory = new DataServiceEndpoint("payment/setPaymentCategory");
        self.paymentTransactionInfo = new DataServiceEndpoint("payment/PaymentTransactionInfo");
        self.accessMembership = new DataServiceEndpoint("accessMembership");
    }

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        dataService: new DataService()
    });

})(window);;
(function (window, undefined) {

    function FileUploadService() {

        var self = this;


        self.uploadFormData = function (url, fileInput, progressHandler) {
            var $fileInput = $(fileInput);
            var formData = new FormData($fileInput[0].form);

            var promise = $.ajax({
                url: url,
                type: 'POST',
                data: formData,
                cache: false,
                contentType: false,
                processData: false,

                xhr: function () {
                    var xhr = $.ajaxSettings.xhr();

                    if (xhr.upload) {
                        xhr.upload.addEventListener('progress', progressHandler, false);
                    }

                    return xhr;
                }
            });

            return promise;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.Services', {
        fileUploadService: new FileUploadService()
    });

})(window);;
(function (window, mixpanel, undefined) {
    'use strict';


    function AnalyticsService() {

        function _injectTrackingCode(token) {
            _injectMixpanelScript(token);
        };

        function _injectMixpanelScript(token) {
            /*
             *  Implementation copied "as is" from Mixpanel web page.
             */
            (function (e, b) {
                if (!b.__SV) {
                    var a, f, i, g; window.mixpanel = b; b._i = []; b.init = function (a, e, d) {
                        function f(b, h) { var a = h.split("."); 2 == a.length && (b = b[a[0]], h = a[1]); b[h] = function () { b.push([h].concat(Array.prototype.slice.call(arguments, 0))) } } var c = b; "undefined" !== typeof d ? c = b[d] = [] : d = "mixpanel"; c.people = c.people || []; c.toString = function (b) { var a = "mixpanel"; "mixpanel" !== d && (a += "." + d); b || (a += " (stub)"); return a }; c.people.toString = function () { return c.toString(1) + ".people (stub)" }; i = "disable track track_pageview track_links track_forms register register_once alias unregister identify name_tag set_config people.set people.set_once people.increment people.append people.track_charge people.clear_charges people.delete_user".split(" ");
                        for (g = 0; g < i.length; g++) f(c, i[g]); b._i.push([a, e, d])
                    }; b.__SV = 1.2; a = e.createElement("script"); a.type = "text/javascript"; a.async = !0; a.src = ("https:" === e.location.protocol ? "https:" : "http:") + '//cdn.mxpnl.com/libs/mixpanel-2.2.min.js'; f = e.getElementsByTagName("script")[0]; f.parentNode.insertBefore(a, f)
                }
            })(document, window.mixpanel || []);

            mixpanel.init(token);
        };

        function _getParametersFromUrl(url, parameters) {
            var queryString = {};
            var regex = /([^?=&]+)(=([^&]*))?/g;

            url.replace(regex, function ($0, $1, $2, $3) {
                var key = decodeURIComponent($1);
                var value = decodeURIComponent($3);

                if (!parameters || (parameters.indexOf(key) > -1)) {
                    queryString[key] = value;
                }
            });

            return queryString;
        };


        return {
            inject: function (token) {
                _injectTrackingCode(token);
            },

            trackPageView: function (url) {
                return;
            },

            trackCurrentPageView: function () {
                return;
            },

            trackEvent: function (action, data, callback) {
                if (mixpanel) {
                    mixpanel.track(action, data, callback || $.noop);
                }
            },

            trackEventWithUrlParameters: function (action) {
                this.trackEvent(action, _getParametersFromUrl(window.location.search));
            },

            setUserIdentity: function (identity) {
                if (mixpanel) {
                    mixpanel.identify(identity.userName);
                }
            },

            setUserInfo: function (user) {
                if (mixpanel) {
                    mixpanel.identify();

                    if (user.firstName) {
                        mixpanel.people.set('$first_name', user.firstName);
                    }

                    if (user.lastName) {
                        mixpanel.people.set('$last_name', user.lastName);
                    }

                    if (user.email) {
                        mixpanel.people.set('$email', user.email)
                    }
                }
            },

            registerUserIdentity: function (identity) {
                if (mixpanel) {
                    mixpanel.alias(identity.userName);

                    mixpanel.people.set({
                        userName: identity.userName,
                        '$first_name': identity.userName,
                        '$email': identity.email
                    });
                }
            },

            parametersFromUrl: function (url) {
                return _getParametersFromUrl(url);
            }
        };
    };


    OnlineApp.Namespace.extend('OnlineApp.Services', {
        analyticsService: new AnalyticsService()
    });

})(window, window.mixpanel);;
(function (window, undefined) {
    'use strict';

    function CaptchaService() {
        var self = this,
            endpoint = '/api/textCaptcha/';

        self.getCaptcha = function (keyForTextCaptchaAnswer) {
            var queryString = "";

            if (keyForTextCaptchaAnswer) {
                queryString = "?keyForTextCaptchaAnswer=" + keyForTextCaptchaAnswer;
            }

            return $.ajax({
                type: 'GET',
                url: endpoint + 'getCaptcha' + queryString
            });
        };

        self.isCaptchaRequiredForRegister = function() {
            return $.ajax({
                type: 'POST',
                url: endpoint + 'isCaptchaRequiredForRegister'
            });
        }

        self.isCaptchaRequiredForLogin = function () {
            return $.ajax({
                type: 'POST',
                url: endpoint + 'isCaptchaRequiredForLogin'
            });
        }
    }

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        captchaService: new CaptchaService()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function PageContextService() {
        var self = this;

        self.isInsideFlyout = function () {
            var $flyout = $('div.flyout-window:not(.hide)');
            return $flyout.length !== 0;
        };

        self.getOnlineAppFlyoutContainer = function () {
            return $('div#apply').first();
        };

        self.getApplicationsPageUrl = function () {
            var agencyPageUrlRegexp = /\/agency(\/[^/]*)\//,
                currentAgencyPageSubLink = window.location.pathname.match(agencyPageUrlRegexp);

            return '/Applications/Index'
                + ((currentAgencyPageSubLink != null
                        && currentAgencyPageSubLink.length > 1)
                    ? currentAgencyPageSubLink[1]
                    : '');
        };

        self.getHomePageUrl = function () {
            return window.location.origin;
        }
    }

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        pageContextService: new PageContextService()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function JobAlertService() {
        var self = this;

        var endpoint = '/JobAlerts/';
        var addJobAlertUrl = endpoint + 'save';
        var deleteJobAlertUrl = endpoint + 'delete';
        var getAllJobAlertsUrl = endpoint + 'getAll';
        var generateJobAlertAlreadyAddedViewUrl = endpoint + 'generateJobAlertAlreadyAddedView';
        var isJobAlertCanBeCreatedUrl = endpoint + 'isJobAlertCanBeCreated';
        var isJobAlertsEnabledUrl = endpoint + 'isJobAlertsEnabled';
        var generateNoFilterSetViewUrl = endpoint + 'generateNoFilterSetView';
        var getJobAlertEditModel = endpoint + 'getEditModel';
        var updateJobAlertEditModel = endpoint + 'updateJobAlertEditFilters';
        var updateJobAlertUrl = endpoint + 'update';
        var updateJobAlertPreferencesUrl = endpoint + 'updatePreferences';
        var isAccessMembershipEnabledUrl = '/api/accessMembership/isAccessMembershipEnabled';

        self.getAll = function () {
            return $.ajax({
                type: 'GET',
                url: getAllJobAlertsUrl,
                cache: false,
            }).done(function (response) {
                return response;
            })
        }

        self.addJobAlert = function (searchCriteria) {
            return $.ajax({
                type: 'POST',
                url: addJobAlertUrl,
                data: {
                    location: searchCriteria.Location,
                    organization: searchCriteria.Organization == null ? null : searchCriteria.Organization[0],
                    category: searchCriteria.Category == null ? null : searchCriteria.Category[0],
                    minimumSalary: searchCriteria.MinimumSalary,
                    distance: searchCriteria.Distance,
                    keyword: searchCriteria.Keyword,
                    remoteWorkOptionId: searchCriteria.RemoteWorkOptionId,
                    jobType: searchCriteria.JobType == null ? null : searchCriteria.JobType[0]
                }
                             
            });
        }

        self.updateJobAlert = function (searchCriteria) {
            return $.ajax({
                type: 'POST',
                url: updateJobAlertUrl,
                data: {
                    location: searchCriteria.Location,
                    organization: searchCriteria.Organization == null ? null : searchCriteria.Organization[0],
                    category: searchCriteria.Category == null ? null : searchCriteria.Category[0],
                    salary: searchCriteria.MinimumSalary,
                    distance: searchCriteria.Distance,
                    keyword: searchCriteria.Keyword,
                    jobAlertId: searchCriteria.JobAlertId,
                    remoteWorkOptionId: searchCriteria.RemoteWorkOptionId,
                    jobType: searchCriteria.JobType == null ? null : searchCriteria.JobType[0]
                }
            });
        }

        self.updateJobAlertPreferences = function (sentJobAlertsFrequency, isJobAlertEnabled) {
            return $.ajax({
                type: 'POST',
                url: updateJobAlertPreferencesUrl,
                data: {
                    jobSeekerId: 0,
                    sentJobAlertsFrequency: sentJobAlertsFrequency,
                    isJobAlertEnabled: isJobAlertEnabled
                }
            });
        }

        self.getJobAlertEditModel = function (jobAlert) {
            return $.ajax({
                type: 'GET',
                url: getJobAlertEditModel,
                data: {
                    location: jobAlert.Location,
                    organization: jobAlert.Organization,
                    category: jobAlert.Category,
                    salary: jobAlert.MinimumSalary,
                    distance: jobAlert.MaxDistance || jobAlert.Distance,
                    keyword: jobAlert.Keyword,
                    jobAlertId: jobAlert.JobAlertId,
                    remoteWorkOptionId: jobAlert.RemoteWorkOptionId,
                    jobType: jobAlert.JobType,
                    isSchoolJobs: jobAlert.SiteSource == 1 ? true : false,
                    isEditClicked: false
                    
                }
            });
        }

        self.updateJobAlertEditModel = function (jobAlert) {
            return $.ajax({
                type: 'GET',
                url: updateJobAlertEditModel,
                data: {
                    location: jobAlert.Location,
                    organization: jobAlert.Organization,
                    category: jobAlert.Category,
                    salary: jobAlert.MinimumSalary,
                    distance: jobAlert.Distance,
                    keyword: jobAlert.Keyword,
                    jobAlertId: jobAlert.JobAlertId
                }
            });
        }

        self.deleteJobAlert = function (jobAlertId, disableJobAlert, jobSeekerId) {
            return $.ajax({
                type: 'DELETE',
                url: deleteJobAlertUrl,
                data: {
                    jobAlertId: jobAlertId,
                    disableJobAlert: disableJobAlert,
                    jobSeekerid: jobSeekerId
                }
            });
        }

        self.generateJobAlertAlreadyAddedView = function () {
            return $.ajax({
                type: 'GET',
                url: generateJobAlertAlreadyAddedViewUrl
            });
        }

        self.generateNoFilterSetView = function (needsToApplySearchFilter) {
            return $.ajax({
                type: 'GET',
                url: generateNoFilterSetViewUrl,
                data: {
                    needsToApplySearchFilter: needsToApplySearchFilter
                }
            });
        }

        self.isJobAlertCanBeCreated = function (searchCriteria) {
            return $.ajax({
                type: 'GET',
                url: isJobAlertCanBeCreatedUrl,
                data: {
                    location: searchCriteria.location,
                    organization: searchCriteria.organization,
                    category: searchCriteria.category,
                    minimumSalary: searchCriteria.salary,
                    distance: searchCriteria.distance,
                    keyword: searchCriteria.keyword,
                    remoteWorkOptionId: searchCriteria.remoteworkoptionid,
                    jobType: searchCriteria.jobType
                }
            });
        }

        self.isJobAlertsEnabled = function () {
            return $.ajax({
                type: 'GET',
                url: isJobAlertsEnabledUrl
            });
        }

        self.isAccessMembershipEnabled = function () {
            return $.ajax({
                url: isAccessMembershipEnabledUrl,
                type: 'GET',
                cache: false
            })
        }
    }

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        jobAlertService: new JobAlertService()
    });
})(window);;
(function (window, undefined) {
    var isIos = function () {
        var deviceAgent = window.navigator.userAgent.toLowerCase();
        return /iphone|ipod|ipad/.test(deviceAgent) && !window.MSStream;
    };

    namespace('gJobs').IosDetector = {
        isIos: isIos
    }

    if (isIos()) {
        document.documentElement.classList.add("ios-device");
    }

})(window);;
(function (window, undefined) {
    'use strict';

    function SessionTrackingService() {
        var self = this;
        var defaults = {
            minutesSessionExpiration: 10,
            minutesBeforeWarning : 5
        }

        var authenticationEventNames = 'loginEvent registerEvent';

        var minutesSessionExpiration;
        var minutesBeforeWarning;
        var secondsKeepAliveInterval = 60;
        var logoutUrl;

        function initialize() {
            logoutUrl = OnlineApp.Services.pageContextService.getHomePageUrl();

            OnlineApp.Services.authenticationService
                .isLoggedIn()
                .done(function(data) {
                    if (data) {
                        activateTracking();
                    }
                })
                .always(function() {
                    $(document).one(authenticationEventNames, activateTracking);
                });
        }

        function logOutAction() {
            OnlineApp.Services.authenticationService.logout().done(function() {
                window.location.href = logoutUrl;
            });

            return true;
        }

        function setInitialValues(expirationData) {
            minutesSessionExpiration = expirationData.timeout;
            minutesBeforeWarning = expirationData.remainingTime;
        }

        function setDefaultValues() {
            minutesSessionExpiration = defaults.minutesSessionExpiration;
            minutesBeforeWarning = defaults.minutesBeforeWarning;
        }

        function activateTracking() {
            var secondsDelay = (minutesSessionExpiration - minutesBeforeWarning) * 60;
            var secondsRemaining = minutesBeforeWarning * 60;

            $(document).idleTimeout({
                idleTimeLimit: secondsDelay,
                dialogDisplayLimit: secondsRemaining,
                sessionKeepAliveTimer: secondsKeepAliveInterval,
                sessionKeepAliveUrl: Resources.EndpointUrls.KeepAlive,
                activityEvents: 'click keyup scroll wheel mousewheel',
                redirectUrl: false,
                customCallback: logOutAction,
                dialogText: Resources.NotificationMessages.SessionTimeoutExpires,
                dialogStayLoggedInButton: Resources.NotificationMessages.SessionTimeoutResume
            });
        }

        $(document).ready(function () {
            var definitionsViewModel = new OnlineApp.ViewModels.DefinitionsViewModel();

            definitionsViewModel.sessionExpirationData.get()
                .done(setInitialValues)
                .fail(setDefaultValues)
                .always(initialize);
        });
    }

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        sessionTrackingService: new SessionTrackingService()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    var CANVASS_FORM_LINK_TEMPLATE =
        '<div class="submitted-canvass referred-candidate-submitted-form">' +
            '<span class="submitted-form-status">Canvass Submitted</span>' +
            '<div class="submitted-date"></div>' +
            '<div class="view-link">' +
                '<i class="ss-standard ss-view"></i>' +
                '<a class="canvass-link" href="#">' +
                    'View Canvass' +
                '</a>' +
            '</div>' +
        '</div>'
    ;

    function CanvassFlyoutService() {
        var self = this;

        self.openCanvassFormFlyout = function (canvassFormId, canvassFormFlyout, canvassViewModel) {      
            window.isCurrentOptionChecked = false;
            window.isValidCurrentPositions = false;
            self.getCanvassForm(canvassFormId)
                    .then(function (data) {
                        var originalTitle = window.document.title;
                        var releaseFocus = [];

                        window.document.title = originalTitle + ' – Canvass Form';

                        var $content = $('#canvass-flyout-content');
                        var $overlay = $('.canvass-flyout-overlay');
                        var $canvassFlyout = canvassFormFlyout.getView();
                        var $responsiveSignature = $('#responsive-signature');
                        var $closeButton = $canvassFlyout.find('.close');

                        ko.cleanNode($content[0]);
                        ko.cleanNode($responsiveSignature[0]);

                        self.setupCanvassFlyout(data.description, data.isReadOnly);

                        ko.applyBindings(canvassViewModel, $content[0]);
                        ko.applyBindings(canvassViewModel.signatureViewModel, $responsiveSignature[0]);
                        canvassViewModel.fromDataModel(data);

                        gJobs.skipToContentService.showOnNextTab();

                        canvassFormFlyout.setSubtitle(data.jobTitle);

                        canvassFormFlyout.open($(document.activeElement));
                        $canvassFlyout.find('.opened-notification').text('View Canvass form flyout is opened.').focus();

                        $('.popover-trigger').popover();

                        $overlay.add($closeButton).on('click', function () {
                            if (releaseFocus) {
                                releaseFocus[0]();
                                releaseFocus[1]();
                                releaseFocus = undefined;
                            }
                            gJobs.focusService.dontRestoreFocus = undefined;
                    
                            window.document.title = originalTitle;
                        });
                        releaseFocus[0] = gJobs.focusService.restrictFocus($canvassFlyout);
                        releaseFocus[1] = gJobs.flyoutTabService.restrictTabbing($canvassFlyout);
                        gJobs.focusService.dontRestoreFocus = true;
                        gJobs.focusService.enableFocusForBrowserControls();
                    })
                    .fail(function() {
                        toastr.error(Resources.NotificationMessages.EncounteredProblem);
                    });
        }

        self.closeCanvassFormFlyout = function () {            
            if (gJobs.areaInfoService.getCurrentArea() == gJobs.areaInfoService.areaNames.Career) {
                AgencyPages.canvassFlyout.close();
            } else {
                gJobs.applicationsPage ?
                    gJobs.applicationsPage.canvassFormFlyout.close() :
                    gJobs.searchPage.canvassFormFlyout.close();
            }
        }

        self.getCanvassForm = function (canvassFormId) {            
            window.isCurrentOptionChecked = false;
            window.isValidCurrentPositions = false;
            return OnlineApp.Services.dataService.canvassForm.get(canvassFormId)
                .then(function(canvassData) {
                    return $.extend(canvassData, {
                        isReadOnly: !!canvassData.dateAnswered
                    })
                });
        }

        self.setupCanvassFlyout = function(initialBody, isReadOnly) {
            var $canvassBody = $('#canvass-body .canvass-main-container').html(
                replaceCanvassFormPlaceholders(initialBody)
            );

            var requiredFields = $canvassBody.find('.required-fields-notification-wrapper')
            var asterisk = $canvassBody.find('.required-asterisk');
            if (gJobs.browserDetector.isMobileBrowser()) {
                $canvassBody.find('.general').find('.general .contacts, .general .department').unwrap();
                $canvassBody
                    .find('.container-body .logo, .container-body .department')
                    .wrapAll('<div class=\'company-general-info\'></div>');
            }

            if (isReadOnly) {
                // Hiding required areas for submitted canvass forms (ONLINE-7315)
                asterisk.replaceWith('');
                requiredFields.replaceWith('');
            } else {
                var isBuffalo = $canvassBody.find('.buffalo').length;
                if (!isBuffalo && isBuffalo <1) {

                    asterisk.removeClass('required-asterisk').addClass('required');
                    requiredFields
                        .replaceWith(
                            '<div class="required-description">' +
                            '<p>Fields marked with an asterisk (<span class="required">*</span>) are required</p>' +
                            '</div>'
                        );
                }
            }
        }

        self.changeCanvassFormStatus = function (canvassFormId, dateAnswered, jobTitle) {
            var $canvassFormLink = $('.canvass-container[data-canvass-id="' + canvassFormId + '"]');

            $canvassFormLink.html(CANVASS_FORM_LINK_TEMPLATE);
            $canvassFormLink.find('.submitted-date').text(dateAnswered);
            $canvassFormLink.find('.canvass-link').attr('aria-label', 'Click to view canvass submitted for ' + jobTitle);
        }

        function replaceCanvassFormPlaceholders (initialBody){
            var body = initialBody;

            body = body.replace('<%placeholder-questionnaire%>',
                '<!-- ko template: "Templates/Canvassing/CanvassQuestionnaire" --><!-- /ko -->'
            );
            
            body = body.replace('<%placeholder-questionnaire capacity="3"%>',
                '<!-- ko template: "Templates/Canvassing/BuffaloCanvassQuestionnaireForCurrentPosition" --><!-- /ko -->'
            );
           

            body = body.replace('<%placeholder-sign-form%>',
                '<!-- ko template: { name: "Templates/Canvassing/CanvassFormFields", afterRender: phoneFieldAfterRender } --><!-- /ko -->'
            );

            body = body.replace('<%placeholder-sign-form-with-date%>',
                '<!-- ko template: { name: "Templates/Canvassing/CanvassFormFieldsWithDate", afterRender: phoneFieldAfterRender } --><!-- /ko -->'
            );

            body = body.replace('<%placeholder-page-break%>',
                '<!-- ko template: "Templates/Canvassing/PageBreak" --><!-- /ko -->'
            );

            return body;
        }      

       
    }




    OnlineApp.Namespace.extend('OnlineApp.Services', {
        canvassFlyoutService: new CanvassFlyoutService()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function OfferFlyoutService() {
        var self = this;

        self.changeOfferStatus = function (offerId, isOfferAccepted) {
            var $offer = $('.offer-container[data-offer-id="' + offerId + '"]');

            var $submittedOffer = $offer.find('.inactive-offer');

            var offerStatus = isOfferAccepted
                ? 'Offer Accepted'
                : 'Offer Rejected';
            $submittedOffer.find('.submitted-form-status').text(offerStatus);

            var answerDate = OnlineApp.Helpers.DateTimeFormatter.getShortDate(new Date());
            $submittedOffer.find('.submitted-date').text(answerDate);

            $offer.find('.active-offer').addClass('hide');
            $submittedOffer.removeClass('hide');
        }
    }

    OnlineApp.Namespace.extend('OnlineApp.Services', {
        offerFlyoutService: new OfferFlyoutService()
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function BrowserDetector() {
        var self = this;

        self.isIE = function(excludeEdge) {
            var userAgent = window.navigator.userAgent;

            var msie = userAgent.indexOf('MSIE ');
            if (msie > 0) {
                // IE 10 or older => return version number
                return parseInt(userAgent.substring(msie + 5, userAgent.indexOf('.', msie)), 10);
            }

            var trident = userAgent.indexOf('Trident/');
            if (trident > 0) {
                // IE 11 => return version number
                var rv = userAgent.indexOf('rv:');
                return parseInt(userAgent.substring(rv + 3, userAgent.indexOf('.', rv)), 10);
            }

            if (!excludeEdge) {
                var edge = userAgent.indexOf('Edge/');
                if (edge > 0) {
                    // IE 12 (aka Edge) => return version number
                    return parseInt(userAgent.substring(edge + 5, userAgent.indexOf('.', edge)), 10);
                }    
            }

            // other browser
            return false;
        }

        self.isFirefox = function() {
            return window.navigator.userAgent.toLowerCase().indexOf('firefox') > -1;
        }

        self.isMobileSafari = function () {
            return navigator.userAgent.match(/(iPod|iPhone|iPad)/) && navigator.userAgent.match(/AppleWebKit/) ? true : false;
        }

        self.isMobileBrowser = function () {
            return /android|webos|iphone|ipod|blackberry|iemobile|opera mini/i.test(navigator.userAgent.toLowerCase())
        }
    };

    namespace('gJobs').browserDetector = new BrowserDetector();

})(window);
;
(function () {

    function CustomLabelService() {

        var self = this;

        self.updateCustomLabels = function ($container, customLabels) {
            var $labelledElements = $container.find('[data-custom-label-key][data-custom-label-type]');
            $labelledElements.each(function (index, element) {
                var $element = $(element);
                var key = $element.data('custom-label-key');
                var type = $element.data('custom-label-type');
                var text = customLabels[key][type];
                if (text) {
                    $element.text(text);
                }
            });
        }
    }

    namespace('gJobs').customLabelService = new CustomLabelService();
})();;
(function (window, undefined) {
    'use strict';

    namespace('gJobs').subjects = {
        EmailUpdated: 'emailUpdated'
    }

    namespace('gJobs').crossWindowCommunicationService = {
        _initialized: false,

        // { subject: string, messageReceivedCallback: function }
        _handlers: [],

        _init: function () {
            var self = this;
            this._initialized = true;
            var eventMethod = window.addEventListener ? "addEventListener" : "attachEvent";
            var eventer = window[eventMethod];
            var messageEvent = eventMethod == "attachEvent" ? "onmessage" : "message";

            eventer(messageEvent, function (e) {
                if (window.location.origin != event.origin) {
                    return;
                }

                var key = e.message ? "message" : "data";
                var data = e[key];

                var handler = self._handlers.filter(function (handler) {
                    return handler.subject == data.subject;
                })[0];

                if (handler != null && typeof handler.messageReceivedCallback === 'function') {
                    handler.messageReceivedCallback(data.message);
                }
            }, false);
        },

        sendMessage: function (subject, message) {
            var opener = window.opener;
            if (opener != null) {
                opener.postMessage({ subject: subject, message: message }, '*');
            }
        },

        setListener: function (subject, callback) {
            if (!this._initialized) {
                this._init();
            }

            this._handlers.push({ subject: subject, messageReceivedCallback: callback });
        }
    }
})(window);;
(function (window, undefined) {
    'use strict';

    function AnalyticsHub() {

        function on(eventName, eventSource, listener) {
            if (arguments.length < 3) {
                listener = arguments[1];
                eventSource = null;
            }


            if (eventSource) {
                $(document).on(eventName, eventSource, listener);
            }
            else {
                $(document).on(eventName, listener);
            }
        }


        function listenForLogin() {
            on(OnlineApp.Events.CommonEventsNames.Login, function (e, data) {
                OnlineApp.Services.analyticsService.setUserIdentity(data.identity);
                OnlineApp.Services.analyticsService.trackEvent('Login', {
                    isInJobContext: data.isInJobContext
                });

                // We do that in order to obtain contact info as soon as user login.
                var contactInfo = new OnlineApp.ViewModels.ContactInfoViewModel({ get: 'contactInfo' });
                contactInfo.load(true);
            });
        }

        function listerForRegister() {
            on(OnlineApp.Events.CommonEventsNames.Register, function (e, data) {
                OnlineApp.Services.analyticsService.registerUserIdentity(data.identity);
                OnlineApp.Services.analyticsService.trackEvent('Account Created', {
                    isInJobContext: data.isInJobContext
                });
            });
        }

        function listenForRegisterLinkClicked() {
            on(OnlineApp.Events.CommonEventsNames.RegisterAccountLinkClicked, function (e, sourceEvent) {
                var isInJobContext = ($(sourceEvent.target).parents('.onlineapp-app-container').length > 0);

                OnlineApp.Services.analyticsService.trackEvent('Create Account (link clicked)', {
                    isInJobContext: isInJobContext
                });
            });
        }

        function listenForContactInformationAvailable() {
            on(OnlineApp.Events.CommonEventsNames.ContactInfomationAvailable, function (e, user) {
                OnlineApp.Services.analyticsService.setUserInfo(user);
            });
        }

        function listenForApplicationSubmit() {
            on(OnlineApp.Events.CommonEventsNames.ApplicationSubmit, function () {
                OnlineApp.Services.analyticsService.trackEvent('Application Received');
            });
        }

        function listenForResumeImportComplete() {
            on(OnlineApp.Events.CommonEventsNames.ResumeImportComplete, function (e) {
                var method;

                switch (e.source) {
                    case 'fileUpload':
                        method = 'Resume Import';
                        break;

                    case 'skipSection':
                        method = 'Profile Created without Import';
                        break;
                }

                var isInJobContext = (e.application === 'Application');

                OnlineApp.Services.analyticsService.trackEvent('Profile Created', {
                    method: method,
                    isInJobContext: isInJobContext
                });
            });
        }

        function listenForCertifyAndSubmitVisible() {
            on('show', 'a[href="#submit-tab"]', function () {
                OnlineApp.Services.analyticsService.trackEvent('Certify & Submit');
            });
        }

        function listenForPasswordResetLinkClickedFromEmail() {
            on(OnlineApp.Events.CommonEventsNames.ResetPasswordClicked, function (e, referrer) {
                if (!referrer.match(location.origin)) {
                    OnlineApp.Services.analyticsService.trackEvent('Set New Password (link clicked)');
                }
            });
        }

        function listenForPasswordResetLinkClicked() {
            on('click', 'a[data-role="reset-password"]', function (e) {
                e.preventDefault();

                OnlineApp.Services.analyticsService.trackEvent('Reset Password (link clicked)', null, function () {
                    location.href = $(e.target).attr('href');
                });
            });
        }

        function listenForSetNewPasswordButtonClicked() {
            on('click', 'button[data-role="set-new-password"]', function (e) {
                e.preventDefault();

                OnlineApp.Services.analyticsService.trackEvent('New Password Set', null, function () {
                    $(e.target).parent('form').submit();
                });
            });
        }

        function listenForUserNameRecoveryLinkClicked() {
            on('click', 'a[data-role="recover-username"]', function (e) {
                e.preventDefault();

                OnlineApp.Services.analyticsService.trackEvent('Forgot Username (link clicked)', null, function () {
                    location.href = $(e.target).attr('href');
                });
            });
        }

        function listenForUserNameRecoveryButtonClicked() {
            on('click', 'button[data-role="recover-username"]', function () {
                OnlineApp.Services.analyticsService.trackEvent('Forgot Username (button clicked)');
            });
        }

        function listenForRecoverySuccess() {
            on(OnlineApp.Events.CommonEventsNames.PasswordReset, function (e, recoveryType) {
                var eventName;

                switch (recoveryType) {
                    case "reset-password":
                        eventName = 'Reset Password (email sent)';
                        break;

                    case "recover-username":
                        eventName = "Forgot Username (email sent)";
                        break;
                }

                OnlineApp.Services.analyticsService.trackEvent(eventName);
            });
        }


        /* turned off listeners to check perfomance issues on Release env
        (function () {
            listenForLogin();
            listerForRegister();
            listenForRegisterLinkClicked();
            listenForContactInformationAvailable();
            listenForApplicationSubmit();
            listenForResumeImportComplete();
            listenForCertifyAndSubmitVisible();
            listenForPasswordResetLinkClickedFromEmail();
            listenForPasswordResetLinkClicked();
            listenForSetNewPasswordButtonClicked();
            listenForUserNameRecoveryLinkClicked();
            listenForUserNameRecoveryButtonClicked();
            listenForRecoverySuccess();
        })(); */
    }


    OnlineApp.Namespace.extend('OnlineApp.Hubs', {
        analyticsHub: new AnalyticsHub()
    });

})(this);;
(function (window, undefined) {
    'use strict';

    /*
        Top-level abstract ViewModel base class.
    */
    function BaseViewModel() {
        var self = this;

        /*
            Makes provided event name unique to actual class.
         */
        self.scopeEventToClass = function (event) {
            return event + '.' + self.constructor.name;
        };

        /*
            Returns equalizes current instance of ViewModel based on passed ViewModel.
                Remark: This method is a template method and expects concrete implementation 
                        of fromDataModel in derived ViewModels. 
        */
        self.fromViewModel = function (viewModel) {
            var data = ko.toJS(viewModel);
            return self.fromDataModel(data);
        };


        /*
            Fills ViewModel properties based on specified data model. 
        */
        self.fromDataModel = function (dataModel) {
        };


        /*
            Converts ViewModel to plain JavaScript object.
        */
        self.toDataModel = function () {
            var jsonData = ko.toCleanJSON(self);
            return ko.utils.parseJson(jsonData);
        };

        /*
            Returns deep copy of ViewModel.
                Remark: This method is a template method and expects concrete implementation 
                        of fromDataModel in derived ViewModels.
        */
        self.clone = function () {
            if (typeof (self.fromDataModel) !== 'function') {
                return self;
            }

            var data = ko.toJS(self);

            var viewModel = new self.constructor();
            viewModel.fromDataModel(data);

            return viewModel;
        };
        
        self.isVisited = ko.observable(false).extend({ ignoreOnSerialization: true });
    }


    OnlineApp.Namespace.extend('OnlineApp.ViewModels.Base', {
        BaseViewModel: BaseViewModel
    });

})(window);;
(function (window, undefined) {
    'use strict';


    function ValidatableViewModel(config) {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;


        function registerFieldGroups(fieldGroupsConfig) {
            for (var fieldGroupName in fieldGroupsConfig) {

                if (fieldGroupsConfig.hasOwnProperty(fieldGroupName)) {
                    var fieldGroupConfig = fieldGroupsConfig[fieldGroupName];
                    registerFieldGroup(fieldGroupName, fieldGroupConfig);
                }
            }
        };

        function registerFieldGroup(fieldGroupName, fieldGroupConfig) {
            var fields = registerFields(fieldGroupConfig);
            registerFieldGroupValidationApi(fieldGroupName, fields);
        };

        function registerFields(fieldGroupConfig) {
            var registeredFields = {};

            for (var fieldName in fieldGroupConfig) {
                var fieldSettings = fieldGroupConfig[fieldName];
                var field = OnlineApp.Namespace.openRelative(self, fieldName);

                field.extend(fieldSettings);

                // Note: Subscribe to dependency observables to trigger dependent field validation
                if (fieldSettings.hasOwnProperty('dependsOn') && fieldSettings.dependsOn.length) {
                    fieldSettings.dependsOn.forEach(function(dependencyObservable) {
                        var currentField = field;
                        dependencyObservable.subscribe(function() {
                            currentField.validate();
                        });
                    });
                }

                registeredFields[fieldName] = field;
            }

            return registeredFields;
        };

        function registerFieldGroupValidationApi(fieldGroupName, fields) {
            var validate = function(suppressValidationErrors) {
                var isValid = true;

                for (var fieldName in fields) {
                    // Note: made validation be invoked for all fields and do not skip validation
                    //       when first invalid field was found
                    isValid = fields[fieldName].validate(suppressValidationErrors) && isValid;
                }

                return !isValid;
            };

            var fieldGroup = {
                validate: validate
            };

            self.hasErrorPureComputed = ko.computed({
                read: function () {
                    return validate(true);
                },
                deferEvaluation: true
            }).extend({ ignoreOnSerialization: true });

            self.validation.fieldGroups[fieldGroupName] = fieldGroup;
        };


        self.validation = {
            fieldGroups: {}
        };


        /*
            Determines whether current ViewModel has validation errors.
        */
        self.hasError = ko.observable(false).extend({ ignoreOnSerialization: true });


        self.showCheckValidationIcon = ko.computed(function() {
            return (self.isVisited() && !self.hasError()) ||
                (OnlineApp.ViewModels.applicationViewModel && OnlineApp.ViewModels.applicationViewModel.isShowAllValidationIcons
                    && OnlineApp.ViewModels.applicationViewModel.isShowAllValidationIcons() && !self.hasError());
        }).extend({ ignoreOnSerialization: true });

        self.showAlertValidationIcon = ko.computed(function () {
            return (self.isVisited() && self.hasError()) ||
                (OnlineApp.ViewModels.applicationViewModel &&
                 OnlineApp.ViewModels.applicationViewModel.isShowAllValidationIcons
                    && OnlineApp.ViewModels.applicationViewModel.isShowAllValidationIcons() && self.hasError());
        }).extend({ ignoreOnSerialization: true });

        /*
            Triggers validation for all field groups.
        */
        self.validate = function () {
            var isValid = true;

            for (var fieldGroupName in self.validation.fieldGroups) {
                isValid = !self.validation.fieldGroups[fieldGroupName].validate() && isValid;
            }

            if (self.editableItem !== undefined && self.editableItem() != null) {
                isValid = isValid && self.editableItem().validate();
            }

            if (self.hasDisability !== undefined && !self.hasDisability()) {
                isValid = false;
            }

            self.hasError(!isValid);

            return isValid;
        };

        /*
            Registers ViewModel fields with Validation Framework.
        */
        self.registerValidation = function (config) {
            registerFieldGroups(config);
        };


        /* Suppress all errors */
        self.suppressValidationErrorsFor = function(context) {
            var suppress = function (obj) {
                for (var field in obj) {
                    if (obj.hasOwnProperty(field) && obj[field] && field !== 'validation') {
                        if (obj[field].hasError != null) {
                            obj[field].hasError(false);

                            if (typeof obj[field].isValidationMessageVisible === 'function') {
                                obj[field].isValidationMessageVisible(false);
                            }
                        }

                        if (typeof obj[field] !== 'function' && !Array.isArray(obj[field])) {
                            suppress(obj[field]);
                        }
                    }
                }
            };

            suppress(context);
        };

        self.suppressValidationErrors = function () {
            self.hasError(false);

            self.suppressValidationErrorsFor(self);
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.ViewModels.Base', {
        ValidatableViewModel: ValidatableViewModel
    });


})(window);;
(function(window, undefined) {
    'use strict';

    /*
        Abstract ViewModel base class giving functionality of loading and saving.
    */

    function DataViewModel(config) {
        var dataService = OnlineApp.Services.dataService;

        var self = OnlineApp.ViewModels.Base.ValidatableViewModel.apply(this, arguments) || this;

        self.isBusy = ko.observable(false).extend({ ignoreOnSerialization: true });

        self.getPostDataKey = function () {
            return config.postDataKey;
        }

        var defaultEndpoints = {
            get: null,
            post: null
        };

        var callChildren = function(object, methodName) {
            for (var propertyName in object) {
                var child = object[propertyName];
                var method = child[methodName];

                if (child instanceof jQuery)
                {
                    continue;
                }

                if (typeof method === 'function') {
                    method.call(child);
                }
            }
        };

        /*
            Normalizes constructor parameters.
        */
        (function() {
            config = config || {};

            if (typeof config.endpoint === 'string') {
                config.endpoint = {
                    // todo: discuss this approach of enabling-disabling endpoints
                    // endpoints are enabled by default
                    get:    config.get    === undefined ? config.endpoint : config.get,
                    post:   config.post   === undefined ? config.endpoint : config.post,
                    'delete': config['delete'] === undefined ? config.endpoint : config['delete']
                };
            }

            config.endpoint =
                $.extend(defaultEndpoints, config.endpoint);
        })();

        var getQueryStringData = function() {
            var queryStringData = {};

            if (config.passResumeTemlateId && OnlineApp.ViewModels.applicationViewModel.resumeTemplateViewModel) {
                queryStringData.resumeTemplateId = OnlineApp.ViewModels.applicationViewModel.resumeTemplateViewModel.resumeTemplateId();
            }

            if (config.passJobId && OnlineApp.ViewModels.applicationViewModel.jobId) {
                queryStringData.jobId = OnlineApp.ViewModels.applicationViewModel.jobId();
            }
            
            if (config.passAgencyFolderName) {
                queryStringData.agencyFolderName =
                    AgencyPages.pageInfoService && AgencyPages.pageInfoService.getCurrentAgencyFolderName();
            }

            if (config.jobApplicationId !== undefined) {
                queryStringData.jobApplicationId = config.jobApplicationId;
            }

            queryStringData = $.isEmptyObject(queryStringData) ? undefined : queryStringData;

            return queryStringData;
        };

        var getRouteData = function() {
            return undefined;
        };

        var getPostData = function(viewModel) {
            var postData = {};

            if (config.passResumeTemlateId || config.passJobId || config.passAgencyFolderName || config.jobApplicationId !== undefined) {
                postData.model = viewModel;
            }

            if (config.passResumeTemlateId && OnlineApp.ViewModels.applicationViewModel.resumeTemplateViewModel) {
                postData.resumeTemplateId = OnlineApp.ViewModels.applicationViewModel.resumeTemplateViewModel.resumeTemplateId();
            }

            if (config.passJobId && OnlineApp.ViewModels.applicationViewModel.jobId) {
                postData.jobId = OnlineApp.ViewModels.applicationViewModel.jobId();
            }
            
            if (config.passAgencyFolderName) {
                postData.agencyFolderName = getAgencyFolderName();
            }

            if (config.jobApplicationId !== undefined) {
                postData.jobApplicationId = config.jobApplicationId;
            }

            postData = $.isEmptyObject(postData) ? undefined : postData;

            return postData;
        };

        function getAgencyFolderName() {
            if (AgencyPages.pageInfoService) {
                return AgencyPages.pageInfoService.getCurrentAgencyFolderName();
            }

            return AgencyPages.pageInfoService ?
                AgencyPages.pageInfoService.getCurrentAgencyFolderName() :
                gJobs.pageInfoService.getCurrentAgencyPageFolderName();
        }

        /*
            Loads data for ViewModel and its children.
        */
        self.load = function(forceLoadFromServer) {
            var success = function(data) {
                self.fromDataModel(data);
            };

            var fail = function() {
                console.log("Service unavailable: " + config.endpoint.get);
                toastr.warning(Resources.NotificationMessages.ServiceUnavailable);
            };

            var promise = $.when();

            if (config.endpoint.get) {
                if (forceLoadFromServer) {
                    OnlineApp.Helpers.layoutHelper.showOnlineAppInnerSpinner(true);
                    promise = dataService[config.endpoint.get]
                        .get(getRouteData(), getQueryStringData())
                        .fail(fail)
                        .done(success)
                        .always(function() {
                            OnlineApp.Helpers.layoutHelper.hideOnlineAppInnerSpinner(true);
                        });
                } else {
                    var path = dataService[config.endpoint.get].pathname.split('/');
                    var data = dataService.dataStorage;
                    for (var i = 0, length = path.length; i < length; i++) {
                        data = data[path[i]];
                    }

                    if (data) {
                        success(data);
                    } else {
                        fail();
                    }
                }
            }

            callChildren(self, 'load');

            return promise;
        };

        /*
            Saves data by pushing it to endpoint.
        */
        self.save = function(viewModel, bypassValidation, dontShowDefaultToastrMessage, queryStringData) {
            if (!bypassValidation && !self.validate()) {
                return null;
            }

            var promise;

            if (config.endpoint.post) {
                var postData = getPostData(viewModel) || viewModel;

                promise = OnlineApp.Helpers.ajaxResponseValidator.ensurePromiseFailsOnInvalidData(
                    dataService[config.endpoint.post].post(postData, queryStringData))
                    .fail(function (data) {
                        if (!dontShowDefaultToastrMessage) {
                            // loop through all server validation errors
                            if (data && data.responseText && JSON) {
                                var response = JSON.parse(data.responseText);
                                OnlineApp.Helpers.Notifications.showResponseMessages(response);
                            } else {
                                toastr.warning(Resources.NotificationMessages.EncounteredProblem);
                            }
                        }
                    });
            }

            return promise;
        };

        /*
            Deletes item by id.
        */
        self['delete'] = function(id) {
            var promise;

            if (config.endpoint['delete']) {
                promise = OnlineApp.Helpers.ajaxResponseValidator.ensurePromiseFailsOnInvalidData(dataService[config.endpoint['delete']]['delete'](id))
                    .fail(function () {
                        toastr.warning(Resources.NotificationMessages.EncounteredProblem);
                    });
            }

            return promise;
        };
    }


    OnlineApp.Namespace.extend('OnlineApp.ViewModels.Base', {
        DataViewModel: DataViewModel
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function EditableViewModel() {

        var self = OnlineApp.ViewModels.Base.DataViewModel.apply(this, arguments) || this;

        /* 
            Consider refactoring by moving this code to custom binding.
            No UI code should be seen in ViewModels according to MVVM.
        */
        function getParentContainerMetrics(child) {

            var $container = getParentContainer(child);

            if (!$container) {
                return null;
            }

            var metrics = {
                offset: $container.offset(),
                position: $container.position(),
                padding: parseInt($container.css('padding-top') || 0),
                containerScroll: $container.scrollParent().scrollTop()
            };

            return metrics;
        }

        function getParentContainer(child) {
            if (!child) {
                return null;
            }

            var $container = $(child).closest('.edit-dialog');

            return $container;
        }

        var sendEndEditEvent = function (containerMetrics, $container, dontScrollAfterEditing) {
            var editCompleteEvent = jQuery.Event(OnlineApp.Events.CommonEventsNames.EditItemComplete);
            editCompleteEvent.targetMetrics = containerMetrics;
            editCompleteEvent.editableItemContainer = $container;
            editCompleteEvent.dontScrollAfterEditing = dontScrollAfterEditing;
            $(document).trigger(editCompleteEvent);
        };

        var dirtyFlag;

        self.editableItem = ko.observable();

        self.isInEditMode = ko.observable(false).extend({ ignoreOnSerialization: true });

        self.validateChanges = function () {
            if (self.editableItem() != null) {
                return self.editableItem().validate();
            }
           
            return true;
        };

        self.beginEdit = function (item, e, dontValidate, editModeOnly) {
            var editableItem = item.clone();

            item.isInEditMode(true);
            editableItem.isInEditMode(true);

            self.editableItem(editableItem);

            if (!dontValidate) {
                self.editableItem().validate();
            }

            dirtyFlag = new ko.dirtyFlag({
                editableItem: self.editableItem
            }, null, true);

            if (OnlineApp.Events) {
                $(document).trigger(
                    OnlineApp.Events.CommonEventsNames.EditableItemBeginEdit,
                    {
                        editEvent: e,
                        item: item,
                        editModeOnly: editModeOnly
                    });
            }
        };

        self.endEdit = function (item) {
            var editedItem = self.editableItem();

            item.isInEditMode(false);
            self.editableItem(null);

            return editedItem;
        };

        self.discardChanges = function (item, e) {
            // find container being edited, before e.target gets removed from DOM

            var target = e && e.target,
                cancelableItem = item || self,
                containerMetrics = getParentContainerMetrics(target),
                $editableItemContainer = getParentContainer(target).parent();

            self.endEdit(cancelableItem);

            if ((item) && (!item.accepted || item.accepted())) {
                sendEndEditEvent(containerMetrics, $editableItemContainer, e.dontScrollAfterEditing);
            }
        };

        self.saveChanges = function (item, e, queryStringData) {

            var target = e && e.target;

            function triggerValidationFailedEvent() {
                if (OnlineApp.Events) {
                    var validationFailedEvent =
                        jQuery.Event(OnlineApp.Events.CommonEventsNames.PreSaveValidationFailed);
                    validationFailedEvent.target = e.target;
                    $(document).trigger(validationFailedEvent);
                }
               
            }

            // Focus on an empty span to prevent focus lost in IE after section saving.
            if (gJobs.browserDetector.isIE()) {
                gJobs.screenReadersService.silenceScreenreader();
            }

            item.isBusy(true);

            if (typeof self.editableItem().validate === 'function') {
                if (!self.editableItem().validate()) {
                    item.isBusy(false);
                    triggerValidationFailedEvent();
                    return window.undefined;
                }
            }

            var editedItem = self.editableItem();
            var viewModelData = editedItem.toDataModel();

            return self.save(viewModelData, true /* skip validation, already validated */, null, queryStringData)
                .done(function (data) {
                    // find container being edited, before e.target gets removed from DOM

                    if (target) {
                        var containerMetrics = getParentContainerMetrics(target);
                        var $editableItemContainer = getParentContainer(target).parent();
                    }

                    item.fromViewModel(editedItem);
                    self.endEdit(item);

                    if (target) {
                        sendEndEditEvent(containerMetrics, $editableItemContainer);
                    }

                    if (data && data.payload && data.payload.isEmailChanged) {

                        if (!data.payload.isImpersonatedJobSeeker) {
                            OnlineApp.Services
                                .emailVerificationService
                                .getRedirectLinkForSuccessfullEmailVerification()
                                .done(function (response) {
                                    var data = response.data;

                                    if (data.redirectedLink !== "") {
                                        window.location = data.redirectedLink;
                                    }
                                });
                        } else {
                            window.location.reload();
                        }
                    }
                })
                .always(function () {
                    if (OnlineApp.Events) {
                        item.isBusy(false);
                    }
                });
        };

        self.isDataChanged = function () {
            return dirtyFlag && dirtyFlag.isDirty();
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.ViewModels.Base', {
        EditableViewModel: EditableViewModel
    });
})(window);;
(function (window, undefined) {
    'use strict';

    function EditableCollectionViewModel() {

        var self = OnlineApp.ViewModels.Base.EditableViewModel.apply(this, arguments) || this;

        /* 
            Consider refactoring by moving this code to custom binding.
            No UI code should be seen in ViewModels according to MVVM.
        */
        function getAddButtonMetrics(child) {
            if (!child) {
                return null;
            }

            var $container = $(child).closest('.box-container');
            if (!$container) {
                return null;
            }

            var $addButton = $container.parent().parent().parent().find('.btn-app-add');
            if (!$addButton) {
                return null;
            }

            var metrics = {
                offset: $addButton.offset(),
                position: $addButton.position(),
                padding: parseInt($addButton.css('padding-top') || 0),
                containerScroll: $addButton.scrollParent().scrollTop(),
                element: $addButton
            };

            return metrics;
        }


        function createItem() {
            var itemTemplate = self.itemTemplate(),
                newItem = new itemTemplate();

            // mark item as "not accepted" so that we can cancel its creation
            newItem.accepted = ko.observable(false);

            return newItem;
        };

        var sendRemoveItemEvent = function (e, index, itemsCount) {
            var editCompleteEvent = jQuery.Event(OnlineApp.Events.CommonEventsNames.RemoveItemComplete);
            editCompleteEvent.target = e.target;
            editCompleteEvent.index = index;
            editCompleteEvent.itemsCount = itemsCount;
            $(document).trigger(editCompleteEvent);
        };

        var sendItemRemovedEvent = function (index) {
            var itemRemovedEvent = jQuery.Event(OnlineApp.Events.CommonEventsNames.ItemRemoved);
            itemRemovedEvent.index = index;
            $(document).trigger(itemRemovedEvent);
        }

        self.items = ko.observableArray([]);
        self.sortedItems = ko.computed(function () { return self.items(); });

        self.hasUnsavedItem = ko.observable(false);

        self.itemsCount = ko.computed(function () {
            return self.items().length;
        });

        self.savedItemsCount = ko.computed(function () {
            // unsaved items are not tracked in items count
            var itemsCount =
                self.hasUnsavedItem()
                    ? self.itemsCount() - 1
                    : self.itemsCount();

            return itemsCount;
        });

        self.add = function () {
            var newItem = createItem();

            self.hasUnsavedItem(true);
            self.items.unshift(newItem);
            self.beginEdit(newItem, null, true);
        };

        self.saveChanges = (function (base) {
            return function (item) {
                var promise = base.apply(this, arguments);
                if (!promise) {
                    return window.undefined;
                }

                promise
                    .done(function (data) {
                        if (data && data.id) {
                            item.id(data.id);

                            self.hasUnsavedItem(false);

                            // mark item as "accepted" so that when we want to cancel our changes
                            // item won't be deleted from items collection
                            if (item.accepted) {
                                item.accepted(true);
                            }
                        }
                    });

                return promise;
            };
        })(self.saveChanges);

        self.discardChanges = (function (base) {
            return function (item, event) {
                var cancelChanges = function (item, event) {
                    var targetMetrics = getAddButtonMetrics(event.target);

                    base.apply(this, arguments);
                    if (item.accepted && !item.accepted()) {
                        var itemDiscardedEvent = jQuery.Event(OnlineApp.Events.CommonEventsNames.EditableCollectionItemDiscarded);
                        itemDiscardedEvent.item = item;
                        itemDiscardedEvent.targetMetrics = targetMetrics;
                        itemDiscardedEvent.dontScrollAfterEditing = event.dontScrollAfterEditing;
                        self.items.remove(item);
                        self.hasUnsavedItem(false);

                        $(document).trigger(itemDiscardedEvent);
                    }
                };

                if (!item && self.items) {
                    var cancelableItem = ko.utils.arrayFirst(self.items(), function (item) {
                        return item.isInEditMode();
                    });
                    cancelChanges(cancelableItem, event);
                } else {
                    cancelChanges(item, event);
                }
            };
        })(self.discardChanges);

        self.removeItem = function (item, e) {

            function successCallback() {
                var index = $.inArray(item, self.sortedItems());
                var length = self.items().length;
                
                // call delete service
                self['delete'](item.id())
                    .done(function () {
                        sendRemoveItemEvent(e, index, length);

                        // remove from collection
                        self.items.remove(item);

                        // clear editable item for EditableCollectionViewModel class
                        self.editableItem(null);

                        self.hasUnsavedItem(false);

                        sendItemRemovedEvent(index);
                    });
            }

            var tryRemoveEvent = jQuery.Event(OnlineApp.Events.CommonEventsNames.TryRemoveItem);
            tryRemoveEvent.successCallback = successCallback;

            $(document).trigger(tryRemoveEvent);
        };

        self.fromDataModel = function (data) {
            var viewModels = ko.utils.arrayMap(data, function (x) {
                var itemTemplate = self.itemTemplate(),
                    emptyItem = new itemTemplate();

                emptyItem.fromDataModel(x);

                return emptyItem;
            });

            self.items(viewModels);
        };

        /*
            Don't show remove btn when new item is added and being edited
        */
        self.isRemoveButtonVisible = function (item) {
            if (!item.accepted ||
                item.accepted && item.accepted() === true) {
                return true;
            }

            return false;
        };

        self.isInEditMode = ko.computed(function () {
            var isInEditMode = false;

            ko.utils.arrayForEach(self.items(), function (item) {
                if (item.isInEditMode()) {
                    isInEditMode = true;
                }
            });

            return isInEditMode;
        });

        self.validate = function () {
            var invalidItem;
            var items = self.items();

            invalidItem = ko.utils.arrayFirst(items, function (item) {
                return !item.validate();
            });

            return !invalidItem;
        };

        // TODO: we may refactor this
        self.hasError = ko.computed(function () {
            var isValid = self.validate();
            var hasError = !isValid;

            return hasError;
        });

        self.isDataChanged = (function (base) {
            return function () {
                if (self.editableItem()) {
                    return base();
                }
                return false;
            }
        })(self.isDataChanged);
    }

    OnlineApp.Namespace.extend('OnlineApp.ViewModels.Base', {
        EditableCollectionViewModel: EditableCollectionViewModel
    });

})(window);;
(function (window, undefined) {
    'use strict';


    function CompositeEditableViewModel() {

        var self = OnlineApp.ViewModels.Base.EditableViewModel.apply(this, arguments) || this;


        var any = function (predicate) {
            var result = false;

            ko.utils.arrayForEach(self.parts(), function (part) {
                result = predicate(part) || result;
            });

            return result;
        };

        self.any = any;

        var all = function (predicate) {
            var result = true;

            ko.utils.arrayForEach(self.parts(), function (part) {
                result = predicate(part) && result;
            });

            return result;
        };

        self.all = all;

        self.parts = ko.observableArray([]);

        self.dirtyFlag = {};

        self.addPart = function (viewModel) {
            self.parts.push(viewModel);
        };

        self.addParts = function (viewModels) {
            ko.utils.arrayPushAll(self.parts(), viewModels);
            self.parts.valueHasMutated();
        };

        self.getParts = function () {
            return self.parts().slice(0);
        };

        self.beginEditAll = function () {
            var i = 0,
                editableItems = {};

            all(function (part) {
                part.beginEdit(part);
                editableItems[i++] = part.editableItem;
            });

            self.dirtyFlag = new ko.dirtyFlag(editableItems, null, true, false);
        };

        self.isInEditMode = ko.computed(function () {
            var isInEditMode = any(function (part) {
                return part.isInEditMode();
            });

            return isInEditMode;
        });


        self.hasError = ko.computed(function () {
            var hasError = any(function (part) {
                return part.hasError();
            });

            return hasError;
        });

        self.validate = function () {
            var isValid = all(function (part) {
                return part.validate();
            });

            return isValid;
        };

        self.validateChanges = function () {
            var isValid = all(function (part) {
                return part.validateChanges();
            });

            return isValid;
        };

        self.save = (function (base) {
            return function () {
                var postData = { };

                all(function (part) {
                    var editableItem = part.editableItem();
                    var postDataKey = part.getPostDataKey();

                    if (postDataKey) {
                        if (editableItem) {
                            postData[postDataKey] = editableItem.toDataModel();
                        } else {
                            postData[postDataKey] = null;
                        }
                    }
                });

                return base(postData, true);
            };
        })(self.save);

        self.saveChanges = function () {
            return self.save().done(function (response) {
                all(function (part) {
                    if (part.isInEditMode()) {
                        part.fromViewModel(part.editableItem());
                        part.endEdit(part);
                    }
                });

                return response;
            });
        };

        self.discardChanges = function (item, e) {
            all(function (part) {
                if (part.isInEditMode()) {
                    part.discardChanges(item, e);
                }
            });
        };

        self.isDataChanged = function () {
            var editableViewModel = this.parts().filter(
                function (part) {
                    return part.isInEditMode();
            })[0];

            return editableViewModel && editableViewModel.isDataChanged();
        }
    };


    OnlineApp.Namespace.extend('OnlineApp.ViewModels.Base', {
        CompositeEditableViewModel: CompositeEditableViewModel
    });

}());;
(function(window, undefined) {
    'use strict';

    function NameViewModel() {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;

        self.firstName = ko.observable();
        self.middleName = ko.observable();
        self.lastName = ko.observable();
        self.formerName = ko.observable();
        self.fullName = ko.computed(function () {
            return ((self.firstName() || '') + ' ' + (self.lastName() || '')).trim();
        }).extend({ ignoreOnSerialization: true });

        self.fromDataModel = function (data) {
            if (!data) {
                return;
            }
            self.firstName(data.firstName);
            self.middleName(data.middleName);
            self.lastName(data.lastName);
            self.formerName(data.formerName);
        };
        self.normalize = function() {
            self.firstName($.trim(self.firstName()));
            self.middleName($.trim(self.middleName()));
            self.lastName($.trim(self.lastName()));
            self.formerName($.trim(self.formerName()));
        }
    }

    function AddressViewModel(prefix) {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;
        var fieldSettings = OnlineApp.FieldSettings || {};

        self.address1 = ko.observable();
        self.address2 = ko.observable();
        self.city = ko.observable();
        self.state = new StateViewModel();
        self.zipCode = ko.observable();
        self.country = new CountryViewModel();
        self.filteredStates = ko.observableArray([]);

        self.visible = function () {
            var visible = false;
            if (!prefix) {
                visible = (fieldSettings['address1'] === undefined || fieldSettings['address1'].visible)
                    || (fieldSettings['address2'] === undefined || fieldSettings['address2'].visible)
                    || (fieldSettings['city'] === undefined || fieldSettings['city'].visible)
                    || (fieldSettings['stateID'] === undefined || fieldSettings['stateID'].visible)
                    || (fieldSettings['countryID'] === undefined || fieldSettings['countryID'].visible)
                    || (fieldSettings['zip'] === undefined || fieldSettings['zip'].visible);
            } else if (prefix === 'education') {
                visible = (fieldSettings[prefix + 'City'] === undefined || fieldSettings[prefix + 'City'].visible)
                    || (fieldSettings[prefix + 'State'] === undefined || fieldSettings[prefix + 'State'].visible)
                    || (fieldSettings[prefix + 'Country'] === undefined || fieldSettings[prefix + 'Country'].visible);
            } else if (prefix === 'workExperience') {
                visible = (fieldSettings[prefix + 'Address'] === undefined || fieldSettings[prefix + 'Address'].visible)
                    || (fieldSettings[prefix + 'City'] === undefined || fieldSettings[prefix + 'City'].visible)
                    || (fieldSettings[prefix + 'State'] === undefined || fieldSettings[prefix + 'State'].visible)
                    || (fieldSettings[prefix + 'ZipCode'] === undefined || fieldSettings[prefix + 'ZipCode'].visible)
                    || (fieldSettings[prefix + 'Country'] === undefined || fieldSettings[prefix + 'Country'].visible);
            }
            return visible;
        }

        self.country.id.subscribe(function(value) {
            var states = OnlineApp.ViewModels.applicationViewModel.definitionsViewModel.states.items();

            if (value && value !== 1 && value !== 39) {
                states = states.filter(function(s) { return s.countryId !== 1 && s.countryId !== 39 });
            } else if(value) {
                states = states.filter(function(s) { return s.countryId === value });
            }

            if (!states.filter(function(s) {return s.id === self.state.id()}).length) {
                self.state.id(undefined);
                self.state.name(undefined);
                self.state.abbrvState(undefined);
                self.state.countryId(undefined);
            }

            if (self.zipCode.validate && !self.zipCode.validate()) {
                self.zipCode(undefined);
            }

            self.filteredStates(states);
        });

        self.cityStateZip = ko.computed(function () {
            var city = '';
            var abbrvState = '';
            var zip = '';

            if (fieldSettings[prefix + 'City'] === undefined || fieldSettings[prefix + 'City'].visible) {
                city = self.city() || '';
            }

            if (fieldSettings[prefix + 'State'] === undefined || fieldSettings[prefix + 'State'].visible) {
                abbrvState = self.state != undefined ? self.state.abbrvState() || '' : '';
            }

            if (fieldSettings[prefix + 'ZipCode'] === undefined || fieldSettings[prefix + 'ZipCode'].visible) {
                zip = self.zipCode() || '';
            }

            return city
                + (city != '' && (abbrvState != '' || zip != '') ? ', ' : '')
                + abbrvState
                + (abbrvState != '' && zip != '' ? ' ' : '')
                + zip;
        }).extend({ ignoreOnSerialization: true });

        self.fromDataModel = function (data) {
            if (!data) {
                return;
            }

            self.filteredStates(OnlineApp.ViewModels.applicationViewModel.definitionsViewModel ?
                OnlineApp.ViewModels.applicationViewModel.definitionsViewModel.states.items() :
                []);
            self.address1(data.address1);
            self.address2(data.address2);
            self.city(data.city);
            self.country.fromDataModel(data.country);
            self.state.fromDataModel(data.state);
            self.zipCode(data.zipCode);

            return self;
        };
    }

    function PhoneViewModel() {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;

        self.primaryPhone = ko.observable();
        self.primaryPhoneExt = ko.observable();
        self.alternatePhone = ko.observable();
        self.alternatePhoneExt = ko.observable();

        var getPhoneWithExt = function (phone, ext) {
            return (phone || '')
                + (ext ? ' ext. ' + ext : '');
        };

        self.fullPrimaryPhone = ko.computed(function () {
            return getPhoneWithExt(self.primaryPhone(), self.primaryPhoneExt());
        }).extend({ ignoreOnSerialization: true });
        self.fullAlternatePhone = ko.computed(function () {
            return getPhoneWithExt(self.alternatePhone(), self.alternatePhoneExt());
        }).extend({ ignoreOnSerialization: true });

        self.fromDataModel = function (data) {
            if (!data) {
                return;
            }
            self.primaryPhone(data.primaryPhone);
            self.primaryPhoneExt(data.primaryPhoneExt);
            self.alternatePhone(data.alternatePhone);
            self.alternatePhoneExt(data.alternatePhoneExt);

            return self;
        };
    }

    function SupervisorViewModel(prefix) {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;
        var fieldSettings = OnlineApp.FieldSettings || {};

        self.name = ko.observable();
        self.title = ko.observable();
        self.fullName = ko.computed(function() {
            var name = '',
                title = '',
                fullName = '';

            if (fieldSettings[prefix + 'SupervisorName'] === undefined || fieldSettings[prefix + 'SupervisorName'].visible) {
                name = self.name() || '';
            }

            if (fieldSettings[prefix + 'SupervisorTitle'] === undefined || fieldSettings[prefix + 'SupervisorTitle'].visible) {
                title = self.title() || '';
            }

            if (name && title) {
                fullName = name + ', ' + title;
            }
            else if (!name || !title) {
                fullName = name || title || '';
            }

            return fullName;
        }).extend({ ignoreOnSerialization: true });

        self.visible = function() {
            return (fieldSettings[prefix + 'SupervisorName'] === undefined || fieldSettings[prefix + 'SupervisorName'].visible) ||
                   (fieldSettings[prefix + 'SupervisorTitle'] === undefined || fieldSettings[prefix + 'SupervisorTitle'].visible);
        }

        self.fromDataModel = function(data) {
            if (!data) {
                return;
            }

            self.name(data.name);
            self.title(data.title);
        };
    }

    function CountryViewModel() {
        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;


        self.id = ko.observable();
        self.name = ko.observable();


        self.fromDataModel = function(data) {
            if (!data) {
                return;
            }

            self.id(data.id);
            self.name(data.name);
        };
    }

    function SchoolTypeViewModel() {
        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;


        self.id = ko.observable();
        self.name = ko.observable();


        self.fromDataModel = function(data) {
            if (!data) {
                return;
            }

            self.id(data.id);
            self.name(data.name);
        };
    }

    function StateViewModel() {
        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;


        self.id = ko.observable();
        self.abbrvState = ko.observable();
        self.name = ko.observable();
        self.countryId = ko.observable();


        self.fromDataModel = function(data) {
            if (!data) {
                return;
            }

            self.id(data.id);
            self.abbrvState(data.abbrvState);
            self.name(data.name);
            self.countryId(data.countryId);
        };
    }

    function SchoolDegreeViewModel() {
        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;


        self.id = ko.observable();
        self.title = ko.observable();


        self.fromDataModel = function(data) {
            if (!data) {
                return;
            }

            self.id(data.id);
            self.title(data.title);
        };
    }

    function HighSchoolHighestLevelViewModel() {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;

        self.id = ko.observable();
        self.name = ko.observable();

        self.fromDataModel = function(data) {
            if (!data) {
                return;
            }

            self.id(data.id);
            self.name(data.name);
        };
    }

    function SupplementalInfoTypeViewModel() {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;

        self.id = ko.observable();
        self.name = ko.observable();

        self.fromDataModel = function(data) {
            if (!data) {
                return;
            }

            self.id(data.id);
            self.name(data.name);
        };
    }


    /* View Models' Extenders */
    function PasswordExtender(ext) {
        var self = ko.observable('');
        if (ext) {
            self.extend(ext);
        }

        self.mismatchMessage = "Passwords don't match!";

        self.confirmPassword = ko.observable('').extend({ required: {} });
        self.isConfirmPasswordSelected = ko.observable(false);

        self.isPasswordConfirmed = ko.computed(function () {
            return self() === self.confirmPassword();
        });

        self.showPasswordMismatch = ko.observable(false);

        self.confirmPassword.subscribe(function () {
            var passwordMismatch = self.confirmPassword() && self() && self() != self.confirmPassword();
            self.showPasswordMismatch(passwordMismatch ? true : false); //so we enforce proper boolean value
        });

        self.validate = (function (baseValidate) {
            return function () {
                var isValid = baseValidate();

                var isConfirmed = self.confirmPassword.validate() && (self.confirmPassword() && self() && self.isPasswordConfirmed());
                self.showPasswordMismatch(!isConfirmed && self());
                self.isPasswordConfirmed.notifySubscribers();

                self.hasError(!isValid);

                return isValid;
            };
        })(self.validate);

        self.clearFields = function () {
            self("");
            self.hasError(false);

            self.confirmPassword("");
            self.confirmPassword.hasError(false);

            self.showPasswordMismatch(false);
        };

        return self;
    }

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        Common: {
            NameViewModel: NameViewModel,
            AddressViewModel: AddressViewModel,
            PhoneViewModel: PhoneViewModel,
            SupervisorViewModel: SupervisorViewModel,
            CountryViewModel: CountryViewModel,
            SchoolTypeViewModel: SchoolTypeViewModel,
            StateViewModel: StateViewModel,
            SchoolDegreeViewModel: SchoolDegreeViewModel,
            HighSchoolHighestLevelViewModel: HighSchoolHighestLevelViewModel,
            SupplementalInfoTypeViewModel: SupplementalInfoTypeViewModel,

            PasswordExtender: PasswordExtender
        }
    });

})(window);;
(function (window, undefined) {
    'use strict';

   

    function SignatureViewModel() {
        var SIGNATURE_PAD_SELECTOR = '.signature-pad:visible';

        var SIGNATURE_TOOLBAR_HEIGHT = 50,
            SIGNATURE_TOOLBAR_WIDTH = 25,
            SIGNATURE_NAME_CONTAINER_HEIGHT = 41;

        var fullScreenChangeEvents = 'fullscreenchange mozfullscreenchange webkitfullscreenchange msfullscreenchange';

        var signaturePad;
        var canvas;

        var self = this;

        self.isMobile = gJobs.browserDetector.isMobileBrowser();

        self.signature = ko.observable('');

        self.isReadOnlyView = ko.observable(true);

        self.username = ko.observable('');
        self.dateAnswered = ko.observable('');

        self.isSignatureCompleted = ko.observable(false);
        self.isSignatureInEditMode = ko.observable(false);
        self.isSignatureInputed = ko.observable(false);

        self.isSignatureInEditModeMobile = ko.computed(function () {
            return self.isMobile && self.isSignatureInEditMode();
        });

        self.fromDataModel = function (signature, isReadOnlyView, dateAnswered, username) {
            self.signature(signature);
            self.isReadOnlyView(isReadOnlyView);

            if (username) {
                self.username(username);
            } else {
                loadUserName();
            }

            self.dateAnswered(dateAnswered);

            self.isSignatureInEditMode(false);
            self.isSignatureCompleted(false);
        }

        self.generateMobileSignatureClick = function () { };
        self.editSignatureClick = function () { };

        self.isSignatureInEditMode.subscribe(function (isInEditMode) {
            if (self.isMobile && !gJobs.browserDetector.isMobileSafari() && !isInEditMode) {
                goOutFullscreen();
                screen.orientation && screen.orientation.unlock();
            }
        });

        self.drawSignatureClick = function () {
            signaturePad.clear();
            signaturePad.on();
            self.isSignatureInputed(false);
        }

        self.generateSignatureClick = function () {
            signaturePad.clear();
            signaturePad.off();

            var canvasContext = canvas[0].getContext('2d');

            OnlineApp.Services.authenticationService.getUserData()
                .then(function (data) {
                    if (data.username) {
                        generateSignatureOnCanvas(canvasContext, data.username);
                    } else {
                        generateSignatureOnCanvas(canvasContext, self.username());
                    }
                });

            self.isSignatureInputed(true);
        }

        self.clearSignatureClick = function () {
            setTimeout(function () {                
                gJobs.screenReadersService.setNotification($("#aria-live-message-container"), 'Signature is cleared', null, true);
            }, 500); 
        }

        self.generateMobileSignatureClick = function () {
            var newCanvas = $('<canvas width="496" height="150"/>')[0];

            OnlineApp.Services.authenticationService.getUserData()
                .then(function (data) {
                    var canvasContext = newCanvas.getContext('2d');
                    clearCanvas(canvasContext);

                    generateSignatureOnCanvas(canvasContext, data.username);

                    self.signature(newCanvas.toDataURL());
                    self.isSignatureCompleted(true);
                });
        }

        self.editSignatureMobileClick = function () {
            if (self.isReadOnlyView()) {
                return;
            }

            self.isSignatureInEditMode(true);

            var $signaturePad = $(SIGNATURE_PAD_SELECTOR);

            canvas = $signaturePad.find('canvas');

            var potraitOrientation = window.matchMedia('(orientation: portrait)');
            rotateSignatureToolbar(potraitOrientation.matches);
            setCanvasSize(potraitOrientation.matches);

            initSignaturePad($signaturePad);

            // handle orientation change for mobile Safari manually as it 
            // is not supporting Fullscreen API and Screen Orientation API
            if (gJobs.browserDetector.isMobileSafari()) {
                potraitOrientation.addListener(function (e) {
                    handleOrientationChange(e);
                });
            } else {
                // add orientation change handle if the user decides to go out of fullscreen mode
                $(document).on(fullScreenChangeEvents, function () {

                    // this timeout is needed to recalculate document height and width after fullscreen transition end
                    setTimeout(function () {
                        rotateSignatureToolbar(potraitOrientation.matches);
                        setCanvasSize(potraitOrientation.matches);
                    }, 150);

                    if (!document.fullscreenElement) {
                        potraitOrientation.addListener(function (e) {
                            handleOrientationChange(e);
                        });
                    }
                });

                goInFullscreen($('.signature-pad-responsive').get(0));
                screen.orientation && screen.orientation.lock(potraitOrientation.matches ? 'portrait' : 'landscape');
            }

            self.isSignatureInputed(false);
        }

        self.saveSignatureMobileClick = function () {
            if (signaturePad.isEmpty()) {
                return;
            }

            var img = new Image();

            img.onload = function () {
                var tempCanv = document.createElement('canvas')

                tempCanv.height = 150;
                tempCanv.width = 496;
                tempCanv.style.position = "absolute";

                var isPortaitOrientaion = window.matchMedia('(orientation: portrait)').matches;
                var scaleRate = isPortaitOrientaion ? tempCanv.height / img.width : tempCanv.height / img.height;

                var ctx = tempCanv.getContext("2d");

                clearCanvas(ctx);

                ctx.scale(scaleRate, scaleRate);

                ctx.imageSmoothingEnabled = false;

                if (isPortaitOrientaion) {
                    ctx.translate(img.height / img.width, img.width);
                    ctx.rotate(-Math.PI / 2);
                }

                ctx.drawImage(img, isPortaitOrientaion ? 0 : img.width * scaleRate / 2, isPortaitOrientaion ? img.height * scaleRate / 2 : 0);

                var res = tempCanv.toDataURL();

                self.signature(res);
                self.isSignatureCompleted(true);
                self.isSignatureInEditMode(false);
            }

            img.src = canvas[0].toDataURL();
        }

        self.editSignatureClick = function () {
            self.isSignatureInEditMode(true);

            var $signaturePad = $(SIGNATURE_PAD_SELECTOR);
            var sigWrapper = $signaturePad.find('.sig-wrapper');

            $signaturePad.find(':tabbable').first().focus();

            canvas = $signaturePad.find('canvas');

            canvas[0].width = sigWrapper.width();
            canvas[0].height = sigWrapper.height();

            initSignaturePad($signaturePad);
            self.isSignatureInputed(false);
        }

        self.saveSignatureClick = function () {
            self.signature(canvas[0].toDataURL());
            self.isSignatureCompleted(true);
            self.isSignatureInEditMode(false);

            handleActionAnnouncement('Signature saved', 0);
            setFocusOnEditSignatureButton();
            if ($('#canvass-form-date')) {
                var now = new Date();
                var day = ("0" + now.getDate()).slice(-2);
                var month = ("0" + (now.getMonth() + 1)).slice(-2);
                var today = now.getFullYear() + "-" + (month) + "-" + (day);
                $('#canvass-form-date').val(today);
                $('#canvass-form-date').keydown();
                //OnlineApp.ViewModels.CanvassViewModel.maskedDate = today;

            }
        }

        self.cancelSignatureClick = function () {
            self.isSignatureInEditMode(false);
            setFocusOnEditSignatureButton();
            handleActionAnnouncement('Signature cancelled', 0);
        }

        function setFocusOnEditSignatureButton() {
            $('.edit-signature-button').focus();
        }

        var initSignaturePad = function ($signaturePad) {
            signaturePad = new SignaturePad(canvas[0], {
                penColor: '#145394',
                backgroundColor: 'transparent'
            });

            self.isSignatureInputed(false);

            $signaturePad.find('.clear-button').on('click', function () {
                signaturePad.clear();
                signaturePad.on();
                self.isSignatureInputed(false);
                handleActionAnnouncement('Signature cleared', 1);
            });

            canvas.on('mousedown', function () {
                self.isSignatureInputed(true);
            });
        }

        var rotateImage = function (img, angleRad) {
            var tempCanv = document.createElement('canvas');

            tempCanv.height = img.width;
            tempCanv.width = img.height;
            tempCanv.style.position = "absolute";

            var ctx = tempCanv.getContext("2d");
            ctx.imageSmoothingEnabled = false;

            if (angleRad > 0) {
                ctx.translate(img.height, img.width / img.height);
            } else {
                ctx.translate(img.height / img.width, img.width);
            }

            ctx.rotate(angleRad);
            ctx.drawImage(img, 0, 0);

            return tempCanv.toDataURL();
        }

        var handleOrientationChange = function (e) {
            var angleRad = Math.PI / 2;
            var image = new Image();
            var isPortaitOrientaion = e.matches;

            image.onload = function () {

                rotateSignatureToolbar(isPortaitOrientaion);
                setCanvasSize(isPortaitOrientaion);
                var rotatedImageDataURL = rotateImage(image, isPortaitOrientaion ? angleRad : -angleRad);

                var rotatedImage = new Image();

                rotatedImage.onload = function () {
                    var canvasContext = canvas[0].getContext('2d');
                    clearCanvas(canvasContext);
                    canvasContext.drawImage(rotatedImage, 0, 0);
                }

                rotatedImage.src = rotatedImageDataURL;
            }

            image.src = canvas[0].toDataURL();
        }

        var goInFullscreen = function (element) {
            if (element.requestFullscreen)
                return element.requestFullscreen();
            else if (element.mozRequestFullScreen)
                return element.mozRequestFullScreen();
            else if (element.webkitRequestFullscreen)
                return element.webkitRequestFullscreen();
            else if (element.msRequestFullscreen)
                return element.msRequestFullscreen();
        }

        var goOutFullscreen = function () {
            if (document.exitFullscreen)
                document.exitFullscreen();
            else if (document.mozCancelFullScreen)
                document.mozCancelFullScreen();
            else if (document.webkitExitFullscreen)
                document.webkitExitFullscreen();
            else if (document.msExitFullscreen)
                document.msExitFullscreen();
        }

        var getScreenSize = function () {

            return {
                height: document.documentElement.clientHeight,
                width: document.documentElement.clientWidth
            };
        }

        var rotateSignatureToolbar = function (isPortaitOrientaion) {
            var $signaturePad = $(SIGNATURE_PAD_SELECTOR);
            var signatureComponentsContainer = $signaturePad.find('.signature-components-container');
            var screenSize = getScreenSize();

            signatureComponentsContainer.find('.sig-name-container').attr('style', 'top: ' +
                ((isPortaitOrientaion ? screenSize.width : screenSize.height) - 50) + 'px');

            if (isPortaitOrientaion) {
                var canvasHeight = screenSize.height - SIGNATURE_TOOLBAR_WIDTH;
                signatureComponentsContainer.attr('style', 'transform: rotate(90deg) translate(' + canvasHeight + 'px,' + SIGNATURE_TOOLBAR_WIDTH + 'px); width: ' + screenSize.height + 'px;');
                $signaturePad.find('.sig-wrapper').removeClass('signature-toolbar-padding');
            } else {
                signatureComponentsContainer.attr('style', 'width: ' + screenSize.width + 'px;');
                $signaturePad.find('.sig-wrapper').addClass('signature-toolbar-padding');
            }
        }

        var setCanvasSize = function (isPortaitOrientaion) {
            var screenSize = getScreenSize();

            if (isPortaitOrientaion) {
                canvas[0].height = screenSize.height;
                canvas[0].width = screenSize.width - SIGNATURE_TOOLBAR_HEIGHT;
            } else {
                canvas[0].height = screenSize.height - SIGNATURE_TOOLBAR_HEIGHT;
                canvas[0].width = screenSize.width;
            }
        }

        var clearCanvas = function (ctx) {
            ctx.fillStyle = "transparent";
            ctx.fillRect(0, 0, ctx.canvas.width, ctx.canvas.height);
        }

        var generateSignatureOnCanvas = function (canvasContext, username) {
            handleActionAnnouncement('Signature generated successfully', 1);

            canvasContext.textAlign = 'center';
            canvasContext.fillStyle = '#145394';
            canvasContext.font = 'normal 300 40px "La Belle Aurore", cursive';

            canvasContext.fillText(username, canvasContext.canvas.width / 2, 2 * canvasContext.canvas.height / 3);
            return canvasContext;
        }

        var loadUserName = function () {
            OnlineApp.Services.authenticationService.getUserData()
                .then(function (data) {
                    self.username(data.username);
                });
        }

        var handleActionAnnouncement = function (message, index) {
            var signatureContainer = $('.signature-container')[0];
            var announcementText = $(signatureContainer).find('.sr-notification')[index];

            OnlineApp.Helpers.layoutHelper.tabbing.updateIndices(signatureContainer);

            gJobs.screenReadersService.setNotification($(announcementText), message, null, true);
        }
       
    }

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        SignatureViewModel: SignatureViewModel
    });
})(window);
;
(function (window, undefined) {
    'use strict';


    var controlStates = {
        loading: 'loading',
        scheduling: 'scheduling',
        schedulingLoaded: 'scheduling-loaded',
        scheduled: 'scheduled',
        confirmed: 'confirmed',
        eligible: 'eligible',
        notimeslots: 'no-time-slots'
    };


    function ScheduleExamViewModel() {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;

        self.applicationId = ko.observable();

        self.evaluationStep = ko.observable();

        self.evaluationStepId = ko.observable();

        self.state = ko.observable(controlStates.scheduling);

        self.exams = ko.observableArray();

        self.customMessage = ko.observable();
        
        self.timeZoneText = ko.observable();

        self.isBusy = ko.observable(false);

        self.calendarEventLinks = ko.observable('');

        self.selectedExam = ko.computed(function () {
            return ko.utils.arrayFirst(self.exams(), function (exam) {
                return exam.selectedTimeSlot();
            });
        });

        self.hasFreeTimeSlots = ko.computed(function () {
            var freeTimeSlots = 0;

            ko.utils.arrayForEach(self.exams(), function (exam) {
                ko.utils.arrayForEach(exam.daySlots(), function (daySlot) {
                    freeTimeSlots += daySlot.timeSlots().length;
                });
            });

            return (freeTimeSlots > 0);
        });

        self.selectTimeSlot = function (timeSlot) {
            var selectedExam = self.selectedExam();
            var selectedTimeSlot = selectedExam && selectedExam.selectedTimeSlot();

            if (selectedTimeSlot) {
                self.unselectTimeSlot(selectedTimeSlot);
            }

            timeSlot.isSelected(true);

            gJobs.screenReadersService.setAriaLiveNotification(timeSlot.label());
        };

        self.unselectTimeSlot = function (timeSlot) {
            timeSlot.isSelected(false);
        };

        self.scheduleExamAsync = function () {

            self.isBusy(true);

            var promise = OnlineApp.Services.dataService.exam.post({
                examId: self.selectedExam().selectedTimeSlot().examId(),
                examDateTime: self.selectedExam().selectedTimeSlot().dateTime(),
                applicationId: self.applicationId(),
                evaluationStep: self.evaluationStep(),
                evaluationStepId: self.evaluationStepId()
            });

            OnlineApp.Helpers.ajaxResponseValidator.ensurePromiseFailsOnInvalidData(promise)
                .done(function (data) {
                    self.calendarEventLinks(data.calendarLinks);
                    self.state(controlStates.confirmed);

                    attachHandlersToCalendarEventLinks();
                })
                .fail(function () {
                    toastr.error('Exam scheduling has failed! Try again later.');
                })
                .always(function () {
                    self.isBusy(false);
                });

            return promise;
        };

        self.unsheduleExamAsync = function () {

            self.isBusy(true);

            var examData = {
                applicationId: self.applicationId(),
                evaluationStep: self.evaluationStep(),
                evaluationStepId: self.evaluationStepId()
            };
            var promise = OnlineApp.Services.dataService.exam['delete'](null, examData);

            OnlineApp.Helpers.ajaxResponseValidator.ensurePromiseFailsOnInvalidData(promise)
                .done(function () {
                    gJobs.screenReadersService.silenceScreenreader();
                    self.state(controlStates.scheduling);
                    gJobs.applicationsPage && gJobs.applicationsPage.scheduleExamViewModel.state('loading');
                    OnlineApp.Services.dataService.exam.get(null, examData)
                        .always(function () {
                            if (gJobs.applicationsPage && gJobs.applicationsPage.currentExamSubscription) {
                                gJobs.applicationsPage.currentExamSubscription.dispose();
                                gJobs.applicationsPage.currentExamSubscription = null;
                            }
                        })
                        .done(function (data) {
                            $.extend(data, examData);
                            if (gJobs.applicationsPage) {
                                var scheduleExamViewModel = gJobs.applicationsPage.scheduleExamViewModel;
                                scheduleExamViewModel.fromDataModel(data);
                                gJobs.applicationsPage.currentExamSubscription = scheduleExamViewModel.state.subscribe(gJobs.applicationsPage.stateChangeHandler);
                            }
                            $(document).trigger(Events.CommonEventsNames.AppointmentFlyoutStateChanged, {
                                state: controlStates.schedulingLoaded
                            });
                        });
                })
                .fail(function () {
                    toastr.error('Exam unscheduling has failed! Try again later.');
                })
                .always(function () {
                    self.isBusy(false);
                });

            return promise;
        };

        self.isSelfSchedulingDeadlineExpired = ko.computed(function () {
            if (!self.selectedExam())
                return false;

            return self.selectedExam().isSelfSchedulingDeadlineExpired();
        });

        self.fromDataModel = function (data) {
            if (!data) {
                return;
            }

            self.applicationId(data.applicationId);
            self.evaluationStep(data.evaluationStep);
            self.evaluationStepId(data.evaluationStepId);
            self.customMessage(data.customMessage);
            self.timeZoneText(data.timeZoneText);
            self.calendarEventLinks(data.calendarLinks);

            self.exams(ko.utils.arrayMap(data.examList, function (item) {
                var viewModel = new ExamViewModel();
                viewModel.fromDataModel(item);

                return viewModel;
            }));

            var state = controlStates.scheduling;

            if (!self.hasFreeTimeSlots()) {
                state = controlStates.notimeslots;
            }

            if (data.customMessage) {
                state = controlStates.eligible;
            }

            if (data.isScheduledForExam) {
                state = controlStates.scheduled;
            }

            self.isScheduledForExam = data.isScheduledForExam;
            self.state(state);

            if (!!data.calendarLinks) {
                attachHandlersToCalendarEventLinks();
            }
        };

        self.state.subscribe(function (oldValue) {
            self.lastState = oldValue;
        }, null, "beforeChange");

        self.state.subscribe(function (state) {
            $(document).trigger(Events.CommonEventsNames.AppointmentFlyoutStateChanged, {
                state: state,
                lastState: self.lastState,
                isScheduledForExam: self.isScheduledForExam
            });
        });

        var attachHandlersToCalendarEventLinks = function () {
            $('.add-to-calendar a').on('click', function (e) {
                var $target = $(e.target);
                gJobs.common.analytics.trackEvent(
                    gJobs.common.analytics.categories.application,
                    'SelfSchedule',
                    $target.text()
                );
            });
        }
    };

    function ExamViewModel() {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;

        self.location = new ExamLocationViewModel();

        self.daySlots = ko.observableArray();

        self.selectedTimeSlot = ko.computed(function () {

            var daySlot = ko.utils.arrayFirst(self.daySlots(), function (daySlot) {
                return daySlot.selectedTimeSlot();
            });


            if (daySlot) {
                return daySlot.selectedTimeSlot();
            }
        });

        self.displaySheduledDateTime = ko.computed(function () {
            if (!self.selectedTimeSlot()) {
                return;
            }

            var daySlot = ko.utils.arrayFirst(self.daySlots(), function (daySlot) {
                return daySlot.selectedTimeSlot();
            });

            var displayString =
                daySlot.displayDate() + ', ' +
                self.selectedTimeSlot().localDateTime().getFullYear() + ' at ' +
                self.selectedTimeSlot().displayTime();

            return displayString;
        });

        self.isSelfSchedulingDeadlineExpired = ko.computed(function () {
            if (!self.selectedTimeSlot())
                return false;

            return self.selectedTimeSlot().isSelfSchedulingDeadlineExpired();
        });

        self.fromDataModel = function (data) {
            if (!data) {
                return;
            }

            self.location.fromDataModel(data.examLocation);
            self.daySlots((function () {

                var timeSlotViewModels = ko.utils.arrayMap(data.timeSlots, function (item) {
                    var timeSlotViewModel = new TimeSlotViewModel();
                    timeSlotViewModel.fromDataModel(item);

                    return timeSlotViewModel;
                });

                var daySlotsObject = (function () {
                    var daySlotsObject = {};

                    ko.utils.arrayForEach(timeSlotViewModels, function (item) {
                        var timeSlotHash = item.localDateTime().toDateString()
                        var daySlotViewModel = daySlotsObject[timeSlotHash];

                        if (!daySlotViewModel) {
                            daySlotViewModel = new DaySlotViewModel();
                            daySlotViewModel.date(new Date(timeSlotHash));
                        }

                        daySlotViewModel.timeSlots.push(item);

                        daySlotsObject[timeSlotHash] = daySlotViewModel;
                    });

                    return daySlotsObject;
                })();

                var daySlots = (function () {
                    var daySlots = [];

                    for (var propertyName in daySlotsObject) {
                        if (daySlotsObject.hasOwnProperty(propertyName)) {
                            daySlots.push(daySlotsObject[propertyName]);
                        }
                    }

                    return daySlots;
                })();

                return daySlots;
            })());
        }
    };


    function ExamLocationViewModel() {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;


        self.address = new OnlineApp.ViewModels.Common.AddressViewModel();

        self.title = ko.observable();

        self.phone = ko.observable();


        self.fromDataModel = function (data) {
            if (!data) {
                return;
            }

            self.address.fromDataModel(data.address);
            self.title(data.locationTitle);
            self.phone(data.phone);
        }
    };


    function DaySlotViewModel() {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;


        self.date = ko.observable(new Date());

        self.displayDate = ko.computed(function () {
            var dateTime = self.date();
            var formattedDate = OnlineApp.Helpers.DateTimeFormatter.getFullDate(dateTime);

            return formattedDate;
        });
        
        self.timeSlots = ko.observableArray();

        self.selectedTimeSlot = ko.computed(function () {
            var timeSlots = self.timeSlots();

            var timeSlot = ko.utils.arrayFirst(timeSlots, function (timeSlot) {
                return timeSlot.isSelected();
            });

            return timeSlot;
        });
    };

    function TimeSlotViewModel() {

        var self = OnlineApp.ViewModels.Base.BaseViewModel.apply(this, arguments) || this;


        self.isSelected = ko.observable();
        
        self.examId = ko.observable();

        self.dateTime = ko.observable();

        self.localDateTime = ko.observable(new Date());

        self.displayDate = null;

        self.displayTime = ko.computed(function () {
            var dateTime = self.localDateTime();
            var formattedTime = OnlineApp.Helpers.DateTimeFormatter.getMilitaryTime(dateTime);

            return formattedTime;
        });

        self.label = ko.computed(function () {
            return (self.isSelected() ? '' : 'Schedule appointment for ')
                + OnlineApp.Helpers.DateTimeFormatter.getFullDateNoDay(self.localDateTime()) + ' ' + self.displayTime()
                + (self.isSelected() ? ' selected' : '');
        });

        self.isSelfSchedulingDeadlineExpired = ko.observable();

        self.fromDataModel = function (data) {
            if (!data) {
                return;
            }

            self.examId(data.examId);
            self.isSelected(data.isSelected);
            self.dateTime(data.date);
            self.localDateTime(new Date(data.dateWithAppliedTimeZonesForDisplayInUi));
            self.isSelfSchedulingDeadlineExpired(data.isSelfSchedulingDeadlineExpired);

            self.displayDate = data.dateWithAppliedTimeZonesForDisplayInUi;
        };
    };

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        ScheduleExamViewModel: ScheduleExamViewModel
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function OfferViewModel() {
        var self = OnlineApp.ViewModels.Base.DataViewModel.apply(this, arguments) || this;

        var offerStatusEnum = { Rejected: 0, Accepted: 1, AnswerPending: 2 };

        self.isMobile = gJobs.browserDetector.isMobileBrowser();
        self.offerId = ko.observable(0);
        self.jobTitle = ko.observable('');
        self.description = ko.observable('');
        self.dueDate = ko.observable('');
        self.offerStatus = ko.observable();
        self.attachments = ko.observableArray([]);
        self.dateAnswered = ko.observable('');
        self.isRejected = offerStatusEnum.Rejected;
        self.signatureViewModel = new OnlineApp.ViewModels.SignatureViewModel();

        self.isSubmitted = false;

        self.isRejectReasonSectionVisible = ko.observable(false);
        self.rejectReason = ko.observable('').extend({
            length: {
                max: 1000,
                validationMessage: 'Reject reason is too long and is limited to 1000 characters'
            }
        });

        self.fileDownloadUrl = function(attachmentId) {
            return '/api/attachments/downloadAttachmentForOffer?offerId=' + 
                self.offerId() + '&attachmentId=' + attachmentId;
        };

        self.isReadOnlyView = ko.computed(function () { 
            return self.offerStatus() === offerStatusEnum.Rejected || self.offerStatus() === offerStatusEnum.Accepted;
        });

        self.isReadOnlyView.subscribe(function (value) {
            self.signatureViewModel.isReadOnlyView(value);
        });

        self.fromDataModel = function(data) {
            self.offerId(data.offerId);
            self.jobTitle(data.jobTitle);
            self.description(data.description);
            self.dueDate(data.dueDate);
            self.offerStatus(data.offerStatus);
            self.attachments(data.attachments);
            self.dateAnswered(data.dateAnswered);
            self.isSubmitted = false;

            self.signatureViewModel.fromDataModel(data.signature, self.isReadOnlyView(), data.dateAnswered);

            var isMobile = gJobs.browserDetector.isMobileBrowser();
            $('a.ss-print.popover-trigger')
                .attr('href', '/applications/offerletter/print/' + self.offerId())
                .attr('hidden', isMobile);
            $('a.ss-download.popover-trigger')
                .attr('href', '/api/offer/downloadOffer?offerId=' + self.offerId());
        };

        self.acceptClick = function() {
            if (self.isSubmitted) {
                return;
            }

            self.isSubmitted = true;

            var signature = self.signatureViewModel.signature();
            OnlineApp.Services.dataService.offer.post({
                id: self.offerId(),
                offerStatus: offerStatusEnum.Accepted,
                signature: signature
            }).then(function (data) {
                if (data.isSuccess) {
                    OnlineApp.Services.offerFlyoutService.changeOfferStatus(self.offerId(), true);
                    closeFlyout();
                    toastr.success('Offer Accepted');
                }
            }).fail(function () {
                self.isSubmitted = false;
            });
        }

        self.rejectOffer = function () {
            if (self.isSubmitted) {
                return;
            }

            self.isSubmitted = true;

            if (!self.rejectReason.validate()) {
                return;
            }

            OnlineApp.Services.dataService.offer.post({
                id: self.offerId(),
                offerStatus: offerStatusEnum.Rejected,
                rejectReason: self.rejectReason()
            }).then(function (data) {
                if (data.isSuccess) {
                    OnlineApp.Services.offerFlyoutService.changeOfferStatus(self.offerId(), false);
                    closeFlyout();
                    toastr.success('Offer Rejected');
                    self.hideRejectReasonSection();
                }
            }).fail(function (data) {
                var response = JSON.parse(data.responseText);
                OnlineApp.Helpers.Notifications.showResponseMessages(response);
                self.isSubmitted = false;
            });
        }

        self.hideRejectReasonSection = function () {
            self.isRejectReasonSectionVisible(false);
            $('#reject-offer-button').focus();
        }

        self.showRejectReasonSection = function () {
            self.isRejectReasonSectionVisible(true);
            $('#reject-reason').focus();
        }

        self.showRejectReasonModal = function () {
            var rejectReasonTextArea =
                '<textarea id="reject-reason-modal-textarea" maxlength="1000"'
                + 'type="text" placeholder="Input your reject reason here">'
                + ko.utils.unwrapObservable(self.rejectReason)
                + '</textarea>';

            $(document).trigger(
                Events.CommonEventsNames.ShowConfirmDialog,
                {
                    header: 'Reject Offer Letter',
                    subHeader: 'Are you sure you want to reject this offer letter?',
                    confirmButtonText: 'Reject',
                    additionalCssClassName: 'reject-offer-letter-dialog',
                    innerHtml: rejectReasonTextArea,
                    confirmClick: function () {
                        populateRejectReasonFromModalTextarea();
                        self.rejectOffer();
                    },
                    cancelClick: function () {
                        populateRejectReasonFromModalTextarea();
                    }
                }
            );
        }

        function populateRejectReasonFromModalTextarea() {
            var $rejectReasonModalTextarea = $('#reject-reason-modal-textarea');
            if ($rejectReasonModalTextarea.length) {
                self.rejectReason($rejectReasonModalTextarea.val());
            }
        }

        function closeFlyout() {
            if (gJobs.areaInfoService.getCurrentArea() == gJobs.areaInfoService.areaNames.Career) {
                AgencyPages.offerFlyout.close();
            } else {
                gJobs.applicationsPage.offerFlyout.close();
            }
        }
    };

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        OfferViewModel: OfferViewModel
    });
})(window);;
(function (window, undefined) {
    'use strict';


    function DefinitionViewModel() {
        var self = this;

        self.items = ko.observableArray();

        self.findItemByField = function (fieldName, fieldValue) {
            var items = self.items();
            for (var i in items) {
                var item = items[i];

                if (item.hasOwnProperty(fieldName) && item[fieldName] == fieldValue) {
                    return item;
                }
            }
            return {};
        };

        self.findItemById = function (id) {
            return self.findItemByField("id", id);
        };
    }


    function ConstantDefinitionViewModel(items) {
        var self = DefinitionViewModel.apply(this, arguments) || this;

        self.items(items);
    }


    function ServiceBasedDefinitionViewModel(dataServiceEndpoint) {
        var self = DefinitionViewModel.apply(this, arguments) || this;


        var items = [];


        var loadItemsAsync = function () {
            dataServiceEndpoint
                .get()
                .done(function (data) {
                    items = data;
                    self.isLoaded(true);
                });
        };


        self.isLoaded = ko.observable(false);

        self.items = ko.computed(function () {
            if (!self.isLoaded()) {
                loadItemsAsync();
            }

            return items;
        });
    }

    function DeferredDefinitionViewModel() {
        var self = DefinitionViewModel.apply(this, arguments) || this;

        var deferred = $.Deferred();
        var promise = deferred.promise();

        self.setItems = function (definition) {
            deferred.resolve(definition);
            self.variableItems(definition);
        }

        self.resetItems = function() {
            deferred.reject();
        }

        self.variableItems = ko.observableArray([]);

        self.items = ko.computed(function () {
            return self.variableItems();
        });

        self.get = function() {
            return promise;
        }
    }

    function DefinitionsViewModel(fetchDeferredDefinitions) {
        var self = this;

        var endpoints = OnlineApp.Services.dataService.definitions;

        // todo: combine this logic into CompositeDefinitionsViewModel
        for (var endpointName in endpoints) {
            if (endpoints.hasOwnProperty(endpointName)) {
                self[endpointName] = new DeferredDefinitionViewModel();
            }
        }

        if (fetchDeferredDefinitions) {

            OnlineApp.Services.dataService.PastFutureRange
                .get()
                .done(function (range) {
                    var currentTime = new Date();
                    var currentYear = currentTime.getFullYear();

                    var pastRange = new Array();
                    for (var i = currentYear; i >= range.data.minYear; i--) {
                        pastRange.push({ id: i, text: i });
                    }
                    self.PastToPresentYear.setItems(pastRange);
                    
                    var pastFutureRange = new Array();
                    for (var i = range.data.maxYear; i >= range.data.minYear; i--) {
                        pastFutureRange.push({ id: i, text: i });
                    }
                    self.PastToFutureYear.setItems(pastFutureRange);
                });

            OnlineApp.Services.dataService.compositeDefinitions
                .get()
                .done(function(definitions) {
                    for (var endpointName in endpoints) {
                        if (endpoints.hasOwnProperty(endpointName)) {
                            self[endpointName].setItems(definitions[endpointName]);
                        }
                    }
                })
                .fail(function() {
                    for (var endpointName in endpoints) {
                        if (endpoints.hasOwnProperty(endpointName)) {
                            self[endpointName].resetItems();
                        }
                    }
                });
                
            OnlineApp.Services.dataService.InvalidSsnValues
                .get()
                .done(function (invalidSsnValues) {
                    self.invalidSsnValues = invalidSsnValues;
                });
        }

        //fetch required data
        OnlineApp.Services.dataService.sessionExpirationData
            .get()
            .done(function (sessionExpirationData){
                self.sessionExpirationData.setItems(sessionExpirationData);
            })
            .fail(function() {
                self.sessionExpirationData.resetItems();
            })

        self.PastToPresentYear = new DeferredDefinitionViewModel();
        self.PastToFutureYear = new DeferredDefinitionViewModel();
        self.sessionExpirationData = new DeferredDefinitionViewModel();

        self.invalidSsnValues = new Array();

        self.menuStepIds = {
            loginSuccess: 0,
            loginFailure: 1,
            resume: 2,
            info: 3,
            work: 4,
            education: 5,
            additional: 6,
            references: 7,
            questions: 8,
            attachments: 9,
            review: 10,
            submit: 11,
            profile: 12,
            register: 13,
            payment: 14,
            contactInfo: 15,
            changePassword: 16,
            deleteAccount: 17,
            emailPreferences: 18,
            preferences: 19,
            textMessagingPreferences: 20,
            twoFactorPreferences: 21
        };

        self.menuStep = new ConstantDefinitionViewModel([
            { id: self.menuStepIds.loginSuccess, text: 'LoginSuccess'},
            { id: self.menuStepIds.loginFailure, text: 'LoginFailure'},
            { id: self.menuStepIds.resume, text: 'Resume', tabId:'#resume-tab'},
            { id: self.menuStepIds.info, text: 'Info', tabId: '#general-info-tab'},
            { id: self.menuStepIds.work, text: 'Work', tabId: '#work-tab' },
            { id: self.menuStepIds.education, text: 'Education', tabId: '#education-tab' },
            { id: self.menuStepIds.additional, text: 'Additional', tabId: '#additional-info-tab' },
            { id: self.menuStepIds.references, text: 'References', tabId: '#references-tab' },
            { id: self.menuStepIds.questions, text: 'Questions', tabId: '#questions-tab' },
            { id: self.menuStepIds.attachments, text: 'Attachments', tabId:  '#attachments-tab'},
            { id: self.menuStepIds.review, text: 'Review', tabId: '#review-tab' },
            { id: self.menuStepIds.submit, text: 'Submit', tabId: '#submit-tab' },
            { id: self.menuStepIds.profile, text: 'Profile', tabId: '#profile-tab' },
            { id: self.menuStepIds.register, text: 'Register' },
            { id: self.menuStepIds.payment, text: 'Payment', tabId: '#payment-tab' },
            { id: self.menuStepIds.contactInfo, text: 'Contact Info', tabId: '#contact-info-tab' },
            { id: self.menuStepIds.changePassword, text: 'Change Password', tabId: '#change-password-tab' },
            { id: self.menuStepIds.deleteAccount, text: 'DeleteAccount', tabId: '#delete-account-tab' },
            { id: self.menuStepIds.emailPreferences, text: 'Email Preferences', tabId: '#email-preferences-tab' },
            { id: self.menuStepIds.preferences, text: 'Preferences', tabId: '#preferences-tab' },
            { id: self.menuStepIds.textMessagingPreferences, text: 'Text Messaging Preferences', tabId: '#text-messaging-preferences-tab' },
            { id: self.menuStepIds.twoFactorPreferences, text: 'Two Factor Preferences', tabId: '#two-step-verification-tab' }
        ]);

        // generate days array
        var days = [];
        for (var i = 1; i <= 31; i++) {
            days.push({
                id: i,
                text: i + ''
            });
        }
        self.day = new ConstantDefinitionViewModel(days);

        self.month = new ConstantDefinitionViewModel([
            { id: 1, text: 'January' },
            { id: 2, text: 'February' },
            { id: 3, text: 'March' },
            { id: 4, text: 'April' },
            { id: 5, text: 'May' },
            { id: 6, text: 'June' },
            { id: 7, text: 'July' },
            { id: 8, text: 'August' },
            { id: 9, text: 'September' },
            { id: 10, text: 'October' },
            { id: 11, text: 'November' },
            { id: 12, text: 'December' }
        ]);
        
        self.educationUnitType = new ConstantDefinitionViewModel([
            { id: 'Semester', text: 'Semester Units' },
            { id: 'Quarter', text: 'Quarter Units' }
        ]);

        self.extendedMonth = new ConstantDefinitionViewModel([
            { id: 1, text: 'January' },
            { id: 2, text: 'February' },
            { id: 3, text: 'March' },
            { id: 4, text: 'April' },
            { id: 5, text: 'May' },
            { id: 6, text: 'June' },
            { id: 7, text: 'July' },
            { id: 8, text: 'August' },
            { id: 9, text: 'September' },
            { id: 10, text: 'October' },
            { id: 11, text: 'November' },
            { id: 12, text: 'December' },
            { id: 14, text: 'Present' }
        ]);

        self.monthWithNoExpiration = new ConstantDefinitionViewModel([
            { id: 1, text: 'January' },
            { id: 2, text: 'February' },
            { id: 3, text: 'March' },
            { id: 4, text: 'April' },
            { id: 5, text: 'May' },
            { id: 6, text: 'June' },
            { id: 7, text: 'July' },
            { id: 8, text: 'August' },
            { id: 9, text: 'September' },
            { id: 10, text: 'October' },
            { id: 11, text: 'November' },
            { id: 12, text: 'December' },
            { id: 15, text: 'No Expiration' }
        ]);
        
        self.year = new ConstantDefinitionViewModel([
            { id: 2013, text: '2013' },
            { id: 2012, text: '2012' },
            { id: 2011, text: '2011' },
            { id: 2010, text: '2010' },
            { id: 2009, text: '2009' },
            { id: 2008, text: '2008' },
            { id: 2007, text: '2007' },
            { id: 2006, text: '2006' },
            { id: 2005, text: '2005' },
            { id: 2004, text: '2004' },
            { id: 2003, text: '2003' },
            { id: 2002, text: '2002' },
            { id: 2001, text: '2001' },
            { id: 2000, text: '2000' },
            { id: 1999, text: '1999' },
            { id: 1998, text: '1998' },
            { id: 1997, text: '1997' },
            { id: 1996, text: '1996' },
            { id: 1995, text: '1995' },
            { id: 1994, text: '1994' },
            { id: 1993, text: '1993' },
            { id: 1992, text: '1992' },
            { id: 1991, text: '1991' },
            { id: 1990, text: '1990' },
            { id: 1989, text: '1989' },
            { id: 1988, text: '1988' },
            { id: 1987, text: '1987' },
            { id: 1986, text: '1986' },
            { id: 1985, text: '1985' },
            { id: 1984, text: '1984' },
            { id: 1983, text: '1983' },
            { id: 1982, text: '1982' },
            { id: 1981, text: '1981' },
            { id: 1980, text: '1980' },
            { id: 1979, text: '1979' },
            { id: 1978, text: '1978' },
            { id: 1977, text: '1977' },
            { id: 1976, text: '1976' },
            { id: 1975, text: '1975' },
            { id: 1974, text: '1974' },
            { id: 1973, text: '1973' },
            { id: 1972, text: '1972' },
            { id: 1971, text: '1971' },
            { id: 1970, text: '1970' }
        ]);

        var expirationYears = [];
        var maxExpirationYearSeed = 15;
        var currentYear = new Date().getFullYear();
        var maxExpirationYear = currentYear + maxExpirationYearSeed;
        for (var i = currentYear; i < maxExpirationYear; i++) {
            expirationYears.push({ id: i, text: i.toString() });
        }
        self.expirationYear = new ConstantDefinitionViewModel(expirationYears);
        
        self.notificationType = new ConstantDefinitionViewModel([
            { id: 0, text: 'None' },
            { id: 1, text: 'Email' },
            { id: 2, text: 'Paper' }
        ]);

        self.relocationType = new ConstantDefinitionViewModel([
            { id: 0, text: 'None' },
            { id: 1, text: 'Yes' },
            { id: 2, text: 'No' },
            { id: 3, text: 'Maybe' },
            { id: 4, text: 'No Response' }
        ]);

        self.shiftType = new ConstantDefinitionViewModel([
            { id: 0, text: 'None' },
            { id: 1, text: 'Day' },
            { id: 2, text: 'Evening' },
            { id: 3, text: 'Night' },
            { id: 4, text: 'Rotating' },
            { id: 5, text: 'Weekends' },
            { id: 6, text: 'On Call' }
        ]);

        self.positionType = new ConstantDefinitionViewModel([
            { id: 0, text: 'None' },
            { id: 1, text: 'Regular' },
            { id: 2, text: 'Temporary' },
            { id: 3, text: 'Seasonal' },
            { id: 4, text: 'Internship' }
        ]);

        self.workType = new ConstantDefinitionViewModel([
            { id: 0, text: 'None' },
            { id: 1, text: 'Full Time' },
            { id: 2, text: 'Part Time' },
            { id: 3, text: 'Per Diem' }
        ]);

        self.level = new ConstantDefinitionViewModel([
            { id: 0, text: 'None' },
            { id: 1, text: 'Beginner' },
            { id: 2, text: 'Intermediate' },
            { id: 3, text: 'Expert' }
        ]);

        self.referenceType = new ConstantDefinitionViewModel([
            { id: 0, text: 'Personal' },
            { id: 1, text: 'Professional' }
        ]);

        self.creditCardType = new ConstantDefinitionViewModel([
            { id: 1, text: 'American Express' },
            { id: 2, text: 'Discover' },
            { id: 3, text: 'MasterCard' },
            { id: 4, text: 'Visa' }
        ]);
        
        self.disabilityAnswer = new ConstantDefinitionViewModel([
            { id: 1, text: 'No' },
            { id: 2, text: 'Yes' },
            { id: 3, text: 'NoAnswer' }
        ]);
    }


    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        DefinitionsViewModel: DefinitionsViewModel
    });

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        ServiceBasedDefinitionViewModel: ServiceBasedDefinitionViewModel
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function FileUploadViewModel() {

        var self = this;

        self.currentlyUploadingFile = ko.observable('');
        self.fileUploadComplete = ko.observable(false);
        self.fileUploadError = ko.observable('');
        self.progressPercent = ko.observable(0);

        self.supportsUploadProgress = ko.observable(true);
        self.fileUploadCancelable = ko.observable(true);

        self.fileIsPasswordProtected = ko.observable(false);

        /**
         * Should be overriden in Attachments.
         */
        self.showFileSelect = function (data, evnt) {
            $(evnt.target).closest('form').find('input').get(0).click();
        };

        /**
         * Should be overriden and called at the end to start uploading.
         * $(this).data('blueimpFileupload').options.url should be changed.
         */
        self.onFileAdd = function (e, data) {

            self.fileUploadJQXHR = data.submit();

            //return focus to main frame. Needed in case of iframe uploads because otherwise clicking buttons doesn't work
            window.focus();
        };

        self.onFileSend = function (e, data) {
            self.currentlyUploadingFile(data.files[0].name);
            self.fileUploadCancelable(true);
            self.fileUploadComplete(false);
            self.fileUploadError('');
            self.progressPercent(0);
            self.fileIsPasswordProtected(false);

            if (data.dataType && data.dataType.substr(0, 6) === 'iframe') {
                self.supportsUploadProgress(false);
            } else {
                self.supportsUploadProgress(true);
            }
        };

        self.onUploadProgress = function (e, data) {
            if (self.supportsUploadProgress()) {
                self.progressPercent(parseInt(data.loaded / data.total * 100, 10));
            }
        };

        /**
         * Should be overriden and called at the end to finish uploading.
         */
        self.onUploadDone = function (e, data) {

            if (data.result && data.result.status === 'OK') {
                self.fileUploadComplete(true);
            } else {
                self.fileUploadError(data.errorThrown || self.getDefaultUploadErrorMessage());
            }
        };

        self.onUploadFail = function (e, data) {
            self.fileUploadError(data.errorThrown);
        };

        self.cancelFileUpload = function () {
            self.fileUploadJQXHR.abort();
            self.currentlyUploadingFile('');
        };

        self.goBackFromError = function () {
            self.currentlyUploadingFile('');
            OnlineApp.Helpers.layoutHelper.tabbing.activateFirstElement();
        };
        self.goBackFromErrorSupplementalAttachment = function () {
            self.currentlyUploadingFile('');
            
        };
        
        self.getDefaultUploadErrorMessage = function () {
            return "An error occurred uploading file " + self.currentlyUploadingFile() + ".";
        };
    }

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        FileUploadViewModel: FileUploadViewModel
    });
    
})(window);
;
(function (window, undefined) {
    'use strict';

    var captchaHelper = new OnlineApp.Helpers.CaptchaHelper('#contact-info-tab');
    var layoutHelper = OnlineApp.Helpers.layoutHelper;

    function ContactInfoViewModel(config) {
        var config = $.extend({}, {
            endpoint: "contactInfo",
            get: false // data is loaded in parent View-Model
        }, config);

        var contactInfoSaveButtonSelector = '#contact-info-tab .form-actions .btn-app-primary-save';

        var pageInfoService = gJobs.pageInfoService ? gJobs.pageInfoService : AgencyPages.pageInfoService;
        var currentPage = pageInfoService.getCurrentPageType();
        var currentPageType;
        var pageTypes = pageInfoService.getPageTypes();

        if (currentPage) {
            currentPageType = currentPage.type;
        }

        var self = OnlineApp.ViewModels.Base.EditableViewModel.call(this, config) || this;

        self.isDiscardChange = ko.observable(false);

        self.radioButtonOptions = ko.observable({
            notificationPreference: [
                {
                    value: '1',
                    id: 'contact-info-notification-preference-email',
                    name: 'ci-radioSet-notify',
                    label: 'Email'
                },
                {
                    value: '2',
                    id: 'contact-info-notification-preference-paper',
                    name: 'ci-radioSet-notify',
                    label: 'Paper'
                }
            ]
        }).extend({ ignoreOnSerialization: true });

        self.enableEmailVerification = ko.observable(window.enableEmailVerification);
        self.fromAppProcess = ko.observable(window.utils.getUrlParameter("fromAppProcess").trim() === 'true'  ? true : false);
        self.isEmailVerified = ko.observable();
        self.isAccountSettingsPage  = ko.observable(currentPageType === pageTypes.accountSettings.type);

        var initialFullName;
        self.name = new OnlineApp.ViewModels.Common.NameViewModel();
        self.address = new OnlineApp.ViewModels.Common.AddressViewModel();
        self.phone = new OnlineApp.ViewModels.Common.PhoneViewModel();
        self.textCaptchaViewModel = new OnlineApp.ViewModels.TextCaptchaViewModel();


        self.initContactInfoEmailVerificationViewModel = function (options) {
            if (!self.contactInfoEmailVerificationViewModel) {
                self.contactInfoEmailVerificationViewModel = new OnlineApp.ViewModels.ContactInfoEmailVerificationViewModel();
            }

            if (options) {
                self.contactInfoEmailVerificationViewModel
                    .emailVerificationViewModel
                    .changedEmailAddressWasAdded = ko.observable(options.changedEmailAddressWasAdded);
            }

            self.contactInfoEmailVerificationViewModel.emailVerificationViewModel.initUserData();

            OnlineApp.Services.emailVerificationService.isEmailVerified().then(function(response) {
                var data = response.data;

                self.isEmailVerified(data.isEmailVerified);
            });
        };
        
        if (self.enableEmailVerification() && self.isAccountSettingsPage() && !self.fromAppProcess()) {
            OnlineApp.Services.authenticationService.isLoggedIn()
            .done(function (isLoggedIn) {
                if (isLoggedIn) {
                   self.initContactInfoEmailVerificationViewModel();
                }
            });
        }


        // todo: implement EmailAvailabilityValidator (promise-based)
        // todo: combine all email-related funtionality into one place
        self.initialEmail = ko.observable(null);
        self.emailAddress = ko.observable('').extend({ required: {}, email: {} });
        self.isEmailNotAvailable = ko.observable(false).extend({ ignoreOnSerialization: true });
        self.isEmailEditable = ko.observable(config.isEmailEditable || false).extend({ ignoreOnSerialization: true });
        self.isPasswordSet = true;
        self.textCaptchaEnabled = window.textCaptcha;

        self.isEmailVerificationNotificationEnabled = ko.observable(config.isEmailVerificationNotificationEnabled);
        self.isEmailVerificationMode = ko.observable(false);
        self.isEmailChanged = ko.observable(false).extend({ ignoreOnSerialization: true });
        self.showCaptchaValidationMessage = ko.observable(false);

        self.currentPassword = ko.observable().extend({ required: {} });
        self.isEmailAddressAvailable = ko.observable(true);

        self.emailAddress.subscribe(function (value) {
            //we assume that user changed email correctly
            self.isEmailNotAvailable(false);
            if (!value) {
                self.isEmailAddressAvailable(false);
            }
            else {
                self.isEmailAddressAvailable(true);
            }
            if (value !== self.initialEmail()) {
                self.isEmailChanged(true);
                
                if (!self.enableEmailVerification()) {
                    if (self.textCaptchaEnabled) {
                        self.textCaptchaViewModel.resetCaptcha(
                            self.textCaptchaViewModel.hasError(),
                            self.textCaptchaViewModel.userAnswer.validationMessage()
                        );
                    } else {
                        captchaHelper.renderCaptcha();
                    }
                }
            }
        });

        self.goToAccountSettingsPage = function () {
            var accountSettingsPagePath = gJobs.accountSettingsHelper.getLinkForAccountSettings();
            accountSettingsPagePath += '?changeEmail=true';

            var pageInfoService = gJobs.pageInfoService ? gJobs.pageInfoService : AgencyPages.pageInfoService;

            if (self.enableEmailVerification() && pageInfoService.isOnApplyPage()) {
                accountSettingsPagePath += '&redirectToVerifyAccountPage=true';
                sessionStorage.setItem(OnlineApp.SessionKeys.ApplicationProcessUrl, window.location.href);
            }

            window.location = accountSettingsPagePath;
        };

        self.changeEmailNotification = ko.computed({
            read: function () {
                return 'Your current email address is ' + self.initialEmail() +
                '. To change the email address, please visit account settings page.';
            },
            deferEvaluation: true
        })

        self.notificationPreference = ko.observable();
        self.jobId = ko.observable();

        self.notificationPreferenceText = ko.computed({
            read: function () {
                // todo: use same approach for every enum
                /* This approach for setting Enum values 
                uses client side enum-like dictionaries
                (see definitionsViewModel) */
                // $root.definitionsViewModel.notificationType.items()[1].id - might be input values

                var prefValue = self.notificationPreference();
                if (!prefValue) {
                    return "";
                }

                var notificationTypes = OnlineApp.ViewModels.applicationViewModel.definitionsViewModel.notificationType.items();
                var pref = notificationTypes[prefValue];

                if (!pref) {
                    return "";
                }

                return pref.text;
            },
            write: function (value) {
                var definition = ko.utils.arrayFirst(
                    OnlineApp.ViewModels.applicationViewModel.definitionsViewModel.notificationType.items(),
                    function(item) {
                        return item.text == value;
                    });

                self.notificationPreference(definition.id);
            }
        }).extend({ ignoreOnSerialization: true });

        self.getValidationConfig = function () {

            var fieldSettings = OnlineApp.FieldSettings;

            var getPrimaryPhone = function () {
                return {
                    subjectField: self.phone.primaryPhone,
                    objectField: self.phone.primaryPhoneExt,
                };
            };

            var getAlternatePhone = function () {
                return {
                    subjectField: self.phone.alternatePhone,
                    objectField: self.phone.alternatePhoneExt,
                };
            };

            var config = {
                'all': {
                    'name.firstName': {
                        required: {},
                        length: {
                            max: 50
                        },
                        regexp: {
                            pattern: /^[a-zA-Z\-\'~\u00C0-\u017F ]*$/,
                            validationMessage: "Invalid first name",
                            isValidationMessageVisible: true
                        }
                    },
                    'name.lastName': {
                        required: {},
                        length: {
                            max: 50
                        },
                        regexp: {
                            pattern: /^[a-zA-Z\-\'~\u00C0-\u017F ]*$/,
                            validationMessage: "Invalid last name",
                            isValidationMessageVisible: true
                        }
                    },
                    'name.middleName': {
                        required: {
                            enabled: !!fieldSettings ? fieldSettings.middleName.required : false
                        },
                        length: {
                            max: 50,
                            enabled: !!fieldSettings ? fieldSettings.middleName.visible : true
                        },
                        disallowHtml: {}
                    },
                    'name.formerName': {
                        required: {
                            enabled: !!fieldSettings ? fieldSettings.formerLastName.required : false
                        },
                        length: {
                            max: 50,
                            enabled: !!fieldSettings ? fieldSettings.formerLastName.visible : true
                        },
                        regexp: {
                            pattern: /^[a-zA-Z\-\'~\u00C0-\u017F ]*$/,
                            validationMessage: "Invalid former last name",
                            isValidationMessageVisible: true,
                            enabled: !!fieldSettings ? fieldSettings.formerLastName.visible : true
                        }
                    },
                    'address.address1': {
                        required: {},
                        length: {
                            max: 100
                        },
                        disallowHtml: {}
                    },
                    'address.address2': {
                        required: {
                            enabled: !!fieldSettings ? fieldSettings.address2.required : false
                        },
                        length: {
                            max: 50,
                            enabled: !!fieldSettings ? fieldSettings.address2.visible : true
                        },
                        disallowHtml: {}
                    },
                    'address.city': {
                        required: {},
                        length: {
                            max: 50
                        },
                        disallowHtml: {}
                    },
                    'address.state.id': {
                        required: {
                            validationMessage: "Please select a state",
                            isValidationMessageVisible: true
                        },
                        regexp: {
                            pattern: /^[1-9]\d*$/,
                            validationMessage: "Please select a state",
                            isValidationMessageVisible: true
                        },
                        deferredDefinitionAwareValue: {
                            deferredDefinitionViewModel: OnlineApp.ViewModels.applicationViewModel.definitionsViewModel.states
                        },
                        state: {
                            onlyIf: function () {
                                return self.address.country.id() && self.address.state.id();
                            },
                            states: OnlineApp.ViewModels.applicationViewModel.definitionsViewModel.states.items(),
                            countryId: self.address.country.id
                        }
                    },
                    'address.country.id': {
                        required: {
                            enabled: !!fieldSettings ? fieldSettings.countryID.required : false,
                            validationMessage: "Please select a country",
                            isValidationMessageVisible: true
                        },
                        regexp: {
                            pattern: !!fieldSettings && fieldSettings.countryID.required ? /^[1-9]\d*$/ : null,
                            validationMessage: "Please select a country",
                            isValidationMessageVisible: true,
                            enabled: !!fieldSettings ? fieldSettings.countryID.visible : true
                        },
                        deferredDefinitionAwareValue: {
                            deferredDefinitionViewModel: OnlineApp.ViewModels.applicationViewModel.definitionsViewModel.countries
                        }
                    },
                    'address.zipCode': {
                        required: {},
                        length: {
                            max: 20
                        },
                        zip: {
                            onlyIf: function () {
                                return self.address.country.id();
                            },
                            countryId: self.address.country.id
                        }
                    },
                    'phone.primaryPhoneExt': {
                        requiredField: $.extend({}, getPrimaryPhone(), {
                            enabled: !!fieldSettings ? fieldSettings.homePhone.visible : true
                        }),
                        length: {
                            max: 10,
                            enabled: !!fieldSettings ? fieldSettings.homePhone.visible : true
                        },
                        disallowHtml: {}
                    },
                    'phone.primaryPhone': {
                        required: {
                            enabled: !!fieldSettings ? fieldSettings.homePhone.required : false
                        },
                        requiredField: $.extend({}, getPrimaryPhone(), {
                            enabled: !!fieldSettings ? fieldSettings.homePhone.visible : true
                        }),
                        phone: {
                            countryID: function () {
                                var phoneNumberAllowed = !!fieldSettings ? fieldSettings.homePhone.visible : true;
                                if (phoneNumberAllowed) {
                                    if (self.editableItem() != undefined) {
                                        if (self.editableItem().address && self.editableItem().address.country)
                                            return self.editableItem().address.country.id();
                                    } else {
                                        if (self.address && self.address.country)
                                            return self.address.country.id();
                                    }
                                }
                            },
                        },
                        length: {
                            //phone number and extension are concatenated into a single field which is maximum 50 chars long.
                            //10 chars are reserved for the extension and 6 for the ' ext. ' text
                            max: 34,
                            enabled: !!fieldSettings ? fieldSettings.homePhone.visible : true
                        },
                        disallowHtml: {}
                    },
                    'phone.alternatePhoneExt': {
                        requiredField: $.extend({}, getAlternatePhone(), {
                            enabled: !!fieldSettings ? fieldSettings.alternatePhone.visible : true
                        }),
                        length: {
                            max: 10,
                            enabled: !!fieldSettings ? fieldSettings.alternatePhone.visible : true
                        },
                        disallowHtml: {}
                    },
                    'phone.alternatePhone': {
                        required: {
                            enabled: !!fieldSettings ? fieldSettings.alternatePhone.required : false
                        },
                        requiredField: $.extend({}, getAlternatePhone(), {
                            enabled: !!fieldSettings ? fieldSettings.alternatePhone.visible : true
                        }),
                        phone: {
                            countryID: function () {
                                var phoneNumberAllowed = !!fieldSettings ? fieldSettings.alternatePhone.visible : true;
                                if (phoneNumberAllowed) {
                                    if (self.editableItem() != undefined) {
                                        if (self.editableItem().address && self.editableItem().address.country)
                                            return self.editableItem().address.country.id();
                                    } else {
                                        if (self.address && self.address.country)
                                            return self.address.country.id();
                                    }
                                }
                            },
                        },
                        length: {
                            max: 34,
                            enabled: !!fieldSettings ? fieldSettings.alternatePhone.visible : true
                        },
                        disallowHtml: {}
                    },
                    'notificationPreference': {
                        required: {
                            enabled: !!fieldSettings ? fieldSettings.notificationType_cd.required : false
                        },
                        definitionAwareValue: {
                            definitionItems: OnlineApp.ViewModels.applicationViewModel.definitionsViewModel.notificationType.items
                        }
                    },
                    'emailAddress': {
                        required: {},
                        email: {}
                    }
                }
            };

            return config;
        };


        self.beginEmailVerificationMode = function () {
            self.contactInfoEmailVerificationViewModel.emailAddress(self.emailAddress());
            self.contactInfoEmailVerificationViewModel.initEmailVerification();
            self.isEmailVerificationMode(true);
        } 

        self.cancelEmailVerificationMode = function () {
            self.isEmailVerificationMode(false);
            $('#verify-email-contact-info-link').focus();
            layoutHelper.tabbing.updateIndices();
        }

        self.resetEmailAddress = function(newEmailAddress) {
            self.emailAddress(newEmailAddress);

            if (self.editableItem()) {
                self.editableItem().emailAddress(newEmailAddress);
            }
        };

        self.updateContactInfoAfterEmailChange = function (options) {

            self.isEmailVerified(false);
            if (options && options.isEmailChanged) self.resetEmailAddress(self.initialEmail());

            if (window.utils.getUrlParameter("redirectToVerifyAccountPage")) {
                window.location = options.forceRedirectUrl;
            } else {
                self.beginEmailVerificationMode();
            }

        };

        self.goToApplicationProcess = function() {
            var applicationProcessUrl = sessionStorage.getItem(OnlineApp.SessionKeys.ApplicationProcessUrl);

            if (applicationProcessUrl) {
                sessionStorage.removeItem(OnlineApp.SessionKeys.ApplicationProcessUrl);

                window.location = applicationProcessUrl;
            }
        };

        self.updateAccessToContactInfoSaveButton = function(isSaveButtonDisabled) {
            if ($(contactInfoSaveButtonSelector).length) $(contactInfoSaveButtonSelector).prop('disabled', isSaveButtonDisabled);
        };

        self.fromDataModel = function (data) {
            if (!data) {
                return;
            }

            self.name.fromDataModel(data.name);
            initialFullName = self.name.fullName();
            self.address.fromDataModel(data.address);
            self.phone.fromDataModel(data.phone);
            self.notificationPreference(data.notificationPreference ? data.notificationPreference.toString():"1"); // Email is default

            self.initialEmail(data.initialEmail || data.emailAddress);
            self.emailAddress(data.emailAddress);

            self.isEmailEditable(self.isEmailEditable() || data.isEmailEditable || !data.emailAddress || false);

            if (data.isPasswordSet != undefined)
            {
                self.isPasswordSet = data.isPasswordSet;
            }

            if (OnlineApp.ViewModels != null
                && OnlineApp.ViewModels.applicationViewModel != null
                && OnlineApp.ViewModels.applicationViewModel.jobId != null
                && OnlineApp.ViewModels.applicationViewModel.jobId() > 0) {
                self.jobId(OnlineApp.ViewModels.applicationViewModel.jobId());
            }

            self.registerValidation(self.getValidationConfig());

            $(document).trigger(OnlineApp.Events.CommonEventsNames.ContactInfomationAvailable, {
                firstName: self.name.firstName(),
                lastName: self.name.lastName(),
                email: self.emailAddress()
            });
        };

        var baseDiscardChanges = self.discardChanges;
        self.discardChanges = function (item, e) {            
            self.isDiscardChange(true);
            baseDiscardChanges.call(self, item, e);
            self.goToApplicationProcess();
        };

        self.saveChanges = (function(base) {
            return function(item) {
                var editableItem = self.editableItem(),
                    that = this,
                    saveChangesArguments = arguments,
                    promise;

                item.isBusy(true);
                self.updateAccessToContactInfoSaveButton(true);


                /*
                   Switch for email verification. The logic is similar the default but conditions related to the captcha were deleted 
                   and the final promise on getting saving result changed

                */
                if (self.enableEmailVerification()) {

                    if (editableItem.isEmailChanged() && self.isEmailEditable()) {


                        var isPasswordValid = (OnlineApp.ViewModels.accountSettingsViewModel 
                                && OnlineApp.ViewModels.accountSettingsViewModel.isImpersonatedJobSeeker) ||
                            !self.isPasswordSet ||
                            editableItem.currentPassword.validate();

                        if (!self.hasErrorPureComputed() && !isPasswordValid) {
                            self.isBusy(false);
                            self.updateAccessToContactInfoSaveButton(false);
                            triggerValidationFailedEvent(saveChangesArguments);
                            return false;
                        }
                    }

                    promise = $.when(function() { return true; });

                    //send request to email check service
                    if (editableItem && editableItem.emailAddress() !== self.initialEmail() && self.isEmailEditable()) {
                        editableItem.emailAddress.validate();

                        var isEmailAllowedRequestData = {
                            email: editableItem.emailAddress(),
                            captchaAnswer: editableItem.textCaptchaViewModel.userAnswer(),
                            password: editableItem.currentPassword()
                        }

                        if (!editableItem.emailAddress.hasError()) {
                            promise = promise.then(function() {
                                return OnlineApp.Services.authenticationService
                                    .isEmailAllowed(isEmailAllowedRequestData)
                                    .then(
                                        function(data) {
                            
                                            if (data.success) {
                                                editableItem.emailAddress.hasError(!data.isEmailAllowed);
                                                editableItem.isEmailNotAvailable(!data.isEmailAllowed);

                                                return data.isEmailAllowed;
                                            } else {

                                                var innerPromise;

                                                innerPromise = $.when(function() { return true; });

                                                innerPromise = innerPromise.then(function() {
                                                    if (data.errorPropertyName == 'Password') {
                                                        editableItem.currentPassword.validationMessage(data.errorMessage);
                                                        editableItem.currentPassword.hasError(true);
                                                        editableItem.currentPassword.isValidationMessageVisible(true);
                                                    }

                                                    return false;
                                                });
                                                
                                                return innerPromise;
                                            }


                                        },
                                        //fail callback
                                        function() {
                                            toastr.warning(Resources.NotificationMessages.ServiceUnavailable);

                                            return window.undefined;
                                        }
                                    );
                            });
                        }
                    }

                    editableItem.name.normalize();

                    var isResumeLoadedInCurrentSession = OnlineApp.ViewModels.applicationViewModel.importResumeViewModel &&
                        OnlineApp.ViewModels.applicationViewModel.importResumeViewModel.resumeUploadComplete();
                    if (!isResumeLoadedInCurrentSession && initialFullName && editableItem && editableItem.name.fullName() !== initialFullName) {
                        var deferred = $.Deferred();
                        OnlineApp.Controllers.notificationController.showCreateNewAccountNotification(function () {
                            deferred.then(function () {
                                return OnlineApp.Services.authenticationService.logout().done(
                                    function() {
                                        sessionStorage.setItem('shouldCreateNewAccount', "true");
                                        $(window).on('beforeunload', function () {
                                            $(window).scrollTop(0);
                                        });
                                        location.reload();
                                    });
                            });

                            deferred.resolve(false);
                        }, function () {
                            deferred.resolve(true);
                        });
                        promise = promise.then(function(isValid) {
                            if (isValid) {
                                return deferred; 
                            }
                            return false;
                        });
                    }

                    promise = promise.then(function (saveAllowed) {
                        if (saveAllowed) {
                            if (editableItem.isEmailChanged() && self.isEmailEditable()) {
                                gJobs.crossWindowCommunicationService.sendMessage(
                                    gJobs.subjects.EmailUpdated,
                                    editableItem.emailAddress()
                                );
                            }

                            var queryStringData = { 
                            fromAppProcess: self.fromAppProcess(),
                            returnUrl: encodeURIComponent(window.location.href)
                        };

                            if (self.enableEmailVerification()) {
                                if (window.utils.getUrlParameter("redirectToVerifyAccountPage")) {
                                    queryStringData.sendAccountVerifEmail = true;
                                }

                                var applicationProcessUrl = sessionStorage.getItem(OnlineApp.SessionKeys.ApplicationProcessUrl);

                                if (applicationProcessUrl) {
                                    queryStringData.redirectionUrl = applicationProcessUrl;
                                    //sessionStorage.removeItem(OnlineApp.SessionKeys.ApplicationProcessUrl);
                                }
                                 
                            }

                        var agencyFolderName = AgencyPages.pageInfoService ?
                            AgencyPages.pageInfoService.getCurrentAgencyFolderName() :
                            gJobs.pageInfoService.getCurrentAgencyPageFolderName();
                        
                        if (agencyFolderName) {
                            queryStringData.agencyFolderName = agencyFolderName;
                        }

                        var args = Array.prototype.slice.call(saveChangesArguments);
                        args.push(queryStringData);
                        
                        return base.apply(that, args);
                        } else {
                            triggerValidationFailedEvent(saveChangesArguments);
                        }

                        return window.undefined;
                    });

                    promise = promise
                        .done(function (data) {
                            if (self.isAccountSettingsPage()) {
                                if (data && data.isSuccess && data.payload && !data.payload.isImpersonatedJobSeeker) {
                                    if (data.payload.forceRedirectUrl) {
                                        window.location = data.payload.forceRedirectUrl;
                                        return;
                                    }

                                    var options = null;

                                    if (data.payload.isEmailChanged) {
                                        options = { changedEmailAddressWasAdded: true, isEmailChanged: data.payload.isEmailChanged, forceRedirectUrl: data.payload.forceRedirectUrl };
                                        gJobs.localStorageHelper.updateItemForMultipleTabs(OnlineApp.LocalStorageKeys.EmailWasChanged, "true");
                                        localStorage.setItem('updatedEmail', data.payload.updatedEmail);
                                    }

                                    if (self.fromAppProcess() || window.utils.getUrlParameter("changeEmail")) {
                                        if (data.payload.isEmailChanged) {
                                            gJobs.localStorageHelper.updateItemForMultipleTabs(
                                                OnlineApp.LocalStorageKeys.EmailWasChangedAndNewVerificationCodeSent,
                                                "true"
                                            );

                                            self.updateContactInfoAfterEmailChange(options);
                                        } else {
                                            self.goToApplicationProcess();
                                        }
                                    } else if (data.payload.isEmailChanged) {
                                        self.updateContactInfoAfterEmailChange(options);
                                    }

                                    if (window.enableTwoFactorAuthentication && data.payload.isEmailChanged) {
                                        $(document).trigger(OnlineApp.Events.CommonEventsNames.EmailWasChanged, options);
                                    }
                                }
                            }
                        })
                    .always(function() {
                        item.isBusy(false);
                        self.updateAccessToContactInfoSaveButton(false);
                        self.validate();
                    });

                    return promise;
            } else {
                if (editableItem.isEmailChanged() && self.isEmailEditable()) {

                    var isCaptchaSubmitted = captchaHelper.isCaptchaSubmitted;
                    editableItem.showCaptchaValidationMessage(!isCaptchaSubmitted);

                    var isPasswordValid = (OnlineApp.ViewModels.accountSettingsViewModel 
                            && OnlineApp.ViewModels.accountSettingsViewModel.isImpersonatedJobSeeker) ||
                        !self.isPasswordSet ||
                        editableItem.currentPassword.validate();

                    if (!self.hasErrorPureComputed() && 
                        !(isPasswordValid && ((isCaptchaSubmitted && !window.textCaptcha) || 
                            (window.textCaptcha && editableItem.textCaptchaViewModel.validate())))) {
                        self.isBusy(false);
                        self.updateAccessToContactInfoSaveButton(false);
                        triggerValidationFailedEvent(saveChangesArguments);
                        return false;
                    }
                }

                promise = $.when(function() { return true; });

                //send request to email check service
                if (editableItem && editableItem.emailAddress() !== self.initialEmail() && self.isEmailEditable()) {
                    editableItem.emailAddress.validate();

                    var isEmailAllowedRequestData = {
                        email: editableItem.emailAddress(),
                        captchaAnswer: editableItem.textCaptchaViewModel.userAnswer(),
                        password: editableItem.currentPassword()
                    }

                    if (!editableItem.emailAddress.hasError()) {
                        promise = promise.then(function() {
                            return OnlineApp.Services.authenticationService
                                .isEmailAllowed(isEmailAllowedRequestData)
                                .then(
                                    function(data) {
                                        if (editableItem.isEmailChanged() && !self.textCaptchaEnabled) {
                                            captchaHelper.resetCaptcha();
                                        }

                                        if (data.success) {
                                            editableItem.emailAddress.hasError(!data.isEmailAllowed);
                                            editableItem.isEmailNotAvailable(!data.isEmailAllowed);

                                            return data.isEmailAllowed;
                                        } else {
                                            var resetTextCaptcha = editableItem.textCaptchaViewModel.validate();

                                            var innerPromise;

                                            if (resetTextCaptcha) {
                                                innerPromise = editableItem.textCaptchaViewModel.resetCaptcha();
                                            } else {
                                                innerPromise = $.when(function() { return true; });
                                            }

                                            innerPromise = innerPromise.then(function() {
                                                if (data.errorPropertyName == 'Password') {
                                                    editableItem.currentPassword.validationMessage(data.errorMessage);
                                                    editableItem.currentPassword.hasError(true);
                                                    editableItem.currentPassword.isValidationMessageVisible(true);
                                                } else if (data.errorPropertyName == 'Captcha') {
                                                    editableItem.textCaptchaViewModel.userAnswer.hasError(true);
                                                    if (resetTextCaptcha) {
                                                        editableItem.textCaptchaViewModel.userAnswer.validationMessage('Captcha is invalid');
                                                    } else {
                                                        editableItem.textCaptchaViewModel.userAnswer.validationMessage('This field is required');
                                                    }
                                                    editableItem.textCaptchaViewModel.userAnswer.isValidationMessageVisible(true);
                                                }

                                                return false;
                                            });
                                            
                                            return innerPromise;
                                        }


                                    },
                                    //fail callback
                                    function() {
                                        toastr.warning(Resources.NotificationMessages.ServiceUnavailable);

                                        return window.undefined;
                                    }
                                );
                        });
                    }
                }

                editableItem.name.normalize();

                var isResumeLoadedInCurrentSession = OnlineApp.ViewModels.applicationViewModel.importResumeViewModel &&
                    OnlineApp.ViewModels.applicationViewModel.importResumeViewModel.resumeUploadComplete();
                if (!isResumeLoadedInCurrentSession && initialFullName && editableItem && editableItem.name.fullName() !== initialFullName) {
                    var deferred = $.Deferred();
                    OnlineApp.Controllers.notificationController.showCreateNewAccountNotification(function () {
                        deferred.then(function () {
                            return OnlineApp.Services.authenticationService.logout().done(
                                function() {
                                    sessionStorage.setItem('shouldCreateNewAccount', "true");
                                    $(window).on('beforeunload', function () {
                                        $(window).scrollTop(0);
                                    });
                                    location.reload();
                                });
                        });

                        deferred.resolve(false);
                    }, function () {
                        deferred.resolve(true);
                    });
                    promise = promise.then(function(isValid) {
                        if (isValid) {
                            return deferred; 
                        }
                        return false;
                    });
                }

                promise = promise.then(function (saveAllowed) {
                    if (saveAllowed) {
                        if (editableItem.isEmailChanged() && self.isEmailEditable()) {
                            gJobs.crossWindowCommunicationService.sendMessage(
                                gJobs.subjects.EmailUpdated,
                                editableItem.emailAddress()
                            );
                        }

                        var queryStringData = { fromAppProcess: self.fromAppProcess(), fromAccountSettings: self.isAccountSettingsPage() };

                        if (self.fromAppProcess()) {

                            var agencyFolderName = AgencyPages.pageInfoService ?
                                AgencyPages.pageInfoService.getCurrentAgencyFolderName() :
                                gJobs.pageInfoService.getCurrentAgencyPageFolderName();

                            if (agencyFolderName) {
                                queryStringData.agencyFolderName = agencyFolderName;
                            }
                        }

                            var args = Array.prototype.slice.call(saveChangesArguments);
                            args.push(queryStringData);

                            return base.apply(that, args);
                        } else {
                            triggerValidationFailedEvent(saveChangesArguments);
                        }

                        return window.undefined;
                    
                });

                promise = promise
                    .done(function (data) {
                        if (data && data.payload && data.payload.isEmailChanged) {
                            if (self.fromAppProcess()) {
                                localStorage.setItem('updatedEmail', data.payload.updatedEmail);
                                sessionStorage.setItem('emailWasChangedAndNewVerificationCodeSent', 'true');
                            }
                        }
                    })
                .always(function() {
                    item.isBusy(false);
                    self.updateAccessToContactInfoSaveButton(false);
                    self.validate();
                });

                return promise;
            }
        }
        })(self.saveChanges);

        function triggerValidationFailedEvent(event) {
            if (OnlineApp.Events) {
                var validationFailedEvent =
                    jQuery.Event(OnlineApp.Events.CommonEventsNames.PreSaveValidationFailed);
                validationFailedEvent.target = event.target;
                $(document).trigger(validationFailedEvent);
            }
        }

        gJobs.crossWindowCommunicationService.setListener(
            gJobs.subjects.EmailUpdated,
            function (newEmail) {
                self.emailAddress(newEmail);
                if (self.editableItem()) {
                    self.editableItem().emailAddress(newEmail);
                }
            }
        );

        self.emailFieldLoaded = function (elements) { 
            var emailInputField = $(elements).find('input');
            emailInputField.keydown(function(e) {
                var keyCode = e.keyCode || e.which;
                var isShiftPressed = e.shiftKey;
                setTimeout(function() {
                    if (!isShiftPressed && keyCode === $.ui.keyCode.TAB && self.isEmailEditable() && self.isEmailChanged()) {
                        $('#currentPassword').focus();
                    }
                });
            });
        }
        
        self.showHideAriaLabel = function () {
            if ($("fieldset.radio-set.css3-radio").length > 0) {
                $("fieldset.radio-set.css3-radio").each(function (i) {
                    $("fieldset.radio-set.css3-radio")[i].removeAttribute("aria-required");
                });
            }
        }

        if (self.enableEmailVerification()) {
            OnlineApp.Services.authenticationService.isLoggedIn()
            .done(function(isLoggedIn) {
                if (isLoggedIn) {
                    OnlineApp.Services.emailVerificationService.isEmailVerified()
                        .then(function(response) {
                        var data = response.data;
        
                        self.isEmailVerified(data.isEmailVerified);
                        });
                }
            });

            $(document).on(OnlineApp.Events.CommonEventsNames.EmailVerified, function (event, data) {
                self.isEmailVerificationMode(false);
                self.isEmailVerified(true);

                if (self.contactInfoEmailVerificationViewModel) {
                    self.contactInfoEmailVerificationViewModel
                        .emailVerificationViewModel
                        .changedEmailAddressWasAdded = ko.observable(false);
                }

                if (data && data.changedEmailAddress) {
                    self.initialEmail(data.changedEmailAddress);
                    self.resetEmailAddress(data.changedEmailAddress);
                }

                var applicationProcessUrl = sessionStorage.getItem(OnlineApp.SessionKeys.ApplicationProcessUrl);

                if (applicationProcessUrl) {
                    sessionStorage.removeItem(OnlineApp.SessionKeys.ApplicationProcessUrl);

                    window.location = applicationProcessUrl;
                }
            });

            $(document).on(OnlineApp.Events.CommonEventsNames.ContactInfoEmailVerificationFormClosed, self.cancelEmailVerificationMode);

            var loginEvents = Events.CommonEventsNames.Login + ' ' + Events.CommonEventsNames.Register;

            $(document).on(loginEvents, function () {
                self.initContactInfoEmailVerificationViewModel();
            });
        }
    };


    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        ContactInfoViewModel: ContactInfoViewModel
    });

})(window);;
(function (window, undefined) {
    'use strict';

    function EmailVerificationViewModel(options) {
        var options = options ? options : {};
        
        var RESEND_VERIFICATION_CODE_ATTEMPTS_COUNT_WITHOUT_CAPTCHA = window.emailVerificationResendAttempts;
        var VERIFICATION_CODE_VERIFY_ATTEMPTS_COUNT_WITHOUT_CAPTCHA = window.emailVerificationVerifyAttempts;
        var CAPTCHA_LABEL_HTML_CONTENT_FOR_RESEND_CODE = "<span>Please answer the question to <b>resend</b> a code again</span>";
        var CAPTCHA_LABEL_HTML_CONTENT_FOR_VERIFICATION_CODE = "<span>Please answer the question to <b>verify</b> a code again</span>";
        var CAPTCHA_INVALID_MESSAGE = "Captcha is invalid";
        var CAPTCHA_USER_ANSWER_INPUT_ID_FOR_VERIFY_CODE = "captcha-user-answer-for-verify-code";
        var CAPTCHA_USER_ANSWER_INPUT_ID_FOR_RESEND_CODE = "captcha-user-answer-for-resend-code";
        var INSTRUCTIONS_MESSAGE_FOR_SENT_CODE = "We've sent a " + window.emailVerificationCodeLength +
            " digit code to your email address and the code is only valid for " + window.emailVerificationCodeDurationInMins +
            " minutes. Please enter the code below. ";

        var verificationCodeInput;
        var lastFocusableElement;

        var isUserDataInitiated = false;
        var emailWasChangedAndNewVerificationCodeSent = false;

        var self = OnlineApp.ViewModels.Base.ValidatableViewModel.apply(this, arguments) || this;

        self.enableEmailVerification = ko.observable(window.enableEmailVerification);

        self.isNeedToHideHeader = ko.observable(options.isNeedToHideHeader);
        self.isNeedToHideInstructions = ko.observable(options.isNeedToHideInstructions);
        self.verificationCodeLabelText = ko.observable(options.verificationCodeLabelText ? options.verificationCodeLabelText : "Verification code");
        self.verificationCodeAriaLabelText = ko.observable(
            options.isNeedToHideInstructions
            ? INSTRUCTIONS_MESSAGE_FOR_SENT_CODE + self.verificationCodeLabelText()
            : self.verificationCodeLabelText());
        self.useCustomVerifyButton = ko.observable(options.useCustomVerifyButton);
        
        var abstractAreaInfoService = new gJobs.AbstractAreaInfoService();

        self.textCaptchaViewModelForResendCode = new OnlineApp.ViewModels.TextCaptchaViewModel("ResendEmailVerificationCodeAnswer");
        self.textCaptchaViewModelForVerificationCode = new OnlineApp.ViewModels.TextCaptchaViewModel("VerifyEmailVerificationCodeAnswer");

        self.textCaptchaEnabled = window.textCaptcha;
        self.isNeedToShowEmailVerificationForm = ko.observable(false);
        self.isEmailVerified = ko.observable();
        self.userEmail = ko.observable();
        self.verificationAttemptsCount = ko.observable(0);
        self.resendEmailVerificationCount = ko.observable(0);
        self.isEmailVerificationSubmitButtonEnabled = ko.observable(false);
        self.emailVerificationCode = ko.observable("").extend({
            required: {},
            verificationCode: {
                regExpForValueTransform: /_/g,
                validationMessage: OnlineApp.Validation.validationMessages.invalidEmailVerificationCode
            }
        });

        self.emailVerificationCode.subscribe(function(newValue) {
            if (newValue !== "" && self.emailVerificationCode.validate(newValue)) {
                self.isEmailVerificationSubmitButtonEnabled(true);
            } else {
                self.isEmailVerificationSubmitButtonEnabled(false);
            }
            
            OnlineApp.Helpers.layoutHelper.tabbing.updateIndices();
        });

        self.changedEmailAddressWasAdded = ko.observable(false);

        function updateFieldErrorState (field, hasError, errorMessage) {
            field.hasError(hasError);
            field.isValidationMessageVisible(hasError);

            if (hasError && errorMessage) {
                field.validationMessage(errorMessage);
            }
        };

        function resetCaptcha (textCaptchaViewModel, htmlContentForLabel, captchaUserAnswerId) {
            textCaptchaViewModel.setCustomLabelHtmlContent(htmlContentForLabel);
            textCaptchaViewModel.setCustomUserAnswerInputId(captchaUserAnswerId);

            return textCaptchaViewModel.resetCaptcha(
                textCaptchaViewModel.userAnswer.hasError(),
                CAPTCHA_INVALID_MESSAGE
            );
        };

        function removeItemFromLocalStorage(key, delay) {
            setTimeout(function () {
                localStorage.removeItem(key);
            }, delay);
        }

        function checkEmailForUpdate() {
            setInterval(function() {
                if (localStorage.getItem('updatedEmail')  && localStorage.getItem('updatedEmail') !== self.userEmail()) {
                    self.userEmail(localStorage.getItem('updatedEmail'));
                    removeItemFromLocalStorage('updatedEmail', 5000);
                }
            }, 5000)
        }

        function tryFocusOnErrorCaptcha (isEmailVerificationContainerVisible, captchaUserAnswerInputId) {
            if (isEmailVerificationContainerVisible
                && lastFocusableElement.length
                && lastFocusableElement.attr('id') === captchaUserAnswerInputId
            ) {
                $("#" + captchaUserAnswerInputId).focus();
            }
        }

        self.initUserData = function (options) {
            self.emailVerificationCode('');
            updateFieldErrorState( self.emailVerificationCode, false);
            updateFieldErrorState(self.textCaptchaViewModelForResendCode.userAnswer, false);
            updateFieldErrorState(self.textCaptchaViewModelForVerificationCode.userAnswer, false);

            OnlineApp.Services.emailVerificationService
            .getUserData()
            .then(function (response) {
                var data = response.data;

                self.isEmailVerified(data.isEmailVerified);
                self.userEmail(data.userEmail);
                self.verificationAttemptsCount(data.verificaitonAttempts)
                self.resendEmailVerificationCount(data.resendEmailVerificationCount);

                if (self.isNeedToShowResendVerificationCodeCaptcha()) {
                    resetCaptcha(
                        self.textCaptchaViewModelForResendCode, 
                        CAPTCHA_LABEL_HTML_CONTENT_FOR_RESEND_CODE,
                        CAPTCHA_USER_ANSWER_INPUT_ID_FOR_RESEND_CODE
                    );
                }

                if (self.isNeedToShowVerificationCodeCaptcha()) {
                    resetCaptcha(
                        self.textCaptchaViewModelForVerificationCode, 
                        CAPTCHA_LABEL_HTML_CONTENT_FOR_VERIFICATION_CODE,
                        CAPTCHA_USER_ANSWER_INPUT_ID_FOR_VERIFY_CODE
                    );
                }

                if (!self.isEmailVerified()) {
                    checkEmailForUpdate();
                    self.isNeedToShowEmailVerificationForm(true);
                }

                isUserDataInitiated = true;

                if (options && options.changedEmailAddressWasAdded) {
                    self.isEmailVerified(false);
                    updateFieldErrorState(self.emailVerificationCode, false);
                    self.emailVerificationCode('');
                }

                self.onReady();
            });
        }

        self.onReady = function () {
            verificationCodeInput = $('#verification-code');
            verificationCodeInput.inputmask({'mask': '999999'});

            if (verificationCodeInput.length) verificationCodeInput.focus();
        }

        self.init = function () {
            if (self.enableEmailVerification()) {
                if (!isUserDataInitiated) {
                    self.initUserData();
                }

                OnlineApp.Services.emailVerificationService.trySendEmailVerificationCode();
            }
        }

        self.resetForm = function () {
            if (self.isNeedToShowVerificationCodeCaptcha()) {
                updateFieldErrorState(self.textCaptchaViewModelForVerificationCode.userAnswer, false);

                resetCaptcha(
                    self.textCaptchaViewModelForVerificationCode,
                    CAPTCHA_LABEL_HTML_CONTENT_FOR_VERIFICATION_CODE,
                    CAPTCHA_USER_ANSWER_INPUT_ID_FOR_VERIFY_CODE
                );
            }

            if (self.isNeedToShowResendVerificationCodeCaptcha()) {
                updateFieldErrorState(self.textCaptchaViewModelForResendCode.userAnswer, false);

                resetCaptcha(
                    self.textCaptchaViewModelForResendCode,
                    CAPTCHA_LABEL_HTML_CONTENT_FOR_RESEND_CODE,
                    CAPTCHA_USER_ANSWER_INPUT_ID_FOR_RESEND_CODE
                );
            }

            self.emailVerificationCode("");
            updateFieldErrorState(self.emailVerificationCode, false);
        }

        self.goToAccountSettingsPage = function() {
            var QUERY_PARAMETERS = '?fromAppProcess=true#contact';

            var linkForAccountSettings = gJobs.accountSettingsHelper.getLinkForAccountSettings();
            linkForAccountSettings += QUERY_PARAMETERS;

            sessionStorage.setItem(OnlineApp.SessionKeys.ApplicationProcessUrl, window.location.href);

            window.location = linkForAccountSettings;
        };

        self.showSuccessNotification = function (htmlContent) {
            var successEmailNotificationEventName = "successEmailNotification";
            var successEmailNotificationSelector = "success-email-notification";
            var successEmailNotification = $('#' + successEmailNotificationSelector);

            if (successEmailNotification.length !== 0) {
                successEmailNotification.html(htmlContent);
                successEmailNotification.css("display", "flex");
            } else {
                $('body').append(
                    "<div class='uses-gjobs-styles'><div id='" + successEmailNotificationSelector + "'>" + htmlContent + "</div></div>"
                );

                successEmailNotification = $('#' + successEmailNotificationSelector);
            }

            gJobs.screenReadersService.setAriaLiveNotification(successEmailNotification.text());

            $(document).on('click.' + successEmailNotificationEventName, function () {
                if (successEmailNotification.is(":visible")) {
                    successEmailNotification.css("display", "none");
                }
            });

            setTimeout(function () {
                if (successEmailNotification.is(":visible")) {
                    successEmailNotification.css("display", "none");
                }

                $(document).off('click.' + successEmailNotificationEventName);
            }, 10000)
        }

        self.showResendCodeSuccessNotification = function () {
            var htmlContent = "<div class='success-email-notification-holder'><span>A new verification code has been sent to your email address</span></div>";

            self.showSuccessNotification(htmlContent);
        }

        self.showResendCodeOnNewEmailNotification = function () {
            var htmlContent = "<div class='success-email-notification-holder'><span>A new verification code has been sent to your new email address</span></div>";
        
            self.showSuccessNotification(htmlContent);
        }

        self.showSuccessEmailVerifcationNotification = function () {
            var htmlContent = "<div class='success-email-notification-holder'><img class='email-verification-success-icon' src='/Content/Images/email-verification-success-notification-icon-white.svg' /><span>Your account (" + self.userEmail() + ") is verified</span></div>";
        
            self.showSuccessNotification(htmlContent);
        }

        self.isNeedToShowResendVerificationCodeCaptcha = function () {
            return !self.isEmailVerified() && self.textCaptchaEnabled && (self.resendEmailVerificationCount() > RESEND_VERIFICATION_CODE_ATTEMPTS_COUNT_WITHOUT_CAPTCHA);
        }

        self.isNeedToShowVerificationCodeCaptcha = function () {
            return !self.isEmailVerified() && self.textCaptchaEnabled && (self.verificationAttemptsCount() > VERIFICATION_CODE_VERIFY_ATTEMPTS_COUNT_WITHOUT_CAPTCHA);
        }

        self.resendEmailVerificationCode = function () {
            if (self.isEmailVerified()) {
                return;
            }

            if (self.isNeedToShowResendVerificationCodeCaptcha()) {
                if (!self.textCaptchaViewModelForResendCode.validate()) {
                    $('#' + CAPTCHA_USER_ANSWER_INPUT_ID_FOR_RESEND_CODE).focus();
                    return;
                };
            }

            OnlineApp.Services.emailVerificationService
            .resendEmailVerificationCode(self.textCaptchaViewModelForResendCode.userAnswer(), self.changedEmailAddressWasAdded())
            .then(function (response) {
                var isCaptchaInvalid = false;
                var data = response.data;
                var newResendEmailVerificationCount = data.resendEmailVerificationCount;
                self.resendEmailVerificationCount(newResendEmailVerificationCount);

                if (data.isResendEmailSucceeded === false) {
                    if (data.isCaptchaInvalid === true) {
                        isCaptchaInvalid = true;
                        updateFieldErrorState(self.textCaptchaViewModelForResendCode.userAnswer, true, CAPTCHA_INVALID_MESSAGE);
                    }
                } else {
                    self.showResendCodeSuccessNotification();
                }

                if (self.isNeedToShowResendVerificationCodeCaptcha()) {
                    resetCaptcha(
                        self.textCaptchaViewModelForResendCode, 
                        CAPTCHA_LABEL_HTML_CONTENT_FOR_RESEND_CODE,
                        CAPTCHA_USER_ANSWER_INPUT_ID_FOR_RESEND_CODE
                    ).always(function () {
                        if (isCaptchaInvalid) {
                            $('#' + CAPTCHA_USER_ANSWER_INPUT_ID_FOR_RESEND_CODE).focus();
                        }
                    });
                }
            });
        }


        self.getRedirectLinkForSuccessfullEmailVerification = function() {
                OnlineApp.Services
                .emailVerificationService
                .getRedirectLinkForSuccessfullEmailVerification()
                .done(function (response) {
                    var data = response.data;

                    if (data.redirectedLink !== "") {
                        window.location = data.redirectedLink;
                    }
                });
        }
        
        self.submitVerifyEmail = function () {
            self.isEmailVerificationSubmitButtonEnabled(false);

            if (self.isNeedToShowVerificationCodeCaptcha()) {
                if (!self.textCaptchaViewModelForVerificationCode.validate()) {
                    $("#" + CAPTCHA_USER_ANSWER_INPUT_ID_FOR_VERIFY_CODE).focus();
                    self.isEmailVerificationSubmitButtonEnabled(true);
                    return;
                };
            }            

            /*
                The default behavior assumes that the verify email button is not available until 
                a 6-digit code is entered, when the custom verify email button is used we cannot
                guarantee the same behavior, in this case we need to validate the email verification code

            */
            if (self.useCustomVerifyButton() && !self.emailVerificationCode.validate()) {
                updateFieldErrorState(self.emailVerificationCode, true);
                verificationCodeInput.focus();
                self.isEmailVerificationSubmitButtonEnabled(true);
                return;
            }

            var dataResponse = OnlineApp.Services
            .emailVerificationService
            .verifyEmail(self.emailVerificationCode(), self.textCaptchaViewModelForVerificationCode.userAnswer(), self.changedEmailAddressWasAdded())
            .done(function (response) {
                var isCaptchaInvalid = false;
                var data = response.data;
            
                if (data.isVerificationSucceeded === true) {   
                    self.isEmailVerified(true);

                    if (self.changedEmailAddressWasAdded()) {
                        self.userEmail(data.changedEmailAddress);
                    }

                    self.showSuccessEmailVerifcationNotification();
                    $(document).trigger(OnlineApp.Events.CommonEventsNames.EmailVerified, { changedEmailAddress: data.changedEmailAddress });
                    gJobs.localStorageHelper.updateItemForMultipleTabs(OnlineApp.LocalStorageKeys.EmailWasVerified, "true");
                } else {
                    var newVerificationAttemptsCount = self.verificationAttemptsCount() + 1;
                    self.verificationAttemptsCount(newVerificationAttemptsCount);

                    if (data.errorFieldName === "captcha") {
                        isCaptchaInvalid = true;
                        self.isEmailVerificationSubmitButtonEnabled(true);
                        updateFieldErrorState(self.textCaptchaViewModelForVerificationCode.userAnswer, true, CAPTCHA_INVALID_MESSAGE);
                    } else {
                        var errorMessage;

                        if (data.errorMessage === "error") {
                            errorMessage = "Invalid verification code";
                        } else if (data.errorMessage === "expired") {
                            errorMessage = "Code is expired. Please resend an email to get a new code";
                        }

                        updateFieldErrorState(self.emailVerificationCode, true, errorMessage);

                        verificationCodeInput.focus();
                    }

                    if (self.isNeedToShowVerificationCodeCaptcha()) {
                        resetCaptcha(
                            self.textCaptchaViewModelForVerificationCode, 
                            CAPTCHA_LABEL_HTML_CONTENT_FOR_VERIFICATION_CODE,
                            CAPTCHA_USER_ANSWER_INPUT_ID_FOR_VERIFY_CODE
                        ).always(function() {
                            if (isCaptchaInvalid) {
                                $("#" + CAPTCHA_USER_ANSWER_INPUT_ID_FOR_VERIFY_CODE).focus();
                            }
                        });
                    }
                }
            });
        }

        self.updateVerificationCodeFormAfterEmailChange = function() {
            self.isEmailVerified(false);
            self.emailVerificationCode('');
        };

        window.onstorage = function (e) {
            if (e.key === OnlineApp.LocalStorageKeys.EmailWasChanged && e.newValue === "true") {
                self.initUserData();
            } else if (e.key === OnlineApp.LocalStorageKeys.EmailWasChangedAndNewVerificationCodeSent && e.newValue === "true") {
                emailWasChangedAndNewVerificationCodeSent = true;
            } else if (e.key === OnlineApp.LocalStorageKeys.EmailWasVerified && e.newValue === "true") {
                self.isEmailVerified(true);
                self.isNeedToShowEmailVerificationForm(false);
            }
        };

        $(window).focus(function () {
            var isEmailVerificationContainerVisible = $("#verify-email-container").is(":visible");
            
            if (emailWasChangedAndNewVerificationCodeSent) {
                if (isEmailVerificationContainerVisible) {
                    OnlineApp.Services.emailVerificationService.trySendEmailVerificationCode();
                }

                self.updateVerificationCodeFormAfterEmailChange();
                emailWasChangedAndNewVerificationCodeSent = false;
            }

            if (self.isNeedToShowVerificationCodeCaptcha()) {
                resetCaptcha(
                    self.textCaptchaViewModelForVerificationCode, 
                    CAPTCHA_LABEL_HTML_CONTENT_FOR_VERIFICATION_CODE,
                    CAPTCHA_USER_ANSWER_INPUT_ID_FOR_VERIFY_CODE
                ).always(function () {
                    tryFocusOnErrorCaptcha(isEmailVerificationContainerVisible, CAPTCHA_USER_ANSWER_INPUT_ID_FOR_VERIFY_CODE);
                });
            }

            if (self.isNeedToShowResendVerificationCodeCaptcha()) {
                resetCaptcha(
                    self.textCaptchaViewModelForResendCode, 
                    CAPTCHA_LABEL_HTML_CONTENT_FOR_RESEND_CODE,
                    CAPTCHA_USER_ANSWER_INPUT_ID_FOR_RESEND_CODE
                ).always(function () {
                    tryFocusOnErrorCaptcha(isEmailVerificationContainerVisible, CAPTCHA_USER_ANSWER_INPUT_ID_FOR_RESEND_CODE);
                });
            }
        });

        $(window).blur(function () {
            lastFocusableElement = $(document.activeElement);
        });
        
        $(document).on(OnlineApp.Events.CommonEventsNames.CertifySubmitTabOpened, function () {
            self.init();
        });

        $(document).on(OnlineApp.Events.CommonEventsNames.EmailWasChanged, function (event, data) {
            self.initUserData(data);
        });
    }

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        EmailVerificationViewModel: EmailVerificationViewModel
    });

})(window);
;
(function (window, undefined) {
    'use strict';

    function ContactInfoEmailVerificationViewModel() {
        var layoutHelper = OnlineApp.Helpers.layoutHelper;
        
        var self = this;

        self.emailAddress = ko.observable('');

        self.onReady = function () {
            layoutHelper.tabbing.activateFirstElement($('#contact-info-email-verification .email-verification-form-container'));
            layoutHelper.tabbing.updateIndices();
        }
        
        self.emailVerificationViewModel = new OnlineApp.ViewModels.EmailVerificationViewModel(
            { 
                isNeedToHideHeader: true, 
                isNeedToHideInstructions: true,
                verificationCodeLabelText: "Please enter the 6 digit code sent to your email address.",
                useCustomVerifyButton: true
            }
        ); 

        self.cancelEmailVerification = function () {
            if (self.emailVerificationViewModel.changedEmailAddressWasAdded()) {
                $(document).trigger(OnlineApp.Events.CommonEventsNames.ShowCancelVerificationRequestDialog);
            } else {
                self.emailVerificationViewModel.resetForm();

                $(document).trigger(OnlineApp.Events.CommonEventsNames.ContactInfoEmailVerificationFormClosed);

                var applicationProcessUrl = sessionStorage.getItem(OnlineApp.SessionKeys.ApplicationProcessUrl);

                if (applicationProcessUrl) {
                    sessionStorage.removeItem(OnlineApp.SessionKeys.ApplicationProcessUrl);

                    window.location = applicationProcessUrl;
                }
            }
        }

        self.initEmailVerification = function () {
            self.emailVerificationViewModel.init();
        }

        $(document).on(OnlineApp.Events.CommonEventsNames.ContactInfoEmailVerificationFormClosed, function() {
            if (self.emailVerificationViewModel.changedEmailAddressWasAdded()) {
                self.emailVerificationViewModel.resetForm();
            }

            self.emailVerificationViewModel.changedEmailAddressWasAdded = ko.observable(false);
        });
    }

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        ContactInfoEmailVerificationViewModel: ContactInfoEmailVerificationViewModel
    });

})(window);
;
(function (window, undefined) {
    'use strict';

    function TalentSearchPreferencesViewModel() {
        var config = {
            endpoint: "talentSearchPreferences"
        };

        var self = OnlineApp.ViewModels.Base.EditableViewModel.call(this, config) || this;

        self.isAccessMembershipEnabled = ko.observable(false);

        self.isAccessMembershipEnabled.subscribe(function(value) {
            var accessMembershipNotification = "Access membership is " +
                (value ? "active" : "inactive");

            gJobs.screenReadersService.setAriaLiveNotification(accessMembershipNotification);
        });

        self.toggleButtonText = function (toggleValue) {
            return toggleValue ? 'ON' : 'OFF';
        };

        self.fromDataModel = function (data) {
            if (!data) {
                return;
            }

            self.isAccessMembershipEnabled(data.isAccessMembershipEnabled);
        };

        self.trackClickOnAccessMembershipLogo = function() {
            gJobs.common.analytics.trackEvent(
                'Access Membership Account Preferences Section',
                'Followed'
            );

            return true;
        };

        self.isInEditMode.subscribe(function(value) {
            var $accessMembershipPreferencesTab = $('.access-membership-preferences-tab');
            var nonEditModeClassName = 'non-edit-mode';

            if (value) {
                $accessMembershipPreferencesTab.removeClass(nonEditModeClassName);
            } else {
                $accessMembershipPreferencesTab.addClass(nonEditModeClassName);
            }
        });

        self.saveChanges = (function(base) {
            var pageInfoService = gJobs.pageInfoService ? gJobs.pageInfoService : AgencyPages.pageInfoService;

            return function(item, e) {
                return base(item, e).always(function() {
                    if (pageInfoService.isOnPreferencesSectionPage()) {
                        if (!self.isAccessMembershipEnabled()) {
                            var configSettingForStickyHeader = $('#sticky-header').data('config-setting-for-sticky-header');

                            if (configSettingForStickyHeader) {
                                $('#content').addClass('respect-sticky-header');
                                window.enableStickyHeader = true;
                            }
                            $(document).trigger(Events.CommonEventsNames.AccessMembershipDisabled);

                        } else if (window.enableStickyHeader && self.isAccessMembershipEnabled()) {
                            $(document).trigger(Events.CommonEventsNames.AccessMembershipEnabled);
                        }
                    }
                });
            };
        })(self.saveChanges);
    }


    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        TalentSearchPreferencesViewModel: TalentSearchPreferencesViewModel
    });

})(window);


;
function TextMessagingPreferencesViewModel(config) {
    var defaultConfig = {
        endpoint: "textMessagingPreferences",
        passAgencyFolderName: true
    };

    var config = $.extend({}, defaultConfig, config);

    var self = OnlineApp.ViewModels.Base.EditableViewModel.call(this, config) || this;

    var TERMS_OF_USE_PAGE_PATH = window.CCPAChanges ? '/termsofuse' : '/legalprivacy';

    self.subscribedToTextMessages = ko.observable(false);

    self.isPhoneFieldVisible = ko.observable(false).extend({ ignoreOnSerialization: true });

    self.agencyName = ko.observable('');

    self.isOnGJobs = gJobs.areaInfoService.getCurrentArea() === gJobs.areaInfoService.areaNames.GJobs;

    if (self.isOnGJobs) {
        self.agencyFolderName = gJobs.pageInfoService.getCurrentAgencyPageFolderName();
    }

    self.subscribedToTextMessages.subscribe(function(value) {
        self.isPhoneFieldVisible(value === true);

        if (value === true) {
            gJobs.screenReadersService.setAriaLiveNotification("Phone section has been opened.");
        } else if (value === false){
            gJobs.screenReadersService.setAriaLiveNotification("Phone section has been closed.");
        }
    });

    self.textMessagingPhone = ko.computed({
        read: function () {
            if (self.maskedTextMessagingPhone()) {
                return ko.utils.unwrapObservable(self.maskedTextMessagingPhone).replace(/-/g, '');
            }

            return '';
        },
        deferEvaluation: true
    });

    self.maskedTextMessagingPhone = ko.observable('').extend({
        required: {
            onlyIf: function () {
                return ko.utils.unwrapObservable(self.isPhoneFieldVisible) === true;
            }
        },
        regexp: {
            onlyIf: function () {
                return ko.utils.unwrapObservable(self.isPhoneFieldVisible) === true;
            },
            pattern: /^[0-9]{3}-[0-9]{3}-[0-9]{4}$/,
            validationMessage: 'Phone number should be 10 digits long'
        },
        ignoreOnSerialization: true
    });

    self.phoneFieldAfterRender = function () {
        $('#text-messaging-phone').inputmask({'mask': '999-999-9999'});
    }

    self.linkToTermsAndPrivacy = ko.computed({
        read: function () {
            var agencyHomePagePath = AgencyPages && AgencyPages.pageInfoService
                && AgencyPages.pageInfoService.getCurrentAgencyHomePath();

            if (agencyHomePagePath) {
                return agencyHomePagePath + TERMS_OF_USE_PAGE_PATH;
            }

            return '/home' + TERMS_OF_USE_PAGE_PATH;
        },
        deferEvaluation: true
    }).extend({ ignoreOnSerialization: true });

    self.toggleButtonText = function (toggleValue) {
        return toggleValue ? 'ON' : 'OFF';
    };

    self.validate = function () {
        return self.isPhoneFieldVisible() ? self.maskedTextMessagingPhone.validate() : true;
    }

    self.fromDataModel = function (data) {
        if (!data) {
            return;
        }

        if (data.subscribedToTextMessages !== null) {
            self.subscribedToTextMessages(data.subscribedToTextMessages);
        }

        if (data.agencyName !== null) {
            self.agencyName(data.agencyName);
        }

        self.maskedTextMessagingPhone(textMessagingPhoneToMaskedPhone(data.textMessagingPhone));

        return self;
    };

    var textMessagingPhoneToMaskedPhone = function(textMessagingPhone) {
        return textMessagingPhone
            ? textMessagingPhone.slice(0, 3) + '-' + textMessagingPhone.slice(3, 6) + '-' + textMessagingPhone.slice(6)
            : null;
    }
};

OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
    TextMessagingPreferencesViewModel: TextMessagingPreferencesViewModel
});;
(function (window, undefined) {
    'use strict';

    function CanvassQuestionViewModel() {
        var self = OnlineApp.ViewModels.Base.ValidatableViewModel.apply(this, arguments) || this;

        self.id = ko.observable('');
        self.parentId = ko.observable('');
        self.question = ko.observable('');
        self.questionTypeId = ko.observable(0);
        self.name = ko.observable('');
        self.answer = ko.observable('');
        self.answerForTextArea = ko.observable('');
        self.checkBoxOneChecked = ko.observable('');
        self.checkBoxTwoChecked = ko.observable('');
        self.checkBoxThreeChecked = ko.observable('');
        self.children = ko.observableArray();
        self.attribute = ko.observable('');
        self.attributeValue = ko.observable('');
        self.level = ko.observable(0);
        self.sortOrder = ko.observable(0);
        self.isTouched = ko.observable(false);
        self.futureOptionRadioValue = ko.observable('');
        var isTouched = true;

        self.fromDataModel = function (data) {
            self.id(data.objectEntityId);
            self.question(data.question);
            self.children(data.children);
            self.questionTypeId(data.questionTypeId);
            self.name(data.name);
            self.parentId(data.parentId);
            self.attribute(data.attribute);
            self.attributeValue(data.attributeValue);
            self.level(data.level);
            self.sortOrder(data.sortOrder);
            self.answer(data.answer);
            self.answerForTextArea(data.answerForTextArea);
            self.checkBoxOneChecked(data.checkBoxOneChecked);
            self.checkBoxTwoChecked(data.checkBoxTwoChecked);
            self.checkBoxThreeChecked(data.checkBoxThreeChecked);
            self.futureOptionRadioValue(data.futureOptionRadioValue);

        }

        self.answer.isValidationMessageVisible = ko.computed({
            read: function () {
                var $canvassBody = $('#canvass-body');
                var isBuffalo = $canvassBody.find('.buffalo');

                if (isBuffalo) {
                    if (self.children()[3])
                        return self.hasError() && (self.children()[3].isTouched());
                    else if (self.children()[0])
                        return self.hasError() && self.children()[0].isTouched();
                    else
                        return self.hasError()

                }
                else {
                    return self.hasError() && self.children()[0].isTouched();
                }
            },
            write: function () { }
        });

        self.onRadioGroupEnter = function (context, ev) {
            gJobs.screenReadersService.onceNotification({
                $element: $(ev.target),
                message: self.question()
            });
        }

        //subscription to answer observable to notify root view model that it needs to be validated
        self.answer.subscribe(function () {
            var questionnaireViewModel = null;
            if (self.answer()) {
                window.isCurrentOptionChecked = true;
            }

            if (gJobs.areaInfoService.getCurrentArea() == gJobs.areaInfoService.areaNames.Career) {
                questionnaireViewModel = agencyPages.canvassViewModel.questionnaireViewModel;
            } else {
                questionnaireViewModel = gJobs.applicationsPage ?
                    gJobs.applicationsPage.canvassViewModel.questionnaireViewModel :
                    gJobs.searchPage.canvassViewModel.questionnaireViewModel;
            }

            questionnaireViewModel.validateQuestionnaire();
            questionnaireViewModel.emptyChildNodesAnswers();
        });

        self.futureOptionRadioValue.subscribe(function () {
            var questionnaireViewModel = null;
            window.futureOptionRadioValue = self.futureOptionRadioValue();
            isTouched = false;            
            if (gJobs.areaInfoService.getCurrentArea() == gJobs.areaInfoService.areaNames.Career) {
                questionnaireViewModel = agencyPages.canvassViewModel.questionnaireViewModel;
            } else {
                questionnaireViewModel = gJobs.applicationsPage ?
                    gJobs.applicationsPage.canvassViewModel.questionnaireViewModel :
                    gJobs.searchPage.canvassViewModel.questionnaireViewModel;
            }

            

        });

        self.checkBoxOneChecked.subscribe(function () {
            var questionnaireViewModel = null;
            window.checkBoxOneChecked = self.checkBoxOneChecked();
            if (gJobs.areaInfoService.getCurrentArea() == gJobs.areaInfoService.areaNames.Career) {
                questionnaireViewModel = agencyPages.canvassViewModel.questionnaireViewModel;
            } else {
                questionnaireViewModel = gJobs.applicationsPage ?
                    gJobs.applicationsPage.canvassViewModel.questionnaireViewModel :
                    gJobs.searchPage.canvassViewModel.questionnaireViewModel;
            }

            questionnaireViewModel.validateQuestionnaire();
            questionnaireViewModel.emptyChildNodesAnswers();
        });

        self.checkBoxTwoChecked.subscribe(function () {
            var questionnaireViewModel = null;
            window.checkBoxTwoChecked = self.checkBoxTwoChecked();
            if (gJobs.areaInfoService.getCurrentArea() == gJobs.areaInfoService.areaNames.Career) {
                questionnaireViewModel = agencyPages.canvassViewModel.questionnaireViewModel;
            } else {
                questionnaireViewModel = gJobs.applicationsPage ?
                    gJobs.applicationsPage.canvassViewModel.questionnaireViewModel :
                    gJobs.searchPage.canvassViewModel.questionnaireViewModel;
            }

            questionnaireViewModel.validateQuestionnaire();
            questionnaireViewModel.emptyChildNodesAnswers();
        });

        self.checkBoxThreeChecked.subscribe(function () {
            var questionnaireViewModel = null;
            window.checkBoxThreeChecked = self.checkBoxThreeChecked();
            if (gJobs.areaInfoService.getCurrentArea() == gJobs.areaInfoService.areaNames.Career) {
                questionnaireViewModel = agencyPages.canvassViewModel.questionnaireViewModel;
            } else {
                questionnaireViewModel = gJobs.applicationsPage ?
                    gJobs.applicationsPage.canvassViewModel.questionnaireViewModel :
                    gJobs.searchPage.canvassViewModel.questionnaireViewModel;
            }

            questionnaireViewModel.validateQuestionnaire();
            questionnaireViewModel.emptyChildNodesAnswers();
        });


        self.registerValidation({
            'all': {
                'answer': {
                    required: {
                        onlyIf: function () {
                            return self.children() && self.children().length;
                        }
                    }
                }

            }
        });
    };

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        CanvassQuestionViewModel: CanvassQuestionViewModel
    });
})(window);;
(function (window, undefined) {
    'use strict';

    function CanvassQuestionnaireViewModel() {
        var self = this;

        self.dueDate = ko.observable('');
        self.selectedAnswer = ko.observable('');

        //questions array of question view models
        self.questionViewModels = ko.observableArray();
        self.questionViewModelsForFuturePosition = ko.observableArray();
        self.questionViewModelsForCurrentPosition = ko.observableArray();
        self.originalQuestions = [];
        self.isReadOnlyView = ko.observable(false);
        var isCheckBoxOneChecked = false;
        var isCheckBoxTwoChecked = false;
        var isCheckBoxThreeChecked = false;
        var answerForTextArea = '';
        var futureOptionRadioValue = '';
        var valueForCheckBoxOne = '';
        var valueForCheckBoxTwo = '';
        var valueForCheckBoxThree = '';


        self.fromDataModel = function (data, isReadOnlyView) {
            self.dueDate(data.dueDate);
            self.isReadOnlyView(isReadOnlyView);

            if (data.questions) {

                isCheckBoxOneChecked = false;
                isCheckBoxTwoChecked = false;
                isCheckBoxThreeChecked = false;
                answerForTextArea = '';
                futureOptionRadioValue = '';
                self.originalQuestions = data.questions;
                self.questionViewModels.removeAll();
                self.questionViewModels.push(generateQuestionsTree(data.questions));


            }

            self.isValid(false);
        }

        function filterQuestions(questions, start, count) {
            var childQuestions = questions.filter(function (q) {
                return q.parentQuestionnaireId != null;
            });

            var mainQuestions = questions.filter(function (q) {
                return q.parentQuestionnaireId == null;
            });

            mainQuestions.sort(function (a, b) {
                return a.sortOrder - b.sortOrder;
            });

            return mainQuestions.slice(start, start + count).concat(childQuestions);
        }

        self.getAnswers = function () {
            var questionsWithAnswers = flattenQuestionsTree();

            self.originalQuestions.forEach(function (question) {
                var isAnswered = questionsWithAnswers.some(function (answer) {
                    return answer.questionnaireId === question.questionnaireId;
                });

                if (!isAnswered) {
                    // TODO: Add enum for Radio checked/unchecked state
                    var answerForType = (question.questionTypeId === 5)
                        ? '0'  // In case it's a radiobutton with no selection
                        : '';
                    questionsWithAnswers.push({
                        questionnaireId: question.questionnaireId,
                        answer: answerForType,
                        isRequired: false,
                        questionTypeId: question.questionTypeId,
                        sortOrder: question.sortOrder
                    });
                }
            });

            var $canvassBody = $('#canvass-body .canvass-main-container');
            var isBuffalo = $canvassBody.find('.buffalo').length;
            if (isBuffalo >= 1) {
                for (var i = 0; i < questionsWithAnswers.length; i++) {
                    if (questionsWithAnswers[i].questionTypeId == 4 && questionsWithAnswers[i].sortOrder == 0) {

                        questionsWithAnswers[i].answer = window.checkBoxOneChecked == true ? "1" : "0";
                        questionsWithAnswers[i].isRequired = window.checkBoxOneChecked == true ? true : false;
                    }
                    if (questionsWithAnswers[i].questionTypeId == 4 && questionsWithAnswers[i].sortOrder == 1) {

                        questionsWithAnswers[i].answer = window.checkBoxTwoChecked == true ? "1" : "0";;
                        questionsWithAnswers[i].isRequired = window.checkBoxOneChecked == true ? true : false;
                    }
                    if (questionsWithAnswers[i].questionTypeId == 4 && questionsWithAnswers[i].sortOrder == 2) {

                        questionsWithAnswers[i].answer = window.checkBoxThreeChecked == true ? "1" : "0";;
                        questionsWithAnswers[i].isRequired = window.checkBoxOneChecked == true ? true : false;
                    }
                    if (questionsWithAnswers[i].questionTypeId == 5 && questionsWithAnswers[i].sortOrder == 3) {

                        questionsWithAnswers[i].answer = window.futureOptionRadioValue == questionsWithAnswers[i].questionnaireId ? "1" : "0";
                        questionsWithAnswers[i].isRequired = true;
                    }
                    if (questionsWithAnswers[i].questionTypeId == 5 && questionsWithAnswers[i].sortOrder == 4) {

                        questionsWithAnswers[i].answer = window.futureOptionRadioValue == questionsWithAnswers[i].questionnaireId ? "1" : "0";
                        questionsWithAnswers[i].isRequired = true;
                    }

                }
            }
            return questionsWithAnswers;
        }

        self.emptyChildNodesAnswers = function () {

            var questions = self.questionViewModels();


            if (questions && questions.length > 0) {
                emptyChildNodesAnswersRecursive(questions[0]);
            }

        }

        self.isValid = ko.observable(false);

        self.validateQuestionnaire = function () {
            var $canvassBody = $('#canvass-body');
            var isBuffalo = $canvassBody.find('.buffalo');
            if (isBuffalo.length == 0) {
                var isValid = true;
                var questions = self.questionViewModels();
                if (questions && questions.length > 0) {
                    isValid = isValidRecursive(questions[0]);
                    self.isValid(isValid);
                } else {
                    self.isValid(true);
                }
            }
            else {
                var isValid = true;
                var isValidCheckBox = true;
                var questions = self.questionViewModels();
                if (questions && questions.length > 0) {
                    isValid = isValidRecursive(questions[0]);
                    for (var i = 0; i < self.originalQuestions.length; i++) {
                        if (questions[0].answer() == self.originalQuestions[i].questionnaireId && self.originalQuestions[i].questionTypeId == 5 && self.originalQuestions[i].sortOrder == 2) {

                            if (window.checkBoxOneChecked || window.checkBoxTwoChecked || window.checkBoxThreeChecked) {
                                isValidCheckBox = true;
                            }
                            else {
                                isValidCheckBox = false;
                            }
                            break;

                        }
                    }
                    if (isValid && isValidCheckBox) {
                        self.isValid(true);
                    }
                    else {
                        self.isValid(false);
                    }

                } else {
                    self.isValid(true);
                }


            }



        };



        // to do: make reusable recursive function
        function emptyChildNodesAnswersRecursive(parent, grandparent) {

            var children = parent.children();
            if (children) {
                children.forEach(function (item) {
                    if (grandparent && grandparent.answer && grandparent.answer() != parent.id()) {
                        parent.answer('');
                        parent.checkBoxOneChecked('');
                        parent.checkBoxTwoChecked('');
                        parent.checkBoxThreeChecked('');
                        item.isTouched(false);
                    }
                    emptyChildNodesAnswersRecursive(item, parent);
                });
            }

        }

        function flattenQuestionsTree() {

            var questions = [];

            ko.utils.arrayForEach(self.questionViewModels(), function (vm) {
                flattenNode(vm, questions);
            });


            return questions;
        }

        function flattenNode(node, arr) {
            if (!node) return;

            if (node.id()) {
                var answerForType = (node.questionTypeId() === 5 || node.questionTypeId() === 4)
                    ? '1'  // In case it's a selected radiobutton
                    : node.answer();
                arr.push({
                    questionnaireId: node.id(),
                    answer: answerForType,
                    isRequired: true,
                    questionTypeId: node.questionTypeId(),
                    sortOrder: node.sortOrder()
                });
            }

            if (node.children()) {
                // Searching for a text field or a radio button with answer among children
                var filteredNodes = node.children().filter(function (childNode) {
                    return (childNode.questionTypeId() === 1)
                        || (childNode.id() == node.answer());
                });
                var answerNode = filteredNodes ? filteredNodes[0] : null;

                if (answerNode && answerNode.questionTypeId() === 1) {
                    arr.push({
                        questionnaireId: answerNode.id(),
                        answer: node.answer(),
                        isRequired: true
                    });
                } else {
                    flattenNode(answerNode, arr);
                }
            }
        }

        function isValidRecursive(parent, grandparent) {
            var isValid = true;

            if (grandparent && grandparent.answer && grandparent.answer() == parent.id()) {
                isValid = parent.validate();
            }

            var children = parent.children();
            if (children && isValid) {
                children.forEach(function (item) {
                    var isValidChild = isValidRecursive(item, parent);
                    isValid = isValid && isValidChild;
                });
            }

            return isValid;
        }

        function generateQuestionsTree(questions) {
            return generateNode(questions, {}, 0, null);
        }


        function getAnswerAmongChildren(children) {
            if (children) {
                for (var i = 0; i < children.length; i++) {
                    var item = children[i];

                    if (item.questionTypeId == 1) {
                        return item.answer;
                    } else if ((item.questionTypeId == 5 || item.questionTypeId == 4) && (item.answer == 1)) {
                        return item.questionnaireId;
                    }
                }
            }
        }

        function generateNode(questions, nodeQuestion, level, parentId, answer) {
            var children = getChildren(questions, nodeQuestion.questionnaireId, level);
            var vm = new OnlineApp.ViewModels.CanvassQuestionViewModel();

            var $canvassBody = $('#canvass-body .canvass-main-container');
            var isBuffalo = $canvassBody.find('.buffalo').length;


            if (isBuffalo == 1) {
                if (nodeQuestion.questionTypeId == 4 && nodeQuestion.sortOrder == 0 && nodeQuestion.answer == "1") {
                    isCheckBoxOneChecked = true;
                    valueForCheckBoxOne = nodeQuestion.questionnaireId;
                }
                if (nodeQuestion.questionTypeId == 4 && nodeQuestion.sortOrder == 1 && nodeQuestion.answer == "1") {
                    isCheckBoxTwoChecked = true;
                    valueForCheckBoxTwo = nodeQuestion.questionnaireId;
                }
                if (nodeQuestion.questionTypeId == 4 && nodeQuestion.sortOrder == 2 && nodeQuestion.answer == "1") {
                    isCheckBoxThreeChecked = true;
                    valueForCheckBoxThree = nodeQuestion.questionnaireId;
                }
                if (nodeQuestion.questionTypeId == 1 && nodeQuestion.sortOrder != 0) {
                    answerForTextArea = nodeQuestion.answer;
                }
                if (nodeQuestion.questionTypeId == 5 && nodeQuestion.sortOrder == 3 && nodeQuestion.answer == "1") {
                    futureOptionRadioValue = nodeQuestion.questionnaireId;
                }
                if (nodeQuestion.questionTypeId == 5 && nodeQuestion.sortOrder == 4 && nodeQuestion.answer == "1") {
                    futureOptionRadioValue = nodeQuestion.questionnaireId;
                }
                
                var treeNode = {
                    id: nodeQuestion.questionnaireId,
                    objectEntityId: nodeQuestion.questionnaireId,
                    parentId: parentId,
                    question: ConvertStringToHTML(nodeQuestion.question),
                    questionTypeId: nodeQuestion.questionTypeId,
                    attribute: nodeQuestion.questionnaireAttributeTypeCode,
                    attributeValue: nodeQuestion.attributeValue,
                    level: level,
                    required: true,
                    children: children.childNodes,
                    name: nodeQuestion.questionTypeId == 5 ? "cf-" + window.capacity : "cf-" + level,
                    sortOrder: nodeQuestion.sortOrder,
                    answer: nodeQuestion.questionTypeId == 4 ? undefined : children.answer != undefined ? children.answer.toString() : "",
                    checkBoxOneChecked: isCheckBoxOneChecked == true ? valueForCheckBoxOne : undefined,
                    checkBoxTwoChecked: isCheckBoxTwoChecked == true ? valueForCheckBoxTwo : undefined,
                    checkBoxThreeChecked: isCheckBoxThreeChecked == true ? valueForCheckBoxThree : undefined,
                    answerForTextArea: answerForTextArea,
                    futureOptionRadioValue: futureOptionRadioValue
                    

                };
                vm.fromDataModel(treeNode);
            }
            else {
                var treeNode = {
                    id: nodeQuestion.questionnaireId,
                    objectEntityId: nodeQuestion.questionnaireId,
                    parentId: parentId,
                    question: nodeQuestion.question,
                    questionTypeId: nodeQuestion.questionTypeId,
                    attribute: nodeQuestion.questionnaireAttributeTypeCode,
                    attributeValue: nodeQuestion.attributeValue,
                    level: level,
                    required: true,
                    children: children.childNodes,
                    name: "cf-" + level,
                    sortOrder: nodeQuestion.sortOrder,
                    answer: children.answer != undefined ? children.answer.toString() : "",
                };
                vm.fromDataModel(treeNode);
            }

            return vm;
        }

        let ConvertStringToHTML = function (str) {
            let parser = new DOMParser();
            let doc = parser.parseFromString(str, 'text/html');
            return doc.body;
        };

        function getChildren(questions, id, level) {
            var childQuestions = questions.filter(function (q) {
                return q.parentQuestionnaireId == id;
            });

            childQuestions = childQuestions.sort(function (a, b) {
                return a.sortOrder - b.sortOrder;
            });

            var answer = getAnswerAmongChildren(childQuestions);
            var childNodes = childQuestions.map(function (q) {
                return generateNode(questions, q, level + 1, id);
            });

            return { childNodes: childNodes, answer: answer };
        }
    };

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        CanvassQuestionnaireViewModel: CanvassQuestionnaireViewModel
    });
})(window);
function blurRadio(e) {
    var radio = document.getElementsByName('buffaloRadio');
    var flag = false;
    for (var i = 0; i < radio.length; i++) {
        if (radio[i].checked) {
            flag = true;
        }
    }
    if (!flag) {
        $('.radioValidation').removeAttr('hidden');
    }
}
function getRadioValue() {
    $('.radioValidation').attr('hidden','true');
    var radio = document.getElementsByName('buffaloRadio');
    for (var i = 0; i < radio.length; i++) {
        if (radio[i].checked) {

            document.getElementById(radio[i].id).setAttribute('aria-checked', 'true');
        }
        else {
            document.getElementById(radio[i].id).setAttribute('aria-checked', 'false');
        }
    }
}

function getCheckBoxValue() {

    var checkBox = document.getElementsByName('buffaloCheckBox');
    for (var i = 0; i < checkBox.length; i++) {
        if (checkBox[i].checked) {

            document.getElementById(checkBox[i].id).setAttribute('aria-checked', 'true');
        }
        else {
            document.getElementById(checkBox[i].id).setAttribute('aria-checked', 'false');
        }
    }
}

function textAreaValidation(event) {
    var id = event.target.id;
    var deferementTextArea = document.getElementById(id);
    if (deferementTextArea) {
        var text = document.getElementById(id).value;
        if (text != null && text != undefined && text != '') {
            document.getElementById(id).removeAttribute('aria-describedby');
        }
        else {
            document.getElementById(id).setAttribute('aria-describedby', id + '-canvass-form-field-error-message');
           
        }
    }

};
(function (window, undefined) {
    'use strict';

    function CanvassViewModel() {
        var self = this;

        self.questionnaireViewModel = new OnlineApp.ViewModels.CanvassQuestionnaireViewModel();
        self.signatureViewModel = new OnlineApp.ViewModels.SignatureViewModel();

        self.isMobile = gJobs.browserDetector.isMobileBrowser();
        self.canvassId = ko.observable(0);
        self.title = ko.observable('');
        self.jobTitle = ko.observable('');
        self.dueDate = ko.observable('');
        self.dateAnswered = ko.observable('');
        self.description = ko.observable('');

        self.isBusy = ko.observable(false);
        self.isReadOnlyView = ko.observable(false);
        self.isSubmitted = false;

        self.phone = ko.computed({
            read: function () {
                if (self.maskedPhone()) {
                    return ko.utils.unwrapObservable(self.maskedPhone).replace(/-/g, '');
                }

                return '';
            },
            deferEvaluation: true
        });

        self.date = ko.computed({
            read: function () {
                if (self.maskedDate()) {
                    return ko.utils.unwrapObservable(self.maskedDate);
                }

                return '';
            },
            deferEvaluation: true
        });

        self.maskedPhone = ko.observable('').extend({
            required: {},
            regexp: {
                pattern: /^[0-9]{3}-[0-9]{3}-[0-9]{4}$/,
                validationMessage: 'Phone number should be 10 digits long'
            },
            ignoreOnSerialization: true
        });
        self.maskedDate = ko.observable('').extend({
            required: {},
            ignoreOnSerialization: true
        });

        self.phoneFieldAfterRender = function () {
            $('#canvass-form-phone').inputmask({ 'mask': '999-999-9999' });
        }
        self.dateFieldAfterRender = function () {
            $('#canvass-form-date').inputmask({ 'mask': 'MM/DD/YYYY' });                

        }



        self.isTemporaryUnavailabilitySectionVisible = ko.observable(false);
        self.TemporaryUnavailabilityReason = ko.observable('').extend({
            length: {
                max: 114,
                validationMessage: 'Unavailability reason is too long and is limited to 114 characters'
            }
        });

        self.isValid = ko.computed(function () {
            return self.isReadOnlyView()
                || (self.maskedPhone().trim() !== "" && !self.maskedPhone.hasError() && self.maskedDate().trim() !== "" && !self.maskedDate.hasError()
                    && self.questionnaireViewModel.isValid()
                    && self.signatureViewModel.isSignatureCompleted()
                    && !self.signatureViewModel.isSignatureInEditMode());
        });

        self.submit = function () {
            if (self.isSubmitted) {
                return;
            }

            self.isSubmitted = true;
            self.isBusy(true);
            var signature = self.signatureViewModel.signature();
            var answers = self.questionnaireViewModel.getAnswers();           

            OnlineApp.Services.dataService.canvassForm.post({
                sentCanvassFormId: self.canvassId(),
                signature: signature,
                phoneNumber: self.phone(),
                questionAnswers: answers
            })
                .then(function (data) {
                    if (data.isSuccess) {
                        OnlineApp.Services.canvassFlyoutService.closeCanvassFormFlyout();
                        OnlineApp.Services.canvassFlyoutService.changeCanvassFormStatus(self.canvassId(), data.dateAnswered, self.jobTitle());
                        toastr.success('Canvass form submitted');
                        gJobs.screenReadersService.setAriaLiveNotification('Canvass form submitted');
                    }
                })
                .always(function () {
                    self.isSubmitted = false;
                    self.isBusy(false);
                });
        }

        self.fromDataModel = function (data) {
            self.canvassId(data.canvassFormId);
            self.jobTitle(data.jobTitle);
            self.dueDate(data.dueDate);
            self.dateAnswered(data.dateAnswered);
            self.description(data.description);
            self.isReadOnlyView(data.isReadOnly);
            var dateAnswered = new Date();

           
            $('#canvass-form-date').val(dt)
            
            if (self.isReadOnlyView()) {
                dateAnswered = new Date(data.dateAnswered);
               
                
                self.maskedPhone(formatAsPhoneNumber(data.phoneNumber));

                $('a.ss-print.popover-trigger')
                    .attr('href', '/applications/canvass/print/' + self.canvassId());
                $('a.ss-print.popover-trigger').show();
                $('a.ss-download.popover-trigger').show();
            } else {
                $('a.ss-print.popover-trigger').hide();
                $('a.ss-download.popover-trigger').hide();
            }

            var month = dateAnswered.getMonth() + 1;
            var day = dateAnswered.getDate();
            var year = dateAnswered.getFullYear();
            if (month < 10)
                month = '0' + month.toString();
            if (day < 10)
                day = '0' + day.toString();

            var dt = year + '-' + month + '-' + day;
            $('#canvass-form-date').attr('min', dt);
            $('#canvass-form-date').val(dt)
            $('#canvass-form-date').keydown();
            self.maskedDate(dt);

            self.questionnaireViewModel.fromDataModel(data, self.isReadOnlyView());
            self.signatureViewModel.signature(null);
            self.signatureViewModel.fromDataModel(data.signature, self.isReadOnlyView(), data.dateAnswered, data.applicantName);
            self.maskedPhone.isValidationMessageVisible(false);
            self.maskedPhone.hasError(false);
            self.maskedDate.isValidationMessageVisible(false);
            self.maskedDate.hasError(false);
        }

        function formatAsPhoneNumber(phone) {
            return phone.slice(0, 3) + '-' + phone.slice(3, 6) + '-' + phone.slice(6);
        }
    }

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        CanvassViewModel: CanvassViewModel
    });
})(window);;
var editJobAlertIndex;
(function (window, undefined) {
    'use strict';

    var ARIA_LIVE_NOTIFICATION_CONTAINER = $("#aria-live-message-container");

    var $jobAlertPopup = $('#job-alert-out-container');
    var $deleteJobAlertPopup = $('#job-alert-preference-dialog')
    var $jobAlertAuthorizationPopup = $('#job-alert-authorization-popup');
    var $jobAlertAccessMembershipPopup = $('#job-alert-access-membership-popup');
    var $jobAlertShadow = $('#job-alert-shadow');
    var $headerShadow = $('#header-shadow');
    var $jobAlertPreferences = $('#job-alert-preferences-container');
    var $jobAlertEditView = $('#job-alert-sidebar-container');
    var $searchFormView = $('#search-form');
    var $stickyHeader = $('#sticky-header');
    var $setJobAlertBtn = $('#set-job-alert');    
    var isExistingJobAlert = false;

    var jobAlertIndex;
    var jobAlertLocationAutocompleteMenuClassName = 'job-alert-location-autocomplete-menu';
    var jobAlertKeywordAutocompleteMenuClassName = 'job-alert-keyword-autocomplete-menu';
    var jobAlertSearchFieldSelector = '#job-alert-location-search-input';
    var jobAlertKeywordSearchFieldSelector = '#job-alert-keyword-search-input';
    var displayJobAlertsLoginPopupQueryParameter = "displayJobAlertsLoginPopup";
    var facetGroupNameDataAttribute = "facet-group-name";
    var facetFilterNameDataAttribute = "facet-filter-name";
    var facetGroupNames = {
        datePosted: "Date Posted",
        remote: "Remote",
        jobType: "Job Type",
        organizations: "Top Organizations",
        categories: "Top Categories",
        salary: "Salary Estimate"
    };

    var initialLocation;
    var selectedOrganization;
    var selectedCategory;
    var selectedSalary;
    var selectedRemoteWorkOptionId;
    var selectedJobType;

    const gJobsSite = 0;
    const sJobsSite = 1;
    
    function JobAlertsViewModel() {
        //var self = this;
        var config = {
            endpoint: "jobAlertsPreferences"
        };
        var self = OnlineApp.ViewModels.Base.EditableViewModel.call(this, config) || this;

        self.jobAlerts = ko.observableArray([]);
        self.jobAlertsGJobs = ko.observableArray([]);
        self.jobAlertsSJobs = ko.observableArray([]);
        self.jobAlertPreference = ko.observable();
        self.isInEditMode = ko.observable(false);
        self.jobAlertsIsEmpty = ko.observable(false);
        self.jobAlertsGJobsIsEmpty = ko.observable(false);
        self.jobAlertsSJobsIsEmpty = ko.observable(false);
        self.frequencyPreference = ko.observable();
        self.selectedJobAlert = ko.observable();
        self.selectedFrequency = ko.observable();
        self.isInDeleteMode = ko.observable(false);
        self.isAccessMembershipEnabled = ko.observable(false);
        self.isJobAlertsEnabled = ko.observable(false);
        self.isLoggedIn = ko.observable(false);
        self.jobSeekerId = ko.observable(0);

        self.initialToggleValue = ko.observable();
        self.initialFrequencyValue = ko.observable();

        self.isJobAlertsEnabled.subscribe(function (value) {

            if (self.initialToggleValue() == null && value !== null) {
                self.initialToggleValue(value);
            }

            self.isJobAlertsEnabled(value);
            var jobAlertNotification = "Job Alert is " +
                (value ? "active" : "inactive");

            gJobs.screenReadersService.setAriaLiveNotification(jobAlertNotification);
        });

        self.showHideAriaLabel = function () {
            if ($("fieldset.radio-set.css3-radio").length > 0) {
                $("fieldset.radio-set.css3-radio").each(function (i) {
                    $("fieldset.radio-set.css3-radio")[i].removeAttribute("aria-required");
                });
            }
        }

        OnlineApp.Services.authenticationService.isLoggedIn()
            .done(function (isLoggedIn) {
                self.isLoggedIn(isLoggedIn);

                if (self.isLoggedIn()) {
                    OnlineApp.Services.jobAlertService.getAll().then(function (data) {
                        data.jobAlerts.sort(function (a, b) {
                            return a.SiteSource - b.SiteSource;
                        });
                        data.jobAlerts.forEach(function (value, i) {
                            value.Index = i;
                        })
                        self.jobAlerts(data.jobAlerts);
                        self.jobAlertsGJobs(data.jobAlerts.filter(function (jobAlertElement) {
                            return jobAlertElement.SiteSource == gJobsSite;
                        }));
                        self.jobAlertsSJobs(data.jobAlerts.filter(function (jobAlertElement) {
                            return jobAlertElement.SiteSource == sJobsSite;
                        }));

                        self.jobAlertsGJobsIsEmpty(data.jobAlerts.filter(function (g) { var countGJobs = 0; if (g.SiteSource == gJobsSite) { countGJobs++; } return countGJobs; }).length == 0);
                        self.jobAlertsSJobsIsEmpty(data.jobAlerts.filter(function (s) { var countSJobs = 0; if (s.SiteSource == sJobsSite) { countSJobs++; } return countSJobs; }).length == 0);
                        
                        self.jobAlertsIsEmpty(data.jobAlerts.length == 0);
                        
                        self.jobAlertPreference(data.jobAlertPreference);
                        self.jobSeekerId(data.jobAlertPreference.JobSeekerId);
                        self.isJobAlertsEnabled(data.jobAlertPreference.IsJobAlertEnabled);
                        self.frequencyPreference(data.jobAlertPreference.SentJobAlertsFrequency.toString());
                        self.isAccessMembershipEnabled(data.isAccessMembershipEnabled);
                    })
                }
            });



        self.isInEditMode.subscribe(function (value) {
            var $jobAlertsPreferencesTab = $('.job-alerts-preferences-tab');
            var nonEditModeClassName = 'non-edit-mode';

            if (value) {
                $jobAlertsPreferencesTab.removeClass(nonEditModeClassName);
            } else {
                $jobAlertsPreferencesTab.addClass(nonEditModeClassName);
            }
        });

        self.radioButtonOptions = ko.observable({
            frequencyPreference: [
                {
                    value: '0',
                    id: 'job-alert-frequency-preference-weekly',
                    name: 'ci-radioSet-notify',
                    label: 'Weekly'
                },
                {
                    value: '1',
                    id: 'job-alert-frequency-preference-daily',
                    name: 'ci-radioSet-notify',
                    label: 'Daily'
                }
            ]
        }).extend({ ignoreOnSerialization: true });

        self.frequencyPreference.subscribe(function (value) {
            if (!self.initialFrequencyValue()) {
                self.initialFrequencyValue(self.frequencyPreference())
            }
            self.frequencyPreference(value.toString());
        });

        self.saveChanges = function (item) {
            var frequency = self.frequencyPreference();
            var isJobAlertsEnabled = self.isJobAlertsEnabled();
            OnlineApp.Services.jobAlertService.updateJobAlertPreferences(frequency, isJobAlertsEnabled)
                .then(function (data) {
                    self.jobAlertPreference(data.jobAlertPreference);
                    self.initialToggleValue(isJobAlertsEnabled);
                    self.initialFrequencyValue(frequency);
                    self.endEdit(item);
                    self.focusEditButton(true);

                    OnlineApp.Helpers.layoutHelper.tabbing.updateIndices('.job-alerts-list');
                })
        }

        self.discardChanges = function (item) {
            self.frequencyPreference(self.initialFrequencyValue().toString());
            self.isJobAlertsEnabled(self.initialToggleValue());

            gJobs.screenReadersService.setAriaLiveNotification("Job Alert is " + (self.initialToggleValue() ? "active" : "inactive"));

            self.endEdit(item);
            self.focusEditButton();
        }

        self.focusEditButton = function (saved) {
            var $editableItemContainer = $('#job-alerts-preferences');
            var $editButton = $editableItemContainer.find('.item-edit-button');

            if (saved) {
                gJobs.screenReadersService.setAriaLiveNotification("Job Alert Preferences has been saved.");
                ARIA_LIVE_NOTIFICATION_CONTAINER.focus();
            }

            $editButton.focus();
        }

        self.beginEdit = function (item) {
            var editableItem = item.clone();

            item.isInEditMode(true);
            editableItem.isInEditMode(true);

            self.editableItem(editableItem);
            OnlineApp.Helpers.layoutHelper.tabbing.updateIndices('.job-alerts-list');
            $('#job-alerts-preferences').find(':focusable').first().focus();
        }

        self.fromDataModel = function (data) {
            if (!data) {
                return;
            }

            self.isJobAlertsEnabled(data.isJobAlertsEnabled);
        };

        self.openDeleteJobAlertDialog = function (jobAlert) {
            jobAlert.JobSeekerId = self.jobSeekerId();
            self.selectedJobAlert(jobAlert);
            showHideElementsOnDialog(false);
            gJobs.dialogHelper.disableTabIndexOnParentView();
            self.isInDeleteMode(true);
            showHideDeleteJobAlertPopup(true);
            hideScrollBar('html');

            jobAlertIndex = jobAlert.Index;
            gJobs.dialogHelper.setTabIndexOnJobAlertsPopup("#job-alert-preference-dialog");
            focusOnFistTabbableDialogElement($('.job-alert-preference-dialog'));
        };

        self.closeDeleteJobAlertDialog = function () {
            gJobs.screenReadersService.setAriaLiveNotification("Delete Job Alert modal is closed.");
            ARIA_LIVE_NOTIFICATION_CONTAINER.focus();

            self.isInDeleteMode(false);
            $jobAlertPreferences.addClass("hidden");
            showScrollBar('html');
            showHideDeleteJobAlertPopup(false);
            showHideElementsOnDialog(false);
            focusOnDeleteButton(jobAlertIndex);
        };

        self.deleteJobAlert = function () {
            var jobAlert = self.selectedJobAlert();
            jobAlert.JobSeekerId = self.jobSeekerId();
            var disableJobAlert = self.jobAlerts().length === 1;
            OnlineApp.Services.jobAlertService.deleteJobAlert(jobAlert.JobAlertId, disableJobAlert, jobAlert.JobSeekerId)
                .done(function (response) {
                    showHideElementsOnDialog(false);
                    gJobs.screenReadersService.setAriaLiveNotification("Job Alert was deleted.");
                    ARIA_LIVE_NOTIFICATION_CONTAINER.focus();

                    self.isInDeleteMode(false);
                    self.jobAlerts.remove(jobAlert);
                    if (jobAlert.SiteSource == gJobsSite) {
                        self.jobAlertsGJobs.remove(jobAlert);
                    }
                    if (jobAlert.SiteSource == sJobsSite) {
                        self.jobAlertsSJobs.remove(jobAlert);
                    }
                    showScrollBar('html');

                    if (disableJobAlert) {
                        self.isInEditMode(false);
                        self.jobAlertsIsEmpty(true);
                        self.jobAlertsGJobsIsEmpty(true);
                        self.jobAlertsSJobsIsEmpty(true);
                        self.isJobAlertsEnabled(false);
                    }
                    gJobs.dialogHelper.setTabIndexOnJobAlertsPopup("#setJobAlertDialog");
                    focusOnFistTabbableDialogElement($('.job-alerts-list'));
                    $headerShadow.addClass('hidden');
                })
        };

        self.editJobAlert = function (jobAlert) {
            jobAlertIndex = jobAlert.Index;
            editJobAlertIndex = jobAlert.Index;
            OnlineApp.Services.jobAlertService.getJobAlertEditModel(jobAlert)
                .done(function (response) {
                    $jobAlertEditView.html(response.data);
                    $searchFormView.html(response.searchForm);
                    window.isJobAlertEdit = true;
                    gJobs.screenReadersService.setAriaLiveNotification("Edit Job Alert flyout is openned.");
                    ARIA_LIVE_NOTIFICATION_CONTAINER.focus();
                    $jobAlertEditView.removeClass("hidden");
                    $jobAlertEditView.css({ height: window.innerHeight-95 });
                    hideScrollBar('html');
                    $('#skip-to-content-button').focus();
                    $("#account-settings").attr('aria-hidden', true);
                    $("#account-settings").attr('visible', false);
                    var $tabbableElements;
                    $tabbableElements = $('#account-settings')
                        .find(':tabbable');
                    $tabbableElements.attr('tabindex', -1);
                    $("#footer-new").hide();
                    $("#sjobs-footer-new").hide();
                })
        };

        $(document)
            .on(Events.CommonEventsNames.JobAlertUpdated, function () {
                OnlineApp.Services.jobAlertService.getAll().then(function (data) {
                    data.jobAlerts.sort(function (a, b) {
                        return a.SiteSource - b.SiteSource;
                    });
                    data.jobAlerts.forEach(function (value, i) {
                        value.Index = i;
                    })
                    self.jobAlerts(data.jobAlerts);
                    self.jobAlertsGJobs(data.jobAlerts.filter(function (jobAlertElement) {
                        return jobAlertElement.SiteSource == 0;
                    }));
                    self.jobAlertsSJobs(data.jobAlerts.filter(function (jobAlertElement) {
                        return jobAlertElement.SiteSource == 1;
                    }));
                    OnlineApp.Helpers.layoutHelper.tabbing.updateIndices('.job-alerts-list');
                })
            })
            .on(Events.CommonEventsNames.AccessMembershipDisabled, function (event, data) {
                self.isAccessMembershipEnabled(false);
                self.isJobAlertsEnabled(false);
                self.initialToggleValue(false);
                self.isInEditMode(false);
            })
            .on(Events.CommonEventsNames.AccessMembershipEnabled, function (event, data) {
                self.isAccessMembershipEnabled(true);
                self.isInEditMode(false);
            })
            .on(Events.CommonEventsNames.Login + " " + Events.CommonEventsNames.Register, function (event, data) {
                OnlineApp.Services.jobAlertService.getAll().then(function (data) {
                    data.jobAlerts.sort(function (a, b) {
                        return a.SiteSource - b.SiteSource;
                    });
                    data.jobAlerts.forEach(function (value, i) {
                        value.Index = i;
                    })
                    self.jobAlerts(data.jobAlerts);
                    self.jobAlertsGJobs(data.jobAlerts.filter(function (jobAlertElement) {
                        return jobAlertElement.SiteSource == gJobsSite;
                    }));
                    self.jobAlertsSJobs(data.jobAlerts.filter(function (jobAlertElement) {
                        return jobAlertElement.SiteSource == sJobsSite;
                    }));

                    self.jobAlertsGJobsIsEmpty(data.jobAlerts.filter(function (g) { var countGJobs = 0; if (g.SiteSource == gJobsSite) { countGJobs++; } return countGJobs; }).length == 0);
                    self.jobAlertsSJobsIsEmpty(data.jobAlerts.filter(function (s) { var countSJobs = 0; if (s.SiteSource == sJobsSite) { countSJobs++; } return countSJobs; }).length == 0);
                    
                    self.jobAlertsIsEmpty(data.jobAlerts.length == 0);
                    
                    self.jobAlertPreference(data.jobAlertPreference);
                    self.isJobAlertsEnabled(data.jobAlertPreference.IsJobAlertEnabled);
                    self.frequencyPreference(data.jobAlertPreference.SentJobAlertsFrequency.toString());
                    self.isAccessMembershipEnabled(data.isAccessMembershipEnabled);
                    $stickyHeader.hide();
                })
            })
    }

    $(document).ready(function () {
        var showJobAlertPopup = sessionStorage.getItem(OnlineApp.LocalStorageKeys.ShowJobAlertPopup);        
        if (showJobAlertPopup === 'true') {
            sessionStorage.setItem(OnlineApp.LocalStorageKeys.ShowJobAlertPopup, "false");
            sessionStorage.setItem(OnlineApp.LocalStorageKeys.RedirectToShowJobAlertPopup, "false");

            OnlineApp.Services.jobAlertService.isJobAlertCanBeCreated(OnlineApp.Helpers.Url.getJsonFromUrl(location.search))
                .done(function () {
                    showHideJobAlertPopup(true);
                });

        }
    })

    $(document).keydown(function (e) {
        if (e.keyCode == $.ui.keyCode.ESCAPE) {
            var elementsToExclude = getListOfElmentsToBeExcluded();
            if (elementsToExclude.includes(e.target.id)) {
                return;
            }

            if (e.target.id != 'gmapLink' && $(e.target).attr('data-toggle') != 'popover') {
                if ($(e.target).hasClass('things-to-consider-popover-trigger')
                    || $(e.target).hasClass('st-custom-button')
                    || $(e.target).hasClass('job-details-location-icon')
                    || $(e.target).hasClass('job-details-salary-icon')
                    || $(e.target).hasClass('inbox-header-id')
                    || $(e.target).hasClass('flag-left')
                    || $(e.target).hasClass('doNotSellMyPersonalInformationDialogCloseButton')) return;
                if ($('.job-alert-preferences').length && !$('.job-alert-preferences').is(':visible') && $jobAlertEditView.length && $jobAlertEditView.hasClass('hidden') && !isExistingJobAlert) return;
                var deleteModeWasActive = $('.job-alert-preferences').length && $('.job-alert-preferences').is(':visible');
                $jobAlertAuthorizationPopup.addClass('hidden');
                var closeJobAlertButton = document.getElementById("close-job-alert");
                var closeJobAlertOkButton = document.getElementById("close-job-alert-ok-button");
                var closeJobAlertDeleteButton = document.getElementById("close-job-alert-delete");

                var closeAccessMembershipAlert = document.getElementById("close-access-membership-alert");
                if (typeof (closeAccessMembershipAlert) != 'undefined' && closeAccessMembershipAlert != null) {
                    closeAccessMembershipAlert.click();
                }

                if (typeof (closeJobAlertButton) != 'undefined' && closeJobAlertButton != null) {
                    closeJobAlertButton.click();
                }
                if (typeof (closeJobAlertOkButton) != 'undefined' && closeJobAlertOkButton != null) {
                    closeJobAlertOkButton.click();
                }
                if (typeof (closeJobAlertDeleteButton) != 'undefined' && closeJobAlertDeleteButton != null) {
                    closeJobAlertDeleteButton.click();
                }
                self.closeJobAlert();
                self.closeEditMode();
                if (isExistingJobAlert) { self.showJobAlertEditView(); isExistingJobAlert = false; } else { $setJobAlertBtn.focus(); }
                if (deleteModeWasActive) {
                    var setJobAlertIndex = jobAlertIndex ? jobAlertIndex : 0;
                    focusOnDeleteButton(setJobAlertIndex);
                }
            }
            if ($(e.target).attr('data-toggle') == 'popover') {
                $(e.target).popover('hide');
            }
        } else if (e.keyCode == $.ui.keyCode.ENTER) {
            if (e.target.className === "btn-show-results" || e.target.className === "hidden-facet clearAllFilter") {
                self.showResults();
            }
            else if (e.target.className === "btn-gjobs-secondary") {
                if (e.target.id != "set-job-alert") {
                    self.showResults(e.target.className);
                }
            }
            else if (e.target.className === "facet-link") {
                $(e.target).click();
            }
        }
    });   

    self.setJobAlert = function () {
        $stickyHeader.hide();
        $('#content').removeClass('respect-sticky-header');
        gJobs.dialogHelper.setTabIndexOnJobAlertsPopup("#setJobAlertDialog");

        if ($('#job-alert-access-membership-popup')[0]) {
            var isAccessMemberShipEnabled = false;
            $(document).on(Events.CommonEventsNames.AccessMembershipEnabled, function () {
                isAccessMemberShipEnabled = true;
            });
            $(document).on(Events.CommonEventsNames.CloseAccessMembershipDialog, function (event) {
                if (isAccessMemberShipEnabled) {
                    $jobAlertAccessMembershipPopup.remove();
                    $('#job-alert-out-container').removeClass('hidden');
                    gJobs.dialogHelper.setTabIndexOnJobAlertsPopup("#setJobAlertDialog");
                }
                else {
                    self.showHideJobAlertAcessMembershipPopup(true, false);
                }
            });
            //Event handler added to prevent displaying both landing accesmembership dialog and job alert accessmembership  popup if page refreshed post set jobalert sign in
            $(document).on(Events.CommonEventsNames.OpenAccessMembershipDialog, function () {
                self.showHideJobAlertAcessMembershipPopup(false, false);
            });
        }

        OnlineApp.Services.authenticationService.isLoggedIn()
            .done(function (isLoggedIn) {
                showHideElementsOnDialog(false);
                gJobs.dialogHelper.disableTabIndexOnParentView();
                hideScrollBar('body');
                hideScrollBar('html');
                if (isLoggedIn) {
                    if ($('#job-alert-access-membership-popup')[0]) {
                        self.showHideJobAlertAcessMembershipPopup(true, true);
                        return;
                    }
                    else
                        showHideJobAlertPopup(true);
                }
                else {
                    showHideJobAlertAuthPopup(true);
                    OnlineApp.ViewModels.applicationViewModel.loginViewModel.signInViewModel.showJobAlert(true);
                    OnlineApp.ViewModels.applicationViewModel.loginViewModel.registerViewModel.showJobAlert(true);

                    if (window.enableEmailVerificationRefinements) {
                        if (!window.utils.getUrlParameter(displayJobAlertsLoginPopupQueryParameter)) {
                            var currentUrl = addEmailVerificationParametersToUrl();
                            history.pushState(null, "", currentUrl);
                        }
                    }
                }
                gJobs.screenReadersService.setAriaLiveNotification("Set Job Alert modal is openned.");
                ARIA_LIVE_NOTIFICATION_CONTAINER.focus();
                gJobs.dialogHelper.setTabIndexOnJobAlertsPopup("#setJobAlertDialog");
                focusOnFistTabbableDialogElement(isLoggedIn ? $jobAlertPopup : $jobAlertAuthorizationPopup);
            });
    }
    self.addJobAlert = function (searchCriteria) {
        $("#add-job-alert").attr("disabled", true);
        OnlineApp.Services.jobAlertService.addJobAlert(searchCriteria)
            .done(function (response) {
                showHideElementsOnDialog(false);
                gJobs.dialogHelper.disableTabIndexOnParentView();
                $('#job-alert-out-container').html(response);
                $(document).trigger(Events.CommonEventsNames.JobAlertCreated);
                gJobs.dialogHelper.setTabIndexOnJobAlertsPopup("#setJobAlertDialog");
            })
    }

    self.updateJobAlert = function (jobAlert) {

        jobAlert.Location = document.getElementById('job-alert-location-search-input').value;
        jobAlert.Keyword = document.getElementById('job-alert-keyword-search-input').value;

        OnlineApp.Services.jobAlertService.updateJobAlert(jobAlert)
            .done(function (response) {
                showHideElementsOnDialog(false);
                gJobs.dialogHelper.disableTabIndexOnParentView();
                var updateResultMessage = "Job Alert is saved. ";
                ARIA_LIVE_NOTIFICATION_CONTAINER.focus();

                if (!response.isSuccessfull) {
                    hideScrollBar('body');
                    $jobAlertPopup.html(response.responseView);
                    gJobs.dialogHelper.disableTabIndexOnParentView();
                    showHideJobAlertPopup(true);
                    jobAlertIndex = 1;
                    isExistingJobAlert = true;
                    updateResultMessage = "Job Alert is not saved. ";
                } else {
                    showScrollBar('html');
                    $(document).trigger(Events.CommonEventsNames.JobAlertUpdated);
                }
                
                $jobAlertEditView.addClass("hidden");
                hideScrollBar('html');
                $("#footer-new").hide();
                $("#skip-to-content-button").hide();
                self.closeEditMode(updateResultMessage);
                gJobs.dialogHelper.setTabIndexOnJobAlertsPopup("#setJobAlertDialog");
                if (!response.isSuccessfull) {
                    window.isJobAlertEdit = true;
                }
            })
    };

    function showHideElementsOnDialog(hide) {
        gJobs.dialogHelper.showHideElementsOnDialog(
            {
                selector: '#body-container, #main-container,'
                    + '#footer, #footer-new, #sjobs-footer-new, .new-job-flyout, #skip-to-content-button,'
                    + '#last-focusable-element, #cookie-consent, #account-settings',
                shouldDisableRestoreTabIndex: true,
                hide: hide
            }
        );
    }

    self.closeEditMode = function (updateResultMessage) {
        window.isJobAlertEdit = false;
        var flyoutCloseMessage = "Edit Job Alert flyout is closed.";
        if (updateResultMessage) flyoutCloseMessage = updateResultMessage + flyoutCloseMessage;
        gJobs.screenReadersService.setAriaLiveNotification(flyoutCloseMessage);
        ARIA_LIVE_NOTIFICATION_CONTAINER.focus();
        showHideElementsOnDialog(false);
        $jobAlertEditView.addClass("hidden");
        showScrollBar('html');
        $("#account-settings").attr('aria-hidden', false);
        var $tabbableElements;
        $tabbableElements = $('#account-settings').find(':tabbable');
        $tabbableElements.attr('tabindex', 0);
        $("#footer-new").show();
        $("#sjobs-footer-new").show();
        $("#skip-to-content-button").show();
        gJobs.dialogHelper.setTabIndexOnJobAlertsPopup("#setJobAlertDialog");
        focusOnEditButton(jobAlertIndex);
    }

    self.keyDown = function (jobAlert, event) {
        if (event.keyCode == 13) {
            changeJobAlert(jobAlert);
        }
    }

    self.getJobAlertFilterChangePrefix = function (jobAlertFilter, facetFilterValue) {
        var filterIsAppliedPrefix = " filter is applied";
        var filterIsRemovedPrefix = " filter is removed";

        return jobAlertFilter === facetFilterValue
            ? filterIsAppliedPrefix
            : filterIsRemovedPrefix;
    }

    self.getJobAlertChangeMessage = function (jobAlert, event) {
        var facetFilterValue = $(event.target).data(facetFilterNameDataAttribute);
        var facetGroupValue = $(event.target).data(facetGroupNameDataAttribute);
 
        var message = facetGroupValue + " , " + facetFilterValue;

        if (facetGroupValue === facetGroupNames.organizations) {
            message += self.getJobAlertFilterChangePrefix(jobAlert.Organization, facetFilterValue);
        } else if (facetGroupValue === facetGroupNames.categories) {
            message += self.getJobAlertFilterChangePrefix(jobAlert.Category, facetFilterValue);
        } else if (facetGroupValue === facetGroupNames.jobType) {
            message += self.getJobAlertFilterChangePrefix(jobAlert.JobType, facetFilterValue);
        } else if (facetGroupValue === facetGroupNames.salary) {
            message += self.getJobAlertFilterChangePrefix("$" + jobAlert.MinimumSalary + "+", facetFilterValue.replace(',',''));
        } else if (facetGroupValue === facetGroupNames.datePosted) {
            message += self.getJobAlertFilterChangePrefix(jobAlert.DaysPosted, facetFilterValue);
        } else if (facetGroupValue === facetGroupNames.remote) {
            message += self.getJobAlertFilterChangePrefix(jobAlert.RemoteOptionsText, facetFilterValue);
        }

        return message;
    }

    self.changeJobAlert = function (jobAlert, event) {
        if (!jobAlert.JobAlertId || jobAlert.JobAlertId === 0) {
            jobAlert.JobAlertId = document.getElementById('job-alert-id').textContent;
        }

        selectedOrganization = null;
        selectedCategory = null;
        selectedJobType = null;

        if (jobAlert.Organization) {
            jobAlert.Organization = jobAlert.Organization[0];
            selectedOrganization = jobAlert.Organization;
        }
        if (jobAlert.Category) {
            jobAlert.Category = jobAlert.Category[0];
            selectedCategory = jobAlert.Category;
        }
        if (jobAlert.JobType) {
            jobAlert.JobType = jobAlert.JobType[0];
            selectedJobType = jobAlert.JobType;
        }
        selectedRemoteWorkOptionId = jobAlert.RemoteWorkOptionId;
        //selectedJobType = jobAlert.JobType;
        selectedSalary = jobAlert.MinimumSalary;
        jobAlert.Location = document.getElementById('job-alert-location-search-input').value;
        jobAlert.Keyword = document.getElementById('job-alert-keyword-search-input').value;
        var screenReaderChangeMessage = "";
        if (event) {
            screenReaderChangeMessage = self.getJobAlertChangeMessage(jobAlert, event);
        }
        OnlineApp.Services.jobAlertService.getAll().then(function (data) {
            data.jobAlerts.sort(function (a, b) {
                return a.SiteSource - b.SiteSource;
            });
            data.jobAlerts.forEach(function (value, i) {
                value.Index = i;
                if (value.JobAlertId == jobAlert.JobAlertId) {
                    jobAlert.SiteSource = value.SiteSource;
                }
            })

            OnlineApp.Services.jobAlertService.getJobAlertEditModel(jobAlert)
                .done(function (response) {
                    $jobAlertEditView.html(response.data);
                    $searchFormView.html(response.searchForm);

                    $jobAlertEditView.removeClass("hidden");
                    $jobAlertEditView.css({ height: window.screen.height - 95 });
                    hideScrollBar('html');
                    document.getElementById('save-job-alert').removeAttribute("disabled");
                    gJobs.screenReadersService.setAriaLiveNotification(screenReaderChangeMessage);
                    $("#skip-to-content-button").show();
                    gJobs.screenReadersService.silenceScreenreaderForBanner("");
                })
        })
    };

    self.clearFilter = function (jobAlert) {
        jobAlert.Location = document.getElementById('job-alert-location-search-input').value;
        jobAlert.Keyword = document.getElementById('job-alert-keyword-search-input').value;
        selectedCategory = null;
        selectedOrganization = null;
        selectedSalary = null;
        selectedRemoteWorkOptionId = 0;
        selectedJobType = null;
        //$("#skip-to-content-button").show();
        $("#skip-to-content-button").focus();
        OnlineApp.Services.jobAlertService.getJobAlertEditModel(jobAlert)
            .done(function (response) {
                var jobAlertId = document.getElementById('job-alert-id').textContent;
                $jobAlertEditView.html(response.data);
                document.getElementById('job-alert-id').textContent = jobAlertId;
                $searchFormView.html(response.searchForm);

                $jobAlertEditView.removeClass("hidden");
                $jobAlertEditView.css({ height: window.screen.height-95 });
                hideScrollBar('html');
                gJobs.screenReadersService.setAriaLiveNotification("Filter are cleared.");
                ARIA_LIVE_NOTIFICATION_CONTAINER.focus();
            })
    }

    self.clearFilterOnKeyDown = function (jobAlert, event) {
        if (event.keyCode == $.ui.keyCode.ENTER) {
            jobAlert.Location = document.getElementById('job-alert-location-search-input').value;
            jobAlert.Keyword = document.getElementById('job-alert-keyword-search-input').value;
            selectedCategory = null;
            selectedOrganization = null;
            selectedSalary = null;
            selectedRemoteWorkOptionId = 0;
            selectedJobType = null;
            //$("#skip-to-content-button").show();
            $("#skip-to-content-button").focus();
            OnlineApp.Services.jobAlertService.getJobAlertEditModel(jobAlert)
                .done(function (response) {
                    var jobAlertId = document.getElementById('job-alert-id').textContent;
                    $jobAlertEditView.html(response.data);
                    document.getElementById('job-alert-id').textContent = jobAlertId;
                    $searchFormView.html(response.searchForm);

                    $jobAlertEditView.removeClass("hidden");
                    $jobAlertEditView.css({ height: window.screen.height-95 });
                    hideScrollBar('html');
                    gJobs.screenReadersService.setAriaLiveNotification("Filter are cleared.");
                    ARIA_LIVE_NOTIFICATION_CONTAINER.focus();
                })
        }
    }

    self.blurInputs = function () {
        $('#job-alert-keyword-search-input').blur();
        $('#job-alert-location-search-input').blur();
    }

    self.anounceTooltip = function () {
        var isDisabled = document.getElementById('save-job-alert').disabled;
        if (isDisabled) {
            gJobs.screenReadersService.setAriaLiveNotification('To set a job alert, you must select/apply at least one filter. To apply a filter, click on the “Show results” button.');
            ARIA_LIVE_NOTIFICATION_CONTAINER.focus();
        }
    }

    self.disableSaveButton = function (e) {
        if (initialLocation === undefined) {
            initialLocation = document.getElementById('job-alert-location-search-input').value;
        }
        if (e.keyCode !== $.ui.keyCode.TAB && !e.shiftKey) {
            document.getElementById('save-job-alert').setAttribute("disabled", "disabled");
        }
    }

    self.jobAlertLocationFieldAfterRender = function () {
        var initOptions = {
            autocompleteMenuClassName: jobAlertLocationAutocompleteMenuClassName
        };

        var options = {
            searchFieldSelectors: [jobAlertSearchFieldSelector],
            additionalCssClassNames: initOptions.autocompleteMenuClassName
        };

        $(document).trigger(OnlineApp.Events.CommonEventsNames.InitSearchFieldsWithAutocomplete, options);

    };

    self.jobAlertKeywordFieldAfterRender = function () {
        var initOptions = {
            autocompleteMenuClassName: jobAlertKeywordAutocompleteMenuClassName
        };

        var options = {
            searchFieldSelectors: [jobAlertKeywordSearchFieldSelector],
            additionalCssClassNames: initOptions.autocompleteMenuClassName
        };

        $(document).trigger(OnlineApp.Events.CommonEventsNames.InitSearchFieldsWithAutocomplete, options);
    }

    self.showResults = function (className) {
        var jobAlert = [];
        jobAlert.Location = document.getElementById('job-alert-location-search-input').value;
        jobAlert.Keyword = document.getElementById('job-alert-keyword-search-input').value;
        jobAlert.JobAlertId = document.getElementById('job-alert-id').textContent;
        jobAlert.Organization = selectedOrganization;
        jobAlert.Category = selectedCategory;
        jobAlert.MinimumSalary = selectedSalary;
        jobAlert.RemoteWorkOptionId = selectedRemoteWorkOptionId;
        jobAlert.JobType = selectedJobType;

        OnlineApp.Services.jobAlertService.updateJobAlertEditModel(jobAlert)
            .done(function (response) {
                var jobAlertId = document.getElementById('job-alert-id').textContent;
                $jobAlertEditView.html(response.data);
                document.getElementById('job-alert-id').textContent = jobAlertId;
                $searchFormView.html(response.searchForm);

                $jobAlertEditView.removeClass("hidden");
                $jobAlertEditView.css({ height: window.screen.height-95 });
                hideScrollBar('html');
                document.getElementById('save-job-alert').removeAttribute("disabled");
                gJobs.screenReadersService.setAriaLiveNotification("New results are uploaded.");
                $("#skip-to-content-button").show();
                gJobs.screenReadersService.silenceScreenreaderForBanner("");
                if (className == "btn-gjobs-secondary") {
                    setFocusOnEditJobAlert(editJobAlertIndex);
                }
            })
    }
    
    self.toggleModels = function () {
        var loginModel = OnlineApp.ViewModels.applicationViewModel.loginViewModel;
        loginModel.signInViewModel.isActive(!loginModel.signInViewModel.isActive());
        loginModel.registerViewModel.isActive(!loginModel.registerViewModel.isActive());
    }

    self.closeAccessMembershipAlert = function () {
        if (window.enableStickyHeader) {
            $stickyHeader.show();
            $('#content').addClass('respect-sticky-header');
        }

        showHideElementsOnDialog(false);       

        self.showHideJobAlertAcessMembershipPopup(false, true);
        showScrollBar('html');
        $setJobAlertBtn.focus();
        checkAndRemoveEmailVerificationParam();
    }

    self.closeJobAlert = function (isAuthorizationPopup, isAddedSuccessfully, showEditPageBack) {
        if (window.enableStickyHeader) {
            if (!($jobAlertAccessMembershipPopup[0] && !$('#job-alert-access-membership-popup')[0])){
                $stickyHeader.show();
                $('#content').addClass('respect-sticky-header');
            }
        }

        showHideElementsOnDialog(false);

        gJobs.screenReadersService.setAriaLiveNotification("Set Job Alert modal is closed.");
        ARIA_LIVE_NOTIFICATION_CONTAINER.focus();

        OnlineApp.ViewModels.applicationViewModel.loginViewModel.signInViewModel.showJobAlert(false);
        OnlineApp.ViewModels.applicationViewModel.loginViewModel.registerViewModel.showJobAlert(false);

        if (isAuthorizationPopup) {
            showHideJobAlertAuthPopup(false);
            showScrollBar('html');
        }        
        else {
            showHideJobAlertPopup(false);
            if (showEditPageBack) {
                $jobAlertEditView.removeClass("hidden");
                var $tabbableElements;

                $tabbableElements = $('#account-settings')
                    .find(':tabbable');
                $tabbableElements.attr('tabindex', -1);
                $(".close-job-alert-edit-mode").attr('tabindex', 0);
                $("#job-alert-keyword-search-input").attr('tabindex', 0);
                $("#job-alert-location-search-input").attr('tabindex', 0);
                $("#show-results").attr('tabindex', 0);
                $("#save-job-alert").attr('tabindex', 0);
                $tabbableElements = $('#header-content')
                    .find(':tabbable');
                $tabbableElements.attr('tabindex', 0);
                $("#footer-new").hide();
                $tabbableElements = $jobAlertEditView
                    .find(':tabbable');
                $tabbableElements.attr('tabindex', 0);
                $("#footer-new").hide();
                $tabbableElements = $("#facet-container")
                    .find('a');
                $tabbableElements.attr('tabindex', 0);
                $('#save-job-alert').focus();
                $("#footer-new").hide();
                $stickyHeader.hide();
            }
            else {
                showScrollBar('html');
            }
        }

        if (isAddedSuccessfully) {
            OnlineApp.Services.jobAlertService.generateJobAlertAlreadyAddedView()
                .done(function (response) {
                    $('#job-alert-out-container').html(response);
                });
        }

        $setJobAlertBtn.focus();
        gJobs.dialogHelper.setTabIndexOnJobAlertsPopup("#setJobAlertDialog");

        checkAndRemoveEmailVerificationParam();        
    }

    function checkAndRemoveEmailVerificationParam() {
        if (window.enableEmailVerificationRefinements) {
            if (window.utils.getUrlParameter(displayJobAlertsLoginPopupQueryParameter)) {
                var currentUrl = removeEmailVerificationParametersFromUrl();
                history.pushState(null, "", currentUrl);
            }
        }
    }

    self.showJobAlertEditView = function () {
        $jobAlertEditView.removeClass("hidden");
        var $tabbableElements;
        $tabbableElements = $('#account-settings')
            .find(':tabbable');
        $tabbableElements.attr('tabindex', -1);
        $(".close-job-alert-edit-mode").attr('tabindex', 0);
        $("#job-alert-keyword-search-input").attr('tabindex', 0);
        $("#job-alert-location-search-input").attr('tabindex', 0);
        $("#show-results").attr('tabindex', 0);
        $("#save-job-alert").attr('tabindex', 0);
        $tabbableElements = $('#header-content')
            .find(':tabbable');
        $tabbableElements.attr('tabindex', 0);
        $tabbableElements = $jobAlertEditView
            .find(':tabbable');
        $tabbableElements.attr('tabindex', 0);
        $tabbableElements = $("#facet-container")
            .find('a');
        $tabbableElements.attr('tabindex', 0);
        hideScrollBar('html');
        $("#footer-new").hide();
        $('#save-job-alert').focus();
    }

    self.isAuthorized = ko.observable(false);

    self.loginLoaded = function () {
        $(document).trigger('JobAlertsViewModel:ViewLoaded');
    };

    self.goToAccountSettingsPage = function () {
        var accountSettingsPagePath = gJobs.accountSettingsHelper.getLinkForAccountSettings();

        window.open(accountSettingsPagePath, '_blank');
    };

    self.enrollAcessMembership = function () {
        OnlineApp.Services.dataService.accessMembership.post({
            wantsToUpgrade: true,
            credential: null
        }).done(function (data) {
            gJobs.common.analytics.trackEvent(
                'Access Membership Page',
                'Upgraded'
            );

            $jobAlertAccessMembershipPopup.remove();
            gJobs.screenReadersService.setAriaLiveNotification("Access Membership Enrolled and Set Job Alert modal is opened.");
            ARIA_LIVE_NOTIFICATION_CONTAINER.focus();
            $('#job-alert-out-container').removeClass('hidden');
            gJobs.dialogHelper.setTabIndexOnJobAlertsPopup("#setJobAlertDialog");
        });
    };

    self.showHideJobAlertAcessMembershipPopup = function (show, showShadow) {
        hideScrollBar('body');
        hideScrollBar('html');
        if (show) {
            $jobAlertAccessMembershipPopup.removeClass('hidden');
            if (showShadow) {
                $jobAlertShadow.removeClass('hidden');
                $headerShadow.removeClass('hidden');
            }
            gJobs.screenReadersService.setAriaLiveNotification("Enroll in Free Access Membership modal is opened.");
            ARIA_LIVE_NOTIFICATION_CONTAINER.focus();
            gJobs.dialogHelper.setTabIndexOnJobAlertsPopup('#job-alert-access-membership-popup');
            focusOnFistTabbableDialogElement($jobAlertAccessMembershipPopup);

        } else {
            $jobAlertAccessMembershipPopup.addClass('hidden');
            if (showShadow) {
                $jobAlertShadow.addClass('hidden');
                $headerShadow.addClass('hidden');
            }
            gJobs.screenReadersService.setAriaLiveNotification("Enroll in Free Access Membership modal is closed.");
            ARIA_LIVE_NOTIFICATION_CONTAINER.focus();
        }
    };

    function hideScrollBar(element) {
        $(element).css({ 'overflow': 'hidden' });
    }

    function showScrollBar(element) {
        $(element).css({ 'overflow-y': 'scroll' });
    }

    function focusOnFistTabbableDialogElement(element) {
        element.find(":tabbable").first().focus();
    }

    function focusOnEditButton(index) {
        if (index == undefined) {
            if (!$('.job-alert-edit-btn')[0]) return;
            $('.job-alert-edit-btn')[0].focus();
            setTimeout(function () { $('.job-alert-edit-btn')[0].focus(); }, 1500);
        }
        else {
            $('#skip-to-content-button').show();
            $('.job-alert-edit-btn')[index].focus();
            setTimeout(function () { $('.job-alert-edit-btn')[index].focus(); }, 1500);
        }
    }

    function setFocusOnEditJobAlert(i) {
        showHideElementsOnDialog(false);
        $jobAlertEditView.addClass("hidden");
        showScrollBar('html');
        $("#account-settings").attr('aria-hidden', false);
        var $tabbableElements;
        $tabbableElements = $('#account-settings').find(':tabbable');
        $tabbableElements.attr('tabindex', 0);
        $("#footer-new").show();
        $("#skip-to-content-button").show();
        if ($('.job-alert-edit-btn').length > 0) {
            $('.job-alert-edit-btn')[i].focus();
            setTimeout(function () { $('.job-alert-edit-btn')[i].focus(); }, 1500);
        }
    }

    function focusOnDeleteButton(index) {
        if (index !== undefined) {
            $('.job-alert-delete-btn')[index].focus();
        }
    }

    function showHideDeleteJobAlertPopup(show) {
        if (show) {
            $jobAlertShadow.removeClass('hidden');
            $deleteJobAlertPopup.removeClass('hidden');
            $headerShadow.removeClass('hidden');
        } else {
            $jobAlertShadow.addClass('hidden');
            $deleteJobAlertPopup.addClass('hidden');
            $headerShadow.addClass('hidden');
        }
    }

    function showHideJobAlertPopup(show) {
        if (show) {
            $jobAlertShadow.removeClass('hidden');
            $jobAlertPopup.removeClass('hidden');
            $headerShadow.removeClass('hidden');
        } else {
            $jobAlertShadow.addClass('hidden');
            $jobAlertPopup.addClass('hidden');
            $headerShadow.addClass('hidden');
        }
    }

    function showHideJobAlertAuthPopup(show) {
        hideScrollBar('body');
        hideScrollBar('html');
        if (show) {
            $jobAlertAuthorizationPopup.removeClass('hidden');
            $jobAlertShadow.removeClass('hidden');
            $headerShadow.removeClass('hidden');
        } else {
            $jobAlertAuthorizationPopup.addClass('hidden');
            $jobAlertShadow.addClass('hidden');
            $headerShadow.addClass('hidden');
        }
    }    

    function removeEmailVerificationParametersFromUrl() {
        var currentUrl = window.location.href.replace(/&?(displayJobAlertsLoginPopup)=([^&]$|[^&]*)/ig, "");

        return currentUrl;
    }

    function addEmailVerificationParametersToUrl() {
        var currentUrl = window.location.search + "&displayJobAlertsLoginPopup=true";

        return currentUrl;
    }

    $(document).ready(function() {
        if (window.enableEmailVerificationRefinements) {
            if (window.utils.getUrlParameter(displayJobAlertsLoginPopupQueryParameter)) {
                self.setJobAlert();
            }
        }
    });

    OnlineApp.Namespace.extend('OnlineApp.ViewModels', {
        jobAlertsViewModel: JobAlertsViewModel
    });

})(window); ;
(function () {
    var NOTIFICATION_CLASS = 'screenreader-notification';
    var ARIA_LIVE_NOTIFICATION_CONTAINER = "#aria-live-message-container";
    var ARIA_LIVE_PAGE_LOAD_MESSAGE_NOTIFICATION_CONTAINER = "#aria-live-page-load-message-container";
    var PAGE_LOAD_MESSAGES_SELECTOR = '.page-load-message';

    function ScreenReadersService() {
        var self = this;

        self.setNotification = function ($element, text, suffix, setFocus, rememberPreviousElement) {
            if ($element) {
                var notification = text || '';
                if (suffix) {
                    notification += ' ' + suffix;
                }
                var $commonNitification = $element.find('.common-notification');
                                if ($commonNitification.length) {
                    $commonNitification.text(notification);                   
                    $commonNitification.attr('aria-label', notification);
                } else {
                    $element.text(notification);
                }
                $element.attr('aria-label', notification);
                if (setFocus) {
                    if (gJobs && gJobs.focusService && gJobs.focusService.setFocus && rememberPreviousElement) {
                        setTimeout(() => gJobs.focusService.setFocus($element), 300);                        
                        
                    } else {
                        setTimeout(() => $element.focus(), 200);
                    }
                }
            }
        }

        self.setNotificationWithDelay = function($element, text, suffix, setFocus, rememberPreviousElement, delay) {
            setTimeout(function() {
                self.setNotification($element, text, suffix, setFocus, rememberPreviousElement);
            }, delay);
        }

        self.onceNotification = function (options) {
            var $element = options.$element;
            var ariaLabelText = $element.attr('aria-label') || $element.text() || $element.attr('placeholder');
            var newAriaLabelText = options.message + ariaLabelText;
            $element.attr('aria-label', newAriaLabelText);
            $element.one('blur', function () {
                $element.attr('aria-label', ariaLabelText);
            });
        }

        self.onceAriaLabelledByNotification = function (options) {
            var $element = options.$element;
            var ariaLabelledBy = $element.attr('aria-labelledby') || '';

            var containerIds = options.notificationContainerIds.split(',');
            var newAriaLabelledBy = containerIds.join(' ') + ' ' + ariaLabelledBy;

            var setAriaHiddenAttr = function (containerIds, ariaHiddenAttr) {
                var idsSelector = '#' + containerIds.join(', #');
                $(idsSelector).attr('aria-hidden', ariaHiddenAttr);
            }

            setAriaHiddenAttr(containerIds, false);

            $element.attr('aria-labelledby', newAriaLabelledBy);
            $element.one('blur', function () {
                setAriaHiddenAttr(containerIds, true);

                $element.attr('aria-labelledby', ariaLabelledBy);
            });
        }

        self.setNotificationWithFocusSaving = function (options) {
            var $target = (options.$element && options.$element.length) ? options.$element : $(document.activeElement);
            var $notification = $('<span>');

            $notification.attr('aria-label', options.text);
            $notification.text(options.text);

            $notification.addClass(NOTIFICATION_CLASS);
            $notification.attr('tabindex', '-1');
            copyElementMetrics($notification, $target, options.dontConsiderParentScroll);

            options.moveFocusToNextElement ? $target.after($notification) : $target.before($notification);
            $notification.focus();

            $notification.one('keydown', function (e) {
                var keyCode = e.keyCode || e.which;
                if (keyCode === $.ui.keyCode.TAB) {
                    $notification.remove();
                }
            });

            if (options.returnFocusBack) {
                $notification.one('keydown', function (e) {
                    var keyCode = e.keyCode || e.which;
                    if (keyCode === $.ui.keyCode.TAB) {
                        if (options.shouldForceDropdownOpening) {
                            $target.trigger('liszt:open');
                        } else {
                            $target.focus();
                        }
                        return false;
                    }
                });
            }
        }

        self.setNotificationOnElement = function(options) {

            function removeNotificationFromElement() {
                if (savedDropdownlabelledBy !== null) {
                    $target.attr('aria-labelledby', savedDropdownlabelledBy);
                    $dropdownNotification.remove();
                }

                if (savedAriaLabel !== null) {
                    var ariaLabel = savedAriaLabel ? savedAriaLabel : '';
                    $target.attr('aria-label', ariaLabel);
                }

                if (savedLabelHtml !== null) {
                    $label.html(savedLabelHtml);
                }
            }

            var $target = (options.$element && options.$element.length) ? options.$element : $(document.activeElement);

            var isDropdown = $target.hasClass('chzn-container');
            var $label = $('label[for="' + $target[0].id + '"]');
            var elementAriaLabel = $target.attr('aria-label');

            var savedAriaLabel = null;
            var savedLabelHtml = null;

            var savedDropdownlabelledBy = null;
            var $dropdownNotification = null;

            if (isDropdown) {
                var dropdownNotificationId =  $target.attr('id') + '-notification';
                $dropdownNotification = $('<span>')
                    .attr({ 'id': dropdownNotificationId, 'class': 'sr-only' })
                    .text(options.text)
                    .appendTo($target);
                savedDropdownlabelledBy = $target.attr('aria-labelledby') || '';
                $target.attr('aria-labelledby', dropdownNotificationId + ' ' + savedDropdownlabelledBy);
            } else if ($label.length) {
                var savedLabelHtml = $label.html();
                $label.html('<span class="sr-only">' + options.text +'</span>' + savedLabelHtml);
            } else {
                savedAriaLabel = elementAriaLabel;
                var ariaLabelText = savedAriaLabel ? options.text + ' ' + savedAriaLabel : options.text;
                $target.attr('aria-label', ariaLabelText);
            }

            var isFormElement = $target.is('input,textarea,select');
            if (isFormElement) {
                OnlineApp.Helpers.layoutHelper.tabbing.activateFirstElement();
            } else {
                $target.focus();
            }

            $target.one('keydown', removeNotificationFromElement);

            // remove notification only on user-initiated click events
            setTimeout(function () {
                $(document).one('click', removeNotificationFromElement);
            });
        }

        self.clearNotification = function ($element) {
            $element.text('');
            $element.attr('aria-label', '');
        }

        self.setSignInNotification = function ($signInFormNotification, focusRestoreCallback) {
            if (!$signInFormNotification.length) {
                return;
            }

            var notificationText = 'Sign in form is opened';
            if (OnlineApp.ViewModels.applicationViewModel &&
                OnlineApp.ViewModels.applicationViewModel.loginViewModel &&
                OnlineApp.ViewModels.applicationViewModel.loginViewModel.registerViewModel.isActive()) {
                notificationText = 'Create a new account form is opened.';
            }

            gJobs.screenReadersService.setNotification($signInFormNotification, notificationText, null, true);
            $(document).one(OnlineApp.Events.CommonEventsNames.Login, function () {
                $signInFormNotification.remove();
            });

            if (typeof (focusRestoreCallback) == 'function') {
                $signInFormNotification.one('keydown', function (e) {
                    if (e.keyCode !== $.ui.keyCode.TAB) {
                        return;
                    }
                    e.stopPropagation();
                    e.preventDefault();
                    focusRestoreCallback();
                });
            }
        }

        self.setLogInNotification = function (notificationText) {
            var $loginNotification = $('#sign-in-reader-notification');

            gJobs.screenReadersService.setNotification($loginNotification, notificationText, null, true);

            $loginNotification.one('focusout', function () {
                $loginNotification.text(' ');
            });
        }

        self.silenceScreenreader = function () {
            var $emptySpan = $('<span class="hide-notification no-restrict-focus" tabindex="-1">&nbsp;</span>');
            $('body').prepend($emptySpan);
            $emptySpan.focus();
            $emptySpan.one('focusout', function () {
                $emptySpan.remove();
            });
        }

        self.silenceScreenreaderForBanner = function (notification) {
            var $emptySpan = $('<span class="hide-notification no-restrict-focus" tabindex="-1">' + notification + '</span>');
            $('body').prepend($emptySpan);
            $emptySpan.focus();
            $emptySpan.one('focusout', function () {
                $emptySpan.remove();
            });
        }

        // Adding invisible spaces to force NVDA to read the whole phrase.
        self.applyNvdaAriaLiveFix = function ($element, newText) {
            var invisibleSpace = '<span class="hide-notification">&nbsp;</span>';
            var isFixApplied = !!$element.data('aria-live-fixed');
            var output = isFixApplied ? newText : invisibleSpace + newText + invisibleSpace;

            $element.html(output);
            $element.data('aria-live-fixed', !isFixApplied);    
        }

        // Make fake element having the same size and position,
        // so ZoomText border will be the same too.
        function copyElementMetrics ($target, $source, dontConsiderParentScroll) {
            $target.height($source.outerHeight());
            $target.width($source.outerWidth());
            var sourcePosition = $source.position();
            var topPostion = sourcePosition.top;

            if(!dontConsiderParentScroll) {
                topPostion += $source.scrollParent().scrollTop();
            }

            $target.css({
                position: 'absolute',
                // Copying margins instead of calling outerHeight(true),
                // because ZoomText border relies on margins too.
                // We can't copy the whole 'margin' property in FF.
                marginTop: $source.css('marginTop'),
                marginRight: $source.css('marginRight'),
                marginBottom: $source.css('marginBottom'),
                marginLeft: $source.css('marginLeft'),
                top: topPostion,
                left: sourcePosition.left
            });
        }

        self.stopNotification = function (selector) {
            var $container = $(selector);
            var $emptyNotification = $('#empty-notification');
            if ($emptyNotification.length) {
                $emptyNotification.remove();
            }
            $emptyNotification = $("<span id='empty-notification' class='common-notification' tabindex='-1'> </span>");
            $container.before($emptyNotification);
            $emptyNotification.focus();
        }

        self.setAriaLiveNotification = function (notification, selector, addAlertAttribute) {
            if (!selector) {
                selector = ARIA_LIVE_NOTIFICATION_CONTAINER;
            }
            
            $(selector).text('').text(notification);

            if (addAlertAttribute) {
                $(selector).attr('role', 'alert');
            }

            $(selector).focus();
        }

        self.setAriaLiveNotificationWithoutRepeat = function (notification, selector) {
            if (!selector) {
                selector = ARIA_LIVE_NOTIFICATION_CONTAINER;
            }
            var $notificationContainer = $(selector);

            if ($notificationContainer.text() !== notification) {
                $notificationContainer.text('').text(notification);
            }
        }

        self.readPageTitle = function ($element, notificationText) {
            var readingPageTitleHelperContainer = "#reading-page-title-helper";
            $(readingPageTitleHelperContainer).attr("tabindex", 0);
            if (!!notificationText) {
                $(readingPageTitleHelperContainer).text(notificationText);
            }
            $(readingPageTitleHelperContainer).focus();
            setTimeout(function () {
                $element.focus();
                $(readingPageTitleHelperContainer).attr("tabindex", -1);
                $(readingPageTitleHelperContainer).text("");
            }, 300);
        }

        self.notificationOnLoad = function () {
            var getPageLoadedMessage = function () {
                var message = $(PAGE_LOAD_MESSAGES_SELECTOR).map(function (index, element) {
                    return $(element).text();
                }).toArray().join(', ');
                return message;
            }

            self.setAriaLiveNotification(
                getPageLoadedMessage, 
                ARIA_LIVE_PAGE_LOAD_MESSAGE_NOTIFICATION_CONTAINER
            );
        }
    }

    namespace('gJobs').screenReadersService = new ScreenReadersService();
})();;
(function () {
    var FOCUSABLE_SELECTOR = 'a, area[href], input:not([disabled]):not([type="hidden"]),'
                              + 'select:not([disabled]), textarea:not([disabled]),'
                              + 'button:not([disabled]), iframe, object, embed, [tabindex]';                         

    function AriaSelectors() {
        var self = this;

        self.getFocusableSelector = function () {
            return FOCUSABLE_SELECTOR;
        }
    }

    namespace('gJobs').ariaSelectors = new AriaSelectors();
})();
;
(function () {
    var focusableSelector = gJobs.ariaSelectors.getFocusableSelector();     
    var ARIA_SELECTOR = 'h1, h2, h3, h4, h5, h6, ' + focusableSelector; 
    var ARIA_HIDDEN_DATA_NAME = "ariahidden";

    function getOptions (options) {
        options = options || {};

        if (!options.selector) {
            options.selector = ARIA_SELECTOR;
        }

        return options;
    }

    function getElementsBySelector (selector, modalId) {
        var $elements;

        if (modalId) {
            var $modal = $('#' + modalId);
            $elements = $(selector).not($modal.find("*"));
        } else {
            $elements = $(selector);
        }

        return $elements;
    }

    function disableRestoreAriaHidden ($elementsForShowHide, shouldDisable) {
        var isAttributeHasValue = function (attrValue) {
            if (attrValue !== null && attrValue !== undefined) {
                return true;
            } else {
                return false;
            }
        }

        $elementsForShowHide.each(function() {
            var $element = $(this);
            var ariaHidden;

            if (shouldDisable) {
                ariaHidden = $element.attr("aria-hidden");

                if (isAttributeHasValue(ariaHidden)) {
                    $element.data(ARIA_HIDDEN_DATA_NAME, ariaHidden);
                }

                $element.attr("aria-hidden", "true");
            } else {
                $element.removeAttr("aria-hidden");
                ariaHidden = $element.data(ARIA_HIDDEN_DATA_NAME);

                if (isAttributeHasValue(ariaHidden)) {
                    $element.attr("aria-hidden", ariaHidden);
                    $element.removeData(ARIA_HIDDEN_DATA_NAME);
                }
            }
        });
    }

    function DialogHelper() {
        var self = this;

        self.showHideElementsOnDialog = function (options) {
            var options = getOptions(options);

            var $elementsForShowHide = getElementsBySelector(options.selector, options.modalId);  

            if (options.hide) {
                if (options.shouldDisableRestoreTabIndex === true) {
                    OnlineApp.Services.tabIndexService.disableTabIndex({ hideSkipButton: true });
                }

                disableRestoreAriaHidden($elementsForShowHide, true);

            } else {
                if (options.shouldDisableRestoreTabIndex === true) {
                    OnlineApp.Services.tabIndexService.restoreTabIndex({ hideSkipButton: true });
                }

                disableRestoreAriaHidden($elementsForShowHide, false);
            }
        }

        self.disableTabIndexOnParentView = function (options) {
            var options = getOptions(options);
            OnlineApp.Services.tabIndexService.disableTabIndex({ hideSkipButton: true });
        }

        self.setTabIndexOnJobAlertsPopup = function(jobAlertDialogId) {
            const focusableElements =
                'button, [href], input, select, textarea, [tabindex]:not([tabindex="-1"])';
            const modal = document.querySelector(jobAlertDialogId); // select the modal by it's id
            if (!modal) return;
            const firstFocusableElement = modal.querySelectorAll(focusableElements)[0]; // get first element to be focused inside modal
            const focusableContent = modal.querySelectorAll(focusableElements);
            const lastFocusableElement = focusableContent[focusableContent.length - 1]; // get last element to be focused inside modal
            document.addEventListener('keydown', function (e) {
                let isTabPressed = e.key === 'Tab' || e.keyCode === 9;
                if (!isTabPressed) {
                    return;
                }
                if (e.shiftKey) { // if shift key pressed for shift + tab combination
                    if (document.activeElement === firstFocusableElement) {
                        lastFocusableElement.focus(); // add focus for the last focusable element
                        e.preventDefault();
                    }
                } else { // if tab key is pressed
                    if (document.activeElement === lastFocusableElement) { // if focused has reached to last focusable element then focus first focusable element after pressing tab
                        firstFocusableElement.focus(); // add focus for the first focusable element
                        e.preventDefault();
                    }
                }
            });
            firstFocusableElement.focus();
        }
    }

    namespace('gJobs').dialogHelper = new DialogHelper();
})();
;
(function () {
    var PDF_READER_LINK = namespace('Resources').PdfReader.downloadLink;
    var PDF_READER_TITLE = namespace('Resources').PdfReader.downloadTitle;

    function AccessibilityHtmlTransformer() {
        var self = this;

        self.makeElementContentAccessible = function($element) {
            self.addPdfDownloadLinks($element);
            self.addMissingImageDescriptions($element);
            self.fixEmbeddedVideoTabIndex($element);
        };

        self.addPdfDownloadLinks = function($element) {
            var pdfLinks = $element.find('a[href$=".pdf"]:not(.print-button)');
            var readerDownloadLink = $('<a>')
                .text('(' + PDF_READER_TITLE + ')')
                .attr({
                    href: PDF_READER_LINK,
                    target: '_blank'
                });

            pdfLinks.after(readerDownloadLink);
            pdfLinks.after(' ');
        };

        self.addMissingImageDescriptions = function($element) {
            var imagesWithoutDescription = $element
                .find('img')
                .filter(function (index, img) {
                    return !$(img).attr('alt');
                });

            var defaultAltText;
            var jobName = $('.job-header-title, .summary .title').filter(':visible').text();
            if (jobName) {
                defaultAltText = jobName + ' description image';
            } else {
                defaultAltText = 'An image without description';
            }

            imagesWithoutDescription.attr('alt', defaultAltText);
        };

        self.fixEmbeddedVideoTabIndex = function ($element) {
            $element
                .find('div[data-oembed-url]')
                .find('iframe[tabindex="-1"]')
                .removeAttr('tabindex');
        };

        self.initPagerSkipButtons = function (container) {
            function initPaginationItem($container, options) {
                $container.find(options.selector).addClass(options.className).find('a').attr('title', options.title).attr('aria-label', options.title);
            }

            var $container = $(container);
            initPaginationItem($container, { selector: '.PagedList-skipToFirst', className: 'first-page-link', title: 'Skip to the first page' });
            initPaginationItem($container, { selector: '.PagedList-skipToPrevious', className: 'previous-page-link', title: 'Skip to the previous page' });
            initPaginationItem($container, { selector: '.PagedList-skipToNext', className: 'next-page-link', title: 'Skip to the next page' });
            initPaginationItem($container, { selector: '.PagedList-skipToLast', className: 'last-page-link', title: 'Skip to the last page' });
        }

        $('body').on('DOMNodeInserted', 'iframe', function (e) {
            var target = $(e.target);
            var targetSrc = target.attr('src');
            if (!target.length || !targetSrc) {
                return;
            }

            if (targetSrc.indexOf('recruitics') >= 0) {
                target.attr('title', 'Recruitics frame');
                target.attr('aria-hidden', 'true');

                $('body').off('DOMNodeInserted', 'iframe');
            }
        });
    }

    namespace('gJobs').accessibilityHtmlTransformer = new AccessibilityHtmlTransformer();
})();
;
(function (window, undefined) {
    'use strict';

    var aria = gJobs.ariaAttributes;

    // Initialize autocomplete
    $(function () {
        $.fn.tab.Constructor.prototype.activate = window.utils.wrapFunction($.fn.tab.Constructor.prototype.activate,
            function (element, container) {
                if (!container.is('ul')) {
                    return;
                }
                var $selectedTab = element.children().first('a');

                container.find('a[role="tab"]').setAttributes([
                    [ aria.selected, false ]
                ]);

                $selectedTab.setAttributes([
                    [ aria.selected, true ]
                ]);

                $selectedTab.focus();
            });

        $(document).on('keydown', 'a[role="tab"]', function (e) {
            var keyCode = e.keyCode || e.which;
            if (keyCode === $.ui.keyCode.SPACE) {
                var $link = $(e.target || e.srcElement);
                $link.click();
                e.preventDefault();
            }
        });
    });

})(window);;
(function (window, undefined) {
    'use strict';
    $(function () {
        // focus next element after dropdown is closed
        function focusNextElement (event) {
            var $target = $(event.target);
            
            if (!$target.hasClass('dropdown-toggle') && event.keyCode === $.ui.keyCode.ENTER) {
                setTimeout(function() {
                    $target.closest('.dropdown-nav').parent().find('.tab-content').find(':focusable').first().focus();
                });
            }
        }

        // close dropdown when tabbing out of it
        function closeDropdown (event) {
            var focusableElements = $('#navigation-dropdown').find('a[href]');

            var $target = $(event.target)[0];

            if ($target === focusableElements.last()[0] && event.keyCode === $.ui.keyCode.TAB && !event.shiftKey) {
                $('#navigation-dropdown').removeClass('open');
            };

            if ($target === focusableElements.first()[0] && event.keyCode === $.ui.keyCode.TAB && event.shiftKey) {
                $('#navigation-dropdown').removeClass('open');
            };
        };

        function dropdownHandler(e) {
            closeDropdown(e);
            focusNextElement(e);
        }

        $(document).on('keydown.dropdown.data-api', '#navigation-dropdown',  dropdownHandler);
    });

})(window);;
(function (window, $, undefined) {

    var NAVIGATION_HELPER_TEXT_COLLAPSED = '. List is collapsed. Press Enter to open list. Use up and down arrow keys to navigate.';
    var NAVIGATION_HELPER_TEXT_EXPANDED = '. List is expanded. Use up and down arrow keys to navigate.';
    var SELECTED_OPTIONS_POSTFIX = '-selected-option-names-container';

    var isEnterPressed = false;

    var aria = gJobs.ariaAttributes;

    if (typeof $.fn.chosen === 'function') {

        var Chosen = $.fn.chosen;

        $.fn.chosen = function (options) {
            var $dropdowns = Chosen.apply(this, options);

            return $dropdowns.each(function () {

                var $this = $(this);
                var elementId = $this.attr('id');
                var chosen = $this.data('chosen');

                var navigationHelperId = elementId + '-navigation-helper-label';
                var $navigationHelper = createHelper(navigationHelperId, NAVIGATION_HELPER_TEXT_COLLAPSED);
                $this.after($navigationHelper);
                options.describedBy = options.describedBy 
                    ? options.describedBy + ' ' + navigationHelperId
                    : navigationHelperId;

                if (chosen) {
                    var labels = $this.attr(aria.notification);
                    if (labels) {
                        options.labelledby = options.labelledby
                            ? options.labelledby + ' ' + labels
                            : labels;
                    }

                    initElements(chosen, options);

                    var chosenPrototype = chosen.constructor.prototype;
                    if (!chosenPrototype.accessibility) {
                        //There is no direct access to the prototype. It should be extended only once at the first call.
                        extendPrototype(chosenPrototype);
                    }
                }
            });
        };
    }

    function getChosenSelection(chosen) {
        return chosen.selected_item || chosen.search_choices;
    }

    //Sets initial values of WAI ARIA attributes on the Chosen dropdown elements.
    function initElements(chosen, options) {
        var $select = chosen.selected_item;

        if ($select) {
            initSingleDropdown(chosen, $select, options);
        }

        $select = chosen.search_choices;
        if ($select) {
            initNotification(chosen, $select, options);
            initMultipleDropdown(chosen, $select, options);
        }
    }

    function initNotification(chosen, $select, options) {
        if ($select && options && options.labelledby) {
            var notification = getTextByIDs(options.labelledby);
            if (notification) {
                $select.setAttributes([
                    [aria.notification, notification]
                ]);
            }
        }
    }

    function initSingleDropdown(chosen, $select, options) {

        var $input = $select.find('input');
        var $list = chosen.dropdown.find('ul');
        var $container = $(chosen.container);

        $select.off('focus');

        var labelId = options.labelledby;
        var chosenId = $(chosen.form_field).attr('id');
        var listId = chosenId + '_dropdown';
        var inputId = chosenId + '_input';

        var selectedItemSpanId = chosenId + '-selected-item';
        var selectedItemSpan = $select.children('span');
        selectedItemSpan.attr('id', selectedItemSpanId);

        var containerLabel = labelId + ' ' + selectedItemSpanId;

        $input.setAttributes([
            [aria.autocomplete, 'inline'],
            ['id', inputId],
            [aria.role, 'listbox']
        ]);

        $input.addClass('ignore-tabindex-update');

        $container.setAttributes([
            [aria.role, 'listbox'],
            [aria.labelledBy, containerLabel],
            [aria.required, options.required],
            [aria.describedBy, options.describedBy],
            ['tabindex', '0'],
        ]);

        $select.setAttributes([
            ['tabindex', '-1'],
            [aria.role, 'listbox'],
            ['data-toggle', 'popover'],
            ['data-container', 'body'],
            ['data-trigger', 'hover'],
            ['data-placement', 'bottom']
        ]);

        $select.popover({
            template: '<div class="popover job-details-popover" role="tooltip"><div class="arrow">' +
                '</div><h3 class="popover-title"></h3><div class="popover-content"></div></div>',
            animation: false,
            content: function() {
                return $('#' + selectedItemSpanId).text();
            }
        });

        $list.setAttributes([
            ['id', listId],
            ['tabindex', '-1'],
        ]);

        $list.find('li').setAttributes([
            ['tabindex', '-1'],
            [aria.role, 'option']
        ]);

        $select.addClass('ignore-tabindex-update');

        $input.on('keydown', function (e) {
            if (e.which === $.ui.keyCode.ENTER) {
                isEnterPressed ^= true;
                return;
            }
        });

        $input.onFirst('keyup', function (e) {
            if (e.which === $.ui.keyCode.ENTER && !isEnterPressed) {
                // Enter key was pressed down before chosen initialization.
                // It shouldn't be closed immediately, so we're suppressing keyup event.
                e.stopImmediatePropagation();
            }
        });

        $container.keydown(function(evt) {
            if (evt.keyCode === $.ui.keyCode.ENTER || (evt.altKey && evt.keyCode === $.ui.keyCode.DOWN)) {
                chosen.activate_action(evt);
                chosen.selected_item_focus(evt);
            } 
        }); 

        waveFix($input, $select.attr(aria.notification));
    }

    function initMultipleDropdown(chosen, $select, options) {
        var $input = $select.find('input');
        var $list = chosen.dropdown.find('ul');
        var $container = $(chosen.container);

        var chosenId = $(chosen.form_field).attr('id');
        var labelId = options.labelledby;
        var inputId = chosenId + '_input';
        var listId = chosenId + '_dropdown';

        var $selectedOptions = createSelectedOptionNamesContainer(chosen.container_id + SELECTED_OPTIONS_POSTFIX);

        $container.append($selectedOptions);

        $container.setAttributes([
            [aria.role, 'listbox'],
            [aria.labelledBy, labelId + ' ' + chosen.container_id + SELECTED_OPTIONS_POSTFIX],
            [aria.describedBy, options.describedBy],
            [aria.required, options.required],
            ['tabindex', '0']
        ]);

        $input.setAttributes([
            ['id', inputId],
            [aria.role, 'listbox'],
            [aria.owns, listId],
            [aria.required, options.required],
            ['tabindex', '-1']
        ]);

        $input.addClass('ignore-tabindex-update');

        $select.setAttributes([
            [aria.labelledBy, labelId]
        ]);

        $list.setAttributes([
            ['id', listId],
            [aria.role, 'listbox'],
            [aria.labelledBy, labelId]
        ]);

        $list.find('li').setAttributes([
            ['tabindex', '-1'],
            [aria.role, 'option']
        ]);

        $container.on('keydown.chosen.accessibility.multiselect', multiselectKeydownHandler);
        $container.on('keyup.chosen.accessibility.multiselect', multiselectKeyupHandler(chosen));
    }

    //Adds hooks around the Chosen methods to set proper WAI ARIA attribute values in response to user interaction.
    function extendPrototype(chosenPrototype) {

        chosenPrototype.accessibility = {};

        chosenPrototype.getElements = function () {
            return {
                $input: getChosenSelection(this).find('input'),
                $select: getChosenSelection(this),
                $list: this.dropdown.find('ul')
            };
        };

        chosenPrototype.isSingleSelect = function() {
            return this.selected_item !== undefined;
        };

        chosenPrototype.results_build = window.utils.wrapFunction(chosenPrototype.results_build, function () {
            var el = this.getElements();
            //the initial selection is set inside the results_build method
            var initialSelectionId = el.$list.find('.result-selected').attr('id');

            if (!this.isSingleSelect()) {
                var $selectedOptions = el.$select.find('.search-choice');
                var labelId = 'label-' + this.form_field_jq.attr('id');
                $.each($selectedOptions, function (i, val) {
                    var $el = $(val);
                    $removeElement = $el.find('.search-choice-close');
                    $removeElement.setAttributes([
                        [aria.label, 'Remove ' + $el.text()],
                        [aria.describedBy, labelId]
                    ]);
                });
                var selectedOptionsNames = $.map($selectedOptions, function(selectedOption) {
                    return $(selectedOption).text();
                }).join(', ');
                $('#' + this.container_id + SELECTED_OPTIONS_POSTFIX).text(this.choices_count() ? selectedOptionsNames : '');
            }

            el.$input.attr(aria.activeDescendant, initialSelectionId);
        }, true);

        chosenPrototype.set_tab_index_initial = function(el) {
            var ti;
            if (this.form_field_jq.attr("tabindex")) {
                ti = this.form_field_jq.attr("tabindex");
                this.form_field_jq.attr("tabindex", -1);
                return this.container.attr("tabindex", ti);
            }
        };

        chosenPrototype.set_tab_index_on_show = function(el) {
            var ti = this.container.attr("tabindex");

            if (ti !== '-1') {
                this.container.attr('tabindex', -1);
                
                if (this.is_multiple) {
                    this.container.off('keydown.chosen.accessibility.multiselect');
                    this.container.off('keyup.chosen.accessibility.multiselect');
                }

                return this.search_field.attr('tabindex', ti);
            }
        };
      
        chosenPrototype.set_tab_index_on_hide = function(el) {
            var ti = this.search_field.attr('tabindex');

            if (ti !== '-1') {
                this.container.attr('tabindex', ti);
                this.search_field.attr('tabindex', -1);

                if (this.is_multiple) {
                    this.container.on('keydown.chosen.accessibility.multiselect', multiselectKeydownHandler);
                    this.container.on('keyup.chosen.accessibility.multiselect', multiselectKeyupHandler(this));
                }

                return this.container.focus();
            }
        };

        chosenPrototype.results_show = window.utils.wrapFunction(chosenPrototype.results_show, function () {
            var el = this.getElements();
            gJobs.screenReadersService.setAriaLiveNotificationWithoutRepeat(NAVIGATION_HELPER_TEXT_EXPANDED);
            //The list of items is regenerated each time user opens the dropdown, so the roles must be set too.
            var $listParent = el.$list.parent();
            el.$list.detach();
            el.$list.find('li').setAttributes([
                ['tabindex', '-1'],
                [aria.role, 'option']
            ]);

            $listParent.append(el.$list);
        });

        chosenPrototype.winnow_results = window.utils.wrapFunction(chosenPrototype.winnow_results, function () {
            var el = this.getElements();
            var noResult = el.$list.children('.no-results');
            if (noResult.length) {
                var noResultId = this.container_id + 'no-results';
                noResult.attr('id', noResultId);
                noResult.attr('tabindex', -1);
                el.$input.attr(aria.activeDescendant, noResultId);
            }

        }, true);

        chosenPrototype.close_field = window.utils.wrapFunction(chosenPrototype.close_field, function () {
            if (this.$activatedOption) {
                this.$activatedOption = null;
            }
            this.isActivated = false;
            // Removing role attribute to prevent JAWS Forms Mode from displaying them.
            var el = this.getElements();
            var $listParent = el.$list.parent();
            el.$list.detach();

            $listParent.append(el.$list);
        }, true);

        chosenPrototype.results_hide = window.utils.wrapFunction(chosenPrototype.results_hide, function () {
            setTimeout(function() { // Waiting for 'ko if' binding applying
                if (isEnterPressed) {
                    isEnterPressed ^= true;
                }
            });

            gJobs.screenReadersService.setAriaLiveNotification('');
        });

        chosenPrototype.result_do_highlight = window.utils.wrapFunction(chosenPrototype.result_do_highlight, function ($activeElement) {
            var activeOptionId = $activeElement.attr('id');
            var el = this.getElements();
            if (this.isSingleSelect()) {
                el.$list.find('li').attr(aria.selected, "false");
                $activeElement.attr(aria.selected, "true");
            }

            el.$input.attr(aria.activeDescendant, activeOptionId);
        });

        chosenPrototype.keydown_arrow = window.utils.wrapFunction(chosenPrototype.keydown_arrow, function () {
            var el = this.getElements();
            var $activeElement = el.$list.find('.highlighted');

            el.$input.val($activeElement.text());
        }, true);

        chosenPrototype.keyup_arrow = window.utils.wrapFunction(chosenPrototype.keyup_arrow, function () {
            var el = this.getElements();
            if (this.result_highlight && this.result_highlight.prevAll("li.active-result").length === 0) {
                this.selected_option_count = 0;
                var $defaultItemText = $(this.search_results.children(':visible')[0]).text();
                el.$input.val($defaultItemText);
            } else if (!this.result_highlight) {
                this.result_do_highlight($(this.search_results.children(':visible')[0]));
            } else {
                var $activeElement = el.$list.find('.highlighted');

                el.$input.val($activeElement.text());
            }
        }, true);

        chosenPrototype.result_select = (function(base) {
            return function () {
                if (this.result_highlight && this.result_highlight.length) {
                    var el = this.getElements();
                    var activeOptionId = this.result_highlight.attr('id');

                    el.$input.attr(aria.activeDescendant, activeOptionId);
                }

                base.apply(this, arguments);

                return this.container.focus();
            }
        })(chosenPrototype.result_select);

        chosenPrototype.keydown_checker = window.utils.wrapFunction(chosenPrototype.keydown_checker, function(event) {
            event.stopPropagation();
        }, true);

        chosenPrototype.choice_build = window.utils.wrapFunction(chosenPrototype.choice_build, function(item) {
            var chosen = this;

            var itemCloseLink = getChosenSelection(this).find('.search-choice-close[rel=' + item.array_index + ']');

            itemCloseLink.on("keydown", function(evt) {
                if (event.keyCode === $.ui.keyCode.ENTER) {
                    evt.preventDefault();
                    evt.stopImmediatePropagation();
                    return false;
                }
            });

            itemCloseLink.on("keyup", function(evt) {
                if (event.keyCode === $.ui.keyCode.ENTER) {
                    chosen.choice_destroy_link_click(evt);
                    return false;
                }
            });

        }, true);

        chosenPrototype.results_hide = window.utils.wrapFunction(chosenPrototype.results_hide, function() {
            if (!this.is_multiple) {
                this.getElements().$input.val('');
            }
        }, true);

        chosenPrototype.choice_destroy_link_click = (function(func) {
            return function(event) {
                var $focusTarget;
                var $link = $(event.target);
                var $removingItem = $link.parents('li');
                var $prevItem = $removingItem.prev();
                var $nextItem = $removingItem.next();
                var el = this.getElements();
                var relIndex;
                gJobs.screenReadersService.setAriaLiveNotification($removingItem.text() + ' removed.');

                if ($prevItem.length) {
                    $focusTarget = $prevItem;
                } else {
                    $focusTarget = $nextItem;
                }

                // After removing an element all the others are reattached to DOM,
                // so old links are not working anymore.
                relIndex = $focusTarget.find('a').attr('rel');

                func.call(this, event);

                if (relIndex !== undefined) {
                    $focusTarget = el.$select.find('.search-choice-close[rel="' + relIndex + '"]');
                } else {
                    $focusTarget = this.container;
                }

                $focusTarget.focus();
            };
        })(chosenPrototype.choice_destroy_link_click);
    }

    function createHelper(helperId, helperText) {
        var $helper = $('<span class="ui-helper-hidden-accessible"></span>');
        $helper.text(helperText);
        $helper.attr('id', helperId);
        return $helper;
    }

    function createSelectedOptionNamesContainer(containerId) {
        var $selectedOptions = $('<span class="ui-helper-hidden-accessible"></span>');
        $selectedOptions.attr('id', containerId);
        return $selectedOptions;
    }

    function getTextByIDs(id) {
        var selectors = id.replace(/[ ,]+/gi, ' ').trim().split(' ');
        var text = selectors.map(function (selector) {
            if (!selector.length) {
                return '';
            }
            if (selector[0] !== '#') {
                selector = '#' + selector;
            }
            return $(selector).text().trim() + '.';
        });
        var result = text.join(' ').replace(/[*]+/gi, ' ');
        return result;
    }
    function setNotification($element, notification) {
        var text = $element.text();
        var $notificationContainer = $("<span />");
        $notificationContainer.addClass('hide-notification');
        $notificationContainer.text(notification);
        $notificationContainer.prependTo($element);
        $element.attr(aria.label, notification + ' ' + text);
    }
    function clearNotification($element) {
        $element.find('.hide-notification').remove();
        $element.attr(aria.label, $element.text().trim());
    }
    function waveFix($element, text) {
        var label = $('<label />');
        label.attr('for', $element.attr('id'));
        label.css('display', 'none');
        label.text(text);
        label.appendTo($element.parent());
    }

    function multiselectKeydownHandler(evt) {
        if (evt.keyCode === $.ui.keyCode.ENTER || (evt.altKey && evt.keyCode === $.ui.keyCode.DOWN)) {
            evt.stopImmediatePropagation();
            evt.preventDefault();
            return false;
        }
    }

    function multiselectKeyupHandler(chosen) {
        return function(evt) {
            if (evt.keyCode === $.ui.keyCode.ENTER || (evt.altKey && evt.keyCode === $.ui.keyCode.DOWN)) {
                evt.stopImmediatePropagation();
                evt.preventDefault();
                chosen.input_focus();
                return false;
            }
        }
    }

})(window, jQuery);;
(function ($, window, document, undefined) {

    var pluginName = "keySelection",

        keyEventName = "keydown",

        firstItemIndex = 0,

        actions = {
            up: "up",
            down: "down"
        },

        defaults = {

            selectionItemSelector: ".selection-item",

            isCircling: false,

            keyActions: [
                {
                    keyCode: $.ui.keyCode.UP,
                    action: actions.up
                },
                {
                    keyCode: $.ui.keyCode.PAGE_UP,
                    action: actions.up
                },
                {
                    keyCode: $.ui.keyCode.LEFT,
                    action: actions.up
                },
                {
                    keyCode: $.ui.keyCode.DOWN,
                    action: actions.down
                },
                {
                    keyCode: $.ui.keyCode.PAGE_DOWN,
                    action: actions.down
                },
                {
                    keyCode: $.ui.keyCode.RIGHT,
                    action: actions.down
                }
            ]
        };

    function Plugin(container, options) {

        var self = this;

        this.name = pluginName;
        this.defaults = defaults;
        this.options = $.extend({}, defaults, options);

        this.$container = $(container);
        this.$items = this.$container.find(this.options.selectionItemSelector);
        this.$currentItem = null;

        this.init = init;
        this.up = up;
        this.down = down;
        this.destroy = destroy;

        this.init();

        function init() {
            self.$items.on(keyEventName, keydownHandler);
        }
        function up() {
            moveSelection(function (length, index) {
                if (index > firstItemIndex) {
                    return index - 1;
                } else if (self.options.isCircling && index === firstItemIndex) {
                    return length - 1;
                }
                return undefined;
            });
        }
        function down() {
            moveSelection(function (length, index) {
                if (index < (length - 1)) {
                    return index + 1;
                } else if (self.options.isCircling && (index === (length - 1))) {
                    return firstItemIndex;
                }
                return undefined;
            });
        }
        function destroy() {
            self.$items.off(keyEventName, keydownHandler);
        }

        function keydownHandler(e) {
            var keyCode = e.keyCode || e.which;
            self.$currentItem = $(e.target || e.srcElement);
            $.each(self.options.keyActions, function (i, keyAction) {
                if (keyAction.keyCode === keyCode) {
                    e.preventDefault();
                    switch (keyAction.action) {
                        case actions.up:
                            self.up();
                            break;
                        case actions.down:
                            self.down();
                            break;
                    }
                }
            });
        }
        function moveSelection(actionHandler) {
            if (self.$currentItem) {
                var index = self.$items.index(self.$currentItem);
                var nextIndex = actionHandler(self.$items.length, index);
                if (nextIndex !== undefined) {
                    var nextitem = self.$items.get(nextIndex);
                    self.$currentItem = $(nextitem);
                    self.$currentItem.focus();
                }
            }
        }
    }

    $.fn[pluginName] = function (options) {
        return this.each(function () {
            if (!$.data(this, "plugin_" + pluginName)) {
                $.data(this, "plugin_" + pluginName, new Plugin(this, options));
            }
            if ((typeof options === "string" || options instanceof String) && (/up|down|destroy/).test(options)) {
                var plugin = $.data(this, "plugin_" + pluginName);
                plugin[options].call(plugin);
            }
        });
    };

})(jQuery, window, document); ;
