Completed
Push — master ( 908ea6...448b39 )
by Maxence
11:53
created

searchbox.onOptionsLoaded   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 3
rs 10
cc 1
nc 1
nop 0
1
/*
2
 * FullTextSearch - Full text search framework for Nextcloud
3
 *
4
 * This file is licensed under the Affero General Public License version 3 or
5
 * later. See the COPYING file.
6
 *
7
 * @author Maxence Lange <[email protected]>
8
 * @copyright 2018
9
 * @license GNU AGPL version 3 or any later version
10
 *
11
 * This program is free software: you can redistribute it and/or modify
12
 * it under the terms of the GNU Affero General Public License as
13
 * published by the Free Software Foundation, either version 3 of the
14
 * License, or (at your option) any later version.
15
 *
16
 * This program is distributed in the hope that it will be useful,
17
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19
 * GNU Affero General Public License for more details.
20
 *
21
 * You should have received a copy of the GNU Affero General Public License
22
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
23
 *
24
 */
25
26
/** global: OCA */
27
/** global: nav */
28
/** global: _ */
29
/** global: api */
30
/** global: search */
31
/** global: result */
32
/** global: fullTextSearch */
33
/** global: settings */
34
35
36
var box_elements = {
37
	searchInput: null,
38
	searchOptions: null,
39
	searchTemplate: null,
40
	searchError: null,
41
	divFullTextSearchIcon: null,
42
	divFullTextSearchPopup: null
43
};
44
45
46
var searchbox = {
47
48
	init: function () {
49
50
		var self = this;
0 ignored issues
show
Unused Code introduced by
The variable self seems to be never used. Consider removing it.
Loading history...
51
52
		// we remove old search
53
		var search_form = $('FORM.searchbox');
54
		if (search_form.length > 0) {
55
			search_form.remove();
56
		}
57
58
59
		var divHeaderRight = $('DIV.header-right');
60
		var divFullTextSearch = $('<div>', {id: 'fulltextsearch'});
61
		divHeaderRight.prepend(divFullTextSearch);
62
63
		box_elements.divFullTextSearchIcon = searchbox.generateFullTextSearchIcon();
64
		box_elements.divFullTextSearchPopup = searchbox.generateFullTextSearchPopup();
65
		divFullTextSearch.append(box_elements.divFullTextSearchIcon);
66
		divFullTextSearch.append(box_elements.divFullTextSearchPopup);
67
68
		OC.registerMenu(box_elements.divFullTextSearchIcon, box_elements.divFullTextSearchPopup,
0 ignored issues
show
Bug introduced by
The variable OC seems to be never declared. If this is a global, consider adding a /** global: OC */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
69
			searchbox.displayedSearchPopup);
70
71
		api.retrieveOptions(settings.searchProviderId);
72
73
		$(window).bind('keydown', function (event) {
74
			if (event.ctrlKey || event.metaKey) {
75
				if (String.fromCharCode(event.which).toLowerCase() === 'f') {
76
					event.preventDefault();
77
					searchbox.displaySearchPopup(true);
78
				}
79
80
				return;
81
			}
82
83
			if (event.which === 27) {
84
				searchbox.displaySearchPopup(false);
85
			}
86
		});
87
88
	},
89
90
91
	generateFullTextSearchIcon: function () {
92
		var className = 'icon-fulltextsearch';
93
		if (OCA.Theming === undefined || !OCA.Theming.inverted) {
94
			className = 'icon-fulltextsearch-white';
95
		}
96
97
		var icon = $('<div>', {
98
			id: 'fts-icon',
99
			tabindex: 0,
100
			role: 'link',
101
			class: className + ' menutoggle'
102
		});
103
104
		icon.fadeTo(0, 0.6);
105
106
		return icon;
107
	},
108
109
110
	generateFullTextSearchPopup: function () {
111
		var popup = $('<div>', {
112
			id: 'fts-popup'
113
		});
114
115
		var self = this;
116
		box_elements.searchInput = $('<input>', {
117
			id: 'fts-input',
118
			placeholder: 'Search ' + settings.searchProviderName
119
		}).on('keyup', self.searching);
120
		box_elements.searchOptions = $('<div>', {id: 'fts-options'});
121
		box_elements.searchTemplate = $('<div>', {id: 'fts-options-template'});
122
		box_elements.searchError = $('<div>', {id: 'fts-error'});
123
124
		var divHeader = $('<div>', {id: 'fts-header'});
125
		divHeader.append($('<div>').append(box_elements.searchInput));
126
127
		popup.append(divHeader);
128
		popup.append(box_elements.searchOptions);
129
		popup.append(box_elements.searchTemplate);
130
		popup.append(box_elements.searchError.hide());
131
132
		return popup;
133
	},
134
135
136
	displaySearchPopup: function (display) {
137
		if (display) {
138
			OC.showMenu(box_elements.divFullTextSearchIcon, box_elements.divFullTextSearchPopup,
0 ignored issues
show
Bug introduced by
The variable OC seems to be never declared. If this is a global, consider adding a /** global: OC */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
139
				searchbox.displayedSearchPopup);
140
		} else {
141
			OC.hideMenus(null);
142
		}
143
	},
144
145
146
	displayedSearchPopup: function () {
147
		box_elements.searchError.hide();
148
		box_elements.searchInput.focus();
149
	},
150
151
152
	searching: function (force) {
153
		var search = box_elements.searchInput.val();
154
		if (force === undefined) {
155
			force = false;
156
		}
157
158
		if (search.length < 1) {
159
			return;
160
		}
161
162
		if (!force && curr.lastRequest === search) {
0 ignored issues
show
Bug introduced by
The variable curr seems to be never declared. If this is a global, consider adding a /** global: curr */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
163
			return;
164
		}
165
		curr.lastRequest = search;
166
		if (!searchbox.timingRequest(force)) {
167
			return;
168
		}
169
170
		api.search({
171
			providers: settings.searchProviderId,
172
			search: search,
173
			page: curr.page,
174
			options: searchbox.getSearchOptions(),
175
			size: 20
176
		});
177
	},
178
179
180
	timingRequest: function (force) {
181
		if (curr.lastRequestTimer === null) {
0 ignored issues
show
Bug introduced by
The variable curr seems to be never declared. If this is a global, consider adding a /** global: curr */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
182
			curr.lastRequestTimer = window.setTimeout(function () {
183
				curr.lastRequestTimer = null;
0 ignored issues
show
Bug introduced by
The variable curr seems to be never declared. If this is a global, consider adding a /** global: curr */ comment.

This checks looks for references to variables that have not been declared. This is most likey a typographical error or a variable has been renamed.

To learn more about declaring variables in Javascript, see the MDN.

Loading history...
184
				if (curr.lastRequestTimerQueued) {
185
					curr.lastRequestTimerQueued = false;
186
					searchbox.searching(curr.lastRequestTimerForcing);
187
				}
188
			}, settings.searchTimer);
189
		} else {
190
			curr.lastRequestTimerQueued = true;
191
			curr.lastRequestTimerForcing = force;
192
			return false;
193
		}
194
195
		return true;
196
	},
197
198
199
	onOptionsLoaded: function (result) {
200
		if (!result[settings.searchProviderId]) {
201
			return;
202
		}
203
204
		if (result[settings.searchProviderId]['options']) {
0 ignored issues
show
Coding Style introduced by
['options'] could be written in dot notation.

You can rewrite this statement in dot notation:

var obj = { };
obj['foo'] = 'bar'; // Bad
obj.foo = 'bar'; // Good
Loading history...
205
			searchbox.generateOptionsHtml(result[settings.searchProviderId]['options']);
0 ignored issues
show
Coding Style introduced by
['options'] could be written in dot notation.

You can rewrite this statement in dot notation:

var obj = { };
obj['foo'] = 'bar'; // Bad
obj.foo = 'bar'; // Good
Loading history...
206
			box_elements.searchOptions.find('INPUT').each(function () {
207
				searchbox.eventOnOptionsLoadedInput($(this));
208
			});
209
		}
210
211
		if (result[settings.searchProviderId]['template']) {
0 ignored issues
show
Coding Style introduced by
['template'] could be written in dot notation.

You can rewrite this statement in dot notation:

var obj = { };
obj['foo'] = 'bar'; // Bad
obj.foo = 'bar'; // Good
Loading history...
212
			box_elements.searchTemplate.html(result[settings.searchProviderId]['template']);
0 ignored issues
show
Coding Style introduced by
['template'] could be written in dot notation.

You can rewrite this statement in dot notation:

var obj = { };
obj['foo'] = 'bar'; // Bad
obj.foo = 'bar'; // Good
Loading history...
213
			box_elements.searchTemplate.find('INPUT').each(function () {
214
				searchbox.eventOnOptionsLoadedInput($(this))
0 ignored issues
show
Coding Style introduced by
There should be a semicolon.

Requirement of semicolons purely is a coding style issue since JavaScript has specific rules about semicolons which are followed by all browsers.

Further Readings:

Loading history...
215
			});
216
		}
217
	},
218
219
220
	eventOnOptionsLoadedInput: function (div) {
221
		div.on('change keyup', function () {
222
			searchbox.searching(true);
223
		});
224
	},
225
226
227
	generateOptionsHtml: function (options) {
228
		var div = $('<div>', {class: 'div-table'});
229
230
		for (var j = 0; j < options.length; j++) {
231
			var sub = options[j];
232
			searchbox.displayPanelCheckbox(div, sub);
233
			searchbox.displayPanelInput(div, sub);
234
		}
235
236
		box_elements.searchOptions.append(div);
237
	},
238
239
240
	displayPanelOptionTitle (sub) {
0 ignored issues
show
Backwards Compatibility introduced by
'concise methods' is available in ES6 (use 'esversion: 6') or Mozilla JS extensions (use moz).
Loading history...
241
		var subDiv = $('<div>', {
242
			class: 'div-table-row'
243
		});
244
245
		subDiv.append($('<div>',
246
			{
247
				class: 'div-table-col div-table-col-left'
248
			}).append($('<span>', {
249
			class: 'leftcol',
250
			text: sub.title
251
		})));
252
253
		subDiv.append($('<div>',
254
			{class: 'div-table-col div-table-col-right'}));
255
256
		return subDiv;
257
	},
258
259
260
	displayPanelCheckbox: function (div, sub) {
261
		if (sub.type !== 'checkbox') {
262
			return;
263
		}
264
265
		var subDiv = searchbox.displayPanelOptionTitle(sub);
266
		var subDivInput = $('<input>', {
267
			type: 'checkbox',
268
			id: sub.name,
269
			value: 1
270
		});
271
		subDiv.find('.div-table-col-right').append(subDivInput);
272
		div.append(subDiv);
273
	},
274
275
276
	displayPanelInput: function (div, sub) {
277
		if (sub.type !== 'input') {
278
			return;
279
		}
280
281
		var subDiv = searchbox.displayPanelOptionTitle(sub);
282
		var subDivInput = $('<input>', {
283
			class: 'fts_options_input fts_options_input_' + sub.size,
284
			type: 'text',
285
			placeholder: sub.placeholder,
286
			id: sub.name
287
		});
288
		subDiv.find('.div-table-col-right').append(subDivInput);
289
		div.append(subDiv);
290
	},
291
292
293
	getSearchOptions: function () {
294
		var options = {};
295
296
		if (box_elements.searchTemplate === null) {
297
			return options;
298
		}
299
300
		box_elements.searchOptions.find('INPUT').each(function () {
301
			searchbox.getSearchOptionsFromInput($(this), options);
302
		});
303
		box_elements.searchTemplate.find('INPUT').each(function () {
304
			searchbox.getSearchOptionsFromInput($(this), options);
305
		});
306
307
		return options;
308
	},
309
310
311
	getSearchOptionsFromInput: function (div, options) {
312
		var value = div.val();
313
314
		if (div.attr('type') === 'checkbox' && !div.is(':checked')) {
315
			value = '';
316
		}
317
318
		options[div.attr('id')] = value;
319
	}
320
321
322
};
323
324
325