diff --git a/productMods/edit/forms/js/customForm.js b/productMods/edit/forms/js/customForm.js
index 95d0233f..41cc2f0d 100644
--- a/productMods/edit/forms/js/customForm.js
+++ b/productMods/edit/forms/js/customForm.js
@@ -1,133 +1,246 @@
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
+/* ADD new property form
+/* Step 1: Initial step, with choice to select existing or add new secondary individual.
+ * Displays:
+ * - On page load, unless there are validation error messages in the form
+ * - if there are validation error messages in the form, we are returning from a failed
+ * submission, and will go directly to view 2 to display the error messages.
+ * - After cancelling out of step 2
+ *
+ * Step 2: Main data entry step
+ * Displays:
+ * - On page load after an attempted submission that fails validation
+ * - After clicking button or add new link in view 1
+ * Has three view variations:
+ * - Select an existing secondary individual view
+ * - Add new secondary individual view
+ * - Combined view, if we are returning from a failed validation and can't determine
+ * which variant of view 2 we had submitted the form from. Contains the select
+ * existing element plus the add new link.
+ *
+ * EDIT existing property form
+ * Looks like add form step 2 except shows add new link
+ * Has same three view variants as step 2 add form
+ *
+ */
+
var customForm = {
onLoad: function() {
- // Create references to form elements.
- // NB must be done after the elements have been loaded.
+ this.initObjects();
+ this.adjustForJs();
+ this.initForm();
+ },
+
+ // On page load, create references within the customForm scope to DOM elements.
+ // NB These must be assigned after the elements have been loaded onto the page.
+ initObjects: function() {
- this.form = $('#content form'),
- this.button = $('#submit'),
- this.requiredLegend = $('#requiredLegend'),
+ this.form = $('#content form');
+ this.button = $('#submit');
+ this.requiredLegend = $('#requiredLegend');
// These may need to be changed to classes rather than ids, if there are
// multiple sets of divs to show/hide during the workflow.
- this.addNewLink = $('#addNewLink'),
- this.existing = $('#existing'),
- this.addNew = $('#new'),
- this.entry = $('#entry'),
- this.existingOrNew = $('#existingOrNew'),
+ this.addNewLink = $('#addNewLink');
+ this.existing = $('#existing');
+ this.addNew = $('#new');
+ this.entry = $('#entry');
+ this.existingOrNew = $('#existingOrNew');
- this.cancel = this.form.find('.cancel'),
- this.requiredHints = this.form.find('.requiredHint'),
+ this.cancel = this.form.find('.cancel');
+ this.requiredHints = this.form.find('.requiredHint');
// Read values used to control display
- this.editType = $("input[name='editType']").val(),
- this.entryType = $("input[name='entryType']").val().capitalize(),
+ this.editType = $("input[name='editType']").val();
+ this.entryType = $("input[name='entryType']").val().capitalize();
this.newType = $("input[name='newType']").val().capitalize();
-
- this.adjustForJs();
-
- if (this.editType == 'add') { //adding a new entry
- this.initAddForm();
-
- } else { // editing existing entry
- this.initEditForm();
- }
},
// On page load, make changes to the non-Javascript version for the Javascript version.
- // These are features that will not change in the Javascript version.
+ // These are features that will NOT CHANGE throughout the workflow of the Javascript version..
adjustForJs: function() {
- this.existingOrNew.hide();
-
- var selectExistingLabel = $('#existing label');
- selectExistingLabel.html(selectExistingLabel.html().replace('Select Existing ', ''));
-
- },
-
- // Reset add form to initial state (step 1)
- // Should only be needed after returning to step 1 from step 2,
- // but sometimes seems to be needed on page load as well, so call it from initAddForm()
- resetAddForm: function() {
- // Clear all form data and error messages
- $('input:text').val('');
- $('.error').text('');
+ var selectExistingLabel = $('#existing label');
+ selectExistingLabel.html(selectExistingLabel.html().replace(/Select (Existing )?/, ''));
- // Remove previously bound event handlers
- this.cancel.unbind('click');
- this.button.unbind('click');
- this.addNewLink.unbind('click');
+ this.existingOrNew.hide();
+ },
+
+ initForm: function() {
- this.toggleRequiredHints('remove', this.addNew, this.existing);
+ //Adding a new entry
+ if (this.editType == 'add') {
+ this.initAddForm();
+ // Editing an existing entry
+ } else {
+ this.initEditForm();
+ }
+ },
+
+ /***** ADD form *****/
+
+ // Set up add form on page load, or when returning to initial state from step 2
+ initAddForm: function() {
+
+ // If there are validation errors on the page, we're returning from
+ // an attempted submission that failed validation, and we need to go
+ // directly to step 2.
+ if (this.findValidationErrors()) {
+ this.doAddFormStep2();
+ } else {
+ this.doAddFormStep1();
+ }
+
+ },
+
+ // Reset add form to initial state (step 1) after cancelling out of step 2
+ resetAddFormToStep1: function() {
+
+ this.resetForm();
+ this.doAddFormStep1();
},
- // Set up add form on page load, or when returning to initial state
- initAddForm: function() {
+ // Set up the add form for step 1
+ doAddFormStep1: function() {
- this.resetAddForm();
-
- // Step 1 of the form
- this.addNewLink.show();
this.existing.show();
+ this.addNewLink.show();
this.addNew.hide();
this.entry.hide();
this.requiredLegend.hide();
this.button.val('Continue');
- // Assign event listeners
-
- // button => step 2a
+ // Assign event listeners
+ //this.button.unbind('click'); // RY *** Don't need this if we've done a reset
this.button.bind('click', function() {
- customForm.entry.show();
- customForm.showFields(customForm.existing);
- customForm.addNewLink.hide();
- customForm.requiredLegend.show();
-
- $(this).val('Create ' + customForm.entryType);
- $(this).unbind('click');
-
- customForm.doCancel();
-
+ customForm.doAddFormStep2SelectExisting();
return false;
});
- // add new link => step 2b
+ //this.addNewLink.unbind('click'); // RY *** Don't need this if we've done a reset
this.addNewLink.bind('click', function() {
- $(this).hide();
- customForm.existing.hide();
- customForm.showFields(customForm.addNew);
- customForm.entry.show();
- customForm.requiredLegend.show();
-
- customForm.button.val('Create ' + customForm.entryType + ' & ' + customForm.newType);
- customForm.button.unbind('click');
-
- customForm.doCancel();
+ customForm.doAddFormStep2AddNew();
});
},
+ // Set up form when returning directly to step 2, such as after validation errors
+ // on the form submission.
+ doAddFormStep2: function() {
+
+ // If possible, determine which view of the form we were on
+ var existingInputs = this.existing.find(':input'),
+ existingInputsLen = existingInputs.length,
+ addNewInputs = this.addNew.find(':input'),
+ addNewInputsLen = addNewInputs.length,
+ input,
+ i,
+ fn = null;
+
+ // If a value was entered in the addNew section, go back to the addNew view
+ for (i = 0; i < addNewInputsLen; i++) {
+ input = $(addNewInputs[i]);
+ if (input.val() != '') {
+ fn = this.doAddFormStep2AddNew;
+ break;
+ }
+ }
+
+ // If a value was selected in the existing section, go back to the existing view
+ if (fn === null) {
+ for (i = 0; i < existingInputsLen; i++) {
+ input = $(existingInputs[i]);
+ if (input.val() != '') {
+ fn = this.doAddFormStep2SelectExisting;
+ break;
+ }
+ }
+ }
+
+ // Otherwise, default to the combined view
+ // (same as view used to edit existing entry)
+ if (fn === null) {
+ fn = this.doAddFormStep2Combined;
+ }
+
+ fn.call();
+ },
+
+ // Step 2: selecting an existing individual
+ doAddFormStep2SelectExisting: function() {
+
+ // NB Use 'customForm' instead of 'this', because 'this'
+ // doesn't reference customForm when called from an event handler.
+ customForm.entry.show();
+ customForm.showFields(customForm.existing);
+ customForm.addNew.hide();
+ customForm.addNewLink.hide();
+ customForm.requiredLegend.show();
+
+ customForm.doButtonForStep2('Create ' + customForm.entryType);
+ customForm.doCancelForStep2();
+ },
+
+ // Step 2: adding a new individual
+ doAddFormStep2AddNew: function() {
+
+ // NB Use customForm instead of 'this', because 'this'
+ // doesn't reference customForm when called from an event handler.
+ customForm.addNewLink.hide();
+ customForm.existing.hide();
+ customForm.showFields(customForm.addNew);
+ customForm.entry.show();
+ customForm.requiredLegend.show();
+
+ customForm.doButtonForStep2('Create ' + customForm.entryType + ' & ' + customForm.newType);
+ customForm.doCancelForStep2();
+ },
+
+ // Step 2: combined view, when we are returning from validation errors and we
+ // can't determine which view of the form we had been on.
+ doAddFormStep2Combined: function() {
+
+ this.showCombinedView();
+ this.doAddNewLink();
+ this.doButtonForStep2('Create ' + this.newType);
+ this.doCancelForStep2();
+ },
+
+
+ /***** Edit form *****/
+
+ // RY Here we need logic for returning from validation errors, as in add form ********
initEditForm: function() {
- this.showFields(this.existing);
- this.addNewLink.show();
- this.addNew.hide();
- this.entry.show();
- this.requiredLegend.show();
+ this.showCombinedView();
+ this.doAddNewLink();
this.button.val('Save Changes');
-
- this.addNewLink.bind('click', function() {
- $(this).hide();
- customForm.existing.hide();
- customForm.showFields(customForm.addNew);
-
- customForm.button.val('Create ' + customForm.newType + ' & Save Changes');
- });
+ // Cancel just takes us back to the individual page - no event listener needed
},
+ /***** Utilities *****/
+
+ unbindEventListeners: function() {
+ this.cancel.unbind('click');
+ this.button.unbind('click');
+ this.addNewLink.unbind('click');
+ },
+
+ clearFormData: function() {
+ this.form.find('input:text').val('');
+ this.form.find('select').val('');
+ this.form.find('textarea').val('');
+
+ // For now we can remove the error elements. Later we may include them in
+ // the markup, for customized positioning, in which case we will empty them
+ // but not remove them here. See findValidationErrors().
+ //this.form.find('.validationError').text('');
+ this.form.find('.validationError').remove();
+ },
+
// Add required hints to required fields in a list of elements.
// Use when the non-Javascript version should not show the required hint,
// because the field is not required in that version (e.g., it's one of two
@@ -138,9 +251,10 @@ var customForm = {
var labelText,
newLabelText,
- requiredHintText = ' *';
+ requiredHintText = ' *',
+ numArgs = arguments.length;
- for (var i = 1; i < arguments.length; i++) {
+ for (var i = 1; i < numArgs; i++) {
arguments[i].find('label.required').each(function() {
labelText = $(this).html();
newLabelText = action == 'add' ? labelText + requiredHintText :
@@ -155,13 +269,89 @@ var customForm = {
this.toggleRequiredHints('add', el);
},
+ hideFields: function(el) {
+ // Clear any input, so if we reshow the element the input won't still be there.
+ el.find('input:text').val('');
+ alert('here');
+ el.hide();
+ },
+
+
+ doButtonForStep2: function(text) {
+ customForm.button.unbind('click');
+ customForm.button.val(text);
+ },
+
// Add event listener to the cancel link in step 2
- doCancel: function() {
- this.cancel.unbind('click');
- this.cancel.bind('click', function() {
- customForm.initAddForm();
+ doCancelForStep2: function() {
+
+ customForm.cancel.unbind('click');
+ customForm.cancel.bind('click', function() {
+ customForm.resetAddFormToStep1();
return false;
});
+ },
+
+ doAddNewLink: function() {
+
+ this.addNewLink.unbind('click');
+ this.addNewLink.bind('click', function() {
+ $(this).hide();
+ customForm.hideFields(customForm.existing);
+ customForm.showFields(customForm.addNew);
+
+ customForm.button.val('Create ' + customForm.newType + ' & Save Changes');
+ });
+ },
+
+ // Return true iff there are validation errors on the form
+ findValidationErrors: function() {
+
+ return this.form.find('.validationError').length > 0;
+
+// RY For now, we just need to look for the presence of the error elements.
+// Later, however, we may generate empty error messages in the markup, for
+// customized positioning, in which case we need to look for whether they have
+// content. See clearFormData().
+// var foundErrors = false,
+// errors = this.form.find('.validationError'),
+// numErrors = errors.length,
+// i,
+// error;
+//
+// for (i = 0; foundErrors == false && i < numErrors; i++) {
+// error = errors[i];
+// if (error.html() != '') {
+// foundErrors = true;
+// }
+// }
+//
+// return foundErrors;
+ },
+
+ resetForm: function() {
+
+ // Clear all form data and error messages
+ this.clearFormData();
+
+ // Remove previously bound event handlers
+ this.unbindEventListeners();
+
+ // Remove required field hints
+ this.toggleRequiredHints('remove', this.addNew, this.existing);
+ },
+
+ // This version of the form shows both the existing select and add new link.
+ // Used when loading edit form, and when returning from failed submission
+ // of add form when we can't determine which view was being used to make
+ // the submission.
+ showCombinedView: function() {
+
+ this.showFields(this.existing);
+ this.addNewLink.show();
+ this.addNew.hide();
+ this.entry.show();
+ this.requiredLegend.show();
}
};
diff --git a/productMods/templates/entity/positionShortView.jsp b/productMods/templates/entity/positionShortView.jsp
index 9496754f..019d8574 100644
--- a/productMods/templates/entity/positionShortView.jsp
+++ b/productMods/templates/entity/positionShortView.jsp
@@ -4,8 +4,6 @@
<%@ taglib uri="http://java.sun.com/jsp/jstl/functions" prefix="fn" %>
<%@ taglib uri="http://vitro.mannlib.cornell.edu/vitro/tags/StringProcessorTag" prefix="p" %>
-
-
<%-- individual is the OBJECT of the property referenced -- the Position, not the Person or Organization --%>