2011-12-08 30 views
0

我在主窗口上偵聽onload事件,然後在每個瀏覽器/選項卡上(我需要在瀏覽器中最多運行一個代碼)輸入DOMContentLoaded事件,並在代碼在瀏覽器上運行controlExecuted如何在firefox插件中只運行一個代碼實例?

window.addEventListener("load", function(){ 
    try{ 
     var controlExecuted = 0; 
     var appcontent = document.getElementById("appcontent"); // browser 
     if (appcontent && controlExecuted == 0) 
      appcontent.addEventListener("DOMContentLoaded", function docLoader(e){ 
       appcontent.removeEventListener("DOMContentLoaded", docLoader, false); 
       alert('run code') 
       controlExecuted = 1; 
      }, true); 
    }catch(e){ 
     // log! 
    } 
}, false); 

這不行。代碼運行多次,具體取決於瀏覽器/選項卡的數量。

那麼如何在firefox插件中只運行一個代碼實例?

+0

如果將'controlExecuted'變量移動到'load'監聽器之外,會發生什麼?是不是每次'load'在'window'上觸發都創建一個新變量? – robertc

+0

每次創建窗口時都會創建'controlExecuted'。沒關係。 'load'之前或之後並不重要。無論如何我都試過,沒有運氣。謝謝,。 –

+0

但是,它不會爲任何從每個窗口冒出來的「加載」事件創建嗎? – robertc

回答

1

這裏是完整的解決方案,使用JavaScript code modules在firefox插件中只運行一個代碼實例。

// modules/main.jsm 
var EXPORTED_SYMBOLS = ["instancesControl"]; 

var instancesControl = { 
    executed : 0, 
    windowExecuting : 0, 

    get : function(){ 
     return ++instancesControl.executed; 
    }, 
    reset : function(){ 
     instancesControl.executed = 0; 
    }, 
    getWindowExecuting : function(){ 
     return instancesControl.windowExecuting; 
    }, 
    setWindowExecuting : function(id){ 
     instancesControl.windowExecuting = id; 
    } 
}; 

主要調用代碼:

// load instancesControl module 
Components.utils.import("resource://my-own-alias/main.jsm"); 

// identify window that will execute the one-instance code 
var util = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor) 
.getInterface(Components.interfaces.nsIDOMWindowUtils); 
var windowID = util.outerWindowID; 

// listen load window event 
window.addEventListener("load", function(){ 
    var appcontent = document.getElementById("appcontent"); 
    if (appcontent){ 
     // listen load content (on every tab) 
     appcontent.addEventListener("DOMContentLoaded", function docLoader(e){ 
      appcontent.removeEventListener("DOMContentLoaded", docLoader, false); 
      if (instancesControl.get() == 1){ 
       instancesControl.setWindowExecuting(windowID); 

       // this code will run only once no matter 
       // how many tabs or windows user opens. 

      } 
     }, true); 
    } 
}, false); 

// re-init code if executing windows is closed 
window.addEventListener("unload", function(){ 
    if (instancesControl.getWindowExecuting() == windowID){ 
     instancesControl.reset(); 
    } 
}, false); 

當然,你可以改善它。如果你使用@nomikos評論。
THX。

1

正如您已經注意到的,每次打開新的瀏覽器窗口時都會運行您的代碼。你可能沒有意識到的是,在一個窗口中的腳本是在另一個窗口中的相同腳本的完全獨立的。也就是說,每次都會實例化一組新對象,這意味着一個窗口中的controlExecuted與另一個窗口中的controlExecuted不是同一個對象。

有兩大方式的擴展,共享代碼:

  • 創建XPCOM component。這是在瀏覽器擴展中共享代碼的經典,更困難(但非常強大)的方法。

  • 創建一個JavaScript code module(JSM)。簡而言之:

    JavaScript代碼模塊在壁虎1.9引入一個概念,可以 被用於不同的特權作用域之間共享代碼。模塊 也可用於創建以前需要使用JavaScript XPCOM對象的全局JavaScript單例。

您也可以考慮設置該標誌爲用戶偏好,該腳本的每個實例都可以閱讀。這可能是這種簡單用例最簡單的方法。

+0

+1代碼也運行在每個窗口的每個選項卡上。 'controlExecuted'對於每個選項卡都是相同的,因此可以用作標誌。但你是對的。在窗口之間共享代碼不是微不足道的。我使用了「javaScript代碼模塊」。我在代碼中添加了一個答案。謝謝。 –

相關問題