// *********************************************************************
// SETUP
// *********************************************************************
var wrjs = wrjs || {};
wrjs.utils = wrjs.utils || {};
wrjs.utils.form = wrjs.utils.form || {};
// *********************************************************************
// FORM UTILITY FUNCTIONS
// *********************************************************************
(function () {
// ***********************************************************
// PRIVATE
// ***********************************************************
var _init = function() {
_createListeners();
};
var _createListeners = function() {
$(document).ready(function() {
$('body').on('keydown change', '.fielderror :input', function() {
_removeErrorState(this)
});
$('body').on('change', '.wrjs_modal input[type=radio], .wrjs_modal select', function() {
var t = $(this);
var form = t.closest('form');
_callModalPixelFix(form);
});
// STRIP ANGLED BRACKETS <>
$('body').on('keydown paste', 'input.stripspecialchars, .stripspecialchars input, textarea.stripspecialchars, .stripspecialchars textarea', function(e) {
var el = this;
var t = $(this);
setTimeout(function() {
var val = t.val();
var position = t.caret().begin;
var patt = /[<>]/;
if(patt.test(val)) {
var newval = val.replace(/[<>]/g, '');
t.val(newval);
t.caret(position-1);
}
})
})
$('body').on('keydown paste', 'input.numericonly, .numericonly input', function(e) {
var el = this;
var t = $(this);
setTimeout(function() {
var val = t.val();
var position = t.caret().begin;
var containsnonnumber = /\D/
if(containsnonnumber.test(val)) {
var newval = val.replace(/\D/g, "");
t.val(newval);
t.caret(position-1);
}
})
});
$('body').on('keydown paste keyup blur', 'input.numericonlyexcludezero, .numericonlyexcludezero input', function(e) {
var el = this;
var t = $(this);
var val = t.val();
// REMOVE STARTING ZERO
if(val.substring(0,1) == '0') {
val = val.substring(1);
t.val(val);
};
setTimeout(function() {
var position = t.caret().begin;
var containsnonnumber = /\D/
if(containsnonnumber.test(val)) {
var newval = val.replace(/\D/g, "");
t.val(newval);
t.caret(position-1);
}
},1)
});
$('body').on('keydown paste', 'input.numericandperiodonly, .numericandperiodonly input', function(e) {
var el = this;
var t = $(this);
setTimeout(function() {
var val = t.val();
var position = t.caret().begin;
var containsinvalid = /[^0-9.]/
if(containsinvalid.test(val)) {
var newval = val.replace(/[^0-9.]/g, "");
t.val(newval);
t.caret(position-1);
}
})
});
// STRIP SPACES IN EMAIL FIELDS
$('body').on('keydown paste', 'input.stripwhitespace, .stripwhitespace input', function(e) {
var el = this;
var t = $(this);
setTimeout(function() {
var val = t.val();
var position = t.caret().begin;
var patt = /\s/;
if(patt.test(val)) {
var newval = val.replace(/\s/g, '');
t.val(newval);
t.caret(position-1);
}
})
});
})
};
var _removeErrorState = function(el) {
var t = $(el);
var row = t.closest('.form-row');
row.find('.error').remove();
row.removeClass('fielderror');
t.removeClass('fielderror');
var form = t.closest('form');
_callModalPixelFix(form);
};
var _getFormData = function ($form, formConfig) {
formConfig = typeof formConfig == 'undefined' ? false : formConfig;
var stripId = formConfig && formConfig.makeFieldIdsUnique;
var unindexed_array = $form.serializeArray();
var indexed_array = {};
$.map(unindexed_array, function (n, i) {
var name = n['name'];
// BY DEFAULT ALL FIELD VALUES SHOULD BE HTML ENCODED (XSS)
// HOWEVER, IN SOME SCENARIOS, THIS NEEDS TO BE DISABLED (e.g. Allow sending of angled brackets, etc)
// THEREFORE CHECK IF THE PARENT LABEL HAS A CLASS OF "donotencode" ATTACHED, THEN SET ENCODE TO FALSE IF PRESENT
var encode = true;
var field = $('#' + name, $form);
var label = field.closest('label');
if(field.hasClass('donotencode') || (label.length > 0 && label.hasClass('donotencode'))) {
encode = false;
};
var value = n['value'];
if(encode) {
value = $.trim(wrjs.utils.htmlEncode(value));
};
// IF WRJS FORM HAS "makeFieldIdsUnique" CONFIG SET TO TRUE
// THEN STRIP OF THE FORM ID FROM THE FRONT OF THE FIELD NAME
if(stripId) {
name = name.split(formConfig.id + '_')[1];
};
if (indexed_array[name]) {
if (typeof indexed_array[name] == 'string') {
indexed_array[name] = [indexed_array[name], value];
} else {
indexed_array[name].push(value);
}
} else {
indexed_array[name] = value;
}
});
return indexed_array;
};
var _isEmailValid = function (email) {
var regex = /^([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x22([^\x0d\x22\x5c\x80-\xff]|\x5c[\x00-\x7f])*\x22))*\x40([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d)(\x2e([^\x00-\x20\x22\x28\x29\x2c\x2e\x3a-\x3c\x3e\x40\x5b-\x5d\x7f-\xff]+|\x5b([^\x0d\x5b-\x5d\x80-\xff]|\x5c[\x00-\x7f])*\x5d))*$/;
return regex.test(email);
};
var _isURLValid = function(url) {
var regex = /[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&//=]*)/ig
return regex.test(url);
};
var _trimAndCheckUniqueEmails = function (config) {
var emails = config.emails ? config.emails : ''; // PASS A COMMA DELIMITED STRING OF EMAILS
var limit = config.limit ? Number(config.limit) : false; // PASS A MAXIMUM NUMBER OF EMAILS ALLOWED TO REMAIN VALID
// SET DEFAULTS
var toomany = false;
var uniqueEmails = [];
var invalidemails = [];
if(emails.length != 0) {
// STRIP OUT ALL WHITESPACE, THEN SPLIT INTO AN ARRAY OF EMAILS
emails = emails.replace(/(\r\n|\n|\r)/gm, '');
emails = emails.replace(/\s/g, '');
emails = emails.replace(/,$/, '');
emails = emails.split(',');
// LOOP EMAIL ARRAY AND CHECK VALIDITY
$.each(emails, function (i, el) {
var exists = $.inArray(el, uniqueEmails) > -1;
// CHECK FOR DUPLICATES
if(!exists) {
// IF LIMIT HAS BEEN PASSED, AND THE UNIQUEEMAILS ARRAY ALREADY CONTAINS THE LIMIT AMOUNT
if (limit != false && uniqueEmails.length >= limit) {
toomany = true;
};
// RUN EMAIL THROUGH EMAIL REGEX AND PUSH INTO THE CORRECT ARRAY (VALID OR INVALID)
if(el.length > 0) {
if (!_isEmailValid(el)) {
invalidemails.push(el);
};
// ALWAYS PUSH UNIQUE EMAILS, EVEN IF INVALID
uniqueEmails.push(el);
};
}
});
// FORCE INVALID EMAIL MESSAGE IF BLANKS GET PASSED THROUGH SUCCESSFULLY
// DE8237 - Can enter ", , , , ,"
if(uniqueEmails.length == 0) {
if(invalidemails.length == 0) {
invalidemails.push('');
}
};
};
return { emails: uniqueEmails.join(','), invalidemails: invalidemails, toomany: toomany };
};
var _isFormValid = function (form) {
if(!form) {
return true;
}
if(typeof form == 'string') {
form = $(form);
}
var formdata = _getFormData(form);
var valid = true;
var invalidfields = [];
// CHECK IF A RANGE OF INPUTS HAVE BEEN PASSED INSTEAD OF THE PARENT FORM
if(form && form.length > 0) {
form = $(form[0]).closest('form');
} else {
form = $('.wrjs_modal') || $('body');
};
// REMOVE ERROR STATES
$('.error', form).remove();
$('.fielderror', form).removeClass('fielderror');
// ONLY MASK PARENT WHEN FORM ISN'T PART OF A MULTI-STEP TAB PANEL
var steptabs = $('.tabs.steps', form);
var parentModal = form.closest('.wrjs_modal');
if(parentModal.length > 0 && !steptabs) {
parentModal.mask(ls.text_saving);
}
$.each(formdata, function (key, val) {
val = $.trim(val);
var fieldvalid = true;
var fieldError = '';
var input = $('#' + key, form);
var formRow = input.closest('.form-row');
var email = input.attr('type') == 'email' || input.attr('email') == 'true';
var phone = input.attr('type') == 'tel';
var hidden = input.attr('type') == 'hidden';
var button = input.attr('type') == 'button';
var url = input.attr('type') == 'url';
var minlength = input.attr('minlength');
var allowblank = input.attr('allowblank') == "true" ? true : false;
var ignorehidden = form.hasClass('ignorehidden');
var customValidation = input.attr('customValidation');
var validationmessage = input.attr('validationmessage');
var invalidEmailList = '';
if((ignorehidden && hidden) || button) {
allowblank = true;
};
if(customValidation) {
var args = [input, formdata];
// RUN CUSTOM VALIDATION
var result = wrjs.utils.executeFunctionByName(customValidation, args);
// THIS RETURNS AN OBJECT CONSISTING OF:
/*
{
valid: bool,
msg: str
}
*/
//console.log('customValidation', result);
fieldvalid = result.valid;
fieldError = result.msg;
} else {
// EMAIL VALIDITY
if (email) {
var limit = typeof input.attr('limit') == 'undefined' ? 1 : input.attr('limit');
var config = {
emails: val,
limit: limit
};
var result = _trimAndCheckUniqueEmails(config); // EXPECTED RESPONSE {emails: emails, invalidemails: invalidemails, toomany: toomany}
var emails = result.emails;
var invalidemails = result.invalidemails;
var toomany = result.toomany;
// PUT VALIDATED VALUE BACK IN THE FIELD FOR DISPLAY
input.val(emails);
// UPDATE THE FORMDATA VALUE
formdata[key] = emails;
if (toomany) {
fieldvalid = false;
fieldError += ls.text_error_emails + ' (' + ls.text_error_emailslimit + ' ' + limit + ')';
};
if(invalidemails.length > 0) {
// IF IT'S ALREADY TOO MANY, APPEND EXTRA ERROR AFTER BR
if (fieldError.length > 0) { fieldError += '
' };
fieldvalid = false;
var invalids = '';
$.each(invalidemails, function (i, email) {
invalids += '
' + fieldError + '
' + invalidEmailList); } }) if (!valid) { //console.log('FORM'); var firstinvalid = invalidfields[0]; var parent = firstinvalid.closest('.tabcontent'); var form = firstinvalid.closest('form'); if(parentModal.length > 0) { parentModal.unmask(); parentModal.addClass('shake'); setTimeout(function(){ parentModal.removeClass('shake'); }, 500); } if (parent.length > 0) { var parentid = parent.attr('id'); var ullia = $('ul li a[href="#' + parentid + '"]', form); var ul = ullia.closest('ul'); var dis = ul.hasClass('disabled'); // WORK OUT WHETHER TO SHOW/HIDE THE CORRECT STEP BUTTONS var li = ullia.closest('li'); var liindex = li.index() + 1; var licount = $('li', ul).length; var prev = $('.button.prev', form); var next = $('.button.next', form); var finish = $('.button.finish', form); if(liindex == licount) { // LAST STEP - SHOW PREV AND FINISH prev.show(); next.hide(); finish.show(); } else { if(liindex == 1) { // FIRST STEP - SHOW NEXT prev.hide(); next.show(); finish.hide(); } else { // MIDDLE STEP - SHOW PREV AND NEXT prev.show(); next.show(); finish.hide(); } }; // SHOW CORRECT TAB AND TABCONTENT ul.removeClass('disabled'); ullia.trigger('click'); if (dis) { ul.addClass('disabled') }; }; //console.log('INVALID FIELDS: ', invalidfields) }; _callModalPixelFix(form); return valid; }; var _callModalPixelFix = function(form) { if(form && form.length > 0) { var parentModal = form.closest('.wrjs_modal'); if(parentModal.length > 0) { var wrjsModalId = parentModal.attr('wrjs_modal_id'); if(wrjs.get(wrjsModalId)){ wrjs.get(wrjsModalId).pixelFix(); } }; }; }; var _markFieldInvalid = function(selector, str) { var input = $(selector); var name = input.attr('name'); var row = input.closest('.form-row'); // REMOVE PREVIOUS ERROR MESSAGE $('.error', row).remove(); // ADD ERROR STATE row.addClass('fielderror'); var parent = input.parent(); parent.append('' + str + '
') }; // *********************************************************** // PUBLIC // *********************************************************** var publicFunctions = { isFormValid: _isFormValid, isEmailValid: _isEmailValid, isURLValid: _isURLValid, getFormData: _getFormData, markFieldInvalid: _markFieldInvalid }; // *********************************************************** // INIT // *********************************************************** $.extend(wrjs.utils.form, publicFunctions); _init(); })()