panel.js 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  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") // 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. info.panels++;
  25. options.replace.clear();
  26. } else if (options.position == "bottom") {
  27. wrapper.appendChild(node);
  28. } else if (options.position == "before-bottom") {
  29. wrapper.insertBefore(node, cmWrapper.nextSibling);
  30. } else if (options.position == "after-top") {
  31. wrapper.insertBefore(node, cmWrapper);
  32. } else {
  33. wrapper.insertBefore(node, wrapper.firstChild);
  34. }
  35. var height = (options && options.height) || node.offsetHeight;
  36. this._setSize(null, info.heightLeft -= height);
  37. if (!replace) {
  38. info.panels++;
  39. }
  40. if (options.stable && isAtTop(this, node))
  41. this.scrollTo(null, this.getScrollInfo().top + height)
  42. return new Panel(this, node, options, height);
  43. });
  44. function Panel(cm, node, options, height) {
  45. this.cm = cm;
  46. this.node = node;
  47. this.options = options;
  48. this.height = height;
  49. this.cleared = false;
  50. }
  51. Panel.prototype.clear = function() {
  52. if (this.cleared) return;
  53. this.cleared = true;
  54. var info = this.cm.state.panels;
  55. this.cm._setSize(null, info.heightLeft += this.height);
  56. if (this.options.stable && isAtTop(this.cm, this.node))
  57. this.cm.scrollTo(null, this.cm.getScrollInfo().top - this.height)
  58. info.wrapper.removeChild(this.node);
  59. if (--info.panels == 0) removePanels(this.cm);
  60. };
  61. Panel.prototype.changed = function(height) {
  62. var newHeight = height == null ? this.node.offsetHeight : height;
  63. var info = this.cm.state.panels;
  64. this.cm._setSize(null, info.heightLeft -= (newHeight - this.height));
  65. this.height = newHeight;
  66. };
  67. function initPanels(cm) {
  68. var wrap = cm.getWrapperElement();
  69. var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle;
  70. var height = parseInt(style.height);
  71. var info = cm.state.panels = {
  72. setHeight: wrap.style.height,
  73. heightLeft: height,
  74. panels: 0,
  75. wrapper: document.createElement("div")
  76. };
  77. wrap.parentNode.insertBefore(info.wrapper, wrap);
  78. var hasFocus = cm.hasFocus();
  79. info.wrapper.appendChild(wrap);
  80. if (hasFocus) cm.focus();
  81. cm._setSize = cm.setSize;
  82. if (height != null) cm.setSize = function(width, newHeight) {
  83. if (newHeight == null) return this._setSize(width, newHeight);
  84. info.setHeight = newHeight;
  85. if (typeof newHeight != "number") {
  86. var px = /^(\d+\.?\d*)px$/.exec(newHeight);
  87. if (px) {
  88. newHeight = Number(px[1]);
  89. } else {
  90. info.wrapper.style.height = newHeight;
  91. newHeight = info.wrapper.offsetHeight;
  92. info.wrapper.style.height = "";
  93. }
  94. }
  95. cm._setSize(width, info.heightLeft += (newHeight - height));
  96. height = newHeight;
  97. };
  98. }
  99. function removePanels(cm) {
  100. var info = cm.state.panels;
  101. cm.state.panels = null;
  102. var wrap = cm.getWrapperElement();
  103. info.wrapper.parentNode.replaceChild(wrap, info.wrapper);
  104. wrap.style.height = info.setHeight;
  105. cm.setSize = cm._setSize;
  106. cm.setSize();
  107. }
  108. function isAtTop(cm, dom) {
  109. for (var sibling = dom.nextSibling; sibling; sibling = sibling.nextSibling)
  110. if (sibling == cm.getWrapperElement()) return true
  111. return false
  112. }
  113. });