Browse Source

Merge branch 'master' into master

Emanuele 7 years ago
parent
commit
f20275e59a
10 changed files with 805 additions and 656 deletions
  1. 4 1
      .eslintrc.json
  2. 1 0
      .nvmrc
  3. 2 0
      .travis.yml
  4. 340 358
      dist/js/bootstrap-switch.js
  5. 0 0
      dist/js/bootstrap-switch.min.js
  6. 11 2
      package.json
  7. 2 1
      src/js/bootstrap-switch.js
  8. 64 48
      src/js/bootstrap-switch.test.js
  9. 4 0
      src/setup-test.js
  10. 377 246
      yarn.lock

+ 4 - 1
.eslintrc.json

@@ -1,5 +1,8 @@
 {
   "extends": "airbnb-base",
   "parser": "babel-eslint",
-  "env": { "browser": true }
+  "env": {
+    "browser": true,
+    "jest": true
+  }
 }

+ 1 - 0
.nvmrc

@@ -0,0 +1 @@
+9

+ 2 - 0
.travis.yml

@@ -0,0 +1,2 @@
+language: node_js
+node_js: 9

+ 340 - 358
dist/js/bootstrap-switch.js

@@ -70,67 +70,334 @@
 
   var $ = _jquery2.default || window.jQuery || window.$;
 
