Integrated hint alerts in the main frame
diff --git a/dev/demo/all.html b/dev/demo/all.html
index a01fcc3..67c50fd 100644
--- a/dev/demo/all.html
+++ b/dev/demo/all.html
@@ -27,6 +27,7 @@
placeholder="Find ..."
name="q"
id="q-field"
+ value="abcdefghijklmnopqrstuvwxyz"
autofocus="autofocus" />
<button type="submit"><span>Go</span></button>
<!-- <i class="fa fa-arrow-circle-down show-hint" onclick="hint.popUp()"></i> -->
@@ -85,7 +86,7 @@
</div>
<script>
- KorAP.koralQuery = {"matches":["..."],"query":{"wrap":{"layer":"orth","match":"match:eq","foundry":"opennlp","key":"Goethe","@type":"koral:term"},"@type":"koral:token"},"meta":{"serialQuery":"tokens:s:Goethe","startIndex":0,"version":"unknown","itemsPerPage":25,"context":"p","benchmark":"0.103553092 s","totalResults":-1}};
+ KorAP.koralQuery = {"matches":["..."],"errors":[[302,"Parantheses\/brackets unbalanced.","20"]],"query":{"wrap":{"layer":"orth","match":"match:eq","foundry":"opennlp","key":"Goethe","@type":"koral:term"},"@type":"koral:token"},"meta":{"serialQuery":"tokens:s:Goethe","startIndex":0,"version":"unknown","itemsPerPage":25,"context":"p","benchmark":"0.103553092 s","totalResults":-1}};
</script>
<div id="search">
diff --git a/dev/demo/hintdemo.js b/dev/demo/hintdemo.js
index fd80b43..3eb38cc 100644
--- a/dev/demo/hintdemo.js
+++ b/dev/demo/hintdemo.js
@@ -16,5 +16,5 @@
function demoAlert (pos, msg) {
if (hint !== undefined)
- hint.charAlert(pos, msg);
+ hint.alert(pos, msg);
}
diff --git a/dev/js/spec/hintSpec.js b/dev/js/spec/hintSpec.js
index 554b61d..c944410 100644
--- a/dev/js/spec/hintSpec.js
+++ b/dev/js/spec/hintSpec.js
@@ -53,9 +53,10 @@
afterAll(function () {
try {
- document.getElementsByTagName("body")[0].removeChild(
- document.getElementById("searchMirror")
- );
+ var mirrors = document.querySelectorAll(".hint.mirror");
+ for (var i in mirrors) {
+ mirrors[i].parentNode.removeChild(mirrors[i])
+ };
}
catch (e) {};
});
@@ -168,6 +169,34 @@
expect(hint).toBeTruthy();
});
+
+ it('should alert at char pos', function () {
+ var hint = hintClass.create({
+ inputField : input
+ });
+
+ expect(hint.active()).toBeFalsy();
+
+ expect(hint.alert(4, 'That does not work!')).toBeTruthy();
+
+ expect(hint.active()).toBeTruthy();
+
+ var container = hint.inputField().container();
+ expect(container.firstChild.classList.contains('hint')).toBe(true);
+ expect(container.firstChild.classList.contains('alert')).toBe(true);
+ expect(container.firstChild.textContent).toEqual('That does not work!');
+ expect(hint.inputField().mirrorValue()).toEqual('abcd');
+
+ expect(hint.alert(4, 'That does not work!')).toBeFalsy();
+
+ // Update - meaning: hide alert
+ hint.update();
+
+ expect(hint.alert().active).toBeFalsy();
+
+ expect(hint.active()).toBeFalsy();
+
+ });
});
describe('KorAP.HintMenuItem', function () {
diff --git a/dev/js/src/hint.js b/dev/js/src/hint.js
index 4f55d0f..455312d 100644
--- a/dev/js/src/hint.js
+++ b/dev/js/src/hint.js
@@ -14,10 +14,12 @@
'hint/input',
'hint/menu',
'hint/contextanalyzer',
+ 'hint/alert',
'util'
], function (inputClass,
- menuClass,
- analyzerClass) {
+ menuClass,
+ analyzerClass,
+ alertClass) {
"use strict";
/**
@@ -52,7 +54,7 @@
// Some variables
// _firstTry : true,
- active : false,
+ // active : false,
/**
* Create new hint helper.
@@ -66,29 +68,27 @@
param = param || {};
// Holds all menus per prefix context
- this._menu = {};
+ this._menu = {};
+ this._alert = alertClass.create();
+ this._active = false;
// Get input field
var 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 that = this;
+ var c = this._inputField.container();
- // Add event listener for key pressed down
- inputFieldElement.addEventListener(
- "keydown", function (e) {
- var code = _codeFromEvent(e);
- if (code === 40) {
- that.show(false);
- e.halt();
- };
- }, false
- );
+ // create alert
+ c.appendChild(this._alert.element());
+
+
+ var that = this;
this._inputField.container().addEventListener('click', function (e) {
if (!this.classList.contains('active')) {
@@ -96,14 +96,22 @@
};
});
- var _up = function (e) {
- var input = that._inputField;
- input.update();
+ var _down = function (e) {
+ var code = _codeFromEvent(e);
+ if (code === 40) {
+ this.show(false);
+ e.halt();
+ };
};
// Move infobox
- inputFieldElement.addEventListener("keyup", _up);
- inputFieldElement.addEventListener("click", _up);
+ inputFieldElement.addEventListener("keyup", this.update.bind(this));
+ inputFieldElement.addEventListener("click", this.update.bind(this));
+
+ // Add event listener for key pressed down
+ inputFieldElement.addEventListener(
+ "keydown", _down.bind(this), false
+ );
// Set Analyzer for context
this._analyzer = analyzerClass.create(
@@ -124,15 +132,37 @@
/**
* Altert at a specific character position.
*/
- charAlert : function (charPos, msg) {
+ alert : function (charPos, msg) {
+
+ if (arguments.length === 0)
+ return this._alert;
+
+ // Do not alert if already alerted!
+ if (this._alert.active)
+ return false;
+
+ // Move to the correct position
this._inputField.moveto(charPos);
- var c = this._inputField.container();
- c.classList.add('active');
- var error = c.appendChild(document.createElement('div'));
- error.classList.add('alert', 'hint');
- error.appendChild(document.createTextNode(msg));
+
+ // Set container to active (aka hide the hint helper button)
+
+ this._alert.show(msg);
+ this.active(true);
+ return true;
},
+ _unshowAlert : function () {
+ this._alert.unshow();
+ this.active(false);
+ },
+
+ update : function () {
+ this._inputField.update();
+ if (this._alert.unshow())
+ this.active(false);
+ },
+
+
/**
* Return hint menu and probably init based on an action
*/
@@ -169,6 +199,21 @@
return this.menu(context);
},
+ active : function (bool) {
+ if (arguments.length === 1) {
+ var c = this._inputField.container();
+ if (bool && !this._active) {
+ c.classList.add('active');
+ this._active = true;
+ }
+ else {
+ c.classList.remove('active');
+ this._active = false;
+ }
+ };
+ return this._active;
+ },
+
/**
* Show the menu.
@@ -178,20 +223,30 @@
show : function (ifContext) {
// Menu is already active
- if (this.active)
- return;
+ if (this.active()) {
+
+ // Alert is not active
+ if (!this._alert.unshow())
+ return;
+ };
// Get the menu
var menu;
if (menu = this.contextMenu(ifContext)) {
var c = this._inputField.container();
- c.classList.add('active');
+ this.active(true);
+ // c.classList.add('active');
c.appendChild(menu.element());
menu.show();
menu.focus();
// Focus on input field
// this.inputField.element.focus();
};
+ },
+
+ unshow : function () {
+ this.active(false);
+ this.inputField().element().focus();
}
};
});
diff --git a/dev/js/src/hint/alert.js b/dev/js/src/hint/alert.js
new file mode 100644
index 0000000..a5b43de
--- /dev/null
+++ b/dev/js/src/hint/alert.js
@@ -0,0 +1,35 @@
+/**
+ * Hint menu alert
+ */
+define(function () {
+ "use strict";
+ return {
+ create : function (msg) {
+ return Object.create(this)._init(msg);
+ },
+ _init : function (msg) {
+ this.active = false;
+ this._element = document.createElement('div');
+ this._element.style.opacity = 0;
+ this._element.classList.add('alert', 'hint');
+ return this;
+ },
+ show : function (msg) {
+ this._element.textContent = msg;
+ this.active = true;
+ this._element.style.opacity = 1;
+ },
+
+ unshow : function () {
+ if (!this.active)
+ return false;
+ this._element.style.opacity = 0;
+ this.active = false;
+ return true;
+ },
+
+ element : function () {
+ return this._element;
+ }
+ }
+});
diff --git a/dev/js/src/hint/input.js b/dev/js/src/hint/input.js
index 6e02793..7145919 100644
--- a/dev/js/src/hint/input.js
+++ b/dev/js/src/hint/input.js
@@ -49,6 +49,13 @@
return this._element.value;
},
+ /**
+ * Get the value of the input field mirror.
+ */
+ mirrorValue : function () {
+ return this._mirror.firstChild.textContent;
+ },
+
/**
* Update the mirror content.
@@ -130,14 +137,14 @@
// Create mirror for searchField
// This is important for positioning
- if ((this._mirror = document.getElementById("searchMirror")) === null) {
+ // if ((this._mirror = document.getElementById("searchMirror")) === null) {
this._mirror = document.createElement("div");
- this._mirror.setAttribute("id", "searchMirror");
+ this._mirror.classList.add('hint', 'mirror');
this._mirror.appendChild(document.createElement("span"));
this._container = this._mirror.appendChild(document.createElement("div"));
this._mirror.style.height = "0px";
document.getElementsByTagName("body")[0].appendChild(this._mirror);
- };
+// };
// Update position of the mirror
window.addEventListener('resize', this.reposition.bind(this));
diff --git a/dev/js/src/hint/item.js b/dev/js/src/hint/item.js
index 7d97334..317dae7 100644
--- a/dev/js/src/hint/item.js
+++ b/dev/js/src/hint/item.js
@@ -54,8 +54,6 @@
var input = h.inputField();
input.insert(this._action).update();
- h.active = false;
-
e.halt();
h.show(true);
diff --git a/dev/js/src/hint/menu.js b/dev/js/src/hint/menu.js
index 7d89e51..df27a11 100644
--- a/dev/js/src/hint/menu.js
+++ b/dev/js/src/hint/menu.js
@@ -28,9 +28,7 @@
// Focus on input field on hide
obj.onHide = function () {
- var input = this._hint.inputField();
- input.container().classList.remove('active');
- input.element().focus();
+ this._hint.unshow();
};
return obj;
diff --git a/dev/js/src/init.js b/dev/js/src/init.js
index c003a1d..3b911b6 100644
--- a/dev/js/src/init.js
+++ b/dev/js/src/init.js
@@ -178,6 +178,17 @@
};
};
+ if (KorAP.koralQuery["errors"]) {
+ var errors = KorAP.koralQuery["errors"];
+ for (var i in errors) {
+ if (errors[i][0] === 302) {
+ obj.hint = hintClass.create();
+ obj.hint.alert(errors[i][2], errors[i][1]);
+ break;
+ }
+ }
+ };
+
// Session has KQ visibility stored
if (show["kq"])
showKQ.apply();
@@ -303,7 +314,8 @@
*/
// Todo: Pass an element, so this works with
// tutorial pages as well!
- obj.hint = hintClass.create();
+ if (obj.hint === undefined)
+ obj.hint = hintClass.create();
return obj;
});
diff --git a/dev/scss/header/hint.scss b/dev/scss/header/hint.scss
index a50ffbf..5659a2e 100644
--- a/dev/scss/header/hint.scss
+++ b/dev/scss/header/hint.scss
@@ -28,7 +28,7 @@
}
div.alert.hint {
- position: relative;
+ position: absolute;
background-color: rgba(254,26,0,.9); // from alertify
color: $nearly-white;
padding: $item-padding;
@@ -38,6 +38,10 @@
radius: $standard-border-radius;
top-left-radius: 0;
}
+ width: auto;
+ min-width: 10em;
+ max-width: 23em !important;
+ transition: opacity 0.2s ease 0s;
}
div.hint.alert::before {
@@ -55,11 +59,7 @@
}
}
-
-
-
-
-#searchMirror {
+.hint.mirror {
position: absolute;
left: 0;
top: 0;
@@ -72,7 +72,7 @@
white-space: pre-wrap;
overflow: hidden;
}
- // Todo: Besser nur, wenn im Focus
+ // TODO: Only in focus
> div {
position: absolute;
display: block;