Mozilla Extension - tracking data per opened tab - firefox

In a firefox extension I'm temporarily saving data in javascript to show in a sidebar. When a tab is selected, I want to change the text in the sidebar to the right data. What is the best object to use as the "Identifier" for each tab? I'm trying to use the tab object. However, I'm stuck then on how to associate the data to the tab. Currently, I get a load event on the document in a tab. Then I process the data in the document. AFter showing the new data in the tab, I want to save it into a map with the tab as the key so that I can retrieve it on a SelectTab event. However, I'm not sure how to find the tab from the documentin the load event.
So please either tell me how to get the tab object from the document object, or a better thing to use as the key.
The following is one way I've found, but I'm sure there is something more elegant.
getTabForDocument : function (document) {
var wm = Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
for (var found = false, index = 0, tabbrowser = wm.getEnumerator('navigator:browser').getNext().gBrowser;
index < tabbrowser.tabContainer.childNodes.length && !found;
index++) {
// Get the next tab
var currentTab = tabbrowser.tabContainer.childNodes[index];
if (currentTab.linkedBrowser.contentWindow.document == document)
{
return currentTab;
}
}
return null;
},
Thanks...

Take a look at: https://developer.mozilla.org/en/Code_snippets/Tabbed_browser, especially the gBrowser.selectedBrowser section and https://developer.mozilla.org/En/Listening_to_events_on_all_tabs
To associate data with a tab you can use the setUserData method on the browser.
To get the browser for a document use the getBrowserForDocument method on the gBrowser global object.

Related

How to get the current tab's history in a Web Extension in Firefox?

Is there an API that makes it possible to get the current tab's history in a Web Extension in Firefox? Just like when clicking and holding on the Back button, a dropdown will appear to show the current tab's history.
No. You cannot ask for the list for a certain tab by default.
You can, however, listen for the tab events onUpdated, onCreated etc. Using the tabId which stays the same, you can keep a list of URLs in a background script (background.js) which is always running if the addon is enabled.
You would do it like this:
let arr=[]; // At the top of background.js
browser.tabs.onCreated.addListener(handleCreated); // Somewhere in background.js
function handleCreated(tab) {
let tabId = tab.id;
if(arr[tabId]==null) arr[tabId] = [];
arr[tabId].push(url);
}
function getHistoryForCurrentTab(){
function currentTabs(tabs) {
// browser.tabs.query returns an array, lets assume the first one (it's safe to assume)
let tab = tabs[0];
// tab.url requires the `tabs` permission (manifest.json)
// We will now log the tab history to the console.
for(let url of arr[tab.id]){
console.log(url);
}
}
function onError(error) {
console.log(`This should not happen: ${error}`);
}
browser.tabs.query({currentWindow: true, active: true}).then(currentTabs, onError);
}
The above code is a proof of concept. Some improvements you will need to consider: implement onClosed which resets the tab history for that id (arr[tabId] = null), implement onUpdated (will be needed for sure, same logic as in handleCreated).
Links:
https://developer.mozilla.org/en-US/Add-ons/WebExtensions/API/tabs

Nativescript Get Current Page

How can I get the current screen I'm working on? For example, I have a slidedrawer containing buttons to navigate to another page. When I'm on a certain page(About Page) and when I tap the button to navigate to the About Page, I want to just close the slidedrawer if it is on the same page.
My idea is that to get the current page and just compare it but I dont know how.
Note: The slidedrawer content menu is a custom component.
There are several ways to solve this problem. The easiest is to install the nativescript-dom plugin and then you can do this really simply:
// This will return an array of elements that are SlideDrawer's.
var slideDrawers = getElementsByTagName('SlideDrawer');
or even better is if you have assigned your SlideDrawer an id, you can do
<!-- Declarative XML -->
<SlideDrawer id="myId">...</SlideDrawer>
// JS: Will return a single element that matching the id.
var mySlideDrawer = getElementById('myId');
However, if you just want to not use any helpers and you want to get direct access to the currentPage the method is to do:
var frame = require('ui/frame');
var myPage = frame.topmost().currentPage;
Please note; the currentPage will reflect the old page while navigation is taking effect until the navigatedTo event is fired, at that point the currentPage is actually updated to be the currentPage. However, if you are looking for the current page during any of the navigation events (NavigatingTo, NavigatedTo, Loaded, Unloaded) each of those events are transferred a parameter with the current page as part of the object.
exports.onNavigatedTo = function(args) {
var page = args.object;
// do what you want with the current page variable
}

