Modernize match scripts

Change-Id: Iea50c72d0ec1421d50ec4a4b7e7189f31caf934c
diff --git a/dev/js/src/match/treearc.js b/dev/js/src/match/treearc.js
index afcd187..6e7c01c 100644
--- a/dev/js/src/match/treearc.js
+++ b/dev/js/src/match/treearc.js
@@ -19,53 +19,57 @@
     // Initialize the state of the object

     _init : function (snippet) {

 

+      const t = this;

+

       // Predefine some values

-      this._tokens  = [];

-      this._arcs    = [];

-      this._tokenElements = [];

-      this._y = 0;

-      this._currentInFocus = undefined;

+      t._tokens  = [];

+      t._arcs    = [];

+      t._tokenElements = [];

+      t._y = 0;

+      t._currentInFocus = undefined;

 

       // Some configurations

-      this.maxArc      = 200; // maximum height of the bezier control point

-      this.overlapDiff = 40;  // Difference on overlaps and minimum height for self-refernces

-      this.arcDiff     = 15;

-      this.anchorDiff  = 8;

-      this.anchorStart = 15;

-      this.tokenSep    = 30;

-      this.xPadding    = 10;

-      this.yPadding    = 5;

+      t.maxArc      = 200; // maximum height of the bezier control point

+      t.overlapDiff = 40;  // Difference on overlaps and minimum height for self-refernces

+      t.arcDiff     = 15;

+      t.anchorDiff  = 8;

+      t.anchorStart = 15;

+      t.tokenSep    = 30;

+      t.xPadding    = 10;

+      t.yPadding    = 5;

 

       // No snippet to process

       if (snippet == undefined || snippet == null)

-        return this;

+        return t;

 

       // Parse the snippet

-      var html = d.createElement("div");

+      const html = d.createElement("div");

       html.innerHTML = snippet;

 

       // Establish temporary parsing memory

-      this.temp = {

+      t.temp = {

         target : {}, // Remember the map id => pos        

         edges  : [], // Remember edge definitions

         pos    : 0   // Keep track of the current token position

       };

 

       // Start parsing from root

-      this._parse(0, html.childNodes, undefined);

+      t._parse(0, html.childNodes, undefined);

 

       // Establish edge list

-      var targetMap = this.temp['target'];

-      var edges = this.temp['edges'];

+      const targetMap = t.temp['target'];

+      const edges = t.temp['edges'];

 

+      let targetID, target, relation;

+      

       // Iterate over edge lists

       // TODO:

       //   Support spans for anchors!

       edges.forEach(function(edge) {

 

         // Check the target identifier

-        var targetID = edge.targetID;

-        var target = targetMap[targetID];

+        targetID = edge.targetID;

+        target = targetMap[targetID];

 

         if (target != undefined) {

 

@@ -78,7 +82,7 @@
           */

           

           // Add relation

-          var relation = {

+          relation = {

             start : [edge.srcStart, edge.srcEnd],

             end : target,

             direction : 'uni',

@@ -87,10 +91,10 @@
           // console.log(relation);

           this.addRel(relation);

         };

-      }, this);

+      }, t);

 

       // Reset parsing memory

-      this.temp = {};

+      delete t["temp"];

 

       return this;

     },

@@ -104,7 +108,7 @@
         // Element node

         if (c.nodeType == 1) {

 

-          var xmlid, target, start, end;

+          let xmlid, target, start, end;

 

           // Node is an identifier

           if (c.hasAttribute('xml:id')) {

@@ -136,7 +140,7 @@
             // Node is a relation

             // Stricter: c.getAttribute('xlink:show') == "none"

             else {

-              var label;

+              let label;

 

               // Get target id

               target = c.getAttribute('xlink:href').replace(/^#/, "");

@@ -146,6 +150,7 @@
               };

 

               // Remember the defined edge

+// WRONG!

               var edge = {

                 label    : label,

                 srcStart : this.temp['pos'],

@@ -173,7 +178,7 @@
 

             // Element already defined

             if (this.temp['target'][xmlid] !== undefined) {

-              var newtarget = this.temp['target'][xmlid];

+              const newtarget = this.temp['target'][xmlid];

               end = this.temp['pos'] - 1;

               newtarget[0] = start < newtarget[0] ? start : newtarget[0];

               newtarget[1] = end > newtarget[1] ? end : newtarget[1];

@@ -218,7 +223,9 @@
 

           // Check, if there is a non-whitespace token

           if (c.nodeValue !== undefined) {

-            var str = c.nodeValue.trim();

+

+            const str = c.nodeValue.trim();

+

             if (str !== undefined && str.length > 0) {

 

               // Add token to token list

@@ -255,21 +262,23 @@
       return d.createElementNS(svgNS, tag);

     },

 

+

     // Get bounding box - with workaround for text nodes

     _rect : function (node) {

       if (node.tagName == "tspan" && !navigator.userAgent.match(/Edge/)) {

-        var range = d.createRange();

+        const range = d.createRange();

         range.selectNode(node);

-        var rect = range.getBoundingClientRect();

+        const rect = range.getBoundingClientRect();

         range.detach();

         return rect;

       };

       return node.getBoundingClientRect();

     },

 

+

     // Returns the center point of the requesting token

     _tokenPoint : function (node) {

-	    var box = this._rect(node);

+	    const box = this._rect(node);

 	    return box.left + (box.width / 2);

     },

 

@@ -278,17 +287,22 @@
     _drawAnchor : function (anchor) {

 

       // Calculate the span of the first and last token, the anchor spans

-      var firstBox = this._rect(this._tokenElements[anchor.first]);

-      var lastBox  = this._rect(this._tokenElements[anchor.last]);

+      const firstBox = this._rect(this._tokenElements[anchor.first]);

+      const lastBox  = this._rect(this._tokenElements[anchor.last]);

 	

-      var startPos = firstBox.left - this.offsetLeft;

-      var endPos   = lastBox.right - this.offsetLeft;

+      const y = this._y + (anchor.overlaps * this.anchorDiff) - this.anchorStart;

+      const l = this._c('path');

       

-      var y = this._y + (anchor.overlaps * this.anchorDiff) - this.anchorStart;

-

-      var l = this._c('path');

 	    this._arcsElement.appendChild(l);

-	    var pathStr = "M " + startPos + "," + y + " L " + endPos + "," + y;

+

+      const pathStr = "M " +

+          (firstBox.left - this.offsetLeft) +

+          "," +

+          y +

+          " L " +

+          (lastBox.right - this.offsetLeft) +

+          "," + y;

+

       l.setAttribute("d", pathStr);

       l.setAttribute("class", "anchor");

       anchor.element = l;

@@ -301,61 +315,62 @@
     // Potentially needs a height parameter for stacks

     _drawArc : function (arc) {

 

-      var startPos, endPos;

-      var startY = this._y;

-      var endY = this._y;

+      const t = this;

+      let startPos, endPos;

+      let startY = this._y;

+      let endY = this._y;

 	

       if (arc.startAnchor !== undefined) {

-        startPos = this._tokenPoint(arc.startAnchor.element);

+        startPos = t._tokenPoint(arc.startAnchor.element);

         startY = arc.startAnchor.y;

       }

       else {

-        startPos = this._tokenPoint(this._tokenElements[arc.first]);

+        startPos = t._tokenPoint(t._tokenElements[arc.first]);

       };

 

       if (arc.endAnchor !== undefined) {

-        endPos = this._tokenPoint(arc.endAnchor.element)

+        endPos = t._tokenPoint(arc.endAnchor.element)

         endY = arc.endAnchor.y;

       }

       else {

-        endPos = this._tokenPoint(this._tokenElements[arc.last]);

+        endPos = t._tokenPoint(t._tokenElements[arc.last]);

       };

 

-      startPos -= this.offsetLeft;

-      endPos -= this.offsetLeft;

+      startPos -= t.offsetLeft;

+      endPos -= t.offsetLeft;

 

 	    // Special treatment for self-references

       var overlaps = arc.overlaps;

       if (startPos == endPos) {

-        startPos -= this.overlapDiff / 3;

-        endPos   += this.overlapDiff / 3;

+        startPos -= t.overlapDiff / 3;

+        endPos   += t.overlapDiff / 3;

         overlaps += .5;

       };

 

-      var g = this._c("g");

+      const g = t._c("g");

       g.setAttribute("class", "arc");

-      var p = g.appendChild(this._c("path"));

+      const p = g.appendChild(t._c("path"));

       p.setAttribute('class', 'edge');

       

       // Attach the new arc before drawing, so computed values are available

-      this._arcsElement.appendChild(g);

+      t._arcsElement.appendChild(g);

 

       // Create arc

-      var middle = Math.abs(endPos - startPos) / 2;

+      let middle = Math.abs(endPos - startPos) / 2;

 

       // TODO:

       //   take the number of tokens into account!

-      var cHeight = this.arcDiff + (overlaps * this.overlapDiff) + (middle / 2);

+      let cHeight = t.arcDiff + (overlaps * t.overlapDiff) + (middle / 2);

 

       // Respect the maximum height

-      cHeight = cHeight < this.maxArc ? cHeight : this.maxArc;

+      cHeight = cHeight < t.maxArc ? cHeight : t.maxArc;

 

       var x = Math.min(startPos, endPos);

 

       //var controlY = (startY + endY - cHeight);

-      var controlY = (endY - cHeight);

+      let controlY = (endY - cHeight);

       

-      var arcE = "M "+ startPos + "," + startY +

+      const arcE = "M "+ startPos + "," + startY +

           " C " + startPos + "," + controlY +

           " " + endPos + "," + controlY +

           " " + endPos + "," + endY;

@@ -379,53 +394,58 @@
        * of course simplified to symmetric arcs ...

        */

       // Interpolate one side of the control polygon

-      var middleY = (((startY + controlY) / 2) + controlY) / 2;

+      let middleY = (((startY + controlY) / 2) + controlY) / 2;

 

       // Create a boxed label

-      var label = this._c("g");

+      const label = this._c("g");

       label.setAttribute("class", "label");

-      this._labelsElement.appendChild(label);

+      t._labelsElement.appendChild(label);

 

       // Set arc reference

       label.arcRef = g;

 

-      var that = this;

+      const that = t;

       label.addEventListener('mouseenter', function () {

         that.inFocus(this);

       });

 

-      var labelE = label.appendChild(this._c("text"));

+      const labelE = label.appendChild(t._c("text"));

       labelE.setAttribute("x", x + middle);

       labelE.setAttribute("y", middleY + 3);

       labelE.setAttribute("text-anchor", "middle");

-      var textNode = d.createTextNode(arc.label);

+      const textNode = d.createTextNode(arc.label);

       labelE.appendChild(textNode);

 

-      var labelBox   = labelE.getBBox();

+      const labelBox   = labelE.getBBox();

 

+      /*

       if (!labelBox)

         console.log("----");

+      */

       

-      var textWidth  = labelBox.width; // labelE.getComputedTextLength();

-      var textHeight = labelBox.height; // labelE.getComputedTextLength();

+      const textWidth  = labelBox.width; // labelE.getComputedTextLength();

+      const textHeight = labelBox.height; // labelE.getComputedTextLength();

 

       // Add box with padding to left and right

-      var labelR = label.insertBefore(this._c("rect"), labelE);

-      var boxWidth = textWidth + 2 * this.xPadding;

+      const labelR = label.insertBefore(t._c("rect"), labelE);

+      const boxWidth = textWidth + 2 * t.xPadding;

       labelR.setAttribute("x", x + middle - (boxWidth / 2));

       labelR.setAttribute("ry", 5);

-      labelR.setAttribute("y", labelBox.y - this.yPadding);

+      labelR.setAttribute("y", labelBox.y - t.yPadding);

       labelR.setAttribute("width", boxWidth);

-      labelR.setAttribute("height", textHeight + 2 * this.yPadding);

+      labelR.setAttribute("height", textHeight + 2 * t.yPadding);

     },

 

-    // Get the svg element

+

+    /**

+     * Get the svg element

+     */

     element : function () {

       if (this._element !== undefined)

         return this._element;

 

       // Create svg

-      var svg = this._c("svg");

+      const svg = this._c("svg");

 

       window.addEventListener("resize", function () {

         // TODO:

@@ -436,13 +456,14 @@
       }.bind(this));

 

       // Define marker arrows

-      var defs = svg.appendChild(this._c("defs"));

-      var marker = defs.appendChild(this._c("marker"));

+      const defs = svg.appendChild(this._c("defs"));

+      const marker = defs.appendChild(this._c("marker"));

       marker.setAttribute("refX", 9);

       marker.setAttribute("id", "arr");

       marker.setAttribute("orient", "auto-start-reverse");

       marker.setAttribute("markerUnits","userSpaceOnUse");

-      var arrow = this._c("path");

+

+      const arrow = this._c("path");

       arrow.setAttribute("transform", "scale(0.8)");

       arrow.setAttribute("d", "M 0,-5 0,5 10,0 Z");

       marker.appendChild(arrow);

@@ -451,6 +472,7 @@
       return this._element;

     },

 

+

     // Add a relation with a start, an end,

     // a direction value and an optional label text

     addRel : function (rel) {

@@ -468,7 +490,7 @@
 

     // Move label and arc in focus

     inFocus : function (element) {

-      var cif;

+      let cif;

 

       if (this._currentInFocus) {

 

@@ -488,6 +510,7 @@
       cif.arcRef.classList.add('infocus');

     },

     

+

     /*

      * All arcs need to be sorted before shown,

      * to avoid nesting.

@@ -498,7 +521,7 @@
       //   Keep in mind that the arcs may have long anchors!

       //   1. Iterate over all arcs

       //   2. Sort all multi

-      var anchors = {};

+      let anchors = {};

       

       // 1. Sort by length

       // 2. Tag all spans with the number of overlaps before

@@ -510,7 +533,7 @@
       //       reorder

 

       // Normalize start and end

-      var sortedArcs = this._arcs.map(function (v) {

+      const sortedArcs = this._arcs.map(function (v) {

 

         // Check for long anchors

         if (v.start instanceof Array) {

@@ -521,16 +544,18 @@
 

           else {

           

-            var middle = Math.ceil(Math.abs(v.start[1] - v.start[0]) / 2) + v.start[0];

+            const middle = Math.ceil(Math.abs(v.start[1] - v.start[0]) / 2) + v.start[0];

 

             // Calculate signature to avoid multiple anchors

-            var anchorSig = "#" + v.start[0] + "_" + v.start[1];

+            let anchorSig = "#" + v.start[0] + "_" + v.start[1];

+

+            // Reverse signature

             if (v.start[0] > v.start[1]) {

               anchorSig = "#" + v.start[1] + "_" + v.start[0];

             };

             

             // Check if the anchor already exist

-            var anchor = anchors[anchorSig];

+            let anchor = anchors[anchorSig];

             if (anchor === undefined) {

               anchor = {

                 "first":   v.start[0],

@@ -538,7 +563,6 @@
                 "length" : v.start[1] - v.start[0]

               };

               anchors[anchorSig] = anchor;

-              // anchors.push(v.startAnchor);

             };

 

             v.startAnchor = anchor;

@@ -556,10 +580,12 @@
 

           else {

 

-            var middle = Math.abs(v.end[0] - v.end[1]) + v.end[0];

+            const middle = Math.abs(v.end[0] - v.end[1]) + v.end[0];

 

             // Calculate signature to avoid multiple anchors

-            var anchorSig = "#" + v.end[0] + "_" + v.end[1];

+            let anchorSig = "#" + v.end[0] + "_" + v.end[1];

+

+            // Reverse signature

             if (v.end[0] > v.end[1]) {

               anchorSig = "#" + v.end[1] + "_" + v.end[0];

             };

@@ -573,27 +599,24 @@
                 "length" : v.end[1] - v.end[0]

               };

               anchors[anchorSig] = anchor;

-              // anchors.push(v.startAnchor);

             };

             

             v.endAnchor = anchor;

 

             // Add to anchors list

-            // anchors.push(v.endAnchor);

             v.end = middle;

           };

         };

 

         v.first = v.start;

-        v.last = v.end;

+        v.last  = v.end;

 

         // calculate the arch length

         if (v.start < v.end) {

           v.length = v.end - v.start;

         }

+

         else {

-          // v.first = v.end;

-          // v.last = v.start;

           v.length = v.start - v.end;

         };

 

@@ -613,19 +636,20 @@
       this._sortedAnchors = lengthSort(Object.values(anchors), true);

     },

 

+

     /**

      * Center the viewport of the canvas

      * TODO:

-     *   This is identical to tree

+     *   This is identical to treehierarchy

      */

     center : function () {

       if (this._element === undefined)

        return;

 

-      var treeDiv = this._element.parentNode;

+      const treeDiv = this._element.parentNode;

 

-      var cWidth = parseFloat(window.getComputedStyle(this._element).width);

-      var treeWidth = parseFloat(window.getComputedStyle(treeDiv).width);

+      const cWidth = parseFloat(window.getComputedStyle(this._element).width);

+      const treeWidth = parseFloat(window.getComputedStyle(treeDiv).width);

       // Reposition:

       if (cWidth > treeWidth) {

        var scrollValue = (cWidth - treeWidth) / 2;

@@ -636,37 +660,38 @@
 

     // Show the element

     show : function () {

-      var svg = this._element;

-      var height = this.maxArc;

+      const t = this;

+      const svg = this._element;

+      const height = this.maxArc;

 

       // Delete old group

       if (svg.getElementsByTagName("g")[0] !== undefined) {

-        var group = svg.getElementsByTagName("g")[0];

-        svg.removeChild(group);

-        this._tokenElements = [];

+        svg.removeChild(

+          svg.getElementsByTagName("g")[0]

+        );

+        t._tokenElements = [];

       };

 

-      var g = svg.appendChild(this._c("g"));

+      const g = svg.appendChild(t._c("g"));

 

       // Draw token list

-      var text = g.appendChild(this._c("text"));

+      const text = g.appendChild(t._c("text"));

       text.setAttribute('class', 'leaf');

       text.setAttribute("text-anchor", "start");

       text.setAttribute("y", height);

 

       // Calculate the start position

-      this._y = height - (this.anchorStart);

+      t._y = height - (t.anchorStart);

 

       // Introduce some prepending whitespace (yeah - I know ...)

-      var ws = text.appendChild(this._c("tspan"));

+      const ws = text.appendChild(t._c("tspan"));

       ws.appendChild(d.createTextNode('\u00A0'));

       ws.style.textAnchor = "start";

       

-      var lastRight = 0;

-      this._tokens.forEach(function(node_i) {

+      t._tokens.forEach(function(node_i) {

         // Append svg

         // var x = text.appendChild(this._c("text"));

-        var tspan = text.appendChild(this._c("tspan"));

+        const tspan = text.appendChild(this._c("tspan"));

         tspan.appendChild(d.createTextNode(node_i));

         tspan.setAttribute("text-anchor", "middle");

         

@@ -674,38 +699,36 @@
 

         // Add whitespace!

         tspan.setAttribute("dx", this.tokenSep);

-      }, this);

+      }, t);

 

       // Get some global position data that may change on resize

-      var globalBoundingBox = this._rect(g);

-      this.offsetLeft = globalBoundingBox.left;

+      t.offsetLeft = t._rect(g).left;

 

       // The group of arcs

-      var arcs = g.appendChild(this._c("g"));

-      this._arcsElement = arcs;

+      const arcs = g.appendChild(t._c("g"));

+      t._arcsElement = arcs;

       arcs.classList.add("arcs");

 

-      var labels = g.appendChild(this._c("g"));

-      this._labelsElement = labels;

+      const labels = g.appendChild(t._c("g"));

+      t._labelsElement = labels;

       labels.classList.add("labels");

 

       // Sort arcs if not sorted yet

-      if (this._sortedArcs === undefined)

-        this._sortArcs();

+      if (t._sortedArcs === undefined)

+        t._sortArcs();

 

       // 1. Draw all anchors

-      this._sortedAnchors.forEach(

-        i => this._drawAnchor(i)

+      t._sortedAnchors.forEach(

+        i => t._drawAnchor(i)

       );

 

       // 2. Draw all arcs

-      this._sortedArcs.forEach(

-        i => this._drawArc(i)

+      t._sortedArcs.forEach(

+        i => t._drawArc(i)

       );

 

       // Resize the svg with some reasonable margins

-      var width = this._rect(text).width;

-      svg.setAttribute("width", width + 20);

+      svg.setAttribute("width", t._rect(text).width + 20);

       svg.setAttribute("height", height + 20);

       svg.setAttribute("class", "relTree");

     }

@@ -720,15 +743,16 @@
      * e.g. if identical start or endpoints mean overlap or not.

      */

     

-    var stack = [];

+    let stack = [];

 

     // Iterate over all definitions

     list.forEach(function(current) {

 

       // Check the stack order

-      var overlaps = 0;

-      for (var j = (stack.length - 1); j >= 0; j--) {

-        var check = stack[j];

+      let overlaps = 0;

+      let check;

+      for (let j = (stack.length - 1); j >= 0; j--) {

+        check = stack[j];

 

         // (a..(b..b)..a)

         if (current.first <= check.first && current.last >= check.last) {