﻿(function ($, undefined) {
    var rxEmail = /^([a-zA-Z0-9_.-])+@(([a-zA-Z0-9-])+.)+([a-zA-Z0-9]{2,4})+$/,
            rxUrl = /^https{0,1}:\/\/[\S]+[a-z0-9]\/{0,1}/i,
            rxTrim = /^\s+|\s+$/;

    $.fn.html5form = function (options) {
        options = $.extend({}, $.fn.html5form.defaults, options);
        return this.each(function () {
            var form = $(this);

            form.submit(function (e) {
                form.find('.' + options.errorMessageClass).hide();
                var inputs = form.find(':input:not(.placeholder)');
                for (var i = 0; i < inputs.length; i++)
                    if (validate_element(inputs.eq(i), options) === false) {
                        return false;
                    }
            });

            form.find('input, textarea').each(function () {
                var input = $(this);
                if (input.attr('placeholder') || !input.attr('id')) return;
                var label = $("label[for='" + input.attr('id') + "']");
                if (label.length == 0) return;
                input.attr('placeholder', label.text());
            });
        });
    }

    function find(id, options) {
        if (!id) return undefined;
        var match = $("label." + options.errorMessageClass + "[for='" + id + "']");
        if (match.length) return match;
    }

    function bounds(obj) {
        var off = obj.offset();
        off.height = obj.outerHeight();
        off.width = obj.outerWidth();
        off.bottom = off.top + off.height;
        off.right = off.left + off.width;
        return off;
    }

    function visibility() {
        var win = $(window);
        var v = { top: win.scrollTop(), left: win.scrollLeft() };
        v.bottom = v.top + win.height();
        v.right = v.left + win.width();
        return v;
    }

    function topx(x) {
        return (x > 0 ? '+' : '-') + '=' + Math.abs(x) + 'px';
    }

    function scrollBy(x, y) {
        $('html,body').animate({ scrollLeft: topx(x), scrollTop: topx(y) }, 500);
    }

    function validate_element(input, options) {
        input.removeClass(options.errorClass);
        var error = input.data('html5form-error', input.data('html5form-error')
                || find(input.attr('id'), options)
                || $(options.error).attr('for', input.attr('id')).addClass(options.errorMessageClass).insertAfter(input))
            .data('html5form-error');
        error.hide();

        var showerror = function (msg) {
            input.addClass(options.errorClass);
            error.html(msg).show();
            (input[0].select || input[0].focus).apply(input[0]);

            var bound = bounds(input);
            var visible = visibility();
            if (bound.bottom > visible.bottom)
                scrollBy(0, bound.bottom - visible.bottom + options.scrollMargin);
            else if (bound.top < visible.top)
                scrollBy(0, bound.top - visible.top - options.scrollMargin);
            if (bound.right > visible.right)
                scrollBy(bound.right - visible.right + options.scrollMargin, 0);
            else if (bound.left < visible.left)
                scrollBy(bound.left - visible.left - options.scrollMargin, 0);

            return false;
        }

        var value = input.val(), type = (input[0].attributes['type'] || { value: '' }).value.toLowerCase();
        value = value.replace(rxTrim, '');

        if (input.attr('required') && value.length == 0) return showerror(options.messages.required);
        if (type == 'email' && value.length > 0 && !rxEmail.exec(value)) return showerror(options.messages.email);
        if (type == 'url' && value.length > 0 && !rxUrl.exec(value)) {
            console.log(value, rxUrl, rxUrl.test(value));
            return showerror(options.messages.url);
        }
        if (input.attr('pattern') && value.length > 0 && !(new RegExp(input.attr('pattern'))).test(value)) return showerror(options.messages.pattern);
    }

    $.fn.html5form.defaults = {
        messages: { required: 'This field is required', email: 'Please enter a valid email address', url: 'Please enter a valid URL', pattern: 'This value is invalid' },
        errorClass: 'ui-error', errorMessageClass: 'ui-error-message', error: '<label />', scrollMargin: 25
    }

    $(function () {
        $('form.html5').html5form();
    });

})(jQuery);
