Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- const spannerClassName = "non-nested-spanner"
- const spannerQuerySelector = `.${spannerClassName}`
- /**
- *
- * @param {Range} range
- * @returns {?HTMLSpanElement}
- */
- export function getContainingSpanner(range) {
- let cursor = range.commonAncestorContainer
- if (cursor.classList == undefined) cursor = cursor.parentElement
- while (cursor.parentElement != null) {
- if (cursor.classList.contains(spannerClassName)) return cursor
- cursor = cursor.parentElement
- }
- return null
- }
- /**
- *
- * @param {Node} childNode
- * @returns {!HTMLSpanElement}
- */
- export function createSpannerWrapping(childNode) {
- const spanner = document.createElement('span')
- spanner.classList.add(spannerClassName)
- spanner.appendChild(childNode)
- return spanner
- }
- function isEmptySpanner(spanner) {
- if (spanner.childNodes.length == 0) return true
- else if (spanner.childNodes.length == 1) {
- const node = spanner.childNodes[0]
- return node instanceof Text && node.length == 0
- }
- return false
- }
- /**
- *
- * @param {Range} range
- */
- export function wrapInNonNestedSpanners(range) {
- const containingSpanner = getContainingSpanner(range)
- const result = []
- if (containingSpanner != null) {
- const endRange = document.createRange() // contents of the span after range
- endRange.selectNode(containingSpanner)
- endRange.setStart(range.endContainer, range.endOffset)
- const endContents = endRange.cloneContents()
- const wrappedSelectionContents = containingSpanner.cloneNode(false)
- wrappedSelectionContents.appendChild(range.cloneContents())
- endRange.deleteContents()
- range.deleteContents()
- const parent = containingSpanner.parentNode
- const next = containingSpanner.nextSibling
- parent.insertBefore(wrappedSelectionContents, next)
- result.push(wrappedSelectionContents)
- if (!isEmptySpanner(endContents.childNodes[0])) parent.insertBefore(endContents, next)
- if (isEmptySpanner(containingSpanner)) parent.removeChild(containingSpanner)
- const newSelection = document.createRange()
- newSelection.selectNode(wrappedSelectionContents)
- window.getSelection().removeAllRanges()
- window.getSelection().addRange(newSelection)
- } else {
- const contents = range.extractContents()
- const spanners = contents.querySelectorAll(spannerQuerySelector)
- let endRange = document.createRange() // range before the span
- for (let index = spanners.length-1; index>=0; index--) {
- const spanner = spanners[index]
- endRange.selectNodeContents(contents)
- endRange.setStartAfter(spanner)
- if (!endRange.collapsed) {
- const wrappedEndContents = createSpannerWrapping(endRange.extractContents())
- range.insertNode(wrappedEndContents)
- result.unshift(wrappedEndContents)
- }
- range.insertNode(spanner)
- result.unshift(spanner)
- }
- const rest = createSpannerWrapping(contents)
- if (!isEmptySpanner(rest)) {
- range.insertNode(rest)
- result.unshift(rest)
- }
- }
- return result
- }
Add Comment
Please, Sign In to add comment