diff --git a/assets/scripts/app/controllers/build.coffee b/assets/scripts/app/controllers/build.coffee index 1efa56bd..6e61ab6f 100644 --- a/assets/scripts/app/controllers/build.coffee +++ b/assets/scripts/app/controllers/build.coffee @@ -2,7 +2,6 @@ Travis.BuildController = Ember.Controller.extend needs: ['repo'] repoBinding: 'controllers.repo.repo' commitBinding: 'build.commit' - lineNumbersBinding: 'controllers.repo.lineNumbers' currentUserBinding: 'controllers.repo.currentUser' tabBinding: 'controllers.repo.tab' diff --git a/assets/scripts/app/controllers/job.coffee b/assets/scripts/app/controllers/job.coffee index 92e97862..7365d06d 100644 --- a/assets/scripts/app/controllers/job.coffee +++ b/assets/scripts/app/controllers/job.coffee @@ -4,7 +4,6 @@ Travis.JobController = Em.Controller.extend jobBinding: 'controllers.repo.job' repoBinding: 'controllers.repo.repo' commitBinding: 'job.commit' - lineNumbersBinding: 'controllers.repo.lineNumbers' currentUserBinding: 'controllers.repo.currentUser' tabBinding: 'controllers.repo.tab' diff --git a/assets/scripts/app/controllers/repo.coffee b/assets/scripts/app/controllers/repo.coffee index cbd4fa34..88276d71 100644 --- a/assets/scripts/app/controllers/repo.coffee +++ b/assets/scripts/app/controllers/repo.coffee @@ -72,13 +72,3 @@ Travis.RepoController = Travis.Controller.extend urlGithub: (-> Travis.Urls.githubRepo(@get('repo.slug')) ).property('repo.slug') - - setLineNumbers: (start, end) -> - lines = [] - index = start - - while index <= (end || start) - lines.push(index) - index++ - - @set('lineNumbers', lines) diff --git a/assets/scripts/app/routes.coffee b/assets/scripts/app/routes.coffee index 6907527d..4739e648 100644 --- a/assets/scripts/app/routes.coffee +++ b/assets/scripts/app/routes.coffee @@ -1,5 +1,4 @@ require 'travis/location' -require 'travis/line_number_parser' Ember.Router.reopen location: (if testMode? then Ember.NoneLocation.create() else Travis.Location.create()) @@ -80,12 +79,6 @@ Ember.Route.reopen Travis.storeAfterSignInPath(path) @transitionTo('auth') -Travis.Router.reopen - transitionTo: -> - this.container.lookup('controller:repo').set('lineNumbers', []) - - @_super.apply this, arguments - Travis.Router.map -> @resource 'index', path: '/', -> @route 'current', path: '/' @@ -109,13 +102,6 @@ Travis.Router.map -> @route 'index', path: '/' @route 'profile', path: '/profile' -Travis.ApplicationRoute = Ember.Route.extend Travis.LineNumberParser, - setupController: -> - @_super.apply this, arguments - - line_numbers = @fetchLineNumbers(document.location.hash) - this.controllerFor('repo').setLineNumbers line_numbers[0], line_numbers[1] - Travis.SetupLastBuild = Ember.Mixin.create setupController: -> @repoDidLoad() diff --git a/assets/scripts/app/views/log.coffee b/assets/scripts/app/views/log.coffee index f2216ad1..631765b3 100644 --- a/assets/scripts/app/views/log.coffee +++ b/assets/scripts/app/views/log.coffee @@ -1,4 +1,5 @@ require 'log' +require 'travis/lines_selector' Log.DEBUG = false Log.LIMIT = 10000 @@ -26,12 +27,12 @@ Travis.reopen console.log 'log view: did insert' if Log.DEBUG @_super.apply this, arguments @createEngine() - @lineNumbersDidChange() willDestroyElement: -> console.log 'log view: will destroy' if Log.DEBUG parts = @get('log.parts') parts.removeArrayObserver(@, didChange: 'partsDidChange', willChange: 'noop') + @lineSelector?.willDestroy() versionDidChange: (-> @rerender() if @get('state') == 'inDOM' @@ -46,8 +47,8 @@ Travis.reopen console.log 'log view: create engine' if Log.DEBUG @scroll = new Log.Scroll @engine = Log.create(limit: Log.LIMIT, listeners: [@scroll]) + @lineSelector = new Travis.LinesSelector(@$().find('#log'), @scroll, window.location) @observeParts() - @numberLineOnHover() observeParts: -> parts = @get('log.parts') @@ -63,10 +64,6 @@ Travis.reopen @engine.set(part.number, part.content) @propertyDidChange('limited') - lineNumbersDidChange: (-> - @scroll.set(numbers) if !@get('isDestroyed') && numbers = @get('controller.lineNumbers') - ).observes('controller.lineNumbers') - limited: (-> @engine?.limit?.limited ).property() @@ -79,37 +76,11 @@ Travis.reopen Travis.tailing.toggle() event.preventDefault() - numberLineOnHover: -> - $('#log').on 'mouseenter', 'a', (event) -> - hovered = $("#log p:visible").index(@parentNode) + 1 - selected = $("#log p:visible").index($('#log p.highlight')) + 1 - - if event.shiftKey - end = "-L#{hovered}" - start = selected - else - start = hovered - end = '' - - $(@).attr('href', "#L#{start}#{end}") - click: (event) -> - if (href = $(event.target).attr('href')) && matches = href?.match(Travis.LineNumberRegex) - lines = [matches[1], matches[3]].sort (a, b) -> a - b - - @lineNumberClicked(lines[0], lines[1]) - event.stopPropagation() - false - else - target = $(event.target) + target = $(event.target) + if target.prop('tagName') == 'P' target.closest('.fold').toggleClass('open') - lineNumberClicked: (start, end) -> - second_number = if end then "-L#{end}" else '' - path = "#{window.location.pathname}#L#{start}#{second_number}" - window.history.pushState({ path: path }, null, path); - @get('controller.controllers.repo').setLineNumbers(start, end) - actions: toTop: () -> $(window).scrollTop(0) @@ -118,32 +89,14 @@ Travis.reopen Log.Scroll = -> Log.Scroll.prototype = $.extend new Log.Listener, - set: (numbers) -> - return unless numbers.length > 0 - @numbers = numbers - @tryScroll() - insert: (log, data, pos) -> @tryScroll() if @numbers true tryScroll: -> - @removeHighlights() - @scrollToFirstLine() - - first_line = @numbers[0] - 1 - last_line = @numbers[@numbers.length - 1] - - $('#log').find('p:visible').slice(first_line, last_line).addClass('highlight') - @numbers = undefined - - removeHighlights: -> - $('#log p.highlight').removeClass('highlight') - - scrollToFirstLine: -> - if element = $("#log p:visible")[@numbers[0] - 1] + if element = $("#log p:visible.highlight:first") $('#main').scrollTop(0) - $('html, body').scrollTop($(element).offset()?.top) # weird, html works in chrome, body in firefox + $('html, body').scrollTop(element.offset()?.top) # weird, html works in chrome, body in firefox # Log.Logger = -> # Log.Logger.prototype = $.extend new Log.Listener, diff --git a/assets/scripts/lib/travis/line_number_parser.coffee b/assets/scripts/lib/travis/line_number_parser.coffee deleted file mode 100644 index 8cbc87e2..00000000 --- a/assets/scripts/lib/travis/line_number_parser.coffee +++ /dev/null @@ -1,14 +0,0 @@ -Travis.LineNumberRegex = /#L(\d+)(-L(\d+))?$/ -Travis.LineNumberParser = Ember.Mixin.create - - fetchLineNumbers: (hash) -> - if match = hash.match(Travis.LineNumberRegex) - start = match[1] - end = match[3] - - if end? - [start, end] - else - [start] - else - [] diff --git a/assets/scripts/lib/travis/lines_selector.coffee b/assets/scripts/lib/travis/lines_selector.coffee new file mode 100644 index 00000000..1e3cfdc5 --- /dev/null +++ b/assets/scripts/lib/travis/lines_selector.coffee @@ -0,0 +1,53 @@ +class Travis.LinesSelector + element: null + scroll: null + location: null + + constructor: (@element, @scroll, @location) -> + Ember.run.scheduleOnce 'afterRender', this, -> + @highlightLines() + + @element.on 'click', 'a', (event) => + element = $(event.target).parent('p') + @loadLineNumbers(element, event.shiftKey) + + event.preventDefault() + false + + willDestroy: -> + @location.hash = '' + + loadLineNumbers: (element, multiple) -> + @setHashValueWithLine(element, multiple) + @highlightLines() + + highlightLines: -> + @removeAllHighlights() + + if lines = @getSelectedLines() + @element.find('p:visible').slice(lines.first, lines.last).addClass('highlight') + @scroll.tryScroll() + + setHashValueWithLine: (line, multiple) -> + line_number = @getLineNumberFromElement(line) + + if !multiple + hash = "#L#{line_number}" + else + selected_line = @element.find('p:visible.highlight:first')[0] + selected_number = @getLineNumberFromElement(selected_line) + lines = [line_number, selected_number].sort (a,b) -> a - b + hash = "#L#{lines[0]}-L#{lines[1]}" + @location.hash = hash + + getLineNumberFromElement: (element) -> + @element.find('p:visible').index(element) + 1 + + removeAllHighlights: -> + @element.find('p.highlight').removeClass('highlight') + + getSelectedLines: -> + if match = @location.hash.match(/#L(\d+)(-L(\d+))?$/) + first = match[1] - 1 + last = match[3] || match[1] + {first: first, last: last} diff --git a/assets/scripts/spec/unit/line_number_parser_spec.coffee b/assets/scripts/spec/unit/line_number_parser_spec.coffee deleted file mode 100644 index e55e15e1..00000000 --- a/assets/scripts/spec/unit/line_number_parser_spec.coffee +++ /dev/null @@ -1,12 +0,0 @@ -object = Ember.Object.extend(Travis.LineNumberParser) -subject = object.create() - -module "Travis.LineNumberParser", - test "without line numbers", -> - deepEqual subject.fetchLineNumbers(''), [] - - test "with a start date only", -> - deepEqual subject.fetchLineNumbers('#L5'), ['5'] - - test "with a start and end dates", -> - deepEqual subject.fetchLineNumbers('#L5-L6'), ['5', '6'] diff --git a/assets/scripts/spec/unit/line_selector_spec.coffee b/assets/scripts/spec/unit/line_selector_spec.coffee new file mode 100644 index 00000000..6b2c177a --- /dev/null +++ b/assets/scripts/spec/unit/line_selector_spec.coffee @@ -0,0 +1,70 @@ +fakeLocation = {} +fakeScroll = + tryScroll: sinon.spy() + +element = jQuery('
') + +module "Travis.LinesSelector", + setup: -> + fakeLocation.hash = '' + jQuery('body').append(element) + + teardown: -> + element.remove() + +test "defaults to no line selected", -> + Ember.run -> + new Travis.LinesSelector(element, fakeScroll, fakeLocation) + + wait().then -> + equal($('#fakeLog p.highlight').length, 0) + +test "defaults to a single line selected", -> + fakeLocation.hash = '#L2' + Ember.run -> + new Travis.LinesSelector(element, fakeScroll, fakeLocation) + + wait().then -> + equal($('#fakeLog p.highlight').length, 1) + equal($('#fakeLog p:nth-child(2)').hasClass('highlight'), true) + +test "defaults to multiple lines selected", -> + fakeLocation.hash = '#L2-L3' + Ember.run -> + new Travis.LinesSelector(element, fakeScroll, fakeLocation) + + wait().then -> + equal($('#fakeLog p.highlight').length, 2) + equal($('#fakeLog p:nth-child(2)').hasClass('highlight'), true) + equal($('#fakeLog p:nth-child(3)').hasClass('highlight'), true) + +test "selects a single line", -> + Ember.run -> + new Travis.LinesSelector(element, fakeScroll, fakeLocation) + + wait().then -> + equal($('#fakeLog p.highlight').length, 0) + $('#fakeLog p:first a').click() + equal($('#fakeLog p.highlight').length, 1) + equal($('#fakeLog p:nth-child(1)').hasClass('highlight'), true) + equal('#L1', fakeLocation.hash) + +test "selects multiple lines", -> + fakeLocation.hash = '#L2' + Ember.run -> + new Travis.LinesSelector(element, fakeScroll, fakeLocation) + wait().then -> + equal($('#fakeLog p.highlight').length, 1) + + event = jQuery.Event('click') + event.shiftKey = true + $('#fakeLog p:first a').trigger(event) + + equal($('#fakeLog p.highlight').length, 2) + equal($('#fakeLog p:nth-child(1)').hasClass('highlight'), true) + equal($('#fakeLog p:nth-child(2)').hasClass('highlight'), true) + equal('#L1-L2', fakeLocation.hash)