Annotation of loncom/html/adm/LC_math_editor/src/ui.js, revision 1.1
1.1 ! damieng 1: /*
! 2:
! 3: Copyright (C) 2014 Michigan State University Board of Trustees
! 4:
! 5: The JavaScript code in this page is free software: you can
! 6: redistribute it and/or modify it under the terms of the GNU
! 7: General Public License (GNU GPL) as published by the Free Software
! 8: Foundation, either version 3 of the License, or (at your option)
! 9: any later version. The code is distributed WITHOUT ANY WARRANTY;
! 10: without even the implied warranty of MERCHANTABILITY or FITNESS
! 11: FOR A PARTICULAR PURPOSE. See the GNU GPL for more details.
! 12:
! 13: As additional permission under GNU GPL version 3 section 7, you
! 14: may distribute non-source (e.g., minimized or compacted) forms of
! 15: that code without the copy of the GNU GPL normally required by
! 16: section 4, provided you include this license notice and a URL
! 17: through which recipients can access the Corresponding Source.
! 18:
! 19: */
! 20:
! 21: "use strict";
! 22:
! 23: var handleChange = function(math_object) {
! 24: // math_object has 3 fields: ta, output_node, oldtxt
! 25: // we need to pass this object instead of the values because oldtxt will change
! 26: var ta, output_node, txt, parser, output, root, test1, test2;
! 27: ta = math_object.ta;
! 28: output_node = math_object.output_node;
! 29: txt = ta.value;
! 30:
! 31: // automatically add brackets to something like "1;2;3", for LON-CAPA:
! 32: // NOTE: this is ugly and sometimes adds brackets to error messages
! 33: test1 = '';
! 34: test2 = txt;
! 35: while (test2 != test1) {
! 36: test1 = test2;
! 37: test2 = test1.replace(/\[[^\[\]]*\]/g, '');
! 38: }
! 39: if (test2.split("[").length == test2.split("]").length) {
! 40: test1 = '';
! 41: while (test2 != test1) {
! 42: test1 = test2;
! 43: test2 = test1.replace(/\([^\(\)]*\)/g, '');
! 44: }
! 45: if (test2.split("(").length == test2.split(")").length) {
! 46: if (test2.indexOf(Definitions.ARG_SEPARATOR) != -1) {
! 47: txt = '['+txt+']';
! 48: }
! 49: }
! 50: }
! 51:
! 52: if (txt != math_object.oldtxt) {
! 53: math_object.oldtxt = txt;
! 54: while (output_node.firstChild != null)
! 55: output_node.removeChild(output_node.firstChild);
! 56: output_node.removeAttribute("title");
! 57: if (txt != "") {
! 58: parser = math_object.parser;
! 59: try {
! 60: root = parser.parse(txt);
! 61: if (root != null) {
! 62: var math = document.createElement("math");
! 63: math.setAttribute("display", "block");
! 64: math.appendChild(root.toMathML());
! 65: output_node.appendChild(math);
! 66: MathJax.Hub.Queue(["Typeset", MathJax.Hub, output_node]);
! 67: }
! 68: } catch (e) {
! 69: output = "error: " + e;
! 70: output_node.setAttribute("title", output);
! 71: if (e instanceof ParseException) {
! 72: output_node.appendChild(document.createTextNode(txt.substring(0, e.from)));
! 73: var span = document.createElement('span');
! 74: span.appendChild(document.createTextNode(txt.substring(e.from, e.to + 1)));
! 75: span.className = 'math-error';
! 76: output_node.appendChild(span);
! 77: if (e.to < txt.length - 1) {
! 78: output_node.appendChild(document.createTextNode(txt.substring(e.to + 1)));
! 79: }
! 80: } else {
! 81: var tn = document.createTextNode(output);
! 82: output_node.appendChild(tn);
! 83: }
! 84: }
! 85: }
! 86: }
! 87: }
! 88:
! 89: var init_done = false;
! 90:
! 91: /*
! 92: Looks for elements with the "math" class, and
! 93: adds a preview div afterward which is updated automatically.
! 94: */
! 95: var initEditors = function() {
! 96: if (init_done)
! 97: return;
! 98: init_done = true;
! 99: var math_objects = [];
! 100: var math_inputs = document.getElementsByClassName('math');
! 101: for (var i=0; i<math_inputs.length; i++) {
! 102: var ta = math_inputs[i];
! 103: if (ta.nodeName == "TEXTAREA" || ta.nodeName == "INPUT") {
! 104: var output_node = document.createElement("span");
! 105: output_node.setAttribute("style", "display:none");
! 106: if (ta.nextSibling)
! 107: ta.parentNode.insertBefore(output_node, ta.nextSibling);
! 108: else
! 109: ta.parentNode.appendChild(output_node);
! 110: var hideNode = function(node) {
! 111: return function(e) { node.setAttribute("style", "display:none"); };
! 112: };
! 113: var showNode = function(node) {
! 114: return function(e) { node.setAttribute("style", "display: inline-block; background-color: #FFFFE0"); };
! 115: };
! 116: ta.addEventListener("blur", hideNode(output_node), false);
! 117: ta.addEventListener("focus", showNode(output_node), false);
! 118: var implicit_operators = (ta.getAttribute("data-implicit_operators") === "true");
! 119: var unit_mode = (ta.getAttribute("data-unit_mode") === "true");
! 120: var constants = ta.getAttribute("data-constants");
! 121: if (constants)
! 122: constants = constants.split(/[\s,]+/);
! 123: var oldtxt = "";
! 124: math_objects[i] = {
! 125: "ta": ta,
! 126: "output_node": output_node,
! 127: "oldtxt": oldtxt,
! 128: "parser": new Parser(implicit_operators, unit_mode, constants)
! 129: };
! 130: var changeObjectN = function(n) {
! 131: return function(e) {
! 132: var obj = math_objects[n];
! 133: if (document.activeElement == obj.ta) {
! 134: // this is useful if there is data in the field with the page default focus
! 135: // (there might not be a focus event for the active element)
! 136: obj.output_node.setAttribute("style", "display: inline-block; background-color: #FFFFE0");
! 137: }
! 138: handleChange(obj);
! 139: };
! 140: };
! 141: var startChange = changeObjectN(i);
! 142: if (ta.value != oldtxt)
! 143: startChange(); // process non-empty fields even though they are not visible yet
! 144: ta.addEventListener('change', startChange, false);
! 145: ta.addEventListener('keyup', startChange, false);
! 146: }
! 147: }
! 148: }
! 149:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>