How to change the label of widget(Firefox Add-on SDK) - firefox

I want to change the label of a widget when user click it, then I write the code looks like this:
var widgets = require("sdk/widget");
var statusBar = widgets.Widget({
id: "patchouliStatus",
label: "Wait Page Loading...",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(){
this.contentURL = "http://www.google.com/favicon.ico";
this.label = "Clicked";
}
});
When I click the widget, the icon has changed, but nothing happen to the label.I move the mouse to the widget and it still show "Wait Page Loading...".Is there a way to dynamically change the label?
Firefox: v27.0.1
Add-on SDK: v1.15

Widget's label is read-only. You must use tooltip attribute to show the user a text on mouse hover, this way:
var widgets = require("sdk/widget");
var statusBar = widgets.Widget({
id: "patchouliStatus",
label: "Wait Page Loading...",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(){
this.contentURL = "http://www.google.com/favicon.ico";
this.tooltip = "Clicked";
}
});
As docs says somewhere in this section -I think it could be more clearly documented-, tooltip value is an "optional text to show when the user's mouse hovers over the widget. If not given, the label is used". Also, examples in that section don't make it clear enough as I think they should.

Ok man thanks for the XPI, change changeLabel function to this, my above was really bugged.
function changeLabel(str){
var DOMWindows = Services.wm.getEnumerator('navigator:browser');
while (DOMWindows.hasMoreElements()) {
var aDOMWindow = DOMWindows.getNext();
var myWidget = aDOMWindow.document.getElementById('widget:jid1-njALX8gXKY872g#jetpack-patchouliStatus');
if (myWidget) {
Services.appShell.hiddenDOMWindow.console.info('myWidget:', myWidget);
myWidget.setAttribute('label', str);
myWidget.setAttribute('tooltiptext', 'tooltip changed');
} else {
Services.appShell.hiddenDOMWindow.console.info('myWidget null:', myWidget);
}
}
}
It also seems that the id of your widget starts with tyour addon id name.
Now I gave you the enumerator function because that goes over all windows and you can add event listener. But really if you just want to target the one that was clicked just get the most recent window, as that will obviously hold the correct window with your widget as we just clicked there and the event listener fires on click.
Change changeLabel to this:
function changeLabel(str){
var aDOMWindow = Services.wm.getMostRecentWindow('navigator:browser');
var myWidget = aDOMWindow.document.getElementById('widget:jid1-njALX8gXKY872g#jetpack-patchouliStatus');
if (myWidget) {
Services.appShell.hiddenDOMWindow.console.info('myWidget:', myWidget);
myWidget.setAttribute('label', str);
myWidget.setAttribute('tooltiptext', 'tooltip changed');
} else {
Services.appShell.hiddenDOMWindow.console.info('myWidget null:', myWidget);
}
}
Also that Services.appShell.hiddenDOMWindow.console.info is just something nice to debug, I left it in there so you can see how it works. It logs to "Browser Console" (Ctrl+Shift+J).
As a final note I used a non-sdk solution by requiring chrome. they advise you not to do that because they want you to use the SDK functions I don't know about SDK but you can use the getEnumerator and recentWindow function by requiring window/utils it looks like:
Read window/utils article here

I'll give you non-sdk solution here but someone will have to help convert it to sdk solution. You can paste this in your code it will work though.
Im not sure how the element is inserted into the dom but I guessed.
var {Cu, Ci} = require('chrome'); //if you want to paste this into scratchpad with with Environemnt set to Browser than dont need this line, this line is for sdk
var DOMWindows = Services.wm.getWindowEnumerator(null);
while (DOMWindows.hasMoreElements()) {
var aDOMWindow = aXULWindow.QueryInterface(Ci.nsIInterfaceRequestor).getInterface(Ci.nsIDOMWindowInternal || Ci.nsIDOMWindow);
var myWidget = aDOMWindow.querySelector('#patchouliStatus'); //im not exactly sure how the element is inserted in the dom but im guessing here
if (myWidget) {
myWidget.label = 'rawr';
}
}

Related

firexfox extension toggle on off on icon click

