blob: 4f55d0fae7fd2a069a521482d558cd77e415c261 [file] [log] [blame]
Nils Diewald19ccee92014-12-08 11:30:08 +00001/**
Nils Diewald5c5a7472015-04-02 22:13:38 +00002 * Hint menu for Kalamar.
Nils Diewald47f366b2015-04-15 20:06:35 +00003 * Based on menu object.
Nils Diewald19ccee92014-12-08 11:30:08 +00004 *
5 * @author Nils Diewald
6 */
Akron308db382016-05-30 22:34:07 +02007/*
8 * TODO: List can be shown when prefix is like 'base/s=pcorenlp/'
9 * TODO: Sometimes the drop-down box down vanish when list is shown
10 * TODO: Create should expect an input text field
11 * TODO: Embed only one single menu (not multiple)
12 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000013define([
14 'hint/input',
15 'hint/menu',
16 'hint/contextanalyzer',
17 'util'
18], function (inputClass,
19 menuClass,
20 analyzerClass) {
Nils Diewald19ccee92014-12-08 11:30:08 +000021 "use strict";
22
Nils Diewald19ccee92014-12-08 11:30:08 +000023 /**
24 * @define {regex} Regular expression for context
25 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000026 KorAP.context = KorAP.context ||
Nils Diewald19ccee92014-12-08 11:30:08 +000027 "(?:^|[^-_a-zA-Z0-9])" + // Anchor
28 "((?:[-_a-zA-Z0-9]+?)\/" + // Foundry
29 "(?:" +
30 "(?:[-_a-zA-Z0-9]+?)=" + // Layer
Akron113cc1a2016-01-22 21:17:57 +010031 "(?:"+
32 "(?:[^:=\/ ]+?):|" + // Key
Akron308db382016-05-30 22:34:07 +020033 "(?:[^-=\/ ]+?)-" + // Node
Akron113cc1a2016-01-22 21:17:57 +010034 ")?" +
Nils Diewald19ccee92014-12-08 11:30:08 +000035 ")?" +
36 ")$";
Nils Diewald19ccee92014-12-08 11:30:08 +000037 KorAP.hintArray = KorAP.hintArray || {};
38
Nils Diewald0e6992a2015-04-14 20:13:52 +000039 /**
40 * Return keycode based on event
41 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000042
43 // Initialize hint array
Nils Diewald5c5a7472015-04-02 22:13:38 +000044
45 /**
46 * KorAP.Hint.create({
47 * inputField : node,
48 * context : context regex
49 * });
50 */
Nils Diewald0e6992a2015-04-14 20:13:52 +000051 return {
Nils Diewald5c5a7472015-04-02 22:13:38 +000052
53 // Some variables
54 // _firstTry : true,
55 active : false,
56
Nils Diewald0e6992a2015-04-14 20:13:52 +000057 /**
58 * Create new hint helper.
59 */
Nils Diewald5c5a7472015-04-02 22:13:38 +000060 create : function (param) {
Nils Diewald0e6992a2015-04-14 20:13:52 +000061 return Object.create(this)._init(param);
Nils Diewald5c5a7472015-04-02 22:13:38 +000062 },
63
Nils Diewald0e6992a2015-04-14 20:13:52 +000064 // Initialize hint helper
Nils Diewald5c5a7472015-04-02 22:13:38 +000065 _init : function (param) {
66 param = param || {};
67
68 // Holds all menus per prefix context
69 this._menu = {};
70
71 // Get input field
Nils Diewald0e6992a2015-04-14 20:13:52 +000072 var qfield = param["inputField"] || document.getElementById("q-field");
73 if (!qfield)
74 return null;
75
76 this._inputField = inputClass.create(qfield);
Nils Diewald5c5a7472015-04-02 22:13:38 +000077
78 var inputFieldElement = this._inputField.element();
79
80 var that = this;
81
82 // Add event listener for key pressed down
83 inputFieldElement.addEventListener(
Nils Diewald47f366b2015-04-15 20:06:35 +000084 "keydown", function (e) {
Nils Diewald5c5a7472015-04-02 22:13:38 +000085 var code = _codeFromEvent(e);
86 if (code === 40) {
87 that.show(false);
88 e.halt();
89 };
90 }, false
91 );
92
Nils Diewald47f366b2015-04-15 20:06:35 +000093 this._inputField.container().addEventListener('click', function (e) {
94 if (!this.classList.contains('active')) {
95 that.show(false);
96 };
97 });
98
99 var _up = function (e) {
100 var input = that._inputField;
101 input.update();
102 };
103
104 // Move infobox
105 inputFieldElement.addEventListener("keyup", _up);
106 inputFieldElement.addEventListener("click", _up);
Nils Diewald5c5a7472015-04-02 22:13:38 +0000107
108 // Set Analyzer for context
Nils Diewald0e6992a2015-04-14 20:13:52 +0000109 this._analyzer = analyzerClass.create(
Nils Diewald5c5a7472015-04-02 22:13:38 +0000110 param["context"] || KorAP.context
111 );
Nils Diewald19ccee92014-12-08 11:30:08 +0000112 return this;
113 },
114
Akron308db382016-05-30 22:34:07 +0200115
116 /**
117 * Return the input field attached to the hint helper.
118 */
Nils Diewald5c5a7472015-04-02 22:13:38 +0000119 inputField : function () {
120 return this._inputField;
121 },
Nils Diewald19ccee92014-12-08 11:30:08 +0000122
Akron308db382016-05-30 22:34:07 +0200123
124 /**
125 * Altert at a specific character position.
126 */
127 charAlert : function (charPos, msg) {
128 this._inputField.moveto(charPos);
129 var c = this._inputField.container();
130 c.classList.add('active');
131 var error = c.appendChild(document.createElement('div'));
132 error.classList.add('alert', 'hint');
133 error.appendChild(document.createTextNode(msg));
134 },
135
Nils Diewald5c5a7472015-04-02 22:13:38 +0000136 /**
Nils Diewald5c5a7472015-04-02 22:13:38 +0000137 * Return hint menu and probably init based on an action
138 */
139 menu : function (action) {
140
141 if (this._menu[action] === undefined) {
142
143 // No matching hint menu
144 if (KorAP.hintArray[action] === undefined)
145 return;
146
147 // Create matching hint menu
Nils Diewald0e6992a2015-04-14 20:13:52 +0000148 this._menu[action] = menuClass.create(
Nils Diewald5c5a7472015-04-02 22:13:38 +0000149 this, action, KorAP.hintArray[action]
Nils Diewald19ccee92014-12-08 11:30:08 +0000150 );
Nils Diewald5c5a7472015-04-02 22:13:38 +0000151 };
152
153 // Return matching hint menu
154 return this._menu[action];
155 },
156
157 /**
158 * Get the correct menu based on the context
159 */
160 contextMenu : function (ifContext) {
161 var context = this._inputField.context();
162 if (context === undefined || context.length == 0)
163 return ifContext ? undefined : this.menu("-");
164
165 context = this._analyzer.test(context);
166 if (context === undefined || context.length == 0)
167 return ifContext ? undefined : this.menu("-");
168
169 return this.menu(context);
170 },
171
172
173 /**
Akron308db382016-05-30 22:34:07 +0200174 * Show the menu.
175 * Currently this means that multiple menus may be loaded
176 * but not shown.
Nils Diewald5c5a7472015-04-02 22:13:38 +0000177 */
178 show : function (ifContext) {
179
180 // Menu is already active
181 if (this.active)
182 return;
183
Nils Diewald5c5a7472015-04-02 22:13:38 +0000184 // Get the menu
185 var menu;
186 if (menu = this.contextMenu(ifContext)) {
Nils Diewald2488d052015-04-09 21:46:02 +0000187 var c = this._inputField.container();
188 c.classList.add('active');
189 c.appendChild(menu.element());
Akron6ed13992016-05-23 18:06:05 +0200190 menu.show();
Nils Diewald5c5a7472015-04-02 22:13:38 +0000191 menu.focus();
Akron308db382016-05-30 22:34:07 +0200192 // Focus on input field
193 // this.inputField.element.focus();
Nils Diewald19ccee92014-12-08 11:30:08 +0000194 };
195 }
196 };
Nils Diewald0e6992a2015-04-14 20:13:52 +0000197});