Skip to content

Commit

Permalink
Apply init/destroy EventListeners feature to modal component (#602)
Browse files Browse the repository at this point in the history
This PR adds the eventListeners option to the modal component along with the `initEventListeners()` and `destroyEventListeners()` methods to the API.

This PR fixes #601
  • Loading branch information
sebnitu committed May 29, 2021
1 parent 4864d14 commit d0766d9
Show file tree
Hide file tree
Showing 7 changed files with 157 additions and 4 deletions.
26 changes: 26 additions & 0 deletions docs/_packages/modal.md
Original file line number Diff line number Diff line change
Expand Up @@ -574,6 +574,11 @@ Adjusts the size of modals. This modifier provides two options, `modal_size_sm`
<td data-mobile-label="Default"><code class="code color-secondary text-nowrap">'modal:'</code></td>
<td data-mobile-label="Desc">Prefix to be used on custom events.</td>
</tr>
<tr>
<td data-mobile-label="Key"><code class="code text-nowrap">eventListeners</code></td>
<td data-mobile-label="Default"><code class="code color-secondary text-nowrap">true</code></td>
<td data-mobile-label="Desc">Whether or not to set the document event listeners on init.</td>
</tr>
<tr>
<td data-mobile-label="Key"><code class="code text-nowrap">moveModals</code></td>
<td data-mobile-label="Default">
Expand Down Expand Up @@ -634,6 +639,27 @@ modal.init();
modal.destroy();
```

### `modal.initEventListeners()`

Set the document event listeners for click, touchend and keyup events.

```js
const modal = new Modal({ eventListeners: false });
modal.init();
modal.initEventListeners();
```

### `modal.destroyEventListeners()`

Remove the document event listeners for click, touchend and keyup events.

```js
const modal = new Modal();
modal.init();
// ...
modal.destroyEventListeners();
```

### `modal.open(key)`

Opens a modal provided the modal key and returns a promise that resolves to the modal object once the transition has finished.
Expand Down
2 changes: 1 addition & 1 deletion docs/dist/bundle.js

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion docs/dist/bundle.js.map

Large diffs are not rendered by default.

22 changes: 22 additions & 0 deletions packages/modal/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -208,6 +208,7 @@ Adjusts the size of modals. This modifier provides two options, `modal_size_sm`
| `selectorInert` | `null` | Applies `inert` and `aria-hidden` attributes to all matching elements when a modal is opened. |
| `selectorOverflow` | `'body'` | Applies `overflow:hidden` styles on all matching elements when a modal is opened. |
| `customEventPrefix` | `'modal:'` | Prefix to be used on custom events. |
| `eventListeners` | `true` | Whether or not to set the document event listeners on init. |
| `moveModals` | `{ type: null, ref: null }` | Moves all modals to a location in the DOM relative to the passed reference selector on `init()`. Move type options include `after`, `before`, `append` and `prepend`. |
| `setTabindex` | `true` | Whether or not to set `tabindex="-1"` on all modal dialog elements on init. |
| `transition` | `true` | Toggle the transition animation for the modal. Set to `false` to disable. |
Expand Down Expand Up @@ -249,6 +250,27 @@ modal.init();
modal.destroy();
```

### `modal.initEventListeners()`

Set the document event listeners for click, touchend and keyup events.

```js
const modal = new Modal({ eventListeners: false });
modal.init();
modal.initEventListeners();
```

### `modal.destroyEventListeners()`

Remove the document event listeners for click, touchend and keyup events.

```js
const modal = new Modal();
modal.init();
// ...
modal.destroyEventListeners();
```

### `modal.open(key)`

Opens a modal provided the modal key and returns a promise that resolves to the modal object once the transition has finished.
Expand Down
20 changes: 18 additions & 2 deletions packages/modal/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,13 +25,29 @@ export default class Modal {
this.moveModals();
this.setTabindex(this.settings.setTabindex);
this.setInitialState();
if (this.settings.eventListeners) {
this.initEventListeners();
}
}

destroy() {
this.memory = {};
if (this.settings.eventListeners) {
this.destroyEventListeners();
}
}

/**
* Event listeners
*/

initEventListeners() {
document.addEventListener('click', this.__handlerClick, false);
document.addEventListener('touchend', this.__handlerClick, false);
document.addEventListener('keyup', this.__handlerKeyup, false);
}

destroy() {
this.memory = {};
destroyEventListeners() {
document.removeEventListener('click', this.__handlerClick, false);
document.removeEventListener('touchend', this.__handlerClick, false);
document.removeEventListener('keyup', this.__handlerKeyup, false);
Expand Down
1 change: 1 addition & 0 deletions packages/modal/src/js/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ export default {

// Feature toggles
customEventPrefix: 'modal:',
eventListeners: true,
moveModals: {
ref: null,
type: null
Expand Down
88 changes: 88 additions & 0 deletions packages/modal/tests/eventListeners.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
import Modal from '../index.js';
import '@testing-library/jest-dom/extend-expect';
import { transitionStart, transitionEnd } from './helpers/transition';

let modal;
const ev = new Event('transitionend');

const markup = `
<button data-modal-open="modal-default">Modal Default</button>
<div data-modal="modal-default" class="modal">
<div data-modal-dialog class="modal__dialog">
<button data-modal-close>Close</button>
</div>
</div>
`;

beforeEach(() => {
document.body.innerHTML = null;
});

afterEach(() => {
modal.destroy();
modal.destroyEventListeners();
modal = null;
});

test('should not set event listeners when option is set to false', async () => {
document.body.innerHTML = markup;
modal = new Modal({ eventListeners: false });
const el = document.querySelector('[data-modal]');
const btn = document.querySelector('[data-modal-open]');

modal.init();
expect(el).toHaveClass('modal is-closed');

btn.click();
await transitionStart(el);
expect(el).not.toHaveClass('is-opening');

await transitionEnd(el);
expect(el).not.toHaveClass('is-opened');
});

test('should add event listeners using api call', async () => {
document.body.innerHTML = markup;
modal = new Modal({ eventListeners: false });
const el = document.querySelector('[data-modal]');
const btn = document.querySelector('[data-modal-open]');

modal.init();
expect(el).toHaveClass('modal is-closed');

btn.click();
await transitionStart(el);
expect(el).not.toHaveClass('is-opening');

await transitionEnd(el);
expect(el).not.toHaveClass('is-opened');

modal.initEventListeners();

btn.click();
await transitionStart(el);
expect(el).toHaveClass('is-opening');

await transitionEnd(el);
expect(el).toHaveClass('is-opened');
});

test('should remove event listeners using api call', async () => {
document.body.innerHTML = markup;
modal = new Modal();
const el = document.querySelector('[data-modal]');
const btn = document.querySelector('[data-modal-open]');

modal.init();
expect(el).toHaveClass('modal is-closed');

modal.destroyEventListeners();

btn.click();
await transitionStart(el);
expect(el).not.toHaveClass('is-opening');

el.dispatchEvent(ev);
await transitionEnd(el);
expect(el).not.toHaveClass('is-opened');
});

0 comments on commit d0766d9

Please sign in to comment.