undo preventDefault() or better way to programmatically disable collections of links

jon3laze picture jon3laze · Jun 14, 2011 · Viewed 16.6k times · Source

I have a page that has event listeners for the network status. When the network is 'offline' I want to disable any cross domain links as to go into an offline mode. I was trying to use .preventDefault(), however when the app comes back online I need to re-enable the links.

Event Listeners

//check network status
if(!navigator.onLine) { 
    offlineLinks(); //Offline mode function
}
//add event listeners for network status
window.addEventListener('offline', function(e) {
    offlineLinks(); //Offline mode function
}, false);
window.addEventListener('online', function(e) {
    //need to re-enable links/Online mode
}, false);
window.addEventListener('error', function(e) {
    alert('Error fetching manifest: there is a good chance we are offline.');
    offlineLinks(); //Offline mode function
});

Function for 'de-linking'

function offlineLinks() {
    $('a[href^="http"]').click(function(e) {
        e.preventDefault();
        $('#offline-dialog').dialog({
            modal: true,
            buttons: {
                Ok: function() {
                    $(this).dialog('close');
                }
            }
        });
    });
}

I am looking for a scalable solution that won't cause lag if there are significant numbers of links on the page. Is there a simple solution to reverse the .preventDefault() call or a better way to accomplish this task?

Possible Solutions


My initial thoughts were either having store an array of the href values and then remove/add. I have been playing around with the HTML5 storage using webdb's I could create a database for and dynamically pull the hrefs onclick...however I'm not sure if this is the best solution for this.

Answer

NeilK picture NeilK · Jun 14, 2011

You seem to be using jQuery, at least for the link handler part.

The thing to realize is that $.click(handler) is just shorthand for .bind('click', handler). If you define the handler elsewhere, you can also unbind it later, like this:

var handler = function(event) { 
  event.preventDefault();
  console.log("the links, they do nothing!");
}

// when you want the external links to be inactive.
// you could use .click(handler) here too, it's the same.
$('a[href^="http"]').bind('click', handler);

// when you want them back
$('a[href^="http"]').unbind('click', handler);

By the way, href^="http" is a bit fragile, if you only want this to happen to external links. Internal links might start with "http", and some external links could start with other protocols like "ftp". Better to give such links their own class, like Wikipedia does with 'external'.