/* Minification failed. Returning unminified contents.
(5066,54-55): run-time error JS1195: Expected expression: >
(5081,1-2): run-time error JS1002: Syntax error: }
(5082,24-25): run-time error JS1004: Expected ';': {
(6484,46-47): run-time error JS1195: Expected expression: )
(6484,49-50): run-time error JS1195: Expected expression: >
(6486,18-19): run-time error JS1195: Expected expression: )
(6488,9-10): run-time error JS1002: Syntax error: }
(6489,37-38): run-time error JS1004: Expected ';': {
(6521,46-47): run-time error JS1195: Expected expression: )
(6521,49-50): run-time error JS1195: Expected expression: >
(6523,18-19): run-time error JS1195: Expected expression: )
(6526,9-13): run-time error JS1034: Unmatched 'else'; no 'if' defined: else
(6526,37-38): run-time error JS1004: Expected ';': {
(6558,47-48): run-time error JS1195: Expected expression: )
(6558,50-51): run-time error JS1195: Expected expression: >
(6560,18-19): run-time error JS1195: Expected expression: )
(6563,5-6): run-time error JS1002: Syntax error: }
(6564,92-93): run-time error JS1195: Expected expression: )
(6564,94-95): run-time error JS1004: Expected ';': {
(6568,6-7): run-time error JS1195: Expected expression: )
(6570,96-97): run-time error JS1004: Expected ';': {
 */
/* NUGET: BEGIN LICENSE TEXT
 *
 * Microsoft grants you the right to use these script files for the sole
 * purpose of either: (i) interacting through your browser with the Microsoft
 * website or online service, subject to the applicable licensing or use
 * terms; or (ii) using the files as included with a Microsoft product subject
 * to that product's license terms. Microsoft reserves all other rights to the
 * files not expressly granted by Microsoft, whether by implication, estoppel
 * or otherwise. Insofar as a script file is dual licensed under GPL,
 * Microsoft neither took the code under GPL nor distributes it thereunder but
 * under the terms set out in this paragraph. All notices and licenses
 * below are for informational purposes only.
 *
 * NUGET: END LICENSE TEXT */
/*!
** Unobtrusive Ajax support library for jQuery
** Copyright (C) Microsoft Corporation. All rights reserved.
*/

/*jslint white: true, browser: true, onevar: true, undef: true, nomen: true, eqeqeq: true, plusplus: true, bitwise: true, regexp: true, newcap: true, immed: true, strict: false */
/*global window: false, jQuery: false */

(function ($) {
    var data_click = "unobtrusiveAjaxClick",
        data_target = "unobtrusiveAjaxClickTarget",
        data_validation = "unobtrusiveValidation";

    function getFunction(code, argNames) {
        var fn = window, parts = (code || "").split(".");
        while (fn && parts.length) {
            fn = fn[parts.shift()];
        }
        if (typeof (fn) === "function") {
            return fn;
        }
        argNames.push(code);
        return Function.constructor.apply(null, argNames);
    }

    function isMethodProxySafe(method) {
        return method === "GET" || method === "POST";
    }

    function asyncOnBeforeSend(xhr, method) {
        if (!isMethodProxySafe(method)) {
            xhr.setRequestHeader("X-HTTP-Method-Override", method);
        }
    }

    function asyncOnSuccess(element, data, contentType) {
        var mode;

        if (contentType.indexOf("application/x-javascript") !== -1) {  
            return;
        }

        mode = (element.getAttribute("data-ajax-mode") || "").toUpperCase();
        $(element.getAttribute("data-ajax-update")).each(function (i, update) {
            var top;

            switch (mode) {
            case "BEFORE":
                top = update.firstChild;
                $("<div />").html(data).contents().each(function () {
                    update.insertBefore(this, top);
                });
                break;
            case "AFTER":
                $("<div />").html(data).contents().each(function () {
                    update.appendChild(this);
                });
                break;
            case "REPLACE-WITH":
                $(update).replaceWith(data);
                break;
            default:
                $(update).html(data);
                break;
            }
        });
    }

    function asyncRequest(element, options) {
        var confirm, loading, method, duration;

        confirm = element.getAttribute("data-ajax-confirm");
        if (confirm && !window.confirm(confirm)) {
            return;
        }

        loading = $(element.getAttribute("data-ajax-loading"));
        duration = parseInt(element.getAttribute("data-ajax-loading-duration"), 10) || 0;

        $.extend(options, {
            type: element.getAttribute("data-ajax-method") || undefined,
            url: element.getAttribute("data-ajax-url") || undefined,
            cache: !!element.getAttribute("data-ajax-cache"),
            beforeSend: function (xhr) {
                var result;
                asyncOnBeforeSend(xhr, method);
                result = getFunction(element.getAttribute("data-ajax-begin"), ["xhr"]).apply(element, arguments);
                if (result !== false) {
                    loading.show(duration);
                }
                return result;
            },
            complete: function () {
                loading.hide(duration);
                getFunction(element.getAttribute("data-ajax-complete"), ["xhr", "status"]).apply(element, arguments);
            },
            success: function (data, status, xhr) {
                asyncOnSuccess(element, data, xhr.getResponseHeader("Content-Type") || "text/html");
                getFunction(element.getAttribute("data-ajax-success"), ["data", "status", "xhr"]).apply(element, arguments);
            },
            error: function () {
                getFunction(element.getAttribute("data-ajax-failure"), ["xhr", "status", "error"]).apply(element, arguments);
            }
        });

        options.data.push({ name: "X-Requested-With", value: "XMLHttpRequest" });

        method = options.type.toUpperCase();
        if (!isMethodProxySafe(method)) {
            options.type = "POST";
            options.data.push({ name: "X-HTTP-Method-Override", value: method });
        }

        $.ajax(options);
    }

    function validate(form) {
        var validationInfo = $(form).data(data_validation);
        return !validationInfo || !validationInfo.validate || validationInfo.validate();
    }

    $(document).on("click", "a[data-ajax=true]", function (evt) {
        evt.preventDefault();
        asyncRequest(this, {
            url: this.href,
            type: "GET",
            data: []
        });
    });

    $(document).on("click", "form[data-ajax=true] input[type=image]", function (evt) {
        var name = evt.target.name,
            target = $(evt.target),
            form = $(target.parents("form")[0]),
            offset = target.offset();

        form.data(data_click, [
            { name: name + ".x", value: Math.round(evt.pageX - offset.left) },
            { name: name + ".y", value: Math.round(evt.pageY - offset.top) }
        ]);

        setTimeout(function () {
            form.removeData(data_click);
        }, 0);
    });

    $(document).on("click", "form[data-ajax=true] :submit", function (evt) {
        var name = evt.currentTarget.name,
            target = $(evt.target),
            form = $(target.parents("form")[0]);

        form.data(data_click, name ? [{ name: name, value: evt.currentTarget.value }] : []);
        form.data(data_target, target);

        setTimeout(function () {
            form.removeData(data_click);
            form.removeData(data_target);
        }, 0);
    });

    $(document).on("submit", "form[data-ajax=true]", function (evt) {
        var clickInfo = $(this).data(data_click) || [],
            clickTarget = $(this).data(data_target),
            isCancel = clickTarget && clickTarget.hasClass("cancel");
        evt.preventDefault();
        if (!isCancel && !validate(this)) {
            return;
        }
        asyncRequest(this, {
            url: this.action,
            type: this.method || "GET",
            data: clickInfo.concat($(this).serializeArray())
        });
    });
}(jQuery));;
/*!
 * jQuery Validation Plugin v1.13.1
 *
 * http://jqueryvalidation.org/
 *
 * Copyright (c) 2014 Jörn Zaefferer
 * Released under the MIT license
 */
(function( factory ) {
	if ( typeof define === "function" && define.amd ) {
		define( ["jquery"], factory );
	} else {
		factory( jQuery );
	}
}(function( $ ) {

$.extend($.fn, {
	validate: function( options ) {

		if ( !this.length ) {
			if ( options && options.debug && window.console ) {
				console.warn( "Nothing selected, can't validate, returning nothing." );
			}
			return;
		}

		var validator = $.data( this[ 0 ], "validator" );
		if ( validator ) {
			return validator;
		}

		this.attr( "novalidate", "novalidate" );

		validator = new $.validator( options, this[ 0 ] );
		$.data( this[ 0 ], "validator", validator );

		if ( validator.settings.onsubmit ) {

			this.validateDelegate( ":submit", "click", function( event ) {
				if ( validator.settings.submitHandler ) {
					validator.submitButton = event.target;
				}
				
				if ( $( event.target ).hasClass( "cancel" ) ) {
					validator.cancelSubmit = true;
				}
                				
				if ( $( event.target ).attr( "formnovalidate" ) !== undefined ) {
					validator.cancelSubmit = true;
				}
			});

			
			this.submit( function( event ) {
				if ( validator.settings.debug ) {
					
					event.preventDefault();
				}
				function handle() {
					var hidden, result;
					if ( validator.settings.submitHandler ) {
						if ( validator.submitButton ) {
							
							hidden = $( "<input type='hidden'/>" )
								.attr( "name", validator.submitButton.name )
								.val( $( validator.submitButton ).val() )
								.appendTo( validator.currentForm );
						}
						result = validator.settings.submitHandler.call( validator, validator.currentForm, event );
						if ( validator.submitButton ) {
							
							hidden.remove();
						}
						if ( result !== undefined ) {
							return result;
						}
						return false;
					}
					return true;
				}

				
				if ( validator.cancelSubmit ) {
					validator.cancelSubmit = false;
					return handle();
				}
				if ( validator.form() ) {
					if ( validator.pendingRequest ) {
						validator.formSubmitted = true;
						return false;
					}
					return handle();
				} else {
					validator.focusInvalid();
					return false;
				}
			});
		}

		return validator;
	},
	
	valid: function() {
		var valid, validator;

		if ( $( this[ 0 ] ).is( "form" ) ) {
			valid = this.validate().form();
		} else {
			valid = true;
			validator = $( this[ 0 ].form ).validate();
			this.each( function() {
				valid = validator.element( this ) && valid;
			});
		}
		return valid;
	},
	
	removeAttrs: function( attributes ) {
		var result = {},
			$element = this;
		$.each( attributes.split( /\s/ ), function( index, value ) {
			result[ value ] = $element.attr( value );
			$element.removeAttr( value );
		});
		return result;
	},
	
	rules: function( command, argument ) {
		var element = this[ 0 ],
			settings, staticRules, existingRules, data, param, filtered;

		if ( command ) {
			settings = $.data( element.form, "validator" ).settings;
			staticRules = settings.rules;
			existingRules = $.validator.staticRules( element );
			switch ( command ) {
			case "add":
				$.extend( existingRules, $.validator.normalizeRule( argument ) );
				
				delete existingRules.messages;
				staticRules[ element.name ] = existingRules;
				if ( argument.messages ) {
					settings.messages[ element.name ] = $.extend( settings.messages[ element.name ], argument.messages );
				}
				break;
			case "remove":
				if ( !argument ) {
					delete staticRules[ element.name ];
					return existingRules;
				}
				filtered = {};
				$.each( argument.split( /\s/ ), function( index, method ) {
					filtered[ method ] = existingRules[ method ];
					delete existingRules[ method ];
					if ( method === "required" ) {
						$( element ).removeAttr( "aria-required" );
					}
				});
				return filtered;
			}
		}

		data = $.validator.normalizeRules(
		$.extend(
			{},
			$.validator.classRules( element ),
			$.validator.attributeRules( element ),
			$.validator.dataRules( element ),
			$.validator.staticRules( element )
		), element );

		
		if ( data.required ) {
			param = data.required;
			delete data.required;
			data = $.extend( { required: param }, data );
			$( element ).attr( "aria-required", "true" );
		}

		
		if ( data.remote ) {
			param = data.remote;
			delete data.remote;
			data = $.extend( data, { remote: param });
		}

		return data;
	}
});


$.extend( $.expr[ ":" ], {
	blank: function( a ) {
		return !$.trim( "" + $( a ).val() );
	},
	filled: function( a ) {
		return !!$.trim( "" + $( a ).val() );
	},
	
	unchecked: function( a ) {
		return !$( a ).prop( "checked" );
	}
});


$.validator = function( options, form ) {
	this.settings = $.extend( true, {}, $.validator.defaults, options );
	this.currentForm = form;
	this.init();
};


$.validator.format = function( source, params ) {
	if ( arguments.length === 1 ) {
		return function() {
			var args = $.makeArray( arguments );
			args.unshift( source );
			return $.validator.format.apply( this, args );
		};
	}
	if ( arguments.length > 2 && params.constructor !== Array  ) {
		params = $.makeArray( arguments ).slice( 1 );
	}
	if ( params.constructor !== Array ) {
		params = [ params ];
	}
	$.each( params, function( i, n ) {
		source = source.replace( new RegExp( "\\{" + i + "\\}", "g" ), function() {
			return n;
		});
	});
	return source;
};

$.extend( $.validator, {

	defaults: {
		messages: {},
		groups: {},
		rules: {},
		errorClass: "error",
		validClass: "valid",
		errorElement: "label",
		focusCleanup: false,
		focusInvalid: true,
		errorContainer: $( [] ),
		errorLabelContainer: $( [] ),
		onsubmit: true,
		ignore: ":hidden",
		ignoreTitle: false,
		onfocusin: function( element ) {
			this.lastActive = element;

			
			if ( this.settings.focusCleanup ) {
				if ( this.settings.unhighlight ) {
					this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
				}
				this.hideThese( this.errorsFor( element ) );
			}
		},
		onfocusout: function( element ) {
			if ( !this.checkable( element ) && ( element.name in this.submitted || !this.optional( element ) ) ) {
				this.element( element );
			}
		},
		onkeyup: function( element, event ) {
			if ( event.which === 9 && this.elementValue( element ) === "" ) {
				return;
			} else if ( element.name in this.submitted || element === this.lastElement ) {
				this.element( element );
			}
		},
		onclick: function( element ) {
			
			if ( element.name in this.submitted ) {
				this.element( element );

			
			} else if ( element.parentNode.name in this.submitted ) {
				this.element( element.parentNode );
			}
		},
		highlight: function( element, errorClass, validClass ) {
			if ( element.type === "radio" ) {
				this.findByName( element.name ).addClass( errorClass ).removeClass( validClass );
			} else {
				$( element ).addClass( errorClass ).removeClass( validClass );
			}
		},
		unhighlight: function( element, errorClass, validClass ) {
			if ( element.type === "radio" ) {
				this.findByName( element.name ).removeClass( errorClass ).addClass( validClass );
			} else {
				$( element ).removeClass( errorClass ).addClass( validClass );
			}
		}
	},

	
	setDefaults: function( settings ) {
		$.extend( $.validator.defaults, settings );
	},

	messages: {
		required: "This field is required.",
		remote: "Please fix this field.",
		email: "Please enter a valid email address.",
		url: "Please enter a valid URL.",
		date: "Please enter a valid date.",
		dateISO: "Please enter a valid date ( ISO ).",
		number: "Please enter a valid number.",
		digits: "Please enter only digits.",
		creditcard: "Please enter a valid credit card number.",
		equalTo: "Please enter the same value again.",
		maxlength: $.validator.format( "Please enter no more than {0} characters." ),
		minlength: $.validator.format( "Please enter at least {0} characters." ),
		rangelength: $.validator.format( "Please enter a value between {0} and {1} characters long." ),
		range: $.validator.format( "Please enter a value between {0} and {1}." ),
		max: $.validator.format( "Please enter a value less than or equal to {0}." ),
		min: $.validator.format( "Please enter a value greater than or equal to {0}." )
	},

	autoCreateRanges: false,

	prototype: {

		init: function() {
			this.labelContainer = $( this.settings.errorLabelContainer );
			this.errorContext = this.labelContainer.length && this.labelContainer || $( this.currentForm );
			this.containers = $( this.settings.errorContainer ).add( this.settings.errorLabelContainer );
			this.submitted = {};
			this.valueCache = {};
			this.pendingRequest = 0;
			this.pending = {};
			this.invalid = {};
			this.reset();

			var groups = ( this.groups = {} ),
				rules;
			$.each( this.settings.groups, function( key, value ) {
				if ( typeof value === "string" ) {
					value = value.split( /\s/ );
				}
				$.each( value, function( index, name ) {
					groups[ name ] = key;
				});
			});
			rules = this.settings.rules;
			$.each( rules, function( key, value ) {
				rules[ key ] = $.validator.normalizeRule( value );
			});

			function delegate( event ) {
				var validator = $.data( this[ 0 ].form, "validator" ),
					eventType = "on" + event.type.replace( /^validate/, "" ),
					settings = validator.settings;
				if ( settings[ eventType ] && !this.is( settings.ignore ) ) {
					settings[ eventType ].call( validator, this[ 0 ], event );
				}
			}
			$( this.currentForm )
				.validateDelegate( ":text, [type='password'], [type='file'], select, textarea, " +
					"[type='number'], [type='search'] ,[type='tel'], [type='url'], " +
					"[type='email'], [type='datetime'], [type='date'], [type='month'], " +
					"[type='week'], [type='time'], [type='datetime-local'], " +
					"[type='range'], [type='color'], [type='radio'], [type='checkbox']",
					"focusin focusout keyup", delegate)
				
				
				.validateDelegate("select, option, [type='radio'], [type='checkbox']", "click", delegate);

			if ( this.settings.invalidHandler ) {
				$( this.currentForm ).bind( "invalid-form.validate", this.settings.invalidHandler );
			}

			
			
			$( this.currentForm ).find( "[required], [data-rule-required], .required" ).attr( "aria-required", "true" );
		},

		
		form: function() {
			this.checkForm();
			$.extend( this.submitted, this.errorMap );
			this.invalid = $.extend({}, this.errorMap );
			if ( !this.valid() ) {
				$( this.currentForm ).triggerHandler( "invalid-form", [ this ]);
			}
			this.showErrors();
			return this.valid();
		},

		checkForm: function() {
			this.prepareForm();
			for ( var i = 0, elements = ( this.currentElements = this.elements() ); elements[ i ]; i++ ) {
				this.check( elements[ i ] );
			}
			return this.valid();
		},

		
		element: function( element ) {
			var cleanElement = this.clean( element ),
				checkElement = this.validationTargetFor( cleanElement ),
				result = true;

			this.lastElement = checkElement;

			if ( checkElement === undefined ) {
				delete this.invalid[ cleanElement.name ];
			} else {
				this.prepareElement( checkElement );
				this.currentElements = $( checkElement );

				result = this.check( checkElement ) !== false;
				if ( result ) {
					delete this.invalid[ checkElement.name ];
				} else {
					this.invalid[ checkElement.name ] = true;
				}
			}
			
			$( element ).attr( "aria-invalid", !result );

			if ( !this.numberOfInvalids() ) {
				
				this.toHide = this.toHide.add( this.containers );
			}
			this.showErrors();
			return result;
		},

		
		showErrors: function( errors ) {
			if ( errors ) {
				
				$.extend( this.errorMap, errors );
				this.errorList = [];
				for ( var name in errors ) {
					this.errorList.push({
						message: errors[ name ],
						element: this.findByName( name )[ 0 ]
					});
				}
				
				this.successList = $.grep( this.successList, function( element ) {
					return !( element.name in errors );
				});
			}
			if ( this.settings.showErrors ) {
				this.settings.showErrors.call( this, this.errorMap, this.errorList );
			} else {
				this.defaultShowErrors();
			}
		},

		
		resetForm: function() {
			if ( $.fn.resetForm ) {
				$( this.currentForm ).resetForm();
			}
			this.submitted = {};
			this.lastElement = null;
			this.prepareForm();
			this.hideErrors();
			this.elements()
					.removeClass( this.settings.errorClass )
					.removeData( "previousValue" )
					.removeAttr( "aria-invalid" );
		},

		numberOfInvalids: function() {
			return this.objectLength( this.invalid );
		},

		objectLength: function( obj ) {
			/* jshint unused: false */
			var count = 0,
				i;
			for ( i in obj ) {
				count++;
			}
			return count;
		},

		hideErrors: function() {
			this.hideThese( this.toHide );
		},

		hideThese: function( errors ) {
			errors.not( this.containers ).text( "" );
			this.addWrapper( errors ).hide();
		},

		valid: function() {
			return this.size() === 0;
		},

		size: function() {
			return this.errorList.length;
		},

		focusInvalid: function() {
			if ( this.settings.focusInvalid ) {
				try {
					$( this.findLastActive() || this.errorList.length && this.errorList[ 0 ].element || [])
					.filter( ":visible" )
					.focus()
					
					.trigger( "focusin" );
				} catch ( e ) {
					
				}
			}
		},

		findLastActive: function() {
			var lastActive = this.lastActive;
			return lastActive && $.grep( this.errorList, function( n ) {
				return n.element.name === lastActive.name;
			}).length === 1 && lastActive;
		},

		elements: function() {
			var validator = this,
				rulesCache = {};

			
			return $( this.currentForm )
			.find( "input, select, textarea" )
			.not( ":submit, :reset, :image, [disabled], [readonly]" )
			.not( this.settings.ignore )
			.filter( function() {
				if ( !this.name && validator.settings.debug && window.console ) {
					console.error( "%o has no name assigned", this );
				}

				
				if ( this.name in rulesCache || !validator.objectLength( $( this ).rules() ) ) {
					return false;
				}

				rulesCache[ this.name ] = true;
				return true;
			});
		},

		clean: function( selector ) {
			return $( selector )[ 0 ];
		},

		errors: function() {
			var errorClass = this.settings.errorClass.split( " " ).join( "." );
			return $( this.settings.errorElement + "." + errorClass, this.errorContext );
		},

		reset: function() {
			this.successList = [];
			this.errorList = [];
			this.errorMap = {};
			this.toShow = $( [] );
			this.toHide = $( [] );
			this.currentElements = $( [] );
		},

		prepareForm: function() {
			this.reset();
			this.toHide = this.errors().add( this.containers );
		},

		prepareElement: function( element ) {
			this.reset();
			this.toHide = this.errorsFor( element );
		},

		elementValue: function( element ) {
			var val,
				$element = $( element ),
				type = element.type;

			if ( type === "radio" || type === "checkbox" ) {
				return $( "input[name='" + element.name + "']:checked" ).val();
			} else if ( type === "number" && typeof element.validity !== "undefined" ) {
				return element.validity.badInput ? false : $element.val();
			}

			val = $element.val();
			if ( typeof val === "string" ) {
				return val.replace(/\r/g, "" );
			}
			return val;
		},

		check: function( element ) {
			element = this.validationTargetFor( this.clean( element ) );

			var rules = $( element ).rules(),
				rulesCount = $.map( rules, function( n, i ) {
					return i;
				}).length,
				dependencyMismatch = false,
				val = this.elementValue( element ),
				result, method, rule;

			for ( method in rules ) {
				rule = { method: method, parameters: rules[ method ] };
				try {

					result = $.validator.methods[ method ].call( this, val, element, rule.parameters );

					if ( result === "dependency-mismatch" && rulesCount === 1 ) {
						dependencyMismatch = true;
						continue;
					}
					dependencyMismatch = false;

					if ( result === "pending" ) {
						this.toHide = this.toHide.not( this.errorsFor( element ) );
						return;
					}

					if ( !result ) {
						this.formatAndAdd( element, rule );
						return false;
					}
				} catch ( e ) {
					if ( this.settings.debug && window.console ) {
						console.log( "Exception occurred when checking element " + element.id + ", check the '" + rule.method + "' method.", e );
					}
					throw e;
				}
			}
			if ( dependencyMismatch ) {
				return;
			}
			if ( this.objectLength( rules ) ) {
				this.successList.push( element );
			}
			return true;
		},

		
		customDataMessage: function( element, method ) {
			return $( element ).data( "msg" + method.charAt( 0 ).toUpperCase() +
				method.substring( 1 ).toLowerCase() ) || $( element ).data( "msg" );
		},

		
		customMessage: function( name, method ) {
			var m = this.settings.messages[ name ];
			return m && ( m.constructor === String ? m : m[ method ]);
		},

		
		findDefined: function() {
			for ( var i = 0; i < arguments.length; i++) {
				if ( arguments[ i ] !== undefined ) {
					return arguments[ i ];
				}
			}
			return undefined;
		},

		defaultMessage: function( element, method ) {
			return this.findDefined(
				this.customMessage( element.name, method ),
				this.customDataMessage( element, method ),
				
				!this.settings.ignoreTitle && element.title || undefined,
				$.validator.messages[ method ],
				"<strong>Warning: No message defined for " + element.name + "</strong>"
			);
		},

		formatAndAdd: function( element, rule ) {
			var message = this.defaultMessage( element, rule.method ),
				theregex = /\$?\{(\d+)\}/g;
			if ( typeof message === "function" ) {
				message = message.call( this, rule.parameters, element );
			} else if ( theregex.test( message ) ) {
				message = $.validator.format( message.replace( theregex, "{$1}" ), rule.parameters );
			}
			this.errorList.push({
				message: message,
				element: element,
				method: rule.method
			});

			this.errorMap[ element.name ] = message;
			this.submitted[ element.name ] = message;
		},

		addWrapper: function( toToggle ) {
			if ( this.settings.wrapper ) {
				toToggle = toToggle.add( toToggle.parent( this.settings.wrapper ) );
			}
			return toToggle;
		},

		defaultShowErrors: function() {
			var i, elements, error;
			for ( i = 0; this.errorList[ i ]; i++ ) {
				error = this.errorList[ i ];
				if ( this.settings.highlight ) {
					this.settings.highlight.call( this, error.element, this.settings.errorClass, this.settings.validClass );
				}
				this.showLabel( error.element, error.message );
			}
			if ( this.errorList.length ) {
				this.toShow = this.toShow.add( this.containers );
			}
			if ( this.settings.success ) {
				for ( i = 0; this.successList[ i ]; i++ ) {
					this.showLabel( this.successList[ i ] );
				}
			}
			if ( this.settings.unhighlight ) {
				for ( i = 0, elements = this.validElements(); elements[ i ]; i++ ) {
					this.settings.unhighlight.call( this, elements[ i ], this.settings.errorClass, this.settings.validClass );
				}
			}
			this.toHide = this.toHide.not( this.toShow );
			this.hideErrors();
			this.addWrapper( this.toShow ).show();
		},

		validElements: function() {
			return this.currentElements.not( this.invalidElements() );
		},

		invalidElements: function() {
			return $( this.errorList ).map(function() {
				return this.element;
			});
		},

		showLabel: function( element, message ) {
			var place, group, errorID,
				error = this.errorsFor( element ),
				elementID = this.idOrName( element ),
				describedBy = $( element ).attr( "aria-describedby" );
			if ( error.length ) {
				
				error.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );
				
				error.html( message );
			} else {
				
				error = $( "<" + this.settings.errorElement + ">" )
					.attr( "id", elementID + "-error" )
					.addClass( this.settings.errorClass )
					.html( message || "" );

				
				place = error;
				if ( this.settings.wrapper ) {
					
					place = error.hide().show().wrap( "<" + this.settings.wrapper + "/>" ).parent();
				}
				if ( this.labelContainer.length ) {
					this.labelContainer.append( place );
				} else if ( this.settings.errorPlacement ) {
					this.settings.errorPlacement( place, $( element ) );
				} else {
					place.insertAfter( element );
				}

				if ( error.is( "label" ) ) {
					
					error.attr( "for", elementID );
				} else if ( error.parents( "label[for='" + elementID + "']" ).length === 0 ) {
					
					errorID = error.attr( "id" ).replace( /(:|\.|\[|\])/g, "\\$1");
					
					if ( !describedBy ) {
						describedBy = errorID;
					} else if ( !describedBy.match( new RegExp( "\\b" + errorID + "\\b" ) ) ) {
						
						describedBy += " " + errorID;
					}
					$( element ).attr( "aria-describedby", describedBy );

					group = this.groups[ element.name ];
					if ( group ) {
						$.each( this.groups, function( name, testgroup ) {
							if ( testgroup === group ) {
								$( "[name='" + name + "']", this.currentForm )
									.attr( "aria-describedby", error.attr( "id" ) );
							}
						});
					}
				}
			}
			if ( !message && this.settings.success ) {
				error.text( "" );
				if ( typeof this.settings.success === "string" ) {
					error.addClass( this.settings.success );
				} else {
					this.settings.success( error, element );
				}
			}
			this.toShow = this.toShow.add( error );
		},

		errorsFor: function( element ) {
			var name = this.idOrName( element ),
				describer = $( element ).attr( "aria-describedby" ),
				selector = "label[for='" + name + "'], label[for='" + name + "'] *";
            			
			if ( describer ) {
				selector = selector + ", #" + describer.replace( /\s+/g, ", #" );
			}
			return this
				.errors()
				.filter( selector );
		},

		idOrName: function( element ) {
			return this.groups[ element.name ] || ( this.checkable( element ) ? element.name : element.id || element.name );
		},

		validationTargetFor: function( element ) {
            			
			if ( this.checkable( element ) ) {
				element = this.findByName( element.name );
			}

			return $( element ).not( this.settings.ignore )[ 0 ];
		},

		checkable: function( element ) {
			return ( /radio|checkbox/i ).test( element.type );
		},

		findByName: function( name ) {
			return $( this.currentForm ).find( "[name='" + name + "']" );
		},

		getLength: function( value, element ) {
			switch ( element.nodeName.toLowerCase() ) {
			case "select":
				return $( "option:selected", element ).length;
			case "input":
				if ( this.checkable( element ) ) {
					return this.findByName( element.name ).filter( ":checked" ).length;
				}
			}
			return value.length;
		},

		depend: function( param, element ) {
			return this.dependTypes[typeof param] ? this.dependTypes[typeof param]( param, element ) : true;
		},

		dependTypes: {
			"boolean": function( param ) {
				return param;
			},
			"string": function( param, element ) {
				return !!$( param, element.form ).length;
			},
			"function": function( param, element ) {
				return param( element );
			}
		},

		optional: function( element ) {
			var val = this.elementValue( element );
			return !$.validator.methods.required.call( this, val, element ) && "dependency-mismatch";
		},

		startRequest: function( element ) {
			if ( !this.pending[ element.name ] ) {
				this.pendingRequest++;
				this.pending[ element.name ] = true;
			}
		},

		stopRequest: function( element, valid ) {
			this.pendingRequest--;
			
			if ( this.pendingRequest < 0 ) {
				this.pendingRequest = 0;
			}
			delete this.pending[ element.name ];
			if ( valid && this.pendingRequest === 0 && this.formSubmitted && this.form() ) {
				$( this.currentForm ).submit();
				this.formSubmitted = false;
			} else if (!valid && this.pendingRequest === 0 && this.formSubmitted ) {
				$( this.currentForm ).triggerHandler( "invalid-form", [ this ]);
				this.formSubmitted = false;
			}
		},

		previousValue: function( element ) {
			return $.data( element, "previousValue" ) || $.data( element, "previousValue", {
				old: null,
				valid: true,
				message: this.defaultMessage( element, "remote" )
			});
		}

	},

	classRuleSettings: {
		required: { required: true },
		email: { email: true },
		url: { url: true },
		date: { date: true },
		dateISO: { dateISO: true },
		number: { number: true },
		digits: { digits: true },
		creditcard: { creditcard: true }
	},

	addClassRules: function( className, rules ) {
		if ( className.constructor === String ) {
			this.classRuleSettings[ className ] = rules;
		} else {
			$.extend( this.classRuleSettings, className );
		}
	},

	classRules: function( element ) {
		var rules = {},
			classes = $( element ).attr( "class" );

		if ( classes ) {
			$.each( classes.split( " " ), function() {
				if ( this in $.validator.classRuleSettings ) {
					$.extend( rules, $.validator.classRuleSettings[ this ]);
				}
			});
		}
		return rules;
	},

	attributeRules: function( element ) {
		var rules = {},
			$element = $( element ),
			type = element.getAttribute( "type" ),
			method, value;

		for ( method in $.validator.methods ) {

			
			if ( method === "required" ) {
				value = element.getAttribute( method );
				if ( value === "" ) {
					value = true;
				}
				value = !!value;
			} else {
				value = $element.attr( method );
			}

			if ( /min|max/.test( method ) && ( type === null || /number|range|text/.test( type ) ) ) {
				value = Number( value );
			}

			if ( value || value === 0 ) {
				rules[ method ] = value;
			} else if ( type === method && type !== "range" ) {
				rules[ method ] = true;
			}
		}

		
		if ( rules.maxlength && /-1|2147483647|524288/.test( rules.maxlength ) ) {
			delete rules.maxlength;
		}

		return rules;
	},

	dataRules: function( element ) {
		var method, value,
			rules = {}, $element = $( element );
		for ( method in $.validator.methods ) {
			value = $element.data( "rule" + method.charAt( 0 ).toUpperCase() + method.substring( 1 ).toLowerCase() );
			if ( value !== undefined ) {
				rules[ method ] = value;
			}
		}
		return rules;
	},

	staticRules: function( element ) {
		var rules = {},
			validator = $.data( element.form, "validator" );

		if ( validator.settings.rules ) {
			rules = $.validator.normalizeRule( validator.settings.rules[ element.name ] ) || {};
		}
		return rules;
	},

	normalizeRules: function( rules, element ) {
		
		$.each( rules, function( prop, val ) {
			
			if ( val === false ) {
				delete rules[ prop ];
				return;
			}
			if ( val.param || val.depends ) {
				var keepRule = true;
				switch ( typeof val.depends ) {
				case "string":
					keepRule = !!$( val.depends, element.form ).length;
					break;
				case "function":
					keepRule = val.depends.call( element, element );
					break;
				}
				if ( keepRule ) {
					rules[ prop ] = val.param !== undefined ? val.param : true;
				} else {
					delete rules[ prop ];
				}
			}
		});

		
		$.each( rules, function( rule, parameter ) {
			rules[ rule ] = $.isFunction( parameter ) ? parameter( element ) : parameter;
		});

		
		$.each([ "minlength", "maxlength" ], function() {
			if ( rules[ this ] ) {
				rules[ this ] = Number( rules[ this ] );
			}
		});
		$.each([ "rangelength", "range" ], function() {
			var parts;
			if ( rules[ this ] ) {
				if ( $.isArray( rules[ this ] ) ) {
					rules[ this ] = [ Number( rules[ this ][ 0 ]), Number( rules[ this ][ 1 ] ) ];
				} else if ( typeof rules[ this ] === "string" ) {
					parts = rules[ this ].replace(/[\[\]]/g, "" ).split( /[\s,]+/ );
					rules[ this ] = [ Number( parts[ 0 ]), Number( parts[ 1 ] ) ];
				}
			}
		});

		if ( $.validator.autoCreateRanges ) {
			
			if ( rules.min != null && rules.max != null ) {
				rules.range = [ rules.min, rules.max ];
				delete rules.min;
				delete rules.max;
			}
			if ( rules.minlength != null && rules.maxlength != null ) {
				rules.rangelength = [ rules.minlength, rules.maxlength ];
				delete rules.minlength;
				delete rules.maxlength;
			}
		}

		return rules;
	},

	
	normalizeRule: function( data ) {
		if ( typeof data === "string" ) {
			var transformed = {};
			$.each( data.split( /\s/ ), function() {
				transformed[ this ] = true;
			});
			data = transformed;
		}
		return data;
	},

	
	addMethod: function( name, method, message ) {
		$.validator.methods[ name ] = method;
		$.validator.messages[ name ] = message !== undefined ? message : $.validator.messages[ name ];
		if ( method.length < 3 ) {
			$.validator.addClassRules( name, $.validator.normalizeRule( name ) );
		}
	},

	methods: {

		
		required: function( value, element, param ) {
			
			if ( !this.depend( param, element ) ) {
				return "dependency-mismatch";
			}
			if ( element.nodeName.toLowerCase() === "select" ) {
				
				var val = $( element ).val();
				return val && val.length > 0;
			}
			if ( this.checkable( element ) ) {
				return this.getLength( value, element ) > 0;
			}
			return $.trim( value ).length > 0;
		},

		
		email: function( value, element ) {
			return this.optional( element ) || /^[a-zA-Z0-9.!#$%&'*+\/=?^_`{|}~-]+@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/.test( value );
		},

		url: function( value, element ) {
			return this.optional( element ) || /^(https?|s?ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test( value );
		},

		date: function( value, element ) {
			return this.optional( element ) || !/Invalid|NaN/.test( new Date( value ).toString() );
		},

		dateISO: function( value, element ) {
			return this.optional( element ) || /^\d{4}[\/\-](0?[1-9]|1[012])[\/\-](0?[1-9]|[12][0-9]|3[01])$/.test( value );
		},

		
		number: function( value, element ) {
			return this.optional( element ) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)?(?:\.\d+)?$/.test( value );
		},

		
		digits: function( value, element ) {
			return this.optional( element ) || /^\d+$/.test( value );
		},
        		
		creditcard: function( value, element ) {
			if ( this.optional( element ) ) {
				return "dependency-mismatch";
			}
			
			if ( /[^0-9 \-]+/.test( value ) ) {
				return false;
			}
			var nCheck = 0,
				nDigit = 0,
				bEven = false,
				n, cDigit;

			value = value.replace( /\D/g, "" );

			
			if ( value.length < 13 || value.length > 19 ) {
				return false;
			}

			for ( n = value.length - 1; n >= 0; n--) {
				cDigit = value.charAt( n );
				nDigit = parseInt( cDigit, 10 );
				if ( bEven ) {
					if ( ( nDigit *= 2 ) > 9 ) {
						nDigit -= 9;
					}
				}
				nCheck += nDigit;
				bEven = !bEven;
			}

			return ( nCheck % 10 ) === 0;
		},

		
		minlength: function( value, element, param ) {
			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
			return this.optional( element ) || length >= param;
		},

		
		maxlength: function( value, element, param ) {
			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
			return this.optional( element ) || length <= param;
		},

		
		rangelength: function( value, element, param ) {
			var length = $.isArray( value ) ? value.length : this.getLength( value, element );
			return this.optional( element ) || ( length >= param[ 0 ] && length <= param[ 1 ] );
		},

		
		min: function( value, element, param ) {
			return this.optional( element ) || value >= param;
		},

		
		max: function( value, element, param ) {
			return this.optional( element ) || value <= param;
		},

		
		range: function( value, element, param ) {
			return this.optional( element ) || ( value >= param[ 0 ] && value <= param[ 1 ] );
		},

		
		equalTo: function( value, element, param ) {
			
			var target = $( param );
			if ( this.settings.onfocusout ) {
				target.unbind( ".validate-equalTo" ).bind( "blur.validate-equalTo", function() {
					$( element ).valid();
				});
			}
			return value === target.val();
		},

		
		remote: function( value, element, param ) {
			if ( this.optional( element ) ) {
				return "dependency-mismatch";
			}

			var previous = this.previousValue( element ),
				validator, data;

			if (!this.settings.messages[ element.name ] ) {
				this.settings.messages[ element.name ] = {};
			}
			previous.originalMessage = this.settings.messages[ element.name ].remote;
			this.settings.messages[ element.name ].remote = previous.message;

			param = typeof param === "string" && { url: param } || param;

			if ( previous.old === value ) {
				return previous.valid;
			}

			previous.old = value;
			validator = this;
			this.startRequest( element );
			data = {};
			data[ element.name ] = value;
			$.ajax( $.extend( true, {
				url: param,
				mode: "abort",
				port: "validate" + element.name,
				dataType: "json",
				data: data,
				context: validator.currentForm,
				success: function( response ) {
					var valid = response === true || response === "true",
						errors, message, submitted;

					validator.settings.messages[ element.name ].remote = previous.originalMessage;
					if ( valid ) {
						submitted = validator.formSubmitted;
						validator.prepareElement( element );
						validator.formSubmitted = submitted;
						validator.successList.push( element );
						delete validator.invalid[ element.name ];
						validator.showErrors();
					} else {
						errors = {};
						message = response || validator.defaultMessage( element, "remote" );
						errors[ element.name ] = previous.message = $.isFunction( message ) ? message( value ) : message;
						validator.invalid[ element.name ] = true;
						validator.showErrors( errors );
					}
					previous.valid = valid;
					validator.stopRequest( element, valid );
				}
			}, param ) );
			return "pending";
		}

	}

});

$.format = function deprecated() {
	throw "$.format has been deprecated. Please use $.validator.format instead.";
};


var pendingRequests = {},
	ajax;
if ( $.ajaxPrefilter ) {
	$.ajaxPrefilter(function( settings, _, xhr ) {
		var port = settings.port;
		if ( settings.mode === "abort" ) {
			if ( pendingRequests[port] ) {
				pendingRequests[port].abort();
			}
			pendingRequests[port] = xhr;
		}
	});
} else {
	ajax = $.ajax;
	$.ajax = function( settings ) {
		var mode = ( "mode" in settings ? settings : $.ajaxSettings ).mode,
			port = ( "port" in settings ? settings : $.ajaxSettings ).port;
		if ( mode === "abort" ) {
			if ( pendingRequests[port] ) {
				pendingRequests[port].abort();
			}
			pendingRequests[port] = ajax.apply(this, arguments);
			return pendingRequests[port];
		}
		return ajax.apply(this, arguments);
	};
}


$.extend($.fn, {
	validateDelegate: function( delegate, type, handler ) {
		return this.bind(type, function( event ) {
			var target = $(event.target);
			if ( target.is(delegate) ) {
				return handler.apply(target, arguments);
			}
		});
	}
});

}));;
/* NUGET: BEGIN LICENSE TEXT
 *
 * Microsoft grants you the right to use these script files for the sole
 * purpose of either: (i) interacting through your browser with the Microsoft
 * website or online service, subject to the applicable licensing or use
 * terms; or (ii) using the files as included with a Microsoft product subject
 * to that product's license terms. Microsoft reserves all other rights to the
 * files not expressly granted by Microsoft, whether by implication, estoppel
 * or otherwise. Insofar as a script file is dual licensed under GPL,
 * Microsoft neither took the code under GPL nor distributes it thereunder but
 * under the terms set out in this paragraph. All notices and licenses
 * below are for informational purposes only.
 *
 * NUGET: END LICENSE TEXT */
