diff --git a/Gruntfile.js b/Gruntfile.js index 09268ecb1..c32f79f0e 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -64,7 +64,8 @@ module.exports = function (grunt) { dist: { files: { 'js/dist/util.js': 'js/src/util.js', - 'js/dist/alert.js': 'js/src/alert.js' + 'js/dist/alert.js': 'js/src/alert.js', + 'js/dist/button.js': 'js/src/button.js', } } }, diff --git a/js/dist/alert.js b/js/dist/alert.js index 76b280a0c..4226dd61a 100644 --- a/js/dist/alert.js +++ b/js/dist/alert.js @@ -11,7 +11,7 @@ function _classCallCheck(instance, Constructor) { if (!(instance instanceof Cons * -------------------------------------------------------------------------- */ -var Alert = (function () { +var Alert = (function ($) { /** * ------------------------------------------------------------------------ @@ -62,6 +62,8 @@ var Alert = (function () { // public value: function close(element) { + element = element || this.element; + var rootElement = this._getRootElement(element); var customEvent = this._triggerCloseEvent(rootElement); @@ -167,10 +169,10 @@ var Alert = (function () { $.fn[NAME] = Alert._jQueryInterface; $.fn[NAME].Constructor = Alert; $.fn[NAME].noConflict = function () { - $.fn[NAME] = Alert._JQUERY_NO_CONFLICT; + $.fn[NAME] = JQUERY_NO_CONFLICT; return Alert._jQueryInterface; }; return Alert; -})(); +})(jQuery); //# sourceMappingURL=alert.js.map \ No newline at end of file diff --git a/js/dist/alert.js.map b/js/dist/alert.js.map index f3bc7ad7f..aa106df1e 100644 Binary files a/js/dist/alert.js.map and b/js/dist/alert.js.map differ diff --git a/js/dist/button.js b/js/dist/button.js new file mode 100644 index 000000000..76aa09a7f --- /dev/null +++ b/js/dist/button.js @@ -0,0 +1,158 @@ +'use strict'; + +var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); + +function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } + +/** + * -------------------------------------------------------------------------- + * Bootstrap (v4.0.0): button.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + +var Button = (function ($) { + + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + + var NAME = 'button'; + var VERSION = '4.0.0'; + var DATA_KEY = 'bs.button'; + var JQUERY_NO_CONFLICT = $.fn[NAME]; + var TRANSITION_DURATION = 150; + + var ClassName = { + ACTIVE: 'active', + BUTTON: 'btn', + FOCUS: 'focus' + }; + + var Selector = { + DATA_TOGGLE_CARROT: '[data-toggle^="button"]', + DATA_TOGGLE: '[data-toggle="buttons"]', + INPUT: 'input', + ACTIVE: '.active', + BUTTON: '.btn' + }; + + var Event = { + CLICK: 'click.bs.button.data-api', + FOCUS_BLUR: 'focus.bs.button.data-api blur.bs.button.data-api' + }; + + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + var Button = (function () { + function Button(element) { + _classCallCheck(this, Button); + + this.element = element; + } + + _createClass(Button, [{ + key: 'toggle', + + // public + + value: function toggle() { + var triggerChangeEvent = true; + var rootElement = $(this.element).closest(Selector.DATA_TOGGLE)[0]; + + if (rootElement) { + var input = $(this.element).find(Selector.INPUT)[0]; + + if (input) { + if (input.type === 'radio') { + if (input.checked && $(this.element).hasClass(ClassName.ACTIVE)) { + triggerChangeEvent = false; + } else { + var activeElement = $(rootElement).find(Selector.ACTIVE)[0]; + + if (activeElement) { + $(activeElement).removeClass(ClassName.ACTIVE); + } + } + } + + if (triggerChangeEvent) { + input.checked = !$(this.element).hasClass(ClassName.ACTIVE); + $(this.element).trigger('change'); + } + } + } else { + this.element.setAttribute('aria-pressed', !$(this.element).hasClass(ClassName.ACTIVE)); + } + + if (triggerChangeEvent) { + $(this.element).toggleClass(ClassName.ACTIVE); + } + } + }], [{ + key: '_jQueryInterface', + + // static + + value: function _jQueryInterface(config) { + return this.each(function () { + var data = $(this).data(DATA_KEY); + + if (!data) { + data = new Button(this); + $(this).data(DATA_KEY, data); + } + + if (config === 'toggle') { + data[config](); + } + }); + } + }]); + + return Button; + })(); + + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + $(document).on(Event.CLICK, Selector.DATA_TOGGLE_CARROT, function (event) { + event.preventDefault(); + + var button = event.target; + + if (!$(button).hasClass(ClassName.BUTTON)) { + button = $(button).closest(Selector.BUTTON); + } + + Button._jQueryInterface.call($(button), 'toggle'); + }).on(Event.FOCUS_BLUR, Selector.DATA_TOGGLE_CARROT, function (event) { + var button = $(event.target).closest(Selector.BUTTON)[0]; + $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type)); + }); + + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $.fn[NAME] = Button._jQueryInterface; + $.fn[NAME].Constructor = Button; + $.fn[NAME].noConflict = function () { + $.fn[NAME] = JQUERY_NO_CONFLICT; + return Button._jQueryInterface; + }; + + return Button; +})(jQuery); +//# sourceMappingURL=button.js.map \ No newline at end of file diff --git a/js/dist/button.js.map b/js/dist/button.js.map new file mode 100644 index 000000000..690b5e0dc Binary files /dev/null and b/js/dist/button.js.map differ diff --git a/js/dist/util.js b/js/dist/util.js index 4c8c4e639..4f25e200d 100644 --- a/js/dist/util.js +++ b/js/dist/util.js @@ -7,7 +7,7 @@ 'use strict'; -var Util = (function () { +var Util = (function ($) { /** * ------------------------------------------------------------------------ @@ -119,5 +119,5 @@ var Util = (function () { setTransitionEndSupport(); return Util; -})(); +})(jQuery); //# sourceMappingURL=util.js.map \ No newline at end of file diff --git a/js/dist/util.js.map b/js/dist/util.js.map index 71ad2163a..5f640b50e 100644 Binary files a/js/dist/util.js.map and b/js/dist/util.js.map differ diff --git a/js/script-compiled.js b/js/script-compiled.js deleted file mode 100644 index 2a50eb3b3..000000000 --- a/js/script-compiled.js +++ /dev/null @@ -1,305 +0,0 @@ -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); - -var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); - -function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } - -function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } - -/** - * -------------------------------------------------------------------------- - * Bootstrap (v4.0.0): alert.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * -------------------------------------------------------------------------- - */ - -var _util = require('util'); - -var _util2 = _interopRequireDefault(_util); - -/** - * -------------------------------------------------------------------------- - * Constants - * -------------------------------------------------------------------------- - */ - -var NAME = 'alert'; -var VERSION = '4.0.0'; -var DATA_KEY = 'bs.alert'; -var JQUERY_NO_CONFLICT = $.fn[NAME]; -var TRANSITION_DURATION = 150; - -var Selector = { - DISMISS: '[data-dismiss="alert"]' -}; - -var Event = { - CLOSE: 'close.bs.alert', - CLOSED: 'closed.bs.alert', - CLICK: 'click.bs.alert.data-api' -}; - -var ClassName = { - ALERT: 'alert', - FADE: 'fade', - IN: 'in' -}; - -/** - * -------------------------------------------------------------------------- - * Class Definition - * -------------------------------------------------------------------------- - */ - -var Alert = (function () { - function Alert(element) { - _classCallCheck(this, Alert); - - if (element) { - this.element = element; - } - } - - _createClass(Alert, [{ - key: 'close', - - // public - - value: function close(element) { - var rootElement = this._getRootElement(element); - var customEvent = this._triggerCloseEvent(rootElement); - - if (customEvent.isDefaultPrevented()) { - return; - } - - this._removeElement(rootElement); - } - }, { - key: '_getRootElement', - - // private - - value: function _getRootElement(element) { - var parent = false; - var selector = _util2['default'].getSelectorFromElement(element); - - if (selector) { - parent = $(selector)[0]; - } - - if (!parent) { - parent = $(element).closest('.' + ClassName.ALERT)[0]; - } - - return parent; - } - }, { - key: '_triggerCloseEvent', - value: function _triggerCloseEvent(element) { - var closeEvent = $.Event(Event.CLOSE); - $(element).trigger(closeEvent); - return closeEvent; - } - }, { - key: '_removeElement', - value: function _removeElement(element) { - $(element).removeClass(ClassName.IN); - - if (!_util2['default'].supportsTransitionEnd() || !$(element).hasClass(ClassName.FADE)) { - this._destroyElement(element); - return; - } - - $(element).one(_util2['default'].TRANSITION_END, this._destroyElement.bind(this, element)).emulateTransitionEnd(TRANSITION_DURATION); - } - }, { - key: '_destroyElement', - value: function _destroyElement(element) { - $(element).detach().trigger(Event.CLOSED).remove(); - } - }], [{ - key: '_jQueryInterface', - - // static - - value: function _jQueryInterface(config) { - return this.each(function () { - var $element = $(this); - var data = $element.data(DATA_KEY); - - if (!data) { - data = new Alert(this); - $element.data(DATA_KEY, data); - } - - if (config === 'close') { - data[config](this); - } - }); - } - }, { - key: '_handleDismiss', - value: function _handleDismiss(alertInstance) { - return function (event) { - if (event) { - event.preventDefault(); - } - - alertInstance.close(this); - }; - } - }]); - - return Alert; -})(); - -exports.Alert = Alert; - -/** - * -------------------------------------------------------------------------- - * Data Api implementation - * -------------------------------------------------------------------------- - */ - -$(document).on(Event.CLICK, Selector.DISMISS, Alert._handleDismiss(new Alert())); - -/** - * -------------------------------------------------------------------------- - * jQuery - * -------------------------------------------------------------------------- - */ - -$.fn[NAME] = Alert._jQueryInterface; -$.fn[NAME].Constructor = Alert; -$.fn[NAME].noConflict = function () { - $.fn[NAME] = Alert._JQUERY_NO_CONFLICT; - return Alert._jQueryInterface; -}; -'use strict'; - -Object.defineProperty(exports, '__esModule', { - value: true -}); -/** - * -------------------------------------------------------------------------- - * Bootstrap (v4.0.0): util.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * -------------------------------------------------------------------------- - */ - -/** - * -------------------------------------------------------------------------- - * Public Util Api - * -------------------------------------------------------------------------- - */ - -var Util = { - - TRANSITION_END: 'bsTransitionEnd', - - getUID: function getUID(prefix) { - do prefix += ~ ~(Math.random() * 1000000); while (document.getElementById(prefix)); - return prefix; - }, - - getSelectorFromElement: function getSelectorFromElement(element) { - var selector = element.getAttribute('data-target'); - - if (!selector) { - selector = element.getAttribute('href') || ''; - selector = /^#[a-z]/i.test(selector) ? selector : null; - } - - return selector; - }, - - reflow: function reflow(element) { - new Function('bs', 'return bs')(element.offsetHeight); - }, - - supportsTransitionEnd: function supportsTransitionEnd() { - return !!transition; - } - -}; - -exports['default'] = Util; - -/** - * -------------------------------------------------------------------------- - * Private TransitionEnd Helpers - * -------------------------------------------------------------------------- - */ - -var transition = false; - -var TransitionEndEvent = { - WebkitTransition: 'webkitTransitionEnd', - MozTransition: 'transitionend', - OTransition: 'oTransitionEnd otransitionend', - transition: 'transitionend' -}; - -function getSpecialTransitionEndEvent() { - return { - bindType: transition.end, - delegateType: transition.end, - handle: function handle(event) { - if ($(event.target).is(this)) { - return event.handleObj.handler.apply(this, arguments); - } - } - }; -} - -function transitionEndTest() { - if (window.QUnit) { - return false; - } - - var el = document.createElement('bootstrap'); - - for (var name in TransitionEndEvent) { - if (el.style[name] !== undefined) { - return { end: TransitionEndEvent[name] }; - } - } - - return false; -} - -function transitionEndEmulator(duration) { - var _this = this; - - var called = false; - - $(this).one(Util.TRANSITION_END, function () { - called = true; - }); - - setTimeout(function () { - if (!called) { - $(_this).trigger(transition.end); - } - }, duration); - - return this; -} - -function setTransitionEndSupport() { - transition = transitionEndTest(); - - $.fn.emulateTransitionEnd = transitionEndEmulator; - - if (Util.supportsTransitionEnd()) { - $.event.special[Util.TRANSITION_END] = getSpecialTransitionEndEvent(); - } -} - -setTransitionEndSupport(); -module.exports = exports['default']; diff --git a/js/src/alert.js b/js/src/alert.js index d69ad8910..67a1ceda4 100644 --- a/js/src/alert.js +++ b/js/src/alert.js @@ -8,7 +8,7 @@ import Util from './util' * -------------------------------------------------------------------------- */ -const Alert = (() => { +const Alert = (($) => { /** @@ -58,6 +58,8 @@ const Alert = (() => { // public close(element) { + element = element || this.element + let rootElement = this._getRootElement(element) let customEvent = this._triggerCloseEvent(rootElement) @@ -167,12 +169,12 @@ const Alert = (() => { $.fn[NAME] = Alert._jQueryInterface $.fn[NAME].Constructor = Alert $.fn[NAME].noConflict = function () { - $.fn[NAME] = Alert._JQUERY_NO_CONFLICT + $.fn[NAME] = JQUERY_NO_CONFLICT return Alert._jQueryInterface } return Alert -})() +})(jQuery) export default Alert diff --git a/js/src/button.js b/js/src/button.js new file mode 100644 index 000000000..7e9344923 --- /dev/null +++ b/js/src/button.js @@ -0,0 +1,158 @@ +/** + * -------------------------------------------------------------------------- + * Bootstrap (v4.0.0): button.js + * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) + * -------------------------------------------------------------------------- + */ + +const Button = (($) => { + + + /** + * ------------------------------------------------------------------------ + * Constants + * ------------------------------------------------------------------------ + */ + + const NAME = 'button' + const VERSION = '4.0.0' + const DATA_KEY = 'bs.button' + const JQUERY_NO_CONFLICT = $.fn[NAME] + const TRANSITION_DURATION = 150 + + const ClassName = { + ACTIVE : 'active', + BUTTON : 'btn', + FOCUS : 'focus' + } + + const Selector = { + DATA_TOGGLE_CARROT : '[data-toggle^="button"]', + DATA_TOGGLE : '[data-toggle="buttons"]', + INPUT : 'input', + ACTIVE : '.active', + BUTTON : '.btn' + } + + const Event = { + CLICK : 'click.bs.button.data-api', + FOCUS_BLUR : 'focus.bs.button.data-api blur.bs.button.data-api' + } + + + /** + * ------------------------------------------------------------------------ + * Class Definition + * ------------------------------------------------------------------------ + */ + + class Button { + + constructor(element) { + this.element = element + } + + // public + + toggle() { + let triggerChangeEvent = true + let rootElement = $(this.element).closest( + Selector.DATA_TOGGLE + )[0] + + if (rootElement) { + let input = $(this.element).find(Selector.INPUT)[0] + + if (input) { + if (input.type === 'radio') { + if (input.checked && + $(this.element).hasClass(ClassName.ACTIVE)) { + triggerChangeEvent = false + + } else { + let activeElement = $(rootElement).find(Selector.ACTIVE)[0] + + if (activeElement) { + $(activeElement).removeClass(ClassName.ACTIVE) + } + } + } + + if (triggerChangeEvent) { + input.checked = !$(this.element).hasClass(ClassName.ACTIVE) + $(this.element).trigger('change') + } + } + } else { + this.element.setAttribute('aria-pressed', + !$(this.element).hasClass(ClassName.ACTIVE)) + } + + if (triggerChangeEvent) { + $(this.element).toggleClass(ClassName.ACTIVE) + } + } + + + // static + + static _jQueryInterface(config) { + return this.each(function () { + let data = $(this).data(DATA_KEY) + + if (!data) { + data = new Button(this) + $(this).data(DATA_KEY, data) + } + + if (config === 'toggle') { + data[config]() + } + }) + } + + } + + + /** + * ------------------------------------------------------------------------ + * Data Api implementation + * ------------------------------------------------------------------------ + */ + + $(document) + .on(Event.CLICK, Selector.DATA_TOGGLE_CARROT, function (event) { + event.preventDefault() + + let button = event.target + + if (!$(button).hasClass(ClassName.BUTTON)) { + button = $(button).closest(Selector.BUTTON) + } + + Button._jQueryInterface.call($(button), 'toggle') + }) + .on(Event.FOCUS_BLUR, Selector.DATA_TOGGLE_CARROT, function (event) { + var button = $(event.target).closest(Selector.BUTTON)[0] + $(button).toggleClass(ClassName.FOCUS, /^focus(in)?$/.test(event.type)) + }) + + + /** + * ------------------------------------------------------------------------ + * jQuery + * ------------------------------------------------------------------------ + */ + + $.fn[NAME] = Button._jQueryInterface + $.fn[NAME].Constructor = Button + $.fn[NAME].noConflict = function () { + $.fn[NAME] = JQUERY_NO_CONFLICT + return Button._jQueryInterface + } + + return Button + +})(jQuery) + +export default Button diff --git a/js/src/util.js b/js/src/util.js index 68205edef..abc548a45 100644 --- a/js/src/util.js +++ b/js/src/util.js @@ -5,7 +5,7 @@ * -------------------------------------------------------------------------- */ -const Util = (() => { +const Util = (($) => { /** @@ -119,6 +119,6 @@ const Util = (() => { return Util -})() +})(jQuery) export default Util diff --git a/js/tests/index.html b/js/tests/index.html index 536e34c74..29c84e2cc 100644 --- a/js/tests/index.html +++ b/js/tests/index.html @@ -132,9 +132,9 @@ + - diff --git a/js/tests/unit/button.js b/js/tests/unit/button.js index 691796c42..5648506cf 100644 --- a/js/tests/unit/button.js +++ b/js/tests/unit/button.js @@ -32,64 +32,6 @@ $(function () { assert.strictEqual($button[0], $el[0], 'collection contains element') }) - QUnit.test('should return set state to loading', function (assert) { - assert.expect(4) - var $btn = $('') - assert.strictEqual($btn.html(), 'mdo', 'btn text equals mdo') - $btn.bootstrapButton('loading') - var done = assert.async() - setTimeout(function () { - assert.strictEqual($btn.html(), 'fat', 'btn text equals fat') - assert.ok($btn[0].hasAttribute('disabled'), 'btn is disabled') - assert.ok($btn.hasClass('disabled'), 'btn has disabled class') - done() - }, 0) - }) - - QUnit.test('should return reset state', function (assert) { - assert.expect(7) - var $btn = $('') - assert.strictEqual($btn.html(), 'mdo', 'btn text equals mdo') - $btn.bootstrapButton('loading') - var doneOne = assert.async() - setTimeout(function () { - assert.strictEqual($btn.html(), 'fat', 'btn text equals fat') - assert.ok($btn[0].hasAttribute('disabled'), 'btn is disabled') - assert.ok($btn.hasClass('disabled'), 'btn has disabled class') - doneOne() - var doneTwo = assert.async() - $btn.bootstrapButton('reset') - setTimeout(function () { - assert.strictEqual($btn.html(), 'mdo', 'btn text equals mdo') - assert.ok(!$btn[0].hasAttribute('disabled'), 'btn is not disabled') - assert.ok(!$btn.hasClass('disabled'), 'btn does not have disabled class') - doneTwo() - }, 0) - }, 0) - }) - - QUnit.test('should work with an empty string as reset state', function (assert) { - assert.expect(7) - var $btn = $('') diff --git a/js/tests/visual/button.html b/js/tests/visual/button.html index d92a08329..a6eed7e05 100644 --- a/js/tests/visual/button.html +++ b/js/tests/visual/button.html @@ -22,10 +22,6 @@

Button Bootstrap Visual Test

- -
@@ -56,8 +52,8 @@ - - + +