Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Apply init/destroy EventListeners feature to modal component #602

Merged
merged 2 commits into from
May 29, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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');
});