Completed
Push — master ( 85b016...ef6491 )
by Maxence
01:57
created

Navigate.displayPanelInput   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 18

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
c 0
b 0
f 0
dl 0
loc 18
rs 9.4285
cc 2
nc 2
nop 2

1 Function

Rating   Name   Duplication   Size   Complexity  
A 0 3 1
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
27
/** global: OCA */
28
/** global: _ */
29
30
var fullTextSearch = OCA.FullTextSearch.api;
31
32
33
var elements = {
34
	searchTimeout: null,
35
	search_input: null,
36
	search_submit: null,
37
	search_result: null,
38
	search_json: null
39
};
40
41
var Navigate = function () {
42
	this.init();
43
};
44
45
Navigate.prototype = {
46
47
	currentTagsResult: {},
48
	selectedTags: {},
49
50
	init: function () {
51
		var self = this;
52
53
		elements.search_input = $('#search_input');
54
		elements.search_submit = $('#search_submit');
55
		elements.search_result = $('#search_result');
56
		elements.search_panels = $('#search_navigation');
57
//		elements.search_json = $('#search_json');
58
		elements.divHeader = $('#search_header');
59
		box_elements.searchError = $('#search_error');
0 ignored issues
show
Bug introduced by
The variable box_elements seems to be never declared. If this is a global, consider adding a /** global: box_elements */ 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...
60
61
		fullTextSearch.setEntryTemplate($('#template_entry'), self);
62
		fullTextSearch.setResultContainer(elements.search_result);
63
64
		elements.search_input.on('input', function () {
65
			self.resetSearch();
66
			if (elements.searchTimeout === null && self.initSearch()) {
67
				elements.searchTimeout = _.delay(function () {
68
					self.initSearch();
69
					elements.searchTimeout = null;
70
				}, 3000);
71
			}
72
		});
73
74
		//
75
		// $(document).keypress(function (e) {
76
		// 	if (e.which === 13) {
77
		// 		self.initSearch(true);
78
		// 	}
79
		// });
80
81
		self.initPanels();
82
	},
83
84
85
	initPanels: function () {
86
		var self = this;
87
88
		$.ajax({
89
			method: 'GET',
90
			url: OC.generateUrl('/apps/fulltextsearch/navigation/panels')
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...
91
		}).done(function (res) {
92
			self.displayPanels(res);
93
		});
94
	},
95
96
97
	displayPanels: function (data) {
98
		var self = this;
99
100
		var ak = Object.keys(data);
101
		for (var i = 0; i < ak.length; i++) {
102
			var providerAppId = ak[i];
103
			var title = data[ak[i]]['title'];
0 ignored issues
show
Coding Style introduced by
['title'] 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...
104
			var nav = data[ak[i]]['navigation'];
0 ignored issues
show
Coding Style introduced by
['navigation'] 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...
105
			var providerId = data[ak[i]]['provider'];
0 ignored issues
show
Coding Style introduced by
['provider'] 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...
106
107
			if (nav.css !== undefined) {
108
				OC.addStyle(providerAppId, nav.css);
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...
109
			}
110
111
			var li = $('<li>', {class: (nav.options !== undefined) ? 'collapsible open' : ''});
112
			var aIcon = $('<a>', {
113
				href: '#',
114
				class: (nav.icon !== undefined) ? nav.icon : 'search_icon'
115
			});
116
			aIcon.text(title);
117
118
			var ul = $('<ul>');
119
			if (nav.options !== undefined) {
120
121
				aIcon.on('click', function () {
0 ignored issues
show
Bug introduced by
It is generally not recommended to make functions within a loop.

While making functions in a loop will not lead to any runtime error, the code might not behave as you expect as the variables in the scope are not imported by value, but by reference. Let’s take a look at an example:

var funcs = [];
for (var i=0; i<10; i++) {
    funcs.push(function() {
        alert(i);
    });
}

funcs[0](); // alert(10);
funcs[1](); // alert(10);
/// ...
funcs[9](); // alert(10);

If you would instead like to bind the function inside the loop to the value of the variable during that specific iteration, you can create the function from another function:

var createFunc = function(i) {
    return function() {
        alert(i);
    };
};

var funcs = [];
for (var i=0; i<10; i++) {
    funcs.push(createFunc(i));
}

funcs[0](); // alert(0)
funcs[1](); // alert(1)
// ...
funcs[9](); // alert(9)
Loading history...
122
					var li = $(this).closest('li');
123
					if (li.hasClass('open')) {
124
						li.removeClass('open');
125
					} else {
126
						li.addClass('open');
127
					}
128
				});
129
130
				for (var j = 0; j < nav.options.length; j++) {
131
					var sub = nav.options[j];
132
					self.displayPanelCheckbox(ul, sub);
133
					self.displayPanelInput(ul, sub);
134
					self.displayPanelTags(ul, sub);
135
					self.displayPanelSearch(providerAppId, ul, sub);
136
					//
137
					// <p id="tag_filter" class="open">
138
					// 		<input value="" style="display: none;" type="text">
139
					// 		<ul class="tagit ui-widget ui-widget-content ui-corner-all">
140
					// 		<li class="tagit-new">
141
					// 		<input class="ui-widget-content ui-autocomplete-input"
142
					// placeholder="Filter by tag" autocomplete="off" type="text"> <span role="status"
143
					// aria-live="polite" class="ui-helper-hidden-accessible"> 1 result is available,
144
					// use up and down arrow keys to navigate.</span></li> <li class="tagit-choice
145
					// ui-widget-content ui-state-default ui-corner-all"> <span
146
					// class="tagit-label">test</span><a class="close"><span class="text-icon">×</span>
147
					// <span class="ui-icon ui-icon-close"></span></a></li> <li class="tagit-choice
148
					// ui-widget-content ui-state-default ui-corner-all"> <span
149
					// class="tagit-label">perdu</span><a class="close"><span class="text-icon">×</span>
150
					// <span class="ui-icon ui-icon-close"></span></a></li></ul> </p>
151
152
153
				}
154
			}
155
156
			li.append(aIcon);
157
			var aInput = $('<input>', {
158
				class: 'search_checkbox',
159
				type: 'checkbox',
160
				'data-provider': ak[i],
161
				'data-provider-id': providerId
162
			});
163
			aInput.change(function () {
0 ignored issues
show
Bug introduced by
It is generally not recommended to make functions within a loop.

While making functions in a loop will not lead to any runtime error, the code might not behave as you expect as the variables in the scope are not imported by value, but by reference. Let’s take a look at an example:

var funcs = [];
for (var i=0; i<10; i++) {
    funcs.push(function() {
        alert(i);
    });
}

funcs[0](); // alert(10);
funcs[1](); // alert(10);
/// ...
funcs[9](); // alert(10);

If you would instead like to bind the function inside the loop to the value of the variable during that specific iteration, you can create the function from another function:

var createFunc = function(i) {
    return function() {
        alert(i);
    };
};

var funcs = [];
for (var i=0; i<10; i++) {
    funcs.push(createFunc(i));
}

funcs[0](); // alert(0)
funcs[1](); // alert(1)
// ...
funcs[9](); // alert(9)
Loading history...
164
				self.initSearch();
165
			});
166
167
			li.append(aInput);
168
			li.append(ul);
169
170
			elements.search_panels.append(li);
171
		}
172
173
	},
174
175
176
	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...
177
		return $('<a>', {
178
			href: '#',
179
			class: 'ulsub',
180
			text: sub.title
181
		});
182
	},
