diff options
author | Pjotr Prins | 2020-05-06 09:06:35 -0500 |
---|---|---|
committer | GitHub | 2020-05-06 09:06:35 -0500 |
commit | 6b4c3697ef59324ef5489c46ed9b1f8a101754d1 (patch) | |
tree | 12ca85281091879b67741b02d1235151b98167f4 /bh20simplewebuploader/static/main.js | |
parent | b6d846b5de6c67b28adab1fa520953115a1a1e30 (diff) | |
parent | fa04ea5388a46746bc219e9bd4adef1d973b9d19 (diff) | |
download | bh20-seq-resource-6b4c3697ef59324ef5489c46ed9b1f8a101754d1.tar.gz bh20-seq-resource-6b4c3697ef59324ef5489c46ed9b1f8a101754d1.tar.lz bh20-seq-resource-6b4c3697ef59324ef5489c46ed9b1f8a101754d1.zip |
Merge pull request #50 from adamnovak/upload-lists
Add support for lists in the web uploader
Diffstat (limited to 'bh20simplewebuploader/static/main.js')
-rw-r--r-- | bh20simplewebuploader/static/main.js | 128 |
1 files changed, 121 insertions, 7 deletions
diff --git a/bh20simplewebuploader/static/main.js b/bh20simplewebuploader/static/main.js index 96199a0..56213fa 100644 --- a/bh20simplewebuploader/static/main.js +++ b/bh20simplewebuploader/static/main.js @@ -34,14 +34,128 @@ let fetchAllaccessions = () => { fetchAPI("/api/getAllaccessions"); }; +/* + * Make sure that only one of the manual metadata entry and metadata upload + * form components is *actually* a child of the form element in the DOM. + * + * Because both make use of the "required" attribute, we can't get away with + * just hiding the one we don't want the user to fill in. The hidden part will + * still have possibly empty required fields and (some) browsers will + * blocksubmission because of it. Moreover, the data (including file uploads) + * from the hidden elements will still be sent to the server, which the user + * may not expect. + */ + +let uploadForm = document.getElementById('metadata_upload_form') +let uploadFormSpot = document.getElementById('metadata_upload_form_spot') +let fillForm = document.getElementById('metadata_fill_form') +let fillFormSpot = document.getElementById('metadata_fill_form_spot') + +function setUploadMode() { + // Make the upload form the one in use. + uploadFormSpot.appendChild(uploadForm) + // Remove the upload form from the DOM so its required-ness does not block submission. + fillFormSpot.removeChild(fillForm) +} + +function setFillMode() { + // Make the fillable form the one in use + uploadFormSpot.removeChild(uploadForm) + // Remove the fillable form from the DOM so its required-ness does not block submission. + fillFormSpot.appendChild(fillForm) +} + +function setMode() { + // Pick mode based on radio + if (document.getElementById('metadata_upload').checked) { + setUploadMode() + } else { + setFillMode() + } +} + +/* + * Machinery for variable-length lists of input items. + */ + +// Start in mode appropriate to selected form item. +// It is important that we run this code when the page starts! The browser may +// have set the radio button to whatever the state was on last page load, +// instead of the default state, without raising an event, and we have to +// handle that. +setMode() + +/** + * Add another form field to the group this button is part of. + */ +function addField(e) { + // Find our parent field-group div + let fieldGroup = this.parentElement + + // Get its keypath + let keypath = fieldGroup.dataset.keypath + + // Find its last field child + let existingFields = fieldGroup.getElementsByClassName('field') + let templateField = existingFields[existingFields.length - 1] + + // Get its number + let fieldNumber = templateField.dataset.number + + // Duplicate it + let newField = templateField.cloneNode(true) + + // Increment the number and use the keypath and number to set IDs and cross + // references. + // TODO: Heavily dependent on the form field HTML. Maybe we want custom + // elements for the labeled controlsd that know how to be list items? + fieldNumber++ + newField.dataset.number = fieldNumber + let newID = keypath + '[' + fieldNumber + ']' + let newControl = newField.getElementsByClassName('control')[0] + newControl.id = newID + newControl.setAttribute('name', newID) + let newLabel = newField.getElementsByTagName('label')[0] + newLabel.setAttribute('for', newID) + + // Find the minus button + let minusButton = fieldGroup.getElementsByClassName('remove-field')[0] + + // Put new field as a child before the minus button + fieldGroup.insertBefore(newField, minusButton) + + // Enable the minus button + minusButton.classList.remove('invisible') +} + /** - * Show form if checked + * Remove the last form field from the group button is part of. */ -let fillFormSpot = document.getElementById('metadata_fill_form_spot'); -function displayForm() { - if (document.getElementById('metadata_form').checked) { - fillFormSpot.classList.remove("invisible"); - return; +function removeField(e) { + // Find our parent field-group div + let fieldGroup = this.parentElement + + // Find its field children + let existingFields = fieldGroup.getElementsByClassName('field') + + if (existingFields.length > 1) { + // There is a last field we can safely remove. + let lastField = existingFields[existingFields.length - 1] + fieldGroup.removeChild(lastField) } - fillFormSpot.classList.add("invisible"); + + if (existingFields.length <= 1) { + // Collection auto-updates. Now there's only one element. Don't let the + // user remove it. If they don't want it, they can leave it empty. + this.classList.add('invisible') + } +} + +// Find all the add and remove field buttons and hook up the listeners. +for (let button of document.getElementsByClassName('add-field')) { + button.addEventListener('click', addField) } +for (let button of document.getElementsByClassName('remove-field')) { + button.addEventListener('click', removeField) +} + |