Introducing MooTools LinkAlert

By  on  

One of my favorite Firefox plugins is called LinkAlert. LinkAlert shows the user an icon when they hover over a special link, like a link to a Microsoft Word DOC or a PDF file. I love that warning because I hate the surprise of opening a PDF file. The problem with LinkAlert in its current state is that it's only available with Firefox...until now. Armed with my favorite JavaScript library, MooTools, I've duplicated the functionality of LinkAlert.

The MooTools JavaScript Class

var LinkAlert = new Class({

	//implements
	Implements: [Options,Events],

	//options
	options: {
		container: document.body,
		extensions: {},
		offsets: { x:6, y:-15 },
		preloadImages: true,
		protocols: {},
		sticky: false,
		onShow: function(el,image) {
			this.image.setStyle('display','');
		},
		onHide: function(el,image) {
			this.image.setStyle('display','none');
		}
	},
	
	//initialization
	initialize: function(options) {
		//set options
		this.setOptions(options);
		this.extensions = new Hash(this.options.extensions);
		this.protocols = new Hash(this.options.protocols);
		this.image = new Element('img',{
			src: '',
			styles: {
				position: 'absolute',
				top: -200,
				left: -200,
				visibility: 'hidden'
			}
		}).inject(document.id(document.body));
		//preload images, if necessary
		if(this.options.preloadImages) { this.preloadImages(); }
		//add the listeners
		this.addListeners(this.extensions,'$=','extensions');
		this.addListeners(this.protocols,'^=','protocols');
	},
	
	//give direction to links
	addListeners: function(items,sep,type) {
		//for every item
		items.each(function(image,extension,type) {
			//for every link of that type
			$$('a[href' + sep + '\'' + extension + '\']').each(function(el) {
				//if the same protocol, don't bother showing
				if(type == 'protocol' && window.location.protocol == extension + ':') { return; }
				//add the show/hide events
				el.addEvents({
					mouseenter: function(e) {
						//position the image and give it the proper SRC
						this.reposition(e).set('src',image);
						//fire the event
						this.fireEvent('show',[el,image]);
					}.bind(this),
					mouseleave: function(e) {
						//fire the event
						this.fireEvent('hide',[el,image]);
					}.bind(this)
				});
				//sticky?
				if(this.options.sticky) {
					el.addEvent('mousemove',function(e) {
						this.reposition(e);
					}.bind(this));
				}
			},this);
		},this);
	},
	
	//repositions
	reposition: function(e) {
		return this.image.setStyles({
			left: e.page.x + this.options.offsets.x,
			top: e.page.y + this.options.offsets.y
		});
	},
	
	//preloads necessary images
	preloadImages: function() {
		var images = [this.protocols.getValues(),this.extensions.getValues()].flatten();
		new Asset.images(images);
	}
});

Options for LinkAlert include:

  • container: (defaults to document.body) The container to search for links within.
  • extensions: (defaults to {}) An object container file extensions and images to look for.
  • offsets: (defaults to { x:6, y:-15 }) The x and y offset from the mouse the icon should display.
  • preloadImages: (defaults to false) Whether or not to preload all file extension and protocol icons.
  • protocols: (defaults to {}) An object container protocols and images to look for.
  • sticky: (defaults to false) Defines whether the icon should follow the mouse while the mouse is hovered over a link.

Events for LinkAlert include:

  • Show: Fires when an icon shows.
  • Hide: Fires when an icon hides.

Sample Usage

/* do it */
window.addEvent('domready', function() {
	var graphicsDir = 'link-alert/';
	var context = new LinkAlert({
		extensions: {
			doc: graphicsDir + 'word.png',
			js: graphicsDir + 'js.png',
			pdf: graphicsDir + 'pdf.png',
			txt: graphicsDir + 'text.gif',
			xls: graphicsDir + 'xls.png',
			jpg: graphicsDir + 'jpg.png'
		},
		protocols: {
			ftp: graphicsDir + 'ftp.png',
			https: graphicsDir + 'secure.png',
			'javascript:': graphicsDir + 'js.png'
		},
		preloadImages: true,
		sticky: true,
		onShow: function(el,image) {
			this.image.fade('in');
		},
		onHide: function(el,image) {
			this.image.fade('out');
		}
	});
});

I use a few of the options and custom show and hide functionality.

I don't know if this plugin has practical usage for all users but I'll definitely be using it for sites that are in-development. Have any any other uses for this? Share them!

Recent Features

  • By
    9 Mind-Blowing Canvas Demos

    The <canvas> element has been a revelation for the visual experts among our ranks.  Canvas provides the means for incredible and efficient animations with the added bonus of no Flash; these developers can flash their awesome JavaScript skills instead.  Here are nine unbelievable canvas demos that...

  • By
    Camera and Video Control with HTML5

    Client-side APIs on mobile and desktop devices are quickly providing the same APIs.  Of course our mobile devices got access to some of these APIs first, but those APIs are slowly making their way to the desktop.  One of those APIs is the getUserMedia API...

Incredible Demos

  • By
    Smooth Scrolling with MooTools Fx.SmoothScroll

    I get quite a few support requests for my previous MooTools SmoothScroll article and the issue usually boils down to the fact that SmoothScroll has become Fx.SmoothScroll. Here's a simple usage of Fx.SmoothScroll. The HTML The only HTML requirement for Fx.SmoothScroll is that all named...

  • By
    MooTools CountDown Plugin

    There are numerous websites around the internet, RapidShare for example, that make you wait an allotted amount of time before presenting you with your reward. Using MooTools, I've created a CountDown plugin that allows you to easily implement a similar system. The MooTools JavaScript The CountDown class...

Discussion

  1. ali

    jQuery please!!!

  2. Mr.X.

    I find css selectors better. Don’t take me wrong this is great, but if you have a lot of script on your site, this would not be something I would recommend. Using just css is way smaller and has the same effect without fancy animation. For anyone who does not know about this.

    Nice script.

    Cheers!

  3. @Mr.X.: I’d usually agree but having icons all over place makes the page look like a circus.

  4. Mr.X.

    @David Walsh maybe so but it is easily fixed.

    You can do it like this

    print("a[href $= '.pdf']{padding-left:20px;}");
    
    print("a[href $= '.pdf']:hover{background: transparent url(../style/icons/pdf.png) no-repeat scroll left top;}");
    
  5. Marc

    Well, I haven’t set it up, but you could use it as user javascript in opera. Then it would pop up for all links in all website. This could be an alternative use I think.

  6. David, thanks a lot for that.
    Another of many useful tips, if I may call your hard work like that! =)

    Thanks!

  7. Wow, a nice piece of work!
    Like Marc said as userJS it’s a good alternative for the Firefox plugin for Opera users.

    But i must admit that for a single website the CSS solution of Mr.X. is more elegant.

    Anyway THX for this useful class.

  8. Wow, this is really nice. I think tweaking it to include the file path and putting in a little box to the lower right of the mouse would be perfect for my needs.

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