From 998c3343631b9d38ecf96b211475ecf5e22c9155 Mon Sep 17 00:00:00 2001 From: j <13580441+gary02@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:32:22 +0800 Subject: [PATCH 1/5] Fix #309 -- handle submit buttons `form*` attributes --- .gitignore | 1 + s3file/static/s3file/js/s3file.js | 13 +++++++++++-- tests/test_forms.py | 2 ++ tests/testapp/templates/form.html | 2 +- tests/testapp/views.py | 2 ++ 5 files changed, 17 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index cfb6375..03ed1e4 100644 --- a/.gitignore +++ b/.gitignore @@ -59,3 +59,4 @@ target/ node_modules *.min.js +.python-version diff --git a/s3file/static/s3file/js/s3file.js b/s3file/static/s3file/js/s3file.js index ad88901..4969477 100644 --- a/s3file/static/s3file/js/s3file.js +++ b/s3file/static/s3file/js/s3file.js @@ -114,7 +114,7 @@ form.appendChild(submitInput) } - function uploadS3Inputs (form) { + function uploadS3Inputs (form, submitter) { window.uploading = 0 form.loaded = 0 form.total = 0 @@ -136,6 +136,15 @@ window.uploading += 1 uploadFiles(form, input, input.name) }) + // override form attributes with submit button attributes + if (submitter) { + form.action = submitter.getAttribute('formaction') || form.action + form.method = submitter.getAttribute('formmethod') || form.method + form.enctype = submitter.getAttribute('formEnctype') || form.enctype + form.formnovalidate = submitter.getAttribute('formnovalidate') || form.novalidate + form.target = submitter.getAttribute('formtarget') || form.target + } + waitForAllFiles(form) } @@ -147,7 +156,7 @@ forms.forEach(function (form) { form.addEventListener('submit', function (e) { e.preventDefault() - uploadS3Inputs(e.target) + uploadS3Inputs(e.target, e.submitter) }) var submitButtons = form.querySelectorAll('input[type=submit], button[type=submit]') Array.from(submitButtons).forEach(function (submitButton) { diff --git a/tests/test_forms.py b/tests/test_forms.py index 9f4ee39..2894ed1 100644 --- a/tests/test_forms.py +++ b/tests/test_forms.py @@ -187,6 +187,7 @@ def test_file_insert_submit_value( with wait_for_page_load(driver, timeout=10): save_button.click() assert "save" in driver.page_source + assert "formaction" not in driver.page_source driver.get(live_server + self.create_url) file_input = driver.find_element(By.XPATH, "//input[@name='file']") @@ -197,6 +198,7 @@ def test_file_insert_submit_value( save_button.click() assert "save_continue" in driver.page_source assert "continue_value" in driver.page_source + assert "formaction" in driver.page_source @pytest.mark.selenium def test_progress(self, driver, live_server, upload_file, freeze_upload_folder): diff --git a/tests/testapp/templates/form.html b/tests/testapp/templates/form.html index 7891e93..335723e 100644 --- a/tests/testapp/templates/form.html +++ b/tests/testapp/templates/form.html @@ -15,7 +15,7 @@ {% csrf_token %} {{ form }} - +
0% diff --git a/tests/testapp/views.py b/tests/testapp/views.py index 85e8f54..9b4ea17 100644 --- a/tests/testapp/views.py +++ b/tests/testapp/views.py @@ -26,6 +26,7 @@ def form_valid(self, form): "file": self.request.FILES.getlist("file"), "other_file": self.request.FILES.getlist("other_file"), }, + "QUERY_STRING": self.request.GET, }, status=201, encoder=FileEncoder, @@ -45,6 +46,7 @@ def form_valid(self, form): "file": self.request.FILES.getlist("file"), "other_file": self.request.FILES.getlist("other_file"), }, + "QUERY_STRING": self.request.GET, }, status=201, encoder=FileEncoder, From 10c44fcb2c7a93d3bffa5db0fe038987cee065f7 Mon Sep 17 00:00:00 2001 From: j <13580441+gary02@users.noreply.github.com> Date: Mon, 14 Oct 2024 17:43:50 +0800 Subject: [PATCH 2/5] Refactor -- gather form mutation code together --- s3file/static/s3file/js/s3file.js | 23 ++++++++--------------- 1 file changed, 8 insertions(+), 15 deletions(-) diff --git a/s3file/static/s3file/js/s3file.js b/s3file/static/s3file/js/s3file.js index 4969477..cbc0424 100644 --- a/s3file/static/s3file/js/s3file.js +++ b/s3file/static/s3file/js/s3file.js @@ -104,16 +104,6 @@ }) } - function clickSubmit (e) { - var submitButton = e.currentTarget - var form = submitButton.closest('form') - var submitInput = document.createElement('input') - submitInput.type = 'hidden' - submitInput.value = submitButton.value || '1' - submitInput.name = submitButton.name - form.appendChild(submitInput) - } - function uploadS3Inputs (form, submitter) { window.uploading = 0 form.loaded = 0 @@ -136,13 +126,20 @@ window.uploading += 1 uploadFiles(form, input, input.name) }) - // override form attributes with submit button attributes + if (submitter) { + // override form attributes with submit button attributes form.action = submitter.getAttribute('formaction') || form.action form.method = submitter.getAttribute('formmethod') || form.method form.enctype = submitter.getAttribute('formEnctype') || form.enctype form.formnovalidate = submitter.getAttribute('formnovalidate') || form.novalidate form.target = submitter.getAttribute('formtarget') || form.target + // add submit button value to form + var submitInput = document.createElement('input') + submitInput.type = 'hidden' + submitInput.value = submitter.value || '1' + submitInput.name = submitter.name + form.appendChild(submitInput) } waitForAllFiles(form) @@ -158,10 +155,6 @@ e.preventDefault() uploadS3Inputs(e.target, e.submitter) }) - var submitButtons = form.querySelectorAll('input[type=submit], button[type=submit]') - Array.from(submitButtons).forEach(function (submitButton) { - submitButton.addEventListener('click', clickSubmit) - }) }) }) })() From 06eb2d95159f7cb07e7084ba795b88a86a7db4c9 Mon Sep 17 00:00:00 2001 From: j <13580441+gary02@users.noreply.github.com> Date: Tue, 15 Oct 2024 09:55:57 +0800 Subject: [PATCH 3/5] Refactor -- remove anonymous function handler also see https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener#memory_issues --- .gitignore | 1 - s3file/static/s3file/js/s3file.js | 13 ++++++++----- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/.gitignore b/.gitignore index 03ed1e4..cfb6375 100644 --- a/.gitignore +++ b/.gitignore @@ -59,4 +59,3 @@ target/ node_modules *.min.js -.python-version diff --git a/s3file/static/s3file/js/s3file.js b/s3file/static/s3file/js/s3file.js index cbc0424..834f31d 100644 --- a/s3file/static/s3file/js/s3file.js +++ b/s3file/static/s3file/js/s3file.js @@ -104,7 +104,13 @@ }) } - function uploadS3Inputs (form, submitter) { + function uploadS3Inputs (event) { + + event.preventDefault() + + var form = event.target + var submitter = event.submitter + window.uploading = 0 form.loaded = 0 form.total = 0 @@ -151,10 +157,7 @@ }) forms = new Set(forms) forms.forEach(function (form) { - form.addEventListener('submit', function (e) { - e.preventDefault() - uploadS3Inputs(e.target, e.submitter) - }) + form.addEventListener('submit', uploadS3Inputs) }) }) })() From c1bfe96faefeeef29d45d7c9b73f76ceafbeeefc Mon Sep 17 00:00:00 2001 From: j <13580441+gary02@users.noreply.github.com> Date: Tue, 15 Oct 2024 10:40:50 +0800 Subject: [PATCH 4/5] Fix typo --- s3file/static/s3file/js/s3file.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/s3file/static/s3file/js/s3file.js b/s3file/static/s3file/js/s3file.js index 834f31d..f08b742 100644 --- a/s3file/static/s3file/js/s3file.js +++ b/s3file/static/s3file/js/s3file.js @@ -138,7 +138,7 @@ form.action = submitter.getAttribute('formaction') || form.action form.method = submitter.getAttribute('formmethod') || form.method form.enctype = submitter.getAttribute('formEnctype') || form.enctype - form.formnovalidate = submitter.getAttribute('formnovalidate') || form.novalidate + form.novalidate = submitter.getAttribute('formnovalidate') || form.novalidate form.target = submitter.getAttribute('formtarget') || form.target // add submit button value to form var submitInput = document.createElement('input') From 9d410288cc5b866768788fdf744b5f0dac5064cc Mon Sep 17 00:00:00 2001 From: j <13580441+gary02@users.noreply.github.com> Date: Sun, 20 Oct 2024 18:00:52 +0800 Subject: [PATCH 5/5] Refactor -- run `standard --fix` to pass lint check --- s3file/static/s3file/js/s3file.js | 57 +++++++++++++++---------------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/s3file/static/s3file/js/s3file.js b/s3file/static/s3file/js/s3file.js index f08b742..a45cadc 100644 --- a/s3file/static/s3file/js/s3file.js +++ b/s3file/static/s3file/js/s3file.js @@ -2,8 +2,8 @@ (function () { function parseURL (text) { - var xml = new window.DOMParser().parseFromString(text, 'text/xml') - var tag = xml.getElementsByTagName('Key')[0] + const xml = new window.DOMParser().parseFromString(text, 'text/xml') + const tag = xml.getElementsByTagName('Key')[0] return decodeURI(tag.childNodes[0].nodeValue) } @@ -20,7 +20,7 @@ function request (method, url, data, fileInput, file, form) { file.loaded = 0 return new Promise(function (resolve, reject) { - var xhr = new window.XMLHttpRequest() + const xhr = new window.XMLHttpRequest() xhr.onload = function () { if (xhr.status === 201) { @@ -31,11 +31,11 @@ } xhr.upload.onprogress = function (e) { - var diff = e.loaded - file.loaded + const diff = e.loaded - file.loaded form.loaded += diff fileInput.loaded += diff file.loaded = e.loaded - var defaultEventData = { + const defaultEventData = { currentFile: file, currentFileName: file.name, currentFileProgress: Math.min(e.loaded / e.total, 1), @@ -67,15 +67,15 @@ } function uploadFiles (form, fileInput, name) { - var url = fileInput.getAttribute('data-url') + const url = fileInput.getAttribute('data-url') fileInput.loaded = 0 fileInput.total = 0 - var promises = Array.from(fileInput.files).map(function (file) { + const promises = Array.from(fileInput.files).map(function (file) { form.total += file.size fileInput.total += file.size - var s3Form = new window.FormData() + const s3Form = new window.FormData() Array.from(fileInput.attributes).forEach(function (attr) { - var name = attr.name + let name = attr.name if (name.startsWith('data-fields')) { name = name.replace('data-fields-', '') @@ -89,7 +89,7 @@ }) Promise.all(promises).then(function (results) { results.forEach(function (result) { - var hiddenFileInput = document.createElement('input') + const hiddenFileInput = document.createElement('input') hiddenFileInput.type = 'hidden' hiddenFileInput.name = name hiddenFileInput.value = parseURL(result) @@ -105,24 +105,23 @@ } function uploadS3Inputs (event) { - event.preventDefault() - var form = event.target - var submitter = event.submitter + const form = event.target + const submitter = event.submitter window.uploading = 0 form.loaded = 0 form.total = 0 - var inputs = Array.from(form.querySelectorAll('input[type=file].s3file')) + const inputs = Array.from(form.querySelectorAll('input[type=file].s3file')) inputs.forEach(function (input) { - var hiddenS3Input = document.createElement('input') + const hiddenS3Input = document.createElement('input') hiddenS3Input.type = 'hidden' hiddenS3Input.name = 's3file' hiddenS3Input.value = input.name form.appendChild(hiddenS3Input) - var hiddenSignatureInput = document.createElement('input') + const hiddenSignatureInput = document.createElement('input') hiddenSignatureInput.type = 'hidden' hiddenSignatureInput.name = input.name + '-s3f-signature' hiddenSignatureInput.value = input.dataset.s3fSignature @@ -134,25 +133,25 @@ }) if (submitter) { - // override form attributes with submit button attributes - form.action = submitter.getAttribute('formaction') || form.action - form.method = submitter.getAttribute('formmethod') || form.method - form.enctype = submitter.getAttribute('formEnctype') || form.enctype - form.novalidate = submitter.getAttribute('formnovalidate') || form.novalidate - form.target = submitter.getAttribute('formtarget') || form.target - // add submit button value to form - var submitInput = document.createElement('input') - submitInput.type = 'hidden' - submitInput.value = submitter.value || '1' - submitInput.name = submitter.name - form.appendChild(submitInput) + // override form attributes with submit button attributes + form.action = submitter.getAttribute('formaction') || form.action + form.method = submitter.getAttribute('formmethod') || form.method + form.enctype = submitter.getAttribute('formEnctype') || form.enctype + form.novalidate = submitter.getAttribute('formnovalidate') || form.novalidate + form.target = submitter.getAttribute('formtarget') || form.target + // add submit button value to form + const submitInput = document.createElement('input') + submitInput.type = 'hidden' + submitInput.value = submitter.value || '1' + submitInput.name = submitter.name + form.appendChild(submitInput) } waitForAllFiles(form) } document.addEventListener('DOMContentLoaded', function () { - var forms = Array.from(document.querySelectorAll('input[type=file].s3file')).map(function (input) { + let forms = Array.from(document.querySelectorAll('input[type=file].s3file')).map(function (input) { return input.closest('form') }) forms = new Set(forms)