seblucas /
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!'); |
||
|
0 ignored issues
–
show
Debugging Code
introduced
by
Loading history...
|
|||
| 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 ("icon-spinner icon-spin").addClass ("icon-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 ("icon-envelope").addClass ("icon-spinner icon-spin"); |
||
| 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='icon-spinner icon-spin'></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 |