Completed
Push — master ( 924656...92b011 )
by Maxence
02:05
created

nav.generateDivProvider   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 47

Duplication

Lines 0
Ratio 0 %

Importance

Changes 2
Bugs 0 Features 0
Metric Value
c 2
b 0
f 0
dl 0
loc 47
rs 9.0303
cc 1
nc 1
nop 2

2 Functions

Rating   Name   Duplication   Size   Complexity  
A 0 9 1
A 0 9 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
/** 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-options', JSON.stringify(request.options));
76
			divProviderNavigation.attr('data-search', request.search);
77
			divProviderNavigation.attr('data-max-page', maxPage);
78
			divProviderNavigation.attr('data-size', request.size);
79
			divProviderNavigation.attr('data-total', meta.total);
80
81
			var providerTitle = divProviderNavigation.attr('data-provider-title');
82
			var left = "Search " + providerTitle + " for '" + request.search + "' returned " +
83
				meta.total + " results in " + meta.time + "ms";
84
			divProviderNavigation.find('.provider_navigation_left').text(left);
85
86
			divProviderNavigation.find('.provider_navigation_curr').text(request.page + ' / ' +
87
				maxPage);
88
89
			divProviderNavigation.find('.provider_navigation_prev').stop().fadeTo(200,
90
				(request.page > 1) ? 1 : 0);
91
			divProviderNavigation.find('.provider_navigation_next').stop().fadeTo(200,
92
				(request.page < maxPage) ? 1 : 0);
93
		},
94
95
96
		manageDivProviderResult: function (divProviderResult, newResult, oldResult) {
97
			//replaceWith();
98
			nav.divProviderResultAddItems(divProviderResult, newResult, oldResult);
99
			if (oldResult) {
100
				nav.divProviderResultRemoveItems(divProviderResult, newResult, oldResult);
101
				nav.divProviderResultMoveItems(divProviderResult, newResult, oldResult);
102
			}
103
		},
104
105
106
		divProviderResultAddItems: function (divProviderResult, newResult, oldResult) {
107
108
			var precItem = null;
109
			for (var i = 0; i < newResult.length; i++) {
110
				var entry = newResult[i];
111
				if (result.getResultIndex(entry.id, oldResult) > -1) {
112
					precItem = nav.getDivResult(entry.id, divProviderResult);
113
					continue;
114
				}
115
116
				var divResult = nav.generateDivResult(entry, nav.generateTemplateEntry(entry));
117
				if (precItem === null) {
118
					divProviderResult.prepend(divResult);
119
				} else {
120
					precItem.after(divResult);
121
				}
122
123
				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...
124
					$(this).children('.result_template').fadeTo(settings.delay_result, 1);
125
				});
126
127
				precItem = divResult;
128
			}
129
130
		},
131
132
133
		divProviderResultRemoveItems: function (divProviderResult, newResult, oldResult) {
134
			for (var i = 0; i < oldResult.length; i++) {
135
				var entry = oldResult[i];
136
				if (result.getResultIndex(entry.id, newResult) === -1) {
137
					var divResult = nav.getDivResult(entry.id, divProviderResult);
138
					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...
139
						$(this).slideUp(settings.delay_result, function () {
140
							$(this).remove();
141
						});
142
					});
143
				}
144
			}
145
		},
146
147
148
		divProviderResultMoveItems: function (divProviderResult, newResult, oldResult) {
149
150
			var precId = '';
151
152
			oldResult = result.recalibrateResult(oldResult, newResult);
153
			newResult = result.recalibrateResult(newResult, oldResult);
154
			for (var i = 0; i < newResult.length; i++) {
155
				var entry = newResult[i];
156
157
				var pos = result.getResultIndex(entry.id, oldResult);
158
				if (pos > -1 && pos !== i) {
159
					nav.animateMoveDivResult(entry.id, divProviderResult, precId);
160
				}
161
162
				precId = newResult[i].id;
163
			}
164
		},
165
166
167
		animateMoveDivResult: function (entryId, divProviderResult, precId) {
168
169
			var divResult = nav.getDivResult(entryId, divProviderResult);
170
171
			if (precId === '') {
172
				divResult.fadeTo(settings.delay_result, 0.35, function () {
173
					$(this).prependTo(divProviderResult).fadeTo(100, 1);
174
				});
175
			} else {
176
				var precItem = nav.getDivResult(precId, divProviderResult);
177
				divResult.fadeTo(settings.delay_result, 0.35, function () {
178
					$(this).insertAfter(precItem).fadeTo(100, 1);
179
				});
180
			}
181
182
		},
183
184
185
		getDivProvider: function (providerId, providerName) {
186
			var ret = null;
187
			settings.resultContainer.children('.provider_header').each(function () {
188
				if ($(this).attr('data-id') === providerId) {
189
					ret = $(this);
190
				}
191
			});
192
193
			if (ret === null) {
194
				ret = nav.generateDivProvider(providerId, providerName);
195
				settings.resultContainer.append(ret);
196
			}
197
198
			return ret;
199
		},
200
201
202
		getDivResult: function (resultId, divProviderResult) {
203
			var ret = null;
204
			divProviderResult.children('.result_entry').each(function () {
205
				if ($(this).attr('data-id') === resultId) {
206
					ret = $(this);
207
				}
208
			});
209
210
			return ret;
211
		},
212
213
214
		fillDivResult: function (divResult, entry) {
215
			divResult.find('#title').text(entry.title);
216
			divResult.find('#score').text(entry.score);
217
218
			nav.fillDivResultExcepts(divResult, entry);
219
220
			if (entry.link !== '') {
221
				divResult.on('click', function () {
222
					window.open(entry.link, '_self');
223
				});
224
				divResult.find('div').each(function () {
225
					$(this).css('cursor', 'pointer');
226
				});
227
			}
228
		},
229
230
231
		/**
232
		 * @namespace entry.excerpts
233
		 */
