From b58f019528fba4a6ee6c6e21e903ab0716f192e3 Mon Sep 17 00:00:00 2001 From: Oguz Date: Wed, 11 Mar 2020 16:43:49 +0100 Subject: [PATCH 1/4] feat(lib): insource closest to support shadow dom Closes #5 --- README.md | 2 +- lib/closest.js | 27 ++++++++++++++++++++++++--- package.json | 1 - 3 files changed, 25 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 2086390..98ddcdf 100644 --- a/README.md +++ b/README.md @@ -27,7 +27,7 @@ The library exposes the following tiny dom helpers: * `attr` - get and set node attributes * `classes` - class name helper * `clear` - remove children from a node -* `closest` - get the closest parent by selector; [component-closest](https://github.com/component/closest) +* `closest` - get the closest parent by selector; * `delegate` - event deletation support; [delegate-events](https://www.npmjs.com/package/delegate-events) * `domify` - html to elements; [domify](https://github.com/component/domify) * `event` - event binding; [component-event](https://github.com/component/event) diff --git a/lib/closest.js b/lib/closest.js index 67e19fa..8664032 100644 --- a/lib/closest.js +++ b/lib/closest.js @@ -1,3 +1,24 @@ -export { - default -} from 'closest'; \ No newline at end of file +import matches from './matches'; + +/** + * Closest + * + * @param {Element} el + * @param {String} selector + * @param {Boolean} checkYourSelf (optional) + */ +export default function(element, selector, checkYourSelf) { + var currentElem = checkYourSelf ? element : element.parentNode; + + while (currentElem && currentElem.nodeType !== document.DOCUMENT_NODE && + currentElem.nodeType !== document.DOCUMENT_FRAGMENT_NODE) { + + if (matches(currentElem, selector)) { + return currentElem; + } + + currentElem = currentElem.parentNode; + } + + return matches(currentElem, selector) ? currentElem : null; +} diff --git a/package.json b/package.json index 4669f4a..d161f8b 100644 --- a/package.json +++ b/package.json @@ -33,7 +33,6 @@ "license": "MIT", "sideEffects": false, "dependencies": { - "closest": "0.0.1", "component-event": "^0.1.4", "delegate-events": "^1.1.1", "domify": "^1.3.1", From 192aee538af61fe6be55167026540aaba02af1c0 Mon Sep 17 00:00:00 2001 From: Oguz Date: Wed, 11 Mar 2020 17:08:41 +0100 Subject: [PATCH 2/4] feat(lib): closest Shadow DOM and Document Fragment tests --- test/closest.js | 57 +++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 55 insertions(+), 2 deletions(-) diff --git a/test/closest.js b/test/closest.js index 03ec7b5..50023d1 100644 --- a/test/closest.js +++ b/test/closest.js @@ -9,6 +9,7 @@ describe('closest', function() { it('should get closest parent', function() { + // given var node = domify('
' + '
' + '
' + @@ -17,9 +18,61 @@ describe('closest', function() { var child = query('.child', node); - // when + // then expect(closest(child, '.root')).to.equal(node); expect(closest(node, '.root', true)).to.equal(node); }); -}); \ No newline at end of file + + it('should work with document fragments', function() { + + // given + var node = domify('
' + + '
' + + '
' + + '
' + + '
'); + var child = query('.child', node); + + var fragment = document.createDocumentFragment(); + fragment.appendChild(node); + + // then + expect(closest(child, '.root')).to.equal(node); + expect(closest(node, '.root', true)).to.equal(node); + expect(closest(node, '.outside')).to.be.null; + }); + + + // Shadow DOM is not supported by PhantomJS headless browser. In order to + // execute this test, use 'karma-chrome-launcher' and set the browser to + // 'Chrome' in karma.conf.js + (window.HTMLShadowElement ? it : it.skip)('should work with shadow dom', function() { + + // .root + // | -> (shadow - This is not a HTML document nor HTML element) + // | -> .innerShadowRoot + // | -> .innerShadowChild + + // given + var root = createDivWithClassname('root'); + var shadow = root.attachShadow({ mode: 'open' }); + + var innerShadowRoot = createDivWithClassname('innerShadowRoot'); + shadow.appendChild(innerShadowRoot); + var innerShadowChild = createDivWithClassname('innerShadowChild'); + innerShadowRoot.appendChild(innerShadowChild); + + // then + expect(closest(innerShadowChild, '.innerShadowRoot')).to.equal(innerShadowRoot); + expect(closest(innerShadowRoot, '.innerShadowRoot', true)).to.equal(innerShadowRoot); + expect(closest(innerShadowChild, '.outside')).to.be.null; + }); +}); + +// helper //// +function createDivWithClassname(className) { + var div = document.createElement('div'); + div.className = className; + return div; +} From aaa8ab42e2dc0609f77abdd4d2cfa295df9eb82d Mon Sep 17 00:00:00 2001 From: Nico Rehwaldt Date: Wed, 11 Mar 2020 19:46:54 +0100 Subject: [PATCH 3/4] chore(ci): test against Firefox and ChromeHeadless --- .travis.yml | 5 ++++- karma.conf.js | 4 +++- package.json | 7 ++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index 9145d1e..67c065a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,5 +3,8 @@ language: node_js node_js: - node +addons: + firefox: 'latest-esr' + script: - - npm run all \ No newline at end of file + - TEST_BROWSERS=ChromeHeadless,PhantomJS,Firefox xvfb-run npm run all \ No newline at end of file diff --git a/karma.conf.js b/karma.conf.js index 226de58..214978f 100644 --- a/karma.conf.js +++ b/karma.conf.js @@ -1,3 +1,5 @@ +const browsers = (process.env.TEST_BROWSERS || 'PhantomJS').split(','); + module.exports = function(karma) { karma.set({ @@ -17,7 +19,7 @@ module.exports = function(karma) { reporters: [ 'progress' ], - browsers: [ 'PhantomJS' ], + browsers, singleRun: true, autoWatch: false, diff --git a/package.json b/package.json index d161f8b..eccb0c0 100644 --- a/package.json +++ b/package.json @@ -48,10 +48,11 @@ "cpx": "^1.5.0", "eslint": "^5.6.1", "eslint-plugin-bpmn-io": "^0.6.0", - "karma": "^3.0.0", - "karma-browserify": "^5.1.1", + "karma": "^4.4.1", + "karma-browserify": "^7.0.0", "karma-chai": "^0.1.0", - "karma-cli": "^1.0.1", + "karma-chrome-launcher": "^3.1.0", + "karma-firefox-launcher": "^1.3.0", "karma-mocha": "^1.3.0", "karma-phantomjs-launcher": "^1.0.4", "mocha": "^5.2.0", From 5f7c7dcaa9287ac62b4f69703fa0ce3a52cd1d86 Mon Sep 17 00:00:00 2001 From: Nico Rehwaldt Date: Wed, 11 Mar 2020 19:54:56 +0100 Subject: [PATCH 4/4] test(closest): use on board domify utility --- test/closest.js | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/test/closest.js b/test/closest.js index 50023d1..e32ff6e 100644 --- a/test/closest.js +++ b/test/closest.js @@ -32,6 +32,7 @@ describe('closest', function() { '
' + '
' + '
'); + var child = query('.child', node); var fragment = document.createDocumentFragment(); @@ -51,28 +52,26 @@ describe('closest', function() { // .root // | -> (shadow - This is not a HTML document nor HTML element) - // | -> .innerShadowRoot - // | -> .innerShadowChild + // | -> .shadowRoot + // | -> .shadowChild // given - var root = createDivWithClassname('root'); + var root = domify('
'); var shadow = root.attachShadow({ mode: 'open' }); - var innerShadowRoot = createDivWithClassname('innerShadowRoot'); - shadow.appendChild(innerShadowRoot); - var innerShadowChild = createDivWithClassname('innerShadowChild'); - innerShadowRoot.appendChild(innerShadowChild); + var shadowRoot = domify('
' + + '
' + + '
'); + + shadow.appendChild(shadowRoot); + + var shadowChild = query('.shadowChild', shadowRoot); // then - expect(closest(innerShadowChild, '.innerShadowRoot')).to.equal(innerShadowRoot); - expect(closest(innerShadowRoot, '.innerShadowRoot', true)).to.equal(innerShadowRoot); - expect(closest(innerShadowChild, '.outside')).to.be.null; + expect(closest(shadowChild, '.shadowRoot')).to.equal(shadowRoot); + expect(closest(shadowRoot, '.shadowRoot', true)).to.equal(shadowRoot); + expect(closest(shadowChild, '.outside')).to.be.null; + expect(closest(shadowChild, '.root')).to.be.null; }); -}); - -// helper //// -function createDivWithClassname(className) { - var div = document.createElement('div'); - div.className = className; - return div; -} + +}); \ No newline at end of file