I'm writing a Firefox extension. I'd like to have my code executed whenever a new tab opens.
I've tried this:
for (var i=0; i<Application.windows.length; i++) {
var w = Application.windows[i];
w.events.addListener("TabOpen", function(event){
alert( 'tab #'+w.activeTab.index +' opened');
});
}
It doesn't work right if windows.length > 1. For example, we have two windows. I open new tab and event fires 2 times, for every window. I wanna only one event call for current window.
Without FUEL: https://developer.mozilla.org/en/Code_snippets/Tabbed_browser#Notification_when_a_tab_is_added_or_removed. I like that better than using Application.activeWindow, since from looking at the code there's no guarantee activeWindow always refers to the same window that your code is executing in. (If they are different, you'll end up with weird hard to reproduce problems).
The reason your original code didn't work was that you're presumably putting your code in a script for an overlay to the main browser window. Such code is executed in every instance of the browser window the user opens. So when you open the second window, the loop executed again and added a second listener for the 1st window and the first (only) listener to the 2nd window.
Answer to my own question:
window.addEventListener('load', function(){
var w = Application.activeWindow;
w.events.addListener("TabOpen", function(event){
alert( 'tab #'+w.activeTab.index +' opened');
});
}, false);
no way i didnt that works i akways attached it to gbrowser, this is how i do it:
https://gist.github.com/Noitidart/8673632
where i attach domContentLoad i also attach TabOpen
Related
Due to how some of our pages work, JS can get injected into the page at any point and sometimes this JS closes the current window. The problem is that I need to attach an event listener to the onunload of the window so that a value may be returned from the window to the parent page. But because the window close script may be injected at any point, I can't bind this event to the onload due to how it works so I was hoping to use DOMContentLoaded since that event will trigger before the injected script does.
However in my tests, I cannot get anything to bind to DOMContentLoaded on the parent page where the new window is being created.
Here is an what I am currently working with: Plunker
We only need this to work in Chrome at the moment.
Our current method of doing this works like this (pseudocode):
onButtonClick = function(){
win = window.open(...);
win.onload = function(){
win.onunload = function(){
//Bind some function that will get the window's "return value" and pass it to the parent page
//This will never happen if the window closes itself before the page is done loading
};
};
};
Can I use DOMContentLoaded to accomplish what I want? If so, how do I properly attach it to the window?
Note: I cannot bind the onunload event directly to the window once it is created. It seems to fire the onunload event twice (once when the window opens and once when it closes). You can see this happening if you use the bindOnCreate function in my example.
If you change line 58 from
w.document.addEventListener('DOMContentLoaded', ...)
to
w.addEventListener('DOMContentLoaded', ...)
it works. I'll try to explain what's actually going on under the hood:
When window is opened, it is initially having URL about:blank. You can check this by logging w.location.toString() in onunload event handler (see next step).
Immediately after that the browser loads URL supplied in window.open, thus triggering onunload for about:blank (first time).
Real page with different window.document is loaded into pop-up window, but your event handlers are still listening to the DOM root of about:blank page because you added events to window.document, not window; and right now as we have another URL loaded, window.document is completely different object than one step before.
When you close window, onunload is triggered again (second time) because your onunload event was connected to window.
If you addEventListener for pop-up's window, it receives events from all window.document-s that will be loaded inside that window because of JS event bubbling mechanism.
I hope this answers your questions.
Alternatively, you can send a message from the child window to its opener, rather than let opener to handle child window's unload event. This will be much easier and you don't need to worry about the injection point. Also you can get rid of twice unload event, as Andrew Dunai has already given the reason for this issue.
Here I give a very simple demo, only shows the skeleton of my messaging solution:
parent.html
<button id="open">Open Window</button>
<button id="close">Close Window</button>
<div></div>
<script>
var child;
document.querySelector('#open').addEventListener('click', function() {
document.querySelector('div').innerHTML = '';
child = window.open('child.html', 'child', 'width=600,height=600');
}, false);
document.querySelector('#close').addEventListener('click', function() {
child.close();
}, false);
window.addEventListener('message', function(e) {
document.querySelector('div').innerHTML = e.data;
}, false);
</script>
child.html
<input type="text" value="" placeholder="input something">
<script>
window.addEventListener('beforeunload', function() {
var msg = document.querySelector('input').value;
window.opener.postMessage(msg, '*');
}, false);
</script>
Either you close child window by click its own window's close button, or the button in parent window, the value in child's input will always send to parent and presented.
This is the key approach for one of my side project, and works very well.
I have a fiddle here:
http://jsfiddle.net/fJMe9/
window.onresize = function (e) {
console.log("Page resized");
};
And every time I resize the window I get two logs to the console
It's a well known bug (perhaps relating to event bubbling? I say well known, but that's other people who know it, not me :P ). Use a setTimeout to check the last time the window was resized to avoid this.
Try:
window.onresize = function (e) {
console.log(e);
};
you'll see the event fires every time you drag the browser window
Depends on implementation: maybe 2 times, the first for tell you the window is being resized and the second for windows finished resizing.
i have that problem: i need to have a variable set to false/true depending on whether the page is loaded in the current tab or in an inactive tab. so i tried to do it with the focus-event, more or less like this (it's jquery):
var hasFocus = false;
$(function() {
$(window).focus(function() {
hasFocus = true;
});
});
firefox and ie it do what i want: if the page is loaded in the active tab the event is triggered immediately, loaded in a background tab the event is only triggered when the tab gets active.
in chrome however the event does not get triggered when the page is loaded in the current active tab. does anybody know a workaround for this? i also tried events like mouseenter, hover but unfortunately they get executed on pageload in an inactive tab too... thanks in advance!
A tricky way would be this.
setInterval/setTimeout is only fired once a second at most for inactive tabs in Chrome. So, you could set an interval (or timeout) to be run after e.g. 10ms. If it only runs after a much longer time (e.g. 1 second), the page must be inactive. Otherwise, it would be run in 10ms (like you set).
I woulds suggest that you try mousemove as an event -- e.g.
var humanHasInteracted = false;
$(function() {
$(window).mousemove(function() {
humanHasInteracted = true;
});
});
alternatively use bind/unbind so that the event handler can removed when the first mousemovement is detected.
I'm using jQuery to detect a click on the DOM - or let's every click.
$(document).click(function(){
alert("Click :-)");
});
This works pretty good in every browser except Safari for iPad/iPhone. I've also tried to apply the event on the html or body element - no way. How to detect a common click on the iPad/iPhone?
Best regards,
Jim
As I found on http://www.danwellman.co.uk/fixing-jquery-click-events-for-the-ipad/ you may test the user agent and use touchstart or click depending on the platform
var ua = navigator.userAgent,
event = (ua.match(/iPad/i)) ? "touchstart" : "click";
$(document).on(event, function (ev) {
...
});
These answers got me started on the right direction (first google for "jquery document.on ipad"), so thanks for that, but borrowing from this answer I simplified it to something like this:
$(document).on("click touchstart", function (ev) {
...
});
This would obviously produce undesired results if a platform (like Android or Windows Phone or something) supported both click and touchstart in the event bubble, so if anyone knows that let me know (and I'll fix my code and delete this answer! :)
You may use the touchstart event instead.
I have used this:
jQuery(document).on('touchstart',function(event){
//your code here
});
-also instead of "document" you can bind to any DOM object.
and this(from another forum answer):
var body = document.getElementsByTagName('body')[0];
if ("ontouchstart" in window) {
body.ontouchstart = function(){
//your code here
};
};
-again, you don't have to use 'body' you can assign a variable to an object by class this way:
var dd = document.getElementsByClassName('infoAction')[0];
$('html').click(function(){
alert("Click :-)");
});
This works for me, I tested it now.
Even works with no content on page, wherever you click on the page.
You can attach the click listener to the main wrapper element (say div that encloses all the components in your page).
<body><div onclick="void(0)">
... your page tags ...
</div></body>
There is a minor difference with others browsers behaviour: the document object will reveive click events only for tags located inside the "... your page tags ..." section.
In other words, suppose your html and body tags have a yellow background color, and their child tags have a red background color.
The document object will receive clicks on the red areas only. This is usually not a serious drawback.
Tested on an iPhone 3 only
Is it possible to determine whether a user is active on the current web page or, say, focused on a different tab or window?
It seems that if you switch tabs, any JavaScript set on a timeout/interval continues running. It would be nice to be able to 'pause' the events when the user is not on the page.
Would something like attaching a mouseover event to the body work, or would that be too resource-intensive?
You can place onfocus/onblur events on the window.
There's wide support for those events on the window.
Example: http://jsfiddle.net/xaTt4/
window.onfocus = function() {
// do something when this window object gets focus.
};
window.onblur = function() {
// do something when this window object loses focus.
};
Open Web Analytics (and perhaps some other tracking tools) has action tracking
You could keep an alive variable going using mousemove events (assuming the user does not leave the mouse still on the page). When this variable (a timestamp likely) has not been updated in x seconds, you could say the page is not active and pause any script.
As long as you do not do a lot of processing in the body event handler you should be okay. It should just update the variable, and then have a script poll it at a certain interval to do the processing/checks (say every 1000ms).
Attach listeners to mousemove, keyup and scroll to the document.
I use this throttle/debounce function (which works without jQuery, even though it's a jQuery plugin if jQuery is present) to only run code in response to them once in ~250ms, so that you're not firing some code on every pixel of the mouse moving.
You can also use the visibilityState of the document:
document.addEventListener("visibilitychange", function() {
if( document.visibilityState === 'visible' ) {
// Do your thing
}
});
There is a wide acceptance of this API.