MooTools OpenLinks Class – Updated

By  on  

A long time back I coded a MooTools class called OpenLinks. The class is quite useful but the code...sucks. I've gotten much better with MooTools over the past years so I thought I'd go back and update the class to be better, faster, etc.

The Original MooTools Class

/* classes */
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');
				el.setStyle('color','#f00');
			}
		});
	}
});

Gross. Everything is an argument and the no_class argument is pointless since you can simply disqualify items in the elements option selector string.

The New MooTools JavaScript

/* class */
var OpenLinks = new Class({
	
	Implements: [Options],
	
	options: {
		elements: 'a',
		extensions: [],
		target: '_blank',
		overrideTarget: true
	},
	
	initialize: function(options) {
		this.setOptions(options);
		$$(this.options.elements).each(this.assign,this);
	},
	
	assign: function(el) {
		var href = 	el.get('href'), ext = href.substring(href.lastIndexOf('.') + 1,href.length).toLowerCase();
		if(this.options.extensions.contains(ext) && (this.options.overrideTarget || !el.get('target'))) {
			el.set('target',this.options.target);
		}
	}
	
});

Instead of making everything arguments I moved each argument into the options object. I also removed the no_class option/parameter.

The MooTools Usage

/* usage */
window.addEvent('load',function() {
	var openers = new OpenLinks({
		extensions: ['pdf','xls','doc','jpg'],
		elements: '#content a'
	});
});

Using OpenLinks is as easy as it should be!

It feels good to clean up code after a long time. I recommend you do so when you can too!

Recent Features

  • By
    Convert XML to JSON with JavaScript

    If you follow me on Twitter, you know that I've been working on a super top secret mobile application using Appcelerator Titanium.  The experience has been great:  using JavaScript to create easy to write, easy to test, native mobile apps has been fun.  My...

  • By
    Serving Fonts from CDN

    For maximum performance, we all know we must put our assets on CDN (another domain).  Along with those assets are custom web fonts.  Unfortunately custom web fonts via CDN (or any cross-domain font request) don't work in Firefox or Internet Explorer (correctly so, by spec) though...

Incredible Demos

  • By
    TextboxList for MooTools and jQuery by Guillermo Rauch

    I'll be honest with you: I still haven't figured out if I like my MooTools teammate Guillermo Rauch. He's got a lot stacked up against him. He's from Argentina so I get IM'ed about 10 times a day about how great Lionel...

  • By
    jQuery topLink Plugin

    Last week I released a snippet of code for MooTools that allowed you to fade in and out a "to the top" link on any page. Here's how to implement that functionality using jQuery. The XHTML A simple link. The CSS A little CSS for position and style. The jQuery...

Discussion

  1. quite cool …. but how about in jQuery side ?

  2. Very nice. Could be extended further to take the styles of the affected links as an option. This way people would be able to style their links during declration, instead of adjusting the class, el.setStyles(this.options.styles), or similar.

    Mootools FTW!

  3. @Colin Gillies: My bad — the link color wasn’t meant to be a part of this — it was only for the example. Removed.

  4. Anton

    That is what I hate. AFAIK, target is no longer part of XHTML. Besides, *user* should decide, whether to open a link in a new window or not.

  5. @Anton: I disagree. Many users click a link to open the PDF and close their browser to “close” the PDF. Then what? They’ve just closed their entire browser and “lost their spot”, so to speak. I contend that any developer should be able to decide if something opens in a new window.

  6. Anton

    @David Walsh: tell that to W3C. Users should be aware of the applications they use, including browser. And modern browsers know how to save last opened pages, so reopening the browser will not be a problem. Besides, a PDF will not open inside a browser, if there is no plugin installed for such behavior.

  7. @Anton: The W3C and validating services can say what they want. The “target” attribute works everywhere and since PDFs open in another program traditionally (Acrobat), opening a new window shouldn’t be anything out of the ordinary.

    Also note that I doubt persons who accidentally close their window know how to recover tabs.

    Use the “grandma” rule — if she doesn’t know, many others wont know.

  8. Anton

    @David Walsh: If my grandma doesn’t know how to switch gears on a manual gearbox, I don’t buy her a car with an automatic gearbox, I make her learn to drive.

    Also:
    – Firefox recovers tabs automatically if there wasn’t an error, same for most other browsers;
    – PDFs, even without target, open as a separate application (after downloading), if there is no PDF plugin in the browser.

  9. @Anton: How do you propose teach thousands of “grandmas” out there how to do some of this stuff? If you own a business, you still want my grandma’s money, don’t you? Most “grandmas” don’t know FireFox — most “grandmas” click the blue “E” icon.

  10. Listen2Me

    I’m with you on this one David; with the W3C removing target from the XHTML standard it has left us having to use window.open() instead. I’d love to see an implementation of your script that parses the string inside the HREF attribute for “http://” and opens these links in a new window as well.

  11. @Listen2Me: Seems easy enough, although in my experience, window.open() is more at risk of being blocked by popup blockers.

  12. Just my 2p, but I agree with David. As much as I like to adhere to W3C, when it comes to opening non-HTML files into the browser I always go for a new window. I have lost count how many times I have watched a client open a PDF / DOC in their browser and then closed the browser thinking it will return them to the site.

    We can’t teach everyone how to do it ‘properly’ without leaving long instructions next to each link. Also, most of the time the application or document isn’t W3C / accesibility friendly anyway.

  13. I’d put the elements in an argument of the initialize function. When I create classes I try to think about what is and isn’t an option. In this case, the links aren’t really an option, they are the whole point of the class.

    And for me, writing this.elements feels better than this.options.elements.

    As for the new window discussion:

    I’ve been doing software training/consulting for several years now for web-based software and have seen countless people “lose their place” when they close the browser thinking they’re just closing the PDF or whatever as David points out.

    However, I’ve also seen just as many people throw their hands up in frustration because the site or application popped up a new window and they “lost their document” or whatever. It’s not lost, it’s just behind the one you’re looking at, after all, it’s called windows for a reason.

    The decision has to be well thought out to pop open a new window or not based on the audience and context. I’m a fan of _blank when it’s appropriate. While I respect the w3c, I don’t understand the cultish clinging to ridiculous standards by the (mostly) basement developers. These aren’t medical documents anymore w3c, they’re applications.

  14. Also … new OpenLinks('a.open') is way better than new OpenLinks({ elements: 'a.open'})

  15. I think the best choice is to let users decide when to open a web page in a new tab/window, but force external documents to open new tabs.

  16. According to the W3C, they realized they made a mistake in deprecating the target attribute. They put it back in in HTML 5.

    http://www.w3.org/TR/html5-diff/

  17. @FoO Iskandar: Requesting the same thing here.

  18. EmEhRKay

    While I agree with David about the usefulness of target, my only beef is that this doesnt create valid html. Instead of doing el.set(‘target’…), one could attach a click event (yeah, the standard work-around for the removal of target) that would mimic target’s behavior.

  19. @EmEhRKay: So window.open? It’s a preference thing I guess but I prefer target-blank as it isn’t as often blocked by popup blockers.

  20. Evan

    I totally hate the idea of “external” links opening in a new window but I prefer for pdf files to open in a new window.

    With window.open you can’t really maximize a window or open it as a tab. The best you can do is get the screen size and open the new window to that dimension but it’s still not maximized. Setting the target to _blank just seems to work better.

    If you care about the appearance of your html validating you can set up the script to add the target attribute.

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