183
184
	displayPanelCheckbox: function (ul, sub) {
185
186
		if (sub.type !== 'checkbox') {
187
			return;
188
		}
189
190
		var subA = this.displayPanelOptionTitle(sub);
191
		var subAInput = $('<input>', {
192
			class: 'search_checkbox_sub',
193
			type: 'checkbox',
194
			'data-option': sub.name
195
		});
196
		subAInput.change(function () {
197
			self.initSearch();
0 ignored issues
show
Bug introduced by
The variable self seems to be never declared. If this is a global, consider adding a /** global: self */ 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...
198
		});
199
200
		ul.append($('<li>').append(subA).append(subAInput));
201
	},
202
203
204
	displayPanelInput: function (ul, sub) {
205
		if (sub.type !== 'input') {
206
			return;
207
		}
208
209
		var subA = this.displayPanelOptionTitle(sub);
210
		var subAInput = $('<input>', {
211
			class: 'search_input_sub search_input_sub_' + sub.size,
212
			type: 'text',
213
			placeholder: sub.placeholder,
214
			'data-option': sub.name
215
		});
216
		subAInput.on('input', function () {
217
			self.initSearch();
0 ignored issues
show
Bug introduced by
The variable self seems to be never declared. If this is a global, consider adding a /** global: self */ 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...
218
		});
219
220
		ul.append($('<li>').append(subA).append(subAInput));
221
	},