LightSwitch Tabbed screen in Browse template

I have a screen where we have 4 tabs, each tab should be displayed as per the login priority.
Ex:Department,Role,Employee,Screen are the tabs.
Each tab is having buttons to add,edit,remove the data.
by default when i log with any user its going to the first tab, but not all the users are having the first tab as their requirement.
how can i resolve this to do it dynamically in html client application
As covered towards the end of the following LightSwitch Team blog post, you can programmatically change the tab by using the screen.showTab method:
Creating a wizard-like experience for HTML client (Andy Kung)
However, in order to use this showTab API command when your screen is loading, its use needs to be delayed until the screen has fully displayed. This can be achieved in your screen's created method by using a combination of the jQuery mobile pagechange event (as the LightSwitch HTML Client uses jQuery mobile) and a setTimeout with a zero timeout (to delay the showTab until the loading screen is rendered).
The following shows a brief example of how you can use this approach to dynamically set the initial screen tab:
myapp.BrowseScreen.created = function (screen) {
var initialTabName = localStorage.getItem("Rolename") + "Tab";
$(window).one("pagechange", function (e, data) {
setTimeout(function () {
screen.showTab(initialTabName);
});
});
};
Based on your earlier post it appears that you're using LocalStorage to track your logged in user and their role.
On this basis, the above example assumes that the user's role will be the factor dictating the tab they are shown when the screen loads (the screen is named BrowseScreen in the above example).
It also assumes that your tabs are named after each employee role (suffixed with the text 'Tab') e.g. a user who is assigned the role 'DepartmentManager' would be directed to a tab called 'DepartmentManagerTab'.
Whilst slightly more involved, if you'd prefer to avoid the pagechange and setTimeout it's possible to customise the LightSwitch library to introduce a new navigationComplete screen event. This new event is ideal for executing any operations dependent upon the screen having fully rendered (such as navigating to a different tab using the showTab function).
If you'd like to introduce this additional event, you'll need to reference the un-minified version of the LightSwitch library by making the following change in your HTML client's default.htm file (to remove the .min from the end of the library script reference):
<!--<script type="text/javascript" src="Scripts/msls-?.?.?.min.js"></script>-->
<script type="text/javascript" src="Scripts/msls-?.?.?.js"></script>
The question marks in the line above will relate to the version of LightSwitch you're using.
You'll then need to locate the section of code in your Scripts/msls-?.?.?.js file that declares the completeNavigation function and change it as follows:
function completeNavigation(targetUnit) {
msls_notify(msls_shell_NavigationComplete, { navigationUnit: targetUnit });
var screen = targetUnit.screen;
var intialNavigation = !screen.activeTab;
var selectedTab = targetUnit.__pageName;
if (screen.activeTab !== selectedTab) {
callNavigationUnitScreenFunction(targetUnit, "navigationComplete", [intialNavigation, selectedTab]);
screen.activeTab = selectedTab; // Set at the end of the process to allow the previous selection to be referenced (activeTab)
}
}
function callNavigationUnitScreenFunction(navigationUnit, functionName, additionalParameters) {
var screenObject = navigationUnit.screen;
var constructorName = "constructor";
var _ScreenType = screenObject[constructorName];
if (!!_ScreenType) {
var fn = _ScreenType[functionName];
if (!!fn) {
return fn.apply(null, [screenObject, navigationUnit].concat(additionalParameters));
}
}
}
You can then use this new event in your screens as follows:
myapp.BrowseScreen.navigationComplete = function (screen, navigationUnit, intialNavigation, selectedTab) {
if (intialNavigation) {
var initialTabName = localStorage.getItem("Rolename") + "Tab";
screen.showTab(initialTabName);
}
};
This event fires whenever a navigation event completes (including a change of tab) with the initialNavigation parameter being set to true upon the initial load of the screen and the selectedTab parameter reflecting the selected tab.
Although modification to the LightSwitch library aren't uncommon with some of the more seasoned LightSwitch developers, if you decide to go down this path you'll need to thoroughly test the change for any adverse side effects. Also, if you upgrade your version of LightSwitch, you'll need to repeat the library modification in the new version.

