-
Notifications
You must be signed in to change notification settings - Fork 33
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #136 from chrischrischris/author_vh_22
#22 Add AuthorVH
- Loading branch information
Showing
6 changed files
with
474 additions
and
49 deletions.
There are no files selected for viewing
53 changes: 5 additions & 48 deletions
53
apps/admin/app/jcr_root/apps/dx/admin/clientlibs/author/src/js/app.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,51 +1,8 @@ | ||
window.dx = window.dx || {}; | ||
window.dx.author = { watch: { functions: [] } }; | ||
// Ignore for code coverage | ||
/* istanbul ignore file */ | ||
|
||
window.dx.author.watch.registerFunction = (func) => { | ||
window.dx.author.watch.functions.push(func); | ||
}; | ||
|
||
const TAG_SCRIPT = 'SCRIPT'; | ||
const WATCH_CONFIG = { | ||
childList: true, | ||
subtree: true, | ||
}; | ||
|
||
/** | ||
* Watch for Author mutations and run functions when they meet node type criteria. | ||
* | ||
* @param {Array} apps The functions or classes to instantiate when a mutation occurs | ||
* @param {DOMElment} parent The top level parent to start the observation | ||
*/ | ||
const watch = (document) => { | ||
const parentToWatch = document.querySelector('body'); | ||
|
||
const callback = (mutationsList) => { | ||
mutationsList.forEach((mutation) => { | ||
// Attempt to cut down on noise from all mutations. | ||
// An AEM component mutation will have only one added node. No more. No less. | ||
if (window.dx.author.watch.functions.length > 0 && mutation.addedNodes.length === 1) { | ||
const addedNode = mutation.addedNodes[0]; | ||
if (addedNode.nodeType === 1 && addedNode.tagName !== TAG_SCRIPT) { | ||
// Loop through each function and instantiate | ||
// it with the added node. | ||
window.dx.author.watch.functions.forEach((app) => { | ||
app(addedNode); | ||
}); | ||
} | ||
} | ||
}); | ||
}; | ||
|
||
// Create an observer instance linked to the callback function | ||
const observer = new MutationObserver(callback); | ||
observer.observe(parentToWatch, WATCH_CONFIG); | ||
}; | ||
|
||
const authorWatch = (document) => { | ||
if (typeof CQ !== 'undefined' && document) { | ||
watch(document); | ||
} | ||
}; | ||
import { initAuthorVh } from './utils/authorVh'; | ||
import authorWatch from './utils/authorWatch'; | ||
|
||
authorWatch(document); | ||
initAuthorVh(document); |
28 changes: 28 additions & 0 deletions
28
apps/admin/app/jcr_root/apps/dx/admin/clientlibs/author/src/js/utils/__mocks__/vh.html
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,28 @@ | ||
<!-- 0 Mobile Only --> | ||
<div data-author-mobile-vh="20" class="has-AuthorVh"></div> | ||
<!-- 1 Tablet --> | ||
<div data-author-mobile-vh="20" data-author-tablet-vh="40" class="has-AuthorVh"></div> | ||
<!-- 2 Desktop --> | ||
<div data-author-mobile-vh="20" data-author-tablet-vh="40" data-author-desktop-vh="60" class="has-AuthorVh"></div> | ||
<!-- 3 Bad Data --> | ||
<div data-author-mobile-vh="asdf" class="has-AuthorVh bad-element"></div> | ||
<!-- No Data --> | ||
<div class="dexter-is-awesome"></div> | ||
|
||
<!-- With item vhs set--> | ||
<!-- 4 Mobile Only --> | ||
<div data-author-mobile-vh="20" data-author-mobile-items-vh="100" class="has-AuthorVh"></div> | ||
<!-- 5 Tablet --> | ||
<div data-author-mobile-vh="20" data-author-mobile-items-vh="20,,40" data-author-tablet-vh="40" data-author-tablet-items-vh="0,15,90" class="has-AuthorVh"></div> | ||
<!-- 6 Desktop --> | ||
<div data-author-mobile-vh="20" data-author-mobile-items-vh=",,99,30" | ||
data-author-tablet-vh="40" data-author-tablet-items-vh="0,15,,40" | ||
data-author-desktop-vh="60" data-author-desktop-items-vh="10" class="has-AuthorVh"> | ||
<div id="i1">i1</div> | ||
<div id="i2">i2</div> | ||
<div id="i3">i3</div> | ||
<div id="i4">i4</div> | ||
</div> | ||
<!-- 7 Bad Data --> | ||
<div data-author-mobile-vh="asdf" data-author-tablet-items-vh="asdf" class="has-AuthorVh bad-element"></div> | ||
|
163 changes: 163 additions & 0 deletions
163
...dmin/app/jcr_root/apps/dx/admin/clientlibs/author/src/js/utils/__tests__/authorVh.test.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
import vhHtml from '../__mocks__/vh.html'; | ||
import { | ||
initAuthorVh, | ||
findAuthorVhElements, | ||
getEditorHeight, | ||
setVh, | ||
getInitialWidth, | ||
getVhAsPx, | ||
getBreakpointVh, | ||
} from '../authorVh'; | ||
|
||
// Define our innerWidth | ||
Object.defineProperties(window, { | ||
innerWidth: { value: 300, configurable: true, writable: true }, | ||
innerHeight: { value: 720 }, | ||
}); | ||
|
||
document.body.innerHTML = vhHtml; | ||
|
||
let elements; | ||
let editorHeight; | ||
|
||
beforeAll(() => { | ||
elements = findAuthorVhElements(document); | ||
}); | ||
|
||
describe('count elements with VH', () => { | ||
test('four total elements', () => { | ||
expect(window.innerWidth).toEqual(300); | ||
expect(elements).toHaveLength(8); | ||
}); | ||
}); | ||
|
||
describe('get editor height', () => { | ||
test('height is height minus AEM toolbar', () => { | ||
editorHeight = getEditorHeight(); | ||
expect(editorHeight).toEqual(610); | ||
}); | ||
}); | ||
|
||
describe('setting VH', () => { | ||
test('VH is correctly set on first element', () => { | ||
const mobileElement = setVh(elements[0], 'mobile', editorHeight); | ||
expect(mobileElement.style.minHeight).toEqual('122px'); | ||
}); | ||
test('bad data is not set on element', () => { | ||
const badElement = document.querySelector('.bad-element'); | ||
expect(badElement.style.minHeight).toBeFalsy(); | ||
}); | ||
}); | ||
|
||
describe('get initial width', () => { | ||
test('width should be mobile', () => { | ||
const initialWidth = getInitialWidth(); | ||
expect(initialWidth).toEqual('mobile'); | ||
}); | ||
|
||
test('width should be tablet', () => { | ||
Object.defineProperties(window, { | ||
innerWidth: { value: 768, configurable: true, writable: true }, | ||
}); | ||
const initialWidth = getInitialWidth(); | ||
expect(initialWidth).toEqual('tablet'); | ||
}); | ||
test('width should be desktop', () => { | ||
Object.defineProperties(window, { | ||
innerWidth: { value: 1366, configurable: true, writable: true }, | ||
}); | ||
const initialWidth = getInitialWidth(); | ||
expect(initialWidth).toEqual('desktop'); | ||
}); | ||
}); | ||
|
||
describe('get vh to px', () => { | ||
test('vh should not convert to px', () => { | ||
const pxValue = getVhAsPx(900, 'foo'); | ||
expect(pxValue).toBeNull(); | ||
}); | ||
test('vh should convert to px', () => { | ||
const pxValue = getVhAsPx(900, 66); | ||
expect(pxValue).toEqual(594); | ||
}); | ||
}); | ||
|
||
describe('get breakpoint vh as px', () => { | ||
test('breakpoint vh should be mobile', () => { | ||
const el = elements[2]; | ||
const pxValueMobile = getBreakpointVh('mobile', window.innerHeight, el.dataset); | ||
expect(pxValueMobile.flexVh).toEqual(144); | ||
}); | ||
|
||
test('breakpoint vh should be tablet', () => { | ||
const el = elements[2]; | ||
const pxValueMobile = getBreakpointVh('tablet', window.innerHeight, el.dataset); | ||
expect(pxValueMobile.flexVh).toEqual(288); | ||
}); | ||
|
||
test('breakpoint vh should be desktop', () => { | ||
const el = elements[2]; | ||
const pxValueMobile = getBreakpointVh('desktop', window.innerHeight, el.dataset); | ||
expect(pxValueMobile.flexVh).toEqual(432); | ||
}); | ||
}); | ||
|
||
describe('breakpoint vh with items defined', () => { | ||
test('mobile only', () => { | ||
const el = elements[4]; | ||
const { flexVh, itemVhs } = getBreakpointVh('mobile', window.innerHeight, el.dataset); | ||
expect(flexVh).toEqual(144); | ||
expect(itemVhs).toEqual([720]); | ||
}); | ||
|
||
test('tablet override', () => { | ||
const el = elements[5]; | ||
const { flexVh, itemVhs } = getBreakpointVh('mobile', window.innerHeight, el.dataset); | ||
expect(flexVh).toEqual(144); | ||
expect(itemVhs).toEqual([144, null, 288]); | ||
|
||
const { flexVh: flexVh1, itemVhs: itemVhs1 } = getBreakpointVh( | ||
'tablet', | ||
window.innerHeight, | ||
el.dataset | ||
); | ||
expect(flexVh1).toEqual(288); | ||
expect(itemVhs1).toEqual([null, 108, 648]); | ||
}); | ||
|
||
test('desktop override + item inheritance', () => { | ||
const el = elements[6]; | ||
|
||
const item1 = el.querySelector('#i1'); | ||
const item2 = el.querySelector('#i2'); | ||
const item3 = el.querySelector('#i3'); | ||
const item4 = el.querySelector('#i4'); | ||
|
||
setVh(el, 'mobile', window.innerHeight, el.dataset); | ||
expect(item1.style.minHeight).toBe(''); | ||
expect(item2.style.minHeight).toBe(''); | ||
expect(item3.style.minHeight).toBe('712.8px'); | ||
expect(item4.style.minHeight).toBe('216px'); | ||
|
||
setVh(el, 'tablet', window.innerHeight, el.dataset); | ||
expect(item1.style.minHeight).toBe(''); | ||
expect(item2.style.minHeight).toBe('108px'); | ||
expect(item3.style.minHeight).toBe('712.8px'); | ||
expect(item4.style.minHeight).toBe('288px'); | ||
|
||
setVh(el, 'desktop', window.innerHeight, el.dataset); | ||
expect(item1.style.minHeight).toBe('72px'); | ||
expect(item2.style.minHeight).toBe('108px'); | ||
expect(item3.style.minHeight).toBe('712.8px'); | ||
expect(item4.style.minHeight).toBe('288px'); | ||
}); | ||
}); | ||
|
||
describe('initAuthorVh', () => { | ||
test('four total elements', () => { | ||
const addListener = jest.fn(); | ||
global.matchMedia = () => ({ addListener }); | ||
initAuthorVh(document); | ||
expect(addListener).toHaveBeenCalled(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.