github.com/fanux/shipyard@v0.0.0-20161009071005-6515ce223235/controller/static/semantic/dist/components/accordion.js (about)

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