These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more
1 | // util.js |
||
2 | // copyright Sébastien Lucas |
||
3 | // https://github.com/seblucas/cops |
||
4 | |||
5 | /*jshint curly: true, latedef: true, trailing: true, noarg: true, undef: true, browser: true, jquery: true, unused: true, devel: true, loopfunc: true */ |
||
6 | /*global LRUCache, doT, Bloodhound, postRefresh */ |
||
7 | |||
8 | var templatePage, templateBookDetail, templateMain, templateSuggestion, currentData, before, filterList; |
||
9 | |||
10 | if (typeof LRUCache != 'undefined') { |
||
11 | console.log('ERROR: LRUCache module not loaded!'); |
||
0 ignored issues
–
show
Debugging Code
introduced
by
![]() |
|||
12 | } |
||
13 | var cache = new LRUCache(30); |
||
14 | |||
15 | $.ajaxSetup({ |
||
16 | cache: false |
||
17 | }); |
||
18 | |||
19 | var copsTypeahead = new Bloodhound({ |
||
20 | datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title'), |
||
21 | queryTokenizer: Bloodhound.tokenizers.whitespace, |
||
22 | limit: 30, |
||
23 | remote: { |
||
24 | url: 'getJSON.php?page=9&search=1&db=%DB&query=%QUERY', |
||
25 | replace: function (url, query) { |
||
26 | if (currentData.multipleDatabase === 1 && currentData.databaseId === "") { |
||
27 | return url.replace('%QUERY', query).replace('&db=%DB', ""); |
||
28 | } |
||
29 | return url.replace('%QUERY', query).replace('%DB', currentData.databaseId); |
||
30 | } |
||
31 | } |
||
32 | }); |
||
33 | |||
34 | copsTypeahead.initialize(); |
||
35 | |||
36 | var DEBUG = false; |
||
37 | var isPushStateEnabled = window.history && window.history.pushState && window.history.replaceState && |
||
38 | // pushState isn't reliable on iOS until 5. |
||
39 | !window.navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/); |
||
40 | |||
41 | function debug_log(text) { |
||
42 | if ( DEBUG ) { |
||
43 | console.log(text); |
||
0 ignored issues
–
show
|
|||
44 | } |
||
45 | } |
||
46 | |||
47 | /*exported updateCookie */ |
||
48 | function updateCookie (id) { |
||
49 | if ($(id).prop('pattern') && !$(id).val().match(new RegExp ($(id).prop('pattern')))) { |
||
50 | return; |
||
51 | } |
||
52 | var name = $(id).attr('id'); |
||
53 | var value = $(id).val (); |
||
54 | $.cookie(name, value, { expires: 365 }); |
||
55 | } |
||
56 | |||
57 | /*exported updateCookieFromCheckbox */ |
||
58 | function updateCookieFromCheckbox (id) { |
||
59 | var name = $(id).attr('id'); |
||
60 | if ((/^style/).test (name)) { |
||
61 | name = "style"; |
||
62 | } |
||
63 | if ($(id).is(":checked")) |
||
64 | { |
||
65 | if ($(id).is(':radio')) { |
||
66 | $.cookie(name, $(id).val (), { expires: 365 }); |
||
67 | } else { |
||
68 | $.cookie(name, '1', { expires: 365 }); |
||
69 | } |
||
70 | } |
||
71 | else |
||
72 | { |
||
73 | $.cookie(name, '0', { expires: 365 }); |
||
74 | } |
||
75 | } |
||
76 | |||
77 | /*exported updateCookieFromCheckboxGroup */ |
||
78 | function updateCookieFromCheckboxGroup (id) { |
||
79 | var name = $(id).attr('name'); |
||
80 | var idBase = name.replace (/\[\]/, ""); |
||
81 | var group = []; |
||
82 | $(':checkbox[name="' + name + '"]:checked').each (function () { |
||
83 | var id = $(this).attr("id"); |
||
84 | group.push (id.replace (idBase + "_", "")); |
||
85 | }); |
||
86 | $.cookie(idBase, group.join (), { expires: 365 }); |
||
87 | } |
||
88 | |||
89 | |||
90 | function elapsed () { |
||
91 | var elapsedTime = new Date () - before; |
||
92 | return "Elapsed : " + elapsedTime; |
||
93 | } |
||
94 | |||
95 | function retourMail(data) { |
||
96 | $("#mailButton :first-child").removeClass ("fas fa-spinner fa-pulse").addClass ("fas fa-envelope"); |
||
97 | alert (data); |
||
98 | } |
||
99 | |||
100 | /*exported sendToMailAddress */ |
||
101 | function sendToMailAddress (component, dataid) { |
||
102 | var email = $.cookie ('email'); |
||
103 | if (!$.cookie ('email')) { |
||
104 | email = window.prompt (currentData.c.i18n.customizeEmail, ""); |
||
105 | if (email === null) |
||
106 | { |
||
107 | return; |
||
108 | } |
||
109 | $.cookie ('email', email, { expires: 365 }); |
||
110 | } |
||
111 | var url = 'sendtomail.php'; |
||
112 | if (currentData.databaseId) { |
||
113 | url = url + '?db=' + currentData.databaseId; |
||
114 | } |
||
115 | $("#mailButton :first-child").removeClass ("fas fa-envelope").addClass ("fas fa-spinner fa-pulse"); |
||
116 | $.ajax ({'url': url, 'type': 'post', 'data': { 'data': dataid, 'email': email }, 'success': retourMail}); |
||
117 | } |
||
118 | |||
119 | function str_format () { |
||
120 | var s = arguments[0]; |
||
121 | for (var i = 0; i < arguments.length - 1; i++) { |
||
122 | var reg = new RegExp("\\{" + i + "\\}", "gm"); |
||
123 | s = s.replace(reg, arguments[i + 1]); |
||
124 | } |
||
125 | return s; |
||
126 | } |
||
127 | |||
128 | function isDefined(x) { |
||
129 | return (typeof x !== 'undefined'); |
||
130 | } |
||
131 | |||
132 | function getCurrentOption (option) { |
||
133 | if (!$.cookie (option)) { |
||
134 | if (currentData && currentData.c && currentData.c.config && currentData.c.config [option]) { |
||
135 | return currentData.c.config [option]; |
||
136 | } |
||
137 | } |
||
138 | return $.cookie (option); |
||
139 | } |
||
140 | |||
141 | /*exported htmlspecialchars */ |
||
142 | function htmlspecialchars(str) { |
||
143 | return String(str) |
||
144 | .replace(/&/g, '&') |
||
145 | .replace(/"/g, '"') |
||
146 | .replace(/'/g, ''') |
||
147 | .replace(/</g, '<') |
||
148 | .replace(/>/g, '>'); |
||
149 | } |
||
150 | |||
151 | /************************************************ |
||
152 | * All functions needed to filter the book list by tags |
||
153 | ************************************************ |
||
154 | */ |
||
155 | |||
156 | function getTagList () { |
||
157 | var tagList = {}; |
||
158 | $(".se").each (function(){ |
||
159 | if ($(this).parents (".filtered").length > 0) { return; } |
||
160 | var taglist = $(this).text(); |
||
161 | |||
162 | var tagarray = taglist.split (","); |
||
163 | for (var i in tagarray) { |
||
164 | if (!tagarray.hasOwnProperty(i)) { |
||
165 | continue; |
||
166 | } |
||
167 | var tag = tagarray [i].replace(/^\s+/g,'').replace(/\s+$/g,''); |
||
168 | tagList [tag] = 1; |
||
169 | } |
||
170 | }); |
||
171 | return tagList; |
||
172 | } |
||
173 | |||
174 | function updateFilters () { |
||
175 | var tagList = getTagList (); |
||
176 | |||
177 | // If there is already some filters then let's prepare to update the list |
||
178 | $("#filter ul li").each (function () { |
||
179 | var text = $(this).text (); |
||
180 | if (isDefined (tagList [text]) || $(this).attr ('class')) { |
||
181 | tagList [text] = 0; |
||
182 | } else { |
||
183 | tagList [text] = -1; |
||
184 | } |
||
185 | }); |
||
186 | |||
187 | // Update the filter -1 to remove, 1 to add, 0 already there |
||
188 | for (var tag in tagList) { |
||
189 | if (!tagList.hasOwnProperty(tag)) { |
||
190 | continue; |
||
191 | } |
||
192 | var tagValue = tagList [tag]; |
||
193 | if (tagValue === -1) { |
||
194 | $("#filter ul li").filter (function () { return $.text([this]) === tag; }).remove(); |
||
0 ignored issues
–
show
|
|||
195 | } |
||
196 | if (tagValue === 1) { |
||
197 | $("#filter ul").append ("<li>" + tag + "</li>"); |
||
198 | } |
||
199 | } |
||
200 | |||
201 | $("#filter ul").append ("<li>_CLEAR_</li>"); |
||
202 | |||
203 | // Sort the list alphabetically |
||
204 | $('#filter ul li').sortElements(function(a, b){ |
||
205 | return $(a).text() > $(b).text() ? 1 : -1; |
||
206 | }); |
||
207 | } |
||
208 | |||
209 | function doFilter () { |
||
210 | $(".books").removeClass("filtered"); |
||
211 | if (jQuery.isEmptyObject(filterList)) { |
||
212 | updateFilters (); |
||
213 | return; |
||
214 | } |
||
215 | |||
216 | $(".se").each (function(){ |
||
217 | var taglist = ", " + $(this).text() + ", "; |
||
218 | var toBeFiltered = false; |
||
219 | for (var filter in filterList) { |
||
220 | if (!filterList.hasOwnProperty(filter)) { |
||
221 | continue; |
||
222 | } |
||
223 | var onlyThisTag = filterList [filter]; |
||
224 | filter = ', ' + filter + ', '; |
||
225 | var myreg = new RegExp (filter); |
||
226 | if (myreg.test (taglist)) { |
||
227 | if (onlyThisTag === false) { |
||
228 | toBeFiltered = true; |
||
229 | } |
||
230 | } else { |
||
231 | if (onlyThisTag === true) { |
||
232 | toBeFiltered = true; |
||
233 | } |
||
234 | } |
||
235 | } |
||
236 | if (toBeFiltered) { $(this).parents (".books").addClass ("filtered"); } |
||
237 | }); |
||
238 | |||
239 | // Handle the books with no tags |
||
240 | var atLeastOneTagSelected = false; |
||
241 | for (var filter in filterList) { |
||
242 | if (!filterList.hasOwnProperty(filter)) { |
||
243 | continue; |
||
244 | } |
||
245 | if (filterList[filter] === true) { |
||
246 | atLeastOneTagSelected = true; |
||
247 | } |
||
248 | } |
||
249 | if (atLeastOneTagSelected) { |
||
250 | $(".books").not (":has(span.se)").addClass ("filtered"); |
||
251 | } |
||
252 | |||
253 | updateFilters (); |
||
254 | } |
||
255 | |||
256 | function handleFilterEvents () { |
||
257 | $("#filter ul").on ("click", "li", function(){ |
||
258 | var filter = $(this).text (); |
||
259 | if (filter === "_CLEAR_") { |
||
260 | filterList = {}; |
||
261 | $("#filter ul li").removeClass ("filter-exclude"); |
||
262 | $("#filter ul li").removeClass ("filter-include"); |
||
263 | doFilter (); |
||
264 | return; |
||
265 | } |
||
266 | switch ($(this).attr("class")) { |
||
267 | case "filter-include" : |
||
268 | $(this).attr("class", "filter-exclude"); |
||
269 | filterList [filter] = false; |
||
270 | break; |
||
271 | case "filter-exclude" : |
||
272 | $(this).removeClass ("filter-exclude"); |
||
273 | delete filterList [filter]; |
||
274 | break; |
||
275 | default : |
||
276 | $(this).attr("class", "filter-include"); |
||
277 | filterList [filter] = true; |
||
278 | break; |
||
279 | } |
||
280 | doFilter (); |
||
281 | }); |
||
282 | } |
||
283 | |||
284 | /************************************************ |
||
285 | * Functions to handle Ajax navigation |
||
286 | ************************************************ |
||
287 | */ |
||
288 | |||
289 | var updatePage, navigateTo; |
||
290 | |||
291 | updatePage = function (data) { |
||
292 | var result; |
||
293 | filterList = {}; |
||
294 | data.c = currentData.c; |
||
295 | if (false && $("section").length && currentData.isPaginated === 0 && data.isPaginated === 0) { |
||
296 | // Partial update (for now disabled) |
||
297 | debug_log ("Partial update"); |
||
298 | result = templateMain (data); |
||
299 | $("h1").html (data.title); |
||
300 | $("section").html (result); |
||
301 | } else { |
||
302 | // Full update |
||
303 | result = templatePage (data); |
||
304 | $("body").html (result); |
||
305 | } |
||
306 | document.title = data.title; |
||
307 | currentData = data; |
||
308 | setTimeout( function() { $("input[name=query]").focus(); }, 500 ); |
||
309 | |||
310 | debug_log (elapsed ()); |
||
311 | |||
312 | if ($.cookie('toolbar') === '1') { $("#tool").show (); } |
||
313 | if (currentData.containsBook === 1) { |
||
314 | $("#sortForm").show (); |
||
315 | if (getCurrentOption ("html_tag_filter") === "1") { |
||
316 | $("#filter ul").empty (); |
||
317 | updateFilters (); |
||
318 | handleFilterEvents (); |
||
319 | } |
||
320 | } else { |
||
321 | $("#sortForm").hide (); |
||
322 | } |
||
323 | |||
324 | $('input[name=query]').typeahead( |
||
325 | { |
||
326 | hint: true, |
||
327 | minLength : 3 |
||
328 | }, |
||
329 | { |
||
330 | name: 'search', |
||
331 | displayKey: 'title', |
||
332 | templates: { |
||
333 | suggestion: templateSuggestion |
||
334 | }, |
||
335 | source: copsTypeahead.ttAdapter() |
||
336 | }); |
||
337 | |||
338 | $('input[name=query]').bind('typeahead:selected', function(obj, datum) { |
||
339 | if (isPushStateEnabled) { |
||
340 | navigateTo (datum.navlink); |
||
341 | } else { |
||
342 | window.location = datum.navlink; |
||
343 | } |
||
344 | }); |
||
345 | |||
346 | if(typeof postRefresh == 'function') |
||
347 | { postRefresh(); } |
||
348 | }; |
||
349 | |||
350 | navigateTo = function (url) { |
||
351 | $("h1").append (" <i class='fas fa-spinner fa-pulse'></i>"); |
||
352 | before = new Date (); |
||
353 | var jsonurl = url.replace ("index", "getJSON"); |
||
354 | var cachedData = cache.get (jsonurl); |
||
355 | if (cachedData) { |
||
356 | window.history.pushState(jsonurl, "", url); |
||
357 | updatePage (cachedData); |
||
358 | } else { |
||
359 | $.getJSON(jsonurl, function(data) { |
||
360 | window.history.pushState(jsonurl, "", url); |
||
361 | cache.put (jsonurl, data); |
||
362 | updatePage (data); |
||
363 | }); |
||
364 | } |
||
365 | }; |
||
366 | |||
367 | function link_Clicked (event) { |
||
368 | var currentLink = $(this); |
||
369 | if (!isPushStateEnabled || |
||
370 | currentData.page === "19") { |
||
371 | return; |
||
372 | } |
||
373 | event.preventDefault(); |
||
374 | var url = currentLink.attr('href'); |
||
375 | |||
376 | if ($(".mfp-ready").length) |
||
377 | { |
||
378 | $.magnificPopup.close(); |
||
379 | } |
||
380 | |||
381 | // The bookdetail / about should be displayed in a lightbox |
||
382 | if (getCurrentOption ("use_fancyapps") === "1" && |
||
383 | (currentLink.hasClass ("fancydetail") || currentLink.hasClass ("fancyabout"))) { |
||
384 | before = new Date (); |
||
385 | var jsonurl = url.replace ("index", "getJSON"); |
||
386 | $.getJSON(jsonurl, function(data) { |
||
387 | data.c = currentData.c; |
||
388 | var detail = ""; |
||
389 | if (data.page === "16") { |
||
390 | detail = data.fullhtml; |
||
391 | } else { |
||
392 | detail = templateBookDetail (data); |
||
393 | } |
||
394 | $.magnificPopup.open({ |
||
395 | items: { |
||
396 | src: detail, |
||
397 | type: 'inline' |
||
398 | } |
||
399 | }); |
||
400 | debug_log (elapsed ()); |
||
401 | }); |
||
402 | return; |
||
403 | } |
||
404 | navigateTo (url); |
||
405 | } |
||
406 | |||
407 | function search_Submitted (event) { |
||
408 | if (!isPushStateEnabled || |
||
409 | currentData.page === "19") { |
||
410 | return; |
||
411 | } |
||
412 | event.preventDefault(); |
||
413 | var url = str_format ("index.php?page=9¤t={0}&query={1}&db={2}", currentData.page, encodeURIComponent ($("input[name=query]").val ()), currentData.databaseId); |
||
414 | navigateTo (url); |
||
415 | } |
||
416 | |||
417 | /*exported handleLinks */ |
||
418 | function handleLinks () { |
||
419 | $("body").on ("click", "a[href^='index']", link_Clicked); |
||
420 | $("body").on ("submit", "#searchForm", search_Submitted); |
||
421 | $("body").on ("click", "#sort", function(){ |
||
422 | $('.books').sortElements(function(a, b){ |
||
423 | var test = 1; |
||
424 | if ($("#sortorder").val() === "desc") |
||
425 | { |
||
426 | test = -1; |
||
427 | } |
||
428 | return $(a).find ("." + $("#sortchoice").val()).text() > $(b).find ("." + $("#sortchoice").val()).text() ? test : -test; |
||
429 | }); |
||
430 | }); |
||
431 | |||
432 | $("body").on ("click", ".headright", function(){ |
||
433 | if ($("#tool").is(":hidden")) { |
||
434 | $("#tool").slideDown("slow"); |
||
435 | $("input[name=query]").focus(); |
||
436 | $.cookie('toolbar', '1', { expires: 365 }); |
||
437 | } else { |
||
438 | $("#tool").slideUp(); |
||
439 | $.removeCookie('toolbar'); |
||
440 | } |
||
441 | }); |
||
442 | $("body").magnificPopup({ |
||
443 | delegate: '.fancycover', // child items selector, by clicking on it popup will open |
||
444 | type: 'image', |
||
445 | gallery:{enabled:true, preload: [0,2]}, |
||
446 | disableOn: function() { |
||
447 | if( getCurrentOption ("use_fancyapps") === "1" ) { |
||
448 | return true; |
||
449 | } |
||
450 | return false; |
||
451 | } |
||
452 | }); |
||
453 | } |
||
454 | |||
455 | window.onpopstate = function(event) { |
||
456 | if (!isDefined (currentData)) { |
||
457 | return; |
||
458 | } |
||
459 | |||
460 | before = new Date (); |
||
461 | var data = cache.get (event.state); |
||
462 | updatePage (data); |
||
463 | }; |
||
464 | |||
465 | $(document).keydown(function(e){ |
||
466 | if (e.keyCode === 37 && $("#prevLink").length > 0) { |
||
467 | navigateTo ($("#prevLink").attr('href')); |
||
468 | } |
||
469 | if (e.keyCode === 39 && $("#nextLink").length > 0) { |
||
470 | navigateTo ($("#nextLink").attr('href')); |
||
471 | } |
||
472 | }); |
||
473 | |||
474 | /*exported initiateAjax */ |
||
475 | function initiateAjax (url, theme) { |
||
476 | $.when($.get('templates/' + theme + '/header.html'), |
||
477 | $.get('templates/' + theme + '/footer.html'), |
||
478 | $.get('templates/' + theme + '/bookdetail.html'), |
||
479 | $.get('templates/' + theme + '/main.html'), |
||
480 | $.get('templates/' + theme + '/page.html'), |
||
481 | $.get('templates/' + theme + '/suggestion.html'), |
||
482 | $.getJSON(url)).done(function(header, footer, bookdetail, main, page, suggestion, data){ |
||
483 | templateBookDetail = doT.template (bookdetail [0]); |
||
484 | |||
485 | var defMain = { |
||
486 | bookdetail: bookdetail [0] |
||
487 | }; |
||
488 | |||
489 | templateMain = doT.template (main [0], undefined, defMain); |
||
490 | |||
491 | var defPage = { |
||
492 | header: header [0], |
||
493 | footer: footer [0], |
||
494 | main : main [0], |
||
495 | bookdetail: bookdetail [0] |
||
496 | }; |
||
497 | |||
498 | templatePage = doT.template (page [0], undefined, defPage); |
||
499 | |||
500 | templateSuggestion = doT.template (suggestion [0]); |
||
501 | |||
502 | currentData = data [0]; |
||
503 | |||
504 | updatePage (data [0]); |
||
505 | cache.put (url, data [0]); |
||
506 | if (isPushStateEnabled) { |
||
507 | window.history.replaceState(url, "", window.location); |
||
508 | } |
||
509 | handleLinks (); |
||
510 | }); |
||
511 | } |
||
512 |