Window focus for a faster loading pop-up - javascript

I am very new to JavaScript. Kindly note that I am trying below issue in a shell which overrides many JavaScript functions.
I have an issue with focusing a window: on a single "click" action, I navigate to a new page which has two JavaScript methods which launch two external URLs which I don't own. For example I launch Yahoo.com and Google.com. My JS launches Yahoo.com in current window (as a page navigate) and Google.com as a pop-up. I WANT Google.com WINDOW TO BE FOCUSED irrespective of loading time of either URLs. The major issue is I cannot use the setTimeout JS function as this function's behavior is altered within the shell and is not usable.
Note: I am using a custom reusable JS function to launch external URLs and I just pass values to that method. So I don't even have access to window object. If I can somehow achieve a time delay without using setTimeout, it will be ideal case. If not, I will have to override that custom JS function, get access to the window object. Even if I have control over those window objects for external URLs, since loading times are different, setting focus to the Google window object is not always giving me the focus on Google window.
(IE6 & 7)

You cannot guarantee the behavior you want, in general; browsers will not let you.
Safari generally ignores requests to focus windows. Firefox and I think Chrome can be configured by their users (not by your code) to allow focus requests, but by default they won't.

Related

Get tab URL from page action (WebExtensions, Android)

I would like to get the URL of the current tab within a page action popup.
At first it seems obvious: Just use the tabs API. But that doesn't seem to be available on Android if I deciphering the docs correctly. So I kept looking for something else and found the onClicked event of the pageAction API.
The pageAction API seems to be listed as compatible with Android and the onClicked event is marked as supported. So that implies that it would actually return a tabs.Tab object. But does it really? Has anyone tried it?
What is the best way to retrieve the URL? I know I could just use a content script and let that run in every single tab and create a long lived messaging connection to send the URL to the page action popup whenever it is requested. But that would be very inefficient and make the code insanely complicated compared to how easy it would be using the tabs API.
Is there anything else I could do?
Current (Firefox 54 and later)
As of Firefox 54, the tabs API is available in Firefox for Android. This means you can use the normal methods available to desktop Firefox. Specifically, chrome.tabs.query() or browser.tabs.query(). However, you will need the activeTab and/or tabs permissions in your manifest.json.
chrome.tabs.query:
chrome.tabs.query({active:true,currentWindow:true},function(tabs){
//'tabs' will be an array with only one element: an Object describing the active tab
// in the current window.
var currentTabUrl = tabs[0].url;
});
browser.tabs.query:
browser.tabs.query({active:true,currentWindow:true}).then(function(tabs){
//'tabs' will be an array with only one element: an Object describing the active tab
// in the current window.
var currentTabUrl = tabs[0].url;
});
Prior to Firefox 54
If you have defined a page/browser action popup
If you have defined a popup for your page/browser action, then the onClicked event does not fire. Your popup is not passed any information when it is created/shown. Thus, you will not receive a tabs.Tab object. The normal way to obtain tab information is from tabs.query, which, as you have already determined, is not (yet) available in Firefox for Android.
The APIs available to Firefox on Android are quite limited. For what you are wanting to do, using webNavigation events to keep a record of each tab's frame 0 URL would be more efficient than a content script in every page. You could use the webNavigation.onCommitted or webNavigation.onCompleted events depending on your needs. You will need to assume that the active tab of the current window is the one which most recently had a webNavigation event, or perhaps you could also monitor webRequest events. However, any way that you do it, which tab you assume to be the current tab will just be an assumption, and will be inaccurate under some circumstances.
A more accurate URL (and active tab determination) requires using a content script
If the page that is being visited changes the tab's URL through some method that does not trigger navigation, using webNavigation events will not give you the updated URL. As you have identified, without the tabs API, the only way to be certain you have the actual current URL for the tab, when you define an actual page/browser action popup (and thus don't get a tabs.Tab object), is to inject a content script into every page. You will either need the content scripts to continuously update the URLs, or be listening with storage.onChanged for a request for that information from your background/popup script. Communication from the background/popup scripts to content scripts must be accomplished through the storage API due to not having the tabs API (i.e. no tabs.sendMessage).
Using page/browser action onClicked
An alternative, which I have not tried on Firefox on Android, would be to not define an actual page/browser action popup. If you don't define an actual popup, you receive the onClicked event (getting the tabs.Tab Object with both the active tab's ID and the URL) and then can open a pseudo-popup1.
1. The implementation of opening a a pseudo-popup in my linked answer uses the tabs and windows APIs which are both currently unavailable for Firefox for Android. It could be re-written to use the above mentioned webNavigation listener to track tab URLs and window.open() to open the window used for the pseudo-popup. Again, I have not tested this with Firefox on Android to determine that it actually works.
You can get it this way with webextensions. Take into account that if you want to debug a popup, you have to "prevent popups to be closed" (4-squares icon at the top-right of the browser's toolbox)
var activeTabPromise = browser.tabs.query({active: true, currentWindow: true});
activeTabPromise.then((tabs) => {
console.log(tabs[0].url);
});
I hope this will help you,

AngularJS: How to open a file in a new tab?

LIVE DEMO
Given a URI of a file, I'd like to open it in a new tab (not a new window).
It looks like it is not possible to use $window.open(uri, '_blank').
So, I tried the following trick:
var link = angular.element('');
angular.element(document.body).append(link);
link[0].click();
link.remove();
and it works.
But, if I put exactly the same code in a promise callback, it doesn't work anymore (it opens the file in a new window instead).
Any idea what's going on here?
PLAYGROUND HERE
From your code/content, you can't force the browser to open a new tab (rather than a new window, or vice-versa). It's up to the browser settings to force it one way or another.
Anything else would be a security risk.
Let us understand fundamental how pop up blocker work.
If user trigger the function to open a new url, then pop up blocker will allow it(it should applied to any modern browser - at least firefox, chrome)
If not from user (like javascript function in background, promise or any other function trigger not from user), browser will block unless user whitelist the site manually.
This is not working.
function openInNewTab() {
window.open('http://stackoverflow.com','_blank');
}
openInNewTab();//fail
This is working
<h1><button onclick="openInNewTab()">Open In New Tab - working</button></h1>
I created simple plunkr version - http://plnkr.co/edit/QqsEzMtG5oawZsQq0XBV?p=preview
So, to answer your question. It is impossible unless user authorize it (user trigger it or white listed the site).
Quote from firefox -
Pop-up windows, or pop-ups, are windows that appear automatically
without your permission.
https://support.mozilla.org/en-US/kb/pop-blocker-settings-exceptions-troubleshooting
*Open in new tab / new windows not make any difference. Pop up blocker will still always block. It doesn't means that browser will allow if open in new tab. It is just coincidentally for certain browser default the settings in that manner.
Workaround
You can ask user explicitly to trigger the function to open in new tab after the background execution.
You can display message in UI to ask user to open the url.
Example - http://plnkr.co/edit/iyNzpg64DtsrijAGbHlT?p=preview
You can only open new windows inside click event handlers fired by the user.
The reason for this is usability.
I'm not sure if all browsers have this behavior but some browsers do not allow scripts to open windows without the user being noticed. Imagine when you visit a web page and suddenly, the web page opens several windows => it's annoying.
See this DEMO (tested with my Chrome and Firefox), even we trigger click event by script, the browser still blocks the popup.
$("#test").click(function(){
openInNewTab();
});
$("#test").click();
You cannot open a new window inside your ajax success callback because your ajax success is run in another cycle after the click event handler has finished its execution.
See this link for a workaround
if I put exactly the same code in a promise callback, it doesn't work
anymore (it opens the file in a new window instead).
I'm surprised that you're still able to open a new window. But this problem really has a lot of things to do with click events fired by the user.
Your problem is two-fold, and both folds tread on uncertain territory.
In the old days of browsers, window.open did exactly that – open a new window. That's because the concept of tabs hadn't been invented yet. When tabs were introduced, they were treated exactly like windows to improve compatibility, and that tradition continues to this day. That, and the fact that window.open was only standardized very recently, means that JavaScript cannot distinguish between windows and tabs.
There is no "normal" way to specify whether a link should open in a new tab or not. You can use the following hack, though: specify a custom window size to the open call (via the third argument), like so:
window.open('http://example.com', '', 'width=' + screen.width);
This will cause almost all browsers to open a separate window because tabs cannot have custom sizes.
In JavaScript, there are trusted events and untrusted events. Trusted events are, for example, legitimate clicks on a link by the user, whereas an untrusted event would be a manual click() call on a link.
Only trusted event handlers may open new windows/tabs. This is to prevent client-side attacks that crash the browser or confuse a user by rapidly opening a hundred tabs on mouseover or something similar.
Your second example doesn't work because the popup blocker blocks the untrusted event that you triggered via the click(). Although it was caused by a real click, the asynchronous call in-between severs the link to trustedness.
working version
$http.get('https://api.github.com/users/angular').then(openInNewTab());
EDIT----------------
Do not know why but a click() method called from a callback function acts differently than calling it straight.
You can see it here with a set interval example.
That is why I had call the function directly rather than going through a callback.
see it with timer callback
or you can use $window service please see here : http://plnkr.co/edit/8egebfFj4T3LwM0Kd64s?p=preview
angular.module("Demo", []).controller("DemoCtrl", function($scope, $http, $window) {
$scope.uri = 'http://martinfowler.com/ieeeSoftware/whenType.pdf';
function openInNewTab() {
var link = angular.element('');
angular.element(document.body).append(link);
link[0].click();
link.remove();
}
$scope.works = openInNewTab;
$scope.doesntWork = function() {
$http.get('https://api.github.com/users/angular').then($window.open($scope.uri));
};
});
For us the following worked well: http://blog-it.hypoport.de/2014/08/19/how-to-open-async-calls-in-a-new-tab-instead-of-new-window-within-an-angularjs-app/
In short: We remember the reference to the new window and changing the location afterwards.

parent.opener doesn't work in webview Android

I have a problem. I need to return to parent Url from Frame opened in a Android Webview.
The sequence is: Open inside Webview new frame. Select in frame options and paramters. Call in frame javascript function like _"javascript:parent.opener.jsfunction"_. Parent Web doesn't open...
I don't have access to Web. I work only in Android side.
I test Web in a firefox for Android and it works.
Need help.
By default, WebView doesn't support multiple windows. If you check, I believe the parent field actually isn't set and doesn't point to the parent window (or anything at all). The same applies to other similar fields like opener and top.
You might be able to work through this by enabling support for multiple windows and then implementing onCreateWindow in your WebChromeClient. I think there's some more you have to do, but it's been a while and I don't recall the details.
One way I've hacked around this in the past is to use setJavascriptInterface and just set the name to parent or whichever field you want. Implement the appropriate methods as necessary on your Java object. This can get a bit messy, but it works.

Communicating between different windows on the same domain [duplicate]

This question already has answers here:
Communication between tabs or windows
(9 answers)
Closed 6 years ago.
I am building an app that performs a lot of client side data downloading and processing. The data processing is isolated from the main app by being processed in an iframe that resides on a sub domain. It is this iframe that downloads the data. Communication is via postMessage.
Everything works fine, except it could be better.
If the user opens extra tabs/windows, the app currently reloads all the data and may even do duplicate processing work, which isn't a problem other than that it slows everything down and pages take longer to load.
What I would like to do is have each top level tab/window communicate with just the one processing iframe, which could be reinstated if the original window is closed. The trouble is, these are not opened via javascript, but via the normal browser methods to open links in tabs so I can't get a reference to the iframe that is needed to send a message.
Is there anyway I can communicate the window reference for the iframe to the other tabs so that they can communicate with it via a postMessage? Could this in someway be achieved using shared workers?
I realize I could use shared workers for the whole processing task, but this would have it's own problems as the the data comes from third party domains, which can't be accessed from within a worker.
Only compatibility with the latest versions of all major browsers is needed.
Edit: I've just discovered that SharedWorker is not yet implemented in firefox, so I guess that is not going to work. Any other way I could achieve this?
Edit 2: I've discovered that you can use :
var win = window.open('', 'my_window_name');
to capture a reference to an iframe from any other window. However, if the iframe does not already exist then it will open it as a window. Even if it is closed immediately, it causes a flicker and causes the 'popup blocked' messages, making it unusable.
In case any one else finds this, I've come up with a solution. It is somewhat hacky and requires further testing. But so far it is working. It works cross domain if that is needed.
It uses a combination of two tricks.
The first is to use
remote_window = window.open("", "remote_window_name");
to fetch a reference to the window. This works because if a window is already open with the given name then a reference is returned to it rather than opening a new window.
It does however have the problem that if the iframe does not exist then a new window will pop up. Local storage is used in order to prevent this. When a window/tab loads, it checks localStorage to see if there is another page already with a shared iframe. If not it inserts the the iframe and sets a flag in local storage to say that it is available.
As a last ditched resort, if the window still opens, a try block is used to close the newly opened window. The try block prevents cross domain errors. This means that the worst that will happen is the user sees a window pop up and disappear or they will see the 'enable pop-ups' message. I've yet to manage to trigger this in testing - it is only an edge case fall back.
try {
if(store_window.location.href === "about:blank" ){
remote_window.close();
remote_window = insertIfame();
}
} catch(err) {
}
An onunload event is added which removes the flag should the page be closed.
Also a setInterval is created that constantly refreshes a timeout flag. I have it running 4 times a second; when a second window/tab is loaded it checks that the iframe flag has not timed out before trying to communicate with it. This is a small overhead, but far less than the cost to me of having that second iframe loading. This serves the purpose of preventing stale data if the browser crashes or the the onunload does not fire for any reason. I include a small leeway when checking the timeout - currently 1 second - in case the main window is stuck in a loop. The leeway is only on the timeout, not the unload event which removes the flag entirely.
The flag needs to be checked every time a message is sent in case the original window with the iframe has closed. When this happens the iframe is reinserted in the first open window that requires it and the flag is reset.
Sending messages back is easy. Just use the event.source property of the receiveMessage -this points to the sending window.
One final edge case to account for is if the primary window closes whilst it's iframe is mid process for a secondary window. Theoretically this could be dealt with by using an onunload event in the iframe to send a message back to any windows with data in process. But I've yet to implement it and it may not finish before the page unloads. Another way of dealing with it would be by having a timeout in the secondary window which checks the flag and retries, I'll probably go this route as the messages already have timeouts attached.

Creating new tab / switching between Tabs in Firefox?

I am looking for a way to improve the workflow in a PHP based CMS. There is a lot of switching between the editor mode and the preview mode of the page. The editor mode is huge to load, and so I would like to open the preview mode in a different window.
I don't want to use new windows or an iframe within the current window to keep the workflow simple and to avoid confusion.
Is there a way to explicitly open a new tab (not window), and to jump to that tab from a document, in Firefox? The number of users is limited, so there is the possibility to set up the client with the necessary extensions / permissions.
I know Firefox can be forced to open all links in tabs, but I think that won't cut it, as I still can't address and focus the newly opened window.
Thanks for all the great answers everyone. I have now enough material to decide whether I'll take the greasemonkey approach, rely on the user to set up "open in tabs" and address the window by name, or use a "inline" HTML solution as so many of you suggested. I am accepting the answer that I feel went most effort into.
There is no way to force a window to open as a tab. It's all dependent on the user's preference settings.
I second the answers that say you should do this in HTML using Javascript. Then it can work in all browsers that support JS.
I would put two divs on the page and show/hide each div depending on which tab is selected. If you are clever about this you could trap the click on the tab and determine if the user left-clicked or middle-clicked. If they left click you load that tab on the page. If they middle-click you let the browser open a new tab/window (according to the user's prefs, don't try to force it), and leave the current window unchanged (that is, don't switch to the new tab). The action for clicking on the tab would be to use AJAX to load the contents of the remote document and put it into the tab. Use Javascript to modify the URL before submitting the AJAX request so that the server knows to send a web page fragment instead of the whole page.
The advantage of this dual-natured solution is that the tabbed approach will work the way you want it to work for the majority of cases, but for users with, say, two screens, or who prefer switching between browser tabs, they will still have the flexibility to work in multi-window mode. This can all be done without any browser extensions and it should work equally well in IE as well as Firefox, Opera, etc. Avoid locking yourself into one browser, even one as excellent as Firefox. One day a customer will need to use Opera or Safari and you'll be stuck.
You say you don't want to use an iframe to avoid confusion. Now I don't know about the layout of your website, but I've been using the approach that the editor opens in its own div right next to the content being edited and the content is being live updated as you edit. No need to change tabs.
(If the window is too narrow there are HTML tabs Edit and Preview)
It does not seem to add confusion to the user and for me this approach works really well. Maybe it's worth considering in your case.
What about using iframes and JavaScript?
I know you said you want to avoid 'confusion using iframes', but in my opinion if you really need to load different pages at the same time this is the best option.
In theory, you could create your own tab system using javascript or even better, using jQuery, because its UI module offers pretty cool tab control.
For every tab you could load separate "headerless-footerless" version of your specific admin page inside <iframe> element. If user wanted to modify something different, he will simply click on the tab and bring different iframe.
All this could also be done using AJAX, but iframe solution is quite easy as you just need to load ready page and all postbacks are already handled by original page and separated from master-admin-page.
You might also need to play a little bit to set correct height of your iframe to fit all the content without scrollbars, but this again, is just bit of javascript.
Nope, there's no way to force the opening of a new tab, simply because this would be unsupported by un-tabbed browsing
You can only set it to open a new window, not a new tab.
Greasemonkey springs to mind - a quick google gives open in tabs on left click. I think you could modify that so it only runs on one particular page, and you'd be up up and away.
This question made me wonder if HTML 5 allows that sort of specification, and it doesn't (nothing in one of the other hyperlink attributes, either). A new browsing context is a new browsing context, there's no way to express a preference for tab over window or foreground over background.
You can't force a tab, but if you use a target with a specific name, like target="my_cms_window", many browsers will open this as a new tab. Additionally, they will remember the name and if you use the target repeatedly, put the contents in the same tab. I have found that this works pretty well in the real world.

Categories

Resources