Extraits de code:Onglets de navigation
Un article de MDC.
Sur cette page, vous trouverez un ensemble de morceaux de code utiles pour vous aider à travailler avec la navigation par onglets de Firefox. Les commentaires indiquent normalement les endroits où vous devez insérer votre propre code.
Chaque extrait contient en principe du code à exécuter lors de l'initialisation, et le meilleur moyen de la faire est d'utiliser un événement de chargement. Ces morceaux de code sont supposés être exécutés dans le contexte d'une fenêtre de navigation. Si vous devez travailler avec des onglets en dehors d'une fenêtre de navigation, vous devrez au préalable obtenir une référence à une fenêtre, voir Travailler avec des fenêtres dans le chrome pour plus de détails.
Notez que Firefox 2 a rendu la détection des modifications sur les onglets beaucoup plus simple, et si vous ne développez que pour Firefox 2 et suivants, vous devriez utiliser les exemples s'y rapportant. Les exemples pour Firefox 1.5 et précédents devraient fonctionner sous Firefox 2 sans problème.
Consultez également la référence de l'élément XUL tabbrowser. L'objet gBrowser (identique à getBrowser()) est un élément tabbrowser.
[modifier] Accéder au navigateur (Browser)
Le navigateur est un élément tabbrowser situé dans la fenêtre principale de l'application (browser.xul pour Firefox). Si votre extension a accès à la fenêtre principale, commune aux extensions qui recouvrent (overlay) browser.xul, alors le navigateur est accessible par la variable globale gBrowser ou par la fonction getBrowser().
// gBrowser/getBrowser() est uniquement accessible depuis le périmètre de la fenêtre principale gBrowser.addTab(...); getBrowser().addTab(...);
Si votre extension n'a pas accès à la fenêtre principale parce que c'est un panneau latéral ou une boîte de dialogue, vous devez obtenir un accès à la fenêtre principale avant de pouvoir utiliser le navigateur. Vous pourrez trouver plus d'informations quant aux moyens d'accéder à la fenêtre principale dans l'article Travailler avec des fenêtres dans le chrome.
Fondamentalement, si le code de votre extension est dans un panneau latéral, vous pouvez utiliser :
var mainWindow = window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIWebNavigation)
.QueryInterface(Components.interfaces.nsIDocShellTreeItem)
.rootTreeItem
.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
.getInterface(Components.interfaces.nsIDOMWindow);
mainWindow.getBrowser().addTab(...);
Si le code de votre extension est dans une boîte de dialogue ouverte directement depuis la fenêtre principale, vous pouvez utiliser :
window.opener.getBrowser().addTab(...);
Si window.opener ne fonctionne pas, essayez :
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var mainWindow = wm.getMostRecentWindow("navigator:browser");
mainWindow.getBrowser().addTab(...);
[modifier] Ouverture d'un nouvel onglet
// Ajout d'un onglet
gBrowser.addTab("http://www.google.fr/");
// Ajout et activation d'un onglet
gBrowser.selectedTab = gBrowser.addTab("http://www.google.fr/");
[modifier] Fermeture d'un onglet
Cet exemple ferme l'onglet actuellement sélectionné.
gBrowser.removeTab(gBrowser.selectedTab);
[modifier] Modification de l'onglet actif
Cet exemple déplace la sélection vers l'onglet suivant (sur la droite).
gBrowser.mTabContainer.advanceSelectedTab(1, true);
Celui-ci la déplace vers l'onglet sur la gauche.
gBrowser.mTabContainer.advanceSelectedTab(-1, true);
[modifier] Détection du chargement d'une page
function examplePageLoad(event)
{
if (event.originalTarget instanceof HTMLDocument) {
var doc = event.originalTarget;
if (event.originalTarget.defaultView.frameElement) {
// Le cadre au sein de l'onglet a été chargé. doc devrait être le document
// racine du frameset. Si vous ne voulez rien faire quand les frames/iframes
// ont été chargées dans cette page Web, décommentez la ligne suivante :
// return;
// Recherche du document racine
while (doc.defaultView.frameElement) {
doc=doc.defaultView.frameElement.ownerDocument;
}
}
}
}
// N'essayez pas d'ajouter un callback avant que la fenêtre du
// navigateur n'aie été initialisée. On ajoute un callback à
// l'onglet quand la fenêtre du navigateur est chargée.
window.addEventListener(
"load",
function () {
// Ajoute un callback à lancer chaque fois qu'un document se charge.
// Notez que cela inclut les frames/iframes au sein du document
gBrowser.addEventListener("load", examplePageLoad, true);
},
false
);
...
// Quand la détection n'est plus nécessaire
gBrowser.removeEventListener("load", examplePageLoad, true);
...
[modifier] Notification lorsqu'un onglet est ajouté ou enlevé (<= Firefox 1.5)
function exampleTabAdded(event)
{ // Écoute des nouveaux onglets
if (event.relatedNode != gBrowser.mPanelContainer)
return; //peut être n'importe où dans le DOM (à moins que l'événement ne provienne de l'interface ?)
var browser;
if (event.target.localName == "browser") // SeaMonkey
browser = event.target;
else if (event.target.localName == "vbox") // Firefox
browser = event.target.childNodes[1];
// browser est l'élément XUL du navigateur qui a été ajouté
}
function exampleTabRemoved(event)
{
if (event.relatedNode != gBrowser.mPanelContainer)
return;
var browser;
if (event.target.localName == "browser") // SeaMonkey
browser = event.target;
else if (event.target.localName == "vbox") // Firefox
browser = event.target.childNodes[1];
// browser est l'élément XUL du navigateur qui a été supprimé
}
// Pendant l'initialisation
var container = gBrowser.mPanelContainer;
container.addEventListener("DOMNodeInserted", exampleTabAdded, false);
container.addEventListener("DOMNodeRemoved", exampleTabRemoved, false);
// Quand les événements ne sont plus nécessaires
container.removeEventListener("DOMNodeInserted", exampleTabAdded, false);
container.removeEventListener("DOMNodeRemoved", exampleTabRemoved, false);
[modifier] Notification lorsqu'un onglet est ajouté ou enlevé (Firefox 2+)
function exampleTabAdded(event)
{
var browser = event.target.linkedBrowser;
// browser est l'élément XUL du navigateur qui a été ajouté
}
function exampleTabMoved(event)
{
var browser = event.target.linkedBrowser;
// browser est l'élément XUL du navigateur qui a été déplacé
}
function exampleTabRemoved(event)
{
var browser = event.target.linkedBrowser;
// browser est l'élément XUL du navigateur qui a été supprimé
}
// Pendant l'initialisation
var container = gBrowser.tabContainer;
container.addEventListener("TabOpen", exampleTabAdded, false);
container.addEventListener("TabMove", exampleTabMoved, false);
container.addEventListener("TabClose", exampleTabRemoved, false);
// Quand les événements ne sont plus nécessaires
container.removeEventListener("TabOpen", exampleTabAdded, false);
container.removeEventListener("TabMove", exampleTabMoved, false);
container.removeEventListener("TabClose", exampleTabRemoved, false);
[modifier] Détection de la sélection d'un onglet (<= Firefox 1.5)
Le code suivant permet de détecter la sélection d'un nouvel onglet du navigateur :
function exampleTabSelected(event)
{
var browser = gBrowser.getBrowserAtIndex(gBrowser.mTabContainer.selectedIndex);
// browser est l'onglet sélectionné
}
// Pendant l'initialisation
var container = gBrowser.mPanelContainer;
container.addEventListener("select", exampleTabSelected, false);
// Quand les événements ne sont plus nécessaires
var container = gBrowser.mPanelContainer;
container.removeEventListener("select", exampleTabSelected, false);
[modifier] Détection de la sélection d'un onglet (Firefox 2+)
Le code suivant permet de détecter la sélection d'un nouvel onglet du navigateur :
function exampleTabSelected(event)
{
var browser = gBrowser.selectedTab;
// browser est l'onglet sélectionné
}
// Pendant l'initialisation
var container = gBrowser.tabContainer;
container.addEventListener("TabSelect", exampleTabSelected, false);
// Quand les événements ne sont plus nécessaires
container.removeEventListener("TabSelect", exampleTabSelected, false);
[modifier] Récupération du document de l'onglet actif
Le code suivant vous permet de récupérer le document qui se trouve dans l'onglet sélectionné :
gBrowser.selectedBrowser.contentDocument;
ou
content.document
Consultez également Travailler avec des fenêtres dans le chrome.
[modifier] Énumération d'onglets
Pour parcourir tous les onglets ouverts dans un navigateur, vous devez d'abord obtenir une référence à la fenêtre de navigation. Si votre code est exécuté depuis un overlay Firefox de browser.xul (par exemple, s'il s'agit d'un bouton d'une barre d'outils ou du gestionnaire click d'un menu), vous pouvez accéder à la fenêtre courante par la variable prédéfinie window. Cependant, si votre code est exécuté depuis sa propre fenêtre (par exemple, une boîte de dialogue de préférence ou d'options), vous pouvez utiliser nsIWindowMediator pour obtenir une fenêtre de navigation.
Ensuite, obtenez l'élément <tabbrowser/>. Vous l'obtenez avec win.gBrowser, où win est la fenêtre de navigation de l'étape précédente. Vous pouvez simplement utiliser gBrowser au lieu de window.gBrowser si vous exécutez dans le contexte d'un overlay browser.xul.
Finalement, utilisez gBrowser.mPanelContainer.childNodes.length pour obtenir le nombre d'onglets ouverts et gBrowser.getBrowserAtIndex() pour obtenir un élément <browser/>. Par exemple :
var num = gBrowser.mPanelContainer.childNodes.length;
for (var i = 0; i < num; i++) {
var b = gBrowser.getBrowserAtIndex(i);
try {
dump(b.currentURI.spec); // Affiche toutes les URLs des onglets ouverts dans la console
} catch(e) {
Components.utils.reportError(e);
}
}
Pour connaître quelles sont les méthodes disponibles pour les éléments <browser/> et <tabbrowser/>, utilisez l'inspecteur DOM ou regardez les liaisons XBL correspondantes dans browser.xml et tabbrowser.xml.
[modifier] Réutilisation d'onglets
Plutôt que d'ouvrir un nouveau navigateur ou un nouvel onglet à chaque fois que vous en avez besoin, il est préférable d'essayer de réutiliser un onglet qui affiche déjà l'URL désirée -- s'il y en a un d'ouvert. En suivant cet exercice, votre extension minimisera la prolifération d'onglets et de navigateurs créés.
[modifier] Réutilisation par URL/URI
Une fonctionnalité classique rencontrée dans de nombreuses extensions est de diriger l'utilisateur vers des URIs chrome:// dans une fenêtre de navigation (par ex., la rubrique d'aide ou À propos) ou des documents HTML externes (liens http(s):// en ligne) lorsqu'il clique sur un lien ou un bouton de l'extension. Le code suivant montre comment réutiliser un onglet existant qui affiche déjà l'URL/URI désiré. Si un tel onglet n'existe pas, un nouveau sera ouvert avec l'URL/URI spécifié.
function openAndReuseOneTabPerURL(url) {
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var browserEnumerator = wm.getEnumerator("navigator:browser");
// Vérifier chaque navigateur avec notre URL
for (var found = false, browserInstance;
browserEnumerator.hasMoreElements() && !found;
browserInstance = browserEnumerator.getNext().getBrowser()) {
// Vérifier chaque onglet de l'instance de ce navigateur
for(var index=0, numTabs = browserInstance.mPanelContainer.childNodes.length;
index < numTabs && !found;
index++) {
var currentTab = browserInstance.getBrowserAtIndex(index);
if (url == currentTab.currentURI.spec) {
// L'URL est déjà ouverte. Sélectionner cet onglet.
browserInstance.selectedTab = currentTab;
// Donner le focus à ce navigateur
browserInstance.focus();
found = true;
}
}
}
// Notre URL n'est pas ouverte. L'ouvrir maintenant.
if (!found) {
var recentWindow = wm.getMostRecentWindow("navigator:browser");
if (recentWindow) {
// Utiliser une fenêtre de navigation existante
recentWindow.delayedOpenTab(url, null, null, null, null);
}
else {
// Aucune fenêtre de navigation n'est ouverte, donc en ouvrir une nouvelle
window.open(url);
}
}
}
[modifier] Réutilisation par d'autres critères
Parfois, vous pouvez réutiliser un onglet déjà ouvert indépendamment de l'URL/URI qui y est affiché. Ceci suppose que l'onglet est ouvert par votre extension, et non par un autre composant de navigation. Vous pouvez réutiliser un onglet arbitraire en lui attachant un attribut personnalisé lors de son ouverture. Plus tard, lorsque vous voulez réutiliser cet onglet, vous devez parcourir tous les onglets ouverts pour chercher celui qui contient l'attribut personnalisé. Si un tel onglet existe, nous modifions son URL/URI et nous le sélectionnons et nous en lui donnons le focus. Si un tel onglet n'existe pas (peut être parce que l'utilisateur l'a fermé ou ne l'a jamais ouvert), nous en créons un nouveau avec notre attribut personnalisé.
function openAndReuseOneTabPerAttribute(attrName, url) {
var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
for (var found = false, index = 0, browserInstance = wm.getEnumerator('navigator:browser').getNext().getBrowser();
index < browserInstance.mTabContainer.childNodes.length && !found;
index++) {
// Récupèrer l'onglet suivant
var currentTab = browserInstance.mTabContainer.childNodes[index];
// Est-ce que cet onglet contient notre attribut personnalisé ?
if (currentTab.hasAttribute(attrName)) {
// Oui--Le sélectionner et lui donner le focus.
browserInstance.selectedTab = currentTab;
// Donner le focus à *ce* navigateur au cas où un autre l'aurait
browserInstance.focus();
found = true;
}
}
if (!found) {
// Notre onglet n'est pas ouvert. L'ouvrir.
var browserEnumerator = wm.getEnumerator("navigator:browser");
var browserInstance = browserEnumerator.getNext().getBrowser();
// Créer l'onglet
var newTab = browserInstance.addTab(url);
newTab.setAttribute("myextension-myattribute", "xyz");
// Donner le focus à l'onglet
browserInstance.selectedTab = newTab;
// Donner le focus à *ce* navigateur au cas où un autre l'aurait
browserInstance.focus();
}
La fonction peut être appelée comme ceci :
openAndReuseOneTabPerAttribute("myextension-myattribute", "http://developer.mozilla.org/").