/** * @license Copyright (c) 2003-2015, CKSource - Frederico Knabben. All rights reserved. * For licensing, see LICENSE.md or http://ckeditor.com/license */ /** * @fileOverview [Chemistry] LON-CAPA ckeditor plugin for the element. */ 'use strict'; CKEDITOR.plugins.add( 'chem', { lang: 'de,en,es,fr,ja,pt,pt-br,ru,zh,zh-cn', requires: 'widget', icons: 'chem', hidpi: true, init: function( editor ) { editor.widgets.add( 'chem', { dialog: 'chem', button: editor.lang.chem.button, template: '', data: function() { var span = this.element; if (this.data.reaction) CKEDITOR.plugins.chem.add_html(this.data.reaction, span); else span.setHtml('?'); }, upcast: function( el, data ) { if ( !( el.name == 'chem' ) ) return; if ( el.children.length > 1 || el.children[ 0 ].type != CKEDITOR.NODE_TEXT ) return; data.reaction = CKEDITOR.tools.htmlDecode( el.children[ 0 ].value ); var span = new CKEDITOR.htmlParser.element('span'); span.addClass('chem'); CKEDITOR.plugins.chem.add_html(data.reaction, span); // Add attribute to prevent deleting empty span in data processing. var attrs = span.attributes; attrs[ 'data-cke-survive' ] = 1; if (el.attributes.eval) attrs['data-eval'] = el.attributes.eval; el.replaceWith(span); return span; }, downcast: function( el ) { var chem = new CKEDITOR.htmlParser.element('chem'); if (el.attributes['data-eval']) chem.attributes.eval = el.attributes['data-eval']; chem.add(new CKEDITOR.htmlParser.text(CKEDITOR.tools.htmlEncode(this.data.reaction))); return chem; } } ); // Add dialog. CKEDITOR.dialog.add( 'chem', this.path + 'dialogs/chem.js' ); } } ); /** * @private * @singleton * @class CKEDITOR.plugins.chem */ CKEDITOR.plugins.chem = {}; /** * Adds HTML to the span for the given reaction, using UNICODE characters for arrows. * * @private * @param {string} reaction * @param {CKEDITOR.dom.element} span - element the HTML will be constructed inside */ CKEDITOR.plugins.chem.add_html = function( reaction, span ) { // this is doing the same thing as chemparse, except it uses UNICODE characters instead of LaTeX var tokens = reaction.split(/(\s\+|\->|<=>|<\-|\.)/); var formula = ''; for (var i=0; i' ) { formula += '→ '; continue; } if (token == '<-' ) { formula += '← '; continue; } if (token == '<=>') { formula += '⇌ '; continue; } if (token == '.') { formula = formula.replace(/ | /, ''); formula += '·'; continue; } var found = token.match(/^\s*([\d|\/]*(?:&frac\d\d)?)(.*)/); if (found != null && found.length > 1 && found[1] != '1') formula += found[1]; // stoichiometric coefficient var molecule; if (found != null && found.length > 2) molecule = found[2]; else molecule = ''; // subscripts // $molecule =~ s|(?<=[a-zA-Z\)\]\s])(\d+)|$1|g; // Javascript does not support look-behind like Perl molecule = molecule.replace(/([a-zA-Z\)\]\s])(\d+)/g, '$1$2'); // superscripts molecule = molecule.replace(/\^(\d*[+\-]*)/g, '$1'); // strip whitespace molecule = molecule.replace(/\s*/g, ''); // forced space molecule = molecule.replace(/_/g, ' '); molecule = molecule.replace(/-/g, '−'); formula += molecule + ' '; } // get rid of trailing space formula = formula.replace(/( | )$/, ''); // we need to add CSS here, because ckeditor changes CSS for sup and sub, and ckeditor css for plugins is not used inside dialogs // (whether we define it with CKEDITOR.editor.addContentsCss or CKEDITOR.addCss) formula = formula.replace(//g,''); formula = formula.replace(//g,''); span.setHtml(formula); }