Add client-side checks.
This commit is contained in:
Родитель
c200b2e63e
Коммит
6b585b0ea9
|
@ -200,8 +200,8 @@
|
|||
<script id="state_caus_tmpl" type="text/html">
|
||||
<tr>
|
||||
<td><span>${label}:</span></td>
|
||||
<td><input type="text" class="state" name="${id}"
|
||||
id="${id}" size="30" value=""/>
|
||||
<td><input type="text" class="state_caus ${extraClass}" name="${id}"
|
||||
id="${id}" length="30" value=""/>
|
||||
<span class="error"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -211,8 +211,8 @@
|
|||
<script id="credit_card_tmpl" type="text/html">
|
||||
<tr>
|
||||
<td><span>${label}:</span></td>
|
||||
<td><input type="text" class="creditcard" name="${id}"
|
||||
id="${id}" size="16" value=""/>
|
||||
<td><input type="text" class="creditcard ${extraClass}" name="${id}"
|
||||
id="${id}" length="16" value=""/>
|
||||
<span class="error"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -222,8 +222,8 @@
|
|||
<script id="num_tmpl" type="text/html">
|
||||
<tr>
|
||||
<td><span>${label}:</span></td>
|
||||
<td><input type="text" name="${id}"
|
||||
id="${id}" size="${length}" value=""/>
|
||||
<td><input type="text" name="${id}" class="num ${extraClass}"
|
||||
id="${id}" length="${length}" value=""/>
|
||||
<span class="error"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -233,7 +233,7 @@
|
|||
<script id="month_tmpl" type="text/html">
|
||||
<tr>
|
||||
<td><span>${label}:</span></td>
|
||||
<td><select id="${id}" name="${id}">
|
||||
<td><select id="${id}" name="${id}" class="month ${extraClass}">
|
||||
<option value="" selected>-- Please choose your Month --</option>
|
||||
<option value="01">January</option>
|
||||
<option value="02">February</option>
|
||||
|
@ -257,7 +257,7 @@
|
|||
<script id="year_future_tmpl" type="text/html">
|
||||
<tr>
|
||||
<td><span>${label}:</span></td>
|
||||
<td><select id="${id}"
|
||||
<td><select id="${id}" class="yearfuture ${extraClass}"
|
||||
name="${id}">
|
||||
<option value="" selected>-- Please choose your Year --</option>
|
||||
<option value="2010">2010</option>
|
||||
|
@ -280,8 +280,8 @@
|
|||
<script id="alpha_num_tmpl" type="text/html">
|
||||
<tr>
|
||||
<td><span>${label}:</span></td>
|
||||
<td><input type="text" name="${id}"
|
||||
id="${id}" size="${length}" value=""/>
|
||||
<td><input type="text" name="${id}" class="${extraClass}"
|
||||
id="${id}" length="${length}" value=""/>
|
||||
<span class="error"/>
|
||||
</td>
|
||||
</tr>
|
||||
|
@ -291,7 +291,7 @@
|
|||
<script id="country_tmpl" type="text/html">
|
||||
<tr>
|
||||
<td><span>${label}:</span></td>
|
||||
<td><select id="${id}" name="${id}">
|
||||
<td><select id="${id}" name="${id}" class="country ${extraClass}">
|
||||
<option value="" selected>-- Please choose your Country --</option>
|
||||
<option value="AF">Afghanistan (افغانستان)</option>
|
||||
<option value="AX">Aland Islands</option>
|
||||
|
|
|
@ -62,7 +62,7 @@ function getLocalStorage(page) {
|
|||
/**
|
||||
* Save the state of this page to localstorage, so we can reconstitute it
|
||||
* later.
|
||||
**/
|
||||
*/
|
||||
function saveState() {
|
||||
var firstname = $("#FirstName").val();
|
||||
var lastname = $("#LastName").val();
|
||||
|
@ -112,7 +112,7 @@ function setObjectsForKey(root, key, value) {
|
|||
*
|
||||
* @param {jQuery Collection} inputs The inputs to convert.
|
||||
* @return {object} An object containing all the inputs.
|
||||
**/
|
||||
*/
|
||||
function objectify(inputs, provider) {
|
||||
var rv = {}
|
||||
$(provider.api.reverse()).each(function(index, item) {
|
||||
|
@ -131,11 +131,146 @@ function objectify(inputs, provider) {
|
|||
else {
|
||||
value = inputs.filter("[name="+item.id+"]").attr("value");
|
||||
}
|
||||
if ((item.type == "credit_card") || (item.type == "num") ||
|
||||
(item.type == "year_future") || (item.type == "month"))
|
||||
value = value.replace(/\D+/g, '');
|
||||
|
||||
value = value.trim();
|
||||
|
||||
setObjectsForKey(rv, key, value);
|
||||
});
|
||||
return rv;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate the credit card using the Luhn algorithm.
|
||||
*
|
||||
* @param {String} cc The credit card number.
|
||||
* @return {boolean} True if the credit card number is valid.
|
||||
*/
|
||||
function validateCreditCard(cc) {
|
||||
cc = cc.replace(/\D+/g, '')
|
||||
|
||||
// Test credit card number == true.
|
||||
if (cc == "4111111111111111")
|
||||
return true;
|
||||
|
||||
// Empty credit card number == false.
|
||||
if (!cc.length)
|
||||
return false;
|
||||
|
||||
// Calculate the checksum according to:
|
||||
// http://en.wikipedia.org/wiki/Luhn_algorithm
|
||||
checksum = 0;
|
||||
for each (let [i, a] in Iterator(cc)) {
|
||||
a = parseInt(a, 10);
|
||||
if (((i % 2) == 0) || (a == 9))
|
||||
checksum += a;
|
||||
else if (a < 5)
|
||||
checksum += 2 * a;
|
||||
else
|
||||
checksum += (2 * a) % 9;
|
||||
}
|
||||
return (checksum % 10) == 0;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate the values for a set of inputs, returning any errors.
|
||||
*
|
||||
* @param {jQuery Collection} inputs The inputs to validate.
|
||||
* @return {array} The (possibly-empty) array of errors.
|
||||
*/
|
||||
function validateForm(inputs) {
|
||||
let rv = {hasErrors: false};
|
||||
inputs.each(function(index, item) {
|
||||
let item = $(item);
|
||||
|
||||
// Get the value.
|
||||
let value = item.attr("value").trim();
|
||||
if (item.hasClass("creditcard") || item.hasClass("num") ||
|
||||
item.hasClass("yearfuture"))
|
||||
value = value.replace(/\D+/g, '');
|
||||
|
||||
// Check that required elements have a value.
|
||||
if (item.hasClass("required") && (item.attr("value") == "")) {
|
||||
rv[item.attr("id")] = "Missing required value.";
|
||||
rv.hasErrors = true;
|
||||
return;
|
||||
}
|
||||
|
||||
let length = item.attr("length");
|
||||
if (length && (value.length > length)) {
|
||||
rv[item.attr("id")] = "Value too long.";
|
||||
rv.hasErrors = true;
|
||||
return;
|
||||
}
|
||||
|
||||
// Check that credit cards pass the luhn check.
|
||||
if (item.hasClass("creditcard")) {
|
||||
if (!validateCreditCard(value)) {
|
||||
rv[item.attr("id")] = "Credit card number invalid.";
|
||||
rv.hasErrors = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check that future years are in the future.
|
||||
if (item.hasClass("yearfuture")) {
|
||||
|
||||
let expiryYear = parseInt(value, 10);
|
||||
let expiryMonth = parseInt(inputs.filter(".month").attr("value"), 10) - 1;
|
||||
let currentYear = new Date().getFullYear();
|
||||
let currentMonth = new Date().getMonth();
|
||||
|
||||
if ((currentYear > expiryYear) ||
|
||||
((currentYear == expiryYear) && (currentMonth > expiryMonth))) {
|
||||
rv[item.attr("id")] = "Credit card has expired.";
|
||||
rv.hasErrors = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Check that state_caus is there if the country is CA or US.
|
||||
if (item.hasClass("state_caus")) {
|
||||
let country = inputs.filter(".country").attr("value");
|
||||
if (((country == "CA") || (country == "US")) && (value == "")) {
|
||||
rv[item.attr("id")] = "Missing required value.";
|
||||
rv.hasErrors = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return rv;
|
||||
}
|
||||
|
||||
/**
|
||||
* Display the errors for set of inputs in the specified form.
|
||||
*
|
||||
* @param {jQuery Collection} inputs The possibly-erroneous inputs.
|
||||
* @param {array} The (possibly-empty) array of errors.
|
||||
*/
|
||||
function displayErrors(inputs, errors) {
|
||||
// General errors go in $("#provision_form .error").text("");
|
||||
// value.next(".error").text(data.errors[i]);
|
||||
for (let i in errors) {
|
||||
// Populate the errors.
|
||||
if (i == "hasErrors")
|
||||
continue;
|
||||
|
||||
let value = inputs.filter("#"+i.replace(".", "\\.", "g"));
|
||||
if (!value.length)
|
||||
// Assume it's a global error if we can't find the
|
||||
// specific element it applies to.
|
||||
value = $("#provision_form #global");
|
||||
value.next(".error").text(errors[i]);
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
$(function() {
|
||||
// Snarf the things I need out of the window arguments.
|
||||
let NewMailAccount = window.arguments[0].NewMailAccount;
|
||||
|
@ -163,7 +298,7 @@ $(function() {
|
|||
currentProvider = i;
|
||||
// Fill in #provision_form.
|
||||
for each (let [i, field] in Iterator(provider.api.reverse())) {
|
||||
dump("Populating "+field.id+", "+field.type+"\n");
|
||||
field.extraClass = field.required ? "required" : "";
|
||||
$("#"+field.type+"_tmpl").render(field).prependTo($("#provision_form"));
|
||||
};
|
||||
// Update the terms of service and privacy policy links.
|
||||
|
@ -252,9 +387,15 @@ $(function() {
|
|||
saveState();
|
||||
$("#provision_form .error").text("");
|
||||
let realname = $("#FirstName").val() + " " + $("#LastName").val();
|
||||
|
||||
var inputs = $("#new_account :input").not("[readonly]").not("button");
|
||||
|
||||
// Make sure we pass the client-side checks.
|
||||
let errors = validateForm(inputs);
|
||||
if (errors.hasErrors) {
|
||||
displayErrors(inputs, errors);
|
||||
return;
|
||||
}
|
||||
|
||||
// Then add the information from this page.
|
||||
var data = objectify(inputs, providers[currentProvider]);
|
||||
$.ajax({url: providers[currentProvider].url,
|
||||
|
@ -264,6 +405,7 @@ $(function() {
|
|||
contentType: 'text/json',
|
||||
data: JSON.stringify(data),
|
||||
success: function(data) {
|
||||
dump("data="+JSON.stringify(data)+"\n");
|
||||
if (data.succeeded) {
|
||||
// Create the account using data.config!
|
||||
let password = data.password
|
||||
|
@ -273,15 +415,7 @@ $(function() {
|
|||
window.close();
|
||||
}
|
||||
else {
|
||||
for (let i in data.errors) {
|
||||
// Populate the errors.
|
||||
let value = $("#provision_form #"+i.replace(".", "\\.", "g"));
|
||||
if (!value.length)
|
||||
// Assume it's a global error if we can't find the
|
||||
// specific element it applies to.
|
||||
value = $("#provision_form #global");
|
||||
value.next(".error").text(data.errors[i]);
|
||||
}
|
||||
displayErrors(inputs, data.errors);
|
||||
}
|
||||
}});
|
||||
});
|
||||
|
|
Загрузка…
Ссылка в новой задаче