222
223
224
	displayPanelTags: function (ul, sub) {
225
		if (sub.type !== 'tags') {
226
			return;
227
		}
228
229
		var subAInput = $('<input>', {
230
			id: sub.name,
231
			class: 'search_tags_sub',
232
			type: 'text',
233
			placeholder: sub.title,
234
			list: sub.name + '_datalist',
235
			'data-option': sub.name
236
		});
237
238
		var subADataList = $('<datalist>', {
239
			id: sub.name + '_datalist'
240
		});
241
242
		sub.list.forEach(function (item) {
243
			subADataList.append($('<option>', {value: item}));
244
		});
245
246
247
		/**
248
		 * <div class="systemTagsInfoView">
249
		 *       <div class="systemTagsInputFieldContainer">
250
		 *           <div id="s2id_autogen15" class="select2-container select2-container-multi
251
		 * systemTagsInputField systemtags-select2-container">
252
		 *               <ul class="select2-choices">
253
		 *                   <li class="select2-search-choice">
254
		 *                       <div>
255
		 *                           <span class="label">dsfsdfds</span>
256
		 *                       </div>
257
		 *                       <a href="#" class="select2-search-choice-close" tabindex="-1"></a>
258
		 *                   </li>
259
		 *               </ul>
260
		 *           </div>
261
		 *           <input class="systemTagsInputField select2-offscreen" name="tags"
262
		 * value="5,4,3,1,2,6" tabindex="-1" type="hidden">
263
		 *       </div>
264
		 * </div>
265
		 */
266
		// subAInput.on('change', function (e) {
267
		// 	var div = $(this);
268
		// 	if (e.which === 13 && div.val() !== '') {
269
		// 		self.selectPanelTags($(this).attr('id'));
270
		// 	}
271
		//
272
		//
273
		// 	var url = '/apps/' + div.attr('data-provider');
274
		// 	var route = JSON.parse(div.attr('data-route'));
275
		//
276
		// 	route.url = url + route.url;
277
		// 	self.quickSearch(route, div.val(), function (res) {
278
		// 		self.resultTagsSearch(div, res);
279
		// 	});
280
		// });
281
282
		ul.append($('<li>').append(subAInput).append(subADataList));
283
	},
284
285
	displayPanelSearch: function (appId, ul, sub) {
286
		var self = this;
287
288
		if (sub.type !== 'search') {
289
			return;
290
		}
291
292
		var subAInput = $('<input>', {
293
			id: sub.name,
294
			class: 'search_tags_sub',
295
			type: 'text',
296
			placeholder: sub.title,
297
			list: sub.name + '_datalist',
298
			'data-option': sub.name,
299
			'data-provider': appId,
300
			'data-route': JSON.stringify(sub.route)
301
		});
302
303
		var subADataList = $('<datalist>', {
304
			id: sub.name + '_datalist'
305
		});
306
307
308
		subAInput.on('keypress', function (e) {
309
			var div = $(this);
310
			if (e.which === 13 && div.val() !== '') {
311
				self.selectPanelTags($(this).attr('id'));
312
			}
313
314
315
			var url = '/apps/' + div.attr('data-provider');
316
			var route = JSON.parse(div.attr('data-route'));
317
318
			route.url = url + route.url;
319
			self.quickSearch(route, div.val(), function (res) {
320
				self.resultTagsSearch(div, res);
321
			});
322
		});
323
324
		ul.append($('<li>').append(subAInput).append(subADataList));
325
	},
326
327
328
	// selectPanelTags: function (panelId) {
329
	// 	if (this.currentTagsResult === undefined) {
330
	// 		return;
331
	// 	}
332
	//
333
	// 	var tags = this.currentTagsResult[panelId];
334
	// 	if (tags.length === 0) {
335
	// 		return;
336
	// 	}
337
	//
338
	// 	if (this.selectedTags[panelId] === undefined)
339
	// 		this.selectedTags[panelId] = [];
