Attempt to fix Hint compatibility problem (WIP)
Change-Id: I3016afc2f74b90c223dd4f8f2386b71aab1eedcd
diff --git a/dev/js/spec/hintSpec.js b/dev/js/spec/hintSpec.js
index 79726f3..45850a4 100644
--- a/dev/js/spec/hintSpec.js
+++ b/dev/js/spec/hintSpec.js
@@ -241,13 +241,22 @@
// Show menu, hide alert!
hint.show(false);
-
- // PROBLEM!
- expect(hint.active()).toBeTruthy();
- expect(hint.inputField().mirrorValue()).toEqual('abcde');
- expect(hint.alert().active).toBeFalsy();
});
+ it('should work both in Chrome and Firefox', function () {
+ var hint = hintClass.create({
+ inputField : input
+ });
+ hint.show(false);
+ expect(hint.alert(5, 'That does not work!')).toBeTruthy();
+
+ // Show menu, hide alert!
+ hint.show(false);
+
+ expect(hint.active()).toBeFalsy();
+ });
+
+
it('should view main menu on default', function () {
var hint = hintClass.create({
inputField : input
diff --git a/dev/js/src/hint.js b/dev/js/src/hint.js
index 91381f5..409bd6f 100644
--- a/dev/js/src/hint.js
+++ b/dev/js/src/hint.js
@@ -16,6 +16,9 @@
* TODO: Improve context analyzer from hint!
* TODO: Marked annotations should be addable to "fragments"
*/
+
+"use strict";
+
define([
'hint/input',
'hint/menu',
@@ -26,11 +29,6 @@
menuClass,
analyzerClass,
alertClass) {
- "use strict";
-
- /**
- * Return keycode based on event
- */
// Initialize hint array
@@ -42,10 +40,6 @@
*/
return {
- // Some variables
- // _firstTry : true,
- // active : false,
-
/**
* Create new hint helper.
*/
@@ -53,6 +47,7 @@
return Object.create(this)._init(param);
},
+
// Initialize hint helper
_init : function (param) {
param = param || {};
@@ -60,6 +55,8 @@
// Holds all menus per prefix context
this._menu = {};
this._alert = alertClass.create();
+
+ // Active may either hold an alert or a menu
this._active = null;
// No annotation helper available
@@ -84,41 +81,37 @@
")$";
// Get input field
- var qfield = param["inputField"] || document.getElementById("q-field");
+ const qfield = param["inputField"] || document.getElementById("q-field");
if (!qfield)
return null;
// Create input field
this._inputField = inputClass.create(qfield);
- var inputFieldElement = this._inputField.element();
-
- var c = this._inputField.container();
-
// create alert
+ const that = this;
+
+ const c = this._inputField.container();
c.appendChild(this._alert.element());
-
- var that = this;
-
- this._inputField.container().addEventListener('click', function (e) {
+ c.addEventListener('click', function (e) {
if (!this.classList.contains('active')) {
that.show(false);
};
});
- var _down = function (e) {
- var code = _codeFromEvent(e);
- if (code === 40) {
- this.show(false);
- e.halt();
- };
- };
-
// Move infobox
+ const inputFieldElement = this._inputField.element();
inputFieldElement.addEventListener("keyup", this.update.bind(this));
inputFieldElement.addEventListener("click", this.update.bind(this));
// Add event listener for key pressed down
+ let _down = function (e) {
+ if (_codeFromEvent(e) === 40) {
+ this.show(false);
+ e.halt();
+ };
+ };
+
inputFieldElement.addEventListener(
"keydown", _down.bind(this), false
);
@@ -160,29 +153,28 @@
* Altert at a specific character position.
*/
alert : function (charPos, msg) {
-
+ const t = this;
if (arguments.length === 0)
- return this._alert;
+ return t._alert;
// Do not alert if already alerted!
- if (this._alert.active)
+ if (t._alert.active)
return false;
// Move to the correct position
- this._inputField.moveto(charPos);
+ t._inputField.moveto(charPos);
// Set container to active (aka hide the hint helper button)
- this._alert.show(msg);
- this.active(this._alert);
+ t._alert.show(msg);
+ t.active(t._alert);
return true;
},
- _unshowAlert : function () {
- this._alert.hide();
- this.active(null);
- },
+ /**
+ * Update input field.
+ */
update : function () {
this._inputField.update();
if (this._alert.hide())
@@ -195,7 +187,7 @@
*/
menu : function (action) {
if (this._menu[action] === undefined) {
-
+
// No matching hint menu
if (KorAP.annotationHelper[action] === undefined)
return;
@@ -210,28 +202,31 @@
return this._menu[action];
},
+
/**
* Get the correct menu based on the context
*/
contextMenu : function (ifContext) {
+ const noC = ifContext ? undefined : this.menu("-");
// Get context (aka left text)
- var context = this._inputField.context();
+ let context = this._inputField.context();
if (context === undefined || context.length === 0) {
- return ifContext ? undefined : this.menu("-");
+ return noC;
};
// Get context (aka left text matching regex)
context = this._analyzer.test(context);
if (context === undefined || context.length == 0) {
- return ifContext ? undefined : this.menu("-");
+ return noC;
};
- return this.menu(context) || (ifContext ? undefined : this.menu('-'));
+ return this.menu(context) || noC;
},
+
/**
* Activate a certain menu.
* If a menu is passed, the menu will be activated.
@@ -239,11 +234,11 @@
* If nothing is passed, returns the active menu.
*/
active : function (obj) {
-
+
// A menu or null was passed
- if (arguments.length === 1) {
- var c = this._inputField.container();
-
+ if (arguments.length === 1) {
+ const c = this._inputField.container();
+
// Make the menu active
if (obj !== null) {
c.classList.add('active');
@@ -277,33 +272,31 @@
this._unshow();
// Get the menu
- var menu;
+ let menu;
if (menu = this.contextMenu(ifContext)) {
+
this.active(menu);
- var c = this._inputField.container();
- c.appendChild(menu.element());
+ let e = menu.element();
+ // console.log("Chrome may send a blur on the old menu here");
+ this._active.element().blur();
+ this._inputField.container().appendChild(e);
menu.show();
menu.focus();
// Focus on input field
// this.inputField.element.focus();
}
+
else {
this._inputField.element().focus();
};
},
+
// This will get the context of the field
getContext : function () {},
- /**
- * Deactivate the current menu and focus on the input field.
- */
- unshow_old : function () {
- this.active(null);
- this.inputField().element().focus();
- },
/**
* Deactivate the current menu and focus on the input field.
@@ -316,17 +309,16 @@
// Catch touch events
_touch : function (e) {
-
if (e.type === 'touchstart') {
- var t = e.touches[0];
- this._lastTouch = t.clientY;
+ this._lastTouch = e.touches[0].clientY;
}
+
else if (e.type === 'touchend') {
this._lastTouch = undefined;
}
+
else if (e.type == 'touchmove') {
- var t = e.touches[0];
- if ((this._lastTouch + 10) < t.clientY) {
+ if ((this._lastTouch + 10) < e.touches[0].clientY) {
this.show();
this._lastTouch = undefined;
};
@@ -334,26 +326,32 @@
}
},
-
+
+ // Unshow the hint menu
_unshow : function () {
if (this.active() !== null) {
- // var act = this.active();
-
+
// This does not work for alert currently!
- //if (act._type !== 'alert') {
if (!this._alert.active) {
- // This does not work for webkit!
- var c = this._inputField.container();
- c.removeChild(this._active.element());
+ // TODO: This does not work for webkit?
+ this._inputField
+ .container()
+ .removeChild(this._active.element());
}
+
else {
this._unshowAlert();
};
- // this._active.hide();
this.active(null);
};
+ },
+
+ // Unshow alert
+ _unshowAlert : function () {
+ this._alert.hide();
+ this.active(null);
}
};
});
diff --git a/dev/js/src/hint/alert.js b/dev/js/src/hint/alert.js
index 768d719..c8d7696 100644
--- a/dev/js/src/hint/alert.js
+++ b/dev/js/src/hint/alert.js
@@ -1,26 +1,45 @@
/**
- * Hint menu alert
+ * Hint menu alert, positioned at the exact char.
*/
+"use strict";
+
define(function () {
- "use strict";
+
return {
+
+ /**
+ * Construct a new alert object
+ */
create : function (msg) {
return Object.create(this)._init(msg);
},
+
+ // Init
_init : function (msg) {
- this._type = 'alert';
- this.active = false;
- this._element = document.createElement('div');
- this._element.style.display = 'none';
- this._element.classList.add('alert', 'hint');
- return this;
- },
- show : function (msg) {
- this._element.textContent = msg;
- this.active = true;
- this._element.style.display = 'block';
+ const t = this;
+ t._type = 'alert';
+ t.active = false;
+ t._element = document.createElement('div');
+ t._element.style.display = 'none';
+ t._element.classList.add('alert', 'hint');
+ return t;
},
+
+ /**
+ * Show alert.
+ */
+ show : function (msg) {
+ this.active = true;
+ const e = this._element;
+ e.textContent = msg;
+ e.style.display = 'block';
+ },
+
+
+ /**
+ * Hide alert.
+ */
hide : function () {
if (!this.active)
return false;
@@ -29,6 +48,10 @@
return true;
},
+
+ /**
+ * Get alert object.
+ */
element : function () {
return this._element;
}
diff --git a/dev/js/src/hint/contextanalyzer.js b/dev/js/src/hint/contextanalyzer.js
index fc01662..7030cb9 100644
--- a/dev/js/src/hint/contextanalyzer.js
+++ b/dev/js/src/hint/contextanalyzer.js
@@ -1,6 +1,8 @@
/**
* Regex object for checking the context of the hint
*/
+"use strict";
+
define({
/**
diff --git a/dev/js/src/hint/foundries.js b/dev/js/src/hint/foundries.js
index 256ee76..ce6ef43 100644
--- a/dev/js/src/hint/foundries.js
+++ b/dev/js/src/hint/foundries.js
@@ -1,22 +1,21 @@
-window.KorAP = window.KorAP || {};
KorAP.annotationHelper = KorAP.annotationHelper || { '-' : [] };
-define([], function () {
- "use strict";
+"use strict";
+
+define(["util"], function () {
const ah = KorAP.annotationHelper;
- ah["getDesc"] = function (foundryLayer, value) {
+ ah.getDesc = function (foundryLayer, value) {
if (!foundryLayer)
return;
- var anno = this[foundryLayer];
+ let anno = this[foundryLayer];
if (!anno)
return;
- // if (value.indexOf(':') < 0) {
if (!value.includes(':')) {
value += ' ';
@@ -35,16 +34,15 @@
return;
}
- else {
- var text = '';
- var v = value.split(":");
- var l1 = v[0];
- var l2 = v[1];
- l1 += ':';
+ else {
+ const v = value.split(":");
+ let l1 = v[0] + ':';
+ let l2 = v[1] + ' ';
+ let text = '';
// Add key description
- for (var i = 0; i < anno.length; i++) {
+ for (let i = 0; i < anno.length; i++) {
if (anno[i] &&
anno[i][1] == l1) {
if (anno[i][2])
@@ -65,10 +63,8 @@
if (!anno)
return;
- l2 += ' ';
-
// Add value description
- for (var i = 0; i < anno.length; i++) {
+ for (let i = 0; i < anno.length; i++) {
if (anno[i] &&
anno[i][1] == l2) {
if (anno[i][2])
diff --git a/dev/js/src/hint/input.js b/dev/js/src/hint/input.js
index 120a953..d779776 100644
--- a/dev/js/src/hint/input.js
+++ b/dev/js/src/hint/input.js
@@ -1,194 +1,203 @@
// Input field for queries
/*
- * TODO: Support allert for query problems.
+ * TODO: Support alert for query problems.
*/
-define({
+"use strict";
- /**
- * Create a new input field.
- */
- create : function (element) {
- return Object.create(this)._init(element);
- },
+define(['util'], function () {
+
+ return {
+
+ /**
+ * Create a new input field.
+ */
+ create : function (element) {
+ return Object.create(this)._init(element);
+ },
- /**
- * Get the mirrored input field.
- */
- mirror : function () {
- return this._mirror;
- },
+ // Initialize new input field
+ _init : function (element) {
+ this._element = element;
+
+ this._container = document.createElement("div");
+ this._container.setAttribute('id', 'hint');
+
+ // Create mirror for searchField
+ // This is important for positioning
+ // if ((this._mirror = document.getElementById("searchMirror")) === null) {
+ this._mirror = document.createElement("div");
+ const m = this._mirror;
+ m.classList.add('hint', 'mirror');
+ m.addE("span");
+ m.appendChild(this._container);
+ m.style.height = "0px";
+ document.getElementsByTagName("body")[0].appendChild(m);
+
+ // Update position of the mirror
+ const re = this.reposition.bind(this);
+ window.addEventListener('resize', re);
+ this._element.addEventListener('onfocus', re);
+ this.reposition();
+ return this;
+ },
- /**
- * Get the container element.
- * This contains the hint helper / menus
- * and probably an
- * error message.
- */
- container : function () {
- return this._container;
- },
+ /**
+ * Get the mirrored input field.
+ */
+ mirror : function () {
+ return this._mirror;
+ },
- /**
- * Get the input element the
- * hint helper is attached to.
- */
- element : function () {
- return this._element;
- },
+ /**
+ * Get the container element.
+ * This contains the hint helper / menus
+ * and probably an
+ * error message.
+ */
+ container : function () {
+ return this._container;
+ },
- /**
- * Get the value of the input field
- * the hint helper is attached to.
- */
- value : function () {
- return this._element.value;
- },
+ /**
+ * Get the input element the
+ * hint helper is attached to.
+ */
+ element : function () {
+ return this._element;
+ },
- /**
- * Get the value of the input field mirror.
- */
- mirrorValue : function () {
- return this._mirror.firstChild.textContent;
- },
+ /**
+ * Get the value of the input field
+ * the hint helper is attached to.
+ */
+ value : function () {
+ return this._element.value;
+ },
- /**
- * Reset the input value
- */
- reset : function () {
- this._element.value = "";
- },
+ /**
+ * Get the value of the input field mirror.
+ */
+ mirrorValue : function () {
+ return this._mirror.firstChild.textContent;
+ },
- /**
- * Update the mirror content.
- */
- update : function () {
- this._mirror.firstChild.textContent = this._split()[0];
- this._container.style.left = this._rightPos() + 'px';
- return this;
- },
+ /**
+ * Reset the input value
+ */
+ reset : function () {
+ this._element.value = "";
+ },
- /**
- * Insert text into the mirror.
- * This is a prefix of the input field's
- * value.
- */
- insert : function (text) {
- var splittedText = this._split();
- var s = this._element;
- s.value = splittedText[0] + text + splittedText[1];
- s.selectionStart = (splittedText[0] + text).length;
- s.selectionEnd = s.selectionStart;
-
- // Maybe update?
- this._mirror.firstChild.textContent = splittedText[0] + text;
- return this;
- },
-
- /**
- * Move hinthelper to given character position
- */
- moveto : function (charpos) {
- this._element.selectionStart = charpos;
- this._element.selectionEnd = charpos;
- this._element.focus();
- return this.update();
- },
-
- /**
- * Reposition the input mirror directly
- * below the input box.
- */
- reposition : function () {
- var inputClientRect = this._element.getBoundingClientRect();
- var inputStyle = window.getComputedStyle(this._element, null);
-
- var bodyClientRect =
- document.getElementsByTagName('body')[0].getBoundingClientRect();
-
- // Reset position
- var mirrorStyle = this._mirror.style;
- mirrorStyle.left = parseInt(inputClientRect.left) + "px";
- mirrorStyle.top = parseInt(inputClientRect.bottom - bodyClientRect.top) + "px";
- mirrorStyle.width = inputStyle.getPropertyValue("width");
-
- // These may be relevant in case of media depending css
- mirrorStyle.paddingLeft = inputStyle.getPropertyValue("padding-left");
- mirrorStyle.marginLeft = inputStyle.getPropertyValue("margin-left");
- mirrorStyle.borderLeftWidth = inputStyle.getPropertyValue("border-left-width");
- mirrorStyle.borderLeftStyle = inputStyle.getPropertyValue("border-left-style");
- mirrorStyle.fontSize = inputStyle.getPropertyValue("font-size");
- mirrorStyle.fontFamily = inputStyle.getPropertyValue("font-family");
- },
+ /**
+ * Update the mirror content.
+ */
+ update : function () {
+ this._mirror.firstChild.textContent = this._split()[0];
+ this._container.style.left = this._rightPos() + 'px';
+ return this;
+ },
- /**
- * Get the context, which is the input
- * field's value bounded to the
- * cursor position.
- */
- context : function () {
- return this._split()[0];
- },
+ /**
+ * Insert text into the mirror.
+ * This is a prefix of the input field's
+ * value.
+ */
+ insert : function (text) {
+ const splittedText = this._split();
+ const s = this._element;
+ s.value = splittedText[0] + text + splittedText[1];
+ s.selectionStart = (splittedText[0] + text).length;
+ s.selectionEnd = s.selectionStart;
+
+ // Maybe update?
+ this._mirror.firstChild.textContent = splittedText[0] + text;
+ return this;
+ },
- // Initialize new input field
- _init : function (element) {
- this._element = element;
-
- // Create mirror for searchField
- // This is important for positioning
- // if ((this._mirror = document.getElementById("searchMirror")) === null) {
- this._mirror = document.createElement("div");
- this._mirror.classList.add('hint', 'mirror');
- this._mirror.appendChild(document.createElement("span"));
- this._container = document.createElement("div");
- this._container.setAttribute('id', 'hint');
-
- this._mirror.appendChild(this._container);
- this._mirror.style.height = "0px";
- document.getElementsByTagName("body")[0].appendChild(this._mirror);
- // };
-
- // Update position of the mirror
- window.addEventListener('resize', this.reposition.bind(this));
- this._element.addEventListener('onfocus', this.reposition.bind(this));
- this.reposition();
- return this;
- },
+ /**
+ * Move hinthelper to given character position
+ */
+ moveto : function (charpos) {
+ const e = this._element;
+ e.selectionStart = charpos;
+ e.selectionEnd = charpos;
+ e.focus();
+ return this.update();
+ },
- // Get the right position
- _rightPos : function () {
- var box = this._mirror.firstChild.getBoundingClientRect();
- return box.right - box.left;
- },
+ /**
+ * Reposition the input mirror directly
+ * below the input box.
+ */
+ reposition : function () {
+ const inputClientRect = this._element.getBoundingClientRect();
+ const inputStyle = window.getComputedStyle(this._element, null);
+
+ const bodyClientRect =
+ document.getElementsByTagName('body')[0].getBoundingClientRect();
+
+ // Reset position
+ const mirrorStyle = this._mirror.style;
+ mirrorStyle.left = parseInt(inputClientRect.left) + "px";
+ mirrorStyle.top = parseInt(inputClientRect.bottom - bodyClientRect.top) + "px";
+ mirrorStyle.width = inputStyle.getPropertyValue("width");
+
+ // These may be relevant in case of media depending css
+ mirrorStyle.paddingLeft = inputStyle.getPropertyValue("padding-left");
+ mirrorStyle.marginLeft = inputStyle.getPropertyValue("margin-left");
+ mirrorStyle.borderLeftWidth = inputStyle.getPropertyValue("border-left-width");
+ mirrorStyle.borderLeftStyle = inputStyle.getPropertyValue("border-left-style");
+ mirrorStyle.fontSize = inputStyle.getPropertyValue("font-size");
+ mirrorStyle.fontFamily = inputStyle.getPropertyValue("font-family");
+ },
- /*
- * Return two substrings,
- * splitted at a given position
- * or at the current cursor position.
- */
- _split : function (start) {
- var s = this._element;
- var value = s.value;
+ /**
+ * Get the context, which is the input
+ * field's value bounded to the
+ * cursor position.
+ */
+ context : function () {
+ return this._split()[0];
+ },
- // Get start from cursor position
- if (arguments.length === 0)
- start = s.selectionStart;
- return new Array(
- value.substring(0, start),
- value.substring(start, value.length)
- );
+ // Get the right position
+ _rightPos : function () {
+ const box = this._mirror.firstChild.getBoundingClientRect();
+ return box.right - box.left;
+ },
+
+
+ /*
+ * Return two substrings,
+ * splitted at a given position
+ * or at the current cursor position.
+ */
+ _split : function (start) {
+ const s = this._element;
+ const value = s.value;
+
+ // Get start from cursor position
+ if (arguments.length === 0)
+ start = s.selectionStart;
+
+ return new Array(
+ value.substring(0, start),
+ value.substring(start, value.length)
+ );
+ }
}
});
diff --git a/dev/js/src/hint/lengthField.js b/dev/js/src/hint/lengthField.js
index 541b917..79c7b7d 100644
--- a/dev/js/src/hint/lengthField.js
+++ b/dev/js/src/hint/lengthField.js
@@ -1,3 +1,5 @@
+"use strict";
+
define(['menu/lengthField', 'util'], function (lengthFieldClass) {
return {
diff --git a/dev/js/src/hint/menu.js b/dev/js/src/hint/menu.js
index a9a3fb2..bf1a04b 100644
--- a/dev/js/src/hint/menu.js
+++ b/dev/js/src/hint/menu.js
@@ -1,6 +1,9 @@
/**
* Hint menu
*/
+
+"use strict";
+
define([
'menu',
'hint/item',
diff --git a/dev/js/src/hint/prefix.js b/dev/js/src/hint/prefix.js
index dc14d5c..197e36e 100644
--- a/dev/js/src/hint/prefix.js
+++ b/dev/js/src/hint/prefix.js
@@ -1,3 +1,5 @@
+"use strict";
+
define(['menu/prefix'], function (prefixClass) {
return {