Changing erik vold toolbarbutton image on the fly - javascript

I'm trying to make a firefox extension with the SDK. (if I can avoid XUL i'm happy)
I'm using erik vold toolbarbutton
But I need to change the toolbar image on the fly.
My lib/main.js (background page) is :
var tbb = require("toolbarbutton").ToolbarButton({
id: "My-button",
label: "My menu",
image: Data.url('off.png'),
onCommand: function(){
Tabs.open(Data.url("signin.html"));
}
});
tbb.setIcon({image:Data.url('on.png')});
console.log(tbb.image);
tbb.moveTo({
toolbarID: "nav-bar",
forceMove: false // only move once
});
tbb.image is correct, but the button isn't refreshed.
I tried to change packages/toolbarbutton-jplib/lib/toolbarbutton.js
function setIcon(aOptions) {
options.image = aOptions.image || aOptions.url;
getToolbarButtons(function(tbb) {
tbb.image = options.image;
tbb.setAttribute("image", options.image); // added line
}, options.id);
return options.image;
}
But it doesn't seem to refresh...
Is erik vold lib enough for this kind of need ?

also be sure to update with this fix https://github.com/voldsoftware/toolbarbutton-jplib/pull/13/files

there is a setIcon method and a image setter that you can use to update the toolbar button's image

I had the same problem so I just wrote the code my self using this tutorial:
http://kendsnyder.com/posts/firefox-extensions-add-button-to-nav-bar
Try this, I rewrote my code to fit your needs:
var btn = null;
var btnId = 'My-button';
var btnLabel = 'My menu';
var btnIconOn = 'on.png';
var btnIconOff = 'off.png';
var {Cc, Ci} = require('chrome');
var self = require("sdk/self");
var mediator = Cc['#mozilla.org/appshell/window-mediator;1'].getService(Ci.nsIWindowMediator);
// exports.main is called when extension is installed or re-enabled
exports.main = function(options, callbacks) {
btn = addToolbarButton();
// do other stuff
};
// exports.onUnload is called when Firefox starts and when the extension is disabled or uninstalled
exports.onUnload = function(reason) {
removeToolbarButton();
// do other stuff
};
// add our button
function addToolbarButton() {
// this document is an XUL document
var document = mediator.getMostRecentWindow('navigator:browser').document;
var navBar = document.getElementById('nav-bar');
if (!navBar) {
return;
}
var btn = document.createElement('toolbarbutton');
btn.setAttribute('id', btnId);
btn.setAttribute('type', 'button');
// the toolbarbutton-1 class makes it look like a traditional button
btn.setAttribute('class', 'toolbarbutton-1');
// the data.url is relative to the data folder
btn.setAttribute('image', self.data.url(btnIconOff));
btn.setAttribute('orient', 'horizontal');
// this text will be shown when the toolbar is set to text or text and iconss
btn.setAttribute('label', btnLabel);
navBar.appendChild(btn);
return btn;
}
function removeToolbarButton() {
// this document is an XUL document
var document = mediator.getMostRecentWindow('navigator:browser').document;
var navBar = document.getElementById('nav-bar');
var btn = document.getElementById(btnId);
if (navBar && btn) {
navBar.removeChild(btn);
}
}
btn.addEventListener('click', function() {
Tabs.open(Data.url("signin.html"));
}, false);
tbb.setIcon({image:self.data.url(btnIconOn)});

Related

Remove dynamically created elements by class name Javascript