+  function getClasses(options, id) {
+    var state = options.state,
+        size = options.size,
+        disabled = options.disabled,
+        readonly = options.readonly,
+        indeterminate = options.indeterminate,
+        inverse = options.inverse;
+
+    return [state ? 'on' : 'off', size, disabled ? 'disabled' : undefined, readonly ? 'readonly' : undefined, indeterminate ? 'indeterminate' : undefined, inverse ? 'inverse' : undefined, id ? 'id-' + id : undefined].filter(function (v) {
+      return v == null;
+    });
+  }
+
+  function prvgetElementOptions() {
+    return {
+      state: this.$element.is(':checked'),
+      size: this.$element.data('size'),
+      animate: this.$element.data('animate'),
+      disabled: this.$element.is(':disabled'),
+      readonly: this.$element.is('[readonly]'),
+      indeterminate: this.$element.data('indeterminate'),
+      inverse: this.$element.data('inverse'),
+      radioAllOff: this.$element.data('radio-all-off'),
+      onColor: this.$element.data('on-color'),
+      offColor: this.$element.data('off-color'),
+      onText: this.$element.data('on-text'),
+      offText: this.$element.data('off-text'),
+      labelText: this.$element.data('label-text'),
+      handleWidth: this.$element.data('handle-width'),
+      labelWidth: this.$element.data('label-width'),
+      baseClass: this.$element.data('base-class'),
+      wrapperClass: this.$element.data('wrapper-class')
+    };
+  }
+
+  function prvwidth() {
+    var _this = this;
+
+    var $handles = this.$on.add(this.$off).add(this.$label).css('width', '');
+    var handleWidth = this.options.handleWidth === 'auto' ? Math.round(Math.max(this.$on.width(), this.$off.width())) : this.options.handleWidth;
+    $handles.width(handleWidth);
+    this.$label.width(function (index, width) {
+      if (_this.options.labelWidth !== 'auto') {
+        return _this.options.labelWidth;
+      }
+      if (width < handleWidth) {
+        return handleWidth;
+      }
+      return width;
+    });
+    this.privateHandleWidth = this.$on.outerWidth();
+    this.privateLabelWidth = this.$label.outerWidth();
+    this.$container.width(this.privateHandleWidth * 2 + this.privateLabelWidth);
+    return this.$wrapper.width(this.privateHandleWidth + this.privateLabelWidth);
+  }
+
+  function prvcontainerPosition() {
+    var _this2 = this;
+
+    var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.ope;
+
+    this.$container.css('margin-left', function () {
+      var values = [0, '-' + _this2.privateHandleWidth + 'px'];
+      if (_this2.options.indeterminate) {
+        return '-' + _this2.privateHandleWidth / 2 + 'px';
+      }
+      if (state) {
+        if (_this2.options.inverse) {
+          return values[1];
+        }
+        return values[0];
+      }
+      if (_this2.options.inverse) {
+        return values[0];
+      }
+      return values[1];
+    });
+  }
+
+  function prvgetClass(name) {
+    return this.options.baseClass + '-' + name;
+  }
+
+  function prvinit() {
+    var _this3 = this;
+
+    var init = function init() {
+      _this3.setPrevOptions();
+      prvwidth.call(_this3);
+      prvcontainerPosition.call(_this3);
+      setTimeout(function () {
+        return _this3.options.animate && _this3.$wrapper.addClass(prvgetClass.call(_this3, 'animate'));
+      }, 50);
+    };
+    if (this.$wrapper.is(':visible')) {
+      init();
+      return;
+    }
+    var initInterval = window.setInterval(function () {
+      return _this3.$wrapper.is(':visible') && (init() || true) && window.clearInterval(initInterval);
+    }, 50);
+  }
+
+  function prvelementHandlers() {
+    var _this4 = this;
+
+    return this.$element.on({
+      'setPreviousOptions.bootstrapSwitch': function setPreviousOptionsBootstrapSwitch() {
+        return _this4.setPrevOptions();
+      },
+
+      'previousState.bootstrapSwitch': function previousStateBootstrapSwitch() {
+        _this4.options = _this4.prevOptions;
+        if (_this4.options.indeterminate) {
+          _this4.$wrapper.addClass(prvgetClass.call(_this4, 'indeterminate'));
+        }
+        _this4.$element.prop('checked', _this4.options.state).trigger('change.bootstrapSwitch', true);
+      },
+
+      'change.bootstrapSwitch': function changeBootstrapSwitch(event, skip) {
+        event.preventDefault();
+        event.stopImmediatePropagation();
+        var state = _this4.$element.is(':checked');
+        prvcontainerPosition.call(_this4, state);
+        if (state === _this4.options.state) {
+          return;
+        }
+        _this4.options.state = state;
+        _this4.$wrapper.toggleClass(prvgetClass.call(_this4, 'off')).toggleClass(prvgetClass.call(_this4, 'on'));
+        if (!skip) {
+          if (_this4.$element.is(':radio')) {
+            $('[name="' + _this4.$element.attr('name') + '"]').not(_this4.$element).prop('checked', false).trigger('change.bootstrapSwitch', true);
+          }
+          _this4.$element.trigger('switchChange.bootstrapSwitch', [state]);
+        }
+      },
+
+      'focus.bootstrapSwitch': function focusBootstrapSwitch(event) {
+        event.preventDefault();
+        _this4.$wrapper.addClass(prvgetClass.call(_this4, 'focused'));
+      },
+
+      'blur.bootstrapSwitch': function blurBootstrapSwitch(event) {
+        event.preventDefault();
+        _this4.$wrapper.removeClass(prvgetClass.call(_this4, 'focused'));
+      },
+
+      'keydown.bootstrapSwitch': function keydownBootstrapSwitch(event) {
+        if (!event.which || _this4.options.disabled || _this4.options.readonly) {
+          return;
+        }
+        if (event.which === 37 || event.which === 39) {
+          event.preventDefault();
+          event.stopImmediatePropagation();
+          _this4.state(event.which === 39);
+        }
+      }
+    });
+  }
+
+  function prvhandleHandlers() {
+    var _this5 = this;
+
+    this.$on.on('click.bootstrapSwitch', function (event) {
+      event.preventDefault();
+      event.stopPropagation();
+      _this5.state(false);
+      return _this5.$element.trigger('focus.bootstrapSwitch');
+    });
+    return this.$off.on('click.bootstrapSwitch', function (event) {
+      event.preventDefault();
+      event.stopPropagation();
+      _this5.state(true);
+      return _this5.$element.trigger('focus.bootstrapSwitch');
+    });
+  }
+
+  function prvlabelHandlers() {
+    var _this6 = this;
+
+    var dragStart = void 0;
+    var dragEnd = void 0;
+    var handlers = {
+      click: function click(event) {
+        event.stopPropagation();
+      },
+
+
+      'mousedown.bootstrapSwitch touchstart.bootstrapSwitch': function mousedownBootstrapSwitchTouchstartBootstrapSwitch(event) {
+        if (dragStart || _this6.options.disabled || _this6.options.readonly) {
+          return;
+        }
+        event.preventDefault();
+        event.stopPropagation();
+        dragStart = (event.pageX || event.originalEvent.touches[0].pageX) - parseInt(_this6.$container.css('margin-left'), 10);
+        if (_this6.options.animate) {
+          _this6.$wrapper.removeClass(prvgetClass.call(_this6, 'animate'));
+        }
+        _this6.$element.trigger('focus.bootstrapSwitch');
+      },
+
+      'mousemove.bootstrapSwitch touchmove.bootstrapSwitch': function mousemoveBootstrapSwitchTouchmoveBootstrapSwitch(event) {
+        if (dragStart == null) {
+          return;
+        }
+        var difference = (event.pageX || event.originalEvent.touches[0].pageX) - dragStart;
+        event.preventDefault();
+        if (difference < -_this6.privateHandleWidth || difference > 0) {
+          return;
+        }
+        dragEnd = difference;
+        _this6.$container.css('margin-left', dragEnd + 'px');
+      },
+
+      'mouseup.bootstrapSwitch touchend.bootstrapSwitch': function mouseupBootstrapSwitchTouchendBootstrapSwitch(event) {
+        if (!dragStart) {
+          return;
+        }
+        event.preventDefault();
+        if (_this6.options.animate) {
+          _this6.$wrapper.addClass(prvgetClass.call(_this6, 'animate'));
+        }
+        if (dragEnd) {
+          var state = dragEnd > -(_this6.privateHandleWidth / 2);
+          dragEnd = false;
+          _this6.state(_this6.options.inverse ? !state : state);
+        } else {
+          _this6.state(!_this6.options.state);
+        }
+        dragStart = false;
+      },
+
+      'mouseleave.bootstrapSwitch': function mouseleaveBootstrapSwitch() {
+        _this6.$label.trigger('mouseup.bootstrapSwitch');
+      }
+    };
+    this.$label.on(handlers);
+  }
+
+  function prvexternalLabelHandler() {
+    var _this7 = this;
+
+    var $externalLabel = this.$element.closest('label');
+    $externalLabel.on('click', function (event) {
+      event.preventDefault();
+      event.stopImmediatePropagation();
+      if (event.target === $externalLabel[0]) {
+        _this7.toggleState();
+      }
+    });
+  }
+
+  function prvformHandler() {
+    function isBootstrapSwitch() {
+      return $(this).data('bootstrap-switch');
+    }
+
+    function performReset() {
+      return $(this).bootstrapSwitch('state', this.checked);
+    }
+
+    var $form = this.$element.closest('form');
+    if ($form.data('bootstrap-switch')) {
+      return;
+    }
+    $form.on('reset.bootstrapSwitch', function () {
+      window.setTimeout(function () {
+        $form.find('input').filter(isBootstrapSwitch).each(performReset);
+      }, 1);
+    }).data('bootstrap-switch', true);
+  }
+
+  function prvgetClasses(classes) {
+    var _this8 = this;
+
+    if (!$.isArray(classes)) {
+      return [prvgetClass.call(this, classes)];
+    }
+    return classes.map(function (v) {
+      return prvgetClass.call(_this8, v);
+    });
+  }
+
   var BootstrapSwitch = function () {
     function BootstrapSwitch(element) {
-      var _this = this;
+      var _this9 = this;
 
       var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {};
 
       _classCallCheck(this, BootstrapSwitch);
 
       this.$element = $(element);
-      this.options = $.extend({}, $.fn.bootstrapSwitch.defaults, this._getElementOptions(), options);
+      this.options = $.extend({}, $.fn.bootstrapSwitch.defaults, prvgetElementOptions.call(this), options);
       this.prevOptions = {};
       this.$wrapper = $('<div>', {
         class: function _class() {
-          var classes = [];
-          classes.push(_this.options.state ? 'on' : 'off');
-          if (_this.options.size) {
-            classes.push(_this.options.size);
-          }
-          if (_this.options.disabled) {
-            classes.push('disabled');
-          }
-          if (_this.options.readonly) {
-            classes.push('readonly');
-          }
-          if (_this.options.indeterminate) {
-            classes.push('indeterminate');
-          }
-          if (_this.options.inverse) {
-            classes.push('inverse');
-          }
-          if (_this.$element.attr('id')) {
-            classes.push('id-' + _this.$element.attr('id'));
-          }
-          return classes.map(_this._getClass.bind(_this)).concat([_this.options.baseClass], _this._getClasses(_this.options.wrapperClass)).join(' ');
+          return getClasses(_this9.options, _this9.$element.attr('id')).map(function (v) {
+            return prvgetClass.call(_this9, v);
+          }).concat([_this9.options.baseClass], prvgetClasses.call(_this9, _this9.options.wrapperClass)).join(' ');
         }
       });
-      this.$container = $('<div>', { class: this._getClass('container') });
+      this.$container = $('<div>', { class: prvgetClass.call(this, 'container') });
       this.$on = $('<span>', {
         html: this.options.onText,
-        class: this._getClass('handle-on') + ' ' + this._getClass(this.options.onColor)
+        class: prvgetClass.call(this, 'handle-on') + ' ' + prvgetClass.call(this, this.options.onColor)
       });
       this.$off = $('<span>', {
         html: this.options.offText,
-        class: this._getClass('handle-off') + ' ' + this._getClass(this.options.offColor)
+        class: prvgetClass.call(this, 'handle-off') + ' ' + prvgetClass.call(this, this.options.offColor)
       });
       this.$label = $('<span>', {
         html: this.options.labelText,
-        class: this._getClass('label')
+        class: prvgetClass.call(this, 'label')
       });
 
-      this.$element.on('init.bootstrapSwitch', this.options.onInit.bind(this, element));
+      this.$element.on('init.bootstrapSwitch', function () {
+        return _this9.options.onInit(element);
+      });
       this.$element.on('switchChange.bootstrapSwitch', function () {
         for (var _len = arguments.length, args = Array(_len), _key = 0; _key < _len; _key++) {
           args[_key] = arguments[_key];
         }
 
-        if (_this.options.onSwitchChange.apply(element, args) === false) {
-          if (_this.$element.is(':radio')) {
-            $('[name="' + _this.$element.attr('name') + '"]').trigger('previousState.bootstrapSwitch', true);
+        if (_this9.options.onSwitchChange.apply(element, args) === false) {
+          if (_this9.$element.is(':radio')) {
+            $('[name="' + _this9.$element.attr('name') + '"]').trigger('previousState.bootstrapSwitch', true);
           } else {
-            _this.$element.trigger('previousState.bootstrapSwitch', true);
+            _this9.$element.trigger('previousState.bootstrapSwitch', true);
           }
         }
       });
@@ -143,12 +410,12 @@
         this.$element.prop('indeterminate', true);
       }
 
-      this._init();
-      this._elementHandlers();
-      this._handleHandlers();
-      this._labelHandlers();
-      this._formHandler();
-      this._externalLabelHandler();
+      prvinit.call(this);
+      prvelementHandlers.call(this);
+      prvhandleHandlers.call(this);
+      prvlabelHandlers.call(this);
+      prvformHandler.call(this);
+      prvexternalLabelHandler.call(this);
       this.$element.trigger('init.bootstrapSwitch', this.options.state);
     }
 
@@ -186,9 +453,8 @@
         if (this.options.indeterminate) {
           this.indeterminate(false);
           return this.state(true);
-        } else {
-          return this.$element.prop('checked', !this.options.state).trigger('change.bootstrapSwitch', skip);
         }
+        return this.$element.prop('checked', !this.options.state).trigger('change.bootstrapSwitch', skip);
       }
     }, {
       key: 'size',
@@ -197,13 +463,13 @@
           return this.options.size;
         }
         if (this.options.size != null) {
-          this.$wrapper.removeClass(this._getClass(this.options.size));
+          this.$wrapper.removeClass(prvgetClass.call(this, this.options.size));
         }
         if (value) {
-          this.$wrapper.addClass(this._getClass(value));
+          this.$wrapper.addClass(prvgetClass.call(this, value));
         }
