From 07ff2d0f44d07bcca830f020e72ae2389a909f4f Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Tue, 5 May 2020 14:27:58 -0700 Subject: Add JS at front end for lists, and date support on backend --- bh20simplewebuploader/static/main.css | 15 +++++-- bh20simplewebuploader/static/main.js | 75 +++++++++++++++++++++++++++++++++++ 2 files changed, 86 insertions(+), 4 deletions(-) (limited to 'bh20simplewebuploader/static') diff --git a/bh20simplewebuploader/static/main.css b/bh20simplewebuploader/static/main.css index 57e29ef..80ee6b7 100644 --- a/bh20simplewebuploader/static/main.css +++ b/bh20simplewebuploader/static/main.css @@ -167,16 +167,19 @@ pre code { border: solid 1px black; } -.record { +.record, .record .field-group, .record .field-group .field { display: flex; flex-direction: column; + -webkit-column-break-inside: avoid; /* Chrome, Safari, Opera */ + page-break-inside: avoid; /* Firefox */ + break-inside: avoid; +} + +.record { border: solid 1px #808080; padding: 1em; background: #F8F8F8; margin-bottom: 1em; - -webkit-column-break-inside: avoid; /* Chrome, Safari, Opera */ - page-break-inside: avoid; /* Firefox */ - break-inside: avoid; } .record label { @@ -184,6 +187,10 @@ pre code { margin-top: 10px; } +.hidden { + display: none; +} + .search-section { display: flex; justify-content: space-between; diff --git a/bh20simplewebuploader/static/main.js b/bh20simplewebuploader/static/main.js index 96199a0..a67d3df 100644 --- a/bh20simplewebuploader/static/main.js +++ b/bh20simplewebuploader/static/main.js @@ -45,3 +45,78 @@ function displayForm() { } fillFormSpot.classList.add("invisible"); } + +/** + * 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('hidden') +} + +/** + * Remove the last form field from the group button is part of. + */ +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) + } + + 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('hidden') + } +} + +// 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) +} + -- cgit v1.2.3 From 90bd12eba8aa938c4b2b40f24f716494fdc2f958 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Tue, 5 May 2020 14:40:07 -0700 Subject: Use invisible class instead of hidden class --- bh20simplewebuploader/static/main.css | 4 ---- bh20simplewebuploader/static/main.js | 4 ++-- bh20simplewebuploader/templates/form.html | 20 ++++++++++---------- 3 files changed, 12 insertions(+), 16 deletions(-) (limited to 'bh20simplewebuploader/static') diff --git a/bh20simplewebuploader/static/main.css b/bh20simplewebuploader/static/main.css index 80ee6b7..5c3d568 100644 --- a/bh20simplewebuploader/static/main.css +++ b/bh20simplewebuploader/static/main.css @@ -187,10 +187,6 @@ pre code { margin-top: 10px; } -.hidden { - display: none; -} - .search-section { display: flex; justify-content: space-between; diff --git a/bh20simplewebuploader/static/main.js b/bh20simplewebuploader/static/main.js index a67d3df..6a1daa6 100644 --- a/bh20simplewebuploader/static/main.js +++ b/bh20simplewebuploader/static/main.js @@ -86,7 +86,7 @@ function addField(e) { fieldGroup.insertBefore(newField, minusButton) // Enable the minus button - minusButton.classList.remove('hidden') + minusButton.classList.remove('invisible') } /** @@ -108,7 +108,7 @@ function removeField(e) { 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('hidden') + this.classList.add('invisible') } } diff --git a/bh20simplewebuploader/templates/form.html b/bh20simplewebuploader/templates/form.html index cea444c..ed4c9fb 100644 --- a/bh20simplewebuploader/templates/form.html +++ b/bh20simplewebuploader/templates/form.html @@ -95,13 +95,13 @@ Make sure the metadata has submitter attribution details.
-
-
- -
- -
-
+
+
+ +
+ +
+
@@ -140,7 +140,7 @@ {% endif %} {% if record['list'] %} - + {% endif %} @@ -153,8 +153,8 @@ - - + +
-- cgit v1.2.3 From fa04ea5388a46746bc219e9bd4adef1d973b9d19 Mon Sep 17 00:00:00 2001 From: Adam Novak Date: Tue, 5 May 2020 14:51:51 -0700 Subject: Add back necessary form-swapping javascript This partially reverts 03cbed808805ccdbff639eaa67e8f8b26c7275b3. Unless we actually take the inactive form fields out of the form in the DOM, their "required" attributes will prevent form submission. We can't just hide them. --- bh20simplewebuploader/static/main.css | 7 ---- bh20simplewebuploader/static/main.js | 57 ++++++++++++++++++++++++++----- bh20simplewebuploader/templates/form.html | 5 ++- 3 files changed, 50 insertions(+), 19 deletions(-) (limited to 'bh20simplewebuploader/static') diff --git a/bh20simplewebuploader/static/main.css b/bh20simplewebuploader/static/main.css index 5c3d568..c881253 100644 --- a/bh20simplewebuploader/static/main.css +++ b/bh20simplewebuploader/static/main.css @@ -235,13 +235,6 @@ footer { .sponsors img { width: 100%; } -.metadata input#metadata_upload:checked ~ #metadata_upload_form_spot { - display: block; -} - -.metadata input#metadata_upload ~ #metadata_upload_form_spot { - display: none; -} .loader { display: block; diff --git a/bh20simplewebuploader/static/main.js b/bh20simplewebuploader/static/main.js index 6a1daa6..56213fa 100644 --- a/bh20simplewebuploader/static/main.js +++ b/bh20simplewebuploader/static/main.js @@ -34,18 +34,57 @@ let fetchAllaccessions = () => { fetchAPI("/api/getAllaccessions"); }; -/** - * Show form if checked +/* + * 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 fillFormSpot = document.getElementById('metadata_fill_form_spot'); -function displayForm() { - if (document.getElementById('metadata_form').checked) { - fillFormSpot.classList.remove("invisible"); - return; - } - fillFormSpot.classList.add("invisible"); + +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. */ diff --git a/bh20simplewebuploader/templates/form.html b/bh20simplewebuploader/templates/form.html index ed4c9fb..1bbf515 100644 --- a/bh20simplewebuploader/templates/form.html +++ b/bh20simplewebuploader/templates/form.html @@ -87,9 +87,9 @@

- + - +
Make sure the metadata has submitter attribution details. @@ -153,7 +153,6 @@
- -- cgit v1.2.3