﻿// jQuery Alert Dialogs Plugin
// Version 1.1
// Cory S.N. LaViska
// A Beautiful Site (http://abeautifulsite.net/)
// 14 May 2009
// Visit http://abeautifulsite.net/notebook/87 for more information
(function ($) {
    $.alerts = { verticalOffset: -75, horizontalOffset: 0, repositionOnResize: true, overlayOpacity: .51, overlayColor: '#999', draggable: true, okButton: ' Yes ', cancelButton: ' No ', dialogClass: null, alert: function (message, title, callback) { if (title == null) title = 'Information'; $.alerts._show(title, message, null, 'alert', function (result) { if (callback) callback(result); }); }, confirm: function (message, title, callback) { if (title == null) title = 'Confirmation dialog'; $.alerts._show(title, message, null, 'confirm', function (result) { if (callback) callback(result); }); }, prompt: function (message, value, title, callback) { if (title == null) title = 'Prompt'; $.alerts._show(title, message, value, 'prompt', function (result) { if (callback) callback(result); }); }, _show: function (title, msg, value, type, callback) {
        $.alerts._hide(); $.alerts._overlay('show'); $("BODY").append('<div id="popup_container">' + '<h1 id="popup_title"></h1>' + '<div id="popup_content">' + '<div id="popup_message"></div>' + '</div>' + '</div>'); if ($.alerts.dialogClass) $("#popup_container").addClass($.alerts.dialogClass); var pos = ($.browser.msie && parseInt($.browser.version) <= 9) ? 'absolute' : 'fixed'; $("#popup_container").css({ position: pos, zIndex: 9999, padding: 0, margin: 0 }); $("#popup_title").text(title); $("#popup_content").addClass(type); $("#popup_message").text(msg); $("#popup_message").html($("#popup_message").text().replace(/\n/g, '<br />')); $("#popup_container").css({ minWidth: $("#popup_container").outerWidth(), maxWidth: $("#popup_container").outerWidth() }); $.alerts._reposition(); $.alerts._maintainPosition(true); switch (type) { case 'alert': $("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /></div>'); $("#popup_ok").click(function () { $.alerts._hide(); callback(true); }); $("#popup_ok").focus().keypress(function (e) { if (e.keyCode == 13 || e.keyCode == 27) $("#popup_ok").trigger('click'); }); break; case 'confirm': $("#popup_message").after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /> <input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel" /></div>'); $("#popup_ok").click(function () { $.alerts._hide(); if (callback) callback(true); }); $("#popup_cancel").click(function () { $.alerts._hide(); if (callback) callback(false); }); $("#popup_ok").focus(); $("#popup_ok, #popup_cancel").keypress(function (e) { if (e.keyCode == 13) $("#popup_ok").trigger('click'); if (e.keyCode == 27) $("#popup_cancel").trigger('click'); }); break; case 'prompt': $("#popup_message").append('<br /><input type="text" size="30" id="popup_prompt" />').after('<div id="popup_panel"><input type="button" value="' + $.alerts.okButton + '" id="popup_ok" /> <input type="button" value="' + $.alerts.cancelButton + '" id="popup_cancel" /></div>'); $("#popup_prompt").width($("#popup_message").width()); $("#popup_ok").click(function () { var val = $("#popup_prompt").val(); $.alerts._hide(); if (callback) callback(val); }); $("#popup_cancel").click(function () { $.alerts._hide(); if (callback) callback(null); }); $("#popup_prompt, #popup_ok, #popup_cancel").keypress(function (e) { if (e.keyCode == 13) $("#popup_ok").trigger('click'); if (e.keyCode == 27) $("#popup_cancel").trigger('click'); }); if (value) $("#popup_prompt").val(value); $("#popup_prompt").focus().select(); break; }
        if ($.alerts.draggable) { try { $("#popup_container").draggable({ handle: $("#popup_title") }); $("#popup_title").css({ cursor: 'move' }); } catch (e) { } }
    }, _hide: function () { $("#popup_container").remove(); $.alerts._overlay('hide'); $.alerts._maintainPosition(false); }, _overlay: function (status) { switch (status) { case 'show': $.alerts._overlay('hide'); $("BODY").append('<div id="popup_overlay"></div>'); $("#popup_overlay").css({ position: 'absolute', zIndex: 9998, top: '0px', left: '0px', width: '100%', height: $(document).height(), background: $.alerts.overlayColor, opacity: $.alerts.overlayOpacity }); break; case 'hide': $("#popup_overlay").remove(); break; } }, _reposition: function () { var top = (($(window).height() / 2) - ($("#popup_container").outerHeight() / 2)) + $.alerts.verticalOffset; var left = (($(window).width() / 2) - ($("#popup_container").outerWidth() / 2)) + $.alerts.horizontalOffset; if (top < 0) top = 0; if (left < 0) left = 0; if ($.browser.msie && parseInt($.browser.version) <= 6) top = top + $(window).scrollTop(); $("#popup_container").css({ top: top + 'px', left: left + 'px' }); $("#popup_overlay").height($(document).height()); }, _maintainPosition: function (status) { if ($.alerts.repositionOnResize) { switch (status) { case true: $(window).bind('resize', $.alerts._reposition); break; case false: $(window).unbind('resize', $.alerts._reposition); break; } } }
    }
    jAlert = function (message, title, callback) { $.alerts.alert(message, title, callback); }
    jConfirm = function (message, title, callback) { $.alerts.confirm(message, title, callback); }; jPrompt = function (message, value, title, callback) { $.alerts.prompt(message, value, title, callback); };
})(jQuery);

/*
* imgPreview jQuery plugin
* Copyright (c) 2009 James Padolsey
* j@qd9.co.uk | http://james.padolsey.com
* Dual licensed under MIT and GPL.
* Updated: 09/02/09
* @author James Padolsey
* @version 0.22
*/
(function ($) {

    $.expr[':'].linkingToImage = function (elem, index, match) {
        // This will return true if the specified attribute contains a valid link to an image:
        return !!($(elem).attr(match[3]) && $(elem).attr(match[3]).match(/\.(gif|jpe?g|png|bmp)$/i));
    };

    $.fn.imgPreview = function (userDefinedSettings) {

        var s = $.extend({

            /* DEFAULTS */

            // CSS to be applied to image:
            imgCSS: {},
            // Distance between cursor and preview:
            distanceFromCursor: { top: 10, left: 10 },
            // Boolean, whether or not to preload images:
            preloadImages: true,
            // Callback: run when link is hovered: container is shown:
            onShow: function () { },
            // Callback: container is hidden:
            onHide: function () { },
            // Callback: Run when image within container has loaded:
            onLoad: function () { },
            // ID to give to container (for CSS styling):
            containerID: 'imgPreviewContainer',
            // Class to be given to container while image is loading:
            containerLoadingClass: 'loading',
            // Prefix (if using thumbnails), e.g. 'thumb_'
            thumbPrefix: '',
            // Where to retrieve the image from:
            srcAttr: 'href'

        }, userDefinedSettings),

        $container = $('<div/>').attr('id', s.containerID)
                        .append('<img/>').hide()
                        .css('position', 'absolute')
                        .appendTo('body'),

        $img = $('img', $container).css(s.imgCSS),

        // Get all valid elements (linking to images / ATTR with image link):
        $collection = this.filter(':linkingToImage(' + s.srcAttr + ')');

        // Re-usable means to add prefix (from setting):
        function addPrefix(src) {
            return src.replace(/(\/?)([^\/]+)$/, '$1' + s.thumbPrefix + '$2');
        }

        if (s.preloadImages) {
            (function (i) {
                var tempIMG = new Image(),
                    callee = arguments.callee;
                tempIMG.src = addPrefix($($collection[i]).attr(s.srcAttr));
                tempIMG.onload = function () {
                    $collection[i + 1] && callee(i + 1);
                };
            })(0);
        }

        $collection
            .mousemove(function (e) {

                $container.css({
                    top: e.pageY + s.distanceFromCursor.top + 'px',
                    left: e.pageX + s.distanceFromCursor.left + 'px'
                });

            })
            .hover(function () {

                var link = this;
                $container
                    .addClass(s.containerLoadingClass)
                    .show();
                $img
                    .load(function () {
                        $container.removeClass(s.containerLoadingClass);
                        $img.show();
                        s.onLoad.call($img[0], link);
                    })
                    .attr('src', addPrefix($(link).attr(s.srcAttr)));
                s.onShow.call($container[0], link);

            }, function () {

                $container.hide();
                $img.unbind('load').attr('src', '').hide();
                s.onHide.call($container[0], this);

            });

        // Return full selection, not $collection!
        return this;

    };

})(jQuery);

/*
Autogrow textarea (run through JSLint and JSMin) from:
Grab Bag - Assorted Detritus
(c) 2008 Jason Frame (jason@onehackoranother.com)
Released under The MIT License.
*/
(function ($) {
    $.fn.autogrow = function (options) {
        this.filter('textarea').each(function () {
            var $this = $(this), minHeight = $this.height(), lineHeight = $this.css('lineHeight'); var shadow = $('<div></div>').css({ position: 'absolute', top: -10000, left: -10000, width: $(this).width() - parseInt($this.css('paddingLeft'), 10) - parseInt($this.css('paddingRight'), 10), fontSize: $this.css('fontSize'), fontFamily: $this.css('fontFamily'), lineHeight: $this.css('lineHeight'), resize: 'none' }).appendTo(document.body); var update = function () {
                var times = function (string, number) {
                    for (var i = 0, r = ''; i < number; i++) { r += string; }
                    return r;
                }; var val = this.value.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/&/g, '&amp;').replace(/\n$/, '<br/>&nbsp;').replace(/\n/g, '<br/>').replace(/ {2,}/g, function (space) { return times('&nbsp;', space.length - 1) + ' '; }); shadow.html(val); $(this).css('height', Math.max(shadow.height() + 20, minHeight));
            }; $(this).change(update).keyup(update).keydown(update); update.apply(this);
        }); return this;
    };
})(jQuery);


/* jFeed : jQuery feed parser plugin
* Copyright (C) 2007 Jean-FranÃ§ois Hovinne - http://www.hovinne.com/
* Dual licensed under the MIT (MIT-license.txt)
* and GPL (GPL-license.txt) licenses.
*/
jQuery.getFeed = function (options) { options = jQuery.extend({ url: null, data: null, success: null }, options); if (options.url) { $.ajax({ type: 'GET', url: options.url, data: options.data, dataType: 'xml', success: function (xml) { var feed = new JFeed(xml); if (jQuery.isFunction(options.success)) options.success(feed); } }); } }; function JFeed(xml) { if (xml) this.parse(xml); }; JFeed.prototype = { type: '', version: '', title: '', link: '', description: '', parse: function (xml) {
    if (jQuery('channel', xml).length == 1) { this.type = 'rss'; var feedClass = new JRss(xml); } else if (jQuery('feed', xml).length == 1) { this.type = 'atom'; var feedClass = new JAtom(xml); }
    if (feedClass) jQuery.extend(this, feedClass);
}
}; function JFeedItem() { }; JFeedItem.prototype = { title: '', link: '', description: '', updated: '', id: '' }; function JAtom(xml) { this._parse(xml); }; JAtom.prototype = { _parse: function (xml) { var channel = jQuery('feed', xml).eq(0); this.version = '1.0'; this.title = jQuery(channel).find('title:first').text(); this.link = jQuery(channel).find('link:first').attr('href'); this.description = jQuery(channel).find('subtitle:first').text(); this.language = jQuery(channel).attr('xml:lang'); this.updated = jQuery(channel).find('updated:first').text(); this.items = new Array(); var feed = this; jQuery('entry', xml).each(function () { var item = new JFeedItem(); item.title = jQuery(this).find('title').eq(0).text(); item.link = jQuery(this).find('link').eq(0).attr('href'); item.description = jQuery(this).find('content').eq(0).text(); item.updated = jQuery(this).find('updated').eq(0).text(); item.id = jQuery(this).find('id').eq(0).text(); feed.items.push(item); }); } }; function JRss(xml) { this._parse(xml); }; JRss.prototype = { _parse: function (xml) { if (jQuery('rss', xml).length == 0) this.version = '1.0'; else this.version = jQuery('rss', xml).eq(0).attr('version'); var channel = jQuery('channel', xml).eq(0); this.title = jQuery(channel).find('title:first').text(); this.link = jQuery(channel).find('link:first').text(); this.description = jQuery(channel).find('description:first').text(); this.language = jQuery(channel).find('language:first').text(); this.updated = jQuery(channel).find('lastBuildDate:first').text(); this.items = new Array(); var feed = this; jQuery('item', xml).each(function () { var item = new JFeedItem(); item.title = jQuery(this).find('title').eq(0).text(); item.link = jQuery(this).find('link').eq(0).text(); item.description = jQuery(this).find('description').eq(0).text(); item.updated = jQuery(this).find('pubDate').eq(0).text(); item.id = jQuery(this).find('guid').eq(0).text(); feed.items.push(item); }); } };

jQuery.fn.fadeToggle = function (speed, easing, callback) {
    return this.animate({ opacity: 'toggle' }, speed, easing, callback);
};

/*	
Watermark plugin for jQuery
Version: 3.1.1
http://jquery-watermark.googlecode.com/

Copyright (c) 2009-2011 Todd Northrop
http://www.speednet.biz/
	
January 10, 2011

Requires:  jQuery 1.2.3+
	
Dual licensed under the MIT or GPL Version 2 licenses.
See mit-license.txt and gpl2-license.txt in the project root for details.
------------------------------------------------------*/

(function ($, window, undefined) {

    var 
    // String constants for data names
	dataFlag = "watermark",
	dataClass = "watermarkClass",
	dataFocus = "watermarkFocus",
	dataFormSubmit = "watermarkSubmit",
	dataMaxLen = "watermarkMaxLength",
	dataPassword = "watermarkPassword",
	dataText = "watermarkText",

    // Copy of native jQuery regex use to strip return characters from element value
	rreturn = /\r/g,

    // Includes only elements with watermark defined
	selWatermarkDefined = ":data(" + dataFlag + ")",

    // Includes only elements capable of having watermark
	selWatermarkAble = ":text,:password,:search,textarea",

    // triggerFns:
    // Array of function names to look for in the global namespace.
    // Any such functions found will be hijacked to trigger a call to
    // hideAll() any time they are called.  The default value is the
    // ASP.NET function that validates the controls on the page
    // prior to a postback.
    // 
    // Am I missing other important trigger function(s) to look for?
    // Please leave me feedback:
    // http://code.google.com/p/jquery-watermark/issues/list
	triggerFns = [
		"Page_ClientValidate"
	],

    // Holds a value of true if a watermark was displayed since the last
    // hideAll() was executed. Avoids repeatedly calling hideAll().
	pageDirty = false,

    // Detects if the browser can handle native placeholders
	hasNativePlaceholder = ("placeholder" in document.createElement("input"));

    // Best practice: this plugin adds only one method to the jQuery object.
    // Also ensures that the watermark code is only added once.
    $.watermark = $.watermark || {

        // Current version number of the plugin
        version: "3.1.1",

        runOnce: true,

        // Default options used when watermarks are instantiated.
        // Can be changed to affect the default behavior for all
        // new or updated watermarks.
        options: {

            // Default class name for all watermarks
            className: "watermark",

            // If true, plugin will detect and use native browser support for
            // watermarks, if available. (e.g., WebKit's placeholder attribute.)
            useNative: true,

            // If true, all watermarks will be hidden during the window's
            // beforeunload event. This is done mainly because WebKit
            // browsers remember the watermark text during navigation
            // and try to restore the watermark text after the user clicks
            // the Back button. We can avoid this by hiding the text before
            // the browser has a chance to save it. The regular unload event
            // was tried, but it seems the browser saves the text before
            // that event kicks off, because it didn't work.
            hideBeforeUnload: true
        },

        // Hide one or more watermarks by specifying any selector type
        // i.e., DOM element, string selector, jQuery matched set, etc.
        hide: function (selector) {
            $(selector).filter(selWatermarkDefined).each(
			function () {
			    $.watermark._hide($(this));
			}
		);
        },

        // Internal use only.
        _hide: function ($input, focus) {
            var elem = $input[0],
			inputVal = (elem.value || "").replace(rreturn, ""),
			inputWm = $input.data(dataText) || "",
			maxLen = $input.data(dataMaxLen) || 0,
			className = $input.data(dataClass);

            if ((inputWm.length) && (inputVal == inputWm)) {
                elem.value = "";

                // Password type?
                if ($input.data(dataPassword)) {

                    if (($input.attr("type") || "") === "text") {
                        var $pwd = $input.data(dataPassword) || [],
						$wrap = $input.parent() || [];

                        if (($pwd.length) && ($wrap.length)) {
                            $wrap[0].removeChild($input[0]); // Can't use jQuery methods, because they destroy data
                            $wrap[0].appendChild($pwd[0]);
                            $input = $pwd;
                        }
                    }
                }

                if (maxLen) {
                    $input.attr("maxLength", maxLen);
                    $input.removeData(dataMaxLen);
                }

                if (focus) {
                    $input.attr("autocomplete", "off");  // Avoid NS_ERROR_XPC_JS_THREW_STRING error in Firefox

                    window.setTimeout(
					function () {
					    $input.select();  // Fix missing cursor in IE
					}
				, 1);
                }
            }

            className && $input.removeClass(className);
        },

        // Display one or more watermarks by specifying any selector type
        // i.e., DOM element, string selector, jQuery matched set, etc.
        // If conditions are not right for displaying a watermark, ensures that watermark is not shown.
        show: function (selector) {
            $(selector).filter(selWatermarkDefined).each(
			function () {
			    $.watermark._show($(this));
			}
		);
        },

        // Internal use only.
        _show: function ($input) {
            var elem = $input[0],
			val = (elem.value || "").replace(rreturn, ""),
			text = $input.data(dataText) || "",
			type = $input.attr("type") || "",
			className = $input.data(dataClass);

            if (((val.length == 0) || (val == text)) && (!$input.data(dataFocus))) {
                pageDirty = true;

                // Password type?
                if ($input.data(dataPassword)) {

                    if (type === "password") {
                        var $pwd = $input.data(dataPassword) || [],
						$wrap = $input.parent() || [];

                        if (($pwd.length) && ($wrap.length)) {
                            $wrap[0].removeChild($input[0]); // Can't use jQuery methods, because they destroy data
                            $wrap[0].appendChild($pwd[0]);
                            $input = $pwd;
                            $input.attr("maxLength", text.length);
                            elem = $input[0];
                        }
                    }
                }

                // Ensure maxLength big enough to hold watermark (input of type="text" or type="search" only)
                if ((type === "text") || (type === "search")) {
                    var maxLen = $input.attr("maxLength") || 0;

                    if ((maxLen > 0) && (text.length > maxLen)) {
                        $input.data(dataMaxLen, maxLen);
                        $input.attr("maxLength", text.length);
                    }
                }

                className && $input.addClass(className);
                elem.value = text;
            }
            else {
                $.watermark._hide($input);
            }
        },

        // Hides all watermarks on the current page.
        hideAll: function () {
            if (pageDirty) {
                $.watermark.hide(selWatermarkAble);
                pageDirty = false;
            }
        },

        // Displays all watermarks on the current page.
        showAll: function () {
            $.watermark.show(selWatermarkAble);
        }
    };

    $.fn.watermark = $.fn.watermark || function (text, options) {
        ///	<summary>
        ///		Set watermark text and class name on all input elements of type="text/password/search" and
        /// 	textareas within the matched set. If className is not specified in options, the default is
        /// 	"watermark". Within the matched set, only input elements with type="text/password/search"
        /// 	and textareas are affected; all other elements are ignored.
        ///	</summary>
        ///	<returns type="jQuery">
        ///		Returns the original jQuery matched set (not just the input and texarea elements).
        /// </returns>
        ///	<param name="text" type="String">
        ///		Text to display as a watermark when the input or textarea element has an empty value and does not
        /// 	have focus. The first time watermark() is called on an element, if this argument is empty (or not
        /// 	a String type), then the watermark will have the net effect of only changing the class name when
        /// 	the input or textarea element's value is empty and it does not have focus.
        ///	</param>
        ///	<param name="options" type="Object" optional="true">
        ///		Provides the ability to override the default watermark options ($.watermark.options). For backward
        /// 	compatibility, if a string value is supplied, it is used as the class name that overrides the class
        /// 	name in $.watermark.options.className. Properties include:
        /// 		className: When the watermark is visible, the element will be styled using this class name.
        /// 		useNative (Boolean or Function): Specifies if native browser support for watermarks will supersede
        /// 			plugin functionality. If useNative is a function, the return value from the function will
        /// 			determine if native support is used. The function is passed one argument -- a jQuery object
        /// 			containing the element being tested as the only element in its matched set -- and the DOM
        /// 			element being tested is the object on which the function is invoked (the value of "this").
        ///	</param>
        /// <remarks>
        ///		The effect of changing the text and class name on an input element is called a watermark because
        ///		typically light gray text is used to provide a hint as to what type of input is required. However,
        ///		the appearance of the watermark can be something completely different: simply change the CSS style
        ///		pertaining to the supplied class name.
        ///		
        ///		The first time watermark() is called on an element, the watermark text and class name are initialized,
        ///		and the focus and blur events are hooked in order to control the display of the watermark.  Also, as
        /// 	of version 3.0, drag and drop events are hooked to guard against dropped text being appended to the
        /// 	watermark.  If native watermark support is provided by the browser, it is detected and used, unless
        /// 	the useNative option is set to false.
        ///		
        ///		Subsequently, watermark() can be called again on an element in order to change the watermark text
        ///		and/or class name, and it can also be called without any arguments in order to refresh the display.
        ///		
        ///		For example, after changing the value of the input or textarea element programmatically, watermark()
        /// 	should be called without any arguments to refresh the display, because the change event is only
        /// 	triggered by user actions, not by programmatic changes to an input or textarea element's value.
        /// 	
        /// 	The one exception to programmatic updates is for password input elements:  you are strongly cautioned
        /// 	against changing the value of a password input element programmatically (after the page loads).
        /// 	The reason is that some fairly hairy code is required behind the scenes to make the watermarks bypass
        /// 	IE security and switch back and forth between clear text (for watermarks) and obscured text (for
        /// 	passwords).  It is *possible* to make programmatic changes, but it must be done in a certain way, and
        /// 	overall it is not recommended.
        /// </remarks>

        if (!this.length) {
            return this;
        }

        var hasClass = false,
		hasText = (typeof (text) === "string");

        if (hasText) {
            text = text.replace(rreturn, "");
        }

        if (typeof (options) === "object") {
            hasClass = (typeof (options.className) === "string");
            options = $.extend({}, $.watermark.options, options);
        }
        else if (typeof (options) === "string") {
            hasClass = true;
            options = $.extend({}, $.watermark.options, { className: options });
        }
        else {
            options = $.watermark.options;
        }

        if (typeof (options.useNative) !== "function") {
            options.useNative = options.useNative ? function () { return true; } : function () { return false; };
        }

        return this.each(
		function () {
		    var $input = $(this);

		    if (!$input.is(selWatermarkAble)) {
		        return;
		    }

		    // Watermark already initialized?
		    if ($input.data(dataFlag)) {

		        // If re-defining text or class, first remove existing watermark, then make changes
		        if (hasText || hasClass) {
		            $.watermark._hide($input);

		            if (hasText) {
		                $input.data(dataText, text);
		            }

		            if (hasClass) {
		                $input.data(dataClass, options.className);
		            }
		        }
		    }
		    else {

		        // Detect and use native browser support, if enabled in options
		        if (
					(hasNativePlaceholder)
					&& (options.useNative.call(this, $input))
					&& (($input.attr("tagName") || "") !== "TEXTAREA")
				) {
		            // className is not set because current placeholder standard doesn't
		            // have a separate class name property for placeholders (watermarks).
		            if (hasText) {
		                $input.attr("placeholder", text);
		            }

		            // Only set data flag for non-native watermarks
		            // [purposely commented-out] -> $input.data(dataFlag, 1);
		            return;
		        }

		        $input.data(dataText, hasText ? text : "");
		        $input.data(dataClass, options.className);
		        $input.data(dataFlag, 1); // Flag indicates watermark was initialized

		        // Special processing for password type
		        if (($input.attr("type") || "") === "password") {
		            var $wrap = $input.wrap("<span>").parent(),
						$wm = $($wrap.html().replace(/type=["']?password["']?/i, 'type="text"'));

		            $wm.data(dataText, $input.data(dataText));
		            $wm.data(dataClass, $input.data(dataClass));
		            $wm.data(dataFlag, 1);
		            $wm.attr("maxLength", text.length);

		            $wm.focus(
						function () {
						    $.watermark._hide($wm, true);
						}
					).bind("dragenter",
						function () {
						    $.watermark._hide($wm);
						}
					).bind("dragend",
						function () {
						    window.setTimeout(function () { $wm.blur(); }, 1);
						}
					);
		            $input.blur(
						function () {
						    $.watermark._show($input);
						}
					).bind("dragleave",
						function () {
						    $.watermark._show($input);
						}
					);

		            $wm.data(dataPassword, $input);
		            $input.data(dataPassword, $wm);
		        }
		        else {

		            $input.focus(
						function () {
						    $input.data(dataFocus, 1);
						    $.watermark._hide($input, true);
						}
					).blur(
						function () {
						    $input.data(dataFocus, 0);
						    $.watermark._show($input);
						}
					).bind("dragenter",
						function () {
						    $.watermark._hide($input);
						}
					).bind("dragleave",
						function () {
						    $.watermark._show($input);
						}
					).bind("dragend",
						function () {
						    window.setTimeout(function () { $.watermark._show($input); }, 1);
						}
					).bind("drop",
		            // Firefox makes this lovely function necessary because the dropped text
		            // is merged with the watermark before the drop event is called.
						function (evt) {
						    var elem = $input[0],
								dropText = evt.originalEvent.dataTransfer.getData("Text");

						    if ((elem.value || "").replace(rreturn, "").replace(dropText, "") === $input.data(dataText)) {
						        elem.value = dropText;
						    }

						    $input.focus();
						}
					);
		        }

		        // In order to reliably clear all watermarks before form submission,
		        // we need to replace the form's submit function with our own
		        // function.  Otherwise watermarks won't be cleared when the form
		        // is submitted programmatically.
		        if (this.form) {
		            var form = this.form,
						$form = $(form);

		            if (!$form.data(dataFormSubmit)) {
		                $form.submit($.watermark.hideAll);

		                // form.submit exists for all browsers except Google Chrome
		                // (see "else" below for explanation)
		                if (form.submit) {
		                    $form.data(dataFormSubmit, form.submit);

		                    form.submit = (function (f, $f) {
		                        return function () {
		                            var nativeSubmit = $f.data(dataFormSubmit);

		                            $.watermark.hideAll();

		                            if (nativeSubmit.apply) {
		                                nativeSubmit.apply(f, Array.prototype.slice.call(arguments));
		                            }
		                            else {
		                                nativeSubmit();
		                            }
		                        };
		                    })(form, $form);
		                }
		                else {
		                    $form.data(dataFormSubmit, 1);

		                    // This strangeness is due to the fact that Google Chrome's
		                    // form.submit function is not visible to JavaScript (identifies
		                    // as "undefined").  I had to invent a solution here because hours
		                    // of Googling (ironically) for an answer did not turn up anything
		                    // useful.  Within my own form.submit function I delete the form's
		                    // submit function, and then call the non-existent function --
		                    // which, in the world of Google Chrome, still exists.
		                    form.submit = (function (f) {
		                        return function () {
		                            $.watermark.hideAll();
		                            delete f.submit;
		                            f.submit();
		                        };
		                    })(form);
		                }
		            }
		        }
		    }

		    $.watermark._show($input);
		}
	);
    };

    // The code included within the following if structure is guaranteed to only run once,
    // even if the watermark script file is included multiple times in the page.
    if ($.watermark.runOnce) {
        $.watermark.runOnce = false;

        $.extend($.expr[":"], {

            // Extends jQuery with a custom selector - ":search" for determining is the element
            // is a "search" input type.
            search: function (elem) {
                return "search" === (elem.type || "");
            },

            // Extends jQuery with a custom selector - ":data(...)"
            // :data(<name>)  Includes elements that have a specific name defined in the jQuery data
            // collection. (Only the existence of the name is checked; the value is ignored.)
            // A more sophisticated version of the :data() custom selector originally part of this plugin
            // was removed for compatibility with jQuery UI. The original code can be found in the SVN
            // source listing in the file, "jquery.data.js".
            data: function (elem, i, match) {
                return !!$.data(elem, match[3]);
            }
        });

        // Overloads the jQuery .val() function to return the underlying input value on
        // watermarked input elements.  When .val() is being used to set values, this
        // function ensures watermarks are properly set/removed after the values are set.
        // Uses self-executing function to override the default jQuery function.
        (function (valOld) {

            $.fn.val = function () {

                // Best practice: return immediately if empty matched set
                if (!this.length) {
                    return arguments.length ? this : undefined;
                }

                // If no args, then we're getting the value of the first element;
                // otherwise we're setting values for all elements in matched set
                if (!arguments.length) {

                    // If element is watermarked, get the underlying value;
                    // otherwise use native jQuery .val()
                    if (this.data(dataFlag)) {
                        var v = (this[0].value || "").replace(rreturn, "");
                        return (v === (this.data(dataText) || "")) ? "" : v;
                    }
                    else {
                        return valOld.apply(this, arguments);
                    }
                }
                else {
                    valOld.apply(this, arguments);
                    $.watermark.show(this);
                    return this;
                }
            };

        })($.fn.val);

        // Hijack any functions found in the triggerFns list
        if (triggerFns.length) {

            // Wait until DOM is ready before searching
            $(function () {
                var i, name, fn;

                for (i = triggerFns.length - 1; i >= 0; i--) {
                    name = triggerFns[i];
                    fn = window[name];

                    if (typeof (fn) === "function") {
                        window[name] = (function (origFn) {
                            return function () {
                                $.watermark.hideAll();
                                return origFn.apply(null, Array.prototype.slice.call(arguments));
                            };
                        })(fn);
                    }
                }
            });
        }

        $(window).bind("beforeunload", function () {
            if ($.watermark.options.hideBeforeUnload) {
                $.watermark.hideAll();
            }
        });
    }

})(jQuery, window);

/*!
* jQuery UI 1.8.9
*
* Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*
* http://docs.jquery.com/UI
*/
(function (c, j) {
    function k(a) { return !c(a).parents().andSelf().filter(function () { return c.curCSS(this, "visibility") === "hidden" || c.expr.filters.hidden(this) }).length } c.ui = c.ui || {}; if (!c.ui.version) {
        c.extend(c.ui, { version: "1.8.9", keyCode: { ALT: 18, BACKSPACE: 8, CAPS_LOCK: 20, COMMA: 188, COMMAND: 91, COMMAND_LEFT: 91, COMMAND_RIGHT: 93, CONTROL: 17, DELETE: 46, DOWN: 40, END: 35, ENTER: 13, ESCAPE: 27, HOME: 36, INSERT: 45, LEFT: 37, MENU: 93, NUMPAD_ADD: 107, NUMPAD_DECIMAL: 110, NUMPAD_DIVIDE: 111, NUMPAD_ENTER: 108, NUMPAD_MULTIPLY: 106,
            NUMPAD_SUBTRACT: 109, PAGE_DOWN: 34, PAGE_UP: 33, PERIOD: 190, RIGHT: 39, SHIFT: 16, SPACE: 32, TAB: 9, UP: 38, WINDOWS: 91
        }
        }); c.fn.extend({ _focus: c.fn.focus, focus: function (a, b) { return typeof a === "number" ? this.each(function () { var d = this; setTimeout(function () { c(d).focus(); b && b.call(d) }, a) }) : this._focus.apply(this, arguments) }, scrollParent: function () {
            var a; a = c.browser.msie && /(static|relative)/.test(this.css("position")) || /absolute/.test(this.css("position")) ? this.parents().filter(function () {
                return /(relative|absolute|fixed)/.test(c.curCSS(this,
"position", 1)) && /(auto|scroll)/.test(c.curCSS(this, "overflow", 1) + c.curCSS(this, "overflow-y", 1) + c.curCSS(this, "overflow-x", 1))
            }).eq(0) : this.parents().filter(function () { return /(auto|scroll)/.test(c.curCSS(this, "overflow", 1) + c.curCSS(this, "overflow-y", 1) + c.curCSS(this, "overflow-x", 1)) }).eq(0); return /fixed/.test(this.css("position")) || !a.length ? c(document) : a
        }, zIndex: function (a) {
            if (a !== j) return this.css("zIndex", a); if (this.length) {
                a = c(this[0]); for (var b; a.length && a[0] !== document; ) {
                    b = a.css("position");
                    if (b === "absolute" || b === "relative" || b === "fixed") { b = parseInt(a.css("zIndex"), 10); if (!isNaN(b) && b !== 0) return b } a = a.parent()
                }
            } return 0
        }, disableSelection: function () { return this.bind((c.support.selectstart ? "selectstart" : "mousedown") + ".ui-disableSelection", function (a) { a.preventDefault() }) }, enableSelection: function () { return this.unbind(".ui-disableSelection") }
        }); c.each(["Width", "Height"], function (a, b) {
            function d(f, g, l, m) {
                c.each(e, function () {
                    g -= parseFloat(c.curCSS(f, "padding" + this, true)) || 0; if (l) g -= parseFloat(c.curCSS(f,
"border" + this + "Width", true)) || 0; if (m) g -= parseFloat(c.curCSS(f, "margin" + this, true)) || 0
                }); return g
            } var e = b === "Width" ? ["Left", "Right"] : ["Top", "Bottom"], h = b.toLowerCase(), i = { innerWidth: c.fn.innerWidth, innerHeight: c.fn.innerHeight, outerWidth: c.fn.outerWidth, outerHeight: c.fn.outerHeight }; c.fn["inner" + b] = function (f) { if (f === j) return i["inner" + b].call(this); return this.each(function () { c(this).css(h, d(this, f) + "px") }) }; c.fn["outer" + b] = function (f, g) {
                if (typeof f !== "number") return i["outer" + b].call(this, f); return this.each(function () {
                    c(this).css(h,
d(this, f, true, g) + "px")
                })
            }
        }); c.extend(c.expr[":"], { data: function (a, b, d) { return !!c.data(a, d[3]) }, focusable: function (a) { var b = a.nodeName.toLowerCase(), d = c.attr(a, "tabindex"); if ("area" === b) { b = a.parentNode; d = b.name; if (!a.href || !d || b.nodeName.toLowerCase() !== "map") return false; a = c("img[usemap=#" + d + "]")[0]; return !!a && k(a) } return (/input|select|textarea|button|object/.test(b) ? !a.disabled : "a" == b ? a.href || !isNaN(d) : !isNaN(d)) && k(a) }, tabbable: function (a) { var b = c.attr(a, "tabindex"); return (isNaN(b) || b >= 0) && c(a).is(":focusable") } });
        c(function () { var a = document.body, b = a.appendChild(b = document.createElement("div")); c.extend(b.style, { minHeight: "100px", height: "auto", padding: 0, borderWidth: 0 }); c.support.minHeight = b.offsetHeight === 100; c.support.selectstart = "onselectstart" in b; a.removeChild(b).style.display = "none" }); c.extend(c.ui, { plugin: { add: function (a, b, d) { a = c.ui[a].prototype; for (var e in d) { a.plugins[e] = a.plugins[e] || []; a.plugins[e].push([b, d[e]]) } }, call: function (a, b, d) {
            if ((b = a.plugins[b]) && a.element[0].parentNode) for (var e = 0; e < b.length; e++) a.options[b[e][0]] &&
b[e][1].apply(a.element, d)
        }
        }, contains: function (a, b) { return document.compareDocumentPosition ? a.compareDocumentPosition(b) & 16 : a !== b && a.contains(b) }, hasScroll: function (a, b) { if (c(a).css("overflow") === "hidden") return false; b = b && b === "left" ? "scrollLeft" : "scrollTop"; var d = false; if (a[b] > 0) return true; a[b] = 1; d = a[b] > 0; a[b] = 0; return d }, isOverAxis: function (a, b, d) { return a > b && a < b + d }, isOver: function (a, b, d, e, h, i) { return c.ui.isOverAxis(a, d, h) && c.ui.isOverAxis(b, e, i) }
        })
    }
})(jQuery);
; /*!
 * jQuery UI Widget 1.8.9
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Widget
 */
(function (b, j) {
    if (b.cleanData) { var k = b.cleanData; b.cleanData = function (a) { for (var c = 0, d; (d = a[c]) != null; c++) b(d).triggerHandler("remove"); k(a) } } else { var l = b.fn.remove; b.fn.remove = function (a, c) { return this.each(function () { if (!c) if (!a || b.filter(a, [this]).length) b("*", this).add([this]).each(function () { b(this).triggerHandler("remove") }); return l.call(b(this), a, c) }) } } b.widget = function (a, c, d) {
        var e = a.split(".")[0], f; a = a.split(".")[1]; f = e + "-" + a; if (!d) { d = c; c = b.Widget } b.expr[":"][f] = function (h) {
            return !!b.data(h,
a)
        }; b[e] = b[e] || {}; b[e][a] = function (h, g) { arguments.length && this._createWidget(h, g) }; c = new c; c.options = b.extend(true, {}, c.options); b[e][a].prototype = b.extend(true, c, { namespace: e, widgetName: a, widgetEventPrefix: b[e][a].prototype.widgetEventPrefix || a, widgetBaseClass: f }, d); b.widget.bridge(a, b[e][a])
    }; b.widget.bridge = function (a, c) {
        b.fn[a] = function (d) {
            var e = typeof d === "string", f = Array.prototype.slice.call(arguments, 1), h = this; d = !e && f.length ? b.extend.apply(null, [true, d].concat(f)) : d; if (e && d.charAt(0) === "_") return h;
            e ? this.each(function () { var g = b.data(this, a), i = g && b.isFunction(g[d]) ? g[d].apply(g, f) : g; if (i !== g && i !== j) { h = i; return false } }) : this.each(function () { var g = b.data(this, a); g ? g.option(d || {})._init() : b.data(this, a, new c(d, this)) }); return h
        }
    }; b.Widget = function (a, c) { arguments.length && this._createWidget(a, c) }; b.Widget.prototype = { widgetName: "widget", widgetEventPrefix: "", options: { disabled: false }, _createWidget: function (a, c) {
        b.data(c, this.widgetName, this); this.element = b(c); this.options = b.extend(true, {}, this.options,
this._getCreateOptions(), a); var d = this; this.element.bind("remove." + this.widgetName, function () { d.destroy() }); this._create(); this._trigger("create"); this._init()
    }, _getCreateOptions: function () { return b.metadata && b.metadata.get(this.element[0])[this.widgetName] }, _create: function () { }, _init: function () { }, destroy: function () { this.element.unbind("." + this.widgetName).removeData(this.widgetName); this.widget().unbind("." + this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass + "-disabled ui-state-disabled") },
        widget: function () { return this.element }, option: function (a, c) { var d = a; if (arguments.length === 0) return b.extend({}, this.options); if (typeof a === "string") { if (c === j) return this.options[a]; d = {}; d[a] = c } this._setOptions(d); return this }, _setOptions: function (a) { var c = this; b.each(a, function (d, e) { c._setOption(d, e) }); return this }, _setOption: function (a, c) { this.options[a] = c; if (a === "disabled") this.widget()[c ? "addClass" : "removeClass"](this.widgetBaseClass + "-disabled ui-state-disabled").attr("aria-disabled", c); return this },
        enable: function () { return this._setOption("disabled", false) }, disable: function () { return this._setOption("disabled", true) }, _trigger: function (a, c, d) { var e = this.options[a]; c = b.Event(c); c.type = (a === this.widgetEventPrefix ? a : this.widgetEventPrefix + a).toLowerCase(); d = d || {}; if (c.originalEvent) { a = b.event.props.length; for (var f; a; ) { f = b.event.props[--a]; c[f] = c.originalEvent[f] } } this.element.trigger(c, d); return !(b.isFunction(e) && e.call(this.element[0], c, d) === false || c.isDefaultPrevented()) }
    }
})(jQuery);
; /*!
 * jQuery UI Mouse 1.8.9
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Mouse
 *
 * Depends:
 *	jquery.ui.widget.js
 */
(function (c) {
    c.widget("ui.mouse", { options: { cancel: ":input,option", distance: 1, delay: 0 }, _mouseInit: function () { var a = this; this.element.bind("mousedown." + this.widgetName, function (b) { return a._mouseDown(b) }).bind("click." + this.widgetName, function (b) { if (true === c.data(b.target, a.widgetName + ".preventClickEvent")) { c.removeData(b.target, a.widgetName + ".preventClickEvent"); b.stopImmediatePropagation(); return false } }); this.started = false }, _mouseDestroy: function () { this.element.unbind("." + this.widgetName) }, _mouseDown: function (a) {
        a.originalEvent =
a.originalEvent || {}; if (!a.originalEvent.mouseHandled) {
            this._mouseStarted && this._mouseUp(a); this._mouseDownEvent = a; var b = this, e = a.which == 1, f = typeof this.options.cancel == "string" ? c(a.target).parents().add(a.target).filter(this.options.cancel).length : false; if (!e || f || !this._mouseCapture(a)) return true; this.mouseDelayMet = !this.options.delay; if (!this.mouseDelayMet) this._mouseDelayTimer = setTimeout(function () { b.mouseDelayMet = true }, this.options.delay); if (this._mouseDistanceMet(a) && this._mouseDelayMet(a)) {
                this._mouseStarted =
this._mouseStart(a) !== false; if (!this._mouseStarted) { a.preventDefault(); return true }
            } this._mouseMoveDelegate = function (d) { return b._mouseMove(d) }; this._mouseUpDelegate = function (d) { return b._mouseUp(d) }; c(document).bind("mousemove." + this.widgetName, this._mouseMoveDelegate).bind("mouseup." + this.widgetName, this._mouseUpDelegate); a.preventDefault(); return a.originalEvent.mouseHandled = true
        }
    }, _mouseMove: function (a) {
        if (c.browser.msie && !(document.documentMode >= 9) && !a.button) return this._mouseUp(a); if (this._mouseStarted) {
            this._mouseDrag(a);
            return a.preventDefault()
        } if (this._mouseDistanceMet(a) && this._mouseDelayMet(a)) (this._mouseStarted = this._mouseStart(this._mouseDownEvent, a) !== false) ? this._mouseDrag(a) : this._mouseUp(a); return !this._mouseStarted
    }, _mouseUp: function (a) {
        c(document).unbind("mousemove." + this.widgetName, this._mouseMoveDelegate).unbind("mouseup." + this.widgetName, this._mouseUpDelegate); if (this._mouseStarted) {
            this._mouseStarted = false; a.target == this._mouseDownEvent.target && c.data(a.target, this.widgetName + ".preventClickEvent",
true); this._mouseStop(a)
        } return false
    }, _mouseDistanceMet: function (a) { return Math.max(Math.abs(this._mouseDownEvent.pageX - a.pageX), Math.abs(this._mouseDownEvent.pageY - a.pageY)) >= this.options.distance }, _mouseDelayMet: function () { return this.mouseDelayMet }, _mouseStart: function () { }, _mouseDrag: function () { }, _mouseStop: function () { }, _mouseCapture: function () { return true }
    })
})(jQuery);
; /*
 * jQuery UI Position 1.8.9
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Position
 */
(function (c) {
    c.ui = c.ui || {}; var n = /left|center|right/, o = /top|center|bottom/, t = c.fn.position, u = c.fn.offset; c.fn.position = function (b) {
        if (!b || !b.of) return t.apply(this, arguments); b = c.extend({}, b); var a = c(b.of), d = a[0], g = (b.collision || "flip").split(" "), e = b.offset ? b.offset.split(" ") : [0, 0], h, k, j; if (d.nodeType === 9) { h = a.width(); k = a.height(); j = { top: 0, left: 0} } else if (d.setTimeout) { h = a.width(); k = a.height(); j = { top: a.scrollTop(), left: a.scrollLeft()} } else if (d.preventDefault) {
            b.at = "left top"; h = k = 0; j = { top: b.of.pageY,
                left: b.of.pageX
            }
        } else { h = a.outerWidth(); k = a.outerHeight(); j = a.offset() } c.each(["my", "at"], function () { var f = (b[this] || "").split(" "); if (f.length === 1) f = n.test(f[0]) ? f.concat(["center"]) : o.test(f[0]) ? ["center"].concat(f) : ["center", "center"]; f[0] = n.test(f[0]) ? f[0] : "center"; f[1] = o.test(f[1]) ? f[1] : "center"; b[this] = f }); if (g.length === 1) g[1] = g[0]; e[0] = parseInt(e[0], 10) || 0; if (e.length === 1) e[1] = e[0]; e[1] = parseInt(e[1], 10) || 0; if (b.at[0] === "right") j.left += h; else if (b.at[0] === "center") j.left += h / 2; if (b.at[1] === "bottom") j.top +=
k; else if (b.at[1] === "center") j.top += k / 2; j.left += e[0]; j.top += e[1]; return this.each(function () {
    var f = c(this), l = f.outerWidth(), m = f.outerHeight(), p = parseInt(c.curCSS(this, "marginLeft", true)) || 0, q = parseInt(c.curCSS(this, "marginTop", true)) || 0, v = l + p + (parseInt(c.curCSS(this, "marginRight", true)) || 0), w = m + q + (parseInt(c.curCSS(this, "marginBottom", true)) || 0), i = c.extend({}, j), r; if (b.my[0] === "right") i.left -= l; else if (b.my[0] === "center") i.left -= l / 2; if (b.my[1] === "bottom") i.top -= m; else if (b.my[1] === "center") i.top -=
m / 2; i.left = Math.round(i.left); i.top = Math.round(i.top); r = { left: i.left - p, top: i.top - q }; c.each(["left", "top"], function (s, x) { c.ui.position[g[s]] && c.ui.position[g[s]][x](i, { targetWidth: h, targetHeight: k, elemWidth: l, elemHeight: m, collisionPosition: r, collisionWidth: v, collisionHeight: w, offset: e, my: b.my, at: b.at }) }); c.fn.bgiframe && f.bgiframe(); f.offset(c.extend(i, { using: b.using }))
})
    }; c.ui.position = { fit: { left: function (b, a) {
        var d = c(window); d = a.collisionPosition.left + a.collisionWidth - d.width() - d.scrollLeft(); b.left =
d > 0 ? b.left - d : Math.max(b.left - a.collisionPosition.left, b.left)
    }, top: function (b, a) { var d = c(window); d = a.collisionPosition.top + a.collisionHeight - d.height() - d.scrollTop(); b.top = d > 0 ? b.top - d : Math.max(b.top - a.collisionPosition.top, b.top) }
    }, flip: { left: function (b, a) {
        if (a.at[0] !== "center") {
            var d = c(window); d = a.collisionPosition.left + a.collisionWidth - d.width() - d.scrollLeft(); var g = a.my[0] === "left" ? -a.elemWidth : a.my[0] === "right" ? a.elemWidth : 0, e = a.at[0] === "left" ? a.targetWidth : -a.targetWidth, h = -2 * a.offset[0]; b.left +=
a.collisionPosition.left < 0 ? g + e + h : d > 0 ? g + e + h : 0
        }
    }, top: function (b, a) { if (a.at[1] !== "center") { var d = c(window); d = a.collisionPosition.top + a.collisionHeight - d.height() - d.scrollTop(); var g = a.my[1] === "top" ? -a.elemHeight : a.my[1] === "bottom" ? a.elemHeight : 0, e = a.at[1] === "top" ? a.targetHeight : -a.targetHeight, h = -2 * a.offset[1]; b.top += a.collisionPosition.top < 0 ? g + e + h : d > 0 ? g + e + h : 0 } }
    }
    }; if (!c.offset.setOffset) {
        c.offset.setOffset = function (b, a) {
            if (/static/.test(c.curCSS(b, "position"))) b.style.position = "relative"; var d = c(b),
g = d.offset(), e = parseInt(c.curCSS(b, "top", true), 10) || 0, h = parseInt(c.curCSS(b, "left", true), 10) || 0; g = { top: a.top - g.top + e, left: a.left - g.left + h }; "using" in a ? a.using.call(b, g) : d.css(g)
        }; c.fn.offset = function (b) { var a = this[0]; if (!a || !a.ownerDocument) return null; if (b) return this.each(function () { c.offset.setOffset(this, b) }); return u.call(this) }
    }
})(jQuery);
; /*
 * jQuery UI Button 1.8.9
 *
 * Copyright 2011, AUTHORS.txt (http://jqueryui.com/about)
 * Dual licensed under the MIT or GPL Version 2 licenses.
 * http://jquery.org/license
 *
 * http://docs.jquery.com/UI/Button
 *
 * Depends:
 *	jquery.ui.core.js
 *	jquery.ui.widget.js
 */
(function (a) {
    var g, i = function (b) { a(":ui-button", b.target.form).each(function () { var c = a(this).data("button"); setTimeout(function () { c.refresh() }, 1) }) }, h = function (b) { var c = b.name, d = b.form, e = a([]); if (c) e = d ? a(d).find("[name='" + c + "']") : a("[name='" + c + "']", b.ownerDocument).filter(function () { return !this.form }); return e }; a.widget("ui.button", { options: { disabled: null, text: true, label: null, icons: { primary: null, secondary: null} }, _create: function () {
        this.element.closest("form").unbind("reset.button").bind("reset.button",
i); if (typeof this.options.disabled !== "boolean") this.options.disabled = this.element.attr("disabled"); this._determineButtonType(); this.hasTitle = !!this.buttonElement.attr("title"); var b = this, c = this.options, d = this.type === "checkbox" || this.type === "radio", e = "ui-state-hover" + (!d ? " ui-state-active" : ""); if (c.label === null) c.label = this.buttonElement.html(); if (this.element.is(":disabled")) c.disabled = true; this.buttonElement.addClass("ui-button ui-widget ui-state-default ui-corner-all").attr("role", "button").bind("mouseenter.button",
function () { if (!c.disabled) { a(this).addClass("ui-state-hover"); this === g && a(this).addClass("ui-state-active") } }).bind("mouseleave.button", function () { c.disabled || a(this).removeClass(e) }).bind("focus.button", function () { a(this).addClass("ui-state-focus") }).bind("blur.button", function () { a(this).removeClass("ui-state-focus") }); d && this.element.bind("change.button", function () { b.refresh() }); if (this.type === "checkbox") this.buttonElement.bind("click.button", function () {
    if (c.disabled) return false; a(this).toggleClass("ui-state-active");
    b.buttonElement.attr("aria-pressed", b.element[0].checked)
}); else if (this.type === "radio") this.buttonElement.bind("click.button", function () { if (c.disabled) return false; a(this).addClass("ui-state-active"); b.buttonElement.attr("aria-pressed", true); var f = b.element[0]; h(f).not(f).map(function () { return a(this).button("widget")[0] }).removeClass("ui-state-active").attr("aria-pressed", false) }); else {
            this.buttonElement.bind("mousedown.button", function () {
                if (c.disabled) return false; a(this).addClass("ui-state-active");
                g = this; a(document).one("mouseup", function () { g = null })
            }).bind("mouseup.button", function () { if (c.disabled) return false; a(this).removeClass("ui-state-active") }).bind("keydown.button", function (f) { if (c.disabled) return false; if (f.keyCode == a.ui.keyCode.SPACE || f.keyCode == a.ui.keyCode.ENTER) a(this).addClass("ui-state-active") }).bind("keyup.button", function () { a(this).removeClass("ui-state-active") }); this.buttonElement.is("a") && this.buttonElement.keyup(function (f) { f.keyCode === a.ui.keyCode.SPACE && a(this).click() })
        } this._setOption("disabled",
c.disabled)
    }, _determineButtonType: function () {
        this.type = this.element.is(":checkbox") ? "checkbox" : this.element.is(":radio") ? "radio" : this.element.is("input") ? "input" : "button"; if (this.type === "checkbox" || this.type === "radio") { this.buttonElement = this.element.parents().last().find("label[for=" + this.element.attr("id") + "]"); this.element.addClass("ui-helper-hidden-accessible"); var b = this.element.is(":checked"); b && this.buttonElement.addClass("ui-state-active"); this.buttonElement.attr("aria-pressed", b) } else this.buttonElement =
this.element
    }, widget: function () { return this.buttonElement }, destroy: function () {
        this.element.removeClass("ui-helper-hidden-accessible"); this.buttonElement.removeClass("ui-button ui-widget ui-state-default ui-corner-all ui-state-hover ui-state-active  ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only").removeAttr("role").removeAttr("aria-pressed").html(this.buttonElement.find(".ui-button-text").html()); this.hasTitle ||
this.buttonElement.removeAttr("title"); a.Widget.prototype.destroy.call(this)
    }, _setOption: function (b, c) { a.Widget.prototype._setOption.apply(this, arguments); if (b === "disabled") c ? this.element.attr("disabled", true) : this.element.removeAttr("disabled"); this._resetButton() }, refresh: function () {
        var b = this.element.is(":disabled"); b !== this.options.disabled && this._setOption("disabled", b); if (this.type === "radio") h(this.element[0]).each(function () {
            a(this).is(":checked") ? a(this).button("widget").addClass("ui-state-active").attr("aria-pressed",
true) : a(this).button("widget").removeClass("ui-state-active").attr("aria-pressed", false)
        }); else if (this.type === "checkbox") this.element.is(":checked") ? this.buttonElement.addClass("ui-state-active").attr("aria-pressed", true) : this.buttonElement.removeClass("ui-state-active").attr("aria-pressed", false)
    }, _resetButton: function () {
        if (this.type === "input") this.options.label && this.element.val(this.options.label); else {
            var b = this.buttonElement.removeClass("ui-button-icons-only ui-button-icon-only ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary ui-button-text-only"),
c = a("<span></span>").addClass("ui-button-text").html(this.options.label).appendTo(b.empty()).text(), d = this.options.icons, e = d.primary && d.secondary; if (d.primary || d.secondary) {
                b.addClass("ui-button-text-icon" + (e ? "s" : d.primary ? "-primary" : "-secondary")); d.primary && b.prepend("<span class='ui-button-icon-primary ui-icon " + d.primary + "'></span>"); d.secondary && b.append("<span class='ui-button-icon-secondary ui-icon " + d.secondary + "'></span>"); if (!this.options.text) {
                    b.addClass(e ? "ui-button-icons-only" : "ui-button-icon-only").removeClass("ui-button-text-icons ui-button-text-icon-primary ui-button-text-icon-secondary");
                    this.hasTitle || b.attr("title", c)
                }
            } else b.addClass("ui-button-text-only")
        }
    }
    }); a.widget("ui.buttonset", { options: { items: ":button, :submit, :reset, :checkbox, :radio, a, :data(button)" }, _create: function () { this.element.addClass("ui-buttonset") }, _init: function () { this.refresh() }, _setOption: function (b, c) { b === "disabled" && this.buttons.button("option", b, c); a.Widget.prototype._setOption.apply(this, arguments) }, refresh: function () { this.buttons = this.element.find(this.options.items).filter(":ui-button").button("refresh").end().not(":ui-button").button().end().map(function () { return a(this).button("widget")[0] }).removeClass("ui-corner-all ui-corner-left ui-corner-right").filter(":first").addClass("ui-corner-left").end().filter(":last").addClass("ui-corner-right").end().end() },
        destroy: function () { this.element.removeClass("ui-buttonset"); this.buttons.map(function () { return a(this).button("widget")[0] }).removeClass("ui-corner-left ui-corner-right").end().button("destroy"); a.Widget.prototype.destroy.call(this) }
    })
})(jQuery);
;

// Click outside event / Bruno Silva / Buildium
(function ($) {
    $.fn.clickOutside = function (handler) {
        return this.each(function () {
            var elem = this;

            $(document).click(function (e) {
                var $parents = $(e.target).parents();

                var outside = e.target != elem;
                for (var i = 0; i < $parents.length; i++) {
                    if ($parents.get(i) == elem) {
                        outside = false;
                        break;
                    }
                }

                if (outside)
                    handler(e);

                return true;
            });
        });
    };
})(jQuery);


// Split button plugin / Bruno Silva / Buildium
// Options: matchWidth - resizes the menu to have the same width as the button
(function ($) {
    $.fn.splitButton = function (options) {

        var defaults = {
            matchWidth: true,
            hasDefaultAction: false
        };

        var options = $.extend(defaults, options);

        return this.each(function () {
            var $this = $(this);

            var $menu = $this.siblings('ul').remove();
            $this.wrap('<div class="splitButton" />').wrap('<span class="sbButtons" />');
            var $buttonsContainer = $this.parent();
            var $container = $buttonsContainer.parent();
            var $ddButton = $('<button>Click to open</button>');
            var $menuContainer = $menu.wrap('<div class="menu" />').parent();

            // reorganize elements
            // add extra button if there is a default action
            if (options.hasDefaultAction) {
                $this.button();
                $ddButton.button({
                    text: false,
                    icons: {
                        primary: "ui-icon-triangle-1-s"
                    }
                });
                $this.after($ddButton);
                $buttonsContainer.buttonset();
            } else {
                $this.addClass('ui-no-primary-icon').button({
                    icons: {
                        primary: "ui-icon-null",
                        secondary: "ui-icon-triangle-1-s"
                    }
                });
            }

            $container.append($menuContainer);

            // add handlers
            var $ddButtons = options.hasDefaultAction ? $ddButton : $buttonsContainer.children('button');
            $ddButtons.click(function () {
                if (options.matchWidth)
                    $menuContainer.width($this.parent().find('button').outerWidth() - 2);

                // scroll to menu if necessary
                var windowHeight = $(window).height();
                var docViewTop = $(window).scrollTop();
                var docViewBottom = docViewTop + windowHeight;

                var visibleViewBottom = $this.offset().top + $this.height() + $menuContainer.height();
                if (docViewBottom < visibleViewBottom)
                    $('html,body').animate({ scrollTop: 10 + visibleViewBottom - windowHeight }, 'fast');
                // end scroll

                $menuContainer.slideToggle('fast');

                $menuContainer.clickOutside(function () {
                    $menuContainer.slideUp('fast');
                });

                return false;
            });
        });
    };
})(jQuery);

/*
* jQuery Cycle Lite Plugin
* http://malsup.com/jquery/cycle/lite/
* Copyright (c) 2008 M. Alsup
* Version: 1.0 (06/08/2008)
* Dual licensed under the MIT and GPL licenses:
* http://www.opensource.org/licenses/mit-license.php
* http://www.gnu.org/licenses/gpl.html
* Requires: jQuery v1.2.3 or later
*/
; (function ($) {

    var ver = 'Lite-1.0';

    $.fn.cycle = function (options) {
        return this.each(function () {
            options = options || {};

            if (this.cycleTimeout) clearTimeout(this.cycleTimeout);
            this.cycleTimeout = 0;
            this.cyclePause = 0;

            var $cont = $(this);
            var $slides = options.slideExpr ? $(options.slideExpr, this) : $cont.children();
            var els = $slides.get();
            if (els.length < 2) {
                if (window.console && window.console.log)
                    window.console.log('terminating; too few slides: ' + els.length);
                return; // don't bother
            }

            // support metadata plugin (v1.0 and v2.0)
            var opts = $.extend({}, $.fn.cycle.defaults, options || {}, $.metadata ? $cont.metadata() : $.meta ? $cont.data() : {});

            opts.before = opts.before ? [opts.before] : [];
            opts.after = opts.after ? [opts.after] : [];
            opts.after.unshift(function () { opts.busy = 0; });

            // allow shorthand overrides of width, height and timeout
            var cls = this.className;
            opts.width = parseInt((cls.match(/w:(\d+)/) || [])[1]) || opts.width;
            opts.height = parseInt((cls.match(/h:(\d+)/) || [])[1]) || opts.height;
            opts.timeout = parseInt((cls.match(/t:(\d+)/) || [])[1]) || opts.timeout;

            if ($cont.css('position') == 'static')
                $cont.css('position', 'relative');
            if (opts.width)
                $cont.width(opts.width);
            if (opts.height && opts.height != 'auto')
                $cont.height(opts.height);

            var first = 0;
            $slides.css({ position: 'absolute', top: 0, left: 0 }).hide().each(function (i) {
                $(this).css('z-index', els.length - i)
            });

            $(els[first]).css('opacity', 1).show(); // opacity bit needed to handle reinit case
            if ($.browser.msie) els[first].style.removeAttribute('filter');

            if (opts.fit && opts.width)
                $slides.width(opts.width);
            if (opts.fit && opts.height && opts.height != 'auto')
                $slides.height(opts.height);
            if (opts.pause)
                $cont.hover(function () { this.cyclePause = 1; }, function () { this.cyclePause = 0; });

            $.fn.cycle.transitions.fade($cont, $slides, opts);

            $slides.each(function () {
                var $el = $(this);
                this.cycleH = (opts.fit && opts.height) ? opts.height : $el.height();
                this.cycleW = (opts.fit && opts.width) ? opts.width : $el.width();
            });

            $slides.not(':eq(' + first + ')').css({ opacity: 0 });
            if (opts.cssFirst)
                $($slides[first]).css(opts.cssFirst);

            if (opts.timeout) {
                // ensure that timeout and speed settings are sane
                if (opts.speed.constructor == String)
                    opts.speed = { slow: 600, fast: 200}[opts.speed] || 400;
                if (!opts.sync)
                    opts.speed = opts.speed / 2;
                while ((opts.timeout - opts.speed) < 250)
                    opts.timeout += opts.speed;
            }
            opts.speedIn = opts.speed;
            opts.speedOut = opts.speed;

            opts.slideCount = els.length;
            opts.currSlide = first;
            opts.nextSlide = 1;

            // fire artificial events
            var e0 = $slides[first];
            if (opts.before.length)
                opts.before[0].apply(e0, [e0, e0, opts, true]);
            if (opts.after.length > 1)
                opts.after[1].apply(e0, [e0, e0, opts, true]);

            if (opts.click && !opts.next)
                opts.next = opts.click;
            if (opts.next)
                $(opts.next).bind('click', function () { return advance(els, opts, opts.rev ? -1 : 1) });
            if (opts.prev)
                $(opts.prev).bind('click', function () { return advance(els, opts, opts.rev ? 1 : -1) });

            if (opts.timeout)
                this.cycleTimeout = setTimeout(function () {
                    go(els, opts, 0, !opts.rev)
                }, opts.timeout + (opts.delay || 0));
        });
    };

    function go(els, opts, manual, fwd) {
        if (opts.busy) return;
        var p = els[0].parentNode, curr = els[opts.currSlide], next = els[opts.nextSlide];
        if (p.cycleTimeout === 0 && !manual)
            return;

        if (manual || !p.cyclePause) {
            if (opts.before.length)
                $.each(opts.before, function (i, o) { o.apply(next, [curr, next, opts, fwd]); });
            var after = function () {
                if ($.browser.msie)
                    this.style.removeAttribute('filter');
                $.each(opts.after, function (i, o) { o.apply(next, [curr, next, opts, fwd]); });
            };

            if (opts.nextSlide != opts.currSlide) {
                opts.busy = 1;
                $.fn.cycle.custom(curr, next, opts, after);
            }
            var roll = (opts.nextSlide + 1) == els.length;
            opts.nextSlide = roll ? 0 : opts.nextSlide + 1;
            opts.currSlide = roll ? els.length - 1 : opts.nextSlide - 1;
        }
        if (opts.timeout)
            p.cycleTimeout = setTimeout(function () { go(els, opts, 0, !opts.rev) }, opts.timeout);
    };

    // advance slide forward or back
    function advance(els, opts, val) {
        var p = els[0].parentNode, timeout = p.cycleTimeout;
        if (timeout) {
            clearTimeout(timeout);
            p.cycleTimeout = 0;
        }
        opts.nextSlide = opts.currSlide + val;
        if (opts.nextSlide < 0) {
            opts.nextSlide = els.length - 1;
        }
        else if (opts.nextSlide >= els.length) {
            opts.nextSlide = 0;
        }
        go(els, opts, 1, val >= 0);
        return false;
    };

    $.fn.cycle.custom = function (curr, next, opts, cb) {
        var $l = $(curr), $n = $(next);
        $n.css({ opacity: 0 });
        var fn = function () { $n.animate({ opacity: 1 }, opts.speedIn, opts.easeIn, cb) };
        $l.animate({ opacity: 0 }, opts.speedOut, opts.easeOut, function () {
            $l.css({ display: 'none' });
            if (!opts.sync) fn();
        });
        if (opts.sync) fn();
    };

    $.fn.cycle.transitions = {
        fade: function ($cont, $slides, opts) {
            $slides.not(':eq(0)').css('opacity', 0);
            opts.before.push(function () { $(this).show() });
        }
    };

    $.fn.cycle.ver = function () { return ver; };

    // @see: http://malsup.com/jquery/cycle/lite/
    $.fn.cycle.defaults = {
        timeout: 4000,
        speed: 1000,
        next: null,
        prev: null,
        before: null,
        after: null,
        height: 'auto',
        sync: 1,
        fit: 0,
        pause: 0,
        delay: 0,
        slideExpr: null
    };

})(jQuery);

// Editable text / Bruno Silva / Buildium
// Usage: $(selector).editableText(showInputIfEmpty, handler)
//     * showInputIfEmpty - just show input box if the initial value is an empty string
//     * handler - optional JS function with the following signature: function handler([dom input element]);
(function ($) {
    $.fn.editableText = function (showInputIfEmpty, handler) {
        return this.each(function () {
            var elem = this;
            var $elem = $(this);

            if ($elem.val().trim() == '' && showInputIfEmpty) {
                $(this).show();
                return;
            }

            var $text = $('<span class="inlineEditText">' + $elem.val() + '</span>');
            var $editArea = $('<div class="inlineEditArea" style="display: none"></div>');
            var $editLink = $('<a href="#" class="inlineEditLink">Edit</a>');
            var $saveLink = $('<a href="#" class="inlineEditSaveLink">Save</a>');
            var $cancelLink = $('<a href="#" class="inlineEditCancelLink">Cancel</a>');

            var enterReadMode = function () {
                $text.hide();
                $editLink.hide();
                $elem.show();
                $editArea.show();

                return false;
            };

            var enterWriteMode = function () {
                $elem.hide();
                $editArea.hide();
                $text.show();
                $editLink.show();

                return false;
            };

            $(this).before($text).before($editLink).after($editArea).hide();
            $editArea.append($saveLink).append(' | ').append($cancelLink);

            $editLink.click(enterReadMode);
            $cancelLink.click(function () {
                $elem.val($text.html());
                return enterWriteMode();
            });
            $saveLink.click(function () {
                var success = true;
                if (typeof (handler) != 'undefined') {
                    success = handler(elem);
                }

                if (success != false) {
                    $text.html($elem.val());
                    enterWriteMode();
                }

                return false;
            });
        });
    };
})(jQuery);


/*!
* jQuery Templates Plugin 1.0.0pre
* http://github.com/jquery/jquery-tmpl
* Requires jQuery 1.4.2
*
* Copyright Software Freedom Conservancy, Inc.
* Dual licensed under the MIT or GPL Version 2 licenses.
* http://jquery.org/license
*/
(function (jQuery, undefined) {
    var oldManip = jQuery.fn.domManip, tmplItmAtt = "_tmplitem", htmlExpr = /^[^<]*(<[\w\W]+>)[^>]*$|\{\{\! /,
		newTmplItems = {}, wrappedItems = {}, appendToTmplItems, topTmplItem = { key: 0, data: {} }, itemKey = 0, cloneIndex = 0, stack = [];

    function newTmplItem(options, parentItem, fn, data) {
        // Returns a template item data structure for a new rendered instance of a template (a 'template item').
        // The content field is a hierarchical array of strings and nested items (to be
        // removed and replaced by nodes field of dom elements, once inserted in DOM).
        var newItem = {
            data: data || (parentItem ? parentItem.data : {}),
            _wrap: parentItem ? parentItem._wrap : null,
            tmpl: null,
            parent: parentItem || null,
            nodes: [],
            calls: tiCalls,
            nest: tiNest,
            wrap: tiWrap,
            html: tiHtml,
            update: tiUpdate
        };
        if (options) {
            jQuery.extend(newItem, options, { nodes: [], parent: parentItem });
        }
        if (fn) {
            // Build the hierarchical content to be used during insertion into DOM
            newItem.tmpl = fn;
            newItem._ctnt = newItem._ctnt || newItem.tmpl(jQuery, newItem);
            newItem.key = ++itemKey;
            // Keep track of new template item, until it is stored as jQuery Data on DOM element
            (stack.length ? wrappedItems : newTmplItems)[itemKey] = newItem;
        }
        return newItem;
    }

    // Override appendTo etc., in order to provide support for targeting multiple elements. (This code would disappear if integrated in jquery core).
    jQuery.each({
        appendTo: "append",
        prependTo: "prepend",
        insertBefore: "before",
        insertAfter: "after",
        replaceAll: "replaceWith"
    }, function (name, original) {
        jQuery.fn[name] = function (selector) {
            var ret = [], insert = jQuery(selector), elems, i, l, tmplItems,
				parent = this.length === 1 && this[0].parentNode;

            appendToTmplItems = newTmplItems || {};
            if (parent && parent.nodeType === 11 && parent.childNodes.length === 1 && insert.length === 1) {
                insert[original](this[0]);
                ret = this;
            } else {
                for (i = 0, l = insert.length; i < l; i++) {
                    cloneIndex = i;
                    elems = (i > 0 ? this.clone(true) : this).get();
                    jQuery(insert[i])[original](elems);
                    ret = ret.concat(elems);
                }
                cloneIndex = 0;
                ret = this.pushStack(ret, name, insert.selector);
            }
            tmplItems = appendToTmplItems;
            appendToTmplItems = null;
            jQuery.tmpl.complete(tmplItems);
            return ret;
        };
    });

    jQuery.fn.extend({
        // Use first wrapped element as template markup.
        // Return wrapped set of template items, obtained by rendering template against data.
        tmpl: function (data, options, parentItem) {
            return jQuery.tmpl(this[0], data, options, parentItem);
        },

        // Find which rendered template item the first wrapped DOM element belongs to
        tmplItem: function () {
            return jQuery.tmplItem(this[0]);
        },

        // Consider the first wrapped element as a template declaration, and get the compiled template or store it as a named template.
        template: function (name) {
            return jQuery.template(name, this[0]);
        },

        domManip: function (args, table, callback, options) {
            if (args[0] && jQuery.isArray(args[0])) {
                var dmArgs = jQuery.makeArray(arguments), elems = args[0], elemsLength = elems.length, i = 0, tmplItem;
                while (i < elemsLength && !(tmplItem = jQuery.data(elems[i++], "tmplItem"))) { }
                if (tmplItem && cloneIndex) {
                    dmArgs[2] = function (fragClone) {
                        // Handler called by oldManip when rendered template has been inserted into DOM.
                        jQuery.tmpl.afterManip(this, fragClone, callback);
                    };
                }
                oldManip.apply(this, dmArgs);
            } else {
                oldManip.apply(this, arguments);
            }
            cloneIndex = 0;
            if (!appendToTmplItems) {
                jQuery.tmpl.complete(newTmplItems);
            }
            return this;
        }
    });

    jQuery.extend({
        // Return wrapped set of template items, obtained by rendering template against data.
        tmpl: function (tmpl, data, options, parentItem) {
            var ret, topLevel = !parentItem;
            if (topLevel) {
                // This is a top-level tmpl call (not from a nested template using {{tmpl}})
                parentItem = topTmplItem;
                tmpl = jQuery.template[tmpl] || jQuery.template(null, tmpl);
                wrappedItems = {}; // Any wrapped items will be rebuilt, since this is top level
            } else if (!tmpl) {
                // The template item is already associated with DOM - this is a refresh.
                // Re-evaluate rendered template for the parentItem
                tmpl = parentItem.tmpl;
                newTmplItems[parentItem.key] = parentItem;
                parentItem.nodes = [];
                if (parentItem.wrapped) {
                    updateWrapped(parentItem, parentItem.wrapped);
                }
                // Rebuild, without creating a new template item
                return jQuery(build(parentItem, null, parentItem.tmpl(jQuery, parentItem)));
            }
            if (!tmpl) {
                return []; // Could throw...
            }
            if (typeof data === "function") {
                data = data.call(parentItem || {});
            }
            if (options && options.wrapped) {
                updateWrapped(options, options.wrapped);
            }
            ret = jQuery.isArray(data) ?
				jQuery.map(data, function (dataItem) {
				    return dataItem ? newTmplItem(options, parentItem, tmpl, dataItem) : null;
				}) :
				[newTmplItem(options, parentItem, tmpl, data)];
            return topLevel ? jQuery(build(parentItem, null, ret)) : ret;
        },

        // Return rendered template item for an element.
        tmplItem: function (elem) {
            var tmplItem;
            if (elem instanceof jQuery) {
                elem = elem[0];
            }
            while (elem && elem.nodeType === 1 && !(tmplItem = jQuery.data(elem, "tmplItem")) && (elem = elem.parentNode)) { }
            return tmplItem || topTmplItem;
        },

        // Set:
        // Use $.template( name, tmpl ) to cache a named template,
        // where tmpl is a template string, a script element or a jQuery instance wrapping a script element, etc.
        // Use $( "selector" ).template( name ) to provide access by name to a script block template declaration.

        // Get:
        // Use $.template( name ) to access a cached template.
        // Also $( selectorToScriptBlock ).template(), or $.template( null, templateString )
        // will return the compiled template, without adding a name reference.
        // If templateString includes at least one HTML tag, $.template( templateString ) is equivalent
        // to $.template( null, templateString )
        template: function (name, tmpl) {
            if (tmpl) {
                // Compile template and associate with name
                if (typeof tmpl === "string") {
                    // This is an HTML string being passed directly in.
                    tmpl = buildTmplFn(tmpl)
                } else if (tmpl instanceof jQuery) {
                    tmpl = tmpl[0] || {};
                }
                if (tmpl.nodeType) {
                    // If this is a template block, use cached copy, or generate tmpl function and cache.
                    tmpl = jQuery.data(tmpl, "tmpl") || jQuery.data(tmpl, "tmpl", buildTmplFn(tmpl.innerHTML));
                    // Issue: In IE, if the container element is not a script block, the innerHTML will remove quotes from attribute values whenever the value does not include white space. 
                    // This means that foo="${x}" will not work if the value of x includes white space: foo="${x}" -> foo=value of x. 
                    // To correct this, include space in tag: foo="${ x }" -> foo="value of x"
                }
                return typeof name === "string" ? (jQuery.template[name] = tmpl) : tmpl;
            }
            // Return named compiled template
            return name ? (typeof name !== "string" ? jQuery.template(null, name) :
				(jQuery.template[name] ||
            // If not in map, treat as a selector. (If integrated with core, use quickExpr.exec) 
					jQuery.template(null, htmlExpr.test(name) ? name : jQuery(name)))) : null;
        },

        encode: function (text) {
            // Do HTML encoding replacing < > & and ' and " by corresponding entities.
            return ("" + text).split("<").join("&lt;").split(">").join("&gt;").split('"').join("&#34;").split("'").join("&#39;");
        }
    });

    jQuery.extend(jQuery.tmpl, {
        tag: {
            "tmpl": {
                _default: { $2: "null" },
                open: "if($notnull_1){_=_.concat($item.nest($1,$2));}"
                // tmpl target parameter can be of type function, so use $1, not $1a (so not auto detection of functions)
                // This means that {{tmpl foo}} treats foo as a template (which IS a function). 
                // Explicit parens can be used if foo is a function that returns a template: {{tmpl foo()}}.
            },
            "wrap": {
                _default: { $2: "null" },
                open: "$item.calls(_,$1,$2);_=[];",
                close: "call=$item.calls();_=call._.concat($item.wrap(call,_));"
            },
            "each": {
                _default: { $2: "$index, $value" },
                open: "if($notnull_1){$.each($1a,function($2){with(this){",
                close: "}});}"
            },
            "if": {
                open: "if(($notnull_1) && $1a){",
                close: "}"
            },
            "else": {
                _default: { $1: "true" },
                open: "}else if(($notnull_1) && $1a){"
            },
            "html": {
                // Unecoded expression evaluation. 
                open: "if($notnull_1){_.push($1a);}"
            },
            "=": {
                // Encoded expression evaluation. Abbreviated form is ${}.
                _default: { $1: "$data" },
                open: "if($notnull_1){_.push($.encode($1a));}"
            },
            "!": {
                // Comment tag. Skipped by parser
                open: ""
            }
        },

        // This stub can be overridden, e.g. in jquery.tmplPlus for providing rendered events
        complete: function (items) {
            newTmplItems = {};
        },

        // Call this from code which overrides domManip, or equivalent
        // Manage cloning/storing template items etc.
        afterManip: function afterManip(elem, fragClone, callback) {
            // Provides cloned fragment ready for fixup prior to and after insertion into DOM
            var content = fragClone.nodeType === 11 ?
				jQuery.makeArray(fragClone.childNodes) :
				fragClone.nodeType === 1 ? [fragClone] : [];

            // Return fragment to original caller (e.g. append) for DOM insertion
            callback.call(elem, fragClone);

            // Fragment has been inserted:- Add inserted nodes to tmplItem data structure. Replace inserted element annotations by jQuery.data.
            storeTmplItems(content);
            cloneIndex++;
        }
    });

    //========================== Private helper functions, used by code above ==========================

    function build(tmplItem, nested, content) {
        // Convert hierarchical content into flat string array 
        // and finally return array of fragments ready for DOM insertion
        var frag, ret = content ? jQuery.map(content, function (item) {
            return (typeof item === "string") ?
            // Insert template item annotations, to be converted to jQuery.data( "tmplItem" ) when elems are inserted into DOM.
				(tmplItem.key ? item.replace(/(<\w+)(?=[\s>])(?![^>]*_tmplitem)([^>]*)/g, "$1 " + tmplItmAtt + "=\"" + tmplItem.key + "\" $2") : item) :
            // This is a child template item. Build nested template.
				build(item, tmplItem, item._ctnt);
        }) :
        // If content is not defined, insert tmplItem directly. Not a template item. May be a string, or a string array, e.g. from {{html $item.html()}}. 
		tmplItem;
        if (nested) {
            return ret;
        }

        // top-level template
        ret = ret.join("");

        // Support templates which have initial or final text nodes, or consist only of text
        // Also support HTML entities within the HTML markup.
        ret.replace(/^\s*([^<\s][^<]*)?(<[\w\W]+>)([^>]*[^>\s])?\s*$/, function (all, before, middle, after) {
            frag = jQuery(middle).get();

            storeTmplItems(frag);
            if (before) {
                frag = unencode(before).concat(frag);
            }
            if (after) {
                frag = frag.concat(unencode(after));
            }
        });
        return frag ? frag : unencode(ret);
    }

    function unencode(text) {
        // Use createElement, since createTextNode will not render HTML entities correctly
        var el = document.createElement("div");
        el.innerHTML = text;
        return jQuery.makeArray(el.childNodes);
    }

    // Generate a reusable function that will serve to render a template against data
    function buildTmplFn(markup) {
        return new Function("jQuery", "$item",
			"var $=jQuery,call,_=[],$data=$item.data;" +

        // Introduce the data as local variables using with(){}
			"with($data){_.push('" +

        // Convert the template into pure JavaScript
			jQuery.trim(markup)
				.replace(/([\\'])/g, "\\$1")
				.replace(/[\r\t\n]/g, " ")
				.replace(/\$\{([^\}]*)\}/g, "{{= $1}}")
				.replace(/\{\{(\/?)(\w+|.)(?:\(((?:[^\}]|\}(?!\}))*?)?\))?(?:\s+(.*?)?)?(\(((?:[^\}]|\}(?!\}))*?)\))?\s*\}\}/g,
				function (all, slash, type, fnargs, target, parens, args) {
				    var tag = jQuery.tmpl.tag[type], def, expr, exprAutoFnDetect;
				    if (!tag) {
				        throw "Template command not found: " + type;
				    }
				    def = tag._default || [];
				    if (parens && !/\w$/.test(target)) {
				        target += parens;
				        parens = "";
				    }
				    if (target) {
				        target = unescape(target);
				        args = args ? ("," + unescape(args) + ")") : (parens ? ")" : "");
				        // Support for target being things like a.toLowerCase();
				        // In that case don't call with template item as 'this' pointer. Just evaluate...
				        expr = parens ? (target.indexOf(".") > -1 ? target + unescape(parens) : ("(" + target + ").call($item" + args)) : target;
				        exprAutoFnDetect = parens ? expr : "(typeof(" + target + ")==='function'?(" + target + ").call($item):(" + target + "))";
				    } else {
				        exprAutoFnDetect = expr = def.$1 || "null";
				    }
				    fnargs = unescape(fnargs);
				    return "');" +
						tag[slash ? "close" : "open"]
							.split("$notnull_1").join(target ? "typeof(" + target + ")!=='undefined' && (" + target + ")!=null" : "true")
							.split("$1a").join(exprAutoFnDetect)
							.split("$1").join(expr)
							.split("$2").join(fnargs || def.$2 || "") +
						"_.push('";
				}) +
			"');}return _;"
		);
    }
    function updateWrapped(options, wrapped) {
        // Build the wrapped content. 
        options._wrap = build(options, true,
        // Suport imperative scenario in which options.wrapped can be set to a selector or an HTML string.
			jQuery.isArray(wrapped) ? wrapped : [htmlExpr.test(wrapped) ? wrapped : jQuery(wrapped).html()]
		).join("");
    }

    function unescape(args) {
        return args ? args.replace(/\\'/g, "'").replace(/\\\\/g, "\\") : null;
    }
    function outerHtml(elem) {
        var div = document.createElement("div");
        div.appendChild(elem.cloneNode(true));
        return div.innerHTML;
    }

    // Store template items in jQuery.data(), ensuring a unique tmplItem data data structure for each rendered template instance.
    function storeTmplItems(content) {
        var keySuffix = "_" + cloneIndex, elem, elems, newClonedItems = {}, i, l, m;
        for (i = 0, l = content.length; i < l; i++) {
            if ((elem = content[i]).nodeType !== 1) {
                continue;
            }
            elems = elem.getElementsByTagName("*");
            for (m = elems.length - 1; m >= 0; m--) {
                processItemKey(elems[m]);
            }
            processItemKey(elem);
        }
        function processItemKey(el) {
            var pntKey, pntNode = el, pntItem, tmplItem, key;
            // Ensure that each rendered template inserted into the DOM has its own template item,
            if ((key = el.getAttribute(tmplItmAtt))) {
                while (pntNode.parentNode && (pntNode = pntNode.parentNode).nodeType === 1 && !(pntKey = pntNode.getAttribute(tmplItmAtt))) { }
                if (pntKey !== key) {
                    // The next ancestor with a _tmplitem expando is on a different key than this one.
                    // So this is a top-level element within this template item
                    // Set pntNode to the key of the parentNode, or to 0 if pntNode.parentNode is null, or pntNode is a fragment.
                    pntNode = pntNode.parentNode ? (pntNode.nodeType === 11 ? 0 : (pntNode.getAttribute(tmplItmAtt) || 0)) : 0;
                    if (!(tmplItem = newTmplItems[key])) {
                        // The item is for wrapped content, and was copied from the temporary parent wrappedItem.
                        tmplItem = wrappedItems[key];
                        tmplItem = newTmplItem(tmplItem, newTmplItems[pntNode] || wrappedItems[pntNode]);
                        tmplItem.key = ++itemKey;
                        newTmplItems[itemKey] = tmplItem;
                    }
                    if (cloneIndex) {
                        cloneTmplItem(key);
                    }
                }
                el.removeAttribute(tmplItmAtt);
            } else if (cloneIndex && (tmplItem = jQuery.data(el, "tmplItem"))) {
                // This was a rendered element, cloned during append or appendTo etc.
                // TmplItem stored in jQuery data has already been cloned in cloneCopyEvent. We must replace it with a fresh cloned tmplItem.
                cloneTmplItem(tmplItem.key);
                newTmplItems[tmplItem.key] = tmplItem;
                pntNode = jQuery.data(el.parentNode, "tmplItem");
                pntNode = pntNode ? pntNode.key : 0;
            }
            if (tmplItem) {
                pntItem = tmplItem;
                // Find the template item of the parent element. 
                // (Using !=, not !==, since pntItem.key is number, and pntNode may be a string)
                while (pntItem && pntItem.key != pntNode) {
                    // Add this element as a top-level node for this rendered template item, as well as for any
                    // ancestor items between this item and the item of its parent element
                    pntItem.nodes.push(el);
                    pntItem = pntItem.parent;
                }
                // Delete content built during rendering - reduce API surface area and memory use, and avoid exposing of stale data after rendering...
                delete tmplItem._ctnt;
                delete tmplItem._wrap;
                // Store template item as jQuery data on the element
                jQuery.data(el, "tmplItem", tmplItem);
            }
            function cloneTmplItem(key) {
                key = key + keySuffix;
                tmplItem = newClonedItems[key] =
					(newClonedItems[key] || newTmplItem(tmplItem, newTmplItems[tmplItem.parent.key + keySuffix] || tmplItem.parent));
            }
        }
    }

    //---- Helper functions for template item ----

    function tiCalls(content, tmpl, data, options) {
        if (!content) {
            return stack.pop();
        }
        stack.push({ _: content, tmpl: tmpl, item: this, data: data, options: options });
    }

    function tiNest(tmpl, data, options) {
        // nested template, using {{tmpl}} tag
        return jQuery.tmpl(jQuery.template(tmpl), data, options, this);
    }

    function tiWrap(call, wrapped) {
        // nested template, using {{wrap}} tag
        var options = call.options || {};
        options.wrapped = wrapped;
        // Apply the template, which may incorporate wrapped content, 
        return jQuery.tmpl(jQuery.template(call.tmpl), call.data, options, call.item);
    }

    function tiHtml(filter, textOnly) {
        var wrapped = this._wrap;
        return jQuery.map(
			jQuery(jQuery.isArray(wrapped) ? wrapped.join("") : wrapped).filter(filter || "*"),
			function (e) {
			    return textOnly ?
					e.innerText || e.textContent :
					e.outerHTML || outerHtml(e);
			});
    }

    function tiUpdate() {
        var coll = this.nodes;
        jQuery.tmpl(null, null, null, this).insertBefore(coll[0]);
        jQuery(coll).remove();
    }
})(jQuery);



/*
* jQuery Globalization plugin
* http://github.com/nje/jquery-glob
*/
(function ($) {

    var localized = { en: {} };
    localized["default"] = localized.en;

    $.extend({
        findClosestCulture: function (name) {
            var match;
            if (!name) {
                match = $.culture || $.cultures["default"];
            }
            else if ($.isPlainObject(name)) {
                match = name;
            }
            else {
                var cultures = $.cultures,
                list = $.isArray(name) ? name : [name],
                i, l = list.length;
                for (i = 0; i < l; i++) {
                    name = list[i];
                    match = cultures[name];
                    if (match) {
                        return match;
                    }
                }
                for (i = 0; i < l; i++) {
                    name = list[i];
                    do {
                        var index = name.lastIndexOf("-");
                        if (index === -1) {
                            break;
                        }
                        // strip off the last part. e.g. en-US => en
                        name = name.substr(0, index);
                        match = cultures[name];
                        if (match) {
                            return match;
                        }
                    }
                    while (1);
                }
            }
            return match || null;
        },
        preferCulture: function (name) {
            $.culture = $.findClosestCulture(name) || $.cultures["default"];
        },
        localize: function (key, culture, value) {
            if (typeof culture === 'string') {
                culture = culture || "default";
                culture = $.cultures[culture] || { name: culture };
            }
            var local = localized[culture.name];
            if (arguments.length === 3) {
                if (!local) {
                    local = localized[culture.name] = {};
                }
                local[key] = value;
            }
            else {
                if (local) {
                    value = local[key];
                }
                if (typeof value === 'undefined') {
                    var language = localized[culture.language];
                    if (language) {
                        value = language[key];
                    }
                    if (typeof value === 'undefined') {
                        value = localized["default"][key];
                    }
                }
            }
            return typeof value === "undefined" ? null : value;
        },
        format: function (value, format, culture) {
            culture = $.findClosestCulture(culture);
            if (typeof value === "number") {
                value = formatNumber(value, format, culture);
            }
            else if (value instanceof Date) {
                value = formatDate(value, format, culture);
            }
            return value;
        },
        parseInt: function (value, radix, culture) {
            return Math.floor($.parseFloat(value, radix, culture));
        },
        parseFloat: function (value, radix, culture) {
            culture = $.findClosestCulture(culture);
            var ret = NaN,
            nf = culture.numberFormat;

            // trim leading and trailing whitespace
            value = trim(value);

            // allow infinity or hexidecimal
            if (regexInfinity.test(value)) {
                ret = parseFloat(value, radix);
            }
            else if (!radix && regexHex.test(value)) {
                ret = parseInt(value, 16);
            }
            else {
                var signInfo = parseNegativePattern(value, nf, nf.pattern[0]),
                sign = signInfo[0],
                num = signInfo[1];
                // determine sign and number
                if (sign === "" && nf.pattern[0] !== "-n") {
                    signInfo = parseNegativePattern(value, nf, "-n");
                    sign = signInfo[0];
                    num = signInfo[1];
                }
                sign = sign || "+";
                // determine exponent and number
                var exponent,
                intAndFraction,
                exponentPos = num.indexOf('e');
                if (exponentPos < 0) exponentPos = num.indexOf('E');
                if (exponentPos < 0) {
                    intAndFraction = num;
                    exponent = null;
                }
                else {
                    intAndFraction = num.substr(0, exponentPos);
                    exponent = num.substr(exponentPos + 1);
                }
                // determine decimal position
                var integer,
                fraction,
                decSep = nf['.'],
                decimalPos = intAndFraction.indexOf(decSep);
                if (decimalPos < 0) {
                    integer = intAndFraction;
                    fraction = null;
                }
                else {
                    integer = intAndFraction.substr(0, decimalPos);
                    fraction = intAndFraction.substr(decimalPos + decSep.length);
                }
                // handle groups (e.g. 1,000,000)
                var groupSep = nf[","];
                integer = integer.split(groupSep).join('');
                var altGroupSep = groupSep.replace(/\u00A0/g, " ");
                if (groupSep !== altGroupSep) {
                    integer = integer.split(altGroupSep).join('');
                }
                // build a natively parsable number string
                var p = sign + integer;
                if (fraction !== null) {
                    p += '.' + fraction;
                }
                if (exponent !== null) {
                    // exponent itself may have a number patternd
                    var expSignInfo = parseNegativePattern(exponent, nf, "-n");
                    p += 'e' + (expSignInfo[0] || "+") + expSignInfo[1];
                }
                if (regexParseFloat.test(p)) {
                    ret = parseFloat(p);
                }
            }
            return ret;
        },
        parseDate: function (value, formats, culture) {
            culture = $.findClosestCulture(culture);

            var date;
            if (formats) {
                if (typeof formats === "string") {
                    formats = [formats];
                }
                if (formats.length) {
                    for (var i = 0, l = formats.length; i < l; i++) {
                        var format = formats[i];
                        if (format) {
                            date = parseExact(value, format, culture);
                            if (date) {
                                break;
                            }
                        }
                    }
                }
            }
            else {
                $.each(culture.calendar.patterns, function (name, format) {
                    date = parseExact(value, format, culture);
                    if (date) {
                        return false;
                    }
                });
            }
            return date || null;
        }
    });

    // 1.    When defining a culture, all fields are required except the ones stated as optional.
    // 2.    You can use $.extend to copy an existing culture and provide only the differing values,
    //       a good practice since most cultures do not differ too much from the 'default' culture.
    //       DO use the 'default' culture if you do this, as it is the only one that definitely
    //       exists.
    // 3.    Other plugins may add to the culture information provided by extending it. However,
    //       that plugin may extend it prior to the culture being defined, or after. Therefore,
    //       do not overwrite values that already exist when defining the baseline for a culture,
    //       by extending your culture object with the existing one.
    // 4.    Each culture should have a ".calendars" object with at least one calendar named "standard"
    //       which serves as the default calendar in use by that culture.
    // 5.    Each culture should have a ".calendar" object which is the current calendar being used,
    //       it may be dynamically changed at any time to one of the calendars in ".calendars".

    // To define a culture, use the following pattern, which handles defining the culture based
    // on the 'default culture, extending it with the existing culture if it exists, and defining
    // it if it does not exist.
    // $.cultures.foo = $.extend(true, $.extend(true, {}, $.cultures['default'], fooCulture), $.cultures.foo)

    var cultures = $.cultures = $.cultures || {};
    var en = cultures["default"] = cultures.en = $.extend(true, {
        // A unique name for the culture in the form <language code>-<country/region code>
        name: "en",
        // the name of the culture in the english language
        englishName: "English",
        // the name of the culture in its own language
        nativeName: "English",
        // whether the culture uses right-to-left text
        isRTL: false,
        // 'language' is used for so-called "specific" cultures.
        // For example, the culture "es-CL" means "Spanish, in Chili".
        // It represents the Spanish-speaking culture as it is in Chili,
        // which might have different formatting rules or even translations
        // than Spanish in Spain. A "neutral" culture is one that is not
        // specific to a region. For example, the culture "es" is the generic
        // Spanish culture, which may be a more generalized version of the language
        // that may or may not be what a specific culture expects.
        // For a specific culture like "es-CL", the 'language' field refers to the
        // neutral, generic culture information for the language it is using.
        // This is not always a simple matter of the string before the dash.
        // For example, the "zh-Hans" culture is netural (Simplified Chinese).
        // And the 'zh-SG' culture is Simplified Chinese in Singapore, whose lanugage
        // field is "zh-CHS", not "zh".
        // This field should be used to navigate from a specific culture to it's
        // more general, neutral culture. If a culture is already as general as it 
        // can get, the language may refer to itself.
        language: "en",
        // numberFormat defines general number formatting rules, like the digits in
        // each grouping, the group separator, and how negative numbers are displayed.
        numberFormat: {
            // [negativePattern]
            // Note, numberFormat.pattern has no 'positivePattern' unlike percent and currency,
            // but is still defined as an array for consistency with them.
            //  negativePattern: one of "(n)|-n|- n|n-|n -"
            pattern: ["-n"],
            // number of decimal places normally shown
            decimals: 2,
            // string that separates number groups, as in 1,000,000
            ',': ",",
            // string that separates a number from the fractional portion, as in 1.99
            '.': ".",
            // array of numbers indicating the size of each number group.
            // TODO: more detailed description and example
            groupSizes: [3],
            // symbol used for positive numbers
            '+': "+",
            // symbol used for negative numbers
            '-': "-",
            percent: {
                // [negativePattern, positivePattern]
                //     negativePattern: one of "-n %|-n%|-%n|%-n|%n-|n-%|n%-|-% n|n %-|% n-|% -n|n- %"
                //     positivePattern: one of "n %|n%|%n|% n"
                pattern: ["-n %", "n %"],
                // number of decimal places normally shown
                decimals: 2,
                // array of numbers indicating the size of each number group.
                // TODO: more detailed description and example
                groupSizes: [3],
                // string that separates number groups, as in 1,000,000
                ',': ",",
                // string that separates a number from the fractional portion, as in 1.99
                '.': ".",
                // symbol used to represent a percentage
                symbol: "%"
            },
            currency: {
                // [negativePattern, positivePattern]
                //     negativePattern: one of "($n)|-$n|$-n|$n-|(n$)|-n$|n-$|n$-|-n $|-$ n|n $-|$ n-|$ -n|n- $|($ n)|(n $)"
                //     positivePattern: one of "$n|n$|$ n|n $"
                pattern: ["($n)", "$n"],
                // number of decimal places normally shown
                decimals: 2,
                // array of numbers indicating the size of each number group.
                // TODO: more detailed description and example
                groupSizes: [3],
                // string that separates number groups, as in 1,000,000
                ',': ",",
                // string that separates a number from the fractional portion, as in 1.99
                '.': ".",
                // symbol used to represent currency
                symbol: "$"
            }
        },
        // calendars defines all the possible calendars used by this culture.
        // There should be at least one defined with name 'standard', and is the default
        // calendar used by the culture.
        // A calendar contains information about how dates are formatted, information about
        // the calendar's eras, a standard set of the date formats,
        // translations for day and month names, and if the calendar is not based on the Gregorian
        // calendar, conversion functions to and from the Gregorian calendar.
        calendars: {
            standard: {
                // name that identifies the type of calendar this is
                name: "Gregorian_USEnglish",
                // separator of parts of a date (e.g. '/' in 11/05/1955)
                '/': "/",
                // separator of parts of a time (e.g. ':' in 05:44 PM)
                ':': ":",
                // the first day of the week (0 = Sunday, 1 = Monday, etc)
                firstDay: 0,
                days: {
                    // full day names
                    names: ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"],
                    // abbreviated day names
                    namesAbbr: ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"],
                    // shortest day names
                    namesShort: ["Su", "Mo", "Tu", "We", "Th", "Fr", "Sa"]
                },
                months: {
                    // full month names (13 months for lunar calendards -- 13th month should be "" if not lunar)
                    names: ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December", ""],
                    // abbreviated month names
                    namesAbbr: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec", ""]
                },
                // AM and PM designators in one of these forms:
                // The usual view, and the upper and lower case versions
                //      [standard,lowercase,uppercase] 
                // The culture does not use AM or PM (likely all standard date formats use 24 hour time)
                //      null
                AM: ["AM", "am", "AM"],
                PM: ["PM", "pm", "PM"],
                eras: [
                // eras in reverse chronological order.
                // name: the name of the era in this culture (e.g. A.D., C.E.)
                // start: when the era starts in ticks (gregorian, gmt), null if it is the earliest supported era.
                // offset: offset in years from gregorian calendar
                {"name": "A.D.", "start": null, "offset": 0 }
            ],
                // when a two digit year is given, it will never be parsed as a four digit
                // year greater than this year (in the appropriate era for the culture)
                twoDigitYearMax: 2029,
                // set of predefined date and time patterns used by the culture
                // these represent the format someone in this culture would expect
                // to see given the portions of the date that are shown.
                patterns: {
                    // short date pattern
                    d: "M/d/yyyy",
                    // long date pattern
                    D: "dddd, MMMM dd, yyyy",
                    // short time pattern
                    t: "h:mm tt",
                    // long time pattern
                    T: "h:mm:ss tt",
                    // long date, short time pattern
                    f: "dddd, MMMM dd, yyyy h:mm tt",
                    // long date, long time pattern
                    F: "dddd, MMMM dd, yyyy h:mm:ss tt",
                    // month/day pattern
                    M: "MMMM dd",
                    // month/year pattern
                    Y: "yyyy MMMM",
                    // S is a sortable format that does not vary by culture
                    S: "yyyy\u0027-\u0027MM\u0027-\u0027dd\u0027T\u0027HH\u0027:\u0027mm\u0027:\u0027ss"
                }
                // optional fields for each calendar:
                /*
                monthsGenitive:
                Same as months but used when the day preceeds the month.
                Omit if the culture has no genitive distinction in month names.
                For an explaination of genitive months, see http://blogs.msdn.com/michkap/archive/2004/12/25/332259.aspx
                convert:
                Allows for the support of non-gregorian based calendars. This convert object is used to
                to convert a date to and from a gregorian calendar date to handle parsing and formatting.
                The two functions:
                fromGregorian(date)
                Given the date as a parameter, return an array with parts [year, month, day]
                corresponding to the non-gregorian based year, month, and day for the calendar.
                toGregorian(year, month, day)
                Given the non-gregorian year, month, and day, return a new Date() object 
                set to the corresponding date in the gregorian calendar.
                */
            }
        }
    }, cultures.en);
    en.calendar = en.calendar || en.calendars.standard;

    var regexTrim = /^\s+|\s+$/g,
    regexInfinity = /^[+-]?infinity$/i,
    regexHex = /^0x[a-f0-9]+$/i,
    regexParseFloat = /^[+-]?\d*\.?\d*(e[+-]?\d+)?$/;

    function startsWith(value, pattern) {
        return value.indexOf(pattern) === 0;
    }

    function endsWith(value, pattern) {
        return value.substr(value.length - pattern.length) === pattern;
    }

    function trim(value) {
        return (value + "").replace(regexTrim, "");
    }

    function zeroPad(str, count, left) {
        for (var l = str.length; l < count; l++) {
            str = (left ? ('0' + str) : (str + '0'));
        }
        return str;
    }

    // *************************************** Numbers ***************************************

    function expandNumber(number, precision, formatInfo) {
        var groupSizes = formatInfo.groupSizes,
        curSize = groupSizes[0],
        curGroupIndex = 1,
        factor = Math.pow(10, precision),
        rounded = Math.round(number * factor) / factor;
        if (!isFinite(rounded)) {
            rounded = number;
        }
        number = rounded;

        var numberString = number + "",
        right = "",
        split = numberString.split(/e/i),
        exponent = split.length > 1 ? parseInt(split[1], 10) : 0;
        numberString = split[0];
        split = numberString.split(".");
        numberString = split[0];
        right = split.length > 1 ? split[1] : "";

        var l;
        if (exponent > 0) {
            right = zeroPad(right, exponent, false);
            numberString += right.slice(0, exponent);
            right = right.substr(exponent);
        }
        else if (exponent < 0) {
            exponent = -exponent;
            numberString = zeroPad(numberString, exponent + 1);
            right = numberString.slice(-exponent, numberString.length) + right;
            numberString = numberString.slice(0, -exponent);
        }

        if (precision > 0) {
            right = formatInfo['.'] +
            ((right.length > precision) ? right.slice(0, precision) : zeroPad(right, precision));
        }
        else {
            right = "";
        }

        var stringIndex = numberString.length - 1,
        sep = formatInfo[","],
        ret = "";

        while (stringIndex >= 0) {
            if (curSize === 0 || curSize > stringIndex) {
                return numberString.slice(0, stringIndex + 1) + (ret.length ? (sep + ret + right) : right);
            }
            ret = numberString.slice(stringIndex - curSize + 1, stringIndex + 1) + (ret.length ? (sep + ret) : "");

            stringIndex -= curSize;

            if (curGroupIndex < groupSizes.length) {
                curSize = groupSizes[curGroupIndex];
                curGroupIndex++;
            }
        }
        return numberString.slice(0, stringIndex + 1) + sep + ret + right;
    }


    function parseNegativePattern(value, nf, negativePattern) {
        var neg = nf["-"],
        pos = nf["+"],
        ret;
        switch (negativePattern) {
            case "n -":
                neg = ' ' + neg;
                pos = ' ' + pos;
                // fall through
            case "n-":
                if (endsWith(value, neg)) {
                    ret = ['-', value.substr(0, value.length - neg.length)];
                }
                else if (endsWith(value, pos)) {
                    ret = ['+', value.substr(0, value.length - pos.length)];
                }
                break;
            case "- n":
                neg += ' ';
                pos += ' ';
                // fall through
            case "-n":
                if (startsWith(value, neg)) {
                    ret = ['-', value.substr(neg.length)];
                }
                else if (startsWith(value, pos)) {
                    ret = ['+', value.substr(pos.length)];
                }
                break;
            case "(n)":
                if (startsWith(value, '(') && endsWith(value, ')')) {
                    ret = ['-', value.substr(1, value.length - 2)];
                }
                break;
        }
        return ret || ['', value];
    }

    function formatNumber(value, format, culture) {
        if (!format || format === 'i') {
            return culture.name.length ? value.toLocaleString() : value.toString();
        }
        format = format || "D";

        var nf = culture.numberFormat,
        number = Math.abs(value),
        precision = -1,
        pattern;
        if (format.length > 1) precision = parseInt(format.slice(1), 10);

        var current = format.charAt(0).toUpperCase(),
        formatInfo;

        switch (current) {
            case "D":
                pattern = 'n';
                if (precision !== -1) {
                    number = zeroPad("" + number, precision, true);
                }
                if (value < 0) number = -number;
                break;
            case "N":
                formatInfo = nf;
                // fall through
            case "C":
                formatInfo = formatInfo || nf.currency;
                // fall through
            case "P":
                formatInfo = formatInfo || nf.percent;
                pattern = value < 0 ? formatInfo.pattern[0] : (formatInfo.pattern[1] || "n");
                if (precision === -1) precision = formatInfo.decimals;
                number = expandNumber(number * (current === "P" ? 100 : 1), precision, formatInfo);
                break;
            default:
                $.error("Bad number format specifier: " + current);
        }

        var patternParts = /n|\$|-|%/g,
        ret = "";
        for (; ; ) {
            var index = patternParts.lastIndex,
            ar = patternParts.exec(pattern);

            ret += pattern.slice(index, ar ? ar.index : pattern.length);

            if (!ar) {
                break;
            }

            switch (ar[0]) {
                case "n":
                    ret += number;
                    break;
                case "$":
                    ret += nf.currency.symbol;
                    break;
                case "-":
                    // don't make 0 negative
                    if (/[1-9]/.test(number)) {
                        ret += nf["-"];
                    }
                    break;
                case "%":
                    ret += nf.percent.symbol;
                    break;
            }
        }

        return ret;
    }

    // *************************************** Dates ***************************************

    function outOfRange(value, low, high) {
        return value < low || value > high;
    }

    function expandYear(cal, year) {
        // expands 2-digit year into 4 digits.
        var now = new Date(),
        era = getEra(now);
        if (year < 100) {
            var twoDigitYearMax = cal.twoDigitYearMax;
            twoDigitYearMax = typeof twoDigitYearMax === 'string' ? new Date().getFullYear() % 100 + parseInt(twoDigitYearMax, 10) : twoDigitYearMax;
            var curr = getEraYear(now, cal, era);
            year += curr - (curr % 100);
            if (year > twoDigitYearMax) {
                year -= 100;
            }
        }
        return year;
    }

    function getEra(date, eras) {
        if (!eras) return 0;
        var start, ticks = date.getTime();
        for (var i = 0, l = eras.length; i < l; i++) {
            start = eras[i].start;
            if (start === null || ticks >= start) {
                return i;
            }
        }
        return 0;
    }

    function toUpper(value) {
        // 'he-IL' has non-breaking space in weekday names.
        return value.split("\u00A0").join(' ').toUpperCase();
    }

    function toUpperArray(arr) {
        return $.map(arr, function (e) {
            return toUpper(e);
        });
    }

    function getEraYear(date, cal, era, sortable) {
        var year = date.getFullYear();
        if (!sortable && cal.eras) {
            // convert normal gregorian year to era-shifted gregorian
            // year by subtracting the era offset
            year -= cal.eras[era].offset;
        }
        return year;
    }

    function getDayIndex(cal, value, abbr) {
        var ret,
        days = cal.days,
        upperDays = cal._upperDays;
        if (!upperDays) {
            cal._upperDays = upperDays = [
            toUpperArray(days.names),
            toUpperArray(days.namesAbbr),
            toUpperArray(days.namesShort)
        ];
        }
        value = toUpper(value);
        if (abbr) {
            ret = $.inArray(value, upperDays[1]);
            if (ret === -1) {
                ret = $.inArray(value, upperDays[2]);
            }
        }
        else {
            ret = $.inArray(value, upperDays[0]);
        }
        return ret;
    }

    function getMonthIndex(cal, value, abbr) {
        var months = cal.months,
        monthsGen = cal.monthsGenitive || cal.months,
        upperMonths = cal._upperMonths,
        upperMonthsGen = cal._upperMonthsGen;
        if (!upperMonths) {
            cal._upperMonths = upperMonths = [
            toUpperArray(months.names),
            toUpperArray(months.namesAbbr),
        ];
            cal._upperMonthsGen = upperMonthsGen = [
            toUpperArray(monthsGen.names),
            toUpperArray(monthsGen.namesAbbr)
        ];
        }
        value = toUpper(value);
        var i = $.inArray(value, abbr ? upperMonths[1] : upperMonths[0]);
        if (i < 0) {
            i = $.inArray(value, abbr ? upperMonthsGen[1] : upperMonthsGen[0]);
        }
        return i;
    }

    function appendPreOrPostMatch(preMatch, strings) {
        // appends pre- and post- token match strings while removing escaped characters.
        // Returns a single quote count which is used to determine if the token occurs
        // in a string literal.
        var quoteCount = 0,
        escaped = false;
        for (var i = 0, il = preMatch.length; i < il; i++) {
            var c = preMatch.charAt(i);
            switch (c) {
                case '\'':
                    if (escaped) {
                        strings.push("'");
                    }
                    else {
                        quoteCount++;
                    }
                    escaped = false;
                    break;
                case '\\':
                    if (escaped) {
                        strings.push("\\");
                    }
                    escaped = !escaped;
                    break;
                default:
                    strings.push(c);
                    escaped = false;
                    break;
            }
        }
        return quoteCount;
    }

    function expandFormat(cal, format) {
        // expands unspecified or single character date formats into the full pattern.
        format = format || "F";
        var pattern,
        patterns = cal.patterns,
        len = format.length;
        if (len === 1) {
            pattern = patterns[format];
            if (!pattern) {
                $.error("Invalid date format string '" + format + "'.");
            }
            format = pattern;
        }
        else if (len === 2 && format.charAt(0) === "%") {
            // %X escape format -- intended as a custom format string that is only one character, not a built-in format.
            format = format.charAt(1);
        }
        return format;
    }

    function getParseRegExp(cal, format) {
        // converts a format string into a regular expression with groups that
        // can be used to extract date fields from a date string.
        // check for a cached parse regex.
        var re = cal._parseRegExp;
        if (!re) {
            cal._parseRegExp = re = {};
        }
        else {
            var reFormat = re[format];
            if (reFormat) {
                return reFormat;
            }
        }

        // expand single digit formats, then escape regular expression characters.
        var expFormat = expandFormat(cal, format).replace(/([\^\$\.\*\+\?\|\[\]\(\)\{\}])/g, "\\\\$1"),
        regexp = ["^"],
        groups = [],
        index = 0,
        quoteCount = 0,
        tokenRegExp = getTokenRegExp(),
        match;

        // iterate through each date token found.
        while ((match = tokenRegExp.exec(expFormat)) !== null) {
            var preMatch = expFormat.slice(index, match.index);
            index = tokenRegExp.lastIndex;

            // don't replace any matches that occur inside a string literal.
            quoteCount += appendPreOrPostMatch(preMatch, regexp);
            if (quoteCount % 2) {
                regexp.push(match[0]);
                continue;
            }

            // add a regex group for the token.
            var m = match[0],
            len = m.length,
            add;
            switch (m) {
                case 'dddd': case 'ddd':
                case 'MMMM': case 'MMM':
                case 'gg': case 'g':
                    add = "(\\D+)";
                    break;
                case 'tt': case 't':
                    add = "(\\D*)";
                    break;
                case 'yyyy':
                case 'fff':
                case 'ff':
                case 'f':
                    add = "(\\d{" + len + "})";
                    break;
                case 'dd': case 'd':
                case 'MM': case 'M':
                case 'yy': case 'y':
                case 'HH': case 'H':
                case 'hh': case 'h':
                case 'mm': case 'm':
                case 'ss': case 's':
                    add = "(\\d\\d?)";
                    break;
                case 'zzz':
                    add = "([+-]?\\d\\d?:\\d{2})";
                    break;
                case 'zz': case 'z':
                    add = "([+-]?\\d\\d?)";
                    break;
                case '/':
                    add = "(\\" + cal["/"] + ")";
                    break;
                default:
                    $.error("Invalid date format pattern '" + m + "'.");
                    break;
            }
            if (add) {
                regexp.push(add);
            }
            groups.push(match[0]);
        }
        appendPreOrPostMatch(expFormat.slice(index), regexp);
        regexp.push("$");

        // allow whitespace to differ when matching formats.
        var regexpStr = regexp.join('').replace(/\s+/g, "\\s+"),
        parseRegExp = { 'regExp': regexpStr, 'groups': groups };

        // cache the regex for this format.
        return re[format] = parseRegExp;
    }

    function getTokenRegExp() {
        // regular expression for matching date and time tokens in format strings.
        return /\/|dddd|ddd|dd|d|MMMM|MMM|MM|M|yyyy|yy|y|hh|h|HH|H|mm|m|ss|s|tt|t|fff|ff|f|zzz|zz|z|gg|g/g;
    }

    function parseExact(value, format, culture) {
        // try to parse the date string by matching against the format string
        // while using the specified culture for date field names.
        value = trim(value);
        var cal = culture.calendar,
        // convert date formats into regular expressions with groupings.
        // use the regexp to determine the input format and extract the date fields.
        parseInfo = getParseRegExp(cal, format),
        match = new RegExp(parseInfo.regExp).exec(value);
        if (match === null) {
            return null;
        }
        // found a date format that matches the input.
        var groups = parseInfo.groups,
        era = null, year = null, month = null, date = null, weekDay = null,
        hour = 0, hourOffset, min = 0, sec = 0, msec = 0, tzMinOffset = null,
        pmHour = false;
        // iterate the format groups to extract and set the date fields.
        for (var j = 0, jl = groups.length; j < jl; j++) {
            var matchGroup = match[j + 1];
            if (matchGroup) {
                var current = groups[j],
                clength = current.length,
                matchInt = parseInt(matchGroup, 10);
                switch (current) {
                    case 'dd': case 'd':
                        // Day of month.
                        date = matchInt;
                        // check that date is generally in valid range, also checking overflow below.
                        if (outOfRange(date, 1, 31)) return null;
                        break;
                    case 'MMM':
                    case 'MMMM':
                        month = getMonthIndex(cal, matchGroup, clength === 3);
                        if (outOfRange(month, 0, 11)) return null;
                        break;
                    case 'M': case 'MM':
                        // Month.
                        month = matchInt - 1;
                        if (outOfRange(month, 0, 11)) return null;
                        break;
                    case 'y': case 'yy':
                    case 'yyyy':
                        year = clength < 4 ? expandYear(cal, matchInt) : matchInt;
                        if (outOfRange(year, 0, 9999)) return null;
                        break;
                    case 'h': case 'hh':
                        // Hours (12-hour clock).
                        hour = matchInt;
                        if (hour === 12) hour = 0;
                        if (outOfRange(hour, 0, 11)) return null;
                        break;
                    case 'H': case 'HH':
                        // Hours (24-hour clock).
                        hour = matchInt;
                        if (outOfRange(hour, 0, 23)) return null;
                        break;
                    case 'm': case 'mm':
                        // Minutes.
                        min = matchInt;
                        if (outOfRange(min, 0, 59)) return null;
                        break;
                    case 's': case 'ss':
                        // Seconds.
                        sec = matchInt;
                        if (outOfRange(sec, 0, 59)) return null;
                        break;
                    case 'tt': case 't':
                        // AM/PM designator.
                        // see if it is standard, upper, or lower case PM. If not, ensure it is at least one of
                        // the AM tokens. If not, fail the parse for this format.
                        pmHour = cal.PM && (matchGroup === cal.PM[0] || matchGroup === cal.PM[1] || matchGroup === cal.PM[2]);
                        if (!pmHour && (!cal.AM || (matchGroup !== cal.AM[0] && matchGroup !== cal.AM[1] && matchGroup !== cal.AM[2]))) return null;
                        break;
                    case 'f':
                        // Deciseconds.
                    case 'ff':
                        // Centiseconds.
                    case 'fff':
                        // Milliseconds.
                        msec = matchInt * Math.pow(10, 3 - clength);
                        if (outOfRange(msec, 0, 999)) return null;
                        break;
                    case 'ddd':
                        // Day of week.
                    case 'dddd':
                        // Day of week.
                        weekDay = getDayIndex(cal, matchGroup, clength === 3);
                        if (outOfRange(weekDay, 0, 6)) return null;
                        break;
                    case 'zzz':
                        // Time zone offset in +/- hours:min.
                        var offsets = matchGroup.split(/:/);
                        if (offsets.length !== 2) return null;
                        hourOffset = parseInt(offsets[0], 10);
                        if (outOfRange(hourOffset, -12, 13)) return null;
                        var minOffset = parseInt(offsets[1], 10);
                        if (outOfRange(minOffset, 0, 59)) return null;
                        tzMinOffset = (hourOffset * 60) + (startsWith(matchGroup, '-') ? -minOffset : minOffset);
                        break;
                    case 'z': case 'zz':
                        // Time zone offset in +/- hours.
                        hourOffset = matchInt;
                        if (outOfRange(hourOffset, -12, 13)) return null;
                        tzMinOffset = hourOffset * 60;
                        break;
                    case 'g': case 'gg':
                        var eraName = matchGroup;
                        if (!eraName || !cal.eras) return null;
                        eraName = trim(eraName.toLowerCase());
                        for (var i = 0, l = cal.eras.length; i < l; i++) {
                            if (eraName === cal.eras[i].name.toLowerCase()) {
                                era = i;
                                break;
                            }
                        }
                        // could not find an era with that name
                        if (era === null) return null;
                        break;
                }
            }
        }
        var result = new Date(), defaultYear, convert = cal.convert;
        defaultYear = convert ? convert.fromGregorian(result)[0] : result.getFullYear();
        if (year === null) {
            year = defaultYear;
        }
        else if (cal.eras) {
            // year must be shifted to normal gregorian year
            // but not if year was not specified, its already normal gregorian
            // per the main if clause above.
            year += cal.eras[(era || 0)].offset;
        }
        // set default day and month to 1 and January, so if unspecified, these are the defaults
        // instead of the current day/month.
        if (month === null) {
            month = 0;
        }
        if (date === null) {
            date = 1;
        }
        // now have year, month, and date, but in the culture's calendar.
        // convert to gregorian if necessary
        if (convert) {
            result = convert.toGregorian(year, month, date);
            // conversion failed, must be an invalid match
            if (result === null) return null;
        }
        else {
            // have to set year, month and date together to avoid overflow based on current date.
            result.setFullYear(year, month, date);
            // check to see if date overflowed for specified month (only checked 1-31 above).
            if (result.getDate() !== date) return null;
            // invalid day of week.
            if (weekDay !== null && result.getDay() !== weekDay) {
                return null;
            }
        }
        // if pm designator token was found make sure the hours fit the 24-hour clock.
        if (pmHour && hour < 12) {
            hour += 12;
        }
        result.setHours(hour, min, sec, msec);
        if (tzMinOffset !== null) {
            // adjust timezone to utc before applying local offset.
            var adjustedMin = result.getMinutes() - (tzMinOffset + result.getTimezoneOffset());
            // Safari limits hours and minutes to the range of -127 to 127.  We need to use setHours
            // to ensure both these fields will not exceed this range.  adjustedMin will range
            // somewhere between -1440 and 1500, so we only need to split this into hours.
            result.setHours(result.getHours() + parseInt(adjustedMin / 60, 10), adjustedMin % 60);
        }
        return result;
    }

    function formatDate(value, format, culture) {
        var cal = culture.calendar,
        convert = cal.convert;
        if (!format || !format.length || format === 'i') {
            var ret;
            if (culture && culture.name.length) {
                if (convert) {
                    // non-gregorian calendar, so we cannot use built-in toLocaleString()
                    ret = formatDate(value, cal.patterns.F, culture);
                }
                else {
                    var eraDate = new Date(value.getTime()),
                    era = getEra(value, cal.eras);
                    eraDate.setFullYear(getEraYear(value, cal, era));
                    ret = eraDate.toLocaleString();
                }
            }
            else {
                ret = value.toString();
            }
            return ret;
        }

        var eras = cal.eras,
        sortable = format === "s";
        format = expandFormat(cal, format);

        // Start with an empty string
        ret = [];
        var hour,
        zeros = ['0', '00', '000'],
        foundDay,
        checkedDay,
        dayPartRegExp = /([^d]|^)(d|dd)([^d]|$)/g,
        quoteCount = 0,
        tokenRegExp = getTokenRegExp(),
        converted;

        function padZeros(num, c) {
            var r, s = num + '';
            if (c > 1 && s.length < c) {
                r = (zeros[c - 2] + s);
                return r.substr(r.length - c, c);
            }
            else {
                r = s;
            }
            return r;
        }

        function hasDay() {
            if (foundDay || checkedDay) {
                return foundDay;
            }
            foundDay = dayPartRegExp.test(format);
            checkedDay = true;
            return foundDay;
        }

        function getPart(date, part) {
            if (converted) {
                return converted[part];
            }
            switch (part) {
                case 0: return date.getFullYear();
                case 1: return date.getMonth();
                case 2: return date.getDate();
            }
        }

        if (!sortable && convert) {
            converted = convert.fromGregorian(value);
        }

        for (; ; ) {
            // Save the current index
            var index = tokenRegExp.lastIndex,
            // Look for the next pattern
            ar = tokenRegExp.exec(format);

            // Append the text before the pattern (or the end of the string if not found)
            var preMatch = format.slice(index, ar ? ar.index : format.length);
            quoteCount += appendPreOrPostMatch(preMatch, ret);

            if (!ar) {
                break;
            }

            // do not replace any matches that occur inside a string literal.
            if (quoteCount % 2) {
                ret.push(ar[0]);
                continue;
            }

            var current = ar[0],
            clength = current.length;

            switch (current) {
                case "ddd":
                    //Day of the week, as a three-letter abbreviation
                case "dddd":
                    // Day of the week, using the full name
                    names = (clength === 3) ? cal.days.namesAbbr : cal.days.names;
                    ret.push(names[value.getDay()]);
                    break;
                case "d":
                    // Day of month, without leading zero for single-digit days
                case "dd":
                    // Day of month, with leading zero for single-digit days
                    foundDay = true;
                    ret.push(padZeros(getPart(value, 2), clength));
                    break;
                case "MMM":
                    // Month, as a three-letter abbreviation
                case "MMMM":
                    // Month, using the full name
                    var part = getPart(value, 1);
                    ret.push((cal.monthsGenitive && hasDay())
                    ? cal.monthsGenitive[clength === 3 ? "namesAbbr" : "names"][part]
                    : cal.months[clength === 3 ? "namesAbbr" : "names"][part]);
                    break;
                case "M":
                    // Month, as digits, with no leading zero for single-digit months
                case "MM":
                    // Month, as digits, with leading zero for single-digit months
                    ret.push(padZeros(getPart(value, 1) + 1, clength));
                    break;
                case "y":
                    // Year, as two digits, but with no leading zero for years less than 10
                case "yy":
                    // Year, as two digits, with leading zero for years less than 10
                case "yyyy":
                    // Year represented by four full digits
                    part = converted ? converted[0] : getEraYear(value, cal, getEra(value, eras), sortable);
                    if (clength < 4) {
                        part = part % 100;
                    }
                    ret.push(padZeros(part, clength));
                    break;
                case "h":
                    // Hours with no leading zero for single-digit hours, using 12-hour clock
                case "hh":
                    // Hours with leading zero for single-digit hours, using 12-hour clock
                    hour = value.getHours() % 12;
                    if (hour === 0) hour = 12;
                    ret.push(padZeros(hour, clength));
                    break;
                case "H":
                    // Hours with no leading zero for single-digit hours, using 24-hour clock
                case "HH":
                    // Hours with leading zero for single-digit hours, using 24-hour clock
                    ret.push(padZeros(value.getHours(), clength));
                    break;
                case "m":
                    // Minutes with no leading zero  for single-digit minutes
                case "mm":
                    // Minutes with leading zero  for single-digit minutes
                    ret.push(padZeros(value.getMinutes(), clength));
                    break;
                case "s":
                    // Seconds with no leading zero for single-digit seconds
                case "ss":
                    // Seconds with leading zero for single-digit seconds
                    ret.push(padZeros(value.getSeconds(), clength));
                    break;
                case "t":
                    // One character am/pm indicator ("a" or "p")
                case "tt":
                    // Multicharacter am/pm indicator
                    part = value.getHours() < 12 ? (cal.AM ? cal.AM[0] : " ") : (cal.PM ? cal.PM[0] : " ");
                    ret.push(clength === 1 ? part.charAt(0) : part);
                    break;
                case "f":
                    // Deciseconds
                case "ff":
                    // Centiseconds
                case "fff":
                    // Milliseconds
                    ret.push(padZeros(value.getMilliseconds(), 3).substr(0, clength));
                    break;
                case "z":
                    // Time zone offset, no leading zero
                case "zz":
                    // Time zone offset with leading zero
                    hour = value.getTimezoneOffset() / 60;
                    ret.push((hour <= 0 ? '+' : '-') + padZeros(Math.floor(Math.abs(hour)), clength));
                    break;
                case "zzz":
                    // Time zone offset with leading zero
                    hour = value.getTimezoneOffset() / 60;
                    ret.push((hour <= 0 ? '+' : '-') + padZeros(Math.floor(Math.abs(hour)), 2) +
                    // Hard coded ":" separator, rather than using cal.TimeSeparator
                    // Repeated here for consistency, plus ":" was already assumed in date parsing.
                    ":" + padZeros(Math.abs(value.getTimezoneOffset() % 60), 2));
                    break;
                case "g":
                case "gg":
                    if (cal.eras) {
                        ret.push(cal.eras[getEra(value, eras)].name);
                    }
                    break;
                case "/":
                    ret.push(cal["/"]);
                    break;
                default:
                    $.error("Invalid date format pattern '" + current + "'.");
                    break;
            }
        }
        return ret.join('');
    }

})(jQuery);

/* Datepicker changes - Make sure to consider this while migrating to other version */

if ($.datepicker) {
    //Script to enable and disable calendar control
    //this helps to override with our regular element disable and enable like (document.getElementById('txtEndDate').disabled=true;)
    var oldShowDatepicker = $.datepicker.constructor.prototype._showDatepicker;
    $.datepicker.constructor.prototype._showDatepicker = function (input) { if (input.disabled) return; oldShowDatepicker(input); };

    //_doKeyPress event is commented because we don't want to validate date format in client browser
    $.datepicker.constructor.prototype._doKeyPress = function () { };

    // Globalization .NET support
    $.datepicker.constructor.prototype.formatDate = function (date, format, settings) {
        return $.format(date, format, 'default');
    };
    $.datepicker.constructor.prototype._formatDate = function (inst, day, month, year) {
        if (!day) {
            inst.currentDay = inst.selectedDay;
            inst.currentMonth = inst.selectedMonth;
            inst.currentYear = inst.selectedYear;
        }
        var date = (day ? (typeof day == 'object' ? day :
			    this._daylightSavingAdjust(new Date(year, month, day))) :
			    this._daylightSavingAdjust(new Date(inst.currentYear, inst.currentMonth, inst.currentDay)));
        return this.formatDate(date, this._get(inst, 'dateFormat'), 'default');
    };
    $.datepicker.constructor.prototype.parseDate = function (formats, value, settings) {
        return $.parseDate(value, formats, 'default');
    };
    $.datepicker.constructor.prototype._checkOffset = function (inst, offset, isFixed) {
        var dpWidth = inst.dpDiv.outerWidth();
        var dpHeight = inst.dpDiv.outerHeight();
        var inputWidth = inst.input ? inst.input.outerWidth() : 0;
        var inputHeight = inst.input ? inst.input.outerHeight() : 0;

        var clientWidth = 0;
        var clientHeight = 0;
        if (document.body) {
            clientWidth = document.body.clientWidth;
            clientHeight = document.body.clientHeight - 10;
        }
        if (clientWidth == 0 || (document.documentElement.clientWidth > 0 && document.documentElement.clientWidth < clientWidth))
            clientWidth = document.documentElement.clientWidth;
        if (clientHeight == 0 || (document.documentElement.clientHeight > 0 && document.documentElement.clientHeight < clientHeight))
            clientHeight = document.documentElement.clientHeight;

        var viewWidth = clientWidth + $(document).scrollLeft();
        var viewHeight = clientHeight + $(document).scrollTop();

        offset.left -= (this._get(inst, 'isRTL') ? (dpWidth - inputWidth) : 0);
        offset.left -= (isFixed && offset.left == inst.input.offset().left) ? $(document).scrollLeft() : 0;
        offset.top -= (isFixed && offset.top == (inst.input.offset().top + inputHeight)) ? $(document).scrollTop() : 0;

        // now check if datepicker is showing outside window viewport - move to a better place if so.
        offset.left -= Math.min(offset.left, (offset.left + dpWidth > viewWidth && viewWidth > dpWidth) ?
			Math.abs(offset.left + dpWidth - viewWidth) : 0);
        offset.top -= Math.min(offset.top, (offset.top + dpHeight > viewHeight && viewHeight > dpHeight) ?
			Math.abs(dpHeight + inputHeight) : 0);

        return offset;
    };
}

/* End datepicker changes */