234
		fillDivResultExcepts: function (divResult, entry) {
235
			if (entry.excerpts === null) {
236
				return;
237
			}
238
239
			if (entry.excerpts.length > 0) {
240
				divResult.find('#line1').text(entry.excerpts[0]);
241
			}
242
243
			if (entry.excerpts.length > 1) {
244
				divResult.find('#line2').text(entry.excerpts[1]);
245
			}
246
247
		},
248
249
		onEntryGenerated: function (divResult) {
250
251
			nav.deleteEmptyDiv(divResult, '#line1');
252
			nav.deleteEmptyDiv(divResult, '#line2');
253
254
			if (settings.parentHasMethod('onEntryGenerated')) {
255
				settings.parent.onEntryGenerated(divResult);
256
			}
257
		},
258
259
		onSearchRequest: function (data) {
260
			if (settings.parentHasMethod('onSearchRequest')) {
261
				settings.parent.onSearchRequest(data);
262
			}
263
		},
264
265
		onSearchReset: function () {
266
			if (settings.parentHasMethod('onSearchReset')) {
267
				settings.parent.onSearchReset();
268
			}
269
		},
270
271
		onResultDisplayed: function () {
272
			if (settings.parentHasMethod('onResultDisplayed')) {
273
				settings.parent.onResultDisplayed();
274
			}
275
		},
276
277
		deleteEmptyDiv: function (entry, divId) {
278
			var div = entry.find(divId);
279
			if (div.text() === '') {
280
				div.remove();
281
			}
282
		},
283
284
285
		generateTemplateEntry: function (document) {
286
			var divTemplate = settings.entryTemplate;
287
			if (divTemplate === null) {
288
				divTemplate = settings.generateDefaultTemplate();
289
			}
290
291
			if (!divTemplate.length) {
292
				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...
293
				return;
294
			}
295
296
			var tmpl = divTemplate.html();
297
			tmpl = tmpl.replace(/%%id%%/g, escapeHTML(document.id));
298
299
			var div = $('<div>', {class: 'result_template'});
300
			div.html(tmpl).fadeTo(0);
301
302
			return div;
303
		},
304
305
306
		generateDivResult: function (entry, divResultContent) {
307
			var divResult = $('<div>', {class: 'result_entry'});
308
			divResult.hide();
309
			divResult.attr('data-id', entry.id);
310
			divResult.attr('data-link', entry.link);
311
			divResult.attr('data-result', JSON.stringify(entry));
312
			divResult.append(divResultContent);
313
314
			nav.fillDivResult(divResult, entry);
315
			nav.onEntryGenerated(divResult);
316
317
			return divResult;
318
		},
319
320
321
		generateDivProvider: function (providerId, providerName) {
322
323
324
			var divProviderNavigation = $('<div>', {class: 'provider_navigation'});
325
			divProviderNavigation.attr('data-provider-id', providerId);
326
			divProviderNavigation.attr('data-provider-title', providerName);
327
			divProviderNavigation.append($('<div>', {class: 'provider_navigation_left'}));
328
329
			var divProviderPagination = $('<div>', {class: 'provider_navigation_right'});
330
			var divProviderPaginationPrev = $('<div>', {class: 'icon-page-prev provider_navigation_prev'});
331
			divProviderPaginationPrev.on('click', function () {
332
				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...
333
					providers: providerId,
334
					options: JSON.parse(divProviderNavigation.attr('data-options')),
335
					search: divProviderNavigation.attr('data-search'),
336
					page: Number(divProviderNavigation.attr('data-page')) - 1,
337
					size: divProviderNavigation.attr('data-size')
338
				});
339
			});
340
			divProviderPagination.append(divProviderPaginationPrev);
341
342
			divProviderPagination.append($('<div>', {class: 'provider_navigation_curr'}));
343
344
			var divProviderPaginationNext = $('<div>', {class: 'icon-page-next provider_navigation_next'});
345
			divProviderPaginationNext.on('click', function () {
346
				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...
347
					providers: providerId,
348
					options: JSON.parse(divProviderNavigation.attr('data-options')),
349
					search: divProviderNavigation.attr('data-search'),
350
					page: Number(divProviderNavigation.attr('data-page')) + 1,
351
					size: divProviderNavigation.attr('data-size')
352
				});
353
			});
354
			divProviderPagination.append(divProviderPaginationNext);
355
356
			divProviderNavigation.append(divProviderPagination);
357
358
			var divProviderResult = $('<div>', {class: 'provider_result'});
359
360
			var divProvider = $('<div>', {class: 'provider_header'});
361
			divProvider.hide();
362
			divProvider.attr('data-id', providerId);
363
			divProvider.append(divProviderNavigation);
364
			divProvider.append(divProviderResult);
365
366
			return divProvider;
367
		}
368
369
	}
370
;
371