ChangeListView.coffee 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278
  1. define [
  2. "moment"
  3. "libs/mustache"
  4. "libs/backbone"
  5. ], (moment)->
  6. ChangeListView = Backbone.View.extend
  7. template: $("#changeListTemplate").html()
  8. events:
  9. "scroll" : () -> @loadUntilFull()
  10. initialize: () ->
  11. @itemViews = []
  12. @atEndOfCollection = false
  13. self = this
  14. @collection.on "add", (model) ->
  15. self.addItem model
  16. @collection.on "reset", (collection) ->
  17. self.addItem model for model in collection.models
  18. @selectedFromIndex = 0
  19. @selectedToIndex = 0
  20. @render()
  21. @hideLoading()
  22. render: ->
  23. @$el.html Mustache.to_html @template
  24. @$el.css
  25. overflow: "scroll"
  26. this
  27. addItem: (model) ->
  28. index = @collection.indexOf(model)
  29. view = new ChangeListItemView(model : model)
  30. @itemViews.push view
  31. elementAtIndex = @$(".change-list").children()[index]
  32. view.$el.insertBefore(elementAtIndex)
  33. view.on "click", (e, v) =>
  34. @setSelectionRange(index, index)
  35. view.on "selected:to", (e, v) =>
  36. @setSelectionRange(@selectedFromIndex, index)
  37. view.on "selected:from", (e, v) =>
  38. @setSelectionRange(index, @selectedToIndex)
  39. view.on "mouseenter:to", (e) =>
  40. @hoverToIndex = index
  41. @resetHoverStates()
  42. view.on "mouseleave:to", (e) =>
  43. delete @hoverToIndex
  44. @resetHoverStates()
  45. view.on "mouseenter:from", (e) =>
  46. @hoverFromIndex = index
  47. @resetHoverStates()
  48. view.on "mouseleave:from", (e) =>
  49. delete @hoverFromIndex
  50. @resetHoverStates()
  51. view.on "click:restore", (e) =>
  52. @trigger "restore", view.model
  53. view.resetSelector(index, @selectedFromIndex, @selectedToIndex)
  54. setSelectionRange: (fromIndex, toIndex) ->
  55. @selectedFromIndex = fromIndex
  56. @selectedToIndex = toIndex
  57. @resetAllSelectors()
  58. @triggerChangeDiff()
  59. resetAllSelectors: () ->
  60. for view, i in @itemViews
  61. view.resetSelector(i, @selectedFromIndex, @selectedToIndex)
  62. resetHoverStates: () ->
  63. if @hoverToIndex? and @hoverToIndex != @selectedToIndex
  64. @$("ul").addClass("hover-state")
  65. for view, i in @itemViews
  66. view.resetHoverState(i, @selectedFromIndex, @hoverToIndex)
  67. else if @hoverFromIndex? and @hoverFromIndex != @selectedFromIndex
  68. @$("ul").addClass("hover-state")
  69. for view, i in @itemViews
  70. view.resetHoverState(i, @hoverFromIndex, @selectedToIndex)
  71. else
  72. @$("ul").removeClass("hover-state")
  73. for view, i in @itemViews
  74. view.setHoverUnselected()
  75. triggerChangeDiff: () ->
  76. @trigger "change_diff", @collection.models[@selectedFromIndex], @collection.models[@selectedToIndex]
  77. listShorterThanContainer: ->
  78. @$el.height() > @$(".change-list").height()
  79. atEndOfListView: ->
  80. @$el.scrollTop() + @$el.height() >= @$(".change-list").height() - 30
  81. loadUntilFull: (callback = (error) ->) ->
  82. if (@listShorterThanContainer() or @atEndOfListView()) and not @atEndOfCollection and not @loading
  83. @showLoading()
  84. @hideEmptyMessage()
  85. @collection.fetchNextBatch
  86. error: (error) =>
  87. @hideLoading()
  88. @showEmptyMessageIfCollectionEmpty()
  89. callback(error)
  90. success: (collection, response) =>
  91. @hideLoading()
  92. if response.updates.length == @collection.batchSize
  93. @loadUntilFull(callback)
  94. else
  95. @atEndOfCollection = true
  96. @showEmptyMessageIfCollectionEmpty()
  97. callback()
  98. else
  99. callback() if callback?
  100. showEmptyMessageIfCollectionEmpty: ()->
  101. if @collection.isEmpty()
  102. @$(".empty-message").show()
  103. else
  104. @$(".empty-message").hide()
  105. hideEmptyMessage: () ->
  106. @$(".empty-message").hide()
  107. showLoading: ->
  108. @loading = true
  109. @$(".loading-changes").show()
  110. hideLoading: ->
  111. @loading = false
  112. @$(".loading-changes").hide()
  113. ChangeListItemView = Backbone.View.extend
  114. tagName: "li"
  115. events:
  116. "click .change-description" : "onClick"
  117. "click .change-selector-from" : "onFromSelectorClick"
  118. "click .change-selector-to" : "onToSelectorClick"
  119. "mouseenter .change-selector-to": (args...) ->
  120. @trigger "mouseenter:to", args...
  121. "mouseleave .change-selector-to": (args...) ->
  122. @trigger "mouseleave:to", args...
  123. "mouseenter .change-selector-from": (args...) ->
  124. @trigger "mouseenter:from", args...
  125. "mouseleave .change-selector-from": (args...) ->
  126. @trigger "mouseleave:from", args...
  127. "click .restore a": "onRestoreClick"
  128. templates:
  129. item: $("#changeListItemTemplate").html()
  130. user: $("#changeListItemUserTemplate").html()
  131. initialize: ->
  132. @render()
  133. render: ->
  134. userHtml = for user in @model.get("users")
  135. Mustache.to_html @templates.user, {
  136. hue: user.hue()
  137. name: user.name()
  138. }
  139. data = {
  140. date: moment(parseInt(@model.get("end_ts"), 10)).calendar()
  141. users: userHtml.join("")
  142. }
  143. @$el.html Mustache.to_html(@templates.item, data)
  144. return this
  145. onClick: (e) ->
  146. e.preventDefault()
  147. @trigger "click", e, @
  148. onToSelectorClick: (e) ->
  149. @trigger "selected:to", e, @
  150. onFromSelectorClick: (e) ->
  151. @trigger "selected:from", e, @
  152. onRestoreClick: (e) ->
  153. e.preventDefault()
  154. @trigger "click:restore", e, @
  155. isSelectedFrom: () ->
  156. @$(".change-selector-from").is(":checked")
  157. isSelectedTo: () ->
  158. @$(".change-selector-to").is(":checked")
  159. hideFromSelector: () ->
  160. @$(".change-selector-from").hide()
  161. showFromSelector: () ->
  162. @$(".change-selector-from").show()
  163. hideToSelector: () ->
  164. @$(".change-selector-to").hide()
  165. showToSelector: () ->
  166. @$(".change-selector-to").show()
  167. setFromChecked: (checked) ->
  168. @$(".change-selector-from").prop("checked", checked)
  169. setToChecked: (checked) ->
  170. @$(".change-selector-to").prop("checked", checked)
  171. setSelected: (first, last) ->
  172. @$el.addClass("selected")
  173. if first
  174. @$el.addClass("selected-to")
  175. else
  176. @$el.removeClass("selected-to")
  177. if last
  178. @$el.addClass("selected-from")
  179. else
  180. @$el.removeClass("selected-from")
  181. setUnselected: () ->
  182. @$el.removeClass("selected-to")
  183. @$el.removeClass("selected-from")
  184. @$el.removeClass("selected")
  185. setHoverSelected: (first, last) ->
  186. @$el.addClass("hover-selected")
  187. if first
  188. @$el.addClass("hover-selected-to")
  189. else
  190. @$el.removeClass("hover-selected-to")
  191. if last
  192. @$el.addClass("hover-selected-from")
  193. else
  194. @$el.removeClass("hover-selected-from")
  195. setHoverUnselected: () ->
  196. @$el.removeClass("hover-selected-to")
  197. @$el.removeClass("hover-selected-from")
  198. @$el.removeClass("hover-selected")
  199. resetSelector: (myIndex, selectedFromIndex, selectedToIndex) ->
  200. if myIndex >= selectedToIndex
  201. @showFromSelector()
  202. else
  203. @hideFromSelector()
  204. if myIndex <= selectedFromIndex
  205. @showToSelector()
  206. else
  207. @hideToSelector()
  208. if selectedToIndex <= myIndex <= selectedFromIndex
  209. @setSelected(selectedToIndex == myIndex, selectedFromIndex == myIndex)
  210. else
  211. @setUnselected()
  212. @setFromChecked(myIndex == selectedFromIndex)
  213. @setToChecked(myIndex == selectedToIndex)
  214. resetHoverState: (myIndex, hoverFromIndex, hoverToIndex) ->
  215. if hoverToIndex <= myIndex <= hoverFromIndex
  216. @setHoverSelected(hoverToIndex == myIndex, hoverFromIndex == myIndex)
  217. else
  218. @setHoverUnselected()
  219. return ChangeListView