-        this._width();
-        this._containerPosition();
+        prvwidth.call(this);
+        prvcontainerPosition.call(this);
         this.options.size = value;
         return this.$element;
       }
@@ -222,7 +488,7 @@
       key: 'toggleAnimate',
       value: function toggleAnimate() {
         this.options.animate = !this.options.animate;
-        this.$wrapper.toggleClass(this._getClass('animate'));
+        this.$wrapper.toggleClass(prvgetClass.call(this, 'animate'));
         return this.$element;
       }
     }, {
@@ -241,7 +507,7 @@
       value: function toggleDisabled() {
         this.options.disabled = !this.options.disabled;
         this.$element.prop('disabled', this.options.disabled);
-        this.$wrapper.toggleClass(this._getClass('disabled'));
+        this.$wrapper.toggleClass(prvgetClass.call(this, 'disabled'));
         return this.$element;
       }
     }, {
@@ -260,7 +526,7 @@
       value: function toggleReadonly() {
         this.options.readonly = !this.options.readonly;
         this.$element.prop('readonly', this.options.readonly);
-        this.$wrapper.toggleClass(this._getClass('readonly'));
+        this.$wrapper.toggleClass(prvgetClass.call(this, 'readonly'));
         return this.$element;
       }
     }, {
@@ -279,8 +545,8 @@
       value: function toggleIndeterminate() {
         this.options.indeterminate = !this.options.indeterminate;
         this.$element.prop('indeterminate', this.options.indeterminate);
-        this.$wrapper.toggleClass(this._getClass('indeterminate'));
-        this._containerPosition();
+        this.$wrapper.toggleClass(prvgetClass.call(this, 'indeterminate'));
+        prvcontainerPosition.call(this);
         return this.$element;
       }
     }, {
@@ -297,7 +563,7 @@
     }, {
       key: 'toggleInverse',
       value: function toggleInverse() {
-        this.$wrapper.toggleClass(this._getClass('inverse'));
+        this.$wrapper.toggleClass(prvgetClass.call(this, 'inverse'));
         var $on = this.$on.clone(true);
         var $off = this.$off.clone(true);
         this.$on.replaceWith($off);
@@ -314,9 +580,9 @@
           return this.options.onColor;
         }
         if (this.options.onColor) {
-          this.$on.removeClass(this._getClass(this.options.onColor));
+          this.$on.removeClass(prvgetClass.call(this, this.options.onColor));
         }
-        this.$on.addClass(this._getClass(value));
+        this.$on.addClass(prvgetClass.call(this, value));
         this.options.onColor = value;
         return this.$element;
       }
