PDA

View Full Version : target="_blank" is not working



bktinsc
03-19-2012, 10:11 PM
Hi,

I have a complicated problem with a large Javascript script that someone else developed. I cannot post the script here because my boss won't let me, so forgive me for giving out just pieces of the situation.

This opens the PDF link in a new tab as expected: <a href="formulas.pdf" target="_blank">formulas</a>

This opens the PDF link in the same tab (not in a new tab): <a href="formulas.pdf" target="_blank" id="105">formulas</a>

The difference between the 2 links is the 2nd one has id="105" in it.

This 105 reference is something very unique to how the script "binds" itself to the link. If it "sees" 105, then it makes a call to a php program, the program does stuff, then returns "OK" as a string...and then opens the window on the browser.

This all works fine, except for links that have target="_blank" in them.

Below is the line of code from the script that I think is not recognizing whenever a target was bound to the link. I included the comment from the author.




// Redirect if the element is a link, submit if it was a form, otherwise do nothing
element2.href && element2.href != window.location ? window.document.location.href = element2.href : (element2.nodeName.toLowerCase() == 'form' ? element2.submit() : null);



(1) Does anyone have any idea how to pass the "target" to the link?


(2) I find the line of code above to be confusing. Is there another way this could be written with IF statements so it could be easier to follow?

Thank you for your help!!

jscheuer1
03-20-2012, 02:51 AM
Before we go trying to rewrite it, let's see if this really is the line where we can get the result we want. Change this part:


window.document.location.href = element2.href

to:


window.open(element2.href, element2.target)

So you would have:


// Redirect if the element is a link, submit if it was a form, otherwise do nothing
element2.href && element2.href != window.location ? window.open(element2.href, element2.target) : (element2.nodeName.toLowerCase() == 'form' ? element2.submit() : null);

If that is the line, then if there is a target, it will be respected. If there is no target, it will open in the current window. But the open() function is a little different than the location object. If there's a timeout involved (the code you show doesn't say so one way or the other), that would probably mess up open(). Give it a shot. If it works we can see about making the line more understandable.

bktinsc
03-20-2012, 03:33 PM
Hi John,

I can't thank you enough for stepping in and helping me with this!!

I did just what you said and IT WORKS...but another problem has been created.

Now, every link opens in a new window, with or without, the target="_blank". Here are 3 examples:

<a href="formulas.pdf">formulas</a>
<a href="formulas.pdf" target="_blank">formulas</a>
<a href="formulas.pdf" target="_blank" id="105">formulas</a>

I put these alerts in before the call to that line:

alert('href - ' + element2.href);
alert('target - ' + element2.target);

They show exactly what you would expect, when target is _blank it shows in the alert. When there is no target, the alert is empty. The Href is always correct.

To give more context to the line of code that you repaired, here are the 2 sections where that line is contained. One function is for all browsers, the other is only for IE.




// For well behaved browsers, this function called when the code gets a response from the server
script.onload = function ()
{
if (!responded) {
responded = true;
if (evalString) {
eval(evalString);
} // If the element had a previous function it is passed into this function as evalString. Run the function when a response is received from the server

// Redirect if the element was a link, submit if it was a form, otherwise do nothing
element2.href && element2.href != window.location ? window.open(element2.href, element2.target) : (element2.nodeName.toLowerCase() == 'form' ? element2.submit() : null);
}
};



// For Internet Explorer, this function called when the code gets a response from the server
script.onreadystatechange = function ()
{
if (this.readyState == 'complete' || this.readyState == 'loaded') {
if (!responded) {
responded = true;
if (evalString) {
eval(evalString);
} // If the element had a previous function it is passed into this function as evalString. Run the function when a response is received from the server
element2.href && element2.href != window.location ? window.open(element2.href, element2.target) : (element2.nodeName.toLowerCase() == 'form' ? element2.submit() : null);
}
}
};


Yes, there is a "time" concept here because this function is waiting on a text "OK" response back from a PHP program. Could this be affecting how window.open() is handled?

Thank you!!

jscheuer1
03-20-2012, 04:02 PM
The problem with open() and time is that many browsers see it as no longer a user initiated action so their popup blockers come into effect. But if you're getting a new tab, that's not a problem. And the problem you are getting is one I thought of as a possibility, but didn't want to complicate the code with if it wasn't. To fix that, let's try:


window.open(element2.href, element2.target || '_self')

bktinsc
03-20-2012, 05:57 PM
Hi John,

