github.com/fanux/shipyard@v0.0.0-20161009071005-6515ce223235/controller/static/semantic/src/definitions/modules/checkbox.js (about)

     1  /*!
     2   * # Semantic UI - Checkbox
     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.checkbox = function(parameters) {
    17    var
    18      $allModules    = $(this),
    19      moduleSelector = $allModules.selector || '',
    20  
    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        = $.extend(true, {}, $.fn.checkbox.settings, parameters),
    34  
    35          className       = settings.className,
    36          namespace       = settings.namespace,
    37          selector        = settings.selector,
    38          error           = settings.error,
    39  
    40          eventNamespace  = '.' + namespace,
    41          moduleNamespace = 'module-' + namespace,
    42  
    43          $module         = $(this),
    44          $label          = $(this).find(selector.label).first(),
    45          $input          = $(this).find(selector.input),
    46  
    47          instance        = $module.data(moduleNamespace),
    48  
    49          observer,
    50          element         = this,
    51          module
    52        ;
    53  
    54        module      = {
    55  
    56          initialize: function() {
    57            module.verbose('Initializing checkbox', settings);
    58  
    59            module.create.label();
    60            module.add.events();
    61  
    62            if( module.is.checked() ) {
    63              module.set.checked();
    64              if(settings.fireOnInit) {
    65                settings.onChecked.call($input.get());
    66              }
    67            }
    68            else {
    69              module.remove.checked();
    70              if(settings.fireOnInit) {
    71                settings.onUnchecked.call($input.get());
    72              }
    73            }
    74            module.observeChanges();
    75  
    76            module.instantiate();
    77          },
    78  
    79          instantiate: function() {
    80            module.verbose('Storing instance of module', module);
    81            instance = module;
    82            $module
    83              .data(moduleNamespace, module)
    84            ;
    85          },
    86  
    87          destroy: function() {
    88            module.verbose('Destroying module');
    89            module.remove.events();
    90            $module
    91              .removeData(moduleNamespace)
    92            ;
    93          },
    94  
    95          refresh: function() {
    96            $module = $(this);
    97            $label  = $(this).find(selector.label).first();
    98            $input  = $(this).find(selector.input);
    99          },
   100  
   101          observeChanges: function() {
   102            if('MutationObserver' in window) {
   103              observer = new MutationObserver(function(mutations) {
   104                module.debug('DOM tree modified, updating selector cache');
   105                module.refresh();
   106              });
   107              observer.observe(element, {
   108                childList : true,
   109                subtree   : true
   110              });
   111              module.debug('Setting up mutation observer', observer);
   112            }
   113          },
   114  
   115          attachEvents: function(selector, event) {
   116            var
   117              $element = $(selector)
   118            ;
   119            event = $.isFunction(module[event])
   120              ? module[event]
   121              : module.toggle
   122            ;
   123            if($element.length > 0) {
   124              module.debug('Attaching checkbox events to element', selector, event);
   125              $element
   126                .on('click' + eventNamespace, event)
   127              ;
   128            }
   129            else {
   130              module.error(error.notFound);
   131            }
   132          },
   133  
   134          event: {
   135            keydown: function(event) {
   136              var
   137                key     = event.which,
   138                keyCode = {
   139                  enter  : 13,
   140                  space  : 32,
   141                  escape : 27
   142                }
   143              ;
   144              if( key == keyCode.escape) {
   145                module.verbose('Escape key pressed blurring field');
   146                $module
   147                  .blur()
   148                ;
   149              }
   150              if(!event.ctrlKey && (key == keyCode.enter || key == keyCode.space)) {
   151                module.verbose('Enter key pressed, toggling checkbox');
   152                module.toggle.call(this);
   153                event.preventDefault();
   154              }
   155            }
   156          },
   157  
   158          is: {
   159            radio: function() {
   160              return $module.hasClass(className.radio);
   161            },
   162            checked: function() {
   163              return $input.prop('checked') !== undefined && $input.prop('checked');
   164            },
   165            unchecked: function() {
   166              return !module.is.checked();
   167            }
   168          },
   169  
   170          can: {
   171            change: function() {
   172              return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') );
   173            },
   174            uncheck: function() {
   175              return (typeof settings.uncheckable === 'boolean')
   176                ? settings.uncheckable
   177                : !module.is.radio()
   178              ;
   179            }
   180          },
   181  
   182          set: {
   183            checked: function() {
   184              $module.addClass(className.checked);
   185            },
   186            tab: function() {
   187              if( $input.attr('tabindex') === undefined) {
   188                $input
   189                  .attr('tabindex', 0)
   190                ;
   191              }
   192            }
   193          },
   194  
   195          create: {
   196            label: function() {
   197              if($input.prevAll(selector.label).length > 0) {
   198                $input.prev(selector.label).detach().insertAfter($input);
   199                module.debug('Moving existing label', $label);
   200              }
   201              else if( !module.has.label() ) {
   202                $label = $('<label>').insertAfter($input);
   203                module.debug('Creating label', $label);
   204              }
   205            }
   206          },
   207  
   208          has: {
   209            label: function() {
   210              return ($label.length > 0);
   211            }
   212          },
   213  
   214          add: {
   215            events: function() {
   216              module.verbose('Attaching checkbox events');
   217              $module
   218                .on('click'   + eventNamespace, module.toggle)
   219                .on('keydown' + eventNamespace, selector.input, module.event.keydown)
   220              ;
   221            }
   222          },
   223  
   224          remove: {
   225            checked: function() {
   226              $module.removeClass(className.checked);
   227            },
   228            events: function() {
   229              module.debug('Removing events');
   230              $module
   231                .off(eventNamespace)
   232                .removeData(moduleNamespace)
   233              ;
   234              $input
   235                .off(eventNamespace, module.event.keydown)
   236              ;
   237              $label
   238                .off(eventNamespace)
   239              ;
   240            }
   241          },
   242  
   243          enable: function() {
   244            module.debug('Enabling checkbox functionality');
   245            $module.removeClass(className.disabled);
   246            $input.prop('disabled', false);
   247            settings.onEnabled.call($input.get());
   248          },
   249  
   250          disable: function() {
   251            module.debug('Disabling checkbox functionality');
   252            $module.addClass(className.disabled);
   253            $input.prop('disabled', 'disabled');
   254            settings.onDisabled.call($input.get());
   255          },
   256  
   257          check: function() {
   258            module.debug('Enabling checkbox', $input);
   259            $input
   260              .prop('checked', true)
   261              .trigger('change')
   262            ;
   263            module.set.checked();
   264            $input.trigger('blur');
   265            settings.onChange.call($input.get());
   266            settings.onChecked.call($input.get());
   267          },
   268  
   269          uncheck: function() {
   270            module.debug('Disabling checkbox');
   271            $input
   272              .prop('checked', false)
   273              .trigger('change')
   274            ;
   275            module.remove.checked();
   276            $input.trigger('blur');
   277            settings.onChange.call($input.get());
   278            settings.onUnchecked.call($input.get());
   279          },
   280  
   281          toggle: function(event) {
   282            if( !module.can.change() ) {
   283              console.log(module.can.change());
   284              module.debug('Checkbox is read-only or disabled, ignoring toggle');
   285              return;
   286            }
   287            module.verbose('Determining new checkbox state');
   288            if( module.is.unchecked() ) {
   289              module.check();
   290            }
   291            else if( module.is.checked() && module.can.uncheck() ) {
   292              module.uncheck();
   293            }
   294          },
   295          setting: function(name, value) {
   296            module.debug('Changing setting', name, value);
   297            if( $.isPlainObject(name) ) {
   298              $.extend(true, settings, name);
   299            }
   300            else if(value !== undefined) {
   301              settings[name] = value;
   302            }
   303            else {
   304              return settings[name];
   305            }
   306          },
   307          internal: function(name, value) {
   308            if( $.isPlainObject(name) ) {
   309              $.extend(true, module, name);
   310            }
   311            else if(value !== undefined) {
   312              module[name] = value;
   313            }
   314            else {
   315              return module[name];
   316            }
   317          },
   318          debug: function() {
   319            if(settings.debug) {
   320              if(settings.performance) {
   321                module.performance.log(arguments);
   322              }
   323              else {
   324                module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
   325                module.debug.apply(console, arguments);
   326              }
   327            }
   328          },
   329          verbose: function() {
   330            if(settings.verbose && settings.debug) {
   331              if(settings.performance) {
   332                module.performance.log(arguments);
   333              }
   334              else {
   335                module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
   336                module.verbose.apply(console, arguments);
   337              }
   338            }
   339          },
   340          error: function() {
   341            module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
   342            module.error.apply(console, arguments);
   343          },
   344          performance: {
   345            log: function(message) {
   346              var
   347                currentTime,
   348                executionTime,
   349                previousTime
   350              ;
   351              if(settings.performance) {
   352                currentTime   = new Date().getTime();
   353                previousTime  = time || currentTime;
   354                executionTime = currentTime - previousTime;
   355                time          = currentTime;
   356                performance.push({
   357                  'Name'           : message[0],
   358                  'Arguments'      : [].slice.call(message, 1) || '',
   359                  'Element'        : element,
   360                  'Execution Time' : executionTime
   361                });
   362              }
   363              clearTimeout(module.performance.timer);
   364              module.performance.timer = setTimeout(module.performance.display, 100);
   365            },
   366            display: function() {
   367              var
   368                title = settings.name + ':',
   369                totalTime = 0
   370              ;
   371              time = false;
   372              clearTimeout(module.performance.timer);
   373              $.each(performance, function(index, data) {
   374                totalTime += data['Execution Time'];
   375              });
   376              title += ' ' + totalTime + 'ms';
   377              if(moduleSelector) {
   378                title += ' \'' + moduleSelector + '\'';
   379              }
   380              if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
   381                console.groupCollapsed(title);
   382                if(console.table) {
   383                  console.table(performance);
   384                }
   385                else {
   386                  $.each(performance, function(index, data) {
   387                    console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
   388                  });
   389                }
   390                console.groupEnd();
   391              }
   392              performance = [];
   393            }
   394          },
   395          invoke: function(query, passedArguments, context) {
   396            var
   397              object = instance,
   398              maxDepth,
   399              found,
   400              response
   401            ;
   402            passedArguments = passedArguments || queryArguments;
   403            context         = element         || context;
   404            if(typeof query == 'string' && object !== undefined) {
   405              query    = query.split(/[\. ]/);
   406              maxDepth = query.length - 1;
   407              $.each(query, function(depth, value) {
   408                var camelCaseValue = (depth != maxDepth)
   409                  ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
   410                  : query
   411                ;
   412                if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
   413                  object = object[camelCaseValue];
   414                }
   415                else if( object[camelCaseValue] !== undefined ) {
   416                  found = object[camelCaseValue];
   417                  return false;
   418                }
   419                else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
   420                  object = object[value];
   421                }
   422                else if( object[value] !== undefined ) {
   423                  found = object[value];
   424                  return false;
   425                }
   426                else {
   427                  module.error(error.method, query);
   428                  return false;
   429                }
   430              });
   431            }
   432            if ( $.isFunction( found ) ) {
   433              response = found.apply(context, passedArguments);
   434            }
   435            else if(found !== undefined) {
   436              response = found;
   437            }
   438            if($.isArray(returnedValue)) {
   439              returnedValue.push(response);
   440            }
   441            else if(returnedValue !== undefined) {
   442              returnedValue = [returnedValue, response];
   443            }
   444            else if(response !== undefined) {
   445              returnedValue = response;
   446            }
   447            return found;
   448          }
   449        };
   450  
   451        if(methodInvoked) {
   452          if(instance === undefined) {
   453            module.initialize();
   454          }
   455          module.invoke(query);
   456        }
   457        else {
   458          if(instance !== undefined) {
   459            instance.invoke('destroy');
   460          }
   461          module.initialize();
   462        }
   463      })
   464    ;
   465  
   466    return (returnedValue !== undefined)
   467      ? returnedValue
   468      : this
   469    ;
   470  };
   471  
   472  $.fn.checkbox.settings = {
   473  
   474    name        : 'Checkbox',
   475    namespace   : 'checkbox',
   476  
   477    debug       : false,
   478    verbose     : true,
   479    performance : true,
   480  
   481    // delegated event context
   482    uncheckable : 'auto',
   483    fireOnInit  : true,
   484  
   485    onChange    : function(){},
   486    onChecked   : function(){},
   487    onUnchecked : function(){},
   488    onEnabled   : function(){},
   489    onDisabled  : function(){},
   490  
   491    className   : {
   492      checked  : 'checked',
   493      disabled : 'disabled',
   494      radio    : 'radio',
   495      readOnly : 'read-only'
   496    },
   497  
   498    error     : {
   499      method   : 'The method you called is not defined'
   500    },
   501  
   502    selector : {
   503      input  : 'input[type="checkbox"], input[type="radio"]',
   504      label  : 'label'
   505    }
   506  
   507  };
   508  
   509  })( jQuery, window , document );