Made Unspecified docs editable and start general Menu class
diff --git a/public/js/runner/menu.html b/public/js/runner/menu.html
new file mode 100644
index 0000000..2b05abc
--- /dev/null
+++ b/public/js/runner/menu.html
@@ -0,0 +1,16 @@
+<!DOCTYPE html>
+<html>
+<head>
+ <meta charset="utf-8">
+ <title>Spec Runner for Menu Helper</title>
+ <link rel="shortcut icon" type="image/png" href="../lib/jasmine-2.1.1/jasmine_favicon.png">
+ <link rel="stylesheet" href="../lib/jasmine-2.1.1/jasmine.css">
+ <script src="../lib/jasmine-2.1.1/jasmine.js"></script>
+ <script src="../lib/jasmine-2.1.1/jasmine-html.js"></script>
+ <script src="../lib/jasmine-2.1.1/boot.js"></script>
+ <script src="../src/menu.js"></script>
+ <script src="../spec/menuSpec.js"></script>
+</head>
+<body>
+</body>
+</html>
diff --git a/public/js/spec/menuSpec.js b/public/js/spec/menuSpec.js
new file mode 100644
index 0000000..0477442
--- /dev/null
+++ b/public/js/spec/menuSpec.js
@@ -0,0 +1,674 @@
+KorAP.OwnMenuItem = {
+ create : function (params) {
+ return Object.create(KorAP.MenuItem).upgradeTo(KorAP.OwnMenuItem)._init(params);
+ },
+ content : function (content) {
+ if (arguments.length === 1) {
+ this._content = content;
+ };
+ return this._content;
+ },
+ _init : function (params) {
+ if (params[0] === undefined)
+ throw new Error("Missing parameters");
+
+ this._content = document.createTextNode(params[0]);
+ this._lcField = ' ' + this.content().textContent.toLowerCase();
+
+ return this;
+ }
+};
+
+KorAP.ComplexMenuItem = {
+ create : function (params) {
+ return Object.create(KorAP.MenuItem)
+ .upgradeTo(KorAP.ComplexMenuItem)
+ ._init(params);
+ },
+ content : function (content) {
+ if (arguments.length === 1) {
+ this._content = content;
+ };
+ return this._content;
+ },
+ _init : function (params) {
+ if (params[0] === undefined)
+ throw new Error("Missing parameters");
+
+ var r = document.createElement('div');
+ for (var i = 1; i <= params.length; i++) {
+ var h = document.createElement('h' + i);
+ h.appendChild(document.createTextNode(params[i-1]));
+ r.appendChild(h);
+ };
+
+ this._content = r;
+ this._lcField = ' ' + this.content().textContent.toLowerCase();
+
+ return this;
+ }
+};
+
+
+describe('KorAP.MenuItem', function () {
+ it('should be initializable', function () {
+ expect(
+ function() { KorAP.MenuItem.create([]) }
+ ).toThrow(new Error("Missing parameters"));
+
+ expect(
+ function() { KorAP.OwnMenuItem.create([]) }
+ ).toThrow(new Error("Missing parameters"));
+
+ var mi = KorAP.OwnMenuItem.create(["Baum"]);
+ expect(mi.element().firstChild.nodeValue).toEqual('Baum');
+ expect(mi.lcField()).toEqual(' baum');
+ });
+
+ it('should be activatable and deactivateable by class', function () {
+ var menuItem = KorAP.OwnMenuItem.create(['Test']);
+
+ expect(menuItem.active()).toBe(false);
+ expect(menuItem.element().getAttribute("class")).toBe(null);
+ menuItem.active(true);
+ expect(menuItem.active()).toBe(true);
+ expect(menuItem.element().getAttribute("class")).toEqual("active");
+ menuItem.active(false); // Is active
+ expect(menuItem.active()).toBe(false);
+ expect(menuItem.element().getAttribute("class")).toEqual("");
+ menuItem.active(true);
+ expect(menuItem.active()).toBe(true);
+ expect(menuItem.element().getAttribute("class")).toEqual("active");
+
+ menuItem = KorAP.OwnMenuItem.create(['Spiegel']);
+ expect(menuItem.active()).toBe(false);
+ expect(menuItem.element().getAttribute("class")).toBe(null);
+ menuItem.active(false); // Is not active
+ expect(menuItem.active()).toBe(false);
+ expect(menuItem.element().getAttribute("class")).toBe(null);
+ });
+
+ it('should be set to boundary', function () {
+ var menuItem = KorAP.OwnMenuItem.create(['CoreNLP']);
+ expect(menuItem.active()).toBe(false);
+ expect(menuItem.element().getAttribute("class")).toBe(null);
+
+ // Set active
+ menuItem.active(true);
+ expect(menuItem.active()).toBe(true);
+ expect(menuItem.noMore()).toBe(false);
+ expect(menuItem.element().getAttribute("class")).toEqual("active");
+
+ // Set no more
+ menuItem.noMore(true);
+ expect(menuItem.active()).toBe(true);
+ expect(menuItem.noMore()).toBe(true);
+ expect(menuItem.element().getAttribute("class")).toEqual("active no-more");
+
+ // No no more
+ menuItem.noMore(false);
+ expect(menuItem.active()).toBe(true);
+ expect(menuItem.noMore()).toBe(false);
+ expect(menuItem.element().getAttribute("class")).toEqual("active");
+
+ // Set no more, deactivate
+ menuItem.noMore(true);
+ menuItem.active(false);
+ expect(menuItem.active()).toBe(false);
+ expect(menuItem.noMore()).toBe(true);
+ expect(menuItem.element().getAttribute("class")).toEqual("no-more");
+
+ // Set active
+ menuItem.active(true);
+ expect(menuItem.active()).toBe(true);
+ expect(menuItem.noMore()).toBe(true);
+ expect(menuItem.element().getAttribute("class")).toEqual("no-more active");
+ });
+
+
+ it('should be highlightable', function () {
+ // Highlight in the middle
+ var menuItem = KorAP.OwnMenuItem.create(['CoreNLP']);
+ menuItem.highlight("ren");
+ expect(menuItem.element().innerHTML).toEqual("Co<mark>reN</mark>LP");
+
+ menuItem.lowlight();
+ expect(menuItem.element().innerHTML).toEqual("CoreNLP");
+
+ var plain = "<div><h1>CoreNLP</h1><h2>corenlp/</h2></div>";
+
+ // Starting highlight
+ menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
+ menuItem.highlight("cor");
+ expect(menuItem.element().innerHTML).toEqual("<div><h1><mark>Cor</mark>eNLP</h1><h2><mark>cor</mark>enlp/</h2></div>");
+
+ menuItem.lowlight();
+ expect(menuItem.element().innerHTML).toEqual(plain);
+
+ // Starting highlight - short
+ menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
+ menuItem.highlight("c");
+ expect(menuItem.element().innerHTML).toEqual("<div><h1><mark>C</mark>oreNLP</h1><h2><mark>c</mark>orenlp/</h2></div>");
+
+ menuItem.lowlight();
+ expect(menuItem.element().innerHTML).toEqual(plain);
+
+ // Highlight at the end
+ menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
+ menuItem.highlight("nlp");
+ expect(menuItem.element().innerHTML).toEqual("<div><h1>Core<mark>NLP</mark></h1><h2>core<mark>nlp</mark>/</h2></div>");
+
+ menuItem.lowlight();
+ expect(menuItem.element().innerHTML).toEqual(plain);
+
+ // Highlight at the end - short
+ menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
+ menuItem.highlight("p");
+ expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNL<mark>P</mark></h1><h2>corenl<mark>p</mark>/</h2></div>");
+
+ menuItem.lowlight();
+ expect(menuItem.element().innerHTML).toEqual(plain);
+
+ // No highlight
+ menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/']);
+ menuItem.highlight("xp");
+ expect(menuItem.element().innerHTML).toEqual(plain);
+
+ menuItem.lowlight();
+ expect(menuItem.element().innerHTML).toEqual(plain);
+
+ // Highlight in the middle - first
+ menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+ menuItem.highlight("ren");
+ expect(menuItem.element().innerHTML).toEqual("<div><h1>Co<mark>reN</mark>LP</h1><h2>co<mark>ren</mark>lp/</h2><h3>This is my Example</h3></div>");
+
+ plain = "<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3>This is my Example</h3></div>"
+
+ menuItem.lowlight();
+ expect(menuItem.element().innerHTML).toEqual(plain);
+
+ // Highlight in the middle - second
+ menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+ menuItem.highlight("ampl");
+ expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3>This is my Ex<mark>ampl</mark>e</h3></div>");
+
+ menuItem.lowlight();
+ expect(menuItem.element().innerHTML).toEqual(plain);
+
+ // Highlight in the middle - both
+ menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+ menuItem.highlight("e");
+ expect(menuItem.element().innerHTML).toEqual("<div><h1>Cor<mark>e</mark>NLP</h1><h2>cor<mark>e</mark>nlp/</h2><h3>This is my <mark>E</mark>xampl<mark>e</mark></h3></div>");
+
+ menuItem.lowlight();
+ expect(menuItem.element().innerHTML).toEqual(plain);
+
+ // Highlight in the end - second
+ menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+ menuItem.highlight("le");
+ expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3>This is my Examp<mark>le</mark></h3></div>");
+
+ menuItem.lowlight();
+ expect(menuItem.element().innerHTML).toEqual(plain);
+
+ // Highlight at the beginning - second
+ menuItem = KorAP.ComplexMenuItem.create(['CoreNLP', 'corenlp/', 'This is my Example']);
+ menuItem.highlight("this");
+ expect(menuItem.element().innerHTML).toEqual("<div><h1>CoreNLP</h1><h2>corenlp/</h2><h3><mark>This</mark> is my Example</h3></div>");
+
+ menuItem.lowlight();
+ expect(menuItem.element().innerHTML).toEqual(plain);
+ });
+
+});
+
+
+/*
+
+describe('KorAP.MenuItem', function () {
+
+});
+
+
+describe('KorAP.Menu', function () {
+
+ var list = [
+ ["Constituency", "c=", "Example 1"],
+ ["Lemma", "l="],
+ ["Morphology", "m=", "Example 2"],
+ ["Part-of-Speech", "p="],
+ ["Syntax", "syn="]
+ ];
+
+
+ it('should be initializable', function () {
+
+ var menu = KorAP.Menu.create("cnx/", list);
+ expect(menu.context).toEqual('cnx/');
+ expect(menu.element.nodeName).toEqual('UL');
+ expect(menu.element.style.opacity).toEqual("0");
+
+ KorAP.limit = 8;
+
+ // view
+ menu.show();
+
+ // First element in list
+ expect(menu.item(0).active()).toBe(true);
+ expect(menu.item(0).noMore()).toBe(true);
+
+ // Middle element in list
+ expect(menu.item(2).active()).toBe(false);
+ expect(menu.item(2).noMore()).toBe(false);
+
+ // Last element in list
+ expect(menu.item(menu.length - 1).active()).toBe(false);
+ expect(menu.item(menu.length - 1).noMore()).toBe(true);
+ });
+
+ it('should be visible', function () {
+ var menu = KorAP.Menu.create("cnx/", list);
+ expect(menu.delete()).toBe(undefined);
+
+ KorAP.limit = 3;
+
+ expect(menu.show()).toBe(undefined);
+ expect(menu.element.firstChild.innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
+ expect(menu.element.childNodes[1].getAttribute("data-action")).toEqual("l=");
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Check boundaries
+ expect(menu.element.childNodes[0].classList.contains("no-more")).toBe(true);
+ expect(menu.element.childNodes[1].classList.contains("no-more")).toBe(false);
+ expect(menu.element.childNodes[2].classList.contains("no-more")).toBe(false);
+ });
+
+
+ it('should be filterable', function () {
+ var menu = KorAP.Menu.create("cnx/", list);
+
+ KorAP.limit = 3;
+
+ expect(menu.show("o")).toBe(undefined);
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>C<em>o</em>nstituency</strong><span>Example 1</span>");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Part-<em>o</em>f-Speech</strong>");
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Check boundaries
+ expect(menu.element.childNodes[0].classList.contains("no-more")).toBe(true);
+ expect(menu.element.childNodes[1].classList.contains("no-more")).toBe(false);
+ expect(menu.element.childNodes[2].classList.contains("no-more")).toBe(true);
+
+
+ KorAP.limit = 2;
+
+ expect(menu.show("o")).toBe(undefined);
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>C<em>o</em>nstituency</strong><span>Example 1</span>");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
+ expect(menu.element.childNodes[2]).toBe(undefined);
+
+ // Check boundaries
+ expect(menu.element.childNodes[0].classList.contains("no-more")).toBe(true);
+ expect(menu.element.childNodes[1].classList.contains("no-more")).toBe(false);
+ expect(menu.element.childNodes[2]).toBe(undefined);
+ });
+
+ it('should be nextable', function () {
+ var menu = KorAP.Menu.create("cnx/", list);
+
+ KorAP.limit = 3;
+ expect(menu.show()).toBe(undefined);
+
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate next (1)
+ menu.next();
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
+ expect(menu.shownItem(1).active()).toBe(true);
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate next (2)
+ menu.next();
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(2).active()).toBe(true);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate next (3)
+ menu.next();
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Lemma</strong>");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
+ expect(menu.shownItem(2).active()).toBe(true);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate next (4)
+ menu.next();
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Syntax</strong>");
+ expect(menu.shownItem(2).active()).toBe(true);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate next (5) - ROLL
+ menu.next();
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Active next (6)
+ menu.next();
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
+ expect(menu.shownItem(1).active()).toBe(true);
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ });
+
+
+ it('should be prevable', function () {
+ var menu = KorAP.Menu.create("cnx/", list);
+
+ KorAP.limit = 3;
+ expect(menu.show()).toBe(undefined);
+
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span>Example 1</span>");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Lemma</strong>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate prev (1) - roll to bottom
+ menu.prev();
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Syntax</strong>");
+ expect(menu.shownItem(2).active()).toBe(true);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate prev (2)
+ menu.prev();
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Morphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Part-of-Speech</strong>");
+ expect(menu.shownItem(1).active()).toBe(true);
+ expect(menu.element.childNodes[2].innerHTML).toEqual("<strong>Syntax</strong>");
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate prev (3)
+ menu.prev();
+ expect(menu.shownItem(0).name).toEqual("Morphology");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(1).name).toEqual("Part-of-Speech");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2).name).toEqual("Syntax");
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate prev (4)
+ menu.prev();
+ expect(menu.shownItem(0).name).toEqual("Lemma");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(1).name).toEqual("Morphology");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2).name).toEqual("Part-of-Speech");
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate prev (5)
+ menu.prev();
+ expect(menu.shownItem(0).name).toEqual("Constituency");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(1).name).toEqual("Lemma");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2).name).toEqual("Morphology");
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate next (1)
+ menu.next();
+ expect(menu.shownItem(0).name).toEqual("Constituency");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(1).name).toEqual("Lemma");
+ expect(menu.shownItem(1).active()).toBe(true);
+ expect(menu.shownItem(2).name).toEqual("Morphology");
+ expect(menu.shownItem(2).active()).toBe(false);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+
+ // Activate prev (6)
+ menu.prev();
+
+ // Activate prev (7)
+ menu.prev();
+ expect(menu.shownItem(0).name).toEqual("Morphology");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(1).name).toEqual("Part-of-Speech");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2).name).toEqual("Syntax");
+ expect(menu.shownItem(2).active()).toBe(true);
+ expect(menu.element.childNodes[3]).toBe(undefined);
+ });
+
+ it('should be navigatable and filterable (prefix = "o")', function () {
+ var menu = KorAP.Menu.create("cnx/", list);
+
+ KorAP.limit = 2;
+
+ expect(menu.show("o")).toBe(undefined);
+
+ expect(menu.shownItem(0).name).toEqual("Constituency");
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>C<em>o</em>nstituency</strong><span>Example 1</span>");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(1).name).toEqual("Morphology");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2)).toBe(undefined);
+
+ // Next (1)
+ menu.next();
+ expect(menu.shownItem(0).name).toEqual("Constituency");
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>C<em>o</em>nstituency</strong><span>Example 1</span>");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(1).name).toEqual("Morphology");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(1).active()).toBe(true);
+ expect(menu.shownItem(2)).toBe(undefined);
+
+
+ // Next (2)
+ menu.next();
+ expect(menu.shownItem(0).name).toEqual("Morphology");
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(1).name).toEqual("Part-of-Speech");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Part-<em>o</em>f-Speech</strong>");
+ expect(menu.shownItem(1).active()).toBe(true);
+ expect(menu.shownItem(2)).toBe(undefined);
+
+ // Next (3)
+ menu.next();
+ expect(menu.shownItem(0).name).toEqual("Constituency");
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>C<em>o</em>nstituency</strong><span>Example 1</span>");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(1).name).toEqual("Morphology");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>M<em>o</em>rphology</strong><span>Example 2</span>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2)).toBe(undefined);
+ });
+
+ it('should be navigatable and filterable (prefix = "ex", "e")', function () {
+ var menu = KorAP.Menu.create("cnx/", list);
+
+ KorAP.limit = 2;
+
+ expect(menu.show("ex")).toBe(undefined);
+
+ expect(menu.shownItem(0).name).toEqual("Constituency");
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span><em>Ex</em>ample 1</span>");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(1).name).toEqual("Morphology");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>Ex</em>ample 2</span>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2)).toBe(undefined);
+
+ // Next (1)
+ menu.next();
+ expect(menu.shownItem(0).name).toEqual("Constituency");
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span><em>Ex</em>ample 1</span>");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(1).name).toEqual("Morphology");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>Ex</em>ample 2</span>");
+ expect(menu.shownItem(1).active()).toBe(true);
+ expect(menu.shownItem(2)).toBe(undefined);
+
+ // Next (2)
+ menu.next();
+ expect(menu.shownItem(0).name).toEqual("Constituency");
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constituency</strong><span><em>Ex</em>ample 1</span>");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(1).name).toEqual("Morphology");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>Ex</em>ample 2</span>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2)).toBe(undefined);
+
+ // Reset limit
+ KorAP.limit = 5;
+
+ // Change show
+ expect(menu.show("e")).toBe(undefined);
+
+ expect(menu.shownItem(0).name).toEqual("Constituency");
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constitu<em>e</em>ncy</strong><span><em>E</em>xample 1</span>");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(1).name).toEqual("Morphology");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>E</em>xample 2</span>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2)).toBe(undefined);
+
+ // Next (1)
+ menu.next();
+ expect(menu.shownItem(0).name).toEqual("Constituency");
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constitu<em>e</em>ncy</strong><span><em>E</em>xample 1</span>");
+ expect(menu.shownItem(0).active()).toBe(false);
+ expect(menu.shownItem(1).name).toEqual("Morphology");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>E</em>xample 2</span>");
+ expect(menu.shownItem(1).active()).toBe(true);
+ expect(menu.shownItem(2)).toBe(undefined);
+
+ // Next (2)
+ menu.next();
+ expect(menu.shownItem(0).name).toEqual("Constituency");
+ expect(menu.element.childNodes[0].innerHTML).toEqual("<strong>Constitu<em>e</em>ncy</strong><span><em>E</em>xample 1</span>");
+ expect(menu.shownItem(0).active()).toBe(true);
+ expect(menu.shownItem(1).name).toEqual("Morphology");
+ expect(menu.element.childNodes[1].innerHTML).toEqual("<strong>Morphology</strong><span><em>E</em>xample 2</span>");
+ expect(menu.shownItem(1).active()).toBe(false);
+ expect(menu.shownItem(2)).toBe(undefined);
+ });
+});
+
+describe('KorAP.ContextAnalyzer', function () {
+
+ it('should be initializable', function () {
+ var analyzer = KorAP.ContextAnalyzer.create(")");
+ expect(analyzer).toBe(undefined);
+
+ analyzer = KorAP.ContextAnalyzer.create(".+?");
+ expect(analyzer).not.toBe(undefined);
+
+ });
+
+ it('should check correctly', function () {
+ analyzer = KorAP.ContextAnalyzer.create(KorAP.context);
+ expect(analyzer.test("cnx/]cnx/c=")).toEqual("cnx/c=");
+ expect(analyzer.test("cnx/c=")).toEqual("cnx/c=");
+ expect(analyzer.test("cnx/c=np mate/m=mood:")).toEqual("mate/m=mood:");
+ expect(analyzer.test("impcnx/")).toEqual("impcnx/");
+ expect(analyzer.test("cnx/c=npcnx/")).toEqual("npcnx/");
+ expect(analyzer.test("mate/m=degree:pos corenlp/ne_dewac_175m_600="))
+ .toEqual("corenlp/ne_dewac_175m_600=");
+ });
+});
+
+describe('KorAP.InputField', function () {
+ var input;
+
+ beforeAll(function () {
+ input = document.createElement("input");
+ input.setAttribute("type", "text");
+ input.setAttribute("value", "abcdefghijklmno");
+ input.style.position = 'absolute';
+ input.style.top = "20px";
+ input.style.left = "30px";
+ input.focus();
+ input.selectionStart = 5;
+ });
+
+ afterAll(function () {
+ document.getElementsByTagName("body")[0].removeChild(input);
+ document.getElementsByTagName("body")[0].removeChild(
+ document.getElementById("searchMirror")
+ );
+ });
+
+ it('should be initializable', function () {
+ // Supports: context, searchField
+ var inputField = KorAP.InputField.create(input);
+ expect(inputField._element).not.toBe(undefined);
+ });
+
+ it('should have text', function () {
+ var inputField = KorAP.InputField.create(input);
+
+ expect(inputField.value).toEqual("abcdefghijklmno");
+ expect(inputField.element.selectionStart).toEqual(5);
+ expect(inputField.split()[0]).toEqual("abcde");
+ expect(inputField.split()[1]).toEqual("fghijklmno");
+
+ inputField.insert("xyz");
+ expect(inputField.split()[0]).toEqual("abcdexyz");
+ expect(inputField.split()[1]).toEqual("fghijklmno");
+
+ });
+
+ it('should be correctly positioned', function () {
+ var inputField = KorAP.InputField.create(input);
+ document.getElementsByTagName("body")[0].appendChild(input);
+ inputField.reposition();
+ expect(inputField.mirror.style.left).toEqual("30px");
+ expect(inputField.mirror.style.top.match(/^(\d+)px$/)[1]).toBeGreaterThan(20);
+ });
+});
+*/
diff --git a/public/js/spec/vcSpec.js b/public/js/spec/vcSpec.js
index da5ddaa..11ada63 100644
--- a/public/js/spec/vcSpec.js
+++ b/public/js/spec/vcSpec.js
@@ -534,7 +534,7 @@
expect(docElement.getAttribute('class')).toEqual('doc unspecified');
expect(docElement.firstChild.firstChild.data).toEqual('⋯');
expect(docElement.lastChild.lastChild.data).toEqual('⋯');
- expect(doc.toQuery()).toEqual('⋯');
+ expect(doc.toQuery()).toEqual('');
// Only removable
expect(docElement.lastChild.children.length).toEqual(0);
@@ -566,6 +566,79 @@
expect(unspec.lastChild.children.length).toEqual(1);
expect(unspec.lastChild.children[0].getAttribute('class')).toEqual('delete');
});
+
+ it('should be replaceable by a doc', function () {
+ var doc = KorAP.UnspecifiedDoc.create();
+ expect(doc.ldType()).toEqual("non");
+ // No parent, therefor not updateable
+ expect(doc.key("baum")).toBeNull();
+
+ var docGroup = KorAP.DocGroup.create();
+ docGroup.operation('or');
+ expect(docGroup.operation()).toEqual('or');
+
+ docGroup.append({
+ "@type": 'korap:doc',
+ "key": 'pubDate',
+ "match": 'match:eq',
+ "value": '2014-12-05',
+ "type": 'type:date'
+ });
+
+ expect(docGroup.toQuery()).toEqual("pubDate in 2014-12-05");
+ docGroup.append();
+
+ expect(docGroup.getOperand(0).ldType()).toEqual("doc");
+ expect(docGroup.getOperand(1).ldType()).toEqual("non");
+
+ var op = docGroup.getOperand(1).element().lastChild;
+ expect(op.getAttribute('class')).toEqual('operators');
+ expect(op.children[0].getAttribute('class')).toEqual('delete');
+ expect(op.children.length).toEqual(1);
+
+ // Replace unspecified doc
+ expect(docGroup.getOperand(1).key("name")).not.toBeNull();
+ expect(docGroup.getOperand(1).ldType()).toEqual("doc");
+ expect(docGroup.getOperand(1).key()).toEqual("name");
+ expect(docGroup.getOperand(1).value()).toEqual("");
+
+ op = docGroup.getOperand(1).element().lastChild;
+ expect(op.getAttribute('class')).toEqual('operators');
+ expect(op.children[0].getAttribute('class')).toEqual('and');
+ expect(op.children[1].getAttribute('class')).toEqual('or');
+ expect(op.children[2].getAttribute('class')).toEqual('delete');
+ expect(op.children.length).toEqual(3);
+
+ docGroup.getOperand(1).value("Pachelbel");
+ expect(docGroup.getOperand(1).value()).toEqual("Pachelbel");
+ expect(docGroup.getOperand(1).type()).toEqual("string");
+ expect(docGroup.getOperand(1).matchop()).toEqual("eq");
+
+ // Specified!
+ expect(docGroup.toQuery()).toEqual('pubDate in 2014-12-05 | name = "Pachelbel"');
+ });
+
+ it('should be replaceable on root', function () {
+ var vc = KorAP.VirtualCollection.render();
+ expect(vc.toQuery()).toEqual("");
+
+ expect(vc.root().ldType()).toEqual("non");
+
+ // No operators on root
+ op = vc.root().element().lastChild;
+ expect(op.lastChild.textContent).toEqual('⋯');
+
+ // Replace
+ expect(vc.root().key("baum")).not.toBeNull();
+ expect(vc.root().ldType()).toEqual("doc");
+
+ op = vc.root().element().lastChild;
+ expect(op.getAttribute('class')).toEqual('operators');
+ expect(op.children[0].getAttribute('class')).toEqual('and');
+ expect(op.children[1].getAttribute('class')).toEqual('or');
+ expect(op.children[2].getAttribute('class')).toEqual('delete');
+ expect(op.children.length).toEqual(3);
+ });
});
describe('KorAP.Doc element', function () {
@@ -1038,7 +1111,7 @@
// Clean everything
vc.clean();
- expect(vc.toQuery()).toEqual('⋯');
+ expect(vc.toQuery()).toEqual('');
});
});
@@ -1125,7 +1198,7 @@
// Clean with delete from root
expect(vc.root().element().lastChild.lastChild.getAttribute('class')).toEqual('delete');
_delOn(vc.root());
- expect(vc.root().toQuery()).toEqual('⋯');
+ expect(vc.root().toQuery()).toEqual('');
expect(vc.root().element().lastChild.lastChild.data).toEqual('⋯');
});
@@ -1184,7 +1257,7 @@
// Cleanwith direct element access
expect(vc.toQuery()).toEqual('pubDate in 2014-12-05 & foo = "bar"');
_delOn(vc.root());
- expect(vc.toQuery()).toEqual('⋯');
+ expect(vc.toQuery()).toEqual('');
expect(vc.root().ldType()).toEqual('non');
});
@@ -1696,14 +1769,18 @@
]
}
);
-
- expect(vc.toQuery()).toEqual('pubDate in 2014-12-05');
- expect(vc.root().key()).toEqual('pubDate');
- expect(vc.root().value()).toEqual('2014-12-05');
-
- // Wrap on root
- _orOn(vc.root());
- expect(vc.root().ldType()).toEqual('docGroup');
+ expect(vc.toQuery()).toEqual(
+ '(title = "t1" & title = "t2") | (title = "t3" & title = "t4")'
+ );
expect(vc.root().operation()).toEqual('or');
+ expect(vc.root().getOperand(0).toQuery()).toEqual('title = "t1" & title = "t2"');
+ expect(vc.root().getOperand(1).toQuery()).toEqual('title = "t3" & title = "t4"');
+
+ _andOn(vc.root());
+
+ expect(vc.root().operation()).toEqual('and');
+ expect(vc.root().getOperand(0).ldType()).toEqual('docGroup');
+ expect(vc.root().getOperand(1).ldType()).toEqual('non');
});
});
+
diff --git a/public/js/src/menu.js b/public/js/src/menu.js
new file mode 100644
index 0000000..3b79bdd
--- /dev/null
+++ b/public/js/src/menu.js
@@ -0,0 +1,202 @@
+var KorAP = KorAP || {};
+
+(function (KorAP) {
+ "use strict";
+
+ /**
+ * Item in the Dropdown menu
+ */
+ KorAP.MenuItem = {
+
+ /**
+ * Create a new MenuItem object.
+ *
+ * @constructor
+ * @this {MenuItem}
+ * @param {Array.<string>} An array object of name, action and
+ * optionally a description
+ */
+ create : function (params) {
+ return Object.create(KorAP.MenuItem)._init(params);
+ },
+
+ /**
+ * Upgrade this object to another object,
+ * while private data stays intact.
+ *
+ * @param {Object] An object with properties.
+ */
+ upgradeTo : function (props) {
+ for (var prop in props) {
+ this[prop] = props[prop];
+ };
+ return this;
+ },
+
+ content : function (content) {
+ if (arguments.length === 1)
+ this._content = document.createTextNode(content);
+ return this._content;
+ },
+
+ lcField : function () {
+ return this._lcField;
+ },
+
+ action : function (action) {
+ if (arguments.length === 1)
+ this._action = action;
+ return this._action;
+ },
+
+ /**
+ * Check or set if the item is active
+ *
+ * @param {boolean|null} State of activity
+ */
+ active : function (bool) {
+ var cl = this.element().classList;
+ if (bool === undefined)
+ return cl.contains("active");
+ else if (bool)
+ cl.add("active");
+ else
+ cl.remove("active");
+ },
+
+ /**
+ * Check or set if the item is
+ * at the boundary of the menu
+ * list
+ *
+ * @param {boolean|null} State of activity
+ */
+ noMore : function (bool) {
+ var cl = this.element().classList;
+ if (bool === undefined)
+ return cl.contains("no-more");
+ else if (bool)
+ cl.add("no-more");
+ else
+ cl.remove("no-more");
+ },
+
+ /**
+ * Get the document element of the menu item
+ */
+ element : function () {
+ // already defined
+ if (this._element !== undefined)
+ return this._element;
+
+ // Create list item
+ var li = document.createElement("li");
+
+ // Connect action
+ li["action"] = this._action;
+
+ // Append template
+ li.appendChild(this.content());
+
+ return this._element = li;
+ },
+
+ /**
+ * Highlight parts of the item
+ *
+ * @param {string} Prefix string for highlights
+ */
+ highlight : function (prefix) {
+ this._highlight(this.element().firstChild, prefix);
+ },
+
+ // Highlight a certain substring of the menu item
+ _highlight : function (elem, prefix) {
+
+ if (elem.nodeType === 3) {
+
+ var text = elem.nodeValue;
+ var textlc = text.toLowerCase();
+ var pos = textlc.indexOf(prefix);
+ if (pos >= 0) {
+
+ // First element
+ if (pos > 0) {
+ elem.parentNode.insertBefore(
+ document.createTextNode(text.substr(0, pos)),
+ elem
+ );
+ };
+
+ // Second element
+ var hl = document.createElement("mark");
+ hl.appendChild(
+ document.createTextNode(text.substr(pos, prefix.length))
+ );
+ elem.parentNode.insertBefore(hl, elem);
+
+ // Third element
+ var third = text.substr(pos + prefix.length);
+ if (third.length > 0) {
+ var thirdE = document.createTextNode(third);
+ elem.parentNode.insertBefore(
+ thirdE,
+ elem
+ );
+ this._highlight(thirdE, prefix);
+ };
+
+ var p = elem.parentNode;
+ p.removeChild(elem);
+ };
+ }
+ else {
+ var children = elem.childNodes;
+ for (var i = children.length -1; i >= 0; i--) {
+ this._highlight(children[i], prefix);
+ };
+ };
+ },
+
+
+ /**
+ * Remove highlight of the menu item
+ */
+ lowlight : function () {
+ var e = this.element();
+
+ var marks = e.getElementsByTagName("mark");
+ for (var i = marks.length - 1; i >= 0; i--) {
+ // Create text node clone
+ var x = document.createTextNode(
+ marks[i].firstChild.nodeValue
+ );
+
+ // Replace with content
+ marks[i].parentNode.replaceChild(
+ x,
+ marks[i]
+ );
+ };
+
+ // Remove consecutive textnodes
+ e.normalize();
+ },
+
+ // Initialize menu item
+ _init : function (params) {
+ if (params[0] === undefined)
+ throw new Error("Missing parameters");
+
+ this.content(params[0]);
+
+ if (params.length === 2)
+ this._action = params[1];
+
+ this._lcField = ' ' + this.content().textContent.toLowerCase();
+
+ return this;
+ },
+ };
+
+}(this.KorAP));
diff --git a/public/js/src/vc.js b/public/js/src/vc.js
index 42e51c3..b68f0aa 100644
--- a/public/js/src/vc.js
+++ b/public/js/src/vc.js
@@ -60,6 +60,7 @@
// Add new unspecified document
KorAP._add = function (obj, type) {
var ref = obj.parentNode.refTo;
+ console.log("DEBUG: " + type + " on " + ref.toQuery());
var parent = ref.parent();
if (ref.ldType() === 'docGroup') {
@@ -106,6 +107,7 @@
// Remove doc or docGroup
KorAP._delete = function () {
var ref = this.parentNode.refTo;
+console.log("DEBUG: delete " + ref.toQuery());
if (ref.parent().ldType() !== null) {
return ref.parent().delOperand(ref).update();
}
@@ -326,6 +328,34 @@
return obj;
},
+ // Set key - replace
+ key : function (v) {
+
+ // Not replaceable
+ if (this._parent === undefined)
+ return null;
+
+ // Set JSON-LD type
+ var newDoc = KorAP.Doc.create(this._parent, {
+ "@type" : "korap:doc",
+ "value" : "",
+ "key" : v
+ });
+
+ // Unspecified document on root
+ if (this._parent.ldType() === null) {
+ this._parent.root(newDoc);
+ this.destroy();
+ }
+
+ // Unspecified document in group
+ else {
+ this._parent.replaceOperand(this, newDoc);
+ };
+ this._parent.update();
+ return newDoc;
+ },
+
update : function () {
if (this._element === undefined)
@@ -361,7 +391,9 @@
this._element.setAttribute('class', 'doc unspecified');
this.update();
return this._element;
- }
+ },
+
+
};
@@ -370,7 +402,7 @@
*/
KorAP.Doc = {
_ldType : "doc",
- _obj : function () { return KorAP.Doc; },
+ _obj : function () { return KorAP.Doc },
create : function (parent, json) {
var obj = Object(KorAP.JsonLD).
@@ -572,6 +604,7 @@
if (arguments.length === 1) {
this._key = value;
this._changed = true;
+ return this;
};
return this._key;
},
@@ -580,6 +613,7 @@
if (arguments.length === 1) {
this._matchop = match.replace(/^match:/, '');
this._changed = true;
+ return this;
};
return this._matchop || "eq";
},
@@ -588,6 +622,7 @@
if (arguments.length === 1) {
this._type = type;
this._changed = true;
+ return this;
};
return this._type || "string";
},
@@ -596,6 +631,7 @@
if (arguments.length === 1) {
this._value = value;
this._changed = true;
+ return this;
};
return this._value;
},
@@ -1042,7 +1078,7 @@
},
toQuery : function () {
- return loc.EMPTY;
+ return '';
}
};