2808 |
rexy |
1 |
/**
|
|
|
2 |
* jGrowl 1.2.6+jquery1.9fix+jquery3fix+bindfix
|
|
|
3 |
*
|
|
|
4 |
* Dual licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
|
|
|
5 |
* and GPL (http://www.opensource.org/licenses/gpl-license.php) licenses.
|
|
|
6 |
*
|
|
|
7 |
* Written by Stan Lemon <stosh1985@gmail.com>
|
|
|
8 |
* Last updated: 2011.03.27
|
|
|
9 |
*
|
|
|
10 |
* jGrowl is a jQuery plugin implementing unobtrusive userland notifications. These
|
|
|
11 |
* notifications function similarly to the Growl Framework available for
|
|
|
12 |
* Mac OS X (http://growl.info).
|
|
|
13 |
*
|
|
|
14 |
* To Do:
|
|
|
15 |
* - Move library settings to containers and allow them to be changed per container
|
|
|
16 |
*
|
|
|
17 |
* Changes in 1.2.6
|
|
|
18 |
* - Fixed js error when a notification is opening and closing at the same time
|
|
|
19 |
*
|
|
|
20 |
* Changes in 1.2.5
|
|
|
21 |
* - Changed wrapper jGrowl's options usage to "o" instead of $.jGrowl.defaults
|
|
|
22 |
* - Added themeState option to control 'highlight' or 'error' for jQuery UI
|
|
|
23 |
* - Ammended some CSS to provide default positioning for nested usage.
|
|
|
24 |
* - Changed some CSS to be prefixed with jGrowl- to prevent namespacing issues
|
|
|
25 |
* - Added two new options - openDuration and closeDuration to allow
|
|
|
26 |
* better control of notification open and close speeds, respectively
|
|
|
27 |
* Patch contributed by Jesse Vincet.
|
|
|
28 |
* - Added afterOpen callback. Patch contributed by Russel Branca.
|
|
|
29 |
*
|
|
|
30 |
* Changes in 1.2.4
|
|
|
31 |
* - Fixed IE bug with the close-all button
|
|
|
32 |
* - Fixed IE bug with the filter CSS attribute (special thanks to gotwic)
|
|
|
33 |
* - Update IE opacity CSS
|
|
|
34 |
* - Changed font sizes to use "em", and only set the base style
|
|
|
35 |
*
|
|
|
36 |
* Changes in 1.2.3
|
|
|
37 |
* - The callbacks no longer use the container as context, instead they use the actual notification
|
|
|
38 |
* - The callbacks now receive the container as a parameter after the options parameter
|
|
|
39 |
* - beforeOpen and beforeClose now check the return value, if it's false - the notification does
|
|
|
40 |
* not continue. The open callback will also halt execution if it returns false.
|
|
|
41 |
* - Fixed bug where containers would get confused
|
|
|
42 |
* - Expanded the pause functionality to pause an entire container.
|
|
|
43 |
*
|
|
|
44 |
* Changes in 1.2.2
|
|
|
45 |
* - Notification can now be theme rolled for jQuery UI, special thanks to Jeff Chan!
|
|
|
46 |
*
|
|
|
47 |
* Changes in 1.2.1
|
|
|
48 |
* - Fixed instance where the interval would fire the close method multiple times.
|
|
|
49 |
* - Added CSS to hide from print media
|
|
|
50 |
* - Fixed issue with closer button when div { position: relative } is set
|
|
|
51 |
* - Fixed leaking issue with multiple containers. Special thanks to Matthew Hanlon!
|
|
|
52 |
*
|
|
|
53 |
* Changes in 1.2.0
|
|
|
54 |
* - Added message pooling to limit the number of messages appearing at a given time.
|
|
|
55 |
* - Closing a notification is now bound to the notification object and triggered by the close button.
|
|
|
56 |
*
|
|
|
57 |
* Changes in 1.1.2
|
|
|
58 |
* - Added iPhone styled example
|
|
|
59 |
* - Fixed possible IE7 bug when determining if the ie6 class shoudl be applied.
|
|
|
60 |
* - Added template for the close button, so that it's content could be customized.
|
|
|
61 |
*
|
|
|
62 |
* Changes in 1.1.1
|
|
|
63 |
* - Fixed CSS styling bug for ie6 caused by a mispelling
|
|
|
64 |
* - Changes height restriction on default notifications to min-height
|
|
|
65 |
* - Added skinned examples using a variety of images
|
|
|
66 |
* - Added the ability to customize the content of the [close all] box
|
|
|
67 |
* - Added jTweet, an example of using jGrowl + Twitter
|
|
|
68 |
*
|
|
|
69 |
* Changes in 1.1.0
|
|
|
70 |
* - Multiple container and instances.
|
|
|
71 |
* - Standard $.jGrowl() now wraps $.fn.jGrowl() by first establishing a generic jGrowl container.
|
|
|
72 |
* - Instance methods of a jGrowl container can be called by $.fn.jGrowl(methodName)
|
|
|
73 |
* - Added glue preferenced, which allows notifications to be inserted before or after nodes in the container
|
|
|
74 |
* - Added new log callback which is called before anything is done for the notification
|
|
|
75 |
* - Corner's attribute are now applied on an individual notification basis.
|
|
|
76 |
*
|
|
|
77 |
* Changes in 1.0.4
|
|
|
78 |
* - Various CSS fixes so that jGrowl renders correctly in IE6.
|
|
|
79 |
*
|
|
|
80 |
* Changes in 1.0.3
|
|
|
81 |
* - Fixed bug with options persisting across notifications
|
|
|
82 |
* - Fixed theme application bug
|
|
|
83 |
* - Simplified some selectors and manipulations.
|
|
|
84 |
* - Added beforeOpen and beforeClose callbacks
|
|
|
85 |
* - Reorganized some lines of code to be more readable
|
|
|
86 |
* - Removed unnecessary this.defaults context
|
|
|
87 |
* - If corners plugin is present, it's now customizable.
|
|
|
88 |
* - Customizable open animation.
|
|
|
89 |
* - Customizable close animation.
|
|
|
90 |
* - Customizable animation easing.
|
|
|
91 |
* - Added customizable positioning (top-left, top-right, bottom-left, bottom-right, center)
|
|
|
92 |
*
|
|
|
93 |
* Changes in 1.0.2
|
|
|
94 |
* - All CSS styling is now external.
|
|
|
95 |
* - Added a theme parameter which specifies a secondary class for styling, such
|
|
|
96 |
* that notifications can be customized in appearance on a per message basis.
|
|
|
97 |
* - Notification life span is now customizable on a per message basis.
|
|
|
98 |
* - Added the ability to disable the global closer, enabled by default.
|
|
|
99 |
* - Added callbacks for when a notification is opened or closed.
|
|
|
100 |
* - Added callback for the global closer.
|
|
|
101 |
* - Customizable animation speed.
|
|
|
102 |
* - jGrowl now set itself up and tears itself down.
|
|
|
103 |
*
|
|
|
104 |
* Changes in 1.0.1:
|
|
|
105 |
* - Removed dependency on metadata plugin in favor of .data()
|
|
|
106 |
* - Namespaced all events
|
|
|
107 |
*/
|
|
|
108 |
(function($) {
|
|
|
109 |
|
|
|
110 |
/** jGrowl Wrapper - Establish a base jGrowl Container for compatibility with older releases. **/
|
|
|
111 |
$.jGrowl = function( m , o ) {
|
|
|
112 |
// To maintain compatibility with older version that only supported one instance we'll create the base container.
|
|
|
113 |
if ( $('#jGrowl').length == 0 )
|
|
|
114 |
$('<div id="jGrowl"></div>').addClass( (o && o.position) ? o.position : $.jGrowl.defaults.position ).appendTo('body');
|
|
|
115 |
|
|
|
116 |
// Create a notification on the container.
|
|
|
117 |
$('#jGrowl').jGrowl(m,o);
|
|
|
118 |
};
|
|
|
119 |
|
|
|
120 |
|
|
|
121 |
/** Raise jGrowl Notification on a jGrowl Container **/
|
|
|
122 |
$.fn.jGrowl = function( m , o ) {
|
|
|
123 |
if ( $.isFunction(this.each) ) {
|
|
|
124 |
var args = arguments;
|
|
|
125 |
|
|
|
126 |
return this.each(function() {
|
|
|
127 |
var self = this;
|
|
|
128 |
|
|
|
129 |
/** Create a jGrowl Instance on the Container if it does not exist **/
|
|
|
130 |
if ( $(this).data('jGrowl.instance') == undefined ) {
|
|
|
131 |
$(this).data('jGrowl.instance', $.extend( new $.fn.jGrowl(), { notifications: [], element: null, interval: null } ));
|
|
|
132 |
$(this).data('jGrowl.instance').startup( this );
|
|
|
133 |
}
|
|
|
134 |
|
|
|
135 |
/** Optionally call jGrowl instance methods, or just raise a normal notification **/
|
|
|
136 |
if ( $.isFunction($(this).data('jGrowl.instance')[m]) ) {
|
|
|
137 |
$(this).data('jGrowl.instance')[m].apply( $(this).data('jGrowl.instance') , $.makeArray(args).slice(1) );
|
|
|
138 |
} else {
|
|
|
139 |
$(this).data('jGrowl.instance').create( m , o );
|
|
|
140 |
}
|
|
|
141 |
});
|
|
|
142 |
};
|
|
|
143 |
};
|
|
|
144 |
|
|
|
145 |
$.extend( $.fn.jGrowl.prototype , {
|
|
|
146 |
|
|
|
147 |
/** Default JGrowl Settings **/
|
|
|
148 |
defaults: {
|
|
|
149 |
pool: 0,
|
|
|
150 |
header: '',
|
|
|
151 |
group: '',
|
|
|
152 |
sticky: false,
|
|
|
153 |
position: 'top-right',
|
|
|
154 |
glue: 'after',
|
|
|
155 |
theme: 'default',
|
|
|
156 |
themeState: 'highlight',
|
|
|
157 |
corners: '10px',
|
|
|
158 |
check: 250,
|
|
|
159 |
life: 3000,
|
|
|
160 |
closeDuration: 'normal',
|
|
|
161 |
openDuration: 'normal',
|
|
|
162 |
easing: 'swing',
|
|
|
163 |
closer: true,
|
|
|
164 |
closeTemplate: '×',
|
|
|
165 |
closerTemplate: '<div>[ close all ]</div>',
|
|
|
166 |
log: function(e,m,o) {},
|
|
|
167 |
beforeOpen: function(e,m,o) {},
|
|
|
168 |
afterOpen: function(e,m,o) {},
|
|
|
169 |
open: function(e,m,o) {},
|
|
|
170 |
beforeClose: function(e,m,o) {},
|
|
|
171 |
close: function(e,m,o) {},
|
|
|
172 |
animateOpen: {
|
|
|
173 |
opacity: 'show'
|
|
|
174 |
},
|
|
|
175 |
animateClose: {
|
|
|
176 |
opacity: 'hide'
|
|
|
177 |
}
|
|
|
178 |
},
|
|
|
179 |
|
|
|
180 |
notifications: [],
|
|
|
181 |
|
|
|
182 |
/** jGrowl Container Node **/
|
|
|
183 |
element: null,
|
|
|
184 |
|
|
|
185 |
/** Interval Function **/
|
|
|
186 |
interval: null,
|
|
|
187 |
|
|
|
188 |
/** Create a Notification **/
|
|
|
189 |
create: function( message , o ) {
|
|
|
190 |
var o = $.extend({}, this.defaults, o);
|
|
|
191 |
|
|
|
192 |
/* To keep backward compatibility with 1.24 and earlier, honor 'speed' if the user has set it */
|
|
|
193 |
if (typeof o.speed !== 'undefined') {
|
|
|
194 |
o.openDuration = o.speed;
|
|
|
195 |
o.closeDuration = o.speed;
|
|
|
196 |
}
|
|
|
197 |
|
|
|
198 |
this.notifications.push({ message: message , options: o });
|
|
|
199 |
|
|
|
200 |
o.log.apply( this.element , [this.element,message,o] );
|
|
|
201 |
},
|
|
|
202 |
|
|
|
203 |
render: function( notification ) {
|
|
|
204 |
var self = this;
|
|
|
205 |
var message = notification.message;
|
|
|
206 |
var o = notification.options;
|
|
|
207 |
|
|
|
208 |
// Support for jQuery theme-states, if this is not used it displays a widget header
|
|
|
209 |
o.themeState = (o.themeState == '') ? '' : 'ui-state-' + o.themeState;
|
|
|
210 |
|
|
|
211 |
var notification = $(
|
|
|
212 |
'<div class="jGrowl-notification ' + o.themeState + ' ui-corner-all' +
|
|
|
213 |
((o.group != undefined && o.group != '') ? ' ' + o.group : '') + '">' +
|
|
|
214 |
'<div class="jGrowl-close">' + o.closeTemplate + '</div>' +
|
|
|
215 |
'<div class="jGrowl-header">' + o.header + '</div>' +
|
|
|
216 |
'<div class="jGrowl-message">' + message + '</div></div>'
|
|
|
217 |
).data("jGrowl", o).addClass(o.theme).children('div.jGrowl-close').on("click.jGrowl", function() {
|
|
|
218 |
$(this).parent().trigger('jGrowl.close');
|
|
|
219 |
}).parent();
|
|
|
220 |
|
|
|
221 |
|
|
|
222 |
/** Notification Actions **/
|
|
|
223 |
$(notification).on("mouseover.jGrowl", function() {
|
|
|
224 |
$('div.jGrowl-notification', self.element).data("jGrowl.pause", true);
|
|
|
225 |
}).on("mouseout.jGrowl", function() {
|
|
|
226 |
$('div.jGrowl-notification', self.element).data("jGrowl.pause", false);
|
|
|
227 |
}).on('jGrowl.beforeOpen', function() {
|
|
|
228 |
if ( o.beforeOpen.apply( notification , [notification,message,o,self.element] ) != false ) {
|
|
|
229 |
$(this).trigger('jGrowl.open');
|
|
|
230 |
}
|
|
|
231 |
}).on('jGrowl.open', function() {
|
|
|
232 |
if ( o.open.apply( notification , [notification,message,o,self.element] ) != false ) {
|
|
|
233 |
if ( o.glue == 'after' ) {
|
|
|
234 |
$('div.jGrowl-notification:last', self.element).after(notification);
|
|
|
235 |
} else {
|
|
|
236 |
$('div.jGrowl-notification:first', self.element).before(notification);
|
|
|
237 |
}
|
|
|
238 |
|
|
|
239 |
$(this).animate(o.animateOpen, o.openDuration, o.easing, function() {
|
|
|
240 |
// Fixes some anti-aliasing issues with IE filters.
|
|
|
241 |
if ((navigator.userAgent.match(/MSIE ([1-9])/) !== null) && (parseInt($(this).css('opacity'), 10) === 1 || parseInt($(this).css('opacity'), 10) === 0))
|
|
|
242 |
this.style.removeAttribute('filter');
|
|
|
243 |
|
|
|
244 |
if ( $(this).data("jGrowl") != null ) // Happens when a notification is closing before it's open.
|
|
|
245 |
$(this).data("jGrowl").created = new Date();
|
|
|
246 |
|
|
|
247 |
$(this).trigger('jGrowl.afterOpen');
|
|
|
248 |
});
|
|
|
249 |
}
|
|
|
250 |
}).on('jGrowl.afterOpen', function() {
|
|
|
251 |
o.afterOpen.apply( notification , [notification,message,o,self.element] );
|
|
|
252 |
}).on('jGrowl.beforeClose', function() {
|
|
|
253 |
if ( o.beforeClose.apply( notification , [notification,message,o,self.element] ) != false )
|
|
|
254 |
$(this).trigger('jGrowl.close');
|
|
|
255 |
}).on('jGrowl.close', function() {
|
|
|
256 |
// Pause the notification, lest during the course of animation another close event gets called.
|
|
|
257 |
$(this).data('jGrowl.pause', true);
|
|
|
258 |
$(this).animate(o.animateClose, o.closeDuration, o.easing, function() {
|
|
|
259 |
if ( $.isFunction(o.close) ) {
|
|
|
260 |
if ( o.close.apply( notification , [notification,message,o,self.element] ) !== false )
|
|
|
261 |
$(this).remove();
|
|
|
262 |
} else {
|
|
|
263 |
$(this).remove();
|
|
|
264 |
}
|
|
|
265 |
});
|
|
|
266 |
}).trigger('jGrowl.beforeOpen');
|
|
|
267 |
|
|
|
268 |
/** Optional Corners Plugin **/
|
|
|
269 |
if ( o.corners != '' && $.fn.corner != undefined ) $(notification).corner( o.corners );
|
|
|
270 |
|
|
|
271 |
/** Add a Global Closer if more than one notification exists **/
|
|
|
272 |
if ( $('div.jGrowl-notification:parent', self.element).length > 1 &&
|
|
|
273 |
$('div.jGrowl-closer', self.element).length == 0 && this.defaults.closer != false ) {
|
|
|
274 |
$(this.defaults.closerTemplate).addClass('jGrowl-closer ' + this.defaults.themeState + ' ui-corner-all').addClass(this.defaults.theme)
|
|
|
275 |
.appendTo(self.element).animate(this.defaults.animateOpen, this.defaults.speed, this.defaults.easing)
|
|
|
276 |
.on("click.jGrowl", function() {
|
|
|
277 |
$(this).siblings().trigger("jGrowl.beforeClose");
|
|
|
278 |
|
|
|
279 |
if ( $.isFunction( self.defaults.closer ) ) {
|
|
|
280 |
self.defaults.closer.apply( $(this).parent()[0] , [$(this).parent()[0]] );
|
|
|
281 |
}
|
|
|
282 |
});
|
|
|
283 |
};
|
|
|
284 |
},
|
|
|
285 |
|
|
|
286 |
/** Update the jGrowl Container, removing old jGrowl notifications **/
|
|
|
287 |
update: function() {
|
|
|
288 |
$(this.element).find('div.jGrowl-notification:parent').each( function() {
|
|
|
289 |
if ( $(this).data("jGrowl") != undefined && $(this).data("jGrowl").created != undefined &&
|
|
|
290 |
($(this).data("jGrowl").created.getTime() + parseInt($(this).data("jGrowl").life)) < (new Date()).getTime() &&
|
|
|
291 |
$(this).data("jGrowl").sticky != true &&
|
|
|
292 |
($(this).data("jGrowl.pause") == undefined || $(this).data("jGrowl.pause") != true) ) {
|
|
|
293 |
|
|
|
294 |
// Pause the notification, lest during the course of animation another close event gets called.
|
|
|
295 |
$(this).trigger('jGrowl.beforeClose');
|
|
|
296 |
}
|
|
|
297 |
});
|
|
|
298 |
|
|
|
299 |
if ( this.notifications.length > 0 &&
|
|
|
300 |
(this.defaults.pool == 0 || $(this.element).find('div.jGrowl-notification:parent').length < this.defaults.pool) )
|
|
|
301 |
this.render( this.notifications.shift() );
|
|
|
302 |
|
|
|
303 |
if ( $(this.element).find('div.jGrowl-notification:parent').length < 2 ) {
|
|
|
304 |
$(this.element).find('div.jGrowl-closer').animate(this.defaults.animateClose, this.defaults.speed, this.defaults.easing, function() {
|
|
|
305 |
$(this).remove();
|
|
|
306 |
});
|
|
|
307 |
}
|
|
|
308 |
},
|
|
|
309 |
|
|
|
310 |
/** Setup the jGrowl Notification Container **/
|
|
|
311 |
startup: function(e) {
|
|
|
312 |
this.element = $(e).addClass('jGrowl').append('<div class="jGrowl-notification"></div>');
|
|
|
313 |
this.interval = setInterval( function() {
|
|
|
314 |
$(e).data('jGrowl.instance').update();
|
|
|
315 |
}, parseInt(this.defaults.check));
|
|
|
316 |
|
|
|
317 |
if ((navigator.userAgent.match(/MSIE ([2-6]\.)/) !== null) && !window["XMLHttpRequest"]) {
|
|
|
318 |
$(this.element).addClass('ie6');
|
|
|
319 |
}
|
|
|
320 |
},
|
|
|
321 |
|
|
|
322 |
/** Shutdown jGrowl, removing it and clearing the interval **/
|
|
|
323 |
shutdown: function() {
|
|
|
324 |
$(this.element).removeClass('jGrowl').find('div.jGrowl-notification').remove();
|
|
|
325 |
clearInterval( this.interval );
|
|
|
326 |
},
|
|
|
327 |
|
|
|
328 |
close: function() {
|
|
|
329 |
$(this.element).find('div.jGrowl-notification').each(function(){
|
|
|
330 |
$(this).trigger('jGrowl.beforeClose');
|
|
|
331 |
});
|
|
|
332 |
}
|
|
|
333 |
});
|
|
|
334 |
|
|
|
335 |
/** Reference the Defaults Object for compatibility with older versions of jGrowl **/
|
|
|
336 |
$.jGrowl.defaults = $.fn.jGrowl.prototype.defaults;
|
|
|
337 |
|
|
|
338 |
})(jQuery);
|