Annotation of loncom/html/adm/LC_math_editor/src/enode.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: /**
! 22: * Parsed tree node. ENode.toMathML(hcolors) contains the code for the transformation into MathML.
! 23: * @constructor
! 24: * @param {number} type - ENode.UNKNOWN | NAME | NUMBER | OPERATOR | FUNCTION | VECTOR
! 25: * @param {Operator} op - The operator
! 26: * @param {string} value - Node value as a string, null for type VECTOR
! 27: * @param {Array.<ENode>} children - The children nodes, only for types OPERATOR, FUNCTION, VECTOR, SUBSCRIPT
! 28: */
! 29: function ENode(type, op, value, children) {
! 30: this.type = type;
! 31: this.op = op;
! 32: this.value = value;
! 33: this.children = children;
! 34: }
! 35:
! 36: ENode.UNKNOWN = 0;
! 37: ENode.NAME = 1;
! 38: ENode.NUMBER = 2;
! 39: ENode.OPERATOR = 3;
! 40: ENode.FUNCTION = 4;
! 41: ENode.VECTOR = 5;
! 42: ENode.SUBSCRIPT = 6;
! 43: ENode.COLORS = ["#E01010", "#0010FF", "#009000", "#FF00FF", "#00B0B0", "#F09000",
! 44: "#800080", "#F080A0", "#6090F0", "#902000", "#70A050", "#A07060",
! 45: "#5000FF", "#E06050", "#008080", "#808000"];
! 46:
! 47: /**
! 48: * Returns the node as a string, for debug
! 49: * @returns {string}
! 50: */
! 51: ENode.prototype.toString = function() {
! 52: var s = '(';
! 53: switch (this.type) {
! 54: case ENode.UNKNOWN:
! 55: s += 'UNKNOWN';
! 56: break;
! 57: case ENode.NAME:
! 58: s += 'NAME';
! 59: break;
! 60: case ENode.NUMBER:
! 61: s += 'NUMBER';
! 62: break;
! 63: case ENode.OPERATOR:
! 64: s += 'OPERATOR';
! 65: break;
! 66: case ENode.FUNCTION:
! 67: s += 'FUNCTION';
! 68: break;
! 69: case ENode.VECTOR:
! 70: s += 'VECTOR';
! 71: break;
! 72: case ENode.SUBSCRIPT:
! 73: s += 'SUBSCRIPT';
! 74: break;
! 75: }
! 76: if (this.op)
! 77: s += " '" + this.op.id + "'";
! 78: if (this.value)
! 79: s += " '" + this.value + "'";
! 80: if (this.children) {
! 81: s += ' [';
! 82: for (var i = 0; i < this.children.length; i++) {
! 83: s += this.children[i].toString();
! 84: if (i != this.children.length - 1)
! 85: s += ',';
! 86: }
! 87: s += ']';
! 88: }
! 89: s+= ')';
! 90: return s;
! 91: };
! 92:
! 93: /**
! 94: * Returns the color for an identifier.
! 95: * @param {string} name
! 96: * @param {Object.<string, string>} hcolors - hash identifier->color
! 97: * @returns {string}
! 98: */
! 99: ENode.prototype.getColorForIdentifier = function(name, hcolors) {
! 100: var res = hcolors[name];
! 101: if (!res) {
! 102: res = ENode.COLORS[Object.keys(hcolors).length % ENode.COLORS.length];
! 103: hcolors[name] = res;
! 104: }
! 105: return res;
! 106: }
! 107:
! 108: /**
! 109: * Transforms this ENode into a MathML HTML DOM element.
! 110: * @param {Object} [context] - display context (not needed for the root element)
! 111: * @param {Object.<string, string>} context.hcolors - hash identifier->color
! 112: * @param {number} context.depth - Depth in parenthesis, used for coloring
! 113: * @returns {Element}
! 114: */
! 115: ENode.prototype.toMathML = function(context) {
! 116: var c0, c1, c2, c3, c4, i, j, el, par, mrow, mo, mtable, mfrac, msub, msup;
! 117: if (typeof context == "undefined")
! 118: context = { hcolors: {}, depth: 0 };
! 119: if (this.children != null && this.children.length > 0)
! 120: c0 = this.children[0];
! 121: else
! 122: c0 = null;
! 123: if (this.children != null && this.children.length > 1)
! 124: c1 = this.children[1];
! 125: else
! 126: c1 = null;
! 127: if (this.children != null && this.children.length > 2)
! 128: c2 = this.children[2];
! 129: else
! 130: c2 = null;
! 131: if (this.children != null && this.children.length > 3)
! 132: c3 = this.children[3];
! 133: else
! 134: c3 = null;
! 135: if (this.children != null && this.children.length > 4)
! 136: c4 = this.children[4];
! 137: else
! 138: c4 = null;
! 139:
! 140: switch (this.type) {
! 141: case ENode.UNKNOWN:
! 142: el = document.createElement('mtext');
! 143: el.appendChild(document.createTextNode("???"));
! 144: return(el);
! 145:
! 146: case ENode.NAME:
! 147: if (this.value.search(/^[a-zA-Z]+[0-9]+$/) >= 0) {
! 148: var ind = this.value.search(/[0-9]/);
! 149: msub = document.createElement('msub');
! 150: msub.appendChild(this.mi(this.value.substring(0,ind)));
! 151: msub.appendChild(this.mn(this.value.substring(ind)));
! 152: el = msub;
! 153: } else {
! 154: el = this.mi(this.value)
! 155: }
! 156: el.setAttribute("mathcolor", this.getColorForIdentifier(this.value, context.hcolors));
! 157: return(el);
! 158:
! 159: case ENode.NUMBER:
! 160: if (this.value.indexOf('e') != -1 || this.value.indexOf('E') != -1) {
! 161: var index = this.value.indexOf('e');
! 162: if (index == -1)
! 163: index = this.value.indexOf('E');
! 164: mrow = document.createElement('mrow');
! 165: mrow.appendChild(this.mn(this.value.substring(0, index)));
! 166: mrow.appendChild(this.mo("\u22C5"));
! 167: msup = document.createElement('msup');
! 168: msup.appendChild(this.mn(10));
! 169: msup.appendChild(this.mn(this.value.substring(index + 1)));
! 170: mrow.appendChild(msup);
! 171: return(mrow);
! 172: }
! 173: return(this.mn(this.value));
! 174:
! 175: case ENode.OPERATOR:
! 176: if (this.value == "/") {
! 177: mfrac = document.createElement('mfrac');
! 178: mfrac.appendChild(c0.toMathML(context));
! 179: mfrac.appendChild(c1.toMathML(context));
! 180: el = mfrac;
! 181: } else if (this.value == "^") {
! 182: if (c0.type == ENode.FUNCTION) {
! 183: if (c0.value == "sqrt" || c0.value == "abs" || c0.value == "matrix" ||
! 184: c0.value == "diff")
! 185: par = false;
! 186: else
! 187: par = true;
! 188: } else if (c0.type == ENode.OPERATOR) {
! 189: par = true;
! 190: } else
! 191: par = false;
! 192: el = document.createElement('msup');
! 193: if (par)
! 194: el.appendChild(this.addP(c0, context));
! 195: else
! 196: el.appendChild(c0.toMathML(context));
! 197: el.appendChild(c1.toMathML(context));
! 198: } else if (this.value == "*") {
! 199: mrow = document.createElement('mrow');
! 200: if (c0.type == ENode.OPERATOR && (c0.value == "+" || c0.value == "-"))
! 201: mrow.appendChild(this.addP(c0, context));
! 202: else
! 203: mrow.appendChild(c0.toMathML(context));
! 204: // should the x operator be visible ? We need to check if there is a number to the left of c1
! 205: var firstinc1 = c1;
! 206: while (firstinc1.type == ENode.OPERATOR) {
! 207: firstinc1 = firstinc1.children[0];
! 208: }
! 209: // ... and if it's an operation between vectors/matrices, the * operator should be displayed
! 210: // (it is ambiguous otherwise)
! 211: // note: this will not work if the matrix is calculated, for instance with 2[1;2]*[3;4]
! 212: if (c0.type == ENode.VECTOR && c1.type == ENode.VECTOR)
! 213: mrow.appendChild(this.mo("*"));
! 214: else if (firstinc1.type == ENode.NUMBER)
! 215: mrow.appendChild(this.mo("\u22C5"));
! 216: if (c1.type == ENode.OPERATOR && (c1.value == "+" || c1.value == "-"))
! 217: mrow.appendChild(this.addP(c1, context));
! 218: else
! 219: mrow.appendChild(c1.toMathML(context));
! 220: el = mrow;
! 221: } else if (this.value == "-") {
! 222: mrow = document.createElement('mrow');
! 223: if (this.children.length == 1) {
! 224: mrow.appendChild(this.mo("-"));
! 225: mrow.appendChild(c0.toMathML(context));
! 226: } else {
! 227: mrow.appendChild(c0.toMathML(context));
! 228: mrow.appendChild(this.mo("-"));
! 229: if (c1.type == ENode.OPERATOR && (c1.value == "+" || c1.value == "-"))
! 230: mrow.appendChild(this.addP(c1, context));
! 231: else
! 232: mrow.appendChild(c1.toMathML(context));
! 233: }
! 234: el = mrow;
! 235: } else if (this.value == "!") {
! 236: mrow = document.createElement('mrow');
! 237: mo = this.mo(this.value);
! 238: if (c0.type == ENode.OPERATOR && (c0.value == "+" || c0.value == "-"))
! 239: mrow.appendChild(this.addP(c0, context));
! 240: else
! 241: mrow.appendChild(c0.toMathML(context));
! 242: mrow.appendChild(mo);
! 243: el = mrow;
! 244: } else if (this.value == "+") {
! 245: mrow = document.createElement('mrow');
! 246: mo = this.mo(this.value);
! 247: mrow.appendChild(c0.toMathML(context));
! 248: mrow.appendChild(mo);
! 249: // should we add parenthesis ? We need to check if there is a '-' to the left of c1
! 250: par = false;
! 251: var first = c1;
! 252: while (first.type == ENode.OPERATOR) {
! 253: if (first.value == "-" && first.children.length == 1) {
! 254: par = true;
! 255: break;
! 256: } else if (first.value == "+" || first.value == "-" || first.value == "*") {
! 257: first = first.children[0];
! 258: } else {
! 259: break;
! 260: }
! 261: }
! 262: if (par)
! 263: mrow.appendChild(this.addP(c1, context));
! 264: else
! 265: mrow.appendChild(c1.toMathML(context));
! 266: el = mrow;
! 267: } else if (this.value == ".") {
! 268: mrow = document.createElement('mrow');
! 269: if (c0.type == ENode.OPERATOR && (c0.value == "+" || c0.value == "-"))
! 270: mrow.appendChild(this.addP(c0, context));
! 271: else
! 272: mrow.appendChild(c0.toMathML(context));
! 273: mrow.appendChild(this.mo("\u22C5"));
! 274: if (c1.type == ENode.OPERATOR && (c1.value == "+" || c1.value == "-"))
! 275: mrow.appendChild(this.addP(c1, context));
! 276: else
! 277: mrow.appendChild(c1.toMathML(context));
! 278: el = mrow;
! 279: } else if (this.value == "`") {
! 280: mrow = document.createElement('mrow');
! 281: if (c0.type == ENode.OPERATOR && (c0.value == "+" || c0.value == "-"))
! 282: mrow.appendChild(this.addP(c0, context));
! 283: else
! 284: mrow.appendChild(c0.toMathML(context));
! 285: // the units should not be in italics
! 286: var mstyle = document.createElement("mstyle");
! 287: mstyle.setAttribute("fontstyle", "normal");
! 288: if (c1.type == ENode.OPERATOR && (c1.value == "+" || c1.value == "-"))
! 289: mstyle.appendChild(this.addP(c1, context));
! 290: else
! 291: mstyle.appendChild(c1.toMathML(context));
! 292: mrow.appendChild(mstyle);
! 293: el = mrow;
! 294: } else {
! 295: // relational operators
! 296: mrow = document.createElement('mrow');
! 297: mo = this.mo(this.value);
! 298: mrow.appendChild(c0.toMathML(context));
! 299: mrow.appendChild(mo);
! 300: mrow.appendChild(c1.toMathML(context));
! 301: el = mrow;
! 302: }
! 303: return(el);
! 304:
! 305: case ENode.FUNCTION: /* TODO: throw exceptions if wrong nb of args ? */
! 306: // c0 contains the function name
! 307: if (c0.value == "sqrt" && c1 != null) {
! 308: el = document.createElement('msqrt');
! 309: el.appendChild(c1.toMathML(context));
! 310: } else if (c0.value == "abs" && c1 != null) {
! 311: mrow = document.createElement('mrow');
! 312: mrow.appendChild(this.mo("|"));
! 313: mrow.appendChild(c1.toMathML(context));
! 314: mrow.appendChild(this.mo("|"));
! 315: el = mrow;
! 316: } else if (c0.value == "exp" && c1 != null) {
! 317: el = document.createElement('msup');
! 318: el.appendChild(this.mi("e"));
! 319: el.appendChild(c1.toMathML(context));
! 320: } else if (c0.value == "factorial") {
! 321: mrow = document.createElement('mrow');
! 322: mo = this.mo("!");
! 323: if (c1.type == ENode.OPERATOR && (c1.value == "+" || c1.value == "-"))
! 324: mrow.appendChild(this.addP(c1, context));
! 325: else
! 326: mrow.appendChild(c1.toMathML(context));
! 327: mrow.appendChild(mo);
! 328: el = mrow;
! 329: } else if (c0.value == "diff" && this.children != null && this.children.length == 3) {
! 330: mrow = document.createElement('mrow');
! 331: mfrac = document.createElement('mfrac');
! 332: mfrac.appendChild(this.mi("d"));
! 333: var f2 = document.createElement('mrow');
! 334: f2.appendChild(this.mi("d"));
! 335: f2.appendChild(this.mi(c2.value));
! 336: mfrac.appendChild(f2);
! 337: mrow.appendChild(mfrac);
! 338: if (c1.type == ENode.OPERATOR && (c1.value == "+" || c1.value == "-"))
! 339: mrow.appendChild(this.addP(c1, context));
! 340: else
! 341: mrow.appendChild(c1.toMathML(context));
! 342: el = mrow;
! 343: } else if (c0.value == "diff" && this.children != null && this.children.length == 4) {
! 344: mrow = document.createElement('mrow');
! 345: mfrac = document.createElement('mfrac');
! 346: msup = document.createElement('msup');
! 347: msup.appendChild(this.mi("d"));
! 348: msup.appendChild(c3.toMathML(context));
! 349: mfrac.appendChild(msup);
! 350: var f2 = document.createElement('mrow');
! 351: f2.appendChild(this.mi("d"));
! 352: msup = document.createElement('msup');
! 353: msup.appendChild(c2.toMathML(context));
! 354: msup.appendChild(c3.toMathML(context));
! 355: f2.appendChild(msup);
! 356: mfrac.appendChild(f2);
! 357: mrow.appendChild(mfrac);
! 358: if (c1.type == ENode.OPERATOR && (c1.value == "+" || c1.value == "-"))
! 359: mrow.appendChild(this.addP(c1, context));
! 360: else
! 361: mrow.appendChild(c1.toMathML(context));
! 362: el = mrow;
! 363: } else if (c0.value == "integrate" && this.children != null && this.children.length == 3) {
! 364: mrow = document.createElement('mrow');
! 365: var mo = this.mo("\u222B");
! 366: mo.setAttribute("stretchy", "true"); // doesn't work with MathJax
! 367: mrow.appendChild(mo);
! 368: if (c2.type == ENode.OPERATOR && (c2.value == "+" || c2.value == "-"))
! 369: mrow.appendChild(this.addP(c1, context));
! 370: else
! 371: mrow.appendChild(c1.toMathML(context));
! 372: mrow.appendChild(this.mi("d"));
! 373: mrow.appendChild(c2.toMathML(context));
! 374: el = mrow;
! 375: } else if (c0.value == "integrate" && this.children != null && this.children.length == 5) {
! 376: mrow = document.createElement('mrow');
! 377: var msubsup = document.createElement('msubsup');
! 378: var mo = this.mo("\u222B");
! 379: mo.setAttribute("stretchy", "true"); // doesn't work with MathJax
! 380: msubsup.appendChild(mo);
! 381: msubsup.appendChild(c3.toMathML(context));
! 382: msubsup.appendChild(c4.toMathML(context));
! 383: mrow.appendChild(msubsup);
! 384: if (c2.type == ENode.OPERATOR && (c2.value == "+" || c2.value == "-"))
! 385: mrow.appendChild(this.addP(c1, context));
! 386: else
! 387: mrow.appendChild(c1.toMathML(context));
! 388: mrow.appendChild(this.mi("d"));
! 389: mrow.appendChild(c2.toMathML(context));
! 390: el = mrow;
! 391: } else if (c0.value == "sum" && this.children != null && this.children.length == 5) {
! 392: mrow = document.createElement('mrow');
! 393: var munderover = document.createElement('munderover');
! 394: var mo = this.mo("\u2211");
! 395: mo.setAttribute("stretchy", "true"); // doesn't work with MathJax
! 396: munderover.appendChild(mo);
! 397: var mrow2 = document.createElement('mrow');
! 398: mrow2.appendChild(c2.toMathML(context));
! 399: mrow2.appendChild(this.mo("="));
! 400: mrow2.appendChild(c3.toMathML(context));
! 401: munderover.appendChild(mrow2);
! 402: munderover.appendChild(c4.toMathML(context));
! 403: mrow.appendChild(munderover);
! 404: if (c2.type == ENode.OPERATOR && (c2.value == "+" || c2.value == "-"))
! 405: mrow.appendChild(this.addP(c1, context));
! 406: else
! 407: mrow.appendChild(c1.toMathML(context));
! 408: el = mrow;
! 409: } else if (c0.value == "product" && this.children != null && this.children.length == 5) {
! 410: mrow = document.createElement('mrow');
! 411: var munderover = document.createElement('munderover');
! 412: var mo = this.mo("\u220F");
! 413: mo.setAttribute("stretchy", "true"); // doesn't work with MathJax
! 414: munderover.appendChild(mo);
! 415: var mrow2 = document.createElement('mrow');
! 416: mrow2.appendChild(c2.toMathML(context));
! 417: mrow2.appendChild(this.mo("="));
! 418: mrow2.appendChild(c3.toMathML(context));
! 419: munderover.appendChild(mrow2);
! 420: munderover.appendChild(c4.toMathML(context));
! 421: mrow.appendChild(munderover);
! 422: if (c2.type == ENode.OPERATOR && (c2.value == "+" || c2.value == "-"))
! 423: mrow.appendChild(this.addP(c1, context));
! 424: else
! 425: mrow.appendChild(c1.toMathML(context));
! 426: el = mrow;
! 427: } else if (c0.value == "limit") {
! 428: mrow = document.createElement('mrow');
! 429: if (this.children.length < 4) {
! 430: mrow.appendChild(this.mo("lim"));
! 431: } else {
! 432: var munder = document.createElement('munder');
! 433: munder.appendChild(this.mo("lim"));
! 434: var mrowunder = document.createElement('mrow');
! 435: mrowunder.appendChild(c2.toMathML(context));
! 436: mrowunder.appendChild(this.mo("\u2192"));
! 437: mrowunder.appendChild(c3.toMathML(context));
! 438: if (c4 != null) {
! 439: if (c4.value == "plus")
! 440: mrowunder.appendChild(this.mo("+"));
! 441: else if (c4.value == "minus")
! 442: mrowunder.appendChild(this.mo("-"));
! 443: }
! 444: munder.appendChild(mrowunder);
! 445: mrow.appendChild(munder);
! 446: }
! 447: mrow.appendChild(c1.toMathML(context));
! 448: el = mrow;
! 449: } else if (c0.value == "binomial") {
! 450: // displayed like a vector
! 451: mrow = document.createElement('mrow');
! 452: mrow.appendChild(this.mo("("));
! 453: mtable = document.createElement('mtable');
! 454: for (i=1; i<this.children.length; i++) {
! 455: var mtr = document.createElement('mtr');
! 456: mtr.appendChild(this.children[i].toMathML(context));
! 457: mtable.appendChild(mtr);
! 458: }
! 459: mrow.appendChild(mtable);
! 460: mrow.appendChild(this.mo(")"));
! 461: el = mrow;
! 462: } else if (c0.value == "matrix") {
! 463: for (i=1; i<this.children.length; i++) {
! 464: // check that all children are vectors
! 465: if (this.children[i].type !== ENode.VECTOR) {
! 466: el = document.createElement('mtext');
! 467: el.appendChild(document.createTextNode("???")); // could throw here
! 468: return(el);
! 469: }
! 470: }
! 471: mrow = document.createElement('mrow');
! 472: mrow.appendChild(this.mo("("));
! 473: mtable = document.createElement('mtable');
! 474: for (i=1; i<this.children.length; i++) {
! 475: var mtr = document.createElement('mtr');
! 476: for (j=0; j<this.children[i].children.length; j++) {
! 477: mtr.appendChild(this.children[i].children[j].toMathML(context));
! 478: }
! 479: mtable.appendChild(mtr);
! 480: }
! 481: mrow.appendChild(mtable);
! 482: mrow.appendChild(this.mo(")"));
! 483: el = mrow;
! 484: } else {
! 485: // default display for a function
! 486: mrow = document.createElement('mrow');
! 487: mrow.appendChild(c0.toMathML(context));
! 488: mrow.appendChild(this.mo("("));
! 489: for (i=1; i<this.children.length; i++) {
! 490: mrow.appendChild(this.children[i].toMathML(context));
! 491: if (i < this.children.length - 1)
! 492: mrow.appendChild(this.mo(Definitions.ARG_SEPARATOR));
! 493: }
! 494: mrow.appendChild(this.mo(")"));
! 495: el = mrow;
! 496: }
! 497: return(el);
! 498:
! 499: case ENode.VECTOR:
! 500: var is_matrix = true;
! 501: for (i=0; i<this.children.length; i++) {
! 502: if (this.children[i].type !== ENode.VECTOR)
! 503: is_matrix = false;
! 504: }
! 505: mrow = document.createElement('mrow');
! 506: mrow.appendChild(this.mo("("));
! 507: mtable = document.createElement('mtable');
! 508: for (i=0; i<this.children.length; i++) {
! 509: var mtr = document.createElement('mtr');
! 510: if (is_matrix) {
! 511: for (j=0; j<this.children[i].children.length; j++) {
! 512: mtr.appendChild(this.children[i].children[j].toMathML(context));
! 513: }
! 514: } else {
! 515: mtr.appendChild(this.children[i].toMathML(context));
! 516: }
! 517: mtable.appendChild(mtr);
! 518: }
! 519: mrow.appendChild(mtable);
! 520: mrow.appendChild(this.mo(")"));
! 521: return(mrow);
! 522:
! 523: case ENode.SUBSCRIPT:
! 524: msub = document.createElement('msub');
! 525: msub.appendChild(c0.toMathML(context));
! 526: if (this.children.length > 2) {
! 527: mrow = document.createElement('mrow');
! 528: for (i=1; i<this.children.length; i++) {
! 529: mrow.appendChild(this.children[i].toMathML(context));
! 530: if (i < this.children.length - 1)
! 531: mrow.appendChild(this.mo(Definitions.ARG_SEPARATOR));
! 532: }
! 533: msub.appendChild(mrow);
! 534: } else {
! 535: msub.appendChild(c1.toMathML(context));
! 536: }
! 537: return(msub);
! 538: }
! 539: };
! 540:
! 541: /**
! 542: * Creates a MathML mi element with the given name
! 543: * @param {string} name
! 544: * @returns {Element}
! 545: */
! 546: ENode.prototype.mi = function(name) {
! 547: var mi = document.createElement('mi');
! 548: if (ENode.symbols[name])
! 549: name = ENode.symbols[name];
! 550: mi.appendChild(document.createTextNode(name));
! 551: return mi;
! 552: };
! 553:
! 554: /**
! 555: * Creates a MathML mn element with the given number or string
! 556: * @param {string} n
! 557: * @returns {Element}
! 558: */
! 559: ENode.prototype.mn = function(n) {
! 560: var mn = document.createElement('mn');
! 561: mn.appendChild(document.createTextNode(n));
! 562: return mn;
! 563: };
! 564:
! 565: /**
! 566: * Creates a MathML mo element with the given name
! 567: * @param {string} name
! 568: * @returns {Element}
! 569: */
! 570: ENode.prototype.mo = function(name) {
! 571: var mo = document.createElement('mo');
! 572: if (ENode.symbols[name])
! 573: name = ENode.symbols[name];
! 574: mo.appendChild(document.createTextNode(name));
! 575: return mo;
! 576: };
! 577:
! 578: /**
! 579: * Add parenthesis and returns a MathML element
! 580: * @param {ENode} en
! 581: * @param {Object} [context] - display context (not needed for the root element)
! 582: * @param {Object.<string, string>} context.hcolors - hash identifier->color
! 583: * @param {number} context.depth - Depth in parenthesis, used for coloring
! 584: * @returns {Element}
! 585: */
! 586: ENode.prototype.addP = function(en, context) {
! 587: var mrow, mo;
! 588: mrow = document.createElement('mrow');
! 589: mo = this.mo("(");
! 590: mo.setAttribute("mathcolor", ENode.COLORS[context.depth % ENode.COLORS.length]);
! 591: mrow.appendChild(mo);
! 592: context.depth++;
! 593: mrow.appendChild(en.toMathML(context));
! 594: context.depth--;
! 595: mo = this.mo(")");
! 596: mo.setAttribute("mathcolor", ENode.COLORS[context.depth % ENode.COLORS.length]);
! 597: mrow.appendChild(mo);
! 598: return mrow;
! 599: };
! 600:
! 601: ENode.symbols = {
! 602: /* lowercase greek */
! 603: "alpha": "\u03B1", "beta": "\u03B2", "gamma": "\u03B3",
! 604: "delta": "\u03B4", "epsilon": "\u03B5", "zeta": "\u03B6",
! 605: "eta": "\u03B7", "theta": "\u03B8", "iota": "\u03B9",
! 606: "kappa": "\u03BA", "lambda": "\u03BB", "mu": "\u03BC",
! 607: "nu": "\u03BD", "xi": "\u03BE", "omicron": "\u03BF",
! 608: "pi": "\u03C0", "rho": "\u03C1", "sigma": "\u03C3",
! 609: "tau": "\u03C4", "upsilon": "\u03C5", "phi": "\u03C6",
! 610: "chi": "\u03C7", "psi": "\u03C8", "omega": "\u03C9",
! 611: /* uppercase greek */
! 612: "Alpha": "\u0391", "Beta": "\u0392", "Gamma": "\u0393",
! 613: "Delta": "\u0394", "Epsilon": "\u0395", "Zeta": "\u0396",
! 614: "Eta": "\u0397", "Theta": "\u0398", "Iota": "\u0399",
! 615: "Kappa": "\u039A", "Lambda": "\u039B", "Mu": "\u039C",
! 616: "Nu": "\u039D", "Xi": "\u039E", "Omicron": "\u039F",
! 617: "Pi": "\u03A0", "Rho": "\u03A1", "Sigma": "\u03A3",
! 618: "Tau": "\u03A4", "Upsilon": "\u03A5", "Phi": "\u03A6",
! 619: "Chi": "\u03A7", "Psi": "\u03A8", "Omega": "\u03A9",
! 620:
! 621: /* operators */
! 622: "#": "\u2260",
! 623: ">=": "\u2265",
! 624: "<=": "\u2264",
! 625:
! 626: /* other */
! 627: "inf": "\u221E",
! 628: "minf": "-\u221E",
! 629: "hbar": "\u210F",
! 630: "G": "\uD835\uDCA2" // 1D4A2
! 631: };
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>