Mozila Firefox: Capturing an event right before tab change - tabs

I'm looking for an event that can be fired just right before changing a tab?
I have already seen this post, and I have also looked into the tabSelect event in the firefox extension, but I couldn't find any event that can be fired just before the tab change.

Unfortunately there is no such event.
However you can watch, with a MutationObserver, the type attribute of selected tab's browser element (gBrowser.mCurrentBrowser). When it changes from content-primary to content-targetable it's a signal that a tab switch is in progress.

As paa already noted, there is no event that happens before a tab is selected. What you can use are tricks, e.g. the Object.watch() method (yes, using it isn't exactly recommended). It allows you to listen to changes of the gBrowser.tabContainer.selectedIndex property (the setter of this property is where the select event is being fired):
gBrowser.tabContainer.watch("selectedIndex", function(prop, oldval, newval)
{
// New tab being selected, do something here!
return newval;
});
The advantage of this approach: by returning oldval from the handler you can prevent the selection from taking place.

Related

EvalError: Possible side-effect in debug-evaluate in Google Chrome

I get this error in the Chrome console every time I try to evaluate an expression.
EvalError: Possible side-effect in debug-evaluate
What could be causing it?
I think I found the issue, reading through a discussion on an electron issues board.
It could potentially be caused by this: [inspector] Add custom error dispatch machinery for debug evaluate.
And hopefully fixed in this: [inspector] Don't trigger window.onerror with side-effects disabled.
This was an oversight in https://crrev.com/c/3557234, which led to a really weird developer experience: once a window.onerror handler was installed, typing into the Console or other side-effect free debug evaluations triggered this handler.
The website you are inspecting contains an onerror event listener.
A new bug in the latest version of Chrome triggers this event every time an expression is evaluated in DevTools. This includes live expressions and the console.
If this is your own website, add this line of JavaScript to your event listener to ignore any errors triggered outside of a script, where script is the second argument of the event listener function:
if(!script.endsWith(".js")) return;
Note that this will only work for external JavaScript (in .js files), in the case of JavaScript embedded in HTML <script> tags, it will disable your event listener entirely.
If this is not your website, you can temporarily disable the event listener in DevTools, like this:
At the top of DevTools, open the "Elements" tab
Press "ยป", on the right of "Styles", "Computed", "Layout"
Choose "Event listeners"
Find and expand "onerror"
Click "Remove"
This will remove the event listener, but the issue will return after you refresh the page.
Hopefully the next version of Chrome will fix this bug.

Chrome: alert during onfocus creates an infinite loop?

I was trying to figure out how to get some focus/blur behavior working for something when I ran into a really strange and annoying behavior in the Chrome debugger where I got an infinite loop while trying to debug an onfocus handler. It seems to be related to any action which takes focus away as I've been able to reproduce it using alerts instead of a breakpoint.
Here is my minimal example. Make sure you open this in another tab. Closing the tab is the only way I've found to end the loop.
https://codepen.io/cebo494/pen/OJxVZxq
Is this a known issue? Is there an easy workaround other than just using print statements to debug everything?
My final goal in my actual handlers isn't to take away focus, so it's not a problem if this is just a bad practice that I should avoid, but it's super annoying not being able to use the chrome debugger for my focus callbacks.
This seems to be specifically a Chrome issue, as the loop didn't occur in Firefox or IE. It only happens in Chrome and Edge (which is chromium)
I tried the sandbox, it actually got triggered on Firefox as well. I think the problem is that when you close the alert, the focus is lost on the button, but React internally re-focus on the button again, therefore trigger another onFocus call.
I would set a flag to manage the alert behavior, and reset the flag during onBlur event:
const [alert, setAlert] = useState(false);
// you can also pass event to implement the onblur method in the same function
const alertInfo = () => {
if (!alert) {
alert("focus");
setAlert(true);
}
}
Or if the event is only triggered by mouse, you can also use onmouseup/onmousedown to handle the event.

Did html spec require focus fire after mousedown?

Or it's just every browser happen to implement same behaviour? Only place I found in spec is in click event section which says
If the event target is focusable, the default action MUST be to give that element document focus.
But actually focus is the default action of mousedown event, which is widely used in today's frontend development, so I'd like to know why
Isn't the answer in the very quote you've posted?
If the event target is focusable, the default action MUST be to give that element document focus.
And then https://www.w3.org/TR/uievents/#event-type-focus
4.2.4.2. focus
...
A user agent MUST dispatch this event when an event target receives focus.
In other words: the spec indeed requires focus event to be fired when and if an element receives focus
By the way, the focus as event and focus as a property - is two different things.
But!.. The quote is actually from click event, not from mousedown
And if you test it in browsers you'll see that:
They behave differently (at least mine Chrome 81 and FF 75).
If you click inside <textarea>, but move out an only then release the button Chrome won't send click to the <textarea>, but FF will
But they give focus to <textarea> and fire focus event right after mousedown.
So that probably means, that:
No the spec doesn't require focus event to be fired after mousedown. (Instead it requires it to be fired after click)
Yes it's just so happens that every browser (well... at least those two I've tested) implement same non-standard behavior
So far the only thing I found in spec is
Many implementations use the mousedown event to begin a variety of contextually dependent default actions. These default actions can be prevented if this event is canceled. Some of these default actions could include: beginning a drag/drop interaction with an image or link, starting text selection, etc. Additionally, some implementations provide a mouse-driven panning feature that is activated when the middle mouse button is pressed at the time the mousedown event is dispatched.
Although it didn't explicitly says focus, I guess it's still enough evidence

Changing chrome extension html using chrome storage event listener

With this code I want to create an event listener for whenever chrome storage updates.
I want 2 things to happen when the event listener is triggered:
The code will console log the updated values. This part works.
I want the HTML for the extension (the document that opens in the corner when you click the icon) to update and render the data value that is in chrome storage. This is that part I need help with.
chrome.storage.onChanged.addListener(function(changes, namespace) {
//part 1
console.log('New data type is %s. New value is %s',
changes['type'].newValue, changes['data'].newValue)
//part 2
document.getElementById('output').innerHTML =
changes['data'].newValue
});
I realize that calling "document" inside the function doesn't make sense, but I'm unsure how to move forward to get it to render in the extension's HTML.
I tried creating an event listener for when the context menu is accessed (users can update the chrome storage but clicking a button in the context menu) but I couldn't get it to work. Also the event should trigger when chrome storage is updated, not when the context menu is simply accessed.
Right now I get this error:
Error in event handler: TypeError: Cannot set property 'innerHTML' of null
(There is an element with id 'output', so that isn't the problem)
Thanks for your help!
The background script runs in a separate hidden background page. It's not related to the browserAction or pageAction popup page, it doesn't have any of the popup page elements, its DOM is empty except for the auto-generated script tags of the background scripts.
The popup is also a separate page and just like any normal page its environment/DOM exists only when the page is shown. You can't modify it when it's not shown. You can't show it from your code in general case either.
Solution 1
Put that onChanged listener in popup.js script that's loaded in your popup.html (declared as "browser_action": {"default_popup":"popup.html"} in your manifest.json) using the standard <script src="popup.js"></script> tag. It will update the popup page if it's shown, and to display the current values when the popup opens read them with chrome.storage.local.get or chrome.storage.sync.get depending on which storage you're using in your extension.
Solution 2
Use chrome.notifications API to show a small notification at the bottom of the screen, see also the official demo extensions.
Solution 3
Use chrome.browserAction.setBadgeText to display short text like a temperature right under the extension icon. Don't forget to declare at least "browser_action": {} in your manifest.json.

show page action popup on click

I'm making a chrome extension that uses pageAction.
I can set when it shows whether I want it to have a popup or handle the click myself.
What I want to do is handle the click myself, but with certain scenarios I don't want to process the normal code, and want to show the user a message. Preferably with a popup.
But it seams I can either make the pageAction have a popup or have an onClick. But not both.
I can show an alert, but that is ugly.
Currently, there is no "neat" or official way to handle both. You can just do either. But there are some work arounds that some Google extension product have done.
First of all, set it up to show the popup. And within your pageAction popup, you can have the initialization code to be something like this:
Page Action Popup:
function init() {
if (getClickBehaviour() == 'popup')
handlePopup();
else
openPage();
}
function getClickBehaviour() {
return localStorage['CLICK_BEHAVIOR'] || 'popup';
}
function openPage() {
chrome.tabs.create({url: 'http://google.ca'});
window.close();
});
}
init();
Then you can let your options, set the click behavior. If you want different behaviors on each click, you can do that too.
As you noticed, we are closing the popup right after for the "default" behavior that we don't want the popup to show. That is currently the only way to implement different behaviors.
I haven't tested this myself yet, but have you tried setting the popup to the empty string when you want to handle the click (chrome.pageAction.setPopup('')) and to your popup when you want to show a message. I'm not perfectly sure if the onClicked event handler gets called in that case (where the popup is dynamically set to the empty string), but it's worth looking into.
As far as I know, there is generally no way to programmatically open a popup window for a page or browser action. (Which is too bad, I would love this functionality; but you can imagine some of the annoyances if this were possible.)