/*
** Unobtrusive validation support library for jQuery and jQuery Validate
** Copyright (C) Microsoft Corporation. All rights reserved.
*/
(function(a){var d=a.validator,b,e="unobtrusiveValidation";function c(a,b,c){a.rules[b]=c;if(a.message)a.messages[b]=a.message}function j(a){return a.replace(/^\s+|\s+$/g,"").split(/\s*,\s*/g)}function f(a){return a.replace(/([!"#$%&'()*+,./:;<=>?@\[\\\]^`{|}~])/g,"\\$1")}function h(a){return a.substr(0,a.lastIndexOf(".")+1)}function g(a,b){if(a.indexOf("*.")===0)a=a.replace("*.",b);return a}function m(c,e){var b=a(this).find("[data-valmsg-for='"+f(e[0].name)+"']"),d=b.attr("data-valmsg-replace"),g=d?a.parseJSON(d)!==false:null;b.removeClass("field-validation-valid").addClass("field-validation-error");c.data("unobtrusiveContainer",b);if(g){b.empty();c.removeClass("input-validation-error").appendTo(b)}else c.hide()}function l(e,d){var c=a(this).find("[data-valmsg-summary=true]"),b=c.find("ul");if(b&&b.length&&d.errorList.length){b.empty();c.addClass("validation-summary-errors").removeClass("validation-summary-valid");a.each(d.errorList,function(){a("<li />").html(this.message).appendTo(b)})}}function k(d){var b=d.data("unobtrusiveContainer"),c=b.attr("data-valmsg-replace"),e=c?a.parseJSON(c):null;if(b){b.addClass("field-validation-valid").removeClass("field-validation-error");d.removeData("unobtrusiveContainer");e&&b.empty()}}function n(){var b=a(this),c="__jquery_unobtrusive_validation_form_reset";if(b.data(c))return;b.data(c,true);try{b.data("validator").resetForm()}finally{b.removeData(c)}b.find(".validation-summary-errors").addClass("validation-summary-valid").removeClass("validation-summary-errors");b.find(".field-validation-error").addClass("field-validation-valid").removeClass("field-validation-error").removeData("unobtrusiveContainer").find(">*").removeData("unobtrusiveContainer")}function i(b){var c=a(b),f=c.data(e),i=a.proxy(n,b),g=d.unobtrusive.options||{},h=function(e,d){var c=g[e];c&&a.isFunction(c)&&c.apply(b,d)};if(!f){f={options:{errorClass:g.errorClass||"input-validation-error",errorElement:g.errorElement||"span",errorPlacement:function(){m.apply(b,arguments);h("errorPlacement",arguments)},invalidHandler:function(){l.apply(b,arguments);h("invalidHandler",arguments)},messages:{},rules:{},success:function(){k.apply(b,arguments);h("success",arguments)}},attachValidation:function(){c.off("reset."+e,i).on("reset."+e,i).validate(this.options)},validate:function(){c.validate();return c.valid()}};c.data(e,f)}return f}d.unobtrusive={adapters:[],parseElement:function(b,h){var d=a(b),f=d.parents("form")[0],c,e,g;if(!f)return;c=i(f);c.options.rules[b.name]=e={};c.options.messages[b.name]=g={};a.each(this.adapters,function(){var c="data-val-"+this.name,i=d.attr(c),h={};if(i!==undefined){c+="-";a.each(this.params,function(){h[this]=d.attr(c+this)});this.adapt({element:b,form:f,message:i,params:h,rules:e,messages:g})}});a.extend(e,{__dummy__:true});!h&&c.attachValidation()},parse:function(c){var b=a(c),e=b.parents().addBack().filter("form").add(b.find("form")).has("[data-val=true]");b.find("[data-val=true]").each(function(){d.unobtrusive.parseElement(this,true)});e.each(function(){var a=i(this);a&&a.attachValidation()})}};b=d.unobtrusive.adapters;b.add=function(c,a,b){if(!b){b=a;a=[]}this.push({name:c,params:a,adapt:b});return this};b.addBool=function(a,b){return this.add(a,function(d){c(d,b||a,true)})};b.addMinMax=function(e,g,f,a,d,b){return this.add(e,[d||"min",b||"max"],function(b){var e=b.params.min,d=b.params.max;if(e&&d)c(b,a,[e,d]);else if(e)c(b,g,e);else d&&c(b,f,d)})};b.addSingleVal=function(a,b,d){return this.add(a,[b||"val"],function(e){c(e,d||a,e.params[b])})};d.addMethod("__dummy__",function(){return true});d.addMethod("regex",function(b,c,d){var a;if(this.optional(c))return true;a=(new RegExp(d)).exec(b);return a&&a.index===0&&a[0].length===b.length});d.addMethod("nonalphamin",function(c,d,b){var a;if(b){a=c.match(/\W/g);a=a&&a.length>=b}return a});if(d.methods.extension){b.addSingleVal("accept","mimtype");b.addSingleVal("extension","extension")}else b.addSingleVal("extension","extension","accept");b.addSingleVal("regex","pattern");b.addBool("creditcard").addBool("date").addBool("digits").addBool("email").addBool("number").addBool("url");b.addMinMax("length","minlength","maxlength","rangelength").addMinMax("range","min","max","range");b.addMinMax("minlength","minlength").addMinMax("maxlength","minlength","maxlength");b.add("equalto",["other"],function(b){var i=h(b.element.name),j=b.params.other,d=g(j,i),e=a(b.form).find(":input").filter("[name='"+f(d)+"']")[0];c(b,"equalTo",e)});b.add("required",function(a){(a.element.tagName.toUpperCase()!=="INPUT"||a.element.type.toUpperCase()!=="CHECKBOX")&&c(a,"required",true)});b.add("remote",["url","type","additionalfields"],function(b){var d={url:b.params.url,type:b.params.type||"GET",data:{}},e=h(b.element.name);a.each(j(b.params.additionalfields||b.element.name),function(i,h){var c=g(h,e);d.data[c]=function(){var d=a(b.form).find(":input").filter("[name='"+f(c)+"']");return d.is(":checkbox")?d.filter(":checked").val()||d.filter(":hidden").val()||"":d.is(":radio")?d.filter(":checked").val()||"":d.val()}});c(b,"remote",d)});b.add("password",["min","nonalphamin","regex"],function(a){a.params.min&&c(a,"minlength",a.params.min);a.params.nonalphamin&&c(a,"nonalphamin",a.params.nonalphamin);a.params.regex&&c(a,"regex",a.params.regex)});a(function(){d.unobtrusive.parse(document)})})(jQuery);;
(function(e){var o="left",n="right",d="up",v="down",c="in",w="out",l="none",r="auto",k="swipe",s="pinch",x="tap",i="doubletap",b="longtap",A="horizontal",t="vertical",h="all",q=10,f="start",j="move",g="end",p="cancel",a="ontouchstart" in window,y="TouchSwipe";var m={fingers:1,threshold:75,cancelThreshold:null,pinchThreshold:20,maxTimeThreshold:null,fingerReleaseThreshold:250,longTapThreshold:500,doubleTapThreshold:200,swipe:null,swipeLeft:null,swipeRight:null,swipeUp:null,swipeDown:null,swipeStatus:null,pinchIn:null,pinchOut:null,pinchStatus:null,click:null,tap:null,doubleTap:null,longTap:null,triggerOnTouchEnd:true,triggerOnTouchLeave:false,allowPageScroll:"auto",fallbackToMouseEvents:true,excludedElements:"button, input, select, textarea, a, .noSwipe"};e.fn.swipe=function(D){var C=e(this),B=C.data(y);if(B&&typeof D==="string"){if(B[D]){return B[D].apply(this,Array.prototype.slice.call(arguments,1))}else{e.error("Method "+D+" does not exist on jQuery.swipe")}}else{if(!B&&(typeof D==="object"||!D)){return u.apply(this,arguments)}}return C};e.fn.swipe.defaults=m;e.fn.swipe.phases={PHASE_START:f,PHASE_MOVE:j,PHASE_END:g,PHASE_CANCEL:p};e.fn.swipe.directions={LEFT:o,RIGHT:n,UP:d,DOWN:v,IN:c,OUT:w};e.fn.swipe.pageScroll={NONE:l,HORIZONTAL:A,VERTICAL:t,AUTO:r};e.fn.swipe.fingers={ONE:1,TWO:2,THREE:3,ALL:h};function u(B){if(B&&(B.allowPageScroll===undefined&&(B.swipe!==undefined||B.swipeStatus!==undefined))){B.allowPageScroll=l}if(B.click!==undefined&&B.tap===undefined){B.tap=B.click}if(!B){B={}}B=e.extend({},e.fn.swipe.defaults,B);return this.each(function(){var D=e(this);var C=D.data(y);if(!C){C=new z(this,B);D.data(y,C)}})}function z(a0,aq){var av=(a||!aq.fallbackToMouseEvents),G=av?"touchstart":"mousedown",au=av?"touchmove":"mousemove",R=av?"touchend":"mouseup",P=av?null:"mouseleave",az="touchcancel";var ac=0,aL=null,Y=0,aX=0,aV=0,D=1,am=0,aF=0,J=null;var aN=e(a0);var W="start";var T=0;var aM=null;var Q=0,aY=0,a1=0,aa=0,K=0;var aS=null;try{aN.bind(G,aJ);aN.bind(az,a5)}catch(ag){e.error("events not supported "+G+","+az+" on jQuery.swipe")}this.enable=function(){aN.bind(G,aJ);aN.bind(az,a5);return aN};this.disable=function(){aG();return aN};this.destroy=function(){aG();aN.data(y,null);return aN};this.option=function(a8,a7){if(aq[a8]!==undefined){if(a7===undefined){return aq[a8]}else{aq[a8]=a7}}else{e.error("Option "+a8+" does not exist on jQuery.swipe.options")}};function aJ(a9){if(ax()){return}if(e(a9.target).closest(aq.excludedElements,aN).length>0){return}var ba=a9.originalEvent?a9.originalEvent:a9;var a8,a7=a?ba.touches[0]:ba;W=f;if(a){T=ba.touches.length}else{a9.preventDefault()}ac=0;aL=null;aF=null;Y=0;aX=0;aV=0;D=1;am=0;aM=af();J=X();O();if(!a||(T===aq.fingers||aq.fingers===h)||aT()){ae(0,a7);Q=ao();if(T==2){ae(1,ba.touches[1]);aX=aV=ap(aM[0].start,aM[1].start)}if(aq.swipeStatus||aq.pinchStatus){a8=L(ba,W)}}else{a8=false}if(a8===false){W=p;L(ba,W);return a8}else{ak(true)}}function aZ(ba){var bd=ba.originalEvent?ba.originalEvent:ba;if(W===g||W===p||ai()){return}var a9,a8=a?bd.touches[0]:bd;var bb=aD(a8);aY=ao();if(a){T=bd.touches.length}W=j;if(T==2){if(aX==0){ae(1,bd.touches[1]);aX=aV=ap(aM[0].start,aM[1].start)}else{aD(bd.touches[1]);aV=ap(aM[0].end,aM[1].end);aF=an(aM[0].end,aM[1].end)}D=a3(aX,aV);am=Math.abs(aX-aV)}if((T===aq.fingers||aq.fingers===h)||!a||aT()){aL=aH(bb.start,bb.end);ah(ba,aL);ac=aO(bb.start,bb.end);Y=aI();aE(aL,ac);if(aq.swipeStatus||aq.pinchStatus){a9=L(bd,W)}if(!aq.triggerOnTouchEnd||aq.triggerOnTouchLeave){var a7=true;if(aq.triggerOnTouchLeave){var bc=aU(this);a7=B(bb.end,bc)}if(!aq.triggerOnTouchEnd&&a7){W=ay(j)}else{if(aq.triggerOnTouchLeave&&!a7){W=ay(g)}}if(W==p||W==g){L(bd,W)}}}else{W=p;L(bd,W)}if(a9===false){W=p;L(bd,W)}}function I(a7){var a8=a7.originalEvent;if(a){if(a8.touches.length>0){C();return true}}if(ai()){T=aa}a7.preventDefault();aY=ao();Y=aI();if(a6()){W=p;L(a8,W)}else{if(aq.triggerOnTouchEnd||(aq.triggerOnTouchEnd==false&&W===j)){W=g;L(a8,W)}else{if(!aq.triggerOnTouchEnd&&a2()){W=g;aB(a8,W,x)}else{if(W===j){W=p;L(a8,W)}}}}ak(false)}function a5(){T=0;aY=0;Q=0;aX=0;aV=0;D=1;O();ak(false)}function H(a7){var a8=a7.originalEvent;if(aq.triggerOnTouchLeave){W=ay(g);L(a8,W)}}function aG(){aN.unbind(G,aJ);aN.unbind(az,a5);aN.unbind(au,aZ);aN.unbind(R,I);if(P){aN.unbind(P,H)}ak(false)}function ay(bb){var ba=bb;var a9=aw();var a8=aj();var a7=a6();if(!a9||a7){ba=p}else{if(a8&&bb==j&&(!aq.triggerOnTouchEnd||aq.triggerOnTouchLeave)){ba=g}else{if(!a8&&bb==g&&aq.triggerOnTouchLeave){ba=p}}}return ba}function L(a9,a7){var a8=undefined;if(F()||S()){a8=aB(a9,a7,k)}else{if((M()||aT())&&a8!==false){a8=aB(a9,a7,s)}}if(aC()&&a8!==false){a8=aB(a9,a7,i)}else{if(al()&&a8!==false){a8=aB(a9,a7,b)}else{if(ad()&&a8!==false){a8=aB(a9,a7,x)}}}if(a7===p){a5(a9)}if(a7===g){if(a){if(a9.touches.length==0){a5(a9)}}else{a5(a9)}}return a8}function aB(ba,a7,a9){var a8=undefined;if(a9==k){aN.trigger("swipeStatus",[a7,aL||null,ac||0,Y||0,T]);if(aq.swipeStatus){a8=aq.swipeStatus.call(aN,ba,a7,aL||null,ac||0,Y||0,T);if(a8===false){return false}}if(a7==g&&aR()){aN.trigger("swipe",[aL,ac,Y,T]);if(aq.swipe){a8=aq.swipe.call(aN,ba,aL,ac,Y,T);if(a8===false){return false}}switch(aL){case o:aN.trigger("swipeLeft",[aL,ac,Y,T]);if(aq.swipeLeft){a8=aq.swipeLeft.call(aN,ba,aL,ac,Y,T)}break;case n:aN.trigger("swipeRight",[aL,ac,Y,T]);if(aq.swipeRight){a8=aq.swipeRight.call(aN,ba,aL,ac,Y,T)}break;case d:aN.trigger("swipeUp",[aL,ac,Y,T]);if(aq.swipeUp){a8=aq.swipeUp.call(aN,ba,aL,ac,Y,T)}break;case v:aN.trigger("swipeDown",[aL,ac,Y,T]);if(aq.swipeDown){a8=aq.swipeDown.call(aN,ba,aL,ac,Y,T)}break}}}if(a9==s){aN.trigger("pinchStatus",[a7,aF||null,am||0,Y||0,T,D]);if(aq.pinchStatus){a8=aq.pinchStatus.call(aN,ba,a7,aF||null,am||0,Y||0,T,D);if(a8===false){return false}}if(a7==g&&a4()){switch(aF){case c:aN.trigger("pinchIn",[aF||null,am||0,Y||0,T,D]);if(aq.pinchIn){a8=aq.pinchIn.call(aN,ba,aF||null,am||0,Y||0,T,D)}break;case w:aN.trigger("pinchOut",[aF||null,am||0,Y||0,T,D]);if(aq.pinchOut){a8=aq.pinchOut.call(aN,ba,aF||null,am||0,Y||0,T,D)}break}}}if(a9==x){if(a7===p||a7===g){clearTimeout(aS);if(V()&&!E()){K=ao();aS=setTimeout(e.proxy(function(){K=null;aN.trigger("tap",[ba.target]);if(aq.tap){a8=aq.tap.call(aN,ba,ba.target)}},this),aq.doubleTapThreshold)}else{K=null;aN.trigger("tap",[ba.target]);if(aq.tap){a8=aq.tap.call(aN,ba,ba.target)}}}}else{if(a9==i){if(a7===p||a7===g){clearTimeout(aS);K=null;aN.trigger("doubletap",[ba.target]);if(aq.doubleTap){a8=aq.doubleTap.call(aN,ba,ba.target)}}}else{if(a9==b){if(a7===p||a7===g){clearTimeout(aS);K=null;aN.trigger("longtap",[ba.target]);if(aq.longTap){a8=aq.longTap.call(aN,ba,ba.target)}}}}}return a8}function aj(){var a7=true;if(aq.threshold!==null){a7=ac>=aq.threshold}return a7}function a6(){var a7=false;if(aq.cancelThreshold!==null&&aL!==null){a7=(aP(aL)-ac)>=aq.cancelThreshold}return a7}function ab(){if(aq.pinchThreshold!==null){return am>=aq.pinchThreshold}return true}function aw(){var a7;if(aq.maxTimeThreshold){if(Y>=aq.maxTimeThreshold){a7=false}else{a7=true}}else{a7=true}return a7}function ah(a7,a8){if(aq.allowPageScroll===l||aT()){a7.preventDefault()}else{var a9=aq.allowPageScroll===r;switch(a8){case o:if((aq.swipeLeft&&a9)||(!a9&&aq.allowPageScroll!=A)){a7.preventDefault()}break;case n:if((aq.swipeRight&&a9)||(!a9&&aq.allowPageScroll!=A)){a7.preventDefault()}break;case d:if((aq.swipeUp&&a9)||(!a9&&aq.allowPageScroll!=t)){a7.preventDefault()}break;case v:if((aq.swipeDown&&a9)||(!a9&&aq.allowPageScroll!=t)){a7.preventDefault()}break}}}function a4(){var a8=aK();var a7=U();var a9=ab();return a8&&a7&&a9}function aT(){return !!(aq.pinchStatus||aq.pinchIn||aq.pinchOut)}function M(){return !!(a4()&&aT())}function aR(){var ba=aw();var bc=aj();var a9=aK();var a7=U();var a8=a6();var bb=!a8&&a7&&a9&&bc&&ba;return bb}function S(){return !!(aq.swipe||aq.swipeStatus||aq.swipeLeft||aq.swipeRight||aq.swipeUp||aq.swipeDown)}function F(){return !!(aR()&&S())}function aK(){return((T===aq.fingers||aq.fingers===h)||!a)}function U(){return aM[0].end.x!==0}function a2(){return !!(aq.tap)}function V(){return !!(aq.doubleTap)}function aQ(){return !!(aq.longTap)}function N(){if(K==null){return false}var a7=ao();return(V()&&((a7-K)<=aq.doubleTapThreshold))}function E(){return N()}function at(){return((T===1||!a)&&(isNaN(ac)||ac===0))}function aW(){return((Y>aq.longTapThreshold)&&(ac<q))}function ad(){return !!(at()&&a2())}function aC(){return !!(N()&&V())}function al(){return !!(aW()&&aQ())}function C(){a1=ao();aa=event.touches.length+1}function O(){a1=0;aa=0}function ai(){var a7=false;if(a1){var a8=ao()-a1;if(a8<=aq.fingerReleaseThreshold){a7=true}}return a7}function ax(){return !!(aN.data(y+"_intouch")===true)}function ak(a7){if(a7===true){aN.bind(au,aZ);aN.bind(R,I);if(P){aN.bind(P,H)}}else{aN.unbind(au,aZ,false);aN.unbind(R,I,false);if(P){aN.unbind(P,H,false)}}aN.data(y+"_intouch",a7===true)}function ae(a8,a7){var a9=a7.identifier!==undefined?a7.identifier:0;aM[a8].identifier=a9;aM[a8].start.x=aM[a8].end.x=a7.pageX||a7.clientX;aM[a8].start.y=aM[a8].end.y=a7.pageY||a7.clientY;return aM[a8]}function aD(a7){var a9=a7.identifier!==undefined?a7.identifier:0;var a8=Z(a9);a8.end.x=a7.pageX||a7.clientX;a8.end.y=a7.pageY||a7.clientY;return a8}function Z(a8){for(var a7=0;a7<aM.length;a7++){if(aM[a7].identifier==a8){return aM[a7]}}}function af(){var a7=[];for(var a8=0;a8<=5;a8++){a7.push({start:{x:0,y:0},end:{x:0,y:0},identifier:0})}return a7}function aE(a7,a8){a8=Math.max(a8,aP(a7));J[a7].distance=a8}function aP(a7){return J[a7].distance}function X(){var a7={};a7[o]=ar(o);a7[n]=ar(n);a7[d]=ar(d);a7[v]=ar(v);return a7}function ar(a7){return{direction:a7,distance:0}}function aI(){return aY-Q}function ap(ba,a9){var a8=Math.abs(ba.x-a9.x);var a7=Math.abs(ba.y-a9.y);return Math.round(Math.sqrt(a8*a8+a7*a7))}function a3(a7,a8){var a9=(a8/a7)*1;return a9.toFixed(2)}function an(){if(D<1){return w}else{return c}}function aO(a8,a7){return Math.round(Math.sqrt(Math.pow(a7.x-a8.x,2)+Math.pow(a7.y-a8.y,2)))}function aA(ba,a8){var a7=ba.x-a8.x;var bc=a8.y-ba.y;var a9=Math.atan2(bc,a7);var bb=Math.round(a9*180/Math.PI);if(bb<0){bb=360-Math.abs(bb)}return bb}function aH(a8,a7){var a9=aA(a8,a7);if((a9<=45)&&(a9>=0)){return o}else{if((a9<=360)&&(a9>=315)){return o}else{if((a9>=135)&&(a9<=225)){return n}else{if((a9>45)&&(a9<135)){return v}else{return d}}}}}function ao(){var a7=new Date();return a7.getTime()}function aU(a7){a7=e(a7);var a9=a7.offset();var a8={left:a9.left,right:a9.left+a7.outerWidth(),top:a9.top,bottom:a9.top+a7.outerHeight()};return a8}function B(a7,a8){return(a7.x>a8.left&&a7.x<a8.right&&a7.y>a8.top&&a7.y<a8.bottom)}}})(jQuery);;
/**
 * alertifyjs 1.6.0 http://alertifyjs.com
 * AlertifyJS is a javascript framework for developing pretty browser dialogs and notifications.
 * Copyright 2015 Mohammad Younes <Mohammad@alertifyjs.com> (http://alertifyjs.com) 
 * Licensed under MIT <http://opensource.org/licenses/mit-license.php>*/
( function ( window ) {
    'use strict';
    
    /**
     * Keys enum
     * @type {Object}
     */
    var keys = {
        ENTER: 13,
        ESC: 27,
        F1: 112,
        F12: 123,
        LEFT: 37,
        RIGHT: 39
    };
    /**
     * Default options 
     * @type {Object}
     */
    var defaults = {
        modal:true,
        basic:false,
        frameless:false,
        movable:true,
        moveBounded:false,
        resizable:true,
        closable:true,
        closableByDimmer:true,
        maximizable:true,
        startMaximized:false,
        pinnable:true,
        pinned:true,
        padding: true,
        overflow:true,
        maintainFocus:true,
        transition:'pulse',
        autoReset:true,
        notifier:{
            delay:5,
            position:'bottom-right'
        },
        glossary:{
            title:'Xổ Số Trực Tiếp 24H',
            ok: 'Đồng ý',
            cancel: 'Đóng',
            acccpt: 'Đồng ý',
            deny: 'Hủy',
            confirm: 'Xác nhận',
            decline: 'Từ chối',
            close: 'Đóng',
            maximize: 'Phóng to',
            restore: 'Quay lại',
        },
        theme:{
            input:'ajs-input',
            ok:'ajs-ok',
            cancel:'ajs-cancel',
        }
    };
    
    /*holds open dialogs instances*/
    var openDialogs = [];

    /**
     * [Helper]  Adds the specified class(es) to the element.
     *
     * @element {node}      The element
     * @className {string}  One or more space-separated classes to be added to the class attribute of the element.
     * 
     * @return {undefined}
     */
    function addClass(element,classNames){
        element.className += ' ' + classNames;
    }
    
    /**
     * [Helper]  Removes the specified class(es) from the element.
     *
     * @element {node}      The element
     * @className {string}  One or more space-separated classes to be removed from the class attribute of the element.
     * 
     * @return {undefined}
     */
    function removeClass(element,classNames){
        var classes = classNames.split(' ');
        for(var x=0;x<classes.length;x+=1){
            element.className = element.className.replace(' ' + classes[x], '');
        }
    }

    /**
     * [Helper]  Checks if the document is RTL
     *
     * @return {Boolean} True if the document is RTL, false otherwise.
     */
    function isRightToLeft(){
        return window.getComputedStyle(document.body).direction === 'rtl';
    }
    /**
     * [Helper]  Get the document current scrollTop
     *
     * @return {Number} current document scrollTop value
     */
    function getScrollTop(){
        return ((document.documentElement && document.documentElement.scrollTop) || document.body.scrollTop);
    }

    /**
     * [Helper]  Get the document current scrollLeft
     *
     * @return {Number} current document scrollLeft value
     */
    function getScrollLeft(){
        return ((document.documentElement && document.documentElement.scrollLeft) || document.body.scrollLeft);
    }

    /**
    * Helper: clear contents
    *
    */
    function clearContents(element){
        while (element.lastChild) {
            element.removeChild(element.lastChild);
        }
    }
    /**
     * Extends a given prototype by merging properties from base into sub.
     *
     * @sub {Object} sub The prototype being overwritten.
     * @base {Object} base The prototype being written.
     *
     * @return {Object} The extended prototype.
     */
    function copy(src) {
        if(null === src){
            return src;
        }
        var cpy;
        if(Array.isArray(src)){
            cpy = [];
            for(var x=0;x<src.length;x+=1){
                cpy.push(copy(src[x]));
            }
            return cpy;
        }
      
        if(src instanceof Date){
            return new Date(src.getTime());
        }
      
        if(src instanceof RegExp){
            cpy = new RegExp(src.source);
            cpy.global = src.global;
            cpy.ignoreCase = src.ignoreCase;
            cpy.multiline = src.multiline;
            cpy.lastIndex = src.lastIndex;
            return cpy;
        }
        
        if(typeof src === 'object'){
            cpy = {};
            /* copy dialog pototype over definition.*/
            for (var prop in src) {
                if (src.hasOwnProperty(prop)) {
                    cpy[prop] = copy(src[prop]);
                }
            }
            return cpy;
        }
        return src;
    }
    /**
      * Helper: destruct the dialog
      *
      */
    function destruct(instance, initialize){
        /*delete the dom and it's references.*/
        var root = instance.elements.root;
        root.parentNode.removeChild(root);
        delete instance.elements;
        /*copy back initial settings.*/
        instance.settings = copy(instance.__settings);
        /*re-reference init function.*/
        instance.__init = initialize;
        /*delete __internal variable to allow re-initialization.*/
        delete instance.__internal;
    }

    /**
     * Use a closure to return proper event listener method. Try to use
     * `addEventListener` by default but fallback to `attachEvent` for
     * unsupported browser. The closure simply ensures that the test doesn't
     * happen every time the method is called.
     *
     * @param    {Node}     el    Node element
     * @param    {String}   event Event type
     * @param    {Function} fn    Callback of event
     * @return   {Function}
     */
    var on = (function () {
        if (document.addEventListener) {
            return function (el, event, fn, useCapture) {
                el.addEventListener(event, fn, useCapture === true);
            };
        } else if (document.attachEvent) {
            return function (el, event, fn) {
                el.attachEvent('on' + event, fn);
            };
        }
    }());

    /**
     * Use a closure to return proper event listener method. Try to use
     * `removeEventListener` by default but fallback to `detachEvent` for
     * unsupported browser. The closure simply ensures that the test doesn't
     * happen every time the method is called.
     *
     * @param    {Node}     el    Node element
     * @param    {String}   event Event type
     * @param    {Function} fn    Callback of event
     * @return   {Function}
     */
    var off = (function () {
        if (document.removeEventListener) {
            return function (el, event, fn, useCapture) {
                el.removeEventListener(event, fn, useCapture === true);
            };
        } else if (document.detachEvent) {
            return function (el, event, fn) {
                el.detachEvent('on' + event, fn);
            };
        }
    }());

    /**
     * Prevent default event from firing
     *
     * @param  {Event} event Event object
     * @return {undefined}

    function prevent ( event ) {
        if ( event ) {
            if ( event.preventDefault ) {
                event.preventDefault();
            } else {
                event.returnValue = false;
            }
        }
    }
    */
    var transition = (function () {
        var t, type;
        var supported = false;
        var transitions = {
            'animation'        : 'animationend',
            'OAnimation'       : 'oAnimationEnd oanimationend',
            'msAnimation'      : 'MSAnimationEnd',
            'MozAnimation'     : 'animationend',
            'WebkitAnimation'  : 'webkitAnimationEnd'
        };

        for (t in transitions) {
            if (document.documentElement.style[t] !== undefined) {
                type = transitions[t];
                supported = true;
                break;
            }
        }

        return {
            type: type,
            supported: supported
        };
    }());

    /**
    * Creates event handler delegate that sends the instance as last argument.
    * 
    * @return {Function}    a function wrapper which sends the instance as last argument.
    */
    function delegate(context, method) {
        return function () {
            if (arguments.length > 0) {
                var args = [];
                for (var x = 0; x < arguments.length; x += 1) {
                    args.push(arguments[x]);
                }
                args.push(context);
                return method.apply(context, args);
            }
            return method.apply(context, [null, context]);
        };
    }
    /**
    * Helper for creating a dialog close event.
    * 
    * @return {object}
    */
    function createCloseEvent(index, button) {
        return {
            index: index,
            button: button,
            cancel: false
        };
    }


    /**
     * Super class for all dialogs
     *
     * @return {Object}		base dialog prototype
     */
    var dialog = (function () {
        var /*holds the list of used keys.*/
            usedKeys = [],
            /*dummy variable, used to trigger dom reflow.*/
            reflow = null,
            /*condition for detecting safari*/
            isSafari = window.navigator.userAgent.indexOf('Safari') > -1 && window.navigator.userAgent.indexOf('Chrome') < 0,
            /*dialog building blocks*/
            templates = {
                dimmer:'<div class="ajs-dimmer"></div>',
                /*tab index required to fire click event before body focus*/
                modal: '<div class="ajs-modal" tabindex="0"></div>',
                dialog: '<div class="ajs-dialog" tabindex="0"></div>',
                reset: '<button class="ajs-reset"></button>',
                commands: '<div class="ajs-commands"><button class="ajs-pin"></button><button class="ajs-maximize"></button><button class="ajs-close"></button></div>',
                header: '<div class="ajs-header"></div>',
                body: '<div class="ajs-body"></div>',
                content: '<div class="ajs-content"></div>',
                footer: '<div class="ajs-footer"></div>',
                buttons: { primary: '<div class="ajs-primary ajs-buttons"></div>', auxiliary: '<div class="ajs-auxiliary ajs-buttons"></div>' },
                button: '<button class="ajs-button"></button>',
                resizeHandle: '<div class="ajs-handle"></div>',
            },
            /*common class names*/
            classes = {
                base: 'alertify',
                prefix: 'ajs-',
                hidden: 'ajs-hidden',
                noSelection: 'ajs-no-selection',
                noOverflow: 'ajs-no-overflow',
                noPadding:'ajs-no-padding',
                modeless: 'ajs-modeless',
                movable: 'ajs-movable',
                resizable: 'ajs-resizable',
                capture: 'ajs-capture',
                fixed: 'ajs-fixed',
                closable:'ajs-closable',
                maximizable:'ajs-maximizable',
                maximize: 'ajs-maximize',
                restore: 'ajs-restore',
                pinnable:'ajs-pinnable',
                unpinned:'ajs-unpinned',
                pin:'ajs-pin',
                maximized: 'ajs-maximized',
                animationIn: 'ajs-in',
                animationOut: 'ajs-out',
                shake:'ajs-shake',
                basic:'ajs-basic',
                frameless:'ajs-frameless'
            };
			
        /**
         * Helper: initializes the dialog instance
         * 
         * @return	{Number}	The total count of currently open modals.
         */
        function initialize(instance){
            
            if(!instance.__internal){
				
                /*no need to expose init after this.*/
                delete instance.__init;
              
                /*keep a copy of initial dialog settings*/
                if(!instance.__settings){
                    instance.__settings = copy(instance.settings);
                }
                /*in case the script was included before body.*/
                /*after first dialog gets initialized, it won't be null anymore!*/
                if(null === reflow){
                    /* set tabindex attribute on body element this allows script to give it
                     focus after the dialog is closed
                     */
                    document.body.setAttribute( 'tabindex', '0' );
                }
				
                /*get dialog buttons/focus setup*/
                var setup;
                if(typeof instance.setup === 'function'){
                    setup = instance.setup();
                    setup.options = setup.options  || {};
                    setup.focus = setup.focus  || {};
                }else{
                    setup = {
                        buttons:[],
                        focus:{
                            element:null,
                            select:false
                        },
                        options:{
                        }
                    };
                }
                
                /*initialize hooks object.*/
                if(typeof instance.hooks !== 'object'){
                    instance.hooks = {};
                }

                /*copy buttons defintion*/
                var buttonsDefinition = [];
                if(Array.isArray(setup.buttons)){
                    for(var b=0;b<setup.buttons.length;b+=1){
                        var ref  = setup.buttons[b],
                            cpy = {};
                        for (var i in ref) {
                            if (ref.hasOwnProperty(i)) {
                                cpy[i] = ref[i];
                            }
                        }
                        buttonsDefinition.push(cpy);
                    }
                }

                var internal = instance.__internal = {
                    /**
                     * Flag holding the open state of the dialog
                     * 
                     * @type {Boolean}
                     */
                    isOpen:false,
                    /**
                     * Active element is the element that will receive focus after
                     * closing the dialog. It defaults as the body tag, but gets updated
                     * to the last focused element before the dialog was opened.
                     *
                     * @type {Node}
                     */
                    activeElement:document.body,
                    timerIn:undefined,
                    timerOut:undefined,
                    buttons: buttonsDefinition,
                    focus: setup.focus,
                    options: {
                        title: undefined,
                        modal: undefined,
                        basic:undefined,
                        frameless:undefined,
                        pinned: undefined,
                        movable: undefined,
                        moveBounded:undefined,
                        resizable: undefined,
                        autoReset: undefined,
                        closable: undefined,
                        closableByDimmer: undefined,
                        maximizable: undefined,
                        startMaximized: undefined,
                        pinnable: undefined,
                        transition: undefined,
                        padding:undefined,
                        overflow:undefined,
                        onshow:undefined,
                        onclose:undefined,
                        onfocus:undefined,
                    },
                    resetHandler:undefined,
                    beginMoveHandler:undefined,
                    beginResizeHandler:undefined,
                    bringToFrontHandler:undefined,
                    modalClickHandler:undefined,
                    buttonsClickHandler:undefined,
                    commandsClickHandler:undefined,
                    transitionInHandler:undefined,
                    transitionOutHandler:undefined,
                    destroy:undefined
                };
				
                                
                var elements = {};
                /*root node*/
                elements.root = document.createElement('div');
                
                elements.root.className = classes.base + ' ' + classes.hidden + ' ';
				
                elements.root.innerHTML = templates.dimmer + templates.modal;
                
                /*dimmer*/
                elements.dimmer = elements.root.firstChild;
				
                /*dialog*/
                elements.modal = elements.root.lastChild;
                elements.modal.innerHTML = templates.dialog;
                elements.dialog = elements.modal.firstChild;
                elements.dialog.innerHTML = templates.reset + templates.commands + templates.header + templates.body + templates.footer + templates.resizeHandle + templates.reset;

                /*reset links*/
                elements.reset = [];
                elements.reset.push(elements.dialog.firstChild);
                elements.reset.push(elements.dialog.lastChild);
                
                /*commands*/
                elements.commands = {};
                elements.commands.container = elements.reset[0].nextSibling;
                elements.commands.pin = elements.commands.container.firstChild;
                elements.commands.maximize = elements.commands.pin.nextSibling;
                elements.commands.close = elements.commands.maximize.nextSibling;
                
                /*header*/
                elements.header = elements.commands.container.nextSibling;

                /*body*/
                elements.body = elements.header.nextSibling;
                elements.body.innerHTML = templates.content;
                elements.content = elements.body.firstChild;

                /*footer*/
                elements.footer = elements.body.nextSibling;
                elements.footer.innerHTML = templates.buttons.auxiliary + templates.buttons.primary;
                
                /*resize handle*/
                elements.resizeHandle = elements.footer.nextSibling;

                /*buttons*/
                elements.buttons = {};
                elements.buttons.auxiliary = elements.footer.firstChild;
                elements.buttons.primary = elements.buttons.auxiliary.nextSibling;
                elements.buttons.primary.innerHTML = templates.button;
                elements.buttonTemplate = elements.buttons.primary.firstChild;
                /*remove button template*/
                elements.buttons.primary.removeChild(elements.buttonTemplate);
                               
                for(var x=0; x < instance.__internal.buttons.length; x+=1) {
                    var button = instance.__internal.buttons[x];
                    
                    /* add to the list of used keys.*/
                    if(usedKeys.indexOf(button.key) < 0){
                        usedKeys.push(button.key);
                    }

                    button.element = elements.buttonTemplate.cloneNode();
                    button.element.innerHTML = button.text;
                    if(typeof button.className === 'string' &&  button.className !== ''){
                        addClass(button.element, button.className);
                    }
                    for(var key in button.attrs){
                        if(key !== 'className' && button.attrs.hasOwnProperty(key)){
                            button.element.setAttribute(key, button.attrs[key]);
                        }
                    }
                    if(button.scope === 'auxiliary'){
                        elements.buttons.auxiliary.appendChild(button.element);
                    }else{
                        elements.buttons.primary.appendChild(button.element);
                    }
                }
                /*make elements pubic*/
                instance.elements = elements;
                
                /*save event handlers delegates*/
                internal.resetHandler = delegate(instance, onReset);
                internal.beginMoveHandler = delegate(instance, beginMove);
                internal.beginResizeHandler = delegate(instance, beginResize);
                internal.bringToFrontHandler = delegate(instance, bringToFront);
                internal.modalClickHandler = delegate(instance, modalClickHandler);
                internal.buttonsClickHandler = delegate(instance, buttonsClickHandler);
                internal.commandsClickHandler = delegate(instance, commandsClickHandler);
                internal.transitionInHandler = delegate(instance, handleTransitionInEvent);
                internal.transitionOutHandler = delegate(instance, handleTransitionOutEvent);

                
                /*settings*/
                instance.set('title', setup.options.title === undefined ? alertify.defaults.glossary.title : setup.options.title);
				
                instance.set('modal', setup.options.modal === undefined ? alertify.defaults.modal : setup.options.modal);
                instance.set('basic', setup.options.basic === undefined ? alertify.defaults.basic : setup.options.basic);
                instance.set('frameless', setup.options.frameless === undefined ? alertify.defaults.frameless : setup.options.frameless);
							
                instance.set('movable', setup.options.movable === undefined ? alertify.defaults.movable : setup.options.movable);
                instance.set('moveBounded', setup.options.moveBounded === undefined ? alertify.defaults.moveBounded : setup.options.moveBounded);
                instance.set('resizable', setup.options.resizable === undefined ? alertify.defaults.resizable : setup.options.resizable);
                instance.set('autoReset', setup.options.autoReset === undefined ? alertify.defaults.autoReset : setup.options.autoReset);
				
                instance.set('closable', setup.options.closable === undefined ? alertify.defaults.closable : setup.options.closable);
                instance.set('closableByDimmer', setup.options.closableByDimmer === undefined ? alertify.defaults.closableByDimmer : setup.options.closableByDimmer);
                instance.set('maximizable', setup.options.maximizable === undefined ? alertify.defaults.maximizable : setup.options.maximizable);
                instance.set('startMaximized', setup.options.startMaximized === undefined ? alertify.defaults.startMaximized : setup.options.startMaximized);
				
                instance.set('pinnable', setup.options.pinnable === undefined ? alertify.defaults.pinnable : setup.options.pinnable);
                instance.set('pinned', setup.options.pinned === undefined ? alertify.defaults.pinned : setup.options.pinned);
				
                instance.set('transition', setup.options.transition === undefined ? alertify.defaults.transition : setup.options.transition);

                instance.set('padding', setup.options.padding === undefined ? alertify.defaults.padding : setup.options.padding);
                instance.set('overflow', setup.options.overflow === undefined ? alertify.defaults.overflow : setup.options.overflow);
				

                /* allow dom customization*/
                if(typeof instance.build === 'function'){
                    instance.build();
                }
            }
            
            /*add to the end of the DOM tree.*/
            document.body.appendChild(instance.elements.root);
        }

        /**
         * Helper: maintains scroll position
         *
         */
        var scrollX, scrollY;
        function saveScrollPosition(){
            scrollX = getScrollLeft();
            scrollY = getScrollTop();
        }
        function restoreScrollPosition(){
            window.scrollTo(scrollX, scrollY);
        }

        /**
         * Helper: adds/removes no-overflow class from body
         *
         */
        function ensureNoOverflow(){
            var requiresNoOverflow = 0;
            for(var x=0;x<openDialogs.length;x+=1){
                var instance = openDialogs[x];
                if(instance.isModal() || instance.isMaximized()){
                    requiresNoOverflow+=1;
                }
            }
            if(requiresNoOverflow === 0){
                /*last open modal or last maximized one*/
                removeClass(document.body, classes.noOverflow);
            }else if(requiresNoOverflow > 0 && document.body.className.indexOf(classes.noOverflow) < 0){
                /*first open modal or first maximized one*/
                addClass(document.body, classes.noOverflow);
            }
        }
		
        /**
         * Sets the name of the transition used to show/hide the dialog
         * 
         * @param {Object} instance The dilog instance.
         *
         */
        function updateTransition(instance, value, oldValue){
            if(typeof oldValue === 'string'){
                removeClass(instance.elements.root,classes.prefix +  oldValue);
            }
            addClass(instance.elements.root, classes.prefix + value);
            reflow = instance.elements.root.offsetWidth;
        }
		
        /**
         * Toggles the dialog display mode
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function updateDisplayMode(instance){
            if(instance.get('modal')){

                /*make modal*/
                removeClass(instance.elements.root, classes.modeless);
				
                /*only if open*/
                if(instance.isOpen()){
                    unbindModelessEvents(instance);
					
                    /*in case a pinned modless dialog was made modal while open.*/
                    updateAbsPositionFix(instance);
					
                    ensureNoOverflow();
                }
            }else{
                /*make modelss*/
                addClass(instance.elements.root, classes.modeless);
								
                /*only if open*/
                if(instance.isOpen()){
                    bindModelessEvents(instance);
					
                    /*in case pin/unpin was called while a modal is open*/
                    updateAbsPositionFix(instance);
										
                    ensureNoOverflow();
                }
            }
        }

        /**
         * Toggles the dialog basic view mode 
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function updateBasicMode(instance){
            if (instance.get('basic')) {
                /* add class */
                addClass(instance.elements.root, classes.basic);
            } else {
                /* remove class */
                removeClass(instance.elements.root, classes.basic);
            }
        }

        /**
         * Toggles the dialog frameless view mode 
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function updateFramelessMode(instance){
            if (instance.get('frameless')) {
                /* add class */
                addClass(instance.elements.root, classes.frameless);
            } else {
                /* remove class */
                removeClass(instance.elements.root, classes.frameless);
            }
        }
		
        /**
         * Helper: Brings the modeless dialog to front, attached to modeless dialogs.
         *
         * @param {Event} event Focus event
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function bringToFront(event, instance){
            
            /* Do not bring to front if preceeded by an open modal */
            var index = openDialogs.indexOf(instance);
            for(var x=index+1;x<openDialogs.length;x+=1){
                if(openDialogs[x].isModal()){
                    return;
                }
            }
			
            /* Bring to front by making it the last child. */
            if(document.body.lastChild !== instance.elements.root){
                document.body.appendChild(instance.elements.root);
                /* also make sure its at the end of the list */
                openDialogs.splice(openDialogs.indexOf(instance),1);
                openDialogs.push(instance);
                setFocus(instance);
            }
			
            return false;
        }
		
        /**
         * Helper: reflects dialogs options updates
         *
         * @param {Object} instance The dilog instance.
         * @param {String} option The updated option name.
         *
         * @return	{undefined}	
         */
        function optionUpdated(instance, option, oldValue, newValue){
            switch(option){
            case 'title':
                instance.setHeader(newValue);
                break;
            case 'modal':
                updateDisplayMode(instance);
                break;
            case 'basic':
                updateBasicMode(instance);
                break;
            case 'frameless':
                updateFramelessMode(instance);
                break;
            case 'pinned':
                updatePinned(instance);
                break;
            case 'closable':
                updateClosable(instance);
                break;
            case 'maximizable':
                updateMaximizable(instance);
                break;
            case 'pinnable':
                updatePinnable(instance);
                break;
            case 'movable':
                updateMovable(instance);
                break;
            case 'resizable':
                updateResizable(instance);
                break;
            case 'transition':
                updateTransition(instance,newValue, oldValue);
                break;
            case 'padding':
                if(newValue){
                    removeClass(instance.elements.root, classes.noPadding);
                }else if(instance.elements.root.className.indexOf(classes.noPadding) < 0){
                    addClass(instance.elements.root, classes.noPadding);
                }
                break;
            case 'overflow':
                if(newValue){
                    removeClass(instance.elements.root, classes.noOverflow);
                }else if(instance.elements.root.className.indexOf(classes.noOverflow) < 0){
                    addClass(instance.elements.root, classes.noOverflow);
                }
                break;
            case 'transition':
                updateTransition(instance,newValue, oldValue);
                break;
            }

            /* internal on option updated event */
            if(typeof instance.hooks.onupdate === 'function'){
                instance.hooks.onupdate.call(instance, option, oldValue, newValue);
            }
        }
		
        /**
         * Helper: reflects dialogs options updates
         *
         * @param {Object} instance The dilog instance.
         * @param {Object} obj The object to set/get a value on/from.
         * @param {Function} callback The callback function to call if the key was found.
         * @param {String|Object} key A string specifying a propery name or a collection of key value pairs.
         * @param {Object} value Optional, the value associated with the key (in case it was a string).
         * @param {String} option The updated option name.
         *
         * @return	{Object} result object 
         *	The result objects has an 'op' property, indicating of this is a SET or GET operation.
         *		GET: 
         *		- found: a flag indicating if the key was found or not.
         *		- value: the property value.
         *		SET:
         *		- items: a list of key value pairs of the properties being set.
         *				each contains:
         *					- found: a flag indicating if the key was found or not.
         *					- key: the property key.
         *					- value: the property value.
         */
        function update(instance, obj, callback, key, value){
            var result = {op:undefined, items: [] };
            if(typeof value === 'undefined' && typeof key === 'string') {
                result.op = 'get';
                if(obj.hasOwnProperty(key)){
                    result.found = true;
                    result.value = obj[key];
                }else{
                    result.found = false;
                    result.value = undefined;
                }
            }
            else
            {
                var old;
                result.op = 'set';
                if(typeof key === 'object'){
                    /* set multiple */
                    var args = key;
                    for (var prop in args) {
                        if (obj.hasOwnProperty(prop)) {
                            if(obj[prop] !== args[prop]){
                                old = obj[prop];
                                obj[prop] = args[prop];
                                callback.call(instance,prop, old, args[prop]);
                            }
                            result.items.push({ 'key': prop, 'value': args[prop], 'found':true});
                        }else{
                            result.items.push({ 'key': prop, 'value': args[prop], 'found':false});
                        }
                    }
                } else if (typeof key === 'string'){
                    /* set single */
                    if (obj.hasOwnProperty(key)) {
                        if(obj[key] !== value){
                            old  = obj[key];
                            obj[key] = value;
                            callback.call(instance,key, old, value);
                        }
                        result.items.push({'key': key, 'value': value , 'found':true});
						
                    }else{
                        result.items.push({'key': key, 'value': value , 'found':false});
                    }
                } else {
                    /* invalid params */
                    throw new Error('args must be a string or object');
                }
            }
            return result;
        }
		

        /**
         * Triggers a close event.
         *
         * @param {Object} instance	The dilog instance.
         * 
         * @return {undefined}
         */
        function triggerClose(instance) {
            var found;
            triggerCallback(instance, function (button) {
                return found = (button.invokeOnClose === true);
            });
            if (!found && instance.isOpen()) {
                instance.close();
            }
        }

        /**
         * Dialogs commands event handler, attached to the dialog commands element.
         *
         * @param {Event} event	DOM event object.
         * @param {Object} instance	The dilog instance.
         * 
         * @return {undefined}
         */
        function commandsClickHandler(event, instance) {
            var target = event.srcElement || event.target;
            switch (target) {
            case instance.elements.commands.pin:
                if (!instance.isPinned()) {
                    pin(instance);
                } else {
                    unpin(instance);
                }
                break;
            case instance.elements.commands.maximize:
                if (!instance.isMaximized()) {
                    maximize(instance);
                } else {
                    restore(instance);
                }
                break;
            case instance.elements.commands.close:
                triggerClose(instance);
                break;
            }
            return false;
        }

        /**
         * Helper: pins the modeless dialog.
         *
         * @param {Object} instance	The dialog instance.
         * 
         * @return {undefined}
         */
        function pin(instance) {
            instance.set('pinned', true);
        }

        /**
         * Helper: unpins the modeless dialog.
         *
         * @param {Object} instance	The dilog instance.
         * 
         * @return {undefined}
         */
        function unpin(instance) {
            instance.set('pinned', false);
        }


        /**
         * Helper: enlarges the dialog to fill the entire screen.
         *
         * @param {Object} instance	The dilog instance.
         * 
         * @return {undefined}
         */
        function maximize(instance) {
            addClass(instance.elements.root, classes.maximized);
            if (instance.isOpen()) {
                ensureNoOverflow();
            }
        }

        /**
         * Helper: returns the dialog to its former size.
         *
         * @param {Object} instance	The dilog instance.
         * 
         * @return {undefined}
         */
        function restore(instance) {
            removeClass(instance.elements.root, classes.maximized);
            if (instance.isOpen()) {
                ensureNoOverflow();
            }
        }

        /**
         * Show or hide the maximize box.
         *
         * @param {Object} instance The dilog instance.
         * @param {Boolean} on True to add the behavior, removes it otherwise.
         *
         * @return {undefined}
         */
        function updatePinnable(instance) {
            if (instance.get('pinnable')) {
                addClass(instance.elements.root, classes.pinnable);
            } else {
                removeClass(instance.elements.root, classes.pinnable);
            }
        }

        /**
         * Helper: Fixes the absolutly positioned modal div position.
         *
         * @param {Object} instance The dialog instance.
         *
         * @return {undefined}
         */
        function addAbsPositionFix(instance) {
            var scrollLeft = getScrollLeft();
            instance.elements.modal.style.marginTop = getScrollTop() + 'px';
            instance.elements.modal.style.marginLeft = scrollLeft + 'px';
            instance.elements.modal.style.marginRight = (-scrollLeft) + 'px';
        }

        /**
         * Helper: Removes the absolutly positioned modal div position fix.
         *
         * @param {Object} instance The dialog instance.
         *
         * @return {undefined}
         */
        function removeAbsPositionFix(instance) {
            var marginTop = parseInt(instance.elements.modal.style.marginTop, 10);
            var marginLeft = parseInt(instance.elements.modal.style.marginLeft, 10);
            instance.elements.modal.style.marginTop = '';
            instance.elements.modal.style.marginLeft = '';
            instance.elements.modal.style.marginRight = '';

            if (instance.isOpen()) {
                var top = 0,
                    left = 0
                ;
                if (instance.elements.dialog.style.top !== '') {
                    top = parseInt(instance.elements.dialog.style.top, 10);
                }
                instance.elements.dialog.style.top = (top + (marginTop - getScrollTop())) + 'px';

                if (instance.elements.dialog.style.left !== '') {
                    left = parseInt(instance.elements.dialog.style.left, 10);
                }
                instance.elements.dialog.style.left = (left + (marginLeft - getScrollLeft())) + 'px';
            }
        }
        /**
         * Helper: Adds/Removes the absolutly positioned modal div position fix based on its pinned setting.
         *
         * @param {Object} instance The dialog instance.
         *
         * @return {undefined}
         */
        function updateAbsPositionFix(instance) {
            if (!instance.get('modal') && !instance.get('pinned')) {
                addAbsPositionFix(instance);
            } else {
                removeAbsPositionFix(instance);
            }
        }
        /**
         * Toggles the dialog position lock | modeless only.
         *
         * @param {Object} instance The dilog instance.
         * @param {Boolean} on True to make it modal, false otherwise.
         *
         * @return {undefined}
         */
        function updatePinned(instance) {
            if (instance.get('pinned')) {
                removeClass(instance.elements.root, classes.unpinned);
                if (instance.isOpen()) {
                    removeAbsPositionFix(instance);
                }
            } else {
                addClass(instance.elements.root, classes.unpinned);
                if (instance.isOpen() && !instance.isModal()) {
                    addAbsPositionFix(instance);
                }
            }
        }

        /**
         * Show or hide the maximize box.
         *
         * @param {Object} instance The dilog instance.
         * @param {Boolean} on True to add the behavior, removes it otherwise.
         *
         * @return {undefined}
         */
        function updateMaximizable(instance) {
            if (instance.get('maximizable')) {
                addClass(instance.elements.root, classes.maximizable);
            } else {
                removeClass(instance.elements.root, classes.maximizable);
            }
        }

        /**
         * Show or hide the close box.
         *
         * @param {Object} instance The dilog instance.
         * @param {Boolean} on True to add the behavior, removes it otherwise.
         *
         * @return {undefined}
         */
        function updateClosable(instance) {
            if (instance.get('closable')) {
                addClass(instance.elements.root, classes.closable);
                bindClosableEvents(instance);
            } else {
                removeClass(instance.elements.root, classes.closable);
                unbindClosableEvents(instance);
            }
        }

        var cancelClick = false;

        /**
         * Helper: closes the modal dialog when clicking the modal
         *
         * @param {Event} event	DOM event object.
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function modalClickHandler(event, instance) {
            var target = event.srcElement || event.target;
            if (!cancelClick && target === instance.elements.modal && instance.get('closableByDimmer') === true) {
                triggerClose(instance);
            }
            cancelClick = false;
            return false;
        }

        var cancelKeyup = false;
        /** 
         * Helper: triggers a button callback
         *
         * @param {Object}		The dilog instance.
         * @param {Function}	Callback to check which button triggered the event.
         *
         * @return {undefined}
         */
        function triggerCallback(instance, check) {
            for (var idx = 0; idx < instance.__internal.buttons.length; idx += 1) {
                var button = instance.__internal.buttons[idx];
                if (!button.element.disabled && check(button)) {
                    var closeEvent = createCloseEvent(idx, button);
                    if (typeof instance.callback === 'function') {
                        instance.callback.apply(instance, [closeEvent]);
                    }
                    if (closeEvent.cancel === false) {
                        instance.close();
                    }
                    break;
                }
            }
        }

        /**
         * Clicks event handler, attached to the dialog footer.
         *
         * @param {Event}		DOM event object.
         * @param {Object}		The dilog instance.
         * 
         * @return {undefined}
         */
        function buttonsClickHandler(event, instance) {
            var target = event.srcElement || event.target;
            triggerCallback(instance, function (button) {
                return button.element === target && (cancelKeyup = true);
            });
        }

        /**
         * Keyup event handler, attached to the document.body
         *
         * @param {Event}		DOM event object.
         * @param {Object}		The dilog instance.
         * 
         * @return {undefined}
         */
        function keyupHandler(event) {
            if (cancelKeyup) {
                cancelKeyup = false;
                return;
            }
            var instance = openDialogs[openDialogs.length - 1];
            var keyCode = event.keyCode;
            if (instance.__internal.buttons.length === 0 && keyCode === keys.ESC && instance.get('closable') === true) {
                triggerClose(instance);
                return false;
            }else if (usedKeys.indexOf(keyCode) > -1) {
                triggerCallback(instance, function (button) {
                    return button.key === keyCode;
                });
                return false;
            }
        }
        /**
        * Keydown event handler, attached to the document.body
        *
        * @param {Event}		DOM event object.
        * @param {Object}		The dilog instance.
        * 
        * @return {undefined}
        */
        function keydownHandler(event) {
            var instance = openDialogs[openDialogs.length - 1];
            var keyCode = event.keyCode;
            if (keyCode === keys.LEFT || keyCode === keys.RIGHT) {
                var buttons = instance.__internal.buttons;
                for (var x = 0; x < buttons.length; x += 1) {
                    if (document.activeElement === buttons[x].element) {
                        switch (keyCode) {
                        case keys.LEFT:
                            buttons[(x || buttons.length) - 1].element.focus();
                            return;
                        case keys.RIGHT:
                            buttons[(x + 1) % buttons.length].element.focus();
                            return;
                        }
                    }
                }
            }else if (keyCode < keys.F12 + 1 && keyCode > keys.F1 - 1 && usedKeys.indexOf(keyCode) > -1) {
                event.preventDefault();
                event.stopPropagation();
                triggerCallback(instance, function (button) {
                    return button.key === keyCode;
                });
                return false;
            }
        }


        /**
         * Sets focus to proper dialog element
         *
         * @param {Object} instance The dilog instance.
         * @param {Node} [resetTarget=undefined] DOM element to reset focus to.
         *
         * @return {undefined}
         */
        function setFocus(instance, resetTarget) {
            if (resetTarget) {
                resetTarget.focus();
            } else {
                var focus = instance.__internal.focus;
                var element = focus.element;

                switch (typeof focus.element) {
                case 'number':
                    if (instance.__internal.buttons.length > focus.element) {
                        if (instance.get('basic') === true) {
                            element = instance.elements.reset[0];
                        } else {
                            element = instance.__internal.buttons[focus.element].element;
                        }
                    }
                    break;
                case 'string':
                    element = instance.elements.body.querySelector(focus.element);
                    break;
                case 'function':
                    element = focus.element.call(instance);
                    break;
                }
                
                if ((typeof element === 'undefined' || element === null) && instance.__internal.buttons.length === 0) {
                    element = instance.elements.reset[0];
                }
                if (element && element.focus) {
                    element.focus();
                    if (focus.select && element.select) {
                        element.select();
                    }
                }
            }
        }

        /**
         * Focus event handler, attached to document.body and dialogs own reset links.
         * handles the focus for modal dialogs only.
         *
         * @param {Event} event DOM focus event object.
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function onReset(event, instance) {

            if (!instance) {
                for (var x = openDialogs.length - 1; x > -1; x -= 1) {
                    if (openDialogs[x].isModal()) {
                        instance = openDialogs[x];
                        break;
                    }
                }
            }
            if (instance && instance.isModal()) {
                var resetTarget, target = event.srcElement || event.target;
                var lastResetElement = target === instance.elements.reset[1] || (instance.__internal.buttons.length === 0 && target === document.body);

                if (lastResetElement) {
                    if (instance.get('maximizable')) {
                        resetTarget = instance.elements.commands.maximize;
                    } else if (instance.get('closable')) {
                        resetTarget = instance.elements.commands.close;
                    }
                }
                if (resetTarget === undefined) {
                    if (typeof instance.__internal.focus.element === 'number') {
                        if (target === instance.elements.reset[0]) {
                            resetTarget = instance.elements.buttons.auxiliary.firstChild || instance.elements.buttons.primary.firstChild;
                        } else if (lastResetElement) {
                            resetTarget = instance.elements.reset[0];
                        }
                    } else {
                        if (target === instance.elements.reset[0]) {
                            resetTarget = instance.elements.buttons.primary.lastChild || instance.elements.buttons.auxiliary.lastChild;
                        }
                    }
                }
                setFocus(instance, resetTarget);
            }
        }
        /**
         * Transition in transitionend event handler. 
         *
         * @param {Event}		TransitionEnd event object.
         * @param {Object}		The dilog instance.
         *
         * @return {undefined}
         */
        function handleTransitionInEvent(event, instance) {
            clearTimeout(instance.__internal.timerIn);

            setFocus(instance);

            restoreScrollPosition();

            cancelKeyup = false;

            if (typeof instance.get('onfocus') === 'function') {
                instance.get('onfocus').call(instance);
            }

            off(instance.elements.dialog, transition.type, instance.__internal.transitionInHandler);

            removeClass(instance.elements.root, classes.animationIn);
        }

        /**
         * Transition out transitionend event handler. 
         *
         * @param {Event}		TransitionEnd event object.
         * @param {Object}		The dilog instance.
         *
         * @return {undefined}
         */
        function handleTransitionOutEvent(event, instance) {
            clearTimeout(instance.__internal.timerOut);
            off(instance.elements.dialog, transition.type, instance.__internal.transitionOutHandler);

            resetMove(instance);
            resetResize(instance);

            if (instance.isMaximized() && !instance.get('startMaximized')) {
                restore(instance);
            }

            if (alertify.defaults.maintainFocus && instance.__internal.activeElement) {
                instance.__internal.activeElement.focus();
                instance.__internal.activeElement = null;
            }
            
            if (typeof instance.__internal.destroy === 'function') {
                instance.__internal.destroy.apply(instance);
            }
        }
        /* Controls moving a dialog around */
        var movable = null,
            offsetX = 0,
            offsetY = 0,
            xProp = 'pageX',
            yProp = 'pageY',
            bounds = null,
            refreshTop = false,
            moveDelegate = null
        ;

        /**
         * Helper: sets the element top/left coordinates
         *
         * @param {Event} event	DOM event object.
         * @param {Node} element The element being moved.
         * 
         * @return {undefined}
         */
        function moveElement(event, element) {
            var left = (event[xProp] - offsetX),
                top  = (event[yProp] - offsetY);

            if(refreshTop){
                top -= document.body.scrollTop;
            }
           
            element.style.left = left + 'px';
            element.style.top = top + 'px';
           
        }
        /**
         * Helper: sets the element top/left coordinates within screen bounds
         *
         * @param {Event} event	DOM event object.
         * @param {Node} element The element being moved.
         * 
         * @return {undefined}
         */
        function moveElementBounded(event, element) {
            var left = (event[xProp] - offsetX),
                top  = (event[yProp] - offsetY);

            if(refreshTop){
                top -= document.body.scrollTop;
            }
            
            element.style.left = Math.min(bounds.maxLeft, Math.max(bounds.minLeft, left)) + 'px';
            if(refreshTop){
                element.style.top = Math.min(bounds.maxTop, Math.max(bounds.minTop, top)) + 'px';
            }else{
                element.style.top = Math.max(bounds.minTop, top) + 'px';
            }
        }
            

        /**
         * Triggers the start of a move event, attached to the header element mouse down event.
         * Adds no-selection class to the body, disabling selection while moving.
         *
         * @param {Event} event	DOM event object.
         * @param {Object} instance The dilog instance.
         * 
         * @return {Boolean} false
         */
        function beginMove(event, instance) {
            if (resizable === null && !instance.isMaximized() && instance.get('movable')) {
                var eventSrc, left=0, top=0;
                if (event.type === 'touchstart') {
                    event.preventDefault();
                    eventSrc = event.targetTouches[0];
                    xProp = 'clientX';
                    yProp = 'clientY';
                } else if (event.button === 0) {
                    eventSrc = event;
                }

                if (eventSrc) {

                    var element = instance.elements.dialog;
                    addClass(element, classes.capture);

                    if (element.style.left) {
                        left = parseInt(element.style.left, 10);
                    }

                    if (element.style.top) {
                        top = parseInt(element.style.top, 10);
                    }
                    
                    offsetX = eventSrc[xProp] - left;
                    offsetY = eventSrc[yProp] - top;

                    if(instance.isModal()){
                        offsetY += instance.elements.modal.scrollTop;
                    }else if(instance.isPinned()){
                        offsetY -= document.body.scrollTop;
                    }
                    
                    if(instance.get('moveBounded')){
                        var current = element,
                            offsetLeft = -left,
                            offsetTop = -top;
                        
                        do {
                            offsetLeft += current.offsetLeft;
                            offsetTop += current.offsetTop;
                        } while (current = current.offsetParent);
                        
                        bounds = {
                            maxLeft : offsetLeft,
                            minLeft : -offsetLeft,
                            maxTop  : document.documentElement.clientHeight - element.clientHeight - offsetTop,
                            minTop  : -offsetTop
                        };
                        moveDelegate = moveElementBounded;
                    }else{
                        bounds = null;
                        moveDelegate = moveElement;
                    }
                    
                    refreshTop = !instance.isModal() && instance.isPinned();
                    movable = instance;
                    moveDelegate(eventSrc, element);
                    addClass(document.body, classes.noSelection);
                    return false;
                }
            }
        }

        /**
         * The actual move handler,  attached to document.body mousemove event.
         *
         * @param {Event} event	DOM event object.
         * 
         * @return {undefined}
         */
        function move(event) {
            if (movable) {
                var eventSrc;
                if (event.type === 'touchmove') {
                    event.preventDefault();
                    eventSrc = event.targetTouches[0];
                } else if (event.button === 0) {
                    eventSrc = event;
                }
                if (eventSrc) {
                    moveDelegate(eventSrc, movable.elements.dialog);
                }
            }
        }

        /**
         * Triggers the end of a move event,  attached to document.body mouseup event.
         * Removes no-selection class from document.body, allowing selection.
         *
         * @return {undefined}
         */
        function endMove() {
            if (movable) {
                var element = movable.elements.dialog;
                movable = bounds = null;
                removeClass(document.body, classes.noSelection);
                removeClass(element, classes.capture);
            }
        }

        /**
         * Resets any changes made by moving the element to its original state,
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function resetMove(instance) {
            movable = null;
            var element = instance.elements.dialog;
            element.style.left = element.style.top = '';
        }

        /**
         * Updates the dialog move behavior.
         *
         * @param {Object} instance The dilog instance.
         * @param {Boolean} on True to add the behavior, removes it otherwise.
         *
         * @return {undefined}
         */
        function updateMovable(instance) {
            if (instance.get('movable')) {
                addClass(instance.elements.root, classes.movable);
                if (instance.isOpen()) {
                    bindMovableEvents(instance);
                }
            } else {

                resetMove(instance);
                removeClass(instance.elements.root, classes.movable);
                if (instance.isOpen()) {
                    unbindMovableEvents(instance);
                }
            }
        }

        /* Controls moving a dialog around */
        var resizable = null,
            startingLeft = Number.Nan,
            startingWidth = 0,
            minWidth = 0,
            handleOffset = 0
        ;

        /**
         * Helper: sets the element width/height and updates left coordinate if neccessary.
         *
         * @param {Event} event	DOM mousemove event object.
         * @param {Node} element The element being moved.
         * @param {Boolean} pinned A flag indicating if the element being resized is pinned to the screen.
         * 
         * @return {undefined}
         */
        function resizeElement(event, element, pageRelative) {

            var current = element;
            var offsetLeft = 0;
            var offsetTop = 0;
            do {
                offsetLeft += current.offsetLeft;
                offsetTop += current.offsetTop;
            } while (current = current.offsetParent);

            var X, Y;
            if (pageRelative === true) {
                X = event.pageX;
                Y = event.pageY;
            } else {
                X = event.clientX;
                Y = event.clientY;
            }
            var isRTL = isRightToLeft();
            if (isRTL) {
                X = document.body.offsetWidth - X;
                if (!isNaN(startingLeft)) {
                    offsetLeft = document.body.offsetWidth - offsetLeft - element.offsetWidth;
                }
            }

            element.style.height = (Y - offsetTop + handleOffset) + 'px';
            element.style.width = (X - offsetLeft + handleOffset) + 'px';

            if (!isNaN(startingLeft)) {
                var diff = Math.abs(element.offsetWidth - startingWidth) * 0.5;
                if (isRTL) {
                    diff *= -1;
                }
                if (element.offsetWidth > startingWidth) {
                    element.style.left = (startingLeft + diff) + 'px';
                } else if (element.offsetWidth >= minWidth) {
                    element.style.left = (startingLeft - diff) + 'px';
                }
            }
        }

        /**
         * Triggers the start of a resize event, attached to the resize handle element mouse down event.
         * Adds no-selection class to the body, disabling selection while moving.
         *
         * @param {Event} event	DOM event object.
         * @param {Object} instance The dilog instance.
         * 
         * @return {Boolean} false
         */
        function beginResize(event, instance) {
            if (!instance.isMaximized()) {
                var eventSrc;
                if (event.type === 'touchstart') {
                    event.preventDefault();
                    eventSrc = event.targetTouches[0];
                } else if (event.button === 0) {
                    eventSrc = event;
                }
                if (eventSrc) {
                    resizable = instance;
                    handleOffset = instance.elements.resizeHandle.offsetHeight / 2;
                    var element = instance.elements.dialog;
                    addClass(element, classes.capture);
                    startingLeft = parseInt(element.style.left, 10);
                    element.style.height = element.offsetHeight + 'px';
                    element.style.minHeight = instance.elements.header.offsetHeight + instance.elements.footer.offsetHeight + 'px';
                    element.style.width = (startingWidth = element.offsetWidth) + 'px';

                    if (element.style.maxWidth !== 'none') {
                        element.style.minWidth = (minWidth = element.offsetWidth) + 'px';
                    }
                    element.style.maxWidth = 'none';
                    addClass(document.body, classes.noSelection);
                    return false;
                }
            }
        }

        /**
         * The actual resize handler,  attached to document.body mousemove event.
         *
         * @param {Event} event	DOM event object.
         * 
         * @return {undefined}
         */
        function resize(event) {
            if (resizable) {
                var eventSrc;
                if (event.type === 'touchmove') {
                    event.preventDefault();
                    eventSrc = event.targetTouches[0];
                } else if (event.button === 0) {
                    eventSrc = event;
                }
                if (eventSrc) {
                    resizeElement(eventSrc, resizable.elements.dialog, !resizable.get('modal') && !resizable.get('pinned'));
                }
            }
        }

        /**
         * Triggers the end of a resize event,  attached to document.body mouseup event.
         * Removes no-selection class from document.body, allowing selection.
         *
         * @return {undefined}
         */
        function endResize() {
            if (resizable) {
                var element = resizable.elements.dialog;
                resizable = null;
                removeClass(document.body, classes.noSelection);
                removeClass(element, classes.capture);
                cancelClick = true;
            }
        }

        /**
         * Resets any changes made by resizing the element to its original state.
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function resetResize(instance) {
            resizable = null;
            var element = instance.elements.dialog;
            if (element.style.maxWidth === 'none') {
                element.style.maxWidth = element.style.minWidth = element.style.width = element.style.height = element.style.minHeight = element.style.left = '';
                startingLeft = Number.Nan;
                startingWidth = minWidth = handleOffset = 0;
            }
        }


        /**
         * Updates the dialog move behavior.
         *
         * @param {Object} instance The dilog instance.
         * @param {Boolean} on True to add the behavior, removes it otherwise.
         *
         * @return {undefined}
         */
        function updateResizable(instance) {
            if (instance.get('resizable')) {
                addClass(instance.elements.root, classes.resizable);
                if (instance.isOpen()) {
                    bindResizableEvents(instance);
                }
            } else {
                resetResize(instance);
                removeClass(instance.elements.root, classes.resizable);
                if (instance.isOpen()) {
                    unbindResizableEvents(instance);
                }
            }
        }

        /**
         * Reset move/resize on window resize.
         *
         * @param {Event} event	window resize event object.
         *
         * @return {undefined}
         */
        function windowResize(/*event*/) {
            for (var x = 0; x < openDialogs.length; x += 1) {
                var instance = openDialogs[x];
                if (instance.get('autoReset')) {
                    resetMove(instance);
                    resetResize(instance);
                }
            }
        }
        /**
         * Bind dialogs events
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function bindEvents(instance) {
            if (openDialogs.length === 1) {
                on(window, 'resize', windowResize);
                on(document.body, 'keyup', keyupHandler);
                on(document.body, 'keydown', keydownHandler);
                on(document.body, 'focus', onReset);

                on(document.documentElement, 'mousemove', move);
                on(document.documentElement, 'touchmove', move);
                on(document.documentElement, 'mouseup', endMove);
                on(document.documentElement, 'touchend', endMove);
                on(document.documentElement, 'mousemove', resize);
                on(document.documentElement, 'touchmove', resize);
                on(document.documentElement, 'mouseup', endResize);
                on(document.documentElement, 'touchend', endResize);
            }

            on(instance.elements.commands.container, 'click', instance.__internal.commandsClickHandler);
            on(instance.elements.footer, 'click', instance.__internal.buttonsClickHandler);
            on(instance.elements.reset[0], 'focus', instance.__internal.resetHandler);
            on(instance.elements.reset[1], 'focus', instance.__internal.resetHandler);

            cancelKeyup = true;
            on(instance.elements.dialog, transition.type, instance.__internal.transitionInHandler);

            if (!instance.get('modal')) {
                bindModelessEvents(instance);
            }

            if (instance.get('resizable')) {
                bindResizableEvents(instance);
            }

            if (instance.get('movable')) {
                bindMovableEvents(instance);
            }
        }

        /**
         * Unbind dialogs events
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function unbindEvents(instance) {
            if (openDialogs.length === 1) {
                off(window, 'resize', windowResize);
                off(document.body, 'keyup', keyupHandler);
                off(document.body, 'keydown', keydownHandler);
                off(document.body, 'focus', onReset);
                off(document.documentElement, 'mousemove', move);
                off(document.documentElement, 'mouseup', endMove);
                off(document.documentElement, 'mousemove', resize);
                off(document.documentElement, 'mouseup', endResize);
            }

            off(instance.elements.commands.container, 'click', instance.__internal.commandsClickHandler);
            off(instance.elements.footer, 'click', instance.__internal.buttonsClickHandler);
            off(instance.elements.reset[0], 'focus', instance.__internal.resetHandler);
            off(instance.elements.reset[1], 'focus', instance.__internal.resetHandler);

            on(instance.elements.dialog, transition.type, instance.__internal.transitionOutHandler);

            if (!instance.get('modal')) {
                unbindModelessEvents(instance);
            }

            if (instance.get('movable')) {
                unbindMovableEvents(instance);
            }

            if (instance.get('resizable')) {
                unbindResizableEvents(instance);
            }

        }

        /**
         * Bind modeless specific events
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function bindModelessEvents(instance) {
            on(instance.elements.dialog, 'focus', instance.__internal.bringToFrontHandler, true);
        }

        /**
         * Unbind modeless specific events
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function unbindModelessEvents(instance) {
            off(instance.elements.dialog, 'focus', instance.__internal.bringToFrontHandler, true);
        }



        /**
         * Bind movable specific events
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function bindMovableEvents(instance) {
            on(instance.elements.header, 'mousedown', instance.__internal.beginMoveHandler);
            on(instance.elements.header, 'touchstart', instance.__internal.beginMoveHandler);
        }

        /**
         * Unbind movable specific events
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function unbindMovableEvents(instance) {
            off(instance.elements.header, 'mousedown', instance.__internal.beginMoveHandler);
            off(instance.elements.header, 'touchstart', instance.__internal.beginMoveHandler);
        }



        /**
         * Bind resizable specific events
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function bindResizableEvents(instance) {
            on(instance.elements.resizeHandle, 'mousedown', instance.__internal.beginResizeHandler);
            on(instance.elements.resizeHandle, 'touchstart', instance.__internal.beginResizeHandler);
        }

        /**
         * Unbind resizable specific events
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function unbindResizableEvents(instance) {
            off(instance.elements.resizeHandle, 'mousedown', instance.__internal.beginResizeHandler);
            off(instance.elements.resizeHandle, 'touchstart', instance.__internal.beginResizeHandler);
        }

        /**
         * Bind closable events
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function bindClosableEvents(instance) {
            on(instance.elements.modal, 'click', instance.__internal.modalClickHandler);
        }

        /**
         * Unbind closable specific events
         *
         * @param {Object} instance The dilog instance.
         *
         * @return {undefined}
         */
        function unbindClosableEvents(instance) {
            off(instance.elements.modal, 'click', instance.__internal.modalClickHandler);
        }
        return {
            __init:initialize,
            /**
             * Check if dialog is currently open
             *
             * @return {Boolean}
             */
            isOpen: function () {
                return this.__internal.isOpen;
            },
            isModal: function (){
                return this.elements.root.className.indexOf(classes.modeless) < 0;
            },
            isMaximized:function(){
                return this.elements.root.className.indexOf(classes.maximized) > -1;
            },
            isPinned:function(){
                return this.elements.root.className.indexOf(classes.unpinned) < 0;
            },
            maximize:function(){
                if(!this.isMaximized()){
                    maximize(this);
                }
                return this;
            },
            restore:function(){
                if(this.isMaximized()){
                    restore(this);
                }
                return this;
            },
            pin:function(){
                if(!this.isPinned()){
                    pin(this);
                }
                return this;
            },
            unpin:function(){
                if(this.isPinned()){
                    unpin(this);
                }
                return this;
            },
            bringToFront:function(){
                bringToFront(null, this);
                return this;
            },
            /**
             * Move the dialog to a specific x/y coordinates
             *
             * @param {Number} x    The new dialog x coordinate in pixels.
             * @param {Number} y    The new dialog y coordinate in pixels.
             *
             * @return {Object} The dialog instance.
             */
            moveTo:function(x,y){
                if(!isNaN(x) && !isNaN(y)){
                    var element = this.elements.dialog,
                        current = element,
                        offsetLeft = 0,
                        offsetTop = 0;
                    
                    if (element.style.left) {
                        offsetLeft -= parseInt(element.style.left, 10);
                    }
                    if (element.style.top) {
                        offsetTop -= parseInt(element.style.top, 10);
                    }
                    do {
                        offsetLeft += current.offsetLeft;
                        offsetTop += current.offsetTop;
                    } while (current = current.offsetParent);

                    var left = (x - offsetLeft);
                    var top  = (y - offsetTop);

                    if (isRightToLeft()) {
                        left *= -1;
                    }

                    element.style.left = left + 'px';
                    element.style.top = top + 'px';
                }
                return this;
            },
            /**
             * Resize the dialog to a specific width/height (the dialog must be 'resizable').
             * The dialog can be resized to:
             *  A minimum width equal to the initial display width
             *  A minimum height equal to the sum of header/footer heights.
             *
             *
             * @param {Number or String} width    The new dialog width in pixels or in percent.
             * @param {Number or String} height   The new dialog height in pixels or in percent.
             *
             * @return {Object} The dialog instance.
             */
            resizeTo:function(width,height){
                var w = parseFloat(width),
                    h = parseFloat(height),
                    regex = /(\d*\.\d+|\d+)%/
                ;

                if(!isNaN(w) && !isNaN(h) && this.get('resizable') === true){

                    if(('' + width).match(regex)){
                        w = w / 100 * document.documentElement.clientWidth ;
                    }

                    if(('' + height).match(regex)){
                        h = h / 100 * document.documentElement.clientHeight;
                    }

                    var element = this.elements.dialog;
                    if (element.style.maxWidth !== 'none') {
                        element.style.minWidth = (minWidth = element.offsetWidth) + 'px';
                    }
                    element.style.maxWidth = 'none';
                    element.style.minHeight = this.elements.header.offsetHeight + this.elements.footer.offsetHeight + 'px';
                    element.style.width = w + 'px';
                    element.style.height = h + 'px';
                }
                return this;
            },
            /**
             * Gets or Sets dialog settings/options 
             *
             * @param {String|Object} key A string specifying a propery name or a collection of key/value pairs.
             * @param {Object} value Optional, the value associated with the key (in case it was a string).
             *
             * @return {undefined}
             */
            setting : function (key, value) {
                var self = this;
                var result = update(this, this.__internal.options, function(k,o,n){ optionUpdated(self,k,o,n); }, key, value);
                if(result.op === 'get'){
                    if(result.found){
                        return result.value;
                    }else if(typeof this.settings !== 'undefined'){
                        return update(this, this.settings, this.settingUpdated || function(){}, key, value).value;
                    }else{
                        return undefined;
                    }
                }else if(result.op === 'set'){
                    if(result.items.length > 0){
                        var callback = this.settingUpdated || function(){};
                        for(var x=0;x<result.items.length;x+=1){
                            var item = result.items[x];
                            if(!item.found && typeof this.settings !== 'undefined'){
                                update(this, this.settings, callback, item.key, item.value);
                            }
                        }
                    }
                    return this;
                }
            },
            /**
             * [Alias] Sets dialog settings/options 
             */
            set:function(key, value){
                this.setting(key,value);
                return this;
            },
            /**
             * [Alias] Gets dialog settings/options 
             */
            get:function(key){
                return this.setting(key);
            },
            /**
            * Sets dialog header
            * @content {string or element}
            *
            * @return {undefined}
            */
            setHeader:function(content){
                if(typeof content === 'string'){
                    clearContents(this.elements.header);
                    this.elements.header.innerHTML = content;
                }else if (content instanceof window.HTMLElement && this.elements.header.firstChild !== content){
                    clearContents(this.elements.header);
                    this.elements.header.appendChild(content);
                }
                return this;
            },
            /**
            * Sets dialog contents
            * @content {string or element}
            *
            * @return {undefined}
            */
            setContent:function(content){
                if(typeof content === 'string'){
                    clearContents(this.elements.content);
                    this.elements.content.innerHTML = content;
                }else if (content instanceof window.HTMLElement && this.elements.content.firstChild !== content){
                    clearContents(this.elements.content);
                    this.elements.content.appendChild(content);
                }
                return this;
            },
            /**
             * Show the dialog as modal
             *
             * @return {Object} the dialog instance.
             */
            showModal: function(className){
                return this.show(true, className);
            },
            /**
             * Show the dialog
             *
             * @return {Object} the dialog instance.
             */
            show: function (modal, className) {
                
                initialize(this);
								
                if ( !this.__internal.isOpen ) {
					
                    this.__internal.isOpen = true;
                    openDialogs.push(this);

                    if(alertify.defaults.maintainFocus){
                        this.__internal.activeElement = document.activeElement;
                    }

                    if(typeof this.prepare === 'function'){
                        this.prepare();
                    }

                    bindEvents(this);

                    if(modal !== undefined){
                        this.set('modal', modal);
                    }
					
                    saveScrollPosition();

                    ensureNoOverflow();
					
                    if(typeof className === 'string' && className !== ''){
                        this.__internal.className = className;
                        addClass(this.elements.root, className);
                    }

                    if ( this.get('startMaximized')) {
                        this.maximize();
                    }else if(this.isMaximized()){
                        restore(this);
                    }
					
                    updateAbsPositionFix(this);

                    removeClass(this.elements.root, classes.animationOut);
                    addClass(this.elements.root, classes.animationIn);

                    clearTimeout( this.__internal.timerIn);
                    this.__internal.timerIn = setTimeout( this.__internal.transitionInHandler, transition.supported ? 1000 : 100 );

                    if(isSafari){
                        var root = this.elements.root;
                        root.style.display  = 'none';
                        setTimeout(function(){root.style.display  = 'block';}, 0);
                    }

                    reflow = this.elements.root.offsetWidth;
                  
                    removeClass(this.elements.root, classes.hidden);

                    if(typeof this.hooks.onshow === 'function'){
                        this.hooks.onshow.call(this);
                    }

                    if ( typeof this.get('onshow') === 'function' ) {
                        this.get('onshow').call(this);
                    }

                }else{
                    resetMove(this);
                    resetResize(this);
                    addClass(this.elements.dialog, classes.shake);
                    var self = this;
                    setTimeout(function(){
                        removeClass(self.elements.dialog, classes.shake);
                    },200);
                }
                return this;
            },
            /**
             * Close the dialog
             *
             * @return {Object} The dialog instance
             */
            close: function () {
                if (this.__internal.isOpen ) {
					
                    unbindEvents(this);
					
                    removeClass(this.elements.root, classes.animationIn);
                    addClass(this.elements.root, classes.animationOut);

                    clearTimeout( this.__internal.timerOut );
                    this.__internal.timerOut = setTimeout( this.__internal.transitionOutHandler, transition.supported ? 1000 : 100 );
                    addClass(this.elements.root, classes.hidden);
                    reflow = this.elements.modal.offsetWidth;

                    if (typeof this.__internal.className !== 'undefined' && this.__internal.className !== '') {
                        removeClass(this.elements.root, this.__internal.className);
                    }

                    if(typeof this.hooks.onclose === 'function'){
                        this.hooks.onclose.call(this);
                    }

                    if ( typeof this.get('onclose') === 'function' ) {
                        this.get('onclose').call(this);
                    }
					
                    openDialogs.splice(openDialogs.indexOf(this),1);
                    this.__internal.isOpen = false;
					
                    ensureNoOverflow();
					
                }
                return this;
            },
            /**
             * Close all open dialogs except this.
             *
             * @return {undefined}
             */
            closeOthers:function(){
                alertify.closeAll(this);
                return this;
            },
            /**
             * Destroys this dialog instance
             *
             * @return {undefined}
             */
            destroy:function(){
                if (this.__internal.isOpen ) {
                    this.__internal.destroy = function(){
                        destruct(this, initialize);
                    };
                    this.close();
                }else{
                    destruct(this, initialize);
                }
                return this;
            },
        };
	} () );
    var notifier = (function () {
        var reflow,
            element,
            openInstances = [],
            classes = {
                base: 'alertify-notifier',
                message: 'ajs-message',
                top: 'ajs-top',
                right: 'ajs-right',
                bottom: 'ajs-bottom',
                left: 'ajs-left',
                visible: 'ajs-visible',
                hidden: 'ajs-hidden'
            };
        /**
         * Helper: initializes the notifier instance
         * 
         */
        function initialize(instance) {

            if (!instance.__internal) {
                instance.__internal = {
                    position: alertify.defaults.notifier.position,
                    delay: alertify.defaults.notifier.delay,
                };

                element = document.createElement('DIV');

                updatePosition(instance);
            }

            if (element.parentNode !== document.body) {
                document.body.appendChild(element);
            }
        }
        
        function pushInstance(instance) {
            instance.__internal.pushed = true;
            openInstances.push(instance);
        }
        function popInstance(instance) {
            openInstances.splice(openInstances.indexOf(instance), 1);
            instance.__internal.pushed = false;
        }
        /**
         * Helper: update the notifier instance position
         * 
         */
        function updatePosition(instance) {
            element.className = classes.base;
            switch (instance.__internal.position) {
            case 'top-right':
                addClass(element, classes.top + ' ' + classes.right);
                break;
            case 'top-left':
                addClass(element, classes.top + ' ' + classes.left);
                break;
            case 'bottom-left':
                addClass(element, classes.bottom + ' ' + classes.left);
                break;

            default:
            case 'bottom-right':
                addClass(element, classes.bottom + ' ' + classes.right);
                break;
            }
        }

        /**
        * creates a new notification message
        *
        * @param  {DOMElement} message	The notifier message element
        * @param  {Number} wait   Time (in ms) to wait before the message is dismissed, a value of 0 means keep open till clicked.
        * @param  {Function} callback A callback function to be invoked when the message is dismissed.
        *
        * @return {undefined}
        */
        function create(div, callback) {

            function clickDelegate(event, instance) {
                instance.dismiss(true);
            }

            function transitionDone(event, instance) {
                off(instance.element, transition.type, transitionDone);
                element.removeChild(instance.element);
            }

            function initialize(instance) {
                if (!instance.__internal) {
                    instance.__internal = {
                        pushed: false,
                        delay : undefined,
                        timer: undefined,
                        clickHandler: undefined,
                        transitionEndHandler: undefined,
                        transitionTimeout: undefined
                    };
                    instance.__internal.clickHandler = delegate(instance, clickDelegate);
                    instance.__internal.transitionEndHandler = delegate(instance, transitionDone);
                }
                return instance;
            }
            function clearTimers(instance) {
                clearTimeout(instance.__internal.timer);
                clearTimeout(instance.__internal.transitionTimeout);
            }
            return initialize({
                /* notification DOM element*/
                element: div,
                /*
                 * Pushes a notification message 
                 * @param {string or DOMElement} content The notification message content
                 * @param {Number} wait The time (in seconds) to wait before the message is dismissed, a value of 0 means keep open till clicked.
                 * 
                 */
                push: function (_content, _wait) {
                    if (!this.__internal.pushed) {

                        pushInstance(this);
                        clearTimers(this);

                        var content, wait;
                        switch (arguments.length) {
                        case 0:
                            wait = this.__internal.delay;
                            break;
                        case 1:
                            if (typeof (_content) === 'number') {
                                wait = _content;
                            } else {
                                content = _content;
                                wait = this.__internal.delay;
                            }
                            break;
                        case 2:
                            content = _content;
                            wait = _wait;
                            break;
                        }
                        if (typeof content !== 'undefined') {
                            this.setContent(content);
                        }
                        if (notifier.__internal.position.indexOf('top') < 0) {
                            element.appendChild(this.element);
                        } else {
                            element.insertBefore(this.element, element.firstChild);
                        }
                        reflow = this.element.offsetWidth;
                        addClass(this.element, classes.visible);
                        on(this.element, 'click', this.__internal.clickHandler);
                        return this.delay(wait);
                    }
                    return this;
                },
                /*
                 * {Function} callback function to be invoked before dismissing the notification message.
                 * Remarks: A return value === 'false' will cancel the dismissal
                 * 
                 */
                ondismiss: function () { },
                /*
                 * {Function} callback function to be invoked when the message is dismissed.
                 * 
                 */
                callback: callback,
                /*
                 * Dismisses the notification message 
                 * @param {Boolean} clicked A flag indicating if the dismissal was caused by a click.
                 * 
                 */
                dismiss: function (clicked) {
                    if (this.__internal.pushed) {
                        clearTimers(this);
                        if (!(typeof this.ondismiss === 'function' && this.ondismiss.call(this) === false)) {
                            off(this.element, 'click', this.__internal.clickHandler);
                            if (typeof this.element !== 'undefined' && this.element.parentNode === element) {
                                this.__internal.transitionTimeout = setTimeout(this.__internal.transitionEndHandler, transition.supported ? 1000 : 100);
                                removeClass(this.element, classes.visible);

                                if (typeof this.callback === 'function') {
                                    this.callback.call(this, clicked);
                                }
                            }
                            popInstance(this);
                        }
                    }
                    return this;
                },
                /*
                 * Delays the notification message dismissal
                 * @param {Number} wait The time (in seconds) to wait before the message is dismissed, a value of 0 means keep open till clicked.
                 * 
                 */
                delay: function (wait) {
                    clearTimers(this);
                    this.__internal.delay = typeof wait !== 'undefined' && !isNaN(+wait) ? +wait : notifier.__internal.delay;
                    if (this.__internal.delay > 0) {
                        var  self = this;
                        this.__internal.timer = setTimeout(function () { self.dismiss(); }, this.__internal.delay * 1000);
                    }
                    return this;
                },
                /*
                 * Sets the notification message contents
                 * @param {string or DOMElement} content The notification message content
                 * 
                 */
                setContent: function (content) {
                    if (typeof content === 'string') {
                        clearContents(this.element);
                        this.element.innerHTML = content;
                    } else if (content instanceof window.HTMLElement && this.element.firstChild !== content) {
                        clearContents(this.element);
                        this.element.appendChild(content);
                    }
                    return this;
                },
                /*
                 * Dismisses all open notifications except this.
                 * 
                 */
                dismissOthers: function () {
                    notifier.dismissAll(this);
                    return this;
                }
            });
        }

        return {
            /**
             * Gets or Sets notifier settings. 
             *
             * @param {string} key The setting name
             * @param {Variant} value The setting value.
             *
             * @return {Object}	if the called as a setter, return the notifier instance.
             */
            setting: function (key, value) {
                initialize(this);

                if (typeof value === 'undefined') {
                    return this.__internal[key];
                } else {
                    switch (key) {
                    case 'position':
                        this.__internal.position = value;
                        updatePosition(this);
                        break;
                    case 'delay':
                        this.__internal.delay = value;
                        break;
                    }
                }
                return this;
            },
            /**
             * [Alias] Sets dialog settings/options 
             */
            set:function(key,value){
                this.setting(key,value);
                return this;
            },
            /**
             * [Alias] Gets dialog settings/options 
             */
            get:function(key){
                return this.setting(key);
            },
            /**
             * Creates a new notification message
             *
             * @param {string} type The type of notification message (simply a CSS class name 'ajs-{type}' to be added).
             * @param {Function} callback  A callback function to be invoked when the message is dismissed.
             *
             * @return {undefined}
             */
            create: function (type, callback) {
                initialize(this);
                var div = document.createElement('div');
                div.className = classes.message + ((typeof type === 'string' && type !== '') ? ' ajs-' + type : '');
                return create(div, callback);
            },
            /**
             * Dismisses all open notifications.
             *
             * @param {Object} excpet [optional] The notification object to exclude from dismissal.
             *
             */
            dismissAll: function (except) {
                var clone = openInstances.slice(0);
                for (var x = 0; x < clone.length; x += 1) {
                    var  instance = clone[x];
                    if (except === undefined || except !== instance) {
                        instance.dismiss();
                    }
                }
            }
        };
    })();
    /**
     * Alertify public API
     * This contains everything that is exposed through the alertify object.
     *
     * @return {Object}
     */
    function Alertify() {

        var dialogs = {};

        /**
         * Extends a given prototype by merging properties from base into sub.
         *
         * @sub {Object} sub The prototype being overwritten.
         * @base {Object} base The prototype being written.
         *
         * @return {Object} The extended prototype.
         */
        function extend(sub, base) {
            for (var prop in base) {
                if (base.hasOwnProperty(prop)) {
                    sub[prop] = base[prop];
                }
            }
            return sub;
        }


        /**
        * Helper: returns a dialog instance from saved dialogs.
        * and initializes the dialog if its not already initialized.
        *
        * @name {String} name The dialog name.
        *
        * @return {Object} The dialog instance.
        */
        function get_dialog(name) {
            var dialog = dialogs[name].dialog;
            if (dialog && typeof dialog.__init === 'function') {
                dialog.__init(dialog);
            }
            return dialog;
        }

        /**
         * Helper:  registers a new dialog definition.
         *
         * @name {String} name The dialog name.
         * @Factory {Function} Factory a function resposible for creating dialog prototype.
         * @transient {Boolean} transient True to create a new dialog instance each time the dialog is invoked, false otherwise.
         * @base {String} base the name of another dialog to inherit from.
         *
         * @return {Object} The dialog definition.
         */
        function register(name, Factory, transient, base) {
            var definition = {
                dialog: null,
                factory: Factory
            };

            if (base !== undefined) {
                definition.factory = function () {
                    return extend(new dialogs[base].factory(), new Factory());
                };
            }

            if (!transient) {
                definition.dialog = extend(new definition.factory(), dialog);
            }
            return dialogs[name] = definition;
        }

        return {
            /**
             * Alertify defaults
             * 
             * @type {Object}
             */
            defaults: defaults,
            /**
             * Dialogs factory 
             *
             * @param {string}      Dialog name.
             * @param {Function}    A Dialog factory function.
             * @param {Boolean}     Indicates whether to create a singleton or transient dialog.
             * @param {String}      The name of the base type to inherit from.
             */
            dialog: function (name, Factory, transient, base) {

                if (typeof Factory !== 'function') {
                    return get_dialog(name);
                }

                if (this.hasOwnProperty(name)) {
                    throw new Error('alertify.dialog: name already exists');
                }

                var definition = register(name, Factory, transient, base);

                if (transient) {

                    this[name] = function () {
                        if (arguments.length === 0) {
                            return definition.dialog;
                        } else {
                            var instance = extend(new definition.factory(), dialog);
                            if (instance && typeof instance.__init === 'function') {
                                instance.__init(instance);
                            }
                            instance['main'].apply(instance, arguments);
                            return instance['show'].apply(instance);
                        }
                    };
                } else {
                    this[name] = function () {
                        if (definition.dialog && typeof definition.dialog.__init === 'function') {
                            definition.dialog.__init(definition.dialog);
                        }
                        if (arguments.length === 0) {
                            return definition.dialog;
                        } else {
                            var dialog = definition.dialog;
                            dialog['main'].apply(definition.dialog, arguments);
                            return dialog['show'].apply(definition.dialog);
                        }
                    };
                }
            },
            /**
             * Close all open dialogs.
             *
             * @param {Object} excpet [optional] The dialog object to exclude from closing.
             *
             * @return {undefined}
             */
            closeAll: function (except) {
                var clone = openDialogs.slice(0);
                for (var x = 0; x < clone.length; x += 1) {
                    var instance = clone[x];
                    if (except === undefined || except !== instance) {
                        instance.close();
                    }
                }
            },
            /**
             * Gets or Sets dialog settings/options. if the dialog is transient, this call does nothing.
             *
             * @param {string} name The dialog name.
             * @param {String|Object} key A string specifying a propery name or a collection of key/value pairs.
             * @param {Variant} value Optional, the value associated with the key (in case it was a string).
             *
             * @return {undefined}
             */
            setting: function (name, key, value) {

                if (name === 'notifier') {
                    return notifier.setting(key, value);
                }

                var dialog = get_dialog(name);
                if (dialog) {
                    return dialog.setting(key, value);
                }
            },
            /**
             * [Alias] Sets dialog settings/options 
             */
            set: function(name,key,value){
                return this.setting(name, key,value);
            },
            /**
             * [Alias] Gets dialog settings/options 
             */
            get: function(name, key){
                return this.setting(name, key);
            },
            /**
             * Creates a new notification message.
             * If a type is passed, a class name "ajs-{type}" will be added.
             * This allows for custom look and feel for various types of notifications.
             *
             * @param  {String | DOMElement}    [message=undefined]		Message text
             * @param  {String}                 [type='']				Type of log message
             * @param  {String}                 [wait='']				Time (in seconds) to wait before auto-close
             * @param  {Function}               [callback=undefined]	A callback function to be invoked when the log is closed.
             *
             * @return {Object} Notification object.
             */
            notify: function (message, type, wait, callback) {
                return notifier.create(type, callback).push(message, wait);
            },
            /**
             * Creates a new notification message.
             *
             * @param  {String}		[message=undefined]		Message text
             * @param  {String}     [wait='']				Time (in seconds) to wait before auto-close
             * @param  {Function}	[callback=undefined]	A callback function to be invoked when the log is closed.
             *
             * @return {Object} Notification object.
             */
            message: function (message, wait, callback) {
                return notifier.create(null, callback).push(message, wait);
            },
            /**
             * Creates a new notification message of type 'success'.
             *
             * @param  {String}		[message=undefined]		Message text
             * @param  {String}     [wait='']				Time (in seconds) to wait before auto-close
             * @param  {Function}	[callback=undefined]	A callback function to be invoked when the log is closed.
             *
             * @return {Object} Notification object.
             */
            success: function (message, wait, callback) {
                return notifier.create('success', callback).push(message, wait);
            },
            /**
             * Creates a new notification message of type 'error'.
             *
             * @param  {String}		[message=undefined]		Message text
             * @param  {String}     [wait='']				Time (in seconds) to wait before auto-close
             * @param  {Function}	[callback=undefined]	A callback function to be invoked when the log is closed.
             *
             * @return {Object} Notification object.
             */
            error: function (message, wait, callback) {
                return notifier.create('error', callback).push(message, wait);
            },
            /**
             * Creates a new notification message of type 'warning'.
             *
             * @param  {String}		[message=undefined]		Message text
             * @param  {String}     [wait='']				Time (in seconds) to wait before auto-close
             * @param  {Function}	[callback=undefined]	A callback function to be invoked when the log is closed.
             *
             * @return {Object} Notification object.
             */
            warning: function (message, wait, callback) {
                return notifier.create('warning', callback).push(message, wait);
            },
            /**
             * Dismisses all open notifications
             *
             * @return {undefined}
             */
            dismissAll: function () {
                notifier.dismissAll();
            }
        };
    }
    var alertify = new Alertify();

    /**
    * Alert dialog definition
    *
    * invoked by:
    *	alertify.alert(message);
    *	alertify.alert(title, message);
    *	alertify.alert(message, onok);
    *	alertify.alert(title, message, onok);
     */
    alertify.dialog('alert', function () {
        return {
            main: function (_title, _message, _onok) {
                var title, message, onok;
                switch (arguments.length) {
                case 1:
                    message = _title;
                    break;
                case 2:
                    if (typeof _message === 'function') {
                        message = _title;
                        onok = _message;
                    } else {
                        title = _title;
                        message = _message;
                    }
                    break;
                case 3:
                    title = _title;
                    message = _message;
                    onok = _onok;
                    break;
                }
                this.set('title', title);
                this.set('message', message);
                this.set('onok', onok);
                return this;
            },
            setup: function () {
                return {
                    buttons: [
                        {
                            text: alertify.defaults.glossary.ok,
                            key: keys.ESC,
                            invokeOnClose: true,
                            className: alertify.defaults.theme.ok,
                        }
                    ],
                    focus: {
                        element: 0,
                        select: false
                    },
                    options: {
                        maximizable: false,
                        resizable: false
                    }
                };
            },
            build: function () {
                
            },
            prepare: function () {
                
            },
            setMessage: function (message) {
                this.setContent(message);
            },
            settings: {
                message: undefined,
                onok: undefined,
                label: undefined,
            },
            settingUpdated: function (key, oldValue, newValue) {
                switch (key) {
                case 'message':
                    this.setMessage(newValue);
                    break;
                case 'label':
                    if (this.__internal.buttons[0].element) {
                        this.__internal.buttons[0].element.innerHTML = newValue;
                    }
                    break;
                }
            },
            callback: function (closeEvent) {
                if (typeof this.get('onok') === 'function') {
                    var returnValue = this.get('onok').call(this, closeEvent);
                    if (typeof returnValue !== 'undefined') {
                        closeEvent.cancel = !returnValue;
                    }
                }
            }
        };
    });
    /**
     * Confirm dialog object
     *
     *	alertify.confirm(message);
     *	alertify.confirm(message, onok);
     *	alertify.confirm(message, onok, oncancel);
     *	alertify.confirm(title, message, onok, oncancel);
     */
    alertify.dialog('confirm', function () {

        var autoConfirm = {
            timer: null,
            index: null,
            text: null,
            duration: null,
            task: function (event, self) {
                if (self.isOpen()) {
                    self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text + ' (&#8207;' + autoConfirm.duration + '&#8207;) ';
                    autoConfirm.duration -= 1;
                    if (autoConfirm.duration === -1) {
                        clearAutoConfirm(self);
                        var button = self.__internal.buttons[autoConfirm.index];
                        var closeEvent = createCloseEvent(autoConfirm.index, button);

                        if (typeof self.callback === 'function') {
                            self.callback.apply(self, [closeEvent]);
                        }
                        if (closeEvent.close !== false) {
                            self.close();
                        }
                    }
                } else {
                    clearAutoConfirm(self);
                }
            }
        };

        function clearAutoConfirm(self) {
            if (autoConfirm.timer !== null) {
                clearInterval(autoConfirm.timer);
                autoConfirm.timer = null;
                self.__internal.buttons[autoConfirm.index].element.innerHTML = autoConfirm.text;
            }
        }

        function startAutoConfirm(self, index, duration) {
            clearAutoConfirm(self);
            autoConfirm.duration = duration;
            autoConfirm.index = index;
            autoConfirm.text = self.__internal.buttons[index].element.innerHTML;
            autoConfirm.timer = setInterval(delegate(self, autoConfirm.task), 1000);
            autoConfirm.task(null, self);
        }


        return {
            main: function (_title, _message, _onok, _oncancel) {
                var title, message, onok, oncancel;
                switch (arguments.length) {
                case 1:
                    message = _title;
                    break;
                case 2:
                    message = _title;
                    onok = _message;
                    break;
                case 3:
                    message = _title;
                    onok = _message;
                    oncancel = _onok;
                    break;
                case 4:
                    title = _title;
                    message = _message;
                    onok = _onok;
                    oncancel = _oncancel;
                    break;
                }
                this.set('title', title);
                this.set('message', message);
                this.set('onok', onok);
                this.set('oncancel', oncancel);
                return this;
            },
            setup: function () {
                return {
                    buttons: [
                        {
                            text: alertify.defaults.glossary.ok,
                            key: keys.ENTER,
                            className: alertify.defaults.theme.ok,
                        },
                        {
                            text: alertify.defaults.glossary.cancel,
                            key: keys.ESC,
                            invokeOnClose: true,
                            className: alertify.defaults.theme.cancel,
                        }
                    ],
                    focus: {
                        element: 0,
                        select: false
                    },
                    options: {
                        maximizable: false,
                        resizable: false
                    }
                };
            },
            build: function () {
                
            },
            prepare: function () {
                
            },
            setMessage: function (message) {
                this.setContent(message);
            },
            settings: {
                message: null,
                labels: null,
                onok: null,
                oncancel: null,
                defaultFocus: null,
                reverseButtons: null,
            },
            settingUpdated: function (key, oldValue, newValue) {
                switch (key) {
                case 'message':
                    this.setMessage(newValue);
                    break;
                case 'labels':
                    if ('ok' in newValue && this.__internal.buttons[0].element) {
                        this.__internal.buttons[0].text = newValue.ok;
                        this.__internal.buttons[0].element.innerHTML = newValue.ok;
                    }
                    if ('cancel' in newValue && this.__internal.buttons[1].element) {
                        this.__internal.buttons[1].text = newValue.cancel;
                        this.__internal.buttons[1].element.innerHTML = newValue.cancel;
                    }
                    break;
                case 'reverseButtons':
                    if (newValue === true) {
                        this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element);
                    } else {
                        this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element);
                    }
                    break;
                case 'defaultFocus':
                    this.__internal.focus.element = newValue === 'ok' ? 0 : 1;
                    break;
                }
            },
            callback: function (closeEvent) {
                clearAutoConfirm(this);
                var returnValue;
                switch (closeEvent.index) {
                case 0:
                    if (typeof this.get('onok') === 'function') {
                        returnValue = this.get('onok').call(this, closeEvent);
                        if (typeof returnValue !== 'undefined') {
                            closeEvent.cancel = !returnValue;
                        }
                    }
                    break;
                case 1:
                    if (typeof this.get('oncancel') === 'function') {
                        returnValue = this.get('oncancel').call(this, closeEvent);
                        if (typeof returnValue !== 'undefined') {
                            closeEvent.cancel = !returnValue;
                        }
                    }
                    break;
                }
            },
            autoOk: function (duration) {
                startAutoConfirm(this, 0, duration);
                return this;
            },
            autoCancel: function (duration) {
                startAutoConfirm(this, 1, duration);
                return this;
            }
        };
    });
    /**
     * Prompt dialog object
     *
     * invoked by:
     *	alertify.prompt(message);
     *	alertify.prompt(message, value);
     *	alertify.prompt(message, value, onok);
     *	alertify.prompt(message, value, onok, oncancel);
     *	alertify.prompt(title, message, value, onok, oncancel);
     */
    alertify.dialog('prompt', function () {
        var input = document.createElement('INPUT');
        var p = document.createElement('P');
        return {
            main: function (_title, _message, _value, _onok, _oncancel) {
                var title, message, value, onok, oncancel;
                switch (arguments.length) {
                case 1:
                    message = _title;
                    break;
                case 2:
                    message = _title;
                    value = _message;
                    break;
                case 3:
                    message = _title;
                    value = _message;
                    onok = _value;
                    break;
                case 4:
                    message = _title;
                    value = _message;
                    onok = _value;
                    oncancel = _onok;
                    break;
                case 5:
                    title = _title;
                    message = _message;
                    value = _value;
                    onok = _onok;
                    oncancel = _oncancel;
                    break;
                }
                this.set('title', title);
                this.set('message', message);
                this.set('value', value);
                this.set('onok', onok);
                this.set('oncancel', oncancel);
                return this;
            },
            setup: function () {
                return {
                    buttons: [
                        {
                            text: alertify.defaults.glossary.ok,
                            key: keys.ENTER,
                            className: alertify.defaults.theme.ok,
                        },
                        {
                            text: alertify.defaults.glossary.cancel,
                            key: keys.ESC,
                            invokeOnClose: true,
                            className: alertify.defaults.theme.cancel,
                        }
                    ],
                    focus: {
                        element: input,
                        select: true
                    },
                    options: {
                        maximizable: false,
                        resizable: false
                    }
                };
            },
            build: function () {
                input.className = alertify.defaults.theme.input;
                input.setAttribute('type', 'text');
                input.value = this.get('value');
                this.elements.content.appendChild(p);
                this.elements.content.appendChild(input);
            },
            prepare: function () {
                
            },
            setMessage: function (message) {
                if (typeof message === 'string') {
                    clearContents(p);
                    p.innerHTML = message;
                } else if (message instanceof window.HTMLElement && p.firstChild !== message) {
                    clearContents(p);
                    p.appendChild(message);
                }
            },
            settings: {
                message: undefined,
                labels: undefined,
                onok: undefined,
                oncancel: undefined,
                value: '',
                type:'text',
                reverseButtons: undefined,
            },
            settingUpdated: function (key, oldValue, newValue) {
                switch (key) {
                case 'message':
                    this.setMessage(newValue);
                    break;
                case 'value':
                    input.value = newValue;
                    break;
                case 'type':
                    switch (newValue) {
                    case 'text':
                    case 'color':
                    case 'date':
                    case 'datetime-local':
                    case 'email':
                    case 'month':
                    case 'number':
                    case 'password':
                    case 'search':
                    case 'tel':
                    case 'time':
                    case 'week':
                        input.type = newValue;
                        break;
                    default:
                        input.type = 'text';
                        break;
                    }
                    break;
                case 'labels':
                    if (newValue.ok && this.__internal.buttons[0].element) {
                        this.__internal.buttons[0].element.innerHTML = newValue.ok;
                    }
                    if (newValue.cancel && this.__internal.buttons[1].element) {
                        this.__internal.buttons[1].element.innerHTML = newValue.cancel;
                    }
                    break;
                case 'reverseButtons':
                    if (newValue === true) {
                        this.elements.buttons.primary.appendChild(this.__internal.buttons[0].element);
                    } else {
                        this.elements.buttons.primary.appendChild(this.__internal.buttons[1].element);
                    }
                    break;
                }
            },
            callback: function (closeEvent) {
                var returnValue;
                switch (closeEvent.index) {
                case 0:
                    this.settings.value = input.value;
                    if (typeof this.get('onok') === 'function') {
                        returnValue = this.get('onok').call(this, closeEvent, this.settings.value);
                        if (typeof returnValue !== 'undefined') {
                            closeEvent.cancel = !returnValue;
                        }
                    }
                    break;
                case 1:
                    if (typeof this.get('oncancel') === 'function') {
                        returnValue = this.get('oncancel').call(this, closeEvent);
                        if (typeof returnValue !== 'undefined') {
                            closeEvent.cancel = !returnValue;
                        }
                    }
                    break;
                }
            }
        };
    });

    
    if ( typeof module === 'object' && typeof module.exports === 'object' ) {
        module.exports = alertify;
    
    } else if ( typeof define === 'function' && define.amd) {
        define( [], function () {
            return alertify;
        } );
    
    } else if ( !window.alertify ) {
        window.alertify = alertify;
    }

} ( typeof window !== 'undefined' ? window : this ) );
;
var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
var EventClick = "click";
if (iOS == true) { EventClick = "click touchstart"; }
$(document).ready(function () {
    if (location.pathname.toLowerCase() == "/home/index") {
        location.href = "https://www.matbao.net/";
    }
    var navUA = navigator.userAgent;
    //console.log(navUA);
    $('[data-toggle="lefteffect"]').click(function () {
        var targetid = $(this).attr("data-target");
        $(targetid).children().children("ul.navbar-nav-1").animate({ left: 0 }, 300);
    });
    //$("#showMenuAccount").click(function () {
    //    var MenuAccount = $("#MenuAccount").attr("class");
    //    if (MenuAccount.indexOf("hidden") > -1) {
    //        $("#MenuAccount").removeClass("hidden");
    //    }
    //    else {
    //        $("#MenuAccount").addClass("hidden");
    //    }
    //});
    $("#whoisdomaintext,#domainwhois").keydown(function (e) {
        if (e.keyCode == 13) {
            $("#btnWhois").trigger("click");
            return false;
        }
    });
    $(".topSubjectMenu").click(function () {
        $(".topclose").removeClass("active");
        $(".topSubjectMenu").removeClass("active");
    });
    $("#mbMenuClose").click(function () {
        console.log('menu-x');
        var textback = $(".navbar-nav > li.active > a");
        textback.show();
        $(".topSubjectMenu").removeClass("hidden");
        $("#currentChoice").text($("#currentChoice").attr("data-text"));
        $(".topclose").removeClass("active");
        $(".topSubjectMenu").removeClass("active");
        $("#mbMenuClose").children("img").removeClass("hidden");
        $("#mbMenuClose").children("b").addClass("hidden");
        var isactive = $(".navbar-nav > li.active:not(.topclose, .topSubjectMenu)");
        if (isactive.html() == undefined) {
            var targetid = $(this).parent().parent();
            $(targetid).animate({ left: -100 + "%" }, 300);
        }
        else {
            $(isactive).removeClass("active");
        }
        $(".darkbackground").hide();
        $("body").removeClass("fixed");
    });
    $(".navbar-nav > li:not(.topclose, .topSubjectMenu)").click(function () {
        var winWidth = $(window).width();
        var textback = $(".navbar-nav > li.active > a");
        if (winWidth <= 768) {
            textback.hide();
        }
        if ($("#currentChoice").html() != undefined) {
            $("#currentChoice").text(textback.text());
        }
        $("#mbMenuClose").children("b").removeClass("hidden");
        $("#mbMenuClose").children("img").addClass("hidden");
    });
    var ua = navigator.userAgent,
        scrollTopPosition,
        iOS = /iPad|iPhone|iPod/.test(ua),
        iOS11 = /OS 11_0|OS 11_1|OS 11_2|OS 10_3/.test(ua);
    // ios 11 bug caret position
    if (iOS && iOS11) {
        $(document.body).on('touchstart', '#matbao-login, #loginpopup, [data-target="#myModalTK"]', function (e) {
            // Get scroll position before moving top
            scrollTopPosition = $(document).scrollTop();
            // Add CSS to body "position: fixed"
            $("body").addClass("iosBugFixCaret");
        });

        $(document.body).on('touchstart', '#myModalTK .close', function (e) {
            // Remove CSS to body "position: fixed"
            $("body").removeClass("iosBugFixCaret");
            //Go back to initial position in document
            $(document).scrollTop(scrollTopPosition);
        });
    }
    $('form[data-ajax="false"]').each(function () {
        $(this).attr("data-ajax", "true");
    });
    $('body').on("submit", 'form[data-ajax="false"]', function (event) {
        location.href = 'https://www.matbao.net'
        event.preventDefault();
    });
    $('form[data-ajax="false"]').submit(function (event) {
        location.href = 'https://www.matbao.net'
        event.preventDefault();
    });
    //$("#whoisdomaintext").keyup(function (e) {
    //    if (e.keyCode == 13) {
    //        $("#btnWhois,#btnWhois1").trigger("click");
    //    }
    //});
    $("#btnWhois,#btnWhois1").click(function () {//debugger;
        var tenmien = ($("#domainwhois").html() == undefined ? $("#whoisdomaintext") : $("#domainwhois"));
        if (!($('#whoisdomaintextMulti:visible').length == 0)) {
            tenmien = $("#whoisdomaintextMulti");
        }
        var tenmienvalue = tenmien.val();
        $(this).hide(); var Errorj = "";
        var loading = $($("#loadingaction").html() == undefined ? $("#loadingaction_new") : $("#loadingaction"))
        loading.show();
        var _data = { ReturnUrl: "", Message: "", Type: 0 };
        try {
            var MinLen_TMQT = parseInt(tenmien.attr("data-len1") == undefined ? "0" : tenmien.attr("data-len1"));
            var MinLen_TMTV = parseInt(tenmien.attr("data-len2") == undefined ? "0" : tenmien.attr("data-len2"));
            var MaxLen_TM = parseInt(tenmien.attr("data-len3") == undefined ? "0" : tenmien.attr("data-len3"));
            var arrTenmien = tenmien.val().replace(/\n/g, ';').split(';');
            var dataext = "";
            dataext = (tenmien.attr("data-ext") == undefined ? "" : tenmien.attr("data-ext"));
            tenmien.val("");
            $.each(arrTenmien, function (index, itemTenmien) {
                if (itemTenmien.indexOf(".") <= -1) {
                    tenmienvalue = itemTenmien + dataext;
                    tenmien.val(tenmien.val() == "" ? tenmienvalue : tenmien.val() + "\n" + tenmienvalue);
                }
                else {
                    tenmienvalue = itemTenmien;
                    tenmien.val(tenmien.val() == "" ? tenmienvalue : tenmien.val() + "\n" + tenmienvalue);
                }
                //tenmienvalue = tenmien.val().replace(/[`~!@#$%^&*()_|+\=?;:'",<>\{\}\[\]\\\/]/gi, '');
                var arr = (tenmienvalue).split('.');
                if (tenmienvalue.indexOf('-') == 0 || tenmienvalue.indexOf('-') == tenmienvalue.length - 1 || tenmienvalue.indexOf('--') > -1) {
                    alertify.notify("Tên miền không được bắt đầu, kết thúc bằng dấu gạch hoặc hai dấu gạch liên tục.", "error", 15, null);
                    Errorj = "1";
                }
                if (MinLen_TMQT != "0" && MinLen_TMTV != "0" && MaxLen_TM != "0") {
                    var minLen = MinLen_TMQT;
                    if (itemTenmien.endsWith(".vn") && itemTenmien.split('.').length <= 2) {/* && !itemTenmien.endsWith(".com.vn") && !itemTenmien.endsWith(".net.vn") && !itemTenmien.endsWith(".edu.vn") && !itemTenmien.endsWith(".biz.vn") && !itemTenmien.endsWith(".info.vn")*/
                        minLen = MinLen_TMTV;
                    }
                    else if (itemTenmien.endsWith(".vn") && itemTenmien.split('.').length > 2) {
                        minLen = 0;
                    }
                    var tenmienlen = 0;//arr.length - 2;
                    if (arr[tenmienlen].length <= minLen || arr[tenmienlen].length > MaxLen_TM) {
                        alertify.notify("Tên miền phải từ 3 đến 63 ký tự", "error", 15, null);
                        Errorj = "2";
                    }
                }
            });
            if (Errorj == "") {
                var myUrl = ($(this).attr("data-url") == undefined ? "/ten-mien/ket-qua-kiem-tra-ten-mien.html" : $(this).attr("data-url"));
                var urlRedirect = myUrl + "?tenmien=" + tenmien.val().replace(/\n/g,';') + "#boxwhoisincheckdomain";
                _data.ReturnUrl = urlRedirect;
                _data.Message = "";
                _data.Type = 1;
                ChecksearchDomain(_data);
                $(this).show();
            }
            else {
                $(this).show();
                loading.hide();
            }
        } catch (e) {
            $(this).show();
            loading.hide();
            alertify.notify("Hiện tại bạn không thể kiểm tra tên miền do có ký tự đặc biệt hoặc khoảng trắng, hãy loại bỏ các ký tự đặc biệt hoặc khoảng trắng trong cụm từ tra cứu và thử lại.", "error", 15, null);
        }
    });
    var battooltip = false;
    $(document).scroll(function () {
        var checkHtml = $("#GoiHostingNew:visible .slick-slide:nth-child(2) .mbtooltip-promotion:not(.dis)");
        var checkHtml1 = $("#GoiHostingNew:first-child .pricebox:nth-child(2) .mbtooltip-promotion:visible");
        if (checkHtml.html() == undefined) {
            checkHtml = checkHtml1;
        }
        if (checkHtml.html() != undefined && !battooltip && checkHtml.is(":visible")) {
            var topScroll = $(window).scrollTop();
            var topGoi = $("#GoiHostingNew").position().top - 150;
            if (topScroll >= topGoi) {
                setTimeout(function () {
                    checkHtml.trigger("click");
                    battooltip = true;
                    return false;
                }, 2000);
            }
        }
    });
});
document.addEventListener('readystatechange', event => {
    if (event.target.readyState === "interactive") {
        setTimeout(function () {
            $("ul.navbar-nav>li").click(function () {
                $("img[menu-src*='/']").each(function () {
                    $(this).attr("src", $(this).attr('menu-src'));
                    $(this).removeAttr('menu-src');
                });
            });
            initLoadImg();
            $(document).scroll(function () {
                initLoadImg();
            });
        }, 1000);
    }
});
function initLoadImg() {
    var topScroll = $(window).scrollTop();
    $("img[data-src*='/']").each(function () {
        var elm = $(this);
        var posYtop = elm.offset().top - 1500;
        if ($(this).attr('data-src') && topScroll >= posYtop) {
            $(this).attr('src', $(this).attr('data-src'));
            $(this).removeAttr('data-src');
        }
    });
}
function RemoveUnicode1(e) {
    var a = [{
        key: "a", value: "á|à|ả|ã|ạ|ă|ắ|ặ|ằ|ẳ|ẵ|â|ấ|ầ|ẩ|ẫ|ậ"
    }
    ,
    {
        key: "d", value: "đ"
    }
    ,
    {
        key: "e", value: "é|è|ẻ|ẽ|ẹ|ê|ế|ề|ể|ễ|ệ"
    }
    ,
    {
        key: "i", value: "í|ì|ỉ|ĩ|ị"
    }
    ,
    {
        key: "o", value: "ó|ò|ỏ|õ|ọ|ô|ố|ồ|ổ|ỗ|ộ|ơ|ớ|ờ|ở|ỡ|ợ"
    }
    ,
    {
        key: "u", value: "ú|ù|ủ|ũ|ụ|ư|ứ|ừ|ử|ữ|ự"
    }
    ,
    {
        key: "y", value: "ý|ỳ|ỷ|ỹ|ỵ"
    }
    ,
    {
        key: "A", value: "Á|À|Ả|Ã|Ạ|Ă|Ắ|Ặ|Ằ|Ẳ|Ẵ|Â|Ấ|Ầ|Ẩ|Ẫ|Ậ"
    }
    ,
    {
        key: "D", value: "Đ"
    }
    ,
    {
        key: "E", value: "É|È|Ẻ|Ẽ|Ẹ|Ê|Ế|Ề|Ể|Ễ|Ệ"
    }
    ,
    {
        key: "I", value: "Í|Ì|Ỉ|Ĩ|Ị"
    }
    ,
    {
        key: "O", value: "Ó|Ò|Ỏ|Õ|Ọ|Ô|Ố|Ồ|Ổ|Ỗ|Ộ|Ơ|Ớ|Ờ|Ở|Ỡ|Ợ"
    }
    ,
    {
        key: "U", value: "Ú|Ù|Ủ|Ũ|Ụ|Ư|Ứ|Ừ|Ử|Ữ|Ự"
    }
    ,
    {
        key: "Y", value: "Ý|Ỳ|Ỷ|Ỹ|Ỵ"
    }
    ];
    for (vars in a) e = e.replace(new RegExp(a[vars].value, "g"), a[vars].key);
    return e
}
function alertDomain() {
    if ($("#popupAlert").html() == undefined) {
        var alTitle = "Tên miền không được chứa các ký tự đặc biệt!";
        var alDetail = "Chỉ chấp nhận các ký tự bao gồm: “a-z”, “0-9”, dấu “-” và các ký tự tiếng Việt có mũ, dấu trong bảng mã Unicode dựng sẵn (theo TCVN 6909-2001).";
        var alBtntx = "Đã hiểu";
        $("body").append("<div id='popupAlert' style='display: block; width: 100%; height: 100%; z-index: 9000000; position: fixed; top: 0; left: 0;background: #00000042;'><div style='width:450px;max-width:calc(100vw - 30px);display:block;border-radius: 12px;box-shadow: 0px 4px 4px rgba(0, 0, 0, 0.25);position: absolute;top:32px;left: 50%;transform: translate(-50%, 30px);z-index: 500000;background: #FFF;'><b style='display:block;padding: 25px 25px 20px 55px;background: url(/Content/images/dm_alert.svg) no-repeat;background-size: 23px;background-position: 25px center;border-bottom: 1px solid rgba(204, 206, 208, 0.5);'>" + alTitle + "</b><span style='display: inline-block;padding: 20px 25px 25px;width: 100%;'><p>" + alDetail + "</p><a id='clickOK' style='padding: 10px 30px; text-align:center;float:right;display: block;background:#2376E5;border-radius: 4px;color:#FFF;cursor: pointer;'>" + alBtntx + "</a></span></div><input type='text' style='display:block;width:1px;height:1px;border:none;background-color: transparent;' /></div>");
        $("#popupAlert input").focus();
        var iOS1 = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
        var EventClick1 = "click";
        if (iOS1 == true) { EventClick1 = "click touchstart"; }
        $("body").on(EventClick1, "#clickOK,#popupAlert", function () {
            $("#popupAlert").remove();
            $('.loadingaction,#loadingaction,#loadingaction_new').hide();
            $("#btnWhois").show();
            var el = $("#domainwhois").get(0);
            if (el == undefined) {
                el = $("#whoisdomaintext").get(0);
            }
            var elemLen = el.value.length; el.selectionStart = 0;
            el.selectionEnd = elemLen;
            el.focus();
        });
        $("#popupAlert input").keypress(function (e) {
            if (e.keyCode == 13) {
                $("#popupAlert").remove();
                $('.loadingaction,#loadingaction,#loadingaction_new').hide();
                $("#btnWhois").show();
                var el = $("#domainwhois").get(0);
                if (el == undefined) {
                    el = $("#whoisdomaintext").get(0);
                }
                var elemLen = el.value.length; el.selectionStart = 0;
                el.selectionEnd = elemLen;
                el.focus();
            }
        });
    }
}
var ChecksearchDomain = function (data) {
    var e = ($("#domainwhois").html() == undefined ? $("#whoisdomaintext").val() : $("#domainwhois").val());
    if (!($('#whoisdomaintextMulti:visible').length == 0)) {
        e = $("#whoisdomaintextMulti").val();
    }
    if ((e = (e = (e = e.replace(/\s+/gi, "")).replace(/\, +/gi, "", e)).replace(/^\s+/gi, "")).length, -1 != e.lastIndexOf(" ")) {
        for ($v in array = e.split(" "), $len_array = array.length, array) $v < $len_array - 1 && (array[$v] = array[$v].replace(".", ""));
        e = (e = array.join("")).replace(/\s+/gi, "", e)
    }
    tmpstr = RemoveUnicode1(e);/*alert("Tên miền chỉ chứa các ký tự a-z, 0-9, dấu - và các ký tự tiếng việt có mũ, dấu trong bảng mã Unicode dựng sẵn(theo TCVN 6909-2001)")*/
    var hero = !(/^([^a-z0-9]+)/gi.test(tmpstr) || /([^a-z0-9]+)$/gi.test(tmpstr) || /([^a-z0-9\.\-\s]+)/gi.test(tmpstr)) || (alertDomain(), !1);
    //$('.submitform_new').show();
    //$('#loadingaction_new').hide();
    //$('.submitform').show();
    //$('.nSubmitform').show();
    //$('.loadingbtn').hide();
    //$('#loadingaction').hide();
    //$("#loadingaction2").hide();
    //$("#loadingaction3").hide();
    //$(".btn-search-mobile").show();
    if (hero) {
        if (data.ReturnUrl != null && data.ReturnUrl != "") {
            if (data.Message != null && data.Message != "") {
                alertify.success(data.Message, "success", 15, null);
            }
            if (data.ReturnUrl.indexOf("undefined") <= -1)
                window.location.href = data.ReturnUrl;
        }
        else {
            alertify.notify(data.Message, "error", 15, null);
            $('.nSubmitform').show();
            $('.loadingaction,#loadingaction').hide();
        }
    }
    else {
        $('.nSubmitform').show();
        $('.loadingaction,#loadingaction').hide();
        if ($("#popupAlert").html() == undefined) {
            var el = $("#domainwhois").get(0);
            if (multi) {
                el = $("#whoisdomaintextMulti").get(0);
            }
            var elemLen = el.value.length; el.selectionStart = 0;
            el.selectionEnd = elemLen;
            el.focus();
        }

    }
}
alertify.set('notifier', 'position', 'top-right');
$('.submitform').click(function () {
    var _val = $($(this).closest('div').prev('input')[0]).val();
    var currentForm = $(this.form);
    $(this).hide();
    if ($(this).hasClass("ld2")) {
        $("#loadingaction2").insertAfter($(this));
        $("#loadingaction2").show();
    }
    else if ($(this).hasClass("btn-pm")) {
        $("#loadingaction3").insertAfter($(this));
        $("#loadingaction3").css('display', 'inline-block');
    }
    else if ($(this).hasClass("btn-popup")) {
        $("#loadingaction-mobile").show();
    }
    else if (_val === "" || _val == undefined || _val == null) {
        $(this).show();
    }
    else {
        $("#loadingaction").insertAfter($(this));
        $("#loadingaction").show();
    }
    if (currentForm.valid()) {
        currentForm.submit();
        /*currentForm.children().find('input[type=text]').val('');
        currentForm.children().find('textarea').val('');*/
    }
});
$("#footer-doitac,.footer-doitac").on('click', function () {
    var _ul = $($(this).next('ul')[0]);
    if (_ul.css("display") === "none") {
        _ul.css("display", "block");
    } else {
        _ul.css("display", "none");
    }
});

