移动图像预览包装器时文件上传表单不起作用
File Upload Form Not Working When Image Preview Wrapper Is Moved
我有一个文件上传器可以处理多个文件,所有文件都按预期工作。
要上传的文件的预览放在上传表单的容器内。当我将此元素移动到表单的不同部分(或表单之外)时,上传器不起作用?理想情况下,我希望保存图像的预览容器位于提交按钮下方(在表单内部或外部)。
我一辈子都弄不明白为什么会这样。在图像预览填充它之前元素本身是空的,我认为问题不是由 javascript 引起的(尽管很乐意就此提供指导)。
有问题的元素是这个:
<div id="show-selected-images"></div>
它目前位于拖放区和(隐藏的)文件输入元素以及一个可见的提交按钮之间的表单中间,但如前所述,我想将它移到提交按钮下方。
注意:我包含了 JS,因此上传器可以正常工作,但我怀疑 JS 可能不是问题所在。
代码笔:https://codepen.io/pauljohnknight/pen/xxdrvmR
// Query all needed elements in one go
const [dropZone, showSelectedImages, fileUploader] = document.querySelectorAll(
"#standard-upload-files, #drop-zone, #show-selected-images"
);
dropZone.addEventListener("click", (evt) => {
// assigns the dropzone to the hidden input element so when you click 'select files' it brings up a file picker window
fileUploader.click();
});
// Prevent browser default when draging over
dropZone.addEventListener("dragover", (evt) => {
evt.preventDefault();
});
fileUploader.addEventListener("change", (evt) => {
// Clear the already selected images
showSelectedImages.innerHTML = "";
// this function is further down but declared here and shows a thumbnail of the image
[...fileUploader.files].forEach(updateThumbnail);
});
dropZone.addEventListener("drop", (evt) => {
evt.preventDefault();
// Clear the already selected images
showSelectedImages.innerHTML = "";
// assign dropped files to the hidden input element
if (evt.dataTransfer.files.length) {
fileUploader.files = evt.dataTransfer.files;
}
// function is declared here but written further down
[...evt.dataTransfer.files].forEach(updateThumbnail);
});
// updateThumbnail function that needs to be able to handle multiple files
function updateThumbnail(file) {
if (file.type.startsWith("image/")) {
const thumbnailElement = new Image();
thumbnailElement.classList.add("drop-zone__thumb");
thumbnailElement.src = URL.createObjectURL(file);
showSelectedImages.append(thumbnailElement);
}
} // end of 'updateThumbnail' function
body {
margin: 0;
display: flex;
justify-content: center;
width: 100%;
}
form {
width: 30%;
}
#drop-zone {
border: 1px dashed;
width: 100%;
padding: 1rem;
margin-bottom: 1rem;
}
.select-files {
text-decoration: underline;
cursor: pointer;
}
/* image that is previewed prior to form submission*/
.drop-zone__thumb {
width: 200px;
height: auto;
display: block;
}
#submit-images {
margin-top: 1rem;
}
<form id="upload-images-form" enctype="multipart/form-data" method="post">
<h1>Upload Your Images</h1>
<div id="drop-zone" class="drop-zone">
<p class="td text-center">DRAG AND DROP IMAGES HERE</p>
<p>Or</p>
<p class="select-files">Select Files</p>
</div>
<!-- below is the element that has the issue when moved -->
<div id="show-selected-images"></div>
<div class="inner-input-wrapper">
<div class="upload-label-wrapper">
<input id="standard-upload-files" style="display:none" type="file" name="standard-upload-files[]" multiple>
</div>
<input type="submit" name="submit-images" id="submit-images" value="SUBMIT IMAGES">
</div>
</form>
我认为这部分导致了问题:
// Query all needed elements in one go
const [dropZone, showSelectedImages, fileUploader] = document.querySelectorAll(
"#standard-upload-files, #drop-zone, #show-selected-images"
);
这样查询元素是非常糟糕的做法,因为如果不更改解构数组中的元素,就无法更改它们在 html 中的顺序。在您的情况下,您最终要移动预览,现在您的 showSelectedImages
变量实际上是上传器,fileUploader
现在是 div,它包含预览,一切都搞砸了。
您需要一一查询:
const fileUploader = document.getElementById('standard-upload-files');
const dropZone = document.getElementById('drop-zone');
const showSelectedImages = document.getElementById('show-selected-images');
我有一个文件上传器可以处理多个文件,所有文件都按预期工作。
要上传的文件的预览放在上传表单的容器内。当我将此元素移动到表单的不同部分(或表单之外)时,上传器不起作用?理想情况下,我希望保存图像的预览容器位于提交按钮下方(在表单内部或外部)。
我一辈子都弄不明白为什么会这样。在图像预览填充它之前元素本身是空的,我认为问题不是由 javascript 引起的(尽管很乐意就此提供指导)。
有问题的元素是这个:
<div id="show-selected-images"></div>
它目前位于拖放区和(隐藏的)文件输入元素以及一个可见的提交按钮之间的表单中间,但如前所述,我想将它移到提交按钮下方。
注意:我包含了 JS,因此上传器可以正常工作,但我怀疑 JS 可能不是问题所在。
代码笔:https://codepen.io/pauljohnknight/pen/xxdrvmR
// Query all needed elements in one go
const [dropZone, showSelectedImages, fileUploader] = document.querySelectorAll(
"#standard-upload-files, #drop-zone, #show-selected-images"
);
dropZone.addEventListener("click", (evt) => {
// assigns the dropzone to the hidden input element so when you click 'select files' it brings up a file picker window
fileUploader.click();
});
// Prevent browser default when draging over
dropZone.addEventListener("dragover", (evt) => {
evt.preventDefault();
});
fileUploader.addEventListener("change", (evt) => {
// Clear the already selected images
showSelectedImages.innerHTML = "";
// this function is further down but declared here and shows a thumbnail of the image
[...fileUploader.files].forEach(updateThumbnail);
});
dropZone.addEventListener("drop", (evt) => {
evt.preventDefault();
// Clear the already selected images
showSelectedImages.innerHTML = "";
// assign dropped files to the hidden input element
if (evt.dataTransfer.files.length) {
fileUploader.files = evt.dataTransfer.files;
}
// function is declared here but written further down
[...evt.dataTransfer.files].forEach(updateThumbnail);
});
// updateThumbnail function that needs to be able to handle multiple files
function updateThumbnail(file) {
if (file.type.startsWith("image/")) {
const thumbnailElement = new Image();
thumbnailElement.classList.add("drop-zone__thumb");
thumbnailElement.src = URL.createObjectURL(file);
showSelectedImages.append(thumbnailElement);
}
} // end of 'updateThumbnail' function
body {
margin: 0;
display: flex;
justify-content: center;
width: 100%;
}
form {
width: 30%;
}
#drop-zone {
border: 1px dashed;
width: 100%;
padding: 1rem;
margin-bottom: 1rem;
}
.select-files {
text-decoration: underline;
cursor: pointer;
}
/* image that is previewed prior to form submission*/
.drop-zone__thumb {
width: 200px;
height: auto;
display: block;
}
#submit-images {
margin-top: 1rem;
}
<form id="upload-images-form" enctype="multipart/form-data" method="post">
<h1>Upload Your Images</h1>
<div id="drop-zone" class="drop-zone">
<p class="td text-center">DRAG AND DROP IMAGES HERE</p>
<p>Or</p>
<p class="select-files">Select Files</p>
</div>
<!-- below is the element that has the issue when moved -->
<div id="show-selected-images"></div>
<div class="inner-input-wrapper">
<div class="upload-label-wrapper">
<input id="standard-upload-files" style="display:none" type="file" name="standard-upload-files[]" multiple>
</div>
<input type="submit" name="submit-images" id="submit-images" value="SUBMIT IMAGES">
</div>
</form>
我认为这部分导致了问题:
// Query all needed elements in one go
const [dropZone, showSelectedImages, fileUploader] = document.querySelectorAll(
"#standard-upload-files, #drop-zone, #show-selected-images"
);
这样查询元素是非常糟糕的做法,因为如果不更改解构数组中的元素,就无法更改它们在 html 中的顺序。在您的情况下,您最终要移动预览,现在您的 showSelectedImages
变量实际上是上传器,fileUploader
现在是 div,它包含预览,一切都搞砸了。
您需要一一查询:
const fileUploader = document.getElementById('standard-upload-files');
const dropZone = document.getElementById('drop-zone');
const showSelectedImages = document.getElementById('show-selected-images');