/** * @author Rafael Ostertag <rafael.ostertag@math.uzh.ch> */ /* global $ */ if (!QfqNS) { var QfqNS = {}; } (function (n) { 'use strict'; n.QfqForm = function (formId, submitTo, deleteUrl) { this.formId = formId; this.submitTo = submitTo; this.deleteUrl = deleteUrl; this.form = new n.Form(this.formId); this.bsTabs = null; this.getSaveButton().addClass("disabled").attr("disabled", "disabled"); this.form.addChangeHandler(this.changeHandler.bind(this)); this.form.addResetHandler(this.resetHandler.bind(this)); this.form.addSubmitSuccessHandler(this.submitSuccessDispatcher.bind(this)); this.form.addSubmitFailureHandler(this.submitFailureHandler.bind(this)); this.getSaveButton().click(this.handleSaveClick.bind(this)); this.getCloseButton().click(this.handleCloseClick.bind(this)); this.getNewButton().click(this.handleNewClick.bind(this)); this.getDeleteButton().click(this.handleDeleteClick.bind(this)); }; n.QfqForm.prototype.setBsTabs = function (bsTabs) { this.bsTabs = bsTabs; }; /** * @private */ n.QfqForm.prototype.handleSaveClick = function () { QfqNS.Log.debug("save click"); // First, remove all validation states, in case a previous submit has set a validation state, thus we're not // stockpiling them. this.clearAllValidationStates(); this.form.submitTo(this.submitTo); }; /** * @private */ n.QfqForm.prototype.handleCloseClick = function () { if (this.form.getFormChanged()) { var alert = new QfqNS.Alert("You have unsaved changes. Do you want to close?", "warning", "yesnosave"); var that = this; alert.addSaveButtonHandler(function () { that.form.submitTo(that.submitTo); }); alert.addOkButtonHandler(function () { window.history.back(); }); alert.show(); } else { window.history.back(); } }; /** * @private */ n.QfqForm.prototype.handleNewClick = function () { QfqNS.Log.debug("new click"); }; /** * @private */ n.QfqForm.prototype.handleDeleteClick = function () { QfqNS.Log.debug("delete click"); $.post(this.deleteUrl) .done(this.ajaxDeleteSuccessDispatcher.bind(this)) .fail(this.ajaxDeleteFailureHandler.bind(this)); }; /** * * @param data * @param textStatus * @param jqXHR * * @private */ n.QfqForm.prototype.ajaxDeleteSuccessDispatcher = function (data, textStatus, jqXHR) { if (!data.status) { throw new Error("No 'status' property 'data'"); } switch (data.status) { case "error": this.handleLogicDeleteError(data); break; case "success": this.handleDeleteSuccess(data); break; default: throw new Error("Status '" + data.status + "' unknown."); } }; /** * * @param data * * @private */ n.QfqForm.prototype.handleDeleteSuccess = function (data) { if (!data.redirect || data.redirect === "client") { window.history.back(); return; } if (data.redirect === "no") { var alert = new QfqNS.Alert("redirect=='no' not allowed", "error"); alert.show(); return; } if (data.redirect === "url" || data['redirect-url']) { window.location = data['redirect-url']; return; } }; /** * * @param data * * @private */ n.QfqForm.prototype.handleLogicDeleteError = function (data) { if (!data.message) { throw Error("Status is 'error' but required 'message' attribute is missing."); } var alert = new QfqNS.Alert(data.message, "error"); alert.show(); }; /** * * @param form {QfqNS.QfqForm} * * @private */ n.QfqForm.prototype.changeHandler = function (form) { this.getSaveButton().removeClass("disabled"); this.getSaveButton().addClass("alert-warning"); this.getSaveButton().removeAttr("disabled"); }; /** * * @param form {QfqNS.QfqForm} * * @private */ n.QfqForm.prototype.resetHandler = function (form) { this.getSaveButton().removeClass("alert-warning"); this.getSaveButton().addClass("disabled"); this.getSaveButton().attr("disabled", "disabled"); }; /** * * @returns {jQuery|HTMLElement} * * @private */ n.QfqForm.prototype.getSaveButton = function () { return $("#save-button"); }; /** * * @returns {jQuery|HTMLElement} * * @private */ n.QfqForm.prototype.getCloseButton = function () { return $("#close-button"); }; /** * * @returns {jQuery|HTMLElement} * * @private */ n.QfqForm.prototype.getDeleteButton = function () { return $("#delete-button"); }; /** * * @returns {jQuery|HTMLElement} * * @private */ n.QfqForm.prototype.getNewButton = function () { return $("#new-button"); }; /** * * @param jqXHR * @param textStatus * @param errorThrown * * @private */ n.QfqForm.prototype.submitFailureHandler = function (form, textStatus, jqXHR, errorThrown) { this.showAjaxError(errorThrown); }; /** * * @param jqXHR * @param textStatus * @param errorThrown * * @private */ n.QfqForm.prototype.ajaxDeleteFailureHandler = function (jqXHR, textStatus, errorThrown) { this.showAjaxError(errorThrown); }; n.QfqForm.prototype.showAjaxError = function (errorThrown) { var alert = new QfqNS.Alert("Error:<br> " + errorThrown, "error"); alert.show(); }; /** * @private */ n.QfqForm.prototype.submitSuccessDispatcher = function (form, data, textStatus) { if (!data.status) { throw new Error("No 'status' property in 'data'"); } switch (data.status) { case "error": this.handleLogicSubmitError(form, data); break; case "success": this.handleSubmitSuccess(form, data); break; default: throw new Error("Status '" + data.status + "' unknown."); } }; /** * * @param form * @param data * * @private */ n.QfqForm.prototype.handleLogicSubmitError = function (form, data) { if (!data.message) { throw Error("Status is 'error' but required 'message' attribute is missing."); } var alert = new QfqNS.Alert(data.message, "error"); alert.show(); if (data["field-name"] && this.bsTabs) { var tabId = this.bsTabs.getContainingTabIdForFormControl(data["field-name"]); if (tabId) { this.bsTabs.activateTab(tabId); } this.setValidationState(data["field-name"], "error"); this.setHelpBlockValidationMessage(data["field-name"], data["field-message"]); } }; /** * * @param form * @param data * * @private */ n.QfqForm.prototype.handleSubmitSuccess = function (form, data) { QfqNS.Log.debug('Reset form state'); form.resetFormChanged(); if (!data.redirect || data.redirect === "no") { if (data.message) { var alert = new QfqNS.Alert(data.message); alert.timeout = 3000; alert.show(); } return; } if (data.redirect === "client") { window.history.back(); return; } if (data.redirect === "url" || data['redirect-url']) { window.location = data['redirect-url']; return; } }; n.QfqForm.prototype.getFormGroupByControlName = function (formControlName) { var $formControl = $("[name=" + formControlName + "]"); if ($formControl.length === 0) { QfqNS.Log.debug("QfqForm.setValidationState(): unable to find form control with name '" + formControlName + "'"); return null; } var iterator = $formControl[0]; while (iterator !== null) { var $iterator = $(iterator); if ($iterator.hasClass('form-group')) { return $iterator; } iterator = iterator.parentElement; } return null; }; n.QfqForm.prototype.setValidationState = function (formControlName, state) { var $formGroup = this.getFormGroupByControlName(formControlName); if ($formGroup) { $formGroup.addClass("has-" + state); } }; n.QfqForm.prototype.resetValidationState = function (formControlName) { var $formGroup = this.getFormGroupByControlName(formControlName); $formGroup.removeClass("has-warning"); $formGroup.removeClass("has-error"); $formGroup.removeClass("has-success"); }; n.QfqForm.prototype.clearAllValidationStates = function () { $('.has-warning,.has-error,.has-success').removeClass("has-warning has-error has-success"); $('[data-qfq=validation-message]').remove(); }; n.QfqForm.prototype.setHelpBlockValidationMessage = function (formControlName, text) { var $formGroup = this.getFormGroupByControlName(formControlName); if (!$formGroup) { return; } var $helpBlockColumn; var $formGroupSubDivs = $formGroup.find("div"); if ($formGroupSubDivs.length < 3) { $helpBlockColumn = $("<div>").addClass("col-md-4"); $formGroup.append($helpBlockColumn); } else { $helpBlockColumn = $($formGroupSubDivs[2]); } $helpBlockColumn.append( $("<p>") .addClass("help-block") .attr("data-qfq", "validation-message") .append(text) ); }; })(QfqNS);