mirror of
https://github.com/atom/atom.git
synced 2026-04-06 03:02:13 -04:00
Prepare DOMElementPool to account for text nodes
This commit is contained in:
@@ -10,23 +10,32 @@ class DOMElementPool
|
||||
freeElements.length = 0
|
||||
return
|
||||
|
||||
build: (tagName, className, textContent = "") ->
|
||||
build: (tagName, factory, reset) ->
|
||||
element = @freeElementsByTagName[tagName]?.pop()
|
||||
element ?= document.createElement(tagName)
|
||||
delete element.dataset[dataId] for dataId of element.dataset
|
||||
element.removeAttribute("class")
|
||||
element.removeAttribute("style")
|
||||
element.className = className if className?
|
||||
element.textContent = textContent
|
||||
|
||||
element ?= factory()
|
||||
reset(element)
|
||||
@freedElements.delete(element)
|
||||
|
||||
element
|
||||
|
||||
buildElement: (tagName, className, textContent = "") ->
|
||||
factory = -> document.createElement(tagName)
|
||||
reset = (element) ->
|
||||
delete element.dataset[dataId] for dataId of element.dataset
|
||||
element.removeAttribute("class")
|
||||
element.removeAttribute("style")
|
||||
element.className = className if className?
|
||||
element.textContent = textContent
|
||||
@build(tagName, factory, reset)
|
||||
|
||||
buildText: (textContent) ->
|
||||
factory = -> document.createTextNode(textContent)
|
||||
reset = (element) -> element.textContent = textContent
|
||||
@build("#text", factory, reset)
|
||||
|
||||
freeElementAndDescendants: (element) ->
|
||||
@free(element)
|
||||
for index in [element.children.length - 1..0] by -1
|
||||
child = element.children[index]
|
||||
for index in [element.childNodes.length - 1..0] by -1
|
||||
child = element.childNodes[index]
|
||||
@freeElementAndDescendants(child)
|
||||
return
|
||||
|
||||
@@ -34,7 +43,7 @@ class DOMElementPool
|
||||
throw new Error("The element cannot be null or undefined.") unless element?
|
||||
throw new Error("The element has already been freed!") if @freedElements.has(element)
|
||||
|
||||
tagName = element.tagName.toLowerCase()
|
||||
tagName = element.nodeName.toLowerCase()
|
||||
@freeElementsByTagName[tagName] ?= []
|
||||
@freeElementsByTagName[tagName].push(element)
|
||||
@freedElements.add(element)
|
||||
|
||||
@@ -9,7 +9,7 @@ class HighlightsComponent
|
||||
@highlightNodesById = {}
|
||||
@regionNodesByHighlightId = {}
|
||||
|
||||
@domNode = @domElementPool.build("div", "highlights")
|
||||
@domNode = @domElementPool.buildElement("div", "highlights")
|
||||
|
||||
getDomNode: ->
|
||||
@domNode
|
||||
@@ -29,7 +29,7 @@ class HighlightsComponent
|
||||
# add or update highlights
|
||||
for id, highlightState of newState
|
||||
unless @oldState[id]?
|
||||
highlightNode = @domElementPool.build("div", "highlight")
|
||||
highlightNode = @domElementPool.buildElement("div", "highlight")
|
||||
@highlightNodesById[id] = highlightNode
|
||||
@regionNodesByHighlightId[id] = {}
|
||||
@domNode.appendChild(highlightNode)
|
||||
@@ -73,7 +73,7 @@ class HighlightsComponent
|
||||
for newRegionState, i in newHighlightState.regions
|
||||
unless oldHighlightState.regions[i]?
|
||||
oldHighlightState.regions[i] = {}
|
||||
regionNode = @domElementPool.build("div", "region")
|
||||
regionNode = @domElementPool.buildElement("div", "region")
|
||||
# This prevents highlights at the tiles boundaries to be hidden by the
|
||||
# subsequent tile. When this happens, subpixel anti-aliasing gets
|
||||
# disabled.
|
||||
|
||||
@@ -7,7 +7,7 @@ class LineNumbersTileComponent
|
||||
|
||||
constructor: ({@id, @domElementPool}) ->
|
||||
@lineNumberNodesById = {}
|
||||
@domNode = @domElementPool.build("div")
|
||||
@domNode = @domElementPool.buildElement("div")
|
||||
@domNode.style.position = "absolute"
|
||||
@domNode.style.display = "block"
|
||||
@domNode.style.top = 0 # Cover the space occupied by a dummy lineNumber
|
||||
@@ -99,7 +99,7 @@ class LineNumbersTileComponent
|
||||
{screenRow, bufferRow, softWrapped, top, decorationClasses, zIndex} = lineNumberState
|
||||
|
||||
className = @buildLineNumberClassName(lineNumberState)
|
||||
lineNumberNode = @domElementPool.build("div", className)
|
||||
lineNumberNode = @domElementPool.buildElement("div", className)
|
||||
lineNumberNode.dataset.screenRow = screenRow
|
||||
lineNumberNode.dataset.bufferRow = bufferRow
|
||||
|
||||
@@ -115,7 +115,7 @@ class LineNumbersTileComponent
|
||||
lineNumber = (bufferRow + 1).toString()
|
||||
|
||||
padding = _.multiplyString("\u00a0", maxLineNumberDigits - lineNumber.length)
|
||||
iconRight = @domElementPool.build("div", "icon-right")
|
||||
iconRight = @domElementPool.buildElement("div", "icon-right")
|
||||
|
||||
lineNumberNode.textContent = padding + lineNumber
|
||||
lineNumberNode.appendChild(iconRight)
|
||||
|
||||
@@ -19,7 +19,7 @@ class LinesTileComponent
|
||||
@lineNodesByLineId = {}
|
||||
@screenRowsByLineId = {}
|
||||
@lineIdsByScreenRow = {}
|
||||
@domNode = @domElementPool.build("div")
|
||||
@domNode = @domElementPool.buildElement("div")
|
||||
@domNode.style.position = "absolute"
|
||||
@domNode.style.display = "block"
|
||||
|
||||
@@ -126,7 +126,7 @@ class LinesTileComponent
|
||||
{width} = @newState
|
||||
{screenRow, tokens, text, top, lineEnding, fold, isSoftWrapped, indentLevel, decorationClasses} = @newTileState.lines[id]
|
||||
|
||||
lineNode = @domElementPool.build("div", "line")
|
||||
lineNode = @domElementPool.buildElement("div", "line")
|
||||
lineNode.dataset.screenRow = screenRow
|
||||
|
||||
if decorationClasses?
|
||||
@@ -138,7 +138,7 @@ class LinesTileComponent
|
||||
else
|
||||
@setLineInnerNodes(id, lineNode)
|
||||
|
||||
lineNode.appendChild(@domElementPool.build("span", "fold-marker")) if fold
|
||||
lineNode.appendChild(@domElementPool.buildElement("span", "fold-marker")) if fold
|
||||
lineNode
|
||||
|
||||
setEmptyLineInnerNodes: (id, lineNode) ->
|
||||
@@ -148,11 +148,11 @@ class LinesTileComponent
|
||||
if indentGuidesVisible and indentLevel > 0
|
||||
invisibleIndex = 0
|
||||
for i in [0...indentLevel]
|
||||
indentGuide = @domElementPool.build("span", "indent-guide")
|
||||
indentGuide = @domElementPool.buildElement("span", "indent-guide")
|
||||
for j in [0...tabLength]
|
||||
if invisible = endOfLineInvisibles?[invisibleIndex++]
|
||||
indentGuide.appendChild(
|
||||
@domElementPool.build("span", "invisible-character", invisible)
|
||||
@domElementPool.buildElement("span", "invisible-character", invisible)
|
||||
)
|
||||
else
|
||||
indentGuide.insertAdjacentText("beforeend", " ")
|
||||
@@ -161,7 +161,7 @@ class LinesTileComponent
|
||||
while invisibleIndex < endOfLineInvisibles?.length
|
||||
invisible = endOfLineInvisibles[invisibleIndex++]
|
||||
lineNode.appendChild(
|
||||
@domElementPool.build("span", "invisible-character", invisible)
|
||||
@domElementPool.buildElement("span", "invisible-character", invisible)
|
||||
)
|
||||
else
|
||||
unless @appendEndOfLineNodes(id, lineNode)
|
||||
@@ -180,7 +180,7 @@ class LinesTileComponent
|
||||
openScopeNode = openScopeNode.parentElement
|
||||
|
||||
for scope in @tokenIterator.getScopeStarts()
|
||||
newScopeNode = @domElementPool.build("span", scope.replace(/\.+/g, ' '))
|
||||
newScopeNode = @domElementPool.buildElement("span", scope.replace(/\.+/g, ' '))
|
||||
openScopeNode.appendChild(newScopeNode)
|
||||
openScopeNode = newScopeNode
|
||||
|
||||
@@ -213,7 +213,7 @@ class LinesTileComponent
|
||||
|
||||
appendTokenNodes: (tokenText, isHardTab, firstNonWhitespaceIndex, firstTrailingWhitespaceIndex, hasIndentGuide, hasInvisibleCharacters, scopeNode) ->
|
||||
if isHardTab
|
||||
hardTabNode = @domElementPool.build("span", "hard-tab", tokenText)
|
||||
hardTabNode = @domElementPool.buildElement("span", "hard-tab", tokenText)
|
||||
hardTabNode.classList.add("leading-whitespace") if firstNonWhitespaceIndex?
|
||||
hardTabNode.classList.add("trailing-whitespace") if firstTrailingWhitespaceIndex?
|
||||
hardTabNode.classList.add("indent-guide") if hasIndentGuide
|
||||
@@ -228,7 +228,7 @@ class LinesTileComponent
|
||||
trailingWhitespaceNode = null
|
||||
|
||||
if firstNonWhitespaceIndex?
|
||||
leadingWhitespaceNode = @domElementPool.build(
|
||||
leadingWhitespaceNode = @domElementPool.buildElement(
|
||||
"span",
|
||||
"leading-whitespace",
|
||||
tokenText.substring(0, firstNonWhitespaceIndex)
|
||||
@@ -241,7 +241,7 @@ class LinesTileComponent
|
||||
if firstTrailingWhitespaceIndex?
|
||||
tokenIsOnlyWhitespace = firstTrailingWhitespaceIndex is 0
|
||||
|
||||
trailingWhitespaceNode = @domElementPool.build(
|
||||
trailingWhitespaceNode = @domElementPool.buildElement(
|
||||
"span",
|
||||
"trailing-whitespace",
|
||||
tokenText.substring(firstTrailingWhitespaceIndex)
|
||||
@@ -256,7 +256,7 @@ class LinesTileComponent
|
||||
if tokenText.length > MaxTokenLength
|
||||
while startIndex < endIndex
|
||||
text = @sliceText(tokenText, startIndex, startIndex + MaxTokenLength)
|
||||
scopeNode.appendChild(@domElementPool.build("span", null, text))
|
||||
scopeNode.appendChild(@domElementPool.buildElement("span", null, text))
|
||||
startIndex += MaxTokenLength
|
||||
else
|
||||
scopeNode.insertAdjacentText("beforeend", @sliceText(tokenText, startIndex, endIndex))
|
||||
@@ -276,7 +276,7 @@ class LinesTileComponent
|
||||
for invisible in endOfLineInvisibles
|
||||
hasInvisibles = true
|
||||
lineNode.appendChild(
|
||||
@domElementPool.build("span", "invisible-character", invisible)
|
||||
@domElementPool.buildElement("span", "invisible-character", invisible)
|
||||
)
|
||||
|
||||
hasInvisibles
|
||||
|
||||
Reference in New Issue
Block a user