I develop my first firefox extension. My usecase (already sucessfully implemented as a chrome extension):
Inject CSS of a specific page
Default load: contentscript-on.js
On Click icon (icon-on.png / icon-off.png) switch from contentscript-on.js to contentscript-off.js and backward
The contentscript-on.js already works on page load. I´ve searched a lot to find help or an example for my usecase. Any ideas?
Thank you very much!
main.js
var pageMod = require("sdk/page-mod");
var self = require("sdk/self");
pageMod.PageMod({
include: "https://app.example.de/dashboard",
contentScriptFile: [self.data.url("jquery-1.11.0.min.js"), self.data.url("contentscript-on.js")]
});
In my chrome extension, I use a background.js to toggle on / off and switch between the scripts
//toggle = true, because the contenscript-on.js is already loaded on initial loading of the page
var toggle = true;
chrome.browserAction.onClicked.addListener(function(tab) {
toggle = !toggle;
if(toggle){
//change the icon after pushed the icon to On
chrome.browserAction.setIcon({path: "icon-on.png", tabId:tab.id});
//start the content script to hide dashboard
chrome.tabs.executeScript({file:"contentscript-on.js"});
}
else{
//change the icon after pushed the icon to Off
chrome.browserAction.setIcon({path: "icon-off.png", tabId:tab.id});
//start the content script to hide dashboard
chrome.tabs.executeScript({file:"contentscript-off.js"});
}
});
Is there a similar way to this in firefox extensions?
The PageMod constructor has an optional onAttach property which passes a content worker to your function. This worker can be destroyed to remove the scripts from the page
var contentWorker; // Global (or greater scope) variable
// …
onAttach: function(worker) {
contentWorker = worker;
}
Then, in your click listener
var tab = contentWorker.tab;
contentWorker.destroy();
contentWorker = tab.attach( {
contentScriptFile: [self.data.url("jquery-1.11.0.min.js"), self.data.url("contentscript-off.js")]
});
Frankly, it would probably be easier just to attach both and toggle them somehow from within the content script code
As a side note, there's a new toggle button that you can can use that will have an activated/deactivated look that sounds like it would be good for your scenario.

How to add Toolbar Button for Firefox Australis

I used below code to add toolbar buttons automatically in navigation toolbar below Firefox Australis.
var buttonId = "toolbarbutton-toolbarbutton";
var navBar = document.getElementById("nav-bar");
var currentSet = navBar.currentSet;
var curSet = currentSet.split(",");
if (curSet.indexOf(buttonId) == -1)
{
navBar.insertItem(buttonId);
navBar.setAttribute("currentset", navBar.currentSet);
document.persist("nav-bar", "currentset");
try
{
top.BrowserToolboxCustomizeDone(true);
}
catch (e)
{
}
}
Because user interface and modules changed for Australis, the code needs to be updated. How can I add Toolbar Button for Australis proper way?
You have to use the CustomizableUI module:
try
{
Components.utils.import("resource:///modules/CustomizableUI.jsm");
CustomizableUI.createWidget({
id: "toolbarbutton-toolbarbutton",
defaultArea: "nav-bar",
removable: true,
label: "My button",
tooltiptext: "My tooltip text",
onClick: function()
{
alert("Clicked");
}
});
}
catch (e)
{
Components.utils.reportError(e);
// No such module? Try the old approach.
...
}
Note that the widget no longer needs to be added for each browser window, it is enough to do it once. Unfortunately, the module documentation is practically non-existent right now, the code above has been deduced from module's source code. The documentation should improve soon however.
If it helps, Adblock Plus source code contains an emulation of the CustomizableUI API for older Firefox versions. This one is far from complete however, it is only meant to cover the needs of Adblock Plus.

Firefox Addon builder: how to keep a panel shown

I have done a firefox addon using the Addon Builder. This addon display a panel containing a web page.
The problem I have is that I would like to keep this panel displayed and probably had a close button to hide it. Actually the panel disappear when we click out of the panel.
This is the code I use to make my panel:
var HauteurPopup = 400;
var LargeurPopup = 650;
function getPanel(contentURL){
var popupPanel = require("panel").Panel({
width:LargeurPopup,
height:HauteurPopup,
contentURL: contentURL
});
return popupPanel;
}
var btn = require("toolbarbutton").ToolbarButton({
id: 'propelink-button',
label: 'Propulesez ce lien!',
image: 'https://www.users.prplk.com/img/mini-logo-propel-bar.jpg',
onCommand: function() {
if (typeof(tabs.activeTab._worker) == 'undefined') {
let worker = tabs.activeTab.attach({
contentScript: btnContentScript
});
tabs.activeTab._worker = worker;
}
tabs.activeTab._worker.port.emit("btnContentScript");
var panelPopup = myPanel.getPanel("http://example.com");
panelPopup.show();
}
});
Someone know how to keep this panel displayed and close it adding a button?
Thanks in advance
In xul based extensions there is an option in the creation of the panel to accomplish that (panel.noautohide). In firefox-addon-sdk it seems that it doesn't exist. See 595040 – Add a "isPersistent" attribute for panels
Although it is mentioned that you can do a workaround by editing panel.js, but i never tried to do that, but you may want to give it a try.

