From 5ef0302243b2d1ddcce1cf1c8fe72480b3c1db10 Mon Sep 17 00:00:00 2001
From: Damien Mathieu <42@dmathieu.com>
Date: Thu, 16 Jan 2014 12:11:37 +0100
Subject: [PATCH] automatically unfold lines starting or ending an highlight

---
 assets/scripts/app/views/log.coffee           |  2 +-
 .../scripts/lib/travis/lines_selector.coffee  | 11 +++++++-
 assets/scripts/lib/travis/log_folder.coffee   | 20 ++++++++++++--
 .../spec/unit/line_selector_spec.coffee       | 22 +++++++++++-----
 .../scripts/spec/unit/log_folder_spec.coffee  | 26 ++++++++++++++++---
 5 files changed, 67 insertions(+), 14 deletions(-)

diff --git a/assets/scripts/app/views/log.coffee b/assets/scripts/app/views/log.coffee
index ac68ee1b..927fa88a 100644
--- a/assets/scripts/app/views/log.coffee
+++ b/assets/scripts/app/views/log.coffee
@@ -48,8 +48,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)
       @logFolder = new Travis.LogFolder(@$().find('#log'))
+      @lineSelector = new Travis.LinesSelector(@$().find('#log'), @scroll, @logFolder)
       @observeParts()
 
     observeParts: ->
diff --git a/assets/scripts/lib/travis/lines_selector.coffee b/assets/scripts/lib/travis/lines_selector.coffee
index ba4242cb..1f81002c 100644
--- a/assets/scripts/lib/travis/lines_selector.coffee
+++ b/assets/scripts/lib/travis/lines_selector.coffee
@@ -10,10 +10,12 @@ class Travis.LinesSelector
   element: null
   scroll: null
   location: null
+  view: null
   last_selected_line: null
 
-  constructor: (@element, @scroll, location) ->
+  constructor: (@element, @scroll, @folder, location) ->
     @location = location || @Location
+
     Ember.run.scheduleOnce 'afterRender', this, ->
       @last_selected_line = @getSelectedLines()?.first
       @highlightLines()
@@ -38,6 +40,13 @@ class Travis.LinesSelector
     if lines = @getSelectedLines()
       @element.find('p:visible').slice(lines.first - 1, lines.last).addClass('highlight')
     @scroll.tryScroll()
+    @unfoldLines()
+
+  unfoldLines: ->
+    if lines = @getSelectedLines()
+      for index, l of lines
+        line = @element.find('p:visible').slice(l - 1, l)
+        @folder.unfold line
 
   setHashValueWithLine: (line, multiple) ->
     line_number = @getLineNumberFromElement(line)
diff --git a/assets/scripts/lib/travis/log_folder.coffee b/assets/scripts/lib/travis/log_folder.coffee
index 42506d3e..1d1bb1be 100644
--- a/assets/scripts/lib/travis/log_folder.coffee
+++ b/assets/scripts/lib/travis/log_folder.coffee
@@ -1,8 +1,24 @@
 class Travis.LogFolder
   constructor: (@element) ->
     @element.on 'click', '.fold', (event) =>
-      target = $(event.target).closest('.fold')
-      target.toggleClass('open')
+      folder = @getFolderFromLine $(event.target)
+      @toggle folder
 
       event.preventDefault()
       false
