Code Duplication    Length = 821-821 lines in 2 locations

public/lib/semantic/semantic.js 1 location

@@ 2827-3647 (lines=821) @@
2824
 *
2825
 */
2826
2827
;(function ($, window, document, undefined) {
2828
2829
"use strict";
2830
2831
window = (typeof window != 'undefined' && window.Math == Math)
2832
  ? window
2833
  : (typeof self != 'undefined' && self.Math == Math)
2834
    ? self
2835
    : Function('return this')()
2836
;
2837
2838
$.fn.checkbox = function(parameters) {
2839
  var
2840
    $allModules    = $(this),
2841
    moduleSelector = $allModules.selector || '',
2842
2843
    time           = new Date().getTime(),
2844
    performance    = [],
2845
2846
    query          = arguments[0],
2847
    methodInvoked  = (typeof query == 'string'),
2848
    queryArguments = [].slice.call(arguments, 1),
2849
    returnedValue
2850
  ;
2851
2852
  $allModules
2853
    .each(function() {
2854
      var
2855
        settings        = $.extend(true, {}, $.fn.checkbox.settings, parameters),
2856
2857
        className       = settings.className,
2858
        namespace       = settings.namespace,
2859
        selector        = settings.selector,
2860
        error           = settings.error,
2861
2862
        eventNamespace  = '.' + namespace,
2863
        moduleNamespace = 'module-' + namespace,
2864
2865
        $module         = $(this),
2866
        $label          = $(this).children(selector.label),
2867
        $input          = $(this).children(selector.input),
2868
        input           = $input[0],
2869
2870
        initialLoad     = false,
2871
        shortcutPressed = false,
2872
        instance        = $module.data(moduleNamespace),
2873
2874
        observer,
2875
        element         = this,
2876
        module
2877
      ;
2878
2879
      module      = {
2880
2881
        initialize: function() {
2882
          module.verbose('Initializing checkbox', settings);
2883
2884
          module.create.label();
2885
          module.bind.events();
2886
2887
          module.set.tabbable();
2888
          module.hide.input();
2889
2890
          module.observeChanges();
2891
          module.instantiate();
2892
          module.setup();
2893
        },
2894
2895
        instantiate: function() {
2896
          module.verbose('Storing instance of module', module);
2897
          instance = module;
2898
          $module
2899
            .data(moduleNamespace, module)
2900
          ;
2901
        },
2902
2903
        destroy: function() {
2904
          module.verbose('Destroying module');
2905
          module.unbind.events();
2906
          module.show.input();
2907
          $module.removeData(moduleNamespace);
2908
        },
2909
2910
        fix: {
2911
          reference: function() {
2912
            if( $module.is(selector.input) ) {
2913
              module.debug('Behavior called on <input> adjusting invoked element');
2914
              $module = $module.closest(selector.checkbox);
2915
              module.refresh();
2916
            }
2917
          }
2918
        },
2919
2920
        setup: function() {
2921
          module.set.initialLoad();
2922
          if( module.is.indeterminate() ) {
2923
            module.debug('Initial value is indeterminate');
2924
            module.indeterminate();
2925
          }
2926
          else if( module.is.checked() ) {
2927
            module.debug('Initial value is checked');
2928
            module.check();
2929
          }
2930
          else {
2931
            module.debug('Initial value is unchecked');
2932
            module.uncheck();
2933
          }
2934
          module.remove.initialLoad();
2935
        },
2936
2937
        refresh: function() {
2938
          $label = $module.children(selector.label);
2939
          $input = $module.children(selector.input);
2940
          input  = $input[0];
2941
        },
2942
2943
        hide: {
2944
          input: function() {
2945
            module.verbose('Modifying <input> z-index to be unselectable');
2946
            $input.addClass(className.hidden);
2947
          }
2948
        },
2949
        show: {
2950
          input: function() {
2951
            module.verbose('Modifying <input> z-index to be selectable');
2952
            $input.removeClass(className.hidden);
2953
          }
2954
        },
2955
2956
        observeChanges: function() {
2957
          if('MutationObserver' in window) {
2958
            observer = new MutationObserver(function(mutations) {
2959
              module.debug('DOM tree modified, updating selector cache');
2960
              module.refresh();
2961
            });
2962
            observer.observe(element, {
2963
              childList : true,
2964
              subtree   : true
2965
            });
2966
            module.debug('Setting up mutation observer', observer);
2967
          }
2968
        },
2969
2970
        attachEvents: function(selector, event) {
2971
          var
2972
            $element = $(selector)
2973
          ;
2974
          event = $.isFunction(module[event])
2975
            ? module[event]
2976
            : module.toggle
2977
          ;
2978
          if($element.length > 0) {
2979
            module.debug('Attaching checkbox events to element', selector, event);
2980
            $element
2981
              .on('click' + eventNamespace, event)
2982
            ;
2983
          }
2984
          else {
2985
            module.error(error.notFound);
2986
          }
2987
        },
2988
2989
        event: {
2990
          click: function(event) {
2991
            var
2992
              $target = $(event.target)
2993
            ;
2994
            if( $target.is(selector.input) ) {
2995
              module.verbose('Using default check action on initialized checkbox');
2996
              return;
2997
            }
2998
            if( $target.is(selector.link) ) {
2999
              module.debug('Clicking link inside checkbox, skipping toggle');
3000
              return;
3001
            }
3002
            module.toggle();
3003
            $input.focus();
3004
            event.preventDefault();
3005
          },
3006
          keydown: function(event) {
3007
            var
3008
              key     = event.which,
3009
              keyCode = {
3010
                enter  : 13,
3011
                space  : 32,
3012
                escape : 27
3013
              }
3014
            ;
3015
            if(key == keyCode.escape) {
3016
              module.verbose('Escape key pressed blurring field');
3017
              $input.blur();
3018
              shortcutPressed = true;
3019
            }
3020
            else if(!event.ctrlKey && ( key == keyCode.space || key == keyCode.enter) ) {
3021
              module.verbose('Enter/space key pressed, toggling checkbox');
3022
              module.toggle();
3023
              shortcutPressed = true;
3024
            }
3025
            else {
3026
              shortcutPressed = false;
3027
            }
3028
          },
3029
          keyup: function(event) {
3030
            if(shortcutPressed) {
3031
              event.preventDefault();
3032
            }
3033
          }
3034
        },
3035
3036
        check: function() {
3037
          if( !module.should.allowCheck() ) {
3038
            return;
3039
          }
3040
          module.debug('Checking checkbox', $input);
3041
          module.set.checked();
3042
          if( !module.should.ignoreCallbacks() ) {
3043
            settings.onChecked.call(input);
3044
            settings.onChange.call(input);
3045
          }
3046
        },
3047
3048
        uncheck: function() {
3049
          if( !module.should.allowUncheck() ) {
3050
            return;
3051
          }
3052
          module.debug('Unchecking checkbox');
3053
          module.set.unchecked();
3054
          if( !module.should.ignoreCallbacks() ) {
3055
            settings.onUnchecked.call(input);
3056
            settings.onChange.call(input);
3057
          }
3058
        },
3059
3060
        indeterminate: function() {
3061
          if( module.should.allowIndeterminate() ) {
3062
            module.debug('Checkbox is already indeterminate');
3063
            return;
3064
          }
3065
          module.debug('Making checkbox indeterminate');
3066
          module.set.indeterminate();
3067
          if( !module.should.ignoreCallbacks() ) {
3068
            settings.onIndeterminate.call(input);
3069
            settings.onChange.call(input);
3070
          }
3071
        },
3072
3073
        determinate: function() {
3074
          if( module.should.allowDeterminate() ) {
3075
            module.debug('Checkbox is already determinate');
3076
            return;
3077
          }
3078
          module.debug('Making checkbox determinate');
3079
          module.set.determinate();
3080
          if( !module.should.ignoreCallbacks() ) {
3081
            settings.onDeterminate.call(input);
3082
            settings.onChange.call(input);
3083
          }
3084
        },
3085
3086
        enable: function() {
3087
          if( module.is.enabled() ) {
3088
            module.debug('Checkbox is already enabled');
3089
            return;
3090
          }
3091
          module.debug('Enabling checkbox');
3092
          module.set.enabled();
3093
          settings.onEnable.call(input);
3094
          // preserve legacy callbacks
3095
          settings.onEnabled.call(input);
3096
        },
3097
3098
        disable: function() {
3099
          if( module.is.disabled() ) {
3100
            module.debug('Checkbox is already disabled');
3101
            return;
3102
          }
3103
          module.debug('Disabling checkbox');
3104
          module.set.disabled();
3105
          settings.onDisable.call(input);
3106
          // preserve legacy callbacks
3107
          settings.onDisabled.call(input);
3108
        },
3109
3110
        get: {
3111
          radios: function() {
3112
            var
3113
              name = module.get.name()
3114
            ;
3115
            return $('input[name="' + name + '"]').closest(selector.checkbox);
3116
          },
3117
          otherRadios: function() {
3118
            return module.get.radios().not($module);
3119
          },
3120
          name: function() {
3121
            return $input.attr('name');
3122
          }
3123
        },
3124
3125
        is: {
3126
          initialLoad: function() {
3127
            return initialLoad;
3128
          },
3129
          radio: function() {
3130
            return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
3131
          },
3132
          indeterminate: function() {
3133
            return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
3134
          },
3135
          checked: function() {
3136
            return $input.prop('checked') !== undefined && $input.prop('checked');
3137
          },
3138
          disabled: function() {
3139
            return $input.prop('disabled') !== undefined && $input.prop('disabled');
3140
          },
3141
          enabled: function() {
3142
            return !module.is.disabled();
3143
          },
3144
          determinate: function() {
3145
            return !module.is.indeterminate();
3146
          },
3147
          unchecked: function() {
3148
            return !module.is.checked();
3149
          }
3150
        },
3151
3152
        should: {
3153
          allowCheck: function() {
3154
            if(module.is.determinate() && module.is.checked() && !module.should.forceCallbacks() ) {
3155
              module.debug('Should not allow check, checkbox is already checked');
3156
              return false;
3157
            }
3158
            if(settings.beforeChecked.apply(input) === false) {
3159
              module.debug('Should not allow check, beforeChecked cancelled');
3160
              return false;
3161
            }
3162
            return true;
3163
          },
3164
          allowUncheck: function() {
3165
            if(module.is.determinate() && module.is.unchecked() && !module.should.forceCallbacks() ) {
3166
              module.debug('Should not allow uncheck, checkbox is already unchecked');
3167
              return false;
3168
            }
3169
            if(settings.beforeUnchecked.apply(input) === false) {
3170
              module.debug('Should not allow uncheck, beforeUnchecked cancelled');
3171
              return false;
3172
            }
3173
            return true;
3174
          },
3175
          allowIndeterminate: function() {
3176
            if(module.is.indeterminate() && !module.should.forceCallbacks() ) {
3177
              module.debug('Should not allow indeterminate, checkbox is already indeterminate');
3178
              return false;
3179
            }
3180
            if(settings.beforeIndeterminate.apply(input) === false) {
3181
              module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
3182
              return false;
3183
            }
3184
            return true;
3185
          },
3186
          allowDeterminate: function() {
3187
            if(module.is.determinate() && !module.should.forceCallbacks() ) {
3188
              module.debug('Should not allow determinate, checkbox is already determinate');
3189
              return false;
3190
            }
3191
            if(settings.beforeDeterminate.apply(input) === false) {
3192
              module.debug('Should not allow determinate, beforeDeterminate cancelled');
3193
              return false;
3194
            }
3195
            return true;
3196
          },
3197
          forceCallbacks: function() {
3198
            return (module.is.initialLoad() && settings.fireOnInit);
3199
          },
3200
          ignoreCallbacks: function() {
3201
            return (initialLoad && !settings.fireOnInit);
3202
          }
3203
        },
3204
3205
        can: {
3206
          change: function() {
3207
            return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
3208
          },
3209
          uncheck: function() {
3210
            return (typeof settings.uncheckable === 'boolean')
3211
              ? settings.uncheckable
3212
              : !module.is.radio()
3213
            ;
3214
          }
3215
        },
3216
3217
        set: {
3218
          initialLoad: function() {
3219
            initialLoad = true;
3220
          },
3221
          checked: function() {
3222
            module.verbose('Setting class to checked');
3223
            $module
3224
              .removeClass(className.indeterminate)
3225
              .addClass(className.checked)
3226
            ;
3227
            if( module.is.radio() ) {
3228
              module.uncheckOthers();
3229
            }
3230
            if(!module.is.indeterminate() && module.is.checked()) {
3231
              module.debug('Input is already checked, skipping input property change');
3232
              return;
3233
            }
3234
            module.verbose('Setting state to checked', input);
3235
            $input
3236
              .prop('indeterminate', false)
3237
              .prop('checked', true)
3238
            ;
3239
            module.trigger.change();
3240
          },
3241
          unchecked: function() {
3242
            module.verbose('Removing checked class');
3243
            $module
3244
              .removeClass(className.indeterminate)
3245
              .removeClass(className.checked)
3246
            ;
3247
            if(!module.is.indeterminate() &&  module.is.unchecked() ) {
3248
              module.debug('Input is already unchecked');
3249
              return;
3250
            }
3251
            module.debug('Setting state to unchecked');
3252
            $input
3253
              .prop('indeterminate', false)
3254
              .prop('checked', false)
3255
            ;
3256
            module.trigger.change();
3257
          },
3258
          indeterminate: function() {
3259
            module.verbose('Setting class to indeterminate');
3260
            $module
3261
              .addClass(className.indeterminate)
3262
            ;
3263
            if( module.is.indeterminate() ) {
3264
              module.debug('Input is already indeterminate, skipping input property change');
3265
              return;
3266
            }
3267
            module.debug('Setting state to indeterminate');
3268
            $input
3269
              .prop('indeterminate', true)
3270
            ;
3271
            module.trigger.change();
3272
          },
3273
          determinate: function() {
3274
            module.verbose('Removing indeterminate class');
3275
            $module
3276
              .removeClass(className.indeterminate)
3277
            ;
3278
            if( module.is.determinate() ) {
3279
              module.debug('Input is already determinate, skipping input property change');
3280
              return;
3281
            }
3282
            module.debug('Setting state to determinate');
3283
            $input
3284
              .prop('indeterminate', false)
3285
            ;
3286
          },
3287
          disabled: function() {
3288
            module.verbose('Setting class to disabled');
3289
            $module
3290
              .addClass(className.disabled)
3291
            ;
3292
            if( module.is.disabled() ) {
3293
              module.debug('Input is already disabled, skipping input property change');
3294
              return;
3295
            }
3296
            module.debug('Setting state to disabled');
3297
            $input
3298
              .prop('disabled', 'disabled')
3299
            ;
3300
            module.trigger.change();
3301
          },
3302
          enabled: function() {
3303
            module.verbose('Removing disabled class');
3304
            $module.removeClass(className.disabled);
3305
            if( module.is.enabled() ) {
3306
              module.debug('Input is already enabled, skipping input property change');
3307
              return;
3308
            }
3309
            module.debug('Setting state to enabled');
3310
            $input
3311
              .prop('disabled', false)
3312
            ;
3313
            module.trigger.change();
3314
          },
3315
          tabbable: function() {
3316
            module.verbose('Adding tabindex to checkbox');
3317
            if( $input.attr('tabindex') === undefined) {
3318
              $input.attr('tabindex', 0);
3319
            }
3320
          }
3321
        },
3322
3323
        remove: {
3324
          initialLoad: function() {
3325
            initialLoad = false;
3326
          }
3327
        },
3328
3329
        trigger: {
3330
          change: function() {
3331
            var
3332
              events       = document.createEvent('HTMLEvents'),
3333
              inputElement = $input[0]
3334
            ;
3335
            if(inputElement) {
3336
              module.verbose('Triggering native change event');
3337
              events.initEvent('change', true, false);
3338
              inputElement.dispatchEvent(events);
3339
            }
3340
          }
3341
        },
3342
3343
3344
        create: {
3345
          label: function() {
3346
            if($input.prevAll(selector.label).length > 0) {
3347
              $input.prev(selector.label).detach().insertAfter($input);
3348
              module.debug('Moving existing label', $label);
3349
            }
3350
            else if( !module.has.label() ) {
3351
              $label = $('<label>').insertAfter($input);
3352
              module.debug('Creating label', $label);
3353
            }
3354
          }
3355
        },
3356
3357
        has: {
3358
          label: function() {
3359
            return ($label.length > 0);
3360
          }
3361
        },
3362
3363
        bind: {
3364
          events: function() {
3365
            module.verbose('Attaching checkbox events');
3366
            $module
3367
              .on('click'   + eventNamespace, module.event.click)
3368
              .on('keydown' + eventNamespace, selector.input, module.event.keydown)
3369
              .on('keyup'   + eventNamespace, selector.input, module.event.keyup)
3370
            ;
3371
          }
3372
        },
3373
3374
        unbind: {
3375
          events: function() {
3376
            module.debug('Removing events');
3377
            $module
3378
              .off(eventNamespace)
3379
            ;
3380
          }
3381
        },
3382
3383
        uncheckOthers: function() {
3384
          var
3385
            $radios = module.get.otherRadios()
3386
          ;
3387
          module.debug('Unchecking other radios', $radios);
3388
          $radios.removeClass(className.checked);
3389
        },
3390
3391
        toggle: function() {
3392
          if( !module.can.change() ) {
3393
            if(!module.is.radio()) {
3394
              module.debug('Checkbox is read-only or disabled, ignoring toggle');
3395
            }
3396
            return;
3397
          }
3398
          if( module.is.indeterminate() || module.is.unchecked() ) {
3399
            module.debug('Currently unchecked');
3400
            module.check();
3401
          }
3402
          else if( module.is.checked() && module.can.uncheck() ) {
3403
            module.debug('Currently checked');
3404
            module.uncheck();
3405
          }
3406
        },
3407
        setting: function(name, value) {
3408
          module.debug('Changing setting', name, value);
3409
          if( $.isPlainObject(name) ) {
3410
            $.extend(true, settings, name);
3411
          }
3412
          else if(value !== undefined) {
3413
            if($.isPlainObject(settings[name])) {
3414
              $.extend(true, settings[name], value);
3415
            }
3416
            else {
3417
              settings[name] = value;
3418
            }
3419
          }
3420
          else {
3421
            return settings[name];
3422
          }
3423
        },
3424
        internal: function(name, value) {
3425
          if( $.isPlainObject(name) ) {
3426
            $.extend(true, module, name);
3427
          }
3428
          else if(value !== undefined) {
3429
            module[name] = value;
3430
          }
3431
          else {
3432
            return module[name];
3433
          }
3434
        },
3435
        debug: function() {
3436
          if(!settings.silent && settings.debug) {
3437
            if(settings.performance) {
3438
              module.performance.log(arguments);
3439
            }
3440
            else {
3441
              module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
3442
              module.debug.apply(console, arguments);
3443
            }
3444
          }
3445
        },
3446
        verbose: function() {
3447
          if(!settings.silent && settings.verbose && settings.debug) {
3448
            if(settings.performance) {
3449
              module.performance.log(arguments);
3450
            }
3451
            else {
3452
              module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
3453
              module.verbose.apply(console, arguments);
3454
            }
3455
          }
3456
        },
3457
        error: function() {
3458
          if(!settings.silent) {
3459
            module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
3460
            module.error.apply(console, arguments);
3461
          }
3462
        },
3463
        performance: {
3464
          log: function(message) {
3465
            var
3466
              currentTime,
3467
              executionTime,
3468
              previousTime
3469
            ;
3470
            if(settings.performance) {
3471
              currentTime   = new Date().getTime();
3472
              previousTime  = time || currentTime;
3473
              executionTime = currentTime - previousTime;
3474
              time          = currentTime;
3475
              performance.push({
3476
                'Name'           : message[0],
3477
                'Arguments'      : [].slice.call(message, 1) || '',
3478
                'Element'        : element,
3479
                'Execution Time' : executionTime
3480
              });
3481
            }
3482
            clearTimeout(module.performance.timer);
3483
            module.performance.timer = setTimeout(module.performance.display, 500);
3484
          },
3485
          display: function() {
3486
            var
3487
              title = settings.name + ':',
3488
              totalTime = 0
3489
            ;
3490
            time = false;
3491
            clearTimeout(module.performance.timer);
3492
            $.each(performance, function(index, data) {
3493
              totalTime += data['Execution Time'];
3494
            });
3495
            title += ' ' + totalTime + 'ms';
3496
            if(moduleSelector) {
3497
              title += ' \'' + moduleSelector + '\'';
3498
            }
3499
            if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
3500
              console.groupCollapsed(title);
3501
              if(console.table) {
3502
                console.table(performance);
3503
              }
3504
              else {
3505
                $.each(performance, function(index, data) {
3506
                  console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
3507
                });
3508
              }
3509
              console.groupEnd();
3510
            }
3511
            performance = [];
3512
          }
3513
        },
3514
        invoke: function(query, passedArguments, context) {
3515
          var
3516
            object = instance,
3517
            maxDepth,
3518
            found,
3519
            response
3520
          ;
3521
          passedArguments = passedArguments || queryArguments;
3522
          context         = element         || context;
3523
          if(typeof query == 'string' && object !== undefined) {
3524
            query    = query.split(/[\. ]/);
3525
            maxDepth = query.length - 1;
3526
            $.each(query, function(depth, value) {
3527
              var camelCaseValue = (depth != maxDepth)
3528
                ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
3529
                : query
3530
              ;
3531
              if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
3532
                object = object[camelCaseValue];
3533
              }
3534
              else if( object[camelCaseValue] !== undefined ) {
3535
                found = object[camelCaseValue];
3536
                return false;
3537
              }
3538
              else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
3539
                object = object[value];
3540
              }
3541
              else if( object[value] !== undefined ) {
3542
                found = object[value];
3543
                return false;
3544
              }
3545
              else {
3546
                module.error(error.method, query);
3547
                return false;
3548
              }
3549
            });
3550
          }
3551
          if ( $.isFunction( found ) ) {
3552
            response = found.apply(context, passedArguments);
3553
          }
3554
          else if(found !== undefined) {
3555
            response = found;
3556
          }
3557
          if($.isArray(returnedValue)) {
3558
            returnedValue.push(response);
3559
          }
3560
          else if(returnedValue !== undefined) {
3561
            returnedValue = [returnedValue, response];
3562
          }
3563
          else if(response !== undefined) {
3564
            returnedValue = response;
3565
          }
3566
          return found;
3567
        }
3568
      };
3569
3570
      if(methodInvoked) {
3571
        if(instance === undefined) {
3572
          module.initialize();
3573
        }
3574
        module.invoke(query);
3575
      }
3576
      else {
3577
        if(instance !== undefined) {
3578
          instance.invoke('destroy');
3579
        }
3580
        module.initialize();
3581
      }
3582
    })
