Completed
Push — master ( 31966b...865827 )
by Markus
04:30
created

Upgrade to new PHP Analysis Engine

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
    var cache = new LRUCache(30);
12
}
13
14
$.ajaxSetup({
15
    cache: false
16
});
17
18
var copsTypeahead = new Bloodhound({
19
    datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title'),
20
    queryTokenizer: Bloodhound.tokenizers.whitespace,
21
    limit: 30,
22
    remote: {
23
                url: 'getJSON.php?page=9&search=1&db=%DB&query=%QUERY',
24
                replace: function (url, query) {
25
                    if (currentData.multipleDatabase === 1 && currentData.databaseId === "") {
26
                        return url.replace('%QUERY', query).replace('&db=%DB', "");
27
                    }
28
                    return url.replace('%QUERY', query).replace('%DB', currentData.databaseId);
29
                }
30
            }
31
});
32
33
copsTypeahead.initialize();
34
35
var DEBUG = false;
36
var isPushStateEnabled = window.history && window.history.pushState && window.history.replaceState &&
37
  // pushState isn't reliable on iOS until 5.
38
  !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/);
0 ignored issues
show
The variable navigator seems to be never declared. If this is a global, consider adding a /** global: navigator */ 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...
39
40
function debug_log(text) {
41
    if ( DEBUG ) {
42
        console.log(text);
0 ignored issues
show
console.log looks like debug code. Are you sure you do not want to remove it?
Loading history...
43
    }
44
}
45
46
/*exported updateCookie */
47
function updateCookie (id) {
48
    if ($(id).prop('pattern') && !$(id).val().match(new RegExp ($(id).prop('pattern')))) {
49
        return;
50
    }
51
    var name = $(id).attr('id');
52
    var value = $(id).val ();
53
    $.cookie(name, value, { expires: 365 });
54
}
55
56
/*exported updateCookieFromCheckbox */
57
function updateCookieFromCheckbox (id) {
58
    var name = $(id).attr('id');
59
    if ((/^style/).test (name)) {
60
        name = "style";
61
    }
62
    if ($(id).is(":checked"))
63
    {
64
        if ($(id).is(':radio')) {
65
            $.cookie(name, $(id).val (), { expires: 365 });
66
        } else {
67
            $.cookie(name, '1', { expires: 365 });
68
        }
69
    }
70
    else
71
    {
72
        $.cookie(name, '0', { expires: 365 });
73
    }
74
}
75
76
/*exported updateCookieFromCheckboxGroup */
77
function updateCookieFromCheckboxGroup (id) {
78
    var name = $(id).attr('name');
79
    var idBase = name.replace (/\[\]/, "");
80
    var group = [];
81
    $(':checkbox[name="' + name + '"]:checked').each (function () {
82
        var id = $(this).attr("id");
83
        group.push (id.replace (idBase + "_", ""));
84
    });
85
    $.cookie(idBase, group.join (), { expires: 365 });
86
}
87
88
89
function elapsed () {
90
    var elapsedTime = new Date () - before;
91
    return "Elapsed : " + elapsedTime;
92
}
93
94
function retourMail(data) {
95
    $("#mailButton :first-child").removeClass ("icon-spinner icon-spin").addClass ("icon-envelope");
96
    alert (data);
97
}
98
99
/*exported sendToMailAddress */
100
function sendToMailAddress (component, dataid) {
101
    var email = $.cookie ('email');
102
    if (!$.cookie ('email')) {
103
        email = window.prompt (currentData.c.i18n.customizeEmail, "");
104
        if (email === null)
105
        {
106
            return;
107
        }
108
        $.cookie ('email', email, { expires: 365 });
109
    }
110
    var url = 'sendtomail.php';
111
    if (currentData.databaseId) {
112
        url = url + '?db=' + currentData.databaseId;
113
    }
114
    $("#mailButton :first-child").removeClass ("icon-envelope").addClass ("icon-spinner icon-spin");
115
    $.ajax ({'url': url, 'type': 'post', 'data': { 'data':  dataid, 'email': email }, 'success': retourMail});
116
}
117
118
function str_format () {
119
    var s = arguments[0];
120
    for (var i = 0; i < arguments.length - 1; i++) {
121
        var reg = new RegExp("\\{" + i + "\\}", "gm");
122
        s = s.replace(reg, arguments[i + 1]);
123
    }
124
    return s;
125
}
126
127
function isDefined(x) {
128
    var undefinedVar;
129
    return x !== undefinedVar;
0 ignored issues
show
The variable undefinedVar seems to be never initialized.
Loading history...
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, '&amp;')
145
            .replace(/"/g, '&quot;')
146
            .replace(/'/g, '&#39;')
147
            .replace(/</g, '&lt;')
148
            .replace(/>/g, '&gt;');
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) {
0 ignored issues
show
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
164
            var tag = tagarray [i].replace(/^\s+/g,'').replace(/\s+$/g,'');
165
            tagList [tag] = 1;
166
        }
167
    });
