blob: 3b79bddec987178bbe6c4cc5e12cca7938fc633f [file] [log] [blame]
Nils Diewaldfda29d92015-01-22 17:28:01 +00001var KorAP = KorAP || {};
2
3(function (KorAP) {
4 "use strict";
5
6 /**
7 * Item in the Dropdown menu
8 */
9 KorAP.MenuItem = {
10
11 /**
12 * Create a new MenuItem object.
13 *
14 * @constructor
15 * @this {MenuItem}
16 * @param {Array.<string>} An array object of name, action and
17 * optionally a description
18 */
19 create : function (params) {
20 return Object.create(KorAP.MenuItem)._init(params);
21 },
22
23 /**
24 * Upgrade this object to another object,
25 * while private data stays intact.
26 *
27 * @param {Object] An object with properties.
28 */
29 upgradeTo : function (props) {
30 for (var prop in props) {
31 this[prop] = props[prop];
32 };
33 return this;
34 },
35
36 content : function (content) {
37 if (arguments.length === 1)
38 this._content = document.createTextNode(content);
39 return this._content;
40 },
41
42 lcField : function () {
43 return this._lcField;
44 },
45
46 action : function (action) {
47 if (arguments.length === 1)
48 this._action = action;
49 return this._action;
50 },
51
52 /**
53 * Check or set if the item is active
54 *
55 * @param {boolean|null} State of activity
56 */
57 active : function (bool) {
58 var cl = this.element().classList;
59 if (bool === undefined)
60 return cl.contains("active");
61 else if (bool)
62 cl.add("active");
63 else
64 cl.remove("active");
65 },
66
67 /**
68 * Check or set if the item is
69 * at the boundary of the menu
70 * list
71 *
72 * @param {boolean|null} State of activity
73 */
74 noMore : function (bool) {
75 var cl = this.element().classList;
76 if (bool === undefined)
77 return cl.contains("no-more");
78 else if (bool)
79 cl.add("no-more");
80 else
81 cl.remove("no-more");
82 },
83
84 /**
85 * Get the document element of the menu item
86 */
87 element : function () {
88 // already defined
89 if (this._element !== undefined)
90 return this._element;
91
92 // Create list item
93 var li = document.createElement("li");
94
95 // Connect action
96 li["action"] = this._action;
97
98 // Append template
99 li.appendChild(this.content());
100
101 return this._element = li;
102 },
103
104 /**
105 * Highlight parts of the item
106 *
107 * @param {string} Prefix string for highlights
108 */
109 highlight : function (prefix) {
110 this._highlight(this.element().firstChild, prefix);
111 },
112
113 // Highlight a certain substring of the menu item
114 _highlight : function (elem, prefix) {
115
116 if (elem.nodeType === 3) {
117
118 var text = elem.nodeValue;
119 var textlc = text.toLowerCase();
120 var pos = textlc.indexOf(prefix);
121 if (pos >= 0) {
122
123 // First element
124 if (pos > 0) {
125 elem.parentNode.insertBefore(
126 document.createTextNode(text.substr(0, pos)),
127 elem
128 );
129 };
130
131 // Second element
132 var hl = document.createElement("mark");
133 hl.appendChild(
134 document.createTextNode(text.substr(pos, prefix.length))
135 );
136 elem.parentNode.insertBefore(hl, elem);
137
138 // Third element
139 var third = text.substr(pos + prefix.length);
140 if (third.length > 0) {
141 var thirdE = document.createTextNode(third);
142 elem.parentNode.insertBefore(
143 thirdE,
144 elem
145 );
146 this._highlight(thirdE, prefix);
147 };
148
149 var p = elem.parentNode;
150 p.removeChild(elem);
151 };
152 }
153 else {
154 var children = elem.childNodes;
155 for (var i = children.length -1; i >= 0; i--) {
156 this._highlight(children[i], prefix);
157 };
158 };
159 },
160
161
162 /**
163 * Remove highlight of the menu item
164 */
165 lowlight : function () {
166 var e = this.element();
167
168 var marks = e.getElementsByTagName("mark");
169 for (var i = marks.length - 1; i >= 0; i--) {
170 // Create text node clone
171 var x = document.createTextNode(
172 marks[i].firstChild.nodeValue
173 );
174
175 // Replace with content
176 marks[i].parentNode.replaceChild(
177 x,
178 marks[i]
179 );
180 };
181
182 // Remove consecutive textnodes
183 e.normalize();
184 },
185
186 // Initialize menu item
187 _init : function (params) {
188 if (params[0] === undefined)
189 throw new Error("Missing parameters");
190
191 this.content(params[0]);
192
193 if (params.length === 2)
194 this._action = params[1];
195
196 this._lcField = ' ' + this.content().textContent.toLowerCase();
197
198 return this;
199 },
200 };
201
202}(this.KorAP));