var OnActionFailure = function (ajaxContext) {
    $('.submitform').show();
    $('#loadingaction').hide();
    $("#loadingaction2").hide();
    $("#loadingaction3").hide();
    $('#loadingaction_new').hide();
    alertify.warning("Có lỗi xảy ra, vui lòng thử lại!", "warning", 15, null);
    window.location.href = "/";
}
var OnActionFailureHome = function (ajaxContext) {
    $('.submitform').show();
    $('#loadingaction').hide();
    $("#loadingaction2").hide();
    $("#loadingaction3").hide();
    window.location.href = "/";
}
var OnActionSuccess = function (data) {
    $('.submitform_new').show();
    $('#loadingaction_new').hide();
    $('.submitform').show();
    $('.loadingbtn').hide();
    $('#loadingaction').hide();
    $("#loadingaction2").hide();
    $("#loadingaction3").hide();
    $(".btn-search-mobile").show();
    if (data.Type != 1) {
        if (data.Type == 3) { /*== 3 chỉ giành riêng cho chọn tên miền cho dịch vụ (hosting, email, ssl)*/
            var tenMienChuaDangKy = $("#TenMien1").val();
            $("#tenmienchuadangky").html(tenMienChuaDangKy);
            $("#TenMienChuaDangKy").val(tenMienChuaDangKy);
            $("#box-container-warning").fadeIn();
            $("#DanhSachTenMienChoDichVu").html("");
            $("#TenMienBaoVay").html("");
            $.get("/TenMien/DanhSachTenMienChoDichVu", function (htmldata) {
                $('#DanhSachTenMienChoDichVu').html(htmldata);
            });
            /*
             Hiển thị thông tin tên miền cho dịch vụ
            $.get("/TenMien/TenMienAvailableChoDichVu", function (htmldata) {
                $('#TenMienChoDichVu').html(htmldata);
                $.get("/TenMien/_ListTenMienBaoVay", function (htmldata) {
                    $('#TenMienBaoVay').html(htmldata);
                    $(".ten-mien-de-xuat .list-ten-mien-de-xuat .matbao-label-2").find("span").text("TÊN MIỀN BẠN CÓ THỂ MUA THÊM");
                });
            });

             Đỗ danh sách tên miền bao vây vào popup chọn tên miền cho dịch vụ
            $.get("/TenMien/_ListTenMienBaoVay", function (htmldata) {
                $('#TenMienBaoVay').html(htmldata);
            });*/
        } else if (data.Type == 6) {
            $('#dvKetQuaKiemTraDonHang').show();
            $("#thongTinDonHang").html(data.Message);
            $('#kqKiemTraDonHang_TrangThai').html(data.OrderStage);
            $('#kqKiemTraDonHang_NhanVienXuLy').html(data.StaffName);
            $('#kqKiemTraDonHang_DienThoai').html(data.StaffPhone);

            grecaptcha.reset();
        }
        else if (data.Type == 33) { /*== 33 Dành cho kiểm tra tên miền để đăng ký combo seo recommend*/
            var tenMienChuaDangKy = $("#TenMien1").val();
            $("#tenmienchuadangky").html(tenMienChuaDangKy);
            $("#TenMienChuaDangKy").val(tenMienChuaDangKy);
            $(".ten-mien-de-xuat ").slideDown();
            $("#DanhSachTenMienChoDichVu").html("");
            $("#TenMienBaoVay").html("");
            $.get("/TenMien/DanhSachTenMienChoDichVuCombo?tenMienChoCombo=" + tenMienChuaDangKy, function (htmldata) {
                $('#DanhSachTenMienChoDichVu').html(htmldata);
            });
            $(".dialog-warning-combo-ssl").css("height", "570");
        } else if (data.Type == 44) { /*== 44 Dành cho kiểm tra tên miền để đăng ký combo seo recommend*/
            alertify.notify(data.Message, "error", 15, null);
        } else if (data.Type == 11) { /*== 11 Dành cho kiểm tra tên miền để đăng ký combo seo recommend*/
            alertify.success(data.Message, "success", 15, null);
            $("#box-container-warning").fadeOut();
            $("#SoLuongGioHang").html(data.ServiceTotal);
            $("#SoLuongGioHangScroll").html(data.ServiceTotal);
            $(".gio-hang-scroll").children("a").attr("href", data.ReturnUrl);
            $("#SoLuongGioHang").parent().attr("href", data.ReturnUrl);
            if (data.ReturnUrl != null && data.ReturnUrl != "") {
                window.location.href = data.ReturnUrl;
            }
        } else if (data.Type == 2) {
            if (data.ReturnUrl != null && data.ReturnUrl != "") {
                window.location.href = data.ReturnUrl;
            }
        } else {
            if (data.ControlId != null) {
                $('#' + data.ControlId).focus();
            }
            alertify.notify(data.Message, "error", 15, null);

            if (data.Type == 404) {
                grecaptcha.reset();
                $(".g-recaptcha").show();
            }

            return false;
        }
    }
    else {
        $("#thongTinDonHang").html("");
        if (data.ReturnUrl != null && data.ReturnUrl != "") {
            if (data.Message != null && data.Message != "") {
                alertify.success(data.Message, "success", 15, null);
            }
            window.location.href = data.ReturnUrl;
        }
        else {
            if (data.Message.indexOf("thành công")) {
                alertify.success(data.Message, "success", 15, null);
            }
            else {
                alertify.notify(data.Message, "error", 15, null);
            }
        }
    }
}