+
+  fold: (line) ->
+    folder = @getFolderFromLine(line)
+    if folder.hasClass('open')
+      @toggle(folder)
+
+  unfold: (line) ->
+    folder = @getFolderFromLine(line)
+    unless folder.hasClass('open')
+      @toggle(folder)
+
+  toggle: (folder) ->
+    folder.toggleClass('open')
+
+  getFolderFromLine: (line) ->
+    line.parent('.fold')
diff --git a/assets/scripts/spec/unit/line_selector_spec.coffee b/assets/scripts/spec/unit/line_selector_spec.coffee
index 04e882cf..93a5a7c3 100644
--- a/assets/scripts/spec/unit/line_selector_spec.coffee
+++ b/assets/scripts/spec/unit/line_selector_spec.coffee
@@ -7,6 +7,7 @@ fakeLocation = {
 
 fakeScroll =
   tryScroll: sinon.spy()
+fakeFolder = {}
 
 element = jQuery('<div id="fakeLog">
   <p><a></a>first line</p>
@@ -16,6 +17,7 @@ element = jQuery('<div id="fakeLog">
 
 module "Travis.LinesSelector",
   setup: ->
+    fakeFolder.unfold = sinon.spy()
     fakeLocation.hash = ''
     jQuery('body').append(element)
 
@@ -24,7 +26,7 @@ module "Travis.LinesSelector",
 
 test "defaults to no line selected", ->
   Ember.run ->
-    new Travis.LinesSelector(element, fakeScroll, fakeLocation)
+    new Travis.LinesSelector(element, fakeScroll, fakeFolder, fakeLocation)
 
   wait().then ->
     equal($('#fakeLog p.highlight').length, 0)
@@ -32,7 +34,7 @@ test "defaults to no line selected", ->
 test "defaults to a single line selected", ->
   fakeLocation.hash = '#L2'
   Ember.run ->
-    new Travis.LinesSelector(element, fakeScroll, fakeLocation)
+    new Travis.LinesSelector(element, fakeScroll, fakeFolder, fakeLocation)
 
   wait().then ->
     equal($('#fakeLog p.highlight').length, 1)
@@ -41,7 +43,7 @@ test "defaults to a single line selected", ->
 test "defaults to multiple lines selected", ->
   fakeLocation.hash = '#L2-L3'
   Ember.run ->
-    new Travis.LinesSelector(element, fakeScroll, fakeLocation)
+    new Travis.LinesSelector(element, fakeScroll, fakeFolder, fakeLocation)
 
   wait().then ->
     equal($('#fakeLog p.highlight').length, 2)
@@ -50,7 +52,7 @@ test "defaults to multiple lines selected", ->
 
 test "selects a single line", ->
   Ember.run ->
-    new Travis.LinesSelector(element, fakeScroll, fakeLocation)
+    new Travis.LinesSelector(element, fakeScroll, fakeFolder, fakeLocation)
 
   wait().then ->
     equal($('#fakeLog p.highlight').length, 0)
@@ -62,7 +64,7 @@ test "selects a single line", ->
 test "selects multiple lines", ->
   fakeLocation.hash = '#L2'
   Ember.run ->
-    new Travis.LinesSelector(element, fakeScroll, fakeLocation)
+    new Travis.LinesSelector(element, fakeScroll, fakeFolder, fakeLocation)
 
   wait().then ->
     equal($('#fakeLog p.highlight').length, 1)
@@ -79,7 +81,7 @@ test "selects multiple lines", ->
 test "uses the last selected line as second selection line", ->
   selector = null
   Ember.run ->
-    selector = new Travis.LinesSelector(element, fakeScroll, fakeLocation)
+    selector = new Travis.LinesSelector(element, fakeScroll, fakeFolder, fakeLocation)
 
   wait().then ->
     $('#fakeLog p:last a').click()
@@ -96,3 +98,11 @@ test "uses the last selected line as second selection line", ->
     equal($('#fakeLog p:nth-child(3)').hasClass('highlight'), true)
     equal('#L1-L3', fakeLocation.hash)
     equal(1, selector.last_selected_line)
+
+test "unfolds the first and last selected lines", ->
+  fakeLocation.hash = '#L1-L3'
+  Ember.run ->
+    new Travis.LinesSelector(element, fakeScroll, fakeFolder, fakeLocation)
+
+  wait().then ->
+    ok(fakeFolder.unfold.calledTwice, 'the first and last lines have been unfolded')
diff --git a/assets/scripts/spec/unit/log_folder_spec.coffee b/assets/scripts/spec/unit/log_folder_spec.coffee
index e3d1fccd..d683c45b 100644
--- a/assets/scripts/spec/unit/log_folder_spec.coffee
+++ b/assets/scripts/spec/unit/log_folder_spec.coffee
@@ -6,23 +6,24 @@ element = jQuery('<div id="fakeLog">
   </div>
   <p>fourth line</p>
 </div>')
+logFolder = null
 
 module "Travis.LogFolder",
   setup: ->
     jQuery('body').append(element)
-    new Travis.LogFolder jQuery('#fakeLog')
+    logFolder = new Travis.LogFolder jQuery('#fakeLog')
 
   teardown: ->
     element.remove()
 
 test "displays the fold", ->
   equal($('#fakeLog .fold.open').length, 0)
-  $('#fakeLog .fold').click()
+  $('#fakeLog .fold p:first').click()
   equal($('#fakeLog .fold.open').length, 1)
 
 test "hides the fold", ->
   $('#fakeLog .fold').addClass('open')
-  $('#fakeLog .fold').click()
+  $('#fakeLog .fold p:first').click()
   equal($('#fakeLog .fold.open').length, 0)
 
 test "binds new elements", ->
@@ -32,5 +33,22 @@ test "binds new elements", ->
   jQuery('#fakeLog').append new_element
 
   equal($('#fakeLog .fold.open').length, 0)
-  $('#fakeLog .fold').click()
+  $('#fakeLog .fold p:first-child').click()
   equal($('#fakeLog .fold.open').length, 2)
+
+test "fold", ->
+  fold = jQuery('#fakeLog .fold')
+  line = fold.find('p:first')
+  fold.addClass('open')
+
+  equal(fold.hasClass('open'), true)
+  logFolder.fold(line)
+  equal(fold.hasClass('open'), false)
+
+test "unfold", ->
+  fold = jQuery('#fakeLog .fold')
+  line = fold.find('p:first')
+
+  equal(fold.hasClass('open'), false)
+  logFolder.unfold(line)
+  equal(fold.hasClass('open'), true)