~johnsca/charms/trusty/cloudfoundry/reconciler-ui

« back to all changes in this revision

Viewing changes to reconciler/ui/static/semantic/less/modules/nag.js

  • Committer: Whit Morriss
  • Date: 2014-10-13 06:50:17 UTC
  • Revision ID: whit.morriss@canonical.com-20141013065017-0feo2ku3yllymkol
reorg reconciler

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * # Semantic - Nag
 
3
 * http://github.com/jlukic/semantic-ui/
 
4
 *
 
5
 *
 
6
 * Copyright 2014 Contributors
 
7
 * Released under the MIT license
 
8
 * http://opensource.org/licenses/MIT
 
9
 *
 
10
 */
 
11
 
 
12
;(function ($, window, document, undefined) {
 
13
 
 
14
$.fn.nag = function(parameters) {
 
15
  var
 
16
    $allModules     = $(this),
 
17
    moduleSelector  = $allModules.selector || '',
 
18
 
 
19
    time            = new Date().getTime(),
 
20
    performance     = [],
 
21
 
 
22
    query           = arguments[0],
 
23
    methodInvoked   = (typeof query == 'string'),
 
24
    queryArguments  = [].slice.call(arguments, 1),
 
25
    returnedValue
 
26
  ;
 
27
  $(this)
 
28
    .each(function() {
 
29
      var
 
30
        settings        = $.extend(true, {}, $.fn.nag.settings, parameters),
 
31
 
 
32
        className       = settings.className,
 
33
        selector        = settings.selector,
 
34
        error           = settings.error,
 
35
        namespace       = settings.namespace,
 
36
 
 
37
        eventNamespace  = '.' + namespace,
 
38
        moduleNamespace = namespace + '-module',
 
39
 
 
40
        $module         = $(this),
 
41
 
 
42
        $close          = $module.find(selector.close),
 
43
        $context        = $(settings.context),
 
44
 
 
45
 
 
46
        element         = this,
 
47
        instance        = $module.data(moduleNamespace),
 
48
 
 
49
        moduleOffset,
 
50
        moduleHeight,
 
51
 
 
52
        contextWidth,
 
53
        contextHeight,
 
54
        contextOffset,
 
55
 
 
56
        yOffset,
 
57
        yPosition,
 
58
 
 
59
        timer,
 
60
        module,
 
61
 
 
62
        requestAnimationFrame = window.requestAnimationFrame
 
63
          || window.mozRequestAnimationFrame
 
64
          || window.webkitRequestAnimationFrame
 
65
          || window.msRequestAnimationFrame
 
66
          || function(callback) { setTimeout(callback, 0); }
 
67
      ;
 
68
      module = {
 
69
 
 
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();
 
78
 
 
79
          $module
 
80
            .data(moduleNamespace, module)
 
81
          ;
 
82
          $close
 
83
            .on('click' + eventNamespace, module.dismiss)
 
84
          ;
 
85
          // lets avoid javascript if we dont need to reposition
 
86
          if(settings.context == window && settings.position == 'fixed') {
 
87
            $module
 
88
              .addClass(className.fixed)
 
89
            ;
 
90
          }
 
91
          if(settings.sticky) {
 
92
            module.verbose('Adding scroll events');
 
93
            // retrigger on scroll for absolute
 
94
            if(settings.position == 'absolute') {
 
95
              $context
 
96
                .on('scroll' + eventNamespace, module.event.scroll)
 
97
                .on('resize' + eventNamespace, module.event.scroll)
 
98
              ;
 
99
            }
 
100
            // fixed is always relative to window
 
101
            else {
 
102
              $(window)
 
103
                .on('scroll' + eventNamespace, module.event.scroll)
 
104
                .on('resize' + eventNamespace, module.event.scroll)
 
105
              ;
 
106
            }
 
107
            // fire once to position on init
 
108
            $.proxy(module.event.scroll, this)();
 
109
          }
 
110
 
 
111
          if(settings.displayTime > 0) {
 
112
            setTimeout(module.hide, settings.displayTime);
 
113
          }
 
114
          if(module.should.show()) {
 
115
            if( !$module.is(':visible') ) {
 
116
              module.show();
 
117
            }
 
118
          }
 
119
          else {
 
120
            module.hide();
 
121
          }
 
122
        },
 
123
 
 
124
        destroy: function() {
 
125
          module.verbose('Destroying instance');
 
126
          $module
 
127
            .removeData(moduleNamespace)
 
128
            .off(eventNamespace)
 
129
          ;
 
130
          if(settings.sticky) {
 
131
            $context
 
132
              .off(eventNamespace)
 
133
            ;
 
134
          }
 
135
        },
 
136
 
 
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();
 
144
        },
 
145
 
 
146
        show: function() {
 
147
          module.debug('Showing nag', settings.animation.show);
 
148
          if(settings.animation.show == 'fade') {
 
149
            $module
 
150
              .fadeIn(settings.duration, settings.easing)
 
151
            ;
 
152
          }
 
153
          else {
 
154
            $module
 
155
              .slideDown(settings.duration, settings.easing)
 
156
            ;
 
157
          }
 
158
        },
 
159
 
 
160
        hide: function() {
 
161
          module.debug('Showing nag', settings.animation.hide);
 
162
          if(settings.animation.show == 'fade') {
 
163
            $module
 
164
              .fadeIn(settings.duration, settings.easing)
 
165
            ;
 
166
          }
 
167
          else {
 
168
            $module
 
169
              .slideUp(settings.duration, settings.easing)
 
170
            ;
 
171
          }
 
172
        },
 
173
 
 
174
        onHide: function() {
 
175
          module.debug('Removing nag', settings.animation.hide);
 
176
          $module.remove();
 
177
          if (settings.onHide) {
 
178
            settings.onHide();
 
179
          }
 
180
        },
 
181
 
 
182
        stick: function() {
 
183
          module.refresh();
 
184
 
 
185
          if(settings.position == 'fixed') {
 
186
            var
 
187
              windowScroll = $(window).prop('pageYOffset') || $(window).scrollTop(),
 
188
              fixedOffset = ( $module.hasClass(className.bottom) )
 
189
                ? contextOffset.top + (contextHeight - moduleHeight) - windowScroll
 
190
                : contextOffset.top - windowScroll
 
191
            ;
 
192
            $module
 
193
              .css({
 
194
                position : 'fixed',
 
195
                top      : fixedOffset,
 
196
                left     : contextOffset.left,
 
197
                width    : contextWidth - settings.scrollBarWidth
 
198
              })
 
199
            ;
 
200
          }
 
201
          else {
 
202
            $module
 
203
              .css({
 
204
                top : yPosition
 
205
              })
 
206
            ;
 
207
          }
 
208
        },
 
209
        unStick: function() {
 
210
          $module
 
211
            .css({
 
212
              top : ''
 
213
            })
 
214
          ;
 
215
        },
 
216
        dismiss: function(event) {
 
217
          if(settings.storageMethod) {
 
218
            module.storage.set(settings.storedKey, settings.storedValue);
 
219
          }
 
220
          module.hide();
 
221
          event.stopImmediatePropagation();
 
222
          event.preventDefault();
 
223
        },
 
224
 
 
225
        should: {
 
226
          show: function() {
 
227
            if(settings.persist) {
 
228
              module.debug('Persistent nag is set, can show nag');
 
229
              return true;
 
230
            }
 
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));
 
233
              return true;
 
234
            }
 
235
            module.debug('Stored value is set, cannot show nag', module.storage.get(settings.storedKey));
 
236
            return false;
 
237
          },
 
238
          stick: function() {
 
239
            yOffset   = $context.prop('pageYOffset') || $context.scrollTop();
 
240
            yPosition = ( $module.hasClass(className.bottom) )
 
241
              ? (contextHeight - $module.outerHeight() ) + yOffset
 
242
              : yOffset
 
243
            ;
 
244
            // absolute position calculated when y offset met
 
245
            if(yPosition > moduleOffset.top) {
 
246
              return true;
 
247
            }
 
248
            else if(settings.position == 'fixed') {
 
249
              return true;
 
250
            }
 
251
            return false;
 
252
          }
 
253
        },
 
254
 
 
255
        storage: {
 
256
 
 
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);
 
261
            }
 
262
            // store by cookie
 
263
            else if($.cookie !== undefined) {
 
264
              $.cookie(key, value);
 
265
            }
 
266
            else {
 
267
              module.error(error.noStorage);
 
268
            }
 
269
          },
 
270
          get: function(key) {
 
271
            module.debug('Getting stored value', key, settings.storageMethod);
 
272
            if(settings.storageMethod == 'local' && window.store !== undefined) {
 
273
              return window.store.get(key);
 
274
            }
 
275
            // get by cookie
 
276
            else if($.cookie !== undefined) {
 
277
              return $.cookie(key);
 
278
            }
 
279
            else {
 
280
              module.error(error.noStorage);
 
281
            }
 
282
          }
 
283
 
 
284
        },
 
285
 
 
286
        event: {
 
287
          scroll: function() {
 
288
            if(timer !== undefined) {
 
289
              clearTimeout(timer);
 
290
            }
 
291
            timer = setTimeout(function() {
 
292
              if(module.should.stick() ) {
 
293
                requestAnimationFrame(module.stick);
 
294
              }
 
295
              else {
 
296
                module.unStick();
 
297
              }
 
298
            }, settings.lag);
 
299
          }
 
300
        },
 
301
        setting: function(name, value) {
 
302
          if( $.isPlainObject(name) ) {
 
303
            $.extend(true, settings, name);
 
304
          }
 
305
          else if(value !== undefined) {
 
306
            settings[name] = value;
 
307
          }
 
308
          else {
 
309
            return settings[name];
 
310
          }
 
311
        },
 
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);
 
317
            }
 
318
            else {
 
319
              module[name] = value;
 
320
            }
 
321
          }
 
322
          else {
 
323
            return module[name];
 
324
          }
 
325
        },
 
326
        debug: function() {
 
327
          if(settings.debug) {
 
328
            if(settings.performance) {
 
329
              module.performance.log(arguments);
 
330
            }
 
331
            else {
 
332
              module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
 
333
              module.debug.apply(console, arguments);
 
334
            }
 
335
          }
 
336
        },
 
337
        verbose: function() {
 
338
          if(settings.verbose && settings.debug) {
 
339
            if(settings.performance) {
 
340
              module.performance.log(arguments);
 
341
            }
 
342
            else {
 
343
              module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
 
344
              module.verbose.apply(console, arguments);
 
345
            }
 
346
          }
 
347
        },
 
348
        error: function() {
 
349
          module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
 
350
          module.error.apply(console, arguments);
 
351
        },
 
352
        performance: {
 
353
          log: function(message) {
 
354
            var
 
355
              currentTime,
 
356
              executionTime,
 
357
              previousTime
 
358
            ;
 
359
            if(settings.performance) {
 
360
              currentTime   = new Date().getTime();
 
361
              previousTime  = time || currentTime;
 
362
              executionTime = currentTime - previousTime;
 
363
              time          = currentTime;
 
364
              performance.push({
 
365
                'Element'        : element,
 
366
                'Name'           : message[0],
 
367
                'Arguments'      : [].slice.call(message, 1) || '',
 
368
                'Execution Time' : executionTime
 
369
              });
 
370
            }
 
371
            clearTimeout(module.performance.timer);
 
372
            module.performance.timer = setTimeout(module.performance.display, 100);
 
373
          },
 
374
          display: function() {
 
375
            var
 
376
              title = settings.name + ':',
 
377
              totalTime = 0
 
378
            ;
 
379
            time = false;
 
380
            clearTimeout(module.performance.timer);
 
381
            $.each(performance, function(index, data) {
 
382
              totalTime += data['Execution Time'];
 
383
            });
 
384
            title += ' ' + totalTime + 'ms';
 
385
            if(moduleSelector) {
 
386
              title += ' \'' + moduleSelector + '\'';
 
387
            }
 
388
            if($allModules.size() > 1) {
 
389
              title += ' ' + '(' + $allModules.size() + ')';
 
390
            }
 
391
            if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
 
392
              console.groupCollapsed(title);
 
393
              if(console.table) {
 
394
                console.table(performance);
 
395
              }
 
396
              else {
 
397
                $.each(performance, function(index, data) {
 
398
                  console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
 
399
                });
 
400
              }
 
401
              console.groupEnd();
 
402
            }
 
403
            performance = [];
 
404
          }
 
