forked from jboesch/Gritter
/
jquery.gritter.js
executable file
·388 lines (306 loc) · 10.5 KB
/
jquery.gritter.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
/*
* Gritter for jQuery
* http://www.boedesign.com/
*
* Copyright (c) 2009 Jordan Boesch
* Dual licensed under the MIT and GPL licenses.
*
* Date: December 1, 2009
* Version: 1.6
*/
(function($){
/**
* Set it up as an object under the jQuery namespace
*/
$.gritter = {};
/**
* Set up global options that the user can over-ride
*/
$.gritter.options = {
fade_in_speed: 'medium', // how fast notifications fade in
fade_out_speed: 2000, // how fast the notices fade out
time: 6000 // hang on the screen for...
}
/**
* Add a gritter notification to the screen
* @see Gritter#add();
*/
$.gritter.add = function(params){
try {
// returns a unique id
return Gritter.add(params);
} catch(e) {
var err = 'Gritter Error: ' + e;
(console && console.error) ? console.error(err, params) : alert(err);
}
}
/**
* Remove a gritter notification from the screen
* @see Gritter#removeSpecific();
*/
$.gritter.remove = function(id, params){
Gritter.removeSpecific(id, params || '');
}
/**
* Remove all notifications
* @see Gritter#stop();
*/
$.gritter.removeAll = function(params){
Gritter.stop(params || '');
}
/**
* The initialization of our Gritter object literal goodness
* @constructor
*/
var Gritter = {
// Public - options to over-ride with $.gritter.options in "add"
fade_in_speed: '',
fade_out_speed: '',
time: '',
// Private - no touchy the private parts
_custom_timer: 0,
_item_count: 0,
_is_setup: 0,
_tpl_close: '<div class="gritter-close"></div>',
_tpl_item: '<div id="gritter-item-[[number]]" class="gritter-item-wrapper [[item_class]]" style="display:none"><div class="gritter-top"></div><div class="gritter-item">[[image]]<div class="[[class_name]]"><span class="gritter-title">[[username]]</span><p>[[text]]</p></div><div style="clear:both"></div></div><div class="gritter-bottom"></div></div>',
_tpl_wrap: '<div id="gritter-notice-wrapper"></div>',
/**
* Add a gritter notification to the screen
* @param {Object} params The object that contains all the options for drawing the notification
* @return {Integer} The specific numeric id to that gritter notification
*/
add: function(params){
// We might have some issues if we don't have a title or text!
if(!params.title || !params.text){
throw 'You need to fill out the first 2 params: "title" and "text"';
}
// check the options and set them once
if(!this._is_setup){
this._runSetup();
}
// basics
var user = params.title,
text = params.text,
image = params.image || '',
sticky = params.sticky || false,
item_class = params.class_name || '',
time_alive = params.time || '';
this._verifyWrapper();
this._item_count++;
var number = this._item_count,
tmp = this._tpl_item;
// callbacks - each callback has a unique identifier so they don't get over-ridden
this['_before_open_' + number] = ($.isFunction(params.before_open)) ? params.before_open : function(){};
this['_after_open_' + number] = ($.isFunction(params.after_open)) ? params.after_open : function(){};
this['_before_close_' + number] = ($.isFunction(params.before_close)) ? params.before_close : function(){};
this['_after_close_' + number] = ($.isFunction(params.after_close)) ? params.after_close : function(){};
// reset
this._custom_timer = 0;
// a custom fade time set
if(time_alive){
this._custom_timer = time_alive;
}
var image_str = (image != '') ? '<img src="' + image + '" class="gritter-image" />' : '',
class_name = (image != '') ? 'gritter-with-image' : 'gritter-without-image';
tmp = this._str_replace(
['[[username]]', '[[text]]', '[[image]]', '[[number]]', '[[class_name]]', '[[item_class]]'],
[user, text, image_str, this._item_count, class_name, item_class], tmp
);
this['_before_open_' + number]();
$('#gritter-notice-wrapper').append(tmp);
var item = $('#gritter-item-' + this._item_count);
item.fadeIn(this.fade_in_speed, function(){
Gritter['_after_open_' + number]($(this));
});
if(!sticky){
this._setFadeTimer(item, number);
}
// bind the hovering states
$(item).bind('mouseenter mouseleave', function(event){
if(event.type == 'mouseenter'){
if(!sticky){
Gritter._restoreItemIfFading(this, number);
}
}
else {
if(!sticky){
Gritter._setFadeTimer($(this), number);
}
}
Gritter._hoverState($(this), event.type);
});
return number;
},
/**
* If we don't have any more gritter notifications, get rid of the wrapper using this check
* @param {Integer} unique_id The ID of the element that was just deleted, use it for a callback
*/
_countRemoveWrapper: function(unique_id){
// callback
this['_after_close_' + unique_id]($('#gritter-item-' + unique_id));
// check if it's empty, if it is.. remove the wrapper
if($('.gritter-item-wrapper').length == 0){
$('#gritter-notice-wrapper').remove();
}
},
/**
* Fade out an element after it's been on the screen for x amount of time
* @param {Object} e The jQuery element to get rid of
* @param {Integer} unique_id The id of the element to remove
*/
_fade: function(e, unique_id){
Gritter['_before_close_' + unique_id](e);
e.animate({
opacity:0
}, Gritter.fade_out_speed, function(){
e.animate({ height: 0 }, 300, function(){
e.remove();
Gritter._countRemoveWrapper(unique_id);
})
})
},
/**
* Perform actions based on the type of bind (mouseenter, mouseleave)
* @param {Object} e The jQuery element
* @param {String} type The type of action we're performing: mouseenter or mouseleave
*/
_hoverState: function(e, type){
// Change the border styles and add the (X) close button when you hover
if(type == 'mouseenter'){
e.addClass('hover');
if(e.find('img').length){
e.find('img').before(this._tpl_close);
}
else {
e.find('span').before(this._tpl_close);
}
e.find('.gritter-close').click(function(){
Gritter._remove(this);
});
}
// Remove the border styles and (X) close button when you mouse out
else {
e.removeClass('hover');
e.find('.gritter-close').remove();
}
},
/**
* Remove a notification, this is called from "close" button
* @param {Object} e The jQuery element
*/
_remove: function(e){
var gritter_wrap = $(e).parents('.gritter-item-wrapper');
var unique_id = gritter_wrap.attr('id').split('-')[2];
this['_before_close_' + unique_id](gritter_wrap);
gritter_wrap.fadeOut('medium', function(){
$(this).remove();
Gritter._countRemoveWrapper(unique_id);
});
},
/**
* Remove a specific notification based on an ID
* @param {Integer} unique_id The ID used to delete a specific notification
* @param {Object} params A set of options passed in to determine how to get rid of it
*/
removeSpecific: function(unique_id, params){
var e = $('#gritter-item-' + unique_id);
this['_before_close_' + unique_id](e);
if(typeof(params) === 'object'){
if(params.fade){
var speed = this.fade_out_speed;
if(params.speed){
speed = params.speed;
}
e.fadeOut(speed, function(){
e.remove();
});
}
}
else {
e.remove();
}
this._countRemoveWrapper(unique_id);
},
/**
* If the item is fading out and we hover over it, restore it!
* @param {Object} e The HTML element to remove
* @param {Integer} unique_id The ID of the element
*/
_restoreItemIfFading: function(e, unique_id){
clearTimeout(Gritter['_int_id_' + unique_id]);
$(e).stop().css({ opacity: 1 });
},
/**
* Setup the global options - only once
*/
_runSetup: function(){
for(opt in $.gritter.options){
this[opt] = $.gritter.options[opt];
}
this._is_setup = 1;
},
/**
* Set the notification to fade out after a certain amount of time
* @param {Object} item The HTML element we're dealing with
* @param {Integer} unique_id The ID of the element
*/
_setFadeTimer: function(item, unique_id){
var timer_str = (this._custom_timer) ? this._custom_timer : this.time;
Gritter['_int_id_' + unique_id] = setTimeout(function(){ Gritter._fade(item, unique_id); }, timer_str);
},
/**
* Bring everything to a halt
* @param {Object} params A list of callback functions to pass when all notifications are removed
*/
stop: function(params){
// callbacks (if passed)
var before_close = ($.isFunction(params.before_close)) ? params.before_close : function(){};
var after_close = ($.isFunction(params.after_close)) ? params.after_close : function(){};
var wrap = $('#gritter-notice-wrapper');
before_close(wrap);
wrap.fadeOut(function(){
$(this).remove();
after_close();
});
},
/**
* An extremely handy PHP function ported to JS, works well for templating
* @param {String/Array} search A list of things to search for
* @param {String/Array} replace A list of things to replace the searches with
* @return {String} sa The output
*/
_str_replace: function(search, replace, subject, count){
var i = 0, j = 0, temp = '', repl = '', sl = 0, fl = 0,
f = [].concat(search),
r = [].concat(replace),
s = subject,
ra = r instanceof Array, sa = s instanceof Array;
s = [].concat(s);
if(count){
this.window[count] = 0;
}
for(i = 0, sl = s.length; i < sl; i++){
if(s[i] === ''){
continue;
}
for (j = 0, fl = f.length; j < fl; j++){
temp = s[i] + '';
repl = ra ? (r[j] !== undefined ? r[j] : '') : r[0];
s[i] = (temp).split(f[j]).join(repl);
if(count && s[i] !== temp){
this.window[count] += (temp.length-s[i].length) / f[j].length;
}
}
}
return sa ? s : s[0];
},
/**
* A check to make sure we have something to wrap our notices with
*/
_verifyWrapper: function(){
if($('#gritter-notice-wrapper').length == 0){
$('body').append(this._tpl_wrap);
}
}
}
})(jQuery);