panel.js 5.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141
  1. // CodeMirror, copyright (c) by Marijn Haverbeke and others
  2. // Distributed under an MIT license: https://codemirror.net/LICENSE
  3. ;(function (mod) {
  4. if (typeof exports == 'object' && typeof module == 'object')
  5. // CommonJS
  6. mod(require('../../lib/codemirror'))
  7. else if (typeof define == 'function' && define.amd)
  8. // AMD
  9. define(['../../lib/codemirror'], mod)
  10. // Plain browser env
  11. else mod(CodeMirror)
  12. })(function (CodeMirror) {
  13. CodeMirror.defineExtension('addPanel', function (node, options) {
  14. options = options || {}
  15. if (!this.state.panels) initPanels(this)
  16. var info = this.state.panels
  17. var wrapper = info.wrapper
  18. var cmWrapper = this.getWrapperElement()
  19. var replace = options.replace instanceof Panel && !options.replace.cleared
  20. if (options.after instanceof Panel && !options.after.cleared) {
  21. wrapper.insertBefore(node, options.before.node.nextSibling)
  22. } else if (options.before instanceof Panel && !options.before.cleared) {
  23. wrapper.insertBefore(node, options.before.node)
  24. } else if (replace) {
  25. wrapper.insertBefore(node, options.replace.node)
  26. options.replace.clear(true)
  27. } else if (options.position == 'bottom') {
  28. wrapper.appendChild(node)
  29. } else if (options.position == 'before-bottom') {
  30. wrapper.insertBefore(node, cmWrapper.nextSibling)
  31. } else if (options.position == 'after-top') {
  32. wrapper.insertBefore(node, cmWrapper)
  33. } else {
  34. wrapper.insertBefore(node, wrapper.firstChild)
  35. }
  36. var height = (options && options.height) || node.offsetHeight
  37. var panel = new Panel(this, node, options, height)
  38. info.panels.push(panel)
  39. this.setSize()
  40. if (options.stable && isAtTop(this, node)) this.scrollTo(null, this.getScrollInfo().top + height)
  41. return panel
  42. })
  43. function Panel(cm, node, options, height) {
  44. this.cm = cm
  45. this.node = node
  46. this.options = options
  47. this.height = height
  48. this.cleared = false
  49. }
  50. /* when skipRemove is true, clear() was called from addPanel().
  51. * Thus removePanels() should not be called (issue 5518) */
  52. Panel.prototype.clear = function (skipRemove) {
  53. if (this.cleared) return
  54. this.cleared = true
  55. var info = this.cm.state.panels
  56. info.panels.splice(info.panels.indexOf(this), 1)
  57. this.cm.setSize()
  58. if (this.options.stable && isAtTop(this.cm, this.node)) this.cm.scrollTo(null, this.cm.getScrollInfo().top - this.height)
  59. info.wrapper.removeChild(this.node)
  60. if (info.panels.length == 0 && !skipRemove) removePanels(this.cm)
  61. }
  62. Panel.prototype.changed = function () {
  63. this.height = this.node.getBoundingClientRect().height
  64. this.cm.setSize()
  65. }
  66. function initPanels(cm) {
  67. var wrap = cm.getWrapperElement()
  68. var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle
  69. var height = parseInt(style.height)
  70. var info = (cm.state.panels = {
  71. setHeight: wrap.style.height,
  72. panels: [],
  73. wrapper: document.createElement('div'),
  74. })
  75. var hasFocus = cm.hasFocus(),
  76. scrollPos = cm.getScrollInfo()
  77. wrap.parentNode.insertBefore(info.wrapper, wrap)
  78. info.wrapper.appendChild(wrap)
  79. cm.scrollTo(scrollPos.left, scrollPos.top)
  80. if (hasFocus) cm.focus()
  81. cm._setSize = cm.setSize
  82. if (height != null)
  83. cm.setSize = function (width, newHeight) {
  84. if (!newHeight) newHeight = info.wrapper.offsetHeight
  85. info.setHeight = newHeight
  86. if (typeof newHeight != 'number') {
  87. var px = /^(\d+\.?\d*)px$/.exec(newHeight)
  88. if (px) {
  89. newHeight = Number(px[1])
  90. } else {
  91. info.wrapper.style.height = newHeight
  92. newHeight = info.wrapper.offsetHeight
  93. }
  94. }
  95. var editorheight =
  96. newHeight -
  97. info.panels
  98. .map(function (p) {
  99. return p.node.getBoundingClientRect().height
  100. })
  101. .reduce(function (a, b) {
  102. return a + b
  103. }, 0)
  104. cm._setSize(width, editorheight)
  105. height = newHeight
  106. }
  107. }
  108. function removePanels(cm) {
  109. var info = cm.state.panels
  110. cm.state.panels = null
  111. var wrap = cm.getWrapperElement()
  112. var hasFocus = cm.hasFocus(),
  113. scrollPos = cm.getScrollInfo()
  114. info.wrapper.parentNode.replaceChild(wrap, info.wrapper)
  115. cm.scrollTo(scrollPos.left, scrollPos.top)
  116. if (hasFocus) cm.focus()
  117. wrap.style.height = info.setHeight
  118. cm.setSize = cm._setSize
  119. cm.setSize()
  120. }
  121. function isAtTop(cm, dom) {
  122. for (var sibling = dom.nextSibling; sibling; sibling = sibling.nextSibling) if (sibling == cm.getWrapperElement()) return true
  123. return false
  124. }
  125. })