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