So, in plain terms I am creating a Chrome Extension that so far can only save links from the internet but not delete them. What I want to add is a "remove" button for deleting unwanted links. So far I haven't got that to work.
The buttons I want to remove are added using JavaScript. Each new block of HTML features a "remove" button but clicking that button does nothing. I have tried binding listeners to each element using a for loop but that doesn't seem to work.
The code runs without errors and I'm certain that the issue is a slight oversight but I have only just started using JavaScript so I'm lost for solutions at the moment.
I have included all the code because I don't want to leave out anything that might be imperative to finding a solution.
It starts with the code for adding a link, followed by removing a single link and then removing all links at once. Thank you all for any help, really want to get this working.
https://github.com/mmmamer/Drop Repository for the rest of the code. Mainly popup.html and popup.css.
var urlList = [];
var i = 0;
document.addEventListener('DOMContentLoaded', function() {
getUrlListAndRestoreInDom();
// event listener for the button inside popup window
document.getElementById('save').addEventListener('click', addLink);
});
function addLink() {
var url = document.getElementById("saveLink").value;
addUrlToListAndSave(url);
addUrlToDom(url);
}
function getUrlListAndRestoreInDom() {
chrome.storage.local.get({
urlList: []
}, function(data) {
urlList = data.urlList;
urlList.forEach(function(url) {
addUrlToDom(url);
});
});
}
function addUrlToDom(url) {
// change the text message
document.getElementById("saved-pages").innerHTML = "<h2>Saved pages</h2>";
var newEntry = document.createElement('li');
var newLink = document.createElement('a');
var removeButton = document.createElement('button');
removeButton.textContent = "Remove";
//removeButton.createElement('button');
removeButton.type = "button";
removeButton.className = "remove";
newLink.textContent = url;
newLink.setAttribute('href', url);
newLink.setAttribute('target', '_blank');
newEntry.appendChild(newLink)
newEntry.appendChild(removeButton);
newEntry.className = "listItem";
document.getElementById("list").appendChild(newEntry);
}
function addUrlToListAndSave(url) {
urlList.push(url);
saveUrlList();
//}
}
function saveUrlList(callback) {
chrome.storage.local.set({
urlList
}, function() {
if (typeof callback === 'function') {
//If there was no callback provided, don't try to call it.
callback();
}
});
}
// remove a single bookmark item
document.addEventListener('DOMContentLoaded', function() {
getUrlListAndRestoreInDom();
var allButtons = document.getElementsByClassName('remove');
function listenI(i) {
allButtons[i].addEventListener('click', () => removeMe(i));
}
for (var i = 0; i < allButtons.length; i++) {
listenI(i);
}
});
function removeMe(i) {
var fullList = documents.getElementsByClassName('listItem');
listItem[i].parentNode.removeChild(listItem[i]);
}
//remove all button
document.addEventListener('DOMContentLoaded', function() {
document.getElementById("remove-all").addEventListener('click', function() {
var removeList = document.getElementsByClassName("listItem");
while(removeList[0]) {
removeList[0].parentNode.removeChild(removeList[0]);
}
})
});
chrome.storage.local.get() is asynchronous. So when you try to add the event listeners to the Remove buttons, they're not in the DOM yet.
You can add the listener in the addUrlToDom() function instead. That way you'll also add the event listener when you create new buttons.
function addUrlToDom(url) {
// change the text message
document.getElementById("saved-pages").innerHTML = "<h2>Saved pages</h2>";
var newEntry = document.createElement('li');
var newLink = document.createElement('a');
var removeButton = document.createElement('button');
removeButton.textContent = "Remove";
//removeButton.createElement('button');
removeButton.type = "button";
removeButton.className = "remove";
newLink.textContent = url;
newLink.setAttribute('href', url);
newLink.setAttribute('target', '_blank');
newEntry.appendChild(newLink)
newEntry.appendChild(removeButton);
removeButton.addEventListener("click", function() {
var anchor = this.previousElementSibling;
var url = anchor.getAttribute("href");
removeUrlAndSave(url);
this.parentNode.remove();
});
newEntry.className = "listItem";
document.getElementById("list").appendChild(newEntry);
}
function removeUrlAndSave(url) {
var index = urlList.indexOf(url);
if (index != -1) {
urlList.splice(index, 1);
saveUrlList();
}
}

Copy/Paste element with jQuery

I have a div that I'm appending to another div when a button is clicked. I'm also calling a bunch of functions on the div that gets created.
HTML
<a onClick="drawRect();">Rect</a>
JS
function drawRect(){
var elemRect = document.createElement('div');
elemRect.className = 'elem elemRect';
elemRect.style.position = "absolute";
elemRect.style.background = "#ecf0f1";
elemRect.style.width = "100%";
elemRect.style.height = "100%";
elemRect.style.opacity = "100";
renderUIObject(elemRect);
$('.elemContainer').draggableParent();
$('.elemContainer').resizableParent();
makeDeselectable();
handleDblClick();
}
var createDefaultElement = function() {
..
..
};
var handleDblClick = function() {
..
..
};
var renderUIObject = function(object) {
..
..
};
var makeDeselectable = function() {
..
..
};
I could clone the element when the browser detects a keydown event
$(window).keydown(function(e) {
if (e.keyCode == 77) {
$('.ui-selected').clone();
return false;
}
});
then append it to #canvas. But the problem is, none of the functions I mentioned above get called with this method.
How can I copy/paste an element (by pressing CMD+C then CMD+V) and call those above functions on the cloned element?
The jQuery.clone method returns the cloned node. So you could adjust your code to do something like this:
var myNodes = $('.ui-selected').clone();
myNodes.each(function () {
createDefaultElement(this);
appendResizeHandles(this);
appendOutline(this);
});

Adding a custom context menu item to elFinder

