Code Duplication    Length = 599-599 lines in 2 locations

public/lib/semantic/semantic.js 1 location

@@ 2216-2814 (lines=599) @@
2213
 *
2214
 */
2215
2216
;(function ($, window, document, undefined) {
2217
2218
"use strict";
2219
2220
window = (typeof window != 'undefined' && window.Math == Math)
2221
  ? window
2222
  : (typeof self != 'undefined' && self.Math == Math)
2223
    ? self
2224
    : Function('return this')()
2225
;
2226
2227
$.fn.accordion = function(parameters) {
2228
  var
2229
    $allModules     = $(this),
2230
2231
    time            = new Date().getTime(),
2232
    performance     = [],
2233
2234
    query           = arguments[0],
2235
    methodInvoked   = (typeof query == 'string'),
2236
    queryArguments  = [].slice.call(arguments, 1),
2237
2238
    requestAnimationFrame = window.requestAnimationFrame
2239
      || window.mozRequestAnimationFrame
2240
      || window.webkitRequestAnimationFrame
2241
      || window.msRequestAnimationFrame
2242
      || function(callback) { setTimeout(callback, 0); },
2243
2244
    returnedValue
2245
  ;
2246
  $allModules
2247
    .each(function() {
2248
      var
2249
        settings        = ( $.isPlainObject(parameters) )
2250
          ? $.extend(true, {}, $.fn.accordion.settings, parameters)
2251
          : $.extend({}, $.fn.accordion.settings),
2252
2253
        className       = settings.className,
2254
        namespace       = settings.namespace,
2255
        selector        = settings.selector,
2256
        error           = settings.error,
2257
2258
        eventNamespace  = '.' + namespace,
2259
        moduleNamespace = 'module-' + namespace,
2260
        moduleSelector  = $allModules.selector || '',
2261
2262
        $module  = $(this),
2263
        $title   = $module.find(selector.title),
2264
        $content = $module.find(selector.content),
2265
2266
        element  = this,
2267
        instance = $module.data(moduleNamespace),
2268
        observer,
2269
        module
2270
      ;
2271
2272
      module = {
2273
2274
        initialize: function() {
2275
          module.debug('Initializing', $module);
2276
          module.bind.events();
2277
          if(settings.observeChanges) {
2278
            module.observeChanges();
2279
          }
2280
          module.instantiate();
2281
        },
2282
2283
        instantiate: function() {
2284
          instance = module;
2285
          $module
2286
            .data(moduleNamespace, module)
2287
          ;
2288
        },
2289
2290
        destroy: function() {
2291
          module.debug('Destroying previous instance', $module);
2292
          $module
2293
            .off(eventNamespace)
2294
            .removeData(moduleNamespace)
2295
          ;
2296
        },
2297
2298
        refresh: function() {
2299
          $title   = $module.find(selector.title);
2300
          $content = $module.find(selector.content);
2301
        },
2302
2303
        observeChanges: function() {
2304
          if('MutationObserver' in window) {
2305
            observer = new MutationObserver(function(mutations) {
2306
              module.debug('DOM tree modified, updating selector cache');
2307
              module.refresh();
2308
            });
2309
            observer.observe(element, {
2310
              childList : true,
2311
              subtree   : true
2312
            });
2313
            module.debug('Setting up mutation observer', observer);
2314
          }
2315
        },
2316
2317
        bind: {
2318
          events: function() {
2319
            module.debug('Binding delegated events');
2320
            $module
2321
              .on(settings.on + eventNamespace, selector.trigger, module.event.click)
2322
            ;
2323
          }
2324
        },
2325
2326
        event: {
2327
          click: function() {
2328
            module.toggle.call(this);
2329
          }
2330
        },
2331
2332
        toggle: function(query) {
2333
          var
2334
            $activeTitle = (query !== undefined)
2335
              ? (typeof query === 'number')
2336
                ? $title.eq(query)
2337
                : $(query).closest(selector.title)
2338
              : $(this).closest(selector.title),
2339
            $activeContent = $activeTitle.next($content),
2340
            isAnimating = $activeContent.hasClass(className.animating),
2341
            isActive    = $activeContent.hasClass(className.active),
2342
            isOpen      = (isActive && !isAnimating),
2343
            isOpening   = (!isActive && isAnimating)
2344
          ;
2345
          module.debug('Toggling visibility of content', $activeTitle);
2346
          if(isOpen || isOpening) {
2347
            if(settings.collapsible) {
2348
              module.close.call($activeTitle);
2349
            }
2350
            else {
2351
              module.debug('Cannot close accordion content collapsing is disabled');
2352
            }
2353
          }
2354
          else {
2355
            module.open.call($activeTitle);
2356
          }
2357
        },
2358
2359
        open: function(query) {
2360
          var
2361
            $activeTitle = (query !== undefined)
2362
              ? (typeof query === 'number')
2363
                ? $title.eq(query)
2364
                : $(query).closest(selector.title)
2365
              : $(this).closest(selector.title),
2366
            $activeContent = $activeTitle.next($content),
2367
            isAnimating = $activeContent.hasClass(className.animating),
2368
            isActive    = $activeContent.hasClass(className.active),
2369
            isOpen      = (isActive || isAnimating)
2370
          ;
2371
          if(isOpen) {
2372
            module.debug('Accordion already open, skipping', $activeContent);
2373
            return;
2374
          }
2375
          module.debug('Opening accordion content', $activeTitle);
2376
          settings.onOpening.call($activeContent);
2377
          if(settings.exclusive) {
2378
            module.closeOthers.call($activeTitle);
2379
          }
2380
          $activeTitle
2381
            .addClass(className.active)
2382
          ;
2383
          $activeContent
2384
            .stop(true, true)
2385
            .addClass(className.animating)
2386
          ;
2387
          if(settings.animateChildren) {
2388
            if($.fn.transition !== undefined && $module.transition('is supported')) {
2389
              $activeContent
2390
                .children()
2391
                  .transition({
2392
                    animation   : 'fade in',
2393
                    queue       : false,
2394
                    useFailSafe : true,
2395
                    debug       : settings.debug,
2396
                    verbose     : settings.verbose,
2397
                    duration    : settings.duration
2398
                  })
2399
              ;
2400
            }
2401
            else {
2402
              $activeContent
2403
                .children()
2404
                  .stop(true, true)
2405
                  .animate({
2406
                    opacity: 1
2407
                  }, settings.duration, module.resetOpacity)
2408
              ;
2409
            }
2410
          }
2411
          $activeContent
2412
            .slideDown(settings.duration, settings.easing, function() {
2413
              $activeContent
2414
                .removeClass(className.animating)
2415
                .addClass(className.active)
2416
              ;
2417
              module.reset.display.call(this);
2418
              settings.onOpen.call(this);
2419
              settings.onChange.call(this);
2420
            })
2421
          ;
2422
        },
2423
2424
        close: function(query) {
2425
          var
2426
            $activeTitle = (query !== undefined)
2427
              ? (typeof query === 'number')
2428
                ? $title.eq(query)
2429
                : $(query).closest(selector.title)
2430
              : $(this).closest(selector.title),
2431
            $activeContent = $activeTitle.next($content),
2432
            isAnimating    = $activeContent.hasClass(className.animating),
2433
            isActive       = $activeContent.hasClass(className.active),
2434
            isOpening      = (!isActive && isAnimating),
2435
            isClosing      = (isActive && isAnimating)
2436
          ;
2437
          if((isActive || isOpening) && !isClosing) {
2438
            module.debug('Closing accordion content', $activeContent);
2439
            settings.onClosing.call($activeContent);
2440
            $activeTitle
2441
              .removeClass(className.active)
2442
            ;
2443
            $activeContent
2444
              .stop(true, true)
2445
              .addClass(className.animating)
2446
            ;
2447
            if(settings.animateChildren) {
2448
              if($.fn.transition !== undefined && $module.transition('is supported')) {
2449
                $activeContent
2450
                  .children()
2451
                    .transition({
2452
                      animation   : 'fade out',
2453
                      queue       : false,
2454
                      useFailSafe : true,
2455
                      debug       : settings.debug,
2456
                      verbose     : settings.verbose,
2457
                      duration    : settings.duration
2458
                    })
2459
                ;
2460
              }
2461
              else {
2462
                $activeContent
2463
                  .children()
2464
                    .stop(true, true)
2465
                    .animate({
2466
                      opacity: 0
2467
                    }, settings.duration, module.resetOpacity)
2468
                ;
2469
              }
2470
            }
2471
            $activeContent
2472
              .slideUp(settings.duration, settings.easing, function() {
2473
                $activeContent
2474
                  .removeClass(className.animating)
2475
                  .removeClass(className.active)
2476
                ;
2477
                module.reset.display.call(this);
2478
                settings.onClose.call(this);
2479
                settings.onChange.call(this);
2480
              })
2481
            ;
2482
          }
2483
        },
2484
2485
        closeOthers: function(index) {
2486
          var
2487
            $activeTitle = (index !== undefined)
2488
              ? $title.eq(index)
2489
              : $(this).closest(selector.title),
2490
            $parentTitles    = $activeTitle.parents(selector.content).prev(selector.title),
2491
            $activeAccordion = $activeTitle.closest(selector.accordion),
2492
            activeSelector   = selector.title + '.' + className.active + ':visible',
2493
            activeContent    = selector.content + '.' + className.active + ':visible',
2494
            $openTitles,
2495
            $nestedTitles,
2496
            $openContents
2497
          ;
2498
          if(settings.closeNested) {
2499
            $openTitles   = $activeAccordion.find(activeSelector).not($parentTitles);
2500
            $openContents = $openTitles.next($content);
2501
          }
2502
          else {
2503
            $openTitles   = $activeAccordion.find(activeSelector).not($parentTitles);
2504
            $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
2505
            $openTitles   = $openTitles.not($nestedTitles);
2506
            $openContents = $openTitles.next($content);
2507
          }
2508
          if( ($openTitles.length > 0) ) {
2509
            module.debug('Exclusive enabled, closing other content', $openTitles);
2510
            $openTitles
2511
              .removeClass(className.active)
2512
            ;
2513
            $openContents
2514
              .removeClass(className.animating)
2515
              .stop(true, true)
2516
            ;
2517
            if(settings.animateChildren) {
2518
              if($.fn.transition !== undefined && $module.transition('is supported')) {
2519
                $openContents
2520
                  .children()
2521
                    .transition({
2522
                      animation   : 'fade out',
2523
                      useFailSafe : true,
2524
                      debug       : settings.debug,
2525
                      verbose     : settings.verbose,
2526
                      duration    : settings.duration
2527
                    })
2528
                ;
2529
              }
2530
              else {
2531
                $openContents
2532
                  .children()
2533
                    .stop(true, true)
2534
                    .animate({
2535
                      opacity: 0
2536
                    }, settings.duration, module.resetOpacity)
2537
                ;
2538
              }
2539
            }
2540
            $openContents
2541
              .slideUp(settings.duration , settings.easing, function() {
2542
                $(this).removeClass(className.active);
2543
                module.reset.display.call(this);
2544
              })
2545
            ;
2546
          }
2547
        },
2548
2549
        reset: {
2550
2551
          display: function() {
2552
            module.verbose('Removing inline display from element', this);
2553
            $(this).css('display', '');
2554
            if( $(this).attr('style') === '') {
2555
              $(this)
2556
                .attr('style', '')
2557
                .removeAttr('style')
2558
              ;
2559
            }
2560
          },
2561
2562
          opacity: function() {
2563
            module.verbose('Removing inline opacity from element', this);
2564
            $(this).css('opacity', '');
2565
            if( $(this).attr('style') === '') {
2566
              $(this)
2567
                .attr('style', '')
2568
                .removeAttr('style')
2569
              ;
2570
            }
2571
          },
2572
2573
        },
2574
2575
        setting: function(name, value) {
2576
          module.debug('Changing setting', name, value);
2577
          if( $.isPlainObject(name) ) {
2578
            $.extend(true, settings, name);
2579
          }
2580
          else if(value !== undefined) {
2581
            if($.isPlainObject(settings[name])) {
2582
              $.extend(true, settings[name], value);
2583
            }
2584
            else {
2585
              settings[name] = value;
2586
            }
2587
          }
2588
          else {
2589
            return settings[name];
2590
          }
2591
        },
2592
        internal: function(name, value) {
2593
          module.debug('Changing internal', name, value);
2594
          if(value !== undefined) {
2595
            if( $.isPlainObject(name) ) {
2596
              $.extend(true, module, name);
2597
            }
2598
            else {
2599
              module[name] = value;
2600
            }
2601
          }
2602
          else {
2603
            return module[name];
2604
          }
2605
        },
2606
        debug: function() {
2607
          if(!settings.silent && settings.debug) {
2608
            if(settings.performance) {
2609
              module.performance.log(arguments);
2610
            }
2611
            else {
2612
              module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
2613
              module.debug.apply(console, arguments);
2614
            }
2615
          }
2616
        },
2617
        verbose: function() {
2618
          if(!settings.silent && settings.verbose && settings.debug) {
2619
            if(settings.performance) {
2620
              module.performance.log(arguments);
2621
            }
2622
            else {
2623
              module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
2624
              module.verbose.apply(console, arguments);
2625
            }
2626
          }
2627
        },
2628
        error: function() {
2629
          if(!settings.silent) {
2630
            module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
2631
            module.error.apply(console, arguments);
2632
          }
2633
        },
2634
        performance: {
2635
          log: function(message) {
2636
            var
2637
              currentTime,
2638
              executionTime,
2639
              previousTime
2640
            ;
2641
            if(settings.performance) {
2642
              currentTime   = new Date().getTime();
2643
              previousTime  = time || currentTime;
2644
              executionTime = currentTime - previousTime;
2645
              time          = currentTime;
2646
              performance.push({
2647
                'Name'           : message[0],
2648
                'Arguments'      : [].slice.call(message, 1) || '',
2649
                'Element'        : element,
2650
                'Execution Time' : executionTime
2651
              });
2652
            }
2653
            clearTimeout(module.performance.timer);
2654
            module.performance.timer = setTimeout(module.performance.display, 500);
2655
          },
2656
          display: function() {
2657
            var
2658
              title = settings.name + ':',
2659
              totalTime = 0
2660
            ;
2661
            time = false;
2662
            clearTimeout(module.performance.timer);
2663
            $.each(performance, function(index, data) {
2664
              totalTime += data['Execution Time'];
2665
            });
2666
            title += ' ' + totalTime + 'ms';
2667
            if(moduleSelector) {
2668
              title += ' \'' + moduleSelector + '\'';
2669
            }
2670
            if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
2671
              console.groupCollapsed(title);
2672
              if(console.table) {
2673
                console.table(performance);
2674
              }
2675
              else {
2676
                $.each(performance, function(index, data) {
2677
                  console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
2678
                });
2679
              }
2680
              console.groupEnd();
2681
            }
2682
            performance = [];
2683
          }
2684
        },
2685
        invoke: function(query, passedArguments, context) {
2686
          var
2687
            object = instance,
2688
            maxDepth,
2689
            found,
2690
            response
2691
          ;
2692
          passedArguments = passedArguments || queryArguments;
2693
          context         = element         || context;
2694
          if(typeof query == 'string' && object !== undefined) {
2695
            query    = query.split(/[\. ]/);
2696
            maxDepth = query.length - 1;
2697
            $.each(query, function(depth, value) {
2698
              var camelCaseValue = (depth != maxDepth)
2699
                ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
2700
                : query
2701
              ;
2702
              if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
2703
                object = object[camelCaseValue];
2704
              }
2705
              else if( object[camelCaseValue] !== undefined ) {
2706
                found = object[camelCaseValue];
2707
                return false;
2708
              }
2709
              else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
2710
                object = object[value];
2711
              }
2712
              else if( object[value] !== undefined ) {
2713
                found = object[value];
2714
                return false;
2715
              }
2716
              else {
2717
                module.error(error.method, query);
2718
                return false;
2719
              }
2720
            });
2721
          }
2722
          if ( $.isFunction( found ) ) {
2723
            response = found.apply(context, passedArguments);
2724
          }
2725
          else if(found !== undefined) {
2726
            response = found;
2727
          }
2728
          if($.isArray(returnedValue)) {
2729
            returnedValue.push(response);
2730
          }
2731
          else if(returnedValue !== undefined) {
2732
            returnedValue = [returnedValue, response];
2733
          }
2734
          else if(response !== undefined) {
2735
            returnedValue = response;
2736
          }
2737
          return found;
2738
        }
2739
      };
2740
      if(methodInvoked) {
2741
        if(instance === undefined) {
2742
          module.initialize();
2743
        }
2744
        module.invoke(query);
2745
      }
2746
      else {
2747
        if(instance !== undefined) {
2748
          instance.invoke('destroy');
2749
        }
2750
        module.initialize();
2751
      }
2752
    })
