content.coffee 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184
  1. class app.views.Content extends app.View
  2. @el: '._content'
  3. @loadingClass: '_content-loading'
  4. @events:
  5. click: 'onClick'
  6. @shortcuts:
  7. altUp: 'scrollStepUp'
  8. altDown: 'scrollStepDown'
  9. pageUp: 'scrollPageUp'
  10. pageDown: 'scrollPageDown'
  11. pageTop: 'scrollToTop'
  12. pageBottom: 'scrollToBottom'
  13. altF: 'onAltF'
  14. @routes:
  15. before: 'beforeRoute'
  16. after: 'afterRoute'
  17. init: ->
  18. @scrollEl = if app.isMobile() then document.body else @el
  19. @scrollMap = {}
  20. @scrollStack = []
  21. @rootPage = new app.views.RootPage
  22. @staticPage = new app.views.StaticPage
  23. @settingsPage = new app.views.SettingsPage
  24. @offlinePage = new app.views.OfflinePage
  25. @typePage = new app.views.TypePage
  26. @entryPage = new app.views.EntryPage
  27. @entryPage
  28. .on 'loading', @onEntryLoading
  29. .on 'loaded', @onEntryLoaded
  30. app
  31. .on 'ready', @onReady
  32. .on 'bootError', @onBootError
  33. return
  34. show: (view) ->
  35. @hideLoading()
  36. unless view is @view
  37. @view?.deactivate()
  38. @html @view = view
  39. @view.activate()
  40. return
  41. showLoading: ->
  42. @addClass @constructor.loadingClass
  43. return
  44. isLoading: ->
  45. @el.classList.contains @constructor.loadingClass
  46. hideLoading: ->
  47. @removeClass @constructor.loadingClass
  48. return
  49. scrollTo: (value) ->
  50. @scrollEl.scrollTop = value or 0
  51. return
  52. smoothScrollTo: (value) ->
  53. if app.settings.get('fastScroll')
  54. @scrollTo value
  55. else
  56. $.smoothScroll @scrollEl, value or 0
  57. return
  58. scrollBy: (n) ->
  59. @smoothScrollTo @scrollEl.scrollTop + n
  60. return
  61. scrollToTop: =>
  62. @smoothScrollTo 0
  63. return
  64. scrollToBottom: =>
  65. @smoothScrollTo @scrollEl.scrollHeight
  66. return
  67. scrollStepUp: =>
  68. @scrollBy -80
  69. return
  70. scrollStepDown: =>
  71. @scrollBy 80
  72. return
  73. scrollPageUp: =>
  74. @scrollBy 40 - @scrollEl.clientHeight
  75. return
  76. scrollPageDown: =>
  77. @scrollBy @scrollEl.clientHeight - 40
  78. return
  79. scrollToTarget: ->
  80. return if @isLoading()
  81. if @routeCtx.hash and el = @findTargetByHash @routeCtx.hash
  82. $.scrollToWithImageLock el, @scrollEl, 'top',
  83. margin: 20 + if @scrollEl is @el then 0 else $.offset(@el).top
  84. $.highlight el, className: '_highlight'
  85. else
  86. @scrollTo @scrollMap[@routeCtx.state.id]
  87. clearTimeout @scrollTimeout
  88. return
  89. onReady: =>
  90. @hideLoading()
  91. return
  92. onBootError: =>
  93. @hideLoading()
  94. @html @tmpl('bootError')
  95. return
  96. onEntryLoading: =>
  97. @showLoading()
  98. return
  99. onEntryLoaded: =>
  100. @hideLoading()
  101. @scrollToTarget()
  102. return
  103. beforeRoute: (context) =>
  104. @cacheScrollPosition()
  105. @routeCtx = context
  106. @scrollTimeout = @delay @scrollToTarget
  107. return
  108. cacheScrollPosition: ->
  109. return if not @routeCtx or @routeCtx.hash
  110. unless @scrollMap[@routeCtx.state.id]?
  111. @scrollStack.push @routeCtx.state.id
  112. while @scrollStack.length > app.config.history_cache_size
  113. delete @scrollMap[@scrollStack.shift()]
  114. @scrollMap[@routeCtx.state.id] = @scrollEl.scrollTop
  115. return
  116. afterRoute: (route, context) =>
  117. switch route
  118. when 'root'
  119. @show @rootPage
  120. when 'entry'
  121. @show @entryPage
  122. when 'type'
  123. @show @typePage
  124. when 'settings'
  125. @show @settingsPage
  126. when 'offline'
  127. @show @offlinePage
  128. else
  129. @show @staticPage
  130. @view.onRoute(context)
  131. app.document.setTitle @view.getTitle?()
  132. return
  133. onClick: (event) =>
  134. link = $.closestLink event.target, @el
  135. if link and @isExternalUrl link.getAttribute('href')
  136. $.stopEvent(event)
  137. $.popup(link)
  138. return
  139. onAltF: (event) =>
  140. unless document.activeElement and $.hasChild @el, document.activeElement
  141. @find('a:not(:empty)')?.focus()
  142. $.stopEvent(event)
  143. findTargetByHash: (hash) ->
  144. el = try $.id decodeURIComponent(hash) catch
  145. el or= try $.id(hash) catch
  146. el
  147. isExternalUrl: (url) ->
  148. url?[0..5] in ['http:/', 'https:']