var OnActionSuccess2 = function (data) {
    $('.submitform').show();
    $('#loadingaction').hide();
    $("#loadingaction2").hide();
    $("#loadingaction3").hide();
    if (data.Type == 1) {
        alertify.success(data.Message, "success", 15, null);
    }
    else {
        alertify.notify(data.Message, "error", 15, null);
    }
}

$('.inputnumberonly').keypress(function (evt) {
    var numbervalue = $(this).val();
    var charCode = (evt.which) ? evt.which : event.keyCode
    var c = String.fromCharCode(charCode);
    if (charCode == 46) {
        return false;
    }
    if (numbervalue.indexOf(c) > 0 && charCode == 46) {
        return false;
    }
    else if (charCode != 46 && charCode > 31 && (charCode < 48 || charCode > 57)) {
        return false;
    }
    return true;
});

$("input, textarea").not(".ck-input").keypress(function (evt) {
    var charCode = (evt.which) ? evt.which : evt.keyCode
    if (charCode == 60 || charCode == 62)
        return false;
    return true;
});

$('#TenDangNhap, #MatKhau').keypress(function (e) {
    if (e.keyCode == 13) {
        $('.btn-login').trigger("click");
    }
});

$(function () {
    //$('.slide-partner-payment').jcarouselAutoscroll({
    //    interval: 2000
    //});

    //$('.slide-partner-service').jcarouselAutoscroll({
    //    interval: 3000
    //});

    $(".radio-soft").click(function () {
        var currentname = $(this).children("input:radio").attr("name");
        $(".radio-soft").children("input:radio[name=" + currentname + "]").removeAttr('checked');
        $(".radio-soft").children("input:radio[name=" + currentname + "]").parent().css("background", "url('/Content/images/uncheck.png') no-repeat");

        if ($(this).children().find('input:radio').attr('checked') != "checked") {
            $(this).find('input:radio').attr('checked', 'checked');
            $(this).css("background", "url('/Content/images/check.png') no-repeat");
        } else {
            $(this).children().find('input:radio').removeAttr('checked');
            $(this).css("background", "url('/Content/images/uncheck.png') no-repeat");
        }
    });

    $('input:radio').each(function (index) {
        if ($(this).parent().hasClass('radio-soft')) {
            if ($(this).prop('checked')) {
                $(this).parent().css("background", "url('/Content/images/check.png') no-repeat");
            } else {
                $(this).parent().css("background", "url('/Content/images/uncheck.png') no-repeat");
            }
        }
    });

    $('.boxbanggiatenmien .btn-xem-tiep').click(function () {
        $(this).find('div').find('div').css('height', 'auto');
    });

    $(".radio-soft label").click(function () {
        var radio_input = $(this).prev();
        radio_input.trigger("click");
    });

});

