📜 ⬆️ ⬇️

How to make FF more convenient - we write our own buttons

Preamble


I switched to FF from IE for a very long time - I needed a browser with convenient development and debugging tools that allows me to fully customize myself as it was my main work tool — the tool should be convenient.

And FF has completely coped with its duties - maybe I will seem strange to someone - but I spent about 2 months reading the site with the additions and finding the best of them for me to set, configure, etc.
As a result, I received a powerful, well-tuned and convenient program for my needs.

image
')
Despite the fact that I know JS, it never occurred to me to write any extensions under ff for one simple reason - so that I don’t want to - it was already in the extension depository. It lasted until yesterday :)


Yesterday, I thought about something: while working, I always need to switch and go to localhost , where my Apache is spinning with the current project, and to the address where the current release projects are posted on the Internet is quite a standard situation. There are plenty of solutions to the solution - it is possible (and how it was done by me) to hang this thing on mouse gestures, but the problem is that I am simultaneously conducting not one project but several dozens.

You can use your favorites ... but somehow I have a lot of things not related to work there ... the folders there are also an option - but I don’t like it somehow.

Search...


And I began to look for how to do it all beautifully and conveniently.
To start a site with extensions, I did not find anything specifically suitable and was in a somewhat shocked state x_X, but since the fighters in the World Wide Web never lose heart, somewhat surprised I realized that the moment of creating my extension under ff finally came, but how always summed up the engine of progress - namely, laziness.

There was absolutely no desire to understand how to package it, how to install and write localizations to it - however, the solution was found quickly - there is such a wonderful extension that many programmers Custom Buttons probably have, there is an even more sophisticated version of Custom Buttons 2 - who likes what, I chose the first one, since I am guided by the principle if several entities satisfy your needs equally - use the simplest one - yes, it's me - and you can choose based on your principles :)

Then everything is simple - these extensions are some kind of binding that allows you to create your own buttons on the toolbar and implement your own functionality in them. It is written in JS, extended by internal FF objects.

Those. Particularly inquisitive habrarudyam still have to climb and read the documentation :)

The algorithm for adding a button is simple: right-click on the toolbar -> add a button , later after filling in all the required fields and saving the button, you will still need to drag it to the right toolbar using the right-click on the toolbar -> adjust , and then find your button to drag her to the right place.

image

As for the fields:
Name - the name of your button
Picture - the path to the picture, which will be the button (you can specify the path to click base64 - then for the place of the path to the picture you get dataURL, and the picture will be stored in the button itself)

Next tabs
Code - the code that is executed by pressing
Initialization - code executed once when the browser is loaded

Accordingly, all the power of FF in your hands, you can do whatever you want :)
For example, in order to make a separate button to call your favorites just add this:
Code:
if ( ! this .lastChild ) {
var mc = document .getElementById( "bookmarksMenuPopup" );
var mcc = mc.cloneNode( true );
this .appendChild( mcc );
}

var bo = document .getBoxObjectFor( this );
this .lastChild.showPopup ( this , -1, -1, "popup" , "bottomleft" , "topleft" );


* This source code was highlighted with Source Code Highlighter .
if ( ! this .lastChild ) {
var mc = document .getElementById( "bookmarksMenuPopup" );
var mcc = mc.cloneNode( true );
this .appendChild( mcc );
}

var bo = document .getBoxObjectFor( this );
this .lastChild.showPopup ( this , -1, -1, "popup" , "bottomleft" , "topleft" );


* This source code was highlighted with Source Code Highlighter .


Initialization:
is empty
Here I did without a separate initialization code, sticking it and checking into the main code.
Naturally, you can separate it as it should be correctly - by rewriting the entire contents of the first if into the initialization code and removing the if from the code, but so much more :)

Actually by right clicking on our button we will get the Custom Buttons menu with which you can edit the button code, copy the button code - in general, work and change our small extension, while the left click will open your favorites by executing our code.

image

Copying the button code will allow you to create this button in any other FF, and all the fields of your button will be saved there (and, of course, pictures if they were dataURL).

Here it is!


Returning to my personal task and while I was writing code for it, I still had a small functional:
  1. ability to open a specific URL
  2. I wanted to be able to quickly launch the necessary applications (for example, the password keeper)
  3. it would be convenient to be able to run some standard JS code on any page (of course, you can have a look at the FireBug, but sometimes it is even more convenient to click twice than to run through its tabs)
  4. Well, and some kind of roboform , only with a simpler functionality - namely - open the desired URL and fill in the defined fields with specific values

p.3 - I use for example to look at the list of iframes or timers on the page and a lot more for that. Very often I need it.

