2012-06-26 37 views
1
var json_string=$.parseJSON(document.getElementById("json_db").innerHTML); 
$(function() 
{ 
    $("#folder_tree").jstree({ 
     contextmenu: {items: customMenu}, 
     "json_data" : {data:json_string}, 
     "plugins" : [ "themes", "json_data", "ui", "contextmenu" ], 

    }); 
}); 
function customMenu(node) 
{ 
    var items = { }; 
} 



$('#folder_tree').delegate('a', 'contextmenu', function (e) 
{ 

     idn = $(this).parent().attr("id"); 
     if(idn) pool_control(idn,e); //sendMsg(idn) 

}); 

嗨,我在jsTree中發現了一些非常奇怪的東西。 上面的代碼顯示了樹的創建和委託右鍵單擊事件。 sendMsg(idn)發送一個AJAX請求到另一個頁面。 pool_control(idn,e)使用該事件在單擊的節點旁顯示一個表單。表單填充後,它會調用sendMsg。在jstree代理中創建意外的多實例

當我在委託事件處理程序(而不是pool_control)中直接調用sendMsg時,該腳本完美工作。但是,當我通過pool_control調用它時,會發生這種情況: 每個pool_control都被調用,發送的Ajax請求增加1。請求的內容似乎是相同的,但我不知道爲什麼沒有。的Ajax請求增加。當我直接調用sendMsg時不會發生這種情況。

發生了什麼事?我該如何解決?

pool_control和sendmsg:

function pool_control(id,ev) 
{ 

    $("#pool_count").css("left",ev.pageX); 
    $("#pool_count").css("top",ev.pageY); 
    $("#pool_count").css("visibility","visible"); 
    $("#poolbutton").click(function() 
    { 
     $('#pool_count').css('visibility','hidden');  
     sendMsg(id); 
    }); 
    $("#poolcancel").click(function() 
    { 
     $('#pool_count').css('visibility','hidden'); 
    }); 
} 

function sendMsg(a,ev) 
{ 

    $('#pool_count').css('visibility','hidden');  
    var factid = $("#factid").val(); 
    var floor = $("#floor").val(); 
    var ceiling = $("#ceiling").val(); 
    var pool_count = $('#poolsize').val(); 
    var userid = document.getElementById("userid").innerHTML; 
    $.ajax(
    { 
     type: "POST", 
     url: "generator.php", 
     data: {what:a,name:factid,author:userid,floor:floor,ceiling:ceiling,pool_count:pool_count}, 
     async: false, 
     cache: false, 
     timeout:50000, 
    }); 
} 

這是一個長輪詢網頁。 sendMsg在樹中發送用戶自定義的更改並且不關心響應。 另一個函數waitForMsg是長輪詢ajax請求。當它看到由於sendMsg引起的數據庫更改時,它會再次調用jstree()函數來重新生成樹。 當我在樹中進行更改時,sendMsg第一次發送1個請求,第二次發送2個請求,第三次發送3個請求,依此類推。 我敢肯定,沒有什麼是錯在功能,但在這裏它,以防萬一

function waitForMsg() 
{ 
    var lastupdate = document.getElementById("lastupdate").innerHTML; 
    var msg; 
    $.ajax({ 
     type: "POST", 
     url: "oracle.php", 
     data: {lastupdate:lastupdate}, 
     async: true, 
     cache: false, 
     timeout:20000, 

     success: function(data) 
     { 
      msg = data.split("@"); 
      document.getElementById("lastupdate").innerHTML=msg[0]; 
      document.getElementById("json_db").innerHTML=msg[1]; 
      initPage(); //a <body onready> function which creates the tree again     
      setTimeout('waitForMsg()', 200); 
     }, 
     error: function(XMLHttpRequest, textStatus, errorThrown){ 
          setTimeout('waitForMsg()', 1000); 

     } 
    }); 
} 
+0

嘗試增加e.stopImmediatePropagation()在委託塊 – Mahn

+0

槽糕......它真的沒有做任何事情來增加Ajax請求。它只是開始使默認的窗口上下文菜單開始出現。 –

+0

好吧,那麼你可能必須顯示pool_control後面的代碼 – Mahn

回答

0

的事件,因爲jQuery中的工作方式,每次使用附加功能,如。點擊一個事件() ,該事件被「堆疊」到一個列表中,而不是被取代。

在通俗地說,下面的代碼:

$("#poolbutton").click(function() 
    { 
     $('#pool_count').css('visibility','hidden');  
     sendMsg(id); 
    }); 

沒有告訴jQuery來運行這個當點擊發生,而是添加這應該運行的事情的清單,當點擊被觸發

也就是說,如果附加的事件多次,例如以下列方式:

$("#poolbutton").click(function() 
    { 
     $('#pool_count').css('visibility','hidden');  
     sendMsg(id); 
    }); 

    $("#poolbutton").click(function() 
    { 
     $('#pool_count').css('visibility','hidden');  
     sendMsg(id); 
    }); 

    $("#poolbutton").click(function() 
    { 
     $('#pool_count').css('visibility','hidden');  
     sendMsg(id); 
    }); 

其結果將是(你猜對了)SENDMSG()被調用每次點擊3次,因爲每個附加事件都是獨立處理的。

由於每次調用pool_control時都會附加新的click事件,因此每次調用pool_control()時,結果都是sendMsg()調用的次數,因此ajax請求會增加1次。

修復?無論是在pool_control再結合他們()之前解除綁定click事件:

function pool_control(id,ev) 
{ 

    $("#pool_count").css("left",ev.pageX); 
    $("#pool_count").css("top",ev.pageY); 
    $("#pool_count").css("visibility","visible"); 
    $("#poolbutton").unbind('click').click(function() 
    { 
     $('#pool_count').css('visibility','hidden');  
     sendMsg(id); 
    }); 
    $("#poolcancel").unbind('click').click(function() 
    { 
     $('#pool_count').css('visibility','hidden'); 
    }); 
} 

OR,和我個人比較推薦這種方式,因爲除其他外有更少的開銷,在初始化代碼附加的事件只有一次。您可以將事件,只要你想,這是完全正常的在你的榜樣,呼籲文本菜單代表pool_control()以外的例如前將其附加:

var json_string=$.parseJSON(document.getElementById("json_db").innerHTML); 
$(function() 
{ 
    $("#folder_tree").jstree({ 
     contextmenu: {items: customMenu}, 
     "json_data" : {data:json_string}, 
     "plugins" : [ "themes", "json_data", "ui", "contextmenu" ], 

    }); 
}); 
function customMenu(node) 
{ 
    var items = { }; 
} 

$("#poolbutton").click(function() 
{ 
    $('#pool_count').css('visibility','hidden');  
    sendMsg(id); 
}); 
$("#poolcancel").click(function() 
{ 
    $('#pool_count').css('visibility','hidden'); 
}); 

$('#folder_tree').delegate('a', 'contextmenu', function (e) 
{ 

     idn = $(this).parent().attr("id"); 
     if(idn) pool_control(idn,e); //sendMsg(idn) 

}); 

function pool_control(id,ev) 
{ 
    $("#pool_count").css("left",ev.pageX); 
    $("#pool_count").css("top",ev.pageY); 
    $("#pool_count").css("visibility","visible"); 
} 

這種方法可以確保事件只連接一次,並作爲只要你不摧毀你要去的#pool_count,只要發生點擊而不必在pool_control()中關心它,事件就會被觸發。

+0

是的!它現在可以正常工作!非常感謝! –