(function() { var FORM_ID_ATTR = "data-form-id"; var FORM_CLASS = "form-builder"; var SAVE_BUTTON_CLASS = "form-builder-save"; var CAPTCHA_PARAM_KEY = "g-recaptcha-response"; var formCache = {}; function Form(id, $element) { this.id = id; this.$element = $element; formCache[this.id] = this; this.actionUrl = ""; this.captchaEnabled = false; this.confirmMessage = null; this.modified = false; this.recentlySubmitted = false; this.onceSubmitted = false; this.saveResponseDataCallbacks = []; } Form.prototype.getSaveButtons = function() { return $("." + SAVE_BUTTON_CLASS + "[" + FORM_ID_ATTR + '="' + this.id + '"]'); }; Form.prototype.save = function() { var form = this; if(form.recentlySubmitted || (form.confirmMessage && !confirm(form.confirmMessage))) { return $.Deferred().reject().promise(); } form.onceSubmitted = true; form.recentlySubmitted = true; setTimeout(function() { form.recentlySubmitted = false; }, 2000); var loadIcons = form.getSaveButtons().find("i"); loadIcons.show(); function getFormData(additionalParams) { var dataArray = form.$element.serializeArray(); var data = {}; dataArray.forEach(function(item) { data[item.name] = item.value; }); //Special case to ensure checkboxes are booleans form.$element.find("input[type=checkbox]").each(function() { data[this.name] = $(this).is(":checked") ? 1 : 0; }); //Add in additional params if(additionalParams) { for(var key in additionalParams) { if(additionalParams.hasOwnProperty(key)) { data[key] = additionalParams[key]; } } } return data; } function sendFormData(additionalParams) { return $.post(form.actionUrl, getFormData(additionalParams)) .then(function(response) { form.modified = false; return response; }) .always(function(response) { loadIcons.hide(); return response; }); } if(form.captchaEnabled) { return ReCAPTCHA.challenge().then(function(response) { var params = {}; params[CAPTCHA_PARAM_KEY] = response; return sendFormData(params); }); } else { return sendFormData(); } } Form.prototype.onDefaultSaveResponseData = function(callback) { this.saveResponseDataCallbacks.push(callback); } $(document).ready(function() { tryFocusFirstFormInput(); $("form." + FORM_CLASS).each(function() { var $form = $(this); var form = new Form($form.attr("id"), $form); form.actionUrl = $form.attr("action"); form.confirmMessage = $form.attr("data-confirm-message"); form.captchaEnabled = !!$form.attr("data-captcha-enabled"); $form.on("change", "input, select", function() { form.modified = true; }); form.getSaveButtons().find("i").hide(); form.getSaveButtons().click(function(e) { var redirectTo = $(this).attr("data-redirect-to"); var redirectMessage = $(this).attr("data-redirect-message"); if(!redirectTo) { redirectTo = $form.attr("data-redirect-to"); redirectMessage = $form.attr("data-redirect-message"); } var allowUnnecessarySubmit = !!$(this).attr("data-allow-unnecessary-submit"); saveFormAndHandleResult(redirectTo, redirectMessage, allowUnnecessarySubmit); e.preventDefault(); }); $form.submit(function(e) { var redirectTo = $(this).attr("data-redirect-to"); var redirectMessage = $(this).attr("data-redirect-message"); var allowUnnecessarySubmit = !!$(this).attr("data-allow-unnecessary-submit"); saveFormAndHandleResult(redirectTo, redirectMessage, allowUnnecessarySubmit); e.preventDefault(); }); $(window).on("beforeunload", function(e) { if(form.modified) { var message = "There is unsaved information on the page. Are you sure you want to leave? Unsaved changes will be lost."; e.returnValue = message; return message; } }); function saveFormAndHandleResult(redirectTo, redirectMessage, allowUnnecessarySubmit) { if(!form.modified && !allowUnnecessarySubmit && form.onceSubmitted) { doRedirect(redirectTo, redirectMessage); return; } var responseMan; form.save().always(function(response) { var responseData = undefined; if(response) { responseMan = new ResponseMan(response); responseData = responseMan.handle(); } for (var i = 0; i < form.saveResponseDataCallbacks.length; i++) { form.saveResponseDataCallbacks[i](responseData); } }).then(function() { if(responseMan) { var hasErrors = responseMan.errors.length > 0; if(!hasErrors) { doRedirect(redirectTo, redirectMessage); } } }); } function doRedirect(redirectTo, redirectMessage) { if(redirectTo) { if(redirectMessage) { kindlyRedirect(redirectMessage, redirectTo); } else { window.location.href = redirectTo; } } } }); }); function tryFocusFirstFormInput() { try { var $firstInput = $('form *:input[type!="hidden"][type!="submit"]').first(); $firstInput.focus(); var longerThanLength = $firstInput.val().length * 2; $firstInput[0].setSelectionRange(longerThanLength, longerThanLength); } catch(e) { // suppress error } } window.FormBuilder = {}; FormBuilder.getFormById = function(id) { return formCache[id]; } })();