@@ -327,9 +593,9 @@
           return this.options.offColor;
         }
         if (this.options.offColor) {
-          this.$off.removeClass(this._getClass(this.options.offColor));
+          this.$off.removeClass(prvgetClass.call(this, this.options.offColor));
         }
-        this.$off.addClass(this._getClass(value));
+        this.$off.addClass(prvgetClass.call(this, value));
         this.options.offColor = value;
         return this.$element;
       }
@@ -340,8 +606,8 @@
           return this.options.onText;
         }
         this.$on.html(value);
-        this._width();
-        this._containerPosition();
+        prvwidth.call(this);
+        prvcontainerPosition.call(this);
         this.options.onText = value;
         return this.$element;
       }
@@ -352,8 +618,8 @@
           return this.options.offText;
         }
         this.$off.html(value);
-        this._width();
-        this._containerPosition();
+        prvwidth.call(this);
+        prvcontainerPosition.call(this);
         this.options.offText = value;
         return this.$element;
       }
@@ -364,7 +630,7 @@
           return this.options.labelText;
         }
         this.$label.html(value);
-        this._width();
+        prvwidth.call(this);
         this.options.labelText = value;
         return this.$element;
       }
@@ -375,8 +641,8 @@
           return this.options.handleWidth;
         }
         this.options.handleWidth = value;
-        this._width();
-        this._containerPosition();
+        prvwidth.call(this);
+        prvcontainerPosition.call(this);
         return this.$element;
       }
     }, {
@@ -386,13 +652,13 @@
           return this.options.labelWidth;
         }
         this.options.labelWidth = value;