2753
  ;
2754
  return (returnedValue !== undefined)
2755
    ? returnedValue
2756
    : this
2757
  ;
2758
};
2759
2760
$.fn.accordion.settings = {
2761
2762
  name            : 'Accordion',
2763
  namespace       : 'accordion',
2764
2765
  silent          : false,
2766
  debug           : false,
2767
  verbose         : false,
2768
  performance     : true,
2769
2770
  on              : 'click', // event on title that opens accordion
2771
2772
  observeChanges  : true,  // whether accordion should automatically refresh on DOM insertion
2773
2774
  exclusive       : true,  // whether a single accordion content panel should be open at once
2775
  collapsible     : true,  // whether accordion content can be closed
2776
  closeNested     : false, // whether nested content should be closed when a panel is closed
2777
  animateChildren : true,  // whether children opacity should be animated
2778
2779
  duration        : 350, // duration of animation
2780
  easing          : 'easeOutQuad', // easing equation for animation
2781
2782
2783
  onOpening       : function(){}, // callback before open animation
2784
  onOpen          : function(){}, // callback after open animation
2785
  onClosing       : function(){}, // callback before closing animation
2786
  onClose         : function(){}, // callback after closing animation
2787
  onChange        : function(){}, // callback after closing or opening animation
2788
2789
  error: {
2790
    method : 'The method you called is not defined'
2791
  },
2792
2793
  className   : {
2794
    active    : 'active',
2795
    animating : 'animating'
2796
  },
2797
2798
  selector    : {
2799
    accordion : '.accordion',
2800
    title     : '.title',
2801
    trigger   : '.title',
2802
    content   : '.content'
2803
  }
2804
2805
};
2806
2807
// Adds easing
2808
$.extend( $.easing, {
2809
  easeOutQuad: function (x, t, b, c, d) {
2810
    return -c *(t/=d)*(t-2) + b;
2811
  }
2812
});
2813
2814
})( jQuery, window, document );
2815
2816
2817
/*!

public/lib/semantic/components/accordion.js 1 location

@@ 11-609 (lines=599) @@
8
 *
9
 */