$(".close-warning-btn").click(function () {
    $("#box-container-warning").fadeOut();
});

var mbnwarning = function (status, content, callback) {
    bootbox.alert(content, function () {
        eval(callback);
    });
    if (status == 1) {
        $(".bootbox-body").addClass("bootbox-body-ok");
    }
};

$("#whoisdomaintext").keypress(function (event) {
    if (event.which == 13) {
        event.preventDefault();
        /*$('.whoissubmit').click();
        WhoisDomain();*/
    }
});

$('.whoissubmit').click(function () {

    var currentForm = $(this.form);
    if (currentForm.valid()) {
        currentForm.submit();
    } 
    
    /*var tenMienMultiValue = $("#whoisdomaintextMulti").val();
    tenMienMultiValue = tenMienMultiValue.replace(/\r\n|\n|\r/g, ',');
    var tenMienMultiValueSplit = tenMienMultiValue.split(",");
    if (tenMienMultiValueSplit.length > 50) {
        alertify.notify("Quý khách chỉ có thể nhập tối đa 50 tên miền", "warning", 15, null);
        return false;
    }
    else {
        var currentForm = $(this.form);
        if (currentForm.valid()) {
            currentForm.submit();
        }
    }*/
});
/*
$(".mbtooltip").tooltip({
    container: 'body'
});

$(".mbtooltip").qtip();
*/
var updateGiaTuyChinhMayChu = function () {
    var hddTuyChinh = parseInt($("#btn-datmua-tuychoncauhinh").attr('data-tuychinhhdd'));
    var ramTuyChinh = parseInt($("#btn-datmua-tuychoncauhinh").attr('data-tuychinhram'));
    var cpuTuyChinh = parseInt($("#btn-datmua-tuychoncauhinh").attr('data-tuychinhcpucore'));
    $.get("/lay-gia-may-chu-tuy-chinh.html?hddTuyChinh=" + hddTuyChinh + "&ramTuyChinh=" + ramTuyChinh + "&cpuTuyChinh=" + cpuTuyChinh + "", function (data) {
        $("#totalvalue").html(data);
    });
};