168
    return tagList;
169
}
170
171
function updateFilters () {
172
    var tagList = getTagList ();
173
174
    // If there is already some filters then let's prepare to update the list
175
    $("#filter ul li").each (function () {
176
        var text = $(this).text ();
177
        if (isDefined (tagList [text]) || $(this).attr ('class')) {
178
            tagList [text] = 0;
179
        } else {
180
            tagList [text] = -1;
181
        }
182
    });
183
184
    // Update the filter -1 to remove, 1 to add, 0 already there
185
    for (var tag in tagList) {
0 ignored issues
show
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
186
        var tagValue = tagList [tag];
187
        if (tagValue === -1) {
188
            $("#filter ul li").filter (function () { return $.text([this]) === tag; }).remove();
0 ignored issues
show
The variable tag is changed by the for-each loop on line 185. Only the value of the last iteration will be visible in this function if it is called outside of the loop.
Loading history...
189
        }
190
        if (tagValue === 1) {
191
            $("#filter ul").append ("<li>" + tag + "</li>");
192
        }
193
    }
194
195
    $("#filter ul").append ("<li>_CLEAR_</li>");
196
197
    // Sort the list alphabetically
198
    $('#filter ul li').sortElements(function(a, b){
199
        return $(a).text() > $(b).text() ? 1 : -1;
200
    });
201
}
202
203
function doFilter () {
204
    $(".books").removeClass("filtered");
205
    if (jQuery.isEmptyObject(filterList)) {
206
        updateFilters ();
207
        return;
208
    }
209
210
    $(".se").each (function(){
211
        var taglist = ", " + $(this).text() + ", ";
212
        var toBeFiltered = false;
213
        for (var filter in filterList) {
0 ignored issues
show
A for in loop automatically includes the property of any prototype object, consider checking the key using hasOwnProperty.

When iterating over the keys of an object, this includes not only the keys of the object, but also keys contained in the prototype of that object. It is generally a best practice to check for these keys specifically:

var someObject;
for (var key in someObject) {
    if ( ! someObject.hasOwnProperty(key)) {
        continue; // Skip keys from the prototype.
    }

    doSomethingWith(key);
}
Loading history...
214
            var onlyThisTag = filterList [filter];
215
            filter = ', ' + filter + ', ';
216
            var myreg = new RegExp (filter);
217
            if (myreg.test (taglist)) {
218
                if (onlyThisTag === false) {
219
                    toBeFiltered = true;
220
                }
221
            } else {
222
                if (onlyThisTag === true) {
223
                    toBeFiltered = true;
224
                }
225
            }
226
        }
227
        if (toBeFiltered) { $(this).parents (".books").addClass ("filtered"); }
228
    });
229
230
    // Handle the books with no tags
231
    var atLeastOneTagSelected = false;
232
    for (var filter in filterList) {
233
        if (filterList [filter] === true) {
234
            atLeastOneTagSelected = true;
235
        }
236
    }
237
    if (atLeastOneTagSelected) {
238
        $(".books").not (":has(span.se)").addClass ("filtered");
239
    }
240
241
    updateFilters ();
242
}
243
244
function handleFilterEvents () {
245
    $("#filter ul").on ("click", "li", function(){
246
        var filter = $(this).text ();
247
        if (filter === "_CLEAR_") {
248
            filterList = {};
249
            $("#filter ul li").removeClass ("filter-exclude");
250
            $("#filter ul li").removeClass ("filter-include");
251
            doFilter ();
252
            return;
253
        }
254
        switch ($(this).attr("class")) {
255
            case "filter-include" :
256
                $(this).attr("class", "filter-exclude");
257
                filterList [filter] = false;
258
                break;
259
            case "filter-exclude" :
260
                $(this).removeClass ("filter-exclude");
261
                delete filterList [filter];
262
                break;
263
            default :
264
                $(this).attr("class", "filter-include");
265
                filterList [filter] = true;
266
                break;
267
        }
268
        doFilter ();
269
    });
270
}
271
272
/************************************************
273
 * Functions to handle Ajax navigation
274
 ************************************************
275
 */
