Modernize match scripts
Change-Id: Iea50c72d0ec1421d50ec4a4b7e7189f31caf934c
diff --git a/dev/js/src/match/attachement.js b/dev/js/src/match/attachement.js
index 7b6cb94..9211728 100644
--- a/dev/js/src/match/attachement.js
+++ b/dev/js/src/match/attachement.js
@@ -10,6 +10,9 @@
* @author Nils Diewald
*/
define(function () {
+
+ "use strict";
+
const uriRE = new RegExp("^data: *([^;,]*?(?: *; *[^,;]+?)*) *, *(.+)$");
const mapRE = new RegExp("^ *([^=]+?) *= *(.+?) *$");
@@ -24,6 +27,7 @@
// Parse URI scheme
_init : function (url) {
+ const t = this;
// Decode
url = decodeURIComponent(url);
@@ -31,39 +35,40 @@
if (!uriRE.exec(url))
return;
- this.payload = RegExp.$2;
+ t.payload = RegExp.$2;
let map = {};
let start = 0;
- this.base64 = false;
- this.isLink = false;
- this.contentType = "text/plain";
+ t.base64 = false;
+ t.isLink = false;
+ t.contentType = "text/plain";
// Split parameter map
RegExp.$1.split(/ *; */).map(function (item) {
+ const t = this;
// Check first parameter
if (!start++ && item.match(/^[-a-z0-9]+?\/.+$/)) {
- this.contentType = item;
+ t.contentType = item;
if (item === "application/x.korap-link")
- this.isLink = true;
+ t.isLink = true;
}
// Decode b64
else if (item.toLowerCase() == "base64") {
- this.base64 = true;
- this.payload = window.atob(this.payload);
+ t.base64 = true;
+ t.payload = window.atob(t.payload);
}
// Parse arbitrary metadata
else if (mapRE.exec(item)) {
map[RegExp.$1] = RegExp.$2;
};
- }.bind(this));
+ }.bind(t));
- this.param = map;
- return this;
+ t.param = map;
+ return t;
},
/**
@@ -72,8 +77,8 @@
*/
inline : function () {
if (this.isLink) {
- let title = this.param["title"] || this.payload;
- let a = document.createElement('a');
+ const title = this.param["title"] || this.payload;
+ const a = document.createElement('a');
a.setAttribute('href', this.payload);
a.setAttribute('rel', 'noopener noreferrer');
a.addT(title);
diff --git a/dev/js/src/match/corpusByMatch.js b/dev/js/src/match/corpusByMatch.js
index 92d219a..6d5baa5 100644
--- a/dev/js/src/match/corpusByMatch.js
+++ b/dev/js/src/match/corpusByMatch.js
@@ -1,7 +1,9 @@
define(['vc/fragment', 'util'], function (vcFragmentClass) {
+
"use strict";
return {
+
/**
* Constructor
*/
@@ -9,8 +11,10 @@
return Object.create(this)._init(meta);
},
+
// Initialize corpusByMatch
_init : function (meta) {
+ const t = this;
// Meta is an element <dl />
if (meta === undefined) {
@@ -21,10 +25,10 @@
};
// Collect the meta constraints
- this._vc = {};
+ t._vc = {};
// Remember the meta table
- this._meta = meta;
+ t._meta = meta;
// CorpusByMatch can be disabled per configuration.
// This is necessary, as the feature won't work with
@@ -33,23 +37,24 @@
// removed in future versions.
// This will also require a change in matchinfo.scss
if (KorAP.Conf && KorAP.Conf["CorpusByMatchDisabled"]) {
- this._meta.classList.add("cbm-disabled");
- return this;
+ t._meta.classList.add("cbm-disabled");
+ return t;
};
- this._meta.addEventListener(
- "click", this.clickOnMeta.bind(this), false
+ t._meta.addEventListener(
+ "click", t.clickOnMeta.bind(t), false
);
- this._fragment = vcFragmentClass.create();
+ t._fragment = vcFragmentClass.create();
- this._fragment.element().addEventListener(
- "click", this.toVcBuilder.bind(this), true
+ t._fragment.element().addEventListener(
+ "click", t.toVcBuilder.bind(t), true
);
- return this;
+ return t;
},
+
/**
* Join fragment with VC
*/
@@ -60,26 +65,24 @@
if (this._fragment.isEmpty())
return;
- let vc = KorAP.vc;
+ const vc = KorAP.vc;
if (!vc) {
console.log("Global VC not established");
return;
};
-
for (const doc of this._fragment.documents()) {
vc.addRequired(doc);
- // console.log("Add " + doc.toQuery());
};
- if (!vc.isOpen()) {
+ if (!vc.isOpen())
vc.open();
- };
// Scroll to top
window.scrollTo(0, 0);
},
+
// Event handler for meta constraint creation
clickOnMeta : function (e) {
e.stopPropagation();
@@ -88,7 +91,7 @@
};
// Get event target
- let target = e.target;
+ const target = e.target;
let key, value, type;
@@ -114,45 +117,53 @@
// Add or remove the constraint to the fragment
if (key && value) {
+ const t = this;
if (target.classList.contains("chosen")) {
target.classList.remove("chosen");
- this.remove(key, value);
+ t.remove(key, value);
}
else {
target.classList.add("chosen");
- this.add(key, value, type);
+ t.add(key, value, type);
};
// Check if the fragment is empty
// If empty - hide!
- if (!this._fragment.isEmpty()) {
- this._meta.parentNode.insertBefore(
- this._fragment.element(),
- this._meta.nextSibling
+ if (!t._fragment.isEmpty()) {
+ t._meta.parentNode.insertBefore(
+ t._fragment.element(),
+ t._meta.nextSibling
);
}
// Otherwise show!
else {
- this._meta.parentNode.removeChild(
- this._fragment.element()
+ t._meta.parentNode.removeChild(
+ t._fragment.element()
);
};
}
},
- // Add constraint
+ /**
+ * Add constraint to fragment
+ */
add : function (key, value, type) {
type = type.replace(/^type:/, '');
this._fragment.add(key, value, type);
},
- // Remove constraint
+
+ /**
+ * Remove constraint from fragment
+ */
remove : function (key, value) {
this._fragment.remove(key, value);
},
- // Stringify annotation
+ /**
+ * Stringify fragment
+ */
toQuery : function () {
return this._fragment.toQuery();
}
diff --git a/dev/js/src/match/infolayer.js b/dev/js/src/match/infolayer.js
index 82b9bd3..8d28286 100644
--- a/dev/js/src/match/infolayer.js
+++ b/dev/js/src/match/infolayer.js
@@ -3,7 +3,9 @@
* about a match's layer annotation.
*/
define(function () {
- var _AvailableRE =
+ "use strict";
+
+ const _AvailableRE =
new RegExp("^([^\/]+?)\/([^=]+?)(?:=(spans|rels|tokens))?$");
return {
@@ -20,31 +22,34 @@
return Object.create(this)._init(foundry, layer, type);
},
+
// Initialize Layer
_init : function (foundry, layer, type) {
if (foundry === undefined)
throw new Error("Missing parameters");
+
+ const t = this;
if (layer === undefined) {
if (_AvailableRE.exec(foundry)) {
- this.foundry = RegExp.$1;
- this.layer = RegExp.$2;
- this.type = RegExp.$3;
+ t.foundry = RegExp.$1;
+ t.layer = RegExp.$2;
+ t.type = RegExp.$3;
}
else {
throw new Error("Missing parameters");
};
}
else {
- this.foundry = foundry;
- this.layer = layer;
- this.type = type;
+ t.foundry = foundry;
+ t.layer = layer;
+ t.type = type;
};
- if (this.type === undefined)
- this.type = 'tokens';
+ if (t.type === undefined)
+ t.type = 'tokens';
- return this;
+ return t;
}
};
});
diff --git a/dev/js/src/match/meta.js b/dev/js/src/match/meta.js
index 3cc7512..9c4dfb1 100644
--- a/dev/js/src/match/meta.js
+++ b/dev/js/src/match/meta.js
@@ -1,5 +1,7 @@
define(['match/corpusByMatch','match/attachement','util'], function (cbmClass, attClass) {
+ "use strict";
+
// Localization values
const loc = KorAP.Locale;
loc.METADATA = loc.METADATA || 'Metadata';
@@ -13,16 +15,17 @@
return Object.create(this)._init(match, fields);
},
+
/**
* Initialize object
*/
_init : function (match, fields) {
this._match = match;
this._fields = fields;
- // this.opened = false;
return this;
},
+
/**
* Get match object
*/
@@ -30,6 +33,7 @@
return this._match;
},
+
/**
* Create match reference view.
*/
@@ -40,42 +44,40 @@
if (this._fields === null)
return;
- var metaDL = document.createElement('dl');
+ const metaDL = document.createElement('dl');
metaDL.classList.add("flex");
this._element = metaDL;
- let fields = this._fields;
+ const fields = this._fields;
// Copy original array position to object
// before sorting by key title
- let posInMetaArray = {};
+ const posInMetaArray = {};
fields.forEach((f,i) => posInMetaArray[f["key"]] = i);
-
// TODO: Meta fields should be separated
+
// Sort all meta keys alphabetically
Object.keys(posInMetaArray).sort().forEach(function(k) {
let field = fields[posInMetaArray[k]]; // This is the object
+ let metaL, dt, metaDescr, metaDD, att;
+
// Ignore internal IDs
if (k !== "UID" &&
k !== "corpusID" &&
k !== "docID" &&
k !== "textID" &&
- /*
- k !== "corpusSigle" &&
- k !== "docSigle" &&
- */
k !== "layerInfos") {
- const metaL = document.createElement('div');
+ metaL = document.createElement('div');
- const dt = metaL.addE('dt');
+ dt = metaL.addE('dt');
dt.addT(k);
dt.setAttribute("title", k);
- let metaDescr = field["value"];
+ metaDescr = field["value"];
metaDD = metaL.addE('dd');
metaDD.setAttribute('data-type', field["type"]);
@@ -83,7 +85,7 @@
metaDD.classList.add("metakeyvalues");
metaDescr.forEach(function(md) {
if (field["type"] === 'type:attachement') {
- let att = attClass.create(md);
+ att = attClass.create(md);
if (att)
metaDD.addE('div').appendChild(att.inline());
}
@@ -94,9 +96,9 @@
}
else{
if (field["type"] === 'type:attachement') {
- let att = attClass.create(field["value"]);
+ att = attClass.create(field["value"]);
if (att)
- metaDD.appendChild(att.inline());
+ metaDD.appendChild(att.inline());
}
else {
metaDD.addT(field["value"]);
diff --git a/dev/js/src/match/querycreator.js b/dev/js/src/match/querycreator.js
index 99b0bc1..bfb6f09 100644
--- a/dev/js/src/match/querycreator.js
+++ b/dev/js/src/match/querycreator.js
@@ -19,7 +19,7 @@
const loc = KorAP.Locale;
loc.NEW_QUERY = loc.NEW_QUERY || 'New Query';
- var esc = RegExp("[ \.\'\\\\\|\&]");
+ const esc = RegExp("[ \.\'\\\\\|\&]");
function _getKeyValue (keyValue) {
if (keyValue.match(esc) != null) {
@@ -27,13 +27,12 @@
};
return keyValue;
};
-
function _getAnnotation (prefix, target) {
// Complex annotation
if (target.childNodes.length > 1) {
- var orGroup = [];
+ let orGroup = [];
// Iterate over alternative annotations
target.childNodes.forEach(function (item) {
@@ -70,39 +69,41 @@
else if (!(matchTable instanceof Node))
throw new Error('Requires element');
+ const t = this;
+
// Collect the token sequence in an array
- this._query = []
+ t._query = []
// Get the match table
- this._matchTable = matchTable;
+ t._matchTable = matchTable;
// Listen on the match table
- this._matchTable.addEventListener(
- "click", this.clickOnAnno.bind(this), false
+ t._matchTable.addEventListener(
+ "click", t.clickOnAnno.bind(t), false
);
// Initialize element
- this._element = document.createElement('p');
- this._element.classList.add('query','fragment');
+ const e = t._element = document.createElement('p');
+ e.classList.add('query','fragment');
// Prepend info text
- this._element.addE('span').addT(loc.NEW_QUERY + ':');
+ e.addE('span').addT(loc.NEW_QUERY + ':');
// Append query fragment part
- this._queryFragment = this._element.addE('span');
+ t._queryFragment = e.addE('span');
// Event when the query fragment is clicked
- this._element.addEventListener('click', this.toQueryBar.bind(this), 1);
+ e.addEventListener('click', t.toQueryBar.bind(t), 1);
// Get some basic information - see tutorial.js
// TODO:
// It may be better to consultate a global object
// like KorAP.Hint, however ...
- this._ql = document.getElementById("ql-field");
- this._q = document.getElementById("q-field")
+ t._ql = document.getElementById("ql-field");
+ t._q = document.getElementById("q-field")
- this._shown = false;
- return this;
+ t._shown = false;
+ return t;
},
@@ -113,7 +114,9 @@
if (event.target !== event.currentTarget) {
// Get target event
- var target = event.target;
+ const target = event.target;
+
+ let head, foundry, layer, i, sib, annotation;
if (target.tagName == 'TD') {
@@ -125,26 +128,23 @@
// Check foundry and layer
- var head = target.parentNode.getElementsByTagName('th');
- var foundry = head[0].innerText;
- var layer = head[1].innerText;
+ head = target.parentNode.getElementsByTagName('th');
+ foundry = head[0].innerText;
+ layer = head[1].innerText;
// Check index position:
- var i = -2;
- var sib = target;
- while((sib = sib.previousSibling) != null) {
+ i = -2;
+ sib = target;
+ while ((sib = sib.previousSibling) != null) {
if (sib.nodeType === 1)
i++;
};
-
- var prefix = foundry + '/' + layer + '=';
- var annotation = '';
-
// Get annotation value from cell
- var annotation = _getAnnotation(prefix, target);
+ annotation = _getAnnotation(foundry + '/' + layer + '=', target);
if (annotation !== '') {
+
// Add term
this.toggleInToken(target, i, annotation);
};
@@ -152,6 +152,7 @@
// The annotation is part of a key-value-pair
else if (target.tagName == 'SPAN' || target.tagName == 'DIV') {
+
if (target.innerText == '')
return;
@@ -160,24 +161,21 @@
};
// Check foundry and layer
- var parentCell = target.parentNode;
- var head = parentCell.parentNode.getElementsByTagName('th');
- var foundry = head[0].innerText;
- var layer = head[1].innerText;
+ const parentCell = target.parentNode;
+ head = parentCell.parentNode.getElementsByTagName('th');
+ foundry = head[0].innerText;
+ layer = head[1].innerText;
// Check index position of parent cell
- var i = -2;
- var sib = parentCell;
+ i = -2;
+ sib = parentCell;
while((sib = sib.previousSibling) != null) {
if (sib.nodeType === 1)
i++;
};
- var prefix = foundry + '/' + layer + '=';
- var annotation = '';
-
// Get annotation value from cell
- var annotation = _getAnnotation(prefix, target);
+ annotation = _getAnnotation(foundry + '/' + layer + '=', target);
if (annotation !== '') {
@@ -197,8 +195,8 @@
return;
}
- var i = -2;
- var sib = target;
+ i = -2;
+ sib = target;
while ((sib = sib.previousSibling) != null) {
if (sib.nodeType === 1)
i++;
@@ -215,14 +213,14 @@
else {
// Check foundry and layer
- var head = target.parentNode.getElementsByTagName('th');
- var foundry = head[0].innerText;
- var layer = head[1].innerText;
- var prefix = foundry + '/' + layer + '=';
+ head = target.parentNode.getElementsByTagName('th');
+ foundry = head[0].innerText;
+ layer = head[1].innerText;
+ const prefix = foundry + '/' + layer + '=';
// Iterate over all siblings
- var i = 0;
- var sib = target;
+ i = 0;
+ sib = target;
while ((sib = sib.nextSibling) != null) {
if (sib.nodeType !== 1 || sib.tagName === 'TH')
continue;
@@ -235,7 +233,7 @@
).forEach(function(keyvaluepair){
// Get annotation value from cell
- var annotation = _getAnnotation(prefix, keyvaluepair);
+ annotation = _getAnnotation(prefix, keyvaluepair);
if (annotation !== '') {
@@ -250,7 +248,7 @@
else {
// Get annotation value from cell
- var annotation = _getAnnotation(prefix, sib);
+ annotation = _getAnnotation(prefix, sib);
if (annotation !== '') {
@@ -269,10 +267,11 @@
event.stopPropagation();
},
+
// Add term to token
_addToToken : function (index, term) {
- var token = this._query[index];
+ let token = this._query[index];
// Initialize token
if (token === undefined) {
@@ -295,18 +294,15 @@
// Remove term from token
_removeFromToken : function (index, term) {
- var token = this._query[index];
+ let token = this._query[index];
if (token === undefined)
return;
token.splice(token.indexOf(term), 1);
- if (token.length > 0)
- this._query[index] = token;
- else
- this._query[index] = undefined;
-
+ this._query[index] = token.length > 0 ? token : undefined;
+
this.show();
},
@@ -326,56 +322,62 @@
// Show annotation fragment
show : function () {
- var str = this.toString();
+ const t = this;
+ const str = t.toString();
+ const m = t._matchTable;
// Fragment is empty
if (str === '') {
// Hide element
- if (this._shown === true) {
- this._matchTable.parentNode.removeChild(this._element);
- this._shown = false;
+ if (t._shown === true) {
+ m.parentNode.removeChild(t._element);
+ t._shown = false;
}
}
// Fragment is defined
else {
- if (this._shown === false) {
+ if (t._shown === false) {
// Insert after
- this._matchTable.parentNode.insertBefore(
- this._element, this._matchTable.nextSibling
+ m.parentNode.insertBefore(
+ t._element, m.nextSibling
);
- this._shown = true;
+ t._shown = true;
};
// set value
- this._queryFragment.innerText = str;
+ t._queryFragment.innerText = str;
};
},
+
// Add term to token if not yet chosen, otherwise remove
toggleInToken : function (node, index, term) {
- if (node.classList.contains('chosen')) {
+ const cl = node.classList;
+ if (cl.contains('chosen')) {
this._removeFromToken(index, term);
- node.classList.remove('chosen');
+ cl.remove('chosen');
}
else {
this._addToToken(index, term);
- node.classList.add('chosen');
+ cl.add('chosen');
};
},
+
// Stringify annotation
toString : function () {
- var str = '';
- var distance = 0;
+ let str = '';
+ let distance = 0;
// This needs to take undefined tokens into account, therefore
// forEach() is not an option
- for (var i = 0; i < this._query.length; i++) {
- var token = this._query[i];
+ let token;
+ for (let i = 0; i < this._query.length; i++) {
+ token = this._query[i];
// Token is defined
if (token !== undefined) {
@@ -399,24 +401,26 @@
return str;
},
+
// Add query fragment to query bar
toQueryBar : function (e) {
+ const t = this;
- if (this._ql === undefined || this._q === undefined || this._ql === null) {
+ if (t._ql === undefined || t._q === undefined || t._ql === null) {
console.log('No query language object defined');
return;
};
- // Set query language field
+ // Find query language field for Poliqarp
const ql = Array.from(
- this._ql.options
+ t._ql.options
).find(e => e.value == 'poliqarp');
if (ql)
ql.selected = true;
// Insert to query bar
- this._q.value = this.toString();
+ t._q.value = t.toString();
// Scroll to top
window.scrollTo(0, 0);
diff --git a/dev/js/src/match/table.js b/dev/js/src/match/table.js
index 92d4e5a..285e615 100644
--- a/dev/js/src/match/table.js
+++ b/dev/js/src/match/table.js
@@ -6,6 +6,8 @@
'match/querycreator',
"util"
], function (matchQueryCreator) {
+ "use strict";
+
/*
* TODO:
* Create base object for all matchinfo classes!
@@ -27,31 +29,35 @@
// Initialize table based on snippet
_init : function (snippet) {
+
// Create html for traversal
- var html = d.createElement("div");
+ const html = d.createElement("div");
+ const t = this;
html.innerHTML = snippet;
- this._pos = 0;
- this._token = [];
- this._mark = [];
- this._markE = undefined;
- this._cutted = [];
- this._info = [];
- this._foundry = {};
- this._layer = {};
+ t._pos = 0;
+ t._token = [];
+ t._mark = [];
+ t._markE = undefined;
+ t._cutted = [];
+ t._info = [];
+ t._foundry = {};
+ t._layer = {};
// Parse the snippet
- this._parse(html.childNodes, false);
+ t._parse(html.childNodes, false);
html.innerHTML = '';
- return this;
+ return t;
},
+
// TODO: Destroy match!
destroy : function () {
this._matchCreator = undefined;
},
+
/**
* Length of the table (columns),
* aka the number of tokens
@@ -74,6 +80,7 @@
});
},
+
/**
* Get the token in the snippet
* At a given position.
@@ -86,6 +93,7 @@
return this._token[pos];
},
+
/**
* Get the annotation of a token
* in the snippet based on the position,
@@ -105,18 +113,19 @@
// Get all children
children.forEach(function(c) {
+ const t = this;
// Create object on position unless it exists
- if (this._info[this._pos] === undefined) {
- this._info[this._pos] = {};
+ if (t._info[t._pos] === undefined) {
+ t._info[t._pos] = {};
};
// Store at position in foundry/layer as array
- var found = this._info[this._pos];
+ const found = t._info[t._pos];
// Element with title
if (c.nodeType === 1) {
- var newMark = mark;
+ let newMark = mark;
if (c.tagName === 'MARK') {
newMark = true;
@@ -126,7 +135,7 @@
_TermRE.exec(c.getAttribute("title"))) {
// Fill position with info
- var foundry, layer, value;
+ let foundry, layer, value;
if (RegExp.$2) {
foundry = RegExp.$1;
layer = RegExp.$2;
@@ -150,33 +159,33 @@
}
// Set foundry
- if (this._foundry[foundry] === undefined)
- this._foundry[foundry] = {};
- this._foundry[foundry][layer] = 1;
+ if (t._foundry[foundry] === undefined)
+ t._foundry[foundry] = {};
+ t._foundry[foundry][layer] = 1;
// Set layer
- if (this._layer[layer] === undefined)
- this._layer[layer] = {};
- this._layer[layer][foundry] = 1;
+ if (t._layer[layer] === undefined)
+ t._layer[layer] = {};
+ t._layer[layer][foundry] = 1;
}
// The current position marks a cut
else if (c.hasAttribute("class") && c.getAttribute("class") == "cutted") {
- this._cutted.push(this._pos);
- this._token[this._pos++] = "";
+ t._cutted.push(t._pos);
+ t._token[t._pos++] = "";
}
// depth search
if (c.hasChildNodes())
- this._parse(c.childNodes, newMark);
+ t._parse(c.childNodes, newMark);
}
// Leaf node
// store string on position and go to next string
else if (c.nodeType === 3) {
if (c.nodeValue.match(/[a-z0-9\u25ae]/iu)) {
- this._mark[this._pos] = mark ? true : false;
- this._token[this._pos++] = c.nodeValue;
+ t._mark[t._pos] = mark ? true : false;
+ t._token[t._pos++] = c.nodeValue;
};
};
}, this);
@@ -193,20 +202,20 @@
return this._element;
// First the legend table
- var wrap = d.createElement('div');
+ const wrap = d.createElement('div');
- var table = wrap.addE('table');
+ const table = wrap.addE('table');
this._element = wrap;
// Single row in head
- var tr = table.addE('thead').addE('tr');
+ let tr = table.addE('thead').addE('tr');
- var ah = KorAP.annotationHelper || { "getDesc" : function () {}};
-
+ const ah = KorAP.annotationHelper || { "getDesc" : function () {}};
+
// Add cell to row
- var addCell = function (type, key, value) {
- var c = this.addE(type);
+ const addCell = function (type, key, value) {
+ const c = this.addE(type);
if (value === undefined)
return c;
@@ -236,7 +245,7 @@
c.addT(value);
// Add tooltip
- var anno = ah.getDesc(key, value);
+ const anno = ah.getDesc(key, value);
if (anno)
c.setAttribute("title", anno);
};
@@ -252,8 +261,8 @@
// Add tokens
Object.keys(this._token).forEach(function(i) {
- let surface = this.getToken(i);
- var c = tr.addCell('th', undefined, surface);
+ const surface = this.getToken(i);
+ const c = tr.addCell('th', undefined, surface);
if (this._mark[i]) {
c.classList.add('mark');
if (this._markE === undefined) {
@@ -270,13 +279,11 @@
}
}, this);
- var tbody = table.addE('tbody');
-
- var foundryList = Object.keys(this._foundry).sort();
+ const tbody = table.addE('tbody');
let layerList, key, v, value, cell;
- foundryList.forEach(function(foundry) {
+ Object.keys(this._foundry).sort().forEach(function(foundry) {
let layerList =
Object.keys(this._foundry[foundry]).sort();
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) {
diff --git a/dev/js/src/match/treehierarchy.js b/dev/js/src/match/treehierarchy.js
index 9fc2480..e54ef29 100644
--- a/dev/js/src/match/treehierarchy.js
+++ b/dev/js/src/match/treehierarchy.js
@@ -16,10 +16,10 @@
// Create path for node connections
function _line (src, target) {
- var x1 = src.x,
- y1 = src.y,
- x2 = target.x,
- y2 = target.y - target.height / 2;
+ const x1 = src.x,
+ y1 = src.y,
+ x2 = target.x,
+ y2 = target.y - target.height / 2;
// c 0,0 -10,0
return 'M ' + x1 + ',' + y1 + ' ' +
@@ -36,7 +36,7 @@
*/
create : function (snippet) {
return Object.create(this).
- _init(snippet);
+ _init(snippet);
},
@@ -45,16 +45,18 @@
this._next = new Number(0);
// Create html for traversal
- var html = d.createElement("div");
+ let html = d.createElement("div");
html.innerHTML = snippet;
- var g = new dagre.graphlib.Graph({
- "directed" : true
+
+ const g = new dagre.graphlib.Graph({
+ "directed" : true
});
+
g.setGraph({
- "nodesep" : 35,
- "ranksep" : 15,
- "marginx" : 40,
- "marginy" : 10
+ "nodesep" : 35,
+ "ranksep" : 15,
+ "marginx" : 40,
+ "marginy" : 10
});
g.setDefaultEdgeLabel({});
@@ -62,8 +64,8 @@
// This is a new root
this._addNode(
- this._next++,
- { "class" : "root" }
+ this._next++,
+ { "class" : "root" }
);
// Parse nodes from root
@@ -71,7 +73,7 @@
// Root node has only one child - remove
if (g.outEdges(0).length === 1)
- g.removeNode(0);
+ g.removeNode(0);
html = undefined;
return this;
@@ -82,6 +84,7 @@
return d.createElementNS(svgNS, tag);
},
+
/**
* The number of nodes in the tree.
*/
@@ -89,6 +92,7 @@
return this._next;
},
+
// Add new node to graph
_addNode : function (id, obj) {
obj["width"] = WIDTH;
@@ -97,81 +101,84 @@
return obj;
},
+
// Add new edge to graph
_addEdge : function (src, target) {
this._graph.setEdge(src, target);
},
+
// Remove foundry and layer for labels
_clean : function (title) {
return title.replace(_TermRE, "$3");
},
+
// Parse the snippet
_parse : function (parent, children, mark) {
children.forEach(function(c) {
- // Element node
- if (c.nodeType == 1) {
+ // Element node
+ if (c.nodeType == 1) {
- // Get title from html
- if (c.getAttribute("title")) {
- var title = this._clean(c.getAttribute("title"));
+ // Get title from html
+ if (c.getAttribute("title")) {
- // Add child node
- var id = this._next++;
+ // Add child node
+ const id = this._next++;
- var obj = this._addNode(id, {
- "class" : "middle",
- "label" : title
- });
+ const obj = this._addNode(id, {
+ "class" : "middle",
+ "label" : this._clean(c.getAttribute("title"))
+ });
if (mark !== undefined) {
obj.class += ' mark';
};
- this._addEdge(parent, id);
+ this._addEdge(parent, id);
- // Check for next level
- if (c.hasChildNodes())
- this._parse(id, c.childNodes, mark);
- }
+ // Check for next level
+ if (c.hasChildNodes())
+ this._parse(id, c.childNodes, mark);
+ }
- // Step further
- else if (c.hasChildNodes()) {
+ // Step further
+ else if (c.hasChildNodes()) {
- if (c.tagName === 'MARK') {
- this._parse(parent, c.childNodes, true);
- }
- else {
- this._parse(parent, c.childNodes, mark);
- };
+ this._parse(
+ parent,
+ c.childNodes,
+ c.tagName === 'MARK' ? true : mark
+ );
};
- }
+ }
- // Text node
- else if (c.nodeType == 3)
+ // Text node
+ else if (c.nodeType == 3)
- if (c.nodeValue.match(/[-a-z0-9]/i)) {
+ if (c.nodeValue.match(/[-a-z0-9]/i)) {
+
+ // Add child node
+ const id = this._next++;
+ this._addNode(id, {
+ "class" : "leaf",
+ "label" : c.nodeValue
+ });
- // Add child node
- var id = this._next++;
- this._addNode(id, {
- "class" : "leaf",
- "label" : c.nodeValue
- });
-
- this._addEdge(parent, id);
- };
+ this._addEdge(parent, id);
+ };
}, this);
return this;
},
+
// Dummy method to be compatible with relTree
show : function () {
return;
},
+
/**
* Center the viewport of the canvas
* TODO:
@@ -179,16 +186,15 @@
*/
center : function () {
if (this._element === undefined)
- return;
+ return;
- var treeDiv = this._element.parentNode;
+ const treeDiv = this._element.parentNode;
+ const cWidth = parseFloat(window.getComputedStyle(this._element).width);
+ const treeWidth = parseFloat(window.getComputedStyle(treeDiv).width);
- var cWidth = parseFloat(window.getComputedStyle(this._element).width);
- var treeWidth = parseFloat(window.getComputedStyle(treeDiv).width);
// Reposition:
if (cWidth > treeWidth) {
- var scrollValue = (cWidth - treeWidth) / 2;
- treeDiv.scrollLeft = scrollValue;
+ treeDiv.scrollLeft = (cWidth - treeWidth) / 2;
};
},
@@ -199,11 +205,12 @@
toBase64 : function () {
// First clone element
- var svgWrapper = d.createElement('div')
+ const svgWrapper = d.createElement('div')
svgWrapper.innerHTML = this.element().outerHTML;
- var svg = svgWrapper.firstChild;
- var style = this._c('style');
+ const svg = svgWrapper.firstChild;
+ const style = this._c('style');
+
svg.getElementsByTagName('defs')[0].appendChild(style);
style.innerHTML =
@@ -217,45 +224,50 @@
return btoa(unescape(encodeURIComponent(svg.outerHTML)).replace(/ /g, ' '));
},
+
/**
* Get the dom element of the tree view.
*/
element : function () {
+
if (this._element !== undefined)
- return this._element;
+ return this._element;
- var g = this._graph;
-
+ const g = this._graph;
dagre.layout(g);
- var canvas = this._c('svg');
+ const canvas = this._c('svg');
this._element = canvas;
- var that = this;
canvas.appendChild(this._c('defs'));
-
- var height = g.graph().height;
// Create edges
+ const that = this;
+
+ let src, target, p;
+
g.edges().forEach(
function (e) {
- var src = g.node(e.v);
- var target = g.node(e.w);
- var p = that._c('path');
+ src = g.node(e.v);
+ target = g.node(e.w);
+ p = that._c('path');
p.setAttributeNS(null, "d", _line(src, target));
p.classList.add('edge');
canvas.appendChild(p);
- });
+ }
+ );
+
+ let height = g.graph().height;
// Create nodes
g.nodes().forEach(
function (v) {
v = g.node(v);
- var group = that._c('g');
+ const group = that._c('g');
group.setAttribute('class', v.class);
// Add node box
- var rect = group.appendChild(that._c('rect'));
+ const rect = group.appendChild(that._c('rect'));
rect.setAttribute('x', v.x - v.width / 2);
rect.setAttribute('y', v.y - v.height / 2);
rect.setAttribute('rx', 5);
@@ -271,18 +283,18 @@
// Add label
if (v.label !== undefined) {
- var text = group.appendChild(that._c('text'));
- var y = v.y - v.height / 2;
+ const text = group.appendChild(that._c('text'));
+ let y = v.y - v.height / 2;
text.setAttribute('y', y);
text.setAttribute(
'transform',
'translate(' + v.width/2 + ',' + ((v.height / 2) + 5) + ')'
);
- var vLabel = v.label.replace(/ /g, " ")
- .replace(/&/g, '&')
- .replace(/</g, '<')
- .replace(/>/g, '>');
+ const vLabel = v.label.replace(/ /g, " ")
+ .replace(/&/g, '&')
+ .replace(/</g, '<')
+ .replace(/>/g, '>');
if (v.class === "leaf") {
text.setAttribute('title', vLabel);
@@ -295,10 +307,12 @@
tspan = that._c('tspan');
tspan.appendChild(d.createTextNode(p));
+
if (n !== 0)
tspan.setAttribute('dy', LINEHEIGHT + 'pt');
else
n = 1;
+
tspan.setAttribute('x', v.x - v.width / 2);
y += LINEHEIGHT;
text.appendChild(tspan);
@@ -311,7 +325,7 @@
height = y;
}
else {
- var tspan = that._c('tspan');
+ const tspan = that._c('tspan');
tspan.appendChild(d.createTextNode(vLabel));
tspan.setAttribute('x', v.x - v.width / 2);
text.appendChild(tspan);
@@ -325,9 +339,9 @@
canvas.setAttribute('height', height);
return this._element;
},
-
+
downloadLink : function () {
- var a = d.createElement('a');
+ const a = d.createElement('a');
a.setAttribute('href-lang', 'image/svg+xml');
a.setAttribute('href', 'data:image/svg+xml;base64,' + this.toBase64());
a.setAttribute('download', 'tree.svg');
diff --git a/dev/js/src/match/treeitem.js b/dev/js/src/match/treeitem.js
index d99165a..422f3d7 100644
--- a/dev/js/src/match/treeitem.js
+++ b/dev/js/src/match/treeitem.js
@@ -27,6 +27,7 @@
return this._content;
},
+
/**
* The foundry attribute of the menu item.
*/
@@ -34,6 +35,7 @@
return this._foundry;
},
+
/**
* The layer attribute of the menu item.
*/
@@ -41,6 +43,7 @@
return this._layer;
},
+
/**
* The type attribute of the menu item.
* Is either "spans" or "rels".
@@ -49,30 +52,35 @@
return this._type;
},
+
/**
* Override click action of the menu item.
*/
onclick : function (e) {
- var menu = this.menu();
+ const menu = this.menu();
menu.hide();
e.halt();
+
if (menu.panel() !== undefined) {
menu.panel().addTree(this._foundry, this._layer, this._type);
};
},
+
// Initialize tree menu item.
_init : function (params) {
if (params[0] === undefined)
throw new Error("Missing parameters");
- this._name = params[0];
- this._foundry = params[1];
- this._layer = params[2];
- this._type = params[3];
- this._content = document.createTextNode(this._name);
- this._lcField = ' ' + this.content().textContent.toLowerCase();
- return this;
+ const t = this;
+
+ t._name = params[0];
+ t._foundry = params[1];
+ t._layer = params[2];
+ t._type = params[3];
+ t._content = document.createTextNode(t._name);
+ t._lcField = ' ' + t.content().textContent.toLowerCase();
+ return t;
}
};
});