How to access content of a tab from firefox addon - javascript

In my addon I find the tab I want to operate and then try to access the elements of it.
Currently I am finding the tab I need by
var b = this.wm.getMostRecentWindow("navigator:browser");
// qqDPSWD This allows for correct window targeting.
var foundW = null;
var en = this.wm.getEnumerator("navigator:browser");
while (en.hasMoreElements()) {
var w = en.getNext();
if ((w.title && w.title.indexOf(parameters['title_identifier']) != -1) ||
(w.document && w.document.title.indexOf(parameters['title_identifier']) != -1))
{
var doc = w.document;
var temp2 = doc.getElementById("myframe");
foundW = temp2.contentWindow;
}
}
temp2 is null though the tab does have an iframe with id myframe.
I get the object doc as an XUL object but doc.getElementById("myframe") is null. Currently I have an html file opened in the desired tab with the desired iframe residing inside the html page loaded in the main tab. I am able to identify the tab properly but couldn't return the iframe window. How do I do it?
I tried looking at the documentation for browsing between the tabs but couldn't find right answer in https://developer.mozilla.org/en/docs/Working_with_windows_in_chrome_code
Node I am working on https://github.com/sebuilder/se-builder/blob/master/seleniumbuilder/components/command_processor.js#L10103 and want to replace
foundW = w;
with
foundW = w.document.getElementById("myframe").contentWindow
as unlike the open source project where he wants to return the tab window I want to return the iframe window present inside the tab he returns.