276
277
var updatePage, navigateTo;
278
279
updatePage = function (data) {
280
    var result;
281
    filterList = {};
282
    data.c = currentData.c;
283
    if (false && $("section").length && currentData.isPaginated === 0 &&  data.isPaginated === 0) {
284
        // Partial update (for now disabled)
285
        debug_log ("Partial update");
286
        result = templateMain (data);
287
        $("h1").html (data.title);
288
        $("section").html (result);
289
    } else {
290
        // Full update
291
        result = templatePage (data);
292
        $("body").html (result);
293
    }
294
    document.title = data.title;
295
    currentData = data;
296
    setTimeout( function() { $("input[name=query]").focus(); }, 500 );
297
298
    debug_log (elapsed ());
299
300
    if ($.cookie('toolbar') === '1') { $("#tool").show (); }
301
    if (currentData.containsBook === 1) {
302
        $("#sortForm").show ();
303
        if (getCurrentOption ("html_tag_filter") === "1") {
304
            $("#filter ul").empty ();
305
            updateFilters ();
306
            handleFilterEvents ();
307
        }
308
    } else {
309
        $("#sortForm").hide ();
310
    }
311
312
    $('input[name=query]').typeahead(
313
    {
314
        hint: true,
315
        minLength : 3
316
    },
317
    {
318
        name: 'search',
319
        displayKey: 'title',
320
        templates: {
321
            suggestion: templateSuggestion
322
        },
323
        source: copsTypeahead.ttAdapter()
324
    });
325
326
    $('input[name=query]').bind('typeahead:selected', function(obj, datum) {
327
        if (isPushStateEnabled) {
328
            navigateTo (datum.navlink);
329
        } else {
330
            window.location = datum.navlink;
331
        }
332
    });
333
334
    if(typeof postRefresh == 'function')
335
    { postRefresh(); }
336
};
337
338
navigateTo = function (url) {
339
    $("h1").append (" <i class='icon-spinner icon-spin'></i>");
340
    before = new Date ();
341
    var jsonurl = url.replace ("index", "getJSON");
342
    var cachedData = cache.get (jsonurl);
0 ignored issues
show
The variable cache does not seem to be initialized in case typeof LRUCache != "undefined" on line 10 is false. Are you sure this can never be the case?
Loading history...
343
    if (cachedData) {
344
        history.pushState(jsonurl, "", url);
0 ignored issues
show
The variable history seems to be never declared. If this is a global, consider adding a /** global: history */ 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...
345
        updatePage (cachedData);
346
    } else {
347
        $.getJSON(jsonurl, function(data) {
348
            history.pushState(jsonurl, "", url);
0 ignored issues
show
The variable history seems to be never declared. If this is a global, consider adding a /** global: history */ 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...
349
            cache.put (jsonurl, data);
0 ignored issues
show
The variable cache does not seem to be initialized in case typeof LRUCache != "undefined" on line 10 is false. Are you sure this can never be the case?
Loading history...
350
            updatePage (data);
351
        });
352
    }
353
};
354
355
function link_Clicked (event) {
356
    var currentLink = $(this);
357
    if (!isPushStateEnabled ||
358
        currentData.page === "19") {
359
        return;
360
    }
361
    event.preventDefault();
362
    var url = currentLink.attr('href');
363
364
    if ($(".mfp-ready").length)
365
    {
366
        $.magnificPopup.close();
367
    }
368
369
    // The bookdetail / about should be displayed in a lightbox
370
    if (getCurrentOption ("use_fancyapps") === "1" &&
371
        (currentLink.hasClass ("fancydetail") || currentLink.hasClass ("fancyabout"))) {
372
        before = new Date ();
373
        var jsonurl = url.replace ("index", "getJSON");
374
        $.getJSON(jsonurl, function(data) {
375
            data.c = currentData.c;
376
            var detail = "";
377
            if (data.page === "16") {
378
                detail = data.fullhtml;
379
            } else {
380
                detail = templateBookDetail (data);
381
            }
382
            $.magnificPopup.open({
383
              items: {
384
                src: detail,
385
                type: 'inline'
386
              }
387
            });
388
            debug_log (elapsed ());
389
        });
390
        return;
391
    }
392
    navigateTo (url);
393
}
394
395
function search_Submitted (event) {
396
    if (!isPushStateEnabled ||
397
        currentData.page === "19") {
398
        return;
399
    }
400
    event.preventDefault();
401
    var url = str_format ("index.php?page=9&current={0}&query={1}&db={2}", currentData.page, encodeURIComponent ($("input[name=query]").val ()), currentData.databaseId);
402
    navigateTo (url);
403
}
404
405
/*exported handleLinks */
406
function handleLinks () {
407
    $("body").on ("click", "a[href^='index']", link_Clicked);
408
    $("body").on ("submit", "#searchForm", search_Submitted);
409
    $("body").on ("click", "#sort", function(){
410
        $('.books').sortElements(function(a, b){
411
            var test = 1;
412
            if ($("#sortorder").val() === "desc")
413
            {
414
                test = -1;
415
            }
416
            return $(a).find ("." + $("#sortchoice").val()).text() > $(b).find ("." + $("#sortchoice").val()).text() ? test : -test;
417
        });
418
    });
419
420
    $("body").on ("click", ".headright", function(){
421
        if ($("#tool").is(":hidden")) {
422
            $("#tool").slideDown("slow");
423
            $("input[name=query]").focus();
424
            $.cookie('toolbar', '1', { expires: 365 });
425
        } else {
426
            $("#tool").slideUp();
427
            $.removeCookie('toolbar');
428
        }
429
    });
430
    $("body").magnificPopup({
431
        delegate: '.fancycover', // child items selector, by clicking on it popup will open
432
        type: 'image',
433
        gallery:{enabled:true, preload: [0,2]},
434
        disableOn: function() {
435
          if( getCurrentOption ("use_fancyapps") === "1" ) {
436
            return true;
437
          }
438
          return false;
439
        }
440
    });
441
}
442
443
window.onpopstate = function(event) {
444
    if (!isDefined (currentData)) {
445
        return;
446
    }
447
448
    before = new Date ();
449
    var data = cache.get (event.state);
0 ignored issues
show
The variable cache does not seem to be initialized in case typeof LRUCache != "undefined" on line 10 is false. Are you sure this can never be the case?
Loading history...
450
    updatePage (data);
451
};
452
453
$(document).keydown(function(e){
454
    if (e.keyCode === 37 && $("#prevLink").length > 0) {
455
        navigateTo ($("#prevLink").attr('href'));
456
    }
457
    if (e.keyCode === 39  && $("#nextLink").length > 0) {
458
        navigateTo ($("#nextLink").attr('href'));
459
    }
460
});
461
462
/*exported initiateAjax */
463
function initiateAjax (url, theme) {
464
    $.when($.get('templates/' + theme + '/header.html'),
465
           $.get('templates/' + theme + '/footer.html'),
466
           $.get('templates/' + theme + '/bookdetail.html'),
467
           $.get('templates/' + theme + '/main.html'),
468
           $.get('templates/' + theme + '/page.html'),
469
           $.get('templates/' + theme + '/suggestion.html'),
470
           $.getJSON(url)).done(function(header, footer, bookdetail, main, page, suggestion, data){
471
        templateBookDetail = doT.template (bookdetail [0]);
472
473
        var defMain = {
474
            bookdetail: bookdetail [0]
475
        };
476
477
        templateMain = doT.template (main [0], undefined, defMain);
478
479
        var defPage = {
480
            header: header [0],
481
            footer: footer [0],
482
            main  : main [0],
483
            bookdetail: bookdetail [0]
484
        };
485
486
        templatePage = doT.template (page [0], undefined, defPage);
487
488
        templateSuggestion = doT.template (suggestion [0]);
489
490
        currentData = data [0];
491
492
        updatePage (data [0]);
493
        cache.put (url, data [0]);
0 ignored issues
show
The variable cache does not seem to be initialized in case typeof LRUCache != "undefined" on line 10 is false. Are you sure this can never be the case?
Loading history...
494
        if (isPushStateEnabled) {
495
            history.replaceState(url, "", window.location);
0 ignored issues
show
The variable history seems to be never declared. If this is a global, consider adding a /** global: history */ 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...
496
        }
497
        handleLinks ();
498
    });
499
}