Guest User

Untitled

a guest
Jul 19th, 2018
76
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.81 KB | None | 0 0
  1. const spannerClassName = "non-nested-spanner"
  2. const spannerQuerySelector = `.${spannerClassName}`
  3.  
  4. /**
  5. *
  6. * @param {Range} range
  7. * @returns {?HTMLSpanElement}
  8. */
  9. export function getContainingSpanner(range) {
  10. let cursor = range.commonAncestorContainer
  11. if (cursor.classList == undefined) cursor = cursor.parentElement
  12. while (cursor.parentElement != null) {
  13. if (cursor.classList.contains(spannerClassName)) return cursor
  14. cursor = cursor.parentElement
  15. }
  16. return null
  17. }
  18.  
  19. /**
  20. *
  21. * @param {Node} childNode
  22. * @returns {!HTMLSpanElement}
  23. */
  24. export function createSpannerWrapping(childNode) {
  25. const spanner = document.createElement('span')
  26. spanner.classList.add(spannerClassName)
  27. spanner.appendChild(childNode)
  28. return spanner
  29. }
  30.  
  31. function isEmptySpanner(spanner) {
  32. if (spanner.childNodes.length == 0) return true
  33. else if (spanner.childNodes.length == 1) {
  34. const node = spanner.childNodes[0]
  35. return node instanceof Text && node.length == 0
  36. }
  37. return false
  38. }
  39.  
  40. /**
  41. *
  42. * @param {Range} range
  43. */
  44. export function wrapInNonNestedSpanners(range) {
  45. const containingSpanner = getContainingSpanner(range)
  46. const result = []
  47. if (containingSpanner != null) {
  48. const endRange = document.createRange() // contents of the span after range
  49. endRange.selectNode(containingSpanner)
  50. endRange.setStart(range.endContainer, range.endOffset)
  51. const endContents = endRange.cloneContents()
  52. const wrappedSelectionContents = containingSpanner.cloneNode(false)
  53. wrappedSelectionContents.appendChild(range.cloneContents())
  54. endRange.deleteContents()
  55. range.deleteContents()
  56. const parent = containingSpanner.parentNode
  57. const next = containingSpanner.nextSibling
  58. parent.insertBefore(wrappedSelectionContents, next)
  59. result.push(wrappedSelectionContents)
  60. if (!isEmptySpanner(endContents.childNodes[0])) parent.insertBefore(endContents, next)
  61. if (isEmptySpanner(containingSpanner)) parent.removeChild(containingSpanner)
  62. const newSelection = document.createRange()
  63. newSelection.selectNode(wrappedSelectionContents)
  64. window.getSelection().removeAllRanges()
  65. window.getSelection().addRange(newSelection)
  66. } else {
  67. const contents = range.extractContents()
  68. const spanners = contents.querySelectorAll(spannerQuerySelector)
  69. let endRange = document.createRange() // range before the span
  70. for (let index = spanners.length-1; index>=0; index--) {
  71. const spanner = spanners[index]
  72. endRange.selectNodeContents(contents)
  73. endRange.setStartAfter(spanner)
  74. if (!endRange.collapsed) {
  75. const wrappedEndContents = createSpannerWrapping(endRange.extractContents())
  76. range.insertNode(wrappedEndContents)
  77. result.unshift(wrappedEndContents)
  78. }
  79. range.insertNode(spanner)
  80. result.unshift(spanner)
  81. }
  82. const rest = createSpannerWrapping(contents)
  83. if (!isEmptySpanner(rest)) {
  84. range.insertNode(rest)
  85. result.unshift(rest)
  86. }
  87. }
  88. return result
  89. }
Add Comment
Please, Sign In to add comment