3583
  ;
3584
3585
  return (returnedValue !== undefined)
3586
    ? returnedValue
3587
    : this
3588
  ;
3589
};
3590
3591
$.fn.checkbox.settings = {
3592
3593
  name                : 'Checkbox',
3594
  namespace           : 'checkbox',
3595
3596
  silent              : false,
3597
  debug               : false,
3598
  verbose             : true,
3599
  performance         : true,
3600
3601
  // delegated event context
3602
  uncheckable         : 'auto',
3603
  fireOnInit          : false,
3604
3605
  onChange            : function(){},
3606
3607
  beforeChecked       : function(){},
3608
  beforeUnchecked     : function(){},
3609
  beforeDeterminate   : function(){},
3610
  beforeIndeterminate : function(){},
3611
3612
  onChecked           : function(){},
3613
  onUnchecked         : function(){},
3614
3615
  onDeterminate       : function() {},
3616
  onIndeterminate     : function() {},
3617
3618
  onEnable            : function(){},
3619
  onDisable           : function(){},
3620
3621
  // preserve misspelled callbacks (will be removed in 3.0)
3622
  onEnabled           : function(){},
3623
  onDisabled          : function(){},
3624
3625
  className       : {
3626
    checked       : 'checked',
3627
    indeterminate : 'indeterminate',
3628
    disabled      : 'disabled',
3629
    hidden        : 'hidden',
3630
    radio         : 'radio',
3631
    readOnly      : 'read-only'
3632
  },
3633
3634
  error     : {
3635
    method       : 'The method you called is not defined'
3636
  },
3637
3638
  selector : {
3639
    checkbox : '.ui.checkbox',
3640
    label    : 'label, .box',
3641
    input    : 'input[type="checkbox"], input[type="radio"]',
3642
    link     : 'a[href]'
3643
  }
3644
3645
};
3646
3647
})( jQuery, window, document );
3648
3649
/*!
3650
 * # Semantic UI 2.2.11 - Dimmer

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

@@ 11-831 (lines=821) @@
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.checkbox = function(parameters) {
23
  var
24
    $allModules    = $(this),
25
    moduleSelector = $allModules.selector || '',
26
27
    time           = new Date().getTime(),
28
    performance    = [],
29
30
    query          = arguments[0],
31
    methodInvoked  = (typeof query == 'string'),
32
    queryArguments = [].slice.call(arguments, 1),
33
    returnedValue
34
  ;
35
36
  $allModules
37
    .each(function() {
38
      var
39
        settings        = $.extend(true, {}, $.fn.checkbox.settings, parameters),
40
41
        className       = settings.className,
42
        namespace       = settings.namespace,
43
        selector        = settings.selector,
44
        error           = settings.error,
45
46
        eventNamespace  = '.' + namespace,
47
        moduleNamespace = 'module-' + namespace,
48
49
        $module         = $(this),
50
        $label          = $(this).children(selector.label),
51
        $input          = $(this).children(selector.input),
52
        input           = $input[0],
53
54
        initialLoad     = false,
55
        shortcutPressed = false,
56
        instance        = $module.data(moduleNamespace),
57
58
        observer,
59
        element         = this,
60
        module
61
      ;
62
63
      module      = {
64
65
        initialize: function() {
66
          module.verbose('Initializing checkbox', settings);
67
68
          module.create.label();
69
          module.bind.events();
70
71
          module.set.tabbable();
72
          module.hide.input();
73
74
          module.observeChanges();
75
          module.instantiate();
76
          module.setup();
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.unbind.events();
90
          module.show.input();
91
          $module.removeData(moduleNamespace);
92
        },
93
94
        fix: {
95
          reference: function() {
96
            if( $module.is(selector.input) ) {
97
              module.debug('Behavior called on <input> adjusting invoked element');
98
              $module = $module.closest(selector.checkbox);
99
              module.refresh();
100
            }
101
          }
102
        },
103
104
        setup: function() {
105
          module.set.initialLoad();
106
          if( module.is.indeterminate() ) {
107
            module.debug('Initial value is indeterminate');
108
            module.indeterminate();
109
          }
110
          else if( module.is.checked() ) {
111
            module.debug('Initial value is checked');
112
            module.check();
113
          }
114
          else {
115
            module.debug('Initial value is unchecked');
116
            module.uncheck();
117
          }
118
          module.remove.initialLoad();
119
        },
120
121
        refresh: function() {
122
          $label = $module.children(selector.label);
123
          $input = $module.children(selector.input);
124
          input  = $input[0];
125
        },
126
127
        hide: {
128
          input: function() {
129
            module.verbose('Modifying <input> z-index to be unselectable');
130
            $input.addClass(className.hidden);
131
          }
132
        },
133
        show: {
134
          input: function() {
135
            module.verbose('Modifying <input> z-index to be selectable');
136
            $input.removeClass(className.hidden);
137
          }
138
        },
139
140
        observeChanges: function() {
141
          if('MutationObserver' in window) {
142
            observer = new MutationObserver(function(mutations) {
143
              module.debug('DOM tree modified, updating selector cache');
144
              module.refresh();
145
            });
146
            observer.observe(element, {
147
              childList : true,
148
              subtree   : true
149
            });
150
            module.debug('Setting up mutation observer', observer);
151
          }
152
        },
153
154
        attachEvents: function(selector, event) {
155
          var
156
            $element = $(selector)
157
          ;
158
          event = $.isFunction(module[event])
159
            ? module[event]
160
            : module.toggle
161
          ;
162
          if($element.length > 0) {
163
            module.debug('Attaching checkbox events to element', selector, event);
164
            $element
165
              .on('click' + eventNamespace, event)
166
            ;
167
          }
168
          else {
169
            module.error(error.notFound);
170
          }
171
        },
172
173
        event: {
174
          click: function(event) {
175
            var
176
              $target = $(event.target)
177
            ;
178
            if( $target.is(selector.input) ) {
179
              module.verbose('Using default check action on initialized checkbox');
180
              return;
181
            }
182
            if( $target.is(selector.link) ) {
183
              module.debug('Clicking link inside checkbox, skipping toggle');
184
              return;
185
            }
186
            module.toggle();
187
            $input.focus();
188
            event.preventDefault();
189
          },
190
          keydown: function(event) {
191
            var
192
              key     = event.which,
193
              keyCode = {
194
                enter  : 13,
195
                space  : 32,
196
                escape : 27
197
              }
198
            ;
199
            if(key == keyCode.escape) {
200
              module.verbose('Escape key pressed blurring field');
201
              $input.blur();
202
              shortcutPressed = true;
203
            }
204
            else if(!event.ctrlKey && ( key == keyCode.space || key == keyCode.enter) ) {
205
              module.verbose('Enter/space key pressed, toggling checkbox');
206
              module.toggle();
207
              shortcutPressed = true;
208
            }
209
            else {
210
              shortcutPressed = false;
211
            }
212
          },
213
          keyup: function(event) {
214
            if(shortcutPressed) {
215
              event.preventDefault();
216
            }
217
          }
218
        },
219
220
        check: function() {
221
          if( !module.should.allowCheck() ) {
222
            return;
223
          }
224
          module.debug('Checking checkbox', $input);
225
          module.set.checked();
226
          if( !module.should.ignoreCallbacks() ) {
227
            settings.onChecked.call(input);
228
            settings.onChange.call(input);
229
          }
230
        },
231
232
        uncheck: function() {
233
          if( !module.should.allowUncheck() ) {
234
            return;
235
          }
236
          module.debug('Unchecking checkbox');
237
          module.set.unchecked();
238
          if( !module.should.ignoreCallbacks() ) {
239
            settings.onUnchecked.call(input);
240
            settings.onChange.call(input);
241
          }
242
        },
243
244
        indeterminate: function() {
245
          if( module.should.allowIndeterminate() ) {
246
            module.debug('Checkbox is already indeterminate');
247
            return;
248
          }
249
          module.debug('Making checkbox indeterminate');
250
          module.set.indeterminate();
251
          if( !module.should.ignoreCallbacks() ) {
252
            settings.onIndeterminate.call(input);
253
            settings.onChange.call(input);
254
          }
255
        },
256
257
        determinate: function() {
258
          if( module.should.allowDeterminate() ) {
259
            module.debug('Checkbox is already determinate');
260
            return;
261
          }
262
          module.debug('Making checkbox determinate');
263
          module.set.determinate();
264
          if( !module.should.ignoreCallbacks() ) {
265
            settings.onDeterminate.call(input);
266
            settings.onChange.call(input);
267
          }
268
        },
269
270
        enable: function() {
271
          if( module.is.enabled() ) {
272
            module.debug('Checkbox is already enabled');
273
            return;
274
          }
275
          module.debug('Enabling checkbox');
276
          module.set.enabled();
277
          settings.onEnable.call(input);
278
          // preserve legacy callbacks
279
          settings.onEnabled.call(input);
280
        },
281
282
        disable: function() {
283
          if( module.is.disabled() ) {
284
            module.debug('Checkbox is already disabled');
285
            return;
286
          }
287
          module.debug('Disabling checkbox');
288
          module.set.disabled();
289
          settings.onDisable.call(input);
290
          // preserve legacy callbacks
291
          settings.onDisabled.call(input);
292
        },
293
294
        get: {
295
          radios: function() {
296
            var
297
              name = module.get.name()
298
            ;
299
            return $('input[name="' + name + '"]').closest(selector.checkbox);
300
          },
301
          otherRadios: function() {
302
            return module.get.radios().not($module);
303
          },
304
          name: function() {
305
            return $input.attr('name');
306
          }
307
        },
308
309
        is: {
310
          initialLoad: function() {
311
            return initialLoad;
312
          },
313
          radio: function() {
314
            return ($input.hasClass(className.radio) || $input.attr('type') == 'radio');
315
          },
316
          indeterminate: function() {
317
            return $input.prop('indeterminate') !== undefined && $input.prop('indeterminate');
318
          },
319
          checked: function() {
320
            return $input.prop('checked') !== undefined && $input.prop('checked');
321
          },
322
          disabled: function() {
323
            return $input.prop('disabled') !== undefined && $input.prop('disabled');
324
          },
325
          enabled: function() {
326
            return !module.is.disabled();
327
          },
328
          determinate: function() {
329
            return !module.is.indeterminate();
330
          },
331
          unchecked: function() {
332
            return !module.is.checked();
333
          }
334
        },
335
336
        should: {
337
          allowCheck: function() {
338
            if(module.is.determinate() && module.is.checked() && !module.should.forceCallbacks() ) {
339
              module.debug('Should not allow check, checkbox is already checked');
340
              return false;
341
            }
342
            if(settings.beforeChecked.apply(input) === false) {
343
              module.debug('Should not allow check, beforeChecked cancelled');
344
              return false;
345
            }
346
            return true;
347
          },
348
          allowUncheck: function() {
349
            if(module.is.determinate() && module.is.unchecked() && !module.should.forceCallbacks() ) {
350
              module.debug('Should not allow uncheck, checkbox is already unchecked');
351
              return false;
352
            }
353
            if(settings.beforeUnchecked.apply(input) === false) {
354
              module.debug('Should not allow uncheck, beforeUnchecked cancelled');
355
              return false;
356
            }
357
            return true;
358
          },
359
          allowIndeterminate: function() {
360
            if(module.is.indeterminate() && !module.should.forceCallbacks() ) {
361
              module.debug('Should not allow indeterminate, checkbox is already indeterminate');
362
              return false;
363
            }
364
            if(settings.beforeIndeterminate.apply(input) === false) {
365
              module.debug('Should not allow indeterminate, beforeIndeterminate cancelled');
366
              return false;
367
            }
368
            return true;
369
          },
370
          allowDeterminate: function() {
371
            if(module.is.determinate() && !module.should.forceCallbacks() ) {
372
              module.debug('Should not allow determinate, checkbox is already determinate');
373
              return false;
374
            }
375
            if(settings.beforeDeterminate.apply(input) === false) {
376
              module.debug('Should not allow determinate, beforeDeterminate cancelled');
377
              return false;
378
            }
379
            return true;
380
          },
381
          forceCallbacks: function() {
382
            return (module.is.initialLoad() && settings.fireOnInit);
383
          },
384
          ignoreCallbacks: function() {
385
            return (initialLoad && !settings.fireOnInit);
386
          }
387
        },
388
389
        can: {
390
          change: function() {
391
            return !( $module.hasClass(className.disabled) || $module.hasClass(className.readOnly) || $input.prop('disabled') || $input.prop('readonly') );
392
          },
393
          uncheck: function() {
394
            return (typeof settings.uncheckable === 'boolean')
395
              ? settings.uncheckable
396
              : !module.is.radio()
397
            ;
398
          }
399
        },
400
401
        set: {
402
          initialLoad: function() {
403
            initialLoad = true;
404
          },
405
          checked: function() {
406
            module.verbose('Setting class to checked');
407
            $module
408
              .removeClass(className.indeterminate)
409
              .addClass(className.checked)
410
            ;
411
            if( module.is.radio() ) {
412
              module.uncheckOthers();
413
            }
414
            if(!module.is.indeterminate() && module.is.checked()) {
415
              module.debug('Input is already checked, skipping input property change');
416
              return;
417
            }
418
            module.verbose('Setting state to checked', input);
419
            $input
420
              .prop('indeterminate', false)
421
              .prop('checked', true)
422
            ;
423
            module.trigger.change();
424
          },
425
          unchecked: function() {
426
            module.verbose('Removing checked class');
427
            $module
428
              .removeClass(className.indeterminate)
429
              .removeClass(className.checked)
430
            ;
431
            if(!module.is.indeterminate() &&  module.is.unchecked() ) {
432
              module.debug('Input is already unchecked');
433
              return;
434
            }
435
            module.debug('Setting state to unchecked');
436
            $input
437
              .prop('indeterminate', false)
438
              .prop('checked', false)
439
            ;
440
            module.trigger.change();
441
          },
442
          indeterminate: function() {
443
            module.verbose('Setting class to indeterminate');
444
            $module
445
              .addClass(className.indeterminate)
446
            ;
447
            if( module.is.indeterminate() ) {
448
              module.debug('Input is already indeterminate, skipping input property change');
449
              return;
450
            }
451
            module.debug('Setting state to indeterminate');
452
            $input
453
              .prop('indeterminate', true)
454
            ;
455
            module.trigger.change();
456
          },
457
          determinate: function() {
458
            module.verbose('Removing indeterminate class');
459
            $module
460
              .removeClass(className.indeterminate)
461
            ;
462
            if( module.is.determinate() ) {
463
              module.debug('Input is already determinate, skipping input property change');
464
              return;
465
            }
466
            module.debug('Setting state to determinate');
467
            $input
468
              .prop('indeterminate', false)
469
            ;
470
          },
471
          disabled: function() {
472
            module.verbose('Setting class to disabled');
473
            $module
474
              .addClass(className.disabled)
475
            ;
476
            if( module.is.disabled() ) {
477
              module.debug('Input is already disabled, skipping input property change');
478
              return;
479
            }
480
            module.debug('Setting state to disabled');
481
            $input
482
              .prop('disabled', 'disabled')
483
            ;
484
            module.trigger.change();
485
          },
486
          enabled: function() {
487
            module.verbose('Removing disabled class');
488
            $module.removeClass(className.disabled);
489
            if( module.is.enabled() ) {
490
              module.debug('Input is already enabled, skipping input property change');
491
              return;
492
            }
493
            module.debug('Setting state to enabled');
494
            $input
495
              .prop('disabled', false)
496
            ;
497
            module.trigger.change();
498
          },
499
          tabbable: function() {
500
            module.verbose('Adding tabindex to checkbox');
501
            if( $input.attr('tabindex') === undefined) {
502
              $input.attr('tabindex', 0);
503
            }
504
          }
505
        },
506
507
        remove: {
508
          initialLoad: function() {
509
            initialLoad = false;
510
          }
511
        },
512
513
        trigger: {
514
          change: function() {
515
            var
516
              events       = document.createEvent('HTMLEvents'),
517
              inputElement = $input[0]
518
            ;
519
            if(inputElement) {
520
              module.verbose('Triggering native change event');
521
              events.initEvent('change', true, false);
522
              inputElement.dispatchEvent(events);
523
            }
524
          }
525
        },
526
527
528
        create: {
529
          label: function() {
530
            if($input.prevAll(selector.label).length > 0) {
531
              $input.prev(selector.label).detach().insertAfter($input);
532
              module.debug('Moving existing label', $label);
533
            }
534
            else if( !module.has.label() ) {
535
              $label = $('<label>').insertAfter($input);
536
              module.debug('Creating label', $label);
537
            }
538
          }
539
        },
540
541
        has: {
542
          label: function() {
543
            return ($label.length > 0);
544
          }
545
        },
546
547
        bind: {
548
          events: function() {
549
            module.verbose('Attaching checkbox events');
550
            $module
551
              .on('click'   + eventNamespace, module.event.click)
552
              .on('keydown' + eventNamespace, selector.input, module.event.keydown)
553
              .on('keyup'   + eventNamespace, selector.input, module.event.keyup)
554
            ;
555
          }
556
        },
557
558
        unbind: {
559
          events: function() {
560
            module.debug('Removing events');
561
            $module
562
              .off(eventNamespace)
563
            ;
564
          }
565
        },
566
567
        uncheckOthers: function() {
568
          var
569
            $radios = module.get.otherRadios()
570
          ;
571
          module.debug('Unchecking other radios', $radios);
572
          $radios.removeClass(className.checked);
573
        },
574
575
        toggle: function() {
576
          if( !module.can.change() ) {
577
            if(!module.is.radio()) {
578
              module.debug('Checkbox is read-only or disabled, ignoring toggle');
579
            }
580
            return;
581
          }
582
          if( module.is.indeterminate() || module.is.unchecked() ) {
583
            module.debug('Currently unchecked');
584
            module.check();
585
          }
586
          else if( module.is.checked() && module.can.uncheck() ) {
587
            module.debug('Currently checked');
588
            module.uncheck();
589
          }
590
        },
591
        setting: function(name, value) {
592
          module.debug('Changing setting', name, value);
593
          if( $.isPlainObject(name) ) {
594
            $.extend(true, settings, name);
595
          }
596
          else if(value !== undefined) {
597
            if($.isPlainObject(settings[name])) {
598
              $.extend(true, settings[name], value);
599
            }
600
            else {
601
              settings[name] = value;
602
            }
603
          }
604
          else {
605
            return settings[name];
606
          }
607
        },
608
        internal: function(name, value) {
609
          if( $.isPlainObject(name) ) {
610
            $.extend(true, module, name);
611
          }
612
          else if(value !== undefined) {
613
            module[name] = value;
614
          }
615
          else {
616
            return module[name];
617
          }
618
        },
619
        debug: function() {
620
          if(!settings.silent && settings.debug) {
621
            if(settings.performance) {
622
              module.performance.log(arguments);
623
            }
624
            else {
625
              module.debug = Function.prototype.bind.call(console.info, console, settings.name + ':');
626
              module.debug.apply(console, arguments);
627
            }
628
          }
629
        },
630
        verbose: function() {
631
          if(!settings.silent && settings.verbose && settings.debug) {
632
            if(settings.performance) {
633
              module.performance.log(arguments);
634
            }
635
            else {
636
              module.verbose = Function.prototype.bind.call(console.info, console, settings.name + ':');
637
              module.verbose.apply(console, arguments);
638
            }
639
          }
640
        },
641
        error: function() {
642
          if(!settings.silent) {
643
            module.error = Function.prototype.bind.call(console.error, console, settings.name + ':');
644
            module.error.apply(console, arguments);
645
          }
646
        },
647
        performance: {
648
          log: function(message) {
649
            var
650
              currentTime,
651
              executionTime,
652
              previousTime
653
            ;
654
            if(settings.performance) {
655
              currentTime   = new Date().getTime();
656
              previousTime  = time || currentTime;
657
              executionTime = currentTime - previousTime;
658
              time          = currentTime;
659
              performance.push({
660
                'Name'           : message[0],
661
                'Arguments'      : [].slice.call(message, 1) || '',
662
                'Element'        : element,
663
                'Execution Time' : executionTime
664
              });
665
            }
666
            clearTimeout(module.performance.timer);
667
            module.performance.timer = setTimeout(module.performance.display, 500);
668
          },
669
          display: function() {
670
            var
671
              title = settings.name + ':',
672
              totalTime = 0
673
            ;
674
            time = false;
675
            clearTimeout(module.performance.timer);
676
            $.each(performance, function(index, data) {
677
              totalTime += data['Execution Time'];
678
            });
679
            title += ' ' + totalTime + 'ms';
680
            if(moduleSelector) {
681
              title += ' \'' + moduleSelector + '\'';
682
            }
683
            if( (console.group !== undefined || console.table !== undefined) && performance.length > 0) {
684
              console.groupCollapsed(title);
685
              if(console.table) {
686
                console.table(performance);
687
              }
688
              else {
689
                $.each(performance, function(index, data) {
690
                  console.log(data['Name'] + ': ' + data['Execution Time']+'ms');
691
                });
692
              }
693
              console.groupEnd();
694
            }
695
            performance = [];
696
          }
697
        },
698
        invoke: function(query, passedArguments, context) {
699
          var
700
            object = instance,
701
            maxDepth,
702
            found,
703
            response
704
          ;
705
          passedArguments = passedArguments || queryArguments;
706
          context         = element         || context;
707
          if(typeof query == 'string' && object !== undefined) {
708
            query    = query.split(/[\. ]/);
709
            maxDepth = query.length - 1;
710
            $.each(query, function(depth, value) {
711
              var camelCaseValue = (depth != maxDepth)
712
                ? value + query[depth + 1].charAt(0).toUpperCase() + query[depth + 1].slice(1)
713
                : query
714
              ;
715
              if( $.isPlainObject( object[camelCaseValue] ) && (depth != maxDepth) ) {
716
                object = object[camelCaseValue];
717
              }
718
              else if( object[camelCaseValue] !== undefined ) {
719
                found = object[camelCaseValue];
720
                return false;
721
              }
722
              else if( $.isPlainObject( object[value] ) && (depth != maxDepth) ) {
723
                object = object[value];
724
              }
725
              else if( object[value] !== undefined ) {
726
                found = object[value];
727
                return false;
728
              }
729
              else {
730
                module.error(error.method, query);
731
                return false;
732
              }
733
            });
734
          }
735
          if ( $.isFunction( found ) ) {
736
            response = found.apply(context, passedArguments);
737
          }
738
          else if(found !== undefined) {
739
            response = found;
740
          }
741
          if($.isArray(returnedValue)) {
742
            returnedValue.push(response);
743
          }
744
          else if(returnedValue !== undefined) {
745
            returnedValue = [returnedValue, response];
746
          }
747
          else if(response !== undefined) {
748
            returnedValue = response;
749
          }
750
          return found;
751
        }
752
      };
753
754
      if(methodInvoked) {
755
        if(instance === undefined) {
756
          module.initialize();
757
        }
758
        module.invoke(query);
759
      }
760
      else {
761
        if(instance !== undefined) {
762
          instance.invoke('destroy');
763
        }
764
        module.initialize();
765
      }
766
    })
767
  ;
768
769
  return (returnedValue !== undefined)
770
    ? returnedValue
771
    : this
772
  ;
773
};
774
775
$.fn.checkbox.settings = {
776
777
  name                : 'Checkbox',
778
  namespace           : 'checkbox',
779
780
  silent              : false,
781
  debug               : false,
782
  verbose             : true,
783
  performance         : true,
784
785
  // delegated event context
786
  uncheckable         : 'auto',
787
  fireOnInit          : false,
788
789
  onChange            : function(){},
790
791
  beforeChecked       : function(){},
792
  beforeUnchecked     : function(){},
793
  beforeDeterminate   : function(){},
794
  beforeIndeterminate : function(){},
795
796
  onChecked           : function(){},
797
  onUnchecked         : function(){},
798
799
  onDeterminate       : function() {},
800
  onIndeterminate     : function() {},
801
802
  onEnable            : function(){},
803
  onDisable           : function(){},
804
805
  // preserve misspelled callbacks (will be removed in 3.0)
806
  onEnabled           : function(){},
807
  onDisabled          : function(){},
808
809
  className       : {
810
    checked       : 'checked',
811
    indeterminate : 'indeterminate',
812
    disabled      : 'disabled',
813
    hidden        : 'hidden',
814
    radio         : 'radio',
815
    readOnly      : 'read-only'
816
  },
817
818
  error     : {
819
    method       : 'The method you called is not defined'
820
  },
821
822
  selector : {
823
    checkbox : '.ui.checkbox',
824
    label    : 'label, .box',
825
    input    : 'input[type="checkbox"], input[type="radio"]',
826
    link     : 'a[href]'
827
  }
828
829
};
830
831
})( jQuery, window, document );
832