MDN’s new design is in Beta! A sneak peek: https://blog.mozilla.org/opendesign/mdns-new-design-beta/

Criando Alvos de Eventos

Este tutorial descreve o uso de APIS de baixo nível. Estas APIs estão ainda em desenvolvimento, e nós esperamos fazer mudanças incompatíveis nela em lançamentos futuros.

O guia de programação de eventos dirigidos com SDK descreve como consumir eventos: isto é, como escutar eventos gerados pelo alvos de evento. Por exemplo, você pode escutar ao evento evento ready do módulo tab ou o event show do objeto Panel.

Com o SDK, também é simples implementar seus próprios alvos de eventos. Isto é especialmente útil se você quiser construir seus próprios módulos, ou organizar seu add-on melhor ou permitir a outros desenvolvedores reusar seu código. Se você usa o framework de eventos do SDK para seus alvos de eventos, os usuários de seus módulos podem escutar pelos eventos usando a API de evento padrão do SDK.

Neste tutorial nów criaremos parte de um módulo para acessar a API Local do navegador. Ele emitirá eventos quando o usuário adicionar e visitar um favorito, permitindo aos usuários escutar estes eventos usando a API de evento padrão do SDK.

Usando a API Local

Primeiro, vamos escrever algun código usando a API Local que registra as URIs do favorito que o usuário adicinou.

Crie uma novo diretório chamado "bookmarks", navegue até ele, e execute jpm init, aceitando todos os padrões. Então abra o "index.js" e adicione o seguinte código:

var {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
var bookmarkService = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]
                          .getService(Ci.nsINavBookmarksService);
 
var bookmarkObserver = {
  onItemAdded: function(aItemId, aFolder, aIndex) {
    console.log("added ", bookmarkService.getBookmarkURI(aItemId).spec);
  },
  onItemVisited: function(aItemId, aVisitID, time) {
    console.log("visited ", bookmarkService.getBookmarkURI(aItemId).spec);
  },
  QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
};
 
exports.main = function() {
  bookmarkService.addObserver(bookmarkObserver, false);   
};
 
exports.onUnload = function() {
  bookmarkService.removeObserver(bookmarkObserver);
}

Tente executar este add-on, adicionando e visitando favoritos, e observando a saída no console.

Módulos como Alvos de Evento

Nós podemos adaptar esse código em módulos separados que expõe a interface de evento padrão do SDK.

Para fazer isso nós usaremos o módulo event/core.

Crie um novo arquivo no "lib" chamado "bookmarks.js", e adicione o seguinte código:

var { emit, on, once, off } = require("sdk/event/core");
 
var {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
var bookmarkService = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]
                          .getService(Ci.nsINavBookmarksService);
 
var bookmarkObserver = {
  onItemAdded: function(aItemId, aFolder, aIndex) {
    emit(exports, "added", bookmarkService.getBookmarkURI(aItemId).spec);
  },
  onItemVisited: function(aItemId, aVisitID, time) {
    emit(exports, "visited", bookmarkService.getBookmarkURI(aItemId).spec);
  },
  QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
};
 
bookmarkService.addObserver(bookmarkObserver, false);
 
exports.on = on.bind(null, exports);
exports.once = once.bind(null, exports);
exports.removeListener = function removeListener(type, listener) {
  off(exports, type, listener);
};

Este código implementa um módulo que pode emitir eventos added e visited. Ele duplica o código anterior, mas com um pouco de mudanças:

  • importe emit(), on(), once(), e off() do event/core
  • substitua as funções de escuta com chamadas para emit(), passando o tipo de evento apropriado
  • exporte sua própria API de evento. Este consiste de três funções:
    • on(): inicia a escuta pelo evento ou um dado tipo
    • once(): escuta pela ocorrência de um dado evento, e então para
    • removeListener(): para a escuta por eventos de um dado tipo

O on() e once() exporta delegação a uma função correspondente do event/core, e usa bind() para passar o objeto exports por si só como o argumento target(alvo) à função subjacente. A função removeListener() é implementada pela chamada da função subjacente  off().

Nós podemos usar este módulo do mesmo modo que nós usamos qualquer outro módulo que emite eventos a nível de módulo, tais como tabs. Por exemplo, nós podemos adaptar o "index.js" como segue:

var bookmarks = require("./bookmarks");
 
function logAdded(uri) {
  console.log("added: " + uri);
}
 
function logVisited(uri) {
  console.log("visited: " + uri);
}
 
exports.main = function() {
  bookmarks.on("added", logAdded);
  bookmarks.on("visited", logVisited);
};
 
exports.onUnload = function() {
  bookmarks.removeListener("added", logAdded);
  bookmarks.removeListener("visited", logVisited);
}

