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 | /** global: navigator, history */ |
||
| 9 | |||
| 10 | var templatePage, templateBookDetail, templateMain, templateSuggestion, currentData, before, filterList; |
||
| 11 | |||
| 12 | if (typeof LRUCache != 'undefined') { |
||
| 13 | var cache = new LRUCache(30); |
||
| 14 | } |
||
| 15 | |||
| 16 | $.ajaxSetup({ |
||
| 17 | cache: false |
||
| 18 | }); |
||
| 19 | |||
| 20 | var copsTypeahead = new Bloodhound({ |
||
| 21 | datumTokenizer: Bloodhound.tokenizers.obj.whitespace('title'), |
||
| 22 | queryTokenizer: Bloodhound.tokenizers.whitespace, |
||
| 23 | limit: 30, |
||
| 24 | remote: { |
||
| 25 | url: 'getJSON.php?page=9&search=1&db=%DB&query=%QUERY', |
||
| 26 | replace: function (url, query) { |
||
| 27 | if (currentData.multipleDatabase === 1 && currentData.databaseId === "") { |
||
| 28 | return url.replace('%QUERY', query).replace('&db=%DB', ""); |
||
| 29 | } |
||
| 30 | return url.replace('%QUERY', query).replace('%DB', currentData.databaseId); |
||
| 31 | } |
||
| 32 | } |
||
| 33 | }); |
||
| 34 | |||
| 35 | copsTypeahead.initialize(); |
||
| 36 | |||
| 37 | var DEBUG = false; |
||
| 38 | var isPushStateEnabled = window.history && window.history.pushState && window.history.replaceState && |
||
| 39 | // pushState isn't reliable on iOS until 5. |
||
| 40 | !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/); |
||
| 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) { |
||
|
0 ignored issues
–
show
|
|||
| 166 | var tag = tagarray [i].replace(/^\s+/g,'').replace(/\s+$/g,''); |
||
| 167 | tagList [tag] = 1; |
||
| 168 | } |
||
| 169 | }); |
||
| 170 | return tagList; |
||
| 171 | } |
||
| 172 | |||
| 173 | function updateFilters () { |
||
| 174 | var tagList = getTagList (); |
||
| 175 | |||
| 176 | // If there is already some filters then let's prepare to update the list |
||
| 177 | $("#filter ul li").each (function () { |
||
| 178 | var text = $(this).text (); |
||
| 179 | if (isDefined (tagList [text]) || $(this).attr ('class')) { |
||
| 180 | tagList [text] = 0; |
||
| 181 | } else { |
||
| 182 | tagList [text] = -1; |
||
| 183 | } |
||
| 184 | }); |
||
| 185 | |||
| 186 | // Update the filter -1 to remove, 1 to add, 0 already there |
||
| 187 | 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...
|
|||
| 188 | var tagValue = tagList [tag]; |
||
| 189 | if (tagValue === -1) { |
||
| 190 | $("#filter ul li").filter (function () { return $.text([this]) === tag; }).remove(); |
||
| 191 | } |
||
| 192 | if (tagValue === 1) { |
||
| 193 | $("#filter ul").append ("<li>" + tag + "</li>"); |
||
| 194 | } |
||
| 195 | } |
||
| 196 | |||
| 197 | $("#filter ul").append ("<li>_CLEAR_</li>"); |
||
| 198 | |||
| 199 | // Sort the list alphabetically |
||
| 200 | $('#filter ul li').sortElements(function(a, b){ |
||
| 201 | return $(a).text() > $(b).text() ? 1 : -1; |
||
| 202 | }); |
||
| 203 | } |
||
| 204 | |||
| 205 | function doFilter () { |
||
| 206 | $(".books").removeClass("filtered"); |
||
| 207 | if (jQuery.isEmptyObject(filterList)) { |
||
| 208 | updateFilters (); |
||
| 209 | return; |
||
| 210 | } |
||
| 211 | |||
| 212 | $(".se").each (function(){ |
||
| 213 | var taglist = ", " + $(this).text() + ", "; |
||
| 214 | var toBeFiltered = false; |
||
| 215 | for (var filter in filterList) { |
||
| 216 | var onlyThisTag = filterList [filter]; |
||
| 217 | filter = ', ' + filter + ', '; |
||
| 218 | var myreg = new RegExp (filter); |
||
| 219 | if (myreg.test (taglist)) { |
||
| 220 | if (onlyThisTag === false) { |
||
| 221 | toBeFiltered = true; |
||
| 222 | } |
||
| 223 | } else { |
||
| 224 | if (onlyThisTag === true) { |
||
| 225 | toBeFiltered = true; |
||
| 226 | } |
||
| 227 | } |
||
| 228 | } |
||
| 229 | if (toBeFiltered) { $(this).parents (".books").addClass ("filtered"); } |
||
| 230 | }); |
||
| 231 | |||
| 232 | // Handle the books with no tags |
||
| 233 | var atLeastOneTagSelected = false; |
||
| 234 | for (var filter in filterList) { |
||
| 235 | if (filterList [filter] === true) { |
||
| 236 | atLeastOneTagSelected = true; |
||
| 237 | } |
||
| 238 | } |
||
| 239 | if (atLeastOneTagSelected) { |
||
| 240 | $(".books").not (":has(span.se)").addClass ("filtered"); |
||
| 241 | } |
||
| 242 | |||
| 243 | updateFilters (); |
||
| 244 | } |
||
| 245 | |||
| 246 | function handleFilterEvents () { |
||
| 247 | $("#filter ul").on ("click", "li", function(){ |
||
| 248 | var filter = $(this).text (); |
||
| 249 | if (filter === "_CLEAR_") { |
||
| 250 | filterList = {}; |
||
| 251 | $("#filter ul li").removeClass ("filter-exclude"); |
||
| 252 | $("#filter ul li").removeClass ("filter-include"); |
||
| 253 | doFilter (); |
||
| 254 | return; |
||
| 255 | } |
||
| 256 | switch ($(this).attr("class")) { |
||
| 257 | case "filter-include" : |
||
| 258 | $(this).attr("class", "filter-exclude"); |
||
| 259 | filterList [filter] = false; |
||
| 260 | break; |
||
| 261 | case "filter-exclude" : |
||
| 262 | $(this).removeClass ("filter-exclude"); |
||
| 263 | delete filterList [filter]; |
||
| 264 | break; |
||
| 265 | default : |
||
| 266 | $(this).attr("class", "filter-include"); |
||
| 267 | filterList [filter] = true; |
||
| 268 | break; |
||
| 269 | } |
||
| 270 | doFilter (); |
||
| 271 | }); |
||
| 272 | } |
||
| 273 | |||
| 274 | /************************************************ |
||
| 275 | * Functions to handle Ajax navigation |
||
| 276 | ************************************************ |
||
| 277 | */ |
||
| 278 | |||
| 279 | var updatePage, navigateTo; |
||
| 280 | |||
| 281 | updatePage = function (data) { |
||
| 282 | var result; |
||
| 283 | filterList = {}; |
||
| 284 | data.c = currentData.c; |
||
| 285 | if (false && $("section").length && currentData.isPaginated === 0 && data.isPaginated === 0) { |
||
| 286 | // Partial update (for now disabled) |
||
| 287 | debug_log ("Partial update"); |
||
| 288 | result = templateMain (data); |
||
| 289 | $("h1").html (data.title); |
||
| 290 | $("section").html (result); |
||
| 291 | } else { |
||
| 292 | // Full update |
||
| 293 | result = templatePage (data); |
||
| 294 | $("body").html (result); |
||
| 295 | } |
||
| 296 | document.title = data.title; |
||
| 297 | currentData = data; |
||
| 298 | setTimeout( function() { $("input[name=query]").focus(); }, 500 ); |
||
| 299 | |||
| 300 | debug_log (elapsed ()); |
||
| 301 | |||
| 302 | if ($.cookie('toolbar') === '1') { $("#tool").show (); } |
||
| 303 | if (currentData.containsBook === 1) { |
||
| 304 | $("#sortForm").show (); |
||
| 305 | if (getCurrentOption ("html_tag_filter") === "1") { |
||
| 306 | $("#filter ul").empty (); |
||
| 307 | updateFilters (); |
||
| 308 | handleFilterEvents (); |
||
| 309 | } |
||
| 310 | } else { |
||
| 311 | $("#sortForm").hide (); |
||
| 312 | } |
||
| 313 | |||
| 314 | $('input[name=query]').typeahead( |
||
| 315 | { |
||
| 316 | hint: true, |
||
| 317 | minLength : 3 |
||
| 318 | }, |
||
| 319 | { |
||
| 320 | name: 'search', |
||
| 321 | displayKey: 'title', |
||
| 322 | templates: { |
||
| 323 | suggestion: templateSuggestion |
||
| 324 | }, |
||
| 325 | source: copsTypeahead.ttAdapter() |
||
| 326 | }); |
||
| 327 | |||
| 328 | $('input[name=query]').bind('typeahead:selected', function(obj, datum) { |
||
| 329 | if (isPushStateEnabled) { |
||
| 330 | navigateTo (datum.navlink); |
||
| 331 | } else { |
||
| 332 | window.location = datum.navlink; |
||
| 333 | } |
||
| 334 | }); |
||
| 335 | |||
| 336 | if(typeof postRefresh == 'function') |
||
| 337 | { postRefresh(); } |
||
| 338 | }; |
||
| 339 | |||
| 340 | navigateTo = function (url) { |
||
| 341 | $("h1").append (" <i class='icon-spinner icon-spin'></i>"); |
||
| 342 | before = new Date (); |
||
| 343 | var jsonurl = url.replace ("index", "getJSON"); |
||
| 344 | var cachedData = cache.get (jsonurl); |
||
| 345 | if (cachedData) { |
||
| 346 | history.pushState(jsonurl, "", url); |
||
| 347 | updatePage (cachedData); |
||
| 348 | } else { |
||
| 349 | $.getJSON(jsonurl, function(data) { |
||
| 350 | history.pushState(jsonurl, "", url); |
||
| 351 | cache.put (jsonurl, data); |
||
| 352 | updatePage (data); |
||
| 353 | }); |
||
| 354 | } |
||
| 355 | }; |
||
| 356 | |||
| 357 | function link_Clicked (event) { |
||
| 358 | var currentLink = $(this); |
||
| 359 | if (!isPushStateEnabled || |
||
| 360 | currentData.page === "19") { |
||
| 361 | return; |
||
| 362 | } |
||
| 363 | event.preventDefault(); |
||
| 364 | var url = currentLink.attr('href'); |
||
| 365 | |||
| 366 | if ($(".mfp-ready").length) |
||
| 367 | { |
||
| 368 | $.magnificPopup.close(); |
||
| 369 | } |
||
| 370 | |||
| 371 | // The bookdetail / about should be displayed in a lightbox |
||
| 372 | if (getCurrentOption ("use_fancyapps") === "1" && |
||
| 373 | (currentLink.hasClass ("fancydetail") || currentLink.hasClass ("fancyabout"))) { |
||
| 374 | before = new Date (); |
||
| 375 | var jsonurl = url.replace ("index", "getJSON"); |
||
| 376 | $.getJSON(jsonurl, function(data) { |
||
| 377 | data.c = currentData.c; |
||
| 378 | var detail = ""; |
||
| 379 | if (data.page === "16") { |
||
| 380 | detail = data.fullhtml; |
||
| 381 | } else { |
||
| 382 | detail = templateBookDetail (data); |
||
| 383 | } |
||
| 384 | $.magnificPopup.open({ |
||
| 385 | items: { |
||
| 386 | src: detail, |
||
| 387 | type: 'inline' |
||
| 388 | } |
||
| 389 | }); |
||
| 390 | debug_log (elapsed ()); |
||
| 391 | }); |
||
| 392 | return; |
||
| 393 | } |
||
| 394 | navigateTo (url); |
||
| 395 | } |
||
| 396 | |||
| 397 | function search_Submitted (event) { |
||
| 398 | if (!isPushStateEnabled || |
||
| 399 | currentData.page === "19") { |
||
| 400 | return; |
||
| 401 | } |
||
| 402 | event.preventDefault(); |
||
| 403 | var url = str_format ("index.php?page=9¤t={0}&query={1}&db={2}", currentData.page, encodeURIComponent ($("input[name=query]").val ()), currentData.databaseId); |
||
| 404 | navigateTo (url); |
||
| 405 | } |
||
| 406 | |||
| 407 | /*exported handleLinks */ |
||
| 408 | function handleLinks () { |
||
| 409 | $("body").on ("click", "a[href^='index']", link_Clicked); |
||
| 410 | $("body").on ("submit", "#searchForm", search_Submitted); |
||
| 411 | $("body").on ("click", "#sort", function(){ |
||
| 412 | $('.books').sortElements(function(a, b){ |
||
| 413 | var test = 1; |
||
| 414 | if ($("#sortorder").val() === "desc") |
||
| 415 | { |
||
| 416 | test = -1; |
||
| 417 | } |
||
| 418 | return $(a).find ("." + $("#sortchoice").val()).text() > $(b).find ("." + $("#sortchoice").val()).text() ? test : -test; |
||
| 419 | }); |
||
| 420 | }); |
||
| 421 | |||
| 422 | $("body").on ("click", ".headright", function(){ |
||
| 423 | if ($("#tool").is(":hidden")) { |
||
| 424 | $("#tool").slideDown("slow"); |
||
| 425 | $("input[name=query]").focus(); |
||
| 426 | $.cookie('toolbar', '1', { expires: 365 }); |
||
| 427 | } else { |
||
| 428 | $("#tool").slideUp(); |
||
| 429 | $.removeCookie('toolbar'); |
||
| 430 | } |
||
| 431 | }); |
||
| 432 | $("body").magnificPopup({ |
||
| 433 | delegate: '.fancycover', // child items selector, by clicking on it popup will open |
||
| 434 | type: 'image', |
||
| 435 | gallery:{enabled:true, preload: [0,2]}, |
||
| 436 | disableOn: function() { |
||
| 437 | if( getCurrentOption ("use_fancyapps") === "1" ) { |
||
| 438 | return true; |
||
| 439 | } |
||
| 440 | return false; |
||
| 441 | } |
||
| 442 | }); |
||
| 443 | } |
||
| 444 | |||
| 445 | window.onpopstate = function(event) { |
||
| 446 | if (!isDefined (currentData)) { |
||
| 447 | return; |
||
| 448 | } |
||
| 449 | |||
| 450 | before = new Date (); |
||
| 451 | var data = cache.get (event.state); |
||
| 452 | updatePage (data); |
||
| 453 | }; |
||
| 454 | |||
| 455 | $(document).keydown(function(e){ |
||
| 456 | if (e.keyCode === 37 && $("#prevLink").length > 0) { |
||
| 457 | navigateTo ($("#prevLink").attr('href')); |
||
| 458 | } |
||
| 459 | if (e.keyCode === 39 && $("#nextLink").length > 0) { |
||
| 460 | navigateTo ($("#nextLink").attr('href')); |
||
| 461 | } |
||
| 462 | }); |
||
| 463 | |||
| 464 | /*exported initiateAjax */ |
||
| 465 | function initiateAjax (url, theme) { |
||
| 466 | $.when($.get('templates/' + theme + '/header.html'), |
||
| 467 | $.get('templates/' + theme + '/footer.html'), |
||
| 468 | $.get('templates/' + theme + '/bookdetail.html'), |
||
| 469 | $.get('templates/' + theme + '/main.html'), |
||
| 470 | $.get('templates/' + theme + '/page.html'), |
||
| 471 | $.get('templates/' + theme + '/suggestion.html'), |
||
| 472 | $.getJSON(url)).done(function(header, footer, bookdetail, main, page, suggestion, data){ |
||
| 473 | templateBookDetail = doT.template (bookdetail [0]); |
||
| 474 | |||
| 475 | var defMain = { |
||
| 476 | bookdetail: bookdetail [0] |
||
| 477 | }; |
||
| 478 | |||
| 479 | templateMain = doT.template (main [0], undefined, defMain); |
||
| 480 | |||
| 481 | var defPage = { |
||
| 482 | header: header [0], |
||
| 483 | footer: footer [0], |
||
| 484 | main : main [0], |
||
| 485 | bookdetail: bookdetail [0] |
||
| 486 | }; |
||
| 487 | |||
| 488 | templatePage = doT.template (page [0], undefined, defPage); |
||
| 489 | |||
| 490 | templateSuggestion = doT.template (suggestion [0]); |
||
| 491 | |||
| 492 | currentData = data [0]; |
||
| 493 | |||
| 494 | updatePage (data [0]); |
||
| 495 | cache.put (url, data [0]); |
||
| 496 | if (isPushStateEnabled) { |
||
| 497 | history.replaceState(url, "", window.location); |
||
| 498 | } |
||
| 499 | handleLinks (); |
||
| 500 | }); |
||
| 501 | } |
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: