~johnsca/charms/trusty/cloudfoundry/better-basic-reconciler-status

« back to all changes in this revision

Viewing changes to reconciler/ui/static/semantic/uncompressed/modules/dropdown.js

  • Committer: Whit Morriss
  • Date: 2014-10-13 06:50:17 UTC
  • mto: (132.2.1 reconciler) (145.1.1 trunk)
  • mto: This revision was merged to the branch mainline in revision 156.
  • 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 - Dropdown
 
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
;(function ( $, window, document, undefined ) {
 
12
 
 
13
$.fn.dropdown = function(parameters) {
 
14
    var
 
15
    $allModules    = $(this),
 
16
    $document      = $(document),
 
17
 
 
18
    moduleSelector = $allModules.selector || '',
 
19
 
 
20
    hasTouch       = ('ontouchstart' in document.documentElement),
 
21
    time           = new Date().getTime(),
 
22
    performance    = [],
 
23
 
 
24
    query          = arguments[0],
 
25
    methodInvoked  = (typeof query == 'string'),
 
26
    queryArguments = [].slice.call(arguments, 1),
 
27
    returnedValue
 
28
  ;
 
29
 
 
30
  $allModules
 
31
    .each(function() {
 
32
      var
 
33
        settings          = ( $.isPlainObject(parameters) )
 
34
          ? $.extend(true, {}, $.fn.dropdown.settings, parameters)
 
35
          : $.extend({}, $.fn.dropdown.settings),
 
36
 
 
37
        className       = settings.className,
 
38
        metadata        = settings.metadata,
 
39
        namespace       = settings.namespace,
 
40
        selector        = settings.selector,
 
41
        error           = settings.error,
 
42
 
 
43
        eventNamespace  = '.' + namespace,
 
44
        moduleNamespace = 'module-' + namespace,
 
45
 
 
46
        $module         = $(this),
 
47
        $item           = $module.find(selector.item),
 
48
        $text           = $module.find(selector.text),
 
49
        $input          = $module.find(selector.input),
 
50
 
 
51
        $menu           = $module.children(selector.menu),
 
52
 
 
53
 
 
54
        element         = this,
 
55
        instance        = $module.data(moduleNamespace),
 
56
        module
 
57
      ;
 
58
 
 
59
      module = {
 
60
 
 
61
        initialize: function() {
 
62
          module.debug('Initializing dropdown', settings);
 
63
 
 
64
          module.save.defaults();
 
65
          module.set.selected();
 
66
 
 
67
          if(hasTouch) {
 
68
            module.bind.touchEvents();
 
69
          }
 
70
          module.bind.mouseEvents();
 
71
          module.bind.keyboardEvents();
 
72
          module.instantiate();
 
73
        },
 
74
 
 
75
        instantiate: function() {
 
76
          module.verbose('Storing instance of dropdown', module);
 
77
          instance = module;
 
78
          $module
 
79
            .data(moduleNamespace, module)
 
80
          ;
 
81
        },
 
82
 
 
83
        destroy: function() {
 
84
          module.verbose('Destroying previous dropdown for', $module);
 
85
          $item
 
86
            .off(eventNamespace)
 
87
          ;
 
88
          $module
 
89
            .off(eventNamespace)
 
90
            .removeData(moduleNamespace)
 
91
          ;
 
92
        },
 
93
 
 
94
        bind: {
 
95
          keyboardEvents: function() {
 
96
            module.debug('Binding keyboard events');
 
97
            $module
 
98
              .on('keydown' + eventNamespace, module.handleKeyboard)
 
99
            ;
 
100
            $module
 
101
              .on('focus' + eventNamespace, module.show)
 
102
            ;
 
103
          },
 
104
          touchEvents: function() {
 
105
            module.debug('Touch device detected binding touch events');
 
106
            $module
 
107
              .on('touchstart' + eventNamespace, module.event.test.toggle)
 
108
            ;
 
109
            $item
 
110
              .on('touchstart' + eventNamespace, module.event.item.mouseenter)
 
111
              .on('touchstart' + eventNamespace, module.event.item.click)
 
112
            ;
 
113
          },
 
114
          mouseEvents: function() {
 
115
            module.verbose('Mouse detected binding mouse events');
 
116
            if(settings.on == 'click') {
 
117
              $module
 
118
                .on('click' + eventNamespace, module.event.test.toggle)
 
119
              ;
 
120
            }
 
121
            else if(settings.on == 'hover') {
 
122
              $module
 
123
                .on('mouseenter' + eventNamespace, module.delay.show)
 
124
                .on('mouseleave' + eventNamespace, module.delay.hide)
 
125
              ;
 
126
            }
 
127
            else {
 
128
              $module
 
129
                .on(settings.on + eventNamespace, module.toggle)
 
130
              ;
 
131
            }
 
132
            $item
 
133
              .on('mouseenter' + eventNamespace, module.event.item.mouseenter)
 
134
              .on('mouseleave' + eventNamespace, module.event.item.mouseleave)
 
135
              .on('click'      + eventNamespace, module.event.item.click)
 
136
            ;
 
137
          },
 
138
          intent: function() {
 
139
            module.verbose('Binding hide intent event to document');
 
140
            if(hasTouch) {
 
141
              $document
 
142
                .on('touchstart' + eventNamespace, module.event.test.touch)
 
143
                .on('touchmove'  + eventNamespace, module.event.test.touch)
 
144
              ;
 
145
            }
 
146
            $document
 
147
              .on('click' + eventNamespace, module.event.test.hide)
 
148
            ;
 
149
          }
 
150
        },
 
151
 
 
152
        unbind: {
 
153
          intent: function() {
 
154
            module.verbose('Removing hide intent event from document');
 
155
            if(hasTouch) {
 
156
              $document
 
157
                .off('touchstart' + eventNamespace)
 
158
                .off('touchmove' + eventNamespace)
 
159
              ;
 
160
            }
 
161
            $document
 
162
              .off('click' + eventNamespace)
 
163
            ;
 
164
          }
 
165
        },
 
166
 
 
167
        handleKeyboard: function(event) {
 
168
          var
 
169
            $selectedItem = $item.filter('.' + className.selected),
 
170
            pressedKey    = event.which,
 
171
            keys          = {
 
172
              enter     : 13,
 
173
              escape    : 27,
 
174
              upArrow   : 38,
 
175
              downArrow : 40
 
176
            },
 
177
            selectedClass   = className.selected,
 
178
            currentIndex    = $item.index( $selectedItem ),
 
179
            hasSelectedItem = ($selectedItem.size() > 0),
 
180
            resultSize      = $item.size(),
 
181
            newIndex
 
182
          ;
 
183
          // close shortcuts
 
184
          if(pressedKey == keys.escape) {
 
185
            module.verbose('Escape key pressed, closing dropdown');
 
186
            module.hide();
 
187
          }
 
188
          // result shortcuts
 
189
          if(module.is.visible()) {
 
190
            if(pressedKey == keys.enter && hasSelectedItem) {
 
191
              module.verbose('Enter key pressed, choosing selected item');
 
192
              $.proxy(module.event.item.click, $item.filter('.' + selectedClass) )(event);
 
193
              event.preventDefault();
 
194
              return false;
 
195
            }
 
196
            else if(pressedKey == keys.upArrow) {
 
197
              module.verbose('Up key pressed, changing active item');
 
198
              newIndex = (currentIndex - 1 < 0)
 
199
                ? currentIndex
 
200
                : currentIndex - 1
 
201
              ;
 
202
              $item
 
203
                .removeClass(selectedClass)
 
204
                .eq(newIndex)
 
205
                  .addClass(selectedClass)
 
206
              ;
 
207
              event.preventDefault();
 
208
            }
 
209
            else if(pressedKey == keys.downArrow) {
 
210
              module.verbose('Down key pressed, changing active item');
 
211
              newIndex = (currentIndex + 1 >= resultSize)
 
212
                ? currentIndex
 
213
                : currentIndex + 1
 
214
              ;
 
215
              $item
 
216
                .removeClass(selectedClass)
 
217
                .eq(newIndex)
 
218
                  .addClass(selectedClass)
 
219
              ;
 
220
              event.preventDefault();
 
221
            }
 
222
          }
 
223
          else {
 
224
            if(pressedKey == keys.enter) {
 
225
              module.show();
 
226
            }
 
227
          }
 
228
        },
 
229
 
 
230
        event: {
 
231
          test: {
 
232
            toggle: function(event) {
 
233
              if( module.determine.intent(event, module.toggle) ) {
 
234
                event.preventDefault();
 
235
              }
 
236
            },
 
237
            touch: function(event) {
 
238
              module.determine.intent(event, function() {
 
239
                if(event.type == 'touchstart') {
 
240
                  module.timer = setTimeout(module.hide, settings.delay.touch);
 
241
                }
 
242
                else if(event.type == 'touchmove') {
 
243
                  clearTimeout(module.timer);
 
244
                }
 
245
              });
 
246
              event.stopPropagation();
 
247
            },
 
248
            hide: function(event) {
 
249
              module.determine.intent(event, module.hide);
 
250
            }
 
251
          },
 
252
 
 
253
          item: {
 
254
 
 
255
            mouseenter: function(event) {
 
256
              var
 
257
                $currentMenu = $(this).find(selector.submenu),
 
258
                $otherMenus  = $(this).siblings(selector.item).children(selector.menu)
 
259
              ;
 
260
              if($currentMenu.length > 0  || $otherMenus.length > 0) {
 
261
                clearTimeout(module.itemTimer);
 
262
                  module.itemTimer = setTimeout(function() {
 
263
                  if($otherMenus.length > 0) {
 
264
                    module.animate.hide(false, $otherMenus.filter(':visible'));
 
265
                  }
 
266
                  if($currentMenu.length > 0) {
 
267
                    module.verbose('Showing sub-menu', $currentMenu);
 
268
                    module.animate.show(false, $currentMenu);
 
269
                  }
 
270
                }, settings.delay.show * 2);
 
271
                event.preventDefault();
 
272
                event.stopPropagation();
 
273
              }
 
274
            },
 
275
 
 
276
            mouseleave: function(event) {
 
277
              var
 
278
                $currentMenu = $(this).find(selector.menu)
 
279
              ;
 
280
              if($currentMenu.size() > 0) {
 
281
                clearTimeout(module.itemTimer);
 
282
                module.itemTimer = setTimeout(function() {
 
283
                  module.verbose('Hiding sub-menu', $currentMenu);
 
284
                  module.animate.hide(false,  $currentMenu);
 
285
                }, settings.delay.hide);
 
286
              }
 
287
            },
 
288
 
 
289
            click: function (event) {
 
290
              var
 
291
                $choice = $(this),
 
292
                text    = ( $choice.data(metadata.text) !== undefined )
 
293
                  ? $choice.data(metadata.text)
 
294
                  : $choice.text(),
 
295
                value   = ( $choice.data(metadata.value) !== undefined)
 
296
                  ? $choice.data(metadata.value)
 
297
                  : (typeof text === 'string')
 
298
                      ? text.toLowerCase()
 
299
                      : text,
 
300
                callback = function() {
 
301
                  module.determine.selectAction(text, value);
 
302
                  $.proxy(settings.onChange, element)(value, text);
 
303
                }
 
304
              ;
 
305
              if( $choice.find(selector.menu).size() === 0 ) {
 
306
                if(event.type == 'touchstart') {
 
307
                  $choice.one('click', callback);
 
308
                }
 
309
                else {
 
310
                  callback();
 
311
                }
 
312
              }
 
313
            }
 
314
 
 
315
          },
 
316
 
 
317
          resetStyle: function() {
 
318
            $(this).removeAttr('style');
 
319
          }
 
320
 
 
321
        },
 
322
 
 
323
        determine: {
 
324
          selectAction: function(text, value) {
 
325
            module.verbose('Determining action', settings.action);
 
326
            if( $.isFunction( module.action[settings.action] ) ) {
 
327
              module.verbose('Triggering preset action', settings.action, text, value);
 
328
              module.action[ settings.action ](text, value);
 
329
            }
 
330
            else if( $.isFunction(settings.action) ) {
 
331
              module.verbose('Triggering user action', settings.action, text, value);
 
332
              settings.action(text, value);
 
333
            }
 
334
            else {
 
335
              module.error(error.action, settings.action);
 
336
            }
 
337
          },
 
338
          intent: function(event, callback) {
 
339
            module.debug('Determining whether event occurred in dropdown', event.target);
 
340
            callback = callback || function(){};
 
341
            if( $(event.target).closest($menu).size() === 0 ) {
 
342
              module.verbose('Triggering event', callback);
 
343
              callback();
 
344
              return true;
 
345
            }
 
346
            else {
 
347
              module.verbose('Event occurred in dropdown, canceling callback');
 
348
              return false;
 
349
            }
 
350
          }
 
351
        },
 
352
 
 
353
        action: {
 
354
 
 
355
          nothing: function() {},
 
356
 
 
357
          hide: function() {
 
358
            module.hide();
 
359
          },
 
360
 
 
361
          activate: function(text, value) {
 
362
            value = (value !== undefined)
 
363
              ? value
 
364
              : text
 
365
            ;
 
366
            module.set.selected(value);
 
367
            module.set.value(value);
 
368
            module.hide();
 
369
          },
 
370
 
 
371
          /* Deprecated */
 
372
          auto: function(text, value) {
 
373
            value = (value !== undefined)
 
374
              ? value
 
375
              : text
 
376
            ;
 
377
            module.set.selected(value);
 
378
            module.set.value(value);
 
379
            module.hide();
 
380
          },
 
381
 
 
382
          /* Deprecated */
 
383
          changeText: function(text, value) {
 
384
            value = (value !== undefined)
 
385
              ? value
 
386
              : text
 
387
            ;
 
388
            module.set.selected(value);
 
389
            module.hide();
 
390
          },
 
391
 
 
392
          /* Deprecated */
 
393
          updateForm: function(text, value) {
 
394
            value = (value !== undefined)
 
395
              ? value
 
396
              : text
 
397
            ;
 
398
            module.set.selected(value);
 
399
            module.set.value(value);
 
400
            module.hide();
 
401
          }
 
402
 
 
403
        },
 
404
 
 
405
        get: {
 
406
          text: function() {
 
407
            return $text.text();
 
408
          },
 
409
          value: function() {
 
410
            return ($input.size() > 0)
 
411
              ? $input.val()
 
412
              : $module.data(metadata.value)
 
413
            ;
 
414
          },
 
415
          item: function(value, strict) {
 
416
            var
 
417
              $selectedItem = false
 
418
            ;
 
419
            value = (value !== undefined)
 
420
              ? value
 
421
              : ( module.get.value() !== undefined)
 
422
                ? module.get.value()
 
423
                : module.get.text()
 
424
            ;
 
425
            if(strict === undefined && value === '') {
 
426
              module.debug('Ambiguous dropdown value using strict type check', value);
 
427
              strict = true;
 
428
            }
 
429
            else {
 
430
              strict = strict || false;
 
431
            }
 
432
            if(value !== undefined) {
 
433
              $item
 
434
                .each(function() {
 
435
                  var
 
436
                    $choice       = $(this),
 
437
                    optionText    = ( $choice.data(metadata.text) !== undefined )
 
438
                      ? $choice.data(metadata.text)
 
439
                      : $choice.text(),
 
440
                    optionValue   = ( $choice.data(metadata.value) !== undefined )
 
441
                      ? $choice.data(metadata.value)
 
442
                      : (typeof optionText === 'string')
 
443
                        ? optionText.toLowerCase()
 
444
                        : optionText
 
445
                  ;
 
446
                  if(strict) {
 
447
                    if( optionValue === value ) {
 
448
                      $selectedItem = $(this);
 
449
                    }
 
450
                    else if( !$selectedItem && optionText === value ) {
 
451
                      $selectedItem = $(this);
 
452
                    }
 
453
                  }
 
454
                  else {
 
455
                    if( optionValue == value ) {
 
456
                      $selectedItem = $(this);
 
457
                    }
 
458
                    else if( !$selectedItem && optionText == value ) {
 
459
                      $selectedItem = $(this);
 
460
                    }
 
461
                  }
 
462
                })
 
463
              ;
 
464
            }
 
465
            else {
 
466
              value = module.get.text();
 
467
            }
 
468
            return $selectedItem || false;
 
469
          }
 
470
        },
 
471
 
 
472
        restore: {
 
473
          defaults: function() {
 
474
            module.restore.defaultText();
 
475
            module.restore.defaultValue();
 
476
          },
 
477
          defaultText: function() {
 
478
            var
 
479
              defaultText = $module.data(metadata.defaultText)
 
480
            ;
 
481
            module.debug('Restoring default text', defaultText);
 
482
            module.set.text(defaultText);
 
483
          },
 
484
          defaultValue: function() {
 
485
            var
 
486
              defaultValue = $module.data(metadata.defaultValue)
 
487
            ;
 
488
            if(defaultValue !== undefined) {
 
489
              module.debug('Restoring default value', defaultValue);
 
490
              module.set.selected(defaultValue);
 
491
              module.set.value(defaultValue);
 
492
            }
 
493
          }
 
494
        },
 
495
 
 
496
        save: {
 
497
          defaults: function() {
 
498
            module.save.defaultText();
 
499
            module.save.defaultValue();
 
500
          },
 
501
          defaultValue: function() {
 
502
            $module.data(metadata.defaultValue, module.get.value() );
 
503
          },
 
504
          defaultText: function() {
 
505
            $module.data(metadata.defaultText, $text.text() );
 
506
          }
 
507
        },
 
508
 
 
509
        set: {
 
510
          text: function(text) {
 
511
            module.debug('Changing text', text, $text);
 
512
            $text.removeClass(className.placeholder);
 
513
            $text.text(text);
 
514
          },
 
515
          value: function(value) {
 
516
            module.debug('Adding selected value to hidden input', value, $input);
 
517
            if($input.size() > 0) {
 
518
              $input
 
519
                .val(value)
 
520
                .trigger('change')
 
521
              ;
 
522
            }
 
523
            else {
 
524
              $module.data(metadata.value, value);
 
525
            }
 
526
          },
 
527
          active: function() {
 
528
            $module.addClass(className.active);
 
529
          },
 
530
          visible: function() {
 
531
            $module.addClass(className.visible);
 
532
          },
 
533
          selected: function(value) {
 
534
            var
 
535
              $selectedItem = module.get.item(value),
 
536
              selectedText
 
537
            ;
 
538
            if($selectedItem) {
 
539
              module.debug('Setting selected menu item to', $selectedItem);
 
540
              selectedText = ($selectedItem.data(metadata.text) !== undefined)
 
541
                ? $selectedItem.data(metadata.text)
 
542
                : $selectedItem.text()
 
543
              ;
 
544
              $item
 
545
                .removeClass(className.active)
 
546
              ;
 
547
              $selectedItem
 
548
                .addClass(className.active)
 
549
              ;
 
550
              module.set.text(selectedText);
 
551
            }
 
552
          }
 
553
        },
 
554
 
 
555
        remove: {
 
556
          active: function() {
 
557
            $module.removeClass(className.active);
 
558
          },
 
559
          visible: function() {
 
560
            $module.removeClass(className.visible);
 
561
          }
 
562
        },
 
563
 
 
564
        is: {
 
565
          selection: function() {
 
566
            return $module.hasClass(className.selection);
 
567
          },
 
568
          animated: function($subMenu) {
 
569
            return ($subMenu)
 
570
              ? $subMenu.is(':animated') || $subMenu.transition && $subMenu.transition('is animating')
 
571
              : $menu.is(':animated') || $menu.transition && $menu.transition('is animating')
 
572
            ;
 
573
          },
 
574
          visible: function($subMenu) {
 
575
            return ($subMenu)
 
576
              ? $subMenu.is(':visible')
 
577
              : $menu.is(':visible')
 
578
            ;
 
579
          },
 
580
          hidden: function($subMenu) {
 
581
            return ($subMenu)
 
582
              ? $subMenu.is(':not(:visible)')
 
583
              : $menu.is(':not(:visible)')
 
584
            ;
 
585
          }
 
586
        },
 
587
 
 
588
        can: {
 
589
          click: function() {
 
590
            return (hasTouch || settings.on == 'click');
 
591
          },
 
592
          show: function() {
 
593
            return !$module.hasClass(className.disabled);
 
594
          }
 
595
        },
 
596
 
 
597
        animate: {
 
598
          show: function(callback, $subMenu) {
 
599
            var
 
600
              $currentMenu = $subMenu || $menu
 
601
            ;
 
602
            callback = callback || function(){};
 
603
            if( module.is.hidden($currentMenu) ) {
 
604
              module.verbose('Doing menu show animation', $currentMenu);
 
605
              if(settings.transition == 'none') {
 
606
                callback();
 
607
              }
 
608
              else if($.fn.transition !== undefined && $module.transition('is supported')) {
 
609
                $currentMenu
 
610
                  .transition({
 
611
                    animation : settings.transition + ' in',
 
612
                    duration  : settings.duration,
 
613
                    complete  : callback,
 
614
                    queue     : false
 
615
                  })
 
616
                ;
 
617
              }
 
618
              else if(settings.transition == 'slide down') {
 
619
                $currentMenu
 
620
                  .hide()
 
621
                  .clearQueue()
 
622
                  .children()
 
623
                    .clearQueue()
 
624
                    .css('opacity', 0)
 
625
                    .delay(50)
 
626
                    .animate({
 
627
                      opacity : 1
 
628
                    }, settings.duration, 'easeOutQuad', module.event.resetStyle)
 
629
                    .end()
 
630
                  .slideDown(100, 'easeOutQuad', function() {
 
631
                    $.proxy(module.event.resetStyle, this)();
 
632
                    callback();
 
633
                  })
 
634
                ;
 
635
              }
 
636
              else if(settings.transition == 'fade') {
 
637
                $currentMenu
 
638
                  .hide()
 
639
                  .clearQueue()
 
640
                  .fadeIn(settings.duration, function() {
 
641
                    $.proxy(module.event.resetStyle, this)();
 
642
                    callback();
 
643
                  })
 
644
                ;
 
645
              }
 
646
              else {
 
647
                module.error(error.transition, settings.transition);
 
648
              }
 
649
            }
 
650
          },
 
651
          hide: function(callback, $subMenu) {
 
652
            var
 
653
              $currentMenu = $subMenu || $menu
 
654
            ;
 
655
            callback = callback || function(){};
 
656
            if(module.is.visible($currentMenu) ) {
 
657
              module.verbose('Doing menu hide animation', $currentMenu);
 
658
              if($.fn.transition !== undefined && $module.transition('is supported')) {
 
659
                $currentMenu
 
660
                  .transition({
 
661
                    animation : settings.transition + ' out',
 
662
                    duration  : settings.duration,
 
663
                    complete  : callback,
 
664
                    queue     : false
 
665
                  })
 
666
                ;
 
667
              }
 
668
              else if(settings.transition == 'none') {
 
669
                callback();
 
670
              }
 
671
              else if(settings.transition == 'slide down') {
 
672
                $currentMenu
 
673
                  .show()
 
674
                  .clearQueue()
 
675
                  .children()
 
676
                    .clearQueue()
 
677
                    .css('opacity', 1)
 
678
                    .animate({
 
679
                      opacity : 0
 
680
                    }, 100, 'easeOutQuad', module.event.resetStyle)
 
681
                    .end()
 
682
                  .delay(50)
 
683
                  .slideUp(100, 'easeOutQuad', function() {
 
684
                    $.proxy(module.event.resetStyle, this)();
 
685
                    callback();
 
686
                  })
 
687
                ;
 
688
              }
 
689
              else if(settings.transition == 'fade') {
 
690
                $currentMenu
 
691
                  .show()
 
692
                  .clearQueue()
 
693
                  .fadeOut(150, function() {
 
694
                    $.proxy(module.event.resetStyle, this)();
 
695
                    callback();
 
696
                  })
 
697
                ;
 
698
              }
 
699
              else {
 
700
                module.error(error.transition);
 
701
              }
 
702
            }
 
703
          }
 
704
        },
 
705
 
 
706
        show: function() {
 
707
          module.debug('Checking if dropdown can show');
 
708
          if( module.is.hidden() ) {
 
709
            module.hideOthers();
 
710
            module.set.active();
 
711
            module.animate.show(function() {
 
712
              if( module.can.click() ) {
 
713
                module.bind.intent();
 
714
              }
 
715
              module.set.visible();
 
716
            });
 
717
            $.proxy(settings.onShow, element)();
 
718
          }
 
719
        },
 
720
 
 
721
        hide: function() {
 
722
          if( !module.is.animated() && module.is.visible() ) {
 
723
            module.debug('Hiding dropdown');
 
724
            if( module.can.click() ) {
 
725
              module.unbind.intent();
 
726
            }
 
727
            module.remove.active();
 
728
            module.animate.hide(module.remove.visible);
 
729
            $.proxy(settings.onHide, element)();
 
730
          }
 
731
        },
 
732
 
 
733
        delay: {
 
734
          show: function() {
 
735
            module.verbose('Delaying show event to ensure user intent');
 
736
            clearTimeout(module.timer);
 
737
            module.timer = setTimeout(module.show, settings.delay.show);
 
738
          },
 
739
          hide: function() {
 
740
            module.verbose('Delaying hide event to ensure user intent');
 
741
            clearTimeout(module.timer);
 
742
            module.timer = setTimeout(module.hide, settings.delay.hide);
 
743
          }
 
744
        },
 
745
 
 
746
        hideOthers: function() {
 
747
          module.verbose('Finding other dropdowns to hide');
 
748
          $allModules
 
749
            .not($module)
 
750
              .has(selector.menu + ':visible')
 
751
              .dropdown('hide')
 
752
          ;
 
753
        },
 
754
 
 
755
        toggle: function() {
 
756
          module.verbose('Toggling menu visibility');
 
757
          if( module.is.hidden() ) {
 
758
            module.show();
 
759
          }
 
760
          else {
 
761
            module.hide();
 
762
          }
 
763
        },
 
764
 
 
765
        setting: function(name, value) {
 
766
          if( $.isPlainObject(name) ) {
 
767
            $.extend(true, settings, name);
 
768
          }
 
769
          else if(value !== undefined) {
 
770
            settings[name] = value;
 
771
          }
 
772
          else {
 
773
            return settings[name];
 
774
          }
 
775
        },
 
776
        internal: function(name, value) {
 
777
          if( $.isPlainObject(name) ) {
 
778
            $.extend(true, module, name);
 
779
          }
 
780
          else if(value !== undefined) {
 
781
            module[name] = value;
 
782
          }
 
783
          else {
 
784
            return module[name];
 
785
          }
 
786
        },
 
787
        debug: function() {
 
788
          if(settings.debug) {
 
789
            if(settings.performance) {
 
790
              module.performance.log(arguments);
 
791
            }
 
792
            else {
 
793
              module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
 
794
              module.debug.apply(console, arguments);
 
795
            }
 
796
          }
 
797
        },
 
798
        verbose: function() {
 
799
          if(settings.verbose && settings.debug) {
 
800
            if(settings.performance) {
 
801
              module.performance.log(arguments);
 
802
            }
 
803
            else {
 
804
              module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
 
805
              module.verbose.apply(console, arguments);
 
806
            }
 
807
          }
 
808
        },
 
809
        error: function() {
 
810
          module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
 
811
          module.error.apply(console, arguments);
 
812
        },
 
813
        performance: {
 
814
          log: function(message) {
 
815
            var
 
816
              currentTime,
 
817
              executionTime,
 
818
              previousTime
 
819
            ;
 
820
            if(settings.performance) {
 
821
              currentTime   = new Date().getTime();
 
822
              previousTime  = time || currentTime;
 
823
              executionTime = currentTime - previousTime;
 
824
              time          = currentTime;
 
825
              performance.push({
 
826
                'Element'        : element,
 
827
                'Name'           : message[0],
 
828
                'Arguments'      : [].slice.call(message, 1) || '',
 
829
                'Execution Time' : executionTime
 
830
              });
 
831
            }
 
832
            clearTimeout(module.performance.timer);
 
833
            module.performance.timer = setTimeout(module.performance.display, 100);
 
834
          },
 
835
          display: function() {
 
836
            var
 
837
              title = settings.name + ':',
 
838
              totalTime = 0
 
839
            ;
 
840
            time = false;
 
841
            clearTimeout(module.performance.timer);
 
842
            $.each(performance, function(index, data) {
 
843
              totalTime += data['Execution Time'];
 
844
            });
 
845
            title += ' ' + totalTime + 'ms';
 
846
            if(moduleSelector) {
 
847
              title += ' \'' + moduleSelector + '\'';
 
848
            }
 
849
            if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
 
850
              console.groupCollapsed(title);
 
851
              if(console.table) {
 
852
                console.table(performance);
 
853
              }
 
854
              else {
 
855
                $.each(performance, function(index, data) {
 
856
                  console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
 
857
                });
 
858
              }
 
859
              console.groupEnd();
 
860
            }
 
861
            performance = [];
 
862
          }
 
863
        },
 
864
        invoke: function(query, passedArguments, context) {
 
865
          var
 
866
            object = instance,
 
867
            maxDepth,
 
868
            found,
 
869
            response
 
870
          ;
 
871
          passedArguments = passedArguments || queryArguments;
 
872
          context         = element         || context;
 
873
          if(typeof query == 'string' && object !== undefined) {
 
874
            query    = query.split(/[\. ]/);
 
875
            maxDepth = query.length - 1;
 
876
            $.each(query, function(depth, value) {
 
877
              var camelCaseValue = (depth != maxDepth)
 
878
                ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
 
879
                : query
 
880
              ;
 
881
              if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
 
882
                object = object[camelCaseValue];
 
883
              }
 
884
              else if( object[camelCaseValue] !== undefined ) {
 
885
                found = object[camelCaseValue];
 
886
                return false;
 
887
              }
 
888
              else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
 
889
                object = object[value];
 
890
              }
 
891
              else if( object[value] !== undefined ) {
 
892
                found = object[value];
 
893
                return false;
 
894
              }
 
895
              else {
 
896
                module.error(error.method, query);
 
897
                return false;
 
898
              }
 
899
            });
 
900
          }
 
901
          if ( $.isFunction( found ) ) {
 
902
            response = found.apply(context, passedArguments);
 
903
          }
 
904
          else if(found !== undefined) {
 
905
            response = found;
 
906
          }
 
907
          if($.isArray(returnedValue)) {
 
908
            returnedValue.push(response);
 
909
          }
 
910
          else if(returnedValue !== undefined) {
 
911
            returnedValue = [returnedValue, response];
 
912
          }
 
913
          else if(response !== undefined) {
 
914
            returnedValue = response;
 
915
          }
 
916
          return found;
 
917
        }
 
918
      };
 
919
 
 
920
      if(methodInvoked) {
 
921
        if(instance === undefined) {
 
922
          module.initialize();
 
923
        }
 
924
        module.invoke(query);
 
925
      }
 
926
      else {
 
927
        if(instance !== undefined) {
 
928
          module.destroy();
 
929
        }
 
930
        module.initialize();
 
931
      }
 
932
    })
 
933
  ;
 
934
 
 
935
  return (returnedValue !== undefined)
 
936
    ? returnedValue
 
937
    : this
 
938
  ;
 
939
};
 
940
 
 
941
$.fn.dropdown.settings = {
 
942
 
 
943
  name        : 'Dropdown',
 
944
  namespace   : 'dropdown',
 
945
 
 
946
  debug       : false,
 
947
  verbose     : true,
 
948
  performance : true,
 
949
 
 
950
  on          : 'click',
 
951
  action      : 'activate',
 
952
 
 
953
  delay: {
 
954
    show  : 200,
 
955
    hide  : 300,
 
956
    touch : 50
 
957
  },
 
958
 
 
959
  transition : 'slide down',
 
960
  duration   : 250,
 
961
 
 
962
  onChange : function(value, text){},
 
963
  onShow   : function(){},
 
964
  onHide   : function(){},
 
965
 
 
966
  error   : {
 
967
    action    : 'You called a dropdown action that was not defined',
 
968
    method    : 'The method you called is not defined.',
 
969
    transition : 'The requested transition was not found'
 
970
  },
 
971
 
 
972
  metadata: {
 
973
    defaultText  : 'defaultText',
 
974
    defaultValue : 'defaultValue',
 
975
    text         : 'text',
 
976
    value        : 'value'
 
977
  },
 
978
 
 
979
  selector : {
 
980
    menu    : '.menu',
 
981
    submenu : '> .menu',
 
982
    item    : '.menu > .item',
 
983
    text    : '> .text',
 
984
    input   : '> input[type="hidden"]'
 
985
  },
 
986
 
 
987
  className : {
 
988
    active      : 'active',
 
989
    placeholder : 'default',
 
990
    disabled    : 'disabled',
 
991
    visible     : 'visible',
 
992
    selected    : 'selected',
 
993
    selection   : 'selection'
 
994
  }
 
995
 
 
996
};
 
997
 
 
998
// Adds easing
 
999
$.extend( $.easing, {
 
1000
  easeOutQuad: function (x, t, b, c, d) {
 
1001
    return -c *(t/=d)*(t-2) + b;
 
1002
  }
 
1003
});
 
1004
 
 
1005
 
 
1006
})( jQuery, window , document );