Release preparation, documentation, fixing vc bugs
diff --git a/dev/demo/menudemo.js b/dev/demo/menudemo.js
index e089e89..055963b 100644
--- a/dev/demo/menudemo.js
+++ b/dev/demo/menudemo.js
@@ -3,6 +3,7 @@
});
require(['menu','menu/item', 'menu/prefix'], function (menuClass, itemClass, prefixClass) {
+
var OwnMenuItemClass = {
create : function (params) {
return Object.create(itemClass).upgradeTo(this)._init(params);
diff --git a/dev/js/spec/hintSpec.js b/dev/js/spec/hintSpec.js
index 20935e1..ac50f0f 100644
--- a/dev/js/spec/hintSpec.js
+++ b/dev/js/spec/hintSpec.js
@@ -74,13 +74,13 @@
expect(input.selectionStart).toEqual(5);
expect(inputField.element().selectionStart).toEqual(5);
- expect(inputField.split()[0]).toEqual("abcde");
- expect(inputField.split()[1]).toEqual("fghijklmno");
+ expect(inputField._split()[0]).toEqual("abcde");
+ expect(inputField._split()[1]).toEqual("fghijklmno");
inputField.insert("xyz");
expect(inputField.value()).toEqual('abcdexyzfghijklmno');
- expect(inputField.split()[0]).toEqual("abcdexyz");
- expect(inputField.split()[1]).toEqual("fghijklmno");
+ expect(inputField._split()[0]).toEqual("abcdexyz");
+ expect(inputField._split()[1]).toEqual("fghijklmno");
});
it('should be correctly positioned', function () {
@@ -98,7 +98,7 @@
var inputField = inputClass.create(input);
expect(inputField.value()).toEqual("abcdefghijklmno");
expect(inputField.element().selectionStart).toEqual(5);
- expect(inputField.split()[0]).toEqual("abcde");
+ expect(inputField._split()[0]).toEqual("abcde");
expect(inputField.context()).toEqual("abcde");
});
@@ -385,7 +385,6 @@
it('should be initializable', function () {
var menu = menuClass.create(null, "cnx/", list);
- expect(menu.context()).toEqual('cnx/');
expect(menu.element().nodeName).toEqual('UL');
expect(menu.element().style.opacity).toEqual("0");
diff --git a/dev/js/spec/menuSpec.js b/dev/js/spec/menuSpec.js
index 7436e4d..999ec2b 100644
--- a/dev/js/spec/menuSpec.js
+++ b/dev/js/spec/menuSpec.js
@@ -1,7 +1,8 @@
define(['menu'], function () {
var menuItemClass = require('menu/item');
- var menuClass = require('menu');
+ var prefixClass = require('menu/prefix');
+ var menuClass = require('menu');
// The OwnMenu item
KorAP.OwnMenuItem = {
@@ -800,13 +801,13 @@
expect(menu.shownItem(0).name()).toEqual("Autor");
expect(menu.element().childNodes[1].innerHTML).toEqual("<strong><mark>Au</mark>tor</strong>");
- menu._prefix.backspace();
+ menu._prefix.chop();
expect(menu.show()).toBe(true);
expect(menu.prefix()).toEqual("a");
expect(menu.shownItem(0).name()).toEqual("Autor");
expect(menu.element().childNodes[1].innerHTML).toEqual("<strong><mark>A</mark>utor</strong>");
- menu._prefix.backspace();
+ menu._prefix.chop();
expect(menu.show()).toBe(true);
expect(menu.prefix()).toEqual("");
expect(menu.shownItem(0).name()).toEqual("Titel");
@@ -821,7 +822,7 @@
expect(menu.shownItem(3)).toBe(undefined);
// Forward
- menu._prefix.backspace();
+ menu._prefix.chop();
expect(menu.show()).toBe(true);
expect(menu.prefix()).toEqual("");
expect(menu.shownItem(0).name()).toEqual("Titel");
@@ -1054,7 +1055,78 @@
xit('should be page downable');
xit('should be page upable');
- xit('should scroll to a chosen value')
- xit('should highlight a chosen value')
+ xit('should scroll to a chosen value');
+ xit('should highlight a chosen value');
+ });
+
+ describe('KorAP.Prefix', function () {
+ it('should be initializable', function () {
+ var p = prefixClass.create();
+ expect(p.element().classList.contains('pref')).toBeTruthy();
+ expect(p.isSet()).not.toBeTruthy();
+
+/*
+ expect(mi.lcField()).toEqual(' baum');
+*/
+
+ });
+
+ it('should be modifiable', function () {
+ var p = prefixClass.create();
+ expect(p.value()).toEqual('');
+ expect(p.element().firstChild).toBeNull();
+
+ // Set string
+ expect(p.value('Test')).toEqual('Test');
+ expect(p.value()).toEqual('Test');
+ expect(p.element().firstChild.nodeValue).toEqual('Test');
+
+ // Add string
+ expect(p.add('ified')).toEqual('Testified');
+ expect(p.value()).toEqual('Testified');
+ expect(p.element().firstChild.nodeValue).toEqual('Testified');
+
+ // Clear string
+ p.clear();
+ expect(p.value()).toEqual('');
+ expect(p.element().firstChild).toBeNull();
+
+ // Set string
+ expect(p.value('Test')).toEqual('Test');
+ expect(p.value()).toEqual('Test');
+ expect(p.element().firstChild.nodeValue).toEqual('Test');
+
+ expect(p.chop()).toEqual('Tes');
+ expect(p.value()).toEqual('Tes');
+ expect(p.element().firstChild.nodeValue).toEqual('Tes');
+
+ expect(p.chop()).toEqual('Te');
+ expect(p.value()).toEqual('Te');
+ expect(p.element().firstChild.nodeValue).toEqual('Te');
+
+ expect(p.chop()).toEqual('T');
+ expect(p.value()).toEqual('T');
+ expect(p.element().firstChild.nodeValue).toEqual('T');
+
+ expect(p.chop()).toEqual('');
+ expect(p.value()).toEqual('');
+ expect(p.element().firstChild).toBeNull();
+ });
+
+ it('should be activatable', function () {
+ var p = prefixClass.create();
+ expect(p.value()).toEqual('');
+ expect(p.element().firstChild).toBeNull();
+
+ expect(p.value('Test')).toEqual('Test');
+ expect(p.element().firstChild.nodeValue).toEqual('Test');
+
+ expect(p.active()).not.toBeTruthy();
+ expect(p.element().classList.contains('active')).not.toBeTruthy();
+
+ p.active(true);
+ expect(p.active()).toBeTruthy();
+ expect(p.element().classList.contains('active')).toBeTruthy();
+ });
});
});
diff --git a/dev/js/src/app/de.js b/dev/js/src/app/de.js
new file mode 100644
index 0000000..fc576f2
--- /dev/null
+++ b/dev/js/src/app/de.js
@@ -0,0 +1,26 @@
+define(['init'], function () {
+ var loc = KorAP.Locale;
+ loc.OR = 'oder';
+ loc.AND = 'und';
+ // EMPTY, DELETE
+
+ // Virtual collection:
+ loc.VC_subTitle = 'Untertitel';
+ loc.VC_title = 'Titel';
+ loc.VC_pubDate = 'Veröffentlichungsdatum';
+ loc.VC_pubPlace = 'Veröffentlichungsort';
+
+ // Date picker:
+ loc.WDAY = ['Mo', 'Di', 'Mi', 'Do', 'Fr', 'Sa', 'So'];
+ loc.MONTH = [
+ 'Januar', 'Februar', 'März', 'April',
+ 'Mai', 'Juni', 'Juli', 'August',
+ 'September', 'Oktober', 'November',
+ 'Dezember'
+ ];
+
+ // Match view
+ loc.ADDTREE = 'Baumansicht hinzufügen';
+ loc.SHOWINFO = 'Informationen';
+ loc.CLOSE = 'Schließen';
+});
diff --git a/dev/js/src/app/en.js b/dev/js/src/app/en.js
new file mode 100644
index 0000000..c7a4e5c
--- /dev/null
+++ b/dev/js/src/app/en.js
@@ -0,0 +1 @@
+require(['init']);
diff --git a/dev/js/src/datepicker.js b/dev/js/src/datepicker.js
index 90b0572..6d3086d 100644
--- a/dev/js/src/datepicker.js
+++ b/dev/js/src/datepicker.js
@@ -1,16 +1,19 @@
/**
- * Date picker for the
+ * Simple Date picker for the
* Virtual Collection builder.
+ *
+ * @author Nils Diewald
*/
define(['util'], function () {
"use strict";
+ /*
+ * Localizations
+ */
var loc = KorAP.Locale;
-
loc.WDAY = loc.WDAY || [
'Mo', 'Tu', 'We', 'Th', 'Fr', 'Sa', 'Su'
];
-
loc.MONTH = loc.MONTH || [
'January', 'February', 'March', 'April',
'May', 'June', 'July', 'August',
@@ -20,27 +23,24 @@
var d = document;
+ // The datepicker class
return {
+
+ /**
+ * Create a new datepicker view.
+ */
create : function () {
return Object.create(this)._init();
},
+ // Init datepicker
_init : function () {
return this;
},
- set : function (year, month, day) {
- this.select(year, month, day);
- if (this._click !== undefined)
- this._click(this._selected);
- else
- console.dir(this._selected);
- },
-
- onclick : function (cb) {
- this._click = cb;
- },
-
+ /**
+ * Get or select a specific date.
+ */
select : function (year, month, day) {
if (arguments.length >= 1) {
this._selected = {'year' : year};
@@ -54,21 +54,73 @@
return this._selected;
},
+
+ /**
+ * Select a specific date and
+ * init the accompanied action.
+ */
+ set : function (year, month, day) {
+ this.select(year, month, day);
+ if (this._click !== undefined)
+ this._click(this._selected);
+ else
+ console.dir(this._selected);
+ },
+
+
+ /**
+ * Set the action for clicking as a callback.
+ * The callback will retrieve a an object with
+ * an optional year attribute,
+ * an optional month attribute,
+ * and an optional day attribute
+ */
+ onclick : function (cb) {
+ this._click = cb;
+ },
+
+ /**
+ * Show the datepicker.
+ * Will either show the selected year/month
+ * or the current date.
+ * Will return the element for appending to the dom.
+ */
show : function (year, month) {
- this._element = d.createElement('div');
- this._element.classList.add('datepicker');
- this._showYear = year ? year : (this._selected['year'] ? this._selected['year'] : 2012);
- this._showMonth = month ? month : (this._selected['month'] ? this._selected['month'] : 2);
+ var e = this._element = d.createElement('div');
+ e.setAttribute('tabindex', 0);
+ e.style.outline = 0;
+ e.classList.add('datepicker');
+
+ var today = new Date();
+
+ // Show year
+ this._showYear = year ? year :
+ (this._selected['year'] ? this._selected['year'] :
+ today.getYear());
+
+ // Show month
+ this._showMonth = month ? month :
+ (this._selected['month'] ? this._selected['month'] :
+ (today.getMonth() + 1));
+
+ // Append all helpers
this._element.appendChild(this._monthHelper());
this._element.appendChild(this._yearHelper());
this._element.appendChild(this._dayHelper());
return this._element;
},
+ /**
+ * Get the HTML element associated with the datepicker.
+ */
element : function () {
return this._element;
},
+
+ /**
+ * Increment the year.
+ */
incrYear : function () {
this._showYear++;
this._updateYear();
@@ -77,6 +129,9 @@
return;
},
+ /**
+ * Decrement the year.
+ */
decrYear : function () {
this._showYear--;
this._updateYear();
@@ -85,6 +140,9 @@
return;
},
+ /**
+ * Increment the month.
+ */
incrMonth : function () {
this._showMonth++;
if (this._showMonth > 12) {
@@ -97,6 +155,9 @@
};
},
+ /**
+ * Decrement the month.
+ */
decrMonth : function () {
this._showMonth--;
if (this._showMonth < 1) {
@@ -109,6 +170,8 @@
};
},
+
+ // Create the year helper element.
_yearHelper : function () {
var year = d.createElement('div');
year.classList.add('year');
@@ -123,6 +186,7 @@
this._yElement.onclick = function () {
this.set(this._showYear);
}.bind(this);
+ this._selectYear();
// Increment year
year.appendChild(d.createElement('span'))
@@ -131,10 +195,23 @@
return year;
},
+ // Update the year helper view.
_updateYear : function () {
this._yElement.firstChild.data = this._showYear;
+ this._selectYear();
},
+
+ // Check if the viewed year is current
+ _selectYear : function () {
+ if (this._showYear === this.select()['year'])
+ this._yElement.classList.add('selected');
+ else
+ this._yElement.classList.remove('selected');
+ },
+
+
+ // Create the month helper element.
_monthHelper : function () {
var month = d.createElement('div');
month.classList.add('month');
@@ -150,6 +227,8 @@
this._mElement.onclick = function () {
this.set(this._showYear, this._showMonth);
}.bind(this);
+
+ this._selectMonth();
// Increment month
month.appendChild(d.createElement('span'))
@@ -158,13 +237,28 @@
return month;
},
+ // Update the month helper view.
_updateMonth : function () {
this._mElement.firstChild.data = loc.MONTH[this._showMonth-1];
+ this._selectMonth();
},
+
+ // Check if the viewed month is current
+ _selectMonth : function () {
+ if (this._showYear === this.select()['year'] &&
+ this._showMonth === this.select()['month'])
+ this._mElement.classList.add('selected');
+ else
+ this._mElement.classList.remove('selected');
+ },
+
+
+ // Create the day (calendar) helper element.
_dayHelper : function () {
var table = d.createElement('table');
+ // Localized day view
var tr = table.appendChild(d.createElement('thead'))
.appendChild(d.createElement('tr'));
for (var i = 0; i < 7; i++) {
@@ -179,10 +273,29 @@
},
_dayBody : function () {
- var showDate = new Date(this._showYear, this._showMonth - 1, 1, 0, 0, 0, 0);
- var date = new Date(this._showYear, this._showMonth - 1, 1, 0, 0, 0, 0);
- var today = new Date();
+ var showDate = new Date(
+ this._showYear,
+ this._showMonth - 1,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0
+ );
+ var date = new Date(
+ this._showYear,
+ this._showMonth - 1,
+ 1,
+ 0,
+ 0,
+ 0,
+ 0
+ );
+ var today = new Date();
var that = this;
+
+ // What happens, in case someone clicks
+ // on a date
var click = function () {
that.set(
that._showYear,
@@ -245,6 +358,7 @@
return tb;
},
+ // Update the calendar view
_updateDay : function () {
var newBody = this._dayBody();
this._dBElement.parentNode.replaceChild(
diff --git a/dev/js/src/hint/contextanalyzer.js b/dev/js/src/hint/contextanalyzer.js
index bdbf885..fc01662 100644
--- a/dev/js/src/hint/contextanalyzer.js
+++ b/dev/js/src/hint/contextanalyzer.js
@@ -2,9 +2,15 @@
* Regex object for checking the context of the hint
*/
define({
+
+ /**
+ * Create analyzer based on regular expression.
+ */
create : function (regex) {
return Object.create(this)._init(regex);
},
+
+ // Initialize analyzer
_init : function (regex) {
try {
this._regex = new RegExp(regex);
@@ -15,6 +21,11 @@
};
return this;
},
+
+ /**
+ * Check a context based on the analyzer
+ * and return a valid context string.
+ */
test : function (text) {
if (!this._regex.exec(text))
return;
diff --git a/dev/js/src/hint/input.js b/dev/js/src/hint/input.js
index b1c6632..c12d26a 100644
--- a/dev/js/src/hint/input.js
+++ b/dev/js/src/hint/input.js
@@ -1,9 +1,14 @@
// Input field for queries
define({
+
+ /**
+ * Create a new input field.
+ */
create : function (element) {
return Object.create(this)._init(element);
},
-
+
+ // Initialize new input field
_init : function (element) {
this._element = element;
@@ -29,34 +34,62 @@
return this;
},
- rightPos : function () {
+ // Get the right position
+ _rightPos : function () {
var box = this._mirror.firstChild.getBoundingClientRect();
return box.right - box.left;
},
+ /**
+ * Get the mirrored input field.
+ */
mirror : function () {
return this._mirror;
},
+
+ /**
+ * Get the container element.
+ * This contains the mirror and
+ * the hint helper.
+ */
container : function () {
return this._container;
},
+
+ /**
+ * Get the input element the
+ * hint helper is attached to.
+ */
element : function () {
return this._element;
},
+ /**
+ * Get the value of the input field
+ * the hint helper is attached to.
+ */
value : function () {
return this._element.value;
},
+
+ /**
+ * Update the mirror content.
+ */
update : function () {
- this._mirror.firstChild.textContent = this.split()[0];
- this._container.style.left = this.rightPos() + 'px';
+ this._mirror.firstChild.textContent = this._split()[0];
+ this._container.style.left = this._rightPos() + 'px';
},
+ /**
+ * Insert text into the mirror.
+ * This is a prefix of the input field's
+ * value.
+ */
insert : function (text) {
- var splittedText = this.split();
+ var splittedText = this._split();
var s = this._element;
s.value = splittedText[0] + text + splittedText[1];
s.selectionStart = (splittedText[0] + text).length;
@@ -64,18 +97,11 @@
this._mirror.firstChild.textContent = splittedText[0] + text;
},
- // Return two substrings, splitted at current cursor position
- split : function () {
- var s = this._element;
- var value = s.value;
- var start = s.selectionStart;
- return new Array(
- value.substring(0, start),
- value.substring(start, value.length)
- );
- },
- // Position the input mirror directly below the input box
+ /**
+ * Reposition the input mirror directly
+ * below the input box.
+ */
reposition : function () {
var inputClientRect = this._element.getBoundingClientRect();
var inputStyle = window.getComputedStyle(this._element, null);
@@ -97,7 +123,27 @@
mirrorStyle.fontSize = inputStyle.getPropertyValue("font-size");
mirrorStyle.fontFamily = inputStyle.getPropertyValue("font-family");
},
+
+ /**
+ * Get the context, which is the input
+ * field's value bounded to the
+ * cursor position.
+ */
context : function () {
- return this.split()[0];
+ return this._split()[0];
+ },
+
+ /*
+ * Return two substrings,
+ * splitted at the current cursor position.
+ */
+ _split : function () {
+ var s = this._element;
+ var value = s.value;
+ var start = s.selectionStart;
+ return new Array(
+ value.substring(0, start),
+ value.substring(start, value.length)
+ );
}
});
diff --git a/dev/js/src/hint/item.js b/dev/js/src/hint/item.js
index 4b879f8..b9a1bc8 100644
--- a/dev/js/src/hint/item.js
+++ b/dev/js/src/hint/item.js
@@ -3,12 +3,17 @@
*/
define(['menu/item'], function (itemClass) {
return {
+
+ /**
+ * Create new menu item object.
+ */
create : function (params) {
return Object.create(itemClass)
.upgradeTo(this)
._init(params);
},
+ // Initialize menu item object
_init : function (params) {
if (params[0] === undefined ||
params[1] === undefined)
@@ -26,13 +31,20 @@
return this;
},
+ /**
+ * Get or set the content of the item.
+ */
content : function (content) {
if (arguments.length === 1) {
this._content = content;
};
return this._content;
},
-
+
+ /**
+ * Override the click action
+ * of the menu item.
+ */
onclick : function (e) {
var m = this.menu();
var h = m.hint();
@@ -50,15 +62,32 @@
h.show(true);
},
+ /**
+ * The name of the menu entry.
+ */
name : function () {
return this._name;
},
+
+ /**
+ * The action (the string inserted on click)
+ * of the menu item.
+ */
action : function () {
return this._action;
},
+
+ /**
+ * The description of the menu item.
+ */
desc : function () {
return this._desc;
},
+
+ /**
+ * The associated dom element of the
+ * menu item.
+ */
element : function () {
// already defined
if (this._element !== undefined)
diff --git a/dev/js/src/hint/menu.js b/dev/js/src/hint/menu.js
index c579945..bf965d7 100644
--- a/dev/js/src/hint/menu.js
+++ b/dev/js/src/hint/menu.js
@@ -3,6 +3,10 @@
*/
define(['menu', 'hint/item', 'hint/prefix'], function (menuClass, itemClass, prefixClass) {
return {
+
+ /**
+ * Create new hint helper menu.
+ */
create : function (hint, context, params) {
var obj = Object.create(menuClass)
.upgradeTo(this)
@@ -25,10 +29,11 @@
return obj;
},
- // Todo: Is this necessary?
- context : function () {
- return this._context;
- },
+
+ /**
+ * The hint helper object,
+ * the menu is attached to.
+ */
hint : function () {
return this._hint;
}
diff --git a/dev/js/src/hint/prefix.js b/dev/js/src/hint/prefix.js
index 84f785a..7586617 100644
--- a/dev/js/src/hint/prefix.js
+++ b/dev/js/src/hint/prefix.js
@@ -1,8 +1,17 @@
define(['menu/prefix'], function (prefixClass) {
return {
+
+ /**
+ * Create prefix object for the hint helper menu.
+ */
create : function (params) {
- return Object.create(prefixClass).upgradeTo(this)._init(params);
+ return Object.create(prefixClass).
+ upgradeTo(this)._init(params);
},
+
+ /**
+ * Override the prefix action.
+ */
onclick : function () {
var m = this.menu();
var h = m.hint();
diff --git a/dev/js/src/init.js b/dev/js/src/init.js
index cd99df1..5ef8dee 100644
--- a/dev/js/src/init.js
+++ b/dev/js/src/init.js
@@ -4,16 +4,38 @@
'vc',
'tutorial',
'lib/domReady',
+ 'hint/array',
+ 'lib/alertify',
+ 'api',
'util'
], function (matchClass,
hintClass,
vcClass,
tutClass,
- domReady) {
+ domReady,
+ hintArray) {
domReady(function (event) {
var obj = {};
/**
+ * Replace Virtual Collection field
+ */
+ var vcname;
+ var input = document.getElementById('vc');
+ if (input) {
+ input.style.display = 'none';
+ vcname = document.createElement('span');
+ vcname.setAttribute('id', 'vc-choose');
+ vcname.appendChild(
+ document.createTextNode(
+ document.getElementById('vc-name').value
+ )
+ );
+ input.parentNode.insertBefore(vcname, input);
+ };
+
+
+ /**
* Add actions to match entries
*/
var inactiveLi = document.querySelectorAll(
@@ -31,6 +53,7 @@
});
};
+
/**
* Toggle the alignment (left <=> right)
*/
@@ -41,8 +64,7 @@
toggle.setAttribute('title', 'toggle Alignment');
// Todo: Reuse old alignment from cookie!
var cl = toggle.classList;
- cl.add('align');
- cl.add('right');
+ cl.add('align', 'right');
toggle.addEventListener(
'click',
function (e) {
@@ -56,24 +78,11 @@
};
};
- /**
- * Init vc
- */
- var input = document.getElementById('vc');
- if (input) {
- input.style.display = 'none';
- var vcname = document.createElement('span');
- vcname.setAttribute('id', 'vc-choose');
- vcname.appendChild(
- document.createTextNode(
- document.getElementById('vc-name').value
- )
- );
- input.parentNode.insertBefore(vcname, input);
- /**
- * Toggle the Virtual Collection builder
- */
+ /**
+ * Toggle the Virtual Collection builder
+ */
+ if (vcname) {
var vc;
vcname.onclick = function () {
var view = document.getElementById('vc-view');
@@ -131,6 +140,22 @@
// Todo: Pass an element, so this works with
// tutorial pages as well!
obj.hint = hintClass.create();
+
+ // Set hint array for hint helper
+ KorAP.hintArray = hintArray;
+
+ // Override KorAP.log
+ KorAP.log = function (type, msg) {
+
+ // Use alertify to log errors
+ alertify.log(
+ (type === 0 ? '' : type + ': ') +
+ msg,
+ 'warn',
+ 5000
+ );
+ };
+
return obj;
});
});
diff --git a/dev/js/src/match/info.js b/dev/js/src/match/info.js
index c47f5ae..b75e713 100644
--- a/dev/js/src/match/info.js
+++ b/dev/js/src/match/info.js
@@ -12,7 +12,7 @@
matchTreeClass,
matchTreeMenuClass) {
- // TODO: Make this async
+ // Override
KorAP.API.getMatchInfo = KorAP.API.getMatchInfo || function () {
KorAP.log(0, 'KorAP.API.getMatchInfo() not implemented')
return {};
@@ -20,10 +20,11 @@
var loc = KorAP.Locale;
- /**
- * Create new object
- */
return {
+
+ /**
+ * Create new match object
+ */
create : function (match) {
return Object.create(this)._init(match);
},
@@ -44,6 +45,11 @@
return this._match;
},
+
+ /**
+ * Open the information view,
+ * if closed, otherwise close.
+ */
toggle : function () {
if (this.opened == true) {
this._match.element().children[0].removeChild(
@@ -64,7 +70,8 @@
/**
- * Retrieve and parse snippet for table representation
+ * Retrieve and parse snippet for table
+ * representation
*/
getTable : function (tokens, cb) {
var focus = [];
diff --git a/dev/js/src/match/infolayer.js b/dev/js/src/match/infolayer.js
index dbd93f9..0812f71 100644
--- a/dev/js/src/match/infolayer.js
+++ b/dev/js/src/match/infolayer.js
@@ -1,16 +1,26 @@
/**
- *
- * Alternatively pass a string as <tt>base/s=span</tt>
- *
- * @param foundry
+ * Object representing information
+ * about a match's layer annotation.
*/
define(function () {
- var _AvailableRE = new RegExp("^([^\/]+?)\/([^=]+?)(?:=(spans|rels|tokens))?$");
+ var _AvailableRE =
+ new RegExp("^([^\/]+?)\/([^=]+?)(?:=(spans|rels|tokens))?$");
return {
+ /**
+ * Create new match information
+ * object for one layer.
+ *
+ * Alternatively pass a string as
+ * <tt>base/s=span</tt>
+ *
+ * @param foundry
+ */
create : function (foundry, layer, type) {
return Object.create(this)._init(foundry, layer, type);
},
+
+ // Initialize Layer
_init : function (foundry, layer, type) {
if (foundry === undefined)
throw new Error("Missing parameters");
diff --git a/dev/js/src/match/table.js b/dev/js/src/match/table.js
index 7eba8a0..1a167d2 100644
--- a/dev/js/src/match/table.js
+++ b/dev/js/src/match/table.js
@@ -1,10 +1,21 @@
+/**
+ * Table representation of morphological
+ * annotations of a match.
+ */
define(function () {
var _TermRE = new RegExp("^(?:([^\/]+?)\/)?([^:]+?):(.+?)$");
return {
+
+ /**
+ * Create new table view for a match
+ * based on a snippet string.
+ */
create : function (snippet) {
return Object.create(this)._init(snippet);
},
+
+ // Initialize table based on snippet
_init : function (snippet) {
// Create html for traversal
var html = document.createElement("div");
@@ -23,27 +34,49 @@
return this;
},
+
+ /**
+ * Length of the table (columns),
+ * aka the number of tokens
+ * in the snippet.
+ */
length : function () {
return this._pos;
},
+ /**
+ * Get the token in the snippet
+ * At a given position.
+ *
+ * @param pos
+ */
getToken : function (pos) {
if (pos === undefined)
return this._token;
return this._token[pos];
},
-
+
+ /**
+ * Get the annotation of a token
+ * in the snippet based on the position,
+ * the foundry, and the layer.
+ *
+ * @param pos
+ * @param foundry
+ * @param layer
+ */
getValue : function (pos, foundry, layer) {
return this._info[pos][foundry + '/' + layer]
},
- getLayerPerFoundry : function (foundry) {
- return this._foundry[foundry]
- },
-
- getFoundryPerLayer : function (layer) {
- return this._layer[layer];
- },
+ /*
+ getLayerPerFoundry : function (foundry) {
+ return this._foundry[foundry]
+ },
+ getFoundryPerLayer : function (layer) {
+ return this._layer[layer];
+ },
+ */
// Parse the snippet
_parse : function (children) {
diff --git a/dev/js/src/match/tree.js b/dev/js/src/match/tree.js
index b379b37..9722f94 100644
--- a/dev/js/src/match/tree.js
+++ b/dev/js/src/match/tree.js
@@ -1,5 +1,6 @@
/**
- * Visualize span annotations as a tree using Dagre.
+ * Visualize span annotations as a tree
+ * using Dagre.
*/
define(['lib/dagre'], function (dagre) {
"use strict";
@@ -7,6 +8,9 @@
var svgXmlns = "http://www.w3.org/2000/svg";
var _TermRE = new RegExp("^(?:([^\/]+?)\/)?([^:]+?):(.+?)$");
+ // Node size
+ var WIDTH = 55, HEIGHT = 20;
+
// Create path for node connections
function _line (src, target) {
var x1 = src.x,
@@ -22,24 +26,18 @@
};
return {
+
+ /**
+ * Create new tree visualization based
+ * on a match snippet.
+ */
create : function (snippet) {
- return Object.create(this)._init(snippet);
+ return Object.create(this).
+ _init(snippet);
},
- nodes : function () {
- return this._next;
- },
- _addNode : function (id, obj) {
- obj["width"] = 55;
- obj["height"] = 20;
- this._graph.setNode(id, obj)
- },
-
- _addEdge : function (src, target) {
- this._graph.setEdge(src, target);
- },
-
+ // Initialize the tree based on a snippet.
_init : function (snippet) {
this._next = new Number(0);
@@ -76,6 +74,25 @@
return this;
},
+ /**
+ * The number of nodes in the tree.
+ */
+ nodes : function () {
+ return this._next;
+ },
+
+ // Add new node to graph
+ _addNode : function (id, obj) {
+ obj["width"] = WIDTH;
+ obj["height"] = HEIGHT;
+ this._graph.setNode(id, 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");
@@ -148,7 +165,9 @@
};
},
- // Get element
+ /**
+ * Get the dom element of the tree view.
+ */
element : function () {
if (this._element !== undefined)
return this._element;
@@ -183,26 +202,25 @@
// Add node box
var rect = group.appendChild(document.createElementNS(svgXmlns, 'rect'));
- rect.setAttributeNS(null, 'x', v.x - v.width / 2);
- rect.setAttributeNS(null, 'y', v.y - v.height / 2);
- rect.setAttributeNS(null, 'rx', 5);
- rect.setAttributeNS(null, 'ry', 5);
- rect.setAttributeNS(null, 'width', v.width);
- rect.setAttributeNS(null, 'height', v.height);
+ rect.setAttribute('x', v.x - v.width / 2);
+ rect.setAttribute('y', v.y - v.height / 2);
+ rect.setAttribute('rx', 5);
+ rect.setAttribute('ry', 5);
+ rect.setAttribute('width', v.width);
+ rect.setAttribute('height', v.height);
if (v.class === 'root' && v.label === undefined) {
- rect.setAttributeNS(null, 'width', v.height);
- rect.setAttributeNS(null, 'x', v.x - v.height / 2);
- rect.setAttributeNS(null, 'class', 'empty');
+ rect.setAttribute('width', v.height);
+ rect.setAttribute('x', v.x - v.height / 2);
+ rect.setAttribute('class', 'empty');
};
// Add label
if (v.label !== undefined) {
var text = group.appendChild(document.createElementNS(svgXmlns, 'text'));
- text.setAttributeNS(null, 'x', v.x - v.width / 2);
- text.setAttributeNS(null, 'y', v.y - v.height / 2);
- text.setAttributeNS(
- null,
+ text.setAttribute('x', v.x - v.width / 2);
+ text.setAttribute('y', v.y - v.height / 2);
+ text.setAttribute(
'transform',
'translate(' + v.width/2 + ',' + ((v.height / 2) + 5) + ')'
);
diff --git a/dev/js/src/match/treeitem.js b/dev/js/src/match/treeitem.js
index f096861..9a4b952 100644
--- a/dev/js/src/match/treeitem.js
+++ b/dev/js/src/match/treeitem.js
@@ -4,10 +4,20 @@
*/
return {
+
+ /**
+ * Create new menu item
+ * for tree views.
+ */
create : function (params) {
return Object.create(itemClass)
.upgradeTo(this)._init(params);
},
+
+ /**
+ * Get or set the content of the
+ * menu item.
+ */
content : function (content) {
if (arguments.length === 1) {
this._content = content;
@@ -15,17 +25,23 @@
return this._content;
},
- // The foundry attribute
+ /**
+ * The foundry attribute of the menu item.
+ */
foundry : function () {
return this._foundry;
},
- // The layer attribute
+ /**
+ * The layer attribute of the menu item.
+ */
layer : function () {
return this._layer;
},
- // enter or click
+ /**
+ * Override click action of the menu item.
+ */
onclick : function (e) {
var menu = this.menu();
menu.hide();
@@ -33,7 +49,8 @@
if (menu.info() !== undefined)
menu.info().addTree(this._foundry, this._layer);
},
-
+
+ // Initialize tree menu item.
_init : function (params) {
if (params[0] === undefined)
throw new Error("Missing parameters");
diff --git a/dev/js/src/match/treemenu.js b/dev/js/src/match/treemenu.js
index 23341a4..16f6306 100644
--- a/dev/js/src/match/treemenu.js
+++ b/dev/js/src/match/treemenu.js
@@ -5,6 +5,16 @@
"use strict";
return {
+
+ /**
+ * Create new menu object.
+ * Pass the match information object
+ * and the item parameters.
+ *
+ * @param info The match info object
+ * @param params The match menu items
+ * as an array of arrays.
+ */
create : function (info, params) {
var obj = Object.create(menuClass)
.upgradeTo(this)
@@ -19,6 +29,10 @@
return obj;
},
+
+ /**
+ * The match information object of the menu.
+ */
info :function () {
return this._info;
}
diff --git a/dev/js/src/menu.js b/dev/js/src/menu.js
index 2bc356b..cc42855 100644
--- a/dev/js/src/menu.js
+++ b/dev/js/src/menu.js
@@ -1,10 +1,11 @@
/**
- * Create scrollable drop-down menus.
+ * Scrollable drop-down menus with view filter.
*
* @author Nils Diewald
*/
/*
* TODO: space is not a valid prefix!
+ * TODO: Prefix should be case sensitive!
*/
define([
'menu/item',
@@ -13,7 +14,6 @@
], function (defaultItemClass,
defaultPrefixClass) {
- // Todo: This may not be necessary
// Default maximum number of menu items
var menuLimit = 8;
@@ -58,10 +58,15 @@
delete this._prefix['_menu'];
},
+
+ /**
+ * Focus on this menu.
+ */
focus : function () {
this._element.focus();
},
+
// mouse wheel treatment
_mousewheel : function (e) {
var delta = 0;
@@ -74,6 +79,7 @@
e.halt();
},
+
// Arrow key and prefix treatment
_keydown : function (e) {
var code = _codeFromEvent(e);
@@ -122,7 +128,7 @@
e.halt();
break;
case 8: // 'Backspace'
- this._prefix.backspace();
+ this._prefix.chop();
this.show();
e.halt();
break;
@@ -214,22 +220,23 @@
},
/**
- * Get the instantiated HTML element
+ * Get the associated dom element.
*/
element : function () {
return this._element;
},
+
/**
- * Get the creator object for items
+ * Get the creator class for items
*/
itemClass : function () {
return this._itemClass;
},
/**
- * Get and set numerical value for limit,
- * i.e. the number of items visible.
+ * Get and set the numerical value
+ * for the maximum number of items visible.
*/
limit : function (limit) {
if (arguments.length === 1) {
@@ -239,6 +246,7 @@
return this._limit;
},
+
/**
* Upgrade this object to another object,
* while private data stays intact.
@@ -252,6 +260,7 @@
return this;
},
+
// Reset chosen item and prefix
_reset : function () {
this._offset = 0;
@@ -259,6 +268,7 @@
this._prefix.value('');
},
+
/**
* Filter the list and make it visible
*
@@ -287,15 +297,23 @@
return true;
},
+
+ /**
+ * Hide the menu and call the onHide callback.
+ */
hide : function () {
this.active = false;
this.delete();
this._element.style.opacity = 0;
+ this._prefix.clear();
this.onHide();
/* this._element.blur(); */
},
- // To be override
+ /**
+ * Function released when the menu hides.
+ * This method is expected to be overridden.
+ */
onHide : function () {},
// Initialize the list
@@ -356,6 +374,7 @@
this.item(this._list[this._list.length - 1]).noMore(bool);
},
+
/**
* Get the prefix for filtering,
* e.g. "ve" for "verb"
@@ -368,6 +387,7 @@
return this._prefix.value();
},
+
// Append Items that should be shown
_showItems : function (offset) {
this.delete();
@@ -644,7 +664,9 @@
},
- // Length of the filtered list
+ /**
+ * Length of the filtered item list.
+ */
liveLength : function () {
if (this._list === undefined)
this._initList();
diff --git a/dev/js/src/menu/item.js b/dev/js/src/menu/item.js
index b80aa2a..b8e8808 100644
--- a/dev/js/src/menu/item.js
+++ b/dev/js/src/menu/item.js
@@ -34,16 +34,28 @@
return this;
},
+
+ /**
+ * Get or set the content of the meun item.
+ */
content : function (content) {
if (arguments.length === 1)
this._content = document.createTextNode(content);
return this._content;
},
+ /**
+ * Get the lower cased field of the item
+ * (used for analyses).
+ */
lcField : function () {
return this._lcField;
},
+
+ /**
+ * Get or set the information for action of this item.
+ */
action : function (action) {
if (arguments.length === 1)
this._action = action;
diff --git a/dev/js/src/menu/prefix.js b/dev/js/src/menu/prefix.js
index a4e428f..abcf66c 100644
--- a/dev/js/src/menu/prefix.js
+++ b/dev/js/src/menu/prefix.js
@@ -1,7 +1,13 @@
define({
- create : function (params) {
+
+ /**
+ * Create new prefix object.
+ */
+ create : function () {
return Object.create(this)._init();
},
+
+ // Initialize prefix object
_init : function () {
this._string = '';
@@ -15,8 +21,9 @@
return this;
},
+
_update : function () {
- this._element.innerHTML
+ return this._element.innerHTML
= this._string;
},
@@ -33,6 +40,10 @@
return this;
},
+
+ /**
+ * Get or set the activity status of the prefix.
+ */
active : function (bool) {
var cl = this.element().classList;
if (bool === undefined)
@@ -43,31 +54,57 @@
cl.remove("active");
},
- element : function () {
- return this._element;
- },
-
+ /**
+ * Check, if a prefix is given or not.
+ */
isSet : function () {
return this._string.length > 0 ?
true : false;
},
+ /**
+ * Get or set the prefix string.
+ */
value : function (string) {
if (arguments.length === 1) {
this._string = string;
- this._update();
+ return this._update();
};
return this._string;
},
-
+
+
+ /**
+ * Add string to prefix.
+ */
add : function (string) {
this._string += string;
- this._update();
+ return this._update();
},
+
+ /**
+ * Clear prefix
+ */
+ clear : function () {
+ this._string = '';
+ return this._update();
+ },
+
+
+ /**
+ * Action method.
+ * Expected to be overridden.
+ */
onclick : function () {},
- backspace : function () {
+
+ /**
+ * Remove the last character of the string
+ */
+ chop : function () {
+
+ // Prefix is long enough for backspace
if (this._string.length > 1) {
this._string = this._string.substring(
0, this._string.length - 1
@@ -77,9 +114,18 @@
this._string = '';
};
- this._update();
+ return this._update();
},
+
+ /**
+ * Get the associated dom element.
+ */
+ element : function () {
+ return this._element;
+ },
+
+
/**
* Return menu list.
*/
diff --git a/dev/js/src/tutorial.js b/dev/js/src/tutorial.js
index cacbe21..a028b8e 100644
--- a/dev/js/src/tutorial.js
+++ b/dev/js/src/tutorial.js
@@ -54,6 +54,10 @@
return this;
},
+
+ /**
+ * Initialize a search with a defined query.
+ */
useQuery : function (e) {
var q = e.getAttribute("data-query");
var ql = e.getAttribute("data-query-language");
@@ -74,6 +78,10 @@
this.hide();
},
+
+ /**
+ * Decorate a page with query event handler.
+ */
initQueries : function (d) {
var qs = d.querySelectorAll('pre.query.tutorial');
var that = this;
@@ -85,6 +93,9 @@
},
+ /**
+ * Show the tutorial page embedded.
+ */
show : function () {
var element = this._element;
if (element.style.display === 'block')
diff --git a/dev/js/src/vc.js b/dev/js/src/vc.js
index 1bb3b15..1aed3cf 100644
--- a/dev/js/src/vc.js
+++ b/dev/js/src/vc.js
@@ -138,6 +138,7 @@
return obj;
},
+
/**
* Create and render a new virtual collection
* based on a KoralQuery collection document
@@ -171,6 +172,10 @@
return this;
},
+
+ /**
+ * Clean the virtual document to uspecified doc.
+ */
clean : function () {
if (this._root.ldType() !== "non") {
this._root.destroy();
@@ -179,6 +184,7 @@
return this;
},
+
/**
* Get or set the root object of the
* virtual collection.
@@ -206,6 +212,7 @@
return this._root;
},
+
/**
* Get the element associated with the virtual collection
*/
diff --git a/dev/js/src/vc/doc.js b/dev/js/src/vc/doc.js
index 2635b2f..f04b445 100644
--- a/dev/js/src/vc/doc.js
+++ b/dev/js/src/vc/doc.js
@@ -10,10 +10,10 @@
/*
var fieldMenu = menuClass.create([
- ['Titel', 'title', 'string'],
- ['Untertitel', 'subTitle', 'string'],
- ['Veröffentlichungsdatum', 'pubDate', 'date'],
- ['Autor', 'author', 'string']
+ ['Titel', 'title', 'string'],
+ ['Untertitel', 'subTitle', 'string'],
+ ['Veröffentlichungsdatum', 'pubDate', 'date'],
+ ['Autor', 'author', 'string']
]);
fieldMenu.limit(5);
@@ -417,29 +417,37 @@
// Click on the match operator, show me the menu
_changeValue : function (e) {
- // TODO: Just kidding - this is temporary!
+ // Show datepicker
if (this.type() === 'date') {
var dp = KorAP._vcDatePicker;
var v = this.value();
if (v !== undefined) {
- var d = v.split('-');
- dp.select(parseInt(d[0]), parseInt(d[1]), parseInt(d[2]));
+
+ var d = v.split('-', 3);
+ d[0] = parseInt(d[0]);
+ if (d[1]) d[1] = parseInt(d[1]);
+ if (d[2]) d[2] = parseInt(d[2]);
+
+ // Select values
+ dp.select(d[0], d[1], d[2]);
};
var that = this;
+
dp.onclick(function (selected) {
// There are values selected
if (selected['year']) {
- var v = selected['year'];
+ var v = '' + selected['year'];
if (selected['month']) {
v += '-';
v += selected['month'] < 10 ? '0' + selected['month'] : selected['month'];
- if (selected['day'])
+ if (selected['day']) {
v += '-';
v += selected['day'] < 10 ? '0' + selected['day'] : selected['day'];
+ };
};
that.value(v);
that.update();
@@ -452,12 +460,22 @@
);
});
+ // Get element of the date picker
+ var dpElem = dp.show();
+
this._element.insertBefore(
- dp.show(),
+ dpElem,
this._valueE
);
+
+ dpElem.focus();
+ dpElem.addEventListener('blur', function (e) {
+ // Remove datepicker
+ that._element.removeChild(this);
+ });
}
else {
+ // TODO: Just kidding - this is temporary!
this.value(window.prompt('Enter new value'));
this.update();
};
diff --git a/dev/js/src/vc/menu.js b/dev/js/src/vc/menu.js
index d305960..17ad073 100644
--- a/dev/js/src/vc/menu.js
+++ b/dev/js/src/vc/menu.js
@@ -4,9 +4,17 @@
define(['menu', 'vc/item'], function (menuClass, itemClass) {
return {
create : function (params) {
- return Object.create(menuClass)
+ var obj = Object.create(menuClass)
.upgradeTo(this)
- ._init(itemClass, undefined, params)
+ ._init(itemClass, undefined, params);
+ obj.limit(6);
+
+ // This is only domspecific
+ obj.element().addEventListener('blur', function (e) {
+ this.menu.hide();
+ });
+
+ return obj;
},
/**
diff --git a/dev/scss/header/datepicker.scss b/dev/scss/header/datepicker.scss
index 8a3fbcd..806ca1e 100644
--- a/dev/scss/header/datepicker.scss
+++ b/dev/scss/header/datepicker.scss
@@ -6,6 +6,7 @@
div.datepicker {
display: inline-block;
position: absolute;
+ z-index: 8000;
font-size: 80%;
padding: 4pt;
box-shadow: $choose-box-shadow;
@@ -21,7 +22,7 @@
> div.month {
float: right;
}
-
+
@include choose-item;
> div > span {
display: inline-block;
@@ -59,6 +60,9 @@
&:hover {
@include choose-hover;
}
+ &.selected {
+ @include choose-active;
+ }
}
}
table {
diff --git a/dev/scss/header/vc.scss b/dev/scss/header/vc.scss
index 12071db..d13ba6e 100644
--- a/dev/scss/header/vc.scss
+++ b/dev/scss/header/vc.scss
@@ -250,6 +250,10 @@
}
}
+#vc {
+ line-height: 1em;
+ border-radius: $standard-border-radius;
+}
#vc-choose {
&::after {
diff --git a/dev/scss/media.scss b/dev/scss/media.scss
index 45e3bee..43122bc 100644
--- a/dev/scss/media.scss
+++ b/dev/scss/media.scss
@@ -93,9 +93,19 @@
width: 100%;
}
- aside ul {
- font-size: 9pt;
- line-height: 1em;
+ aside {
+ &:not(:focus):not(.active) {
+ margin-left: -1 * $logo-left-distance;
+ &::after {
+ font-size: 12pt;
+ width: 10pt;
+ height: 11pt;
+ }
+ }
+ ul {
+ font-size: 9pt;
+ line-height: 1em;
+ }
}
#tutorial {
@@ -116,15 +126,6 @@
}
/*
-
- #sidebar {
- padding-top: 22px;
- }
- #sidebar:not(.active) > i.fa-bars {
- font-size: 12pt;
- width: 10pt;
- height: 11pt;
- }
pre.query {
font-size: 9.5pt;
}
diff --git a/dev/scss/util.scss b/dev/scss/util.scss
index 8b91f22..7f5f723 100644
--- a/dev/scss/util.scss
+++ b/dev/scss/util.scss
@@ -26,9 +26,10 @@
/**
* Green Colors
*/
-$dark-green: $ids-green-1; // #496000;
-$middle-green: lighten($ids-green-1, 5%); // $ids-green-1; // #688704;
-$light-green: lighten($ids-green-1, 13%); // #7ba400;
+$dark-green: $ids-green-1; // #496000;
+$middle-green: lighten($ids-green-1, 5%); // $ids-green-1; // #688704;
+$light-green: lighten($ids-green-1, 13%); // #7ba400;
+$lightest-green: lighten($ids-green-1, 26%);
/**
* Blue Colors