Completed
Push — master ( 387856...0fc5ee )
by Maxence
01:54
created

nav.onSearchRequest   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 5

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 2
nc 2
nop 1
dl 0
loc 5
rs 9.4285
c 1
b 0
f 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: api */
28
/** global: search */
29
/** global: result */
30
/** global: settings */
31
32
33
34
var curr = {
35
	providerResult: [],
36
	page: 1,
37
	lastRequest: '',
38
	lastRequestTimer: null,
39
	lastRequestTimerQueued: false,
40
	lastRequestTimerForcing: false,
41
42
	setProviderResult: function (id, value) {
43
		curr.providerResult[id] = value;
44
	},
45
46
	getProviderResult: function (id) {
47
		var current = curr.providerResult[id];
48
		if (!current) {
49
			current = [];
50
		}
51
52
		return current;
53
	}
54
55
};
56
57
58
var nav = {
59
60
		failedToAjax: function () {
61
			// OCA.notification.onFail(
62
			// 	'Failed to connect to cloud, page will refresh within few seconds');
63
			// window.setTimeout(function () {
64
			// 	window.location.reload(true);
65
			// }, 4000);
66
		},
67
68
69
		manageDivProviderNavigation: function (divProviderNavigation, request, meta) {
70
71
			var maxPage = Math.ceil(meta.total / request.size);
72
73
			divProviderNavigation.attr('data-time', meta.time);
74
			divProviderNavigation.attr('data-page', request.page);
75
			divProviderNavigation.attr('data-search', request.search);
76
			divProviderNavigation.attr('data-max-page', maxPage);
77
			divProviderNavigation.attr('data-size', request.size);
78
			divProviderNavigation.attr('data-total', meta.total);
79
80
			var providerName = divProviderNavigation.attr('data-provider-name');
81
			var left = "Search " + providerName + " for '" + request.search + "' returned " +
82
				meta.total + " results in " + meta.time + "ms";
83
			divProviderNavigation.find('.provider_navigation_left').text(left);
84
85
			divProviderNavigation.find('.provider_navigation_curr').text(request.page + ' / ' +
86
				maxPage);
87
88
			divProviderNavigation.find('.provider_navigation_prev').stop().fadeTo(200,
89
				(request.page > 1) ? 1 : 0);
90
			divProviderNavigation.find('.provider_navigation_next').stop().fadeTo(200,
91
				(request.page < maxPage) ? 1 : 0);
92
		},
93
94
95
		manageDivProviderResult: function (divProviderResult, newResult, oldResult) {
96
			//replaceWith();
97
			nav.divProviderResultAddItems(divProviderResult, newResult, oldResult);
98
			if (oldResult) {
99
				nav.divProviderResultRemoveItems(divProviderResult, newResult, oldResult);
100
				nav.divProviderResultMoveItems(divProviderResult, newResult, oldResult);
101
			}
102
		},
103
104
105
		divProviderResultAddItems: function (divProviderResult, newResult, oldResult) {
106
107
			var precItem = null;
108
			for (var i = 0; i < newResult.length; i++) {
109
				var entry = newResult[i];
110
				if (result.getResultIndex(entry.id, oldResult) > -1) {
111
					precItem = nav.getDivResult(entry.id, divProviderResult);
112
					continue;
113
				}
114
115
				var divResult = nav.generateDivResult(entry, nav.generateTemplateEntry(entry));
116
				if (precItem === null) {
117
					divProviderResult.prepend(divResult);
118
				} else {
119
					precItem.after(divResult);
120
				}
121
122
				divResult.slideDown(settings.delay_result, 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...
123
					$(this).children('.result_template').fadeTo(settings.delay_result, 1);
124
				});
125
126
				precItem = divResult;
127
			}
128
129
		},