p.4 - For example, when debugging pages with forms - you can of course fill in the form to save and use - but somehow I didn’t have a friendship with form-fillers for FF :) besides - I finished the project - everything is simple - deleted the record and there is no garbage - All fields are stored in the record itself. You can also argue about expediency, but again for me it would be convenient.

After reading the docks and peeping into the installed extensions, pieces of code such a thing was born (it didn’t work on optimizing the code - because it wasn’t before — I’m happy to accept comments :)):
Code:
var bo = document.getBoxObjectFor( this );
this.lastChild.showPopup ( this, -1, -1, "popup", "bottomleft", "topleft" );


Initialization:
var mitems = [
{
"label" : "localhost" ,
"tip" : "localhost" ,
"image" : "" ,
"type" : "url" ,
"val" : "localhost"
},

"separator" ,
{
"label" : "Google" ,
"tip" : "Google" ,
"image" : "" ,
"type" : "url" ,
"val" : "http://www.google.ru"
},
"separator" ,

{
"label" : "Notepad" ,
"tip" : "Notepad" ,
"image" : "" ,
"type" : "exec" ,
"val" : "c:/windows/notepad.exe"
},

"separator" ,

{
"label" : "other" ,
"tip" : "other" ,
"image" : "" ,
"type" : "submenu" ,
"val" :
[
{
"label" : "JS test" ,
"tip" : "JS test" ,
"image" : "" ,
"type" : "js" ,
"val" : "alert( 'js testing...' );"
},

{
"label" : " FF" ,
"tip" : " FF" ,
"image" : "" ,
"type" : "js" ,
"val" : "goQuitApplication();"
}
]
}
];

function createMenu( label, tip, image ) {
var m = document .createElement( "menu" );
m.setAttribute( "label" , label );
if ( image ) {
m.setAttribute( "class" , "menu-iconic" );
m.setAttribute( "image" , image );
}
if ( tip ) m.tooltipText = tip;

return m;
}

function createMenuItem( label, tip, image ) {
var mi = document .createElement( "menuitem" );
mi.setAttribute( "label" , label );
if ( image ) {
mi.setAttribute( "class" , "menuitem-iconic" ); // "menuitem-iconic bookmark-item"
mi.setAttribute( "image" , image );
}
if ( tip ) mi.tooltipText = tip;

return mi;
}

