Bypass popup blocker on window.open when JQuery event.preventDefault() is set
I want to show a JQuery dialog conditionally on click event of an hyperlink .
I have a requirement like on condition1 open a JQuery dialogue and if condition1 is not satisfied, navigate to the page as referenced by 'href' tag of whose click event is in question.
I am able to call a function on link's click event. This function now checks the said condition by executing another URL (that executes my Spring controller and returns response).
All works perfect with only window.open being blocked by popup blocker.
$('a[href*=/viewpage?number]').live('click', function(e) {
e.preventDefault();
redirectionURL = this.href;
pageId= getUrlVars(redirectionURL)["number"];
$.getJSON("redirect/" + pageId, {}, function(status) {
if (status == null) {
alert("Error in verifying the status.");
} else if(!status) {
$("#agreement").dialog("open");
} else {
window.open(redirectionURL);
}
});
});
If I remove e.preventDefault();
from code, popoup blocker doesn't block the page, however for condition1 it then opens the dialogue as well as opens the 'href' page.
If I solve one, it creates issue for another. I am not able to give justice to both conditions simultaneously.
Could you help me solve this issue please?
Once this is solved I have another issue to solve i.e. navigation on dialogue's OK event :)
Popup blockers will typically only allow window.open
if used during the processing of a user event (like a click). In your case, you're calling window.open
later, not during the event, because $.getJSON
is asynchronous.
You have two options:
Do something else, rather than
window.open
.-
Make the ajax call synchronous, which is something you should normally avoid like the plague as it locks up the UI of the browser.
$.getJSON
is equivalent to:$.ajax({ url: url, dataType: 'json', data: data, success: callback });
...and so you can make your
$.getJSON
call synchronous by mapping your params to the above and addingasync: false
:$.ajax({ url: "redirect/" + pageId, async: false, dataType: "json", data: {}, success: function(status) { if (status == null) { alert("Error in verifying the status."); } else if(!status) { $("#agreement").dialog("open"); } else { window.open(redirectionURL); } } });
Again, I don't advocate synchronous ajax calls if you can find any other way to achieve your goal. But if you can't, there you go.
Here's an example of code that fails the test because of the asynchronous call:
Live example | Live source(The live links no longer work because of changes to JSBin)jQuery(function($) { // This version doesn't work, because the window.open is // not during the event processing $("#theButton").click(function(e) { e.preventDefault(); $.getJSON("http://jsbin.com/uriyip", function() { window.open("http://jsbin.com/ubiqev"); }); }); });
And here's an example that does work, using a synchronous call:
Live example | Live source(The live links no longer work because of changes to JSBin)jQuery(function($) { // This version does work, because the window.open is // during the event processing. But it uses a synchronous // ajax call, locking up the browser UI while the call is // in progress. $("#theButton").click(function(e) { e.preventDefault(); $.ajax({ url: "http://jsbin.com/uriyip", async: false, dataType: "json", success: function() { window.open("http://jsbin.com/ubiqev"); } }); }); });
you can call window.open without browser blocking only if user does directly some action. Browser send some flag and determine that window opened by user action.
So, you can try this scenario:
- var myWindow = window.open('')
- draw any loading message in this window
- when request done, just call myWindow.location = 'http://google.com'
I had this problem and I didn't have my url ready untill the callback would return some data. The solution was to open blank window before starting the callback and then just set the location when the callback returns.
$scope.testCode = function () {
var newWin = $window.open('', '_blank');
service.testCode().then(function (data) {
$scope.testing = true;
newWin.location = '/Tests/' + data.url.replace(/["]/g, "");
});
};