web-dev-qa-db-fra.com

Comment utiliser jQuery dans l'extension Firefox

Je veux utiliser jQuery dans une extension firefox, j'ai importé la bibliothèque dans le fichier xul comme ceci:

<script type="application/x-javascript" src="chrome://myExtension/content/jquery.js"> </script>

mais la fonction $ () n'est pas reconnue dans le fichier xul ni jQuery ().

J'ai cherché sur Google le problème et trouvé des solutions mais personne n'a travaillé avec moi: http://gluei.com/blog/view/using-jquery-inside-your-firefox-extensionhttp://forums.mozillazine.org/viewtopic.php?f=19&t=989465

J'ai également essayé de passer l'objet 'content.document' (qui réfère l'objet 'document') comme paramètre de contexte à la fonction jQuery comme ceci:

$('img',content.document);

mais ne fonctionne toujours pas, est-ce que quelqu'un a déjà rencontré ce problème auparavant?

57
user434917

J'utilise les éléments suivants example.xul:

<?xml version="1.0"?>
<overlay id="example" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
<head></head>
<script type="application/x-javascript" src="jquery.js"></script>
<script type="application/x-javascript" src="example.js"></script>
</overlay>

Et voici un example.js

(function() {
    jQuery.noConflict();
    $ = function(selector,context) { 
        return new jQuery.fn.init(selector,context||example.doc); 
    };
    $.fn = $.prototype = jQuery.fn;

    example = new function(){};
    example.log = function() { 
        Firebug.Console.logFormatted(arguments,null,"log"); 
    };
    example.run = function(doc,aEvent) {
        // Check for website
        if (!doc.location.href.match(/^http:\/\/(.*\.)?stackoverflow\.com(\/.*)?$/i))  
            return;

        // Check if already loaded
        if (doc.getElementById("plugin-example")) return;

        // Setup
        this.win = aEvent.target.defaultView.wrappedJSObject;
        this.doc = doc;

        // Hello World
        this.main = main = $('<div id="plugin-example">').appendTo(doc.body).html('Example Loaded!');
        main.css({ 
            background:'#FFF',color:'#000',position:'absolute',top:0,left:0,padding:8
        });
        main.html(main.html() + ' - jQuery <b>' + $.fn.jquery + '</b>');
    };

    // Bind Plugin
    var delay = function(aEvent) { 
        var doc = aEvent.originalTarget; setTimeout(function() { 
            example.run(doc,aEvent); 
        }, 1); 
     };
    var load = function() { 
        gBrowser.addEventListener("DOMContentLoaded", delay, true); 
    };
    window.addEventListener("pageshow", load, false);

})();
28
sunsean

La solution suivante permet d'utiliser jQuery dans contentScriptFile (Targetting 1.5 Addon-sdk)

Dans votre main.js:

exports.main = function() {
    var pageMod = require("page-mod");

    pageMod.PageMod({
          include: "*",
          contentScriptWhen: 'end',
          contentScriptFile: [data.url("jquery-1.7.1-min.js") , data.url("notifier.js") ,   data.url("message.js")],
          onAttach: function onAttach(worker) {
             //show the message
             worker.postMessage("Hello World");
          }
    });

};

Dans votre message.js:

self.on("message", function(message){
    if(message !== "undefined"){
       Notifier.info(message); 
    }
});

Certains pièges que vous devez surveiller:

  • L'ordre du tableau contentScriptFile. si message.js serait placé en premier: jQuery ne sera pas reconstitué.
  • Ne placez pas d'URL http: // dans le data.url (cela ne fonctionne pas)!
  • Tous vos fichiers javascript doivent être dans le dossier de données. (seul main.js doit se trouver dans le dossier lib)
10
David

Il y a un excellent article dans les forums mozillaZine qui décrit cette étape par étape: http://forums.mozillazine.org/viewtopic.php?f=19&t=2105087

Je ne l'ai pas encore essayé, donc j'hésite à dupliquer les informations ici.

3
Skrud

Il s'avère que la première réponse actuelle par @sunsean ne fonctionne pas comme prévu lorsqu'il s'agit de gérer plusieurs charges . La fonction doit se fermer correctement sur le document et éviter l'état global.

De plus, vous devez appeler jQuery.noConflict(true) pour vraiment éviter les conflits avec d'autres modules complémentaires!

C'est à qui je l'écrirais (là encore, j'éviterais jquery (dans les add-ons) comme la peste ...). D'abord la superposition XUL

<?xml version="1.0"?>
<overlay id="test-addon-overlay" xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">
  <script type="text/javascript" src="jquery.js"/>
  <script type="text/javascript" src="overlay.js"/>
</overlay>

Et puis le script de superposition:

// Use strict mode in particular to avoid implicitly var declarations
(function() {
  "use strict";

  // Main runner function for each content window.
  // Similar to SDK page-mod, but without the security boundaries.
  function run(window, document) {
    // jquery setup. per https://stackoverflow.com/a/496970/484441
    $ = function(selector,context) {
      return new jq.fn.init(selector,context || document); 
    };
    $.fn = $.prototype = jq.fn;

    if (document.getElementById("my-example-addon-container"))  {
      return;
    }
    let main = $('<div id="my-example-addon-container">');
    main.appendTo(document.body).text('Example Loaded!');
    main.click(function() { //<--- added this function
      main.text(document.location.href);
    });
    main.css({
      background:'#FFF',color:'#000',position:'absolute',top:0,left:0,padding:8
    });
  };

  const log = Components.utils.reportError.bind(Components.utils);

  // Do not conflict with other add-ons using jquery.
  const jq = jQuery.noConflict(true);

  gBrowser.addEventListener("DOMContentLoaded", function load(evt) {
    try {
      // Call run with this == window ;)
      let doc = evt.target.ownerDocument || evt.target;
      if (!doc.location.href.startsWith("http")) {
        // Do not even attempt to interact with non-http(s)? sites.
        return;
      }
      run.call(doc.defaultView, doc.defaultView, doc);
    }
    catch (ex) {
      log(ex);
    }
  }, true);
})();

Voici n complément complet sous forme de Gist . Il suffit de déposer une copie de jquery et ça devrait être bon d'y aller.

2
nmaier

Je pense que c'est ce que disait Eric, mais vous pouvez charger directement Javascript depuis l'URL.

javascript:var%20s=document.createElement('script');s.setAttribute('src','http://YOURJAVASCRIPTFILE.js');document.getElementsByTagName('body')[0].appendChild(s);void(s);

Je suppose que vous voulez que votre extension charge JQuery afin que vous puissiez manipuler facilement les éléments de la page? Les laboratoires de mon entreprise ont quelque chose qui fait cela en utilisant Javascript directement ici: http://parkerfox.co.uk/labs/pixelperfect

2
Craig Stanford

Au lieu de

$('img',content.document);

tu peux essayer

$('img',window.content.document);

Dans mon cas, cela fonctionne.

0
Alexander Loginov

Cela peut être une mauvaise pratique, mais avez-vous envisagé de l'inclure en ligne?

0
Eric Wendelin