1//uppercase first letter of string 2function jsUcfirst(string) { 3 return string.charAt(0).toUpperCase() + string.slice(1); 4} 5 6//Generate a hash from a string 7function hashCode(s) { 8 return s.split("").reduce(function(a, b) { 9 a = ((a << 5) - a) + b.charCodeAt(0); 10 return a & a; 11 }, 0); 12} 13 14// WordPress REST titles are HTML-rendered strings. Decode their entities before 15// assigning them to text-only browser properties such as document.title. 16function decodeHtmlText(value) { 17 var textarea = document.createElement("textarea"); 18 textarea.innerHTML = value || ""; 19 return textarea.value; 20} 21 22function setCookie(cname, cvalue, exdays) { 23 const d = new Date(); 24 d.setTime(d.getTime() + (exdays*24*60*60*1000)); 25 let expires = "expires="+ d.toUTCString(); 26 document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; 27} 28 29function getCookie(cname) { 30 let name = cname + "="; 31 let decodedCookie = decodeURIComponent(document.cookie); 32 let ca = decodedCookie.split(';'); 33 for(let i = 0; i <ca.length; i++) { 34 let c = ca[i]; 35 while (c.charAt(0) == ' ') { 36 c = c.substring(1); 37 } 38 if (c.indexOf(name) == 0) { 39 return c.substring(name.length, c.length); 40 } 41 } 42 return ""; 43} 44 45//https://phuoc.ng/collection/html-dom/check-if-an-element-is-visible-in-a-scrollable-container/ 46function isVisible(ele, container) { 47 const { bottom, height, top } = ele.getBoundingClientRect(); 48 const containerRect = container.getBoundingClientRect(); 49 50 return top <= containerRect.top ? containerRect.top - top <= height : bottom - containerRect.bottom <= height; 51}; 52 53(function($) { 54 55 //Serialize object function 56 $.fn.serializeObject = function() { 57 var o = {}; 58 var a = this.serializeArray(); 59 $.each(a, function() { 60 if (o[this.name]) { 61 if (!o[this.name].push) { 62 o[this.name] = [o[this.name]]; 63 } 64 o[this.name].push(this.value || ''); 65 } else { 66 o[this.name] = this.value || ''; 67 } 68 }); 69 return o; 70 }; 71 72 //Toggle the loader 73 toggle_loader = function(element_id) { 74 var in_progress = $("#multi-loader").attr("data-loading"); 75 76 var elements = in_progress.split(","); 77 var ipn = []; 78 for(var i = 0; i < elements.length; i++) { 79 if (elements[i] != "") { 80 ipn.push(elements[i]); 81 } 82 } 83 elements = ipn; 84 85 if ($.inArray(element_id, elements) == -1) { 86 elements.push(element_id); 87 } 88 else { 89 var res = $.grep(elements, function( a ) { 90 return a !== element_id; 91 }); 92 elements = res; 93 } 94 in_progress = elements.join(","); 95 $("#multi-loader").attr("data-loading", in_progress); 96 97 if (in_progress == "") { 98 $("#multi-loader").hide(); 99 } 100 else { 101 $("#multi-loader").show(); 102 } 103 } 104 105 //Load the user's bookmarks 106 function ajax_call(action, parameters, target, template) { 107 parameters.action = action; 108 console.log(parameters); 109 110 var id = Date.now(); 111 toggle_loader("collections-" + id); 112 113 $.post(localizations.ajaxUrl, parameters, function(response) { 114 $(target).find(".loading").remove(); 115 116 response = $.parseJSON(response); 117 response.localizations = localizations; 118 console.log("user bookmarks", response); 119 120 $(target).html(window[template](response)); 121 122 toggle_loader("collections-" + id); 123 }); 124 } 125 function trigger_ajax_call(action, parameters, target, template) { 126 if (typeof(window[template]) !== 'undefined') { 127 ajax_call(action, parameters, target, template); 128 } 129 else { 130 setTimeout(function() { 131 trigger_ajax_call(action, parameters, target, template); 132 }, 1000); 133 } 134 } 135 $(document).on("click", ".js-trigger_ajax_call", function() { 136 var button = $(this); 137 var can_fetch = true; 138 139 if (button.attr("data-logged_in") == "1") { 140 if ($("body.logged-in").length) { 141 } 142 else { 143 can_fetch = false; 144 } 145 } 146 147 var parameters = {}; 148 $.each(button.data(), function(k, v) { 149 if (k.substring(0, 9) == "parameter") { 150 var p = k.substring(10); 151 parameters[p] = v; 152 } 153 }); 154 155 if (can_fetch) { 156 console.log(parameters); 157 trigger_ajax_call(button.attr("data-action"), parameters, button.attr("data-target"), button.attr("data-template")); 158 } 159 }); 160 161 //What needs to run after loading a placecast 162 placecast_callback = function(result) { 163 console.log("Entering the placecast callback", result); 164 165 //Pick up covers, if any 166 find_covers(); 167 168 //Track the view directly in Matomo. Logged-in views are also recorded in 169 //WordPress so the recommendation logic can avoid repetitions. 170 track_viewpoint_event("View", result.results.id); 171 if (parseInt($("body").attr("data-user"), 10) > 0) { 172 log_event("view_placecast", {post_id: result.results.id}); 173 } 174 175 //Switch to streetview 176 $("#nav-street_view-tab").trigger("click"); 177 178 var sv = result.results.acf.streetview[0]; 179 var loc = result.results.acf.location; 180 181 //Set up the streetview 182 $("#placecast-streetview").attr("data-lat", sv.latitude); 183 $("#placecast-streetview").attr("data-lng", sv.longitude); 184 $("#placecast-streetview").attr("data-heading", sv.heading); 185 $("#placecast-streetview").attr("data-pitch", sv.pitch); 186 placecloud_reset_streetview(); 187 188 //Set up the map 189 $("#placecast-map").attr("data-lat", result.results.acf.location.lat); 190 $("#placecast-map").attr("data-lng", result.results.acf.location.lng); 191 $("#placecast-map").attr("data-accredited", "0"); 192 $("#placecast-map").attr("data-voted", "0"); 193 $("#placecast-map").attr("data-new", "0"); 194 $("#placecast-map").attr("data-icon", result.results.icon); 195 if (result.results.author.accreditations.length > 0) { 196 $("#placecast-map").attr("data-accredited", "1"); 197 } 198 if (result.results.voted) { 199 $("#placecast-map").attr("data-voted", "1"); 200 } 201 if (result.results.is_new) { 202 $("#placecast-map").attr("data-new", "1"); 203 } 204 placecloud_reset_map(); 205 206 //Set the page title using plain text, not the REST API's encoded HTML. 207 document.title = decodeHtmlText(result.results.title.rendered); 208 209 //Set the redirect url in the login form 210 $("#loginModal input[name='redirect_to']").val('https://placecloud.io/?viewpoint=' + result.results.id); 211 212 //Set the redirect url in the logout button 213 $("#sign-out-link").attr("href", $("#sign-out-link").attr("href") + "&redirect_to=" + encodeURI('https://placecloud.io/?viewpoint=' + result.results.id)); 214 } 215 216 //What needs to run after loading 'my collections' 217 //Storing the collections in a global variable, to be used elsewhere. 218 my_collections_callback = function(result){ 219 console.log(result); 220 221 var current_placecast = $("#random-placecast").attr("data-id"); 222 223 set_collections_for_placecast(current_placecast); 224 } 225 226 //Given a set of collections, set these as the collections the placecast can be added to 227 function set_collections_for_placecast(placecast_id) { 228 console.log("Setting user collections for placecast " + placecast_id); 229 230 var data = { 231 action: "placecloud_placecast_user_collections", 232 post_id: placecast_id 233 }; 234 235 //toggle_loader("user-collections-" + placecast_id); 236 237 //This could be done with a standard rest api call 238 $.post(localizations.ajaxUrl, data, function(response) { 239 response = $.parseJSON(response); 240 console.log("Placecast user collections", response); 241
242 if (response.success) { 243 $(".user-collections .user-collection").remove(); 244 245 var uc = { 246 user_collections: response.result 247 } 248 $(".user-collections").prepend(user_collections_template(uc)); 249 } 250 else { 251 console.log("Problem"); 252 } 253 254 //toggle_loader("user-collections-" + placecast_id); 255 }); 256 } 257 258 //Load all handlebars 259 render_handlebars = function(element,template,r,callback) { 260 if (typeof(window[template]) !== 'undefined') { 261 element.find(".loading").removeClass("d-flex").addClass("d-none"); 262 element.find(".loading-once").addClass("d-none"); 263 264 //Append requires data-page to also be set 265 var append = false; 266//console.log("1"); 267 if (typeof (element.attr("data-append")) !== "undefined") { 268//console.log("2"); 269 if (element.attr("data-append") == "1") { 270//console.log("3"); 271 if (typeof (element.attr("data-page")) !== 'undefined') { 272//console.log("4"); 273 if (element.attr("data-page") != "1") { 274//console.log("5"); 275 append = true; 276 } 277 } 278 } 279 } 280 281 if (append) { 282 element.find(".content").append(window[template](r)).show(); 283 } 284 else { 285 element.find(".content").html(window[template](r)).show(); 286 } 287 288 //Increase the page number 289 if (typeof (element.attr("data-page")) !== 'undefined') { 290 element.attr("data-page", parseInt(element.attr("data-page")) + 1); 291 } 292 293 //console.log(callback); 294 eval(callback); 295 } 296 else { 297 setTimeout(function() { 298 render_handlebars(element,template,r,callback); 299 }, 1000); 300 } 301 } 302 load_handlebars = function() { 303 $( ".load-handlebars" ).each(function() { 304 var element = $(this); 305 306 if (element.attr("data-loading") == "0" && element.attr("data-loaded") == "0") { 307 var current_id = Date.now(); //For loading and stuff 308 309 console.log("Element to load", element.attr("id")); 310 311 element.attr("data-loading", "1"); 312 //element.find(".content").html("").hide(); 313 element.find(".loading").removeClass("d-none").addClass("d-flex"); 314 315 var template = element.attr("data-template"); 316 var post_id = element.attr("data-id"); 317 var post_type = element.attr('data-post_type'); 318 319 var callback = false; 320 if (typeof element.attr("data-callback") !== "undefined") { 321 callback = element.attr("data-callback"); 322 } 323 324 var post_id = ""; 325 if (typeof(element.attr("data-id")) !== 'undefined') { 326 if (element.attr("data-id") != "") { 327 post_id = element.attr("data-id"); 328 } 329 } 330 331 var nonce = ""; 332 if (typeof($("body").attr("data-nonce")) !== 'undefined') { 333 if ($("body").attr("data-nonce") != "") { 334 nonce = '&_wpnonce=' + $("body").attr("data-nonce"); 335 } 336 } 337 338 var fields = ""; 339 if (typeof(element.attr("data-fields")) !== 'undefined') { 340 if (element.attr("data-fields") != "") { 341 //_embedded does not work without _links 342 fields = '&_fields=' + element.attr("data-fields") + ",_embedded,_links"; 343 } 344 } 345 346 var page = ""; 347 if (typeof(element.attr("data-page")) !== 'undefined') { 348 page = "&page=" + element.attr("data-page"); 349 } 350 351 var search = ""; 352 if (typeof(element.attr("data-search")) !== 'undefined') { 353 search = "&search=" + element.attr("data-search"); 354 element.find("form").addClass("disabled"); 355 } 356 357 toggle_loader(template + "-" + post_type + "-" + current_id); 358 359 element.attr("data-loading", "1"); 360 361 var this_is_a_lookup = false; //Whether we have to go through the votes 362 363 var filter = ""; 364 //placecast specific filters: language, tag 365 if (post_type == "placecast" && post_id == "") { 366 var lang = $("html").attr("lang").substring(0,2); 367 console.log("Filtering placecast on lang", lang); 368 filter = "&filter[meta_key]=language&filter[meta_value]=" + lang; 369 370 if (typeof(element.attr("data-filter_type")) !== "undefined") { 371 var typex = element.attr("data-filter_type"); 372 var idx = element.attr("data-filter_id"); 373 374 if (typex == "collection") { 375 //We need to get votes to find the placecasts 376 this_is_a_lookup = true; 377 378 var post_typex = "vote"; 379 var include_embedsx = "_embed&"; 380 var include_fieldsx = "_fields=_links,_embedded,acf,persona&"; 381 //var include_fields = ""; 382 var include_searchx = ""; 383 var filterx = ""; 384 if (typex == "collection" && idx > 0) { 385 filterx = "&filter[meta_query][0][key]=collection&filter[meta_query][0][value]=" + idx + "&filter[meta_query][0][compare]=="; 386 } 387 // else { 388 // filter = "&author=" + $("body").attr("data-user") + "&filter[meta_query][0][key]=collection&filter[meta_query][0][compare]=NOT%20EXISTS"; 389 // } 390 var noncex = ''; 391 if (typeof($("body").attr("data-nonce")) !== "undefined") { 392 noncex = "&_wpnonce=" + $("body").attr("data-nonce"); 393 } 394 var json_urlx = localizations.restUrl + post_typex + "?" + include_embedsx + include_fieldsx + include_searchx + "page=" + page + filterx + noncex; 395 console.log("votes for list", json_urlx); 396 397 var jqxhr = $.get( json_urlx, {}, function(responsex) { 398 console.log("hearts for list", responsex); 399 400 var temp_placecast_ids = []; 401 for (var i = 0; i < responsex.length; i++) { 402 temp_placecast_ids.push(responsex[i].acf.post[0]); 403 } 404 405 if (temp_placecast_ids.length) { 406 //We have placecast ids 407 console.log("placecast ids for list", temp_placecast_ids); 408 409 //Terribly inefficient. Almost same code as below. Should be streamlined. 410 //We need to retrieve by placecast IDs, and not set the page number 411 //post_id is not set 412 var include = "&include=" + temp_placecast_ids.join(","); 413 414 var json_url = localizations.restUrl + post_type + "/?_embed" + filter + include + nonce + fields + search; 415 console.log(json_url); 416 417 var jqxhr = $.ajax( json_url ) 418 .done(function(response) { 419 var treat_as_done = false;
420 421 if (response) { 422 if (Array.isArray(response)) { 423 if (response.length == 0) { 424 treat_as_done = true; 425 } 426 } 427 } 428 else { 429 treat_as_done = true; 430 } 431 432 if (treat_as_done) { 433 if (typeof(element.attr("data-page")) !== 'undefined') { 434 r = { 435 results: [], 436 localizations: localizations 437 }; 438 439 element.attr("data-loaded_all", "1") 440 render_handlebars(element, "no_more_results_template", r, callback); 441 } 442 443 } 444 else { 445 r = { 446 results: response, 447 localizations: localizations 448 }; 449 console.log("rest response", r); 450 451 //console.log(element, template, r, callback); 452 render_handlebars(element, template, r, callback); 453 454 } 455 456 }) 457 .fail(function() { 458 //button.hide(); 459 460 if (typeof(element.attr("data-page")) !== 'undefined') { 461 r = { 462 results: [], 463 localizations: localizations 464 }; 465 466 element.attr("data-loaded_all", "1") 467 render_handlebars(element, "no_more_results_template", r, callback); 468 } 469 470 }) 471 .always(function() { 472 element.attr("data-loading", "0"); 473 element.attr("data-loaded", "1"); 474 475 if (typeof(element.attr("data-search")) !== 'undefined') { 476 element.find("form").removeClass("disabled"); 477 } 478 479 if (element.hasClass("monitor-scroll")) { 480 trigger_handlebars_if_visible(element.find(".trigger").attr("id"), element.attr("id")); 481 } 482 483 toggle_loader(template + "-" + post_type + "-" + current_id); 484 }); 485 } 486 }) 487 .done(function() { 488 }) 489 .fail(function() { 490 //We have reached the end of the vote lookup 491 492 if (typeof(element.attr("data-page")) !== 'undefined') { 493 r = { 494 results: [], 495 localizations: localizations 496 }; 497 498 element.attr("data-loaded_all", "1") 499 render_handlebars(element, "no_more_results_template", r, callback); 500 501 element.attr("data-loading", "0"); 502 element.attr("data-loaded", "1"); 503 504 if (typeof(element.attr("data-search")) !== 'undefined') { 505 element.find("form").removeClass("disabled"); 506 } 507 508 if (element.hasClass("monitor-scroll")) { 509 trigger_handlebars_if_visible(element.find(".trigger").attr("id"), element.attr("id")); 510 } 511 512 toggle_loader(template + "-" + post_type + "-" + current_id); 513 } 514 }) 515 .always(function() { 516 //toggle_loader("map-" + modalId + "-" + type + "-" + id + "-" + paged); 517 }); 518 519 } 520 if (typex == "book") { 521 filter += '&filter[meta_query][0][key]=books_alt&filter[meta_query][0][value]=%22' + idx + '%22&filter[meta_query][0][compare]=LIKE'; 522 } 523 else { 524 filter += "&" + typex + "=" + idx; 525 } 526 } 527 } 528 // if (post_type == "collection" && post_id == "") { 529 // var lang = $("html").attr("lang").substring(0,2); 530 // console.log("Filtering collection on lang", lang); 531 // filter = "&filter[meta_key]=language&filter[meta_value]=" + lang; 532 // } 533 534 if (!this_is_a_lookup) { 535 var json_url = localizations.restUrl + post_type + "/" + post_id + "?_embed" + filter + nonce + fields + page + search; 536 console.log(json_url); 537 538 var jqxhr = $.ajax( json_url ) 539 .done(function(response) { 540 var treat_as_done = false; 541 542 if (response) { 543 if (Array.isArray(response)) { 544 if (response.length == 0) { 545 treat_as_done = true; 546 } 547 } 548 } 549 else { 550 treat_as_done = true; 551 } 552 553 if (treat_as_done) { 554 if (typeof(element.attr("data-page")) !== 'undefined') { 555 r = { 556 results: [], 557 localizations: localizations 558 }; 559 560 element.attr("data-loaded_all", "1") 561 render_handlebars(element, "no_more_results_template", r, callback); 562 } 563 564 } 565 else { 566 r = { 567 results: response, 568 localizations: localizations 569 }; 570 console.log("rest response", r); 571 572 //console.log(element, template, r, callback); 573 render_handlebars(element, template, r, callback); 574 575 } 576 577 }) 578 .fail(function() { 579 //button.hide(); 580 581 if (typeof(element.attr("data-page")) !== 'undefined') { 582 r = { 583 results: [], 584 localizations: localizations 585 }; 586 587 element.attr("data-loaded_all", "1") 588 render_handlebars(element, "no_more_results_template", r, callback); 589 } 590 591 }) 592 .always(function() { 593 element.attr("data-loading", "0"); 594 element.attr("data-loaded", "1"); 595 596 if (typeof(element.attr("data-search")) !== 'undefined') { 597 element.find("form").removeClass("disabled"); 598 } 599 600 if (element.hasClass("monitor-scroll")) { 601 trigger_handlebars_if_visible(element.find(".trigger").attr("id"), element.attr("id")); 602 } 603 604 toggle_loader(template + "-" + post_type + "-" + current_id); 605 }); 606 } 607 } 608 609 }); 610 } 611 load_handlebars(); 612 $(document).on("click", ".js-set_handlebars_filter", function() { 613 var button = $(this); 614 var type = button.attr("data-type"); 615 var id = button.attr("data-id"); 616 var target = button.attr("data-target"); 617 var href = button.attr("href"); 618 619 $(target).attr("data-filter_type", ""); 620 $(target).attr("data-filter_id", ""); 621 $(target).attr("data-page", "1"); 622 $(target).find(".content").html(""); 623 $(target).attr("data-loaded_all", "0"); 624 625 populate_list(href, type, id); 626 627 //Hack 628 if (type == "tag") { 629 type = "placecast_tag"; 630 } 631 632 $(target).attr("data-filter_type", type); 633 $(target).attr("data-filter_id", id); 634 635 }); 636 $(document).on("click", ".js-trigger_handlebars", function() { 637 var button = $(this); 638 var target = button.attr("data-target"); 639 640 $(target).attr("data-loaded", "0"); 641 642 load_handlebars(); 643 644 return false;
645 }); 646 $(document).on("click", ".js-reset_placecast", function() { 647 var button = $(this); 648 649 $(".modal").modal("hide"); 650 $(".offcanvas").offcanvas("hide"); 651 652 $("#random-placecast").attr("data-id", button.attr("data-id")); 653 $("#random-placecast").attr("data-loaded", "0"); 654 655 load_handlebars() 656 657 return false; 658 }); 659 660 /* Copy to clipboard */ 661 $(document).on("click", ".js-copy_to_clipboard", function() { 662 663 var button = $(this); 664 var target = button.attr("data-target"); 665 console.log($(target).text()); 666 667 navigator.clipboard.writeText($(target).text()) 668 .then(() => { console.log(`Copied!`) }) 669 .catch((error) => { console.log(`Copy failed! ${error}`) }) 670 671 button.closest(".copy-wrap").find(".copy-confirmation").show(); 672 setTimeout(function() { 673 button.closest(".copy-wrap").find(".copy-confirmation").fadeOut("fast"); 674 }, 2500); 675 676 return false; 677 }) 678 679 //Toggle a heart, follow 680 $(document).on("click", ".js-toggle_object", function(e) { 681 var button = $(this); 682 var post_type = button.attr("data-post_type"); 683 var object_id = button.attr("data-object"); 684 685 meta = { 686 'id': button.attr("data-id"), 687 'type': button.attr("data-type"), 688 'collection': button.attr("data-collection") 689 } 690 691 button.addClass("disabled"); 692 toggle_loader("toggle-object-" + post_type + "-" + object_id); 693 694 //Use the WP rest API 695 if (button.hasClass("toggled-on")) { 696 697 $.ajax({ 698 method: "DELETE", 699 url: localizations.restUrl + post_type + "/" + object_id, 700 beforeSend: function ( xhr ) { 701 xhr.setRequestHeader( 'X-WP-Nonce', $("body").attr("data-nonce") ); 702 } 703 704 }) 705 .done(function() { 706 console.log( "success" ); 707 button.removeClass("toggled-on"); 708 button.attr("data-object", "0") 709 if (post_type === "vote") { 710 $(document).trigger("placecloud:vote-changed"); 711 } 712 //button.find(".toggles").text(-1 + parseInt(button.find(".toggles").text())); 713 }) 714 .fail(function() { 715 console.log( "error" ); 716 }) 717 .always(function() { 718 console.log( "complete" ); 719 720 if (typeof(button.attr("data-reload")) !== 'undefined') { 721 $(button.attr("data-reload")).trigger("click"); 722 } 723 else { 724 button.removeClass("disabled"); 725 } 726 727 toggle_loader("toggle-object-" + post_type + "-" + object_id);; 728 729 }); 730 731 } 732 else { 733 var ourPostData = { 734 "title" : "User " + post_type + " through REST API", 735 "status" : "publish", 736 "meta" : meta 737 } 738 739 console.log(ourPostData); 740 741 var createPost = new XMLHttpRequest(); 742 743 createPost.open("POST", localizations.restUrl + post_type); 744 createPost.setRequestHeader('X-WP-Nonce', $("body").attr("data-nonce")); 745 createPost.setRequestHeader("Content-Type", "application/json;charset=UTF-8"); 746 createPost.send(JSON.stringify(ourPostData)); 747 createPost.onreadystatechange = function() { 748 if(createPost.readyState == 4) { 749 if( createPost.status == 201 ) { 750 console.log("Used REST API to create " + post_type); 751 752 var response = $.parseJSON(createPost.responseText); 753 console.log(response); 754 755 button.addClass("toggled-on"); 756 button.attr("data-object", response.id) 757 if (post_type === "vote") { 758 $(document).trigger("placecloud:vote-changed"); 759 } 760 //button.find(".toggles").text(1 + parseInt(button.find(".toggles").text())); 761 } else { 762 console.log('Error - Try again.'); 763 } 764 765 if (typeof(button.attr("data-reload")) !== 'undefined') { 766 $(button.attr("data-reload")).trigger("click"); 767 } 768 else { 769 button.removeClass("disabled"); 770 } 771 772 toggle_loader("toggle-object-" + post_type + "-" + object_id);; 773 774 } 775 } 776 } 777 778 return false; 779 }); 780 781 //Find book covers 782 //Not showing indication that it is loading 783 find_covers = function() { 784 console.log("Attempting to get book covers"); 785 $('.bookCover[data-found="0"]').each(function(i, obj) { 786 var cover = $(this); 787 var isbn = cover.attr("data-isbn"); 788 var isbn13 = cover.attr("data-isbn13"); 789 790 var toUse = false; 791 if (isbn) { 792 toUse = isbn; 793 } 794 if (isbn13) { 795 toUse = isbn13; 796 } 797 console.log("ISBN", toUse); 798 if (toUse) { 799 $.getJSON( "https://openlibrary.org/api/books?bibkeys=ISBN:" + toUse + "&format=json&jscmd=data", function( data ) { 800 console.log(data); 801 802 if (typeof data["ISBN:" + toUse] !== 'undefined') { 803 if (typeof data["ISBN:" + toUse].cover !== "undefined") { 804 var newImage = false;
805 if (typeof data["ISBN:" + toUse].cover.medium !== "undefined") { 806 newImage = data["ISBN:" + toUse].cover.medium; 807 } 808 if (typeof data["ISBN:" + toUse].cover.large !== "undefined") { 809 newImage = data["ISBN:" + toUse].cover.large; 810 } 811 812 if (newImage) { 813 console.log(newImage); 814 cover.attr("src", newImage); 815 816 console.log("Bookcover replaced for ", toUse); 817 } 818 } 819 } 820 821 }); 822 } 823 824 cover.attr("data-found", "1"); 825 }); 826 } 827 828 //Get a random placecast 829 //Only retrieves a placecast ID, then passes it to #random-placecast 830 $(document).on("click", ".js-random_placecast", function() { 831 var button = $(this); 832 var match_type = $(this).attr("data-match_type"); 833 var match_id = $(this).attr("data-match_id"); 834 var post_id = $(this).attr("data-post_id"); 835 836 var data = { 837 action: "placecloud_placecast_id", 838 match_type: match_type, 839 match_id: match_id, 840 post_id: post_id, 841 language: localizations.language 842 }; 843 844 //Close modals and menus, in case open 845 $(".modal").modal("hide"); 846 $(".offcanvas").offcanvas("hide"); 847 848 toggle_loader("random-placecast-" + match_type + "-" + match_id + "-" + post_id); 849 $("#random-placecast .loading").removeClass("d-none").addClass("d-flex"); 850 851 console.log(data); 852 853 $.post(localizations.ajaxUrl, data, function(response) { 854 response = $.parseJSON(response); 855 console.log("Random pick up", response); 856 857 if (response.success) { 858 $("#random-placecast").attr("data-id", response.post_id); 859 $("#random-placecast").attr("data-loaded", "0"); 860 load_handlebars(); 861 862 } 863 else { 864 console.log("Problem"); 865 } 866 867 //$("#random-placecast .loading").removeClass("d-flex").addClass("d-none") 868 toggle_loader("random-placecast-" + match_type + "-" + match_id + "-" + post_id); 869 }); 870 871 return false; 872 }); 873 874 /* Create a new collection. */ 875 $(document).on("click", ".js-new_collection", function() { 876 var button = $(this); 877 var y = button.closest("form").find("input[type='text']").val(); 878 var x = y.trim(); 879 if (x != "") { 880 881 var vals = { 882 title: x, 883 status: "publish", 884 language: button.closest("form").find("input[name='language']").val() 885 }; 886 887 console.log(vals); 888 889 button.addClass("disabled"); 890 toggle_loader("new-collection"); 891 892 var post = new wp.api.models.Collection( vals ); 893 post.save().then(function(p) { 894 895 console.log("New collection", p); 896 897 toggle_loader("new-collection"); 898 button.removeClass("disabled"); 899 button.closest("form").find("input[type='text']").val(""); 900 button.closest(".modal").modal("hide"); 901 $("#my-collections").attr("data-loaded", "0"); 902 load_handlebars(); 903 904 }); 905 } 906 907 return false; 908 909 }); 910 911 //Load a recording and start playback. 912 $(document).on("click", ".js-load_recording", function(event) { 913 event.preventDefault(); 914 var button = $(this); 915 var post_id = button.attr("data-id"); 916 917 if ($(".audio[data-id='" + post_id + "']").attr("data-recording-loaded") == "0") { 918 var data = { 919 action: "placecloud_recording", 920 post_id: post_id, 921 }; 922 923 console.log(data); 924 button.addClass("disabled"); 925 button.find(".not-loading").hide(); 926 button.find(".loading").removeClass("d-none"); 927 928 $.post(localizations.ajaxUrl, data, function(response) { 929 response = $.parseJSON(response); 930 console.log(response); 931 932 if (response.success && response.url) { 933 button.removeClass("disabled"); 934 button.closest(".player-alt").find(".play-pause").removeClass("d-none"); 935 button.remove(); 936 937 $(".audio[data-id='" + post_id + "'] audio").attr("src", response.url); 938 $(".audio[data-id='" + post_id + "']").attr("data-init", "0"); 939 $(".audio[data-id='" + post_id + "']").attr("data-recording-loaded", "1"); 940 941 initAudio(post_id); 942 $(".audio[data-id='" + post_id + "'] .play-pause").trigger("click"); 943 } 944 else { 945 button.removeClass("disabled"); 946 button.find(".not-loading").show(); 947 button.find(".loading").addClass("d-none"); 948 console.log("Problem getting player details."); 949 } 950 951 }); 952 } 953 }); 954 955 //Play buttons 956 initAudio = function(post_id) { 957 var limited_to = ""; 958 if (typeof post_id !== 'undefined') { 959 limited_to = '[data-id="' + post_id + '"]'; 960 } 961 962 $('.audio[data-init="0"]' + limited_to).each(function(i, obj) { 963 var this_audio = $(this); 964 //var this_audio_id = $(this).attr("id"); 965 966 //console.log(this_audio_id); 967 968 var audio = $(obj).find('audio')[0]; 969 970 function formatAudioPosition(seconds) { 971 seconds = isFinite(seconds) && seconds > 0 ? Math.floor(seconds) : 0; 972 var minutes = Math.floor(seconds / 60); 973 var remainingSeconds = seconds % 60; 974 return minutes + ":" + (remainingSeconds < 10 ? "0" : "") + remainingSeconds; 975 } 976 977 function updateAudioPosition(showPosition) { 978 this_audio.find(".audio-position") 979 .text(formatAudioPosition(audio.currentTime)) 980 .toggleClass("d-none", !showPosition); 981 this_audio.find(".audio-duration").toggleClass("d-none", showPosition); 982 } 983 984 $(obj).attr("data-playing", "0"); 985 $(obj).attr("data-playtime", "0"); 986 $(obj).attr("data-play-tracked", "0"); 987 $(obj).attr("data-listen-tracked", "0"); 988 989 $(obj).find(".play-pause").on("click", function(){ 990 $(".play-pause").removeClass("d-none").addClass("d-flex"); 991 992 //$(this).find(".play-pause-icon").toggle(); 993 $(".play-pause-icon.loading").hide(); 994 995 if (audio.paused) { 996 if ($(obj).attr("data-play-tracked") !== "1") { 997 track_viewpoint_event("Play", $(obj).attr("data-id")); 998 $(obj).attr("data-play-tracked", "1"); 999 } 1000 1001 audio.play(); 1002 updateAudioPosition(true); 1003 1004 $(obj).attr("data-playing", "1"); 1005 1006 // if (!$(obj).attr("data-started") == "1") { 1007 // $(obj).closest(".card").find(".streetviewCta").slideDown(); 1008 // } 1009 1010 $(".play-pause").removeClass("btn-success").addClass("btn-warning"); 1011 $(".play-pause-icon.play").hide(); 1012 $(".play-pause-icon.pause").show(); 1013 1014 $(obj).attr("data-started", "1"); 1015 1016 console.log("play"); 1017 } 1018 else { 1019 console.log(this_audio); 1020 1021 audio.pause(); 1022 updateAudioPosition(false); 1023 1024 setTimeout(function() { 1025 $(".play-pause").removeClass("btn-warning").addClass("btn-success"); 1026 $(".play-pause-icon.play").show(); 1027 $(".play-pause-icon.pause").hide(); 1028 1029 }, 250); 1030 1031 $(obj).attr("data-playing", "0"); 1032 1033 console.log("pause"); 1034 } 1035 1036 //return false;
1037 }) 1038 audio.ontimeupdate = function(){ 1039 updateAudioPosition(!audio.paused && !audio.ended); 1040 //$(".play-pause").removeClass("btn-success").addClass("btn-warning"); 1041 this_audio.find(".play-pause-icon.loading").hide(); 1042 //this_audio.find(".play-pause-icon.play").hide(); 1043 //this_audio.find(".play-pause-icon.pause").show(); 1044 1045 this_audio.find(".js-jump").removeClass("disabled"); 1046 this_audio.find(".js-restart").removeClass("disabled"); 1047 1048 $(obj).find('.progress-classic').css('width', audio.currentTime / audio.duration * 100 + '%') 1049 $(obj).find('.progress .progress-bar').css('width', audio.currentTime / audio.duration * 100 + '%') 1050 $(obj).find('.progress').attr("aria-valuenow", audio.currentTime / audio.duration * 100); 1051 1052 //A listen is one playback session that reaches 30 seconds. 1053 if (audio.currentTime >= 30 && $(obj).attr("data-listen-tracked") !== "1") { 1054 track_viewpoint_event("Listen", $(obj).attr("data-id")); 1055 $(obj).attr("data-listen-tracked", "1"); 1056 } 1057 1058 if (audio.currentTime / audio.duration > 0.99) { 1059 $(obj).find(".play-pause-icon.play").show(); 1060 $(obj).find(".play-pause-icon.pause").hide(); 1061 $(".play-pause").removeClass("btn-warning").addClass("btn-success"); 1062 } 1063 1064 } 1065 1066 audio.onended = function() { 1067 updateAudioPosition(false); 1068 $(obj).attr("data-playing", "0"); 1069 $(obj).attr("data-play-tracked", "0"); 1070 $(obj).attr("data-listen-tracked", "0"); 1071 } 1072 1073 $(obj).find(".js-restart").on("click", function(){ 1074 var new_time = 0; 1075 var was_playing = !audio.paused; 1076 1077 $(obj).attr("data-play-tracked", "0"); 1078 $(obj).attr("data-listen-tracked", "0"); 1079 audio.currentTime = new_time; 1080 if (was_playing) { 1081 track_viewpoint_event("Play", $(obj).attr("data-id")); 1082 $(obj).attr("data-play-tracked", "1"); 1083 } 1084 1085 return false; 1086 }); 1087 1088 $(obj).find(".js-jump").on("click", function(){ 1089 var jump = parseInt($(this).attr("data-time")); 1090 var new_time = audio.currentTime + jump; 1091 if (new_time < 0) { 1092 new_time = 0; 1093 } 1094 if (new_time > audio.duration) { 1095 new_time = audio_duration; 1096 } 1097 1098 audio.currentTime = new_time; 1099 1100 //return false; 1101 }); 1102 1103 $(obj).attr("data-init", "1'"); 1104 $(obj).removeClass("disabled"); 1105 }); 1106 } 1107 1108 //Track a viewpoint event using the Matomo tracker already loaded in header.php. 1109 track_viewpoint_event = function(action, post_id) { 1110 window._paq = window._paq || []; 1111 window._paq.push(['trackEvent', 'Viewpoint', action, String(post_id)]); 1112 } 1113 1114 //Record application state that still belongs in WordPress. 1115 log_event = function(event_type, parameters) { 1116 var data = { 1117 action: "placecloud_log_event", 1118 event: event_type, 1119 parameters: parameters 1120 }; 1121 1122 console.log("Event to log", data); 1123 1124 $.post(localizations.ajaxUrl, data, function(response) { 1125 response = $.parseJSON(response); 1126 console.log("Event logged", response); 1127 }); 1128 } 1129 1130 //Trigger the help offcanvas 1131 $(document).on("click", ".js-trigger_help a", function() { 1132 $(".offcanvas").offcanvas("hide"); 1133 $("#offcanvasHelp").offcanvas("show"); 1134 1135 return false; 1136 }); 1137 1138 //Search places 1139 $(document).on("click", ".js-search_places", function() { 1140 var button = $(this); 1141 var search_term = button.closest(".input-group").find(".field").val(); 1142 1143 var data = { 1144 action: "placecloud_search_places", 1145 search: search_term 1146 } 1147 1148 console.log(data); 1149 1150 $("#places-search-loading").show(); 1151 $("#places-search-results").html("").hide(); 1152 1153 $.post(localizations.ajaxUrl, data, function(response) { 1154 response = $.parseJSON(response); 1155 console.log("search results", response); 1156 1157 $("#places-search-loading").hide(); 1158 1159 if (response.success) { 1160 response.localizations = localizations; 1161 1162 $("#places-search-results").html(place_search_results_template(response)).show(); 1163 1164 } 1165 else { 1166 console.log("Problem getting search results."); 1167 } 1168 1169 }); 1170 1171 return false; 1172 }); 1173 1174 //On the homepage, remove the logo 1175 if ($("body.home").length) { 1176 setTimeout(function() { 1177 $(".navbar-brand img").fadeOut(); 1178 }, 30000); 1179 } 1180 1181 //Trigger a modal, if relevant values were passed via the URL 1182 trigger = function(id) { 1183 console.log("triggering", id); 1184 var link = document.getElementById('trigger-modal'); 1185 link.click(); 1186 } 1187 if ($("#trigger-modal").length) { 1188 setTimeout(function() { 1189 trigger("#trigger-modal"); 1190 }, 1000); 1191 } 1192 1193 //Trash a collection
1194 $(document).on("click", ".js-delete_collection", function() { 1195 var button = $(this); 1196 var redirect = false; 1197 1198 if (confirm(localizations.Sure)) { 1199 1200 var data = { 1201 action: "placecloud_trash_collection", 1202 collectionId: button.attr("data-id"), 1203 }; 1204 1205 console.log(data); 1206 1207 button.addClass("disabled"); 1208 button.closest("tr").addClass("disabled"); 1209 button.closest("tr").find(".btn").addClass("disabled"); 1210 1211 $.post(localizations.ajaxUrl, data, function(response) { 1212 response = $.parseJSON(response); 1213 console.log(response); 1214 1215 if (response.success) { 1216 console.log("collection deleted"); 1217 1218 if (typeof button.attr("data-redirect") !== 'undefined') { 1219 redirect = button.attr("data-redirect"); 1220 } 1221 1222 if (redirect) { 1223 window.location.replace(redirect); 1224 } 1225 else { 1226 button.closest("tr").slideUp("fast", function() { 1227 button.closest("tr").remove(); 1228 }); 1229 } 1230 } 1231 else { 1232 alert(localizations.Problem); 1233 1234 button.removeClass("disabled"); 1235 button.closest("tr").removeClass("disabled"); 1236 button.closest("tr").find(".btn").removeClass("disabled"); 1237 1238 } 1239 }); 1240 1241 } 1242 1243 return false; 1244 }); 1245
1246 //Fill collection edit form 1247 $(document).on("click", ".js-edit_collection", function() { 1248 var button = $(this); 1249 var id = button.attr("data-id"); 1250 1251 $("#collectionInputId").val(id); 1252 $("#collectionInputTitle").val(button.closest("tr").find(".title").text()); 1253 $("#collectionInputDescription").val(button.closest("tr").find(".description").text()); 1254 1255 $("#collectionRoute").prop("checked", false); 1256 if ($("tr[data-id='" + id + "']").attr("data-route") == '1') { 1257 $("#collectionRoute").prop("checked", true); 1258 } 1259 1260 return false; 1261 }); 1262 1263 //Submit collection edit form 1264 $(document).on("click", ".js-submit_collection", function() { 1265 var button = $(this); 1266 var values = button.closest("form").serializeArray(); 1267 1268 var data = { 1269 action: "placecloud_submit_collection", 1270 values: values, 1271 }; 1272 1273 console.log(data); 1274 1275 button.closest("form").addClass("disabled"); 1276 button.closest("form").find(".btn").addClass("disabled"); 1277 1278 $.post(localizations.ajaxUrl, data, function(response) { 1279 response = $.parseJSON(response); 1280 console.log(response); 1281 1282 if (response.success) { 1283 console.log("collection updated"); 1284 1285 $(".btn-close").trigger("click"); 1286 1287 $("tr[data-id='" + response.v.collectionInputId + "']").find(".title").text(response.v.collectionInputTitle); 1288 $("tr[data-id='" + response.v.collectionInputId + "']").find(".description").text(response.v.collectionInputDescription.replace('\\', '')); 1289 1290 $("tr[data-id='" + response.v.collectionInputId + "']").attr("data-route", "0"); 1291 if (response.v.collectionRoute == "1") { 1292 $("tr[data-id='" + response.v.collectionInputId + "']").attr("data-route", "1"); 1293 } 1294 } 1295 else { 1296 alert(localizations.Problem); 1297 } 1298 1299 button.closest("form").removeClass("disabled"); 1300 button.closest("form").find(".btn").removeClass("disabled"); 1301 }); 1302 1303 return false; 1304 }); 1305 1306 //Prettify acf-input fields 1307 $( ".acf-input input[type='url']" ).addClass("form-control"); 1308 1309 //Process a placecaster request 1310 $(document).on("click", ".js-process_placecaster_request", function() { 1311 var button = $(this); 1312 1313 var data = { 1314 action: "placecloud_process_placecaster_request", 1315 userId: button.attr("data-user"), 1316 process: button.attr("data-process") 1317 }; 1318 1319 console.log(data); 1320 1321 button.closest("table").find("tr[data-user='" + button.attr("data-user") + "']").addClass("disabled"); 1322 1323 $.post(localizations.ajaxUrl, data, function(response) { 1324 response = $.parseJSON(response); 1325 console.log(response); 1326 1327 button.closest("table").find("tr[data-user='" + button.attr("data-user") + "']").removeClass("disabled"); 1328 1329 if (response.success) { 1330 button.closest("tr").find("td.status").text(button.attr("data-process")); 1331 button.closest("td").find(".btn").remove(); 1332 1333 1334 //button.closest("table").find("tr[data-user='" + button.attr("data-user") + "']").slideUp(); 1335 //location.reload(); 1336 } 1337 else { 1338 alert(pc_localizations.Problem); 1339 1340 1341 1342 } 1343 }); 1344 }); 1345 1346 $(document).on("click", ".js-vet_user", function() { 1347 var button = $(this); 1348 var user_id = button.attr("data-id"); 1349 1350 var data = { 1351 action: "placecloud_vet_user", 1352 user_id: user_id, 1353 }; 1354 1355 toggle_loader("toggle-vet"); 1356 button.addClass("disabled"); 1357 1358 console.log(data); 1359 1360 $.post(localizations.ajaxUrl, data, function(response) { 1361 response = $.parseJSON(response); 1362 console.log(response); 1363 1364 button.removeClass("disabled"); 1365 1366 if (response.success) { 1367 button.remove(); 1368 } 1369 else { 1370 } 1371 1372 toggle_loader("toggle-vet"); 1373 }); 1374 }); 1375 1376 //If a file input changes, update the submit button 1377 $(document).on("change", "input[type='file']", function() { 1378 var input_field = $(this); 1379 1380 if (input_field.val() != "") { 1381 console.log("Removing disabled from submit button"); 1382 input_field.closest("form").find("[type='button']").prop("disabled", false); 1383 } 1384 }); 1385 1386 //Check for cookie acceptance 1387 function checkCookieAcceptance() { 1388 let accepted = getCookie("accept_cookies"); 1389 if (accepted != "") { 1390 } else { 1391 $("#offcanvasCookie").offcanvas("show"); 1392 } 1393 1394 } 1395 setTimeout(function() { 1396 checkCookieAcceptance(); 1397 }, 2000); 1398 $(document).on("click", ".js-accept_cookies", function() { 1399 $("#offcanvasCookie").offcanvas("hide"); 1400 1401 setCookie("accept_cookies", "1", 365); 1402 console.log("accepting cookies"); 1403 1404 return false;
1405 }); 1406 function menuHelpHasBeenSeen() { 1407 try { 1408 return window.localStorage.getItem("placecloud_menu_help_seen") === "1"; 1409 } 1410 catch (error) { 1411 return false; 1412 } 1413 } 1414 1415 function rememberMenuHelp() { 1416 try { 1417 window.localStorage.setItem("placecloud_menu_help_seen", "1"); 1418 } 1419 catch (error) { 1420 // The callout will still dismiss for this page if storage is unavailable. 1421 } 1422 } 1423 1424 function dismissMenuHelp() { 1425 var help = $("#main-menu-help"); 1426 rememberMenuHelp(); 1427 help.removeClass("show"); 1428 window.setTimeout(function() { 1429 help.addClass("d-none"); 1430 }, 150); 1431 } 1432 1433 window.setTimeout(function() { 1434 var help = $("#main-menu-help"); 1435 if (help.length && !menuHelpHasBeenSeen()) { 1436 help.removeClass("d-none"); 1437 window.requestAnimationFrame(function() { 1438 help.addClass("show"); 1439 }); 1440 } 1441 }, 1200); 1442 1443 $(document).on("click", ".js-dismiss-menu-help", function() { 1444 dismissMenuHelp(); 1445 return false; 1446 }); 1447 1448 $(document).on("click", "#main-menu-toggle", function() { 1449 dismissMenuHelp(); 1450 }); 1451 1452 //in-page login form 1453 $("#loginModal input.input").addClass("form-control"); 1454 $("#loginModal input.button").addClass("btn btn-success w-100 text-white"); 1455 1456 trigger_handlebars_if_visible = function(trigger_id, element_id) { 1457 1458 var do_the_check = true; 1459 if (typeof ($("#" + element_id).attr("data-loaded_all")) !== "undefined") { 1460 if ($("#" + element_id).attr("data-loaded_all") == "1") { 1461 do_the_check = false; 1462 } 1463 } 1464 1465 if (do_the_check) { 1466 //console.log(trigger_id, element_id); 1467 var el = document.getElementById(trigger_id); 1468 var cont = document.getElementById(element_id); 1469 1470 if (isVisible(el, cont)) { 1471 1472 if ($("#" + element_id).attr("data-loading") == "0") { 1473 $("#" + element_id).attr("data-loaded", "0"); 1474 load_handlebars(); 1475 } 1476 } 1477 else { 1478 //console.log("not visible", trigger_id); 1479 } 1480 } 1481 1482 } 1483 1484 //monitor scrolls. These are also load-handlebars, and presumably have paging and a trigger 1485 $( ".monitor-scroll" ).each(function( index ) { 1486 var element = $(this); 1487 var element_id = element.attr("id"); 1488 var trigger = element.attr("data-trigger"); 1489 var trigger_id = $(trigger).attr("id"); 1490 1491 //console.log("detecting scroll", trigger_id) 1492 element.scroll(function() { 1493 trigger_handlebars_if_visible(trigger_id, element_id); 1494 }); 1495 }); 1496 1497 //search viewpoints 1498 $(document).on("click", ".js-search_placecasts", function() { 1499 var search_term = $(this).closest(".input-group").find(".search-field").val(); 1500 1501 console.log(search_term); 1502 1503 $("#new-placecasts").attr("data-search", search_term.trim()); 1504 $("#new-placecasts").attr("data-page", "1"); 1505 $("#new-placecasts").attr("data-loaded", "0"); 1506 $("#new-placecasts").attr("data-loaded_all", "0"); 1507 load_handlebars(); 1508 1509 return false; 1510 }); 1511 1512 //Detect viewpoint search box change 1513 $('[data-id="placecast-search"]').on('input', function() { 1514 var current_search = $('[data-id="placecast-search"]').val().trim().toLowerCase(); 1515 var most_recent_search = $("#new-placecasts").attr("data-search").trim().toLowerCase(); 1516 1517 if (current_search != most_recent_search) { 1518 if (current_search == "") { 1519 $("#new-placecasts").attr("data-search", ""); 1520 $("#new-placecasts").attr("data-page", "1"); 1521 $("#new-placecasts").attr("data-loaded", "0"); 1522 $("#new-placecasts").attr("data-loaded_all", "0"); 1523 load_handlebars(); 1524 } 1525 } 1526 }); 1527 1528 //Toggle language in list 1529 $(document).on("click", ".js-language_list_toggle", function() { 1530 var button = $(this); 1531 var language = button.attr("data-language"); 1532 1533 console.log("language", language); 1534 $("body").toggleClass("hide-language-" + language); 1535 1536 }); 1537 $(document).on("click", ".js-placecast_micro_override", function() { 1538 var button = $(this); 1539 button.closest(".placecast-mini").toggleClass("placecast-micro-override"); 1540 1541 return false; 1542 }); 1543 1544})(jQuery);
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.