(This is a phonegap app, for iOS & Android, using JS/HTML/CSS)
I open up links I want to use the inappbrowser using the class selector, 'external'. So I have the below code to open up those links:
$("body").on("click", "a.external", function(){
var thisHref = $(this).attr("href");
appBrowser = cordova.InAppBrowser.open(thisHref, '_blank', 'location=no, zoom=no');
appBrowser.addEventListener('loadstart', function(event) {
if (event.url == "XXXXX") { appBrowser.close(); }
});
At the external URLs themselves, I set up links that link to 'XXXXX' that should close out the inAppBrowser. Everything works 100% on the Phonegap Desktop emulator, but when I install the .apk or .ipa files on actual devices, loadstart doesn't get fired EXCEPT for the first initial click within the app.
This leads me to believe it's a scope issue, since it looks like the listener only picks up when the loadstart occurs directly after a click to a.external. (P.S. appBrowser is defined globally [var appBrowser; at top]).
I'm not exactly sure how to arrange the code so that the listener gets attached, and continues working the entire time. I have tried placing the addEventListener on its own, within deviceready function, or the whole thing within deviceready (neither work).
So I'm hoping there's something simple I'm missing here, and it is indeed a scope issue. Strange though that it works as is on the emulator, but only on the first click on the devices themselves.
Thanks!
Here's the relevant portions of how I have things setup in my phonegap project using InAppBrowser, which if I understand your question correctly is similar to how you want your setup.
phonegap-bootstrap.js
onDeviceReady: function() {
window.open = cordova.InAppBrowser.open;
}
when opening links
window.open(url, '_system', 'location=yes');
I suppose you don't need the location flag, but that keeps the URL bar when you open your new window. Hope that helps, I remember having to figure this out at some point, but any greater explanation I might have has been lost in my memory.
Related
We are busy with a web project where we need to capture a signature from a USB device. Getting this to work was pretty simple, but you need a browser add on.
However, once the page is placed into an iFrame (All on the same domain), it stops working. No errors or warnings, just does nothing when you click the button. It looks like the document.dispatchEvent function is not working... I think... I can see the custom event listener in Chrome dev tools.
The thing is, I added an event listener for click and that works on the page inside the iframe. It seems that dispatching custom events is not working.
Now, I'm far from an expert here and after hours of Googling and trying all sorts of different methods of which none worked I am running out of time and need help.
Is there some kind of limitation for custom events in an iframe? Security issue?
I created a JSFiddle using the example page from the company who makes the signature pads. (See below how to install browser addon). If you run the example on it's own, you will see a popup open up when you click the Sign button. You don't actually need the device for the popup to open. When the example page is in an iframe, it does nothing.
We need this to work on linux and windows, but I have the exact same issue on both platforms using google chrome.
<iframe style="width: 100%; height: 500px;" src="https://www.esignemcee.net/SigCaptureWeb/sign_chrome_ff_sigcapturewebsdk.html"></iframe>
JSFiddle
Chrome add-on install guid
EPad Signature example page
Adding top to my code seems to fix the problem. If you load your page in a iframe and need to add event listeners and dispatch those event in the 'child' page, then add top to your code like:
$(document).ready(function (){
top.document.addEventListener("MyCustom", _CustomHandler, true);
setTimeout(function ()
{
var MyDetail =
{
message: "blablabla"
};
var event = new CustomEvent('MyCustom', { detail: MyDetail });
top.document.dispatchEvent(event);
}, 1000);});
function _CustomHandler(EventData){
alert(EventData.detail.message);}
This seems to only be an issue when trying to engage with extensions in chrome. Normal events seem to work just fine. As such the code I've added above will work either way, but this is just to show exactly how the 'top' keyword is used.
Hopefully leaving this here will prevent someone else from spending 4 days trying to figure out why dispatching some events work in an iframe and some don't when using chrome. Chrome seems to handle events dispatched for extensions slightly different. I've not been able to find any documentation on this, but custom events and working with extensions like this from javascript is knew for me. Maybe someone more knowledgeable can add some more info.
In my Wordpress site, I've created a Modal shortcode, which opens a modal when the modal's "name" is in the hash part of the location.
For instance /#contact-us will open my "contact us" modal.
To do this I have a hashchange event listener on the window, using jQuery, as so:
$(document).ready(function () {
$(window).on('hashchange', function () {
openModal();
});
});
On my laptop, this works pretty fine.
The problem is that when I try it on my mobile phone (Nexus 5 - Chrome & Firefox), and even when I use Chrome's devtools emulator, when clicking on an anchor with a href="#contact-us", it won't work - The hash in the url changes but the event handler is not being called.
The weird thing is if I manually add a hash to the url, the event handler will be called.
I thought there might be another handler that is stopping the propagation or something like that, so I tried using jQuery's _data function (as mentioned here) to see if there are any handlers, but couldn't find any.
So I guess my question is, why isn't this working? and what else can I do to find out where the event is "getting lost"?
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.
The spec says, that I should be able to use postMessage() on a window object. Mozilla says, I should be able to do it on an open()'d window, too.
However, I've taken Robert Nyman's postMessage example and tried to make it work across windows. However, neither IE10 nor Chrome seem to provide the postMessage function for a newly opened window.
var target = … // original declaration
popoutbutton.onclick = function(evt) {
realWin = window.open(iframeWin.frameElement.src, "window1", "width=600,height=400,status=yes,scrollbars=no,resizable=yes");
target = realWin;
target.focus();
};
// …snip…
target.postMessage(myMessage.value, expectorigin); // <-- fails because target.postMessage() is undefined
Am I missing something or is this feature simply not there yet?
- update below -
The developer preview simply doesn't seem to do that. I tried again with the consumer preview. IE10 (build 8250) does it like expected. Thanks for your help!
I can get it working in Chrome 15.0.874.121 although in your sample you are calling target.postMessage before you have opened the window, although you have skipped whatever code originally sets target.
You may also be encountering the issue of calling postMessage before the content in the new window has loaded (or at least loaded enough for the event listener to be attached). So the event could be fired off when nothing is actually listening. You may need to add a wait in this scenario to ensure the newly opened window is loaded.
In Internet Explorer 10 I get the error SCRIPT16388: Operation Aborted whenever I try the script - even if I wait 10 seconds.
I'm trying to do something every time a new tab opens up, both via firefox starting and when a new tab is added after firefox starts. I've been following the example at:
https://developer.mozilla.org/en/Code_snippets/Tabbed_browser
So I have
var container = gBrowser.tabContainer;
container.addEventListener("TabOpen", tabAdded, false);
container.addEventListener("TabClose", tabClosed, false);
function tabAdded(event) {
alert("tabAdded!");
var browser = gBrowser.getBrowserForTab(event.target);
browser.pollingService = new PollingService(createGuid());
browser.pollingService.start();
}
And I have a similar function for the close. This works fine for when tabs are actually opened/closed, but I've run into a couple of problems.
Firstly, when Firefox opens, it has that initial tab already open, but the tabAdded event never fires for it. Similarly, when I shut down firefox, it never fires the TabClose for those tabs.
It seems like the correct thing to do in this case is to go through all of the tabs that are in the gBrowser.tabContainer and add my service to them as well, and do something similar for when Firefox closes. Unfortunately, I'm not quite sure how to hook in to know when Firefox closes (It's also possible there's a much better way to handle this, but I can't think of one).
Secondly, gBrowser.tabContainer can be uninitialized sometimes when my initialization script runs; is there a particular event I should be listening to to know when I can safely add listeners to the tabContainer?
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.