Trying to open window.open a page in ajax call response - javascript

i am trying to open window.open a page in ajax call response but its not work, but when i removed window.open line and uncomment alert then alert is working.
$.ajax({
url: "/xyz/xyxkk",
type: 'Get',
success: function (resp) {
window.open("https://www.w3schools.com");
//alert('hi');
if (resp) {
}
else {
alert('Sorry unable to do');
}
}
});
actually my requirement is page open as window popup

Comment would fit better but not enough reputation, sorry.
Due to the ever lasting battles between browsers and intrusive ads, all js functions that can open new tabs or windows have been severely limited for a long time now. You can't just randomly open new pages or windows.
Generally you can get around this, by 'associating' the window.open to a click event or similar user input. Else your solutions will probably break in the future, even if you get it working for the moment.
Try calling different elements of your code with a .onclick() to see what is allowed. Don't forget to check at least Chrome and Firefox, and also try a few adblockers. If your solution works reliably under all of those you should be good for future adwars to come.

Related

Using window.open in an async function in Firefox and Safari

The application I work on integrates with some platforms with some strict security policies when it comes to user authentication, and as such authentication from our side has to be handled a bit differently as well. The details here aren't terribly important.
I'm working on a new feature now where a user can open some items from a list, but from a UX perspective it would make the most sense to open these up in new tabs, since users will want to open a lot of them at once without having to navigate back to the list and find their place within it again.
So to get this working, our API has a redirects endpoint that handles the authentication. Implementation details aren't important, it's just important to know that this endpoint will receive a URL that should be navigated to (supplied from our UI), and it'll spit back out a redirect URL with a token.
As such, I've gone with the following function which gets called when a button is clicked by the user
async function openInNewTab() {
// $ajax is an axios instance that calls the endpoint
const { url } = await $ajax.post('/redirects', {
data: {
url: "myurl.com/route/to/go/to",
//...
}
});
window.open(url)
}
As you can see, it's very simple, it gets the redirect URL from our API and tries to open that URL in a new tab. This works in Chrome, however it doesn't work in Firefox or Safari, prompting the user that a popup was blocked.
I'm well aware that browser have a number of rules regarding popups and when they're blocked, however in this instance this action is being initiated by user interaction via a button click, the only problem being that the function getting called is asynchronous.
Is there any way to make this work in Firefox and Safari? The function simply doesn't work well enough in realistic network speeds without it being asynchronous, and with the way our application works there's no way for us to circumvent the redirect URL with something like a target="_blank" in a link, that would fail to authenticate properly.
There's 2 potential workarounds that I ended up with here.
They're both fairly similar, however from my testing it seems Safari is the strictest when it comes to parsing events as popups.
The one that works in all major browsers (Chromium-based ones, Firefox and Safari), but feels a bit hacky.
Found this here: https://stackoverflow.com/a/70463940/8610114
const { url } = await $ajax.post('/redirects', {
data: {
url: "myurl.com/route/to/go/to",
//...
}
});
setTimeout(() => {
window.open(url, "_blank");
});
And the other solution, although this one doesn't seem like it works in Safari consistently, as it gets blocked sometimes (seemingly randomly)
const newWindow = window.open('about:blank', '_blank');
const { url } = await $ajax.post('/redirects', {
data: {
url: "myurl.com/route/to/go/to",
//...
}
});
newWindow.location.href = url;

Setting HTML frame src not working in Safari

