diff --git a/spec/app/editor-spec.coffee b/spec/app/editor-spec.coffee index 1df99234f..cb40aed2a 100644 --- a/spec/app/editor-spec.coffee +++ b/spec/app/editor-spec.coffee @@ -391,55 +391,68 @@ describe "Editor", -> otherEditor.simulateDomAttachment() expect(otherEditor.setMaxLineLength).toHaveBeenCalled() - describe "when some lines at the end of the buffer are not visible on screen when the editor is attached", -> beforeEach -> editor.attachToDom(heightInLines: 5.5) - it "only renders the visible lines, giving the final line a margin-bottom to account for the missing lines", -> + it "only renders the visible lines, setting the padding-bottom of the lines element to account for the missing lines", -> expect(editor.lines.find('.line').length).toBe 6 - expectedMarginBottom = (buffer.numLines() - 6) * editor.lineHeight - expect(editor.lines.find('.line:last').css('margin-bottom')).toBe "#{expectedMarginBottom}px" + expectedPaddingBottom = (buffer.numLines() - 6) * editor.lineHeight + expect(editor.lines.css('padding-bottom')).toBe "#{expectedPaddingBottom}px" - it "when the lines are scrolled down, removes lines that become invisible and builds lines that become visisble", -> - editor.scroller.scrollTop(editor.lineHeight * 2.5) - editor.scroller.trigger 'scroll' + describe "when the scroller element is scrolled", -> + describe "whes scrolling less than the editor's height", -> + it "removes lines that become invisible and builds lines that become visisble", -> + editor.scroller.scrollTop(editor.lineHeight * 2.5) + editor.scroller.trigger 'scroll' + expect(editor.lines.find('.line').length).toBe 6 + expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(2) + expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(7) - expect(editor.lines.find('.line').length).toBe 6 - expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(2) - expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(7) + editor.scroller.scrollTop(editor.lineHeight * 3.5) + editor.scroller.trigger 'scroll' + expect(editor.lines.find('.line').length).toBe 6 + expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(3) + expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(8) - editor.scroller.scrollTop(editor.lineHeight * 3.5) - editor.scroller.trigger 'scroll' + editor.scroller.scrollTop(editor.lineHeight * 2.5) + editor.scroller.trigger 'scroll' + expect(editor.lines.find('.line').length).toBe 6 + expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(2) + expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(7) - expect(editor.lines.find('.line').length).toBe 6 - expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(3) - expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(8) + editor.scroller.scrollTop(0) + editor.scroller.trigger 'scroll' + expect(editor.lines.find('.line').length).toBe 6 + expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(0) + expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(5) - fit "when the scroller is scrolled to the end, removes lines that become invisible and builds lines that become visible", -> - editor.scroller.scrollBottom(editor.scroller[0].scrollHeight) - editor.scroller.trigger 'scroll' + describe "when scrolling more than the editors height", -> + it "removes lines that become invisible and builds lines that become visible", -> + editor.scroller.scrollBottom(editor.scroller.prop('scrollHeight')) + editor.scroller.trigger 'scroll' + expect(editor.lines.find('.line').length).toBe 6 + expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(7) + expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(12) - expect(editor.lines.find('.line').length).toBe 6 - expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(7) - expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(12) + editor.scroller.scrollBottom(0) + editor.scroller.trigger 'scroll' + expect(editor.lines.find('.line').length).toBe 6 + expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(0) + expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(5) - it "adjusts margins to account for non-rendered lines", -> - editor.scroller.scrollTop(editor.lineHeight * 2.5) - editor.scroller.trigger 'scroll' + it "adjusts the vertical padding of the lines element to account for non-rendered lines", -> + editor.scroller.scrollTop(editor.lineHeight * 2.5) + editor.scroller.trigger 'scroll' + expect(editor.lines.css('padding-top')).toBe "#{2 * editor.lineHeight}px" + expectedPaddingBottom = (buffer.numLines() - 8) * editor.lineHeight + expect(editor.lines.css('padding-bottom')).toBe "#{expectedPaddingBottom}px" + + editor.scroller.scrollBottom(editor.scroller.prop('scrollHeight')) + editor.scroller.trigger 'scroll' + expect(editor.lines.css('padding-top')).toBe "#{7 * editor.lineHeight}px" + expect(editor.lines.css('padding-bottom')).toBe "0px" - for line, index in editor.lines.find('.line') - marginTop = $(line).css('margin-top') - marginBottom = $(line).css('margin-bottom') - if index == 0 - expectedMarginTop = editor.lineHeight * 2 - expect(marginTop).toBe "#{expectedMarginTop}px" - else if index == 5 - expectedMarginBottom = (editor.getLastScreenRow() - 7) * editor.lineHeight - expect(marginBottom).toBe "#{expectedMarginBottom}px" - else - expect(marginBottom).toBe '0px' - expect(marginTop).toBe '0px' it "renders additional lines when the editor is resized", -> setEditorHeightInLines(editor, 10) @@ -449,16 +462,6 @@ describe "Editor", -> expect(editor.lines.find('.line:first').text()).toBe buffer.lineForRow(0) expect(editor.lines.find('.line:last').text()).toBe buffer.lineForRow(9) - # describe "when lines at the beginning of the buffer are not visible on screen when the editor is attached", -> - # beforeEach -> - # editor.attachToDom(heightInLines: 5.5) - - # it "only renders the visible lines, giving the first line a margin-top to account for the missing lines", -> - # expect(editor.lines.find('.line').length).toBe 6 - # expectedMarginBottom = (buffer.numLines() - 6) * editor.lineHeight - # expect(editor.lines.find('.line:last').css('margin-bottom')).toBe "#{expectedMarginBottom}px" - - describe "gutter rendering", -> it "creates a line number element for each line in the buffer", -> expect(editor.gutter.find('.line-number').length).toEqual(buffer.numLines()) diff --git a/src/app/editor.coffee b/src/app/editor.coffee index aed981e1f..0712b27c8 100644 --- a/src/app/editor.coffee +++ b/src/app/editor.coffee @@ -250,19 +250,26 @@ class Editor extends View firstVisibleScreenRow = @getFirstVisibleScreenRow() lastVisibleScreenRow = @getLastVisibleScreenRow() - console.log "updateLines", firstVisibleScreenRow, lastVisibleScreenRow - # console.log "cursor screen position", @getCursorScreenPosition().inspect() - if firstVisibleScreenRow > @firstRenderedScreenRow - console.log "removing from", @firstRenderedScreenRow, "to", firstVisibleScreenRow - 1 @removeLineElements(@firstRenderedScreenRow, firstVisibleScreenRow - 1) @lines.css('padding-top', firstVisibleScreenRow * @lineHeight) - console.log @lines + + if lastVisibleScreenRow < @lastRenderedScreenRow + @removeLineElements(lastVisibleScreenRow + 1, @lastRenderedScreenRow) + @lines.css('padding-bottom', (@getLastScreenRow() - lastVisibleScreenRow) * @lineHeight) + + if firstVisibleScreenRow < @firstRenderedScreenRow + newLinesStartRow = firstVisibleScreenRow + newLinesEndRow = Math.min(@firstRenderedScreenRow - 1, lastVisibleScreenRow) + lineElements = @buildLineElements(newLinesStartRow, newLinesEndRow) + @insertLineElements(newLinesStartRow, lineElements) + @lines.css('padding-top', firstVisibleScreenRow * @lineHeight) if lastVisibleScreenRow > @lastRenderedScreenRow - startRow = Math.max(@lastRenderedScreenRow + 1, firstVisibleScreenRow) - lineElements = @buildLineElements(startRow, lastVisibleScreenRow) - @insertLineElements(startRow, lineElements) + newLinesStartRow = Math.max(@lastRenderedScreenRow + 1, firstVisibleScreenRow) + newLinesEndRow = lastVisibleScreenRow + lineElements = @buildLineElements(newLinesStartRow, newLinesEndRow) + @insertLineElements(newLinesStartRow, lineElements) @lines.css('padding-bottom', (@getLastScreenRow() - lastVisibleScreenRow) * @lineHeight) @firstRenderedScreenRow = firstVisibleScreenRow @@ -385,8 +392,13 @@ class Editor extends View @spliceLineElements(startRow, endRow - startRow + 1) spliceLineElements: (startScreenRow, rowCount, lineElements) -> - startRow = startScreenRow - @firstRenderedScreenRow + if startScreenRow < @firstRenderedScreenRow + startRow = 0 + else + startRow = startScreenRow - @firstRenderedScreenRow endRow = startRow + rowCount + + elementToInsertBefore = @lineCache[startRow] elementsToReplace = @lineCache[startRow...endRow] @lineCache[startRow...endRow] = lineElements?.toArray() or []