Classes como Alvos de Eventos

Às vezes nós queremos emitir eventos à nível de objetos individuais, em vez de à nível de módulo.

Para fazer isto, nós podemos herdar da classe EventTarget do SDK. EventTarget fornece uma implementação das funções necessárias a adicionar e remover escutas: on(), once(), e removeListener().

Neste exemplo, nós poderíamos definir uma classe BookmarkManager que herda do EventTarget e emite eventos added e visited.

Abra o "bookmarks.js" e substitua seu conteúdo com este código:

var { emit } = require("sdk/event/core");
var { EventTarget } = require("sdk/event/target");
var { Class } = require("sdk/core/heritage");
var { merge } = require("sdk/util/object");
 
var {Cc, Ci, Cu} = require("chrome");
Cu.import("resource://gre/modules/XPCOMUtils.jsm", this);
var bookmarkService = Cc["@mozilla.org/browser/nav-bookmarks-service;1"]
                          .getService(Ci.nsINavBookmarksService);
 
function createObserver(target) {
   var bookmarkObserver = {
     onItemAdded: function(aItemId, aFolder, aIndex) {
       emit(target, "added", bookmarkService.getBookmarkURI(aItemId).spec);
     },
     onItemVisited: function(aItemId, aVisitID, time) {
       emit(target, "visited", bookmarkService.getBookmarkURI(aItemId).spec);
     },
     QueryInterface: XPCOMUtils.generateQI([Ci.nsINavBookmarkObserver])
   };
   bookmarkService.addObserver(bookmarkObserver, false);
}
 
var BookmarkManager = Class({
  extends: EventTarget,
  initialize: function initialize(options) {
    EventTarget.prototype.initialize.call(this, options);
    merge(this, options);
    createObserver(this);
  }
});
 
exports.BookmarkManager = BookmarkManager;

O código para interagir com a API Local é o mesmo que aqui. Porém:

  • nós estamos agora importando de quatro módulos:
    • event/core nos dá emit(): note que nós não precisamos on, once, ou off, desde que nós usaremos EventTarget para adicionar e remover escutas
    • event/target nos dá EventTarget, que implementa a interface para adicionar e remover escutas
    • core/heritage nos dá Class(), que nós podemos usar para herdar do EventTarget
    • util/object nos dá merge(), que apenas simplifica a configuração das propriedades do BookmarkManager
  • nós usamos classe para herdar do EventTarget. Em sua função initialize(), nós:
    • chamar o inicializador de classe base
    • use merge() para copiar qualquer opção fornecida dentro do novíssimo objeto criado
    • chama createObserver(), passando o novíssimo objeto criado como o alvo do evento
  • createObserver() é o mesmo do exemplo anterior, exceto que no emit() nós passamos o BookmarkManager criado como o alvo do evento

Para usar este alvo de evento nós podemos criar ele e chamar a funções on(), once(), e removeListener() que ele herdou:

var bookmarks = require("./bookmarks");
var bookmarkManager = bookmarks.BookmarkManager({});
 
function logAdded(uri) {
  console.log("added: " + uri);
}
 
function logVisited(uri) {
  console.log("visited: " + uri);
}
 
exports.main = function() {
  bookmarkManager.on("added", logAdded);
  bookmarkManager.on("visited", logVisited);
};
 
exports.onUnload = function() {
  bookmarkManager.removeListener("added", logAdded);
  bookmarkManager.removeListener("visited", logVisited);
}

Implementando uma opção "onEvent"

Finalmente, a maioria dos alvos de eventos aceitam opções na forma "onEvent", onde "Event" é o nome do evento com a primeira letra em maiúsculo. Por exemplo, você pode escutar o evento show do objeto Panel ou chamando:

myPanel.on("show", listenerFunction);

ou passando a opção onShow para o construtor do Painel:

var myPanel = require("sdk/panel").Panel({
  onShow: listenerFunction,
  contentURL: "https://en.wikipedia.org/w/index.php"
});

Se sua classe herda do EventTarget, opções como this são automaticamente manipuladas para você. Por exemplo, dada a implementação do BookmarkManager acima, seu "index.js" seria reescrito como isto:

var bookmarks = require("./bookmarks");
 
function logAdded(uri) {
  console.log("added: " + uri);
}
 
function logVisited(uri) {
  console.log("visited: " + uri);
}
 
var bookmarkManager = bookmarks.BookmarkManager({
  onAdded: logAdded,
  onVisited: logVisited
});
 
exports.onUnload = function() {
  bookmarkManager.removeListener("added", logAdded);
  bookmarkManager.removeListener("visited", logVisited);
}

Etiquetas do documento e colaboradores

 Colaboradores desta página: Pheanor
 Última atualização por: Pheanor,