I am tasked to rewrite Javascript code built from the year 2000 because it only works in an IE browser. It needs to work in all browsers.
Obviously this was well before AJAX and they used framesets (not even iframe yet) to execute remote JSP/servlet calls into an HTML frame. These frames don't display any HTML other than the main frame. Then you need to make sure you update the code references to know which code to execute from which frame. The frames are a headache, but I have gotten these calls to work in all browsers except Safari.
$('frame[name="RegtypeFrame"]', window.parent.document).attr("src", url);
From there, I am going to the top most document to find the specific frame to load. The url variable is a JSP page that has javascript created by Java scriptlets. Nightmare, yes, but I don't have time/approval to re-write from scratch.
I have tried window.top in Safari but no luck. The code does not execute at all in Safari. I have also tried bypassing the frames altogether by using an AJAX GET, which works in all browsers, but since it is javascript I have to use eval which is a valid security risk.
$.ajax(
{
url: url,
method: "GET",
async: true,
dataType: "html"
}).done(
function(html)
{
// major security risk to use eval on remote javascript code
var dom = $(jQuery.trim(html));
dom.filter('script').each(function()
{
$.globalEval(this.text || this.textContent || this.innerHTML || '');
});
}).fail(
function(jqXHR, textStatus)
{
alert("Request failed: " + textStatus);
});
Does anyone have any suggestions or alternatives on how to resolve this issue? I have a workaround but it is a flawed security risk.
The original code seems to be working in Safari now, though I'm not sure of the reason why. I cleared the developer cache on previous attempts. Maybe there are other caches I'm not aware of. If you attempt to select the frame by id, it won't work for a non-iframe.
$('frame[name="RegtypeFrame"]', window.parent.document).attr("src", url);

Javascript running only once on Internet Explorer, runs properly when developer tools is open

