diff --git a/spec/editor-component-spec.coffee b/spec/editor-component-spec.coffee index e3bdbac5e..d8ff96259 100644 --- a/spec/editor-component-spec.coffee +++ b/spec/editor-component-spec.coffee @@ -743,6 +743,19 @@ describe "EditorComponent", -> expect(selectionNode.offsetTop).toBe editor.getLineHeightInPixels() expect(selectionNode.offsetLeft).toBe editor.pixelPositionForScreenPosition([1, 6]).left + it "will flash the selection when flash:true is passed to editor::setSelectedBufferRange", -> + editor.setSelectedBufferRange([[1, 6], [1, 10]], flash: true) + runSetImmediateCallbacks() + selectionNode = node.querySelector('.selection') + expect(selectionNode.classList.contains('highlighted')).toBe true + + advanceClock 500 + expect(selectionNode.classList.contains('highlighted')).toBe false + + editor.setSelectedBufferRange([[1, 5], [1, 7]], flash: true) + runSetImmediateCallbacks() + expect(selectionNode.classList.contains('highlighted')).toBe true + describe "line decoration rendering", -> [marker, decoration] = [] diff --git a/src/decoration.coffee b/src/decoration.coffee index 3949f857d..13b73c843 100644 --- a/src/decoration.coffee +++ b/src/decoration.coffee @@ -18,6 +18,7 @@ class Decoration constructor: (@marker, @params) -> @id = nextId() @params.id = @id + @flashQueue = null getParams: -> @params @@ -32,4 +33,11 @@ class Decoration true flash: (klass, duration=500) -> - @emit('flash', klass, duration) + flashObject = {class: klass, duration} + @flashQueue ?= [] + @flashQueue.push(flashObject) + @emit('flash') + + consumeNextFlash: -> + return @flashQueue.shift() if @flashQueue?.length > 0 + null diff --git a/src/highlight-component.coffee b/src/highlight-component.coffee index 20eb3676f..6bf7b5ffb 100644 --- a/src/highlight-component.coffee +++ b/src/highlight-component.coffee @@ -23,22 +23,22 @@ HighlightComponent = React.createClass if decoration.id? @decoration = editor.decorationForId(decoration.id) @decoration.on 'flash', @startFlashAnimation - - componentDidUpdate: -> - @startFlashAnimation() if @props.decoration.flash? + @startFlashAnimation() componentWillUnmount: -> @decoration?.off 'flash', @startFlashAnimation - startFlashAnimation: (klass, duration) -> + startFlashAnimation: -> + return unless flash = @decoration.consumeNextFlash() + node = @getDOMNode() - node.classList.remove(klass) + node.classList.remove(flash.class) requestAnimationFrame => - node.classList.add(klass) + node.classList.add(flash.class) clearTimeout(@flashTimeoutId) - removeFlashClass = -> node.classList.remove(klass) - @flashTimeoutId = setTimeout(removeFlashClass, duration) + removeFlashClass = -> node.classList.remove(flash.class) + @flashTimeoutId = setTimeout(removeFlashClass, flash.duration) renderSingleLineRegions: -> {startPixelPosition, endPixelPosition, lineHeightInPixels} = @props diff --git a/src/selection.coffee b/src/selection.coffee index c91a0c81d..5ffa91154 100644 --- a/src/selection.coffee +++ b/src/selection.coffee @@ -78,9 +78,12 @@ class Selection extends Model options.reversed ?= @isReversed() @editor.destroyFoldsIntersectingBufferRange(bufferRange) unless options.preserveFolds @modifySelection => + needsFlash = options.flash + delete options.flash if options.flash? @cursor.needsAutoscroll = false if @needsAutoscroll? @marker.setBufferRange(bufferRange, options) @autoscroll() if @needsAutoscroll and @editor.manageScrollPosition + @decoration.flash('highlighted', 500) if needsFlash # Public: Returns the starting and ending buffer rows the selection is # highlighting.