ajaxRequestsUpdateGiaAddons = new Array();
var updateGiaAddonTuyChinhMayChu = function () {

    var tuychinhAddonRam = parseInt($("#MuaThemRam").val());
    var tuychinhAddonHdd = parseInt($("#MuaThemDungLuong").val());
    var tuyChinhAddonIP = parseInt($("#MuaThemIP").val());

    if (ajaxRequestsUpdateGiaAddons[ajaxRequestsUpdateGiaAddons.length - 1]) {
        ajaxRequestsUpdateGiaAddons[ajaxRequestsUpdateGiaAddons.length - 1].abort();
    }

    ajaxRequestsUpdateGiaAddons[ajaxRequestsUpdateGiaAddons.length] = $.get("/lay-gia-addon-may-chu-tuy-chinh.html?ramAddonTuyChinh=" + tuychinhAddonRam + "&hddAddonTuyChinh=" + tuychinhAddonHdd + "&ipAddonTuyChinh=" + tuyChinhAddonIP + "", function (data) {
        $("#totalvalue").html(data);
    });
};


ajaxRequestsUpdateGiaBangThong = new Array();
var updateGiaBangThongHosting = function () {

    var tuyChinhBangThongHosting = parseInt($("#MuaThemBangThong").val());

    if (ajaxRequestsUpdateGiaBangThong[ajaxRequestsUpdateGiaBangThong.length - 1]) {
        ajaxRequestsUpdateGiaBangThong[ajaxRequestsUpdateGiaBangThong.length - 1].abort();
    }

    ajaxRequestsUpdateGiaBangThong[ajaxRequestsUpdateGiaBangThong.length] = $.get("/lay-gia-addon-bang-thong-hosting.html?bangThongTuyChinh=" + tuyChinhBangThongHosting, function (data) {
        $("#totalvalue").html(data);
    });
};


