Last active
January 9, 2019 13:41
-
-
Save loilo/ace13e897af9d976315918cbeab6acf8 to your computer and use it in GitHub Desktop.
Breaks elements out of their container
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
// This was originally designed for creating virtual print sheet layouts in HTML/CSS, | |
// breaking contents too long for one page to the next one. | |
// You can play around with it here: https://jsfiddle.net/Loilo/L3w8zjuf/3/ | |
function internalBreak (breakItem, outmostContainer, breakDirection, childIsBroken = false) { | |
const container = breakItem.parentElement | |
const containerItems = Array.from(container.children) | |
// Move all items after `breakItem` to a new container | |
const nextContainer = container.cloneNode() | |
const breakItemIndex = containerItems.indexOf(breakItem) | |
for (let i = breakItemIndex + 1; i < containerItems.length; i++) { | |
const containerItem = containerItems[i] | |
nextContainer.appendChild(containerItem) | |
} | |
// Check if the container was broken | |
// If child is broken, parent is always broken as well | |
const isBroken = childIsBroken || (breakDirection === 'before' | |
? breakItem !== containerItems[0] | |
: breakItem !== containerItems[containerItems.length - 1] | |
) | |
// If container is broken, mark original and newly created with data-* attributes | |
if (isBroken) { | |
if (breakDirection === 'before') { | |
container.dataset.brokenAfter = '' | |
nextContainer.dataset.brokenBefore = '' | |
} else { | |
container.dataset.brokenBefore = '' | |
nextContainer.dataset.brokenAfter = '' | |
} | |
} | |
// If `breakItem`'s container is not the outmost possible one, recursively continue to break their parents | |
if (container !== outmostContainer) { | |
const newContainerContainer = internalBreak(container, outmostContainer, breakDirection, isBroken) | |
newContainerContainer.insertAdjacentElement('afterbegin', nextContainer) | |
} else { | |
outmostContainer.insertAdjacentElement('afterend', nextContainer) | |
} | |
return nextContainer | |
} | |
// Break after `breakItem` | |
function breakAfter (breakItem, outmostContainer) { | |
internalBreak(breakItem, outmostContainer, 'after') | |
} | |
// Break before `breakItem` | |
function breakBefore (breakItem, outmostContainer) { | |
const originalContainer = breakItem.parentElement | |
const nextContainer = internalBreak(breakItem, breakItem.closest('.page'), 'before') | |
nextContainer.insertAdjacentElement('afterbegin', breakItem) | |
// Remove empty containers | |
if (!originalContainer.children.length) { | |
let currentContainer = originalContainer | |
while (currentContainer.parentElement.children.length === 1) { | |
currentContainer = currentContainer.parentElement | |
} | |
currentContainer.remove() | |
} | |
} |
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
<!-- The original DOM tree --> | |
<section class="page"> | |
<p>Paragraph 1</p> | |
<p>Paragraph 2</p> | |
<article> | |
<p>Paragraph 3</p> | |
<p data-break-before>Paragraph 4</p> | |
<p>Paragraph 5</p> | |
</article> | |
</section> | |
<!-- Break the DOM! --> | |
<script> | |
const el = document.querySelector('[data-break-before]') | |
breakBefore(el, el.closest('.page') | |
</script> | |
<!-- This will result in the folllowing DOM tree --> | |
<section class="page" data-broken-after> | |
<p>Paragraph 1</p> | |
<p>Paragraph 2</p> | |
<article data-broken-after> | |
<p>Paragraph 3</p> | |
</article> | |
</section> | |
<section class="page" data-broken-before> | |
<article data-broken-before> | |
<p data-break-before>Paragraph 4</p> | |
<p>Paragraph 5</p> | |
</article> | |
</section> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment