From 10d49c6983ef1e8b57abde2141e86da7f081877d Mon Sep 17 00:00:00 2001 From: Damien Mathieu <42@dmathieu.com> Date: Fri, 13 Dec 2013 15:05:32 +0100 Subject: [PATCH 1/2] refactor and add tests to tailing --- assets/scripts/app/app.coffee | 2 +- assets/scripts/app/tailing.coffee | 53 +++++++------ assets/scripts/spec/unit/tailing_spec.coffee | 78 ++++++++++++++++++++ assets/styles/main/log.sass | 4 + 4 files changed, 112 insertions(+), 25 deletions(-) create mode 100644 assets/scripts/spec/unit/tailing_spec.coffee diff --git a/assets/scripts/app/app.coffee b/assets/scripts/app/app.coffee index 4e16be6f..3f5adc8e 100644 --- a/assets/scripts/app/app.coffee +++ b/assets/scripts/app/app.coffee @@ -33,7 +33,7 @@ unless window.TravisApplication @slider = new Travis.Slider() @pusher = new Travis.Pusher(Travis.config.pusher_key) if Travis.config.pusher_key - @tailing = new Travis.Tailing() + @tailing = new Travis.Tailing($(window), '#tail', '#log') @set('auth', Travis.Auth.create(app: this, endpoint: Travis.config.api_endpoint)) diff --git a/assets/scripts/app/tailing.coffee b/assets/scripts/app/tailing.coffee index 276b18c7..a9be33df 100644 --- a/assets/scripts/app/tailing.coffee +++ b/assets/scripts/app/tailing.coffee @@ -1,12 +1,17 @@ -@Travis.Tailing = -> - @position = $(window).scrollTop() - $(window).scroll( $.throttle( 200, @onScroll.bind(this) ) ) - this - -$.extend Travis.Tailing.prototype, +class @Travis.Tailing options: timeout: 200 + tail: -> + $(@tail_selector) + log: -> + $(@log_selector) + + constructor: (@window, @tail_selector, @log_selector) -> + @position = @window.scrollTop() + @window.scroll( $.throttle( 200, @onScroll.bind(this) ) ) + this + run: -> @autoScroll() @positionButton() @@ -16,38 +21,38 @@ $.extend Travis.Tailing.prototype, if @active() then @stop() else @start() active: -> - $('#tail').hasClass('active') + @tail().hasClass('active') start: -> - $('#tail').addClass('active') + @tail().addClass('active') @run() stop: -> - $('#tail').removeClass('active') + @tail().removeClass('active') autoScroll: -> - return unless @active() - win = $(window) - log = $('#log') - logBottom = log.offset().top + log.outerHeight() + 40 - winBottom = win.scrollTop() + win.height() - win.scrollTop(logBottom - win.height()) if logBottom - winBottom > 0 + return false unless @active() + logBottom = @log().offset().top + @log().outerHeight() + 40 + winBottom = @window.scrollTop() + @window.height() + + if logBottom - winBottom > 0 + @window.scrollTop(logBottom - @window.height()) + true + else + false onScroll: -> @positionButton() - position = $(window).scrollTop() + position = @window.scrollTop() @stop() if position < @position @position = position positionButton: -> - tail = $('#tail') - return if tail.length is 0 - offset = $(window).scrollTop() - $('#log').offset().top - max = $('#log').height() - $('#tail').height() + 5 + return if @tail().length is 0 + offset = @window.scrollTop() - @log().offset().top + max = @log().height() - @tail().height() + 5 offset = max if offset > max - if offset > 0 - tail.css(position: 'fixed', right: 32) + @tail().addClass('scrolling') else - tail.css(position: 'absolute', right: 2) - + @tail().removeClass('scrolling') diff --git a/assets/scripts/spec/unit/tailing_spec.coffee b/assets/scripts/spec/unit/tailing_spec.coffee new file mode 100644 index 00000000..a3d59125 --- /dev/null +++ b/assets/scripts/spec/unit/tailing_spec.coffee @@ -0,0 +1,78 @@ +fakeWindow = + scroll: sinon.spy() + scrollTop: sinon.stub().returns(0) + height: sinon.stub().returns(40) +element = jQuery('
') +log = jQuery('') +tail = new Travis.Tailing(fakeWindow, '#specTail', '#specLog') +tail.tail = -> element +tail.log = -> log + +module "Travis.Tailing", + setup: -> + jQuery('body').append(element) + jQuery('body').append(log) + + teardown: -> + element.remove() + log.remove() + tail.stop() + +test "toggle", -> + equal(element.hasClass('active'), false) + tail.toggle() + equal(element.hasClass('active'), true) + tail.toggle() + stop() + + Ember.run.later -> + start() + equal(element.hasClass('active'), false) + , 300 + +test "active", -> + equal(tail.active(), false) + element.addClass('active') + equal(tail.active(), true) + +test "autoscroll when inactive", -> + tail.scrollTo = sinon.spy() + + equal(tail.active(), false) + equal(tail.autoScroll(), false) + equal(tail.scrollTo.called, false) + +test "autoscroll", -> + element.addClass('active') + log.offset = -> {top: 1} + log.outerHeight = -> 1 + + equal(tail.active(), true) + equal(tail.autoScroll(), true) + equal(fakeWindow.scrollTop.calledWith(2), true) + +test "autoscroll when we're at the bottom", -> + element.addClass('active') + log.offset = -> {top: 0} + log.outerHeight = -> 0 + + equal(tail.active(), true) + equal(tail.autoScroll(), false) + equal(fakeWindow.scrollTop.calledWith(0), false) + +test 'should stop scrolling if the position changed', -> + element.addClass('active') + tail.position = 100 + tail.onScroll() + equal(element.hasClass('active'), false) + +test 'positionButton adds the scrolling class', -> + log.offset = -> {top: -1} + + tail.positionButton() + equal(element.hasClass('scrolling'), true) + +test 'positionButton removes the scrolling class', -> + log.offset = -> {top: 1} + tail.positionButton() + equal(element.hasClass('scrolling'), false) diff --git a/assets/styles/main/log.sass b/assets/styles/main/log.sass index 54e1067e..c88a8dcf 100644 --- a/assets/styles/main/log.sass +++ b/assets/styles/main/log.sass @@ -117,6 +117,10 @@ pre#log label display: inline + &.scrolling + position: fixed + right: 32px + .status display: inline-block margin-right: 1px From 1920785f507cc37bb2ae9607f20c76debc9d77e4 Mon Sep 17 00:00:00 2001 From: Damien Mathieu <42@dmathieu.com> Date: Fri, 13 Dec 2013 17:01:02 +0100 Subject: [PATCH 2/2] fix regression when going below the log zone Since a431b68c2858a2d96f35accfe577497344de98a2, when going below the max of the log files, the position button would remain in fixed position. This fixes it. --- assets/scripts/app/tailing.coffee | 9 +++++++-- assets/scripts/spec/unit/tailing_spec.coffee | 11 +++++++++++ assets/styles/main/log.sass | 4 ++++ 3 files changed, 22 insertions(+), 2 deletions(-) diff --git a/assets/scripts/app/tailing.coffee b/assets/scripts/app/tailing.coffee index a9be33df..3df8c872 100644 --- a/assets/scripts/app/tailing.coffee +++ b/assets/scripts/app/tailing.coffee @@ -51,8 +51,13 @@ class @Travis.Tailing return if @tail().length is 0 offset = @window.scrollTop() - @log().offset().top max = @log().height() - @tail().height() + 5 - offset = max if offset > max - if offset > 0 + + if offset > 0 && offset <= max + @tail().removeClass('bottom') @tail().addClass('scrolling') else + if offset > max + @tail().addClass('bottom') + else + @tail().removeClass('bottom') @tail().removeClass('scrolling') diff --git a/assets/scripts/spec/unit/tailing_spec.coffee b/assets/scripts/spec/unit/tailing_spec.coffee index a3d59125..18a836f0 100644 --- a/assets/scripts/spec/unit/tailing_spec.coffee +++ b/assets/scripts/spec/unit/tailing_spec.coffee @@ -71,8 +71,19 @@ test 'positionButton adds the scrolling class', -> tail.positionButton() equal(element.hasClass('scrolling'), true) + equal(element.hasClass('bottom'), false) test 'positionButton removes the scrolling class', -> log.offset = -> {top: 1} tail.positionButton() equal(element.hasClass('scrolling'), false) + equal(element.hasClass('bottom'), false) + +test 'positionButton sets the button as bottom', -> + log.offset = -> {top: -100} + log.height = -> 50 + tail.height = -> 1 + + tail.positionButton() + equal(element.hasClass('scrolling'), false) + equal(element.hasClass('bottom'), true) diff --git a/assets/styles/main/log.sass b/assets/styles/main/log.sass index c88a8dcf..2e0ad5ff 100644 --- a/assets/styles/main/log.sass +++ b/assets/styles/main/log.sass @@ -121,6 +121,10 @@ pre#log position: fixed right: 32px + &.bottom + bottom: 45px + top: inherit + .status display: inline-block margin-right: 1px