405
        },
 
406
        invoke: function(query, passedArguments, context) {
 
407
          var
 
408
            object = instance,
 
409
            maxDepth,
 
410
            found,
 
411
            response
 
412
          ;
 
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)
 
421
                : query
 
422
              ;
 
423
              if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
 
424
                object = object[camelCaseValue];
 
425
              }
 
426
              else if( object[camelCaseValue] !== undefined ) {
 
427
                found = object[camelCaseValue];
 
428
                return false;
 
429
              }
 
430
              else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
 
431
                object = object[value];
 
432
              }
 
433
              else if( object[value] !== undefined ) {
 
434
                found = object[value];
 
435
                return false;
 
436
              }
 
437
              else {
 
438
                return false;
 
439
              }
 
440
            });
 
441
          }
 
442
          if ( $.isFunction( found ) ) {
 
443
            response = found.apply(context, passedArguments);
 
444
          }
 
445
          else if(found !== undefined) {
 
446
            response = found;
 
447
          }
 
448
          if($.isArray(returnedValue)) {
 
449
            returnedValue.push(response);
 
450
          }
 
451
          else if(returnedValue !== undefined) {
 
452
            returnedValue = [returnedValue, response];
 
453
          }
 
454
          else if(response !== undefined) {
 
455
            returnedValue = response;
 
456
          }
 
457
          return found;
 
458
        }
 
459
      };
 
460
      if(methodInvoked) {
 
461
        if(instance === undefined) {
 
462
          module.initialize();
 
463
        }
 
464
        module.invoke(query);
 
465
      }
 
466
      else {
 
467
        if(instance !== undefined) {
 
468
          module.destroy();
 
469
        }
 
470
        module.initialize();
 
471
      }
 
472
 
 
473
    })
 
474
  ;
 
475
  return (returnedValue !== undefined)
 
476
    ? returnedValue
 
477
    : this
 
478
  ;
 
479
};
 
480
 
 
481
$.fn.nag.settings = {
 
482
 
 
483
  name        : 'Nag',
 
484
 
 
485
  debug       : false,
 
486
  verbose     : true,
 
487
  performance : true,
 
488
 
 
489
  namespace   : 'Nag',
 
490
 
 
491
  // allows cookie to be overriden
 
492
  persist     : false,
 
493
 
 
494
  // set to zero to manually dismiss, otherwise hides on its own
 
495
  displayTime : 0,
 
496
 
 
497
  animation   : {
 
498
    show: 'slide',
 
499
    hide: 'slide'
 
500
  },
 
501
 
 
502
  // method of stickyness
 
503
  position       : 'fixed',
 
504
  scrollBarWidth : 18,
 
505
 
 
506
  // type of storage to use
 
507
  storageMethod  : 'cookie',
 
508
 
 
509
  // value to store in dismissed localstorage/cookie
 
510
  storedKey      : 'nag',
 
511
  storedValue    : 'dismiss',
 
512
 
 
513
  // need to calculate stickyness on scroll
 
514
  sticky         : false,
 
515
 
 
516
  // how often to check scroll event
 
517
  lag            : 0,
 
518
 
 
519
  // context for scroll event
 
520
  context        : window,
 
521
 
 
522
  error: {
 
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.'
 
525
  },
 
526
 
 
527
  className     : {
 
528
    bottom      : 'bottom',
 
529
    fixed       : 'fixed'
 
530
  },
 
531
 
 
532
  selector      : {
 
533
    close: '.icon.close'
 
534
  },
 
535
 
 
536
  speed         : 500,
 
537
  easing        : 'easeOutQuad',
 
538
 
 
539
  onHide: function() {}
 
540
 
 
541
};
 
542
 
 
543
})( jQuery, window , document );