1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
// jquery.tools validation with twitter bootstrap layout

var validation_results_selector = '#validation-results-top, #validation-results-bottom';

// Required inputs
$.tools.validator.fn("input.required, select.required", "can't be blank", function(input, value) {
    return !input.is(':visible') || value != '';
});

// Agreement checkboxes
$.tools.validator.fn('input[type="checkbox"].required', "<b>(Must be checked)</b>", function(input, value) {
    return !input.is(':visible') || input.is(':checked');
});

// Date pickers
$.tools.validator.fn("input.date-picker.today-or-in-the-future", "can't be in the past", function(input, value) {
    return !input.is(':visible') || value == '' || (Date.parse(value) > Date.now() - 24*60*60*1000);
});

// Riders (input type = 'radio')
$.tools.validator.fn('input:radio', "must be selected", function(input, value) {
    var value = $('input:radio[name="'+ input.attr('name') +'"]:checked').val(); // Escaped input name with double quotes (AGordikov 09/10/2012)
    return value != null;
});

// User password
$.tools.validator.fn('#new_user_password_confirmation', "doesn't match password", function(input, value) {
    var element = $('#' + input.attr('data-match-field'));
    return element.size() == 0 || element.val() == value;
});

// User email
$.tools.validator.fn('#new_user_email', function(input, value) {
    if (input.is(':visible') && value == ''){
        return false;   // do not send request if field is empty
    }

    // verify email format
    var re = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
    if (!re.test(value)){
        return false;
    }

    // if value is present and format matches, send request to server
    $.ajax({
        type: "GET",
        url: "/policies/ajax_validate_email",
        timeout: 5000,  // 5 seconds
        data: { email: value }
    }).done(function( json_result ) {
        if (json_result.error != null) {
            // validation error
            $('form#policy_form').data('validator').invalidate({'new_user[email]': json_result.error});
        } else {
            // success
        }
    }).error(function ( json_result ) {
        // server error, timeout etc
        //$('form#policy_form').data('validator').invalidate({'new_user[email]': 'Server '+json_result.statusText});
    });

    return true;
});

// Month validator
$.tools.validator.fn("select.month", "can't be in the past", function(input, value) {
    var month = null;
    var year = null;

    if (value <= 12) { // Month selected
        month = parseInt(value);
        year = parseInt(input.next("select").val());
    } else { // Year selected
        month = parseInt(input.prev("select").val());
        year = parseInt(value);
    }

    var today = new Date();
    return year > today.getFullYear() || (year == today.getFullYear() && month >= today.getMonth()+1);
});

// scrolls page to given element
function scrollTo(element) {
    $("html, body").animate({scrollTop:element.offset().top}, 'ease');
}

function disable_hidden_options(){
    // Disable invisible inputs so they are not validated.
    $('input:visible, select:visible').removeAttr("disabled");                                          // 1. enable inputs in expanded sections
    $('input:not(:visible):not([type=hidden]), select:not(:visible)').attr("disabled", "disabled");     // 2. then disable inputs in collapsed sections

}

function add_validation(selector)
{
    $(selector).each(function () {
        var form = $(this);
        var validation_results = $(validation_results_selector);

        form.find('input[type="text"], input[type="password"], input[type="email"], input[type="tel"], input[type="checkbox"], input:radio, select')
            .focus(function() {
                // Andrew K. I haven't found how to reset field error yet.
            })
            .blur(function() {
                var validator = $(this).parents('form').data('validator');
                if (validator != null) {
                    validator.checkValidity($(this));
                }
            });

        form
            .validator({
                errorInputEvent: 'change',
                onBeforeValidate: function(){
                    disable_hidden_options();
                }
            })
            .submit(function(e)  {
                // onsubmit handler
                if (!e.isDefaultPrevented()) {
                    // form is valid
                    validation_results.hide();
                } else {
                    // form with errors
                    validation_results.show();
                    scrollTo($('div.control-group.error:visible:first').first());
                }
            })
            .bind('reset.validator', function () {
                remove_all_validation_markup(form);
                validation_results.hide();
            })
            .bind('onSuccess', function (e, ok) {
                $.each(ok, function() {
                    var input = $(this);
                    remove_validation_markup(input);
                    // uncomment next line to highlight successfully
                    // validated fields in green
                    //add_validation_markup(input, 'success');
                });
            })
            .bind('onFail', function (e, errors) {
                $.each(errors, function() {
                    var err = this;
                    var input = $(err.input);
                    remove_validation_markup(input);
                    add_validation_markup(input, 'error',
                        err.messages.join(' '));
                });
                return false; // skip other errors
            });
    });
}

//stops the a href event from bubbling up if an info help-icon is clicked on
$(document).click(function(e){
    if(e.originalEvent.srcElement && e.originalEvent.srcElement.className == 'icon icon-info-sign'){
        return false;
    }
})

function find_container(input) {
    return input.parents('div.control-group');
}
function remove_validation_markup(input) {
    var cont = find_container(input);
    cont.removeClass('error success warning');
    $('.help-inline.error, .help-inline.success, .help-inline.warning', cont).remove();
}
function add_validation_markup(input, cls, caption) {
    var cont = find_container(input);
    cont.addClass(cls);
    input.addClass(cls);

    if (caption) {
        var msg = $('<span class="help-inline"/>');
        msg.addClass(cls);
        msg.html(caption);

        var asterisk = input.next("abbr");
        var second_select = input.next("select");
        var last_radio = input.closest('label.radio').siblings('label.radio:last');

        if (asterisk.size() > 0) {
            // Checkboxes
            asterisk.after(msg);
        } else if (second_select.size() > 0) {
            // Month control
            second_select.after(msg);
        } else if (last_radio.size() > 0) {
            last_radio.after(msg);
        } else {
            input.after(msg);
        }
    }
}
function remove_all_validation_markup(form) {
    $('.help-inline.error, .help-inline.success, .help-inline.warning', form).remove();
    $('.error, .success, .warning', form)
        .removeClass('error success warning');
}