|
29 | 29 | mask: true,
|
30 | 30 | allowedContent: 'span(!' + cls + ')',
|
31 | 31 |
|
32 |
| - template: |
33 |
| - '<span class="' + cls + '" style="display:inline-block">' + |
34 |
| - '<iframe style="border:0;width:0;height:0" scrolling="no" frameborder="0" allowTransparency="true"></iframe>' + |
35 |
| - '</span>', |
| 32 | + template: '<span class="' + cls + '" style="display:inline-block" data-cke-survive=1></span>', |
36 | 33 |
|
37 | 34 | parts: {
|
38 |
| - iframe: 'iframe' |
| 35 | + span: 'span' |
39 | 36 | },
|
40 | 37 |
|
41 | 38 | defaults: {
|
42 | 39 | math: '\\(x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}\\)'
|
43 | 40 | },
|
44 | 41 |
|
45 | 42 | init: function() {
|
| 43 | + var iframe = this.parts.span.getChild( 0 ); |
| 44 | + |
| 45 | + // Check if span contains iframe and create it otherwise. |
| 46 | + if ( !iframe || iframe.type != CKEDITOR.NODE_ELEMENT || !iframe.is( 'iframe' ) ) { |
| 47 | + iframe = new CKEDITOR.dom.element( 'iframe' ); |
| 48 | + iframe.setAttributes( { |
| 49 | + style: 'border:0;width:0;height:0', |
| 50 | + scrolling: 'no', |
| 51 | + frameborder: 0, |
| 52 | + allowTransparency: true, |
| 53 | + src: CKEDITOR.plugins.mathjax.fixSrc |
| 54 | + } ); |
| 55 | + this.parts.span.append( iframe ); |
| 56 | + } |
| 57 | + |
46 | 58 | // Wait for ready because on some browsers iFrame will not
|
47 | 59 | // have document element until it is put into document.
|
48 | 60 | // This is a problem when you crate widget using dialog.
|
49 | 61 | this.once( 'ready', function() {
|
50 |
| - this.frameWrapper = new CKEDITOR.plugins.mathjax.frameWrapper( this.parts.iframe, editor ); |
| 62 | + // Src attribute must be recreated to fix custom domain error after undo |
| 63 | + // (see iFrame.removeAttribute( 'src' ) in frameWrapper.load). |
| 64 | + if ( CKEDITOR.env.ie ) |
| 65 | + iframe.setAttribute( 'src', CKEDITOR.plugins.mathjax.fixSrc ); |
| 66 | + |
| 67 | + this.frameWrapper = new CKEDITOR.plugins.mathjax.frameWrapper( iframe, editor ); |
51 | 68 | this.frameWrapper.setValue( this.data.math );
|
52 | 69 | } );
|
53 | 70 | },
|
|
68 | 85 |
|
69 | 86 | // Add style display:inline-block to have proper height of widget wrapper and mask.
|
70 | 87 | var attrs = el.attributes;
|
| 88 | + |
71 | 89 | if ( attrs.style )
|
72 | 90 | attrs.style += ';display:inline-block';
|
73 | 91 | else
|
74 | 92 | attrs.style = 'display:inline-block';
|
75 | 93 |
|
76 |
| - el.children[ 0 ].replaceWith( new CKEDITOR.htmlParser.element( 'iframe', { |
77 |
| - style: 'border:0;width:0;height:0', |
78 |
| - scrolling: 'no', |
79 |
| - frameborder: 0, |
80 |
| - allowTransparency: true |
81 |
| - } ) ); |
| 94 | + // Add attribute to prevent deleting empty span in data processing. |
| 95 | + attrs[ 'data-cke-survive' ] = 1; |
| 96 | + |
| 97 | + el.children[ 0 ].remove(); |
82 | 98 |
|
83 | 99 | return el;
|
84 | 100 | },
|
|
104 | 120 | evt.data.dataValue = evt.data.dataValue.replace( /<\/head>/,
|
105 | 121 | '<script src="' + ( editor.config.mathJaxLib ? CKEDITOR.getUrl( editor.config.mathJaxLib ) : cdn ) + '"><\/script><\/head>' );
|
106 | 122 | } );
|
| 123 | + |
| 124 | + editor.on( 'paste', function( evt ) { |
| 125 | + // Firefox does remove iFrame elements from pasted content so this event do the same on other browsers. |
| 126 | + // Also iFrame in paste content is reason of "Unspecified error" in IE9 (#10857). |
| 127 | + var regex = new RegExp( '<span[^>]*?' + cls + '.*?<\/span>', 'ig' ); |
| 128 | + evt.data.dataValue = evt.data.dataValue.replace( regex, function( match ) { |
| 129 | + return match.replace( /(<iframe.*?\/iframe>)/i, '' ); |
| 130 | + } ); |
| 131 | + } ); |
107 | 132 | }
|
108 | 133 | } );
|
109 | 134 |
|
110 | 135 | CKEDITOR.plugins.mathjax = {};
|
111 | 136 |
|
| 137 | + /** |
| 138 | + * Variable to fix problems with iFrame. This variable is global |
| 139 | + * because it is used in both widget and dialog. |
| 140 | + * |
| 141 | + * @private |
| 142 | + */ |
| 143 | + CKEDITOR.plugins.mathjax.fixSrc = |
| 144 | + // In Firefox src must exist and be different than about:blank to emit load event. |
| 145 | + CKEDITOR.env.gecko ? 'javascript:true' : |
| 146 | + // Support for custom document.domain in IE. |
| 147 | + CKEDITOR.env.ie ? 'javascript:' + |
| 148 | + 'void((function(){' + encodeURIComponent( |
| 149 | + 'document.open();' + |
| 150 | + '(' + CKEDITOR.tools.fixDomain + ')();' + |
| 151 | + 'document.close();' |
| 152 | + ) + '})())' : |
| 153 | + // In Chrome src must be undefined to emit load event. |
| 154 | + 'javascript:void(0)'; |
| 155 | + |
| 156 | + /** |
| 157 | + * Loading indicator image generated by preloaders.net. |
| 158 | + * |
| 159 | + * @private |
| 160 | + */ |
| 161 | + CKEDITOR.plugins.mathjax.loadingIcon = CKEDITOR.plugins.get( 'mathjax' ).path + 'images/loader.gif', |
| 162 | + |
112 | 163 | /**
|
113 | 164 | * FrameWrapper is responsible for communication between the MathJax library
|
114 | 165 | * and the `iframe` element that is used for rendering mathematical formulas
|
|
148 | 199 |
|
149 | 200 | // Function called when MathJax finish his job.
|
150 | 201 | updateDoneHandler = CKEDITOR.tools.addFunction( function() {
|
| 202 | + |
| 203 | + // Copy styles from iFrame to body inside iFrame. |
| 204 | + var stylesToCopy = [ 'color', 'font-family', 'font-style', 'font-weight', 'font-variant', 'font-size' ]; |
| 205 | + |
| 206 | + for ( var i = 0; i < stylesToCopy.length; i++ ) { |
| 207 | + var key = stylesToCopy[ i ], |
| 208 | + val = iFrame.getComputedStyle( key ); |
| 209 | + if ( val ) |
| 210 | + preview.setStyle( key, val ); |
| 211 | + } |
| 212 | + |
| 213 | + // Set preview content. |
151 | 214 | preview.setHtml( buffer.getHtml() );
|
152 | 215 |
|
| 216 | + editor.fire( 'lockSnapshot' ); |
| 217 | + |
| 218 | + iFrame.setStyles( { |
| 219 | + height: 0, |
| 220 | + width: 0 |
| 221 | + } ); |
| 222 | + |
| 223 | + // Set iFrame dimensions. |
153 | 224 | var height = Math.max( doc.$.body.offsetHeight, doc.$.documentElement.offsetHeight ),
|
154 | 225 | width = Math.max( preview.$.offsetWidth, doc.$.body.scrollWidth );
|
155 | 226 |
|
156 |
| - editor.fire( 'lockSnapshot' ); |
157 |
| - |
158 | 227 | iFrame.setStyles( {
|
159 | 228 | height: height + 'px',
|
160 |
| - width: width + 'px', |
161 |
| - display: 'inline' |
| 229 | + width: width + 'px' |
162 | 230 | } );
|
163 | 231 |
|
164 | 232 | editor.fire( 'unlockSnapshot' );
|
165 | 233 |
|
166 | 234 | // Private! For test usage only.
|
167 | 235 | iFrame.fire( 'mathJaxUpdateDone' );
|
168 | 236 |
|
| 237 | + // If value changed in the meantime update it again. |
169 | 238 | if ( value != newValue )
|
170 | 239 | update();
|
171 | 240 | else
|
172 | 241 | isRunning = false;
|
173 |
| - } ), |
174 |
| - stylesToCopy = [ 'color', 'font-family', 'font-style', 'font-weight', 'font-variant', 'font-size' ], |
175 |
| - style = ''; |
176 |
| - |
177 |
| - // Copy styles from iFrame to body inside iFrame. |
178 |
| - for ( var i = 0; i < stylesToCopy.length; i++ ) { |
179 |
| - var key = stylesToCopy[ i ], |
180 |
| - val = iFrame.getComputedStyle( key ); |
181 |
| - if ( val ) |
182 |
| - style += key + ': ' + val + ';'; |
| 242 | + } ); |
| 243 | + |
| 244 | + iFrame.on( 'load', load ); |
| 245 | + |
| 246 | + load(); |
| 247 | + |
| 248 | + function load() { |
| 249 | + doc = iFrame.getFrameDocument(); |
| 250 | + |
| 251 | + if ( doc.getById( 'preview' ) ) |
| 252 | + return; |
| 253 | + |
| 254 | + // Because of IE9 bug in a src attribute can not be javascript |
| 255 | + // when you undo (#10930). If you have iFrame with javascript in src |
| 256 | + // and call insertBefore on such element then IE9 will see crash. |
| 257 | + if ( CKEDITOR.env.ie ) |
| 258 | + iFrame.removeAttribute( 'src' ); |
| 259 | + |
| 260 | + doc.write( '<!DOCTYPE html>' + |
| 261 | + '<html>' + |
| 262 | + '<head>' + |
| 263 | + '<meta charset="utf-8">' + |
| 264 | + '<script type="text/x-mathjax-config">' + |
| 265 | + |
| 266 | + // MathJax configuration, disable messages. |
| 267 | + 'MathJax.Hub.Config( {' + |
| 268 | + 'showMathMenu: false,' + |
| 269 | + 'messageStyle: "none"' + |
| 270 | + '} );' + |
| 271 | + |
| 272 | + // Get main CKEDITOR form parent. |
| 273 | + 'function getCKE() {' + |
| 274 | + 'if ( typeof window.parent.CKEDITOR == \'object\' ) {' + |
| 275 | + 'return window.parent.CKEDITOR;' + |
| 276 | + '} else {' + |
| 277 | + 'return window.parent.parent.CKEDITOR;' + |
| 278 | + '}' + |
| 279 | + '}' + |
| 280 | + |
| 281 | + // Run MathJax.Hub with its actual parser and call callback function after that. |
| 282 | + // Because MathJax.Hub is asynchronous create MathJax.Hub.Queue to wait with callback. |
| 283 | + 'function update() {' + |
| 284 | + 'MathJax.Hub.Queue(' + |
| 285 | + '[ \'Typeset\', MathJax.Hub, this.buffer ],' + |
| 286 | + 'function() {' + |
| 287 | + 'getCKE().tools.callFunction( ' + updateDoneHandler + ' );' + |
| 288 | + '}' + |
| 289 | + ');' + |
| 290 | + '}' + |
| 291 | + |
| 292 | + // Run MathJax for the first time, when the script is loaded. |
| 293 | + // Callback function will be called then it's done. |
| 294 | + 'MathJax.Hub.Queue( function() {' + |
| 295 | + 'getCKE().tools.callFunction(' + loadedHandler + ');' + |
| 296 | + '} );' + |
| 297 | + '</script>' + |
| 298 | + |
| 299 | + // Load MathJax lib. |
| 300 | + '<script src="' + ( editor.config.mathJaxLib || cdn ) + '"></script>' + |
| 301 | + '</head>' + |
| 302 | + '<body style="padding:0;margin:0;background:transparent;overflow:hidden">' + |
| 303 | + '<span id="preview"></span>' + |
| 304 | + |
| 305 | + // Render everything here and after that copy it to the preview. |
| 306 | + '<span id="buffer" style="display:none"></span>' + |
| 307 | + '</body>' + |
| 308 | + '</html>' ); |
183 | 309 | }
|
184 | 310 |
|
185 | 311 | // Run MathJax parsing Tex.
|
|
188 | 314 |
|
189 | 315 | value = newValue;
|
190 | 316 |
|
| 317 | + editor.fire( 'lockSnapshot' ); |
| 318 | + |
191 | 319 | buffer.setHtml( value );
|
192 | 320 |
|
193 |
| - editor.fire( 'lockSnapshot' ); |
| 321 | + // Set loading indicator. |
| 322 | + preview.setHtml( '<img src=' + CKEDITOR.plugins.mathjax.loadingIcon + ' alt=' + editor.lang.mathjax.loading + '>' ); |
194 | 323 |
|
195 | 324 | iFrame.setStyles( {
|
196 |
| - height: 0, |
197 |
| - width: 0, |
| 325 | + height: '16px', |
| 326 | + width: '16px', |
| 327 | + display: 'inline', |
198 | 328 | 'vertical-align': 'middle'
|
199 | 329 | } );
|
200 | 330 |
|
|
204 | 334 | doc.getWindow().$.update( value );
|
205 | 335 | }
|
206 | 336 |
|
207 |
| - doc.write( '<!DOCTYPE html>' + |
208 |
| - '<html>' + |
209 |
| - '<head>' + |
210 |
| - '<meta charset="utf-8">' + |
211 |
| - '<style type="text/css">' + |
212 |
| - 'span#preview {' + |
213 |
| - style + |
214 |
| - '}' + |
215 |
| - '</style>' + |
216 |
| - '<script type="text/x-mathjax-config">' + |
217 |
| - |
218 |
| - // MathJax configuration, disable messages. |
219 |
| - 'MathJax.Hub.Config( {' + |
220 |
| - 'showMathMenu: false,' + |
221 |
| - 'messageStyle: "none"' + |
222 |
| - '} );' + |
223 |
| - |
224 |
| - // Get main CKEDITOR form parent. |
225 |
| - 'function getCKE() {' + |
226 |
| - 'if ( typeof window.parent.CKEDITOR == \'object\' ) {' + |
227 |
| - 'return window.parent.CKEDITOR;' + |
228 |
| - '} else {' + |
229 |
| - 'return window.parent.parent.CKEDITOR;' + |
230 |
| - '}' + |
231 |
| - '}' + |
232 |
| - |
233 |
| - // Run MathJax.Hub with its actual parser and call callback function after that. |
234 |
| - // Because MathJax.Hub is asynchronous create MathJax.Hub.Queue to wait with callback. |
235 |
| - 'function update() {' + |
236 |
| - 'MathJax.Hub.Queue(' + |
237 |
| - '[\'Typeset\',MathJax.Hub,this.buffer],' + |
238 |
| - 'function() {' + |
239 |
| - 'getCKE().tools.callFunction( ' + updateDoneHandler + ' );' + |
240 |
| - '}' + |
241 |
| - ');' + |
242 |
| - '}' + |
243 |
| - |
244 |
| - // Run MathJax for the first time, when the script is loaded. |
245 |
| - // Callback function will be called then it's done. |
246 |
| - 'MathJax.Hub.Queue( function() {' + |
247 |
| - 'getCKE().tools.callFunction(' + loadedHandler + ');' + |
248 |
| - '} );' + |
249 |
| - '</script>' + |
250 |
| - |
251 |
| - // Load MathJax lib. |
252 |
| - '<script src="' + ( editor.config.mathJaxLib || cdn ) + '"></script>' + |
253 |
| - '</head>' + |
254 |
| - '<body style="padding:0;margin:0;background:transparent;overflow:hidden">' + |
255 |
| - '<span id="preview"></span>' + |
256 |
| - |
257 |
| - // Render everything here and after that copy it to the preview. |
258 |
| - '<span id="buffer" style="display:none"></span>' + |
259 |
| - '</body>' + |
260 |
| - '</html>' ); |
261 |
| - |
262 | 337 | return {
|
263 | 338 | /**
|
264 | 339 | * Sets the TeX value to be displayed in the `iframe` element inside
|
|
0 commit comments