I'm using elfinder and I would like to add new functionality by adding a command to the context menu. I found a solution on the github issue tracker of the project but I can't get it to work. Here's what I do:
var elf;
jQuery().ready(function() {
elFinder.prototype._options.commands.push('editimage');
elFinder.prototype._options.contextmenu.files.push('editimage');
elFinder.prototype.i18.en.messages['cmdeditimage'] = 'Edit Image';
elFinder.prototype.i18.de.messages['cmdeditimage'] = 'Bild bearbeiten';
elFinder.prototype.commands.editimage = function() {
this.exec = function(hashes) {
console.log('hallo');
}
}
elf = jQuery('#elfinder').elfinder({
...
//elfinder initialization
The context menu item does not show up, no error message is to be found in the console. I also tried putting editimage under contextmenu->"files" in the init part in case that was overwritten by the initialization.
I found the solution: The examples don't show the fact that you need to have a function called this.getstate inside of the elFinder.prototype.commands.yourcommand function. It shall return 0 when the icon is enabled and -1 when it's disabled.
So the full code for adding your own menu item or context menu item looks like this:
var elf;
jQuery().ready(function() {
elFinder.prototype.i18.en.messages['cmdeditimage'] = 'Edit Image';
elFinder.prototype.i18.de.messages['cmdeditimage'] = 'Bild bearbeiten';
elFinder.prototype._options.commands.push('editimage');
elFinder.prototype.commands.editimage = function() {
this.exec = function(hashes) {
//do whatever
}
this.getstate = function() {
//return 0 to enable, -1 to disable icon access
return 0;
}
}
...
elf = jQuery('#elfinder').elfinder({
lang: 'de', // language (OPTIONAL)
url : '/ext/elfinder-2.0-rc1/php/connector.php', //connector URL
width:'100%',
uiOptions : {
// toolbar configuration
toolbar : [
...
['quicklook', 'editimage'],
/*['copy', 'cut', 'paste'],*/
...
]},
contextmenu : {
...
// current directory file menu
files : [
'getfile', '|','open', 'quicklook', 'editimage', ...
]
}
}).elfinder('instance');
});
Hope this helps someone with the same problem.
Thanks for the answer, great!
One thing that wasn't clear was how the variables pass through.
So, for anyone else who finds this page....
elFinder.prototype.commands.editpres = function() {
this.exec = function(hashes) {
var file = this.files(hashes);
var hash = file[0].hash;
var fm = this.fm;
var url = fm.url(hash);
var scope = angular.element("body").scope();
scope.openEditorEdit(url);
}
// Getstate configured to only light up button if a file is selected.
this.getstate = function() {
var sel = this.files(sel),
cnt = sel.length;
return !this._disabled && cnt ? 0 : -1;
}
}
To get your icon to show up, add the following to your css file:
.elfinder-button-icon-editpres { background:url('../img/icons/editpres.png') no-repeat; }

Titanium TabGroup

I am having trouble with tabGroups. I have created a new app (this is my first app) and when I click an option in the table I am calling:
win.open(win,{annimated:true});
The problem is there is no tab at the top of the page to get back to where I was. So I need to use tabgroups. My question is I am not sure how to use them. When I replace the above with:
Ti.UI.currentTab.open(win);
I get an error that currentTab is not defined. How do I enable tabGroups? I have another file called AppTabGroup.js that has the: var self = Ti.UI.createTabGroup(); in it but I am not sure how to use it.
Below is the entire page incase I am doing something way off base.
function AppWindow(title) {
var self = Ti.UI.createWindow({
title:title,
backgroundColor:'white'
});
var data = [
{ title:"Catalog", hasChild:true, test:'ui/CatalogWindow.js', header:'' },
{ title:"Service Calculator", hasChild:true, header:'' }
];
var tableview = Titanium.UI.createTableView({
data:data,
style:Titanium.UI.iPhone.TableViewStyle.GROUPED
});
tableview.addEventListener('click', function(e)
{
if (e.rowData.test)
{
var win =
Titanium.UI.createWindow({
url:e.rowData.test,
title:e.rowData.title
});
win.open(win,{annimated:true});
}
});
self.add(tableview);
return self;
};
module.exports = AppWindow;
You are not alone. Other people (myself included) have been confused by Ti.UI.currentTab being undefined:
http://developer.appcelerator.com/question/98501/titaniumuicurrenttab-is-null
The way I've worked around this in the past is to pass down the containing tab to the window, so that it can use that reference to open another window. So in your example, AppTabGroup.js would look like:
var AppWindow = require('src/AppWindow');
var self = Ti.UI.createTabGroup();
//create app tabs
var appTab = Ti.UI.createTab({
title : L('app'),
icon : '/images/app_tab.png',
window : AppWindow
});
AppWindow.setContainingTab(appTab);
Then in AppWindow.js:
exports.setContainingTab = function(tab) {
containingTab = tab;
}
var win = Titanium.UI.createWindow({
url:e.rowData.test,
title:e.rowData.title
});
containingTab.open(win);

Help converting JavaScript click function to onLoad

I'm trying to convert a JavaScript function that ran off a click event to launch on page load and window resize. As you can see below, I commented out the section governing the click event and added the last line "window.onload," and manually added the class="resizerd" to the element it was working with.
The function isn't running at all. Chrome's Dev tools are showing "Uncaught TypeError: Cannot set property 'prevWidth' of undefined" Did I mess up the syntax somewhere? Any advice for how to launch this on load?
Thank you!
//var clicked = document.getElementById("buttonImportant")
var resizeeContainer = document.getElementById('video_container');
var resizee = resizeeContainer.getElementsByTagName('video')[0];
/*clicked.addEventListener('click',function(){
if( resizeeContainer.className.lastIndexOf("resizerd")>=0 ){
}
else
{
resizeeContainer.className="resizerd";
}*/
myResizerObject.prevWidth = resizee.offsetWidth;
myResizerObject.prevHeight = resizee.offsetHeight;
myResizerObject.Init();
//},false);
myResizerObject.prevWidth = resizee.offsetWidth;
myResizerObject.prevHeight = resizee.offsetHeight;
myResizerObject.Init();
var RESIZER = function(){
this.prevWidth = resizee.offsetWidth;
this.prevHeight = resizee.offsetHeight;
this.resizee = resizeeContainer.getElementsByTagName('video')[0];
this.resizeeContainer = resizee.parentNode;
this.resizeeStyle = this.resizee.style;
var ratio = this.resizee.offsetHeight/this.resizee.offsetWidth;
var that = this;
this.Init = function(){
if( that.resizeeContainer.className.lastIndexOf("resizerd")>=0 )
{
var resizeeContOffsetWidth = that.resizeeContainer.offsetWidth;
var resizeeOffsetWidth = that.resizee.offsetWidth;
var resizeeContOffsetHeight = that.resizeeContainer.offsetHeight;
var resizeeOffsetHeight = that.resizee.offsetHeight;
if(that.prevWidth!= resizeeContOffsetWidth)
{
that.prevWidth = resizeeContOffsetWidth;
var desired = resizeeContainer.offsetHeight/resizeeContainer.offsetWidth;
if(desired>ratio){
that.resizeeStyle.width=resizeeContOffsetWidth*desired+resizeeContOffsetWidth*desired+"px";
that.resizeeStyle.left = -1*(resizeeOffsetWidth-resizeeContOffsetWidth)/2+'px';
}
else{
that.resizeeStyle.cssText="width:100%;height:auto;position:fixed;";
}
}
if(that.prevHeight!=resizeeContOffsetHeight)
{
that.prevHeight = resizeeContOffsetHeight;
var desired = resizeeContOffsetHeight/resizeeContOffsetWidth;
if(desired>ratio){ console.log(ratio);
//that.resizeeStyle.top = '0px';
that.resizeeStyle.left = -1*(resizeeOffsetWidth-resizeeContOffsetWidth)/2+'px';
that.resizeeStyle.width = resizeeContOffsetHeight*desired+resizeeContOffsetHeight/desired+'px';
}
else
{
that.resizeeStyle.top = -1*(resizeeOffsetHeight-resizeeContOffsetHeight)/2+'px';
}
}
}
};
};
var myResizerObject = new RESIZER();
window.onresize = myResizerObject.Init;
window.onload = myResizerObject.Init;
Did you try to execute the function through the <body> tag?
Like:
<body onload="myfunction();">
Try calling the entire resize javascript function in the OnLoad="myfunction();" event of the Body of the page. I have done this to resize the page everytime it loads and it works just fine.
You have this line:
myResizerObject.prevWidth = resizee.offsetWidth;
That is probably giving the error. You've done nothing to declare myResizerObject so it cannot have a property prevWidth.
Somewhere down there you do
var myResizerObject = new RESIZER();
I suspect you want those lines in a more reasonable order :)
Such code should work just fine:
var myResizerObject = new RESIZER();
function UpdateResizerObject() {
var resizeeContainer = document.getElementById('video_container');
var resizee = resizeeContainer.getElementsByTagName('video')[0];
myResizerObject.prevWidth = resizee.offsetWidth;
myResizerObject.prevHeight = resizee.offsetHeight;
myResizerObject.Init();
}
window.onload = function() {
UpdateResizerObject();
};
window.onresize = function() {
UpdateResizerObject();
};
Have it after you define the RESIZER class though.
Your mistake was calling the object instance variable before creating it.
Edit: some basic debug.. add alerts to the function like this:
this.Init = function(){
alert("Init called.. container: " + that.resizeeContainer);
if (that.resizeeContainer)
alert("class: " + hat.resizeeContainer.className);
if( that.resizeeContainer.className.lastIndexOf("resizerd")>=0 )
{
...
}
}
And see what you get.

Categories

Resources