/
salsa.js
188 lines (148 loc) · 6.43 KB
/
salsa.js
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
(function($) {
// Settings.
var defaults = {
inputs: ['input', 'select', 'textarea']
};
var settings;
/*
* Methods available.
*/
var methods = {
/*
* Constructor.
*/
init : function(options){
var that = this;
// We can use the extend method to merge options/settings as usual:
// But with the added first parameter of TRUE to signify a DEEP COPY:
settings = $.extend(true, {}, defaults, options);
// Debug stuff.
if(settings.debug == true) { console.log('Salsa Form Validation Loaded'); }
// Add error messages container to all form controls.
var errContainerHtml = '<ul class="salsa-error-list" style="display: block;"></ul>';
for(var i=0; i<settings.inputs.length; i++) {
$.each(this.find(settings.inputs[i]), function(key, value) {
// Check if either the entire form is to be validated or this specific element.
if($(that).attr('data-validate') == 'salsa' || $(value).attr('data-validate') == 'salsa') {
$(value).parent().append(errContainerHtml);
}
});
}
// Return.
return this;
},
/*
* Validate form.
*/
validate: function() {
// Debug stuff.
if(settings.debug == true) { console.log('[Salsa] Validate'); }
// Clear any error messages.
methods.clearErrors.apply(this);
// Flags that no errors were found.
var isValid = true;
//
// Perform validations coded in the form's HTML.
//
for(var i=0; i<settings.inputs.length; i++) {
// For each of the controls being 'watched'.
$.each(this.find(settings.inputs[i]), function(key, value) {
var el = $(value);
// If required, check if value provided.
if(el.attr('data-required') == 'true') {
if(el.val() == '') {
if(settings.debug == true) { console.log('[Salsa] Validation Error! ID: ' + $(value).attr('id')); }
isValid = false;
el.addClass('salsa-error');
el.parent().find('ul[class="salsa-error-list"]').prepend('<li class="required" style="display: list-item;">This value is required.</li>');
}
}
});
}
// Return whether form is valid or not.
return isValid;
},
/*
* Parse server error (bad request).
*/
processResponse: function() {
// Clear any error messages.
methods.clearErrors.apply(this);
// Response text is required, should be passed as argument.
if(arguments.length != 2) {
this.find('#messages').prepend('<div class="alert alert-error">Client error.</div>')
return;
}
// Fetch arguments.
var status = arguments[0];
var responseText = arguments[1];
// Parse JSON response.
try {
var response = JSON.parse(responseText);
} catch(err) {
this.find('#messages').prepend('<div class="alert alert-error">Response error.</div>')
return;
}
// If 'Bad Request', then check if information regarding what is wrong with the parameters is provided.
if(status == 400 && response.parameters) {
// Check for a message for "all".
if(response.parameters.__all__) {
var messages = response.parameters.__all__;
for(var i=0; i<messages.length; i++) {
var errorMessage = '<div class="alert alert-error">' + messages[i] + '</div>';
this.find('#messages').prepend(errorMessage);
}
}
// Process each parameter's message.
for(param in response.parameters) {
$.each(this.find('#' + param), function(key, value) {
var el = $(value);
var messages = response.parameters[param];
el.addClass('salsa-error');
for(var i=0; i<messages.length; i++) {
el.parent().find('ul[class="salsa-error-list"]').prepend('<li class="required" style="display: list-item;">' + messages[i] + '</li>');
}
});
}
}
// If no details on why the request failed, then show generic message (either provided by server or default one).
else {
var errorMessage = '<div class="alert alert-error">' + ((response.message) ? response.message : 'Bad request.') + '</div>';
this.find('#messages').prepend(errorMessage);
}
},
/*
* Clear errors.
*/
clearErrors: function() {
if(settings.debug == true) { console.log('[Salsa] Clearing errors'); }
// Messages.
this.find('#messages').empty();
// Form controls.
for(var i=0; i<settings.inputs.length; i++) {
$.each(this.find(settings.inputs[i]), function(key, value) {
var el = $(value);
el.removeClass('salsa-error');
el.parent().find('ul[class="salsa-error-list"]').empty();
});
}
}
};
/*
* Attach the plugin to jQuery's namespace.
*/
$.fn.salsa = function(method) {
// Check if method invoked exists.
if(methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
}
// If method is an hash, then we assume the constructor is being called.
else if(typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
}
// Invalid method.
else {
$.error('Method ' + method + ' does not exist on jQuery.salsa');
}
};
}(jQuery));