CKEditor dialog input field above tab elements

I'm building a simple dialog plugin to replace the default link tool. The design calls for a particular layout that is difficult to achieve with the CKEdit dialog definition: We want a single field to appear above the tab elements in the dialog (see illustration).
Can anyone suggest a way that this might be implemented? Thanks!
As far as I can tell it is not possible to achieve this using the built-in dialog definition.
I was able to get around this limitation by building my dialog plugin using the iframedialog plugin. This basically pops up a CKEditor dialog window and loads an external URL into it. You can do anything you want in that iframe, and then return the text to CKEditor when the user presses the OK button.
A simple example:
// plugins/iframelink/plugin.js
CKEDITOR.plugins.add('iframelink', {
requires: ['iframedialog'],
init: function(editor){
CKEDITOR.dialog.addIframe('iframelinkDialog',
// title
'Insert a Link',
// src
this.path + 'dialogs/link.html',
// minWidth
500,
// minHeight
250,
// onContentLoad
);
var cmd = editor.addCommand('iframelink', {exec: iframelinkOnclick});
editor.ui.addButton('iframelink', {
label: 'Insert a Link (Special Link Tool)',
command: 'iframelink',
icon: this.path + 'images/world_link.png'
});
}
});
function iframelinkOnclick(editor){
dialog = editor.openDialog('msiteslinkDialog');
};
// plugins/iframelink/dialogs/iframelink.js
$(function() {
if (typeof(window.parent.CKEDITOR) != 'undefined') {
CKEDITOR = window.parent.CKEDITOR;
var dialog = CKEDITOR.dialog.getCurrent();
var editor = dialog.getParentEditor();
// Get value of the selected text:
var selection = editor.getSelection().getSelectedText();
// Do something when the user presses the OK button:
var okListener = function(ev) {
link = yourFunctionToDoSomethingClever();
this._.editor.insertHtml(link);
dialog.removeListener("ok", okListener);
};
// Bind the OK button to your okListener method:
dialog.on("ok", okListener);
};
}
So you can make the dialog look any way you want:

How to get selected text using the Firefox Add-On SDK?

I'm trying to create a Firefox add-on using the online Add-On SDK.
I'm starting with something simple - I want to add a toolbar button that reads the current selected text.
The documentation for the Selection object makes this looks simple enough:
var selection = require("selection");
if (selection.text)
console.log(selection.text);
This doesn't seem to work for me, I just get null.
Here's my complete code:
var selection = require("selection");
require("widget").Widget({
id: "widgetID1",
label: "Test Mozilla Widget",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(event) {
console.log('selection.text = ' + selection.text);
}
});
I've also tried to create the selection object inside the onClick even, with the same effect.
I am able to use the select event to get notified on new selections, so I guess I can use that instead (and keep the value), but I wonder why the above code isn't working... What am I doing wrong?
The selection variable as defined will only have the selected text as long as it is in focus. Clicking on the widget icon takes focus away from the selected text, so it sees no text selected.
Thats why it works when used inside the listener function.
To confirm this, I tried logging its value when a toolbar button is pressed (using the toolbarbutton module), and it works. Pressing a toolbar button (presumably) does not steal focus.
Here's the code, and you can test it online too:
var selection = require("selection");
var tbb = require("toolbarbutton").ToolbarButton({
id: "test",
label: "test",
image: "http://www.mozilla.org/favicon.ico",
onCommand: function(event) {
console.log('selection = ' + JSON.stringify(selection)); // works!
}
});
Here is a solution using the select event:
var selection = require("selection");
var selectedText = '';
function selectionChanged(event){
//todo: check for selection.isContiguous
selectedText = selection.text;
}
selection.on('select', selectionChanged);
require("widget").Widget({
id: "widgetID1",
label: "Test Mozilla Widget",
contentURL: "http://www.mozilla.org/favicon.ico",
onClick: function(event) {
console.log('Selection: ' + selectedText);
}
});

Resources