Use a load event listener to give the window time to be ready for you to add your Tab event listeners and create the polling service for the existing tab. Then use an unload event listener to do your cleanup.
Answer from Neil on Stack OverflowListening to tab open/close and dealing with existing tabs
Change a tab's DOM from Event Page
Run custom function before open in new tab
Event listener across tabs - javascript
I can't say what's the best solution for the particular use case, but there are various points to consider when deciding what's the best tradeoff:
- the decision to use an
aorbuttontag should not be determined by the presence of the menu. One is a navigational element and the other is used to perform actions on the page. If it's a navigation on a website,<a>is probably the right tag. - the context menu is a browser "thing" and it's in the control sphere of the user. Depending upon your site's philosophy you should not mess up with the browser's basic functionality.
- when the user navigates away from your page, the browser will trigger the
beforeunloadevent, which will trigger when the current page is being closed. It is a browser's native functionality (the same you get here on StackOverflow when you leave a page with unsaved changes), so it's not customizable in style, but it suits more an HTML-first approach. If you need an 'unsaved changes' message, this is the usual way to go. - you can use good ol'
window.openwith target_blankin a button javascript handler if you want to expose a button with theopen in new tabfunctionality. This way you stay in your JavaScript context and can do whatever you need. - if you want more of a Single Page Application style, you can replace the native context menu with something else, as suggested, but you have to evaluate if you are building an application or a website. I like the websites I use to behave like websites and do not interfere with my browser's basic capabilities. YMMV.
Probably there are more considerations worth taking, but this are the ones from the top of my mind.
You already correctly figured out that it cannot work the way you want. You need an idea, right? Here is it: therefore, you need to modify your design. This way, you can combine both kinds of behavior you need.
One of the different possible solutions could be this: on your <a> element, you can handle the event "contextmenu". In the handler of this event, you can implement some custom context menu, or some equivalent behavior that gives the user the opportunity to choose one of alternative actions. At the same time, if the user simply activates the anchor, the navigation will load a new page according to a href value, and, if the user holds Shift key — in a new tab.
Let's assume for simplicity that the page has only one <a> element:
<a href="https://stackoverflow.com">Stack overflow</a>
Then it could be set up like this:
const anchor = document.querySelector("a"); // or more complicated selector
anchor.addEventListener("contextmenu", event => {
// activate menu or something, depending on event.target
});
One of the options in this custom context menu could provide the optional side effect you want. One option may be navigation to the page according to anchor's href, but with the call to your side-effect function.
How to implement a custom menu behavior? This is a separate question. I personally have such a component so I can share it. Or you can implement something, depending on what you want.
Another alternative could be a composite control that has two inner elements: <a>, to provide navigation to the page according to href, in a separate tab or not, and another one to provide the choice of action, not necessarily simulating the behavior of a context menu.
You decide.
In window B you set a cookie and in window A you create a setTimeout function that every "x" milliseconds check if there are any new cookie.
Look at this: Javascript communication between browser tabs/windows
If window A is a parent of window B (A opened B) then it's possible to find the element and add event listener. Also you can use postMessage to communticate between windows.
You should be able to do this with the keyup event. To be specific, event.target should point at the selected element and event.target.href will give you the href-value of that element. See mdn for more information.
The following code is jQuery, but apart from the boilerplate code, the rest is the same in pure javascript. This is a keyup handler that is bound to every link tag.
$('a').on( 'keyup', function( e ) {
if( e.which == 9 ) {
console.log( e.target.href );
}
} );
jsFiddle: http://jsfiddle.net/4PqUF/
Having following html:
<!-- note that not all browsers focus on links when Tab is pressed -->
<a href="http://example.com">Link</a>
<input type="text" placeholder="Some input" />
<a href="http://example.com">Another Link</a>
<textarea>...</textarea>
You can get to active link with:
// event listener for keyup
function checkTabPress(e) {
"use strict";
// pick passed event or global event object if passed one is empty
e = e || event;
var activeElement;
if (e.keyCode == 9) {
// Here read the active selected link.
activeElement = document.activeElement;
// If HTML element is an anchor <a>
if (activeElement.tagName.toLowerCase() == 'a')
// get it's hyperlink
alert(activeElement.href);
}
}
var body = document.querySelector('body');
body.addEventListener('keyup', checkTabPress);
Here is working example.
input.keydown(function(event){
if (event.keyCode === 9) {
event.preventDefault();
}
})
On keyup is too late, you need to call the event on keydown. That worked for me.
Here's an article on how to detect chrome:
http://javascriptly.com/2008/09/javascript-to-detect-google-chrome/
And this question: Disable tab key on a specific div might help you on disabling the tab key. If you are able to combine both yourself, you've probably got it working.
The disable function would become something like:
$('.textarea').on('keyup mouseup', function(e) {
if(e.which == 9) { e.preventDefault(); }
});
e.which = 9 is the tab key according to the last link given. If you are able to wrap the browser detection around it yourself, I guess you've got your working example.
If I get you correctly, you want to know when a tab/window is effectively closed. Well, AFAIK the only way in JavaScript to detect that is to use either onunload or onbeforeunload events.
Unfortunately (or fortunately?), those events are also fired when you leave a site over a link or your browsers back button. So this is the best answer I can give, I don't think you can natively detect a pure close in JavaScript. Correct me if I'm wrong here.
From MDN Documentation
For some reasons, Webkit-based browsers don't follow the spec for the dialog box. An almost cross-working example would be close from the below example.
window.addEventListener("beforeunload", function (e) {
var confirmationMessage = "\o/";
(e || window.event).returnValue = confirmationMessage; //Gecko + IE
return confirmationMessage; //Webkit, Safari, Chrome
});
This example for handling all browsers.
The correct event binding for tab change is shown.bs.tab.
$(document).on('shown.bs.tab', 'a[data-toggle="tab"]', function (e) {
alert('TAB CHANGED');
})
Update 11-01-2020 --- Bootstrap 4.5
This is still the correct answer however, this is a bit of additional helpful information found all the way at the bottom of the official bootstrap docs page at: https://getbootstrap.com/docs/4.5/components/navs/#tabs
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
e.target // newly activated tab
e.relatedTarget // previous active tab
})
You can determine which tab has been selected each time the code fires with e.target.
If you have unique IDs on your elements then you could do something like the following so code only runs when the appropriate tab is clicked.
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
switch (e.target.id){
case "mainTab":{
doMainTabStuff();
break;
}
case "configTab":{
doConfigTabStuff();
break;
}
}
})
<a data-toggle="tab" href="#some_special_tab_anchor">
<div id="some_special_tab_anchor" class="tab-pane fade">
special tab content
</div>
$( 'a[data-toggle="tab"]' ).on( 'shown.bs.tab', function( evt ) {
var anchor = $( evt.target ).attr( 'href' );
alert("TAB SHOWN = "+anchor);
// take action based on what tab was shown
if(anchor === "some_special_tab_anchor"){
// do my special thing :)
}
});