如何在元素属性更改时使用 JQuery 事件委托?
How to use JQuery event delegation on element attribute change?
我有一个带有编辑现有记录按钮的表单。单击按钮时,将打开一个模式以更新记录,包括一个用于删除附加到记录的现有文件的按钮,单击该按钮会触发对 delete_file PHP 脚本的 ajax 调用。如果文件存在,其文件名将在 'p' 元素中预览。
我 运行 遇到的问题是,如果用户编辑了一条不包含文件的记录,上传了一个文件,然后在不保存记录的情况下将其删除,我现有的代码不会无法删除文件。这是因为 HTML 是在文件上传时动态生成的,用于将文件 url 放在按钮属性中,该属性无法传递给文件删除。
经过研究,我认为解决方案是事件委托。我尝试了一些建议,但 none 奏效了。我怎样才能:
- 添加一个文件(文件名在 "$("button").attr("data-fileurl") // 这个有效
- 单击 'delete file' 按钮后,将 $("button").attr("data-fileurl") 存储在变量中
- 将 url 变量传递给 delete_file 函数
HTML:
<div id='file_upload' class='file-upload'>
<input type='file' id='file_input' style='opacity:0;' />
<p class='file_upload_text'>Click to upload file</p>
</div>
<div id='file_upload_preview' class='file-upload file-preview' style='display:none;'>
<div class='file_preview'></div>
<button id='fileurl' data-fileurl='' class='file_delete'>Delete</button>
</div>
JQuery:
jQuery(document).ready(function($) {
var filesToUpload = [];
var fileUrlDelegated = "";
$('#file_input').on('change', function(e) {
var files = e.target.files[0];
filesToUpload.push(files);
prepareUpload(filesToUpload);
$(".file_delete").on('click', function(e) {
e.preventDefault();
$(document.body).on('change', "button [data-fileurl]", function (event) { // not working
fileUrlDelegated = $(event.target).attr("data-fileurl");
});
delete_file(fileUrlDelegated);
});
});
function prepareUpload(file) { // upload file; dynamic HTML generated after an ajax call; this works
var parent = $("#file_input").parent();
var previewID = parent.attr("id") + "_preview";
var previewParent = $("#"+previewID);
previewParent.show();
previewParent.children(".file_preview").empty().append( preview );
previewParent.children( "button" ).attr("data-fileurl", data.url );
parent.children("input").val("");
parent.hide();
}
function delete_file (file_url) { // works as long as url is provided
$(".file_preview").text("");
$("button").attr("data-fileurl", "");
$("#file_upload_preview").hide();
$("#file_upload").show();
var data = new FormData();
data.append("fileurl", file_url);
$.ajax({
url: general_globals.ajaxurl,
type: 'POST',
data: data,
processData: false,
contentType: false,
cache: false,
dataType: 'json'
});
}
尝试使用 FileReader API 而不是依赖 AJAX 调用。你可以做一个像
这样的方法
function readURL() {
var input = grab your input here;
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('#preview').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
};
这样,在用户保存记录之前你不会触及你的数据库,所以你的问题就解决了。
你只需要重写你的逻辑,code
的其余部分看起来很好。到 delete
文件并传递 data-fileurl
- 您可以简单地检查文件 URL 是否存在,它是由 prepare Upload.
生成的
此外,要获取数据属性,我们可以简单地使用 .data 方法并在 jQuery
中写入 .data('fileurl')
以获取按钮 fileurl
然后将其传递给我们删除 function
为 ajax
调用 backend
.
为了获得正确的 fileURL
我们可以在我们的删除函数中使用$(this)
它指的是我们点击的元素将是.file_delete
为了安全起见,我们将在您的案例中使用 event Delegation
,因为 HTML 是动态创建的。
将您的删除文件功能替换为:(代码在本地主机上测试并正常工作)
//Delete file
$(document).on('click', '.file_delete', function(e) {
e.preventDefault();
//Get the file URL
var fileURL = $(this).data('fileurl')
//Check if file URL exist - then call delete else do not anything
if (fileURL != '') {
//Call delete function
delete_file(fileURL);
} else {
return false
}
});
我有一个带有编辑现有记录按钮的表单。单击按钮时,将打开一个模式以更新记录,包括一个用于删除附加到记录的现有文件的按钮,单击该按钮会触发对 delete_file PHP 脚本的 ajax 调用。如果文件存在,其文件名将在 'p' 元素中预览。
我 运行 遇到的问题是,如果用户编辑了一条不包含文件的记录,上传了一个文件,然后在不保存记录的情况下将其删除,我现有的代码不会无法删除文件。这是因为 HTML 是在文件上传时动态生成的,用于将文件 url 放在按钮属性中,该属性无法传递给文件删除。
经过研究,我认为解决方案是事件委托。我尝试了一些建议,但 none 奏效了。我怎样才能:
- 添加一个文件(文件名在 "$("button").attr("data-fileurl") // 这个有效
- 单击 'delete file' 按钮后,将 $("button").attr("data-fileurl") 存储在变量中
- 将 url 变量传递给 delete_file 函数
HTML:
<div id='file_upload' class='file-upload'>
<input type='file' id='file_input' style='opacity:0;' />
<p class='file_upload_text'>Click to upload file</p>
</div>
<div id='file_upload_preview' class='file-upload file-preview' style='display:none;'>
<div class='file_preview'></div>
<button id='fileurl' data-fileurl='' class='file_delete'>Delete</button>
</div>
JQuery:
jQuery(document).ready(function($) {
var filesToUpload = [];
var fileUrlDelegated = "";
$('#file_input').on('change', function(e) {
var files = e.target.files[0];
filesToUpload.push(files);
prepareUpload(filesToUpload);
$(".file_delete").on('click', function(e) {
e.preventDefault();
$(document.body).on('change', "button [data-fileurl]", function (event) { // not working
fileUrlDelegated = $(event.target).attr("data-fileurl");
});
delete_file(fileUrlDelegated);
});
});
function prepareUpload(file) { // upload file; dynamic HTML generated after an ajax call; this works
var parent = $("#file_input").parent();
var previewID = parent.attr("id") + "_preview";
var previewParent = $("#"+previewID);
previewParent.show();
previewParent.children(".file_preview").empty().append( preview );
previewParent.children( "button" ).attr("data-fileurl", data.url );
parent.children("input").val("");
parent.hide();
}
function delete_file (file_url) { // works as long as url is provided
$(".file_preview").text("");
$("button").attr("data-fileurl", "");
$("#file_upload_preview").hide();
$("#file_upload").show();
var data = new FormData();
data.append("fileurl", file_url);
$.ajax({
url: general_globals.ajaxurl,
type: 'POST',
data: data,
processData: false,
contentType: false,
cache: false,
dataType: 'json'
});
}
尝试使用 FileReader API 而不是依赖 AJAX 调用。你可以做一个像
这样的方法function readURL() {
var input = grab your input here;
if (input.files && input.files[0]) {
var reader = new FileReader();
reader.onload = function(e) {
$('#preview').attr('src', e.target.result);
}
reader.readAsDataURL(input.files[0]);
}
};
这样,在用户保存记录之前你不会触及你的数据库,所以你的问题就解决了。
你只需要重写你的逻辑,code
的其余部分看起来很好。到 delete
文件并传递 data-fileurl
- 您可以简单地检查文件 URL 是否存在,它是由 prepare Upload.
此外,要获取数据属性,我们可以简单地使用 .data 方法并在 jQuery
中写入 .data('fileurl')
以获取按钮 fileurl
然后将其传递给我们删除 function
为 ajax
调用 backend
.
为了获得正确的 fileURL
我们可以在我们的删除函数中使用$(this)
它指的是我们点击的元素将是.file_delete
为了安全起见,我们将在您的案例中使用 event Delegation
,因为 HTML 是动态创建的。
将您的删除文件功能替换为:(代码在本地主机上测试并正常工作)
//Delete file
$(document).on('click', '.file_delete', function(e) {
e.preventDefault();
//Get the file URL
var fileURL = $(this).data('fileurl')
//Check if file URL exist - then call delete else do not anything
if (fileURL != '') {
//Call delete function
delete_file(fileURL);
} else {
return false
}
});