diff options
| author | Johann-S <[email protected]> | 2019-10-02 11:43:54 +0200 |
|---|---|---|
| committer | Johann-S <[email protected]> | 2019-10-03 09:55:57 +0200 |
| commit | 3d12b541c488ea09efced2fb987fcbf384c656bb (patch) | |
| tree | 1863095dd8162e25a1909cf741e32faa091c32d4 /js/src/button | |
| parent | 393ddae09b0578c8d381540bdbb4e68cdec1b45b (diff) | |
| download | bootstrap-3d12b541c488ea09efced2fb987fcbf384c656bb.tar.xz bootstrap-3d12b541c488ea09efced2fb987fcbf384c656bb.zip | |
return to the original file structure to avoid breaking modularity
Diffstat (limited to 'js/src/button')
| -rw-r--r-- | js/src/button/button.js | 200 | ||||
| -rw-r--r-- | js/src/button/button.spec.js | 292 |
2 files changed, 0 insertions, 492 deletions
diff --git a/js/src/button/button.js b/js/src/button/button.js deleted file mode 100644 index 4418ba6b8..000000000 --- a/js/src/button/button.js +++ /dev/null @@ -1,200 +0,0 @@ -/** - * -------------------------------------------------------------------------- - * Bootstrap (v4.3.1): button.js - * Licensed under MIT (https://github.com/twbs/bootstrap/blob/master/LICENSE) - * -------------------------------------------------------------------------- - */ - -import { getjQuery } from '../util/index' -import Data from '../dom/data' -import EventHandler from '../dom/event-handler' -import SelectorEngine from '../dom/selector-engine' - -/** - * ------------------------------------------------------------------------ - * Constants - * ------------------------------------------------------------------------ - */ - -const NAME = 'button' -const VERSION = '4.3.1' -const DATA_KEY = 'bs.button' -const EVENT_KEY = `.${DATA_KEY}` -const DATA_API_KEY = '.data-api' - -const ClassName = { - ACTIVE: 'active', - BUTTON: 'btn', - FOCUS: 'focus' -} - -const Selector = { - DATA_TOGGLE_CARROT: '[data-toggle^="button"]', - DATA_TOGGLE: '[data-toggle="buttons"]', - INPUT: 'input:not([type="hidden"])', - ACTIVE: '.active', - BUTTON: '.btn' -} - -const Event = { - CLICK_DATA_API: `click${EVENT_KEY}${DATA_API_KEY}`, - FOCUS_DATA_API: `focus${EVENT_KEY}${DATA_API_KEY}`, - BLUR_DATA_API: `blur${EVENT_KEY}${DATA_API_KEY}` -} - -/** - * ------------------------------------------------------------------------ - * Class Definition - * ------------------------------------------------------------------------ - */ - -class Button { - constructor(element) { - this._element = element - Data.setData(element, DATA_KEY, this) - } - - // Getters - - static get VERSION() { - return VERSION - } - - // Public - - toggle() { - let triggerChangeEvent = true - let addAriaPressed = true - - const rootElement = SelectorEngine.closest( - this._element, - Selector.DATA_TOGGLE - ) - - if (rootElement) { - const input = SelectorEngine.findOne(Selector.INPUT, this._element) - - if (input && input.type === 'radio') { - if (input.checked && - this._element.classList.contains(ClassName.ACTIVE)) { - triggerChangeEvent = false - } else { - const activeElement = SelectorEngine.findOne(Selector.ACTIVE, rootElement) - - if (activeElement) { - activeElement.classList.remove(ClassName.ACTIVE) - } - } - - if (triggerChangeEvent) { - if (input.hasAttribute('disabled') || - rootElement.hasAttribute('disabled') || - input.classList.contains('disabled') || - rootElement.classList.contains('disabled')) { - return - } - - input.checked = !this._element.classList.contains(ClassName.ACTIVE) - EventHandler.trigger(input, 'change') - } - - input.focus() - addAriaPressed = false - } - } - - if (addAriaPressed) { - this._element.setAttribute('aria-pressed', - !this._element.classList.contains(ClassName.ACTIVE)) - } - - if (triggerChangeEvent) { - this._element.classList.toggle(ClassName.ACTIVE) - } - } - - dispose() { - Data.removeData(this._element, DATA_KEY) - this._element = null - } - - // Static - - static jQueryInterface(config) { - return this.each(function () { - let data = Data.getData(this, DATA_KEY) - - if (!data) { - data = new Button(this) - } - - if (config === 'toggle') { - data[config]() - } - }) - } - - static getInstance(element) { - return Data.getData(element, DATA_KEY) - } -} - -/** - * ------------------------------------------------------------------------ - * Data Api implementation - * ------------------------------------------------------------------------ - */ - -EventHandler.on(document, Event.CLICK_DATA_API, Selector.DATA_TOGGLE_CARROT, event => { - event.preventDefault() - - let button = event.target - if (!button.classList.contains(ClassName.BUTTON)) { - button = SelectorEngine.closest(button, Selector.BUTTON) - } - - let data = Data.getData(button, DATA_KEY) - if (!data) { - data = new Button(button) - } - - data.toggle() -}) - -EventHandler.on(document, Event.FOCUS_DATA_API, Selector.DATA_TOGGLE_CARROT, event => { - const button = SelectorEngine.closest(event.target, Selector.BUTTON) - - if (button) { - button.classList.add(ClassName.FOCUS) - } -}) - -EventHandler.on(document, Event.BLUR_DATA_API, Selector.DATA_TOGGLE_CARROT, event => { - const button = SelectorEngine.closest(event.target, Selector.BUTTON) - - if (button) { - button.classList.remove(ClassName.FOCUS) - } -}) - -const $ = getjQuery() - -/** - * ------------------------------------------------------------------------ - * jQuery - * ------------------------------------------------------------------------ - * add .button to jQuery only if jQuery is present - */ -/* istanbul ignore if */ -if ($) { - const JQUERY_NO_CONFLICT = $.fn[NAME] - $.fn[NAME] = Button.jQueryInterface - $.fn[NAME].Constructor = Button - - $.fn[NAME].noConflict = () => { - $.fn[NAME] = JQUERY_NO_CONFLICT - return Button.jQueryInterface - } -} - -export default Button diff --git a/js/src/button/button.spec.js b/js/src/button/button.spec.js deleted file mode 100644 index 622881185..000000000 --- a/js/src/button/button.spec.js +++ /dev/null @@ -1,292 +0,0 @@ -import Button from './button' -import EventHandler from '../dom/event-handler' - -/** Test helpers */ -import { - getFixture, - clearFixture, - createEvent, - jQueryMock -} from '../../tests/helpers/fixture' - -describe('Button', () => { - let fixtureEl - - beforeAll(() => { - fixtureEl = getFixture() - }) - - afterEach(() => { - clearFixture() - }) - - describe('VERSION', () => { - it('should return plugin version', () => { - expect(Button.VERSION).toEqual(jasmine.any(String)) - }) - }) - - describe('data-api', () => { - it('should toggle active class on click', () => { - fixtureEl.innerHTML = [ - '<button class="btn" data-toggle="button">btn</button>', - '<button class="btn testParent" data-toggle="button"><div class="test"></div></button>' - ].join('') - - const btn = fixtureEl.querySelector('.btn') - const divTest = fixtureEl.querySelector('.test') - const btnTestParent = fixtureEl.querySelector('.testParent') - - expect(btn.classList.contains('active')).toEqual(false) - - btn.click() - - expect(btn.classList.contains('active')).toEqual(true) - - btn.click() - - expect(btn.classList.contains('active')).toEqual(false) - - divTest.click() - - expect(btnTestParent.classList.contains('active')).toEqual(true) - }) - - it('should trigger input change event when toggled button has input field', done => { - fixtureEl.innerHTML = [ - '<div class="btn-group" data-toggle="buttons">', - ' <label class="btn btn-primary">', - ' <input type="radio" id="radio" autocomplete="off"> Radio', - ' </label>', - '</div>' - ].join('') - - const input = fixtureEl.querySelector('input') - const label = fixtureEl.querySelector('label') - - input.addEventListener('change', () => { - expect().nothing() - done() - }) - - label.click() - }) - - it('should not trigger input change event when input already checked and button is active', () => { - fixtureEl.innerHTML = [ - '<button type="button" class="btn btn-primary active" data-toggle="buttons">', - ' <input type="radio" id="radio" autocomplete="off" checked> Radio', - '</button>' - ].join('') - - const button = fixtureEl.querySelector('button') - - spyOn(EventHandler, 'trigger') - - button.click() - - expect(EventHandler.trigger).not.toHaveBeenCalled() - }) - - it('should remove active when an other radio button is clicked', () => { - fixtureEl.innerHTML = [ - '<div class="btn-group btn-group-toggle" data-toggle="buttons">', - ' <label class="btn btn-secondary active">', - ' <input type="radio" name="options" id="option1" autocomplete="off" checked> Active', - ' </label>', - ' <label class="btn btn-secondary">', - ' <input type="radio" name="options" id="option2" autocomplete="off"> Radio', - ' </label>', - ' <label class="btn btn-secondary">', - ' <input type="radio" name="options" id="option3" autocomplete="off"> Radio', - ' </label>', - '</div>' - ].join('') - - const option1 = fixtureEl.querySelector('#option1') - const option2 = fixtureEl.querySelector('#option2') - - expect(option1.checked).toEqual(true) - expect(option1.parentElement.classList.contains('active')).toEqual(true) - - const clickEvent = createEvent('click') - - option2.dispatchEvent(clickEvent) - - expect(option1.checked).toEqual(false) - expect(option1.parentElement.classList.contains('active')).toEqual(false) - expect(option2.checked).toEqual(true) - expect(option2.parentElement.classList.contains('active')).toEqual(true) - }) - - it('should do nothing if the child is not an input', () => { - fixtureEl.innerHTML = [ - '<div class="btn-group btn-group-toggle" data-toggle="buttons">', - ' <label class="btn btn-secondary active">', - ' <span id="option1">el 1</span>', - ' </label>', - ' <label class="btn btn-secondary">', - ' <span id="option2">el 2</span>', - ' </label>', - ' <label class="btn btn-secondary">', - ' <span>el 3</span>', - ' </label>', - '</div>' - ].join('') - - const option2 = fixtureEl.querySelector('#option2') - const clickEvent = createEvent('click') - - option2.dispatchEvent(clickEvent) - - expect().nothing() - }) - - it('should add focus class on focus event', () => { - fixtureEl.innerHTML = '<button class="btn" data-toggle="button"><input type="text" /></button>' - - const btn = fixtureEl.querySelector('.btn') - const input = fixtureEl.querySelector('input') - - const focusEvent = createEvent('focus') - input.dispatchEvent(focusEvent) - - expect(btn.classList.contains('focus')).toEqual(true) - }) - - it('should not add focus class', () => { - fixtureEl.innerHTML = '<button data-toggle="button"><input type="text" /></button>' - - const btn = fixtureEl.querySelector('button') - const input = fixtureEl.querySelector('input') - - const focusEvent = createEvent('focus') - input.dispatchEvent(focusEvent) - - expect(btn.classList.contains('focus')).toEqual(false) - }) - - it('should remove focus class on blur event', () => { - fixtureEl.innerHTML = '<button class="btn focus" data-toggle="button"><input type="text" /></button>' - - const btn = fixtureEl.querySelector('.btn') - const input = fixtureEl.querySelector('input') - - const focusEvent = createEvent('blur') - input.dispatchEvent(focusEvent) - - expect(btn.classList.contains('focus')).toEqual(false) - }) - - it('should not remove focus class on blur event', () => { - fixtureEl.innerHTML = '<button class="focus" data-toggle="button"><input type="text" /></button>' - - const btn = fixtureEl.querySelector('button') - const input = fixtureEl.querySelector('input') - - const focusEvent = createEvent('blur') - input.dispatchEvent(focusEvent) - - expect(btn.classList.contains('focus')).toEqual(true) - }) - }) - - describe('toggle', () => { - it('should toggle aria-pressed', () => { - fixtureEl.innerHTML = '<button class="btn" data-toggle="button" aria-pressed="false"></button>' - - const btnEl = fixtureEl.querySelector('.btn') - const button = new Button(btnEl) - - expect(btnEl.getAttribute('aria-pressed')).toEqual('false') - expect(btnEl.classList.contains('active')).toEqual(false) - - button.toggle() - - expect(btnEl.getAttribute('aria-pressed')).toEqual('true') - expect(btnEl.classList.contains('active')).toEqual(true) - }) - - it('should handle disabled attribute on non-button elements', () => { - fixtureEl.innerHTML = [ - '<div class="btn-group disabled" data-toggle="buttons" aria-disabled="true" disabled>', - ' <label class="btn btn-danger disabled" aria-disabled="true" disabled>', - ' <input type="checkbox" aria-disabled="true" autocomplete="off" disabled class="disabled"/>', - ' </label>', - '</div>' - ].join('') - - const btnGroupEl = fixtureEl.querySelector('.btn-group') - const btnDanger = fixtureEl.querySelector('.btn-danger') - const input = fixtureEl.querySelector('input') - - const button = new Button(btnGroupEl) - - button.toggle() - - expect(btnDanger.hasAttribute('disabled')).toEqual(true) - expect(input.checked).toEqual(false) - }) - }) - - describe('dispose', () => { - it('should dispose a button', () => { - fixtureEl.innerHTML = '<button class="btn" data-toggle="button"></button>' - - const btnEl = fixtureEl.querySelector('.btn') - const button = new Button(btnEl) - - expect(Button.getInstance(btnEl)).toBeDefined() - - button.dispose() - - expect(Button.getInstance(btnEl)).toBeNull() - }) - }) - - describe('jQueryInterface', () => { - it('should handle config passed and toggle existing button', () => { - fixtureEl.innerHTML = '<button class="btn" data-toggle="button"></button>' - - const btnEl = fixtureEl.querySelector('.btn') - const button = new Button(btnEl) - - spyOn(button, 'toggle') - - jQueryMock.fn.button = Button.jQueryInterface - jQueryMock.elements = [btnEl] - - jQueryMock.fn.button.call(jQueryMock, 'toggle') - - expect(button.toggle).toHaveBeenCalled() - }) - - it('should create new button instance and call toggle', () => { - fixtureEl.innerHTML = '<button class="btn" data-toggle="button"></button>' - - const btnEl = fixtureEl.querySelector('.btn') - - jQueryMock.fn.button = Button.jQueryInterface - jQueryMock.elements = [btnEl] - - jQueryMock.fn.button.call(jQueryMock, 'toggle') - - expect(Button.getInstance(btnEl)).toBeDefined() - expect(btnEl.classList.contains('active')).toEqual(true) - }) - - it('should just create a button instance without calling toggle', () => { - fixtureEl.innerHTML = '<button class="btn" data-toggle="button"></button>' - - const btnEl = fixtureEl.querySelector('.btn') - - jQueryMock.fn.button = Button.jQueryInterface - jQueryMock.elements = [btnEl] - - jQueryMock.fn.button.call(jQueryMock) - - expect(Button.getInstance(btnEl)).toBeDefined() - expect(btnEl.classList.contains('active')).toEqual(false) - }) - }) -}) |