10
11
;(function ($, window, document, undefined) {
12
13
"use strict";
14
15
window = (typeof window != 'undefined' && window.Math == Math)
16
  ? window
17
  : (typeof self != 'undefined' && self.Math == Math)
18
    ? self
19
    : Function('return this')()
20
;
21
22
$.fn.accordion = function(parameters) {
23
  var
24
    $allModules     = $(this),
25
26
    time            = new Date().getTime(),
27
    performance     = [],
28
29
    query           = arguments[0],
30
    methodInvoked   = (typeof query == 'string'),
31
    queryArguments  = [].slice.call(arguments, 1),
32
33
    requestAnimationFrame = window.requestAnimationFrame
34
      || window.mozRequestAnimationFrame
35
      || window.webkitRequestAnimationFrame
36
      || window.msRequestAnimationFrame
37
      || function(callback) { setTimeout(callback, 0); },
38
39
    returnedValue
40
  ;
41
  $allModules
42
    .each(function() {
43
      var
44
        settings        = ( $.isPlainObject(parameters) )
45
          ? $.extend(true, {}, $.fn.accordion.settings, parameters)
46
          : $.extend({}, $.fn.accordion.settings),
47
48
        className       = settings.className,
49
        namespace       = settings.namespace,
50
        selector        = settings.selector,
51
        error           = settings.error,
52
53
        eventNamespace  = '.' + namespace,
54
        moduleNamespace = 'module-' + namespace,
55
        moduleSelector  = $allModules.selector || '',
56
57
        $module  = $(this),
58
        $title   = $module.find(selector.title),
59
        $content = $module.find(selector.content),
60
61
        element  = this,
62
        instance = $module.data(moduleNamespace),
63
        observer,
64
        module
65
      ;
66
67
      module = {
68
69
        initialize: function() {
70
          module.debug('Initializing', $module);
71
          module.bind.events();
72
          if(settings.observeChanges) {
73
            module.observeChanges();
74
          }
75
          module.instantiate();
76
        },
77
78
        instantiate: function() {
79
          instance = module;
80
          $module
81
            .data(moduleNamespace, module)
82
          ;
83
        },
84
85
        destroy: function() {
86
          module.debug('Destroying previous instance', $module);
87
          $module
88
            .off(eventNamespace)
89
            .removeData(moduleNamespace)
90
          ;
91
        },
92
93
        refresh: function() {
94
          $title   = $module.find(selector.title);
95
          $content = $module.find(selector.content);
96
        },
97
98
        observeChanges: function() {
99
          if('MutationObserver' in window) {
100
            observer = new MutationObserver(function(mutations) {
101
              module.debug('DOM tree modified, updating selector cache');
102
              module.refresh();
103
            });
104
            observer.observe(element, {
105
              childList : true,
106
              subtree   : true
107
            });
108
            module.debug('Setting up mutation observer', observer);
109
          }
110
        },
111
112
        bind: {
113
          events: function() {
114
            module.debug('Binding delegated events');
115
            $module
116
              .on(settings.on + eventNamespace, selector.trigger, module.event.click)
117
            ;
118
          }
119
        },
120
121
        event: {
122
          click: function() {
123
            module.toggle.call(this);
124
          }
125
        },
126
127
        toggle: function(query) {
128
          var
129
            $activeTitle = (query !== undefined)
130
              ? (typeof query === 'number')
131
                ? $title.eq(query)
132
                : $(query).closest(selector.title)
133
              : $(this).closest(selector.title),
134
            $activeContent = $activeTitle.next($content),
135
            isAnimating = $activeContent.hasClass(className.animating),
136
            isActive    = $activeContent.hasClass(className.active),
137
            isOpen      = (isActive && !isAnimating),
138
            isOpening   = (!isActive && isAnimating)
139
          ;
140
          module.debug('Toggling visibility of content', $activeTitle);
141
          if(isOpen || isOpening) {
142
            if(settings.collapsible) {
143
              module.close.call($activeTitle);
144
            }
145
            else {
146
              module.debug('Cannot close accordion content collapsing is disabled');
147
            }
148
          }
149
          else {
150
            module.open.call($activeTitle);
151
          }
152
        },
153
154
        open: function(query) {
155
          var
156
            $activeTitle = (query !== undefined)
157
              ? (typeof query === 'number')
158
                ? $title.eq(query)
159
                : $(query).closest(selector.title)
160
              : $(this).closest(selector.title),
161
            $activeContent = $activeTitle.next($content),
162
            isAnimating = $activeContent.hasClass(className.animating),
163
            isActive    = $activeContent.hasClass(className.active),
164
            isOpen      = (isActive || isAnimating)
165
          ;
166
          if(isOpen) {
167
            module.debug('Accordion already open, skipping', $activeContent);
168
            return;
169
          }
170
          module.debug('Opening accordion content', $activeTitle);
171
          settings.onOpening.call($activeContent);
172
          if(settings.exclusive) {
173
            module.closeOthers.call($activeTitle);
174
          }
175
          $activeTitle
176
            .addClass(className.active)
177
          ;
178
          $activeContent
179
            .stop(true, true)
180
            .addClass(className.animating)
181
          ;
182
          if(settings.animateChildren) {
183
            if($.fn.transition !== undefined && $module.transition('is supported')) {
184
              $activeContent
185
                .children()
186
                  .transition({
187
                    animation   : 'fade in',
188
                    queue       : false,
189
                    useFailSafe : true,
190
                    debug       : settings.debug,
191
                    verbose     : settings.verbose,
192
                    duration    : settings.duration
193
                  })
194
              ;
195
            }
196
            else {
197
              $activeContent
198
                .children()
199
                  .stop(true, true)
200
                  .animate({
201
                    opacity: 1
202
                  }, settings.duration, module.resetOpacity)
203
              ;
204
            }
205
          }
206
          $activeContent
207
            .slideDown(settings.duration, settings.easing, function() {
208
              $activeContent
209
                .removeClass(className.animating)
210
                .addClass(className.active)
211
              ;
212
              module.reset.display.call(this);
213
              settings.onOpen.call(this);
214
              settings.onChange.call(this);
215
            })
216
          ;
217
        },
218
219
        close: function(query) {
220
          var
221
            $activeTitle = (query !== undefined)
222
              ? (typeof query === 'number')
223
                ? $title.eq(query)
224
                : $(query).closest(selector.title)
225
              : $(this).closest(selector.title),
226
            $activeContent = $activeTitle.next($content),
227
            isAnimating    = $activeContent.hasClass(className.animating),
228
            isActive       = $activeContent.hasClass(className.active),
229
            isOpening      = (!isActive && isAnimating),
230
            isClosing      = (isActive && isAnimating)
231
          ;
232
          if((isActive || isOpening) && !isClosing) {
233
            module.debug('Closing accordion content', $activeContent);
234
            settings.onClosing.call($activeContent);
235
            $activeTitle
236
              .removeClass(className.active)
237
            ;
238
            $activeContent
239
              .stop(true, true)
240
              .addClass(className.animating)
241
            ;
242
            if(settings.animateChildren) {
243
              if($.fn.transition !== undefined && $module.transition('is supported')) {
244
                $activeContent
245
                  .children()
246
                    .transition({
247
                      animation   : 'fade out',
248
                      queue       : false,
249
                      useFailSafe : true,
250
                      debug       : settings.debug,
251
                      verbose     : settings.verbose,
252
                      duration    : settings.duration
253
                    })
254
                ;
255
              }
256
              else {
257
                $activeContent
258
                  .children()
259
                    .stop(true, true)
260
                    .animate({
261
                      opacity: 0
262
                    }, settings.duration, module.resetOpacity)
263
                ;
264
              }
265
            }
266
            $activeContent
267
              .slideUp(settings.duration, settings.easing, function() {
268
                $activeContent
269
                  .removeClass(className.animating)
270
                  .removeClass(className.active)
271
                ;
272
                module.reset.display.call(this);
273
                settings.onClose.call(this);
274
                settings.onChange.call(this);
275
              })
276
            ;
277
          }
278
        },
279
280
        closeOthers: function(index) {
281
          var
282
            $activeTitle = (index !== undefined)
283
              ? $title.eq(index)
284
              : $(this).closest(selector.title),
285
            $parentTitles    = $activeTitle.parents(selector.content).prev(selector.title),
286
            $activeAccordion = $activeTitle.closest(selector.accordion),
287
            activeSelector   = selector.title + '.' + className.active + ':visible',
288
            activeContent    = selector.content + '.' + className.active + ':visible',
289
            $openTitles,
290
            $nestedTitles,
291
            $openContents
292
          ;
293
          if(settings.closeNested) {
294
            $openTitles   = $activeAccordion.find(activeSelector).not($parentTitles);
295
            $openContents = $openTitles.next($content);
296
          }
297
          else {
298
            $openTitles   = $activeAccordion.find(activeSelector).not($parentTitles);
299
            $nestedTitles = $activeAccordion.find(activeContent).find(activeSelector).not($parentTitles);
300
            $openTitles   = $openTitles.not($nestedTitles);
301
            $openContents = $openTitles.next($content);
302
          }
303
          if( ($openTitles.length > 0) ) {
304
            module.debug('Exclusive enabled, closing other content', $openTitles);
305
            $openTitles
306
              .removeClass(className.active)
307
            ;
308
            $openContents
309
              .removeClass(className.animating)
310
              .stop(true, true)
311
            ;
312
            if(settings.animateChildren) {
313
              if($.fn.transition !== undefined && $module.transition('is supported')) {
314
                $openContents
315
                  .children()
316
                    .transition({
317
                      animation   : 'fade out',
318
                      useFailSafe : true,
319
                      debug       : settings.debug,
320
                      verbose     : settings.verbose,
321
                      duration    : settings.duration
322
                    })
323
                ;
324
              }
325
              else {
326
                $openContents
327
                  .children()
328
                    .stop(true, true)
329
                    .animate({
330
                      opacity: 0
331
                    }, settings.duration, module.resetOpacity)
332
                ;
333
              }
334
            }
335
            $openContents
336
              .slideUp(settings.duration , settings.easing, function() {
337
                $(this).removeClass(className.active);
338
                module.reset.display.call(this);
339
              })
340
            ;
341
          }
342
        },
343
344
        reset: {
345
346
          display: function() {
347
            module.verbose('Removing inline display from element', this);
348
            $(this).css('display', '');
349
            if( $(this).attr('style') === '') {
350
              $(this)
351
                .attr('style', '')
352
                .removeAttr('style')
353
              ;
354
            }
355
          },
356
357
          opacity: function() {
358
            module.verbose('Removing inline opacity from element', this);
359
            $(this).css('opacity', '');
360
            if( $(this).attr('style') === '') {
361
              $(this)
362
                .attr('style', '')
363
                .removeAttr('style')
364
              ;
365
            }
366
          },
367
368
        },
369
370
        setting: function(name, value) {
371
          module.debug('Changing setting', name, value);
372
          if( $.isPlainObject(name) ) {
373
            $.extend(true, settings, name);
374
          }
375
          else if(value !== undefined) {
376
            if($.isPlainObject(settings[name])) {
377
              $.extend(true, settings[name], value);
378
            }
379
            else {
380
              settings[name] = value;
381
            }
382
          }
383
          else {
384
            return settings[name];
385
          }
386
        },
387
        internal: function(name, value) {
388
          module.debug('Changing internal', name, value);
389
          if(value !== undefined) {
390
            if( $.isPlainObject(name) ) {
391
              $.extend(true, module, name);
392
            }
393
            else {
394
              module[name] = value;
395
            }
396
          }
397
          else {
398
            return module[name];
399
          }
400
        },
401
        debug: function() {
402
          if(!settings.silent && settings.debug) {
403
            if(settings.performance) {
404
              module.performance.log(arguments);
405
            }
406
            else {
407
              module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
408
              module.debug.apply(console, arguments);
409
            }
410
          }
411
        },
412
        verbose: function() {
413
          if(!settings.silent && settings.verbose && settings.debug) {
414
            if(settings.performance) {
415
              module.performance.log(arguments);
416
            }
417
            else {
418
              module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
419
              module.verbose.apply(console, arguments);
420
            }
421
          }
422
        },
423
        error: function() {
424
          if(!settings.silent) {
425
            module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
426
            module.error.apply(console, arguments);
427
          }
428
        },
429
        performance: {
430
          log: function(message) {
431
            var
432
              currentTime,
433
              executionTime,
434
              previousTime
435
            ;
436
            if(settings.performance) {
437
              currentTime   = new Date().getTime();
438
              previousTime  = time || currentTime;
439
              executionTime = currentTime - previousTime;
440
              time          = currentTime;
441
              performance.push({
442
                'Name'           : message[0],
443
                'Arguments'      : [].slice.call(message, 1) || '',
444
                'Element'        : element,
445
                'Execution Time' : executionTime
446
              });
447
            }
448
            clearTimeout(module.performance.timer);
449
            module.performance.timer = setTimeout(module.performance.display, 500);
450
          },
451
          display: function() {
452
            var
453
              title = settings.name + ':',
454
              totalTime = 0
455
            ;
456
            time = false;
457
            clearTimeout(module.performance.timer);
458
            $.each(performance, function(index, data) {
459
              totalTime += data['Execution Time'];
460
            });
461
            title += ' ' + totalTime + 'ms';
462
            if(moduleSelector) {
463
              title += ' \'' + moduleSelector + '\'';
464
            }
465
            if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
466
              console.groupCollapsed(title);
467
              if(console.table) {
468
                console.table(performance);
469
              }
470
              else {
471
                $.each(performance, function(index, data) {
472
                  console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
473
                });
474
              }
475
              console.groupEnd();
476
            }
477
            performance = [];
478
          }
479
        },
480
        invoke: function(query, passedArguments, context) {
481
          var
482
            object = instance,
483
            maxDepth,
484
            found,
485
            response
486
          ;
487
          passedArguments = passedArguments || queryArguments;
488
          context         = element         || context;
489
          if(typeof query == 'string' && object !== undefined) {
490
            query    = query.split(/[\. ]/);
491
            maxDepth = query.length - 1;
492
            $.each(query, function(depth, value) {
493
              var camelCaseValue = (depth != maxDepth)
494
                ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
495
                : query
496
              ;
497
              if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
498
                object = object[camelCaseValue];
499
              }
500
              else if( object[camelCaseValue] !== undefined ) {
501
                found = object[camelCaseValue];
502
                return false;
503
              }
504
              else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
505
                object = object[value];
506
              }
507
              else if( object[value] !== undefined ) {
508
                found = object[value];
509
                return false;
510
              }
511
              else {
512
                module.error(error.method, query);
513
                return false;
514
              }
515
            });
516
          }
517
          if ( $.isFunction( found ) ) {
518
            response = found.apply(context, passedArguments);
519
          }
520
          else if(found !== undefined) {
521
            response = found;
522
          }
523
          if($.isArray(returnedValue)) {
524
            returnedValue.push(response);
525
          }
526
          else if(returnedValue !== undefined) {
527
            returnedValue = [returnedValue, response];
528
          }
529
          else if(response !== undefined) {
530
            returnedValue = response;
531
          }
532
          return found;
533
        }
534
      };
535
      if(methodInvoked) {
536
        if(instance === undefined) {
537
          module.initialize();
538
        }
539
        module.invoke(query);
540
      }
541
      else {
542
        if(instance !== undefined) {
543
          instance.invoke('destroy');
544
        }
545
        module.initialize();
546
      }
547
    })
