Optimization: Use absolute positioning instead of flexbox in editor

Flexbox was causing layouts and repaints to cover the entire scroll view instead of just the edited line. This cuts down on DOM manipulation cost significantly.
This commit is contained in:
Nathan Sobo 2012-09-25 13:27:46 -06:00
parent a6352497b9
commit 5f253d78e9
5 changed files with 38 additions and 23 deletions

View File

@ -517,7 +517,7 @@ describe "Editor", ->
describe "mouse events", ->
beforeEach ->
editor.attachToDom()
editor.css(position: 'absolute', top: 10, left: 10)
editor.css(position: 'absolute', top: 10, left: 10, width: 400)
describe "single-click", ->
it "re-positions the cursor to the clicked row / column", ->
@ -1483,12 +1483,17 @@ describe "Editor", ->
it "sets the width based on largest line number", ->
expect(editor.gutter.lineNumbers.outerWidth()).toBe editor.charWidth * 2
it "updates the width when total number of lines gains a digit", ->
it "updates the width and the left position of the scroll view when total number of lines gains a digit", ->
editor.setText("")
expect(editor.gutter.lineNumbers.outerWidth()).toBe editor.charWidth * 1
expect(parseInt(editor.scrollView.css('left'))).toBe editor.gutter.outerWidth()
for i in [1..9] # Ends on an empty line 10
editor.insertText "#{i}\n"
expect(editor.gutter.lineNumbers.outerWidth()).toBe editor.charWidth * 2
expect(parseInt(editor.scrollView.css('left'))).toBe editor.gutter.outerWidth()
describe "when lines are inserted", ->
it "re-renders the correct line number range in the gutter", ->
@ -1564,6 +1569,13 @@ describe "Editor", ->
expect(editor.gutter.find('.line-number:first').text()).toBe "2"
expect(editor.gutter.find('.line-number:last').text()).toBe "11"
describe "when the editor is mini", ->
it "hides the gutter and does not change the scroll view's left position", ->
miniEditor = new Editor(mini: true)
miniEditor.attachToDom()
expect(miniEditor.gutter).toBeHidden()
expect(miniEditor.scrollView.css('left')).toBe '0px'
describe "folding", ->
beforeEach ->
editSession = rootView.project.buildEditSessionForPath('two-hundred.txt')

View File

@ -147,7 +147,7 @@ window.tokensText = (tokens) ->
_.pluck(tokens, 'value').join('')
window.setEditorWidthInChars = (editor, widthInChars, charWidth=editor.charWidth) ->
editor.width(charWidth * widthInChars + editor.renderedLines.position().left)
editor.width(charWidth * widthInChars + editor.gutter.outerWidth())
$(window).trigger 'resize' # update width of editor's on-screen lines
window.setEditorHeightInLines = (editor, heightInChars, charHeight=editor.lineHeight) ->

View File

@ -19,10 +19,9 @@ class Editor extends View
@content: (params) ->
@div class: @classes(params), tabindex: -1, =>
@input class: 'hidden-input', outlet: 'hiddenInput'
@div class: 'flexbox', =>
@subview 'gutter', new Gutter
@div class: 'scroll-view', outlet: 'scrollView', =>
@div class: 'lines', outlet: 'renderedLines', =>
@subview 'gutter', new Gutter
@div class: 'scroll-view', outlet: 'scrollView', =>
@div class: 'lines', outlet: 'renderedLines', =>
@div class: 'vertical-scrollbar', outlet: 'verticalScrollbar', =>
@div outlet: 'verticalScrollbarContent'
@ -135,7 +134,7 @@ class Editor extends View
'page-down': @pageDown
'page-up': @pageUp
if not @mini
unless @mini
_.extend editorBindings,
'save': @save
'newline-below': @insertNewlineBelow
@ -154,7 +153,6 @@ class Editor extends View
'show-previous-buffer': @loadPreviousEditSession
'toggle-line-comments': @toggleLineCommentsInSelection
for name, method of editorBindings
do (name, method) =>
@on name, => method.call(this); false
@ -331,6 +329,10 @@ class Editor extends View
@verticalScrollbar.on 'scroll', =>
@scrollTop(@verticalScrollbar.scrollTop(), adjustVerticalScrollbar: false)
unless @mini
@gutter.widthChanged = (newWidth) =>
@scrollView.css('left', newWidth + 'px')
@scrollView.on 'scroll', =>
if @scrollView.scrollLeft() == 0
@gutter.removeClass('drop-shadow')
@ -680,7 +682,7 @@ class Editor extends View
@height(@lineHeight) if @mini
fragment.remove()
@gutter.calculateDimensions()
@gutter.calculateWidth()
prepareForScrolling: ->
@adjustHeightOfRenderedLines()

View File

@ -10,7 +10,7 @@ class Gutter extends View
@div outlet: 'lineNumbers', class: 'line-numbers'
editor: ->
editor = @parentView
@parentView
renderLineNumbers: (startScreenRow, endScreenRow) ->
lastScreenRow = -1
@ -21,7 +21,11 @@ class Gutter extends View
@div {class: 'line-number'}, if row == lastScreenRow then '' else row + 1
lastScreenRow = row
@calculateDimensions()
@calculateWidth()
calculateDimensions: ->
@lineNumbers.width(@editor().getLineCount().toString().length * @editor().charWidth)
calculateWidth: ->
width = @editor().getLineCount().toString().length * @editor().charWidth
if width != @cachedWidth
@cachedWidth = width
@lineNumbers.width(width)
@widthChanged?(@outerWidth())

View File

@ -12,16 +12,8 @@
height: auto;
}
.editor .flexbox {
display: -webkit-box;
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
}
.editor .gutter {
position: absolute;
height: 100%;
overflow: hidden;
padding-left: 0.4em;
@ -52,6 +44,11 @@
}
.editor .scroll-view {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
overflow-x: auto;
overflow-y: hidden;
-webkit-box-flex: 1;