diff --git a/README.md b/README.md
index 522a17d..e213345 100644
--- a/README.md
+++ b/README.md
@@ -176,13 +176,13 @@ domassist.html('.my-div', 'hello world'); // add html
domassist.html('.my-div', ''); // remove html
```
-### closest(element, selector)
+### closest(origin, selector)
Find the closest parent element that matches the given selector
#### Parameters:
-`element` - {Element} the element where you want to start looking from
+`origin` - {string|Element} - the element where you want to start looking from. It can be either a valid CSS selector or an Element.
`selector` - {string} A valid CSS of the element to be found.
@@ -262,7 +262,7 @@ domassist.modify('.my-div', {
```
-### on(selector, event, callback, capture)
+### on(selector, event, callback, [capture])
Attach an event to an element based on a valid CSS selector or an Element.
@@ -287,7 +287,7 @@ domassist.on('a', 'click', (e) => {
```
-### off(selector, event)
+### off(selector, event, [capture])
Remove an attached event.
@@ -297,6 +297,8 @@ Remove an attached event.
`event` - {string} The name of the event to remove such as `click`, `mouseenter`, or `touchend`
+`[capture = false]` - {Boolean} Determines which phase to the attach the event to. Default is `false` when means the event is attached to the bubble phase. If `true` then it's attached to the capture phase.
+
### Example:
```javascript
@@ -304,13 +306,13 @@ domassist.off('a', 'click');
```
-### once(element, event, callback, capture)
+### once(selector, event, callback, capture)
Attach an event to an element to be fired once.
#### Parameters:
-`selector` - {Element}
+`selector` - {string|Element}
`event` - {string} The name of the event to attach such as `click`, `mouseenter`, or `touchend`
diff --git a/lib/closest.js b/lib/closest.js
index a1b8bd4..8e20ec8 100644
--- a/lib/closest.js
+++ b/lib/closest.js
@@ -1,6 +1,9 @@
import matches from './matches';
+import findOne from './findOne';
+
+function closest(origin, selector) {
+ const el = (selector instanceof HTMLElement) ? origin : findOne(origin);
-function closest(el, selector) {
let parent = el.parentElement;
while (parent.parentElement && !matches(parent, selector)) {
parent = parent.parentElement;
diff --git a/lib/off.js b/lib/off.js
index a859db8..17b178d 100644
--- a/lib/off.js
+++ b/lib/off.js
@@ -1,8 +1,8 @@
import find from './find';
-function off(selector, event) {
+function off(selector, event, capture = false) {
if (Array.isArray(selector)) {
- selector.forEach((item) => off(item, event));
+ selector.forEach((item) => off(item, event, capture));
}
if (!window._domassistevents) {
window._domassistevents = {};
diff --git a/lib/once.js b/lib/once.js
index 6582f68..7d95484 100644
--- a/lib/once.js
+++ b/lib/once.js
@@ -1,9 +1,9 @@
import on from './on';
import off from './off';
-function once(el, event, run, capture = false) {
- on(el, event, e => {
- off(el, event);
+function once(selector, event, run, capture = false) {
+ on(selector, event, e => {
+ off(selector, event, capture);
run(e);
}, capture);
}
diff --git a/test/closest.test.js b/test/closest.test.js
new file mode 100644
index 0000000..67907af
--- /dev/null
+++ b/test/closest.test.js
@@ -0,0 +1,46 @@
+import domassist from '../domassist';
+import test from 'tape-rollup';
+
+function addNodes() {
+ return `
+
`;
+}
+
+const teardown = (el) => {
+ while (el.firstChild) {
+ el.removeChild(el.firstChild);
+ }
+};
+
+test('closest - element', assert => {
+ const el = domassist.findOne('#domassist');
+ const levels = 4;
+ domassist.html(el, addNodes());
+ const startEl = domassist.findOne(`.level-${levels}`);
+ let count = levels - 1;
+ while (count) {
+ assert.ok(domassist.closest(startEl, `.level-${count}`), `Should find element with class of level-${count}`);
+ --count;
+ }
+ teardown(el);
+ assert.end();
+});
+
+test('closest - selector', assert => {
+ const el = domassist.findOne('#domassist');
+ const levels = 4;
+ domassist.html(el, addNodes());
+ let count = levels - 1;
+ while (count) {
+ assert.ok(domassist.closest(`.level-${levels}`, `.level-${count}`), `Should find element with class of level-${count}`);
+ --count;
+ }
+ teardown(el);
+ assert.end();
+});
diff --git a/test/domassist.test.js b/test/domassist.test.js
index a884413..9c49c4a 100644
--- a/test/domassist.test.js
+++ b/test/domassist.test.js
@@ -10,6 +10,8 @@ import './on.test';
import './off.test';
import './html.test';
import './modify.test';
+import './closest.test';
+import './once.test';
import './show-hide.test';
import './styles.test';
@@ -71,37 +73,6 @@ test('matches', assert => {
assert.end();
});
-test('closest', assert => {
- const el = domassist.findOne('#domassist');
- const levels = 4;
- // clean up test dom
- while (el.firstChild) {
- el.removeChild(el.firstChild);
- }
- function addNode(num) {
- const node = document.createElement('div');
- node.innerText = num;
- node.classList.add(`level-${num}`);
- const children = el.children;
- if (children.length) {
- const child = domassist.findOne(`.level-${num - 1}`);
- child.appendChild(node);
- } else {
- el.appendChild(node);
- }
- }
- for (let i = 0; i < levels; i += 1) {
- addNode(i + 1);
- }
- const startEl = domassist.findOne(`.level-${levels}`);
- let count = levels - 1;
- while (count) {
- assert.ok(domassist.closest(startEl, `.level-${count}`), `Should find element with class of level-${count}`);
- --count;
- }
- assert.end();
-});
-
test('Events - delegate', assert => {
const el = domassist.findOne('#domassist');
@@ -120,32 +91,6 @@ test('Events - delegate', assert => {
page.sendEvent('click', pos.left + pos.width / 2, pos.top + pos.height / 2);
});
-test('Events - once', assert => {
- const el = domassist.findOne('#domassist');
-
- el.innerHTML = `
- Click
- `;
-
- const link = domassist.findOne('a', el);
- const pos = link.getBoundingClientRect();
-
- let clicks = 0;
-
- domassist.once(link, 'click', e => {
- clicks++;
- });
-
- page.sendEvent('click', pos.left + pos.width / 2, pos.top + pos.height / 2);
- page.sendEvent('click', pos.left + pos.width / 2, pos.top + pos.height / 2);
- page.sendEvent('click', pos.left + pos.width / 2, pos.top + pos.height / 2);
-
- setTimeout(() => {
- assert.equal(clicks, 1, 'Only fired once');
- assert.end();
- }, 500);
-});
-
test('Events - hover', assert => {
const el = domassist.findOne('#domassist');
diff --git a/test/once.test.js b/test/once.test.js
new file mode 100644
index 0000000..c2aa9e3
--- /dev/null
+++ b/test/once.test.js
@@ -0,0 +1,63 @@
+import domassist from '../domassist';
+import test from 'tape-rollup';
+
+const page = window.phantom.page;
+
+const teardown = (el) => {
+ while (el.firstChild) {
+ el.removeChild(el.firstChild);
+ }
+};
+
+test('Events - once with Element', assert => {
+ const el = domassist.findOne('#domassist');
+
+ el.innerHTML = `
+ Click
+ `;
+
+ const link = domassist.findOne('a', el);
+ const pos = link.getBoundingClientRect();
+
+ let clicks = 0;
+
+ domassist.once(link, 'click', e => {
+ clicks++;
+ });
+
+ page.sendEvent('click', pos.left + pos.width / 2, pos.top + pos.height / 2);
+ page.sendEvent('click', pos.left + pos.width / 2, pos.top + pos.height / 2);
+ page.sendEvent('click', pos.left + pos.width / 2, pos.top + pos.height / 2);
+
+ setTimeout(() => {
+ assert.equal(clicks, 1, 'Element only fired once');
+ teardown(el);
+ assert.end();
+ }, 500);
+});
+
+test('Events - once with selector', assert => {
+ const el = domassist.findOne('#domassist');
+
+ el.innerHTML = `
+ Click
+ `;
+ const link = domassist.findOne('a', el);
+ const pos = link.getBoundingClientRect();
+
+ let clicks = 0;
+
+ domassist.once('a', 'click', e => {
+ clicks++;
+ });
+
+ page.sendEvent('click', pos.left + pos.width / 2, pos.top + pos.height / 2);
+ page.sendEvent('click', pos.left + pos.width / 2, pos.top + pos.height / 2);
+ page.sendEvent('click', pos.left + pos.width / 2, pos.top + pos.height / 2);
+
+ setTimeout(() => {
+ assert.equal(clicks, 1, 'Selector only fired once');
+ teardown(el);
+ assert.end();
+ }, 500);
+});