Mercurial
comparison .cms/lib/codemirror/addon/display/panel.js @ 0:78edf6b517a0 draft
24.10
author | Coffee CMS <info@coffee-cms.ru> |
---|---|
date | Fri, 11 Oct 2024 22:40:23 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
-1:000000000000 | 0:78edf6b517a0 |
---|---|
1 // CodeMirror, copyright (c) by Marijn Haverbeke and others | |
2 // Distributed under an MIT license: https://codemirror.net/5/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 var replace = options.replace instanceof Panel && !options.replace.cleared; | |
21 | |
22 if (options.after instanceof Panel && !options.after.cleared) { | |
23 wrapper.insertBefore(node, options.before.node.nextSibling); | |
24 } else if (options.before instanceof Panel && !options.before.cleared) { | |
25 wrapper.insertBefore(node, options.before.node); | |
26 } else if (replace) { | |
27 wrapper.insertBefore(node, options.replace.node); | |
28 options.replace.clear(true); | |
29 } else if (options.position == "bottom") { | |
30 wrapper.appendChild(node); | |
31 } else if (options.position == "before-bottom") { | |
32 wrapper.insertBefore(node, cmWrapper.nextSibling); | |
33 } else if (options.position == "after-top") { | |
34 wrapper.insertBefore(node, cmWrapper); | |
35 } else { | |
36 wrapper.insertBefore(node, wrapper.firstChild); | |
37 } | |
38 | |
39 var height = (options && options.height) || node.offsetHeight; | |
40 | |
41 var panel = new Panel(this, node, options, height); | |
42 info.panels.push(panel); | |
43 | |
44 this.setSize(); | |
45 if (options.stable && isAtTop(this, node)) | |
46 this.scrollTo(null, this.getScrollInfo().top + height); | |
47 | |
48 return panel; | |
49 }); | |
50 | |
51 function Panel(cm, node, options, height) { | |
52 this.cm = cm; | |
53 this.node = node; | |
54 this.options = options; | |
55 this.height = height; | |
56 this.cleared = false; | |
57 } | |
58 | |
59 /* when skipRemove is true, clear() was called from addPanel(). | |
60 * Thus removePanels() should not be called (issue 5518) */ | |
61 Panel.prototype.clear = function (skipRemove) { | |
62 if (this.cleared) return; | |
63 this.cleared = true; | |
64 var info = this.cm.state.panels; | |
65 info.panels.splice(info.panels.indexOf(this), 1); | |
66 this.cm.setSize(); | |
67 if (this.options.stable && isAtTop(this.cm, this.node)) | |
68 this.cm.scrollTo(null, this.cm.getScrollInfo().top - this.height) | |
69 info.wrapper.removeChild(this.node); | |
70 if (info.panels.length == 0 && !skipRemove) removePanels(this.cm); | |
71 }; | |
72 | |
73 Panel.prototype.changed = function () { | |
74 this.height = this.node.getBoundingClientRect().height; | |
75 this.cm.setSize(); | |
76 }; | |
77 | |
78 function initPanels(cm) { | |
79 var wrap = cm.getWrapperElement() | |
80 var style = window.getComputedStyle ? window.getComputedStyle(wrap) : wrap.currentStyle; | |
81 var height = parseInt(style.height); | |
82 var info = cm.state.panels = { | |
83 setHeight: wrap.style.height, | |
84 panels: [], | |
85 wrapper: document.createElement("div") | |
86 }; | |
87 var hasFocus = cm.hasFocus(), scrollPos = cm.getScrollInfo() | |
88 wrap.parentNode.insertBefore(info.wrapper, wrap); | |
89 info.wrapper.appendChild(wrap); | |
90 cm.scrollTo(scrollPos.left, scrollPos.top) | |
91 if (hasFocus) cm.focus(); | |
92 | |
93 cm._setSize = cm.setSize; | |
94 if (height != null) cm.setSize = function (width, newHeight) { | |
95 if (!newHeight) newHeight = info.wrapper.offsetHeight; | |
96 info.setHeight = newHeight; | |
97 if (typeof newHeight != "number") { | |
98 var px = /^(\d+\.?\d*)px$/.exec(newHeight); | |
99 if (px) { | |
100 newHeight = Number(px[1]); | |
101 } else { | |
102 info.wrapper.style.height = newHeight; | |
103 newHeight = info.wrapper.offsetHeight; | |
104 } | |
105 } | |
106 var editorheight = newHeight - info.panels | |
107 .map(function (p) { return p.node.getBoundingClientRect().height; }) | |
108 .reduce(function (a, b) { return a + b; }, 0); | |
109 cm._setSize(width, editorheight); | |
110 height = newHeight; | |
111 }; | |
112 } | |
113 | |
114 function removePanels(cm) { | |
115 var info = cm.state.panels; | |
116 cm.state.panels = null; | |
117 | |
118 var wrap = cm.getWrapperElement() | |
119 var hasFocus = cm.hasFocus(), scrollPos = cm.getScrollInfo() | |
120 info.wrapper.parentNode.replaceChild(wrap, info.wrapper); | |
121 cm.scrollTo(scrollPos.left, scrollPos.top) | |
122 if (hasFocus) cm.focus(); | |
123 wrap.style.height = info.setHeight; | |
124 cm.setSize = cm._setSize; | |
125 cm.setSize(); | |
126 } | |
127 | |
128 function isAtTop(cm, dom) { | |
129 for (var sibling = dom.nextSibling; sibling; sibling = sibling.nextSibling) | |
130 if (sibling == cm.getWrapperElement()) return true | |
131 return false | |
132 } | |
133 }); |