548
  ;
549
  return (returnedValue !== undefined)
550
    ? returnedValue
551
    : this
552
  ;
553
};
554
555
$.fn.accordion.settings = {
556
557
  name            : 'Accordion',
558
  namespace       : 'accordion',
559
560
  silent          : false,
561
  debug           : false,
562
  verbose         : false,
563
  performance     : true,
564
565
  on              : 'click', // event on title that opens accordion
566
567
  observeChanges  : true,  // whether accordion should automatically refresh on DOM insertion
568
569
  exclusive       : true,  // whether a single accordion content panel should be open at once
570
  collapsible     : true,  // whether accordion content can be closed
571
  closeNested     : false, // whether nested content should be closed when a panel is closed
572
  animateChildren : true,  // whether children opacity should be animated
573
574
  duration        : 350, // duration of animation
575
  easing          : 'easeOutQuad', // easing equation for animation
576
577
578
  onOpening       : function(){}, // callback before open animation
579
  onOpen          : function(){}, // callback after open animation
580
  onClosing       : function(){}, // callback before closing animation
581
  onClose         : function(){}, // callback after closing animation
582
  onChange        : function(){}, // callback after closing or opening animation
583
584
  error: {
585
    method : 'The method you called is not defined'
586
  },
587
588
  className   : {
589
    active    : 'active',
590
    animating : 'animating'
591
  },
592
593
  selector    : {
594
    accordion : '.accordion',
595
    title     : '.title',
596
    trigger   : '.title',
597
    content   : '.content'
598
  }
599
600
};
601
602
// Adds easing
603
$.extend( $.easing, {
604
  easeOutQuad: function (x, t, b, c, d) {
605
    return -c *(t/=d)*(t-2) + b;
606
  }
607
});
608
609
})( jQuery, window, document );
610
611