entry_page.coffee 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. class app.views.EntryPage extends app.View
  2. @className: '_page'
  3. @errorClass: '_page-error'
  4. @events:
  5. click: 'onClick'
  6. @shortcuts:
  7. altO: 'onAltO'
  8. @routes:
  9. before: 'beforeRoute'
  10. init: ->
  11. @cacheMap = {}
  12. @cacheStack = []
  13. return
  14. deactivate: ->
  15. if super
  16. @empty()
  17. @entry = null
  18. return
  19. loading: ->
  20. @empty()
  21. @trigger 'loading'
  22. return
  23. render: (content = '', fromCache = false) ->
  24. return unless @activated
  25. @empty()
  26. @subview = new (@subViewClass()) @el, @entry
  27. $.batchUpdate @el, =>
  28. @subview.render(content, fromCache)
  29. @addClipboardLinks() unless fromCache
  30. return
  31. if app.disabledDocs.findBy 'slug', @entry.doc.slug
  32. @hiddenView = new app.views.HiddenPage @el, @entry
  33. @delay @polyfillMathML
  34. @trigger 'loaded'
  35. return
  36. addClipboardLinks: ->
  37. unless @clipBoardLink
  38. @clipBoardLink = document.createElement('a')
  39. @clipBoardLink.className = '_pre-clip'
  40. @clipBoardLink.title = 'Copy to clipboard'
  41. @clipBoardLink.tabIndex = -1
  42. el.appendChild(@clipBoardLink.cloneNode()) for el in @el.querySelectorAll('pre')
  43. return
  44. polyfillMathML: ->
  45. return unless window.supportsMathML is false and !@polyfilledMathML and @find('math')
  46. @polyfilledMathML = true
  47. $.append document.head, """<link rel="stylesheet" href="#{app.config.mathml_stylesheet}">"""
  48. return
  49. LINKS =
  50. home: 'Homepage'
  51. code: 'Source code'
  52. prepareContent: (content) ->
  53. return content unless @entry.isIndex() and @entry.doc.links
  54. links = for link, url of @entry.doc.links
  55. """<a href="#{url}" class="_links-link">#{LINKS[link]}</a>"""
  56. """<p class="_links">#{links.join('')}</p>#{content}"""
  57. empty: ->
  58. @subview?.deactivate()
  59. @subview = null
  60. @hiddenView?.deactivate()
  61. @hiddenView = null
  62. @resetClass()
  63. super
  64. return
  65. subViewClass: ->
  66. app.views["#{$.classify(@entry.doc.type)}Page"] or app.views.BasePage
  67. getTitle: ->
  68. @entry.doc.fullName + if @entry.isIndex() then ' documentation' else " / #{@entry.name}"
  69. beforeRoute: =>
  70. @abort()
  71. @cache()
  72. return
  73. onRoute: (context) ->
  74. isSameFile = context.entry.filePath() is @entry?.filePath()
  75. @entry = context.entry
  76. @restore() or @load() unless isSameFile
  77. return
  78. load: ->
  79. @loading()
  80. @xhr = @entry.loadFile @onSuccess, @onError
  81. return
  82. abort: ->
  83. if @xhr
  84. @xhr.abort()
  85. @xhr = null
  86. return
  87. onSuccess: (response) =>
  88. return unless @activated
  89. @xhr = null
  90. @render @prepareContent(response)
  91. return
  92. onError: =>
  93. @xhr = null
  94. @render @tmpl('pageLoadError')
  95. @resetClass()
  96. @addClass @constructor.errorClass
  97. app.appCache?.update()
  98. return
  99. cache: ->
  100. return if not @entry or @cacheMap[path = @entry.filePath()]
  101. @cacheMap[path] = @el.innerHTML
  102. @cacheStack.push(path)
  103. while @cacheStack.length > app.config.history_cache_size
  104. delete @cacheMap[@cacheStack.shift()]
  105. return
  106. restore: ->
  107. if @cacheMap[path = @entry.filePath()]
  108. @render @cacheMap[path], true
  109. true
  110. onClick: (event) =>
  111. target = event.target
  112. if target.hasAttribute 'data-retry'
  113. $.stopEvent(event)
  114. @load()
  115. else if target.classList.contains '_pre-clip'
  116. $.stopEvent(event)
  117. target.classList.add if $.copyToClipboard(target.parentNode.textContent) then '_pre-clip-success' else '_pre-clip-error'
  118. setTimeout (-> target.className = '_pre-clip'), 2000
  119. return
  120. onAltO: =>
  121. return unless link = @find('._attribution:last-child ._attribution-link')
  122. $.popup(link.href + location.hash)
  123. return