130
131
132
		divProviderResultRemoveItems: function (divProviderResult, newResult, oldResult) {
133
			for (var i = 0; i < oldResult.length; i++) {
134
				var entry = oldResult[i];
135
				if (result.getResultIndex(entry.id, newResult) === -1) {
136
					var divResult = nav.getDivResult(entry.id, divProviderResult);
137
					divResult.fadeTo(settings.delay_result, 0, 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...
138
						$(this).slideUp(settings.delay_result, function () {
139
							$(this).remove();
140
						});
141
					});
142
				}
143
			}
144
		},
145
146
147
		divProviderResultMoveItems: function (divProviderResult, newResult, oldResult) {
148
149
			var precId = '';
150
151
			oldResult = result.recalibrateResult(oldResult, newResult);
152
			newResult = result.recalibrateResult(newResult, oldResult);
153
			for (var i = 0; i < newResult.length; i++) {
154
				var entry = newResult[i];
155
156
				var pos = result.getResultIndex(entry.id, oldResult);
157
				if (pos > -1 && pos !== i) {
158
					nav.animateMoveDivResult(entry.id, divProviderResult, precId);
159
				}
160
161
				precId = newResult[i].id;
162
			}
163
		},
164
165
166
		animateMoveDivResult: function (entryId, divProviderResult, precId) {
167
168
			var divResult = nav.getDivResult(entryId, divProviderResult);
169
170
			if (precId === '') {
171
				divResult.fadeTo(settings.delay_result, 0.35, function () {
172
					$(this).prependTo(divProviderResult).fadeTo(100, 1);
173
				});
174
			} else {
175
				var precItem = nav.getDivResult(precId, divProviderResult);
176
				divResult.fadeTo(settings.delay_result, 0.35, function () {
177
					$(this).insertAfter(precItem).fadeTo(100, 1);
178
				});
179
			}
180
181
		},
182
183
184
		getDivProvider: function (providerId, providerName) {
185
			var ret = null;
186
			settings.resultContainer.children('.provider_header').each(function () {
187
				if ($(this).attr('data-id') === providerId) {
188
					ret = $(this);
189
				}
190
			});
191
192
			if (ret === null) {
193
				ret = nav.generateDivProvider(providerId, providerName);
194
				settings.resultContainer.append(ret);
195
			}
196
197
			return ret;
198
		},
199
200
201
		getDivResult: function (resultId, divProviderResult) {
202
			var ret = null;
203
			divProviderResult.children('.result_entry').each(function () {
204
				if ($(this).attr('data-id') === resultId) {
205
					ret = $(this);
206
				}
207
			});
208
209
			return ret;
210
		},
211
212
213
		fillDivResult: function (divResult, entry) {
214
			divResult.find('#title').text(entry.title);
215
			divResult.find('#score').text(entry.score);
216
217
			nav.fillDivResultExcepts(divResult, entry);
218
219
			if (entry.link !== '') {
220
				divResult.on('click', function () {
221
					window.open(entry.link, '_self');
222
				});
223
				divResult.find('div').each(function () {
224
					$(this).css('cursor', 'pointer');
225
				});
226
			}
227
		},
228
229
230
		/**
231
		 * @namespace entry.excerpts
232
		 */
233
		fillDivResultExcepts: function (divResult, entry) {
234
			if (entry.excerpts === null) {
235
				return;
236
			}
237
238
			if (entry.excerpts.length > 0) {
239
				divResult.find('#line1').text(entry.excerpts[0]);
240
			}
241
242
			if (entry.excerpts.length > 1) {
243
				divResult.find('#line2').text(entry.excerpts[1]);
244
			}
245
246
		},
247
248
		onEntryGenerated: function (divResult) {
249
250
			nav.deleteEmptyDiv(divResult, '#line1');
251
			nav.deleteEmptyDiv(divResult, '#line2');
252
253
			if (settings.parentHasMethod('onEntryGenerated')) {
254
				settings.parent.onEntryGenerated(divResult);
255
			}
256
		},
257
258
		onSearchRequest: function (data) {
259
			if (settings.parentHasMethod('onSearchRequest')) {
260
				settings.parent.onSearchRequest(data);
261
			}
262
		},
