MooTools 1.2 OpenLinks Plugin

By  on  

I often incorporate tools into my customers' websites that allow them to have some control over the content on their website. When doing so, I offer some tips to my clients to help them keep their website in good shape. One of the tips I tell my customer is "whenever you create links to PDFs, Excel XLS', Word DOCs, or JPG/GIF/PNG images, make the link open in a new window." Unfortunately, my customers don't always follow this guideline.

In an effort to correct their mistakes, I've created a MooTools class that analyzes links on the page and adds a target attribute when necessary.

The Usage

window.addEvent('domready', function() {
var olinks = new OpenLinks(['doc','pdf','xls','jpg','gif','png'],1,'_that_window','no-target');
});

The class takes four arguments:

  • file_extensions: an array of file extensions you would like to open in a new/specified window. Add file extensions without the '.' and lower-cased.
  • override_targets: boolean, representing whether you want an anchor's "target" attribute to be overidden
  • target: string, defaults to "_blank" if none provided
  • no_class: if you don't want a link's target attribute set, add your custom class to those links.

As you can see in the code example above, I want the following file extensions to open in a window named "_that_window": Word DOCs, PDFs, XLS files, JPGs, GIFs, and PNGs. Links with the class no-target are not modified, even if the file extension is a match.

The Moo JavaScript

var OpenLinks = new Class({
//initialization
initialize: function(file_extensions,override_targets,target,no_class) {

//analyze all anchors
$$('a').each(function(el) {

//check each href for case-insensitive file extensions
var str = el.get('href');
var ext = str.substring(str.lastIndexOf('.') + 1,str.length)
if(file_extensions.contains(ext.toLowerCase()) && ((override_targets || !el.get('target')) && !el.hasClass(no_class + '')))
{
el.setProperty('target',target ? target : '_blank');
}
});
}
});

The Flow

For every link in the document, I extract the file extension. If the link's file extension is in the array of marked file extensions...and the link's target can be overridden or the link doesn't have a target set...and the link doesn't have the specified class...the link is then modified. It's that simple!

Click here to view an example of the class in use.

Click here to download the class in an external .js file.

Note

I'd initially built the class to use more specific CSS selectors:

a[href$='.pdf'], a[href$='.jpg'], a[href$='.doc']//...

The problem with doing this is that the above method doesn't allow for case-insensitiveness. For example, "pdf" would match but "PDF" would not.

Update

MooTools dev digitarald caught wind of my class and coded the following JavaScript to make the class' code a bit shorter:

// a lovely fast case-insensitive regexp build from file extensions
var rex = new RegExp('\\.(?:' + file_extensions.join('|') + ')$', 'i');
 
// href und target sind native properties for links, no get() needed
// no_class is now a required parameter
target = target || '_blank';
 
$$('a[href]:not(.' + no_class + ')').each(function(el) {
  if ((force || !el.target) && rex.test(el.href)) el.target = target;
});

Thank you dig'!

Recent Features

  • By
    Create a CSS Cube

    CSS cubes really showcase what CSS has become over the years, evolving from simple color and dimension directives to a language capable of creating deep, creative visuals.  Add animation and you've got something really neat.  Unfortunately each CSS cube tutorial I've read is a bit...

  • By
    7 Essential JavaScript Functions

    I remember the early days of JavaScript where you needed a simple function for just about everything because the browser vendors implemented features differently, and not just edge features, basic features, like addEventListener and attachEvent.  Times have changed but there are still a few functions each developer should...

Incredible Demos

Discussion

  1. Garrick

    Wouldn’t it be better to addEvent instead of adding a target attribute?

    Your method is just like adding the target attribute inline, which is not standards compliant.

    So you could do something like this instead:

    el.addEvent('click', function(e){
    (new Event(e)).stop();
    //plugin your own code in the open function.
    window.open();
    });
    
  2. @Garrick: I did things this way because people don’t always click on links. Inserting a target attribute makes the browser handle these links as they would had they been properly targeted.

  3. This is one of those cases where I struggle with “well, it validates, because I’m assigning the invalid stuff via JS”. Target’s been deprecated for awhile… so I shy away from using it, simply because there must have been SOME reason it’s frowned upon..

  4. @Andrea: Thank you for sharing!

  5. I personally never open links in new windows, ever. Jakob Nielsen agrees, with the exception of rich internet apps that demand a full, new browser window (and which omit standard browser controls like the back button). Otherwise, opening links in new windows should be at the option of the user.

    That being said, I appreciate that we sometimes must compromise for a client and your solution certainly is clean and to the point.

    Which particulars of your code are specific to MooTools 1.2? I’m going to write a series of articles comparing differences to the MooTools codebase between v1.11 and 1.2, and am curious if you’re using any 1.2-specific functionality in this code.

    Here’s the first article I wrote, which contains a brief overview of the additions/changes in MooTools 1.2:

    http://www.thetruetribe.com/2008/06/whats-new-in-mootools-12.php

  6. @Jonah: One of my biggest web pet peeves is when a PDF, DOC, or XLS file is not opened in a new window. You end up being done with the document, close the program, and realize you just closed your browser and all the tabs you had open. That inspired me to create this class.

  7. I see your point– it’s natural to hit the “x” to close a document when you’re finished with it, and can accidentally close the page you were on.

    After reading up on Jakob Nielsen’s alert box, it appears he agrees with you as well:

    http://www.useit.com/alertbox/open_new_windows.html

    Here’s what Jakob has to say about it:

    “Because users frequently close document windows, the best guidelines for linking to non-Web documents are:

    1. Open non-Web documents in a new browser window.
    2. Warn users in advance that a new window will appear.
    3. Remove the browser chrome (such as the Back button) from the new window.
    4. Best of all, prevent the browser from opening the document in the first place. Instead offer users the choice to save the file on their harddisk or to open it in its native application…”

    I think this is best for the majority of users, and power users can just override the browser’s new window functionality.

    Incidentally, to override target=”” links opening in a new window in Firefox, you can tweak the browser.link.open_newwindow setting in about:config — setting it to 1 opens target=”” links in the current tab, setting it to 2 opens them in a new window and 3 opens in a new tab (default).

Wrap your code in <pre class="{language}"></pre> tags, link to a GitHub gist, JSFiddle fiddle, or CodePen pen to embed!