/**
 * jQuery Validation Plugin 1.9.0
 * 
 * http://bassistance.de/jquery-plugins/jquery-plugin-validation/
 * http://docs.jquery.com/Plugins/Validation
 * 
 * Copyright (c) 2006 - 2011 JГ¶rn Zaefferer
 * 
 * Dual licensed under the MIT and GPL licenses:
 * http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 */

(function($) {

$.extend($.fn, {
    // http://docs.jquery.com/Plugins/Validation/validate
    validate: function( options ) {

        // if nothing is selected, return nothing; can't chain anyway
        if (!this.length) {
            options && options.debug && window.console && console.warn( "nothing selected, can't validate, returning nothing" );
            return;
        }

        // check if a validator for this form was already created
        var validator = $.data(this[0], 'validator');
        if ( validator ) {
            return validator;
        }

        // Add novalidate tag if HTML5.
        this.attr('novalidate', 'novalidate');

        validator = new $.validator( options, this[0] );
        $.data(this[0], 'validator', validator);

        if ( validator.settings.onsubmit ) {

            var inputsAndButtons = this.find("input, button");

            // allow suppresing validation by adding a cancel class to the
            // submit button
            inputsAndButtons.filter(".cancel").click(function () {
                validator.cancelSubmit = true;
            });

            // when a submitHandler is used, capture the submitting button
            if (validator.settings.submitHandler) {
                inputsAndButtons.filter(":submit").click(function () {
                    validator.submitButton = this;
                });
            }

            // validate the form on submit
            this.submit( function( event ) {
                if ( validator.settings.debug )
                    // prevent form submit to be able to see console output
                    event.preventDefault();

                function handle() {
                    if ( validator.settings.submitHandler ) {
                        if (validator.submitButton) {
                            // insert a hidden input as a replacement for the
                            // missing submit button
                            var hidden = $("<input type='hidden'/>").attr("name", validator.submitButton.name).val(validator.submitButton.value).appendTo(validator.currentForm);
                        }
                        validator.settings.submitHandler.call( validator, validator.currentForm );
                        if (validator.submitButton) {
                            // and clean up afterwards; thanks to
                            // no-block-scope, hidden can be referenced
                            hidden.remove();
                        }
                        return false;
                    }
                    return true;
                }

                // prevent submit for invalid forms or custom submit handlers
                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;
    },
    // http://docs.jquery.com/Plugins/Validation/valid
    valid: function() {
        if ( $(this[0]).is('form')) {
            return this.validate().form();
        } else {
            var valid = true;
            var validator = $(this[0].form).validate();
            this.each(function() {
                valid &= validator.element(this);
            });
            return valid;
        }
    },
    // attributes: space seperated list of attributes to retrieve and remove
    removeAttrs: function(attributes) {
        var result = {},
            $element = this;
        $.each(attributes.split(/\s/), function(index, value) {
            result[value] = $element.attr(value);
            $element.removeAttr(value);
        });
        return result;
    },
    // http://docs.jquery.com/Plugins/Validation/rules
    rules: function(command, argument) {
        var element = this[0];

        if (command) {
            var settings = $.data(element.form, 'validator').settings;
            var staticRules = settings.rules;
            var existingRules = $.validator.staticRules(element);
            switch(command) {
            case "add":
                $.extend(existingRules, $.validator.normalizeRule(argument));
                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;
                }
                var filtered = {};
                $.each(argument.split(/\s/), function(index, method) {
                    filtered[method] = existingRules[method];
                    delete existingRules[method];
                });
                return filtered;
            }
        }

        var data = $.validator.normalizeRules(
        $.extend(
            {},
            $.validator.metadataRules(element),
            $.validator.classRules(element),
            $.validator.attributeRules(element),
            $.validator.staticRules(element)
        ), element);

        // make sure required is at front
        if (data.required) {
            var param = data.required;
            delete data.required;
            data = $.extend({required: param}, data);
        }

        return data;
    }
});

// Custom selectors
$.extend($.expr[":"], {
    // http://docs.jquery.com/Plugins/Validation/blank
    blank: function(a) {return !$.trim("" + a.value);},
    // http://docs.jquery.com/Plugins/Validation/filled
    filled: function(a) {return !!$.trim("" + a.value);},
    // http://docs.jquery.com/Plugins/Validation/unchecked
    unchecked: function(a) {return !a.checked;}
});

// constructor for validator
$.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"), n);
    });
    return source;
};

$.extend($.validator, {

    defaults: {
        messages: {},
        groups: {},
        rules: {},
        errorClass: "error",
        validClass: "valid",
        errorElement: "label",
        focusInvalid: true,
        errorContainer: $( [] ),
        errorLabelContainer: $( [] ),
        onsubmit: true,
        ignore: ":hidden",
        ignoreTitle: false,
        onfocusin: function(element, event) {
            this.lastActive = element;

            // hide error label and remove error class on focus if enabled
            if ( this.settings.focusCleanup && !this.blockFocusCleanup ) {
                this.settings.unhighlight && this.settings.unhighlight.call( this, element, this.settings.errorClass, this.settings.validClass );
                this.addWrapper(this.errorsFor(element)).hide();
            }
        },
        onfocusout: function(element, event) {
            if ( !this.checkable(element) && (element.name in this.submitted || !this.optional(element)) ) {
                this.element(element);
            }
        },
        onkeyup: function(element, event) {
            if ( element.name in this.submitted || element == this.lastElement ) {
                this.element(element);
            }
        },
        onclick: function(element, event) {
            // click on selects, radiobuttons and checkboxes
            if ( element.name in this.submitted )
                this.element(element);
            // or option elements, check parent select in that case
            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);
            }
        }
    },

    // http://docs.jquery.com/Plugins/Validation/Validator/setDefaults
    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.",
        accept: "Please enter a value with a valid extension.",
        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 = {});
            $.each(this.settings.groups, function(key, value) {
                $.each(value.split(/\s/), function(index, name) {
                    groups[name] = key;
                });
            });
            var 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/, "");
                validator.settings[eventType] && validator.settings[eventType].call(validator, this[0], event);
            }
            $(this.currentForm)
                   .validateDelegate("[type='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'] ",
                        "focusin focusout keyup", delegate)
                .validateDelegate("[type='radio'], [type='checkbox'], select, option", "click", delegate);

            if (this.settings.invalidHandler)
                $(this.currentForm).bind("invalid-form.validate", this.settings.invalidHandler);
        },

        // http://docs.jquery.com/Plugins/Validation/Validator/form
        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();
        },

        // http://docs.jquery.com/Plugins/Validation/Validator/element
        element: function( element ) {
            element = this.validationTargetFor( this.clean( element ) );
            this.lastElement = element;
            this.prepareElement( element );
            this.currentElements = $(element);
            var result = this.check( element );
            if ( result ) {
                delete this.invalid[element.name];
            } else {
                this.invalid[element.name] = true;
            }
            if ( !this.numberOfInvalids() ) {
                // Hide error containers on last error
                this.toHide = this.toHide.add( this.containers );
            }
            this.showErrors();
            return result;
        },

        // http://docs.jquery.com/Plugins/Validation/Validator/showErrors
        showErrors: function(errors) {
            if(errors) {
                // add items to error list and map
                $.extend( this.errorMap, errors );
                this.errorList = [];
                for ( var name in errors ) {
                    this.errorList.push({
                        message: errors[name],
                        element: this.findByName(name)[0]
                    });
                }
                // remove items from success list
                this.successList = $.grep( this.successList, function(element) {
                    return !(element.name in errors);
                });
            }
            this.settings.showErrors
                ? this.settings.showErrors.call( this, this.errorMap, this.errorList )
                : this.defaultShowErrors();
        },

        // http://docs.jquery.com/Plugins/Validation/Validator/resetForm
        resetForm: function() {
            if ( $.fn.resetForm )
                $( this.currentForm ).resetForm();
            this.submitted = {};
            this.lastElement = null;
            this.prepareForm();
            this.hideErrors();
            this.elements().removeClass( this.settings.errorClass );
        },

        numberOfInvalids: function() {
            return this.objectLength(this.invalid);
        },

        objectLength: function( obj ) {
            var count = 0;
            for ( var i in obj )
                count++;
            return count;
        },

        hideErrors: function() {
            this.addWrapper( this.toHide ).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()
                    // manually trigger focusin event; without it, focusin
                    // handler isn't called, findLastActive won't have anything
                    // to find
                    .trigger("focusin");
                } catch(e) {
                    // ignore IE throwing errors when focusing hidden elements
                }
            }
        },

        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 = {};

            // select all valid inputs inside the form (no submit or reset
            // buttons)
            return $(this.currentForm)
            .find("input, select, textarea")
            .not(":submit, :reset, :image, [disabled]")
            .not( this.settings.ignore )
            .filter(function() {
                !this.name && validator.settings.debug && window.console && console.error( "%o has no name assigned", this);

                // select only the first element for each name, and only those
                // with rules specified
                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() {
            return $( this.settings.errorElement + "." + this.settings.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);
        },

        check: function( element ) {
            element = this.validationTargetFor( this.clean( element ) );

            var rules = $(element).rules();
            var dependencyMismatch = false;
            for (var method in rules ) {
                var rule = { method: method, parameters: rules[method] };
                try {
                    var result = $.validator.methods[method].call( this, element.value.replace(/\r/g, ""), element, rule.parameters );

                    // if a method indicates that the field is optional and
                    // therefore valid,
                    // don't mark it as valid when there are no other rules
                    if ( result == "dependency-mismatch" ) {
                        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) {
                    this.settings.debug && window.console && console.log("exception occured 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;
        },

        // return the custom message for the given element and validation method
        // specified in the element's "messages" metadata
        customMetaMessage: function(element, method) {
            if (!$.metadata)
                return;

            var meta = this.settings.meta
                ? $(element).metadata()[this.settings.meta]
                : $(element).metadata();

            return meta && meta.messages && meta.messages[method];
        },

        // return the custom message for the given element name and validation
        // method
        customMessage: function( name, method ) {
            var m = this.settings.messages[name];
            return m && (m.constructor == String
                ? m
                : m[method]);
        },

        // return the first defined argument, allowing empty strings
        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.customMetaMessage( element, method ),
                // title is never undefined, so handle empty string as undefined
                !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 = jQuery.format(message.replace(theregex, '{$1}'), rule.parameters);
            }
            this.errorList.push({
                message: message,
                element: element
            });

            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() {
            for ( var i = 0; this.errorList[i]; i++ ) {
                var error = this.errorList[i];
                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 ( var i = 0; this.successList[i]; i++ ) {
                    this.showLabel( this.successList[i] );
                }
            }
            if (this.settings.unhighlight) {
                for ( var 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 label = this.errorsFor( element );
            if ( label.length ) {
                // refresh error/success class
                label.removeClass( this.settings.validClass ).addClass( this.settings.errorClass );

                // check if we have a generated label, replace the message then
                label.attr("generated") && label.html(message);
            } else {
                // create label
                label = $("<" + this.settings.errorElement + "/>")
                    .attr({"for":  this.idOrName(element), generated: true})
                    .addClass(this.settings.errorClass)
                    .html(message || "");
                if ( this.settings.wrapper ) {
                    // make sure the element is visible, even in IE
                    // actually showing the wrapped element is handled elsewhere
                    label = label.hide().show().wrap("<" + this.settings.wrapper + "/>").parent();
                }
                if ( !this.labelContainer.append(label).length )
                    this.settings.errorPlacement
                        ? this.settings.errorPlacement(label, $(element) )
                        : label.insertAfter(element);
            }
            if ( !message && this.settings.success ) {
                label.text("");
                typeof this.settings.success == "string"
                    ? label.addClass( this.settings.success )
                    : this.settings.success( label );
            }
            this.toShow = this.toShow.add(label);
        },

        errorsFor: function(element) {
            var name = this.idOrName(element);
            return this.errors().filter(function() {
                return $(this).attr('for') == name;
            });
        },

        idOrName: function(element) {
            return this.groups[element.name] || (this.checkable(element) ? element.name : element.id || element.name);
        },

        validationTargetFor: function(element) {
            // if radio/checkbox, validate first element in group instead
            if (this.checkable(element)) {
                element = this.findByName( element.name ).not(this.settings.ignore)[0];
            }
            return element;
        },

        checkable: function( element ) {
            return /radio|checkbox/i.test(element.type);
        },

        findByName: function( name ) {
            // select by name and filter by form for performance over
            // form.find("[name=...]")
            var form = this.currentForm;
            return $(document.getElementsByName(name)).map(function(index, element) {
                return element.form == form && element.name == name && element  || null;
            });
        },

        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, element) {
                return param;
            },
            "string": function(param, element) {
                return !!$(param, element.form).length;
            },
            "function": function(param, element) {
                return param(element);
            }
        },

        optional: function(element) {
            return !$.validator.methods.required.call(this, $.trim(element.value), element) && "dependency-mismatch";
        },

        startRequest: function(element) {
            if (!this.pending[element.name]) {
                this.pendingRequest++;
                this.pending[element.name] = true;
            }
        },

        stopRequest: function(element, valid) {
            this.pendingRequest--;
            // sometimes synchronization fails, make sure pendingRequest is
            // never < 0
            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},
        dateDE: {dateDE: true},
        number: {number: true},
        numberDE: {numberDE: true},
        digits: {digits: true},
        creditcard: {creditcard: true}
    },

    addClassRules: function(className, rules) {
        className.constructor == String ?
            this.classRuleSettings[className] = rules :
            $.extend(this.classRuleSettings, className);
    },

    classRules: function(element) {
        var rules = {};
        var classes = $(element).attr('class');
        classes && $.each(classes.split(' '), function() {
            if (this in $.validator.classRuleSettings) {
                $.extend(rules, $.validator.classRuleSettings[this]);
            }
        });
        return rules;
    },

    attributeRules: function(element) {
        var rules = {};
        var $element = $(element);

        for (var method in $.validator.methods) {
            var value;
            // If .prop exists (jQuery >= 1.6), use it to get true/false for
            // required
            if (method === 'required' && typeof $.fn.prop === 'function') {
                value = $element.prop(method);
            } else {
                value = $element.attr(method);
            }
            if (value) {
                rules[method] = value;
            } else if ($element[0].getAttribute("type") === method) {
                rules[method] = true;
            }
        }

        // maxlength may be returned as -1, 2147483647 (IE) and 524288 (safari)
        // for text inputs
        if (rules.maxlength && /-1|2147483647|524288/.test(rules.maxlength)) {
            delete rules.maxlength;
        }

        return rules;
    },

    metadataRules: function(element) {
        if (!$.metadata) return {};

        var meta = $.data(element.form, 'validator').settings.meta;
        return meta ?
            $(element).metadata()[meta] :
            $(element).metadata();
    },

    staticRules: function(element) {
        var rules = {};
        var validator = $.data(element.form, 'validator');
        if (validator.settings.rules) {
            rules = $.validator.normalizeRule(validator.settings.rules[element.name]) || {};
        }
        return rules;
    },

    normalizeRules: function(rules, element) {
        // handle dependency check
        $.each(rules, function(prop, val) {
            // ignore rule when param is explicitly false, eg. required:false
            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];
                }
            }
        });

        // evaluate parameters
        $.each(rules, function(rule, parameter) {
            rules[rule] = $.isFunction(parameter) ? parameter(element) : parameter;
        });

        // clean number parameters
        $.each(['minlength', 'maxlength', 'min', 'max'], function() {
            if (rules[this]) {
                rules[this] = Number(rules[this]);
            }
        });
        $.each(['rangelength', 'range'], function() {
            if (rules[this]) {
                rules[this] = [Number(rules[this][0]), Number(rules[this][1])];
            }
        });

        if ($.validator.autoCreateRanges) {
            // auto-create ranges
            if (rules.min && rules.max) {
                rules.range = [rules.min, rules.max];
                delete rules.min;
                delete rules.max;
            }
            if (rules.minlength && rules.maxlength) {
                rules.rangelength = [rules.minlength, rules.maxlength];
                delete rules.minlength;
                delete rules.maxlength;
            }
        }

        // To support custom messages in metadata ignore rule methods titled
        // "messages"
        if (rules.messages) {
            delete rules.messages;
        }

        return rules;
    },

    // Converts a simple string to a {string: true} rule, e.g., "required" to
    // {required:true}
    normalizeRule: function(data) {
        if( typeof data == "string" ) {
            var transformed = {};
            $.each(data.split(/\s/), function() {
                transformed[this] = true;
            });
            data = transformed;
        }
        return data;
    },

    // http://docs.jquery.com/Plugins/Validation/Validator/addMethod
    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: {

        // http://docs.jquery.com/Plugins/Validation/Methods/required
        required: function(value, element, param) {
            // check if dependency is met
            if ( !this.depend(param, element) )
                return "dependency-mismatch";
            switch( element.nodeName.toLowerCase() ) {
            case 'select':
                // could be an array for select-multiple or a string, both are
                // fine this way
                var val = $(element).val();
                return val && val.length > 0;
            case 'input':
                if ( this.checkable(element) )
                    return this.getLength(value, element) > 0;
            default:
                return $.trim(value).length > 0;
            }
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/remote
        remote: function(value, element, param) {
            if ( this.optional(element) )
                return "dependency-mismatch";

            var previous = this.previousValue(element);
            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 ( this.pending[element.name] ) {
                return "pending";
            }
            if ( previous.old === value ) {
                return previous.valid;
            }

            previous.old = value;
            var validator = this;
            this.startRequest(element);
            var data = {};
            data[element.name] = value;
            $.ajax($.extend(true, {
                url: param,
                mode: "abort",
                port: "validate" + element.name,
                dataType: "json",
                data: data,
                success: function(response) {
                    validator.settings.messages[element.name].remote = previous.originalMessage;
                    var valid = response === true;
                    if ( valid ) {
                        var submitted = validator.formSubmitted;
                        validator.prepareElement(element);
                        validator.formSubmitted = submitted;
                        validator.successList.push(element);
                        validator.showErrors();
                    } else {
                        var errors = {};
                        var message = response || validator.defaultMessage( element, "remote" );
                        errors[element.name] = previous.message = $.isFunction(message) ? message(value) : message;
                        validator.showErrors(errors);
                    }
                    previous.valid = valid;
                    validator.stopRequest(element, valid);
                }
            }, param));
            return "pending";
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/minlength
        minlength: function(value, element, param) {
            return this.optional(element) || this.getLength($.trim(value), element) >= param;
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/maxlength
        maxlength: function(value, element, param) {
            return this.optional(element) || this.getLength($.trim(value), element) <= param;
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/rangelength
        rangelength: function(value, element, param) {
            var length = this.getLength($.trim(value), element);
            return this.optional(element) || ( length >= param[0] && length <= param[1] );
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/min
        min: function( value, element, param ) {
            return this.optional(element) || value >= param;
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/max
        max: function( value, element, param ) {
            return this.optional(element) || value <= param;
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/range
        range: function( value, element, param ) {
            return this.optional(element) || ( value >= param[0] && value <= param[1] );
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/email
        email: function(value, element) {
            // contributed by Scott Gonzalez:
            // http://projects.scottsplayground.com/email_address_validation/
            return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([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])))$/i.test(value);
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/url
        url: function(value, element) {
            // contributed by Scott Gonzalez:
            // http://projects.scottsplayground.com/iri/
            return this.optional(element) || /^(https?|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);
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/date
        date: function(value, element) {
            return this.optional(element) || !/Invalid|NaN/.test(new Date(value));
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/dateISO
        dateISO: function(value, element) {
            return this.optional(element) || /^\d{4}[\/-]\d{1,2}[\/-]\d{1,2}$/.test(value);
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/number
        number: function(value, element) {
            return this.optional(element) || /^-?(?:\d+|\d{1,3}(?:,\d{3})+)(?:\.\d+)?$/.test(value);
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/digits
        digits: function(value, element) {
            return this.optional(element) || /^\d+$/.test(value);
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/creditcard
        // based on http://en.wikipedia.org/wiki/Luhn
        creditcard: function(value, element) {
            if ( this.optional(element) )
                return "dependency-mismatch";
            // accept only spaces, digits and dashes
            if (/[^0-9 -]+/.test(value))
                return false;
            var nCheck = 0,
                nDigit = 0,
                bEven = false;

            value = value.replace(/\D/g, "");

            for (var n = value.length - 1; n >= 0; n--) {
                var cDigit = value.charAt(n);
                var nDigit = parseInt(cDigit, 10);
                if (bEven) {
                    if ((nDigit *= 2) > 9)
                        nDigit -= 9;
                }
                nCheck += nDigit;
                bEven = !bEven;
            }

            return (nCheck % 10) == 0;
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/accept
        accept: function(value, element, param) {
            param = typeof param == "string" ? param.replace(/,/g, '|') : "png|jpe?g|gif";
            return this.optional(element) || value.match(new RegExp(".(" + param + ")$", "i"));
        },

        // http://docs.jquery.com/Plugins/Validation/Methods/equalTo
        equalTo: function(value, element, param) {
            // bind to the blur event of the target in order to revalidate
            // whenever the target field is updated
            // TODO find a way to bind the event just once, avoiding the
            // unbind-rebind overhead
            var target = $(param).unbind(".validate-equalTo").bind("blur.validate-equalTo", function() {
                $(element).valid();
            });
            return value == target.val();
        }

    }

});

// deprecated, use $.validator.format instead
$.format = $.validator.format;

})(jQuery);

// ajax mode: abort
// usage: $.ajax({ mode: "abort"[, port: "uniqueport"]});
// if mode:"abort" is used, the previous request on that port (port can be
// undefined) is aborted via XMLHttpRequest.abort()
;(function($) {
    var pendingRequests = {};
    // Use a prefilter if available (1.5+)
    if ( $.ajaxPrefilter ) {
        $.ajaxPrefilter(function(settings, _, xhr) {
            var port = settings.port;
            if (settings.mode == "abort") {
                if ( pendingRequests[port] ) {
                    pendingRequests[port].abort();
                }
                pendingRequests[port] = xhr;
            }
        });
    } else {
        // Proxy ajax
        var 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();
                }
                return (pendingRequests[port] = ajax.apply(this, arguments));
            }
            return ajax.apply(this, arguments);
        };
    }
})(jQuery);

// provides cross-browser focusin and focusout events
// IE has native support, in other browsers, use event caputuring (neither
// bubbles)

// provides delegate(type: String, delegate: Selector, handler: Callback) plugin
// for easier event delegation
// handler is only called when $(event.target).is(delegate), in the scope of the
// jquery-object for event.target
;(function($) {
    // only implement if not provided by jQuery core (since 1.4)
    // TODO verify if jQuery 1.4's implementation is compatible with older
    // jQuery special-event APIs
    if (!jQuery.event.special.focusin && !jQuery.event.special.focusout && document.addEventListener) {
        $.each({
            focus: 'focusin',
            blur: 'focusout'
        }, function( original, fix ){
            $.event.special[fix] = {
                setup:function() {
                    this.addEventListener( original, handler, true );
                },
                teardown:function() {
                    this.removeEventListener( original, handler, true );
                },
                handler: function(e) {
                    arguments[0] = $.event.fix(e);
                    arguments[0].type = fix;
                    return $.event.handle.apply(this, arguments);
                }
            };
            function handler(e) {
                e = $.event.fix(e);
                e.type = fix;
                return $.event.handle.call(this, e);
            }
        });
    };
    $.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);
                }
            });
        }
    });
})(jQuery);


