我正在开发一个 Chrome 扩展程序,需要它在用户尝试上传文件时通过自定义模式窗口提示用户确认。这是我一直在编写的
content.js
脚本:
function showModal(element) {
const modal = document.createElement('div');
modal.innerHTML = `
<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,0.5);display:flex;justify-content:center;align-items:center;z-index:10000;">
<div style="background:white;padding:20px;border-radius:5px;box-shadow:0 4px 6px rgba(0,0,0,0.1);">
<p>Are you sure you want to upload the file?</p>
<button id="confirmUpload">Yes</button>
<button id="cancelUpload">No</button>
</div>
</div>
`;
document.body.appendChild(modal);
// Handling confirmUpload
document.getElementById('confirmUpload').addEventListener('click', () => {
document.body.removeChild(modal);
});
// Handling confirmUpload
document.getElementById('cancelUpload').addEventListener('click', () => {
document.body.removeChild(modal);
// Deleting the file from the element.files
const dt = new DataTransfer()
element.files = dt.files;
});
}
// React to an event when a user uploads a file to the site
document.addEventListener('change', (event) => {
event.preventDefault();
const element = event.target;
if (element instanceof HTMLInputElement && element.type === 'file') {
showModal(element);
}
}, true);
我遇到的主要问题是文件在选择后立即开始上传,然后用户才能响应模式。这种行为违背了寻求用户确认的目的。
event.stopPropagation()
不可行,因为它需要为每个站点自定义上传逻辑,这是不切实际的。考虑到这些限制,是否有人对解决方法或实现所需功能的不同策略有建议?或者是否有可能通过完全不同的方法来实现它?
如果您 console.log()
change
事件监听器返回的事件,您可以看到 cancelable
为 false,这就是您的 e.preventDefault() 不起作用的原因。
要解决此问题,您需要在用户使用 change
事件监听器触发
click
事件之前选择特定输入元素。但是,这也行不通,因为正如您所说,您需要为每个站点添加逻辑。 由于您无法从输入元素的事件内部触发文件选择,因此您需要
隐藏站点的文件输入元素,将其替换为自定义按钮,并从 在自定义按钮的单击事件中添加逻辑使用 .click()
触发网站现在不可见的输入元素的文件选择。
const fileInputElement = document.querySelector('input[type="file"]');
if (fileInputElement instanceof HTMLInputElement) {
fileInputElement.style.display = "none"
}
const myButton = document.getElementById('my-button')
myButton.addEventListener('click', (e) => {
// replace prompt with your modal + return values
let answer = prompt('do you want to continue')
if (answer === "yes" && fileInputElement instanceof HTMLInputElement) {
fileInputElement.click();
}
})