guide.coffee 6.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225
  1. #
  2. # Config
  3. #
  4. FETCH_URL = 'programs.php'
  5. HOUR_WIDTH = 200
  6. CHANNEL_LABEL_WIDTH = 180
  7. STORAGE_NAME = 'tvgids-channels'
  8. #SCROLL_MULTIPLIER = HOUR_WIDTH
  9. #
  10. # Utils
  11. #
  12. seconds_today = (time) -> (time - (new Date()).setHours(0, 0, 0, 0)) / 1000
  13. time2px = (seconds) -> HOUR_WIDTH / 3600 * seconds
  14. zeropad = (digit) -> if digit < 10 then '0' + digit else String(digit)
  15. format_time = (time) ->
  16. date = new Date(time)
  17. zeropad(date.getHours()) + ':' + zeropad(date.getMinutes())
  18. #
  19. # Models & collections
  20. #
  21. Channel = Backbone.Model.extend(
  22. defaults: ->
  23. id: null
  24. name: 'Some channel'
  25. visible: true
  26. programs: []
  27. )
  28. Program = Backbone.Model.extend(
  29. defaults: ->
  30. title: 'Some program'
  31. genre: ''
  32. sort: ''
  33. start: 0
  34. end: 0
  35. article_id: null
  36. article_title: null
  37. )
  38. ChannelList = Backbone.Collection.extend(
  39. model: Channel
  40. comparator: (a, b) -> parseInt(a.get('id')) - parseInt(b.get('id'))
  41. initialize: (models, options) ->
  42. @visible = if localStorage.hasOwnProperty(STORAGE_NAME) \
  43. then localStorage.getItem(STORAGE_NAME).split(',') else @pluck('id')
  44. fetch: ->
  45. @reset(CHANNELS)
  46. #@reset(CHANNELS.slice(0,3))
  47. #$.getJSON('channels.php', (data) => @reset(data))
  48. @propagateVisible()
  49. propagateVisible: ->
  50. for id in @visible
  51. if @length and not @findWhere(id: id)
  52. console.log 'not found:', id, typeof id, typeof @at(0).get('id')
  53. @findWhere(id: id)?.set(visible: true)
  54. for id in _.difference(@pluck('id'), @visible)
  55. if not @findWhere(id: id)
  56. console.log 'not found:', id
  57. @findWhere(id: id)?.set(visible: false)
  58. fetchPrograms: (day) ->
  59. $.getJSON(
  60. FETCH_URL
  61. channels: @pluck('id').join(','), day: day
  62. (channels) ->
  63. _.each channels, (programs, id) ->
  64. channel = Channels.findWhere(id: id)
  65. channel.set('programs', (
  66. new Program(
  67. title: p.titel
  68. genre: p.genre
  69. sort: p.soort
  70. start: Date.parse(p.datum_start)
  71. end: Date.parse(p.datum_end)
  72. article_id: p.artikel_id
  73. article_title: p.artikel_titel
  74. ) for p in programs
  75. ))
  76. )
  77. )
  78. #
  79. # Views
  80. #
  81. ChannelView = Backbone.View.extend(
  82. tagName: 'div'
  83. className: 'channel'
  84. initialize: ->
  85. @listenTo(@model, 'change:programs', @render)
  86. @listenTo(@model, 'change:visible', @toggleVisible)
  87. #@$el.text(@model.get('title'))
  88. render: ->
  89. @$el.empty()
  90. _.each @model.get('programs'), (program) =>
  91. view = new ProgramView(model: program)
  92. view.render()
  93. @$el.append(view.el)
  94. toggleVisible: ->
  95. @$el.toggle(@model.get('visible'))
  96. )
  97. ProgramView = Backbone.View.extend(
  98. tagName: 'div'
  99. className: 'program'
  100. initialize: ->
  101. @$el.text(@model.get('title'))
  102. from = format_time(@model.get('start'))
  103. to = format_time(@model.get('end'))
  104. @$el.attr('title', @model.get('title') + " (#{from} - #{to})")
  105. left = time2px(Math.max(0, seconds_today(@model.get('start'))))
  106. width = time2px(seconds_today(@model.get('end'))) - left
  107. @$el.css(
  108. left: left + 'px'
  109. width: (width - 10) + 'px'
  110. )
  111. render: ->
  112. if @model.get('start') <= Date.now()
  113. if @model.get('end') < Date.now()
  114. @$el.removeClass('current').addClass('past')
  115. else
  116. @$el.addClass('current')
  117. )
  118. ChannelLabelView = Backbone.View.extend(
  119. el: $('.channel-labels')
  120. initialize: (options) ->
  121. @listenTo(Channels, 'reset', @addChannels)
  122. @listenTo(options.app, 'scroll', @moveTop)
  123. addChannels: ->
  124. @$el.empty()
  125. Channels.each((channel) ->
  126. elem = $('<div id="label-' + channel.get('id') + '" class="label"/>')
  127. elem.html(channel.get('name')).toggle(channel.get('visible')).appendTo(@el)
  128. @listenTo(channel, 'change:visible', -> @toggleVisible(channel))
  129. , @)
  130. moveTop: (delta) ->
  131. @$el.css('top', (@$el.position().top - delta) + 'px')
  132. toggleVisible: (channel) ->
  133. @$('#label-' + channel.get('id')).toggle(channel.get('visible'))
  134. )
  135. AppView = Backbone.View.extend(
  136. el: $('#guide')
  137. events:
  138. 'click #yesterday': -> @loadDay(-1)
  139. 'click #today': -> @loadDay(0)
  140. 'click #tomorrow': -> @loadDay(1)
  141. 'scroll': 'moveTimeline'
  142. moveTimeline: ->
  143. if @$el.scrollTop() != @prevScrollTop
  144. @trigger('scroll', @$el.scrollTop() - @prevScrollTop)
  145. @prevScrollTop = @$el.scrollTop()
  146. @$('.timeline').css('top', (@$el.scrollTop() + 37) + 'px')
  147. initialize: ->
  148. @prevScrollTop = null
  149. @listenTo(Channels, 'reset', @addChannels)
  150. @listenTo(Settings, 'change:day', @fetchPrograms)
  151. @labelview = new ChannelLabelView(app: @)
  152. @updateIndicator()
  153. @centerIndicator()
  154. Channels.fetch()
  155. setInterval((=> @updateIndicator()), 3600000 / HOUR_WIDTH)
  156. addChannels: ->
  157. @$('.channels > .channel').remove()
  158. Channels.each((channel) ->
  159. view = new ChannelView(model: channel)
  160. view.render()
  161. @$('.channels').append(view.el)
  162. , @)
  163. @$('.indicator').height(@$('.channels').height())
  164. @fetchPrograms()
  165. loadDay: (day) ->
  166. Settings.set(day: day)
  167. @$('.navbar .active').removeClass('active')
  168. $(@$('.navbar .navitem')[day + 1]).addClass('active')
  169. updateIndicator: ->
  170. left = time2px(seconds_today(Date.now())) + CHANNEL_LABEL_WIDTH - 1
  171. @$('.indicator').css('left', left + 'px')
  172. centerIndicator: ->
  173. @$el.scrollLeft(@$('.indicator').position().left - @$el.width() / 2)
  174. fetchPrograms: ->
  175. Channels.fetchPrograms(Settings.get('day'))
  176. )
  177. #
  178. # Main
  179. #
  180. Settings = new (Backbone.Model.extend(
  181. defaults: ->
  182. day: 0
  183. ))()
  184. Channels = new ChannelList()
  185. App = new AppView()