-        this._width();
-        this._containerPosition();
+        prvwidth.call(this);
+        prvcontainerPosition.call(this);
         return this.$element;
       }
     }, {
       key: 'baseClass',
-      value: function baseClass(value) {
+      value: function baseClass() {
         return this.options.baseClass;
       }
     }, {
@@ -401,12 +667,10 @@
         if (typeof value === 'undefined') {
           return this.options.wrapperClass;
         }
-        if (!value) {
-          value = $.fn.bootstrapSwitch.defaults.wrapperClass;
-        }
-        this.$wrapper.removeClass(this._getClasses(this.options.wrapperClass).join(' '));
-        this.$wrapper.addClass(this._getClasses(value).join(' '));
-        this.options.wrapperClass = value;
+        var wrapperClass = value || $.fn.bootstrapSwitch.defaults.wrapperClass;
+        this.$wrapper.removeClass(prvgetClasses.call(this, this.options.wrapperClass).join(' '));
+        this.$wrapper.addClass(prvgetClasses.call(this, wrapperClass).join(' '));
+        this.options.wrapperClass = wrapperClass;
         return this.$element;
       }
     }, {
@@ -428,10 +692,7 @@
         if (typeof value === 'undefined') {
           return this.options.onInit;
         }
-        if (!value) {
-          value = $.fn.bootstrapSwitch.defaults.onInit;
-        }
-        this.options.onInit = value;
+        this.options.onInit = value || $.fn.bootstrapSwitch.defaults.onInit;
         return this.$element;
       }
     }, {
@@ -440,10 +701,7 @@
         if (typeof value === 'undefined') {
           return this.options.onSwitchChange;
         }
-        if (!value) {
-          value = $.fn.bootstrapSwitch.defaults.onSwitchChange;
-        }
-        this.options.onSwitchChange = value;
+        this.options.onSwitchChange = value || $.fn.bootstrapSwitch.defaults.onSwitchChange;
         return this.$element;
       }
     }, {
@@ -457,290 +715,12 @@
         this.$element.unwrap().unwrap().off('.bootstrapSwitch').removeData('bootstrap-switch');
         return this.$element;
       }