263
264
		onSearchReset: function () {
265
			if (settings.parentHasMethod('onSearchReset')) {
266
				settings.parent.onSearchReset();
267
			}
268
		},
269
270
		onResultDisplayed: function () {
271
			if (settings.parentHasMethod('onResultDisplayed')) {
272
				settings.parent.onResultDisplayed();
273
			}
274
		},
275
276
		deleteEmptyDiv: function (entry, divId) {
277
			var div = entry.find(divId);
278
			if (div.text() === '') {
279
				div.remove();
280
			}
281
		},
282
283
284
		generateTemplateEntry: function (document) {
285
			var divTemplate = settings.entryTemplate;
286
			if (divTemplate === null) {
287
				divTemplate = settings.generateDefaultTemplate();
288
			}
289
290
			if (!divTemplate.length) {
291
				console.log('FullTextSearch Error: template_entry is not defined');
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...
292
				return;
293
			}
294
295
			var tmpl = divTemplate.html();
296
			tmpl = tmpl.replace(/%%id%%/g, escapeHTML(document.id));
297
298
			var div = $('<div>', {class: 'result_template'});
299
			div.html(tmpl).fadeTo(0);
300
301
			return div;
302
		},
303
304
305
		generateDivResult: function (entry, divResultContent) {
306
			var divResult = $('<div>', {class: 'result_entry'});
307
			divResult.hide();
308
			divResult.attr('data-id', entry.id);
309
			divResult.attr('data-link', entry.link);
310
			divResult.attr('data-result', JSON.stringify(entry));
311
			divResult.append(divResultContent);
312
313
			nav.fillDivResult(divResult, entry);
314
			nav.onEntryGenerated(divResult);
315
316
			return divResult;
317
		},
318
319
320
		generateDivProvider: function (providerId, providerName) {
321
322
323
			var divProviderNavigation = $('<div>', {class: 'provider_navigation'});
324
			divProviderNavigation.attr('data-provider-name', providerName);
325
			divProviderNavigation.append($('<div>', {class: 'provider_navigation_left'}));
326
327
			var divProviderPagination = $('<div>', {class: 'provider_navigation_right'});
328
			var divProviderPaginationPrev = $('<div>', {class: 'icon-page-prev provider_navigation_prev'});
329
			divProviderPaginationPrev.on('click', function () {
330
				fullTextSearch.search({
0 ignored issues
show
Bug introduced by
The variable fullTextSearch seems to be never declared. If this is a global, consider adding a /** global: fullTextSearch */ 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...
331
					providers: providerId,
332
					search: divProviderNavigation.attr('data-search'),
333
					page: Number(divProviderNavigation.attr('data-page')) - 1,
334
					size: divProviderNavigation.attr('data-size')
335
				});
336
			});
337
			divProviderPagination.append(divProviderPaginationPrev);
338
339
			divProviderPagination.append($('<div>', {class: 'provider_navigation_curr'}));
340
341
			var divProviderPaginationNext = $('<div>', {class: 'icon-page-next provider_navigation_next'});
342
			divProviderPaginationNext.on('click', function () {
343
				fullTextSearch.search({
0 ignored issues
show
Bug introduced by
The variable fullTextSearch seems to be never declared. If this is a global, consider adding a /** global: fullTextSearch */ 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...
344
					providers: providerId,
345
					search: divProviderNavigation.attr('data-search'),
346
					page: Number(divProviderNavigation.attr('data-page')) + 1,
347
					size: divProviderNavigation.attr('data-size')
348
				});
349
			});
350
			divProviderPagination.append(divProviderPaginationNext);
351
352
			divProviderNavigation.append(divProviderPagination);
353
354
			var divProviderResult = $('<div>', {class: 'provider_result'});
355
356
			var divProvider = $('<div>', {class: 'provider_header'});
357
			divProvider.hide();
358
			divProvider.attr('data-id', providerId);
359
			divProvider.append(divProviderNavigation);
360
			divProvider.append(divProviderResult);
361
362
			return divProvider;
363
		}
364
365
	}
366
;
367