You aren't actually going through all tabs, you are just going through the FIREFOX windows (called CHROME windows) (not the browser and its window inside each tab).
In your code. var doc = w.document is the CHROME document of the FIREFOX window (not the browser inside the tab). So w.title of the FIREFOX window will be the title of the currently selected tab (probably followed by ' - Mozilla Fireox' can you verify this for me? im guessing here)
temp2 is null because your frame is in the BROWSER IN TAB window which is the HTML document. So if your tab is currently selected you would get it like this w.gBrowser.selectedTab.linkedBrowser.contentwindow this will be the html window. w.selectedTab is the actual tab element that you click at top, it has a property called linkedBrowser which holds the "HTML" browser which is inside this tab. (i put html
so to fix your code below:
var b = this.wm.getMostRecentWindow("navigator:browser");
// qqDPSWD This allows for correct window targeting.
var foundW = null;
var en = this.wm.getEnumerator("navigator:browser");
while (en.hasMoreElements()) {
var w = en.getNext();
if ((w.title && w.title.indexOf(parameters['title_identifier']) != -1) ||
(w.document && w.document.title.indexOf(parameters['title_identifier']) != -1))
{
var doc = w.gBrowser.selectedTab.linkedBrowser.contentDocument;
var temp2 = doc.getElementById("myframe");
foundW = doc.defaultView; //im not sure what you want foundW to be, the chrome window? or the tab html window? if you want html window or you can do doc.defaultView OR w.gBrowser.selectedTab.linkedBrowser.contentWindow BUT if you want the chrome window it would be w
}
}
HOWEVER your code has a problem, its not going through all tabs in each window, its only going through the currently selected tab.
This is how you would do it for each tab in each window, read the comments carefully, also i took out your ugly if statement lol it was making things sloppy. Just put it back i replaced with /*your if statement*/ for easyiness for me to make example below
var b = this.wm.getMostRecentWindow("navigator:browser");
// qqDPSWD This allows for correct window targeting.
var foundW = null;
var en = this.wm.getEnumerator("navigator:browser");
while (en.hasMoreElements()) {
var w = en.getNext();
//we know for sure that all your windows have gBrowser element because you are getting enumerator for 'navigator:browser', but its not necessary for it to have tabContainer, for example a pop up window with no tabs in it
if (w.gBrowser.tabContainer) {
for (var i = 0; i < w.gBrowser.tabContainer.childNodes.length; i++) { //this itereates through each tab element in the tab bar (so the thingies you click)
var tab = w.gBrowser.tabContainer.childNodes[i];
var tabBrowser = tab.linkedBrowser;
var tabDoc = tabBrowser.contentDocument;
var tabWin = tabDoc.defaultView; //OR you can do tabBrowser.contentWindow
if ( /*if statement here*/ ) {
var temp2 = tabDoc.getElementById("myframe");
foundW = tabWin; //im not sure what you want here so i set it to the html window
w.focus(); //if you want to focus this FIREFOX window which is chrome window do this:
w.gBrowser.selectedTab = tab[i]; //if you want to select this tab then do this
}
}
} else {
//it has no tabContainer so its like a popup window with no tabs so our browser elment is just gBrowser, ill use same var names as above to keep things straight for you
var tabBrowser = w.gBrowser;
var tabDoc = tabBrowser.contentDocument;
var tabWin = tabDoc.defaultView; //OR you can do tabBrowser.contentWindow
if ( /*if statement here*/ ) {
var temp2 = tabDoc.getElementById("myframe");
foundW = tabWin; //im not sure what you want here so i set it to the html window
w.focus(); //if you want to focus this FIREFOX window which is chrome window do this:
//w.gBrowser.selectedTab = tab[i]; //no tabs in this window so if you do w.focus() on line above it will focus this properly
}
}
}

Related

Why can't I use window.open() to open multiple pages?

function input_check() {
var num = $("#num").val();
var sys = $("#sys").val();
var tp = $("#tp").val();
var urlstring1 = "";
var urlstring2 = "";
if (sys === 'QA') {
if (tp === 'ACOs') {
urlstring1 = "http://stackoverflow.com";
urlstring2 = "http://google.ca";
window.open(urlstring2);
window.open(urlstring1);
}
else {
console.log(0)
};
};
};
$(document).ready(function() {
$('#checkBtn').on('click', input_check);
});
I want Stackoverflow and Google open, but
when sys === 'QA' and tp === 'ACOs', Google opens but Stackoverflow not.
if I change the window.open order, the first page will open but second page not.
For example,
window.open(urlstring1);
window.open(urlstring2); // the urlstring2 and urlstring1 change order. Now it only opens the urlstring1.
This will be due to your browsers popup blocker, which usually only allows on popup per user action.
According to MDN Reference Window.open() , you also probably need to add a target:
window.open(urlstring1, "target1");
window.open(urlstring2, "target2");

Depeloping firefox addon - hide all toolbars

My extension opens in a new FF tab. I would like all toolbars(exept for tabbar) be hidden when the tab is active.
What I want is exactly how the standard FF addons tab works(tools->addons).
Copy paste this code into scratchpad with browser environment and run it:
Cu.import('resource://gre/modules/Services.jsm');
var sss = Cc['#mozilla.org/content/style-sheet-service;1'].getService(Ci.nsIStyleSheetService);
try {
sss.unregisterSheet(cssUri, sss.USER_SHEET);
} catch (ex) {}
var css = '';
css += 'toolbar { display: none }';
var cssEnc = encodeURIComponent(css);
var newURIParam = {
aURL: 'data:text/css,' + cssEnc,
aOriginCharset: null,
aBaseURI: null
}
var cssUri = Services.io.newURI(newURIParam.aURL, newURIParam.aOriginCharset, newURIParam.aBaseURI);
sss.loadAndRegisterSheet(cssUri, sss.USER_SHEET);
to remove just run the sss.unregisterSheet(cssUri, sss.USER_SHEET);
You didn't write what kind of extension you're developing... SDK or XUL.
In a XUL extension, first get all toolbars, then set collapsed according to your wishes.
Here is some same code.
function toggleToolbars() {
// First get all toolbars (that are not the tab bar)
var tbs = Array.filter(document.querySelectorAll('toolbar'), function (x) {
return x.id != 'TabsToolbar';
});
// For each toolbar
for (var tb of tbs) {
// Either un-collapse if we collapsed it.
if (tb.getAttribute('my-addon-collapsed')) {
tb.removeAttribute('collapsed');
tb.removeAttribute('my-addon-collapsed');
}
// Or collapse other-wise, if not already collapsed
else if (!tb.getAttribute('collapsed')) {
tb.setAttribute('collapsed', 'true');
tb.setAttribute('my-addon-collapsed', 'true');
}
}
}
You may wish to fixup the code to handle corner cases, such as the user manually restoring a toolbar, other add-ons add-on entirely new toolbars later and so on.
In an SDK add-on your will need to get to the actual browser.xul windows first. I'm sure how to do this is already somewhere on SO.

How do I dynamically change the background.js to reflect a user's setting in chrome?

So I am developing a chrome extension right now in order to get introduced to the world of web development. I have run into a issue which I can't seem to get my head wrapped around. Currently, my background.js gets all the open windows along with the open tabs in each of them using:
function getAllOpenWindows(winData) {
var tabs = [];
for (var i in winData) {
/*if (winData[i].focused === true) {*/
var winTabs = winData[i].tabs;
var totTabs = winTabs.length;
for (var j=0; j<totTabs;j++) {
tabs.push(winTabs[j].url);
}
/*}*/
}
console.log(tabs);
}
which was actually posted by bpatel here. Now as you can see the commented line, it allows me to decide if the tabs are taken from just the current focused window or all the windows. My issue is that how exactly can I change this setting dynamically once the extension has been loaded into chrome and is being used actively? So if a user goes into options and says they want only all the windows I would be able pass a message to my background.js to say "hey use the all windows function and not the current focused window". I understand that 2 seperate functions should ideally be used here, this is just a sample on how it would be done. Thanks a ton!
You can use localstorage to save any user settings.
The options page and the background page share the same localstorage, so you can update the setting from options page and access the value from background page.
options.html
<input type="checkbox" id="windowType" value="All">Check all windows</input>
<input type="button" id="saveSettings" value="Save">Save</input>
options.js
document.getElementById("saveSettings").onclick = save_settings;
function save_settings()
{
var checkAll = document.getElementById("windowType").checked;
localStorage.setItem("check_all_windows",checkAll);
}
You can use a similar function to update the value of the checkbox with the current value, when the options page loads.
background.js
function getAllOpenWindows(winData) {
var tabs = [];
for (var i in winData) {
var checkAll = (localStorage.getItem("check_all_windows") == "true");
if (checkAll || winData[i].focused === true) {
var winTabs = winData[i].tabs;
var totTabs = winTabs.length;
for (var j=0; j<totTabs;j++) {
tabs.push(winTabs[j].url);
}
}
}
console.log(tabs);
}
In background.js, you can get the value of the same key from localStorage and check if it is set to true or false. Remember that the localStorage will store values as strings so you need to compare it with the proper strings - if("false") will evaluate to true.

Safari print with Javascript produces blank when printing an Iframe

I have read up on all issues regarding Safari and blank printing. It seems that a white flash happens, re-rendering the page, and content of the iframe is lost before a print dialog can grab it.
Here is my javascript - It works in all browsers except safari. It brings up the dialog, but prints a blank page.
function PrintPopupCode(id) {
framedoc = document;
var popupFrame = $(framedoc).find("#" + id + '\\!PopupFrame');
var icontentWindow = popupFrame[0].contentWindow || popupFrame[0].contentDocument;
icontentWindow.focus();
icontentWindow.print();
}
function PrintPopup(id) {
setTimeout(function () { PrintPopupCode(id) }, 3000);
}
I have set a timeout, i previously read it would help if the transfer of content took sometime, but it has not helped.
I have also tried with printElement() function on the icontentWindow variable, but it does not support this method.
Print Element Method
This is all in a .js file, and not on the page. I have tried on the page, but the same thing happens.
Help?
Maybe you should try this:
function PrintPopupCode(id) {
framedoc = document;
var popupFrame = $(framedoc).find("#" + id + '\\!PopupFrame');
var icontentWindow = popupFrame[0].contentWindow || popupFrame[0].contentDocument;
icontentWindow.focus();
setTimeout(icontentWindow.print, 3000);
}
function PrintPopup(id) {
PrintPopupCode(id);
}

Greasemonkey popup loop not waiting for load-event listener

I'm writing a Greasemonkey script to automatically delete my notifications from a site, based on words I enter into a search box.
The delete "button" is basically a link, so I'm trying to open the first link in a new tab. Then, after it loads enough, open the rest of the links, one by one, in that same tab.
I figured out how to get the links I needed and how to loop and manipulate them. I was able to grab the first delete-link and open it in a new tab. I added an event listener to make sure the page was loaded before going to the next link.
I finally made that work so added my search box and button. Then I had to figure out how to wrap the whole thing in the event listener again.
So, I now have the whole thing working, except only the last link loads.
All links are going to my waitFor function so they should open, so it seems the event listener isn't working so it goes through the loop too fast and only the last link loads.
How do I make this script not continue the loop until the previous loaded page is fully loaded?
Complete code except for box and button creation:
var mytable = document.getElementById ('content').getElementsByTagName ('table')[0]
var myrows = mytable.rows
//function openLinkInTab () {
//mywin2.close ();
//}
var mywin2;
mywin2 = window.open ("http://www.aywas.com/message/notices/test/", "my_win2");
var links;
var waitFor = function (i) {
links = myrows[i].cells[1].getElementsByTagName ("a");
mywin2 = window.open (links[0].href, "my_win2");
}
var delnotifs = function () {
var matching;
var toRemove;
toRemove = document.getElementById ('find').value;
alert (toRemove)
for (i = 0; i < 10; i++) {
matching = myrows[i].cells[0].innerHTML;
if (matching.indexOf (toRemove) > 0) {
mywin2.addEventListener ('load', waitFor (i), false);
}
}
}
searchButton.addEventListener ('click', delnotifs, true);
So, why isn't it waiting for `mywin2.addEventListener('load', waitFor(i), false);`? I have a feeling it's something extremely simple that I'm missing here, but I just can't see it.
I also tried mywin2.addEventListener('load', function(){waitFor(i)}, false); and it still does the same thing, so it's not a problem of being a call instead of a pointer.
Swapping mywin2.addEventListener('load', waitFor(i), false); for
if (mywin2.document.readyState === "complete") { waitFor(i)} doesn't work either.
And while I'm at it... every time I see code looping through a list like this it uses
for(i=1;i < myrows.length;i++)
Which was skipping the first link in the list since arrays start at zero. So my question is, if I switch 'i' to zero, and the loop only goes while 'i' is < length, doesn't that mean it won't go through the whole list? Shouldn't it be
for(i=0;i != myrows.length;i++)
When you open a popup (or tab) with window.open, the load event only fires once -- even if you "open" a new URL with the same window handle.
To get the load listener to fire every time, you must close the window after each URL, and open a new one for the next URL.
Because popups are asynchronous and you want to load these links sequentially, don't use a for() loop for that. Use the popup load status to "chain" the links.
Here is the code to do that. It pushes the links onto an array, and then uses the load event to grab and open the next link. You can see the code in action at jsFiddle. :
var searchButton = document.getElementById ('gmPopUpBtn');
var mytable = document.getElementById ('content').getElementsByTagName ('table')[0];
var myrows = mytable.rows;
var linksToOpen = [];
var mywin2 = null;
function delnotifs () {
var toRemove = document.getElementById ('find').value;
for (var J = 0, L = myrows.length; J < L; J++) {
var matching = myrows[J].cells[0].innerHTML;
if (matching.indexOf (toRemove) > 0) {
var links = myrows[J].cells[1].getElementsByTagName ("a");
linksToOpen.push (links[0].href); //-- Add URL to list
}
}
openLinksInSequence ();
};
function openLinksInSequence () {
if (mywin2) {
mywin2.close ();
mywin2 = null;
}
if (linksToOpen.length) {
var link = linksToOpen.shift ();
mywin2 = window.open (link, "my_win2");
mywin2.addEventListener ('load', openLinksInSequence, false);
}
}
searchButton.addEventListener ('click', delnotifs, true);
See https://developer.mozilla.org/en-US/docs/Web/API/EventTarget.addEventListener.
The second argument of the addEventLister function must be a pointer to a function and not a call.

Categories