$(".gotobottom").click(function () {
    //$(window).scrollTop($(window).height());
    var nutgiohang = ($(".btn-vao-giohang").html() != undefined ? $(".btn-vao-giohang").offset().top : $(".gotocart").offset().top);
    var manhinh = ($(window).height() - 50) / 2;
    $('body,html').animate({ scrollTop: nutgiohang - manhinh }, 'slow');
    return false;
});

function XemThemTinhNang() {
    $('body,html').animate({ scrollTop: $("#TinhNangChiTiet").position().top }, 'slow');
}

$("#menu-mb-main").click(function () {
    if ($(this).hasClass("collapsed")) {
        $('body,html').animate({ scrollTop: 0 }, 'slow');
        $(".btncontrolmenu").addClass("btncontrolmenuclose");
        $(".darkbackground").show();
        $("body").addClass("fixed");
    }
    else {
        $(".btncontrolmenu").removeClass("btncontrolmenuclose");
        $(".darkbackground").hide();
        $("body").removeClass("fixed");
    }
    $("#mb-div-login-info").removeClass("showloginbox");
})
var MoniWidth = $(window).width();
if (MoniWidth > 800) {
    $(window).on("scroll", function () {
        var offset = $(".gio-hang-scroll").offset();
        if ($(".wrap-gio-hang-scroll .thanh-doc").html() != undefined)
            $(".wrap-gio-hang-scroll .thanh-doc").height(offset.top - 173);
        if ($(window).scrollTop() > 40) {
            $(".wrap-gio-hang-scroll").show();
            $("#topcontrol1").attr("style", "display:flex");

        } else {
            $(".wrap-gio-hang-scroll").hide();
            $("#topcontrol1").attr("style", "display:none");

        }
    });
}
else {
    $("#topcontrol1").removeAttr("style");
    $(window).on("scroll", function () {
        var MoniTop = $(window).scrollTop();
        if (MoniTop <= 40) {
            $(".wrap-gio-hang-scroll").hide();
            $("#topcontrol1").attr("style", "display:none");
        }
        else {
            $(".wrap-gio-hang-scroll").show();
            $("#topcontrol1").attr("style", $("#callcontrol1").attr("style"));
        }
    });
}

$(window).load(function () {
    var offset = $(".gio-hang-scroll").offset();
    if ($(".wrap-gio-hang-scroll .thanh-doc").html() != undefined)
        $(".wrap-gio-hang-scroll .thanh-doc").height(offset.top - 173);

    /*setInterval(KeepSessionAlive, 60000);*/

});

function KeepSessionAlive() {
    $.post('/Helpers/KeepSessionAlive.ashx', null, function () {
    });
}

$(function () {
    changControlHeaderForMobile();
})

$(window).resize(function () {
    changControlHeaderForMobile();
});

$(window).load(function () {
    changControlHeaderForMobile();
});

var changControlHeaderForMobile = function () {
    if ($(window).width() < 767) {
        $("#mb-a-login-info").children("img").attr("src", "/Content/images/icon-user-mobile.png");
        $("#SLGioHangMobile").next().attr("src", "/Content/images/icon-giohang-mobile.png");
        var widthLogo = $("#logo-mobile").children("img").width();
        var widthHeader = $(".navbar-header").width();
        $("#logo-mobile").attr("style", "position: absolute; left: " + (widthHeader / 2 - widthLogo / 2) + "px");
    }
    else {
        $("#mb-a-login-info").children("img").attr("src", "/Content/images/account-white.png");
        $("#SLGioHangMobile").next().attr("src", "/Content/images/cart-white.png");
        $("#logo-mobile").attr("style", "display: block;");
    }
};


var didScroll;
var lastScrollTop = 0;
var delta = 5;
var navbarHeight = $('.fix-menu-mobile').outerHeight();

$(window).scroll(function (event) {
    didScroll = true;
});

setInterval(function () {
    if (didScroll) {
        hasScrolled();
        didScroll = false;
    }
}, 100);

function hasScrolled() {
    var st = $(this).scrollTop();

    /* Make sure they scroll more than delta*/
    if (Math.abs(lastScrollTop - st) <= delta)
        return;

    /*
    If they scrolled down and are past the navbar, add class .nav-up.
     This is necessary so you never see what is "behind" the navbar.
    */
    if (st > lastScrollTop && st > navbarHeight) {
        /* Scroll Down */
        $('.fix-menu-mobile').removeClass('nav-down').addClass('nav-up');
        $('.navbar-header').removeClass('nav-header-down').addClass('nav-header-up');
    } else {
        /* Scroll Up */
        if (st + $(window).height() < $(document).height()) {
            $('.fix-menu-mobile').removeClass('nav-up').addClass('nav-down');
            $('.navbar-header').removeClass('nav-header-up').addClass('nav-header-down');
        }
    }

    lastScrollTop = st;
}

$("#mb-a-login-info-mobile").click(function () {
    if ($("#mb-div-login-info").hasClass("showloginbox")) {
        $("#mb-div-login-info").removeClass("showloginbox");
    }
    else {
        $("#mb-div-login-info").addClass("showloginbox");
    }
});

$(document).mouseup(function (e) {
    var container = $("#mb-div-login-info");
    if (!container.is(e.target) && container.has(e.target).length === 0) {
        container.hide();
    }
});

$(".txtsearchnews").keypress(function (e) {
    if (e.keyCode == 13) {
        $(".btn-submitsearchnews").trigger("click");
    }
});

$(".btn-submitsearchnews").click(function () {
    var keywordSearchNews = $(".txtsearchnews").val();
    if (keywordSearchNews === '' || keywordSearchNews === null) {
        alertify.warning("Bạn chưa nhập từ khóa cần tìm!", "warning", 15, null);
    }
    else {
        window.location.href = "/tin-tuc-mat-bao/" + keywordSearchNews + ".html";
    }
});

var CheckDonHangOnBegin = function () {
    $('#dvKetQuaKiemTraDonHang').hide();
}
var preClass = "";

$('.top-menu>li.havechild').hover(function () {
    var curClass = $(this).attr('class');
    $('.menu1').addClass("showmenu");
});

$('.top-menu>li.havechild').mouseleave(function () {
    $('.menu1').removeClass("showmenu");
});

$(document).ready(function () {
    if ($("#bannertop").html() != undefined) {
        $("#bannertop").load("/khuyenmai/bannertop?url=" + $(location).attr('pathname'));
    }
});
function capLock(t) {
    try {
        t.getModifierState("CapsLock") ? $(".capslock").show() : $(".capslock").hide()
    } catch (err) { }
}

function LaySoLuongDichVuDH() {
    $.ajax({
        type: "GET",
        url: "/Home/LaySoLuongDichVuDH1",
        timeout: 8000,
        success: function (t) {
            $(".urlPay").removeAttr("href");
            resp = $.parseJSON(t), 1 == resp.Status ? resp.Data[0] != undefined && resp.Data[0].Value > 0 && ($("#SoLuongGioHangScroll").text(resp.Data[0].Value), $("#SoLuongGioHang").text(resp.Data[0].Value), $("#SLGioHangMobile").text(resp.Data[0].Value)) : ($("#SoLuongGioHang").text(""), $("#SoLuongGioHangScroll").text(""), $("#SLGioHangMobile").text(""));
            urlgoc = location.origin;
            urlRoot = (urlgoc.indexOf("localhost") > -1 ? "http://localhost:8839" : urlgoc.indexOf("beta") > -1 ? "https://betapay.matbao.com" : "https://pay.matbao.net");
            $(".urlPay").attr("href", resp.Data[0].Value > 0 ? urlRoot + "/?madh=" + encodeURIComponent(resp.Data[1].Value) : urlRoot + "/gio-hang-trong.html");
        },
        error: function (t) { }
    });
    //$.get("/Home/LaySoLuongDichVuDH1", function (t) {
    //    //console.log('dh1');
    //    $(".urlPay").removeAttr("href");
    //    resp = $.parseJSON(t), 1 == resp.Status ? resp.Data[0].Value > 0 && ($("#SoLuongGioHangScroll").text(resp.Data[0].Value), $("#SoLuongGioHang").text(resp.Data[0].Value), $("#SLGioHangMobile").text(resp.Data[0].Value)) : ($("#SoLuongGioHang").text(""), $("#SoLuongGioHangScroll").text(""), $("#SLGioHangMobile").text(""))
    //    $(".urlPay").attr("href", resp.Data[0].Value > 0 ? "https://pay.matbao.net?madh=" + encodeURIComponent(resp.Data[1].Value) : "");
    //})
}
$(document).ready(function () {
    $(".showpassword").click(function () {
        "0" == $(this).children("img").attr("alt") ? ($(this).children("img").attr("src", "/Content/images/hien thi mat khau.svg"), $(this).children("img").attr("alt", "1"), $(".haveCaps").attr("type", "text")) : ($(this).children("img").attr("src", "/Content/images/tat hien thi mat khau.svg"), $(this).children("img").attr("alt", "0"), $(".haveCaps").attr("type", "password"))
    });
    !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
    $(".haveCaps").attr("onkeyup", "capLock(event);");
    LaySoLuongDichVuDH();
});
jQuery.fn.extend({
    renameAttr: function (name, newName, removeData) {
        var val;
        return this.each(function () {
            val = jQuery.attr(this, name);
            jQuery.attr(this, newName, val);
            jQuery.removeAttr(this, name);
            // remove original data
            if (removeData !== false) {
                jQuery.removeData(this, name.replace('data-', ''));
            }
        });
    }
});
//function clicktip(a) {
//    $('[data-toggle="tooltip"]').popover('hide');
//    var domain = $(a).attr("data-domain");
//    $('[data-domain="' + domain + '"]').popover('show');
//    $('[data-domain="' + domain + '"]').removeAttr("onclick");
//    //$(a).popover({
//    //    position: {
//    //        at: "bottom center",
//    //        my: "top center",
//    //        viewport: $(window)
//    //    }
//    //});
//}
$(function () {
    //$('[data-toggle="tooltip"]').renameAttr('data-original-title', 'data-content');
    //$('[data-toggle="tooltip"]').attr("data-original-title", "<button type='button' class='close'>×</button>");
    //$('[data-toggle="tooltip"]').attr("data-html", "true");
    //$('[data-toggle="popover"]').attr("data-toggle", "tooltip");
    //const $tooltip = $('[data-toggle="tooltip"]');
    //$tooltip.popover({
    //    position: {
    //        at: "bottom center",
    //        my: "top center",
    //        viewport: $(window)
    //    }
    //});
    //$('[data-toggle="tooltip"]').on('click', function (e) {
    //    $('[data-toggle="tooltip"]').not(this).popover('hide');
    //});
    //$('body').on('click', '.popover .close', function () {
    //    $("div[id*='popover']").removeClass("in");
    //    $("div[id*='popover']").remove();
    //    $("[aria-describedby*='popover']").removeAttr("aria-describedby");
    //});
    //$('html').on('click', function (e) {
    //    if (typeof $(e.target).data('original-title') == 'undefined' && !$(e.target).parents().is('.popover.in')) {
    //        $('[data-toggle="tooltip"]').popover('hide');
    //    }
    //});
    //window.onscroll = function() {
    //    var OpenTooltip = $(".popover-content");
    //    var ztooltip = $("[aria-describedby='" + OpenTooltip.parent(".popover").attr("id") + "']");
    //    var OpenGift = $(".overtip").css("display");
    //    if (ztooltip.attr("rel") != "6") {
    //        setTimeout(function () {
    //            if (OpenTooltip.html() != undefined) {
    //                $tooltip.popover('hide');
    //                ztooltip.popover('hide');
    //            }
    //            if (OpenGift == "block") {
    //                $(".overtip").hide();
    //            }
    //        }, 1000);
    //    }
    //};

}), $(document).ready(function () {
    ! function (t) {
        t.fn.outside = function (n, o) {
            return this.each(function () {
                t(this);
                var i = this;
                t(document).bind(n, function e(a) {
                    a.target === i || t.contains(i, a.target) || (o.apply(i, [a]), i.parentNode || t(document.body).unbind(n, e))
                })
            })
        }
    }(jQuery), $("#header-row-nav").outside("click", function (t) {
        $("#header-row-nav").parent().hasClass("in") && ($("#header-row-nav").parent().removeClass("in"), $("#menu-mb-main").addClass("collapsed"), $(".btncontrolmenu").removeClass("btncontrolmenuclose"))
    }), $("#whoisdomaintextMulti").outside("click", function (t) {
        var n = $("#whoisdomaintextMulti").val(),
            o = $("#whoisdomaintextMulti").css("display");
        "" == n && "none" != o ? $("#placeholder-CheckDomainMulti").show() : $("#placeholder-CheckDomainMulti").hide()
    }), $("#placeholder-CheckDomainMulti").click(function () {
        $(this).hide(), $("#whoisdomaintextMulti").focus()
    })
});
/*=========================== Chat ============================*/
function LoadChatMatBao() {
    var isAllow = false;
    if (navigator.userAgent.indexOf('Firefox') != -1 && parseFloat(navigator.userAgent.substring(navigator.userAgent.indexOf('Firefox') + 8)) >= 3.6) {//Firefox
        isAllow = true;
    } else if (navigator.userAgent.indexOf('Chrome') != -1 && parseFloat(navigator.userAgent.substring(navigator.userAgent.indexOf('Chrome') + 7).split(' ')[0]) >= 15) {//Chrome
        isAllow = true;
    } else if (navigator.userAgent.indexOf('Safari') != -1 && navigator.userAgent.indexOf('Version') != -1 && parseFloat(navigator.userAgent.substring(navigator.userAgent.indexOf('Version') + 8).split(' ')[0]) >= 5) {//Safari
        isAllow = true;
    }
    else if (/MSIE (\d+\.\d+);/.test(navigator.userAgent)) { //test for MSIE x.x;
        var ieversion = new Number(RegExp.$1) // capture x.x portion and store as a number
        if (ieversion >= 8) {
            isAllow = true;
        }
    }
    else {
        isAllow = false;
    }
    if (isAllow) {
        var data_arg = $("#hdfdata_chat").attr("value");
        if (data_arg == "") {
            data_arg = $("#hdfuid").attr("value") + '$' + $("#hdfcurDate").attr("value");
        }
        loadChat(data_arg);
        //console.log(data_arg);
    }
}
$(".ngonngudachon").click(function () {
    $(".chonngongumobile").is(":visible") ? $(".chonngongumobile").slideUp("fast") : $(".chonngongumobile").slideDown("fast")
}), $(".itemngonngumobile").click(function () {
    $(".ngonngudachon").html($(this).html() + " &#9660;"), $(".chonngongumobile").slideUp("fast"), window.location.href = $(this).attr("data-val")
}), $(document).ready(function () {
    $("#topcontrol1").click(function () {
        $("html, body").animate({
            scrollTop: 0
        }, 300)
    }), $("#phondv").hide(), $("#iconphone").click(function () {
        $("#phondv").slideToggle("slow")
    });
    var n = 0;
    $("#mb-a-login-info").click(function () {
        0 == n ? ($(this).css("background-color", "#59737E"), $("#mb-div-login-info").show(), n = 1) : ($(this).css("background-color", ""), $("#mb-div-login-info").hide(), n = 0)
    }), $("#wrap-login-id").outside("click", function (o) {
        $("#mb-div-login-info").hide(), $("#mb-a-login-info").css("background-color", ""), n = 0
    });
    var o = 0;
    $("#matbao-login").click(function () {
        $('*').popover('hide');
        o = 0 == o ? 1 : 0
    }), $("#matbao-account").click(function () {
        o = 0 == o ? 1 : 0
    }), $(document).mouseup(function (n) {
        var o = $("#header-row");
        o.is(n.target) || 0 !== o.has(n.target).length || $("#header-row .sub-top-menu:visible").parent("li").removeClass("active");
        var t = $("#lilogin");
        t.is(n.target) || 0 !== t.has(n.target).length || ($("#lilogin .sub-top-menu:visible").parent("li").removeClass("active"), $("#lilogin #matbao-login").children("img").attr("src", "/Content/images/menutop/Dangnhap .svg"));
        var e = $("#accountinfo");
        e.is(n.target) || 0 !== e.has(n.target).length || ($("#accountinfo .sub-top-menu:visible").parent("li").removeClass("active"), $("#accountinfo #matbao-account").children("img").attr("src", "/Content/images/menutop/Dangnhap .svg"))
    });
    var windWidth = window.innerWidth;
    if (windWidth > 1080) {
        $("ul.navbar-nav>li").click(function () {
            var that = this;
            $("ul.navbar-nav>li").removeClass("active")
            $(that).addClass($(that).attr("class") == "active" ? "" : "active");
            /*timer = setTimeout(function () {
                $("ul.navbar-nav>li").removeClass("active")
                $(that).addClass($(that).attr("class") == "active" ? "" : "active");
            }, 400);*/
        }).mouseleave(function () {
            /*if (timer != undefined)
                clearTimeout(timer);*/
            out = setTimeout(function () {
                if ($(".sub-top-menu:hover,#header-row-nav:hover").length > 0) { }
                else {
                    $("ul.navbar-nav>li").removeClass("active");
                }
            }, 400);
        });
        $(".main, .mb-header").hover(function () {
            $("ul.navbar-nav>li").removeClass("active")
        });
    }
    else {
        $("ul.navbar-nav>li>a").click(function () {
            var hotro = ($(this).parent().attr("class") == undefined ? false : $(this).parent().attr("class").indexOf("nochange") > -1);
            "active" == $(this).parent().attr("class") || hotro ? $("ul.navbar-nav>li").removeClass("active") : ($("ul.navbar-nav>li").removeClass("active"), $(this).parent("li").addClass("active"), $(".topSubjectMenu").addClass("hidden"))
        });
    }
    //$(".sub-top-menu .panel-body .col-md-9 ul li").mouseenter(function () {
    //    $(this).children('a').children("i").children('img').attr("src", $(this).children('a').children("i").children('img').attr("src").replace(".svg", "-white.svg"));
    //}).mouseleave(function () {
    //    $(this).children('a').children("i").children('img').attr("src", $(this).children('a').children("i").children('img').attr("src").replace("-white.svg", ".svg"));
    //});
    //$("body").on(EventClick, ".tip, #showMenuAccount", function () {
    //    var style = $(".idpagetooltip").attr("style");
    //    if (style == undefined || style.indexOf("none;") > -1) {
    //        $(".idpagetooltip").show();
    //    }
    //    else {
    //        $(".idpagetooltip").hide();
    //    }
    //});
})
var ngonNguToScript = "vi";
function OnRegisterSuccess(data) {
    $('#registerLoading').hide();
    $('#register_submit').show();
    if (data.ErrorType == 3)
        alert('Mã bảo vệ không đúng!');
    else if (data.ErrorType == 2)
        alert('Thông tin không hợp lệ, vui lòng kiểm tra lại!');
    else if (data.ErrorType == 1)
        alert('Tạo tài khoản lỗi, vui lòng thử lại!');
    else location.href = "/thanh-vien/kich-hoat-tai-khoan.html";
}

function OnRegisterFailure(ajaxContext) {
    alert("Có lỗi hệ thống xảy ra, vui lòng thử lại!");
    $('#registerLoading').hide();
    $('#register_submit').show();
}

function OnLoginFailure(ajaxContext) {
    alert("Có lỗi hệ thống xảy ra, vui lòng thử lại!");
    $('#LoginLoading').hide();
    $('#btn_login_submit').show();
}

function OnLoginSuccess(data) {
    $('#LoginLoading').hide();
    $('#btn_login_submit').show();
    if (data.ErrorType == 1)
        alert('Tên đăng nhập hoặc mật khẩu không đúng!');
    else if (data.ErrorType == 2) {
        alert('Tài khoản chưa được kích hoạt!');
        location.href = "/thanh-vien/lay-lai-ma-kich-hoat-tai-khoan.html";
    }
    else if (data.ErrorType == 3)
        alert('Tài khoản đang tạm khóa, vui lòng liên hệ tổng đài để được giải quyết!');
    else location.href = location.href;
}

function submitLogin() {
    if ($("#form-login").valid()) {
        $('#btn_login_submit').hide();
    }
}

function submitRegister() {
    if ($("#form-register").valid()) {
        $('#register_submit').hide();
    }
}

function OnActiveAccountSuccess(data) {
    $('#ActiveAccountLoading').hide();
    $('#active_submit').show();
    if (data.ErrorType == 0) {
        alert('Tài khoản đã được kích hoạt!');
        location.href = "/";
    }
    else if (data.ErrorType == 1) {
        alert("Mã xác nhận không đúng. Vui lòng kiểm tra lại!");
    }
    if (data.ErrorType == 2) {
        alert("Mã xác nhận đã hết hạn, vui lòng liên hệ ban quản trị để được hỗ trợ!");
    }
}

function OnActiveAccountFailure(ajaxContext) {
    alert("Có lỗi hệ thống xảy ra, vui lòng thử lại!");
    $('#ActiveAccountLoading').hide();
    $('#active_submit').show();
}

function OnResendCodeActiveAccountSuccess(data) {
    $('#ResendCodeActiveAccountLoading').hide();
    $('#resend_code_active_submit').show();
    if (data.ErrorType == 0) {
        alert('Mã xác nhận mới đã được gửi!');
        location.href = "/thanh-vien/kich-hoat-tai-khoan.html";
    }
    else {
        alert("Có lỗi hệ thống xảy ra, vui lòng thử lại!");
    }
}

