Commit 1ec88d8b authored by Rafael Ostertag's avatar Rafael Ostertag
Browse files

Implemented QfqForm.

parent ea51bb1e
......@@ -11,8 +11,11 @@ if (!QfqNS) {
(function (n) {
'use strict';
n.Alert = function (message) {
n.Alert = function (message, messageType, buttons) {
this.message = message;
this.messageType = messageType || "info";
this.buttons = buttons || "none";
this.$alertDiv = null;
this.shown = false;
// this.timeout < 1 means forever
......@@ -20,6 +23,10 @@ if (!QfqNS) {
this.fadeInDuration = 400;
this.fadeOutDuration = 400;
this.timerId = null;
this.userOkButtonHandlers = new QfqNS.Helper.FunctionList();
this.userCancelButtonHandlers = new QfqNS.Helper.FunctionList();
this.userSaveButtonHandlers = new QfqNS.Helper.FunctionList();
};
/**
......@@ -53,20 +60,115 @@ if (!QfqNS) {
$("#qfqAlertContainer").remove();
};
/**
* @private
*/
n.Alert.prototype.getAlertClassBasedOnMessageType = function () {
switch (this.messageType) {
case "warning":
return "alert-warning";
case "error":
return "alert-danger";
/* jshint -W086 */
default:
QfqNS.Log.warning("Message type '" + this.messageType + "' unknown. Use default type.");
case "info":
return "alert-success";
/* jshint +W086 */
}
};
/**
* @private
*/
n.Alert.prototype.getButtons = function () {
var buttons = null;
switch (this.buttons) {
case 'okcancel':
buttons = $("<div>")
.addClass("alert-buttons")
.append(
$("<a>")
.append("Ok")
.addClass("btn btn-default")
.click(this.okButtonHandler.bind(this))
)
.append(
$("<a>")
.append("Cancel")
.addClass("btn btn-default")
.click(this.cancelButtonHandler.bind(this))
);
return buttons;
case "yesno":
buttons = $("<div>")
.addClass("alert-buttons")
.append(
$("<a>")
.append("Yes")
.addClass("btn btn-default")
.click(this.okButtonHandler.bind(this))
)
.append(
$("<a>")
.append("No")
.addClass("btn btn-default")
.click(this.cancelButtonHandler.bind(this))
);
return buttons;
case "yesnosave":
buttons = $("<div>")
.addClass("alert-buttons")
.append(
$("<a>")
.append("Yes")
.addClass("btn btn-default")
.click(this.okButtonHandler.bind(this))
)
.append(
$("<a>")
.append("No")
.addClass("btn btn-default")
.click(this.cancelButtonHandler.bind(this))
)
.append(
$("<a>")
.append("Save & Close")
.addClass("btn btn-default")
.click(this.saveButtonHandler.bind(this))
)
;
return buttons;
/* jshint -W086 */
default:
QfqNS.Log.warning("Buttons '" + this.buttons + "' unknown. Use default buttons");
case "none":
break;
/* jshint +W086 */
}
return buttons;
};
n.Alert.prototype.show = function () {
if (this.shown) {
// We only allow showing once
return;
}
var $alertContainer = this.makeAlertContainerSingleton();
this.$alertDiv = $("<div>")
.addClass("alert")
.addClass("alert-success")
.addClass(this.getAlertClassBasedOnMessageType())
.attr("role", "alert")
.append(this.message)
.click(this.removeAlert.bind(this));
var buttons = this.getButtons();
if (buttons && this.timeout < 1) {
this.$alertDiv.append(buttons);
}
$alertContainer.append(this.$alertDiv);
this.$alertDiv.fadeIn(this.fadeInDuration, this.afterFadeIn.bind(this));
this.shown = true;
......@@ -74,6 +176,9 @@ if (!QfqNS) {
};
/**
* @private
*/
n.Alert.prototype.afterFadeIn = function () {
if (this.timeout > 0) {
this.timerId = window.setTimeout(this.removeAlert.bind(this), this.timeout);
......@@ -109,6 +214,49 @@ if (!QfqNS) {
};
n.Alert.prototype.addOkButtonHandler = function (handler) {
this.userOkButtonHandlers.addFunction(handler);
};
n.Alert.prototype.addCancelButtonHandler = function (handler) {
this.userCancelButtonHandlers.addFunction(handler);
};
n.Alert.prototype.addSaveButtonHandler = function (handler) {
this.userSaveButtonHandlers.addFunction(handler);
};
/**
*
* @param handler
*
* @private
*/
n.Alert.prototype.okButtonHandler = function (handler) {
this.userOkButtonHandlers.call(this);
};
/**
*
* @param handler
*
* @private
*/
n.Alert.prototype.saveButtonHandler = function (handler) {
this.userSaveButtonHandlers.call(this);
};
/**
*
* @param handler
*
* @private
*/
n.Alert.prototype.cancelButtonHandler = function (handler) {
this.userCancelButtonHandlers.call(this);
};
n.Alert.prototype.isShown = function () {
return this.shown;
};
......
......@@ -13,16 +13,17 @@ if (!QfqNS) {
n.Form = function (formId) {
this.formId = formId;
if (!document.forms[this.formId]) {
throw new Error("Form '" + formId + "' does not exist.");
}
this.formChanged = false;
this.userFormChangeHandlers = new QfqNS.Helper.FunctionList();
this.userResetHandlers = new QfqNS.Helper.FunctionList();
this.userSubmitSuccessHandlers = new QfqNS.Helper.FunctionList();
this.userSubmitFailureHandlers = new QfqNS.Helper.FunctionList();
if (!document.forms[this.formId]) {
throw new Error("Form '" + formId + "' does not exist.");
}
this.$form = $(document.forms[this.formId]);
this.$form.on("change", this.changeHandler.bind(this));
};
......
......@@ -11,18 +11,71 @@ if (!QfqNS) {
(function (n) {
'use strict';
n.QfqForm = function (formId) {
n.QfqForm = function (formId, submitTo) {
this.formId = formId;
this.submitTo = submitTo;
this.form = new n.Form(this.formId);
this.bsTabs = null;
this.getSaveButton().addClass("disabled");
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.saveHandler = null;
this.closeHandler = null;
this.deleteHandler = null;
this.newHandler = null;
this.form.addSubmitFailureHandler(this.submitFailureDispatcher.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");
};
......@@ -90,12 +143,26 @@ if (!QfqNS) {
return $("#new-button");
};
/**
*
* @param jqXHR
* @param textStatus
* @param errorThrown
*
* @private
*/
n.QfqForm.prototype.submitFailureDispatcher = function (jqXHR, textStatus, errorThrown) {
var alert = new QfqNS.Alert("Error:<br> " +
errorThrown.status + ": " + errorThrown.statusText, "error");
alert.show();
};
/**
* @private
*/
n.QfqForm.prototype.submitSuccessDispatcher = function (form, data, textStatus) {
if (!data.success) {
throw new Error("No 'success' property in 'data'");
if (!data.status) {
throw new Error("No 'status' property in 'data'");
}
switch (data.status) {
......@@ -111,12 +178,122 @@ if (!QfqNS) {
};
/**
*
* @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);
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);
\ No newline at end of file
......@@ -17,13 +17,15 @@ if (!QfqNS) {
{
tabsId: "qfqTabs",
formId: "qfqForm",
submitTo: "typo3conf/ext/qfq/qfq/api/save.php",
pageState: new QfqNS.PageState()
}, settings
);
this.bsTabs = new QfqNS.BSTabs(this.settings.tabsId);
try {
this.qfqForm = new QfqNS.QfqForm(this.settings.formId);
this.qfqForm = new QfqNS.QfqForm(this.settings.formId, this.settings.submitTo);
this.qfqForm.setBsTabs(this.bsTabs);
} catch (e) {
QfqNS.Log.error(e.message);
this.qfqForm = null;
......
{
"status": "success",
"message": "save sucessful",
"redirect": "client"
}
\ No newline at end of file
{
"status": "error",
"message": "save error",
"redirect": "no",
"field-name": "geburtstag",
"field-message": "Just a message"
}
\ No newline at end of file
{
"status": "error",
"message": "save error",
"redirect": "no",
"field-name": "matno",
"field-message": "Just a message"
}
\ No newline at end of file
{
"status": "success",
"message": "save sucessful",
"redirect": "no"
}
\ No newline at end of file
{
"status": "success",
"message": "save sucessful",
"redirect": "url",
"redirect-url": "http://www.disney.com"
}
\ No newline at end of file
......@@ -16,6 +16,15 @@
</head>
<body>
<select name="submitTo" id="submitTo">
<option>404 error</option>
<option>save_error_matno.json</option>
<option>save_error_geburtstag.json</option>
<option>save_no_redirect.json</option>
<option>save_server_redirect.json</option>
<option>save_client_redirect.json</option>
</select>
<div class="container-fluid">
<div class="row hidden-xs">
......@@ -179,7 +188,7 @@
<label for="personGeburtstag" class="control-label">Geburtstag</label>
</div>
<div class="col-md-6">
<input id="personGeburtstag" type="text" class="form-control">
<input id="personGeburtstag" type="text" class="form-control" name="geburtstag">
</div>
</div>
......@@ -194,7 +203,7 @@
<label for="personMat" class="control-label">Matrikelnummer</label>
</div>
<div class="col-md-6">
<input id="personMat" type="text" class="form-control">
<input id="personMat" type="text" class="form-control" name="matno">
</div>
<div class=" col-md-4">
......@@ -936,7 +945,13 @@
var qfqPage = new QfqNS.QfqPage({
tabsId: 'myTabs',
formId: 'myForm'
formId: 'myForm',
submitTo: $("#submitTo").val()
});
$("#submitTo").on("change", function (evt) {
qfqPage.settings.submitTo = 'api/' + $(evt.target).val();
qfqPage.qfqForm.submitTo = 'api/' + $(evt.target).val();
});
QfqNS.Log.level = 0;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment