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