How to open stubborn javascript links in a new tab or new window?

Some websites use "creative" (javascript?) hyperlinks which break browser functionality, such as the ability to ctrl+click or middle click links to open them in a new tab.

A common example, taleo HR websites http://www.rogers.com/web/Careers.portal?_nfpb=true&_pageLabel=C_CP&_page=9

No matter what I try, I can only follow links by clicking on them normally; I can't open them in a new window. Is there any way around this?


Solution 1:

Your question is specific to Taleo, so my answer will be too :)

I've coded a UserScript that does what you want: it replaces all the JavaScript links with normal links, so you can just click them or open them in a new tab if you want.

// ==UserScript==
// @name        Taleo Fix
// @namespace   https://github.com/raphaelh/taleo_fix
// @description Taleo Fix Links
// @include     http://*.taleo.net/*
// @include     https://*.taleo.net/*
// @version     1
// @grant       none
// ==/UserScript==

function replaceLinks() {
    var rows = document.getElementsByClassName("titlelink");
    var url = window.location.href.substring(0, window.location.href.lastIndexOf("/") + 1) + "jobdetail.ftl";

    for (var i = 0; i < rows.length; i++) {
        rows[i].childNodes[0].href = url + "?job=" + rows[i].parentNode.parentNode.parentNode.parentNode.parentNode.id;
    }
}

if (typeof unsafeWindow.ftlPager_processResponse === 'function') {
    var _ftlPager_processResponse = unsafeWindow.ftlPager_processResponse;
    unsafeWindow.ftlPager_processResponse = function(f, b) {
        _ftlPager_processResponse(f, b);
        replaceLinks();
    };
}

if (typeof unsafeWindow.requisition_restoreDatesValues === 'function') {
    var _requisition_restoreDatesValues = unsafeWindow.requisition_restoreDatesValues;
    unsafeWindow.requisition_restoreDatesValues = function(d, b) {
        _requisition_restoreDatesValues(d, b);
        replaceLinks();
    };
}

You can find it here: https://github.com/raphaelh/taleo_fix/blob/master/Taleo_Fix.user.js

Solution 2:

Yes. You can write your own scripts for Greasemonkey (Firefox) or Tampermonkey (Chrome)

For the example you mentioned, this Tampermonkey UserScript will set all JavaScript links in the search results to open in new tab / window (this depends on browser configuration, it's tabs for me).

// ==UserScript==
// @name       open links in tabs
// @match      http://rogers.taleo.net/careersection/technology/jobsearch.ftl*
// ==/UserScript==

document.getElementById('ftlform').target="_blank"

Though you can write more generic versions of this, enabling this functionality for all JavaScript links without breaking other usability will be hard.

A middlepath could be to set an event handler for Ctrl, that will temporarily set the target for ALL forms to "_blank" as long as the key is held.

Solution 3:

Here's another userscript, which wraps any element with an onclick="document.location='some_url'" attribute in an <a href=some_url> element and removes the onclick.

I wrote it for a specific site, but it's generic enough that it may be useful to others. Don't forget to change the @match URL below.

This works when the links are loaded by an AJAX call, hence the MutationObserver.

// ==UserScript==
// @name         JavaScript link fixer
// @version      0.1
// @description  Change JavaScript links to open in new tab/window
// @author       EM0
// @match        http://WHATEVER-WEBSITE-YOU-WANT/*
// @grant        none
// ==/UserScript==

var modifyLink = function(linkNode) {
    // Re-create the regex every time, otherwise its lastIndex needs to be reset
    var linkRegex = /document\.location\s*=\s*\'([^']+)\'/g;

    var onclickText = linkNode.getAttribute('onclick');
    if (!onclickText)
        return;

    var match = linkRegex.exec(onclickText);
    if (!match) {
        console.log('Failed to find URL in onclick text ' + onclickText);
        return;
    }

    var targetUrl = match[1];
    console.log('Modifying link with target URL ' + targetUrl);

    // Clear onclick, so it doesn't match the selector, before modifying the DOM
    linkNode.removeAttribute('onclick');

    // Wrap the original element in a new <a href='target_url' /> element
    var newLink = document.createElement('a');
    newLink.href = targetUrl;
    var parent = linkNode.parentNode;
    newLink.appendChild(linkNode);
    parent.appendChild(newLink);
};

var modifyLinks = function() {
    var onclickNodes = document.querySelectorAll('*[onclick]');
    [].forEach.call(onclickNodes, modifyLink);
};

var observeDOM = (function(){
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver;

    return function(obj, callback) {
        if (MutationObserver) {
            var obs = new MutationObserver(function(mutations, observer) {
                if (mutations[0].addedNodes.length || mutations[0].removedNodes.length)
                    callback();
            });

            obs.observe(obj, { childList:true, subtree:true });
        }
    };
})();


(function() {
    'use strict';
    observeDOM(document.body, modifyLinks);
})();