Skip to content

Commit

Permalink
Merge branch 't/10937' into major
Browse files Browse the repository at this point in the history
  • Loading branch information
Piotr Jasiun committed Oct 18, 2013
2 parents 2849cd0 + 2052f8b commit 95bd2fe
Show file tree
Hide file tree
Showing 7 changed files with 175 additions and 86 deletions.
8 changes: 8 additions & 0 deletions CHANGES.md
Expand Up @@ -5,6 +5,14 @@ CKEditor 4 Changelog

New Features:

* [#10937](http://dev.ckeditor.com/ticket/10937): MathJax widget improvements:
* loading indicator,
* IE8 support,
* apply paragraph changes (like font color change) to iframe,
* FF and IE9 clipboard fixes,
* fix same origin policy issue,
* fix undo bug,
* fix minor bugs,
* [#10028](http://dev.ckeditor.com/ticket/10028): New [`config.dialog_noConfirmCancel`](http://docs.ckeditor.com/#!/api/CKEDITOR.config-cfg-dialog_noConfirmCancel) configuration option that eliminates the need to confirm closing of a dialog window when the user changed any of its fields.

Fixed Issues:
Expand Down
4 changes: 4 additions & 0 deletions core/htmlparser/fragment.js
Expand Up @@ -45,6 +45,10 @@ CKEDITOR.htmlParser.fragment = function() {
var rootDtd = CKEDITOR.tools.extend( {}, { html:1 }, CKEDITOR.dtd.html, CKEDITOR.dtd.body, CKEDITOR.dtd.head, { style:1,script:1 } );

function isRemoveEmpty( node ) {
// Keep marked element event if it is empty.
if ( node.attributes[ 'data-cke-survive' ] )
return false;

// Empty link is to be removed when empty but not anchor. (#7894)
return node.name == 'a' && node.attributes.href || CKEDITOR.dtd.$removeEmpty[ node.name ];
}
Expand Down
1 change: 1 addition & 0 deletions plugins/mathjax/dev/mathjax.html
Expand Up @@ -15,6 +15,7 @@
<meta name="ckeditor-sample-isnew" content="1">
<script>
CKEDITOR.disableAutoInline = true;
document.domain = 'ckeditor.dev';
</script>
</head>
<body>
Expand Down
2 changes: 1 addition & 1 deletion plugins/mathjax/dialogs/mathjax.js
Expand Up @@ -60,7 +60,7 @@ CKEDITOR.dialog.add( 'mathjax', function( editor ) {
type: 'html',
html:
'<div style="width:100%;text-align:center;">' +
'<iframe style="border:0;width:0;height:0;font-size:20px" scrolling="no" frameborder="0" allowTransparency="true"></iframe>' +
'<iframe style="border:0;width:0;height:0;font-size:20px" scrolling="no" frameborder="0" allowTransparency="true" src="' + CKEDITOR.plugins.mathjax.fixSrc + '"></iframe>' +
'</div>',

onLoad: function( widget ) {
Expand Down
Binary file added plugins/mathjax/images/loader.gif
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
3 changes: 2 additions & 1 deletion plugins/mathjax/lang/en.js
Expand Up @@ -7,5 +7,6 @@ CKEDITOR.plugins.setLang( 'mathjax', 'en', {
button: 'Math',
dialogInput: 'Write you TeX here',
docUrl: 'http://en.wikibooks.org/wiki/LaTeX/Mathematics',
docLabel: 'TeX documentation'
docLabel: 'TeX documentation',
loading: 'loading...'
} );
243 changes: 159 additions & 84 deletions plugins/mathjax/plugin.js
Expand Up @@ -29,25 +29,42 @@
mask: true,
allowedContent: 'span(!' + cls + ')',

template:
'<span class="' + cls + '" style="display:inline-block">' +
'<iframe style="border:0;width:0;height:0" scrolling="no" frameborder="0" allowTransparency="true"></iframe>' +
'</span>',
template: '<span class="' + cls + '" style="display:inline-block" data-cke-survive=1></span>',

parts: {
iframe: 'iframe'
span: 'span'
},

defaults: {
math: '\\(x = {-b \\pm \\sqrt{b^2-4ac} \\over 2a}\\)'
},

init: function() {
var iframe = this.parts.span.getChild( 0 );

// Check if span contains iframe and create it otherwise.
if ( !iframe || iframe.type != CKEDITOR.NODE_ELEMENT || !iframe.is( 'iframe' ) ) {
iframe = new CKEDITOR.dom.element( 'iframe' );
iframe.setAttributes( {
style: 'border:0;width:0;height:0',
scrolling: 'no',
frameborder: 0,
allowTransparency: true,
src: CKEDITOR.plugins.mathjax.fixSrc
} );
this.parts.span.append( iframe );
}

// Wait for ready because on some browsers iFrame will not
// have document element until it is put into document.
// This is a problem when you crate widget using dialog.
this.once( 'ready', function() {
this.frameWrapper = new CKEDITOR.plugins.mathjax.frameWrapper( this.parts.iframe, editor );
// Src attribute must be recreated to fix custom domain error after undo
// (see iFrame.removeAttribute( 'src' ) in frameWrapper.load).
if ( CKEDITOR.env.ie )
iframe.setAttribute( 'src', CKEDITOR.plugins.mathjax.fixSrc );

this.frameWrapper = new CKEDITOR.plugins.mathjax.frameWrapper( iframe, editor );
this.frameWrapper.setValue( this.data.math );
} );
},
Expand All @@ -68,17 +85,16 @@

// Add style display:inline-block to have proper height of widget wrapper and mask.
var attrs = el.attributes;

if ( attrs.style )
attrs.style += ';display:inline-block';
else
attrs.style = 'display:inline-block';

el.children[ 0 ].replaceWith( new CKEDITOR.htmlParser.element( 'iframe', {
style: 'border:0;width:0;height:0',
scrolling: 'no',
frameborder: 0,
allowTransparency: true
} ) );
// Add attribute to prevent deleting empty span in data processing.
attrs[ 'data-cke-survive' ] = 1;

el.children[ 0 ].remove();

return el;
},
Expand All @@ -104,11 +120,46 @@
evt.data.dataValue = evt.data.dataValue.replace( /<\/head>/,
'<script src="' + ( editor.config.mathJaxLib ? CKEDITOR.getUrl( editor.config.mathJaxLib ) : cdn ) + '"><\/script><\/head>' );
} );

editor.on( 'paste', function( evt ) {
// Firefox does remove iFrame elements from pasted content so this event do the same on other browsers.
// Also iFrame in paste content is reason of "Unspecified error" in IE9 (#10857).
var regex = new RegExp( '<span[^>]*?' + cls + '.*?<\/span>', 'ig' );
evt.data.dataValue = evt.data.dataValue.replace( regex, function( match ) {
return match.replace( /(<iframe.*?\/iframe>)/i, '' );
} );
} );
}
} );