-    }, {
-      key: '_getElementOptions',
-      value: function _getElementOptions() {
-        return {
-          state: this.$element.is(':checked'),
-          size: this.$element.data('size'),
-          animate: this.$element.data('animate'),
-          disabled: this.$element.is(':disabled'),
-          readonly: this.$element.is('[readonly]'),
-          indeterminate: this.$element.data('indeterminate'),
-          inverse: this.$element.data('inverse'),
-          radioAllOff: this.$element.data('radio-all-off'),
-          onColor: this.$element.data('on-color'),
-          offColor: this.$element.data('off-color'),
-          onText: this.$element.data('on-text'),
-          offText: this.$element.data('off-text'),
-          labelText: this.$element.data('label-text'),
-          handleWidth: this.$element.data('handle-width'),
-          labelWidth: this.$element.data('label-width'),
-          baseClass: this.$element.data('base-class'),
-          wrapperClass: this.$element.data('wrapper-class')
-        };
-      }
-    }, {
-      key: '_width',
-      value: function _width() {
-        var _this2 = this;
-
-        var $handles = this.$on.add(this.$off).add(this.$label).css('width', '');
-        var handleWidth = this.options.handleWidth === 'auto' ? Math.round(Math.max(this.$on.width(), this.$off.width())) : this.options.handleWidth;
-        $handles.width(handleWidth);
-        this.$label.width(function (index, width) {
-          if (_this2.options.labelWidth !== 'auto') {
-            return _this2.options.labelWidth;
-          }
-          if (width < handleWidth) {
-            return handleWidth;
-          }
-          return width;
-        });
-        this._handleWidth = this.$on.outerWidth();
-        this._labelWidth = this.$label.outerWidth();
-        this.$container.width(this._handleWidth * 2 + this._labelWidth);
-        return this.$wrapper.width(this._handleWidth + this._labelWidth);
-      }
-    }, {
-      key: '_containerPosition',
-      value: function _containerPosition() {
-        var _this3 = this;
-
-        var state = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : this.options.state;
-        var callback = arguments[1];
-
-        this.$container.css('margin-left', function () {
-          var values = [0, '-' + _this3._handleWidth + 'px'];
-          if (_this3.options.indeterminate) {
-            return '-' + _this3._handleWidth / 2 + 'px';
-          }
-          if (state) {
-            if (_this3.options.inverse) {
-              return values[1];
-            } else {
-              return values[0];
-            }
-          } else {
-            if (_this3.options.inverse) {
-              return values[0];
-            } else {
-              return values[1];
-            }
-          }
-        });
-      }
-    }, {
-      key: '_init',
-      value: function _init() {
-        var _this4 = this;
-
-        var init = function init() {
-          _this4.setPrevOptions();
-          _this4._width();
-          _this4._containerPosition();
-          setTimeout(function () {
-            if (_this4.options.animate) {
-              return _this4.$wrapper.addClass(_this4._getClass('animate'));
-            }
-          }, 50);
-        };
-        if (this.$wrapper.is(':visible')) {
-          init();
-          return;
-        }
-        var initInterval = window.setInterval(function () {
-          if (_this4.$wrapper.is(':visible')) {
-            init();
-            return window.clearInterval(initInterval);
-          }
-        }, 50);
-      }
-    }, {
-      key: '_elementHandlers',
-      value: function _elementHandlers() {
-        var _this5 = this;
-
-        return this.$element.on({
-          'setPreviousOptions.bootstrapSwitch': this.setPrevOptions.bind(this),
-
-          'previousState.bootstrapSwitch': function previousStateBootstrapSwitch() {
-            _this5.options = _this5.prevOptions;
-            if (_this5.options.indeterminate) {
-              _this5.$wrapper.addClass(_this5._getClass('indeterminate'));
-            }
-            _this5.$element.prop('checked', _this5.options.state).trigger('change.bootstrapSwitch', true);
-          },
-
-          'change.bootstrapSwitch': function changeBootstrapSwitch(event, skip) {
-            event.preventDefault();
-            event.stopImmediatePropagation();
-            var state = _this5.$element.is(':checked');
-            _this5._containerPosition(state);
-            if (state === _this5.options.state) {
-              return;
-            }
-            _this5.options.state = state;
-            _this5.$wrapper.toggleClass(_this5._getClass('off')).toggleClass(_this5._getClass('on'));
-            if (!skip) {
-              if (_this5.$element.is(':radio')) {
-                $('[name="' + _this5.$element.attr('name') + '"]').not(_this5.$element).prop('checked', false).trigger('change.bootstrapSwitch', true);
-              }
-              _this5.$element.trigger('switchChange.bootstrapSwitch', [state]);
-            }
-          },
-
-          'focus.bootstrapSwitch': function focusBootstrapSwitch(event) {
-            event.preventDefault();
-            _this5.$wrapper.addClass(_this5._getClass('focused'));
-          },
-
-          'blur.bootstrapSwitch': function blurBootstrapSwitch(event) {
-            event.preventDefault();
-            _this5.$wrapper.removeClass(_this5._getClass('focused'));
-          },
-
-          'keydown.bootstrapSwitch': function keydownBootstrapSwitch(event) {
-            if (!event.which || _this5.options.disabled || _this5.options.readonly) {
-              return;
-            }
-            if (event.which === 37 || event.which === 39) {
-              event.preventDefault();
-              event.stopImmediatePropagation();
-              _this5.state(event.which === 39);
-            }
-          }
-        });
-      }
-    }, {
-      key: '_handleHandlers',
-      value: function _handleHandlers() {
-        var _this6 = this;
-
-        this.$on.on('click.bootstrapSwitch', function (event) {
-          event.preventDefault();
-          event.stopPropagation();
-          _this6.state(false);
-          return _this6.$element.trigger('focus.bootstrapSwitch');
-        });
-        return this.$off.on('click.bootstrapSwitch', function (event) {
-          event.preventDefault();
-          event.stopPropagation();
-          _this6.state(true);
-          return _this6.$element.trigger('focus.bootstrapSwitch');
-        });
-      }
-    }, {
-      key: '_labelHandlers',
-      value: function _labelHandlers() {
-        var _this7 = this;
-
-        var handlers = {
-          click: function click(event) {
-            event.stopPropagation();
-          },
-
-
-          'mousedown.bootstrapSwitch touchstart.bootstrapSwitch': function mousedownBootstrapSwitchTouchstartBootstrapSwitch(event) {
-            if (_this7._dragStart || _this7.options.disabled || _this7.options.readonly) {
-              return;
-            }
-            event.preventDefault();
-            event.stopPropagation();
-            _this7._dragStart = (event.pageX || event.originalEvent.touches[0].pageX) - parseInt(_this7.$container.css('margin-left'), 10);
-            if (_this7.options.animate) {
-              _this7.$wrapper.removeClass(_this7._getClass('animate'));
-            }
-            _this7.$element.trigger('focus.bootstrapSwitch');
-          },
-
-          'mousemove.bootstrapSwitch touchmove.bootstrapSwitch': function mousemoveBootstrapSwitchTouchmoveBootstrapSwitch(event) {
-            if (_this7._dragStart == null) {
-              return;
-            }
-            var difference = (event.pageX || event.originalEvent.touches[0].pageX) - _this7._dragStart;
-            event.preventDefault();
-            if (difference < -_this7._handleWidth || difference > 0) {
-              return;
-            }
-            _this7._dragEnd = difference;
-            _this7.$container.css('margin-left', _this7._dragEnd + 'px');
-          },
-
-          'mouseup.bootstrapSwitch touchend.bootstrapSwitch': function mouseupBootstrapSwitchTouchendBootstrapSwitch(event) {
-            if (!_this7._dragStart) {
-              return;
-            }
-            event.preventDefault();
-            if (_this7.options.animate) {
-              _this7.$wrapper.addClass(_this7._getClass('animate'));
-            }
-            if (_this7._dragEnd) {
-              var state = _this7._dragEnd > -(_this7._handleWidth / 2);
-              _this7._dragEnd = false;
-              _this7.state(_this7.options.inverse ? !state : state);
-            } else {
-              _this7.state(!_this7.options.state);
-            }
-            _this7._dragStart = false;
-          },
-
-          'mouseleave.bootstrapSwitch': function mouseleaveBootstrapSwitch() {
-            _this7.$label.trigger('mouseup.bootstrapSwitch');
-          }
-        };
-        this.$label.on(handlers);
-      }
-    }, {
-      key: '_externalLabelHandler',
-      value: function _externalLabelHandler() {
-        var _this8 = this;
-
-        var $externalLabel = this.$element.closest('label');
-        $externalLabel.on('click', function (event) {
-          event.preventDefault();
-          event.stopImmediatePropagation();
-          if (event.target === $externalLabel[0]) {
-            _this8.toggleState();
-          }
-        });
-      }
-    }, {
-      key: '_formHandler',
-      value: function _formHandler() {
-        var $form = this.$element.closest('form');
-        if ($form.data('bootstrap-switch')) {
-          return;
-        }
-        $form.on('reset.bootstrapSwitch', function () {
-          window.setTimeout(function () {
-            $form.find('input').filter(function () {
-              return $(this).data('bootstrap-switch');
-            }).each(function () {
-              return $(this).bootstrapSwitch('state', this.checked);
-            });
-          }, 1);
-        }).data('bootstrap-switch', true);
-      }
-    }, {
-      key: '_getClass',
-      value: function _getClass(name) {
-        return this.options.baseClass + '-' + name;
-      }
-    }, {
-      key: '_getClasses',
-      value: function _getClasses(classes) {
-        if (!$.isArray(classes)) {
-          return [this._getClass(classes)];
-        }
-        return classes.map(this._getClass.bind(this));
-      }
     }]);
 
     return BootstrapSwitch;
   }();
 
