erichynds

Welcome to my online development portfolio and blog. I'm Eric Hynds, a 23 year old website developer living outside of Boston, Massachusetts, and I'm passionate about developing functional, standard-compliant, and user-friendly websites.

A jQuery UI Growl/Ubuntu-like Notification Widget

Update 7/6/2010: version 1.4.1 is out!

There are about a dozen other plugins out there that do this already, except most seem to come with an enormous footprint: 10-12k of code, X-number of images, and roughly 1000 options to support every plausible use case. For other minimalists like myself out there, here’s one built off the jQuery UI widget factory in approx. 110 lines of code and 100% CSS. In typical widget fashion, this implementation supports the most basic (and arguably most common) uses, but is flexible enough for more advanced cases.

Internet Explorer is a big-time downer with no HSLA/border-radius/box-shadow support, so if eye candy is important to you in IE, a transparent png background or similar can be added without much effort.

Usage

Using this widget is a simple four step process:

Step 1:

Include the JavaScript and CSS dependencies. Only the widget factory from jQuery UI is required.

  1. CSS file: ui.notify.css
  2. jQuery and the jQuery UI widget factory: ui.widget.js
  3. This widget: ui.notify.js

Step 2:

Create a container element to hold notifications, and a template from which all notifications will be constructed from. With this, you can have multiple containers on the same page holding different styles of notifications. Each container can contain different templates.

<!-- set the container hidden to avoid a flash of unstyled content
when the page first loads -->
<div id="container" style="display:none">
 
    <!-- 
    Later on, you can choose which template to use by referring to the 
    ID assigned to each template.  Alternatively, you could refer
    to each template by index, so in this example, "basic-tempate" is
    index 0 and "advanced-template" is index 1.
    -->
    <div id="basic-template">
        <a class="ui-notify-cross ui-notify-close" href="#">x</a>
        <h1>#{title}</h1>
        <p>#{text}</p>
    </div>
 
    <div id="advanced-template">
        <!-- ... you get the idea ... -->
    </div>
 
</div>

Once the widget is initialized on the container, each template is cached and removed from the DOM. You can add one or more close links in your template by assigning each anchor the class ui-notify-close. The close link in this example has additional styling through the class ui-notify-cross, which makes the “x” look like an icon.

Define any variables you want to include in this template using #{varname} syntax. You can call these anything you’d like.

Step 3

Initiate the widget on the container, optionally passing in a hash of default options:

// basic
$("#container").notify();
 
// or with options (there are only 2)
$("#container").notify({
    speed: 500,
    expires: false
});

Step 4

Notifications are actually displayed by calling the create method. Pass in an hash of variables to transpose into the template:

// notice the templates in step 2 are expecting title and text variables.
// you can add as many as you like, and call them whatever you want.
$("#container").notify("create", {
    title: 'Test Notification',
    text: 'This is an example of the default config, and will fade out after five seconds.'
});

If you’d like, set specific options for each notification by passing in a second hash:

// example of overriding the expires and speed options for one notification
$("#container").notify("create", {
    title: 'Test Notification',
    text: 'This is an example of the default config, and will fade out after five seconds.'
},{
    expires: false,
    speed: 1000
});

You can specify the template to use by passing in the ID of the template as the second parameter. This is optional, and if not provided the first template defined will be used. Alternatively, you can pass in the index of the template in the container as the second argument.

// create a new notification using the "basic" template
// that we defined in step 2.
$("#container").notify("create", "basic-template", { /* template vars */ });
 
// we can refer to the template by index as well.  this
// statement is equivalent:
$("#container").notify("create", 0, { /* template vars */ });

The create method returns a notification instance object with two public methods: open and close.

// create a new "sticky" notification
var instance = $("#container").notify("create", {}, { sticky:true });
 
// close it
instance.close();
 
// re-open it
instance.open();

Options

These options can be set for all notifications within a container, or on a notification-by-notification basis:

Parameter Description Default
speed The amount of time in milliseconds to fade notifications in and out. 500
expires Notifications will automatically close after this amount of time, in milliseconds. Set to 0 or false to create a “sticky” notifications. 5000
stack

