Diff for /loncom/html/adm/LC_math_editor/src/ui.js between versions 1.1 and 1.2

version 1.1, 2014/09/24 18:14:39 version 1.2, 2015/02/24 15:20:44
Line 43  var handleChange = function(math_object) Line 43  var handleChange = function(math_object)
         test2 = test1.replace(/\([^\(\)]*\)/g, '');          test2 = test1.replace(/\([^\(\)]*\)/g, '');
       }        }
       if (test2.split("(").length == test2.split(")").length) {        if (test2.split("(").length == test2.split(")").length) {
         if (test2.indexOf(Definitions.ARG_SEPARATOR) != -1) {          test1 = '';
           txt = '['+txt+']';          while (test2 != test1) {
             test1 = test2;
             test2 = test1.replace(/\{[^\{\}]*\}/g, '');
           }
           if (test2.split("{").length == test2.split("}").length) {
             if (test2.indexOf(Definitions.ARG_SEPARATOR) != -1) {
               txt = '['+txt+']';
             }
         }          }
       }        }
     }      }
Line 86  var handleChange = function(math_object) Line 93  var handleChange = function(math_object)
     }      }
 }  }
   
 var init_done = false;  var math_objects = [];
   
 /*  /*
   Looks for elements with the "math" class, and    Looks for elements with the "math" class, and
   adds a preview div afterward which is updated automatically.    adds a preview div afterward which is updated automatically.
     Can be called again after math fields have been added, removed, or when options have changed.
 */  */
 var initEditors = function() {  var initEditors = function() {
     if (init_done)      // to hide the MathJax messages (note: this could be done elsewhere)
         return;      MathJax.Hub.Config({
     init_done = true;          messageStyle: "none"
     var math_objects = [];      });
     var math_inputs = document.getElementsByClassName('math');      var math_inputs = document.getElementsByClassName('math');
       // first remove the nodes and objects for the inputs that are gone
       for (var i=0; i<math_objects.length; i++) {
           var ta = math_objects[i].ta;
           var found = false;
           for (var j=0; j<math_inputs.length; j++) {
               if (math_inputs[j] == ta) {
                   found = true;
                   break;
               }
           }
           if (!found) {
               var output_node = math_objects[i].output_node;
               if (output_node.parentNode) {
                   output_node.parentNode.removeChild(output_node);
               }
               math_objects.splice(i, 1);
               i--;
           }
       }
       // then create or update nodes and objects for the new inputs
     for (var i=0; i<math_inputs.length; i++) {      for (var i=0; i<math_inputs.length; i++) {
         var ta = math_inputs[i];          var ta = math_inputs[i];
         if (ta.nodeName == "TEXTAREA" || ta.nodeName == "INPUT") {          if (ta.nodeName == "TEXTAREA" || ta.nodeName == "INPUT") {
             var output_node = document.createElement("span");              var ind_math = -1;
             output_node.setAttribute("style", "display:none");              for (var j=0; j<math_objects.length; j++) {
             if (ta.nextSibling)                  if (math_objects[j].ta == ta) {
                 ta.parentNode.insertBefore(output_node, ta.nextSibling);                      ind_math = j;
             else                      break;
                 ta.parentNode.appendChild(output_node);                  }
             var hideNode = function(node) {              }
                 return function(e) { node.setAttribute("style", "display:none"); };  
             };  
             var showNode = function(node) {  
                 return function(e) { node.setAttribute("style", "display: inline-block; background-color: #FFFFE0"); };  
             };  
             ta.addEventListener("blur", hideNode(output_node), false);  
             ta.addEventListener("focus", showNode(output_node), false);  
             var implicit_operators = (ta.getAttribute("data-implicit_operators") === "true");              var implicit_operators = (ta.getAttribute("data-implicit_operators") === "true");
             var unit_mode = (ta.getAttribute("data-unit_mode") === "true");              var unit_mode = (ta.getAttribute("data-unit_mode") === "true");
             var constants = ta.getAttribute("data-constants");              var constants = ta.getAttribute("data-constants");
             if (constants)              if (constants)
                 constants = constants.split(/[\s,]+/);                  constants = constants.split(/[\s,]+/);
             var oldtxt = "";              var output_node;
             math_objects[i] = {              if (ind_math == -1) {
                 "ta": ta,                  output_node = document.createElement("span");
                 "output_node": output_node,                  output_node.style.display = "none";
                 "oldtxt": oldtxt,                  output_node.style.position = "absolute";
                 "parser": new Parser(implicit_operators, unit_mode, constants)                  output_node.style.backgroundColor = "rgba(255,255,224,0.9)";
             };                  output_node.style.color = "black";
             var changeObjectN = function(n) {                  output_node.style.border = "1px solid #A0A0A0";
                 return function(e) {                  output_node.style.padding = "5px";
                   var obj = math_objects[n];                  output_node.style.zIndex = "1";
                   if (document.activeElement == obj.ta) {                  var getCSSAbsolutePosition = function getCSSAbsolutePosition(el) {
                     // this is useful if there is data in the field with the page default focus                      var x = 0;
                     // (there might not be a focus event for the active element)                      var y = 0;
                     obj.output_node.setAttribute("style", "display: inline-block; background-color: #FFFFE0");                      while (el && !isNaN(el.offsetLeft) && !isNaN(el.offsetTop)) {
                   }                          x += el.offsetLeft - el.scrollLeft;
                   handleChange(obj);                          y += el.offsetTop - el.scrollTop;
                           el = el.offsetParent;
                           if (el) {
                               var style = window.getComputedStyle(el);
                               if (style.position == 'absolute' || style.position == 'relative')
                                   break;
                           }
                       }
                       return {top: y, left: x};
                   }
                   var place = function(ta, output_node) {
                       // position the output_node below or on top of ta
                       var ta_rect = ta.getBoundingClientRect();
                       var root = document.documentElement;
                       var docTop = (window.pageYOffset || root.scrollTop)  - (root.clientTop || 0);
                       var docLeft = (window.pageXOffset || root.scrollLeft) - (root.clientLeft || 0);
                       var ta_pos = getCSSAbsolutePosition(ta);
                       output_node.style.left = ta_pos.left + "px";
                       if (window.innerHeight > ta_rect.bottom + output_node.offsetHeight)
                           output_node.style.top = (ta_pos.top + ta.offsetHeight) + "px";
                       else
                           output_node.style.top = (ta_pos.top - output_node.offsetHeight) + "px";
                   }
                   if (ta.nextSibling)
                       ta.parentNode.insertBefore(output_node, ta.nextSibling);
                   else
                       ta.parentNode.appendChild(output_node);
                   var hide_node = function(an_output_node) {
                       // returns a function that will hide the node on any event
                       // (we can't use the node directly because it changes in the loop)
                       return function(e) {
                         an_output_node.style.display = "none";
                       };
                   }
                   var focus = function(a_ta, an_output_node) {
                       return function(e) {
                           if (a_ta.value != '') {
                               an_output_node.style.display = "block";
                               place(a_ta, an_output_node);
                           }
                       };
                 };                  };
             };                  ta.addEventListener("blur", hide_node(output_node), false);
             var startChange = changeObjectN(i);                  ta.addEventListener("focus", focus(ta, output_node), false);
             if (ta.value != oldtxt)                  output_node.addEventListener("mouseenter", hide_node(output_node), false);
                 startChange(); // process non-empty fields even though they are not visible yet                  ind_math = math_objects.length;
             ta.addEventListener('change', startChange, false);                  var oldtxt = "";
             ta.addEventListener('keyup', startChange, false);                  math_objects[ind_math] = {
                       "ta": ta,
                       "output_node": output_node,
                       "oldtxt": oldtxt,
                       "parser": new Parser(implicit_operators, unit_mode, constants)
                   };
                   var changeObjectN = function(n) {
                       return function(e) {
                         var obj = math_objects[n];
                         handleChange(obj);
                         if (document.activeElement == obj.ta) {
                             if (obj.ta.value != '') {
                                 obj.output_node.style.display = "block";
                                 MathJax.Hub.Queue(function () {
                                     // position the element only when MathJax is done, because the output_node height might change
                                     place(obj.ta, obj.output_node);
                                 });
                             } else {
                                 obj.output_node.style.display = "none";
                             }
                         }
                       };
                   };
                   var startChange = changeObjectN(ind_math);
                   if (ta.value != oldtxt)
                       startChange(); // process non-empty fields even though they are not visible yet
                   ta.addEventListener('change', startChange, false);
                   ta.addEventListener('keyup', startChange, false);
               } else {
                   // only create a new parser and update the result if the options have changed
                   var same_constants;
                   var parser = math_objects[ind_math].parser;
                   if (!constants && parser.constants.length == 0) {
                       same_constants = true;
                   } else {
                       if (constants) {
                           same_constants = parser.constants.length == constants.length;
                           if (same_constants) {
                               for (var j=0; j<constants.length; j++) {
                                   if (parser.constants[j] != constants[j]) {
                                       same_constants = false;
                                       break;
                                   }
                               }
                           }
                       } else {
                           same_constants = false;
                       }
                   }
                   if (parser.implicit_operators != implicit_operators || parser.unit_mode != unit_mode || !same_constants) {
                       math_objects[ind_math].parser = new Parser(implicit_operators, unit_mode, constants);
                       if (ta.value != '') {
                           math_objects[ind_math].oldtxt = '';
                           handleChange(math_objects[ind_math]);
                       }
                   }
               }
         }          }
     }      }
 }  }
   
   /**
    * Updates display for <span class="math"> and <div class="math"> (LON-CAPA ln and dlm tags)
    */
   var updateMathSpanAndDiv = function() {
       var nl = document.getElementsByClassName('math');
       // convert to an array because the nodelist would change as we are removing nodes from the document
       var math_nodes = [];
       for (var i = 0, ref = math_nodes.length = nl.length; i < ref; i++) {
         math_nodes[i] = nl[i];
       }
       for (var i=0; i<math_nodes.length; i++) {
           var el = math_nodes[i];
           if (el.nodeName == "SPAN" || el.nodeName == "DIV") {
               if (el.firstChild == null || el.firstChild.nodeType != 3)
                   continue;
               var bspan = (el.nodeName == "SPAN");
               var txt = el.firstChild.nodeValue;
               var implicit_operators = (el.getAttribute("data-implicit_operators") === "true");
               var unit_mode = (el.getAttribute("data-unit_mode") === "true");
               var constants = el.getAttribute("data-constants");
               if (constants)
                   constants = constants.split(/[\s,]+/);
               var parser = new Parser(implicit_operators, unit_mode, constants);
               try {
                   var root = parser.parse(txt);
                   if (root != null) {
                       var math = document.createElement("math");
                       math.setAttribute("display", bspan ? "inline" : "block");
                       math.appendChild(root.toMathML(['#000000']));
                       // at this point it would be nice to replace el by math, but MathJax does not
                       // always typeset math elements when given directly, so we need to typeset the parent...
                       el.classList.remove('math');
                       el.removeChild(el.firstChild);
                       el.appendChild(math);
                       MathJax.Hub.Queue(["Typeset", MathJax.Hub, el]);
                   }
               } catch (e) {
                   el.firstChild.nodeValue = "[syntax error in math:" + e + "]";
                   el.classList.remove('math');
               }
           }
       }
   }

Removed from v.1.1  
changed lines
  Added in v.1.2


FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>