We have an unusual problem with javascript running on IE 11. I tried it on one of our servers running IE8 and the same problem occurs. However, it runs fine on Chrome and Mozilla.
Here's the code in question:
SetGuideFatningCookie(fid); //set a cookie according to user choice
var validFatningCombo = ValidFatningCheck(); //ask server if user choice is valid using XMLHttpRequest GET request
if(validFatningCombo)
window.location.href = GetGuideTilbehoerURL(); //if valid redirect user to next page
else
popAutoSizeFancy("#GLfancy"); //if not show a fancybox with error text
The user chooses one of 7 choices. Then they click a button that runs the above code. The code sets a cookie containing the user's choice and asks the server if the choice is valid. If valid - we redirect the user and if not, we open a fancybox that contains some error text and two buttons - "Try again"(closes box and they can try again) and "Send us a message"(redirects user to our "ask us a question" page).
The code runs fine the first time the user goes to this process.
However, if they have chosen an invalid choice, they close the fancybox and try to choose another choice and continue -> then the fancy box appears ALWAYS, regardless of what the user chooses.
If they choose a valid choice and continue, get redirected to next page, then come back to this page and choose an invalid choice and press continue -> then they can continue to the next page without fancybox ever coming up.
However, if IE's developer tools are opened, the code runs correct every single time.
I have found many threads describing this is a problem with console.log. I have removed every single reference to console.log from all our .js files. It could be one of the external libraries that we are using, like jquery, modernizr, fancybox and menucool's tooltip library.
Therefore I tried including a console fallback function for IE, like this thread suggests:
Why does JavaScript only work after opening developer tools in IE once?
I am currently trying with this one, and I have tried every single other fallback console replacement from the thred I link to.
if (!window.console) window.console = {};
if (!window.console.log) window.console.log = function () { };
I tried including it:
Somewhere in our .js files
script element in head after loading all our .js files and all external libraries
script element in head before loading all our .js files and all external libraries
Inside $(document).ready(function() {}); , in a script element in head after loading all other js
So far, none of the fallback pieces of code I have tried in any of these 4 locations have solved the problem. It always behaves the same way in IE. I couldn't find another explanation than the "console" one for this problem so far, so if anyone got any insight on it, it would be greatly appreciated.
EDIT: I will include some more info:
The very act of opening Developer Tools removes the unwanted behaviour. No errors are ever shown in console.
I checked the server side to see if the server is getting the call from ValidFatningCheck(); It turns out that the call is made only the first time (or if Developer tools is open - every time) which is rather mysterious since the redirect/fancybox line comes after the server call and it doesn't fail to run, even if it runs wrong.
function ValidFatningCheck(){
var requestUrl = '/Tools.ashx?command=validscreen';
var req = new XMLHttpRequest();
req.open('GET', requestUrl, false);
req.send(null);
var res = "";
if (req.readyState==4)
res = req.responseText;
if(res == "true")
return true;
return false;
}
UPDATE : Problem solved by adding a timestamp to my XMLHttpRequest as multiple replies suggested. I didn't realize XMLHttpRequest uses AJAX so I overlooked it as a probable cause to the problem.
(I put in comments but will make this an answer now as it appears to have solved the problem) get requests are cached by IE but when the developer console is open it does not perform this cache.
three ways to fix:
add a timestamp to the request to trick the browser into thinking it is making a new request each time
var requestUrl = '/Tools.ashx?command=validscreen&time='+new Date().getTime();
set the response header to no-cache
make a POST request as these are not cached
(as pointed out by #juanmendes not ideal you are not editing a resource)

How do I detect if window.location failed?

How do I check if a call to window.location failed because the given URL was invalid, etc? Is there some event I can set on the window object or on some other object that can catch this?
Finally got it to work using a "workaround" that is not a generic solution as I originally hoped:
I am using the fact that the link I am trying to open is a custom url scheme (e.g. myxx://localhost) on mobile, and if it fails, the action I want to perform is a redirection to a standard appstore URL (os-specific). The workaround tries to open the custom URL, and if it fails, the timeout function kicks in shortly after, and opens an alternative url:
setTimeout(function() { window.location=alternateUrl; }, 25);
window.location = customUrl;
The downside is that when the customURL fails, a standard safari browser shows a message box that the site could not be opened, but at least it still redirects the user to the appstore.
Not really possible, because when window.location = someURL is executed, before the URL is even tested, your document is removed from the window. You have no code remaining that could test if it worked.
If the link is on the same origin, you may issue an XMLHttpRequest to test if the page is reachable but there doesn't seem to be a way to test if a page isn't requestable just due to cross origin request or because the URL is wrong.
For a general document, I don't know any way to test if a foreign origin page is reachable (but it can be done for an image using the onload event handler).
you can check if page exists using ajax. didn't test code, but it should work.
var rekuest= new XMLHttpRequest();
rekuest.open('GET', 'http://www.thisdoesnotexits.org', true);
rekuest.send();
if (rekuest.status === "404") {alert("not exist!"); }

How to display error (text/html) response to an AJAX/getJSON request?

My situation is, I'm developing a little web app where the server provides dynamic JSON responses. The server is built on cherrypy. Sometimes, there is a bug in the code creating the JSON data, which throws, and cherrypy catches it and serves back a 500-error with a full HTML page detailing the exception. (That is, the response has everything: <!doctype..><html><head>...</head><body>...</body></html>)
But because the request is AJAX, it doesn't get displayed.
I can intercept this error easily enough, and look at it in the dev tools; but what I'd like to do (to ease debugging) is open a new page (as if user had followed a link) and display that response in the browser. I tried
window.open('', '_self');
$(document).html(jqXHR.responseText);
but I just get a blank page. I suppose I could store the error text and serve it up in a second request to the server, but is there a cleaner way?
To follow up, the final code that worked was this:
.error(function(jqXHR, textStatus, errorThrown) {
$(window).bind('unload', function() { document.write(jqXHR.responseText); } );
var win = window.open('', '_self');
return false;
});
Not sure if that final return false is necessary but it seems good form.
Following up again: the above code worked reliably in Opera. I thought I had seen it working in Webkit as well, but I started noticing that it wasn't; and on further testing, it wasn't working for Firefox either.
What I found that worked in all three platforms was this:
document.open('text/html', true);
document.write(jqXHR.responseText);
document.close();
Don't have to open another window or bind events; just re-open the document and stuff the text in there.
Well, here I am again. The above technique either stopped working or I was tripping when I said it ever worked at all. Chrome, in particular, doesn't seem to have document.open defined.
But! I just found a nifty technique that seems to work everywhere:
errtext = 'data:text/html;base64,' + window.btoa(jqXHR.responseText);
window.open(errtext, '_self');
This simply converts the response into a fully self-contained data: URL and opens it in the window.
Try this:
var win = window.open('', '_self');
win.document.getElementsByTagName('Body')[0].innerText = jqXHR.responseText;

Categories