340
	// 	this.selectedTags[panelId].push(tags[0]);
341
	//
342
	// 	console.log('etntree' + JSON.stringify(this.selectedTags[panelId]));
343
	// },
344
	//
345
	//
346
	// resultTagsSearch: function (div, res) {
347
	// 	this.currentTagsResult[div.attr('id')] = res;
348
	// 	var datalistId = div.attr('data-option') + '_datalist';
349
	// 	var datalist = $('#' + datalistId);
350
	//
351
	// 	datalist.empty();
352
	// 	res.forEach(function (item) {
353
	// 		datalist.append($('<option>', {value: item}));
354
	// 	});
355
	// },
356
357
358
	getProviders: function () {
359
		var providers = [];
360
		elements.search_panels.find('input').each(function () {
361
			if ($(this).hasClass('search_checkbox') && $(this).is(":checked")) {
362
				providers.push($(this).attr('data-provider-id'));
363
			}
364
		});
365
366
		if (providers.length === 0) {
367
			return 'all';
368
		}
369
370
		return providers;
371
	},
372
373
374
	getOptions: function () {
375
		var options = {};
376
		elements.search_panels.find('input').each(function () {
377
			if ($(this).hasClass('search_checkbox_sub')) {
378
				options[$(this).attr('data-option')] = (($(this).is(':checked')) ? '1' : '0');
379
			}
380
381
			if ($(this).hasClass('search_input_sub')) {
382
				options[$(this).attr('data-option')] = $(this).val();
383
			}
384
		});
385
386
		return options;
387
	},
388
389
390
	initSearch: function () {
391
		var search = elements.search_input.val();
392
393
		if (search.length < 1) {
394
			return false;
395
		}
396
397
		var providers = this.getProviders();
398
		var options = this.getOptions();
399
400
		this.displayProviderResults(providers);
401
402
		var request = {
403
			providers: providers,
404
			options: options,
405
			search: search,
406
			page: curr.page
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...
407
		};
408
409
		fullTextSearch.search(request, this.searchResult);
410
		return true;
411
	},
412
413
414
	quickSearch: function (route, search, callback) {
415
		$.ajax({
416
			method: route.verb,
417
			url: OC.generateUrl(route.url),
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...
418
			data: {
419
				search: search
420
			}
421
		}).done(function (res) {
422
			if (_.has(res, 'error')) {
423
				return;
424
			}
425
426
			callback(res);
427
		});
428
	},
429
430
431
	displayProviderResults: function (providers) {
432
		elements.search_result.children('DIV.provider_header').each(function () {
433
			if (providers === 'all' || providers.indexOf($(this).attr('data-id')) > -1) {
434
				$(this).stop().slideDown(100).fadeTo(settings.delay_provider, 1);
0 ignored issues
show
Bug introduced by
The variable settings seems to be never declared. If this is a global, consider adding a /** global: settings */ 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...
435
			} else {
436
				$(this).stop().fadeTo(settings.delay_provider, 0).slideUp(100);
437
			}
438
		});
439
	},
440
441
442
	resetSearch: function () {
443
		// if (elements.search_input.val() !== '') {
444
		// 	return;
445
		// }
446
	},
447
448
449
	searchResult: function (result) {
450
451
		if (elements.search_json !== null) {
452
			elements.search_json.text(JSON.stringify(result));
453
		}
454
455
		// console.log(JSON.stringify(result));
456
//			OCA.notification.onFail('Search returned no result');
457
//		OCA.notification.onSuccess('Search returned ' + res.meta.size + ' result(s)');
458
459
	},
460
461
462
	onError: function (message) {
463
		console.log('error while searching: ' + message);
0 ignored issues
show
Debugging Code introduced by
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
464
	},
465
466
467
	onEntryGenerated: function (entry) {
468
		this.deleteEmptyDiv(entry, '#line1');
469
		this.deleteEmptyDiv(entry, '#line2');
470
	},
471
472
473
	deleteEmptyDiv: function (entry, divId) {
474
		var div = entry.find(divId);
475
		if (div.text() === '') {
476
			div.remove();
477
		}
478
	}
479
480
481
};
482
483
OCA.FullTextSearch.Example = Navigate;
484
485
486
$(document).ready(function () {
487
	OCA.FullTextSearch.example = new Navigate();
488
});
489
490
491
492