New in version 1.2.1!

Notifications will stack downwards if set to “below” (default), or upwards if set to “above.”

below
custom
New in version 1.3!

A boolean value denoting whether or not the widget should apply its own styling classes. Set to false to roll your own notification themes (including ThemeRoller). You could simply overwrite the included CSS, but using this option allows you to create default AND custom notifications within the same containers, as well as maintain a clear upgrade path as you won’t have to touch any of the included files.

false

Events

These events can be bound by passing handlers in as options. Example:

// for a specific notification
$("#example").notify("create", { /* template vars */ },{
   open: function(){
      alert("Notification opened!");
   }
});
 
// or for all notifications within a container
$("#container").notify({
   open: function(){
      alert("Notification opened!");
   }
});
Event Description
beforeopen Fires before the notification opens. If false is returned inside this callback, the notification will not open.
open Fires after the notifcation opens.
close Fires after the notifcation closes.
click Fires if the user clicks anywhere in the notification itself (not on the close link(s), if present). Useful if you want to close the notification or perform some other action once the user has acknowledged the notice. The callback receives two parameters as arguments: the event object, and the notification instance object.

Example:

$("#container").notify("create", {
   title: 'Clickable Notification',
   text: 'Click on me to fire a callback'
},{
   click: function(e,instance){
      // close the notice if the user clicks anywhere inside it
      instance.close();
   }
});

FAQ

How do I use ThemeRoller in my templates?

First, create a template and apply the appropriate ThemeRoller classes, icon classes you want to use, etc.:

<div id="notification-container">
 
   <div id="themeroller" class="ui-state-error">
      <!-- close link -->
      <a class="ui-notify-close" href="#">
         <span class="ui-icon ui-icon-close" style="float:right"></span>
      </a>
 
      <!-- alert icon -->
      <span style="float:left; margin:2px 5px 0 0;" class="ui-icon ui-icon-alert"></span>
 
      <h1>#{title}</h1>
      <p>#{text}</p>
   </div>
 
   <!-- other templates here, if you'd like.. -->
</div>

Next, either when you init the widget or create a notification, ensure the custom parameter is set to false:

// prevent notify from imposing its own styling classes
// on ALL notifications inside this container 
var handler = $("#notification-container")
      .notify({ custom:true })
      .notify("create", { title:"foo", text:"bar" });
 