/*
 * Watermark plugin for jQuery Version: 3.1.3
 * http://jquery-watermark.googlecode.com/
 * 
 * Copyright (c) 2009-2011 Todd Northrop http://www.speednet.biz/
 * 
 * March 22, 2011
 * 
 * Requires: jQuery 1.2.3+
 * 
 * Dual licensed under the MIT or GPL Version 2 licenses. See mit-license.txt
 * and gpl2-license.txt in the project root for details.
 * ------------------------------------------------------
 */

(function ($, window, undefined) {

var
    // String constants for data names
    dataFlag = "watermark",
    dataClass = "watermarkClass",
    dataFocus = "watermarkFocus",
    dataFormSubmit = "watermarkSubmit",
    dataMaxLen = "watermarkMaxLength",
    dataPassword = "watermarkPassword",
    dataText = "watermarkText",
    
    // Copy of native jQuery regex use to strip return characters from element
    // value
    rreturn = /\r/g,

    // Includes only elements with watermark defined
    selWatermarkDefined = "input:data(" + dataFlag + "),textarea:data(" + dataFlag + ")",

    // Includes only elements capable of having watermark
    selWatermarkAble = "input:text,input:password,input[type=search],input:not([type]),textarea",
    
    // triggerFns:
    // Array of function names to look for in the global namespace.
    // Any such functions found will be hijacked to trigger a call to
    // hideAll() any time they are called. The default value is the
    // ASP.NET function that validates the controls on the page
    // prior to a postback.
    // 
    // Am I missing other important trigger function(s) to look for?
    // Please leave me feedback:
    // http://code.google.com/p/jquery-watermark/issues/list
    triggerFns = [
        "Page_ClientValidate"
    ],
    
    // Holds a value of true if a watermark was displayed since the last
    // hideAll() was executed. Avoids repeatedly calling hideAll().
    pageDirty = false,
    
    // Detects if the browser can handle native placeholders
    hasNativePlaceholder = ("placeholder" in document.createElement("input"));

// Best practice: this plugin adds only one method to the jQuery object.
// Also ensures that the watermark code is only added once.
$.watermark = $.watermark || {

    // Current version number of the plugin
    version: "3.1.3",
        
    runOnce: true,
    
    // Default options used when watermarks are instantiated.
    // Can be changed to affect the default behavior for all
    // new or updated watermarks.
    options: {
        
        // Default class name for all watermarks
        className: "watermark",
        
        // If true, plugin will detect and use native browser support for
        // watermarks, if available. (e.g., WebKit's placeholder attribute.)
        useNative: true,
        
        // If true, all watermarks will be hidden during the window's
        // beforeunload event. This is done mainly because WebKit
        // browsers remember the watermark text during navigation
        // and try to restore the watermark text after the user clicks
        // the Back button. We can avoid this by hiding the text before
        // the browser has a chance to save it. The regular unload event
        // was tried, but it seems the browser saves the text before
        // that event kicks off, because it didn't work.
        hideBeforeUnload: true
    },
    
    // Hide one or more watermarks by specifying any selector type
    // i.e., DOM element, string selector, jQuery matched set, etc.
    hide: function (selector) {
        $(selector).filter(selWatermarkDefined).each(
            function () {
                $.watermark._hide($(this));
            }
        );
    },
    
    // Internal use only.
    _hide: function ($input, focus) {
        var elem = $input[0],
            inputVal = (elem.value || "").replace(rreturn, ""),
            inputWm = $input.data(dataText) || "",
            maxLen = $input.data(dataMaxLen) || 0,
            className = $input.data(dataClass);
    
        if ((inputWm.length) && (inputVal == inputWm)) {
            elem.value = "";
            
            // Password type?
            if ($input.data(dataPassword)) {
                
                if (($input.attr("type") || "") === "text") {
                    var $pwd = $input.data(dataPassword) || [], 
                        $wrap = $input.parent() || [];
                        
                    if (($pwd.length) && ($wrap.length)) {
                        $wrap[0].removeChild($input[0]); // Can't use jQuery
                                                            // methods, because
                                                            // they destroy data
                        $wrap[0].appendChild($pwd[0]);
                        $input = $pwd;
                    }
                }
            }
            
            if (maxLen) {
                $input.attr("maxLength", maxLen);
                $input.removeData(dataMaxLen);
            }
        
            if (focus) {
                $input.attr("autocomplete", "off");  // Avoid
                                                        // NS_ERROR_XPC_JS_THREW_STRING
                                                        // error in Firefox
                
                window.setTimeout(
                    function () {
                        $input.select();  // Fix missing cursor in IE
                    }
                , 1);
            }
        }
        
        className && $input.removeClass(className);
    },
    
    // Display one or more watermarks by specifying any selector type
    // i.e., DOM element, string selector, jQuery matched set, etc.
    // If conditions are not right for displaying a watermark, ensures that
    // watermark is not shown.
    show: function (selector) {
        $(selector).filter(selWatermarkDefined).each(
            function () {
                $.watermark._show($(this));
            }
        );
    },
    
    // Internal use only.
    _show: function ($input) {
        var elem = $input[0],
            val = (elem.value || "").replace(rreturn, ""),
            text = $input.data(dataText) || "",
            type = $input.attr("type") || "",
            className = $input.data(dataClass);

        if (((val.length == 0) || (val == text)) && (!$input.data(dataFocus))) {
            pageDirty = true;
        
            // Password type?
            if ($input.data(dataPassword)) {
                
                if (type === "password") {
                    var $pwd = $input.data(dataPassword) || [],
                        $wrap = $input.parent() || [];
                        
                    if (($pwd.length) && ($wrap.length)) {
                        $wrap[0].removeChild($input[0]); // Can't use jQuery
                                                            // methods, because
                                                            // they destroy data
                        $wrap[0].appendChild($pwd[0]);
                        $input = $pwd;
                        $input.attr("maxLength", text.length);
                        elem = $input[0];
                    }
                }
            }
        
            // Ensure maxLength big enough to hold watermark (input of
            // type="text" or type="search" only)
            if ((type === "text") || (type === "search")) {
                var maxLen = $input.attr("maxLength") || 0;
                
                if ((maxLen > 0) && (text.length > maxLen)) {
                    $input.data(dataMaxLen, maxLen);
                    $input.attr("maxLength", text.length);
                }
            }
            
            className && $input.addClass(className);
            elem.value = text;
        }
        else {
            $.watermark._hide($input);
        }
    },
    
    // Hides all watermarks on the current page.
    hideAll: function () {
        if (pageDirty) {
            $.watermark.hide(selWatermarkAble);
            pageDirty = false;
        }
    },
    
    // Displays all watermarks on the current page.
    showAll: function () {
        $.watermark.show(selWatermarkAble);
    }
};

$.fn.watermark = $.fn.watermark || function (text, options) {
    // / <summary>
    // / Set watermark text and class name on all input elements of
    // type="text/password/search" and
    // / textareas within the matched set. If className is not specified in
    // options, the default is
    // / "watermark". Within the matched set, only input elements with
    // type="text/password/search"
    // / and textareas are affected; all other elements are ignored.
    // / </summary>
    // / <returns type="jQuery">
    // / Returns the original jQuery matched set (not just the input and texarea
    // elements).
    // / </returns>
    // / <param name="text" type="String">
    // / Text to display as a watermark when the input or textarea element has
    // an empty value and does not
    // / have focus. The first time watermark() is called on an element, if this
    // argument is empty (or not
    // / a String type), then the watermark will have the net effect of only
    // changing the class name when
    // / the input or textarea element's value is empty and it does not have
    // focus.
    // / </param>
    // / <param name="options" type="Object" optional="true">
    // / Provides the ability to override the default watermark options
    // ($.watermark.options). For backward
    // / compatibility, if a string value is supplied, it is used as the class
    // name that overrides the class
    // / name in $.watermark.options.className. Properties include:
    // / className: When the watermark is visible, the element will be styled
    // using this class name.
    // / useNative (Boolean or Function): Specifies if native browser support
    // for watermarks will supersede
    // / plugin functionality. If useNative is a function, the return value from
    // the function will
    // / determine if native support is used. The function is passed one
    // argument -- a jQuery object
    // / containing the element being tested as the only element in its matched
    // set -- and the DOM
    // / element being tested is the object on which the function is invoked
    // (the value of "this").
    // / </param>
    // / <remarks>
    // / The effect of changing the text and class name on an input element is
    // called a watermark because
    // / typically light gray text is used to provide a hint as to what type of
    // input is required. However,
    // / the appearance of the watermark can be something completely different:
    // simply change the CSS style
    // / pertaining to the supplied class name.
    // /
    // / The first time watermark() is called on an element, the watermark text
    // and class name are initialized,
    // / and the focus and blur events are hooked in order to control the
    // display of the watermark. Also, as
    // / of version 3.0, drag and drop events are hooked to guard against
    // dropped text being appended to the
    // / watermark. If native watermark support is provided by the browser, it
    // is detected and used, unless
    // / the useNative option is set to false.
    // /
    // / Subsequently, watermark() can be called again on an element in order to
    // change the watermark text
    // / and/or class name, and it can also be called without any arguments in
    // order to refresh the display.
    // /
    // / For example, after changing the value of the input or textarea element
    // programmatically, watermark()
    // / should be called without any arguments to refresh the display, because
    // the change event is only
    // / triggered by user actions, not by programmatic changes to an input or
    // textarea element's value.
    // /
    // / The one exception to programmatic updates is for password input
    // elements: you are strongly cautioned
    // / against changing the value of a password input element programmatically
    // (after the page loads).
    // / The reason is that some fairly hairy code is required behind the scenes
    // to make the watermarks bypass
    // / IE security and switch back and forth between clear text (for
    // watermarks) and obscured text (for
    // / passwords). It is *possible* to make programmatic changes, but it must
    // be done in a certain way, and
    // / overall it is not recommended.
    // / </remarks>
    
    if (!this.length) {
        return this;
    }
    
    var hasClass = false,
        hasText = (typeof(text) === "string");
    
    if (hasText) {
        text = text.replace(rreturn, "");
    }
    
    if (typeof(options) === "object") {
        hasClass = (typeof(options.className) === "string");
        options = $.extend({}, $.watermark.options, options);
    }
    else if (typeof(options) === "string") {
        hasClass = true;
        options = $.extend({}, $.watermark.options, {className: options});
    }
    else {
        options = $.watermark.options;
    }
    
    if (typeof(options.useNative) !== "function") {
        options.useNative = options.useNative? function () { return true; } : function () { return false; };
    }
    
    return this.each(
        function () {
            var $input = $(this);
            
            if (!$input.is(selWatermarkAble)) {
                return;
            }
            
            // Watermark already initialized?
            if ($input.data(dataFlag)) {
            
                // If re-defining text or class, first remove existing
                // watermark, then make changes
                if (hasText || hasClass) {
                    $.watermark._hide($input);
            
                    if (hasText) {
                        $input.data(dataText, text);
                    }
                    
                    if (hasClass) {
                        $input.data(dataClass, options.className);
                    }
                }
            }
            else {
            
                // Detect and use native browser support, if enabled in options
                if (
                    (hasNativePlaceholder)
                    && (options.useNative.call(this, $input))
                    && (($input.attr("tagName") || "") !== "TEXTAREA")
                ) {
                    // className is not set because current placeholder standard
                    // doesn't
                    // have a separate class name property for placeholders
                    // (watermarks).
                    if (hasText) {
                        $input.attr("placeholder", text);
                    }
                    
                    // Only set data flag for non-native watermarks
                    // [purposely commented-out] -> $input.data(dataFlag, 1);
                    return;
                }
                
                $input.data(dataText, hasText? text : "");
                $input.data(dataClass, options.className);
                $input.data(dataFlag, 1); // Flag indicates watermark was
                                            // initialized
                
                // Special processing for password type
                if (($input.attr("type") || "") === "password") {
                    var $wrap = $input.wrap("<span>").parent(),
                        $wm = $($wrap.html().replace(/type=["']?password["']?/i, 'type="text"'));
                    
                    $wm.data(dataText, $input.data(dataText));
                    $wm.data(dataClass, $input.data(dataClass));
                    $wm.data(dataFlag, 1);
                    $wm.attr("maxLength", text.length);
                    
                    $wm.focus(
                        function () {
                            $.watermark._hide($wm, true);
                        }
                    ).bind("dragenter",
                        function () {
                            $.watermark._hide($wm);
                        }
                    ).bind("dragend",
                        function () {
                            window.setTimeout(function () { $wm.blur(); }, 1);
                        }
                    );
                    $input.blur(
                        function () {
                            $.watermark._show($input);
                        }
                    ).bind("dragleave",
                        function () {
                            $.watermark._show($input);
                        }
                    );
                    
                    $wm.data(dataPassword, $input);
                    $input.data(dataPassword, $wm);
                }
                else {
                    
                    $input.focus(
                        function () {
                            $input.data(dataFocus, 1);
                            $.watermark._hide($input, true);
                        }
                    ).blur(
                        function () {
                            $input.data(dataFocus, 0);
                            $.watermark._show($input);
                        }
                    ).bind("dragenter",
                        function () {
                            $.watermark._hide($input);
                        }
                    ).bind("dragleave",
                        function () {
                            $.watermark._show($input);
                        }
                    ).bind("dragend",
                        function () {
                            window.setTimeout(function () { $.watermark._show($input); }, 1);
                        }
                    ).bind("drop",
                        // Firefox makes this lovely function necessary because
                        // the dropped text
                        // is merged with the watermark before the drop event is
                        // called.
                        function (evt) {
                            var elem = $input[0],
                                dropText = evt.originalEvent.dataTransfer.getData("Text");
                            
                            if ((elem.value || "").replace(rreturn, "").replace(dropText, "") === $input.data(dataText)) {
                                elem.value = dropText;
                            }
                            
                            $input.focus();
                        }
                    );
                }
                
                // In order to reliably clear all watermarks before form
                // submission,
                // we need to replace the form's submit function with our own
                // function. Otherwise watermarks won't be cleared when the form
                // is submitted programmatically.
                if (this.form) {
                    var form = this.form,
                        $form = $(form);
                    
                    if (!$form.data(dataFormSubmit)) {
                        $form.submit($.watermark.hideAll);
                        
                        // form.submit exists for all browsers except Google
                        // Chrome
                        // (see "else" below for explanation)
                        if (form.submit) {
                            $form.data(dataFormSubmit, form.submit);
                            
                            form.submit = (function (f, $f) {
                                return function () {
                                    var nativeSubmit = $f.data(dataFormSubmit);
                                    
                                    $.watermark.hideAll();
                                    
                                    if (nativeSubmit.apply) {
                                        nativeSubmit.apply(f, Array.prototype.slice.call(arguments));
                                    }
                                    else {
                                        nativeSubmit();
                                    }
                                };
                            })(form, $form);
                        }
                        else {
                            $form.data(dataFormSubmit, 1);
                            
                            // This strangeness is due to the fact that Google
                            // Chrome's
                            // form.submit function is not visible to JavaScript
                            // (identifies
                            // as "undefined"). I had to invent a solution here
                            // because hours
                            // of Googling (ironically) for an answer did not
                            // turn up anything
                            // useful. Within my own form.submit function I
                            // delete the form's
                            // submit function, and then call the non-existent
                            // function --
                            // which, in the world of Google Chrome, still
                            // exists.
                            form.submit = (function (f) {
                                return function () {
                                    $.watermark.hideAll();
                                    delete f.submit;
                                    f.submit();
                                };
                            })(form);
                        }
                    }
                }
            }
            
            $.watermark._show($input);
        }
    );
};

// The code included within the following if structure is guaranteed to only run
// once,
// even if the watermark script file is included multiple times in the page.
if ($.watermark.runOnce) {
    $.watermark.runOnce = false;

    $.extend($.expr[":"], {

        // Extends jQuery with a custom selector - ":data(...)"
        // :data(<name>) Includes elements that have a specific name defined in
        // the jQuery data
        // collection. (Only the existence of the name is checked; the value is
        // ignored.)
        // A more sophisticated version of the :data() custom selector
        // originally part of this plugin
        // was removed for compatibility with jQuery UI. The original code can
        // be found in the SVN
        // source listing in the file, "jquery.data.js".
        data: function( elem, i, match ) {
            return !!$.data( elem, match[ 3 ] );
        }
    });

    // Overloads the jQuery .val() function to return the underlying input value
    // on
    // watermarked input elements. When .val() is being used to set values, this
    // function ensures watermarks are properly set/removed after the values are
    // set.
    // Uses self-executing function to override the default jQuery function.
    (function (valOld) {

        $.fn.val = function () {
            
            // Best practice: return immediately if empty matched set
            if ( !this.length ) {
                return arguments.length? this : undefined;
            }

            // If no args, then we're getting the value of the first element;
            // otherwise we're setting values for all elements in matched set
            if ( !arguments.length ) {

                // If element is watermarked, get the underlying value;
                // otherwise use native jQuery .val()
                if ( this.data(dataFlag) ) {
                    var v = (this[0].value || "").replace(rreturn, "");
                    return (v === (this.data(dataText) || ""))? "" : v;
                }
                else {
                    return valOld.apply( this, arguments );
                }
            }
            else {
                valOld.apply( this, arguments );
                $.watermark.show(this);
                return this;
            }
        };

    })($.fn.val);
    
    // Hijack any functions found in the triggerFns list
    if (triggerFns.length) {

        // Wait until DOM is ready before searching
        $(function () {
            var i, name, fn;
        
            for (i=triggerFns.length-1; i>=0; i--) {
                name = triggerFns[i];
                fn = window[name];
                
                if (typeof(fn) === "function") {
                    window[name] = (function (origFn) {
                        return function () {
                            $.watermark.hideAll();
                            return origFn.apply(null, Array.prototype.slice.call(arguments));
                        };
                    })(fn);
                }
            }
        });
    }

    $(window).bind("beforeunload", function () {
        if ($.watermark.options.hideBeforeUnload) {
            $.watermark.hideAll();
        }
    });
}

})(jQuery, window);




/**
 * wSlide 0.1 - http://www.webinventif.fr/wslide-plugin/
 * 
 * Rendez vos sites glissant !
 * 
 * Copyright (c) 2008 Julien Chauvin (webinventif.fr) Licensed under the
 * Creative Commons License: http://creativecommons.org/licenses/by/3.0/
 * 
 * Date: 2008-01-27
 */
(function($) {
    $.fn.wslide = function(h) {
        h = jQuery.extend( {
            width : 150,
            height : 150,
            pos : 1,
            col : 1,
            effect : 'swing',
            fade : false,
            horiz : false,
            autolink : true,
            duration : 1500
        }, h);
        function gogogo(g) {
            g.each(function(i) {
                var a = $(this);
                var e = a.attr('id');
                if (e == undefined) {
                    e = 'wslide' + i
                }
                $(this).wrap('<div class="wslide-wrap" id="' + e + '-wrap"></div>');
                a = $('#' + e + '-wrap');
                var b = a.find('ul li');
                var f = h.effect;
                if (jQuery.easing.easeInQuad == undefined && (f != 'swing' || f != 'normal')) {
                    f = 'swing'
                }
                var g = h.width;
                var j = h.height;
                function resultante(a) {
                    var b = a;
                    b = b.split('px');
                    b = b[0];
                    return Number(b)
                }
                var k = g - (resultante(b.css('padding-left')) + resultante(b.css('padding-right')));
                var l = j - (resultante(b.css('padding-top')) + resultante(b.css('padding-bottom')));
                var m = h.col;
                if (h.horiz) {
                    m = Number(b.length + 1)
                }
                var n = '';
                var o = Math.ceil(Number(b.length) / m);
                a.css('overflow', 'hidden').css('position', 'relative').css('text-align', 'left').css('height', j + 'px').css('width', g + 'px').css('margin', '0').css('padding', '0');
                a.find('ul').css('position', 'absolute').css('margin', '0').css('padding', '0').css('width', Number((m + 0) * g) + 'px').css('height', Number(o * j) + 'px');
                b.css('display', 'block').css('overflow', 'hidden').css('float', 'left').css('height', l + 'px').css('width', k + 'px');
                b.each(function(i) {
                    var b = a.offset();
                    var c = $(this).offset();
                    $(this).attr('id', e + '-' + Number(i + 1)).attr('rel', Number(c.left - b.left) + ':' + Number(c.top - b.top));
                    n += ' <a href="#' + e + '-' + Number(i + 1) + '"></a>'
                });
                if (typeof h.autolink == 'boolean') {
                    if (h.autolink) {
                        a.after('<div class="wslide-menu" id="' + e + '-menu">' + n + '</div>')
                    }
                } else if (typeof h.autolink == 'string') {
                    if ($('#' + h.autolink).length) {
                        $('#' + h.autolink).html(n)
                    } else {
                        a.after('<div id="#' + h.autolink + '">' + n + '</div>')
                    }
                }
                var p = '#' + e + '-';
                var q = "";
                $('a[href*="' + p + '"]').click(function() {
                    $('a[href*="' + q + '"]').removeClass("wactive");
                    $(this).addClass("wactive");
                    var b = $(this).attr('href');
                    b = b.split('#');
                    b = '#' + b[1];
                    q = b;
                    var c = $(b).attr('rel');
                    c = c.split(':');
                    var d = c[1];
                    d = -d;
                    c = c[0];
                    c = -c;
                    if (h.fade) {
                        a.find('ul').animate( {
                            opacity : 0
                        }, h.duration / 2, f, function() {
                            $(this).css('top', d + 'px').css('left', c + 'px');
                            $(this).animate( {
                                opacity : 1
                            }, h.duration / 2, f)
                        })
                    } else {
                        a.find('ul').animate( {
                            top : d + 'px',
                            left : c + 'px'
                        }, h.duration, f)
                    }
                    return false
                });
                if (h.pos <= 0) {
                    h.pos = 1
                }
                $('a[href$="' + p + h.pos + '"]').addClass("wactive");
                var r = $('a[href*="' + p + '"]:eq(' + Number(h.pos - 1) + ')').attr('href');
                r = r.split('#');
                r = '#' + r[1];
                q = r;
                var s = $(r).attr('rel');
                s = s.split(':');
                var t = s[1];
                t = -t;
                s = s[0];
                s = -s;
                a.find('ul').css('top', t + 'px').css('left', s + 'px')
            })
        }
        gogogo(this);
        return this
    }
})(jQuery);

/* jslint browser: true *//* global jQuery: true */

/**
 * jQuery Cookie plugin
 * 
 * Copyright (c) 2010 Klaus Hartl (stilbuero.de) Dual licensed under the MIT and
 * GPL licenses: http://www.opensource.org/licenses/mit-license.php
 * http://www.gnu.org/licenses/gpl.html
 * 
 */
jQuery.cookie = function(key, value, options) {

    // key and at least value given, set cookie...
    if (arguments.length > 1 && String(value) !== "[object Object]") {
        options = jQuery.extend( {}, options);

        if (value === null || value === undefined) {
            options.expires = -1;
        }

        if (typeof options.expires === 'number') {
            var days = options.expires, t = options.expires = new Date();
            t.setDate(t.getDate() + days);
        }

        value = String(value);

        return (document.cookie = [ encodeURIComponent(key), '=', options.raw ? value : encodeURIComponent(value), options.expires ? '; expires=' + options.expires.toUTCString() : '', // use
                // expires
                // attribute,
                // max-age
                // is
                // not
                // supported
                // by
                // IE
                options.path ? '; path=' + options.path : '', options.domain ? '; domain=' + options.domain : '', options.secure ? '; secure' : '' ].join(''));
    }

    // key and possibly options given, get cookie...
    options = value || {};
    var result, decode = options.raw ? function(s) {
        return s;
    } : decodeURIComponent;
    return (result = new RegExp('(?:^|; )' + encodeURIComponent(key) + '=([^;]*)').exec(document.cookie)) ? decode(result[1]) : null;
};

/**
 * -------------------------------------------------------------------- jQuery
 * customfileinput plugin Author: Scott Jehl, scott@filamentgroup.com Copyright
 * (c) 2009 Filament Group licensed under MIT
 * (filamentgroup.com/examples/mit-license.txt)
 * --------------------------------------------------------------------
 */
$.fn.customFileInput = function(typeoffile) {
    return $(this).each(function() {
        // apply events and styles for file input element
            var fileInput = $(this).addClass('customfile-input') // add class
                    // for CSS
                    .mouseover(function() {
                        upload.addClass('customfile-hover');
                    }).mouseout(function() {
                        upload.removeClass('customfile-hover');
                    }).focus(function() {
                        upload.addClass('customfile-focus');
                        fileInput.data('val', fileInput.val());
                    }).blur(function() {
                        upload.removeClass('customfile-focus');
                        $(this).trigger('checkChange');
                    }).bind('disable', function() {
                        fileInput.attr('disabled', true);
                        upload.addClass('customfile-disabled');
                    }).bind('enable', function() {
                        fileInput.removeAttr('disabled');
                        upload.removeClass('customfile-disabled');
                    }).bind('checkChange', function() {
                        if (fileInput.val() && fileInput.val() != fileInput.data('val')) {
                            fileInput.trigger('change');
                        }
                    }).bind('change', function() {
                        // get file name
                            var fileName = $(this).val().split(/\\/).pop();
                            // get file extension
                            var fileExt = 'customfile-ext-' + fileName.split('.').pop().toLowerCase();
                            // update the feedback
                            uploadFeedback.text(fileName) // set feedback text
                                    // to filename
                                    .removeClass(uploadFeedback.data('fileExt') || '') // remove
                                    // any
                                    // existing
                                    // file
                                    // extension
                                    // class
                                    .addClass(fileExt) // add file extension
                                    // class
                                    .data('fileExt', fileExt) // store file
                                    // extension for
                                    // class removal
                                    // on next
                                    // change
                                    .addClass('customfile-feedback-populated'); // add
                            // class
                            // to
                            // show
                            // populated
                            // state
                        }).click(function() { // for IE and Opera, make sure
                                // change fires after choosing a
                                // file, using an async callback
                                fileInput.data('val', fileInput.val());
                                setTimeout(function() {
                                    fileInput.trigger('checkChange');
                                }, 100);
                            });
            // create custom control container
            var upload = $('<div class="customfile"></div>');
            // create custom control button
            var uploadButton = $('<span class="customfile-button" aria-hidden="true"></span>').appendTo(upload);
            // create custom control feedback
			if(typeoffile == 'resume')
            var uploadFeedback = $('<span class="customfile-feedback" aria-hidden="true">Добавить файл с резюме</span>').appendTo(upload);
			else 
			var uploadFeedback = $('<span class="customfile-feedback" aria-hidden="true">Прикрепить файл</span>').appendTo(upload);

            // match disabled state
            if (fileInput.is('[disabled]')) {
                fileInput.trigger('disable');
            }

            // on mousemove, keep file input under the cursor to steal click
            upload.mousemove(function(e) {
                fileInput.css( {
                    'left' : e.pageX - upload.offset().left - fileInput.outerWidth() + 20, // position
                    // right
                    // side
                    // 20px
                    // right
                    // of
                    // cursor
                    // X)
                    'top' : e.pageY - upload.offset().top - 3
                });
            }).insertAfter(fileInput);

            fileInput.appendTo(upload);
        });
};

$(document).ready(function() {
    $('.field-title').hover(function(){
		$(this).prev('img').css('opacity','0.5');
	}, function(){
		$(this).prev('img').css('opacity','1');
	});
    $('.form-item-file input').customFileInput('resume');
	$('.add-a-file input').customFileInput('file');
    $('.slider').wslide( {
        width : 900,
        height : 150,
        pos : 1,
        horiz : true
    });
    $('.block-21 ul').wslide( {
        width : 510,
        height : 360,
        pos : 1,
        horiz : true
    });
    $('.block-13 li > div, .block-13 li > p.more').css( {
        display : 'none'
    });
    $('.block-13 a.title').bind('click', function() {
        if ($(this).attr('id') != "active") {
            $('.block-13 li > div').slideUp('normal');
            $('.block-13 li > p.more').fadeOut('normal');
            $('.block-13 li a.title').removeAttr('id');
            $(this).attr('id', 'active').parent().next().slideDown('slow').next().animate( {
                margin : '0'
            }, 500).fadeIn('slow');
        } else {
            $('.block-13 li > div').slideUp('normal');
            $('.block-13 li > p.more').fadeOut('normal');
            $('.block-13 li a.title').removeAttr('id');
        }
        return false;
    });
    i = 0;
    $('.block-25 li').each(function() {
        $(this).attr('id', 'title-' + i);
        i++;
    });
    $('.block-25 li:first').each(function() {
        $(this).addClass('active');
    });
	
	var int = self.setInterval("showNextSlide()",3000);
	
    $('.block-25 li').bind('click', function() {
		int = window.clearInterval(int);
                return clickFunction($(this));		
    });
	
    $('a.feedback').click(function() {
        var documents = $(document).height();
        var windows = $(window).height();
        if (windows > documents) {
            $("#fuzz").css("height", $(window).height());
        } else {
            $("#fuzz").css("height", $(document).height());
        }
        $('#fuzz').fadeIn('slow');
        $('.block-28').fadeIn('normal');
        $('.block-28').animate( {
            top : '100px'
        }, 'slow');
        return false;
    });
    $('.block-28 .close, #fuzz').click(function() {
        var documents = $(document).height();
        var windows = $(window).height();
        if (windows > documents) {
            $("#fuzz").css("height", $(window).height());
        } else {
            $("#fuzz").css("height", $(document).height());
        }
        $('#fuzz').fadeOut('normal');
        $('.block-28').fadeOut('fast');
        $('.block-28').animate( {
            top : '-400px'
        }, 'fast');
        return false;
    });
    $('.news li .field-img img, .partners li img, .block-21 li img, .block-20 li img').each(function() {
        src = $(this).attr('src');
        $(this).after('<div class="clear"></div>');
        $(this).wrap('<div class="news-border" style="background-image: url(' + src + ');"></div>');
        $(this).addClass('hidden-img').css( {
            display : 'none'
        });
    });
    // tabs with cockie
        var tabs = $.cookie('tabs_smobile');
        if (tabs) {
            $('body.news-page h1 a').addClass('other');
            $('body.news-page h1 a[href=' + tabs + ']').removeClass();
            $('body.news-page .content-inside').css( {
                display : 'none'
            });
            $('body.news-page ' + tabs).fadeIn('fast');
        }
        $('h1.tabs a').click(function() {
            href = $(this).attr('href');
            $('body.news-page h1 a').addClass('other');
            $('body.news-page h1 a[href=' + href + ']').removeClass();
            $('.content-inside').css( {
                display : 'none'
            });
            $(href).fadeIn('normal');
            $.cookie('tabs_smobile', href);
            return false;
        });
        i=0;
        $('.block-24 .form-item input').each(function(){
            $(this).addClass('input-'+i);
            i++;
        })
        $('.block-28 .form-item input').each(function(){
            $(this).addClass('input-'+i);
            i++;
        })
        $('.block-13 ul li form .form-item input').attr('name', 'email').watermark('Ваша електронная почта');
        $('.block-28 .form-item input.input-0, .block-24 .form-item input.input-0').attr('name', 'firstname').watermark('Представьтесь');
        $('.block-28 .form-item input.input-1, .block-24 .form-item input.input-1').attr('name', 'feedback').watermark("Как с вами связаться?");
        $('.block-28 .form-item textarea, .block-24 .form-item textarea').attr('name', 'content').watermark("О чем вы хотите пообщатся?");
        $('.block-13 form').each(function(){
            $(this).validate( {
                invalidHandler: $.watermark.showAll,
                rules: {
                    email: {
                        required: true,
                        email: true
                    }
            }});
        });
        $('.block-28 form, .block-24 form').validate( {
            invalidHandler: $.watermark.showAll,
            rules: {
                firstname: {
                    required: true,
                    minlength: 4
                },
                feedback: {
                    required: true,
                    minlength: 4
                },
                content: {
                    required: true,
                    minlength: 10
                }
            }});
    });
	
	function clickFunction(obj){
		if (obj.hasClass('active') != true) {
            $('.block-25 li img.title').fadeIn(300);
            $('.block-25 li').animate( {
                width : '170px'
            }, 200);
            $('.block-25 li img.round').fadeOut(0);
            $('.block-25 li img.this-li').fadeOut(0);
            obj.find('img.round').animate( {
                margin : '0'
            }, 400).fadeIn(300);
            obj.find('img.this-li').animate( {
                margin : '0'
            }, 400).fadeIn(300);
            obj.animate( {
                width : '255px'
            }, 'fast');
            obj.find('img.title').fadeOut(300);
            $('.block-25 li.active .field-title').fadeOut(0).css( {
                padding : '57px 0 0'
            }).fadeIn(300);
            obj.find('.field-title').fadeOut(0).css( {
                padding : '51px 0 0'
            }).fadeIn(300);
            obj.find('.field-entry').fadeOut(0).css( {
                fontSize : '16px',
                padding : '21px 0 0 3px',
                color : '#ffffff',
                width : '200px'
            }).fadeIn(300);
            $('.block-25 li.active .field-entry').fadeOut(0).css( {
                fontSize : '13px',
                padding : '22px 0 0 0',
                color : '#494949',
                width : '150px'
            }).fadeIn(300);
            obj.find('.field-title a').css( {
                color : '#FFFFFF',
                fontSize : '25px',
                lineHeight : '25px'
            });
            $('.block-25 li.active .field-title a').css( {
                color : '#DF5721',
                fontSize : '18px',
                lineHeight : '20px'
            });
            $('.block-25 li').removeClass('active');
            $('.block-25 li').removeClass('in-active');
            obj.addClass('active');
            return false;
        }
        else return true;
	}
	
	function showNextSlide(){
		var ind = $('.block-25 > ul > li.active').index();
		if((ind + 1) == 5) ind = -1;
		var $curObj = $('.block-25 > ul > li').eq(ind + 1);
		clickFunction($curObj);
	}
	
$(window).bind("resize", function() {
    var documents = $(document).height();
    var windows = $(window).height();
    if (windows > documents) {
        $("#fuzz").css("height", $(window).height());
    } else {
        $("#fuzz").css("height", $(document).height());
    }
});
$(window).load(function() {
    var documents = $(document).height();
    var windows = $(window).height();
    if (windows > documents) {
        $("#fuzz").css("height", $(window).height());
    } else {
        $("#fuzz").css("height", $(document).height());
    }
    $('#news-entry .content-inside img').each(function() {
        src = $(this).attr('src');
        w = $(this).width();
        h = $(this).height();
        $(this).after('<div class="clear"></div>');
        $(this).wrap('<div class="news-border" style="background-image: url(' + src + '); width: ' + w + 'px; height: ' + h + 'px;"></div>');
        $(this).addClass('hidden-img').css( {
            display : 'none'
        });
    });
});
