3

I am using this code from the SDK Tutorial Website:

var sidebar = require("sdk/ui/sidebar").Sidebar({
    id: 'my-sidebar',
    title: 'My Sidebar',
    url: require("sdk/self").data.url("sidebar.html"),
    onAttach: function (worker) {
       // listen for a "ready" message from the script
       worker.port.on("ready", function() {
       // send an "init" message to the script
       worker.port.emit("init", "message from main.js");
    });
 }
});

This works great. The problem is now that this only allows me to send something via the worker.port onAttach (and on 3 other events for the sidebar). What I need is to use the emit function outside the scope of this sidebar. For example if I use in the same main.js an listener for a tab like

tabs.on('ready', function(tab) {
    sidebar.worker.port.emit("init", "message from main.js");
}

This is not working. I also tried

 sidebar.port.emit("init", "message from main.js");

or

 worker.port.emit("init", "message from main.js");    

Without success.

I have also tried to put the tab listener inside the onAttach of the sidebar (so a listener inside a listener) but that also is not working.

Does anybody have an idea on that one? thanks.

erikvold
  • 15,988
  • 11
  • 54
  • 98
gb5256
  • 191
  • 11
  • 1
    Just an alternative: Maybe dispatch a custom event from your sidebar? https://developer.mozilla.org/en-US/Add-ons/Overlay_Extensions/XUL_School/Appendix_C:_Avoid_using_eval_in_Add-ons?redirectlocale=en-US&redirectslug=XUL_School%2FAppendix_C%3A_Avoid_using_eval_in_Add-ons#Alternative.3A_Dispatch_real_events https://gist.github.com/Noitidart/9288991 – Noitidart Mar 15 '14 at 08:02
  • @Noitidart, thanks for this tip. I have tried it, but the only event that can be used is the sidebar.attach. But that event can not be fired from outside. So I have used now the sidebar.show which seems to fire the sidebar.attach. So whenever the tab changes, the sidebar reloads but is doing what I want. Not the optimal solution, but a quick and dirty. So thanks for this one. – gb5256 Mar 15 '14 at 21:01
  • 1
    I don't know much at all about SDK so dont think my reply was the only possible solution. If you ever go non-sdk though let me know I can help you out. Here's an read made example of how to do a sidebar in boostrap: https://gist.github.com/Noitidart/8728393 – Noitidart Mar 15 '14 at 21:03
  • Ahh, now I know why your name sounded familiar to me. I did actually stumble upon your bootstrap.js some days ago, when I started developing my sidebar. As I come across more and more restrictions within the sdk I am giving your file a try and see how it works. Thanks again. – gb5256 Mar 15 '14 at 21:33
  • Haha cool man I'm so glad to hear people are coming across my tutorials, I hope they help. Let me know if you need any help. SDK has some real heavy restrictions, I've tried to help people out by hack some things up to get past them but came across stuff I couldn't explain. I posted about it and I hear that not too many people know the inner workings of SDK. It's possible but its a ton of digging for something so easy to do in bootstrap. (example topic: https://forums.mozilla.org/addons/viewtopic.php?f=27&t=16038) – Noitidart Mar 16 '14 at 00:19
  • Hi Notidart. Just playing with your solution, looks cool so far. I am right now comparing the two options I have (your bootstrap and the sidebar-sdk), so I do have some questions to make an decision which one to choose... Is there a way to place the sidebar at the left side of the browser (yours is right now on the right side). Is it possible to hide/show the sidebar programatically, like with a button or a menu? – gb5256 Mar 17 '14 at 09:26
  • yes to both. to place on left side replace L#82 `browser.appendChild(splitter);` with `browser.insertBefore(splitter, browser.firstChild);` and then replace L#85 which is `browser.appendChild(sidebar);` with `browser.insertBefore(sidebar, browser.firstChild);` – Noitidart Mar 17 '14 at 10:35
  • to open and close programatically do toggle the `sidebar.hidden` attribute to true for closed and false for open. should probably toggle the hidden attribute on the splitter too – Noitidart Mar 17 '14 at 10:36
  • Notidart: you are my hero. It all works really good and I will post you a link to my extension soon. The final question for me is if it is possible to access the content of one hidden field (ID is known) inside the iframe. So basically I want to send the current URL of the current Tab into the iframe into a hidden field for further processing. Is this possible or will the getElementById not work? – gb5256 Mar 17 '14 at 22:16
  • haha. and you absolutely can but context is important before i answer: when do you want the field pouplated with the url of the current tab? on click of a button in the iframe? or on tab load? – Noitidart Mar 18 '14 at 04:30
  • Inside the iframe is a button which the user clicks, it should take the current URL of the current tab. I have experience with iframes, as this is cross-domain, the iframe can not access the current URL of the parent itself. This one needs to be passed down from outside the iframe into the iframe. So the idea is to use a hidden field inside the iframe and pass the url into this field. As we do not know when (and if) the button will be clicked, I wanted to use postMessage for sending all tab changes into the Field. PostMessage is client side and will not make any calls. – gb5256 Mar 18 '14 at 09:08
  • its hard to answer these questions in comments. but what you do is this after lin , after creating the sidebar add this: `sidebarBrowser.addEventListener('DOMContentLoaded', function (e) { var win = e.originalTarget.defaultView; var btn = win.document.querySelector('#ID_OF_YOUR_BUTTON'); if (btn) { btn.addEventListener('click', function () { var field = win.document.querySelector('#ID OF FIELD'); if (field) { field.value = aDOMWindow.gBrowser.selectedTab.location.href; win.alert('field value updated'); } }, false) } }, false);` – Noitidart Mar 18 '14 at 16:35

1 Answers1

5

Use the method described here:

var workers = [];

function detachWorker(worker, workerArray) {
  var index = workerArray.indexOf(worker);
  if(index != -1) {
    workerArray.splice(index, 1);
  }
}

var sidebar = require("sdk/ui/sidebar").Sidebar({
  ...
  onAttach: function(worker) {
    workers.push(worker);
    worker.on('detach', function () {
      detachWorker(this, workers);
    });
  }
});

Then to emit on open sidebars do:

workers.forEach(worker => {
  worker.port.emit('some-message', data);
})
erikvold
  • 15,988
  • 11
  • 54
  • 98
  • Great answer! I tried using a binding (I only have one sidebar) inside a closure, but I guess the worker changed or something like that. – Reut Sharabani Nov 20 '14 at 00:01