-  $.fn.bootstrapSwitch = function (option) {
+  function bootstrapSwitch(option) {
     for (var _len2 = arguments.length, args = Array(_len2 > 1 ? _len2 - 1 : 0), _key2 = 1; _key2 < _len2; _key2++) {
       args[_key2 - 1] = arguments[_key2];
     }
@@ -758,7 +738,9 @@
       return ret;
     }
     return Array.prototype.reduce.call(this, reducer, this);
-  };
+  }
+
+  $.fn.bootstrapSwitch = bootstrapSwitch;
   $.fn.bootstrapSwitch.Constructor = BootstrapSwitch;
   $.fn.bootstrapSwitch.defaults = {
     state: true,

File diff suppressed because it is too large
+ 0 - 0
dist/js/bootstrap-switch.min.js


+ 11 - 2
package.json

@@ -28,7 +28,9 @@
   "readmeFilename": "README.md",
   "devDependencies": {
     "babel-cli": "^6.22.2",
+    "babel-core": "^6.26.0",
     "babel-eslint": "^7.2.3",
+    "babel-jest": "^22.4.3",
     "babel-polyfill": "^6.22.0",
     "babel-preset-babili": "^0.0.10",
     "babel-preset-env": "^1.1.8",
@@ -41,6 +43,7 @@
     "headr": "0.0.4",
     "jasmine": "^2.5.3",
     "jasmine-core": "^2.5.2",
+    "jest": "^22.4.3",
     "jquery": "^1.12.4",
     "karma": "^1.4.1",
     "karma-babel-preprocessor": "^6.0.1",
@@ -51,11 +54,12 @@
     "less": "^2.7.2",
     "less-plugin-clean-css": "^1.5.0",
     "npm-run-all": "^4.0.1",
+    "regenerator-runtime": "^0.11.1",
     "wintersmith": "^2.3.6"
   },
   "scripts": {
     "js:lint": "eslint src/js/",
-    "js:test": "mkdir -p test && babel -d test src/js && karma start karma.conf.js",
+    "js:test": "jest",
     "js:build:dir": "mkdir -p dist/js",
     "js:build:base": "babel -o dist/js/bootstrap-switch.js src/js/bootstrap-switch.js",
     "js:build:min": "NODE_ENV=production babel -o dist/js/bootstrap-switch.min.js src/js/bootstrap-switch.js",
@@ -88,5 +92,10 @@
       ]
     }
   ],
-  "dependencies": {}
+  "dependencies": {},
+  "jest": {
+    "setupFiles": [
+      "./src/setup-test.js"
+    ]
+  }
 }

+ 2 - 1
src/js/bootstrap-switch.js

