You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

133 lines
4.6 KiB

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