function executeFile( progPath, arg ) {
progPath = progPath.replace( /\ //gi, "\\" );
try {
var argArray = arg ? arg.split(/\s+/) : [];
var nsILocalFile = Components.classes[ "@mozilla.org/file/local;1" ].getService(Components.interfaces.nsILocalFile);
var nsIProcess = Components.classes[ "@mozilla.org/process/util;1" ].getService(Components.interfaces.nsIProcess);
nsILocalFile.initWithPath(progPath);
nsIProcess.init(nsILocalFile);
nsIProcess.run( false , argArray, argArray.length);
// nsIProcess.close();
return nsILocalFile;
}
catch ( ex ) {
alert( ex.toString() );
return null ;
}
}

function buildMenu( items ) {
var menu, i, t, mi, item;
var self = this ;

menu = document .createElement( "menupopup" );
menu.type = "menu" ;
menu.orient = "horizontal" ;
// menu.id = "myCustomMenu";

for ( i in items ) {
item = items[i];
if ( typeof ( item ) == "string" ) {
switch ( item ) {
case "separator" :
mi = document .createElement( "menuseparator" );
break ;

default :
mi = null ;
break ;
}
}
else {
switch ( item.type ) {
case "url" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = function () {
var b = getBrowser();
b.selectedTab = b.addTab( this .onclick.addr );
b.selectedTab.onload = function () {}
};
mi.onclick.addr = item.val;
break ;

case "urlForm" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = function () {
var item = this .onclick.item;
var b = getBrowser();
var tab = gBrowser.addTab( item.val.addr );
var newTabBrowser = b.getBrowserForTab( tab );
b.selectedTab = tab;
var lf = function ( event ) {
var fields = item.val.fields;
newTabBrowser.removeEventListener( 'load' , lf, true );
setTimeout(
function () {
var doc = newTabBrowser.contentDocument;
var inputs = doc.getElementsByTagName( "input" );
for ( var i in fields ) {
for ( var j = 0; j < inputs.length; j++ ) if ( inputs[j].name == i ) inputs[j].value = fields[i];
}
},
100
);
};
newTabBrowser.addEventListener( "load" , lf, true );
};
mi.onclick.item = item;
break ;

case "js" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = new Function( item.val );
break ;

case "submenu" :
mi = createMenu( item.label, item.tip, item.image );
mi.appendChild( buildMenu( item.val ) );
break ;

case "exec" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = new Function( "this.onclick.executeFile('" + item.val + "')" );
mi.onclick.executeFile = executeFile;
break ;

default :
mi = null ;
break ;
}
}

if ( mi ) menu.appendChild( mi );
}

return menu;
}

this .appendChild( buildMenu( mitems, false ) );


* This source code was highlighted with Source Code Highlighter .
var mitems = [
{
"label" : "localhost" ,
"tip" : "localhost" ,
"image" : "" ,
"type" : "url" ,
"val" : "localhost"
},

"separator" ,
{
"label" : "Google" ,
"tip" : "Google" ,
"image" : "" ,
"type" : "url" ,
"val" : "http://www.google.ru"
},
"separator" ,

{
"label" : "Notepad" ,
"tip" : "Notepad" ,
"image" : "" ,
"type" : "exec" ,
"val" : "c:/windows/notepad.exe"
},

"separator" ,

{
"label" : "other" ,
"tip" : "other" ,
"image" : "" ,
"type" : "submenu" ,
"val" :
[
{
"label" : "JS test" ,
"tip" : "JS test" ,
"image" : "" ,
"type" : "js" ,
"val" : "alert( 'js testing...' );"
},

{
"label" : " FF" ,
"tip" : " FF" ,
"image" : "" ,
"type" : "js" ,
"val" : "goQuitApplication();"
}
]
}
];

function createMenu( label, tip, image ) {
var m = document .createElement( "menu" );
m.setAttribute( "label" , label );
if ( image ) {
m.setAttribute( "class" , "menu-iconic" );
m.setAttribute( "image" , image );
}
if ( tip ) m.tooltipText = tip;

return m;
}

function createMenuItem( label, tip, image ) {
var mi = document .createElement( "menuitem" );
mi.setAttribute( "label" , label );
if ( image ) {
mi.setAttribute( "class" , "menuitem-iconic" ); // "menuitem-iconic bookmark-item"
mi.setAttribute( "image" , image );
}
if ( tip ) mi.tooltipText = tip;

return mi;
}

function executeFile( progPath, arg ) {
progPath = progPath.replace( /\ //gi, "\\" );
try {
var argArray = arg ? arg.split(/\s+/) : [];
var nsILocalFile = Components.classes[ "@mozilla.org/file/local;1" ].getService(Components.interfaces.nsILocalFile);
var nsIProcess = Components.classes[ "@mozilla.org/process/util;1" ].getService(Components.interfaces.nsIProcess);
nsILocalFile.initWithPath(progPath);
nsIProcess.init(nsILocalFile);
nsIProcess.run( false , argArray, argArray.length);
// nsIProcess.close();
return nsILocalFile;
}
catch ( ex ) {
alert( ex.toString() );
return null ;
}
}

function buildMenu( items ) {
var menu, i, t, mi, item;
var self = this ;

menu = document .createElement( "menupopup" );
menu.type = "menu" ;
menu.orient = "horizontal" ;
// menu.id = "myCustomMenu";

for ( i in items ) {
item = items[i];
if ( typeof ( item ) == "string" ) {
switch ( item ) {
case "separator" :
mi = document .createElement( "menuseparator" );
break ;

default :
mi = null ;
break ;
}
}
else {
switch ( item.type ) {
case "url" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = function () {
var b = getBrowser();
b.selectedTab = b.addTab( this .onclick.addr );
b.selectedTab.onload = function () {}
};
mi.onclick.addr = item.val;
break ;

case "urlForm" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = function () {
var item = this .onclick.item;
var b = getBrowser();
var tab = gBrowser.addTab( item.val.addr );
var newTabBrowser = b.getBrowserForTab( tab );
b.selectedTab = tab;
var lf = function ( event ) {
var fields = item.val.fields;
newTabBrowser.removeEventListener( 'load' , lf, true );
setTimeout(
function () {
var doc = newTabBrowser.contentDocument;
var inputs = doc.getElementsByTagName( "input" );
for ( var i in fields ) {
for ( var j = 0; j < inputs.length; j++ ) if ( inputs[j].name == i ) inputs[j].value = fields[i];
}
},
100
);
};
newTabBrowser.addEventListener( "load" , lf, true );
};
mi.onclick.item = item;
break ;

case "js" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = new Function( item.val );
break ;

case "submenu" :
mi = createMenu( item.label, item.tip, item.image );
mi.appendChild( buildMenu( item.val ) );
break ;

case "exec" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = new Function( "this.onclick.executeFile('" + item.val + "')" );
mi.onclick.executeFile = executeFile;
break ;

default :
mi = null ;
break ;
}
}

if ( mi ) menu.appendChild( mi );
}

return menu;
}

this .appendChild( buildMenu( mitems, false ) );


* This source code was highlighted with Source Code Highlighter .
var mitems = [
{
"label" : "localhost" ,
"tip" : "localhost" ,
"image" : "" ,
"type" : "url" ,
"val" : "localhost"
},

"separator" ,
{
"label" : "Google" ,
"tip" : "Google" ,
"image" : "" ,
"type" : "url" ,
"val" : "http://www.google.ru"
},
"separator" ,

{
"label" : "Notepad" ,
"tip" : "Notepad" ,
"image" : "" ,
"type" : "exec" ,
"val" : "c:/windows/notepad.exe"
},

"separator" ,

{
"label" : "other" ,
"tip" : "other" ,
"image" : "" ,
"type" : "submenu" ,
"val" :
[
{
"label" : "JS test" ,
"tip" : "JS test" ,
"image" : "" ,
"type" : "js" ,
"val" : "alert( 'js testing...' );"
},

{
"label" : " FF" ,
"tip" : " FF" ,
"image" : "" ,
"type" : "js" ,
"val" : "goQuitApplication();"
}
]
}
];

function createMenu( label, tip, image ) {
var m = document .createElement( "menu" );
m.setAttribute( "label" , label );
if ( image ) {
m.setAttribute( "class" , "menu-iconic" );
m.setAttribute( "image" , image );
}
if ( tip ) m.tooltipText = tip;

return m;
}

function createMenuItem( label, tip, image ) {
var mi = document .createElement( "menuitem" );
mi.setAttribute( "label" , label );
if ( image ) {
mi.setAttribute( "class" , "menuitem-iconic" ); // "menuitem-iconic bookmark-item"
mi.setAttribute( "image" , image );
}
if ( tip ) mi.tooltipText = tip;

return mi;
}

function executeFile( progPath, arg ) {
progPath = progPath.replace( /\ //gi, "\\" );
try {
var argArray = arg ? arg.split(/\s+/) : [];
var nsILocalFile = Components.classes[ "@mozilla.org/file/local;1" ].getService(Components.interfaces.nsILocalFile);
var nsIProcess = Components.classes[ "@mozilla.org/process/util;1" ].getService(Components.interfaces.nsIProcess);
nsILocalFile.initWithPath(progPath);
nsIProcess.init(nsILocalFile);
nsIProcess.run( false , argArray, argArray.length);
// nsIProcess.close();
return nsILocalFile;
}
catch ( ex ) {
alert( ex.toString() );
return null ;
}
}

function buildMenu( items ) {
var menu, i, t, mi, item;
var self = this ;

menu = document .createElement( "menupopup" );
menu.type = "menu" ;
menu.orient = "horizontal" ;
// menu.id = "myCustomMenu";

for ( i in items ) {
item = items[i];
if ( typeof ( item ) == "string" ) {
switch ( item ) {
case "separator" :
mi = document .createElement( "menuseparator" );
break ;

default :
mi = null ;
break ;
}
}
else {
switch ( item.type ) {
case "url" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = function () {
var b = getBrowser();
b.selectedTab = b.addTab( this .onclick.addr );
b.selectedTab.onload = function () {}
};
mi.onclick.addr = item.val;
break ;

case "urlForm" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = function () {
var item = this .onclick.item;
var b = getBrowser();
var tab = gBrowser.addTab( item.val.addr );
var newTabBrowser = b.getBrowserForTab( tab );
b.selectedTab = tab;
var lf = function ( event ) {
var fields = item.val.fields;
newTabBrowser.removeEventListener( 'load' , lf, true );
setTimeout(
function () {
var doc = newTabBrowser.contentDocument;
var inputs = doc.getElementsByTagName( "input" );
for ( var i in fields ) {
for ( var j = 0; j < inputs.length; j++ ) if ( inputs[j].name == i ) inputs[j].value = fields[i];
}
},
100
);
};
newTabBrowser.addEventListener( "load" , lf, true );
};
mi.onclick.item = item;
break ;

case "js" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = new Function( item.val );
break ;

case "submenu" :
mi = createMenu( item.label, item.tip, item.image );
mi.appendChild( buildMenu( item.val ) );
break ;

case "exec" :
mi = createMenuItem( item.label, item.tip, item.image );
mi.onclick = new Function( "this.onclick.executeFile('" + item.val + "')" );
mi.onclick.executeFile = executeFile;
break ;

default :
mi = null ;
break ;
}
}

if ( mi ) menu.appendChild( mi );
}

return menu;
}

this .appendChild( buildMenu( mitems, false ) );


* This source code was highlighted with Source Code Highlighter .



mitems actually an array of our menu items and the menus themselves
set by JS objects, fields:


image

Well, actually our expansion is ready, I will not speak for everyone - and it became more convenient for me.
And, I hope, even if I’m a bit more I will increase the number of users of such a wonderful browser (and maybe something good - and the number of developers of extensions for it :))

I really hope that my article will be useful to someone ...

PS The full code of the button: here

Source: https://habr.com/ru/post/57413/


All Articles