// or just themeroller templates
var handler = $("#notification-container")
      .notify()
      .notify("create", "themeroller", { title:"foo", text:"bar" }, { custom:true };

How do I add a close icon or link to my templates?

Any link, button, etc. with the class ui-notify-close will close the notification when clicked. To use the X close link as seen in the demos, apply the ui-notify-cross class as well:

<a class="ui-notify-close ui-notify-cross" href="#">x</a>

How do I avoid a FOUC (flash of unstyled content) when the page first loads?

Simply give your container the display: none; CSS property. Once you initialize this widget on the container, it’ll take care of the rest.

Related posts:

  1. jQuery UI MultiSelect Widget
  2. Tips for Developing jQuery UI 1.8 Widgets

Tags: , , , ,

View Comments to “A jQuery UI Growl/Ubuntu-like Notification Widget”

  1. Andreas Wenk says:

    if you like Mac's Growl check this jQuery plugin out – really nice

  2. Jan Seidl says:

    This is a really great plugin. I love this kind of notifications!

    Congrats for the job! Suggestions if you permit:

    - Enable prompt() like notifications (Yes/no)
    - Enable alternate positionings (top-left, top-center, bottom-left etc etc)
    - Templates (groupings of positioning/type configurations)

    Keep up the good work, I have a good JS knowlegde, let me know if you need some help.
    I'm on github too.

  3. Chuck says:

    did you inspire in $.growlUI from jQuery BlockUI to make this plugin?

    http://jquery.malsup.com/block/#demos

  4. ehynds says:

    @Jan, thanks. fork it up :)

    @Chuck very cool! Had not seen that. I was looking for something simple and lightweight on the widget factory, and decided to roll my own.

  5. Rilwis says:

    It's cool. I'm using Ubuntu, and when I launch the demo, I don't realize where's the Ubuntu's notification and where's yours. Very nice effect. Thanks for sharing.

  6. Alex Bailey says:

    Wow! Great stuff. Don't know if you noticed that your DISQUS logins don't work or at least they didn't for me.

  7. Evan Byrne says:

    This would be perfect for a project of mine if i could get it to load the notifications from the bottom right. Great job Eric!

  8. Evan Byrne says:

    This would be perfect for a project of mine if i could get it to load the notifications from the bottom right. Great job Eric!

  9. ehynds says:

    Evan, I just added a “position” option. Place the container on the bottom of the screen (position:absolute; bottom:0), and set the “position” option to “above”. See the updated demo page for more examples.

  10. jebaird says:

    Hey Eric, This widget is pretty slick. I just forked and committed a version on github, that adds ThemeRoller support, passing templates through the options, 3 predefined templates, default, error, and highlight so it works “out of the box”. Also I added the defaultTemplate option and rearranged the order of the arguments for the create method due to the default template option

    Please let me know what you think of my changes. Thanks for sharing this awesome piece of code.

  11. htrex says:

    your useful lib fails to replace variables in src and href attributes.
    I haven't checked yet with every browser but in FF and think
    that's normal, because { and } characters are not allowed in URLs and are replaced by the browser with %7B and %7D respectively.
    to make it work also there you should replace your regex with /#(?:{|%7B)(.*?)(?:}|%7D)/g

  12. Pablo says:

    Well, this is great, i'm new with CSS & javascript, I was testing this plugin and I have a question, how can I call create function from HTML? using

    <script type=”text/javascript”>
    create(undefined, { title:'Default Notification', text:'Example of a default notification.'});
    </script>
    simply does not work,

    in a link <a href=”#” onClick=”javascript:create(params)”>Link works perfectly
    I only want to show a notification after inserting a register into mysql database from php, thanks in advance.

    Pablo

  13. ehynds says:

    great catch – thanks a lot. I just committed this new regex.

  14. ehynds says:

    You need to call create on your container: $(“#container”).notify(“create”, { title: 'default', text: 'example' })

  15. ehynds says:

    Awesome jebaird. I love the “cross” close icon in there from themeroller and the error/success classes. nice work!

  16. jebaird says:

    I forked a version on github that integrates jQuery UI ThemeRoller you should check it out – http://github.com/jebaird/jquery-notify

  17. Pablo says:

    Thanks again, it works perfectly.

  18. jebaird says:

    I forked a version on github that integrates jQuery UI ThemeRoller you should check it out – http://github.com/jebaird/jquery-notify

  19. Pablo says:

    Thanks again, it works perfectly.

  20. Adrian says:

    I cannot get beforeOpen event to fire. I have already defined the default options for the parent container, but am trying to overwrite for the beforeOpen for a child. Is this a known bug

  21. Adrian says:

    Sorry let me correct it. I can't get beforeOpen to fire period. I'm testing in firebug

    var $container = jQuery('#notifications').notify({
    expires: 5000,
    open:function(e, instance){
    jQuery(this).effect('bounce');
    },
    speed: 1200,
    stack:'above',
    click:function(e, instance){
    instance.close();
    },
    beforeOpen:function(e, instance){
    jQuery(this).addClass('systemError');
    }
    });

  22. ehynds says:

    Hi Adrian,

    I actually did find a bug while testing this out, but only when binding to the “notifybeforeopen” event, not when passing a handler in the options which is what you're trying to do. Rename “beforeOpen” to “beforeopen” (all lowercase) and see if that doesn't fix it.

    I've put a test together so you can see the events are working correctly: http://jsfiddle.net/866C9/

  23. Don't be fooled by new face, it's Adrian. All lowercase solved the problem! Thanks so much for your help and for developing this awesome widget!

  24. Pablo says:

    I was trying to keep the close button on a regular notification but it seems that the widget itself deletes the close button class.

    Does anyone has a work around for this?
    I would like to be able set a notification to auto fadeout and also give the user to close it.

  25. This is not a solution, but for your first inquiry I think if the sticky property is set to false, the widget will not display the close button.

    As for the second, set an expires time and set the click function to like Eric has done above.
    click:function(e, instance){
    instance.close();
    }

    So i guess a solution would be to set:
    sticky: false,
    click:function(e, instance){
    instance.close();
    }

  26. Pablo says:

    i came with a solution where i can keep the close button and have the auto fadeout effect in the widget as well, using some global variables.

    Maybe not the best solution but it works, here is the function and the globals:
    The pretty print code link: http://pastie.org/989866 *code block are broken when pasted here directly

    If you took a look the code here are some examples:

    Creates a sticky note that fadesout after 5 seconds
    create(false,{title: “Hello World”})

    Creates a sticky note that fadesout after 10 seconds
    create(false,{title: “Hello World”},10)

    Creates a REAL sticky note that won't fadeout automatically
    create(false,{title: “Hello World”},0)

  27. ehynds says:

    Yeah, i hide the close link if the notification isn't “sticky” because I personally don't see a need for it. The notification will close itself and is how Ubuntu/Growl works.

    You guys tell me – does it make sense to have another option labeled “showCloseIcon” or something to the effect?

  28. Pablo says:

    Thanks for the great widget man, is just what i needed , this should be included in the jquery UI widgets.

    One question, can i do some minor modifications to the widget? i just want to edit the animation effects for my own use.

  29. ehynds says:

    Sure, do whatever you'd like!

  30. ehynds says:

    Sure, do whatever you'd like!

  31. ehynds says:

    Hi folks,

    I released 1.3 this morning, which includes an option that will prevent notify from applying it's own styling class. With this, you can truly customize the notifications however you'd like, including applying ThemeRoller classes.

    See the updated demos for an example of ThemeRoller-styled notifications, and read the (new) FAQ section on how to set it up.

    Thanks!

  32. ehynds says:

    Hi folks,

    I released 1.3 this morning, which includes an option that will prevent notify from applying it's own styling class. With this, you can truly customize the notifications however you'd like, including applying ThemeRoller classes.

    See the updated demos for an example of ThemeRoller-styled notifications, and read the (new) FAQ section on how to set it up.

    Thanks!

  33. Dave Forster says:

    I'm liking this a lot but have noticed an issue with this in Internet Explorer (surprise surprise). On page load the “Container” div and it's contents can be seen initially before the widget initialises i.e. it flickers. This behaviour isn't present in FF. Is there a work around ?

  34. ehynds says:

    Hi Dave, thanks for the comment. I released version 1.4 this morning to address this issue… just make sure your container is set to display:none; and you'll be all set.

  35. Dave Forster says:

    Great stuff.. cheers

  36. In your example where you are using an image in your template, you use src=”#{icon}” — this is not a good way to handle this. If you examine the page and your requests/logs, you'll notice that a tag like that will cause the server to make an additional request to the page like: http://example.com/#{icon}. This is no bueno. The way to alleviate this is to, instead, do #{icon} for the entire image tag and then replace it with <img src=”/images/imagesrc.jpg”> instead of just replacing the src attribute.

  37. Guest says:

    Did you submit your plug-in to the jQuery UI Team ? I can't see anything related with it :(

  38. cdnpic says:

    nice.we can create notifications in ubuntu using lib-notify ;)

  39. ehynds says:

    have not. to be honest, I'm too lazy/busy to draw up a spec for their wiki :)

  40. ehynds says:

    no bueno indeed. I shall fix.. thx for the heads up.

  41. Guest says:

    Well if you are ok, i might have some time during the first week of August.
    May be i could improve the plugin by making it more compliant with ThemRoller, more modular, and add some functionnalities inspired by this plugin : http://www.stanlemon.net/projects/jgrowl.html
    And submit it.

  42. Chimpski says:

    I'm having issues with IE7 and this plugin the demo seems to work in IE7 but I can't seem to get 1.4 to work. Is this an issue fixed in 1.4.1? The div is showing up left aligned inside the page instead of on top of it in the right top corner. Any ideas what I'm doing wrong?

  43. ehynds says:

    1.4.1 changes the positioning to fixed instead of absolute, which may very well solve your issue. give it a try.

blog comments powered by Disqus