Annotation of modules/damieng/graphical_editor/loncapa_daxe/web/nodes/lm.dart, revision 1.1
1.1 ! damieng 1: /*
! 2: This file is part of LONCAPA-Daxe.
! 3:
! 4: LONCAPA-Daxe is free software: you can redistribute it and/or modify
! 5: it under the terms of the GNU General Public License as published by
! 6: the Free Software Foundation, either version 3 of the License, or
! 7: (at your option) any later version.
! 8:
! 9: LONCAPA-Daxe is distributed in the hope that it will be useful,
! 10: but WITHOUT ANY WARRANTY; without even the implied warranty of
! 11: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
! 12: GNU General Public License for more details.
! 13:
! 14: You should have received a copy of the GNU General Public License
! 15: along with Daxe. If not, see <http://www.gnu.org/licenses/>.
! 16: */
! 17:
! 18: part of loncapa_daxe;
! 19:
! 20: /**
! 21: * Displays lm and dlm elements (LON-CAPA inline and display math).
! 22: * Jaxe display type: 'lm'.
! 23: */
! 24: class Lm extends DaxeNode {
! 25:
! 26: static String constants = 'c, pi, e, hbar, amu';
! 27: static js.JsObject parser_symbols;
! 28: static js.JsObject parser_units;
! 29:
! 30: Lm.fromRef(x.Element elementRef) : super.fromRef(elementRef) {
! 31: }
! 32:
! 33: Lm.fromNode(x.Node node, DaxeNode parent) : super.fromNode(node, parent) {
! 34: }
! 35:
! 36: @override
! 37: h.Element html() {
! 38: h.Element el;
! 39: if (nodeName == 'dlm')
! 40: el = new h.DivElement();
! 41: else
! 42: el = new h.SpanElement();
! 43: el.id = "$id";
! 44: el.classes.add('dn');
! 45: el.classes.add('math');
! 46: if (!valid)
! 47: el.classes.add('invalid');
! 48: el.onClick.listen((h.MouseEvent event) => makeEditable());
! 49: updateEquationDisplay(el);
! 50: return(el);
! 51: }
! 52:
! 53: @override
! 54: void newNodeCreationUI(ActionFunction okfct) {
! 55: okfct();
! 56: makeEditable();
! 57: }
! 58:
! 59: @override
! 60: Position firstCursorPositionInside() {
! 61: return(null);
! 62: }
! 63:
! 64: @override
! 65: Position lastCursorPositionInside() {
! 66: return(null);
! 67: }
! 68:
! 69: @override
! 70: void afterInsert() {
! 71: h.Element el = h.document.getElementById(id);
! 72: updateEquationDisplay(el);
! 73: }
! 74:
! 75: void updateEquationDisplay(h.Element el) {
! 76: String equationText = '?';
! 77: if (firstChild != null && firstChild.nodeValue.trim() != '')
! 78: equationText = firstChild.nodeValue;
! 79: js.JsObject parser;
! 80: if (getAttribute('mode') == 'units') {
! 81: if (parser_units == null)
! 82: parser_units = new js.JsObject(js.context['LCMATH']['Parser'], [true, true, constants]);
! 83: parser = parser_units;
! 84: } else {
! 85: if (parser_symbols == null)
! 86: parser_symbols = new js.JsObject(js.context['LCMATH']['Parser'], [true, false, constants]);
! 87: parser = parser_symbols;
! 88: }
! 89: for (h.Node n in el.childNodes)
! 90: n.remove();
! 91: try {
! 92: js.JsObject root = parser.callMethod('parse', [equationText]);
! 93: if (root != null) {
! 94: h.Element math = h.document.createElement('math');
! 95: math.setAttribute('display', nodeName == 'dlm' ? 'block' : 'inline');
! 96: js.JsObject colors = new js.JsObject.jsify(['#000000']); // to use only black
! 97: math.append(root.callMethod('toMathML', [colors]));
! 98: el.append(math);
! 99: Timer.run(() {
! 100: js.JsArray params = new js.JsObject.jsify( ['Typeset', js.context['MathJax']['Hub'], id] );
! 101: js.context['MathJax']['Hub'].callMethod('Queue', [params]);
! 102: js.context['MathJax']['Hub'].callMethod('Queue', [() => page.cursor.refresh()]);
! 103: });
! 104: }
! 105: } catch (e) {
! 106: el.text = 'Error: ' + e.toString();
! 107: }
! 108: }
! 109:
! 110: void makeEditable() {
! 111: h.Element el = h.document.getElementById(id);
! 112: if (el == null)
! 113: return;
! 114: h.Element editEl;
! 115: if (nodeName == 'dlm')
! 116: editEl = new h.DivElement();
! 117: else
! 118: editEl = new h.SpanElement();
! 119: editEl.id = id;
! 120: h.TextInputElement input = new h.TextInputElement();
! 121: input.classes.add('math');
! 122: input.setAttribute('data-unit_mode', getAttribute('mode') == 'units' ? 'true' : 'false');
! 123: input.setAttribute('data-constants', constants);
! 124: input.setAttribute('data-implicit_operators', 'true');
! 125: input.setAttribute('spellcheck', 'false');
! 126: if (firstChild != null) {
! 127: input.value = firstChild.nodeValue;
! 128: if (input.value.length > 20)
! 129: input.size = input.value.length;
! 130: }
! 131: editEl.append(input);
! 132: h.SelectElement select = new h.SelectElement();
! 133: h.OptionElement symbolsOption = new h.OptionElement();
! 134: symbolsOption.value = 'symbols';
! 135: symbolsOption.appendText(LCDStrings.get('lm_symbols'));
! 136: if (getAttribute('mode') != 'units')
! 137: symbolsOption.setAttribute('selected', 'selected');
! 138: select.append(symbolsOption);
! 139: h.OptionElement unitsOption = new h.OptionElement();
! 140: unitsOption.value = 'units';
! 141: unitsOption.appendText(LCDStrings.get('lm_units'));
! 142: if (getAttribute('mode') == 'units')
! 143: unitsOption.setAttribute('selected', 'selected');
! 144: select.append(unitsOption);
! 145: select.onInput.listen((h.Event event) {
! 146: if (select.value == 'symbols' && getAttribute('mode') == 'units') {
! 147: setAttribute('mode', 'symbols');
! 148: input.setAttribute('data-unit_mode', 'false');
! 149: js.context['LCMATH'].callMethod('initEditors');
! 150: } else if (select.value == 'units' && getAttribute('mode') != 'units') {
! 151: setAttribute('mode', 'units');
! 152: input.setAttribute('data-unit_mode', 'true');
! 153: js.context['LCMATH'].callMethod('initEditors');
! 154: }
! 155: input.focus();
! 156: });
! 157: editEl.append(select);
! 158: el.replaceWith(editEl);
! 159: input.focus();
! 160: js.context['LCMATH'].callMethod('initEditors');
! 161: var switchDisplay = () {
! 162: String equationText = input.value;
! 163: if (equationText != '') {
! 164: if (firstChild != null)
! 165: firstChild.nodeValue = equationText;
! 166: else
! 167: appendChild(new DNText(equationText));
! 168: } else {
! 169: if (firstChild != null)
! 170: removeChild(firstChild);
! 171: }
! 172: editEl.replaceWith(html());
! 173: };
! 174: input.onBlur.listen((h.Event event) {
! 175: Timer.run(() { // timer so that activeElement is updated
! 176: if (h.document.activeElement == select)
! 177: return;
! 178: switchDisplay();
! 179: });
! 180: });
! 181: select.onBlur.listen((h.Event event) {
! 182: Timer.run(() {
! 183: if (h.document.activeElement == input)
! 184: return;
! 185: switchDisplay();
! 186: });
! 187: });
! 188: if (editEl is h.DivElement) {
! 189: editEl.onClick.listen((h.MouseEvent event) {
! 190: if (event.target != input && event.target != select) {
! 191: page.moveCursorTo(new Position(parent, parent.offsetOf(this)+1));
! 192: }
! 193: });
! 194: }
! 195: input.onKeyDown.listen((h.KeyboardEvent event) {
! 196: String equationText = input.value;
! 197: int inputSize = input.size;
! 198: if (equationText != null && equationText.length > inputSize)
! 199: input.size = equationText.length;
! 200: });
! 201: }
! 202: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>