views:

335

answers:

11

I dynamically add an <a> (link) tag to the DOM with:

var link = document.createElement('a');
link.href = 'http://www.google.com/';
link.onclick = function () { window.open(this.href); return false; };
link.appendChild(document.createTextNode('Google'));
//someDomNode.appendChild(link);

I want the link to open in a new window (I know it's bad, but it's required). I also tried to use the "target" attribute, but I also have the wrong behavior with this solution too.

My code works well in IE and Firefox, but the return false don't work in Safari, Chrome and Opera. By don't work I mean the link is followed after the new window is opened.

I think I might be because of the Google Maps V3 environment...

Edit: To see the behavior on the actual page:

  1. Go to http://tinyurl.com/29q6nw6
  2. Click on any marker on the map, a balloon will show.
  3. Click on the title in the balloon, the link should open in a new window (work in IE and FF but not in Safari, Chrome and Opera.

Any help is welcome!

Edit2: The problem is in function "MakeInfoWindowContent" which is in "gmaps3.js". I don't use DOM to create the elements (I use string) because this HTML string must be passed to Google Maps (for the info window - the balloon). In fact the same link is created at 2 different places. One on the left, created with DOM function (as shown in this question) which works in all browsers and one in the balloon, created with an HTML string, this one don't work well in Safari, Chrome and Opera (the link is followed after the new window open even with the return false).

Edit 3: Still no clue why this is happening... If anyone have an idea, let me know!

A: 

How about avoiding using script to open the window?

var link = document.createElement('a');
link.href = 'http://www.google.com/';
link.target = '_blank';
link.appendChild(document.createTextNode('Google'));
Tim Down
Tested this solution and I have the same problem. Updated question with more details...
AlexV
I tested adding target="_blank" to the element and it worked (you should remove the onclick event handler then).
Gipsy King
+1  A: 

The problem might be a script error that cancels the javascript execution before the return false is reached. In that case the link is usually followed. Check if you are using a browser-specific method/property and check for javascript errors.

I cannot check your script as it doesn't seem to be available atm though.

dbemerlin
The script as you can see is really simple and works in IE 6-7-8 and Firefox. I highly doubt it's a script error as I can't see anything in the error logs in Chrome, Safari and Opera.
AlexV
You should check if you reach the return anyways (maybe just add an alert). If you reach it then the browsers just do not support this syntax for setting onclick events. Try `#` as href if you don't have to worry about users without javascript.
dbemerlin
I added an alert('debug') after the return and the alert isn't showing, so the return is executed but ignored in some browsers... Strange!
AlexV
+1  A: 

Few ideas

  • Google maps somehow re-copies (just a guess) html content before opening popup and leaves js events behind. You could try attach event listener after gmap popup has been opened.

  • in function MakeInfoWindowContent() code contructs events by concating strings -- maybe You should try it too.

  • Last (and stupid one) suggestion: try using addEventListener instead of attaching event directly.

petraszd
After some search, it's the concatening one that isn't working (the one in MakeInfoWindowContent). The one in pure JavaScript is working...
AlexV
+1  A: 

Set the href to 'javascript:void(0);' and instead of referencing this.href inside your onclick handler, hard-code the URL there instead.

Josh Stodola
+1  A: 

Would preventing default action for the event work maybe? Not sure if gmaps handles links in it's info window in some other way, if not, it should work.

Update: first example didn't work. The event wasn't passed when using "inline" onclick to assign event. This one is tested and found to be working.

function bindEvent(target, event, handler) {
    if (typeof target.addEventListener != 'undefined') {      
        target.addEventListener(event, handler, false);
    } else if (typeof target.attachEvent != 'undefined') {
        target.attachEvent('on' + event, handler); 
    } 
}

var link = document.createElement('a');
link.href = 'http://www.google.com/';
link.appendChild(document.createTextNode('Google'));

bindEvent(link, 'click', function (e) { 
    if (typeof e.preventDefault != 'undefined') {
        // Common/W3C events
        e.preventDefault();
    } 

    // (Old) IE specific events
    e.returnValue = false; 

    var target = e.target || e.srcElement;
    window.open(target.href); 

    return false; 
});

document.getElementsByTagName('body')[0].appendChild(link);
nikc
Downvoted, and no comment? Harsh.
nikc
A: 
var link = document.createElement('A');
link.setAttribute('href', 'http://www.google.com/');
link.setAttribute('onclick', 'window.open(this.href, "_blank");return false;');
link.appendChild(document.createTextNode('Google'));
artlung
A: 

Try this:

link.onclick = function(event) {
    window.open(this.href);
    if (event.stopPropagation)
        event.stopPropagation();
    return false;
};

I directly modified the DOM, via the Chrome-Developer-Tools and it worked for me.

Prjio
A: 

You aren't actually "dynamically add a link tag to the DOM". Your code just concatenates HTML strings. Replace your MakeInfoWindowContent function (in gmaps3.js) with native DOM methods.

function MakeInfoWindowContent(name, institutionName, description, address, url) {
    var result = document.createElement('div');
    result.className = 'infoBulle';
    // etc.
    return result;
}
Casey Hope
A: 

@AlexV - You have to keep inline onclick events atomic. There are two easy solutions: wrap the entire action inside a single self-executing function or move the window.open() and return false into its own function:

Option One

Use a self-executing anonymous function.

result += '    <h3><a href="' + url + '" onclick="(function(){window.open(' + url + '); return false;})()">' + instituteName + '</a></h3>' + "\n";

Option Two

Move the code into its own function:

function openCustomWindow(url) {
    window.open(url);
    return false;
}

...and call that function instead:

result += '    <h3><a href="' + url + '" onclick="openCustomWindow(' + url + ')">' + instituteName + '</a></h3>' + "\n";

[EDIT] I'm so sorry. I totally missed this. You should still do one of the two methods above (only a function can return false, not a statement). The problem here is actually that your this changes from your function to the actual onclick. When executed in the onclick, this refers to window, not the event. Because there is no window.href, the instruction to window.open(undefined) fails. And because it fails, the <a> tag kicks in. I think specifying the url twice (once in the <a href> and again in the window.open() should fix it.

Andrew
Ahh I surely tought this would work, but none of your solutions works (the link is followed after the new window is opened in Safari, Chrome and Opera).
AlexV
Wow. Completely missed the problem. I've updated the answer. It's really difficult tearing down what's inside the Google Maps window. I had to use `document.getElementById('resultMap').innerHTML` to see what the rendered HTML looked like in Safari (and FF). I wonder how they do that...
Andrew
A: 

Try using jQuery's event delegation:

function initialize(){
    // ... code ...

        $("#resultMap").delegate("a.myLink").click(function(){
            window.open(this.href, "myWindow");
            return false;
        });
        Search();

    // ... more code ...
 }


function MakeInfoWindowContent(name, instituteName, description, address, url)
{
    var result = '<div class="infoBulle">';
    if (url != '')
        result += '    <h3><a href="' + url + '" class="myLink">' + instituteName + '</a></h3>';
    else
        result += '    <h3>' + instituteName + '</h3>';
    if (Trim(description) != '')
        result += '    <p>' + description + '</p>';
    result += '    <p>' + address + '</p>';
    result += '</div>';
    return result;
}
David Murdoch
A: 

I've tested this solution and it works!

I propose you to take a different approach, but in my opinion easier and more clean: use jQuery .live events (I see that you already use jQuery, so there should be no problems doing this)!

You only need two small changes:

First change:

Change the 3rd line of MakeInfoWindowContent function to create links this way (it just removes the onclick attribute and adds a class for clarity):

result += '<h3><a class="marker_link" href="' + url + '">' + instituteName + '</a></h3>' + "\n";

Second change:

Wherever you want (for example on DOM load or before map creation) execute this:

$('div#resultMap a.marker_link').live('click', function(e) {
    window.open(this.href);
    e.preventDefault();
});

End :)

This works intercepting the click event in the bubbling phase at the document. I've tried it and it works even with Google Chrome.

Andrea Zilio
In fact it uses the same idea of the David Murdoch answer.
Andrea Zilio
Seems not to work since the links are dynamically added to the page. I tried to run the 2nd change at the right place, but the function append isn't made.
AlexV
Let me prove to you that it works :)Open Google Chrome and go to the interested page: http://www.plateformesinnovie.com/ . Then press Shift+Ctrl+J to open the Javascript console and execute (pasting it in the console) the following code (it's a different code from the above, I've removed the marker_link class): `$('div#resultMap a').live('click', function(e) { window.open(this.href); e.preventDefault();});` .Then click the link in a Marker and you would notice that now the link will not be followed in the current page, but only in (two) new windows!!.
Andrea Zilio
So, if you follow the changes I've reported it should really work. Just put the second change code into the window load event! It will work ;)
Andrea Zilio
Another way: use this version of the `gmaps3.js` script that I've updated for you to include the changes I've proposed: http://lab.epper.org/tmp/gmaps3.js Replace your `gmaps3.js` with mine (but don't link it from my website, instead download it and put it in your server... Otherwise the AJAX Request would fail)
Andrea Zilio