3
* http://github.com/jlukic/semantic-ui/
6
* Copyright 2014 Contributors
7
* Released under the MIT license
8
* http://opensource.org/licenses/MIT
12
;(function ($, window, document, undefined) {
14
$.fn.nag = function(parameters) {
16
$allModules = $(this),
17
moduleSelector = $allModules.selector || '',
19
time = new Date().getTime(),
23
methodInvoked = (typeof query == 'string'),
24
queryArguments = [].slice.call(arguments, 1),
30
settings = $.extend(true, {}, $.fn.nag.settings, parameters),
32
className = settings.className,
33
selector = settings.selector,
34
error = settings.error,
35
namespace = settings.namespace,
37
eventNamespace = '.' + namespace,
38
moduleNamespace = namespace + '-module',
42
$close = $module.find(selector.close),
43
$context = $(settings.context),
47
instance = $module.data(moduleNamespace),
62
requestAnimationFrame = window.requestAnimationFrame
63
|| window.mozRequestAnimationFrame
64
|| window.webkitRequestAnimationFrame
65
|| window.msRequestAnimationFrame
66
|| function(callback) { setTimeout(callback, 0); }
70
initialize: function() {
71
module.verbose('Initializing element');
72
// calculate module offset once
73
moduleOffset = $module.offset();
74
moduleHeight = $module.outerHeight();
75
contextWidth = $context.outerWidth();
76
contextHeight = $context.outerHeight();
77
contextOffset = $context.offset();
80
.data(moduleNamespace, module)
83
.on('click' + eventNamespace, module.dismiss)
85
// lets avoid javascript if we dont need to reposition
86
if(settings.context == window && settings.position == 'fixed') {
88
.addClass(className.fixed)
92
module.verbose('Adding scroll events');
93
// retrigger on scroll for absolute
94
if(settings.position == 'absolute') {
96
.on('scroll' + eventNamespace, module.event.scroll)
97
.on('resize' + eventNamespace, module.event.scroll)
100
// fixed is always relative to window
103
.on('scroll' + eventNamespace, module.event.scroll)
104
.on('resize' + eventNamespace, module.event.scroll)
107
// fire once to position on init
108
$.proxy(module.event.scroll, this)();
111
if(settings.displayTime > 0) {
112
setTimeout(module.hide, settings.displayTime);
114
if(module.should.show()) {
115
if( !$module.is(':visible') ) {
124
destroy: function() {
125
module.verbose('Destroying instance');
127
.removeData(moduleNamespace)
130
if(settings.sticky) {
137
refresh: function() {
138
module.debug('Refreshing cached calculations');
139
moduleOffset = $module.offset();
140
moduleHeight = $module.outerHeight();
141
contextWidth = $context.outerWidth();
142
contextHeight = $context.outerHeight();
143
contextOffset = $context.offset();
147
module.debug('Showing nag', settings.animation.show);
148
if(settings.animation.show == 'fade') {
150
.fadeIn(settings.duration, settings.easing)
155
.slideDown(settings.duration, settings.easing)
161
module.debug('Showing nag', settings.animation.hide);
162
if(settings.animation.show == 'fade') {
164
.fadeIn(settings.duration, settings.easing)
169
.slideUp(settings.duration, settings.easing)
175
module.debug('Removing nag', settings.animation.hide);
177
if (settings.onHide) {
185
if(settings.position == 'fixed') {
187
windowScroll = $(window).prop('pageYOffset') || $(window).scrollTop(),
188
fixedOffset = ( $module.hasClass(className.bottom) )
189
? contextOffset.top + (contextHeight - moduleHeight) - windowScroll
190
: contextOffset.top - windowScroll
196
left : contextOffset.left,
197
width : contextWidth - settings.scrollBarWidth
209
unStick: function() {
216
dismiss: function(event) {
217
if(settings.storageMethod) {
218
module.storage.set(settings.storedKey, settings.storedValue);
221
event.stopImmediatePropagation();
222
event.preventDefault();
227
if(settings.persist) {
228
module.debug('Persistent nag is set, can show nag');
231
if(module.storage.get(settings.storedKey) != settings.storedValue) {
232
module.debug('Stored value is not set, can show nag', module.storage.get(settings.storedKey));
235
module.debug('Stored value is set, cannot show nag', module.storage.get(settings.storedKey));
239
yOffset = $context.prop('pageYOffset') || $context.scrollTop();
240
yPosition = ( $module.hasClass(className.bottom) )
241
? (contextHeight - $module.outerHeight() ) + yOffset
244
// absolute position calculated when y offset met
245
if(yPosition > moduleOffset.top) {
248
else if(settings.position == 'fixed') {
257
set: function(key, value) {
258
module.debug('Setting stored value', key, value, settings.storageMethod);
259
if(settings.storageMethod == 'local' && window.store !== undefined) {
260
window.store.set(key, value);
263
else if($.cookie !== undefined) {
264
$.cookie(key, value);
267
module.error(error.noStorage);
271
module.debug('Getting stored value', key, settings.storageMethod);
272
if(settings.storageMethod == 'local' && window.store !== undefined) {
273
return window.store.get(key);
276
else if($.cookie !== undefined) {
277
return $.cookie(key);
280
module.error(error.noStorage);
288
if(timer !== undefined) {
291
timer = setTimeout(function() {
292
if(module.should.stick() ) {
293
requestAnimationFrame(module.stick);
301
setting: function(name, value) {
302
if( $.isPlainObject(name) ) {
303
$.extend(true, settings, name);
305
else if(value !== undefined) {
306
settings[name] = value;
309
return settings[name];
312
internal: function(name, value) {
313
module.debug('Changing internal', name, value);
314
if(value !== undefined) {
315
if( $.isPlainObject(name) ) {
316
$.extend(true, module, name);
319
module[name] = value;
328
if(settings.performance) {
329
module.performance.log(arguments);
332
module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
333
module.debug.apply(console, arguments);
337
verbose: function() {
338
if(settings.verbose && settings.debug) {
339
if(settings.performance) {
340
module.performance.log(arguments);
343
module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
344
module.verbose.apply(console, arguments);
349
module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
350
module.error.apply(console, arguments);
353
log: function(message) {
359
if(settings.performance) {
360
currentTime = new Date().getTime();
361
previousTime = time || currentTime;
362
executionTime = currentTime - previousTime;
367
'Arguments' : [].slice.call(message, 1) || '',
368
'Execution Time' : executionTime
371
clearTimeout(module.performance.timer);
372
module.performance.timer = setTimeout(module.performance.display, 100);
374
display: function() {
376
title = settings.name + ':',
380
clearTimeout(module.performance.timer);
381
$.each(performance, function(index, data) {
382
totalTime += data['Execution Time'];
384
title += ' ' + totalTime + 'ms';
386
title += ' \'' + moduleSelector + '\'';
388
if($allModules.size() > 1) {
389
title += ' ' + '(' + $allModules.size() + ')';
391
if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
392
console.groupCollapsed(title);
394
console.table(performance);
397
$.each(performance, function(index, data) {
398
console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
406
invoke: function(query, passedArguments, context) {
413
passedArguments = passedArguments || queryArguments;
414
context = element || context;
415
if(typeof query == 'string' && object !== undefined) {
416
query = query.split(/[\. ]/);
417
maxDepth = query.length - 1;
418
$.each(query, function(depth, value) {
419
var camelCaseValue = (depth != maxDepth)
420
? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
423
if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
424
object = object[camelCaseValue];
426
else if( object[camelCaseValue] !== undefined ) {
427
found = object[camelCaseValue];
430
else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
431
object = object[value];
433
else if( object[value] !== undefined ) {
434
found = object[value];
442
if ( $.isFunction( found ) ) {
443
response = found.apply(context, passedArguments);
445
else if(found !== undefined) {
448
if($.isArray(returnedValue)) {
449
returnedValue.push(response);
451
else if(returnedValue !== undefined) {
452
returnedValue = [returnedValue, response];
454
else if(response !== undefined) {
455
returnedValue = response;
461
if(instance === undefined) {
464
module.invoke(query);
467
if(instance !== undefined) {
475
return (returnedValue !== undefined)
481
$.fn.nag.settings = {
491
// allows cookie to be overriden
494
// set to zero to manually dismiss, otherwise hides on its own
502
// method of stickyness
506
// type of storage to use
507
storageMethod : 'cookie',
509
// value to store in dismissed localstorage/cookie
511
storedValue : 'dismiss',
513
// need to calculate stickyness on scroll
516
// how often to check scroll event
519
// context for scroll event
523
noStorage : 'Neither $.cookie or store is defined. A storage solution is required for storing state',
524
method : 'The method you called is not defined.'
537
easing : 'easeOutQuad',
539
onHide: function() {}
543
})( jQuery, window , document );