CKEDITOR.plugins.mathjax = {};

/**
* Variable to fix problems with iFrame. This variable is global
* because it is used in both widget and dialog.
*
* @private
*/
CKEDITOR.plugins.mathjax.fixSrc =
// In Firefox src must exist and be different than about:blank to emit load event.
CKEDITOR.env.gecko ? 'javascript:true' :
// Support for custom document.domain in IE.
CKEDITOR.env.ie ? 'javascript:' +
'void((function(){' + encodeURIComponent(
'document.open();' +
'(' + CKEDITOR.tools.fixDomain + ')();' +
'document.close();'
) + '})())' :
// In Chrome src must be undefined to emit load event.
'javascript:void(0)';

/**
* Loading indicator image generated by preloaders.net.
*
* @private
*/
CKEDITOR.plugins.mathjax.loadingIcon = CKEDITOR.plugins.get( 'mathjax' ).path + 'images/loader.gif',

/**
* FrameWrapper is responsible for communication between the MathJax library
* and the `iframe` element that is used for rendering mathematical formulas
Expand Down Expand Up @@ -148,38 +199,113 @@

// Function called when MathJax finish his job.
updateDoneHandler = CKEDITOR.tools.addFunction( function() {

// Copy styles from iFrame to body inside iFrame.
var stylesToCopy = [ 'color', 'font-family', 'font-style', 'font-weight', 'font-variant', 'font-size' ];

for ( var i = 0; i < stylesToCopy.length; i++ ) {
var key = stylesToCopy[ i ],
val = iFrame.getComputedStyle( key );
if ( val )
preview.setStyle( key, val );
}

// Set preview content.
preview.setHtml( buffer.getHtml() );

editor.fire( 'lockSnapshot' );

iFrame.setStyles( {
height: 0,
width: 0
} );

// Set iFrame dimensions.
var height = Math.max( doc.$.body.offsetHeight, doc.$.documentElement.offsetHeight ),
width = Math.max( preview.$.offsetWidth, doc.$.body.scrollWidth );

editor.fire( 'lockSnapshot' );

iFrame.setStyles( {
height: height + 'px',
width: width + 'px',
display: 'inline'
width: width + 'px'
} );

editor.fire( 'unlockSnapshot' );

// Private! For test usage only.
iFrame.fire( 'mathJaxUpdateDone' );

// If value changed in the meantime update it again.
if ( value != newValue )
update();
else
isRunning = false;
} ),
stylesToCopy = [ 'color', 'font-family', 'font-style', 'font-weight', 'font-variant', 'font-size' ],
style = '';

// Copy styles from iFrame to body inside iFrame.
for ( var i = 0; i < stylesToCopy.length; i++ ) {
var key = stylesToCopy[ i ],
val = iFrame.getComputedStyle( key );
if ( val )
style += key + ': ' + val + ';';
} );

iFrame.on( 'load', load );

load();

function load() {
doc = iFrame.getFrameDocument();

if ( doc.getById( 'preview' ) )
return;

// Because of IE9 bug in a src attribute can not be javascript
// when you undo (#10930). If you have iFrame with javascript in src
// and call insertBefore on such element then IE9 will see crash.
if ( CKEDITOR.env.ie )
iFrame.removeAttribute( 'src' );

doc.write( '<!DOCTYPE html>' +
'<html>' +
'<head>' +
'<meta charset="utf-8">' +
'<script type="text/x-mathjax-config">' +

// MathJax configuration, disable messages.
'MathJax.Hub.Config( {' +
'showMathMenu: false,' +
'messageStyle: "none"' +
'} );' +

// Get main CKEDITOR form parent.
'function getCKE() {' +
'if ( typeof window.parent.CKEDITOR == \'object\' ) {' +
'return window.parent.CKEDITOR;' +
'} else {' +
'return window.parent.parent.CKEDITOR;' +
'}' +
'}' +

// Run MathJax.Hub with its actual parser and call callback function after that.
// Because MathJax.Hub is asynchronous create MathJax.Hub.Queue to wait with callback.
'function update() {' +
'MathJax.Hub.Queue(' +
'[ \'Typeset\', MathJax.Hub, this.buffer ],' +
'function() {' +
'getCKE().tools.callFunction( ' + updateDoneHandler + ' );' +
'}' +
');' +
'}' +

// Run MathJax for the first time, when the script is loaded.
// Callback function will be called then it's done.
'MathJax.Hub.Queue( function() {' +
'getCKE().tools.callFunction(' + loadedHandler + ');' +
'} );' +
'</script>' +

// Load MathJax lib.
'<script src="' + ( editor.config.mathJaxLib || cdn ) + '"></script>' +
'</head>' +
'<body style="padding:0;margin:0;background:transparent;overflow:hidden">' +
'<span id="preview"></span>' +

// Render everything here and after that copy it to the preview.
'<span id="buffer" style="display:none"></span>' +
'</body>' +
'</html>' );
}

// Run MathJax parsing Tex.
Expand All @@ -188,13 +314,17 @@

value = newValue;

editor.fire( 'lockSnapshot' );

buffer.setHtml( value );

editor.fire( 'lockSnapshot' );
// Set loading indicator.
preview.setHtml( '<img src=' + CKEDITOR.plugins.mathjax.loadingIcon + ' alt=' + editor.lang.mathjax.loading + '>' );

iFrame.setStyles( {
height: 0,
width: 0,
height: '16px',
width: '16px',
display: 'inline',
'vertical-align': 'middle'
} );

Expand All @@ -204,61 +334,6 @@
doc.getWindow().$.update( value );
}

doc.write( '<!DOCTYPE html>' +
'<html>' +
'<head>' +
'<meta charset="utf-8">' +
'<style type="text/css">' +
'span#preview {' +
style +
'}' +
'</style>' +
'<script type="text/x-mathjax-config">' +

// MathJax configuration, disable messages.
'MathJax.Hub.Config( {' +
'showMathMenu: false,' +
'messageStyle: "none"' +
'} );' +

// Get main CKEDITOR form parent.
'function getCKE() {' +
'if ( typeof window.parent.CKEDITOR == \'object\' ) {' +
'return window.parent.CKEDITOR;' +
'} else {' +
'return window.parent.parent.CKEDITOR;' +
'}' +
'}' +

// Run MathJax.Hub with its actual parser and call callback function after that.
// Because MathJax.Hub is asynchronous create MathJax.Hub.Queue to wait with callback.
'function update() {' +
'MathJax.Hub.Queue(' +
'[\'Typeset\',MathJax.Hub,this.buffer],' +
'function() {' +
'getCKE().tools.callFunction( ' + updateDoneHandler + ' );' +
'}' +
');' +
'}' +

// Run MathJax for the first time, when the script is loaded.
// Callback function will be called then it's done.
'MathJax.Hub.Queue( function() {' +
'getCKE().tools.callFunction(' + loadedHandler + ');' +
'} );' +
'</script>' +

// Load MathJax lib.
'<script src="' + ( editor.config.mathJaxLib || cdn ) + '"></script>' +
'</head>' +
'<body style="padding:0;margin:0;background:transparent;overflow:hidden">' +
'<span id="preview"></span>' +

// Render everything here and after that copy it to the preview.
'<span id="buffer" style="display:none"></span>' +
'</body>' +
'</html>' );

return {
/**
* Sets the TeX value to be displayed in the `iframe` element inside
Expand Down

0 comments on commit 95bd2fe

Please sign in to comment.