diff --git a/editor/extensions/ext-mathjax.js b/editor/extensions/ext-mathjax.js new file mode 100644 index 00000000..d41446b0 --- /dev/null +++ b/editor/extensions/ext-mathjax.js @@ -0,0 +1,271 @@ +/* + * ext-mathjax.js + * + * Licensed under the Apache License + * + * Copyright(c) 2013 Jo Segaert + * + */ + +svgEditor.addExtension("mathjax", function() { + // Configuration of the MathJax extention. + + // This will be added to the head tag before MathJax is loaded. + var mathjaxConfiguration = '', + mathjaxSrc = 'http://cdn.mathjax.org/mathjax/latest/MathJax.js', + mathjaxSrcSecure = 'https://c328740.ssl.cf1.rackcdn.com/mathjax/latest/MathJax.js?config=TeX-AMS-MML_SVG.js', + math, + locationX, + locationY, + mathjaxLoaded = false, + uiStrings = svgEditor.uiStrings; + + // TODO: Implement language support. + $.extend(uiStrings, { + mathjax: { + embed_svg: 'Save as mathematics', + embed_mathml: 'Save as figure', + svg_save_warning: 'The math will be transformed into a figure is manipulatable like everything else. You will not be able to manipulate the TeX-code anymore. ', + mathml_save_warning: 'Advised. The math will be saved as a figure.', + title: 'Mathematics code editor' + } + }); + + + function saveMath() { + var code = $('#mathjax_code_textarea').val(); + // displaystyle to force MathJax NOT to use the inline style. Because it is + // less fancy! + MathJax.Hub.queue.Push(['Text', math, '\\displaystyle{' + code + '}']); + + /* + * The MathJax library doesn't want to bloat your webpage so it creates + * every symbol (glymph) you need only once. These are saved in a on + * the top of your html document, just under the body tag. Each glymph has + * its unique id and is saved as a in the tag of the + * + * Then when the symbols are needed in the rest of your html document they + * are refferd to by a tag. + * Because of bug 1076 we can't just grab the defs tag on the top and add it + * to your formula's and copy the lot. So we have to replace each + * tag by it's . + */ + MathJax.Hub.queue.Push( + function() { + var mathjaxMath = $('.MathJax_SVG'); + var svg = $(mathjaxMath.html()); + svg.find('use').each(function() { + var x, y, transform; + + // TODO: find a less pragmatic and more elegant solution to this. + if ($(this).attr('href')) { + var id = $(this).attr('href').slice(1); // Works in Chrome. + } else { + var id = $(this).attr('xlink:href').slice(1); // Works in Firefox. + } + + var glymph = $('#' + id).clone().removeAttr('id'); + x = $(this).attr('x'); + y = $(this).attr('y'); + transform = $(this).attr('transform'); + if (transform && ( x || y )) { + glymph.attr('transform', transform + ' translate(' + x + ',' + y + ')'); + } + else if (transform) { + glymph.attr('transform', transform); + } + else if (x || y) { + glymph.attr('transform', 'translate(' + x + ',' + y + ')'); + } + $(this).replaceWith(glymph); + }); + // Remove the style tag because it interferes with SVG-Edit. + svg.removeAttr('style'); + svg.attr('xmlns', 'http://www.w3.org/2000/svg'); + svgCanvas.importSvgString($('
').append(svg.clone()).html(), true); + svgCanvas.ungroupSelectedElement(); + // TODO: To undo the adding of the Formula you now have to undo twice. + // This should only be once! + svgCanvas.moveSelectedElements(locationX, locationY, true); + } + ); + } + + return { + name: "MatJax", + svgicons: "extensions/mathjax-icons.xml", + buttons: [{ + id: "tool_mathjax", + type: "mode", + title: "Add Mathematics", + events: { + 'click': function() { + // Only load Mathjax when needed, we don't want to strain Svg-Edit any more. + // From this point on it is very probable that it will be needed, so load it. + if (mathjaxLoaded === false) { + + $('
\ + \ + \ +
\ +
\ +
\ + \ + \ +
\ +
\ + Mathematics Editor\ + \ + \ +
\ +
\ +
' + ).insertAfter('#svg_prefs').hide(); + + // Make the MathEditor draggable. + $('#mathjax_container').draggable({cancel: 'button,fieldset', containment: 'window'}); + + // Add functionality and picture to cancel button. + $('#tool_mathjax_cancel').prepend($.getSvgIcon('cancel', true)) + .on("click touched", function() { + $('#mathjax').hide(); + }); + + // Add functionality and picture to the save button. + $('#tool_mathjax_save').prepend($.getSvgIcon('ok', true)) + .on("click touched", function() { + saveMath(); + $('#mathjax').hide(); + }); + + // MathJax preprocessing has to ignore most of the page. + $('body').addClass('tex2jax_ignore'); + + // Now get (and run) the MathJax Library. + $.getScript(mathjaxSrcSecure) + .done(function(script, textStatus) { + + // When MathJax is loaded get the div where the math will be rendered. + MathJax.Hub.queue.Push(function() { + math = MathJax.Hub.getAllJax('#mathjax_creator')[0]; + console.log(math); + mathjaxLoaded = true; + console.log('MathJax Loaded'); + }); + + }) + // If it fails. + .fail(function() { + console.log("Failed loadeing MathJax."); + $.alert("Failed loading MathJax. You will not be able to change the mathematics."); + }); + } + // Set the mode. + svgCanvas.setMode("mathjax"); + } + } + }], + + mouseDown: function() { + if (svgCanvas.getMode() === "mathjax") { + return {started: true}; + } + }, + mouseUp: function(opts) { + if (svgCanvas.getMode() === "mathjax") { + // Get the coordinates from your mouse. + var zoom = svgCanvas.getZoom(); + // Get the actual coordinate by dividing by the zoom value + locationX = opts.mouse_x / zoom; + locationY = opts.mouse_y / zoom; + + $('#mathjax').show(); + return {started: false}; // Otherwise the last selected object dissapears. + } + }, + callback: function() { + $('