jQuery 用ajax加载后在DOM中找不到元素(想绑定jquery插件)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/16761175/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Can't find element in DOM after loading it with ajax (want to bind jquery plug in to it)
提问by GertV
So I have 2 html pages. 1 that functions as container and 1 that functions as content. When I load the content page with a table I'm able to use drag and drop.
所以我有 2 个 html 页面。1 个用作容器,1 个用作内容。当我用表格加载内容页面时,我可以使用拖放功能。
But when I go to my container page and load the content page into a div with ajax, the drag and drop stops working. All other javascript functionalities inside the content page still work. How can I bind the jquery dnd plugin to the table loaded with ajax?
但是,当我转到我的容器页面并使用 ajax 将内容页面加载到 div 中时,拖放停止工作。内容页面中的所有其他 JavaScript 功能仍然有效。如何将 jquery dnd 插件绑定到加载了 ajax 的表?
I'm using drag & drop with this as tutorial http://isocra.com/2008/02/table-drag-and-drop-jquery-plugin/
我正在使用拖放作为教程http://isocra.com/2008/02/table-drag-and-drop-jquery-plugin/
my code looks like this:
我的代码是这样的:
$(window).load(function()
{ if(temp == 0)
{
DP("eerste keer")
load_table();
temp = 1;
}
} );
function load_table()
{
DP('load_table');
$.ajax({
//async: false,
type: "POST",
url: "/diagnose_hoofdpagina/table_diagnose/" + DosierID, // <== loads requested page
success: function (data) {
$("#diagnoses_zelf").html(''); //<== clears current content of div
$("#diagnoses_zelf").append(data).trigger('create'); // <== appends requested page
},
error: function(){
alert('error');
}
}).done(function() {
update_table();
initialize_table(); // <== calls jquery plug in
});
return false;
}
function initialize_table()
{
var tableid = $('#diagnoses_zelf table').attr('id'); //< this finds the correct table thanks to Fábio Batista => this option worked, rest didn't
alert(tableid);
$(tableid).tableDnD({
onDrop: function(table, row) {
alert(table + " " + row);
},
onDragStart: function(table,row){
var tette = $(row).index;
alert(tette);
},
dragHandle: ".dragHandle"
});
}
How is this possible and what can I do about it? Can anyone help me with this please.
这怎么可能,我该怎么办?任何人都可以帮我解决这个问题。
Very short: I want access to the ID of the table I load into my container page with ajax and use the jquery drag and drop plug in on it.
非常简短:我想访问我使用 ajax 加载到我的容器页面中的表的 ID,并在其上使用 jquery 拖放插件。
EDIT
编辑
Findings:
发现:
Somehow my table in the container page got renamed to pSqlaTableinstead of the id I gave to it in the controller page which is.
不知何故,我在容器页面中的表被重命名为pSqlaTable而不是我在控制器页面中给它的 id。
<table id="tableDiagnose" class="table table-hover">
Thats why the code couldn't find the table annymore Got fixed by this code thanks to Fábio Batista:
这就是为什么代码找不到表 annymore 感谢 Fábio Batista 通过此代码修复:
$('#diagnoses_zelf table').tableDnD( ... );
, but how can I use the dnd plugin now ?
,但我现在如何使用 dnd 插件?
It finds the table now, but I'm still not able to bind the dnd plugin to it, Am I able to bind a jquery plug in to ajax loaded tables ?
它现在找到了表,但我仍然无法将 dnd 插件绑定到它,我可以将 jquery 插件绑定到 ajax 加载的表吗?
EDIT
编辑
//drag & drop http://isocra.com/2008/02/table-drag-and-drop-jquery-plugin/
function initialize_table()
{
var tableid = $('#diagnoses_zelf table').attr('id');
alert(tableid);
$('#' + tableid).tableDnD({
onDrop: function(table, row) {
alert(table + " " + row);
},
onDragStart: function(table,row){
alert('issemer?');
},
dragHandle: ".dragHandle"
});
}
This is the code i'm still stuck with. tableid is correct but the initialisation of the jquery isn't. I can't drag the drows in the table. Is my syntax wrong ?
这是我仍然坚持的代码。tableid 是正确的,但 jquery 的初始化不是。我不能拖动桌子上的卓尔。我的语法错了吗?
EDIT
编辑
Could it be that I can't bind the jquery to the table because I dynamicaly generate the table on the other page with ZPT (or javascript) ?
是不是我无法将 jquery 绑定到表,因为我使用 ZPT(或 javascript)在另一个页面上动态生成表?
回答by Benjamin Gruenbaum
The issue with plugins.
插件的问题。
You're mixing lots of external libraries and code. This results in possible mis-matches between versions, and a lot of black boxes in your code.
您正在混合大量外部库和代码。这会导致版本之间可能的不匹配,以及代码中的大量黑框。
As a developer, this should make you feel very uneasy. Having code you do not fully understand in your code base can get really frustrating really fast.
作为开发人员,这应该会让您感到非常不安。在您的代码库中拥有您不完全理解的代码可能会很快变得非常令人沮丧。
The alternative.
替代方案。
Often, these sort of plugins provide functionality we, as JavaScript developers can accomplish just as easily without them. This development process, in simple enough scenarios, lets us create code we understand and have an easier time maintaining. Not only do we learn from this process, but we also create smaller bits of specific code. Community driven solutions are very good in general, but it's important to remember they're not a silver bullet. Often you're stuck using a not-so-active project which has a bug for your specific case and you have to dig through a large, unfamiliar code base.
通常,这些类型的插件提供了我们作为 JavaScript 开发人员可以在没有它们的情况下轻松完成的功能。这个开发过程,在足够简单的场景中,让我们可以创建我们理解的代码并且更容易维护。我们不仅从这个过程中学习,而且我们还创建了更小的特定代码。社区驱动的解决方案总体上非常好,但重要的是要记住它们不是灵丹妙药。通常,您被困在一个不太活跃的项目中,该项目对您的特定案例存在错误,并且您必须挖掘庞大的、不熟悉的代码库。
Your code
你的代码
So what does this drag and drop plugin do?
那么这个拖放插件有什么作用呢?
Well, I'd break it down as the following:
好吧,我将其分解如下:
- Listens to the
mousedown
event on table rows - When such an event fires, start moving the table row to match the mouse position
- When
mouseup
occurs, detect that, and finalize the position.
- 侦听表行上的
mousedown
事件 - 当此类事件触发时,开始移动表格行以匹配鼠标位置
- 当
mouseup
发生时,检测到并最终确定位置。
Let us see how we can do something similar. Let's assume the table's HTML is something like:
让我们看看如何做类似的事情。让我们假设表格的 HTML 是这样的:
<table>
<tbody>
<tr>
<td> Hello 1</td>
</tr><tr>
<td> Hello 2</td>
</tr>
</tbody>
</table>
Here is a fiddle with the table with some basic styling applied
Next, we'll listen to the selection events. We'll add an event to the table rows for selection and to the document to when the mouse is up. jQuery has event listeners for such events. Since we want these events to stick even after AJAX, we'll use .on
which lets us use delegated events. .on
means that even if we add content to the table later, it won't matter.
接下来,我们将监听选择事件。我们将向表格行添加一个事件以供选择,并在鼠标抬起时向文档添加一个事件。jQuery 具有此类事件的事件侦听器。由于我们希望这些事件即使在 AJAX 之后也能保持,我们将使用.on
which 让我们使用委托事件。.on
意味着即使我们稍后将内容添加到表格中,也无关紧要。
var selected; // currently selected row
$(document).on("mousedown","#MySpecialTable tr",function(){
$("#textDiv").text(this.textContent);
selected = this;
});
$(document).on("mouseup",function(){
$("#textDiv").text("Left "+selected.textContent);
selected = null;
});
Here is a working fiddleof such code.
Now, we'll want to actually change the drag&drop to work when, that is, update the current position to the one reflecting the mouse position. We can listen to mousemove
events, and detect the element we're currently on. Something like
现在,我们要实际更改拖放操作,即将当前位置更新为反映鼠标位置的位置。我们可以监听mousemove
事件,并检测我们当前所在的元素。就像是
$(document).on("mousemove",function(e){
$("#textDiv").text($(e.target).html());
});
You can see a working fiddle here
That's nice, but we want to actually change the element position. So we'll need to change the table structure to allow that. We can remove the element, and append it at the correct position. We'll check if we have a selected element, and if we do, we can track it compared to the current element in the mousemove event. We can for starters detect if we should drag with something like:
这很好,但我们想要真正改变元素的位置。因此,我们需要更改表结构以允许这样做。我们可以删除元素,并将其附加到正确的位置。我们将检查是否有被选中的元素,如果有,我们可以在 mousemove 事件中与当前元素进行比较来跟踪它。首先,我们可以检测是否应该使用以下内容进行拖动:
$(document).on("mousemove",function(e){
if(selected !=null){// got an element selected
if($("#MySpecialTable").has(e.target).length > 0){ //in the table
$("#mousePos").text("DRAGGING");
}
}else{
$("#mousePos").text("NOT SELECTED");
}
});
Now, we'll add actual selection, we'll replace the elements when the target is not our element and we're in the table. Our full code should be something like:
现在,我们将添加实际选择,当目标不是我们的元素并且我们在表格中时,我们将替换元素。我们的完整代码应该是这样的:
var selected;
$(document).on("mousedown","#MySpecialTable tr",function(e){
e.preventDefault();//stop the text selection;
$("#textDiv").text(this.textContent);
selected = $(this);
selected.find("td").css("background-color","#999");
});
$(document).on("mouseup",function(){
$("#textDiv").text("Left "+selected.text());
selected.find("td").css("background-color","");
selected = null;
});
$(document).on("mousemove",function(e){
if(selected !=null){// got an element selected
if($("#MySpecialTable").has(e.target).length > 0){ //in the table
var el = $(e.target).closest("tr");//the tr element we're on
el.before(selected);// replace the elements
}
}else{
$("#mousePos").text("NOT SELECTED");
}
});
$("#MySpecialTable").on('selectstart', false);//Don't let the user select the table
(Fiddle)
(小提琴)
Now, so far we only have a few lines of code, which is nice since we know exactly what's going on and didn't need to use lots of lines of external code we don't fully understand.
现在,到目前为止我们只有几行代码,这很好,因为我们确切地知道发生了什么并且不需要使用很多我们不完全理解的外部代码行。
But will it AJAX?
但它会是 AJAX 吗?
Let's load the data into the table with AJAX and see! We'll simulate an AJAX response using a setTimeout
which would allow us to simulate an asynchronous request. We'll use
让我们用 AJAX 将数据加载到表中,看看吧!我们将使用setTimeout
允许我们模拟异步请求的a 模拟 AJAX 响应。我们会用
setTimeout(function(){
$("#MySpecialTable").html("<tr><td> Hello 1</td></tr><tr><td> Hello 2</td></tr><tr><td> Hello 3</td></tr><tr><td> Hello 4</td></tr><tr><td> Hello 5</td></tr><tr><td> Hello 6</td></tr>");
},1000);
This means, update the HTML of #MySpecialTable
after one second. Let's see if it works shall we?
这意味着,#MySpecialTable
一秒后更新 HTML 。让我们看看它是否有效?
So why does it work?well, we used delegated eventswhich means we don't care if the elements we're loading are in the screen right now or not. We had the insight to do this since we built our code ourselves and knew what our final goal was. The only thing left to do is clean the code a little.
那么它为什么有效呢?好吧,我们使用了委托事件,这意味着我们不关心我们正在加载的元素现在是否在屏幕上。因为我们自己构建了代码并且知道我们的最终目标是什么,所以我们有洞察力来做到这一点。剩下要做的就是稍微清理一下代码。
We'll wrap our code in the following, to prevent $ from being an issue in non-conflict mode (that is, $ is already taken in the page:
我们将在下面包装我们的代码,以防止 $ 在非冲突模式下成为问题(即 $ 已经在页面中使用:
(function($){
})(jQuery);
Next we'll add a binding for our table event:
接下来,我们将为我们的 table 事件添加一个绑定:
$.GertVDragTable = function(elementSelector){ // rest of code.
Eventually, our code might look something like this.
最终,我们的代码可能看起来像这样。
Using it, would be a simple $.GertVDragTable("#MySpecialTable");
alternatively, we can put it on $.fn
and allow every function to call it. Which is a matter of taste.
使用它,将是一个简单的$.GertVDragTable("#MySpecialTable");
选择,我们可以将它放在$.fn
并允许每个函数调用它。这是一个品味问题。
No copy-pasta please :) I'd appreciate it if you stop on every stage and think whythe next step was taken.
请不要复制意大利面:) 如果您在每个阶段都停下来思考为什么要采取下一步行动,我将不胜感激。
回答by Fábio Batista
You don't need to use the ID as a selector, you can use any expression that can find your table.
您不需要使用 ID 作为选择器,您可以使用任何可以找到您的表的表达式。
If there's only one table on the resulting $.ajax
call, you can search for "a table inside the container", using the container ID, which won't change:
如果结果$.ajax
调用中只有一个表,您可以使用不会更改的容器 ID 搜索“容器内的表”:
$('#diagnoses_zelf table').tableDnD( ... );
If there's more than one table, use a different kind of selector, instead of the ID. A CSS class works fine:
如果有多个表,请使用不同类型的选择器,而不是 ID。CSS 类工作正常:
$('table.table-diagnose').tableDnD( ... );
So does a data-
attribute:
所以,做一个data-
属性:
$("table[data-diagnose]").tableDnD( ... );
回答by Joey
Try adding a title
to your table, like so:
尝试将 a 添加title
到您的表中,如下所示:
<table id = "tableDiagnose" class = "table table-hover" title = "table-content">
Then use the jQuery attribute selectorto find this table instead of finding it by id
.
然后使用 jQuery属性选择器来查找该表,而不是通过id
.
$('table[title="table-content"]').tableDnD({
// the rest of your code
回答by TecHunter
If your id is changing you should not use an ID then:
如果您的 ID 正在更改,则不应使用 ID,然后:
<table class="tableDiagnose table table-hover">
Plugin
插入
function initialize_table()
{
$('.tableDiagnose.table').tableDnD({
onDrop: function(table, row) {
alert(table + " " + row);
},
dragHandle: ".dragHandle"
});
DP('nee');
}
EDIT: ajax is asynchronous :
编辑:ajax 是异步的:
function load_table()
{
DP('load_table');
$.ajax({
//async: false,
type: "POST",
url: "/diagnose_hoofdpagina/table_diagnose/" + DosierID, // <== loads requested page
success: function (data) {
$("#diagnoses_zelf").html(''); //<== clears current content of div
$("#diagnoses_zelf").append(data).trigger('create'); // <== appends requested page
update_table();
initialize_table(); // <== calls jquery plug in
},
error: function(){
alert('error');
}
});
//removed .done as you already have a success option in ajax
return false;
}
EDIT: found your bug........
you retrieve the table id then select it in $(tableid) but you missed the #
编辑:找到你的错误......你检索表 ID 然后在 $(tableid) 中选择它但你错过了 #
function initialize_table()
{
/*
var tableid = $('#diagnoses_zelf table').attr('id'); //< this finds the correct table thanks to Fábio Batista => this option worked, rest didn't
alert(tableid);
// but you really should limit the use of variables when you don't need them*/
//$('#'+tableid).tableDnD({
//like this directly
$('#diagnoses_zelf table').tableDnD({
onDrop: function(table, row) {
alert(table + " " + row);
},
onDragStart: function(table,row){
var tette = $(row).index;
//alert(tette);
},
dragHandle: ".dragHandle"
});
}
EDIT
编辑
回答by Igarioshka
Do you include the script file in the container page or in the content page? I guess you might want to try to load it when calling the dnd plugin with getScript:
您将脚本文件包含在容器页面还是内容页面中?我猜您可能想在使用 getScript 调用 dnd 插件时尝试加载它:
...
$.getScript('pathTotableDnDlib').done(function(){
$(tableid).tableDnD({
onDrop: function(table, row) {
alert(table + " " + row);
},
onDragStart: function(table,row){
var tette = $(row).index;
alert(tette);
},
dragHandle: ".dragHandle"
});});
...
more on getscript: here
有关 getscript 的更多信息:这里
回答by user20924
@BenjaminGruenbaum Hi thx a lot for the tutorial, i modified a bit the code to block the drag n'drop on table headers and to improve the drag fluidity tracking the mouse direction.
@BenjaminGruenbaum 嗨,本教程非常感谢,我修改了一些代码以阻止表格标题上的拖放,并改善跟踪鼠标方向的拖拽流动性。
var old_y = 0;
(function ($) {
$.GertVDragTable = function (tableName) {
var selected;
$(document).on("mousedown", tableName+" tr",function (e) {
e.preventDefault(); //stop the text selection;
if (($(this).find('th').length)== 0){ //prevent dragging on tr containing th
selected = $(this);
selected.find("td").css("background-color", "black");
selected.find("td").css("color", "white");
}
});
$(document).on("mouseup", function () {
selected.find("td").css("background-color", "");
selected.find("td").css("color", "");
selected = null;
});
$(document).on("mousemove", function (e) {
if (selected != null ) { // got an element selected
if ($(tableName).has(e.target).length > 0) { //in the table
var el = $(e.target).closest("tr"); //the tr element we're on
if (el.find('th').length==0){ //prevent dropping on headers row
if (e.pageY > old_y){ //**
el.after(selected);}else{ //**-->more fluid dragging based on mouse direction
el.before(selected); //**
}
}
}
old_y = e.pageY;
}
});
$(tableName).on('selectstart', false); //Don't let the user select the table
}
})(jQuery);
here's the fiddle http://jsfiddle.net/59rdq/
这是小提琴http://jsfiddle.net/59rdq/
I hope it will be useful for someone.
我希望它对某人有用。