function OnResendCodeActiveAccountFailure(ajaxContext) {
    alert("Có lỗi hệ thống xảy ra, vui lòng thử lại!");
    $('#ResendCodeActiveAccountLoading').hide();
    $('#resend_code_active_submit').show();
}
function makeid(length) {
    var result = '';
    var characters = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
    var charactersLength = characters.length;
    for (var i = 0; i < length; i++) {
        result += characters.charAt(Math.floor(Math.random() * charactersLength));
    }
    return result;
}
function tooltip() {
    $('body').on(EventClick, ".re-popover .close", function () {
        $(this).parent().remove();
        if ($('#slideDanhGia').html() != undefined) {
            $('#slideDanhGia').slick('slickPlay');
        }
    });
    $('[data-toggle="tooltip"], [data-toggle="popover"]').on(EventClick, function (event) {
        event.stopPropagation(); $('[data-toggle="tooltip"]').popover('hide');
        if ($('#slideDanhGia').html() != undefined) {
            $('#slideDanhGia').slick('slickPause');
        }
        var myContent = $(this).html().trim().replace('<i class="fa fa-question-circle"></i>', "");
        var checkoffice365 = $(this).attr("class") == "off365" || $(this).attr("class") == "btgoiqua";
        if (myContent == undefined || myContent == "" || checkoffice365) {
            $(".re-popover").remove();
            var toolid = "re-" + makeid(5);
            $(this).attr("data-tooltipid", toolid);
            var special_1 = $(this).attr("class").indexOf("special_1") > -1;
            var posi = $(this).attr("data-placement");
            var cont = ($(this).attr("data-content") == undefined ? $(this).attr("data-original-title") : $(this).attr("data-content"));
            var top = $(this).offset().top;
            var left = $(this).offset().left;
            if ($(this).attr("class").indexOf("off365") > -1) {
                top = $(this).offset().top - 2;
                left = $(this).offset().left + $(this).width() / 2;
            }
            if ($(this).attr("class").indexOf("item") > -1) {
                left = $(this).offset().left + $(this).children("span").width() / 2 - 10;
            }
            if ($(this).attr("class").indexOf("mbtooltip-promotion") > -1) {
                left = $(this).offset().left + $(this).width() / 2 - 8;
            }
            var myheight = 0;
            if (posi == "bottom") {
                myheight = $(this).height();
            }
            cont = cont.replace(/"/g, "'").replace("<button class='close' style='margin-top:-5px;margin-right:-5px;'>×</button>", "");
            $('body').append("<div class='re-popover' data-position='" + posi + "' data-showid='" + toolid + "'><button type='button' class='close'></button><span class='re-content'>" + cont + "</span></div>");
            var vheight = $(".re-popover").height() + 57;
            var vwidth = ($(".re-popover").width() / 2) + 18;
            if (special_1) {
                var rtop = top - 50;
                var rleft = left + 23;
                $(".re-popover").append("<style>.re-popover{top:" + rtop + "px !important; left:" + rleft + "px !important;margin-left:0px}.re-popover:before{left:0 !important; top: 53px !important;}</style>");
                return false;
            }
            $(".re-popover").attr("style", (posi == "bottom" ? "top" + ":" + (top + (myheight = 0 ? 15 : myheight + 7)) : "top" + ":" + (top - vheight)) + "px; left:" + (left - vwidth) + "px;margin-left:0px");
            var retop = $(".re-popover").offset().top;
            var releft = $(".re-popover").offset().left + 8;
            var ovleft = 0;
            var overleft = releft + (($(".re-popover").width() + 32) / 2) + 1;
            if (overleft < left) {
                ovleft = vwidth + 8;
            }
            if (releft < 0) {
                $(".re-popover").css("left", "0");
                if (posi == "top") {
                    $(".re-popover").append("<style>.re-popover:after{left: calc(50% + " + (releft - 7) + "px) !important;}</style>");
                }
                else {
                    $(".re-popover").append("<style>.re-popover:before{left: calc(50% + " + (releft - 7) + "px) !important;}</style>");
                }
            }
            else if (ovleft > 0) {
                if (posi == "top") {
                    var nheight = $(".re-popover").height() + 57;
                    var retopa = retop - (nheight - vheight);
                    //var retopa = retop - 17;
                    $(".re-popover").append("<style>.re-popover:after{left: " + ovleft + "px !important;}</style>");
                    $(".re-popover").css("top", retopa + "px");
                }
                else {
                    $(".re-popover").append("<style>.re-popover:before{left: " + ovleft + "px !important;}</style>");
                }
            }
            else {
                if ($(".re-popover").width() < 280) {
                    var rewidth = (((vwidth * 2) - 3) - $(".re-popover").width() - 30) / 2;
                    var reheight = (vheight - 56) - $(".re-popover").height();
                    var overMobile = $(".re-popover").offset().left + $(".re-popover").width() + 50;
                    var mobiWidth = $(window).width();
                    if (overMobile > mobiWidth) {
                        $(".re-popover").css("left", $(".re-popover").offset().left - (overMobile - mobiWidth));
                        rewidth = rewidth + (overMobile - mobiWidth);
                    }
                    $(".re-popover").css("top", $(".re-popover").offset().top + reheight);
                    if (posi == "top")
                        $(".re-popover").append("<style>.re-popover:after{left: calc(50% + " + rewidth + "px) !important;}</style>");
                    else
                        $(".re-popover").append("<style>.re-popover:before{left: calc(50% + " + rewidth + "px) !important;}</style>");
                }
            }
            return false;
        }
    });
    $('body').on(EventClick, ".re-popover", function (event) {
        event.stopPropagation();
    });
    $(window).click(function () {
        $(".re-popover").remove();
        $('#slideDanhGia').slick('slickPlay');
    });
    window.onscroll = function () {
        var OpenTooltip = $(".re-content");
        var OpenGift = $(".overtip").css("display");
        setTimeout(function () {
            //if (OpenTooltip.html() != undefined) {
            //    OpenTooltip.parent(".re-popover").remove();
            //    $('#slideDanhGia').slick('slickPlay');
            //}
            if (OpenGift == "block") {
                $(".overtip").hide();
            }
        }, 1000);
    };
}
function HideChatTalkTo() {
    var s3 = ($("#tawkchat-container").html() == undefined ? "iframe[id*='-160']" : "#tawkchat-container");
    var ChatTalkTo = $(s3).attr('id');
    var xStyle = $("#" + ChatTalkTo).attr("style");
    if (xStyle != undefined) {
        if (xStyle == "display: none !important;" || xStyle == "display: block !important;") {
            zStyle = $("#" + ChatTalkTo).children("iframe").attr("style");
            if (zStyle != undefined) {
                if (zStyle.indexOf("display: none !important;") > -1) {
                    $("iframe[title='chat widget']:first-child").hide();
                    //Tawk_API.hideWidget();
                }
            }
        }
        else {
            if (xStyle.indexOf("top: 0px !important;") <= -1) {
                $("iframe[title='chat widget']:first-child").hide();
                //Tawk_API.hideWidget();
            }
        }
    }
}
if (MoniWidth <= 825) {
    chatInterval = setInterval("HideChatTalkTo()", 1000);
}
//function statusChangeCallback(n) {
//    console.log("statusChangeCallback"), console.log(n), "connected" === n.status ? testAPI() : "not_authorized" === n.status ? document.getElementById("status").innerHTML = "Please log into this app." : document.getElementById("status").innerHTML = "Please log into Facebook."
//}
//function checkLoginState() {
//    FB.getLoginStatus(function (n) {
//        statusChangeCallback(n)
//    })
//}
//function fb_login() {
//    FB.login(function (n) {
//        n.authResponse ? $.get("/FacebookCallback?accessToken=" + n.authResponse.accessToken, function (n) {
//            n.status ? window.location.href = "/" : alertify.notify("Vui lòng đăng nhập https://id.matbao.net và cấu hình đăng nhập bằng Facebook.", "error", 15, null)
//        }) : console.log("User cancelled login or did not fully authorize.")
//    }, {
//        scope: "email,public_profile"
//    })
//}
//function google_login() {
//    var Google_cLient = $("#hdfGoogle_Client_ID").attr("value");
//    gapi.auth.authorize({
//        client_id: Google_cLient,
//        scope: "https://www.googleapis.com/auth/userinfo.email"
//    }, function () {
//        fetch_gg(gapi.auth.getToken())
//    })
//}

//function fetch_gg(n) {
//    $.get("/GoogleCallback?accessToken=" + n.access_token, function (n) {
//        1 == n.status ? window.location.href = "/" : 3 == n.status ? window.location.href = "/XacMinhDangNhap" : 2 == n.status ? window.location.href = "/XacMinhDangNhapGoogleAuthenticator" : alertify.notify("Vui lòng đăng nhập https://id.matbao.net và cấu hình đăng nhập bằng Google.", "error", 15, null)
//    })
//} ! function () {
//    var n = document.createElement("script");
//    n.type = "text/javascript", n.async = !0, n.src = "https://apis.google.com/js/client.js?onload=onLoadCallback";
//    var o = document.getElementsByTagName("script")[0];
//    o.parentNode.insertBefore(n, o)
//}(), window.fbAsyncInit = function () {
//    var Facebook_Client = $("#Facebook_Client_ID").attr("value");
//    FB.init({
//        appId: Facebook_Client,
//        status: !0,
//        cookie: !0,
//        xfbml: !0,
//        oauth: !1,
//        version: "v2.5"
//    })
//},
//    function (n, o, t) {
//        var e, a = n.getElementsByTagName(o)[0];
//        n.getElementById(t) || ((e = n.createElement(o)).id = t, e.src = "//connect.facebook.net/en_US/sdk.js", a.parentNode.insertBefore(e, a))
//    }(document, "script", "facebook-jssdk"), $("#myModalCallAuto").on("hidden.bs.modal", function () {
//        $("#call-error").html(""), $("#call-error").hide(), $("#call-message").html(""), $("#call-message").hide(), $("#ContentInfo").show(), $("#phonenumberautocall").val("")
//    }), 
$("#callcontrol1").click(function () {
    $("#button-call").attr("disabled", false);
});
$("#button-call").click(function () {
    $("#button-call").attr("disabled", true);
    var n = {};
    n.cusphone = $("#phonenumberautocall").val(), n.cusname = $("#namephone").val(), n.khuvuc = $("input[name=cta-location]:checked").val(), n.noidung = $("input[name=cta-noidungtuvan]:checked").val(), n.timeslot = $("#drlTimeSlot").val(), $.ajax({
        type: "POST",
        url: "/Home/CallPhone",
        data: n,
        success: function (n) {
            n.status ? ($("#call-message").html(n.msg), $("#call-error").html(""), $("#call-error").hide(), $("#call-message").show()) : ($("#call-error").html(n.msg), $("#call-error").show())
        },
        error: function (n) { $("#button-call").attr("disabled", false); }
    })
});
$('#ContentInfo .input-call input, #ContentInfo .radio-danger input').on('change', function () {
    $("#button-call").attr("disabled", false);
    $("#call-error").html(""), $("#call-error").hide();
});
$('#drlTimeSlot').on('change', function () {
    if (this.value == "") {
        $("#button-call").text("Tư vấn ngay");
    }
    else {
        $("#button-call").text("Gửi");
    }
});
var createCookie = function (name, value, days) {
    var expires;
    if (days) {
        var date = new Date();
        date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000));
        expires = "; expires=" + date.toGMTString();
    }
    else {
        expires = "";
    }
    document.cookie = name + "=" + value + expires + "; path=/";
}
function getCookie(c_name) {
    if (document.cookie.length > 0) {
        c_start = document.cookie.indexOf(c_name + "=");
        if (c_start != -1) {
            c_start = c_start + c_name.length + 1;
            c_end = document.cookie.indexOf(";", c_start);
            if (c_end == -1) {
                c_end = document.cookie.length;
            }
            return unescape(document.cookie.substring(c_start, c_end));
        }
    }
    return "";
}
var Tawk_API = Tawk_API || {}, Tawk_LoadStart = new Date;
var tawkchat = ($("#tawkchat-container") == undefined ? "div[id*='-160']" : "#tawkchat-container");
var hasclick = false;
function chatvoichungtoi() {
    var t = document.createElement("script"), e = document.getElementsByTagName("script")[0];
    t.async = !0, t.src = "https://embed.tawk.to/5a03f73d198bd56b8c03a1b1/default", t.charset = "UTF-8", t.setAttribute("crossorigin", "*"), e.parentNode.insertBefore(t, e)
}
function loadTawkTo() {
    var iOS = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
    var EventClick1 = "click";
    if (iOS == true) { EventClick1 = "click touchstart"; }
    var MoniWidth = $(window).width();
    var iframeX = $("iframe[id*='-160']");
    if (MoniWidth <= 825) {
        $(".g-useful-links").attr("style", "bottom: 20px;");
    }
    else {
        $("#iChat").remove();
    }
    $("body").on(EventClick1, "#iChat", function () {
        Tawk_API.showWidget();
        Tawk_API.maximize();
        $(tawkchat).append("<a id='iClose' style='color: white;display: block;width: 100%;height: 40px;position: absolute;text-align: right;top: 14px;right: 14px;font-size: 22px;z-index:0;'><i class='fa fa-close'></i></a>");
    });
    $("body").on(EventClick1, "#iClose", function () {
        Tawk_API.minimize();
        Tawk_API.hideWidget();
        $("#iClose").remove();
    });
    $("body").on(EventClick1, "#ShowPop", function () {
        var over = $("#ShowPop").attr("rev");
        if (over == "o") {
            $("#ShowPop").attr("rev", "c");
            $(".g-useful-links a[class*='link-']").attr("style", "display:flex !important;");
            $("#ShowPop").html("<i class='fa fa-close'></i>");
            $("#ShowPop").css("background", "#76b51b");
            $("#ShowPop").removeClass("chuyen");
            $(tawkchat).attr("style", "border: 0px none !important; padding: 0px !important; z-index: 200090000 !important; overflow: visible !important; min-width: 0px !important; min-height: 0px !important; max-width: none !important; max-height: none !important; width: auto !important; height: auto !important; position: fixed !important; display: block !important; margin: 0px !important; bottom: 0px !important; top: auto !important; right: 0px !important; left: auto !important;");
        }
        else {
            $("#ShowPop").attr("rev", "o");
            try {
                Tawk_API.hideWidget();
            } catch (e) { }
            $(".g-useful-links a[class*='link-']").removeAttr("style");
            $("#ShowPop").html("");
            $("#ShowPop").addClass("chuyen");
        }
    });
}
$(window).on('load', function () {
    var disalbedTawkTo = $("input[id='disalbedTawkTo']").val();
    if (disalbedTawkTo == "1") {
        loadTawkTo();
        chatvoichungtoi();
        if (MoniWidth <= 825) {
            setTimeout(function () {
                Tawk_API.hideWidget();
            }, 1800);
        }
    }
    else {
        $("#iChat").remove();
    }
});
$(document).ready(function () {
    tooltip();
    $(".div-doitac").each(function (index) {
        var stylex = $(this).parent().attr("style");
        if (stylex != undefined && stylex != "") {
            $(this).children("a").attr("style", stylex);
        }
        else {
            $(this).children("a").attr("style", "width: 234px;");
        }
    });
    getMapFooter();
    $("body").on(EventClick, ".showPopupISO", function () {
        $("#popISO_27001").remove();
        $("body").append("<div id='popISO_27001' style='width:100%;height:100%;z-index:200090000;overflow: hidden;position: fixed;top: 0;left: 0;background: #00000059;'><span style='display:block;width:1170px;max-width:calc(100vw - 30px);max-height:calc(100vh - 30px);background:#FFF;padding:10px;border-radius:8px;position:absolute;top:50%;left:50%;transform: translate(-50%, -50%);'><a class='close' style='width: 48px; height: 48px; position: absolute; top: -24px; right: -24px; opacity: 1; z-index: 100; background: url(/Content/images/footer_image/Group.svg) center no-repeat, #fff; background-size: 100% 100%; border-radius: 50%; box-shadow: 1px 1px 2px #0000002b;'></a><span style='width:100%;max-height: calc(100vh - 50px);overflow:auto;display: block;'><img alt='MatBao ISO:27001' style='display:block;margin:0 auto; max-width:100%;' src='/Content/images/footer_image/hinh_chung_nhan_ISO_27001.png' /></span></span></div>");
    });
    $("body").on(EventClick, "#popISO_27001:not(a), #popISO_27001 .close", function () {
        $("#popISO_27001").remove();
    });
});
var gMapImported;
function getMapFooter() {
    var iOS1 = !!navigator.platform && /iPad|iPhone|iPod/.test(navigator.platform);
    var EventClick1 = "click";
    if (iOS1 == true) { EventClick1 = "click touchstart"; }
    $("body").on(EventClick1, ".viewMap", function () {
        if (gMapImported == undefined) {
            gMapImported = document.createElement('script');
            gMapImported.src = 'https://maps.googleapis.com/maps/api/js?key=AIzaSyBIekGmpi7nVwxqZ6ZFj_zN2f8ABl1OJKM&callback=getMapFooter&libraries=&v=weekly';
            document.head.appendChild(gMapImported);
            var myidm = $(this);
            setTimeout(function () { myidm.trigger("click"); }, 200);
            return false;
        }
        var lat1 = '10.85266';
        var lng1 = '106.62831';
        var lat2 = '10.800801';
        var lng2 = '106.642195';
        var lat3 = '21.038198';
        var lng3 = '105.813526';
        const iconBase = "/Content/images/";
        const icons = {
            info: {
                icon: iconBase + "logomap.png",
            },
        };
        var numMap = $(this).attr("id");
        if (numMap == "map_1") {
            $(".bgGmap").show();
            $(".popupGMap").fadeIn();
            map = new google.maps.Map(document.getElementById("resultPopupGmap"), {
                center: new google.maps.LatLng(lat1, lng1),
                zoom: 17,
                mapTypeControl: false,
            });
            const contentString0 = "<div style='font-size:12px;'><b style='margin-bottom:0;'>Trụ sở chính</b>\
	        <p style='margin:5px 0;'>Tầng 3 Anna Building, Công Viên Phần Mềm Quang Trung, Q.12, TP.Hồ Chí Minh</p></div>";

            const infowindow1 = new google.maps.InfoWindow({
                content: decodeURIComponent(contentString0),
            });
            const features1 = [
              {
                  position: new google.maps.LatLng(lat1, lng1),
                  type: "info",
              }
            ];
            for (let i = 0; i < features1.length; i++) {
                const marker = new google.maps.Marker({
                    position: features1[i].position,
                    icon: icons[features1[i].type].icon,
                    map: map,
                    title: "Trụ sở chính Công ty Cổ phần Mắt Bão",
                });
                infowindow1.open(map, marker);
                marker.addListener("click", () => {
                    infowindow1.open(map, marker);
                });
            }
        }
        else if (numMap == "map_2") {
            $(".bgGmap").show();
            $(".popupGMap").fadeIn();
            map = new google.maps.Map(document.getElementById("resultPopupGmap"), {
                center: new google.maps.LatLng(lat2, lng2),
                zoom: 17,
                mapTypeControl: false,
            });
            var mName = "Công ty Cổ phần Mắt Bão";
            var mAddress = "12A Đường Núi Thành, Phường 13, Tân Bình, Thành phố Hồ Chí Minh 72110";
            var iframeReviews = "<div style='overflow:hidden;background: #efefef;width: 180px;height: 40px;'><iframe src='https://www.google.com/maps/embed?pb=!1m18!1m12!1m3!1d1959.5686083411972!2d106.64110065802912!3d10.800800998076284!2m3!1f0!2f0!3f0!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x31752945ef719ff9%3A0xaabf9e5bd278f3a0!2zQ8O0bmcgdHkgQ-G7lSBwaOG6p24gTeG6r3QgQsOjbw!5e0!3m2!1svi!2s!4v1620187478461!5m2!1svi!2s' width='400' height='300' style='border:0;margin-left: -23px;margin-top: -90px;' allowfullscreen='' loading='lazy'></iframe></div>";

            const contentString = "<div style='font-size:12px;'><b style='margin-bottom:0;'>" + mName + "</b>\
	        <p style='margin:5px 0;'>" + mAddress + "</p>" + iframeReviews + "</div>";

            const infowindow2 = new google.maps.InfoWindow({
                content: decodeURIComponent(contentString),
            });
            const features2 = [
            {
                position: new google.maps.LatLng(lat2, lng2),
                type: "info",
            }
            ];
            for (let i = 0; i < features2.length; i++) {
                const marker = new google.maps.Marker({
                    position: features2[i].position,
                    icon: icons[features2[i].type].icon,
                    map: map,
                    title: "Công ty Cổ phần Mắt Bão",
                });
                infowindow2.open(map, marker);
                marker.addListener("click", () => {
                    infowindow2.open(map, marker);
                });
            }
        }
        else if (numMap == "map_3") {
            $(".bgGmap").show();
            $(".popupGMap").fadeIn();
            map = new google.maps.Map(document.getElementById("resultPopupGmap"), {
                center: new google.maps.LatLng(lat3, lng3),
                zoom: 17,
                mapTypeControl: false,
            });
            var zmName = "Công ty Mắt Bão chi nhánh Hà Nội";
            var zmAddress = "Tầng 8 - Tòa nhà 381 Đội Cấn - Phường Liễu Giai - Quận Ba Đình, Hà Nội, HaNoi City 100000";
            var ziframeReviews = "<div style='overflow:hidden;background: #efefef;width: 180px;height: 40px;'><iframe src='https://www.google.com/maps/embed?pb=!1m14!1m8!1m3!1d3723.860400915229!2d105.811287!3d21.038271!3m2!1i1024!2i768!4f13.1!3m3!1m2!1s0x0%3A0x644ec34ca49b0b5b!2zQ8O0bmcgdHkgTeG6r3QgQsOjbyBjaGkgbmjDoW5oIEjDoCBO4buZaQ!5e0!3m2!1svi!2s!4v1620187549854!5m2!1svi!2s' width='400' height='300' style='border:0;margin-left: -23px;margin-top: -76px;' allowfullscreen='' loading='lazy'></iframe></div>";

            const contentString1 = "<div style='font-size:12px;'><b style='margin-bottom:0;'>" + zmName + "</b>\
	        <p style='margin:5px 0;'>" + zmAddress + "</p>" + ziframeReviews + "</div>";

            const infowindow3 = new google.maps.InfoWindow({
                content: decodeURIComponent(contentString1),
            });
            const features3 = [
            {
                position: new google.maps.LatLng(lat3, lng3),
                type: "info",
            }
            ];
            for (let i = 0; i < features3.length; i++) {
                const marker1 = new google.maps.Marker({
                    position: features3[i].position,
                    icon: icons[features3[i].type].icon,
                    map: map,
                    title: "Công ty Mắt Bão chi nhánh Hà Nội",
                });
                infowindow3.open(map, marker1);
                marker1.addListener("click", () => {
                    infowindow3.open(map, marker1);
                });
            }
        }
    });
    $("body").on(EventClick1, ".popupGMap .close,.bgGmap:not(#resultPopupGmap)", function () {
        $(".popupGMap").fadeOut();
        $(".bgGmap").hide();
        $("#resultPopupGmap").html("");
    });
}
function layGiaFlashSale(idGia, idFlashSale, vMaDichVu, vTruongHop, vSoNam, giacu, isfulltime) {
    var oldValue = $(idGia).html(); var isInput = false;
    if (isfulltime == undefined) {
        isfulltime = false;
    }
    if (vTruongHop == 2) {
        vTruongHop == 0;
        isInput = true;
    }
    if (vTruongHop == 3) {
        vTruongHop == 1;
        isInput = true;
    }
    if (vSoNam == undefined) {
        vSoNam = "";
    }
    if (giacu == undefined) {
        giacu = "";
    }
    $.ajax({
        type: "GET",
        url: "/Home/LayGiaFlashSale",
        data: { MaDichVu: vMaDichVu, truonghop: vTruongHop, SoNam: vSoNam },
        timeout: 8000,
        success: function (t) {
            resp = $.parseJSON(t);
            if (resp.Status == true) {
                var oldHref = $(idFlashSale.split(',')[0]).attr("href");
                var _data = resp.Data.split('|');
                if (!isInput) {
                    if (!isfulltime) {
                        if (idGia.indexOf("data-ggia1") > -1 && giacu.replace(" đ", "") != _data[1]) {
                            $(idGia).html("<s>" + giacu + "</s><br /><span style='color:red;'>" + _data[1] + " đ</span>");
                            let vggia1 = parseFloat(giacu.replace(" đ", "").replaceAll(/\./gi, ""));
                            let vdata1 = parseFloat(_data[1].replace(" đ", "").replaceAll(/\./gi, ""));
                            let vtong1 = parseFloat($(idGia.replace('ggia1', 'gtong1')).text().replace(" đ", "").replaceAll(/\./gi, ""));
                            $(idGia.replace('ggia1', 'gtong1')).html("<s>" + NumCommas(vtong1) + " đ</s><br /><span style='color:red;'>" + NumCommas(vtong1 - (vggia1 - vdata1)) + " đ</span>");
                        }
                        else {
                            let plusD = 0;
                            if (idGia.indexOf("#isDMcom") > -1 || idGia.indexOf("#isDMnet") > -1 || idGia.indexOf("#isKMHot") > -1) {
                                plusD = 1;
                            }
                            $(idGia).html((plusD == 1 ? " " : "") + _data[1] + (idGia.indexOf("data-ggia1") > -1 || plusD == 1 ? " đ" : ""));
                        }
                    }
                    else {
                    if ((idGia.indexOf("data-ggia") > -1 || idGia.indexOf("data-token") > -1) && _data[1] != undefined && _data[1] != "") {
                            let sonhan = idGia.indexOf("data-ggia") > -1 ? parseInt(idGia.split('=')[0].replace('[', '').replace('data-ggia', '')) : 1;
                            let vggia1 = parseFloat(giacu.replace(" đ", "").replaceAll(/\./gi, ""));
                            let giamoi = idGia.indexOf("data-ggia") > -1 ? vggia1 - parseFloat(_data[1].replace(" đ", "").replaceAll(/\./gi, "")) : parseFloat(_data[1].replace(" đ", "").replaceAll(/\./gi, ""));
                            $(idGia).html("<s>" + giacu + "</s><br /><span style='color:red;'>" + NumCommas(giamoi) + " đ</span>");
                            let vg1gia1 = 0; let ischange = false;
                            let vfgia1 = parseFloat($(idGia.replace('token', 'gfirst').replace('ggia', 'gfirst')).text().replace(" VND", "").replace(" đ", "").replaceAll(/\./gi, ""));
                            let vtong1 = parseFloat($(idGia.replace('token', 'gtong').replace('ggia', 'gtong')).text().replace(" VND", "").replace(" đ", "").replaceAll(/\./gi, ""));
                            if (idGia.indexOf("data-token") > -1 && ($(idGia.replace('token', 'ggia')).children("span").text() != "" || $(idGia + " s").html() != undefined)) {
                                vg1gia1 = parseFloat($(idGia.replace('token', 'ggia')).children("span").text().replace(" VND", "").replaceAll(" đ", "").replace(/\./gi, ""));
                                if (isNaN(vg1gia1)) {
                                    vg1gia1 = parseFloat($(idGia.replace('token', 'ggia')).text().replace(" VND", "").replaceAll(" đ", "").replace(/\./gi, ""));
                                }
                                ischange = true;
                            }
                            if (idGia.indexOf("data-ggia") > -1 && ($(idGia.replace('ggia', 'token')).children("span").text() != "" || $(idGia + " s").html() != undefined)) {
                                vg1gia1 = parseFloat($(idGia.replace('ggia', 'token')).children("span").text().replace(" VND", "").replaceAll(" đ", "").replace(/\./gi, ""));
                                if (isNaN(vg1gia1)) {
                                    vg1gia1 = parseFloat($(idGia.replace('ggia', 'token')).text().replace(" VND", "").replaceAll(" đ", "").replace(/\./gi, ""));
                                }
                                ischange = true;
                            }
                            if (ischange) {
                                $(idGia.replace('token', 'gtong').replace('ggia', 'gtong')).html("<s>" + NumCommas(vtong1) + " đ</s><br /><span style='color:red;'>" + NumCommas(vfgia1 + vg1gia1 + giamoi) + " đ</span>");
                            }
                        }
                        else {
                            $(idGia).html(_data[1] + (idGia.indexOf("data-ggia") > -1 || idGia.indexOf("data-token") > -1 ? " đ" : ""));
                        }
                    }
                    var Goi_First = $("#giagoi_First");
                    if (Goi_First != undefined) {
                        var giagoi_First = $("#giagoi_First,.giagoi_First:visible").text();
                        var unitgoi_First = $("#unitgoi_First,.unitgoi_First:visible").text();
                        var datalang = $("#gia_unit_goi_Get").attr("data-lang");
                        $("#gia_unit_goi_Get").html((datalang == "E" ? "Start with only " : "Chỉ từ ") + giagoi_First + " " + unitgoi_First);
                    }
                }
                else {
                    $(idGia).val(_data[1]);
                }
                if (idFlashSale != "" && _data[2] != "" && oldHref.indexOf("flashsale") <= -1) {
                    if (idFlashSale.indexOf(",") > -1) {
                        var ihref = idFlashSale.split(',');
                        $.each(ihref, function (index, value) {
                            var oHref = $(idFlashSale.split(',')[0]).attr("href");
                            $(value).attr("href", oHref + "&flashsale=" + _data[2]);
                            if (idFlashSale.indexOf("a_") > -1 && idFlashSale.indexOf("_IDERM") > -1) {
                                var isHDD = $("#hdfPhiURL" + vMaDichVu.replace("HDD", "").replace("SSD", "") + "HDD");
                                var isSSD = $("#hdfPhiURL" + vMaDichVu.replace("HDD", "").replace("SSD", "") + "SSD");
                                isHDD.attr("value", (isHDD.attr("value") != undefined ? isHDD.attr("value").replace(/&flashsale/g, '|').split('|')[0] + "&flashsale=" + _data[2] : ""));
                                isSSD.attr("value", (isSSD.attr("value") != undefined ? isSSD.attr("value").replace(/&flashsale/g, '|').split('|')[0] + "&flashsale=" + _data[2] : ""));
                            }
                        });
                    }
                    else {
                        $(idFlashSale).attr("href", oldHref + "&flashsale=" + _data[2]);
                    }
                    if (idGia.indexOf("od") > -1) {
                        $(idGia).parent().children(".giagocFlash").show();
                    }
                    else {
                        $(idGia).parent().children(".giagocFlash").show();
                    }
                }
                else {
                    if ($(idGia).length == 1) {
                        $(idGia).parent().children(".giagocFlash").hide();
                    }
                    let giagiam = _data[1].replaceAll(' ', '').replaceAll('đ', '');
                    let giagoc = $(idGia).parent().children(".giagocFlash").text().replaceAll(' ', '').replaceAll('đ', '');
                    if ($(".hafContent h1").text() != undefined && $(".hafContent h1").text().toLowerCase() == 'cloud server' && giagiam != giagoc) {
                        $(idGia).parent().children(".giagocFlash").show();
                    }
                }
            }
        },
        error: function (t) {
            if (idGia.indexOf("#isDMcom") > -1 || idGia.indexOf("#isDMnet") > -1 || idGia.indexOf("#isKMHot") > -1) {
                $(idGia).html($(idGia).attr("data-giagoc"));
            }
            else {
                $(idGia).html(oldValue);
            }
            $(idFlashSale).attr("href", oldHref);
            console.log(t);
        }
    });
}

function NumCommas(nStr) {
    nStr += '';
    x = nStr.split('.');
    x1 = x[0];
    var rgx = /(\d+)(\d{3})/;
    while (rgx.test(x1)) {
        x1 = x1.replace(rgx, '$1' + '.' + '$2');
    }
    return x1;
}
//function initMap() { console.log('ok'); };
