|
1 /** |
|
2 * plugin.js |
|
3 * |
|
4 * Copyright, Moxiecode Systems AB |
|
5 * Released under LGPL License. |
|
6 * |
|
7 * License: http://www.tinymce.com/license |
|
8 * Contributing: http://www.tinymce.com/contributing |
|
9 */ |
|
10 |
|
11 /*global tinymce:true */ |
|
12 /*eslint no-nested-ternary:0 */ |
|
13 |
|
14 /** |
|
15 * Auto Resize |
|
16 * |
|
17 * This plugin automatically resizes the content area to fit its content height. |
|
18 * It will retain a minimum height, which is the height of the content area when |
|
19 * it's initialized. |
|
20 */ |
|
21 tinymce.PluginManager.add('autoresize', function(editor) { |
|
22 var settings = editor.settings, oldSize = 0; |
|
23 |
|
24 function isFullscreen() { |
|
25 return editor.plugins.fullscreen && editor.plugins.fullscreen.isFullscreen(); |
|
26 } |
|
27 |
|
28 if (editor.settings.inline) { |
|
29 return; |
|
30 } |
|
31 |
|
32 /** |
|
33 * This method gets executed each time the editor needs to resize. |
|
34 */ |
|
35 function resize(e) { |
|
36 var deltaSize, doc, body, docElm, DOM = tinymce.DOM, resizeHeight, myHeight, |
|
37 marginTop, marginBottom, paddingTop, paddingBottom, borderTop, borderBottom; |
|
38 |
|
39 doc = editor.getDoc(); |
|
40 if (!doc) { |
|
41 return; |
|
42 } |
|
43 |
|
44 body = doc.body; |
|
45 docElm = doc.documentElement; |
|
46 resizeHeight = settings.autoresize_min_height; |
|
47 |
|
48 if (!body || (e && e.type === "setcontent" && e.initial) || isFullscreen()) { |
|
49 if (body && docElm) { |
|
50 body.style.overflowY = "auto"; |
|
51 docElm.style.overflowY = "auto"; // Old IE |
|
52 } |
|
53 |
|
54 return; |
|
55 } |
|
56 |
|
57 // Calculate outer height of the body element using CSS styles |
|
58 marginTop = editor.dom.getStyle(body, 'margin-top', true); |
|
59 marginBottom = editor.dom.getStyle(body, 'margin-bottom', true); |
|
60 paddingTop = editor.dom.getStyle(body, 'padding-top', true); |
|
61 paddingBottom = editor.dom.getStyle(body, 'padding-bottom', true); |
|
62 borderTop = editor.dom.getStyle(body, 'border-top-width', true); |
|
63 borderBottom = editor.dom.getStyle(body, 'border-bottom-width', true); |
|
64 myHeight = body.offsetHeight + parseInt(marginTop, 10) + parseInt(marginBottom, 10) + |
|
65 parseInt(paddingTop, 10) + parseInt(paddingBottom, 10) + |
|
66 parseInt(borderTop, 10) + parseInt(borderBottom, 10); |
|
67 |
|
68 // Make sure we have a valid height |
|
69 if (isNaN(myHeight) || myHeight <= 0) { |
|
70 // Get height differently depending on the browser used |
|
71 myHeight = tinymce.Env.ie ? body.scrollHeight : (tinymce.Env.webkit && body.clientHeight === 0 ? 0 : body.offsetHeight); |
|
72 } |
|
73 |
|
74 // Don't make it smaller than the minimum height |
|
75 if (myHeight > settings.autoresize_min_height) { |
|
76 resizeHeight = myHeight; |
|
77 } |
|
78 |
|
79 // If a maximum height has been defined don't exceed this height |
|
80 if (settings.autoresize_max_height && myHeight > settings.autoresize_max_height) { |
|
81 resizeHeight = settings.autoresize_max_height; |
|
82 body.style.overflowY = "auto"; |
|
83 docElm.style.overflowY = "auto"; // Old IE |
|
84 } else { |
|
85 body.style.overflowY = "hidden"; |
|
86 docElm.style.overflowY = "hidden"; // Old IE |
|
87 body.scrollTop = 0; |
|
88 } |
|
89 |
|
90 // Resize content element |
|
91 if (resizeHeight !== oldSize) { |
|
92 deltaSize = resizeHeight - oldSize; |
|
93 DOM.setStyle(editor.iframeElement, 'height', resizeHeight + 'px'); |
|
94 oldSize = resizeHeight; |
|
95 |
|
96 // WebKit doesn't decrease the size of the body element until the iframe gets resized |
|
97 // So we need to continue to resize the iframe down until the size gets fixed |
|
98 if (tinymce.isWebKit && deltaSize < 0) { |
|
99 resize(e); |
|
100 } |
|
101 } |
|
102 } |
|
103 |
|
104 /** |
|
105 * Calls the resize x times in 100ms intervals. We can't wait for load events since |
|
106 * the CSS files might load async. |
|
107 */ |
|
108 function wait(times, interval, callback) { |
|
109 setTimeout(function() { |
|
110 resize({}); |
|
111 |
|
112 if (times--) { |
|
113 wait(times, interval, callback); |
|
114 } else if (callback) { |
|
115 callback(); |
|
116 } |
|
117 }, interval); |
|
118 } |
|
119 |
|
120 // Define minimum height |
|
121 settings.autoresize_min_height = parseInt(editor.getParam('autoresize_min_height', editor.getElement().offsetHeight), 10); |
|
122 |
|
123 // Define maximum height |
|
124 settings.autoresize_max_height = parseInt(editor.getParam('autoresize_max_height', 0), 10); |
|
125 |
|
126 // Add padding at the bottom for better UX |
|
127 editor.on("init", function() { |
|
128 var overflowPadding, bottomMargin; |
|
129 |
|
130 overflowPadding = editor.getParam('autoresize_overflow_padding', 1); |
|
131 bottomMargin = editor.getParam('autoresize_bottom_margin', 50); |
|
132 |
|
133 if (overflowPadding !== false) { |
|
134 editor.dom.setStyles(editor.getBody(), { |
|
135 paddingLeft: overflowPadding, |
|
136 paddingRight: overflowPadding |
|
137 }); |
|
138 } |
|
139 |
|
140 if (bottomMargin !== false) { |
|
141 editor.dom.setStyles(editor.getBody(), { |
|
142 paddingBottom: bottomMargin |
|
143 }); |
|
144 } |
|
145 }); |
|
146 |
|
147 // Add appropriate listeners for resizing content area |
|
148 editor.on("nodechange setcontent keyup FullscreenStateChanged", resize); |
|
149 |
|
150 if (editor.getParam('autoresize_on_init', true)) { |
|
151 editor.on('init', function() { |
|
152 // Hit it 20 times in 100 ms intervals |
|
153 wait(20, 100, function() { |
|
154 // Hit it 5 times in 1 sec intervals |
|
155 wait(5, 1000); |
|
156 }); |
|
157 }); |
|
158 } |
|
159 |
|
160 // Register the command so that it can be invoked by using tinyMCE.activeEditor.execCommand('mceExample'); |
|
161 editor.addCommand('mceAutoResize', resize); |
|
162 }); |