Awesome! Thank you! That change fixed it! (I'm beginning to think I'll be able to keep my job)

The only place that does not work now is when formulas are displayed in a popup. (I am new to DD, so if I need to put this in another thread, please tell me, but this issue relates to the same script.)

I inherited this popup function, and others use it, so I do not have permission to change it. I can only change the calling URL or preferably the "script".

So here is the problem.

When this link is clicked, IE9 shows this error:


'return' statement outside of function


<a id="formulas" onclick="wopenpop('formulas.html', 'popup', 760, 575); return false;" href="formulas.html">Show Formulas (opens in Popup window)</a>




<script>
<!--
function wopenpop(url, name, w, h)
{
w += 32;
h += 96;
var win = window.open(url, name, 'width=' + w + ', height=' + h + ', ' + 'location=no, menubar=no, ' + 'status=no, toolbar=no, scrollbars=no, resizable=no');
win.resizeTo(w, h);
win.focus();
}
// -->
</script>



I think that error is because the script has code looking for "return false;" which I suspect conflicts with wopenpop having return false; too.

This is the function that references "return false;" about 18 lines down where the *** is in the comment.



// ---------------------------------------------------
// Binds the listener event to a page element
// ---------------------------------------------------
function bindTheEvent(elem7, relation) {
// Check if the element is a form, if so it sets the onsubmit event. Otherwise sets onclick event
var eventString = (elem7.nodeName.toLowerCase() == 'form' ? 'onsubmit' : 'onclick');

// Gives a unique ID to the element if it doesnt have one already
elem7.id ? null : elem7.id = 'jsct' + relation;

// Start creating (and formatting) the function string to set the element's event to
var evalString = 'TrackFormula("' + elem7.id + '", ' + userKey + ', ' + domainKey + ', ' + relation;

// Grab the previous onsubmit or onclick function of the element to pass into the listener function
var previousFunction = (elem7.nodeName.toLowerCase() == 'form' ? String(elem7.onsubmit) : String(elem7.onclick));

// *** Configure the element to run the previous function after running the new tracking function
evalString += (previousFunction == 'undefined' || previousFunction == 'null' ? '' : ', "' + previousFunction.substring(previousFunction.indexOf('{') + 1, previousFunction.length - 1).replace(/"/g, '\\"').replace(/(\r\n|\n|\r)/gm, '') + '"') + ');return false;';

// Set new function to the newly configured string function
eval('elem7.' + eventString + ' = function(){' + evalString + '}');
}


Do you think the "evalString" at line 18 could be changed to check if return false already exists, then do not add it?

Thank you again :)

jscheuer1
03-20-2012, 08:45 PM
Probably not, but it might be. Even if it isn't, this might fix it, but then again maybe not - try just removing the return false from the code on the link. Remove the highlighted:


<a id="formulas" onclick="wopenpop('formulas.html', 'popup', 760, 575); return false;" href="formulas.html">Show Formulas (opens in Popup window)</a>

If that fixes it, fine. If not, or if there's a problem with doing it that way, let me know.

bktinsc
03-20-2012, 09:41 PM
Hi John,

Thank you for helping me...again!

I removed the return false; and that did stop the error...Great...but now when the link is clicked, the popup opens in a new tab (as expected) with formulas.html, but when the script returns back, the page containing the link that called wopenpop() opens a link to formulas.html in the same tab.

So there ends up being 2 tabs of formulas.html open at the same time. The 1st tab should have just stayed on the page that made the call to the link.

<a id="formulas" onclick="wopenpop('formulas.html', 'popup', 760, 575);" href="formulas.html">Show Formulas (opens in Popup window)</a>


p.s. Thank you for accepting my friend request. I tried to PM you but it says I do not have permission.

jscheuer1
03-20-2012, 10:58 PM
OK, hmm - Are we still talking about IE 9? I ask because I story boarded the functions and IE 9 (at least my IE 9) doesn't like:


win.resizeTo(w, h);

So no matter what you do, if you try to run that as part of the wopenpop() IE 9 shouldn't be opening the popup.

Additionally, even when that was removed and the onclick function returned false, the popup happened, but the page changed as well.

What I'm saying is that my experience with this isn't what I think you're saying yours is.

And I'm unclear what we can change. If we can change wopenpop(), let's make it:


function wopenpop(url, name, w, h)
{
w += 32;
h += 96;
var win = window.open(url, name, 'width=' + w + ', height=' + h + ', ' + 'location=no, menubar=no, ' + 'status=no, toolbar=no, scrollbars=no, resizable=no');
win.focus();
return false;
}

and make the link:


<a id="formulas" onclick="return wopenpop('formulas.html', 'popup', 760, 575);" href="formulas.html">Show Formulas (opens in Popup window)</a>

bktinsc
03-20-2012, 11:38 PM
Hi John,

(1) Unfortunately I am not allowed to change the wopenpop script, so I was not able to test your change. I wish I could.

(2) I was wrong on the IE version. I have 8 and not 9. But this has the same behavior in Firefox, Opera, and Safari (Mac) where the calling tab switches to formulas.html.

.

jscheuer1
03-21-2012, 03:47 AM
OK then, mmm - After playing with this quite a bit I see now that the wopenpop() function is simply broken. If it ever was OK, due to browser changes, it no longer is. And bindTheEvent(), though apparently serviceable, is ill advised. It could be rewritten to not depend upon strings so much. But I'm not going to worry about that at the moment. I did do that, but there's no guarantee it will dovetail with the rest of the code, which presumably is written using the same arcane approach.

We can dance around that some and make bindTheEvent work together with wopenpop in most but not all cases. Or we can bite the bullet and demand that wopenpop be changed. It can be changed in such a way that will not affect anyone who has come to depend upon it for this and/or other uses. Or we can use bindTheEvent to change it, again in such a way that will not affect anyone who has come to depend upon it for this and/or other uses.

Here's how wopenpop should be:


function wopenpop(url, name, w, h)
{
w += 32;
h += 96;
var win = window.open(url, name, 'width=' + w + ', height=' + h + ', ' + 'location=no, menubar=no, ' + 'status=no, toolbar=no, scrollbars=no, resizable=no');
try{win.resizeTo(w, h);}catch(e){}
win.focus();
}

Now, if still we cannot change it even though this will not hurt anyone else who is using it for this or any purpose, we can as I say write our change to it into bindTheEvent (addition highlighted):


// ---------------------------------------------------
// Binds the listener event to a page element
// ---------------------------------------------------
function bindTheEvent(elem7, relation) {
window.wopenpop = function(url, name, w, h)
{
w += 32;
h += 96;
var win = window.open(url, name, 'width=' + w + ', height=' + h + ', ' + 'location=no, menubar=no, ' + 'status=no, toolbar=no, scrollbars=no, resizable=no');
try{win.resizeTo(w, h);}catch(e){}
win.focus();
};
// Check if the element is a form, if so it sets the onsubmit event. Otherwise sets onclick event
var eventString = (elem7.nodeName.toLowerCase() == 'form' ? 'onsubmit' : 'onclick');

// Gives a unique ID to the element if it doesnt have one already
elem7.id ? null : elem7.id = 'jsct' + relation;

// Start creating (and formatting) the function string to set the element's event to
var evalString = 'TrackFormula("' + elem7.id + '", ' + userKey + ', ' + domainKey + ', ' + relation;

// Grab the previous onsubmit or onclick function of the element to pass into the listener function
var previousFunction = (elem7.nodeName.toLowerCase() == 'form' ? String(elem7.onsubmit) : String(elem7.onclick));

// *** Configure the element to run the previous function after running the new tracking function
evalString += (previousFunction == 'undefined' || previousFunction == 'null' ? '' : ', "' + previousFunction.substring(previousFunction.indexOf('{') + 1, previousFunction.length - 1).replace(/"/g, '\\"').replace(/(\r\n|\n|\r)/gm, '') + '"') + ');return false;';

// Set new function to the newly configured string function
eval('elem7.' + eventString + ' = function(){' + evalString + '}');
}

Now regardless how we do that, whether it's in the above function or by changing wopenpop itself, once we do one or the other of those two, all we need to do is (as we already had) remove the return false from the link:


<a id="formulas" onclick="return wopenpop('formulas.html', 'popup', 760, 575);" href="formulas.html">Show Formulas (opens in Popup window)</a>

bktinsc
03-21-2012, 03:28 PM
Hi John,

I updated the code and I'm still getting the same issue where the calling tab does not stay on the page, it opens formulas.html.

I talked to my boss and she agrees that you have helped us identify that the real issue is with wopenpop, so we are going to get the author of that code to correct their function, instead of us continuing to work on the script for this issue.

I can't thank you enough for stepping in to help me with all of this :) :)

I am sending you a PM through DD in 15 minutes, so please check your PM when you get a chance.

Thank you!!!!!!!