@@ -304,7 +304,8 @@ class BootstrapSwitch {
 
     this.$element.on('init.bootstrapSwitch', () => this.options.onInit(element));
     this.$element.on('switchChange.bootstrapSwitch', (...args) => {
-      if (this.options.onSwitchChange.apply(element, args) === false) {
+      const changeState = this.options.onSwitchChange.apply(element, args);
+      if (changeState === false) {
         if (this.$element.is(':radio')) {
           $(`[name="${this.$element.attr('name')}"]`).trigger('previousState.bootstrapSwitch', true);
         } else {

+ 64 - 48
src/js/bootstrap-switch.test.js

@@ -1,32 +1,31 @@
-const { $, describe, beforeEach, afterEach, it, expect } = window;
+import './bootstrap-switch';
+
+const { $ } = global;
 
 describe('Bootstrap Switch:', () => {
   beforeEach(() => {
     $.support.transition = false;
     $.fx.off = true;
   });
+
   afterEach(() => {
     $(`.${$.fn.bootstrapSwitch.defaults.baseClass}`).bootstrapSwitch('destroy');
   });
 
-  function createCheckbox() {
-    return $('<input>', {
+  const createCheckbox = () =>
+    $('<input>', {
       type: 'checkbox',
       class: 'switch',
     }).appendTo('body');
-  }
 
-  function createRadio() {
-    return $('<input>', {
+  const createRadio = () =>
+    $('<input>', {
       type: 'radio',
       name: 'name',
       class: 'switch',
     }).appendTo('body');
-  }
 
-  function getOptions($element) {
-    return $element.data('bootstrap-switch').options;
-  }
+  const getOptions = $element => $element.data('bootstrap-switch').options;
 
   it('should set the default options as element options, except state', () => {
     const $switch = createCheckbox().prop('checked', true).bootstrapSwitch();
@@ -40,78 +39,95 @@ describe('Bootstrap Switch:', () => {
     expect(getOptions($switch2).state).toBe(false);
   });
 
-  it('should something', () => {
+  it('should trigger the same events on element and document', () => {
     const $switch = createCheckbox().bootstrapSwitch();
-    let eventDoc = 0;
-    let eventElement = 0;
-    $(document).on('switchChange.bootstrapSwitch', ':checkbox', () => { eventDoc += 1; });
-    $(':checkbox').on('switchChange.bootstrapSwitch', () => { eventElement += 1; });
-    $switch.click();
-    expect(eventElement).toEqual(eventDoc);
-    expect(eventElement).toEqual(1);
+    let doc = 0;
+    let element = 0;
+    $(document).on('switchChange.bootstrapSwitch', ':checkbox', () => { doc += 1; });
+    $switch.on('switchChange.bootstrapSwitch', () => { element += 1; });
+    $switch.bootstrapSwitch('state', true);
+    expect(element).toBe(doc);
+    expect(element).toBe(1);
   });
 
-  describe('The Checkbox Bootstrap Switch', () => {
-    it('should conserve its state if onSwitchChange returns false', () => {
+  describe('Checkbox', () => {
+    it('should retain state if `onSwitchChange` returns false', () => {
+      let shadowState = null;
       const $switch = createCheckbox().bootstrapSwitch({
+        state: false,
         onSwitchChange(event, state) {
-          expect(state).toEqual(true);
+          shadowState = state;
           return false;
         },
       });
-      const $indeterminateSwitch = createCheckbox().data('indeterminate', true).bootstrapSwitch({
+      $switch.bootstrapSwitch('state', true);
+      expect(shadowState).toBe(true);
+      expect($switch.bootstrapSwitch('state')).toBe(false);
+    });
+
+    it('should retain state if `onSwitchChange` returns false when intederminate is true', () => {
+      let shadowState;
+      const $indeterminate = createCheckbox().bootstrapSwitch({
+        state: false,
         onSwitchChange(event, state) {
-          expect(state).toEqual(true);
+          shadowState = state;
           return false;
         },
       });
-      $switch.click();
-      $indeterminateSwitch.click();
-      expect($switch.bootstrapSwitch('state')).toEqual(false);
-      expect($indeterminateSwitch.bootstrapSwitch('state')).toEqual(false);
+      $indeterminate.data('indeterminate', true);
+      $indeterminate.bootstrapSwitch('state', true);
+      expect(shadowState).toBe(true);
+      expect($indeterminate.bootstrapSwitch('state')).toBe(false);
     });
 
-    it('should change its state if onSwitchChange does not return false', () => {
+    it('should change state if `onSwitchChange` does not return false', () => {
+      let shadowState = null;
       const $switch = createCheckbox().bootstrapSwitch({
-        onSwitchChange(event, state) {
-          expect(state).toEqual(true);
+        onSwitchChange: (event, state) => {
+          shadowState = state;
         },
       });
-      $switch.click();
-      expect($switch.bootstrapSwitch('state')).toEqual(true);
+      $switch.bootstrapSwitch('state', true);
+      expect(shadowState).toBe(true);
+      expect($switch.bootstrapSwitch('state')).toBe(true);
     });
   });
 
-  describe('The Radio Bootstrap Switch', () => {
-    it('should conserve its state if onSwitchChange returns false', () => {
+  describe('Radio', () => {
+    it('should retain state if `onSwitchChange` returns false', () => {
       const $radio1 = createRadio().prop('checked', true);
       const $radio2 = createRadio().prop('checked', false);
       const $radio3 = createRadio().prop('checked', false);
-      $('[name="name"]').bootstrapSwitch({
-        onSwitchChange(e, s) {
-          expect(s).toEqual(true);
+      let shadowState = null;
+      $radio1.add($radio2).add($radio3).bootstrapSwitch({
+        onSwitchChange(event, state) {
+          shadowState = state;
           return false;
         },
       });
-      $radio2.click();
-      expect($radio1.bootstrapSwitch('state')).toEqual(true);
-      expect($radio2.bootstrapSwitch('state')).toEqual(false);
-      expect($radio3.bootstrapSwitch('state')).toEqual(false);
+      $radio2.bootstrapSwitch('state', true);
+      expect(shadowState).toBe(true);
+      expect($radio1.bootstrapSwitch('state')).toBe(true);
+      expect($radio2.bootstrapSwitch('state')).toBe(false);
+      expect($radio3.bootstrapSwitch('state')).toBe(false);
     });
 
-    it('should change its state if onSwitchChange not returns false', () => {
+    it('should change its state if `onSwitchChange` does not return false', () => {
       const $radio1 = createRadio().prop('checked', true);
       const $radio2 = createRadio().prop('checked', false);
       const $radio3 = createRadio().prop('checked', false);
-      $('[name="name"]').bootstrapSwitch({
-        onSwitchChange(e, s) {
-          expect(s).toEqual(true);
+      let shadowState = null;
+      $radio2.bootstrapSwitch({
+        onSwitchChange(event, state) {
+          shadowState = state;
+          return false;
         },
       });
       $radio2.click();
-      expect($radio1.bootstrapSwitch('state')).toEqual(false);
-      expect($radio2.bootstrapSwitch('state')).toEqual(true);
-      expect($radio3.bootstrapSwitch('state')).toEqual(false);
+      expect(shadowState).toBe(true);
+      expect($radio1.bootstrapSwitch('state')).toBe(false);
+      expect($radio2.bootstrapSwitch('state')).toBe(true);
+      expect($radio3.bootstrapSwitch('state')).toBe(false);
     });
   });
 });

+ 4 - 0
src/setup-test.js

@@ -0,0 +1,4 @@
+import $ from 'jquery';
+
+global.jQuery = $;
+global.$ = global.jQuery;

File diff suppressed because it is too large
+ 377 - 246
yarn.lock


Some files were not shown because too many files changed in this diff