How to get tab in TabOpen event with Firefox FUEL?

I'm writing a firefox extension and really need to listen on TabOpen events and get some details about tab that was opened. But I can't figure out how do I get an actual tab from event object that my callback receives. Is it somewhere in event.data? Is there a way to inspect this object?
Some code that I have tried so far but it doesn't work:
Application.activeWindow.events.addListener("TabOpen",
function(event) {
Application.console.log("TabOpen");
var tab = event.data.target;
Application.console.log(tab.uri);
}
);
In your code, event.data will give you a BrowserTab object. If you want the current URI of the tab, you'd want tab.uri.spec for the string version, or just tab.uri if you want an nsIURI object.
here is an example from the MDC but without using FUEL:
// add event listener
var container = gBrowser.mPanelContainer;
container.addEventListener("DOMNodeInserted", exampleTabAdded, false);
function exampleTabAdded(event)
{ // listening for new tabs
if (event.relatedNode != gBrowser.mPanelContainer)
return; //Could be anywhere in the DOM (unless bubbling is caught at the interface?)
var browser;
browser = event.target.childNodes[1];
// browser is the XUL element of the browser that's been added
}
I've added some new content to MDC that should help with this; information on how to pull the tab object out of the TabOpen event is now available in the example here:
https://developer.mozilla.org/En/FUEL/Window
Also did some other cleaning up while I was at it. Hopefully this will help (especially once the search index refreshes).

Reusing a tab in Firefox, TabOpen event, and beyond

I followed a tutorial on reusing tabs inside Firefox, and right now my extension does it well. However, I also need to reuse tabs that are opened from outside (from some application, start menu etc.). How do I do this?
I tried adding an event listener for TabOpen event, but when I log the
event.target.linkedBrowser.currentURI.spec
it's value is "about:blank". I expected the actual address that I typed into the address bar (automatically opens in a new tab), or the address that I open from some other application, so I can close that tab immediately, and the focus the right one. What am I doing wrong?
Thanks in advance.
Just in case, here's the code that reuses the tab when a new tab is requested from an extension
function openAndReuseOneTabPerURL(url) {
var wm = Components.classes["#mozilla.org/appshell/window-mediator;1"]
.getService(Components.interfaces.nsIWindowMediator);
var browserEnumerator = wm.getEnumerator("navigator:browser");
// Check each browser instance for our URL
var found = false;
while (!found && browserEnumerator.hasMoreElements()) {
var browserWin = browserEnumerator.getNext();
var tabbrowser = browserWin.getBrowser();
// Check each tab of this browser instance
var numTabs = tabbrowser.browsers.length;
for(var index=0; index<numTabs; index++) {
var currentBrowser = tabbrowser.getBrowserAtIndex(index);
if (url == currentBrowser.currentURI.spec) {
// The URL is already opened. Select this tab.
tabbrowser.selectedTab = tabbrowser.mTabs[index];
// Focus *this* browser-window
browserWin.focus();
found = true;
break;
}
}
}
// Our URL isn't open. Open it now.
if (!found) {
var recentWindow = wm.getMostRecentWindow("navigator:browser");
if (recentWindow) {
// Use an existing browser window
recentWindow.delayedOpenTab(url, null, null, null, null);
}
else {
// No browser windows are open, so open a new one.
window.open(url);
}
}
}
When you receive the TabOpen event, it's too early for the page content to be loaded still. When you receive the TabOpen event, however, you should register for load or DOMContentLoaded. When you receive that event, you should be able to access the URI.
I guess you could extract the wanted behaviour from the implementation in the Tab Mix Plus extension

Resources