“return false” is ignored in certain browsers for link added dynamically to the DOM with JavaScript-Collection of common programming errors

I dynamically add an (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!

  1. 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);
    
  2. 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.

  3. 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.

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

  5. 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'));
    
  6. 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'));
    
  7. 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.

  8. 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;
    }
    
  9. 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 = '';
        if (url != '')
            result += '    

    ' + instituteName + '

    ';
        else
            result += '    

    ' + instituteName + '

    ';
        if (Trim(description) != '')
            result += '    
    ' + description + ''; result += '
    ' + address + ''; result += ''; return result; }
  10. @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 += '    

    ' + instituteName + '

    ' + "\n";
    

    Option Two

    Move the code into its own function:

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

    …and call that function instead:

    result += '    

    ' + instituteName + '

    ' + "\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 tag kicks in. I think specifying the url twice (once in the and again in the window.open() should fix it.

  11. 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 += '

    ' + instituteName + '

    ' + "\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.

Originally posted 2013-11-10 00:12:25.